Moving CBotExpression class in its own header and source files.
parent
d44df45d26
commit
3c1296b4b9
|
@ -58,6 +58,7 @@
|
||||||
#include "CBotInstr/CBotExprUnaire.h"
|
#include "CBotInstr/CBotExprUnaire.h"
|
||||||
#include "CBotInstr/CBotBoolExpr.h"
|
#include "CBotInstr/CBotBoolExpr.h"
|
||||||
#include "CBotInstr/CBotTwoOpExpr.h"
|
#include "CBotInstr/CBotTwoOpExpr.h"
|
||||||
|
#include "CBotInstr/CBotExpression.h"
|
||||||
|
|
||||||
// Local include
|
// Local include
|
||||||
|
|
||||||
|
@ -1345,276 +1346,6 @@ void CBotIString::RestoreState(CBotStack* &pj, bool bMain)
|
||||||
m_next2b->RestoreState(pile, bMain);
|
m_next2b->RestoreState(pile, bMain);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// compiles a statement such as " x = 123 " ou " z * 5 + 4 "
|
|
||||||
// with or without assignment
|
|
||||||
|
|
||||||
CBotExpression::CBotExpression()
|
|
||||||
{
|
|
||||||
m_leftop = nullptr;
|
|
||||||
m_rightop = nullptr;
|
|
||||||
name = "CBotExpression";
|
|
||||||
}
|
|
||||||
|
|
||||||
CBotExpression::~CBotExpression()
|
|
||||||
{
|
|
||||||
delete m_leftop;
|
|
||||||
delete m_rightop;
|
|
||||||
}
|
|
||||||
|
|
||||||
CBotInstr* CBotExpression::Compile(CBotToken* &p, CBotCStack* pStack)
|
|
||||||
{
|
|
||||||
CBotToken* pp = p;
|
|
||||||
|
|
||||||
CBotExpression* inst = new CBotExpression();
|
|
||||||
|
|
||||||
inst->m_leftop = CBotLeftExpr::Compile(p, pStack);
|
|
||||||
|
|
||||||
inst->SetToken(p);
|
|
||||||
int OpType = p->GetType();
|
|
||||||
|
|
||||||
if ( pStack->IsOk() &&
|
|
||||||
IsOfTypeList(p, ID_ASS, ID_ASSADD, ID_ASSSUB, ID_ASSMUL, ID_ASSDIV, ID_ASSMODULO,
|
|
||||||
ID_ASSAND, ID_ASSXOR, ID_ASSOR,
|
|
||||||
ID_ASSSL , ID_ASSSR, ID_ASSASR, 0 ))
|
|
||||||
{
|
|
||||||
if (inst->m_leftop == nullptr)
|
|
||||||
{
|
|
||||||
pStack->SetError(TX_BADLEFT, p->GetEnd());
|
|
||||||
delete inst;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inst->m_rightop = CBotExpression::Compile(p, pStack);
|
|
||||||
if (inst->m_rightop == nullptr)
|
|
||||||
{
|
|
||||||
delete inst;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
CBotTypResult type1 = pStack->GetTypResult();
|
|
||||||
|
|
||||||
// get the variable assigned to mark
|
|
||||||
CBotVar* var = nullptr;
|
|
||||||
inst->m_leftop->ExecuteVar(var, pStack);
|
|
||||||
if (var == nullptr)
|
|
||||||
{
|
|
||||||
delete inst;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (OpType != ID_ASS && !var->IsDefined())
|
|
||||||
{
|
|
||||||
pStack->SetError(TX_NOTINIT, pp);
|
|
||||||
delete inst;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
CBotTypResult type2 = var->GetTypResult();
|
|
||||||
|
|
||||||
// what types are acceptable?
|
|
||||||
switch (OpType)
|
|
||||||
{
|
|
||||||
case ID_ASS:
|
|
||||||
// if (type2 == CBotTypClass) type2 = -1;
|
|
||||||
if ((type1.Eq(CBotTypPointer) && type2.Eq(CBotTypPointer)) ||
|
|
||||||
(type1.Eq(CBotTypClass) && type2.Eq(CBotTypClass) ) )
|
|
||||||
{
|
|
||||||
/* CBotClass* c1 = type1.GetClass();
|
|
||||||
CBotClass* c2 = type2.GetClass();
|
|
||||||
if (!c1->IsChildOf(c2)) type2.SetType(-1);
|
|
||||||
//- if (!type1.Eq(CBotTypClass)) var->SetPointer(pStack->GetVar()->GetPointer());*/
|
|
||||||
var->SetInit(CBotVar::InitType::IS_POINTER);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
var->SetInit(CBotVar::InitType::DEF);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case ID_ASSADD:
|
|
||||||
if (type2.Eq(CBotTypBoolean) ||
|
|
||||||
type2.Eq(CBotTypPointer) ) type2 = -1; // numbers and strings
|
|
||||||
break;
|
|
||||||
case ID_ASSSUB:
|
|
||||||
case ID_ASSMUL:
|
|
||||||
case ID_ASSDIV:
|
|
||||||
case ID_ASSMODULO:
|
|
||||||
if (type2.GetType() >= CBotTypBoolean) type2 = -1; // numbers only
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!TypeCompatible(type1, type2, OpType))
|
|
||||||
{
|
|
||||||
pStack->SetError(TX_BADTYPE, &inst->m_token);
|
|
||||||
delete inst;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return inst; // compatible type?
|
|
||||||
}
|
|
||||||
|
|
||||||
delete inst;
|
|
||||||
int start, end, error = pStack->GetError(start, end);
|
|
||||||
|
|
||||||
p = pp; // returns to the top
|
|
||||||
pStack->SetError(0,0); // forget the error
|
|
||||||
|
|
||||||
CBotInstr* i = CBotTwoOpExpr::Compile(p, pStack); // tries without assignment
|
|
||||||
if (i != nullptr && error == TX_PRIVATE && p->GetType() == ID_ASS)
|
|
||||||
pStack->ResetError(error, start, end);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// executes an expression with assignment
|
|
||||||
|
|
||||||
bool CBotExpression::Execute(CBotStack* &pj)
|
|
||||||
{
|
|
||||||
CBotStack* pile = pj->AddStack(this);
|
|
||||||
|
|
||||||
// CBotToken* pToken = m_leftop->GetToken();
|
|
||||||
|
|
||||||
CBotVar* pVar = nullptr;
|
|
||||||
|
|
||||||
CBotStack* pile1 = pile;
|
|
||||||
|
|
||||||
CBotVar::InitType initKind = CBotVar::InitType::DEF;
|
|
||||||
CBotVar* result = nullptr;
|
|
||||||
|
|
||||||
// must be done before any indexes (stack can be changed)
|
|
||||||
if (!m_leftop->ExecuteVar(pVar, pile, nullptr, false)) return false; // variable before accessing the value on the right
|
|
||||||
|
|
||||||
if ( pile1->GetState()==0)
|
|
||||||
{
|
|
||||||
pile1->SetCopyVar(pVar); // keeps the copy on the stack (if interrupted)
|
|
||||||
pile1->IncState();
|
|
||||||
}
|
|
||||||
|
|
||||||
CBotStack* pile2 = pile->AddStack();
|
|
||||||
|
|
||||||
if ( pile2->GetState()==0)
|
|
||||||
{
|
|
||||||
if (m_rightop && !m_rightop->Execute(pile2)) return false; // initial value // interrupted?
|
|
||||||
pile2->IncState();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pile1->GetState() == 1)
|
|
||||||
{
|
|
||||||
if (m_token.GetType() != ID_ASS)
|
|
||||||
{
|
|
||||||
pVar = pile1->GetVar(); // recovers if interrupted
|
|
||||||
initKind = pVar->GetInit();
|
|
||||||
if (initKind == CBotVar::InitType::IS_NAN)
|
|
||||||
{
|
|
||||||
pile2->SetError(TX_OPNAN, m_leftop->GetToken());
|
|
||||||
return pj->Return(pile2);
|
|
||||||
}
|
|
||||||
result = CBotVar::Create("", pVar->GetTypResult(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (m_token.GetType())
|
|
||||||
{
|
|
||||||
case ID_ASS:
|
|
||||||
break;
|
|
||||||
case ID_ASSADD:
|
|
||||||
result->Add(pile1->GetVar(), pile2->GetVar());
|
|
||||||
pile2->SetVar(result);
|
|
||||||
break;
|
|
||||||
case ID_ASSSUB:
|
|
||||||
result->Sub(pile1->GetVar(), pile2->GetVar());
|
|
||||||
pile2->SetVar(result);
|
|
||||||
break;
|
|
||||||
case ID_ASSMUL:
|
|
||||||
result->Mul(pile1->GetVar(), pile2->GetVar());
|
|
||||||
pile2->SetVar(result);
|
|
||||||
break;
|
|
||||||
case ID_ASSDIV:
|
|
||||||
if (initKind != CBotVar::InitType::UNDEF &&
|
|
||||||
result->Div(pile1->GetVar(), pile2->GetVar()))
|
|
||||||
pile2->SetError(TX_DIVZERO, &m_token);
|
|
||||||
pile2->SetVar(result);
|
|
||||||
break;
|
|
||||||
case ID_ASSMODULO:
|
|
||||||
if (initKind != CBotVar::InitType::UNDEF &&
|
|
||||||
result->Modulo(pile1->GetVar(), pile2->GetVar()))
|
|
||||||
pile2->SetError(TX_DIVZERO, &m_token);
|
|
||||||
pile2->SetVar(result);
|
|
||||||
break;
|
|
||||||
case ID_ASSAND:
|
|
||||||
result->And(pile1->GetVar(), pile2->GetVar());
|
|
||||||
pile2->SetVar(result);
|
|
||||||
break;
|
|
||||||
case ID_ASSXOR:
|
|
||||||
result->XOr(pile1->GetVar(), pile2->GetVar());
|
|
||||||
pile2->SetVar(result);
|
|
||||||
break;
|
|
||||||
case ID_ASSOR:
|
|
||||||
result->Or(pile1->GetVar(), pile2->GetVar());
|
|
||||||
pile2->SetVar(result);
|
|
||||||
break;
|
|
||||||
case ID_ASSSL:
|
|
||||||
result->SL(pile1->GetVar(), pile2->GetVar());
|
|
||||||
pile2->SetVar(result);
|
|
||||||
break;
|
|
||||||
case ID_ASSSR:
|
|
||||||
result->SR(pile1->GetVar(), pile2->GetVar());
|
|
||||||
pile2->SetVar(result);
|
|
||||||
break;
|
|
||||||
case ID_ASSASR:
|
|
||||||
result->ASR(pile1->GetVar(), pile2->GetVar());
|
|
||||||
pile2->SetVar(result);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
if (initKind == CBotVar::InitType::UNDEF)
|
|
||||||
pile2->SetError(TX_NOTINIT, m_leftop->GetToken());
|
|
||||||
|
|
||||||
pile1->IncState();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_leftop->Execute( pile2, pile1 ))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return pj->Return(pile2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CBotExpression::RestoreState(CBotStack* &pj, bool bMain)
|
|
||||||
{
|
|
||||||
if (bMain)
|
|
||||||
{
|
|
||||||
// CBotToken* pToken = m_leftop->GetToken();
|
|
||||||
// CBotVar* pVar = nullptr;
|
|
||||||
|
|
||||||
CBotStack* pile = pj->RestoreStack(this);
|
|
||||||
if (pile == nullptr) return;
|
|
||||||
|
|
||||||
CBotStack* pile1 = pile;
|
|
||||||
|
|
||||||
if ( pile1->GetState()==0)
|
|
||||||
{
|
|
||||||
m_leftop->RestoreStateVar(pile, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_leftop->RestoreStateVar(pile, false);
|
|
||||||
|
|
||||||
CBotStack* pile2 = pile->RestoreStack();
|
|
||||||
if (pile2 == nullptr) return;
|
|
||||||
|
|
||||||
if ( pile2->GetState()==0)
|
|
||||||
{
|
|
||||||
if (m_rightop) m_rightop->RestoreState(pile2, bMain);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////
|
||||||
// compile a statement such as "(condition)"
|
// compile a statement such as "(condition)"
|
||||||
|
|
|
@ -708,25 +708,6 @@ public:
|
||||||
void RestoreStateVar(CBotStack* &pj, bool bMain) override;
|
void RestoreStateVar(CBotStack* &pj, bool bMain) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
// expressions like
|
|
||||||
// x = a;
|
|
||||||
// x * y + 3;
|
|
||||||
|
|
||||||
class CBotExpression : public CBotInstr
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
CBotLeftExpr* m_leftop; // left operand
|
|
||||||
CBotInstr* m_rightop; // right operant
|
|
||||||
|
|
||||||
public:
|
|
||||||
CBotExpression();
|
|
||||||
~CBotExpression();
|
|
||||||
static
|
|
||||||
CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
|
|
||||||
bool Execute(CBotStack* &pStack) override;
|
|
||||||
void RestoreState(CBotStack* &pj, bool bMain) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MAX(a,b) ((a>b) ? a : b)
|
#define MAX(a,b) ((a>b) ? a : b)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include "CBotInstr/CBotBlock.h"
|
#include "CBotInstr/CBotBlock.h"
|
||||||
#include "CBotInstr/CBotTwoOpExpr.h"
|
#include "CBotInstr/CBotTwoOpExpr.h"
|
||||||
|
#include "CBotInstr/CBotExpression.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
// Modules inlcude
|
// Modules inlcude
|
||||||
#include "CBotCatch.h"
|
#include "CBotCatch.h"
|
||||||
#include "CBotBlock.h"
|
#include "CBotBlock.h"
|
||||||
|
#include "CBotExpression.h"
|
||||||
|
|
||||||
// Local include
|
// Local include
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
// Modules inlcude
|
// Modules inlcude
|
||||||
#include "CBotExprVar.h"
|
#include "CBotExprVar.h"
|
||||||
#include "CBotInstrMethode.h"
|
#include "CBotInstrMethode.h"
|
||||||
|
#include "CBotExpression.h"
|
||||||
|
|
||||||
// Local include
|
// Local include
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,290 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Modules inlcude
|
||||||
|
#include "CBotExpression.h"
|
||||||
|
#include "CBotTwoOpExpr.h"
|
||||||
|
|
||||||
|
// Local include
|
||||||
|
|
||||||
|
// Global include
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
CBotExpression::CBotExpression()
|
||||||
|
{
|
||||||
|
m_leftop = nullptr;
|
||||||
|
m_rightop = nullptr;
|
||||||
|
name = "CBotExpression";
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
CBotExpression::~CBotExpression()
|
||||||
|
{
|
||||||
|
delete m_leftop;
|
||||||
|
delete m_rightop;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
CBotInstr* CBotExpression::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
|
{
|
||||||
|
CBotToken* pp = p;
|
||||||
|
|
||||||
|
CBotExpression* inst = new CBotExpression();
|
||||||
|
|
||||||
|
inst->m_leftop = CBotLeftExpr::Compile(p, pStack);
|
||||||
|
|
||||||
|
inst->SetToken(p);
|
||||||
|
int OpType = p->GetType();
|
||||||
|
|
||||||
|
if ( pStack->IsOk() &&
|
||||||
|
IsOfTypeList(p, ID_ASS, ID_ASSADD, ID_ASSSUB, ID_ASSMUL, ID_ASSDIV, ID_ASSMODULO,
|
||||||
|
ID_ASSAND, ID_ASSXOR, ID_ASSOR,
|
||||||
|
ID_ASSSL , ID_ASSSR, ID_ASSASR, 0 ))
|
||||||
|
{
|
||||||
|
if (inst->m_leftop == nullptr)
|
||||||
|
{
|
||||||
|
pStack->SetError(TX_BADLEFT, p->GetEnd());
|
||||||
|
delete inst;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inst->m_rightop = CBotExpression::Compile(p, pStack);
|
||||||
|
if (inst->m_rightop == nullptr)
|
||||||
|
{
|
||||||
|
delete inst;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CBotTypResult type1 = pStack->GetTypResult();
|
||||||
|
|
||||||
|
// get the variable assigned to mark
|
||||||
|
CBotVar* var = nullptr;
|
||||||
|
inst->m_leftop->ExecuteVar(var, pStack);
|
||||||
|
if (var == nullptr)
|
||||||
|
{
|
||||||
|
delete inst;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OpType != ID_ASS && !var->IsDefined())
|
||||||
|
{
|
||||||
|
pStack->SetError(TX_NOTINIT, pp);
|
||||||
|
delete inst;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CBotTypResult type2 = var->GetTypResult();
|
||||||
|
|
||||||
|
// what types are acceptable?
|
||||||
|
switch (OpType)
|
||||||
|
{
|
||||||
|
case ID_ASS:
|
||||||
|
// if (type2 == CBotTypClass) type2 = -1;
|
||||||
|
if ((type1.Eq(CBotTypPointer) && type2.Eq(CBotTypPointer)) ||
|
||||||
|
(type1.Eq(CBotTypClass) && type2.Eq(CBotTypClass) ) )
|
||||||
|
{
|
||||||
|
/* CBotClass* c1 = type1.GetClass();
|
||||||
|
CBotClass* c2 = type2.GetClass();
|
||||||
|
if (!c1->IsChildOf(c2)) type2.SetType(-1);
|
||||||
|
//- if (!type1.Eq(CBotTypClass)) var->SetPointer(pStack->GetVar()->GetPointer());*/
|
||||||
|
var->SetInit(CBotVar::InitType::IS_POINTER);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
var->SetInit(CBotVar::InitType::DEF);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ID_ASSADD:
|
||||||
|
if (type2.Eq(CBotTypBoolean) ||
|
||||||
|
type2.Eq(CBotTypPointer) ) type2 = -1; // numbers and strings
|
||||||
|
break;
|
||||||
|
case ID_ASSSUB:
|
||||||
|
case ID_ASSMUL:
|
||||||
|
case ID_ASSDIV:
|
||||||
|
case ID_ASSMODULO:
|
||||||
|
if (type2.GetType() >= CBotTypBoolean) type2 = -1; // numbers only
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TypeCompatible(type1, type2, OpType))
|
||||||
|
{
|
||||||
|
pStack->SetError(TX_BADTYPE, &inst->m_token);
|
||||||
|
delete inst;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return inst; // compatible type?
|
||||||
|
}
|
||||||
|
|
||||||
|
delete inst;
|
||||||
|
int start, end, error = pStack->GetError(start, end);
|
||||||
|
|
||||||
|
p = pp; // returns to the top
|
||||||
|
pStack->SetError(0,0); // forget the error
|
||||||
|
|
||||||
|
CBotInstr* i = CBotTwoOpExpr::Compile(p, pStack); // tries without assignment
|
||||||
|
if (i != nullptr && error == TX_PRIVATE && p->GetType() == ID_ASS)
|
||||||
|
pStack->ResetError(error, start, end);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool CBotExpression::Execute(CBotStack* &pj)
|
||||||
|
{
|
||||||
|
CBotStack* pile = pj->AddStack(this);
|
||||||
|
|
||||||
|
// CBotToken* pToken = m_leftop->GetToken();
|
||||||
|
|
||||||
|
CBotVar* pVar = nullptr;
|
||||||
|
|
||||||
|
CBotStack* pile1 = pile;
|
||||||
|
|
||||||
|
CBotVar::InitType initKind = CBotVar::InitType::DEF;
|
||||||
|
CBotVar* result = nullptr;
|
||||||
|
|
||||||
|
// must be done before any indexes (stack can be changed)
|
||||||
|
if (!m_leftop->ExecuteVar(pVar, pile, nullptr, false)) return false; // variable before accessing the value on the right
|
||||||
|
|
||||||
|
if ( pile1->GetState()==0)
|
||||||
|
{
|
||||||
|
pile1->SetCopyVar(pVar); // keeps the copy on the stack (if interrupted)
|
||||||
|
pile1->IncState();
|
||||||
|
}
|
||||||
|
|
||||||
|
CBotStack* pile2 = pile->AddStack();
|
||||||
|
|
||||||
|
if ( pile2->GetState()==0)
|
||||||
|
{
|
||||||
|
if (m_rightop && !m_rightop->Execute(pile2)) return false; // initial value // interrupted?
|
||||||
|
pile2->IncState();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pile1->GetState() == 1)
|
||||||
|
{
|
||||||
|
if (m_token.GetType() != ID_ASS)
|
||||||
|
{
|
||||||
|
pVar = pile1->GetVar(); // recovers if interrupted
|
||||||
|
initKind = pVar->GetInit();
|
||||||
|
if (initKind == CBotVar::InitType::IS_NAN)
|
||||||
|
{
|
||||||
|
pile2->SetError(TX_OPNAN, m_leftop->GetToken());
|
||||||
|
return pj->Return(pile2);
|
||||||
|
}
|
||||||
|
result = CBotVar::Create("", pVar->GetTypResult(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (m_token.GetType())
|
||||||
|
{
|
||||||
|
case ID_ASS:
|
||||||
|
break;
|
||||||
|
case ID_ASSADD:
|
||||||
|
result->Add(pile1->GetVar(), pile2->GetVar());
|
||||||
|
pile2->SetVar(result);
|
||||||
|
break;
|
||||||
|
case ID_ASSSUB:
|
||||||
|
result->Sub(pile1->GetVar(), pile2->GetVar());
|
||||||
|
pile2->SetVar(result);
|
||||||
|
break;
|
||||||
|
case ID_ASSMUL:
|
||||||
|
result->Mul(pile1->GetVar(), pile2->GetVar());
|
||||||
|
pile2->SetVar(result);
|
||||||
|
break;
|
||||||
|
case ID_ASSDIV:
|
||||||
|
if (initKind != CBotVar::InitType::UNDEF &&
|
||||||
|
result->Div(pile1->GetVar(), pile2->GetVar()))
|
||||||
|
pile2->SetError(TX_DIVZERO, &m_token);
|
||||||
|
pile2->SetVar(result);
|
||||||
|
break;
|
||||||
|
case ID_ASSMODULO:
|
||||||
|
if (initKind != CBotVar::InitType::UNDEF &&
|
||||||
|
result->Modulo(pile1->GetVar(), pile2->GetVar()))
|
||||||
|
pile2->SetError(TX_DIVZERO, &m_token);
|
||||||
|
pile2->SetVar(result);
|
||||||
|
break;
|
||||||
|
case ID_ASSAND:
|
||||||
|
result->And(pile1->GetVar(), pile2->GetVar());
|
||||||
|
pile2->SetVar(result);
|
||||||
|
break;
|
||||||
|
case ID_ASSXOR:
|
||||||
|
result->XOr(pile1->GetVar(), pile2->GetVar());
|
||||||
|
pile2->SetVar(result);
|
||||||
|
break;
|
||||||
|
case ID_ASSOR:
|
||||||
|
result->Or(pile1->GetVar(), pile2->GetVar());
|
||||||
|
pile2->SetVar(result);
|
||||||
|
break;
|
||||||
|
case ID_ASSSL:
|
||||||
|
result->SL(pile1->GetVar(), pile2->GetVar());
|
||||||
|
pile2->SetVar(result);
|
||||||
|
break;
|
||||||
|
case ID_ASSSR:
|
||||||
|
result->SR(pile1->GetVar(), pile2->GetVar());
|
||||||
|
pile2->SetVar(result);
|
||||||
|
break;
|
||||||
|
case ID_ASSASR:
|
||||||
|
result->ASR(pile1->GetVar(), pile2->GetVar());
|
||||||
|
pile2->SetVar(result);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
if (initKind == CBotVar::InitType::UNDEF)
|
||||||
|
pile2->SetError(TX_NOTINIT, m_leftop->GetToken());
|
||||||
|
|
||||||
|
pile1->IncState();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_leftop->Execute( pile2, pile1 ))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return pj->Return(pile2);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void CBotExpression::RestoreState(CBotStack* &pj, bool bMain)
|
||||||
|
{
|
||||||
|
if (bMain)
|
||||||
|
{
|
||||||
|
// CBotToken* pToken = m_leftop->GetToken();
|
||||||
|
// CBotVar* pVar = nullptr;
|
||||||
|
|
||||||
|
CBotStack* pile = pj->RestoreStack(this);
|
||||||
|
if (pile == nullptr) return;
|
||||||
|
|
||||||
|
CBotStack* pile1 = pile;
|
||||||
|
|
||||||
|
if ( pile1->GetState()==0)
|
||||||
|
{
|
||||||
|
m_leftop->RestoreStateVar(pile, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_leftop->RestoreStateVar(pile, false);
|
||||||
|
|
||||||
|
CBotStack* pile2 = pile->RestoreStack();
|
||||||
|
if (pile2 == nullptr) return;
|
||||||
|
|
||||||
|
if ( pile2->GetState()==0)
|
||||||
|
{
|
||||||
|
if (m_rightop) m_rightop->RestoreState(pile2, bMain);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Modules inlcude
|
||||||
|
#include "CBot.h"
|
||||||
|
|
||||||
|
// Local include
|
||||||
|
|
||||||
|
// Global include
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The CBotExpression class Compiles a statement with or without
|
||||||
|
* assignment.
|
||||||
|
* eg :
|
||||||
|
* - x = a;
|
||||||
|
* - x * y + 3;
|
||||||
|
* - x = 123
|
||||||
|
* - z * 5 + 4
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// compiles a statement such as " " ou " z * 5 + 4 "
|
||||||
|
//
|
||||||
|
|
||||||
|
class CBotExpression : public CBotInstr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief CBotExpression
|
||||||
|
*/
|
||||||
|
CBotExpression();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief ~CBotExpression
|
||||||
|
*/
|
||||||
|
~CBotExpression();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Compile
|
||||||
|
* \param p
|
||||||
|
* \param pStack
|
||||||
|
* \return
|
||||||
|
*/
|
||||||
|
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Execute Executes an expression with assignment.
|
||||||
|
* \param pStack
|
||||||
|
* \return
|
||||||
|
*/
|
||||||
|
bool Execute(CBotStack* &pStack) override;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief RestoreState
|
||||||
|
* \param pj
|
||||||
|
* \param bMain
|
||||||
|
*/
|
||||||
|
void RestoreState(CBotStack* &pj, bool bMain) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! Left operand
|
||||||
|
CBotLeftExpr* m_leftop;
|
||||||
|
//! Right operand
|
||||||
|
CBotInstr* m_rightop;
|
||||||
|
};
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
// Modules inlcude
|
// Modules inlcude
|
||||||
#include "CBotInstrCall.h"
|
#include "CBotInstrCall.h"
|
||||||
|
#include "CBotExpression.h"
|
||||||
|
|
||||||
// Local include
|
// Local include
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
// Modules inlcude
|
// Modules inlcude
|
||||||
#include "CBotListExpression.h"
|
#include "CBotListExpression.h"
|
||||||
|
#include "CBotExpression.h"
|
||||||
|
|
||||||
// Local include
|
// Local include
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "CBotNew.h"
|
#include "CBotNew.h"
|
||||||
#include "CBotExprNull.h"
|
#include "CBotExprNull.h"
|
||||||
#include "CBotExprNan.h"
|
#include "CBotExprNan.h"
|
||||||
|
#include "CBotExpression.h"
|
||||||
|
|
||||||
// Local include
|
// Local include
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "CBotSwitch.h"
|
#include "CBotSwitch.h"
|
||||||
#include "CBotCase.h"
|
#include "CBotCase.h"
|
||||||
#include "CBotBlock.h"
|
#include "CBotBlock.h"
|
||||||
|
#include "CBotExpression.h"
|
||||||
|
|
||||||
// Local include
|
// Local include
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
// Modules inlcude
|
// Modules inlcude
|
||||||
#include "CBotThrow.h"
|
#include "CBotThrow.h"
|
||||||
|
#include "CBotExpression.h"
|
||||||
|
|
||||||
// Local include
|
// Local include
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "CBotTwoOpExpr.h"
|
#include "CBotTwoOpExpr.h"
|
||||||
#include "CBotParExpr.h"
|
#include "CBotParExpr.h"
|
||||||
#include "CBotLogicExpr.h"
|
#include "CBotLogicExpr.h"
|
||||||
|
#include "CBotExpression.h"
|
||||||
#include "CBot.h"
|
#include "CBot.h"
|
||||||
|
|
||||||
// Local include
|
// Local include
|
||||||
|
|
|
@ -37,6 +37,7 @@ set(SOURCES
|
||||||
CBotInstr/CBotBoolExpr.cpp
|
CBotInstr/CBotBoolExpr.cpp
|
||||||
CBotInstr/CBotLogicExpr.cpp
|
CBotInstr/CBotLogicExpr.cpp
|
||||||
CBotInstr/CBotTwoOpExpr.cpp
|
CBotInstr/CBotTwoOpExpr.cpp
|
||||||
|
CBotInstr/CBotExpression.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Includes
|
# Includes
|
||||||
|
|
Loading…
Reference in New Issue