Exemple #1
0
BOOL CBotAddExpr::Execute(CBotStack* &pStack)
{
    CBotStack* pStk1 = pStack->AddStack(this);  // ajoute un élément à la pile
                                                // ou le retrouve en cas de reprise
//  if ( pSk1 == EOX ) return TRUE;


    // selon la reprise, on peut être dans l'un des 2 états

    if ( pStk1->GetState() == 0 &&              // 1er état, évalue l'opérande de gauche
        !m_leftop->Execute(pStk1) ) return FALSE; // interrompu ici ?

    // passe à l'étape suivante
    pStk1->SetState(1);                         // prêt pour la suite

    // demande un peu plus de stack pour ne pas toucher le résultat de gauche
    // qui se trouve sur la pile, justement.

    CBotStack* pStk2 = pStk1->AddStack();       // ajoute un élément à la pile
                                                // ou le retrouve en cas de reprise

    // 2e état, évalue l'opérande de droite
    if ( !m_rightop->Execute(pStk2) ) return FALSE; // interrompu ici ?

    int     type1 = pStk1->GetType();           // de quels types les résultats ?
    int     type2 = pStk2->GetType();

    // crée une variable temporaire pour y mettre le résultat
    CBotVar*    result = new CBotVar( NULL, MAX(type1, type2));

    // fait l'opération selon la demande
    switch (GetTokenType())
    {
    case ID_ADD:
        result->Add(pStk1->GetVar(), pStk2->GetVar());      // additionne
        break;
    case ID_SUB:
        result->Sub(pStk1->GetVar(), pStk2->GetVar());      // soustrait
        break;
    }
    pStk2->SetVar(result);                      // met le résultat sur la pile

    pStk1->Return(pStk2);                       // libère la pile
    return pStack->Return(pStk1);               // transmet le résultat
}
Exemple #2
0
bool CBotAddExpr::Execute(CBotStack* &pStack)
{
    CBotStack* pStk1 = pStack->AddStack(this);  // adds an item to the stack
                                                // or is found in case of recovery
//  if ( pSk1 == EOX ) return TRUE;


    // according to recovery, it may be in one of two states

    if ( pStk1->GetState() == 0 &&              // first state, evaluates the left operand
        !m_leftop->Execute(pStk1) ) return FALSE; // interrupted here?

    // passes to the next step
    pStk1->SetState(1);                         // ready for further

    // requires a little more stack to not touch the result of the left
    // which is on the stack, precisely.

    CBotStack* pStk2 = pStk1->AddStack();       // adds an item to the stack
                                                // or is found in case of recovery

    // Second state, evaluates the right operand
    if ( !m_rightop->Execute(pStk2) ) return FALSE; // interrupted here?

    int     type1 = pStk1->GetType();           // what kind of results?
    int     type2 = pStk2->GetType();

    // creates a temporary variable to put the result
    CBotVar*    result = new CBotVar( nullptr, MAX(type1, type2));

    // is the operation as requested
    switch (GetTokenType())
    {
    case ID_ADD:
        result->Add(pStk1->GetVar(), pStk2->GetVar());      // addition
        break;
    case ID_SUB:
        result->Sub(pStk1->GetVar(), pStk2->GetVar());      // subtraction
        break;
    }
    pStk2->SetVar(result);                      // puts the result on the stack

    pStk1->Return(pStk2);                       // frees the stack
    return pStack->Return(pStk1);               // transmits the result
}
Exemple #3
0
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
}