gsmfunc.cc

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

CC
1,808 行
字号
  gText f;  int i;  int j;  for(i = 0; i < _NumFuncs; i++)  {      if( (udf && _FuncInfo[i].UserDefined) ||       (bif && !_FuncInfo[i].UserDefined) )    {      f = _FuncName + '[';      for(j = 0; j < _FuncInfo[i].NumParams; j++)      {	if(j != 0) f += ", ";	if(_FuncInfo[i].ParamInfo[j].DefaultValue) f += '{';	f += _FuncInfo[i].ParamInfo[j].Name;	if(_FuncInfo[i].ParamInfo[j].PassByReference) f += '<';	f += "->";		if(_FuncInfo[i].ParamInfo[j].DefaultValue)	  f += _FuncInfo[i].ParamInfo[j].DefaultValue->OutputString();	else	  f += PortionSpecToText(_FuncInfo[i].ParamInfo[j].Spec);		if(_FuncInfo[i].ParamInfo[j].DefaultValue) 	  f += '}';      }      f += "] =: ";      f += PortionSpecToText(_FuncInfo[i].ReturnSpec);      /*      if( getdesc && _FuncInfo[i].UserDefined )	f += '\n';	*/      if( getdesc && _FuncInfo[i].Desc.Length() > 0 )      {	f += '\n';	f += _FuncInfo[i].Desc;	f += '\n';      }      list.Append(f);    }  }  return list;}void gclFunction::Dump(gOutput& f, int i) const{ f << FuncList()[i+1] << '\n'; }void gclFunction::Dump(gOutput& f) const{  for (int i = 0; i < _NumFuncs; Dump(f, i++));}//---------------------------------------------------------------------//                      CallFuncObj//---------------------------------------------------------------------CallFuncObj::CallFuncObj(gclFunction *p_function,			 int p_line, const gText &p_file)  : gclFunction(*p_function), m_line(p_line), m_file(p_file),    m_funcIndex(-1), m_numParams(0), m_numParamsDefined(0){  for (int f_index = 0; f_index < _NumFuncs; f_index++)  {    if (m_numParams < _FuncInfo[f_index].NumParams)      m_numParams = _FuncInfo[f_index].NumParams;  }  m_params = new Portion*[m_numParams];  m_runTimeParamInfo = new RunTimeParamInfoType[m_numParams];  m_funcMatch = new bool[_NumFuncs];  m_currParamIndex = 0;  for (int f_index = 0; f_index < _NumFuncs; f_index++)    m_funcMatch[f_index] = true;  for (int index = 0; index < m_numParams; index++)  {    m_params[index] = REQUIRED;    m_runTimeParamInfo[index].Ref = 0;    m_runTimeParamInfo[index].Defined = false;    m_runTimeParamInfo[index].AutoValOrRef = false;  }}CallFuncObj::~CallFuncObj(){  for (int index = 0; index < m_numParams; index++)  {     delete m_runTimeParamInfo[index].Ref;    delete m_params[index];  }  delete[] m_funcMatch;  delete[] m_runTimeParamInfo;  delete[] m_params;}//--------------------------// List-related functions//--------------------------static bool ListDimMatch(ListPortion* p1, ListPortion* p2){  if (p1->Length() != p2->Length())    return false;  else {    for (int i = 1; i <= p1->Length(); i++) {      Portion *s1 = (*p1)[i];      Portion *s2 = (*p2)[i];      if (s1->Spec().ListDepth > 0 && s2->Spec().ListDepth > 0) {	if (!ListDimMatch((ListPortion*) s1, (ListPortion*) s2))	  return false;      }    }  }  return true;}static bool ListNestedCheck(Portion* p, const gclParameter& info){  if (p == 0 && info.Spec.Type == porUNDEFINED)    return false;  else if (p->Spec().ListDepth > info.Spec.ListDepth)    return true;  else    return false;}Portion *CallFuncObj::CallNormalFunction(GSM *gsm, Portion **param){  // check to see that all parameters belong to the same game, if so specified  if (_FuncInfo[m_funcIndex].Flag & funcGAMEMATCH) {    void *game = NULL;     for (int index = 0; index < _FuncInfo[m_funcIndex].NumParams; index++) {      if (param[index] != 0 && m_runTimeParamInfo[index].Defined) {	if (param[index]->Game()) {	  if (game == NULL)	    game = param[index]->Game();	  else if (game != param[index]->Game()) {	    throw gclRuntimeError("Function " + _FuncName +				  "[] parameters do not belong to same game\n" +				  "Error at parameter #" + ToText(index + 1));	  }	}      }    }     }  try {    if (!_FuncInfo[m_funcIndex].UserDefined)      return _FuncInfo[m_funcIndex].FuncPtr(*gsm, param);    else       return gsm->ExecuteUserFunc(*(_FuncInfo[m_funcIndex].FuncInstr), 				  _FuncInfo[m_funcIndex], param,				  FuncName() + gText((char) (m_funcIndex+1)));  }  catch (gclQuitOccurred &) {    throw;  }  catch (...) {    gsm->OutputStream() << "In function " << _FuncName 			<< "[], in file \"" << m_file;    gsm->OutputStream() << "\" at line " << ToText(m_line) << ":\n";    throw;  }}Portion *CallFuncObj::CallListFunction(GSM* gsm, Portion **ParamIn){  Portion* result;  int NumParams = _FuncInfo[m_funcIndex].NumParams;  bool *Listed = new bool[NumParams];  ListPortion* Source = 0;  // source to look at to create dimensionality  bool recurse;  // mark down the listed parameters  for (int i = 0; i < NumParams; i++) {    Listed[i] =      ListNestedCheck(ParamIn[i], _FuncInfo[m_funcIndex].ParamInfo[i]);    if (Listed[i])      Source = (ListPortion*) ParamIn[i];  }  // check that all dimensionalities match  for (int i = 0; i < NumParams; i++)  {    for (int j = i + 1; j < NumParams; j++)  {      if (Listed[i] && Listed[j]) {	if (ParamIn[i]->Spec().ListDepth > 0 && 	    ParamIn[j]->Spec().ListDepth > 0)	  if (!ListDimMatch((ListPortion *) ParamIn[i],			    (ListPortion *) ParamIn[j])) {	    delete [] Listed;	    throw gclRuntimeError("Mismatched dimensionalities");	  }      }    }  }  Portion **CurrParam = new Portion *[NumParams];  ListPortion *p = new ListPortion;  // 'i' is the index for the lists  for (int i = 1; i <= Source->Length(); i++)   {    recurse = false;    // while j is the param index    // pickout the current element to process        for (int j = 0; j < NumParams; j++)  {      if (!Listed[j])	CurrParam[j] = ParamIn[j];       else {	CurrParam[j] = (*(ListPortion*) ParamIn[j])[i];	if (ListNestedCheck(CurrParam[j], 			     _FuncInfo[m_funcIndex].ParamInfo[j]))	  recurse = true;      }    }    if (recurse) {      result = CallListFunction(gsm, CurrParam);    }    else  {      for (int j = 0; j < NumParams; j++)  {	if (CurrParam[j]->IsReference()) {	  CurrParam[j] = CurrParam[j]->RefCopy();        }	else  {	  CurrParam[j] = CurrParam[j]->ValCopy();        }      }      bool null_call = false;      for (int j = 0; j < NumParams; j++)	if (CurrParam[j]->Spec().Null && 	    !_FuncInfo[m_funcIndex].ParamInfo[j].Spec.Null) {	  null_call = true;	  break;	}      if (!null_call) {	try { 	  result = CallNormalFunction(gsm, CurrParam);	}	catch (gclRuntimeError &E) {	  throw gclRuntimeError(_FuncName + "[]: " + E.Description() + 				"\nError occurred at element #" +				ToText(p->Length() + 1) +				" during listed function call to " +				_FuncName);	}      }      else if (null_call)  {	throw gclRuntimeError("Null argument encountered");      }      else	throw gclRuntimeError("Error in arguments");      for (int j = 0; j < NumParams; j++)	delete CurrParam[j];    }    if (result == 0)      throw gclRuntimeError("");    if (result->Spec().Type == porUNDEFINED &&	((recurse && result->Spec().ListDepth > 	  _FuncInfo[m_funcIndex].ReturnSpec.ListDepth) ||	 (!recurse && result->Spec().ListDepth == 	  _FuncInfo[m_funcIndex].ReturnSpec.ListDepth))) {      ((ListPortion*) result)->	SetDataType(_FuncInfo[m_funcIndex].ReturnSpec.Type);          }    p->Append(result);  }  delete [] CurrParam;  delete [] Listed;  return p;}typedef enum { matchNONE = 0, matchSUPERTYPE = 1, matchEXACT = 2,               matchSUPERLIST = 3, matchEXACTLIST = 4 } gclMatchLevel;gclMatchLevel TypeMatch(Portion* p, PortionSpec ExpectedSpec, 			bool Listable, bool return_type_check = false){  if (p == 0 && ExpectedSpec.Type == porUNDEFINED)    return matchEXACT;  if (ExpectedSpec.Type == porANYTYPE && return_type_check)    return matchEXACT;    bool nullPortion = false;  PortionSpec CalledSpec = p->Spec();  if (p->Spec().Type == porNULL) {    CalledSpec = ((NullPortion*) p)->DataType();    nullPortion = true;  }  gclMatchLevel matchtype = matchEXACT;  if (CalledSpec.Type == porNUMBER && ExpectedSpec.Type == porINTEGER) {    if (nullPortion) {      if (!return_type_check) {	matchtype = matchNONE;      }    }    else if ((CalledSpec.ListDepth > 0 && ((ListPortion *) p)->IsInteger()) ||	     (CalledSpec.ListDepth == 0 && ((NumberPortion *) p)->Value().IsInteger()))      CalledSpec.Type = porINTEGER;  }  else if (CalledSpec.Type == porNUMBER && ExpectedSpec.Type == porNUMBER) {    if (nullPortion) {      if (!return_type_check) {	matchtype = matchNONE;      }    }    else if ((CalledSpec.ListDepth > 0 && ((ListPortion *) p)->IsInteger()) ||	     (CalledSpec.ListDepth == 0 && ((NumberPortion *) p)->Value().IsInteger()))      matchtype = matchSUPERTYPE;  }  if (CalledSpec.Type & ExpectedSpec.Type)  {    if (CalledSpec.ListDepth == ExpectedSpec.ListDepth)      return matchtype;    else if (CalledSpec.ListDepth > ExpectedSpec.ListDepth && Listable) {      if (matchtype == matchSUPERTYPE)	return matchSUPERLIST;      else if (matchtype == matchEXACT)	return matchEXACTLIST;      else	return matchNONE;    }    else if (CalledSpec.ListDepth > 0 && ExpectedSpec.ListDepth == 1 && 	    !Listable)      return matchtype;    else if (CalledSpec.ListDepth > 0 && ExpectedSpec.ListDepth == NLIST)      return matchtype;  }  else if (CalledSpec.Type == porUNDEFINED && CalledSpec.ListDepth > 0)  {    if (CalledSpec.ListDepth == 1 && ExpectedSpec.ListDepth > 0)       return matchtype;  }  return matchNONE;}bool CallFuncObj::SetCurrParamIndex(const gText& param_name){  int TempFuncIndex = -1;  int result = PARAM_NOT_FOUND;  int times_found = 0;    for (int f_index = 0;        f_index < _NumFuncs && result != PARAM_AMBIGUOUS;       f_index++) {    if (m_funcMatch[f_index])   {      bool name_match_found = false;      for (int index = 0; index < _FuncInfo[f_index].NumParams; index++) {	if (_FuncInfo[f_index].ParamInfo[index].Name == param_name) {	  name_match_found = true;	  if (result == PARAM_NOT_FOUND) {	    result = index;	    TempFuncIndex = f_index;	    times_found++;	  }	  else if(result == index) {	    times_found++;	  }	  else { // (result != index)	    result = PARAM_AMBIGUOUS;	    break;	  }	}      }      if (!name_match_found)	m_funcMatch[f_index] = false;    }  }      if (times_found == 1) {    if (m_funcIndex == -1) {      m_funcIndex = TempFuncIndex;    }    else if (m_funcIndex != TempFuncIndex) {      m_funcIndex = -1;      throw gclRuntimeError(_FuncName +			    "[] called with conflicting parameters");    }  }  if (result == PARAM_NOT_FOUND)  {    throw gclRuntimeError("Parameter \"" + param_name +			  "\" is not defined for " + _FuncName + "[]");   }  else if (result == PARAM_AMBIGUOUS) {    throw gclRuntimeError("Parameter \"" + param_name + 			  "\" is ambiguous in " + _FuncName + "[]");  }  else {    m_currParamIndex = result;    return true;  }}bool CallFuncObj::SetCurrParam(Portion *param, bool auto_val_or_ref){  ReferencePortion* ref_param = 0;  bool AllowUndefinedRef;  int f_index;  int funcs_matched;  int last_match;  // Parameter index out of bounds  if (m_currParamIndex >= m_numParams)  {    delete param;    throw gclRuntimeError(_FuncName + "[] called with too many parameters");  }  // Repeated parameter definition  if (m_runTimeParamInfo[m_currParamIndex].Defined)   {    throw gclRuntimeError(_FuncName + "[] called with parameter #" +			  ToText(m_currParamIndex) + " multiply defined");  }  // Passed an undefined variable  if (param != 0 && param->Spec().Type == porREFERENCE)  {    // check whether undefined variables are allowed    AllowUndefinedRef = false;    for (f_index = 0; f_index < _NumFuncs; f_index++) {      if (m_currParamIndex < _FuncInfo[f_index].NumParams)  {	if((_FuncInfo[f_index].ParamInfo[m_currParamIndex].PassByReference &&	    _FuncInfo[f_index].ParamInfo[m_currParamIndex].DefaultValue != 0)|| 	   _FuncInfo[f_index].UserDefined ||	   _FuncInfo[f_index].ParamInfo[m_currParamIndex].Spec.Type == porUNDEFINED)	  AllowUndefinedRef = true;

⌨️ 快捷键说明

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