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