colobot/src/CBot/CBotAddExpr.cpp

147 lines
5.0 KiB
C++

/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2015, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
///////////////////////////////////////////////////
// expressions of type Operand1 + Operand2
// Operand1 - Operand2
#include "CBot.h"
// various constructors
CBotAddExpr::CBotAddExpr()
{
m_leftop =
m_rightop = nullptr; // nullptr to be able to delete without further
name = "CBotAddExpr"; // debug
}
CBotAddExpr::~CBotAddExpr()
{
delete m_leftop;
delete m_rightop;
}
// compile une instruction de type A + B
CBotInstr* CBotAddExpr::Compile(CBotToken* &p, CBotStack* pStack)
{
CBotStack* pStk = pStack->TokenStack(); // one end of stack please
// looking statements that may be suitable to the left of the operation + or -
CBotInstr* left = CBotMulExpr::Compile( p, pStk ); // expression A * B left
if (left == nullptr) return pStack->Return(nullptr, pStk); // if error, transmit
// do we have the token + or - next?
if ( p->GetType() == ID_ADD ||
p->GetType() == ID_SUB) // more or less
{
CBotAddExpr* inst = new CBotAddExpr(); // element for operation
inst->SetToken(p); // stores the operation
int type1, type2;
type1 = pStack->GetType(); // what kind of the first operand?
p = p->Next(); // skip the token of the operation
// looking statements that may be suitable for right
if ( nullptr != (inst->m_rightop = CBotAddExpr::Compile( p, pStk )) ) // expression (...) rigth
{
// there is an acceptable second operand
type2 = pStack->GetType(); // what kind of results?
if ( type1 == type2 ) // are the results consistent ?
{
// ok so, saves the operand in the object
inst->m_leftop = left;
// and makes the object on demand
return pStack->Return(inst, pStk);
}
}
// in case of error, free the elements
delete left;
delete inst;
// and transmits the error that is on the stack
return pStack->Return(nullptr, pStk);
}
// if we are not dealing with an operation + or -
// goes to that requested, the operand (left) found
// place the object "addition"
return pStack->Return(left, pStk);
}
// operation is addition or subtraction
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
}