bool CBotExprRetVar::Execute(CBotStack* &pj) { CBotStack* pile = pj->AddStack(); CBotStack* pile1 = pile; CBotVar* pVar; if (pile1->GetState() == 0) { pVar = pj->GetVar(); pVar->Update(pj->GetUserPtr()); if (pVar->GetType(CBotVar::GetTypeMode::CLASS_AS_POINTER) == CBotTypNullPointer) { pile1->SetError(CBotErrNull, &m_token); return pj->Return(pile1); } if ( !m_next3->ExecuteVar(pVar, pile, &m_token, true, false) ) return false; if (pVar) pile1->SetCopyVar(pVar); else return pj->Return(pile1); pile1->IncState(); } pVar = pile1->GetVar(); if (pVar == nullptr) { return pj->Return(pile1); } if (pVar->IsUndefined()) { pile1->SetError(CBotErrNotInit, &m_token); return pj->Return(pile1); } return pj->Return(pile1); }
bool CBotTwoOpExpr::Execute(CBotStack* &pStack) { CBotStack* pStk1 = pStack->AddStack(this); // adds an item to the stack // or return in case of recovery // if ( pStk1 == EOX ) return true; // according to recovery, it may be in one of two states if ( pStk1->GetState() == 0 ) // first state, evaluates the left operand { if (!m_leftop->Execute(pStk1) ) return false; // interrupted here? // for OR and AND logic does not evaluate the second expression if not necessary if ( (GetTokenType() == ID_LOG_AND || GetTokenType() == ID_TXT_AND ) && pStk1->GetVal() == false ) { CBotVar* res = CBotVar::Create("", CBotTypBoolean); res->SetValInt(false); pStk1->SetVar(res); return pStack->Return(pStk1); // transmits the result } if ( (GetTokenType() == ID_LOG_OR||GetTokenType() == ID_TXT_OR) && pStk1->GetVal() == true ) { CBotVar* res = CBotVar::Create("", CBotTypBoolean); res->SetValInt(true); pStk1->SetVar(res); return pStack->Return(pStk1); // transmits the result } // passes to the next step pStk1->SetState(1); // ready for further } // requires a little more stack to avoid touching the result // of which is left on the stack, precisely CBotStack* pStk2 = pStk1->AddStack(); // adds an item to the stack // or return in case of recovery // 2e état, évalue l'opérande de droite if ( pStk2->GetState() == 0 ) { if ( !m_rightop->Execute(pStk2) ) return false; // interrupted here? pStk2->IncState(); } assert(pStk1->GetVar() != nullptr && pStk2->GetVar() != nullptr); CBotTypResult type1 = pStk1->GetVar()->GetTypResult(); // what kind of results? CBotTypResult type2 = pStk2->GetVar()->GetTypResult(); CBotStack* pStk3 = pStk2->AddStack(this); // adds an item to the stack if ( pStk3->IfStep() ) return false; // shows the operation if step by step // creates a temporary variable to put the result // what kind of result? int TypeRes = std::max(type1.GetType(), type2.GetType()); // see "any type convertible chain" in compile method if ( GetTokenType() == ID_ADD && (type1.Eq(CBotTypString) || type2.Eq(CBotTypString)) ) { TypeRes = CBotTypString; } switch ( GetTokenType() ) { case ID_LOG_OR: case ID_LOG_AND: case ID_TXT_OR: case ID_TXT_AND: case ID_EQ: case ID_NE: case ID_HI: case ID_LO: case ID_HS: case ID_LS: TypeRes = CBotTypBoolean; break; case ID_DIV: TypeRes = std::max(TypeRes, static_cast<int>(CBotTypFloat)); } // creates a variable for the result CBotVar* result = CBotVar::Create("", TypeRes); // get left and right operands CBotVar* left = pStk1->GetVar(); CBotVar* right = pStk2->GetVar(); // creates a variable to perform the calculation in the appropriate type if ( TypeRes != CBotTypString ) // keep string conversion { TypeRes = std::max(type1.GetType(), type2.GetType()); } else { left->Update(nullptr); right->Update(nullptr); } if ( GetTokenType() == ID_ADD && type1.Eq(CBotTypString) ) { TypeRes = CBotTypString; } CBotVar* temp; if ( TypeRes == CBotTypPointer ) TypeRes = CBotTypNullPointer; if ( TypeRes == CBotTypClass ) temp = CBotVar::Create("", CBotTypResult(CBotTypIntrinsic, type1.GetClass() ) ); else temp = CBotVar::Create("", TypeRes ); CBotError err = CBotNoErr; // is a operation according to request switch (GetTokenType()) { case ID_ADD: if ( !IsNan(left, right, &err) ) result->Add(left , right); // addition break; case ID_SUB: if ( !IsNan(left, right, &err) ) result->Sub(left , right); // substraction break; case ID_MUL: if ( !IsNan(left, right, &err) ) result->Mul(left , right); // multiplies break; case ID_POWER: if ( !IsNan(left, right, &err) ) result->Power(left , right); // power break; case ID_DIV: if ( !IsNan(left, right, &err) ) err = result->Div(left , right);// division break; case ID_MODULO: if ( !IsNan(left, right, &err) ) err = result->Modulo(left , right);// remainder of division break; case ID_LO: if ( !IsNan(left, right, &err) ) result->SetValInt(temp->Lo(left , right)); // lower break; case ID_HI: if ( !IsNan(left, right, &err) ) result->SetValInt(temp->Hi(left , right)); // top break; case ID_LS: if ( !IsNan(left, right, &err) ) result->SetValInt(temp->Ls(left , right)); // less than or equal break; case ID_HS: if ( !IsNan(left, right, &err) ) result->SetValInt(temp->Hs(left , right)); // greater than or equal break; case ID_EQ: if ( IsNan(left, right) ) result->SetValInt(left->GetInit() == right->GetInit()) ; else result->SetValInt(temp->Eq(left , right)); // equal break; case ID_NE: if ( IsNan(left, right) ) result->SetValInt(left ->GetInit() != right->GetInit()) ; else result->SetValInt(temp->Ne(left , right)); // different break; case ID_TXT_AND: case ID_LOG_AND: case ID_AND: if ( !IsNan(left, right, &err) ) result->And(left , right); // AND break; case ID_TXT_OR: case ID_LOG_OR: case ID_OR: if ( !IsNan(left, right, &err) ) result->Or(left , right); // OR break; case ID_XOR: if ( !IsNan(left, right, &err) ) result->XOr(left , right); // exclusive OR break; case ID_ASR: if ( !IsNan(left, right, &err) ) result->ASR(left , right); break; case ID_SR: if ( !IsNan(left, right, &err) ) result->SR(left , right); break; case ID_SL: if ( !IsNan(left, right, &err) ) result->SL(left , right); break; default: assert(0); } delete temp; pStk2->SetVar(result); // puts the result on the stack if ( err ) pStk2->SetError(err, &m_token); // and the possible error (division by zero) // pStk1->Return(pStk2); // releases the stack return pStack->Return(pStk2); // transmits the result }