void CBotFunction::RestoreState(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance) { CBotStack* pile = pj->RestoreStack(this); // one end of stack local to this function if ( pile == NULL ) return; CBotStack* pile2 = pile; pile->SetBotCall(m_pProg); // bases for routines if ( pile->GetBlock() < 2 ) { CBotStack* pile2 = pile->RestoreStack(NULL); // one end of stack local to this function if ( pile2 == NULL ) return; pile->SetState(pile->GetState() + pile2->GetState()); pile2->Delete(); } m_Param->RestoreState(pile2, true); // parameters if ( !m_MasterClass.IsEmpty() ) { CBotVar* pThis = pile->FindVar("this"); pThis->SetInit(2); pThis->SetUniqNum(-2); } m_Block->RestoreState(pile2, true); }
void CBotFunction::RestoreCall(long& nIdent, const char* name, CBotVar* pThis, CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass) { CBotTypResult type; CBotFunction* pt = FindLocalOrPublic(nIdent, name, ppVars, type); if ( pt != NULL ) { CBotStack* pStk = pStack->RestoreStack(pt); if ( pStk == NULL ) return; pStk->SetBotCall(pt->m_pProg); // it may have changed module CBotVar* pthis = pStk->FindVar("this"); pthis->SetUniqNum(-2); CBotStack* pStk3 = pStk->RestoreStack(NULL); // to set parameters passed if ( pStk3 == NULL ) return; pt->m_Param->RestoreState(pStk3, true); // parameters if ( pStk->GetState() > 1 && // latching is effective? pt->m_bSynchro ) { CBotProgram* pProgBase = pStk->GetBotCall(true); pClass->Lock(pProgBase); // locks the class } // finally calls the found function pt->m_Block->RestoreState(pStk3, true); // interrupt ! } }
// 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; }
void CBotFunction::RestoreCall(long& nIdent, const char* name, CBotVar** ppVars, CBotStack* pStack) { CBotTypResult type; CBotFunction* pt = NULL; CBotStack* pStk1; CBotStack* pStk3; // search function to return the ok identifier pt = FindLocalOrPublic(nIdent, name, ppVars, type); if ( pt != NULL ) { pStk1 = pStack->RestoreStack(pt); if ( pStk1 == NULL ) return; pStk1->SetBotCall(pt->m_pProg); // it may have changed module if ( pStk1->GetBlock() < 2 ) { CBotStack* pStk2 = pStk1->RestoreStack(NULL); // used more if ( pStk2 == NULL ) return; pStk3 = pStk2->RestoreStack(NULL); if ( pStk3 == NULL ) return; } else { pStk3 = pStk1->RestoreStack(NULL); if ( pStk3 == NULL ) return; } // preparing parameters on the stack { if ( !pt->m_MasterClass.IsEmpty() ) { // CBotVar* pInstance = m_pProg->m_pInstance; // make "this" known CBotVar* pThis = pStk1->FindVar("this"); pThis->SetInit(2); pThis->SetUniqNum(-2); } } if ( pStk1->GetState() == 0 ) { pt->m_Param->RestoreState(pStk3, true); return; } // initializes the variables as parameters pt->m_Param->RestoreState(pStk3, false); pt->m_Block->RestoreState(pStk3, true); } }
void CBotDefParam::RestoreState(CBotStack* &pj, bool bMain) { // int i = 0; CBotDefParam* p = this; while ( p != NULL ) { // creates a local variable on the stack CBotVar* var = pj->FindVar(p->m_token.GetString()); var->SetUniqNum(p->m_nIdent); p = p->m_next; } }
bool CBotFunction::Execute(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance) { CBotStack* pile = pj->AddStack(this, 2); // one end of stack local to this function // if ( pile == EOX ) return true; pile->SetBotCall(m_pProg); // bases for routines if ( pile->GetState() == 0 ) { if ( !m_Param->Execute(ppVars, pile) ) return false; // define parameters pile->IncState(); } if ( pile->GetState() == 1 && !m_MasterClass.IsEmpty() ) { // makes "this" known CBotVar* pThis ; if ( pInstance == NULL ) { pThis = CBotVar::Create("this", CBotTypResult( CBotTypClass, m_MasterClass )); pThis->SetInit(2); } else { pThis = CBotVar::Create("this", CBotTypResult( CBotTypPointer, m_MasterClass )); pThis->SetPointer(pInstance); pThis->SetInit(2); } // pThis->SetUniqNum(m_nThisIdent); pThis->SetUniqNum(-2); pile->AddVar(pThis); pile->IncState(); } if ( pile->IfStep() ) return false; if ( !m_Block->Execute(pile) ) { if ( pile->GetError() < 0 ) pile->SetError( 0 ); else return false; } return pj->Return(pile); }
bool CBotDefParam::Execute(CBotVar** ppVars, CBotStack* &pj) { int i = 0; CBotDefParam* p = this; while ( p != NULL ) { // creates a local variable on the stack CBotVar* newvar = CBotVar::Create(p->m_token.GetString(), p->m_type); // serves to make the transformation of types: if ( ppVars != NULL && ppVars[i] != NULL ) { switch (p->m_type.GetType()) { case CBotTypInt: newvar->SetValInt(ppVars[i]->GetValInt()); break; case CBotTypFloat: newvar->SetValFloat(ppVars[i]->GetValFloat()); break; case CBotTypString: newvar->SetValString(ppVars[i]->GetValString()); break; case CBotTypBoolean: newvar->SetValInt(ppVars[i]->GetValInt()); break; case CBotTypIntrinsic: (static_cast<CBotVarClass*>(newvar))->Copy(ppVars[i], false); break; case CBotTypPointer: case CBotTypArrayPointer: { newvar->SetPointer(ppVars[i]->GetPointer()); } break; default: ASM_TRAP(); } } newvar->SetUniqNum(p->m_nIdent); pj->AddVar(newvar); // add a variable p = p->m_next; i++; } return true; }
void CBotDefArray::RestoreState(CBotStack* &pj, bool bMain) { CBotStack* pile1 = pj; CBotVar* var = pj->FindVar(m_var->GetToken()->GetString()); if (var != nullptr) var->SetUniqNum((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent); if (bMain) { pile1 = pj->RestoreStack(this); CBotStack* pile = pile1; if (pile == nullptr) return; if (pile1->GetState() == 0) { // seek the maximum dimension of the table CBotInstr* p = GetNext3b(); while (p != nullptr) { pile = pile->RestoreStack(); if (pile == nullptr) return; if (pile->GetState() == 0) { p->RestoreState(pile, bMain); return; } p = p->GetNext3b(); } } if (pile1->GetState() == 1 && m_listass != nullptr) { m_listass->RestoreState(pile1, bMain); } } if (m_next2b ) m_next2b->RestoreState( pile1, bMain); }
void CBotNew::RestoreState(CBotStack* &pj, bool bMain) { if (!bMain) return; CBotStack* pile = pj->RestoreStack(this); //primary stack if (pile == nullptr) return; if (m_exprRetVar != nullptr) // new Class().method() { if (pile->GetState() == 2) { CBotStack* pile3 = pile->RestoreStack(); m_exprRetVar->RestoreState(pile3, bMain); return; } } CBotStack* pile1 = pj->AddStack2(); //secondary stack CBotToken* pt = &m_vartoken; CBotClass* pClass = CBotClass::Find(pt); // create the variable "this" pointer type to the object if ( pile->GetState()==0) { return; } CBotVar* pThis = pile1->GetVar(); // find the pointer pThis->SetUniqNum(-2); // is ther an assignment or parameters (constructor) if ( pile->GetState()==1) { // evaluates the constructor of the instance CBotVar* ppVars[1000]; CBotStack* pile2 = pile; int i = 0; CBotInstr* p = m_parameters; // evaluate the parameters // and places the values on the stack // to be interrupted at any time if (p != nullptr) while ( true) { pile2 = pile2->RestoreStack(); // space on the stack for the result if (pile2 == nullptr) return; if (pile2->GetState() == 0) { p->RestoreState(pile2, bMain); // interrupt here! return; } ppVars[i++] = pile2->GetVar(); p = p->GetNext(); if ( p == nullptr) break; } ppVars[i] = nullptr; pClass->RestoreMethode(m_nMethodeIdent, m_vartoken.GetString(), pThis, ppVars, pile2) ; // interrupt here! } }
bool CBotNew::Execute(CBotStack* &pj) { CBotStack* pile = pj->AddStack(this); //main stack if (m_exprRetVar != nullptr) // new Class().method() { if (pile->GetState() == 2) { CBotStack* pile3 = pile->AddStack(); if (!m_exprRetVar->Execute(pile3)) return false; return pj->Return(pile3); } } if (pile->IfStep()) return false; CBotStack* pile1 = pj->AddStack2(); //secondary stack CBotVar* pThis = nullptr; CBotToken* pt = &m_vartoken; CBotClass* pClass = CBotClass::Find(pt); // create the variable "this" pointer type to the stack if ( pile->GetState()==0) { // create an instance of the requested class // and initialize the pointer to that object pThis = CBotVar::Create("this", pClass); pThis->SetUniqNum(-2) ; pile1->SetVar(pThis); // place on stack1 pile->IncState(); } // fetch the this pointer if it was interrupted if ( pThis == nullptr) { pThis = pile1->GetVar(); // find the pointer } // is there an assignment or parameters (constructor) if ( pile->GetState()==1) { // evaluates the constructor of the instance CBotVar* ppVars[1000]; CBotStack* pile2 = pile; int i = 0; CBotInstr* p = m_parameters; // evaluate the parameters // and places the values on the stack // to be interrupted at any time if (p != nullptr) while ( true) { pile2 = pile2->AddStack(); // space on the stack for the result if (pile2->GetState() == 0) { if (!p->Execute(pile2)) return false; // interrupted here? pile2->SetState(1); } ppVars[i++] = pile2->GetVar(); p = p->GetNext(); if ( p == nullptr) break; } ppVars[i] = nullptr; // create a variable for the result CBotVar* pResult = nullptr; // constructos still void if ( !pClass->ExecuteMethode(m_nMethodeIdent, pClass->GetName(), pThis, ppVars, pResult, pile2, GetToken())) return false; // interrupt pThis->ConstructorSet(); // indicates that the constructor has been called } if (m_exprRetVar != nullptr) // new Class().method() { pile->AddStack()->Delete(); // release pile2 stack CBotStack* pile3 = pile->AddStack(); // add new stack pile3->SetCopyVar(pThis); // copy the pointer (from pile1) pile1->Delete(); // release secondary stack(pile1) pile->SetState(2); return false; // go back to the top ^^^ } return pj->Return(pile1); // passes below }
void CBotClassInst::RestoreState(CBotStack* &pj, bool bMain) { CBotVar* pThis = NULL; CBotStack* pile = pj; if ( bMain ) pile = pj->RestoreStack(this); if ( pile == NULL ) return; // creates the variable of type pointer to the object { CBotString name = m_var->m_token.GetString(); pThis = pile->FindVar(name); pThis->SetUniqNum((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent); // its attribute a unique number } CBotToken* pt = &m_token; CBotClass* pClass = CBotClass::Find(pt); bool bIntrincic = pClass->IsIntrinsic(); if ( bMain && pile->GetState()<3) { // is there an assignment or parameters (constructor) // CBotVarClass* pInstance = NULL; if ( m_expr != NULL ) { // evaluates the expression for the assignment m_expr->RestoreState(pile, bMain); return; } else if ( m_hasParams ) { // evaluates the constructor of an instance if ( !bIntrincic && pile->GetState() == 1) { return; } CBotVar* ppVars[1000]; CBotStack* pile2 = pile; int i = 0; CBotInstr* p = m_Parameters; // evaluates the parameters // and the values an the stack // for the ability to be interrupted at any time (\TODO pour pouvoir être interrompu n'importe quand) if ( p != NULL) while ( true ) { pile2 = pile2->RestoreStack(); // place on the stack for the results if ( pile2 == NULL ) return; if ( pile2->GetState() == 0 ) { p->RestoreState(pile2, bMain); // interrupted here? return; } ppVars[i++] = pile2->GetVar(); p = p->GetNext(); if ( p == NULL) break; } ppVars[i] = NULL; // creates a variable for the result // CBotVar* pResult = NULL; // constructor still void pClass->RestoreMethode(m_nMethodeIdent, pClass->GetName(), pThis, ppVars, pile2); return; } } if ( m_next2b != NULL ) m_next2b->RestoreState(pile, bMain); // other(s) definition(s) }
bool CBotClassInst::Execute(CBotStack* &pj) { CBotVar* pThis = NULL; CBotStack* pile = pj->AddStack(this);//essential for SetState() // if ( pile == EOX ) return true; CBotToken* pt = &m_token; CBotClass* pClass = CBotClass::Find(pt); bool bIntrincic = pClass->IsIntrinsic(); // creates the variable of type pointer to the object if ( pile->GetState()==0) { CBotString name = m_var->m_token.GetString(); if ( bIntrincic ) { pThis = CBotVar::Create(name, CBotTypResult( CBotTypIntrinsic, pClass )); } else { pThis = CBotVar::Create(name, CBotTypResult( CBotTypPointer, pClass )); } pThis->SetUniqNum((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent); // its attribute as unique number pile->AddVar(pThis); // place on the stack pile->IncState(); } if ( pThis == NULL ) pThis = pile->FindVar((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent); if ( pile->GetState()<3) { // ss there an assignment or parameters (contructor) // CBotVarClass* pInstance = NULL; if ( m_expr != NULL ) { // evaluates the expression for the assignment if (!m_expr->Execute(pile)) return false; if ( bIntrincic ) { CBotVar* pv = pile->GetVar(); if ( pv == NULL || pv->GetPointer() == NULL ) { pile->SetError(TX_NULLPT, &m_token); return pj->Return(pile); } pThis->Copy(pile->GetVar(), false); } else { CBotVarClass* pInstance; pInstance = (static_cast<CBotVarPointer*>(pile->GetVar()))->GetPointer(); // value for the assignment pThis->SetPointer(pInstance); } pThis->SetInit(true); } else if ( m_hasParams ) { // evaluates the constructor of an instance if ( !bIntrincic && pile->GetState() == 1) { CBotToken* pt = &m_token; CBotClass* pClass = CBotClass::Find(pt); // creates an instance of the requested class CBotVarClass* pInstance; pInstance = static_cast<CBotVarClass*>(CBotVar::Create("", pClass)); pThis->SetPointer(pInstance); delete pInstance; pile->IncState(); } CBotVar* ppVars[1000]; CBotStack* pile2 = pile; int i = 0; CBotInstr* p = m_Parameters; // evaluates the parameters // and places the values on the stack // to (can) be interrupted (broken) at any time if ( p != NULL) while ( true ) { pile2 = pile2->AddStack(); // place on the stack for the results if ( pile2->GetState() == 0 ) { if (!p->Execute(pile2)) return false; // interrupted here? pile2->SetState(1); } ppVars[i++] = pile2->GetVar(); p = p->GetNext(); if ( p == NULL) break; } ppVars[i] = NULL; // creates a variable for the result CBotVar* pResult = NULL; // constructor still void if ( !pClass->ExecuteMethode(m_nMethodeIdent, pClass->GetName(), pThis, ppVars, pResult, pile2, GetToken())) return false; // interrupt pThis->SetInit(true); pThis->ConstructorSet(); // indicates that the constructor has been called pile->Return(pile2); // releases a piece of stack // pInstance = pThis->GetPointer(); } // if ( !bIntrincic ) pThis->SetPointer(pInstance); // a pointer to the instance pile->SetState(3); // finished this part } if ( pile->IfStep() ) return false; if ( m_next2b != NULL && !m_next2b->Execute(pile)) return false; // other (s) definition (s) return pj->Return( pile ); // transmits below (further) }
CBotInstr* CBotClassInst::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* pClass) { // seeks the corresponding classes if ( pClass == NULL ) { pStack->SetStartError(p->GetStart()); pClass = CBotClass::Find(p); if ( pClass == NULL ) { // not found? is bizare pStack->SetError(TX_NOCLASS, p); return NULL; } p = p->GetNext(); } bool bIntrinsic = pClass->IsIntrinsic(); CBotTypResult type = CBotTypResult( bIntrinsic ? CBotTypIntrinsic : CBotTypPointer, pClass ); CBotClassInst* inst = static_cast<CBotClassInst*>(CompileArray(p, pStack, type)); if ( inst != NULL || !pStack->IsOk() ) return inst; CBotCStack* pStk = pStack->TokenStack(); inst = new CBotClassInst(); /// \TODO Need to be revised and fixed after adding unit tests CBotToken token(pClass->GetName(), CBotString(), p->GetStart(), p->GetEnd()); inst->SetToken(&token); CBotToken* vartoken = p; if ( NULL != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )) ) { (static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = type; if (pStk->CheckVarLocal(vartoken)) // redefinition of the variable { pStk->SetStartError(vartoken->GetStart()); pStk->SetError(TX_REDEFVAR, vartoken->GetEnd()); goto error; } if (IsOfType(p, ID_OPBRK)) // with any clues? { delete inst; // is not type CBotInt p = vartoken; // returns to the variable name // compiles declaration an array inst = static_cast<CBotClassInst*>(CBotInstArray::Compile( p, pStk, type )); if (!pStk->IsOk() ) { pStk->SetError(TX_CLBRK, p->GetStart()); goto error; } goto suite; // no assignment, variable already created } CBotVar* var; var = CBotVar::Create(vartoken->GetString(), type); // creates the instance // var->SetClass(pClass); var->SetUniqNum( (static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum()); // its attribute a unique number pStack->AddVar(var); // placed on the stack // look if there are parameters inst->m_hasParams = (p->GetType() == ID_OPENPAR); CBotVar* ppVars[1000]; inst->m_Parameters = CompileParams(p, pStk, ppVars); if ( !pStk->IsOk() ) goto error; // if there are parameters, is the equivalent to the stament "new" // CPoint A ( 0, 0 ) is equivalent to // CPoint A = new CPoint( 0, 0 ) // if ( NULL != inst->m_Parameters ) if ( inst->m_hasParams ) { // the constructor is there? // CBotString noname; CBotTypResult r = pClass->CompileMethode(pClass->GetName(), var, ppVars, pStk, inst->m_nMethodeIdent); delete pStk->TokenStack(); // releases the supplement stack int typ = r.GetType(); if (typ == TX_UNDEFCALL) { // si le constructeur n'existe pas if (inst->m_Parameters != NULL) // with parameters { pStk->SetError(TX_NOCONST, vartoken); goto error; } typ = 0; } if (typ>20) { pStk->SetError(typ, vartoken->GetEnd()); goto error; } } if (IsOfType(p, ID_ASS)) // with a assignment? { if (inst->m_hasParams) { pStk->SetError(TX_ENDOF, p->GetStart()); goto error; } if ( NULL == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )) ) { goto error; } CBotClass* result = pStk->GetClass(); if ( !pStk->GetTypResult(1).Eq(CBotTypNullPointer) && ( !pStk->GetTypResult(1).Eq(CBotTypPointer) || ( result != NULL && !pClass->IsChildOf(result) ))) // type compatible ? { pStk->SetError(TX_BADTYPE, p->GetStart()); goto error; } // if ( !bIntrinsic ) var->SetPointer(pStk->GetVar()->GetPointer()); if ( !bIntrinsic ) { // does not use the result on the stack, to impose the class CBotVar* pvar = CBotVar::Create("", pClass); var->SetPointer( pvar ); // variable already declared instance pointer delete pvar; // removes the second pointer } var->SetInit(true); // marks the pointer as init } else if (inst->m_hasParams) { // creates the object on the "job" (\TODO "tas") // with a pointer to the object if ( !bIntrinsic ) { CBotVar* pvar = CBotVar::Create("", pClass); var->SetPointer( pvar ); // variable already declared instance pointer delete pvar; // removes the second pointer } var->SetInit(2); // marks the pointer as init } suite: if (IsOfType(p, ID_COMMA)) // several chained definitions { if ( NULL != ( inst->m_next = CBotClassInst::Compile(p, pStk, pClass) )) // compiles the following { return pStack->Return(inst, pStk); } } if (IsOfType(p, ID_SEP)) // complete instruction { return pStack->Return(inst, pStk); } pStk->SetError(TX_ENDOF, p->GetStart()); } error: delete inst; return pStack->Return(NULL, pStk); }
CBotInstr* CBotDefArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResult type) { CBotCStack* pStk = pStack->TokenStack(p); CBotDefArray* inst = new CBotDefArray(); CBotToken* vartoken = p; inst->SetToken(vartoken); // determinse the expression is valid for the item on the left side if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk ))) { if (pStk->CheckVarLocal(vartoken)) // redefinition of the variable? { pStk->SetError(CBotErrRedefVar, vartoken); goto error; } CBotInstr* i; while (IsOfType(p, ID_OPBRK)) { pStk->SetStartError(p->GetStart()); if (p->GetType() != ID_CLBRK) { i = CBotExpression::Compile(p, pStk); // expression for the value if (i == nullptr || pStk->GetType() != CBotTypInt) // must be a number { pStk->SetError(CBotErrBadIndex, p->GetStart()); goto error; } } else i = new CBotEmpty(); // if no special formula inst->AddNext3b(i); // construct a list type = CBotTypResult(CBotTypArrayPointer, type); if (IsOfType(p, ID_CLBRK)) continue; pStk->SetError(CBotErrCloseIndex, p->GetStart()); goto error; } CBotVar* var = CBotVar::Create(*vartoken, type); // create an instance inst->m_typevar = type; var->SetUniqNum( (static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum()); pStack->AddVar(var); // place it on the stack if (IsOfType(p, ID_ASS)) // with an assignment { pStk->SetStartError(p->GetStart()); if ( IsOfType(p, ID_SEP) ) { pStk->SetError(CBotErrNoExpression, p->GetPrev()); goto error; } if ( nullptr == (inst->m_listass = CBotListArray::Compile(p, pStk, type.GetTypElem())) ) { if (pStk->IsOk()) { inst->m_listass = CBotTwoOpExpr::Compile(p, pStk); if (inst->m_listass == nullptr || !pStk->GetTypResult().Compare(type)) // compatible type ? { pStk->SetError(CBotErrBadType1, p->GetStart()); goto error; } } } if (pStk->IsOk()) while (true) // mark initialized { var = var->GetItem(0, true); if (var == nullptr) break; if (var->GetType() == CBotTypArrayPointer) continue; if (var->GetType() <= CBotTypString) var->SetInit(CBotVar::InitType::DEF); break; } } if (pStk->IsOk()) return pStack->Return(inst, pStk); } error: delete inst; return pStack->Return(nullptr, pStk); }
bool CBotDefArray::Execute(CBotStack* &pj) { CBotStack* pile1 = pj->AddStack(this); CBotStack* pile = pile1; if (pile1->GetState() == 0) { // seek the maximum dimension of the table CBotInstr* p = GetNext3b(); // the different formulas int nb = 0; while (p != nullptr) { pile = pile->AddStack(); // little room to work nb++; if (pile->GetState() == 0) { if (!p->Execute(pile)) return false; // size calculation //interrupted? pile->IncState(); } p = p->GetNext3b(); } p = GetNext3b(); pile = pile1; // returns to the stack int n = 0; int max[100]; while (p != nullptr) { pile = pile->AddStack(); CBotVar* v = pile->GetVar(); // result max[n] = v->GetValInt(); // value if (max[n]>MAXARRAYSIZE) { pile->SetError(CBotErrOutArray, &m_token); return pj->Return (pile); } n++; p = p->GetNext3b(); } while (n<100) max[n++] = 0; m_typevar.SetArray(max); // store the limitations // create simply a nullptr pointer CBotVar* var = CBotVar::Create(*(m_var->GetToken()), m_typevar); var->SetPointer(nullptr); var->SetUniqNum((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent); pj->AddVar(var); #if STACKMEM pile1->AddStack()->Delete(); #else delete pile1->AddStack(); // need more indices #endif pile1->IncState(); } if (pile1->GetState() == 1) { if (m_listass != nullptr) // there is the assignment for this table { CBotVar* pVar = pj->FindVar((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent, false); if (!m_listass->Execute(pile1, pVar)) return false; } pile1->IncState(); } if (pile1->IfStep()) return false; if ( m_next2b && !m_next2b->Execute(pile1 )) return false; return pj->Return(pile1); }
bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond) { bool bStatic = false; int mProtect = PR_PUBLIC; bool bSynchro = false; while (IsOfType(p, ID_SEP)) ; CBotTypResult type( -1 ); if ( IsOfType(p, ID_SYNCHO) ) bSynchro = true; CBotToken* pBase = p; if ( IsOfType(p, ID_STATIC) ) bStatic = true; if ( IsOfType(p, ID_PUBLIC) ) mProtect = PR_PUBLIC; if ( IsOfType(p, ID_PRIVATE) ) mProtect = PR_PRIVATE; if ( IsOfType(p, ID_PROTECTED) ) mProtect = PR_PROTECT; if ( IsOfType(p, ID_STATIC) ) bStatic = true; // CBotClass* pClass = NULL; type = TypeParam(p, pStack); // type of the result if ( type.Eq(-1) ) { pStack->SetError(TX_NOTYP, p); return false; } while (pStack->IsOk()) { CBotToken* pp = p; IsOfType(p, ID_NOT); // skips ~ eventual (destructor) if (IsOfType(p, TokenTypVar)) { CBotInstr* limites = NULL; while ( IsOfType( p, ID_OPBRK ) ) // a table? { CBotInstr* i = NULL; if ( p->GetType() != ID_CLBRK ) i = CBotExpression::Compile( p, pStack ); // expression for the value else i = new CBotEmpty(); // special if not a formula type = CBotTypResult(CBotTypArrayPointer, type); if (!pStack->IsOk() || !IsOfType( p, ID_CLBRK ) ) { pStack->SetError(TX_CLBRK, p->GetStart()); return false; } /* CBotVar* pv = pStack->GetVar(); if ( pv->GetType()>= CBotTypBoolean ) { pStack->SetError(TX_BADTYPE, p->GetStart()); return false; }*/ if (limites == NULL) limites = i; else limites->AddNext3(i); } if ( p->GetType() == ID_OPENPAR ) { if ( !bSecond ) { p = pBase; CBotFunction* f = CBotFunction::Compile1(p, pStack, this); if ( f == NULL ) return false; if (m_pMethod == NULL) m_pMethod = f; else m_pMethod->AddNext(f); } else { // return a method precompiled in pass 1 CBotFunction* pf = m_pMethod; CBotFunction* prev = NULL; while ( pf != NULL ) { if (pf->GetName() == pp->GetString()) break; prev = pf; pf = pf->Next(); } bool bConstructor = (pp->GetString() == GetName()); CBotCStack* pile = pStack->TokenStack(NULL, true); // make "this" known CBotToken TokenThis(CBotString("this"), CBotString()); CBotVar* pThis = CBotVar::Create(&TokenThis, CBotTypResult( CBotTypClass, this ) ); pThis->SetUniqNum(-2); pile->AddVar(pThis); if ( m_pParent ) { // makes "super" known CBotToken TokenSuper(CBotString("super"), CBotString()); CBotVar* pThis = CBotVar::Create(&TokenSuper, CBotTypResult( CBotTypClass, m_pParent ) ); pThis->SetUniqNum(-3); pile->AddVar(pThis); } // int num = 1; CBotClass* my = this; while (my != NULL) { // places a copy of variables of a class (this) on a stack CBotVar* pv = my->m_pVar; while (pv != NULL) { CBotVar* pcopy = CBotVar::Create(pv); pcopy->SetInit(!bConstructor || pv->IsStatic()); pcopy->SetUniqNum(pv->GetUniqNum()); pile->AddVar(pcopy); pv = pv->GetNext(); } my = my->m_pParent; } // compiles a method p = pBase; CBotFunction* f = CBotFunction::Compile(p, pile, NULL/*, false*/); if ( f != NULL ) { f->m_pProg = pStack->GetBotCall(); f->m_bSynchro = bSynchro; // replaces the element in the chain f->m_next = pf->m_next; pf->m_next = NULL; delete pf; if (prev == NULL) m_pMethod = f; else prev->m_next = f; } pStack->Return(NULL, pile); } return pStack->IsOk(); } // definition of an element if (type.Eq(0)) { pStack->SetError(TX_ENDOF, p); return false; } CBotInstr* i = NULL; if ( IsOfType(p, ID_ASS ) ) { if ( type.Eq(CBotTypArrayPointer) ) { i = CBotListArray::Compile(p, pStack, type.GetTypElem()); } else { // it has an assignmet to calculate i = CBotTwoOpExpr::Compile(p, pStack); } if ( !pStack->IsOk() ) return false; } if ( !bSecond ) { CBotVar* pv = CBotVar::Create(pp->GetString(), type); pv -> SetStatic( bStatic ); pv -> SetPrivate( mProtect ); AddItem( pv ); pv->m_InitExpr = i; pv->m_LimExpr = limites; if ( pv->IsStatic() && pv->m_InitExpr != NULL ) { CBotStack* pile = CBotStack::FirstStack(); // independent stack while(pile->IsOk() && !pv->m_InitExpr->Execute(pile)); // evaluates the expression without timer pv->SetVal( pile->GetVar() ) ; pile->Delete(); } } else delete i; if ( IsOfType(p, ID_COMMA) ) continue; if ( IsOfType(p, ID_SEP) ) break; } pStack->SetError(TX_ENDOF, p); } return pStack->IsOk(); }
// compiles a new function // bLocal allows of the declaration of parameters on the same level // as the elements belonging to the class for methods CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunction* finput, bool bLocal) { CBotToken* pp; CBotFunction* func = finput; if ( func == NULL ) func = new CBotFunction(); CBotCStack* pStk = pStack->TokenStack(p, bLocal); // func->m_nFuncIdent = CBotVar::NextUniqNum(); while (true) { if ( IsOfType(p, ID_PUBLIC) ) { func->m_bPublic = true; continue; } pp = p; if ( IsOfType(p, ID_EXTERN) ) { func->m_extern = pp; // for the position of the word "extern" func->m_bExtern = true; // func->m_bPublic = true; // therefore also public! continue; } break; } func->m_retToken = *p; // CBotClass* pClass; func->m_retTyp = TypeParam(p, pStk); // type of the result if (func->m_retTyp.GetType() >= 0) { CBotToken* pp = p; func->m_token = *p; if ( IsOfType(p, ID_NOT) ) { CBotToken d("~" + p->GetString()); func->m_token = d; } // un nom de fonction est-il là ? if (IsOfType(p, TokenTypVar)) { if ( IsOfType( p, ID_DBLDOTS ) ) // method for a class { func->m_MasterClass = pp->GetString(); CBotClass* pClass = CBotClass::Find(pp); if ( pClass == NULL ) goto bad; // pp = p; func->m_token = *p; if (!IsOfType(p, TokenTypVar)) goto bad; } func->m_openpar = p; func->m_Param = CBotDefParam::Compile( p, pStk ); func->m_closepar = p->GetPrev(); if (pStk->IsOk()) { pStk->SetRetType(func->m_retTyp); // for knowledge what type returns if (!func->m_MasterClass.IsEmpty()) { // return "this" known CBotVar* pThis = CBotVar::Create("this", CBotTypResult( CBotTypClass, func->m_MasterClass )); pThis->SetInit(2); // pThis->SetUniqNum(func->m_nThisIdent = -2); //CBotVar::NextUniqNum() will not pThis->SetUniqNum(-2); pStk->AddVar(pThis); // initialize variables acording to This // only saves the pointer to the first, // the rest is chained CBotVar* pv = pThis->GetItemList(); // int num = 1; while (pv != NULL) { CBotVar* pcopy = CBotVar::Create(pv); // pcopy->SetInit(2); pcopy->Copy(pv); pcopy->SetPrivate(pv->GetPrivate()); // pcopy->SetUniqNum(pv->GetUniqNum()); //num++); pStk->AddVar(pcopy); pv = pv->GetNext(); } } // and compiles the following instruction block func->m_openblk = p; func->m_Block = CBotBlock::Compile(p, pStk, false); func->m_closeblk = p->GetPrev(); if ( pStk->IsOk() ) { if ( func->m_bPublic ) // public function, return known for all { CBotFunction::AddPublic(func); } return pStack->ReturnFunc(func, pStk); } } } bad: pStk->SetError(TX_NOFONC, p); } pStk->SetError(TX_NOTYP, p); if ( finput == NULL ) delete func; return pStack->ReturnFunc(NULL, pStk); }
int CBotFunction::DoCall(long& nIdent, const char* name, CBotVar* pThis, CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken, CBotClass* pClass) { CBotTypResult type; CBotProgram* pProgCurrent = pStack->GetBotCall(); CBotFunction* pt = FindLocalOrPublic(nIdent, name, ppVars, type, false); if ( pt != NULL ) { // DEBUG( "CBotFunction::DoCall" + pt->GetName(), 0, pStack); CBotStack* pStk = pStack->AddStack(pt, 2); // if ( pStk == EOX ) return true; pStk->SetBotCall(pt->m_pProg); // it may have changed module CBotStack* pStk3 = pStk->AddStack(NULL, true); // to set parameters passed // preparing parameters on the stack if ( pStk->GetState() == 0 ) { // sets the variable "this" on the stack CBotVar* pthis = CBotVar::Create("this", CBotTypNullPointer); pthis->Copy(pThis, false); pthis->SetUniqNum(-2); // special value pStk->AddVar(pthis); CBotClass* pClass = pThis->GetClass()->GetParent(); if ( pClass ) { // sets the variable "super" on the stack CBotVar* psuper = CBotVar::Create("super", CBotTypNullPointer); psuper->Copy(pThis, false); // in fact identical to "this" psuper->SetUniqNum(-3); // special value pStk->AddVar(psuper); } // initializes the variables as parameters pt->m_Param->Execute(ppVars, pStk3); // cannot be interrupted pStk->IncState(); } if ( pStk->GetState() == 1 ) { if ( pt->m_bSynchro ) { CBotProgram* pProgBase = pStk->GetBotCall(true); if ( !pClass->Lock(pProgBase) ) return false; // expected to power \TODO attend de pouvoir } pStk->IncState(); } // finally calls the found function if ( !pStk3->GetRetVar( // puts the result on the stack pt->m_Block->Execute(pStk3) )) // GetRetVar said if it is interrupted { if ( !pStk3->IsOk() ) { if ( pt->m_bSynchro ) { pClass->Unlock(); // release function } if ( pt->m_pProg != pProgCurrent ) { pStk3->SetPosError(pToken); // indicates the error on the procedure call } } return false; // interrupt ! } if ( pt->m_bSynchro ) { pClass->Unlock(); // release function } return pStack->Return( pStk3 ); } return -1; }
int CBotFunction::DoCall(long& nIdent, const char* name, CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken) { CBotTypResult type; CBotFunction* pt = NULL; pt = FindLocalOrPublic(nIdent, name, ppVars, type); if ( pt != NULL ) { CBotStack* pStk1 = pStack->AddStack(pt, 2); // to put "this" // if ( pStk1 == EOX ) return true; pStk1->SetBotCall(pt->m_pProg); // it may have changed module if ( pStk1->IfStep() ) return false; CBotStack* pStk3 = pStk1->AddStack(NULL, true); // parameters // preparing parameters on the stack if ( pStk1->GetState() == 0 ) { if ( !pt->m_MasterClass.IsEmpty() ) { CBotVar* pInstance = m_pProg->m_pInstance; // make "this" known CBotVar* pThis ; if ( pInstance == NULL ) { pThis = CBotVar::Create("this", CBotTypResult( CBotTypClass, pt->m_MasterClass )); pThis->SetInit(2); } else { pThis = CBotVar::Create("this", CBotTypResult( CBotTypPointer, pt->m_MasterClass )); pThis->SetPointer(pInstance); pThis->SetInit(2); } pThis->SetUniqNum(-2); pStk1->AddVar(pThis); } // initializes the variables as parameters pt->m_Param->Execute(ppVars, pStk3); // cannot be interrupted pStk1->IncState(); } // finally execution of the found function if ( !pStk3->GetRetVar( // puts the result on the stack pt->m_Block->Execute(pStk3) )) // GetRetVar said if it is interrupted { if ( !pStk3->IsOk() && pt->m_pProg != m_pProg ) { #ifdef _DEBUG if ( m_pProg->GetFunctions()->GetName() == "LaCommande" ) return false; #endif pStk3->SetPosError(pToken); // indicates the error on the procedure call } return false; // interrupt ! } return pStack->Return( pStk3 ); } return -1; }