bool TypesCompatibles(const CBotTypResult& type1, const CBotTypResult& type2) { int t1 = type1.GetType(); int t2 = type2.GetType(); if (t1 == CBotTypIntrinsic) t1 = CBotTypClass; if (t2 == CBotTypIntrinsic) t2 = CBotTypClass; int max = (t1 > t2) ? t1 : t2; if (max == 99) return false; // result is void? if (max >= CBotTypBoolean) { if (t2 != t1) return false; if (max == CBotTypArrayPointer) return TypesCompatibles(type1.GetTypElem(), type2.GetTypElem()); if (max == CBotTypClass || max == CBotTypPointer) return type1.GetClass() == type2.GetClass() ; return true ; } return true; }
CBotFunction* CBotFunction::FindLocalOrPublic(long& nIdent, const char* name, CBotVar** ppVars, CBotTypResult& TypeOrError, bool bPublic) { TypeOrError.SetType(TX_UNDEFCALL); // no routine of the name CBotFunction* pt; if ( nIdent ) { if ( this != NULL ) for ( pt = this ; pt != NULL ; pt = pt->m_next ) { if ( pt->m_nFuncIdent == nIdent ) { TypeOrError = pt->m_retTyp; return pt; } } // search the list of public functions for ( pt = m_listPublic ; pt != NULL ; pt = pt->m_nextpublic ) { if ( pt->m_nFuncIdent == nIdent ) { TypeOrError = pt->m_retTyp; return pt; } } } if ( name == NULL ) return NULL; int delta = 99999; // seeks the lowest signature CBotFunction* pFunc = NULL; // the best function found if ( this != NULL ) { for ( pt = this ; pt != NULL ; pt = pt->m_next ) { if ( pt->m_token.GetString() == name ) { int i = 0; int alpha = 0; // signature of parameters // parameters are compatible? CBotDefParam* pv = pt->m_Param; // expected list of parameters CBotVar* pw = ppVars[i++]; // provided list parameter while ( pv != NULL && pw != NULL) { if (!TypesCompatibles(pv->GetTypResult(), pw->GetTypResult())) { if ( pFunc == NULL ) TypeOrError = TX_BADPARAM; break; } int d = pv->GetType() - pw->GetType(2); alpha += d>0 ? d : -10*d; // quality loss, 10 times more expensive! pv = pv->GetNext(); pw = ppVars[i++]; } if ( pw != NULL ) { if ( pFunc != NULL ) continue; if ( TypeOrError.Eq(TX_LOWPARAM) ) TypeOrError.SetType(TX_NUMPARAM); if ( TypeOrError.Eq(TX_UNDEFCALL)) TypeOrError.SetType(TX_OVERPARAM); continue; // too many parameters } if ( pv != NULL ) { if ( pFunc != NULL ) continue; if ( TypeOrError.Eq(TX_OVERPARAM) ) TypeOrError.SetType(TX_NUMPARAM); if ( TypeOrError.Eq(TX_UNDEFCALL) ) TypeOrError.SetType(TX_LOWPARAM); continue; // not enough parameters } if (alpha == 0) // perfect signature { nIdent = pt->m_nFuncIdent; TypeOrError = pt->m_retTyp; return pt; } if ( alpha < delta ) // a better signature? { pFunc = pt; delta = alpha; } } } } if ( bPublic ) { for ( pt = m_listPublic ; pt != NULL ; pt = pt->m_nextpublic ) { if ( pt->m_token.GetString() == name ) { int i = 0; int alpha = 0; // signature of parameters // parameters sont-ils compatibles ? CBotDefParam* pv = pt->m_Param; // list of expected parameters CBotVar* pw = ppVars[i++]; // list of provided parameters while ( pv != NULL && pw != NULL) { if (!TypesCompatibles(pv->GetTypResult(), pw->GetTypResult())) { if ( pFunc == NULL ) TypeOrError = TX_BADPARAM; break; } int d = pv->GetType() - pw->GetType(2); alpha += d>0 ? d : -10*d; // quality loss, 10 times more expensive! pv = pv->GetNext(); pw = ppVars[i++]; } if ( pw != NULL ) { if ( pFunc != NULL ) continue; if ( TypeOrError.Eq(TX_LOWPARAM) ) TypeOrError.SetType(TX_NUMPARAM); if ( TypeOrError.Eq(TX_UNDEFCALL)) TypeOrError.SetType(TX_OVERPARAM); continue; // to many parameters } if ( pv != NULL ) { if ( pFunc != NULL ) continue; if ( TypeOrError.Eq(TX_OVERPARAM) ) TypeOrError.SetType(TX_NUMPARAM); if ( TypeOrError.Eq(TX_UNDEFCALL) ) TypeOrError.SetType(TX_LOWPARAM); continue; // not enough parameters } if (alpha == 0) // perfect signature { nIdent = pt->m_nFuncIdent; TypeOrError = pt->m_retTyp; return pt; } if ( alpha < delta ) // a better signature? { pFunc = pt; delta = alpha; } } } } if ( pFunc != NULL ) { nIdent = pFunc->m_nFuncIdent; TypeOrError = pFunc->m_retTyp; return pFunc; } return NULL; }