2012-03-09 16:08:05 +00:00
|
|
|
|
// * This file is part of the COLOBOT source code
|
|
|
|
|
// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
|
|
|
|
|
// *
|
|
|
|
|
// * 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 .
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
#include "CBot.h"
|
|
|
|
|
|
|
|
|
|
// divers constructeurs
|
|
|
|
|
|
|
|
|
|
CBotAddExpr::CBotAddExpr()
|
|
|
|
|
{
|
|
|
|
|
m_leftop =
|
|
|
|
|
m_rightop = NULL; // NULL pour pouvoir faire delete sans autre
|
|
|
|
|
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(); // un bout de pile svp
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// cherche des instructions qui peuvent convenir <20> gauche de l'op<6F>ration + ou -
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
CBotInstr* left = CBotMulExpr::Compile( p, pStk ); // expression A * B <20> gauche
|
2012-03-08 18:32:05 +00:00
|
|
|
|
if (left == NULL) return pStack->Return(NULL, pStk); // si erreur, la transmet
|
|
|
|
|
|
|
|
|
|
// est-ce qu'on a le token + ou - ensuite ?
|
|
|
|
|
|
|
|
|
|
if ( p->GetType() == ID_ADD ||
|
|
|
|
|
p->GetType() == ID_SUB) // plus ou moins
|
|
|
|
|
{
|
2012-03-09 16:08:05 +00:00
|
|
|
|
CBotAddExpr* inst = new CBotAddExpr(); // <20>l<EFBFBD>ment pour op<6F>ration
|
|
|
|
|
inst->SetToken(p); // m<>morise l'op<6F>ration
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
int type1, type2;
|
2012-03-09 16:08:05 +00:00
|
|
|
|
type1 = pStack->GetType(); // de quel type le premier op<6F>rande ?
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
p = p->Next(); // saute le token de l'op<6F>ration
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// cherche des instructions qui peuvent convenir <20> droite
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
if ( NULL != (inst->m_rightop = CBotAddExpr::Compile( p, pStk )) ) // expression (...) <20> droite
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// il y a un second op<6F>rande acceptable
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
type2 = pStack->GetType(); // de quel type le r<>sultat ?
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
if ( type1 == type2 ) // les r<>sultats sont-ils compatibles
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// si ok, enregistre l'op<6F>rande dans l'objet
|
2012-03-08 18:32:05 +00:00
|
|
|
|
inst->m_leftop = left;
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// et rend l'object <20> qui l'a demand<6E>
|
2012-03-08 18:32:05 +00:00
|
|
|
|
return pStack->Return(inst, pStk);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// en cas d'erreur, lib<69>re les <20>l<EFBFBD>ments
|
2012-03-08 18:32:05 +00:00
|
|
|
|
delete left;
|
|
|
|
|
delete inst;
|
|
|
|
|
// et transmet l'erreur qui se trouve sur la pile
|
|
|
|
|
return pStack->Return(NULL, pStk);
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// si on n'a pas affaire <20> une op<6F>ration + ou -
|
|
|
|
|
// rend <20> qui l'a demand<6E>, l'op<6F>rande (de gauche) trouv<75>
|
|
|
|
|
// <20> la place de l'objet "addition"
|
2012-03-08 18:32:05 +00:00
|
|
|
|
return pStack->Return(left, pStk);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// fait l'op<6F>ration d'addition ou de soustraction
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
BOOL CBotAddExpr::Execute(CBotStack* &pStack)
|
|
|
|
|
{
|
2012-03-09 16:08:05 +00:00
|
|
|
|
CBotStack* pStk1 = pStack->AddStack(this); // ajoute un <20>l<EFBFBD>ment <20> la pile
|
2012-03-08 18:32:05 +00:00
|
|
|
|
// ou le retrouve en cas de reprise
|
|
|
|
|
// if ( pSk1 == EOX ) return TRUE;
|
|
|
|
|
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// selon la reprise, on peut <20>tre dans l'un des 2 <20>tats
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
if ( pStk1->GetState() == 0 && // 1er <20>tat, <20>value l'op<6F>rande de gauche
|
2012-03-08 18:32:05 +00:00
|
|
|
|
!m_leftop->Execute(pStk1) ) return FALSE; // interrompu ici ?
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// passe <20> l'<27>tape suivante
|
|
|
|
|
pStk1->SetState(1); // pr<70>t pour la suite
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// demande un peu plus de stack pour ne pas toucher le r<>sultat de gauche
|
2012-03-08 18:32:05 +00:00
|
|
|
|
// qui se trouve sur la pile, justement.
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
CBotStack* pStk2 = pStk1->AddStack(); // ajoute un <20>l<EFBFBD>ment <20> la pile
|
2012-03-08 18:32:05 +00:00
|
|
|
|
// ou le retrouve en cas de reprise
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// 2e <20>tat, <20>value l'op<6F>rande de droite
|
2012-03-08 18:32:05 +00:00
|
|
|
|
if ( !m_rightop->Execute(pStk2) ) return FALSE; // interrompu ici ?
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
int type1 = pStk1->GetType(); // de quels types les r<>sultats ?
|
2012-03-08 18:32:05 +00:00
|
|
|
|
int type2 = pStk2->GetType();
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// cr<63>e une variable temporaire pour y mettre le r<>sultat
|
2012-03-08 18:32:05 +00:00
|
|
|
|
CBotVar* result = new CBotVar( NULL, MAX(type1, type2));
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// fait l'op<6F>ration selon la demande
|
2012-03-08 18:32:05 +00:00
|
|
|
|
switch (GetTokenType())
|
|
|
|
|
{
|
|
|
|
|
case ID_ADD:
|
|
|
|
|
result->Add(pStk1->GetVar(), pStk2->GetVar()); // additionne
|
|
|
|
|
break;
|
|
|
|
|
case ID_SUB:
|
|
|
|
|
result->Sub(pStk1->GetVar(), pStk2->GetVar()); // soustrait
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-03-09 16:08:05 +00:00
|
|
|
|
pStk2->SetVar(result); // met le r<>sultat sur la pile
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
pStk1->Return(pStk2); // lib<69>re la pile
|
|
|
|
|
return pStack->Return(pStk1); // transmet le r<>sultat
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|