2012-03-19 11:44:39 +00:00
|
|
|
|
// * This file is part of the COLOBOT source code
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// * 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
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// * along with this program. If not, see http://www.gnu.org/licenses/.///////////////////////////////////////////////////////////////////////
|
|
|
|
|
// instruction if (condition) op<6F>ration1 else op<6F>ration2;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
#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()
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
delete m_Condition; // lib<69>re la condition
|
|
|
|
|
delete m_Block; // lib<69>re le bloc d'instruction1
|
|
|
|
|
delete m_BlockElse; // lib<69>re le bloc d'instruction2
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// compilation (routine statique)
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// appel<65> lorsque le token "if" a <20>t<EFBFBD> trouv<75>
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
CBotInstr* CBotIf::Compile(CBotToken* &p, CBotCStack* pStack)
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
CBotToken* pp = p; // conserve le ^au token (d<>but instruction)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
if (!IsOfType(p, ID_IF)) return NULL; // ne doit jamais arriver
|
|
|
|
|
|
|
|
|
|
CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
CBotIf* inst = new CBotIf(); // cr<63>e l'object
|
2012-03-08 18:32:05 +00:00
|
|
|
|
inst->SetToken( pp );
|
|
|
|
|
|
|
|
|
|
if ( NULL != (inst->m_Condition = CBotCondition::Compile( p, pStk )) )
|
|
|
|
|
{
|
|
|
|
|
// la condition existe bel et bien
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk, true );
|
2012-03-08 18:32:05 +00:00
|
|
|
|
if ( pStk->IsOk() )
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// le bloc d'instruction est ok (peut <20>tre vide)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
// regarde si l'instruction suivante est le token "else"
|
|
|
|
|
if (IsOfType(p, ID_ELSE))
|
|
|
|
|
{
|
|
|
|
|
// si oui, compile le bloc d'instruction qui suit
|
2012-07-04 20:14:28 +00:00
|
|
|
|
inst->m_BlockElse = CBotBlock::CompileBlkOrInst( p, pStk, true );
|
2012-03-08 18:32:05 +00:00
|
|
|
|
if (!pStk->IsOk())
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// il n'y a pas de bloc correct apr<70>s le else
|
|
|
|
|
// lib<69>re l'objet, et transmet l'erreur qui est sur la pile
|
2012-03-08 18:32:05 +00:00
|
|
|
|
delete inst;
|
|
|
|
|
return pStack->Return(NULL, pStk);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// rend l'object correct <20> qui le demande.
|
2012-03-08 18:32:05 +00:00
|
|
|
|
return pStack->Return(inst, pStk);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// erreur, lib<69>re l'objet
|
2012-03-08 18:32:05 +00:00
|
|
|
|
delete inst;
|
|
|
|
|
// et transmet l'erreur qui se trouve sur la pile.
|
|
|
|
|
return pStack->Return(NULL, pStk);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// ex<65>cution de l'instruction
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotIf :: Execute(CBotStack* &pj)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
CBotStack* pile = pj->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
|
2012-07-04 20:14:28 +00:00
|
|
|
|
// if ( pile == EOX ) return true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( pile->IfStep() ) return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// selon la reprise, on peut <20>tre dans l'un des 2 <20>tats
|
2012-03-08 18:32:05 +00:00
|
|
|
|
if( pile->GivState() == 0 )
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// <20>value la condition
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( !m_Condition->Execute(pile) ) return false; // interrompu ici ?
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
// termine s'il y a une erreur
|
|
|
|
|
if ( !pile->IsOk() )
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
return pj->Return(pile); // transmet le r<>sultat et lib<69>re la pile
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// passe dans le second <20>tat
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!pile->SetState(1)) return false; // pr<70>t pour la suite
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// second <20>tat, <20>value les instructions associ<63>es
|
|
|
|
|
// le r<>sultat de la condition est sur la pile
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( pile->GivVal() == true ) // condition <20>tait vraie ?
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
if ( m_Block != NULL && // bloc peut <20>tre absent
|
2012-07-04 20:14:28 +00:00
|
|
|
|
!m_Block->Execute(pile) ) return false; // interrompu ici ?
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ( m_BlockElse != NULL && // s'il existe un bloc alternatif
|
2012-07-04 20:14:28 +00:00
|
|
|
|
!m_BlockElse->Execute(pile) ) return false; // interrompu ici
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// transmet le r<>sultat et lib<69>re la pile
|
2012-03-08 18:32:05 +00:00
|
|
|
|
return pj->Return(pile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
void CBotIf :: RestoreState(CBotStack* &pj, bool bMain)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
if ( !bMain ) return;
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
CBotStack* pile = pj->RestoreStack(this); // ajoute un <20>l<EFBFBD>ment <20> la pile
|
2012-03-08 18:32:05 +00:00
|
|
|
|
if ( pile == NULL ) return;
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// selon la reprise, on peut <20>tre dans l'un des 2 <20>tats
|
2012-03-08 18:32:05 +00:00
|
|
|
|
if( pile->GivState() == 0 )
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// <20>value la condition
|
2012-03-08 18:32:05 +00:00
|
|
|
|
m_Condition->RestoreState(pile, bMain); // interrompu ici !
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// second <20>tat, <20>value les instructions associ<63>es
|
|
|
|
|
// le r<>sultat de la condition est sur la pile
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( pile->GivVal() == true ) // condition <20>tait vraie ?
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
if ( m_Block != NULL ) // bloc peut <20>tre absent
|
2012-03-08 18:32:05 +00:00
|
|
|
|
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 !
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|