⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gsm.cc

📁 Gambit 是一个游戏库理论软件
💻 CC
📖 第 1 页 / 共 2 页
字号:
//// $Source: /home/gambit/CVS/gambit/sources/gcl/gsm.cc,v $// $Date: 2002/08/27 18:57:17 $// $Revision: 1.5 $//// DESCRIPTION:// Implementation of GSM environment//// 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.//class Portion;class CallFuncObj;class RefHashTable;#include "base/base.h"#include "gsm.h"#include "portion.h"#include "gsmhash.h"#include "gsmfunc.h"#include "gsminstr.h"#include "game/nfg.h"#include "nash/mixedsol.h"#include "nash/behavsol.h"#include "game/efbasis.h"//----------------------------------------------------------------//        declaration of the game reference counter//----------------------------------------------------------------RefCountHashTable< void* > GSM::_GameRefCount;int& GSM::GameRefCount(void* game){  if(_GameRefCount.IsDefined(game))    return _GameRefCount(game);  else {    _GameRefCount.Define(game, 0);    return _GameRefCount(game);  }}//----------------------------------------------------------------//       function list sorting functions//----------------------------------------------------------------class gFuncListSorter : public gListSorter<gclFunction*>{protected:  bool LessThan(gclFunction* const& a, gclFunction* const& b) const  {    return (a->FuncName() > b->FuncName());  }public:  gFuncListSorter(void) { }};class gTextListSorter : public gListSorter<gText>{protected:  bool LessThan(gText const& a, gText const& b) const  {    return (a > b);  }public:  gTextListSorter(void) { }};//--------------------------------------------------------------------//              implementation of GSM (Stack machine)//--------------------------------------------------------------------int GSM::_NumObj = 0;GSM::GSM(gInput& s_in, gOutput& s_out, gOutput& s_err)  : _StdIn(s_in), _StdOut(s_out), _StdErr(s_err){  // global function default variables initialization  // these should be done before InitFunctions() is called  _RefTableStack = new gStack< RefHashTable* >(1);  _RefTableStack->Push(new RefHashTable);  _FuncNameStack = new gStack< gText >;  _FuncTable     = new FunctionHashTable;  InitFunctions();  // This function is located in gsmfunc.cc  _NumObj++;}GSM::~GSM(){  _NumObj--;  delete _FuncTable;  while (_RefTableStack->Depth())     delete _RefTableStack->Pop();  delete _RefTableStack;  delete _FuncNameStack;}bool GSM::VarIsDefined(const gText &p_name) const{  if (p_name == "")    throw gclRuntimeError("Tried to see if empty variable name defined");  else if (p_name[0u] == '$') {    if (p_name[1u] == '$')      return _GlobalRefTable.IsDefined(p_name.Right(p_name.Length() - 2));    else      return _GlobalRefTable.IsDefined(UserFuncName() + gText((char) 1) +				       p_name.Right(p_name.Length() - 1));  }  return _RefTableStack->Peek()->IsDefined(p_name);}void GSM::VarDefine(const gText& var_name, Portion* p){  bool type_match = true;  Portion *old_value = 0;  if (var_name == "")    throw gclRuntimeError("Tried to define empty variable name");  _ResolveRef(p);  if (var_name[0u] == '$') {    gText global_name;    if (var_name[1u] != '$')      global_name = (UserFuncName() + gText((char) 1) +		     var_name.Right(var_name.Length() - 1));    else      global_name = var_name.Right(var_name.Length() - 2);    if (_GlobalRefTable.IsDefined(global_name)) {      old_value = _GlobalRefTable(global_name);      if (p->Spec().ListDepth > 0) {	if (((ListPortion*) old_value)->Spec().Type != 	    ((ListPortion*) p)->Spec().Type)  {	  if (((ListPortion*) p)->Spec().Type == porUNDEFINED)	    ((ListPortion*) p)->SetDataType(old_value->Spec().Type);	  else if (old_value->Spec().Type != porUNDEFINED)	    type_match = false;	}      }      else {	PortionSpec ospec = old_value->Spec();	PortionSpec pspec = p->Spec();	if (ospec.Type == porNULL)	  ospec = ((NullPortion*) old_value)->DataType();	if (pspec.Type == porNULL)	  pspec = ((NullPortion*) p)->DataType();	if (ospec.Type != pspec.Type)	  if (!PortionSpecMatch(ospec, pspec))	    type_match = false;      }    }    if (!type_match) {      delete p;      throw gclRuntimeError("Cannot change the type of variable \"" +			    var_name + "\"");    }    else {      if (old_value)	delete _VarRemove(var_name);      _GlobalRefTable.Define(global_name, p);    }  }      else  {    if (_RefTableStack->Peek()->IsDefined(var_name)) {      old_value = (*_RefTableStack->Peek())(var_name);      if (p->Spec().ListDepth > 0) {	if (((ListPortion*) old_value)->Spec().Type != 	    ((ListPortion*) p)->Spec().Type)  {	  if (((ListPortion*) p)->Spec().Type == porUNDEFINED)	    ((ListPortion*) p)->SetDataType(old_value->Spec().Type);	  else if (old_value->Spec().Type != porUNDEFINED)	    type_match = false;	}      }      else {	PortionSpec ospec = old_value->Spec();	PortionSpec pspec = p->Spec();	if (ospec.Type == porNULL)	  ospec = ((NullPortion*) old_value)->DataType();	if (pspec.Type == porNULL)	  pspec = ((NullPortion*) p)->DataType();	if (ospec.Type != pspec.Type)	  if (!PortionSpecMatch(ospec, pspec))	    type_match = false;      }    }    if (!type_match) {      delete p;      throw gclRuntimeError("Cannot change the type of variable \"" +			    var_name + "\"");    }    else {      if (old_value)	delete _VarRemove(var_name);      _RefTableStack->Peek()->Define(var_name, p);    }  }}Portion* GSM::VarValue(const gText &p_name) const{  if (p_name == "")    throw gclRuntimeError("Tried to get value of empty variable name");  else if (p_name[0u] == '$') {    if (p_name[1u] == '$')      return _GlobalRefTable(p_name.Right(p_name.Length() - 2));    else      return _GlobalRefTable(UserFuncName() + gText((char) 1) +			     p_name.Right(p_name.Length() - 1));  }  return (*_RefTableStack->Peek())(p_name);}Portion* GSM::_VarRemove(const gText &p_name){  if (p_name == "")    throw gclRuntimeError("Tried to remove empty variable name");  else if (p_name[0u] == '$') {    if (p_name[1u] == '$')      return _GlobalRefTable.Remove(p_name.Right(p_name.Length() - 2));    else      return _GlobalRefTable.Remove(UserFuncName() + gText((char) 1) +				    p_name.Right(p_name.Length() - 1));  }  return _RefTableStack->Peek()->Remove(p_name);}//---------------------------------------------------------------------//     Reference related functions//---------------------------------------------------------------------Portion* GSM::Assign( Portion* p1, Portion* p2 ){  Portion* result = 0;  gText varname;  if(p1->Spec().Type == porREFERENCE)    varname = ((ReferencePortion*) p1)->Value();  _ResolveRef( p2 );  _ResolveRef( p1 );  PortionSpec p1Spec(p1->Spec());  PortionSpec p2Spec(p2->Spec());  if(p1->Original() == p2->Original())  // assigning a variable to itself  {    delete p2;    result = p1;  }    else if(p2Spec.Type == porREFERENCE) // assigning from undefined variable  {    throw gclRuntimeError("Undefined variable " +			      ((ReferencePortion *) p2)->Value());  }  else if(p1Spec.Type == porREFERENCE) // assigning to a new variable  {        delete p1;    if( p2->IsReference() )    {      VarDefine( varname, p2->ValCopy() );      delete p2;    }    else      VarDefine( varname, p2 );    result = VarValue( varname )->RefCopy();  }  else if( p1Spec == p2Spec && 	   p1Spec.Type != porNULL && 	   !(p1Spec.Type & porMIXED) &&	   !(p1Spec.Type & porBEHAV) )  {    if(p1Spec.ListDepth == 0) // not a list    {      result = p1;      switch (p1Spec.Type) {      case porNUMBER:	((NumberPortion*) p1)->SetValue(((NumberPortion*) p2)->Value());	break;      case porTEXT:	((TextPortion*) p1)->SetValue(((TextPortion*) p2)->Value());	break;      case porBOOLEAN:	((BoolPortion*) p1)->SetValue(((BoolPortion*) p2)->Value());	break;      case porEFOUTCOME:	((EfOutcomePortion *) p1)->SetValue(((EfOutcomePortion *) p2)->Value());	break;      case porNFOUTCOME:	((NfOutcomePortion *) p1)->SetValue(((NfOutcomePortion *) p2)->Value());	break;      case porNFSUPPORT:	((NfSupportPortion *) p1)->SetValue(new NFSupport(*((NfSupportPortion *) p2)->Value()));	break;      case porEFSUPPORT:	((EfSupportPortion *) p1)->SetValue(new EFSupport(*((EfSupportPortion *) p2)->Value()));	break;      case porEFBASIS:	((EfBasisPortion *) p1)->SetValue(new EFBasis(*((EfBasisPortion *) p2)->Value()));	break;      case porINFOSET:	((InfosetPortion *) p1)->SetValue(((InfosetPortion *) p2)->Value());	break;      case porNFPLAYER:	((NfPlayerPortion *) p1)->SetValue(((NfPlayerPortion *) p2)->Value());	break;      case porEFPLAYER:	((EfPlayerPortion *) p1)->SetValue(((EfPlayerPortion *) p2)->Value());	break;      case porSTRATEGY:	((StrategyPortion *) p1)->SetValue(((StrategyPortion *) p2)->Value());	break;      case porNODE:	((NodePortion *) p1)->SetValue(((NodePortion *) p2)->Value());	break;      case porACTION:	((ActionPortion *) p1)->SetValue((Action *)((ActionPortion *) p2)->Value());	break;      case porNFG:	((NfgPortion *) p1)->SetValue(((NfgPortion *) p2)->Value());	break;      case porEFG:	((EfgPortion *) p1)->SetValue(((EfgPortion *) p2)->Value());	break;      case porINPUT:      case porOUTPUT:	delete p1;	throw gclRuntimeError("Cannot assign from INPUT/OUTPUT variable" );      default:	throw gclRuntimeError("Assigning to unknown type " +			      PortionSpecToText(p1Spec));      }      delete p2;      // result already assigned on top of this block    }    // both p1 and p2 are lists    else if((p1Spec.Type == p2Spec.Type) ||	    (p1Spec.Type == porUNDEFINED))    {      if(!(p1Spec.Type & (porINPUT|porOUTPUT)))      {	((ListPortion*) p1)->AssignFrom(p2);	delete p2;	result = p1;      }      else // error: assigning to (list of) INPUT or OUTPUT      {	delete p2;	delete p1;	throw gclRuntimeError("Cannot assign from INPUT/OUTPUT variable" );      }    }    else // error: changing the type of a list    {      delete p2;      delete p1;      throw gclRuntimeError("Cannot change list type");    }  }  else if(varname != "") // make sure variable is associated with a var name  {    if(p1Spec.Type == porNULL)      p1Spec = ((NullPortion*) p1)->DataType();    if(p2Spec.Type == porNULL)      p2Spec = ((NullPortion*) p2)->DataType();        if(PortionSpecMatch(p1Spec, p2Spec) ||       (p1Spec.Type == porUNDEFINED && p1Spec.ListDepth > 0 &&	p2Spec.ListDepth > 0))    {      delete p1;      if( p2->IsReference() )      {	VarDefine( varname, p2->ValCopy() );	delete p2;      }      else	VarDefine( varname, p2 );      result = VarValue( varname )->RefCopy();    }    else { // error: changing the type of variable      delete p2;      delete p1;      throw gclRuntimeError("Cannot change the type of variable \"" +			    varname + "\" from " +			    PortionSpecToText(p1Spec) + " to " +			    PortionSpecToText(p2Spec));    }  }  else {    delete p2;    delete p1;    throw gclRuntimeError("Must assign to a variable");  }  return result;}bool GSM::UnAssign(Portion *p){  if (p->Spec().Type == porREFERENCE) {    if(VarIsDefined(((ReferencePortion*) p)->Value())) {      delete _VarRemove(((ReferencePortion *) p)->Value());      delete p;      return true;    }    else {      delete p;      return true;    }  }  else {    throw gclRuntimeError("UnAssign[] called on a non-reference value");  }}Portion* GSM::UnAssignExt(Portion *p){  gText txt;  if(p->Spec().Type == porREFERENCE)  {    gText varname = ((ReferencePortion*) p)->Value();     if(VarIsDefined( varname ) )    {      delete p;      delete _VarRemove( varname );      return new BoolPortion(triTRUE);    }    else    {      delete p;      return new BoolPortion(triFALSE);    }  }  else  {    throw gclRuntimeError("UnAssign[] called on a non-reference value");  }}bool GSM::VarRemove(const gText& var_name){  if(VarIsDefined(var_name))    _VarRemove(var_name);  return true;}//-----------------------------------------------------------------------//                        _ResolveRef functions//-----------------------------------------------------------------------void GSM::_ResolveRef(Portion *&p){  if (p->Spec().Type == porREFERENCE) {    gText ref = ((ReferencePortion*) p)->Value();    if (VarIsDefined(ref)) {      Portion *result = VarValue(ref)->RefCopy();      delete p;      p = result;    }  }}//-------------------------------------------------------------------//               CallFunction() related functions//-------------------------------------------------------------------bool GSM::AddFunction(gclFunction* func){  gclFunction *old_func;  bool result;  if (func == 0)  return false;  if(!_FuncTable->IsDefined(func->FuncName()))  {    _FuncTable->Define(func->FuncName(), func);    return true;  }  else {    old_func = (*_FuncTable)(func->FuncName());    result = old_func->Combine(func);    if (!result)      throw gclRuntimeError("New " + old_func->FuncName() +			    "[] ambiguous with existing function");    return result;  }}bool GSM::DeleteFunction(gclFunction* func){  gclFunction *old_func = 0;  if (func == 0)  return 0;  if (!_FuncTable->IsDefined(func->FuncName())) {    throw gclRuntimeError("Function " + old_func->FuncName() + " not found");  }  else {    old_func = (*_FuncTable)(func->FuncName());    if (!old_func->Delete(func))      throw gclRuntimeError("No matching prototype found");  }  return true;}//----------------------------------------------------------------------------//                       Execute function//----------------------------------------------------------------------------Portion *GSM::Execute(gclExpression *expr, bool /*user_func*/){  return expr->Evaluate(*this);}Portion* GSM::ExecuteUserFunc(gclExpression& program, 			      const gclSignature& func_info,			      Portion** param, 			      const gText& funcname ){  Portion *result, *result_copy;

⌨️ 快捷键说明

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