gsmfunc.cc

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

CC
1,808 行
字号
	else	  m_funcMatch[f_index] = false;      }    }    if (AllowUndefinedRef) {      ref_param = (ReferencePortion*) param;      param = 0;    }    else  {      throw gclRuntimeError(_FuncName + "[]: Undefined reference \"" +			    ((ReferencePortion *) param)->Value() +			    "\" passed for parameter #" +			    ToText(m_currParamIndex + 1));     }  }  funcs_matched = 0;  last_match = 0;  for (f_index = 0; f_index < _NumFuncs; f_index++) {    if (m_funcMatch[f_index]) {      last_match = f_index;      funcs_matched++;    }  }  if (funcs_matched == 1)    m_funcIndex = last_match;  if (param != 0) {    if (m_funcIndex == -1) {      // Attempt on-the-fly function matching      for (f_index = 0; f_index < _NumFuncs; f_index++) {	if (m_currParamIndex < _FuncInfo[f_index].NumParams) {	  if (TypeMatch(param, 			_FuncInfo[f_index].ParamInfo[m_currParamIndex].Spec,			(_FuncInfo[f_index].Flag & funcLISTABLE)) == matchNONE) {	    m_funcMatch[f_index] = false;	  }	}	else {	  m_funcMatch[f_index] = false;	}      }    }    else { // (m_funcIndex != -1)      if (m_currParamIndex < _FuncInfo[m_funcIndex].NumParams) {	if (TypeMatch(param, 		      _FuncInfo[m_funcIndex].ParamInfo[m_currParamIndex].Spec,		      (_FuncInfo[m_funcIndex].Flag & funcLISTABLE)) == matchNONE) {	  gText message = (_FuncName + "[]: Type mismatch on parameter #"+			   ToText(m_currParamIndex + 1) + ", \"" +			   _FuncInfo[m_funcIndex].ParamInfo[m_currParamIndex].Name +			   "\"; expected " +			   PortionSpecToText(_FuncInfo[m_funcIndex].					     ParamInfo[m_currParamIndex].Spec) +			   ", got ");	  if (param->Spec().Type != porNULL)	    message += PortionSpecToText(param->Spec());	  else	    message += "NULL(" + PortionSpecToText(((NullPortion *) param)->DataType()) + ")";	  throw gclRuntimeError(message);	}      }      else {	throw gclRuntimeError(_FuncName + "[] called with too many parameters");      }    }  }  m_params[m_currParamIndex] = param;  m_runTimeParamInfo[m_currParamIndex].Defined = true;  m_runTimeParamInfo[m_currParamIndex].AutoValOrRef = auto_val_or_ref;  m_runTimeParamInfo[m_currParamIndex].Ref = ref_param;  m_currParamIndex++;  m_numParamsDefined++;  return true;}ReferencePortion* CallFuncObj::GetParamRef(int index) const{  return m_runTimeParamInfo[index].Ref;}// Attempt to identify the function being called out of all the// overloaded versions.void CallFuncObj::ComputeFuncIndex(void){  int exact_index = 0, supertype_index = 0;  bool exact_listmatch = false, supertype_listmatch = false;  if (m_funcIndex == -1 && _NumFuncs == 1)    m_funcIndex = 0;    if (m_funcIndex == -1) {    int param_upper_bound = -1;    for (int index = 0; index < m_numParams; index++) {      if (m_params[index] != 0 || m_runTimeParamInfo[index].Ref != 0)	param_upper_bound = index;    }        int exact_matches = 0, supertype_matches = 0;    for (int f_index = 0; f_index < _NumFuncs; f_index++)  {      gclMatchLevel matchlevel = matchEXACT;      if (param_upper_bound >= _FuncInfo[f_index].NumParams)	matchlevel = matchNONE;      if (!m_funcMatch[f_index])      	matchlevel = matchNONE;      for (int index = 0; (index < _FuncInfo[f_index].NumParams                           && matchlevel != matchNONE); index++)   {	if (m_params[index] != 0) {	  // parameter is defined	  gclMatchLevel parammatch = 	    TypeMatch(m_params[index],		      _FuncInfo[f_index].ParamInfo[index].Spec,		      (_FuncInfo[f_index].Flag & funcLISTABLE));	  if (parammatch != matchEXACT)	    matchlevel = parammatch;	}	else {	  // parameter is undefined	  if (m_runTimeParamInfo[index].Ref != 0) {	    // specified undefined variable	    if(!_FuncInfo[f_index].ParamInfo[index].PassByReference)	      matchlevel = matchNONE;	  }	  	  if (_FuncInfo[f_index].ParamInfo[index].DefaultValue == 0 &&	      _FuncInfo[f_index].ParamInfo[index].Spec.Type != porUNDEFINED)	    matchlevel = matchNONE;	}      }            if (matchlevel == matchEXACT) {	if ((exact_matches == 0) ||	    (exact_matches > 0 && exact_listmatch)) {	  exact_matches = 1;	  exact_index = f_index;	  exact_listmatch = false;	}	else {	  exact_index = f_index;	  exact_matches++;	  exact_listmatch = false;	}      }      else if (matchlevel == matchEXACTLIST) {	// listable matches are superseded by nonlistable ones	if (exact_listmatch || exact_matches == 0) {	  exact_index = f_index;	  exact_matches++;	  exact_listmatch = true;	}      }      else if (matchlevel == matchSUPERTYPE) {	if ((supertype_matches == 0) ||	    (supertype_matches > 0 && supertype_listmatch)) {	  supertype_matches = 1;	  supertype_index = f_index;	  supertype_listmatch = false;	}	else {	  supertype_index = f_index;	  supertype_matches++;	  supertype_listmatch = false;	}      }      else if (matchlevel == matchSUPERLIST) {	// listable matches are superseded by nonlistable ones	if (supertype_listmatch || supertype_matches == 0) {	  supertype_index = f_index;	  supertype_matches++;	  supertype_listmatch = true;	}      }    }    if (exact_matches == 1)      m_funcIndex = exact_index;    else if (exact_matches > 1 ||	     (exact_matches == 0 && supertype_matches > 1))      throw gclRuntimeError(_FuncName + "[] called with ambiguous parameter(s)");    else if (exact_matches == 0 && supertype_matches == 1)      m_funcIndex = supertype_index;    else      throw gclRuntimeError("No matching parameter specifications found for " + _FuncName + "[]");  }    if (m_funcIndex != -1)  {    for (int index = 0; index < _FuncInfo[m_funcIndex].NumParams; index++) {      if (m_params[index] != 0) {	if (TypeMatch(m_params[index],		      _FuncInfo[m_funcIndex].ParamInfo[index].Spec,		      (_FuncInfo[m_funcIndex].Flag & funcLISTABLE)) == matchNONE)	  throw gclRuntimeError(_FuncName + "[] parameter #" +				ToText(index + 1) + ", \"" +				_FuncInfo[m_funcIndex].ParamInfo[index].Name +				"\", type mismatch");      }    }  }}Portion *CallFuncObj::CallFunction(GSM *gsm, Portion **param){  int index;  Portion* result;  ComputeFuncIndex();  // at this point m_funcIndex should be defined; i.e. the function  // matching stage is done.  Now to weed out some particular errors:  for (index = 0; index < _FuncInfo[m_funcIndex].NumParams; index++) {    if (!m_runTimeParamInfo[index].Defined)  {      if(_FuncInfo[m_funcIndex].ParamInfo[index].DefaultValue != 0) {	m_params[index] = 	  _FuncInfo[m_funcIndex].ParamInfo[index].DefaultValue->ValCopy();      }      else {	throw gclRuntimeError(_FuncName + "[] required parameter #" +			      ToText(index + 1) + ", \"" + 			      _FuncInfo[m_funcIndex].ParamInfo[index].Name +			      "\", missing");      }    }    else { // (m_runTimeParamInfo[index].Defined)      if (m_params[index] == 0) {	if(_FuncInfo[m_funcIndex].ParamInfo[index].DefaultValue == 0) {	  if(_FuncInfo[m_funcIndex].UserDefined) {	    // default values for undefined variables	    switch(_FuncInfo[m_funcIndex].ParamInfo[index].Spec.Type) {	    case porBOOLEAN:	      m_params[index] = new BoolPortion(triFALSE);	      m_runTimeParamInfo[index].Defined = true;	      break;	    case porNUMBER:	      m_params[index] = new NumberPortion(0);	      m_runTimeParamInfo[index].Defined = true;	      break;	    case porTEXT:	      m_params[index] = new TextPortion("");	      m_runTimeParamInfo[index].Defined = true;	      break;	    default:	      throw gclRuntimeError(_FuncName + "[] required parameter #" +				    ToText(index + 1) + ", \"" + 				    _FuncInfo[m_funcIndex].ParamInfo[index].Name +				    "\", missing");	    }	  }	  else if (_FuncInfo[m_funcIndex].ParamInfo[index].Spec.Type != 		   porUNDEFINED) {	    throw gclRuntimeError(_FuncName + "[] required parameter #" +				  ToText(index + 1) + ", \"" + 				  _FuncInfo[m_funcIndex].ParamInfo[index].Name +				  "\", missing");	  }	}	else if (!_FuncInfo[m_funcIndex].ParamInfo[index].PassByReference) {	  throw gclRuntimeError(_FuncName + "[] value parameter #" +				ToText(index + 1) + ", \"" +				_FuncInfo[m_funcIndex].ParamInfo[index].Name +				"\", undefined");	}	else if (m_runTimeParamInfo[index].Ref == 0) {	  throw gclRuntimeError(_FuncName + "[] undefined parameter #" +				ToText(index + 1) + ", \"" +				_FuncInfo[m_funcIndex].ParamInfo[index].Name +				"\", passed by value");	}	else if (m_runTimeParamInfo[index].Ref != 0) {	  m_params[index] = 	    _FuncInfo[m_funcIndex].ParamInfo[index].DefaultValue->ValCopy();	}      }    }  }  // aborts when a value parameter is passed by reference or  //        when a reference parameter is passed by value  for (index = 0; index < _FuncInfo[m_funcIndex].NumParams; index++) {    if (m_params[index] != 0 &&	m_runTimeParamInfo[index].Defined) {      if (!_FuncInfo[m_funcIndex].ParamInfo[index].PassByReference &&	  m_params[index]->IsReference())	{	if (m_runTimeParamInfo[index].AutoValOrRef)  {	  Portion *old = m_params[index];	  m_params[index] = old->ValCopy();	  delete old;	}	else {	  throw gclRuntimeError(_FuncName + "[] value parameter #" +				ToText(index + 1) + ", \"" +				_FuncInfo[m_funcIndex].ParamInfo[index].Name +				"\", passed by reference");	}      }    }  }  // This section makes the actual function call  // first check for null objects; if any present in arguments, then  // the function is not called.  bool null_call = false;  for (int i = 0; i < _FuncInfo[m_funcIndex].NumParams; i++) {    if (m_params[i])      if(m_params[i]->Spec().Null &&	 !_FuncInfo[m_funcIndex].ParamInfo[i].Spec.Null)	{	null_call = true;	break;      }  }    bool list_op = false;  for (int i = 0; i < _FuncInfo[m_funcIndex].NumParams; i++)    if (ListNestedCheck(m_params[i], _FuncInfo[m_funcIndex].ParamInfo[i])) {      list_op = true;      break;    }  if (null_call) { // if null objects are present in the argument list    throw gclRuntimeError("Null argument encountered");  }  if (!list_op || !(_FuncInfo[m_funcIndex].Flag & funcLISTABLE)) {      // normal func call    result = CallNormalFunction( gsm, m_params );  }  else { // listed function call    result = CallListFunction(gsm, m_params);  }  if (result == 0) {    for (index = 0; index < m_numParams; index++)    {      delete m_params[index];      m_params[index] = 0;      delete m_runTimeParamInfo[index].Ref;      m_runTimeParamInfo[index].Ref = 0;    }    throw gclRuntimeError("A general error occurred while executing " +			  _FuncName + "[]");  }  else if (result->Spec().Type == porUNDEFINED &&	   ((list_op && result->Spec().ListDepth > 	     _FuncInfo[m_funcIndex].ReturnSpec.ListDepth) ||	    (!list_op && result->Spec().ListDepth == 	     _FuncInfo[m_funcIndex].ReturnSpec.ListDepth))) {    ((ListPortion*) result)->      SetDataType(_FuncInfo[m_funcIndex].ReturnSpec.Type);        }  else if (TypeMatch(result, _FuncInfo[m_funcIndex].ReturnSpec, 		     list_op && (_FuncInfo[m_funcIndex].Flag & funcLISTABLE),		     true) == matchNONE) {    PortionSpec actualSpec = result->Spec();    delete result;    for (index = 0; index < m_numParams; index++)    {      delete m_params[index];      m_params[index] = 0;      delete m_runTimeParamInfo[index].Ref;      m_runTimeParamInfo[index].Ref = 0;    }    throw gclRuntimeError("Function " + _FuncName +			  "[] return type does not match declaration;\n" +			  "Expected " +  			  PortionSpecToText(_FuncInfo[m_funcIndex].ReturnSpec) +			  ", got " + PortionSpecToText(actualSpec));  }  for (index = 0; index < m_numParams; index++) {    if (!_FuncInfo[m_funcIndex].ParamInfo[index].PassByReference) {      delete m_runTimeParamInfo[index].Ref;      m_runTimeParamInfo[index].Ref = 0;    }    if (m_runTimeParamInfo[index].Ref == 0) {      delete m_params[index];      m_params[index] = 0;    }  }  for (index = 0; index < m_numParams; index++)  {    param[index] = m_params[index];  }      return result;}gText CallFuncObj::ParamName(const int index) const{  gText param_name;  int f_index;  if (m_funcIndex != -1 && m_currParamIndex < _FuncInfo[m_funcIndex].NumParams)    return _FuncInfo[m_funcIndex].ParamInfo[m_currParamIndex].Name;    // check whether all index'th parameters have the same name  param_name = "";  for(f_index = 0; f_index < _NumFuncs; f_index++)  {    if(index < _FuncInfo[f_index].NumParams)    {      if(_FuncInfo[f_index].ParamInfo[index].Name != param_name)      {	if(param_name == "")	{	  param_name = _FuncInfo[f_index].ParamInfo[index].Name;	}	else	{	  param_name = "";	  break;	}      }    }  }  if(param_name != "")    return param_name;  else    return "";}void CallFuncObj::Dump(gOutput& f) const{  if (m_funcIndex < 0)    f << FuncName() << "[]\n";  else    gclFunction::Dump(f, m_funcIndex);}

⌨️ 快捷键说明

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