diff options
Diffstat (limited to 'src/CBot/CBotIf.cpp')
-rw-r--r-- | src/CBot/CBotIf.cpp | 320 |
1 files changed, 161 insertions, 159 deletions
diff --git a/src/CBot/CBotIf.cpp b/src/CBot/CBotIf.cpp index 178992e..c1dc833 100644 --- a/src/CBot/CBotIf.cpp +++ b/src/CBot/CBotIf.cpp @@ -1,159 +1,161 @@ -// * 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 http://www.gnu.org/licenses/.///////////////////////////////////////////////////////////////////////
-// instruction if (condition) opération1 else opération2;
-
-#include "CBot.h"
-
-// les divers constructeurs / destructeurs
-CBotIf::CBotIf()
-{
- m_Condition =
- m_Block =
- m_BlockElse = NULL; // NULL pour pouvoir faire delete directement
- name = "CBotIf"; // debug
-}
-
-CBotIf::~CBotIf()
-{
- delete m_Condition; // libère la condition
- delete m_Block; // libère le bloc d'instruction1
- delete m_BlockElse; // libère le bloc d'instruction2
-}
-
-// compilation (routine statique)
-// appelé lorsque le token "if" a été trouvé
-
-CBotInstr* CBotIf::Compile(CBotToken* &p, CBotCStack* pStack)
-{
- CBotToken* pp = p; // conserve le ^au token (début instruction)
-
- if (!IsOfType(p, ID_IF)) return NULL; // ne doit jamais arriver
-
- CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp
-
- CBotIf* inst = new CBotIf(); // crée l'object
- inst->SetToken( pp );
-
- if ( NULL != (inst->m_Condition = CBotCondition::Compile( p, pStk )) )
- {
- // la condition existe bel et bien
-
- inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk, true );
- if ( pStk->IsOk() )
- {
- // le bloc d'instruction est ok (peut être vide)
-
- // regarde si l'instruction suivante est le token "else"
- if (IsOfType(p, ID_ELSE))
- {
- // si oui, compile le bloc d'instruction qui suit
- inst->m_BlockElse = CBotBlock::CompileBlkOrInst( p, pStk, true );
- if (!pStk->IsOk())
- {
- // il n'y a pas de bloc correct après le else
- // libère l'objet, et transmet l'erreur qui est sur la pile
- delete inst;
- return pStack->Return(NULL, pStk);
- }
- }
-
- // rend l'object correct à qui le demande.
- return pStack->Return(inst, pStk);
- }
- }
-
- // erreur, libère l'objet
- delete inst;
- // et transmet l'erreur qui se trouve sur la pile.
- return pStack->Return(NULL, pStk);
-}
-
-
-// exécution de l'instruction
-
-bool CBotIf :: Execute(CBotStack* &pj)
-{
- CBotStack* pile = pj->AddStack(this); // ajoute un élément à la pile
- // ou le retrouve en cas de reprise
-// if ( pile == EOX ) return true;
-
- if ( pile->IfStep() ) return false;
-
- // selon la reprise, on peut être dans l'un des 2 états
- if( pile->GivState() == 0 )
- {
- // évalue la condition
- if ( !m_Condition->Execute(pile) ) return false; // interrompu ici ?
-
- // termine s'il y a une erreur
- if ( !pile->IsOk() )
- {
- return pj->Return(pile); // transmet le résultat et libère la pile
- }
-
- // passe dans le second état
- if (!pile->SetState(1)) return false; // prêt pour la suite
- }
-
- // second état, évalue les instructions associées
- // le résultat de la condition est sur la pile
-
- if ( pile->GivVal() == true ) // condition était vraie ?
- {
- if ( m_Block != NULL && // bloc peut être absent
- !m_Block->Execute(pile) ) return false; // interrompu ici ?
- }
- else
- {
- if ( m_BlockElse != NULL && // s'il existe un bloc alternatif
- !m_BlockElse->Execute(pile) ) return false; // interrompu ici
- }
-
- // transmet le résultat et libère la pile
- return pj->Return(pile);
-}
-
-
-void CBotIf :: RestoreState(CBotStack* &pj, bool bMain)
-{
- if ( !bMain ) return;
-
- CBotStack* pile = pj->RestoreStack(this); // ajoute un élément à la pile
- if ( pile == NULL ) return;
-
- // selon la reprise, on peut être dans l'un des 2 états
- if( pile->GivState() == 0 )
- {
- // évalue la condition
- m_Condition->RestoreState(pile, bMain); // interrompu ici !
- return;
- }
-
- // second état, évalue les instructions associées
- // le résultat de la condition est sur la pile
-
- if ( pile->GivVal() == true ) // condition était vraie ?
- {
- if ( m_Block != NULL ) // bloc peut être absent
- m_Block->RestoreState(pile, bMain); // interrompu ici !
- }
- else
- {
- if ( m_BlockElse != NULL ) // s'il existe un bloc alternatif
- m_BlockElse->RestoreState(pile, bMain); // interrompu ici !
- }
-}
-
+// * 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 http://www.gnu.org/licenses/. + +/////////////////////////////////////////////////////////////////////// +// instruction if (condition) operation1 else operation2; + +#include "CBot.h" + +// various constructors / destructors +CBotIf::CBotIf() +{ + m_Condition = + m_Block = + m_BlockElse = NULL; // NULL so that delete is not possible further + name = "CBotIf"; // debug +} + +CBotIf::~CBotIf() +{ + delete m_Condition; // frees the condition + delete m_Block; // frees the block of instruction1 + delete m_BlockElse; // frees the block of instruction2 +} + +// compilation (static routine) +// called when the token "if" has been found + +CBotInstr* CBotIf::Compile(CBotToken* &p, CBotCStack* pStack) +{ + CBotToken* pp = p; // preserves at the ^ token (starting instruction) + + if (!IsOfType(p, ID_IF)) return NULL; // should never happen + + CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp + + CBotIf* inst = new CBotIf(); // create the object + inst->SetToken( pp ); + + if ( NULL != (inst->m_Condition = CBotCondition::Compile( p, pStk )) ) + { + // the condition does exist + + inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk, true ); + if ( pStk->IsOk() ) + { + // the statement block is ok (can be empty) + + // see if the next instruction is the token "else" + if (IsOfType(p, ID_ELSE)) + { + // if so, compiles the following statement block + inst->m_BlockElse = CBotBlock::CompileBlkOrInst( p, pStk, true ); + if (!pStk->IsOk()) + { + // there is no correct block after the else + // frees the object, and transmits the error that is on the stack + delete inst; + return pStack->Return(NULL, pStk); + } + } + + // return the corrent object to the application + return pStack->Return(inst, pStk); + } + } + + // error, frees the object + delete inst; + // and transmits the error that is on the stack. + return pStack->Return(NULL, pStk); +} + + +// execution of the instruction + +bool CBotIf :: Execute(CBotStack* &pj) +{ + CBotStack* pile = pj->AddStack(this); // adds an item to the stack + // or found in case of recovery +// if ( pile == EOX ) return true; + + if ( pile->IfStep() ) return false; + + // according to recovery, it may be in one of two states + if( pile->GivState() == 0 ) + { + // evaluates the condition + if ( !m_Condition->Execute(pile) ) return false; // interrupted here? + + // terminates if there is an error + if ( !pile->IsOk() ) + { + return pj->Return(pile); // returns the results and releases the stack + } + + // passes into the second state + if (!pile->SetState(1)) return false; // ready for further + } + + // second state, evaluates the associated instructions + // the result of the condition is on the stack + + if ( pile->GivVal() == true ) // condition was true? + { + if ( m_Block != NULL && // block may be absent + !m_Block->Execute(pile) ) return false; // interrupted here? + } + else + { + if ( m_BlockElse != NULL && // if there is an alternate block + !m_BlockElse->Execute(pile) ) return false; // interrupted here + } + + // sends the results and releases the stack + return pj->Return(pile); +} + + +void CBotIf :: RestoreState(CBotStack* &pj, bool bMain) +{ + if ( !bMain ) return; + + CBotStack* pile = pj->RestoreStack(this); // adds an item to the stack + if ( pile == NULL ) return; + + // according to recovery, it may be in one of two states + if( pile->GivState() == 0 ) + { + // evaluates the condition + m_Condition->RestoreState(pile, bMain); // interrupted here! + return; + } + + // second state, evaluates the associated instructions + // the result of the condition is on the stack + + if ( pile->GivVal() == true ) // condition was true? + { + if ( m_Block != NULL ) // block may be absent + m_Block->RestoreState(pile, bMain); // interrupted here! + } + else + { + if ( m_BlockElse != NULL ) // if there is an alternate block + m_BlockElse->RestoreState(pile, bMain); // interrupted here! + } +} + |