gsmfunc.cc

来自「Gambit 是一个游戏库理论软件」· CC 代码 · 共 1,808 行 · 第 1/4 页

CC
1,808
字号
//// $Source: /home/gambit/CVS/gambit/sources/gcl/gsmfunc.cc,v $// $Date: 2002/08/27 18:57:18 $// $Revision: 1.4 $//// DESCRIPTION:// Implementing predefined GCL functions//// This file is part of Gambit// Copyright (c) 2002, The Gambit Project//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//#include <ctype.h>#include "base/base.h"#include "gsmfunc.h"#include "gsm.h"#include "portion.h"#include "gsmhash.h"#include "gsminstr.h"#include "game/nfg.h"#include "game/efg.h"#include "game/nfstrat.h"#include "game/efstrat.h"// This function is called once at the first instance of GSM.// The Init function of each module should be placed in this function:// Each Init() function should take the argument "this" so each instance// of GSM can add those functions to their memory.extern void Init_gsmoper(GSM *);extern void Init_nfgfunc(GSM *);extern void Init_efgfunc(GSM *);extern void Init_algfunc(GSM *);extern void Init_solfunc(GSM *);extern void Init_listfunc(GSM *);extern void Init_listmath(GSM *);void GSM::InitFunctions(void){  Init_gsmoper(this);  Init_listfunc(this);  //  Init_listmath(this);  Init_nfgfunc(this);  Init_efgfunc(this);  Init_algfunc(this);  Init_solfunc(this);}//---------------------------------------------------------------//                      gclParameter//---------------------------------------------------------------gclParameter::gclParameter(void)  : Name(""), DefaultValue(REQUIRED), PassByReference(BYVAL){ }gclParameter::gclParameter(const gclParameter& paraminfo)  : Name(paraminfo.Name), Spec(paraminfo.Spec),     DefaultValue(paraminfo.DefaultValue),     PassByReference(paraminfo.PassByReference){ }gclParameter::gclParameter(const gText& name, const PortionSpec& spec,			     Portion* default_value, const bool pass_by_ref)  : Name(name), Spec(spec), DefaultValue(default_value),     PassByReference(pass_by_ref){ }gclParameter::~gclParameter(){ }//---------------------------------------------------------------------//                     gclSignature//---------------------------------------------------------------------gclSignature::gclSignature(void)  : UserDefined(false), FuncPtr(0), ReturnSpec(PortionSpec(porUNDEFINED)),    Flag(funcLISTABLE), NumParams(0), ParamInfo(0){ }gclSignature::gclSignature(const gclSignature& funcinfo)  : UserDefined(funcinfo.UserDefined), ReturnSpec(funcinfo.ReturnSpec),    Flag(funcinfo.Flag), NumParams(funcinfo.NumParams), Desc(funcinfo.Desc){  if(!UserDefined)    FuncPtr = funcinfo.FuncPtr;  else    FuncInstr = funcinfo.FuncInstr;  ParamInfo = new gclParameter[NumParams];  for (int i = 0; i < NumParams; i++)    ParamInfo[i] = funcinfo.ParamInfo[i];}gclSignature::gclSignature(Portion *(*funcptr)(GSM &, Portion **),			   PortionSpec returnspec, int numparams,			   gclParameter* paraminfo, FuncFlagType flag)  : UserDefined(false), FuncPtr(funcptr), ReturnSpec(returnspec),    Flag(flag), NumParams(numparams){  ParamInfo = new gclParameter[NumParams];  if (paraminfo)    for (int i = 0; i < NumParams; i++)      ParamInfo[i] = paraminfo[i];}gclSignature::gclSignature(gclExpression* funcinstr,			   PortionSpec returnspec,			   int numparams,			   gclParameter* paraminfo,			   FuncFlagType flag)  : UserDefined(true), FuncInstr(funcinstr), ReturnSpec(returnspec),    Flag(flag), NumParams(numparams){  ParamInfo = new gclParameter[NumParams];  if (paraminfo)    for (int i = 0; i < NumParams; i++)      ParamInfo[i] = paraminfo[i];}gclSignature::~gclSignature(){ }//---------------------------------------------------------------------//                   Function descriptor objects//---------------------------------------------------------------------RefCountHashTable< gclExpression* > gclFunction::_RefCountTable;gclFunction::gclFunction(gclFunction &func)  : m_environment(func.m_environment){  int index;  int f_index;  _FuncName  = func._FuncName;  _NumFuncs  = func._NumFuncs;  _FuncInfo  = new gclSignature[_NumFuncs];  for(f_index = 0; f_index < _NumFuncs; f_index++)  {    _FuncInfo[f_index].UserDefined = func._FuncInfo[f_index].UserDefined;        _FuncInfo[f_index].ReturnSpec  = func._FuncInfo[f_index].ReturnSpec;    _FuncInfo[f_index].Flag    = func._FuncInfo[f_index].Flag;    if(!_FuncInfo[f_index].UserDefined)      _FuncInfo[f_index].FuncPtr     = func._FuncInfo[f_index].FuncPtr;    else      _FuncInfo[f_index].FuncInstr   = func._FuncInfo[f_index].FuncInstr;        if(_FuncInfo[f_index].UserDefined)      if(!_RefCountTable.IsDefined(_FuncInfo[f_index].FuncInstr))	_RefCountTable.Define(_FuncInfo[f_index].FuncInstr, 1);      else	_RefCountTable(_FuncInfo[f_index].FuncInstr)++;        _FuncInfo[f_index].NumParams = func._FuncInfo[f_index].NumParams;    _FuncInfo[f_index].ParamInfo =      new gclParameter[_FuncInfo[f_index].NumParams];    for(index = 0; index < _FuncInfo[f_index].NumParams; index ++)    {      _FuncInfo[f_index].ParamInfo[index] = 	func._FuncInfo[f_index].ParamInfo[index];      if(_FuncInfo[f_index].ParamInfo[index].DefaultValue != 0)      {	_FuncInfo[f_index].ParamInfo[index].DefaultValue = 	  _FuncInfo[f_index].ParamInfo[index].DefaultValue->ValCopy();      }	    }  }}gclFunction::gclFunction(GSM &p_environment,			 const gText& func_name, int numfuncs)  : _FuncName(func_name), _NumFuncs(numfuncs), m_environment(p_environment){  _FuncInfo = new gclSignature[_NumFuncs];}// Assumes one argument, which has a prototype func_protogclFunction::gclFunction(GSM &p_environment, const gText& func_proto,                          Portion *(*funcptr)(GSM &, Portion**),                         FuncFlagType FFT /* = funcLISTABLE */)  : m_environment(p_environment){  _NumFuncs = 1;  _FuncInfo = new gclSignature[1];    unsigned int index = 0;  gText func_name;  char ch = func_proto[index++];  while (isalpha(ch)) {    func_name += ch;    ch=func_proto[index++];  }  _FuncName = func_name;  SetFuncInfo(0, func_proto, funcptr, FFT);}gclFunction::~gclFunction(){  int index;  int f_index;    for(f_index = 0; f_index < _NumFuncs; f_index++)  {    for(index = 0; index < _FuncInfo[f_index].NumParams; index++) {      delete _FuncInfo[f_index].ParamInfo[index].DefaultValue;    }    if(_FuncInfo[f_index].UserDefined) {      if (!_RefCountTable.IsDefined(_FuncInfo[f_index].FuncInstr) ||	  _RefCountTable(_FuncInfo[f_index].FuncInstr) <= 0)	throw gclRuntimeError("Internal GCL error");      _RefCountTable(_FuncInfo[f_index].FuncInstr)--;      if (_RefCountTable(_FuncInfo[f_index].FuncInstr) == 0) {	_RefCountTable.Remove(_FuncInfo[f_index].FuncInstr);	delete _FuncInfo[f_index].FuncInstr;      }    }    delete[] _FuncInfo[f_index].ParamInfo;  }  delete[] _FuncInfo;}void gclFunction::SetFuncInfo(int funcindex, gclSignature funcinfo){  if ((funcindex < 0) || (funcindex >= _NumFuncs))    throw gclRuntimeError("Internal GCL error");  _FuncInfo[funcindex] = funcinfo;  if(funcinfo.UserDefined)    if(!_RefCountTable.IsDefined(funcinfo.FuncInstr))      _RefCountTable.Define(funcinfo.FuncInstr, 1);    else      _RefCountTable(funcinfo.FuncInstr)++;}void gclFunction::SetFuncInfo(int funcindex, const gText& s){  SetFuncInfo(funcindex, s, 0);}  // In this function, the input string "s" is parsed, and the info contained   // in it is used to determine the function info, and then SetFuncInfo   // is called with all data passed as arguments rather than a string.void gclFunction::SetFuncInfo(int funcindex, const gText& s,                              Portion* (*funcptr)(GSM &, Portion **),                               FuncFlagType FFT /* = funcLISTABLE */){  char ch = ' ';  unsigned int index=0, length=s.Length();  int numArgs=0;  bool done = false;  gList<gText> specList;  gList<gText> nameList;  gList<int>     listList;  gList<bool>    refList;  gList<Portion*>     reqList;      // Move ch to the first variable name  while (ch != '[' && index<=length)      ch=s[index++];  ch=s[index++];  // ch should now hold first letter of the first name  if (ch == ']') // If there are no parameters    done = true;    // Loop through the string, parsing a word-argument pair at a time.  while (!done)  // ch should always be at beginning of next name here  {    bool required = true;    if (ch == '{')  {  // If the argument is optional      ch=s[index++];      required = false;    }        // name gets the name of the variable    gText name = ch;    ch=s[index++];    while (isalpha(ch)) { name += ch; ch = s[index++]; }    nameList.Append(name);        // See if it passed by reference    if (ch == '<')    {      refList.Append(BYREF);    }    else    {      refList.Append(BYVAL);    }          // Move ch so that it holds the first character of the type;    while (ch != '>' && ch != ']' && index<=length)        ch=s[index++];    if (ch == ']')  {  // If we hit the end (this should NEVER happen)      throw gclRuntimeError("Bad function signature");    }    else {      ch=s[index++];          // Word gets the word, which is the type of variable.      gText word = ch;      int     listNum = 0;      ch=s[index++];      if (required)  // If required, get word in normal fashion.      {        reqList.Append( REQUIRED );        while (isalpha(ch)) { word += ch; ch = s[index++]; }      }      else  // If optional, get default argument and parse.      {        while (ch != '}') { word += ch; ch = s[index++]; }        ch=s[index++];                /*_gsm->OutputStream() << "Default: " << word << "\n";*/        if (word == "true" || word == "True" || word == "TRUE")        {          bool* tmp = new bool(true);          reqList.Append((Portion*)tmp);          word = "BOOLEAN";        }        else if (word == "false" || word == "False" || word == "FALSE")        {          bool* tmp = new bool(false);          reqList.Append((Portion*)tmp);          word = "BOOLEAN";        }        else if (word == "StdOut") {          OutputPortion* tmp = new OutputPortion(m_environment.OutputStream());          reqList.Append((Portion*) tmp);          word = "OUTPUT";        }        else if (word == "NullOut") {          OutputPortion* tmp = new OutputPortion(*new gNullOutput);          reqList.Append((Portion*)tmp);          word = "OUTPUT";        }        else if (word == "StdIn") {          InputPortion* tmp = new InputPortion(*new gStandardInput);          reqList.Append((Portion*)tmp);          word = "INPUT";        }          // If it is a text string (for now just assume it is if it begins '"')        else if (word[0u] == '"')        {          gText* tmp = new gText(word);          reqList.Append((Portion*)tmp);          word = "TEXT";        }          // If it is a number (int or double)        else if ((word[0u] >= '0' && word[0u] <= '9') || word[0u] == '-') {          int sign = 1;          unsigned int index2 = 0;          bool isDouble = false;          /*gInteger num = 0, denom = 1;*/          gNumber* num = new gNumber(0);                  char cha = word[index2++];                  if (cha == '-')  {  // If the number is negative            sign = -1;            cha = word[index2++];          }                  while (cha >= '0' && cha <= '9')   {  // Read number            *num *= 10;            *num += (int) (cha - '0');            cha = word[index2++];          }                  if (cha == '.')    // If it is a float          {            isDouble = true;            int factor = 1;            cha = word[index2++];                    while (cha >= '0' && cha <= '9')   {              *num += ( ((float) (cha - '0')) / (pow((int)10, (long)factor)) );              factor++;              cha = word[index2++];            }              *num *= sign;          }  // If it is a float                  if (isDouble)          {            word = "NUMBER";            reqList.Append((Portion*) num);          }          else          {            word = "INTEGER";            gInteger* tmp = new gInteger((int)*num);            reqList.Append((Portion*) tmp);            delete num;          }        } // If it is int or float        else {	  m_environment.OutputStream() << "Unknown optional type!!\n\n";          int* silly = new int;          reqList.Append( (Portion *)silly);          word = "MIXED";    // TEMPORARY ONLY SO THAT IT WORKS -- REMOVE!!        }      }      numArgs++;          // Check to see if it is a list  (should prolly only do if req.)      if (word == "LIST")      {        while (word == "LIST")        {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?