CBotTypResult CBotVar::GetTypResult(GetTypeMode mode) { CBotTypResult r = m_type; if ( mode == GetTypeMode::CLASS_AS_POINTER && m_type.Eq(CBotTypClass) ) r.SetType(CBotTypPointer); if ( mode == GetTypeMode::CLASS_AS_INTRINSIC && m_type.Eq(CBotTypClass) ) r.SetType(CBotTypIntrinsic); return r; }
CBotTypResult CBotVar::GetTypResult(int mode) { CBotTypResult r = m_type; if ( mode == 1 && m_type.Eq(CBotTypClass) ) r.SetType(CBotTypPointer); if ( mode == 2 && m_type.Eq(CBotTypClass) ) r.SetType(CBotTypIntrinsic); return r; }
bool TypeCompatible(CBotTypResult& type1, CBotTypResult& type2, int op) { int t1 = type1.GetType(); int t2 = type2.GetType(); int max = (t1 > t2) ? t1 : t2; if (max == 99) return false; // result is void? // special case for strin concatenation if (op == ID_ADD && max >= CBotTypString) return true; if (op == ID_ASSADD && max >= CBotTypString) return true; if (op == ID_ASS && t1 == CBotTypString) return true; if (max >= CBotTypBoolean) { if ( (op == ID_EQ || op == ID_NE) && (t1 == CBotTypPointer && t2 == CBotTypNullPointer)) return true; if ( (op == ID_EQ || op == ID_NE || op == ID_ASS) && (t2 == CBotTypPointer && t1 == CBotTypNullPointer)) return true; if ( (op == ID_EQ || op == ID_NE) && (t1 == CBotTypArrayPointer && t2 == CBotTypNullPointer)) return true; if ( (op == ID_EQ || op == ID_NE || op == ID_ASS) && (t2 == CBotTypArrayPointer && t1 == CBotTypNullPointer)) return true; if (t2 != t1) return false; if (t1 == CBotTypArrayPointer) return type1.Compare(type2); if (t1 == CBotTypPointer || t1 == CBotTypClass || t1 == CBotTypIntrinsic ) { CBotClass* c1 = type1.GetClass(); CBotClass* c2 = type2.GetClass(); return c1->IsChildOf(c2) || c2->IsChildOf(c1); // accept the case in reverse // the transaction will be denied at runtime if the pointer is not // compatible } return true; } type1.SetType(max); type2.SetType(max); return true; }
// compiles a list of parameters CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack) { // mainly not pStack->TokenStack here // declared variables must remain visible thereafter pStack->SetStartError(p->GetStart()); if (IsOfType(p, ID_OPENPAR)) { CBotDefParam* list = NULL; while (!IsOfType(p, ID_CLOSEPAR)) { CBotDefParam* param = new CBotDefParam(); if (list == NULL) list = param; else list->AddNext(param); // added to the list // CBotClass* pClass = NULL;//= CBotClass::Find(p); param->m_typename = p->GetString(); CBotTypResult type = param->m_type = TypeParam(p, pStack); // if ( type == CBotTypPointer ) type = CBotTypClass; // we must create a new object if (param->m_type.GetType() > 0) { CBotToken* pp = p; param->m_token = *p; if (pStack->IsOk() && IsOfType(p, TokenTypVar) ) { // variable already declared? if (pStack->CheckVarLocal(pp)) { pStack->SetError(TX_REDEFVAR, pp); break; } if ( type.Eq(CBotTypArrayPointer) ) type.SetType(CBotTypArrayBody); CBotVar* var = CBotVar::Create(pp->GetString(), type); // creates the variable // if ( pClass ) var->SetClass(pClass); var->SetInit(2); // mark initialized param->m_nIdent = CBotVar::NextUniqNum(); var->SetUniqNum(param->m_nIdent); pStack->AddVar(var); // place on the stack if (IsOfType(p, ID_COMMA) || p->GetType() == ID_CLOSEPAR) continue; } pStack->SetError(TX_CLOSEPAR, p->GetStart()); } pStack->SetError(TX_NOTYP, p); delete list; return NULL; } return list; } pStack->SetError(TX_OPENPAR, p->GetStart()); return NULL; }