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