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 + -
显示快捷键?