Merge pull request #690 from Grunaka/dev

Clean CBot Interface
dev-time-step
krzys-h 2015-12-19 14:14:41 +01:00
commit 95eee3a340
158 changed files with 20993 additions and 13243 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

405
src/CBot/CBotCStack.cpp Normal file
View File

@ -0,0 +1,405 @@
/*
* 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 "CBot/CBotCStack.h"
#include "CBot/CBotToken.h"
#include "CBot/CBotCall.h"
#include "CBot/CBotVar/CBotVar.h"
#include "CBot/CBotInstr/CBotFunction.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotProgram* CBotCStack::m_prog = nullptr; // init the static variable
int CBotCStack::m_error = 0;
int CBotCStack::m_end = 0;
CBotTypResult CBotCStack::m_retTyp = CBotTypResult(0);
////////////////////////////////////////////////////////////////////////////////
CBotCStack::CBotCStack(CBotCStack* ppapa)
{
m_next = nullptr;
m_prev = ppapa;
if (ppapa == nullptr)
{
m_error = 0;
m_start = 0;
m_end = 0;
m_bBlock = true;
}
else
{
m_start = ppapa->m_start;
m_bBlock = false;
}
m_listVar = nullptr;
m_var = nullptr;
}
////////////////////////////////////////////////////////////////////////////////
CBotCStack::~CBotCStack()
{
if (m_next != nullptr) delete m_next;
if (m_prev != nullptr) m_prev->m_next = nullptr; // removes chain
delete m_var;
delete m_listVar;
}
////////////////////////////////////////////////////////////////////////////////
CBotCStack* CBotCStack::TokenStack(CBotToken* pToken, bool bBlock)
{
if (m_next != nullptr) return m_next; // include on an existing stack
CBotCStack* p = new CBotCStack(this);
m_next = p; // channel element
p->m_bBlock = bBlock;
if (pToken != nullptr) p->SetStartError(pToken->GetStart());
return p;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotCStack::Return(CBotInstr* inst, CBotCStack* pfils)
{
if ( pfils == this ) return inst;
if (m_var != nullptr) delete m_var; // value replaced?
m_var = pfils->m_var; // result transmitted
pfils->m_var = nullptr; // not to destroy the variable
if (m_error)
{
m_start = pfils->m_start; // retrieves the position of the error
m_end = pfils->m_end;
}
delete pfils;
return inst;
}
////////////////////////////////////////////////////////////////////////////////
CBotFunction* CBotCStack::ReturnFunc(CBotFunction* inst, CBotCStack* pfils)
{
if (m_var != nullptr) delete m_var; // value replaced?
m_var = pfils->m_var; // result transmitted
pfils->m_var = nullptr; // not to destroy the variable
if (m_error)
{
m_start = pfils->m_start; // retrieves the position of the error
m_end = pfils->m_end;
}
delete pfils;
return inst;
}
////////////////////////////////////////////////////////////////////////////////
int CBotCStack::GetError(int& start, int& end)
{
start = m_start;
end = m_end;
return m_error;
}
////////////////////////////////////////////////////////////////////////////////
int CBotCStack::GetError()
{
return m_error;
}
////////////////////////////////////////////////////////////////////////////////
CBotTypResult CBotCStack::GetTypResult(int mode)
{
if (m_var == nullptr)
return CBotTypResult(99);
return m_var->GetTypResult(mode);
}
////////////////////////////////////////////////////////////////////////////////
int CBotCStack::GetType(int mode)
{
if (m_var == nullptr)
return 99;
return m_var->GetType(mode);
}
////////////////////////////////////////////////////////////////////////////////
CBotClass* CBotCStack::GetClass()
{
if ( m_var == nullptr )
return nullptr;
if ( m_var->GetType(1) != CBotTypPointer ) return nullptr;
return m_var->GetClass();
}
////////////////////////////////////////////////////////////////////////////////
void CBotCStack::SetType(CBotTypResult& type)
{
if (m_var == nullptr) return;
m_var->SetType( type );
}
////////////////////////////////////////////////////////////////////////////////
CBotVar* CBotCStack::FindVar(CBotToken* &pToken)
{
CBotCStack* p = this;
CBotString name = pToken->GetString();
while (p != nullptr)
{
CBotVar* pp = p->m_listVar;
while ( pp != nullptr)
{
if (name == pp->GetName())
{
return pp;
}
pp = pp->m_next;
}
p = p->m_prev;
}
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
CBotVar* CBotCStack::FindVar(CBotToken& Token)
{
CBotToken* pt = &Token;
return FindVar(pt);
}
////////////////////////////////////////////////////////////////////////////////
CBotVar* CBotCStack::CopyVar(CBotToken& Token)
{
CBotVar* pVar = FindVar( Token );
if ( pVar == nullptr) return nullptr;
CBotVar* pCopy = CBotVar::Create( "", pVar->GetType() );
pCopy->Copy(pVar);
return pCopy;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotCStack::IsOk()
{
return (m_error == 0);
}
////////////////////////////////////////////////////////////////////////////////
void CBotCStack::SetStartError( int pos )
{
if ( m_error != 0) return; // does not change existing error
m_start = pos;
}
////////////////////////////////////////////////////////////////////////////////
void CBotCStack::SetError(int n, int pos)
{
if ( n!= 0 && m_error != 0) return; // does not change existing error
m_error = n;
m_end = pos;
}
////////////////////////////////////////////////////////////////////////////////
void CBotCStack::SetError(int n, CBotToken* p)
{
if (m_error) return; // does not change existing error
m_error = n;
m_start = p->GetStart();
m_end = p->GetEnd();
}
////////////////////////////////////////////////////////////////////////////////
void CBotCStack::ResetError(int n, int start, int end)
{
m_error = n;
m_start = start;
m_end = end;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotCStack::NextToken(CBotToken* &p)
{
CBotToken* pp = p;
p = p->GetNext();
if (p!=nullptr) return true;
SetError(TX_ENDOF, pp->GetEnd());
return false;
}
////////////////////////////////////////////////////////////////////////////////
void CBotCStack::SetBotCall(CBotProgram* p)
{
m_prog = p;
}
////////////////////////////////////////////////////////////////////////////////
CBotProgram* CBotCStack::GetBotCall()
{
return m_prog;
}
////////////////////////////////////////////////////////////////////////////////
void CBotCStack::SetRetType(CBotTypResult& type)
{
m_retTyp = type;
}
////////////////////////////////////////////////////////////////////////////////
CBotTypResult CBotCStack::GetRetType()
{
return m_retTyp;
}
////////////////////////////////////////////////////////////////////////////////
void CBotCStack::SetVar( CBotVar* var )
{
if (m_var) delete m_var; // replacement of a variable
m_var = var;
}
////////////////////////////////////////////////////////////////////////////////
void CBotCStack::SetCopyVar( CBotVar* var )
{
if (m_var) delete m_var; // replacement of a variable
if ( var == nullptr ) return;
m_var = CBotVar::Create("", var->GetTypResult(2));
m_var->Copy( var );
}
////////////////////////////////////////////////////////////////////////////////
CBotVar* CBotCStack::GetVar()
{
return m_var;
}
////////////////////////////////////////////////////////////////////////////////
void CBotCStack::AddVar(CBotVar* pVar)
{
CBotCStack* p = this;
// returns to the father element
while (p != nullptr && p->m_bBlock == 0) p = p->m_prev;
if ( p == nullptr ) return;
CBotVar** pp = &p->m_listVar;
while ( *pp != nullptr ) pp = &(*pp)->m_next;
*pp = pVar; // added after
#ifdef _DEBUG
if ( pVar->GetUniqNum() == 0 ) assert(0);
#endif
}
////////////////////////////////////////////////////////////////////////////////
bool CBotCStack::CheckVarLocal(CBotToken* &pToken)
{
CBotCStack* p = this;
CBotString name = pToken->GetString();
while (p != nullptr)
{
CBotVar* pp = p->m_listVar;
while ( pp != nullptr)
{
if (name == pp->GetName())
return true;
pp = pp->m_next;
}
if ( p->m_bBlock ) return false;
p = p->m_prev;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
CBotTypResult CBotCStack::CompileCall(CBotToken* &p, CBotVar** ppVars, long& nIdent)
{
nIdent = 0;
CBotTypResult val(-1);
val = CBotCall::CompileCall(p, ppVars, this, nIdent);
if (val.GetType() < 0)
{
val = m_prog->GetFunctions()->CompileCall(p->GetString(), ppVars, nIdent);
if ( val.GetType() < 0 )
{
// pVar = nullptr; // the error is not on a particular parameter
SetError( -val.GetType(), p );
val.SetType(-val.GetType());
return val;
}
}
return val;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam)
{
CBotString name = pToken->GetString();
if ( CBotCall::CheckCall(name) ) return true;
CBotFunction* pp = m_prog->GetFunctions();
while ( pp != nullptr )
{
if ( pToken->GetString() == pp->GetName() )
{
// are parameters exactly the same?
if ( pp->CheckParam( pParam ) )
return true;
}
pp = pp->Next();
}
pp = CBotFunction::m_listPublic;
while ( pp != nullptr )
{
if ( pToken->GetString() == pp->GetName() )
{
// are parameters exactly the same?
if ( pp->CheckParam( pParam ) )
return true;
}
pp = pp->m_nextpublic;
}
return false;
}

266
src/CBot/CBotCStack.h Normal file
View File

@ -0,0 +1,266 @@
/*
* 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/CBotProgram.h"
// Local include
// Global include
class CBotInstr;
class CBotDefParam;
/*!
* \brief The CBotCStack class Management of the stack of compilation.
*/
class CBotCStack
{
public:
/*!
* \brief CBotCStack
* \param ppapa
*/
CBotCStack(CBotCStack* ppapa);
/*!
* \brief CBotCStack Destructor.
*/
~CBotCStack();
/*!
* \brief IsOk
* \return
*/
bool IsOk();
/*!
* \brief GetError
* \return
*/
int GetError();
/*!
* \brief GetError Gives error number
* \param start
* \param end
* \return
*/
int GetError(int& start, int& end);
/*!
* \brief SetType Set the type of instruction on the stack.
* \param type
*/
void SetType(CBotTypResult& type);
/*!
* \brief GetTypResult Gives the type of value on the stack. Type of
* instruction on the stack.
* \param mode
* \return
*/
CBotTypResult GetTypResult(int mode = 0);
/*!
* \brief GetType Gives the type of value on the stack.
* \param mode
* \return
*/
int GetType(int mode = 0);
/*!
* \brief GetClass Gives the class of the value on the stack.
* \return
*/
CBotClass* GetClass();
/*!
* \brief AddVar Adds a local variable.
* \param p
*/
void AddVar(CBotVar* p);
/*!
* \brief FindVar Finds a variable. Seeks a variable on the stack the token
* may be a result of TokenTypVar (object of a class) or a pointer in the
* source.
* \param p
* \return
*/
CBotVar* FindVar(CBotToken* &p);
/*!
* \brief FindVar
* \param Token
* \return
*/
CBotVar* FindVar(CBotToken& Token);
/*!
* \brief CheckVarLocal Test whether a variable is already defined locally.
* \param pToken
* \return
*/
bool CheckVarLocal(CBotToken* &pToken);
/*!
* \brief CopyVar Finds and makes a copy.
* \param Token
* \return
*/
CBotVar* CopyVar(CBotToken& Token);
/*!
* \brief TokenStack Used only at compile.
* \param pToken
* \param bBlock
* \return
*/
CBotCStack* TokenStack(CBotToken* pToken = nullptr, bool bBlock = false);
/*!
* \brief Return Transmits the result upper.
* \param p
* \param pParent
* \return
*/
CBotInstr* Return(CBotInstr* p, CBotCStack* pParent);
/*!
* \brief ReturnFunc Transmits the result upper.
* \param p
* \param pParent
* \return
*/
CBotFunction* ReturnFunc(CBotFunction* p, CBotCStack* pParent);
/*!
* \brief SetVar
* \param var
*/
void SetVar( CBotVar* var );
/*!
* \brief SetCopyVar Puts on the stack a copy of a variable.
* \param var
*/
void SetCopyVar( CBotVar* var );
/*!
* \brief GetVar
* \return
*/
CBotVar* GetVar();
/*!
* \brief SetStartError
* \param pos
*/
void SetStartError(int pos);
/*!
* \brief SetError
* \param n
* \param pos
*/
void SetError(int n, int pos);
/*!
* \brief SetError
* \param n
* \param p
*/
void SetError(int n, CBotToken* p);
/*!
* \brief ResetError
* \param n
* \param start
* \param end
*/
void ResetError(int n, int start, int end);
/*!
* \brief SetRetType
* \param type
*/
void SetRetType(CBotTypResult& type);
/*!
* \brief GetRetType
* \return
*/
CBotTypResult GetRetType();
/*!
* \brief SetBotCall
* \param p
*/
void SetBotCall(CBotProgram* p);
/*!
* \brief GetBotCall
* \return
*/
CBotProgram* GetBotCall();
/*!
* \brief CompileCall
* \param p
* \param ppVars
* \param nIdent
* \return
*/
CBotTypResult CompileCall(CBotToken* &p, CBotVar** ppVars, long& nIdent);
/*!
* \brief CheckCall Test if a procedure name is already defined somewhere.
* \param pToken
* \param pParam
* \return
*/
bool CheckCall(CBotToken* &pToken, CBotDefParam* pParam);
/*!
* \brief NextToken
* \param p
* \return
*/
bool NextToken(CBotToken* &p);
private:
CBotCStack* m_next;
CBotCStack* m_prev;
static int m_error;
static int m_end;
int m_start;
//! Result of the operations.
CBotVar* m_var;
//! Is part of a block (variables are local to this block).
bool m_bBlock;
CBotVar* m_listVar;
//! List of compiled functions.
static CBotProgram* m_prog;
static CBotTypResult m_retTyp;
};

314
src/CBot/CBotCall.cpp Normal file
View File

@ -0,0 +1,314 @@
/*
* 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 "CBot/CBotCall.h"
#include "CBot/CBotToken.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotUtils.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotCall* CBotCall::m_ListCalls = nullptr;
void* CBotCall::m_pUser = nullptr;
////////////////////////////////////////////////////////////////////////////////
CBotCall::CBotCall(const char* name,
bool rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
CBotTypResult rCompile (CBotVar* &pVar, void* pUser))
{
m_name = name;
m_rExec = rExec;
m_rComp = rCompile;
m_next = nullptr;
m_nFuncIdent = CBotVar::NextUniqNum();
}
////////////////////////////////////////////////////////////////////////////////
CBotCall::~CBotCall()
{
if (m_next) delete m_next;
m_next = nullptr;
}
////////////////////////////////////////////////////////////////////////////////
void CBotCall::Free()
{
delete CBotCall::m_ListCalls;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotCall::AddFunction(const char* name,
bool rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
CBotTypResult rCompile (CBotVar* &pVar, void* pUser))
{
CBotCall* p = m_ListCalls;
CBotCall* pp = nullptr;
if ( p != nullptr ) while ( p->m_next != nullptr )
{
if ( p->GetName() == name )
{
// frees redefined function
if ( pp ) pp->m_next = p->m_next;
else m_ListCalls = p->m_next;
pp = p;
p = p->m_next;
pp->m_next = nullptr; // not to destroy the following list
delete pp;
continue;
}
pp = p; // previous pointer
p = p->m_next;
}
pp = new CBotCall(name, rExec, rCompile);
if (p) p->m_next = pp;
else m_ListCalls = pp;
return true;
}
////////////////////////////////////////////////////////////////////////////////
CBotTypResult CBotCall::CompileCall(CBotToken* &p, CBotVar** ppVar, CBotCStack* pStack, long& nIdent)
{
nIdent = 0;
CBotCall* pt = m_ListCalls;
CBotString name = p->GetString();
while ( pt != nullptr )
{
if ( pt->m_name == name )
{
CBotVar* pVar = MakeListVars(ppVar);
CBotVar* pVar2 = pVar;
CBotTypResult r = pt->m_rComp(pVar2, m_pUser);
int ret = r.GetType();
// if a class is returned, it is actually a pointer
if ( ret == CBotTypClass ) r.SetType( ret = CBotTypPointer );
if ( ret > 20 )
{
if (pVar2) pStack->SetError(ret, p /*pVar2->GetToken()*/ );
}
delete pVar;
nIdent = pt->m_nFuncIdent;
return r;
}
pt = pt->m_next;
}
return -1;
}
////////////////////////////////////////////////////////////////////////////////
void CBotCall::SetPUser(void* pUser)
{
m_pUser = pUser;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotCall::CheckCall(const char* name)
{
CBotCall* p = m_ListCalls;
while ( p != nullptr )
{
if ( name == p->GetName() ) return true;
p = p->m_next;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
CBotString CBotCall::GetName()
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////
CBotCall* CBotCall::Next()
{
return m_next;
}
////////////////////////////////////////////////////////////////////////////////
int CBotCall::DoCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBotStack* pStack, CBotTypResult& rettype)
{
CBotCall* pt = m_ListCalls;
if ( nIdent ) while ( pt != nullptr )
{
if ( pt->m_nFuncIdent == nIdent )
{
goto fund;
}
pt = pt->m_next;
}
pt = m_ListCalls;
if ( token != nullptr )
{
CBotString name = token->GetString();
while ( pt != nullptr )
{
if ( pt->m_name == name )
{
nIdent = pt->m_nFuncIdent;
goto fund;
}
pt = pt->m_next;
}
}
return -1;
fund:
#if !STACKRUN
// lists the parameters depending on the contents of the stack (pStackVar)
CBotVar* pVar = MakeListVars(ppVar, true);
CBotVar* pVarToDelete = pVar;
// creates a variable to the result
CBotVar* pResult = rettype.Eq(0) ? nullptr : CBotVar::Create("", rettype);
CBotVar* pRes = pResult;
int Exception = 0;
int res = pt->m_rExec(pVar, pResult, Exception, pStack->GetPUser());
if ( pResult != pRes ) delete pRes; // different result if made
delete pVarToDelete;
if (res == false)
{
if (Exception!=0)
{
pStack->SetError(Exception, token);
}
delete pResult;
return false;
}
pStack->SetVar(pResult);
if ( rettype.GetType() > 0 && pResult == nullptr )
{
pStack->SetError(TX_NORETVAL, token);
}
nIdent = pt->m_nFuncIdent;
return true;
#else
CBotStack* pile = pStack->AddStackEOX(pt);
if ( pile == EOX ) return true;
// lists the parameters depending on the contents of the stack (pStackVar)
CBotVar* pVar = MakeListVars(ppVar, true);
// CBotVar* pVarToDelete = pVar;
// creates a variable to the result
CBotVar* pResult = rettype.Eq(0) ? nullptr : CBotVar::Create("", rettype);
pile->SetVar( pVar );
CBotStack* pile2 = pile->AddStack();
pile2->SetVar( pResult );
pile->SetError(0, token); // for the position on error + away
return pt->Run( pStack );
#endif
}
#if STACKRUN
////////////////////////////////////////////////////////////////////////////////
bool CBotCall::RestoreCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBotStack* pStack)
{
CBotCall* pt = m_ListCalls;
{
CBotString name = token->GetString();
while ( pt != nullptr )
{
if ( pt->m_name == name )
{
nIdent = pt->m_nFuncIdent;
CBotStack* pile = pStack->RestoreStackEOX(pt);
if ( pile == nullptr ) return true;
// CBotStack* pile2 = pile->RestoreStack();
pile->RestoreStack();
return true;
}
pt = pt->m_next;
}
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotCall::Run(CBotStack* pStack)
{
CBotStack* pile = pStack->AddStackEOX(this);
if ( pile == EOX ) return true;
CBotVar* pVar = pile->GetVar();
CBotStack* pile2 = pile->AddStack();
CBotVar* pResult = pile2->GetVar();
CBotVar* pRes = pResult;
int Exception = 0;
int res = m_rExec(pVar, pResult, Exception, pStack->GetPUser());
if (res == false)
{
if (Exception!=0)
{
pStack->SetError(Exception);
}
if ( pResult != pRes ) delete pResult; // different result if made
return false;
}
if ( pResult != nullptr ) pStack->SetCopyVar( pResult );
if ( pResult != pRes ) delete pResult; // different result if made
return true;
}
#endif

149
src/CBot/CBotCall.h Normal file
View File

@ -0,0 +1,149 @@
/*
* 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/CBotString.h"
// Local include
// Global include
// Forward declaration
class CBotStack;
#define STACKRUN 1 //! \def return execution directly on a suspended routine
/*!
* \brief The CBotCall class. Class for routine calls (external).
*/
class CBotCall
{
public:
/*!
* \brief CBotCall
* \param name
* \param rExec
* \param rCompile
*/
CBotCall(const char* name,
bool rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
CBotTypResult rCompile (CBotVar* &pVar, void* pUser));
/*!
* \brief ~CBotCall
*/
~CBotCall();
/*!
* \brief AddFunction
* \param name
* \param rExec
* \param rCompile
* \return
*/
static bool AddFunction(const char* name,
bool rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
CBotTypResult rCompile (CBotVar* &pVar, void* pUser));
/*!
* \brief CompileCall Is acceptable by a call procedure name and given
* parameters.
* \param p
* \param ppVars
* \param pStack
* \param nIdent
* \return
*/
static CBotTypResult CompileCall(CBotToken* &p, CBotVar** ppVars, CBotCStack* pStack, long& nIdent);
/*!
* \brief CheckCall
* \param name
* \return
*/
static bool CheckCall(const char* name);
/*!
* \brief DoCall
* \param nIdent
* \param token
* \param ppVars
* \param pStack
* \param rettype
* \return
*/
static int DoCall(long& nIdent, CBotToken* token, CBotVar** ppVars, CBotStack* pStack, CBotTypResult& rettype);
#if STACKRUN
/*!
* \brief Run
* \param pStack
* \return
*/
bool Run(CBotStack* pStack);
/*!
* \brief RestoreCall
* \param nIdent
* \param token
* \param ppVar
* \param pStack
* \return
*/
static bool RestoreCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBotStack* pStack);
#endif
/*!
* \brief GetName
* \return
*/
CBotString GetName();
/*!
* \brief Next
* \return
*/
CBotCall* Next();
/*!
* \brief SetPUser
* \param pUser
*/
static void SetPUser(void* pUser);
/*!
* \brief Free
*/
static void Free();
private:
static CBotCall* m_ListCalls;
static void* m_pUser;
long m_nFuncIdent;
CBotString m_name;
bool (*m_rExec) (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser);
CBotTypResult (*m_rComp) (CBotVar* &pVar, void* pUser);
CBotCall* m_next;
};

View File

@ -0,0 +1,182 @@
/*
* 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 "CBot/CBotCallMethode.h"
#include "CBot/CBotUtils.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotCallMethode::CBotCallMethode(const char* name,
bool rExec (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user),
CBotTypResult rCompile (CBotVar* pThis, CBotVar* &pVar))
{
m_name = name;
m_rExec = rExec;
m_rComp = rCompile;
m_next = nullptr;
m_nFuncIdent = CBotVar::NextUniqNum();
}
////////////////////////////////////////////////////////////////////////////////
CBotCallMethode::~CBotCallMethode()
{
delete m_next;
m_next = nullptr;
}
////////////////////////////////////////////////////////////////////////////////
CBotTypResult CBotCallMethode::CompileCall(const char* name,
CBotVar* pThis,
CBotVar** ppVar,
CBotCStack* pStack,
long& nIdent)
{
CBotCallMethode* pt = this;
nIdent = 0;
while ( pt != nullptr )
{
if ( pt->m_name == name )
{
CBotVar* pVar = MakeListVars(ppVar, true);
CBotVar* pVar2 = pVar;
CBotTypResult r = pt->m_rComp(pThis, pVar2);
int ret = r.GetType();
if ( ret > 20 )
{
if (pVar2) pStack->SetError(ret, pVar2->GetToken());
}
delete pVar;
nIdent = pt->m_nFuncIdent;
return r;
}
pt = pt->m_next;
}
return CBotTypResult(-1);
}
////////////////////////////////////////////////////////////////////////////////
CBotString CBotCallMethode::GetName()
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////
CBotCallMethode* CBotCallMethode::Next()
{
return m_next;
}
////////////////////////////////////////////////////////////////////////////////
void CBotCallMethode::AddNext(CBotCallMethode* pt)
{
CBotCallMethode* p = this;
while ( p->m_next != nullptr ) p = p->m_next;
p->m_next = pt;
}
////////////////////////////////////////////////////////////////////////////////
int CBotCallMethode::DoCall(long& nIdent,
const char* name,
CBotVar* pThis,
CBotVar** ppVars,
CBotVar* &pResult,
CBotStack* pStack,
CBotToken* pToken)
{
CBotCallMethode* pt = this;
// search by the identifier
if ( nIdent ) while ( pt != nullptr )
{
if ( pt->m_nFuncIdent == nIdent )
{
// lists the parameters depending on the contents of the stack (pStackVar)
CBotVar* pVar = MakeListVars(ppVars, true);
CBotVar* pVarToDelete = pVar;
// then calls the routine external to the module
int Exception = 0;
int res = pt->m_rExec(pThis, pVar, pResult, Exception, pStack->GetPUser());
pStack->SetVar(pResult);
if (res == false)
{
if (Exception!=0)
{
// pStack->SetError(Exception, pVar->GetToken());
pStack->SetError(Exception, pToken);
}
delete pVarToDelete;
return false;
}
delete pVarToDelete;
return true;
}
pt = pt->m_next;
}
// search by name
while ( pt != nullptr )
{
if ( pt->m_name == name )
{
// lists the parameters depending on the contents of the stack (pStackVar)
CBotVar* pVar = MakeListVars(ppVars, true);
CBotVar* pVarToDelete = pVar;
int Exception = 0;
int res = pt->m_rExec(pThis, pVar, pResult, Exception, pStack->GetPUser());
pStack->SetVar(pResult);
if (res == false)
{
if (Exception!=0)
{
// pStack->SetError(Exception, pVar->GetToken());
pStack->SetError(Exception, pToken);
}
delete pVarToDelete;
return false;
}
delete pVarToDelete;
nIdent = pt->m_nFuncIdent;
return true;
}
pt = pt->m_next;
}
return -1;
}

119
src/CBot/CBotCallMethode.h Normal file
View File

@ -0,0 +1,119 @@
/*
* 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/CBotTypResult.h"
#include "CBot/CBotString.h"
// Local include
// Global include
class CBotVar;
class CBotCStack;
class CBotStack;
class CBotToken;
/*!
* \brief The CBotCallMethode class Class managing the methods declared by
* AddFunction on a class.
*/
class CBotCallMethode
{
public:
/*!
* \brief CBotCallMethode
* \param name
* \param rExec
* \param rCompile
*/
CBotCallMethode(const char* name,
bool rExec (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user),
CBotTypResult rCompile (CBotVar* pThis, CBotVar* &pVar));
/*!
* \brief ~CBotCallMethode
*/
~CBotCallMethode();
/*!
* \brief CompileCall Is acceptable by a call procedure name and given
* parameters.
* \param name
* \param pThis
* \param ppVars
* \param pStack
* \param nIdent
* \return
*/
CBotTypResult CompileCall(const char* name,
CBotVar* pThis,
CBotVar** ppVars,
CBotCStack* pStack,
long& nIdent);
/*!
* \brief DoCall
* \param nIdent
* \param name
* \param pThis
* \param ppVars
* \param pResult
* \param pStack
* \param pFunc
* \return
*/
int DoCall(long& nIdent,
const char* name,
CBotVar* pThis,
CBotVar** ppVars,
CBotVar* &pResult,
CBotStack* pStack,
CBotToken* pFunc);
/*!
* \brief GetName
* \return
*/
CBotString GetName();
/*!
* \brief Next
* \return
*/
CBotCallMethode* Next();
/*!
* \brief AddNext
* \param p
*/
void AddNext(CBotCallMethode* p);
private:
CBotString m_name;
bool (*m_rExec) (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user);
CBotTypResult (*m_rComp) (CBotVar* pThis, CBotVar* &pVar);
CBotCallMethode* m_next;
friend class CBotClass;
long m_nFuncIdent;
};

File diff suppressed because it is too large Load Diff

475
src/CBot/CBotClass.h Normal file
View File

@ -0,0 +1,475 @@
/*
* 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/CBotDefines.h"
#include "CBot/CBotTypResult.h"
#include "CBot/CBotString.h"
// Local include
// Global include
// Forward declaration
class CBotVar;
class CBotClass;
class CBotCallMethode;
class CBotFunction;
class CBotProgram;
class CBotStack;
class CBotDefParam;
/*!
* \brief The CBotClass class Class to define new classes in the language CBOT
* For example to define the class CPoint (x, y) see comments at end of this
* file.
*/
class CBotClass
{
public:
//! Mark if is set or not
bool m_IsDef;
/*!
* \brief CBotClass Constructor. Once a class is created, it is known around
* CBot intrinsic mode gives a class that is not managed by pointers.
* \param name
* \param pParent
* \param bIntrinsic
*/
CBotClass( const char* name,
CBotClass* pParent,
bool bIntrinsic = false );
/*!
* \brief CBotClass Destructor.
*/
~CBotClass( );
/*!
* \brief Create
* \param name
* \param parent
* \param intrinsic
* \return
*/
static CBotClass* Create(const char* name,
CBotClass* parent,
bool intrinsic = false);
/*!
* \brief AddFunction This call allows to add as external new method
* used by the objects of this class. See (**) at end of this file for
* more details.
* \param name
* \param rExec
* \param rCompile
* \return
*/
bool AddFunction(const char* name,
bool rExec (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user),
CBotTypResult rCompile (CBotVar* pThis, CBotVar* &pVar));
/*!
* \brief AddUpdateFunc Defines routine to be called to update the elements
* of the class.
* \param rMaj
* \return
*/
bool AddUpdateFunc( void rMaj ( CBotVar* pThis, void* pUser ) );
//
/*!
* \brief AddItem Adds an element to the class.
* \param name
* \param type
* \param mPrivate
* \return
*/
bool AddItem(CBotString name, CBotTypResult type, int mPrivate = PR_PUBLIC);
/*!
* \brief AddItem Adds an item by passing the pointer to an instance of a
* variable the object is taken as is, so do not destroyed.
* \param pVar
* \return
*/
bool AddItem(CBotVar* pVar);
/*!
* \brief AddNext
* \param pClass
*/
void AddNext(CBotClass* pClass);
/*!
* \brief GetName Gives the name of the class.
* \return
*/
CBotString GetName();
/*!
* \brief GetParent Gives the parent class (or nullptr).
* \return
*/
CBotClass* GetParent();
/*!
* \brief IsChildOf True if a class is derived (Extends) of another.
* \param pClass
* \return true also if the classes are identical
*/
bool IsChildOf(CBotClass* pClass);
/*!
* \brief Find Trouve une classe d'après son nom
* \param pToken
* \return A class by it's its name.
*/
static CBotClass* Find(CBotToken* &pToken);
/*!
* \brief Find
* \param name
* \return
*/
static CBotClass* Find(const char* name);
/*!
* \brief GetVar Return the list of variables.
* \return
*/
CBotVar* GetVar();
/*!
* \brief GetItem One of the variables according to its name.
* \param name
* \return
*/
CBotVar* GetItem(const char* name);
/*!
* \brief GetItemRef
* \param nIdent
* \return
*/
CBotVar* GetItemRef(int nIdent);
/*!
* \brief CompileMethode Compiles a method associated with an instance of
* class the method can be declared by the user or AddFunction.
* \param name
* \param pThis
* \param ppParams
* \param pStack
* \param nIdent
* \return
*/
CBotTypResult CompileMethode(const char* name,
CBotVar* pThis,
CBotVar** ppParams,
CBotCStack* pStack,
long& nIdent);
/*!
* \brief ExecuteMethode Executes a method.
* \param nIdent
* \param name
* \param pThis
* \param ppParams
* \param pResult
* \param pStack
* \param pToken
* \return
*/
bool ExecuteMethode(long& nIdent,
const char* name,
CBotVar* pThis,
CBotVar** ppParams,
CBotVar* &pResult,
CBotStack* &pStack,
CBotToken* pToken);
/*!
* \brief RestoreMethode Restored the execution stack.
* \param nIdent
* \param name
* \param pThis
* \param ppParams
* \param pStack
*/
void RestoreMethode(long& nIdent,
const char* name,
CBotVar* pThis,
CBotVar** ppParams,
CBotStack* &pStack);
/*!
* \brief Compile Compiles a class declared by the user.
* \param p
* \param pStack
* \return
*/
static CBotClass* Compile(CBotToken* &p,
CBotCStack* pStack);
/*!
* \brief Compile1
* \param p
* \param pStack
* \return
*/
static CBotClass* Compile1(CBotToken* &p,
CBotCStack* pStack);
/*!
* \brief CompileDefItem
* \param p
* \param pStack
* \param bSecond
* \return
*/
bool CompileDefItem(CBotToken* &p,
CBotCStack* pStack,
bool bSecond);
/*!
* \brief IsIntrinsic
* \return
*/
bool IsIntrinsic();
/*!
* \brief Purge
*/
void Purge();
/*!
* \brief Free
*/
static void Free();
/*!
* \brief SaveStaticState
* \param pf
* \return
*/
static bool SaveStaticState(FILE* pf);
/*!
* \brief RestoreStaticState
* \param pf
* \return
*/
static bool RestoreStaticState(FILE* pf);
/*!
* \brief Lock
* \param p
* \return
*/
bool Lock(CBotProgram* p);
/*!
* \brief Unlock
*/
void Unlock();
/*!
* \brief FreeLock
* \param p
*/
static void FreeLock(CBotProgram* p);
/*!
* \brief CheckCall Test if a procedure name is already defined somewhere.
* \param pToken
* \param pParam
* \return
*/
bool CheckCall(CBotToken* &pToken,
CBotDefParam* pParam);
private:
//! List of classes existing at a given time.
static CBotClass* m_ExClass;
//! For this general list.
CBotClass* m_ExNext;
//! For this general list.
CBotClass* m_ExPrev;
//! Parent class.
CBotClass* m_pParent;
//! Name of this class.
CBotString m_name;
//! Number of variables in the chain.
int m_nbVar;
//! Content of the class.
CBotVar* m_pVar;
//! Intrinsic class.
bool m_bIntrinsic;
//! The string class.
CBotClass* m_next;
//! List of methods defined in external.
CBotCallMethode* m_pCalls;
//! Compiled list of methods.
CBotFunction* m_pMethod;
void (*m_rMaj) ( CBotVar* pThis, void* pUser );
friend class CBotVarClass;
//! For Lock / UnLock.
int m_cptLock;
//! Lock for reentrancy.
int m_cptOne;
//! Processes waiting for sync.
CBotProgram* m_ProgInLock[5];
};
/*
(**) Note:
To define an external function, proceed as follows:
a) define a routine for compilation this routine receive list of parameters
(no values) and either returns a result type (CBotTyp... or 0 = void)
or an error number.
b) define a routine for the execution this routine receive list of
parameters (with valeurs), a variable to store the result
(according to the given type at compile time)
For example, a routine which calculates the mean of a parameter list
int cMean(CBotVar* &pVar, CBotString& ClassName)
{
if ( pVar == nullptr ) return 6001; // there is no parameter!
while ( pVar != nullptr )
{
if ( pVar->GetType() > CBotTypDouble ) return 6002; // this is not a number
pVar = pVar -> GetNext();
}
return CBotTypFloat; // the type of the result may depend on the parameters!
}
bool rMean(CBotVar* pVar, CBotVar* pResult, int& Exception)
{
float total = 0;
int nb = 0;
while (pVar != nullptr)
{
total += pVar->GetValFloat();
pVar = pVar->GetNext();
nb++;
}
pResult->SetValFloat(total/nb); // returns the mean value
return true; // operation fully completed
}
////////////////////////////////////////////////////////////////////////////////
// Examples of use
// Definition classes and functions
// define the global class CPoint
// --------------------------------
m_pClassPoint = new CBotClass("CPoint", nullptr);
// adds the component ".x"
m_pClassPoint->AddItem("x", CBotTypResult(CBotTypFloat));
// adds the component ".y"
m_pClassPoint->AddItem("y", CBotTypResult(CBotTypFloat));
// the player can then use the instructions
// CPoint position; position.x = 12; position.y = -13.6
// define class CColobotObject
// --------------------------------
// This class manages all the objects in the world of COLOBOT
// the "main" user program belongs to this class
m_pClassObject = new CBotClass("CColobotObject", m_pClassBase);
// adds the component ".position"
m_pClassObject->AddItem("position", m_pClassPoint);
// adds the component ".type"
m_pClassObject->AddItem("type", CBotTypResult(CBotTypShort));
// adds a definition of constant
m_pClassObject->AddConst("ROBOT", CBotTypShort, 1); // ROBOT equivalent to the value 1
// adds the FIND routine
m_pClassObject->AddFunction( rCompFind, rDoFind );
// the player can now use the instructions
// CColobotObject chose; chose = FIND( ROBOT )
// define class CColobotRobot derived from CColobotObject
// ---------------------------------------------------------
// programs "main" associated with robots as a part of this class
m_pClassRobot = new CBotClass("CColobotRobot", m_pClassObject);
// add routine GOTO
m_pClassRobot->AddFunction( rCompGoto, rDoGoto );
// the player can now use
// GOTO( FIND ( ROBOT ) );
// creates an instance of the class Robot
// ------------------------------------
// for example a new robot which has just been manufactured
CBotVar* m_pMonRobot = new CBotVar("MonRobot", m_pClassRobot);
// compiles the program by hand for this robot
// ------------------------------------------
CString LeProgramme( "void main() {GOTO(0, 0); return 0;}" );
if ( !m_pMonRobot->Compile( LeProgramme ) ) {error handling ...};
// build a stack for interpreter
// --------------------------------------
CBotStack* pStack = new CBotStack(nullptr);
// executes the main program
// -------------------------
while( false = m_pMonRobot->Execute( "main", pStack ))
{
// program suspended
// could be pass a handle to another (safeguarding pstack for the robot one)
};
// programme "main" finished !
// routine that implements the GOTO (CPoint pos)
bool rDoGoto( CBotVar* pVar, CBotVar* pResult, int& exception )
{
if (pVar->GetType() != CBotTypeClass ||
pVar->IsElemOfClas("CPoint") ) { exception = 6522; return false; )
// the parameter is not the right class?
// in fact the control is done to the routine of compilation
m_PosToGo.Copy( pVar ); // keeps the target position (object type CBotVar)
// or so
CBotVar* temp;
temp = pVar->GetItem("x"); // is necessary for the object of type CPoint
ASSERT (temp != nullptr && temp->GetType() == CBotTypFloat);
m_PosToGo.x = temp->GetValFloat();
temp = pVar->GetItem("y"); // is necessary for the object of type CPoint
ASSERT (temp != nullptr && temp->GetType() == CBotTypFloat);
m_PosToGo.y = temp->GetValFloat();
return (m_CurentPos == m_PosToGo); // makes true if the position is reached
// returns false if one had wait yet
}
*/

208
src/CBot/CBotDefParam.cpp Normal file
View File

@ -0,0 +1,208 @@
/*
* 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 "CBot/CBotDefParam.h"
#include "CBot/CBotUtils.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVarClass.h"
// Local include
// Global include
#include <cassert>
////////////////////////////////////////////////////////////////////////////////
CBotDefParam::CBotDefParam()
{
m_next = nullptr;
m_nIdent = 0;
}
////////////////////////////////////////////////////////////////////////////////
CBotDefParam::~CBotDefParam()
{
delete m_next;
}
////////////////////////////////////////////////////////////////////////////////
CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack)
{
// mainly not pStack->TokenStack here
// declared variables must remain visible thereafter
pStack->SetStartError(p->GetStart());
if (IsOfType(p, ID_OPENPAR))
{
CBotDefParam* list = nullptr;
while (!IsOfType(p, ID_CLOSEPAR))
{
CBotDefParam* param = new CBotDefParam();
if (list == nullptr) list = param;
else list->AddNext(param); // added to the list
// CBotClass* pClass = nullptr;//= CBotClass::Find(p);
param->m_typename = p->GetString();
CBotTypResult type = param->m_type = TypeParam(p, pStack);
// if ( type == CBotTypPointer ) type = CBotTypClass; // we must create a new object
if (param->m_type.GetType() > 0)
{
CBotToken* pp = p;
param->m_token = *p;
if (pStack->IsOk() && IsOfType(p, TokenTypVar) )
{
// variable already declared?
if (pStack->CheckVarLocal(pp))
{
pStack->SetError(TX_REDEFVAR, pp);
break;
}
if ( type.Eq(CBotTypArrayPointer) ) type.SetType(CBotTypArrayBody);
CBotVar* var = CBotVar::Create(pp->GetString(), type); // creates the variable
// if ( pClass ) var->SetClass(pClass);
var->SetInit(CBotVar::InitType::IS_POINTER); // mark initialized
param->m_nIdent = CBotVar::NextUniqNum();
var->SetUniqNum(param->m_nIdent);
pStack->AddVar(var); // place on the stack
if (IsOfType(p, ID_COMMA) || p->GetType() == ID_CLOSEPAR)
continue;
}
pStack->SetError(TX_CLOSEPAR, p->GetStart());
}
pStack->SetError(TX_NOTYP, p);
delete list;
return nullptr;
}
return list;
}
pStack->SetError(TX_OPENPAR, p->GetStart());
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
void CBotDefParam::AddNext(CBotDefParam* p)
{
CBotDefParam* pp = this;
while (pp->m_next != nullptr) pp = pp->m_next;
pp->m_next = p;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotDefParam::Execute(CBotVar** ppVars, CBotStack* &pj)
{
int i = 0;
CBotDefParam* p = this;
while ( p != nullptr )
{
// creates a local variable on the stack
CBotVar* newvar = CBotVar::Create(p->m_token.GetString(), p->m_type);
// serves to make the transformation of types:
if ( ppVars != nullptr && ppVars[i] != nullptr )
{
switch (p->m_type.GetType())
{
case CBotTypInt:
newvar->SetValInt(ppVars[i]->GetValInt());
break;
case CBotTypFloat:
newvar->SetValFloat(ppVars[i]->GetValFloat());
break;
case CBotTypString:
newvar->SetValString(ppVars[i]->GetValString());
break;
case CBotTypBoolean:
newvar->SetValInt(ppVars[i]->GetValInt());
break;
case CBotTypIntrinsic:
(static_cast<CBotVarClass*>(newvar))->Copy(ppVars[i], false);
break;
case CBotTypPointer:
case CBotTypArrayPointer:
{
newvar->SetPointer(ppVars[i]->GetPointer());
}
break;
default:
assert(0);
}
}
newvar->SetUniqNum(p->m_nIdent);
pj->AddVar(newvar); // add a variable
p = p->m_next;
i++;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
void CBotDefParam::RestoreState(CBotStack* &pj, bool bMain)
{
// int i = 0;
CBotDefParam* p = this;
while ( p != nullptr )
{
// creates a local variable on the stack
CBotVar* var = pj->FindVar(p->m_token.GetString());
var->SetUniqNum(p->m_nIdent);
p = p->m_next;
}
}
////////////////////////////////////////////////////////////////////////////////
int CBotDefParam::GetType()
{
return m_type.GetType();
}
////////////////////////////////////////////////////////////////////////////////
CBotTypResult CBotDefParam::GetTypResult()
{
return m_type;
}
////////////////////////////////////////////////////////////////////////////////
CBotDefParam* CBotDefParam::GetNext()
{
return m_next;
}
////////////////////////////////////////////////////////////////////////////////
CBotString CBotDefParam::GetParamString()
{
CBotString param;
param = m_typename;
param += ' ';
param += m_token.GetString();
return param;
}

114
src/CBot/CBotDefParam.h Normal file
View File

@ -0,0 +1,114 @@
/*
* 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/CBotToken.h"
#include "CBot/CBotStack.h"
// Local include
// Global include
class CBotCStack;
class CBotStack;
class CBotVar;
/*!
* \brief The CBotDefParam class A list of parameters.
*/
class CBotDefParam
{
public:
/*!
* \brief CBotDefParam
*/
CBotDefParam();
/*!
* \brief ~CBotDefParam
*/
~CBotDefParam();
/*!
* \brief Compile Compiles a list of parameters.
* \param p
* \param pStack
* \return
*/
static CBotDefParam* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute
* \param ppVars
* \param pj
* \return
*/
bool Execute(CBotVar** ppVars, CBotStack* &pj);
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain);
/*!
* \brief AddNext
* \param p
*/
void AddNext(CBotDefParam* p);
/*!
* \brief GetType
* \return
*/
int GetType();
/*!
* \brief GetTypResult
* \return
*/
CBotTypResult GetTypResult();
/*!
* \brief GetNext
* \return
*/
CBotDefParam* GetNext();
/*!
* \brief GetParamString
* \return
*/
CBotString GetParamString();
private:
//! Name of the parameter.
CBotToken m_token;
//! Type name.
CBotString m_typename;
//! Type of paramteter.
CBotTypResult m_type;
//! Next parameter.
CBotDefParam* m_next;
long m_nIdent;
};

184
src/CBot/CBotDefines.h Normal file
View File

@ -0,0 +1,184 @@
/*
* 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
// Local include
// Global include
#define STACKMEM 1 /// \def preserve memory for the execution stack
#define MAXSTACK 990 /// \def stack size reserved
#define EOX (reinterpret_cast<CBotStack*>(-1)) /// \def tag special condition
#define MAXARRAYSIZE 9999
// variable type SetPrivate / IsPrivate
#define PR_PUBLIC 0 // public variable
#define PR_READ 1 // read only
#define PR_PROTECT 2 // protected (inheritance)
#define PR_PRIVATE 3 // strictly private
//! Define the current CBot version
#define CBOTVERSION 104
// for SetUserPtr when deleting an object
// \TODO define own types to distinct between different states of objects
#define OBJECTDELETED (reinterpret_cast<void*>(-1))
// value set before initialization
#define OBJECTCREATED (reinterpret_cast<void*>(-2))
////////////////////////////////////////////////////////////////////////
// Error Handling of compilation and execution
////////////////////////////////////////////////////////////////////////
// Here are the list of errors that can be returned by the module
// for compilation
#define CBotErrOpenPar 5000 // missing the opening parenthesis
#define CBotErrClosePar 5001 // missing the closing parenthesis
#define CBotErrNotBoolean 5002 // expression must be a boolean
#define CBotErrUndefVar 5003 // undeclared variable
#define CBotErrBadLeft 5004 // assignment impossible ( 5 = ... )
#define CBotErrNoTerminator 5005 // semicolon expected
#define CBotErrCaseOut 5006 // case outside a switch
#define CBotErrCloseBlock 5008 // missing " } "
#define CBotErrElseWhitoutIf 5009 // else without matching if
#define CBotErrOpenBlock 5010 // missing " { "
#define CBotErrBadType1 5011 // wrong type for the assignment
#define CBotErrRedefVar 5012 // redefinition of the variable
#define CBotErrBadType2 5013 // Two operands are incompatible
#define CBotErrUndefCall 5014 // routine undefined
#define CBotErrNoDoubleDots 5015 // " : " expected
#define CBotErrBreakOutside 5017 // break outside of a loop
#define CBotErrUndefLabel 5019 // label udnefined
#define CBotErrLabel 5018 // label ne peut se mettre ici (label can not get here)
#define CBotErrNoCase 5020 // missing " case "
#define CBotErrBadNum 5021 // expected number
#define CBotErrVoid 5022 // " void " not possible here
#define CBotErrNoType 5023 // type declaration expected
#define CBotErrNoVar 5024 // variable name expected
#define CBotErrNoFunc 5025 // expected function name
#define CBotErrOverParam 5026 // too many parameters
#define CBotErrRedefFunc 5027 // this function already exists
#define CBotErrLowParam 5028 // not enough parameters
#define CBotErrBadParam 5029 // wrong types of parameters
#define CBotErrNbParam 5030 // wrong number of parameters
#define CBotErrUndefItem 5031 // element does not exist in the class
#define CBotErrUndefClass 5032 // variable is not a class
#define CBotErrNoConstruct 5033 // no appropriate constructor
#define CBotErrRedefClass 5034 // class already exists
#define CBotErrCloseIndex 5035 // " ] " expected
#define CBotErrReserved 5036 // reserved word (for a DefineNum)
#define CBotErrBadNew 5037 // wrong setting for new
#define CBotErrOpenIndex 5038 // " [ " expected
#define CBotErrBadString 5039 // expected string
#define CBotErrBadIndex 5040 // wrong index type "[ false ]"
#define CBotErrPrivate 5041 // protected item
#define CBotErrNoPublic 5042 // missing word "public"
// here is the list of errors that can be returned by the module
// for the execution
#define CBotErrZeroDiv 6000 // division by zero
#define CBotErrNotInit 6001 // uninitialized variable
#define CBotErrBadThrow 6002 // throw a negative value
#define CBotErrNoRetVal 6003 // function did not return results
#define CBotErrNoRun 6004 // Run() without active function
#define CBotErrUndefFunc 6005 // calling a function that no longer exists
#define CBotErrNotClass 6006 // this class does not exist
#define CBotErrNull 6007 // null pointer
#define CBotErrNan 6008 // calculation with a NAN
#define CBotErrOutArray 6009 // index out of array
#define CBotErrStackOver 6010 // stack overflow
#define CBotErrDeletedPtr 6011 // pointer to an object destroyed
#define CBotErrFileOpen 6012 // cannot open the file
#define CBotErrNotOpen 6013 // channel not open
#define CBotErrRead 6014 // error while reading
#define CBotErrWrite 6015 // writing error
// other values may be returned
// for example exceptions returned by external routines
// and " throw " with any number.
// TODO: refactor & change to enum!
// Compile errors
#define TX_OPENPAR 5000
#define TX_CLOSEPAR 5001
#define TX_NOTBOOL 5002
#define TX_UNDEFVAR 5003
#define TX_BADLEFT 5004
#define TX_ENDOF 5005
#define TX_OUTCASE 5006
#define TX_CLOSEBLK 5008
#define TX_ELSEWITHOUTIF 5009
#define TX_OPENBLK 5010
#define TX_BADTYPE 5011
#define TX_REDEFVAR 5012
#define TX_BAD2TYPE 5013
#define TX_UNDEFCALL 5014
#define TX_MISDOTS 5015
#define TX_WHILE 5016
#define TX_BREAK 5017
#define TX_LABEL 5018
#define TX_NOLABEL 5019
#define TX_NOCASE 5020
#define TX_BADNUM 5021
#define TX_VOID 5022
#define TX_NOTYP 5023
#define TX_NOVAR 5024
#define TX_NOFONC 5025
#define TX_OVERPARAM 5026
#define TX_REDEF 5027
#define TX_LOWPARAM 5028
#define TX_BADPARAM 5029
#define TX_NUMPARAM 5030
#define TX_NOITEM 5031
#define TX_DOT 5032
#define TX_NOCONST 5033
#define TX_REDEFCLASS 5034
#define TX_CLBRK 5035
#define TX_RESERVED 5036
#define TX_BADNEW 5037
#define TX_BADSTRING 5039
#define TX_BADINDEX 5040
#define TX_PRIVATE 5041
#define TX_NOPUBLIC 5042
// Runtime errors
#define TX_DIVZERO 6000
#define TX_NOTINIT 6001
#define TX_BADTHROW 6002
#define TX_NORUN 6004
#define TX_NOCALL 6005
#define TX_NOCLASS 6006
#define TX_NULLPT 6007
#define TX_OPNAN 6008
#define TX_OUTARRAY 6009
#define TX_STACKOVER 6010
#define TX_DELETEDPT 6011
// Max errors
#define TX_MAX 6012

File diff suppressed because it is too large Load Diff

155
src/CBot/CBotEnums.h Normal file
View File

@ -0,0 +1,155 @@
/*
* 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
// Local include
// Global include
/*! \brief CBotType Defines known types. This types are modeled on Java types.
* Do not change the order of elements
*/
enum CBotType
{
CBotTypVoid = 0,
CBotTypByte = 1, //n
CBotTypShort = 2, //n
CBotTypChar = 3, //n
CBotTypInt = 4,
CBotTypLong = 5, //n
CBotTypFloat = 6,
CBotTypDouble = 7, //n
CBotTypBoolean = 8,
CBotTypString = 9,
CBotTypArrayPointer = 10, // array of variables
CBotTypArrayBody = 11, // same but creates an instance
CBotTypPointer = 12, // pointer to an instance
CBotTypNullPointer = 13, // null pointer is special
CBotTypClass = 15,
CBotTypIntrinsic = 16 // instance of a class intrinsic
};
//n = not implemented yet
//! \brief CBotGet Different modes for GetPosition.
enum CBotGet
{
GetPosExtern = 1,
GetPosNom = 2,
GetPosParam = 3,
GetPosBloc = 4
};
enum EID
{
ID_IF = 2000,
ID_ELSE,
ID_WHILE,
ID_DO,
ID_FOR,
ID_BREAK,
ID_CONTINUE,
ID_SWITCH,
ID_CASE,
ID_DEFAULT,
ID_TRY,
ID_THROW,
ID_CATCH,
ID_FINALLY,
ID_TXT_AND,
ID_TXT_OR,
ID_TXT_NOT,
ID_RETURN,
ID_CLASS,
ID_EXTENDS,
ID_SYNCHO,
ID_NEW,
ID_PUBLIC,
ID_EXTERN,
ID_STATIC,
ID_PROTECTED,
ID_PRIVATE,
ID_INT,
ID_FLOAT,
ID_BOOLEAN,
ID_STRING,
ID_VOID,
ID_BOOL,
ID_TRUE = 2200,
ID_FALSE,
ID_NULL,
ID_NAN,
ID_OPENPAR = 2300,
ID_CLOSEPAR,
ID_OPBLK,
ID_CLBLK,
ID_SEP,
ID_COMMA,
ID_DOTS,
ID_DOT,
ID_OPBRK,
ID_CLBRK,
ID_DBLDOTS,
ID_LOGIC,
ID_ADD,
ID_SUB,
ID_MUL,
ID_DIV,
ID_ASS,
ID_ASSADD,
ID_ASSSUB,
ID_ASSMUL,
ID_ASSDIV,
ID_ASSOR,
ID_ASSAND,
ID_ASSXOR,
ID_ASSSL,
ID_ASSSR,
ID_ASSASR,
ID_SL,
ID_SR,
ID_ASR,
ID_INC,
ID_DEC,
ID_LO,
ID_HI,
ID_LS,
ID_HS,
ID_EQ,
ID_NE,
ID_AND,
ID_XOR,
ID_OR,
ID_LOG_AND,
ID_LOG_OR,
ID_LOG_NOT,
ID_NOT,
ID_MODULO,
ID_POWER,
ID_ASSMODULO,
TX_UNDEF = 4000,
TX_NAN
};

175
src/CBot/CBotFileUtils.cpp Normal file
View File

@ -0,0 +1,175 @@
/*
* 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 "CBot/CBotFileUtils.h"
#include "CBot/CBotString.h"
#include "CBot/CBotClass.h"
#include "CBot/CBotEnums.h"
// Local include
// Global include
// file management
// necessary because it is not possible to do the fopen in the main program
// fwrite and fread in a dll or using the FILE * returned.
////////////////////////////////////////////////////////////////////////////////
FILE* fOpen(const char* name, const char* mode)
{
return fopen(name, mode);
}
////////////////////////////////////////////////////////////////////////////////
int fClose(FILE* filehandle)
{
return fclose(filehandle);
}
////////////////////////////////////////////////////////////////////////////////
std::size_t fWrite(const void *buffer,
std::size_t elemsize,
std::size_t length,
FILE* filehandle)
{
return fwrite(buffer, elemsize, length, filehandle);
}
////////////////////////////////////////////////////////////////////////////////
std::size_t fRead(void *buffer,
std::size_t elemsize,
std::size_t length,
FILE* filehandle)
{
return fread(buffer, elemsize, length, filehandle);
}
////////////////////////////////////////////////////////////////////////////////
bool ReadWord(FILE* pf, unsigned short& w)
{
size_t lg;
lg = fread(&w, sizeof( unsigned short ), 1, pf );
return (lg == 1);
}
////////////////////////////////////////////////////////////////////////////////
bool ReadFloat(FILE* pf, float& w)
{
size_t lg;
lg = fread(&w, sizeof( float ), 1, pf );
return (lg == 1);
}
////////////////////////////////////////////////////////////////////////////////
bool WriteLong(FILE* pf, long w)
{
size_t lg;
lg = fwrite(&w, sizeof( long ), 1, pf );
return (lg == 1);
}
////////////////////////////////////////////////////////////////////////////////
bool ReadLong(FILE* pf, long& w)
{
size_t lg;
lg = fread(&w, sizeof( long ), 1, pf );
return (lg == 1);
}
////////////////////////////////////////////////////////////////////////////////
bool ReadString(FILE* pf, CBotString& s)
{
unsigned short w;
char buf[1000];
size_t lg1, lg2;
if (!ReadWord(pf, w)) return false;
lg1 = w;
lg2 = fread(buf, 1, lg1, pf );
buf[lg2] = 0;
s = buf;
return (lg1 == lg2);
}
////////////////////////////////////////////////////////////////////////////////
bool WriteType(FILE* pf, const CBotTypResult &type)
{
int typ = type.GetType();
if ( typ == CBotTypIntrinsic ) typ = CBotTypClass;
if ( !WriteWord(pf, typ) ) return false;
if ( typ == CBotTypClass )
{
CBotClass* p = type.GetClass();
if ( !WriteString(pf, p->GetName()) ) return false;
}
if ( type.Eq( CBotTypArrayBody ) ||
type.Eq( CBotTypArrayPointer ) )
{
if ( !WriteWord(pf, type.GetLimite()) ) return false;
if ( !WriteType(pf, type.GetTypElem()) ) return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool ReadType(FILE* pf, CBotTypResult &type)
{
unsigned short w, ww;
if ( !ReadWord(pf, w) ) return false;
type.SetType(w);
if ( type.Eq( CBotTypIntrinsic ) )
{
type = CBotTypResult( w, "point" );
}
if ( type.Eq( CBotTypClass ) )
{
CBotString s;
if ( !ReadString(pf, s) ) return false;
type = CBotTypResult( w, s );
}
if ( type.Eq( CBotTypArrayPointer ) ||
type.Eq( CBotTypArrayBody ) )
{
CBotTypResult r;
if ( !ReadWord(pf, ww) ) return false;
if ( !ReadType(pf, r) ) return false;
type = CBotTypResult( w, r );
type.SetLimite(static_cast<short>(ww));
}
return true;
}

156
src/CBot/CBotFileUtils.h Normal file
View File

@ -0,0 +1,156 @@
/*
* 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
// Local include
// Global include
#include <cstdio>
// Forward declaration
class CBotVar;
class CBotString;
class CBotTypResult;
///////////////////////////////////////////////////////////////////////////////
// routines for file management (* FILE)
/*!
* \brief fOpen
* \param name
* \param mode
* \return
*/
FILE* fOpen(const char* name, const char* mode);
/*!
* \brief fClose
* \param filehandle
* \return
*/
int fClose(FILE* filehandle);
/*!
* \brief fWrite
* \param buffer
* \param elemsize
* \param length
* \param filehandle
* \return
*/
std::size_t fWrite(const void *buffer,
std::size_t elemsize,
std::size_t length,
FILE* filehandle);
/*!
* \brief fRead
* \param buffer
* \param elemsize
* \param length
* \param filehandle
* \return
*/
std::size_t fRead(void *buffer,
std::size_t elemsize,
std::size_t length,
FILE* filehandle);
/*!
* \brief SaveVar
* \param pf
* \param pVar
* \return
*/
bool SaveVar(FILE* pf, CBotVar* pVar);
/*!
* \brief WriteWord
* \param pf
* \param w
* \return
*/
bool WriteWord(FILE* pf, unsigned short w);
/*!
* \brief ReadWord
* \param pf
* \param w
* \return
*/
bool ReadWord(FILE* pf, unsigned short& w);
/*!
* \brief ReadLong
* \param pf
* \param w
* \return
*/
bool ReadLong(FILE* pf, long& w);
/*!
* \brief WriteFloat
* \param pf
* \param w
* \return
*/
bool WriteFloat(FILE* pf, float w);
/*!
* \brief WriteLong
* \param pf
* \param w
* \return
*/
bool WriteLong(FILE* pf, long w);
/*!
* \brief ReadFloat
* \param pf
* \param w
* \return
*/
bool ReadFloat(FILE* pf, float& w);
/*!
* \brief ReadString
* \param pf
* \param s
* \return
*/
bool ReadString(FILE* pf, CBotString& s);
/*!
* \brief WriteType
* \param pf
* \param type
* \return
*/
bool WriteType(FILE* pf, const CBotTypResult &type);
/*!
* \brief ReadType
* \param pf
* \param type
* \return
*/
bool ReadType(FILE* pf, CBotTypResult &type);

View File

@ -0,0 +1,73 @@
/*
* 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 "CBot/CBotInstr/CBotBlock.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotInstr/CBotListInstr.h"
#include "CBot/CBotDefines.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotBlock::Compile(CBotToken* &p, CBotCStack* pStack, bool bLocal)
{
pStack->SetStartError(p->GetStart());
if (IsOfType(p, ID_OPBLK))
{
CBotInstr* inst = CBotListInstr::Compile(p, pStack, bLocal);
if (IsOfType(p, ID_CLBLK))
{
return inst;
}
pStack->SetError(TX_CLOSEBLK, p->GetStart()); // missing parenthesis
delete inst;
return nullptr;
}
pStack->SetError(TX_OPENBLK, p->GetStart());
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotBlock::CompileBlkOrInst(CBotToken* &p, CBotCStack* pStack, bool bLocal)
{
// is this a new block
if (p->GetType() == ID_OPBLK) return CBotBlock::Compile(p, pStack);
// otherwise, look for a single statement instead
// to handle the case with local definition instruction (*)
CBotCStack* pStk = pStack->TokenStack(p, bLocal);
return pStack->Return( CBotInstr::Compile(p, pStk), // a single instruction
pStk);
}
// (*) is the case in the following statement
// if (1 == 1) int x = 0;
// where the variable x is known only in the block following the if

View File

@ -0,0 +1,64 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotBlock class An instruction block { .... }.
*/
class CBotBlock : public CBotInstr
{
public:
/*!
* \brief Compile Compiles a statement block " { i ; i ; } "
* \param p
* \param pStack
* \param bLocal
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool bLocal = true);
/*!
* \brief CompileBlkOrInst
* \param p
* \param pStack
* \param bLocal
* \return
*/
static CBotInstr* CompileBlkOrInst(CBotToken* &p, CBotCStack* pStack, bool bLocal = false);
private:
/*!
* \brief CBotBlock This class have no constructor because there is never an
* instance of this class the object returned by Compile is usually of type
* CBotListInstr
*/
CBotBlock() = delete;
CBotBlock(const CBotBlock &) = delete;
};

View File

@ -0,0 +1,52 @@
/*
* 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 "CBot/CBotInstr/CBotBoolExpr.h"
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotDefines.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotBoolExpr::Compile(CBotToken* &p, CBotCStack* pStack)
{
pStack->SetStartError(p->GetStart());
CBotInstr* inst = CBotTwoOpExpr::Compile(p, pStack);
if (nullptr != inst)
{
if (pStack->GetTypResult().Eq(CBotTypBoolean))
{
return inst;
}
pStack->SetError(TX_NOTBOOL, p->GetStart()); // is not a boolean
}
delete inst;
return nullptr;
}

View File

@ -0,0 +1,47 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotBoolExpr class Compile a statement such as "(condition)"
* the condition must be Boolean. This class has no constructor, because there
* is never an instance of this class the object returned by Compile is usually
* type CBotExpression
*/
class CBotBoolExpr : public CBotInstr
{
public:
/*!
* \brief Compile
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
};

View File

@ -0,0 +1,178 @@
/*
* 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 "CBot/CBotInstr/CBotBoolean.h"
#include "CBot/CBotInstr/CBotLeftExprVar.h"
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
#include "CBot/CBotInstr/CBotInstArray.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotBoolean::CBotBoolean()
{
m_var =
m_expr = nullptr;
name = "CBotBoolean";
}
////////////////////////////////////////////////////////////////////////////////
CBotBoolean::~CBotBoolean()
{
delete m_var;
delete m_expr;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotBoolean::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, bool noskip)
{
CBotToken* pp = cont ? nullptr : p;
if (!cont && !IsOfType(p, ID_BOOLEAN, ID_BOOL)) return nullptr;
CBotBoolean* inst = static_cast<CBotBoolean*>(CompileArray(p, pStack, CBotTypBoolean));
if (inst != nullptr || !pStack->IsOk()) return inst;
CBotCStack* pStk = pStack->TokenStack(pp);
inst = new CBotBoolean();
inst->m_expr = nullptr;
CBotToken* vartoken = p;
inst->SetToken(vartoken);
CBotVar* var = nullptr;
if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )))
{
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = CBotTypBoolean;
if (pStk->CheckVarLocal(vartoken)) // redefinition of the variable
{
pStk->SetError(TX_REDEFVAR, vartoken);
goto error;
}
if (IsOfType(p, ID_OPBRK))
{
delete inst; // type is not CBotInt
p = vartoken; // resutns to the variable name
// compiles an array declaration
inst = static_cast<CBotBoolean*>(CBotInstArray::Compile(p, pStk, CBotTypBoolean));
if (!pStk->IsOk() )
{
pStk->SetError(TX_CLBRK, p->GetStart());
goto error;
}
goto suite; // no assignment, variable already created
}
if (IsOfType(p, ID_ASS))
{
if (nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )))
{
goto error;
}
if (!pStk->GetTypResult().Eq(CBotTypBoolean))
{
pStk->SetError(TX_BADTYPE, p->GetStart());
goto error;
}
}
var = CBotVar::Create(vartoken, CBotTypBoolean);// create the variable (evaluated after the assignment)
var->SetInit(inst->m_expr != nullptr ? CBotVar::InitType::DEF : CBotVar::InitType::UNDEF);
var->SetUniqNum(
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
pStack->AddVar(var);
suite:
if (IsOfType(p, ID_COMMA))
{
if (nullptr != ( inst->m_next2b = CBotBoolean::Compile(p, pStk, true, noskip)))
{
return pStack->Return(inst, pStk);
}
}
if (noskip || IsOfType(p, ID_SEP))
{
return pStack->Return(inst, pStk);
}
pStk->SetError(TX_ENDOF, p->GetStart());
}
error:
delete inst;
return pStack->Return(nullptr, pStk);
}
////////////////////////////////////////////////////////////////////////////////
bool CBotBoolean::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this);//essential for SetState()
if ( pile->GetState()==0)
{
if (m_expr && !m_expr->Execute(pile)) return false;
m_var->Execute(pile);
if (!pile->SetState(1)) return false;
}
if (pile->IfStep()) return false;
if ( m_next2b &&
!m_next2b->Execute(pile)) return false;
return pj->Return(pile);
}
////////////////////////////////////////////////////////////////////////////////
void CBotBoolean::RestoreState(CBotStack* &pj, bool bMain)
{
CBotStack* pile = pj;
if (bMain)
{
pile = pj->RestoreStack(this);
if (pile == nullptr) return;
if ( pile->GetState()==0)
{
if (m_expr) m_expr->RestoreState(pile, bMain); // initial value interrupted?
return;
}
}
m_var->RestoreState(pile, bMain);
if (m_next2b)
m_next2b->RestoreState(pile, bMain); // other(s) definition(s)
}

View File

@ -0,0 +1,76 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotBoolean class Defining a boolean variable int a, b = false;
*/
class CBotBoolean : public CBotInstr
{
public:
/*!
* \brief CBotBoolean
*/
CBotBoolean();
/*!
* \brief ~CBotBoolean
*/
~CBotBoolean();
/*!
* \brief Compile
* \param p
* \param pStack
* \param cont
* \param noskip
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool cont = false, bool noskip=false);
/*!
* \brief Execute Executes a boolean variable definition.
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! Variable to initialise.
CBotInstr* m_var;
//! A value to put, if there is.
CBotInstr* m_expr;
};

View File

@ -0,0 +1,96 @@
/*
* 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 "CBot/CBotInstr/CBotBreak.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotBreak::CBotBreak()
{
name = "CBotBreak"; // debug
}
////////////////////////////////////////////////////////////////////////////////
CBotBreak::~CBotBreak()
{
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotBreak::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotToken* pp = p; // preserves at the ^ token (starting position)
int type = p->GetType();
if (!IsOfType(p, ID_BREAK, ID_CONTINUE)) return nullptr; // should never happen
if ( !ChkLvl(CBotString(), type ) )
{
pStack->SetError(TX_BREAK, pp);
return nullptr; // no object, the error is on the stack
}
CBotBreak* inst = new CBotBreak(); // creates the object
inst->SetToken(pp); // keeps the operation
pp = p;
if ( IsOfType( p, TokenTypVar ) )
{
inst->m_label = pp->GetString(); // register the name of label
if ( !ChkLvl(inst->m_label, type ) )
{
delete inst;
pStack->SetError(TX_NOLABEL, pp);
return nullptr; // no object, the error is on the stack
}
}
if (IsOfType(p, ID_SEP))
{
return inst; // return what it wants
}
delete inst;
pStack->SetError(TX_ENDOF, p->GetStart());
return nullptr; // no object, the error is on the stack
}
////////////////////////////////////////////////////////////////////////////////
bool CBotBreak :: Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this);
// if ( pile == EOX ) return true;
if ( pile->IfStep() ) return false;
pile->SetBreak(m_token.GetType()==ID_BREAK ? 1 : 2, m_label);
return pj->Return(pile);
}
////////////////////////////////////////////////////////////////////////////////
void CBotBreak :: RestoreState(CBotStack* &pj, bool bMain)
{
if ( bMain ) pj->RestoreStack(this);
}

View File

@ -0,0 +1,75 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotBreak class Compiles instruction "break" or "continu".
*/
class CBotBreak : public CBotInstr
{
public:
/*!
* \brief CBotBreak
*/
CBotBreak();
/*!
* \brief CBotBreak
*/
~CBotBreak();
/*!
* \brief Compile
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute Execution of statement "break" or "continu"
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! A label if there is
CBotString m_label;
};

View File

@ -0,0 +1,92 @@
/*
* 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 "CBot/CBotInstr/CBotCase.h"
#include "CBot/CBotInstr/CBotExprNum.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotCase::CBotCase()
{
m_Value = nullptr; // nullptr so that delete is not possible further
name = "CBotCase"; // debug
}
////////////////////////////////////////////////////////////////////////////////
CBotCase::~CBotCase()
{
delete m_Value; // frees the value
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotCase::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotCase* inst = new CBotCase(); // creates the object
CBotToken* pp = p; // preserves at the ^ token (starting position)
inst->SetToken(p);
if (!IsOfType(p, ID_CASE, ID_DEFAULT)) return nullptr; // should never happen
if ( pp->GetType() == ID_CASE )
{
pp = p;
inst->m_Value = CBotExprNum::Compile(p, pStack);
if ( inst->m_Value == nullptr )
{
pStack->SetError( TX_BADNUM, pp );
delete inst;
return nullptr;
}
}
if ( !IsOfType( p, ID_DOTS ))
{
pStack->SetError( TX_MISDOTS, p->GetStart() );
delete inst;
return nullptr;
}
return inst;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotCase::Execute(CBotStack* &pj)
{
return true; // the "case" statement does nothing!
}
////////////////////////////////////////////////////////////////////////////////
void CBotCase::RestoreState(CBotStack* &pj, bool bMain)
{
}
////////////////////////////////////////////////////////////////////////////////
bool CBotCase::CompCase(CBotStack* &pile, int val)
{
if ( m_Value == nullptr ) return true; // "default" case
while (!m_Value->Execute(pile)); // puts the value on the correspondent stack (without interruption)
return (pile->GetVal() == val); // compared with the given value
}

View File

@ -0,0 +1,83 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotCase class Compiles instruction "case" we are bound to the
* statement block "switch".
*/
class CBotCase : public CBotInstr
{
public:
/*!
* \brief CBotCase
*/
CBotCase();
/*!
* \brief ~CBotCase
*/
~CBotCase();
/*!
* \brief Compile
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute Execution of instruction "case".
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
/*!
* \brief CompCase Routine to find the entry point of "case" corresponding
* to the value seen.
* \param pj
* \param val
* \return
*/
bool CompCase(CBotStack* &pj, int val) override;
private:
//! Value to compare.
CBotInstr* m_Value;
};

View File

@ -0,0 +1,114 @@
/*
* 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 "CBot/CBotInstr/CBotCatch.h"
#include "CBot/CBotInstr/CBotBlock.h"
#include "CBot/CBotInstr/CBotExpression.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotCatch::CBotCatch()
{
m_Cond =
m_Block = nullptr; // nullptr so that delete is not possible further
m_next = nullptr;
name = "CBotCatch"; // debug
}
////////////////////////////////////////////////////////////////////////////////
CBotCatch::~CBotCatch()
{
delete m_Cond; // frees the list
delete m_Block; // frees the instruction block
delete m_next; // and subsequent
}
////////////////////////////////////////////////////////////////////////////////
CBotCatch* CBotCatch::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotCatch* inst = new CBotCatch(); // creates the object
pStack->SetStartError(p->GetStart());
inst->SetToken(p);
if (!IsOfType(p, ID_CATCH)) return nullptr; // should never happen
if (IsOfType(p, ID_OPENPAR))
{
inst->m_Cond = CBotExpression::Compile(p, pStack);
if (( pStack->GetType() < CBotTypLong ||
pStack->GetTypResult().Eq(CBotTypBoolean) )&& pStack->IsOk() )
{
if (IsOfType(p, ID_CLOSEPAR))
{
inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStack );
if ( pStack->IsOk() )
return inst; // return an object to the application
}
pStack->SetError(TX_CLOSEPAR, p->GetStart());
}
pStack->SetError(TX_BADTYPE, p->GetStart());
}
pStack->SetError(TX_OPENPAR, p->GetStart());
delete inst; // error, frees up
return nullptr; // no object, the error is on the stack
}
////////////////////////////////////////////////////////////////////////////////
bool CBotCatch :: Execute(CBotStack* &pj)
{
if ( m_Block == nullptr ) return true;
return m_Block->Execute(pj); // executes the associated block
}
////////////////////////////////////////////////////////////////////////////////
void CBotCatch :: RestoreState(CBotStack* &pj, bool bMain)
{
if ( bMain && m_Block != nullptr ) m_Block->RestoreState(pj, bMain);
}
////////////////////////////////////////////////////////////////////////////////
void CBotCatch :: RestoreCondState(CBotStack* &pj, bool bMain)
{
m_Cond->RestoreState(pj, bMain);
}
////////////////////////////////////////////////////////////////////////////////
bool CBotCatch :: TestCatch(CBotStack* &pile, int val)
{
if ( !m_Cond->Execute(pile) ) return false;
if ( val > 0 || pile->GetType() != CBotTypBoolean )
{
CBotVar* var = CBotVar::Create(static_cast<CBotToken*>(nullptr), CBotTypBoolean);
var->SetValInt( pile->GetVal() == val );
pile->SetVar(var); // calls on the stack
}
return true;
}

View File

@ -0,0 +1,93 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotCatch class. Compiles instruction "catch".
*/
class CBotCatch : public CBotInstr
{
public:
/*!
* \brief CBotCatch
*/
CBotCatch();
/*!
* \brief CBotCatch
*/
~CBotCatch();
/*!
* \brief Compile
* \param p
* \param pStack
* \return
*/
static CBotCatch* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief TestCatch Routine to see if the catch is to do or not.
* \param pj
* \param val
* \return
*/
bool TestCatch(CBotStack* &pj, int val);
/*!
* \brief Execute Execution of "catch".
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
/*!
* \brief RestoreCondState
* \param pj
* \param bMain
*/
void RestoreCondState(CBotStack* &pj, bool bMain);
private:
//! Instructions
CBotInstr* m_Block;
//! Condition
CBotInstr* m_Cond;
//! Following catch
CBotCatch* m_next;
friend class CBotTry;
};

View File

@ -0,0 +1,441 @@
/*
* 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 "CBotClassInst.h"
#include "CBot/CBotInstr/CBotInstrUtils.h"
#include "CBot/CBotInstr/CBotLeftExprVar.h"
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
#include "CBot/CBotInstr/CBotInstArray.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotClass.h"
#include "CBot/CBotVar/CBotVarPointer.h"
#include "CBot/CBotVar/CBotVarClass.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotClassInst::CBotClassInst()
{
m_next = nullptr;
m_var = nullptr;
m_Parameters = nullptr;
m_expr = nullptr;
m_hasParams = false;
m_nMethodeIdent = 0;
name = "CBotClassInst";
}
////////////////////////////////////////////////////////////////////////////////
CBotClassInst::~CBotClassInst()
{
delete m_var;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotClassInst::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* pClass)
{
// seeks the corresponding classes
if ( pClass == nullptr )
{
pStack->SetStartError(p->GetStart());
pClass = CBotClass::Find(p);
if ( pClass == nullptr )
{
// not found? is bizare
pStack->SetError(TX_NOCLASS, p);
return nullptr;
}
p = p->GetNext();
}
bool bIntrinsic = pClass->IsIntrinsic();
CBotTypResult type = CBotTypResult( bIntrinsic ? CBotTypIntrinsic : CBotTypPointer, pClass );
CBotClassInst* inst = static_cast<CBotClassInst*>(CompileArray(p, pStack, type));
if ( inst != nullptr || !pStack->IsOk() ) return inst;
CBotCStack* pStk = pStack->TokenStack();
inst = new CBotClassInst();
/// TODO Need to be revised and fixed after adding unit tests
CBotToken token(pClass->GetName(), CBotString(), p->GetStart(), p->GetEnd());
inst->SetToken(&token);
CBotToken* vartoken = p;
if ( nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )) )
{
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = type;
if (pStk->CheckVarLocal(vartoken)) // redefinition of the variable
{
pStk->SetStartError(vartoken->GetStart());
pStk->SetError(TX_REDEFVAR, vartoken->GetEnd());
goto error;
}
if (IsOfType(p, ID_OPBRK)) // with any clues?
{
delete inst; // is not type CBotInt
p = vartoken; // returns to the variable name
// compiles declaration an array
inst = static_cast<CBotClassInst*>(CBotInstArray::Compile( p, pStk, type ));
if (!pStk->IsOk() )
{
pStk->SetError(TX_CLBRK, p->GetStart());
goto error;
}
goto suite; // no assignment, variable already created
}
CBotVar* var;
var = CBotVar::Create(vartoken->GetString(), type); // creates the instance
// var->SetClass(pClass);
var->SetUniqNum(
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
// its attribute a unique number
pStack->AddVar(var); // placed on the stack
// look if there are parameters
inst->m_hasParams = (p->GetType() == ID_OPENPAR);
CBotVar* ppVars[1000];
inst->m_Parameters = CompileParams(p, pStk, ppVars);
if ( !pStk->IsOk() ) goto error;
// if there are parameters, is the equivalent to the stament "new"
// CPoint A ( 0, 0 ) is equivalent to
// CPoint A = new CPoint( 0, 0 )
// if ( nullptr != inst->m_Parameters )
if ( inst->m_hasParams )
{
// the constructor is there?
// CBotString noname;
CBotTypResult r = pClass->CompileMethode(pClass->GetName(), var, ppVars, pStk, inst->m_nMethodeIdent);
delete pStk->TokenStack(); // releases the supplement stack
int typ = r.GetType();
if (typ == TX_UNDEFCALL)
{
// si le constructeur n'existe pas
if (inst->m_Parameters != nullptr) // with parameters
{
pStk->SetError(TX_NOCONST, vartoken);
goto error;
}
typ = 0;
}
if (typ>20)
{
pStk->SetError(typ, vartoken->GetEnd());
goto error;
}
}
if (IsOfType(p, ID_ASS)) // with a assignment?
{
if (inst->m_hasParams)
{
pStk->SetError(TX_ENDOF, p->GetStart());
goto error;
}
if ( nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )) )
{
goto error;
}
CBotClass* result = pStk->GetClass();
if ( !pStk->GetTypResult(1).Eq(CBotTypNullPointer) &&
( !pStk->GetTypResult(1).Eq(CBotTypPointer) ||
( result != nullptr && !pClass->IsChildOf(result) ))) // type compatible ?
{
pStk->SetError(TX_BADTYPE, p->GetStart());
goto error;
}
// if ( !bIntrinsic ) var->SetPointer(pStk->GetVar()->GetPointer());
if ( !bIntrinsic )
{
// does not use the result on the stack, to impose the class
CBotVar* pvar = CBotVar::Create("", pClass);
var->SetPointer( pvar ); // variable already declared instance pointer
delete pvar; // removes the second pointer
}
var->SetInit(CBotVar::InitType::DEF); // marks the pointer as init
}
else if (inst->m_hasParams)
{
// creates the object on the "job" (\TODO "tas")
// with a pointer to the object
if ( !bIntrinsic )
{
CBotVar* pvar = CBotVar::Create("", pClass);
var->SetPointer( pvar ); // variable already declared instance pointer
delete pvar; // removes the second pointer
}
var->SetInit(CBotVar::InitType::IS_POINTER); // marks the pointer as init
}
suite:
if (IsOfType(p, ID_COMMA)) // several chained definitions
{
if ( nullptr != ( inst->m_next = CBotClassInst::Compile(p, pStk, pClass) )) // compiles the following
{
return pStack->Return(inst, pStk);
}
}
if (IsOfType(p, ID_SEP)) // complete instruction
{
return pStack->Return(inst, pStk);
}
pStk->SetError(TX_ENDOF, p->GetStart());
}
error:
delete inst;
return pStack->Return(nullptr, pStk);
}
////////////////////////////////////////////////////////////////////////////////
bool CBotClassInst::Execute(CBotStack* &pj)
{
CBotVar* pThis = nullptr;
CBotStack* pile = pj->AddStack(this);//essential for SetState()
// if ( pile == EOX ) return true;
CBotToken* pt = &m_token;
CBotClass* pClass = CBotClass::Find(pt);
bool bIntrincic = pClass->IsIntrinsic();
// creates the variable of type pointer to the object
if ( pile->GetState()==0)
{
CBotString name = m_var->m_token.GetString();
if ( bIntrincic )
{
pThis = CBotVar::Create(name, CBotTypResult( CBotTypIntrinsic, pClass ));
}
else
{
pThis = CBotVar::Create(name, CBotTypResult( CBotTypPointer, pClass ));
}
pThis->SetUniqNum((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent); // its attribute as unique number
pile->AddVar(pThis); // place on the stack
pile->IncState();
}
if ( pThis == nullptr ) pThis = pile->FindVar((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent);
if ( pile->GetState()<3)
{
// ss there an assignment or parameters (contructor)
// CBotVarClass* pInstance = nullptr;
if ( m_expr != nullptr )
{
// evaluates the expression for the assignment
if (!m_expr->Execute(pile)) return false;
if ( bIntrincic )
{
CBotVar* pv = pile->GetVar();
if ( pv == nullptr || pv->GetPointer() == nullptr )
{
pile->SetError(TX_NULLPT, &m_token);
return pj->Return(pile);
}
pThis->Copy(pile->GetVar(), false);
}
else
{
CBotVarClass* pInstance;
pInstance = (static_cast<CBotVarPointer*>(pile->GetVar()))->GetPointer(); // value for the assignment
pThis->SetPointer(pInstance);
}
pThis->SetInit(CBotVar::InitType::DEF);
}
else if ( m_hasParams )
{
// evaluates the constructor of an instance
if ( !bIntrincic && pile->GetState() == 1)
{
CBotToken* pt = &m_token;
CBotClass* pClass = CBotClass::Find(pt);
// creates an instance of the requested class
CBotVarClass* pInstance;
pInstance = static_cast<CBotVarClass*>(CBotVar::Create("", pClass));
pThis->SetPointer(pInstance);
delete pInstance;
pile->IncState();
}
CBotVar* ppVars[1000];
CBotStack* pile2 = pile;
int i = 0;
CBotInstr* p = m_Parameters;
// evaluates the parameters
// and places the values on the stack
// to (can) be interrupted (broken) at any time
if ( p != nullptr) while ( true )
{
pile2 = pile2->AddStack(); // place on the stack for the results
if ( pile2->GetState() == 0 )
{
if (!p->Execute(pile2)) return false; // interrupted here?
pile2->SetState(1);
}
ppVars[i++] = pile2->GetVar();
p = p->GetNext();
if ( p == nullptr) break;
}
ppVars[i] = nullptr;
// creates a variable for the result
CBotVar* pResult = nullptr; // constructor still void
if ( !pClass->ExecuteMethode(m_nMethodeIdent, pClass->GetName(),
pThis, ppVars,
pResult, pile2, GetToken())) return false; // interrupt
pThis->SetInit(CBotVar::InitType::DEF);
pThis->ConstructorSet(); // indicates that the constructor has been called
pile->Return(pile2); // releases a piece of stack
// pInstance = pThis->GetPointer();
}
// if ( !bIntrincic ) pThis->SetPointer(pInstance); // a pointer to the instance
pile->SetState(3); // finished this part
}
if ( pile->IfStep() ) return false;
if ( m_next2b != nullptr &&
!m_next2b->Execute(pile)) return false; // other (s) definition (s)
return pj->Return( pile ); // transmits below (further)
}
////////////////////////////////////////////////////////////////////////////////
void CBotClassInst::RestoreState(CBotStack* &pj, bool bMain)
{
CBotVar* pThis = nullptr;
CBotStack* pile = pj;
if ( bMain ) pile = pj->RestoreStack(this);
if ( pile == nullptr ) return;
// creates the variable of type pointer to the object
{
CBotString name = m_var->m_token.GetString();
pThis = pile->FindVar(name);
pThis->SetUniqNum((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent); // its attribute a unique number
}
CBotToken* pt = &m_token;
CBotClass* pClass = CBotClass::Find(pt);
bool bIntrincic = pClass->IsIntrinsic();
if ( bMain && pile->GetState()<3)
{
// is there an assignment or parameters (constructor)
// CBotVarClass* pInstance = nullptr;
if ( m_expr != nullptr )
{
// evaluates the expression for the assignment
m_expr->RestoreState(pile, bMain);
return;
}
else if ( m_hasParams )
{
// evaluates the constructor of an instance
if ( !bIntrincic && pile->GetState() == 1)
{
return;
}
CBotVar* ppVars[1000];
CBotStack* pile2 = pile;
int i = 0;
CBotInstr* p = m_Parameters;
// evaluates the parameters
// and the values an the stack
// for the ability to be interrupted at any time (\TODO pour pouvoir être interrompu n'importe quand)
if ( p != nullptr) while ( true )
{
pile2 = pile2->RestoreStack(); // place on the stack for the results
if ( pile2 == nullptr ) return;
if ( pile2->GetState() == 0 )
{
p->RestoreState(pile2, bMain); // interrupted here?
return;
}
ppVars[i++] = pile2->GetVar();
p = p->GetNext();
if ( p == nullptr) break;
}
ppVars[i] = nullptr;
// creates a variable for the result
// CBotVar* pResult = nullptr; // constructor still void
pClass->RestoreMethode(m_nMethodeIdent, pClass->GetName(), pThis, ppVars, pile2);
return;
}
}
if ( m_next2b != nullptr )
m_next2b->RestoreState(pile, bMain); // other(s) definition(s)
}

View File

@ -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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotClassInst class Definition of an element of any class.
*/
class CBotClassInst : public CBotInstr
{
public:
/*!
* \brief CBotClassInst
*/
CBotClassInst();
/*!
* \brief ~CBotClassInst
*/
~CBotClassInst();
/*!
* \brief Compile Definition of pointer (s) to an object style CPoint A, B ;
* \param p
* \param pStack
* \param pClass
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* pClass = nullptr);
/*!
* \brief Execute Declaration of the instance of a class, for example:
* CPoint A, B;
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! Variable to initialise.
CBotInstr* m_var;
//! Reference to the class.
CBotClass* m_pClass;
//! Parameters to be evaluated for the contructor.
CBotInstr* m_Parameters;
//! A value to put, if there is.
CBotInstr* m_expr;
//! Has it parameters.
bool m_hasParams;
long m_nMethodeIdent;
};

View File

@ -0,0 +1,54 @@
/*
* 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 "CBot/CBotInstr/CBotCondition.h"
#include "CBot/CBotInstr/CBotBoolExpr.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotDefines.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotCondition::Compile(CBotToken* &p, CBotCStack* pStack)
{
pStack->SetStartError(p->GetStart());
if (IsOfType(p, ID_OPENPAR))
{
CBotInstr* inst = CBotBoolExpr::Compile(p, pStack);
if (nullptr != inst)
{
if (IsOfType(p, ID_CLOSEPAR))
{
return inst;
}
pStack->SetError(TX_CLOSEPAR, p->GetStart()); // missing parenthesis
}
delete inst;
}
pStack->SetError(TX_OPENPAR, p->GetStart()); // missing parenthesis
return nullptr;
}

View File

@ -0,0 +1,46 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotCondition class This class has no constructor, because there
* is never an instance of this class the object returned by Compile is usually
* type CBotExpression
*/
class CBotCondition : public CBotInstr
{
public:
/*!
* \brief Compile Compile a statement such as "(condition)" the condition
* must be Boolean
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
};

View File

@ -0,0 +1,159 @@
/*
* 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 "CBot/CBotInstr/CBotDo.h"
#include "CBot/CBotInstr/CBotBlock.h"
#include "CBot/CBotInstr/CBotCondition.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotDo::CBotDo()
{
m_Condition =
m_Block = nullptr; // nullptr so that delete is not possible further
name = "CBotDo"; // debug
}
////////////////////////////////////////////////////////////////////////////////
CBotDo::~CBotDo()
{
delete m_Condition; // frees the condition
delete m_Block; // frees the instruction block
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotDo::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotDo* inst = new CBotDo(); // creates the object
CBotToken* pp = p; // preserves at the ^ token (starting position)
if ( IsOfType( p, TokenTypVar ) &&
IsOfType( p, ID_DOTS ) )
{
inst->m_label = pp->GetString(); // register the name of label
}
inst->SetToken(p);
if (!IsOfType(p, ID_DO)) return nullptr; // should never happen
CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp
// looking for a statement block after the do
IncLvl(inst->m_label);
inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk, true );
DecLvl();
if ( pStk->IsOk() )
{
if (IsOfType(p, ID_WHILE))
{
if ( nullptr != (inst->m_Condition = CBotCondition::Compile( p, pStk )) )
{
// the condition exists
if (IsOfType(p, ID_SEP))
{
return pStack->Return(inst, pStk); // return an object to the application
}
pStk->SetError(TX_ENDOF, p->GetStart());
}
}
pStk->SetError(TX_WHILE, p->GetStart());
}
delete inst; // error, frees up
return pStack->Return(nullptr, pStk); // no object, the error is on the stack
}
////////////////////////////////////////////////////////////////////////////////
bool CBotDo :: Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this); // adds an item to the stack
// or find in case of recovery
// if ( pile == EOX ) return true;
if ( pile->IfStep() ) return false;
while( true ) switch( pile->GetState() ) // executes the loop
{ // there are two possible states (depending on recovery)
case 0:
// evaluates the associated statement block
if ( m_Block != nullptr &&
!m_Block->Execute(pile) )
{
if (pile->IfContinue(1, m_label)) continue; // if continued, will return to test
return pj->BreakReturn(pile, m_label); // sends the results and releases the stack
}
// terminates if there is an error
if ( !pile->IsOk() )
{
return pj->Return(pile); // sends the results and releases the stack
}
if (!pile->SetState(1)) return false; // ready for further
case 1:
// evaluates the condition
if ( !m_Condition->Execute(pile) ) return false; // interrupted here ?
// the result of the condition is on the stack
// terminates if an error or if the condition is false
if ( !pile->IsOk() || pile->GetVal() != true )
{
return pj->Return(pile); // sends the results and releases the stack
}
// returns to instruction block to start
if (!pile->SetState(0, 0)) return false;
continue;
}
}
////////////////////////////////////////////////////////////////////////////////
void CBotDo :: RestoreState(CBotStack* &pj, bool bMain)
{
if ( !bMain ) return;
CBotStack* pile = pj->RestoreStack(this); // adds an item to the stack
if ( pile == nullptr ) return;
switch( pile->GetState() )
{ // there are two possible states (depending on recovery)
case 0:
// restores the assosiated statement's block
if ( m_Block != nullptr ) m_Block->RestoreState(pile, bMain);
return;
case 1:
// restores the condition
m_Condition->RestoreState(pile, bMain);
return;
}
}

View File

@ -0,0 +1,73 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
class CBotDo : public CBotInstr
{
public:
/*!
* \brief CBotDo Default constructor.
*/
CBotDo();
/*!
* \brief ~CBotDo Destructor.
*/
~CBotDo();
/*!
* \brief Compile Compile the instruction "do".
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! Instruction
CBotInstr* m_Block;
//! Conditions
CBotInstr* m_Condition;
//! A label if there is
CBotString m_label;
};

View File

@ -0,0 +1,44 @@
/*
* 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 "CBot/CBotInstr/CBotEmpty.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
bool CBotEmpty::Execute(CBotStack* &pj)
{
CBotVar* pVar = CBotVar::Create("", CBotTypInt);
pVar->SetValInt(-1);
pj->SetVar(pVar);
return true;
}
////////////////////////////////////////////////////////////////////////////////
void CBotEmpty::RestoreState(CBotStack* &pj, bool bMain)
{
}

View File

@ -0,0 +1,47 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotEmpty class
*/
class CBotEmpty : public CBotInstr
{
/*!
* \brief Execute Special case for empty indexes.
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
};

View File

@ -0,0 +1,82 @@
/*
* 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 "CBot/CBotInstr/CBotExprAlpha.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotExprAlpha::CBotExprAlpha()
{
name = "CBotExprAlpha";
}
////////////////////////////////////////////////////////////////////////////////
CBotExprAlpha::~CBotExprAlpha()
{
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotExprAlpha::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotCStack* pStk = pStack->TokenStack();
CBotExprAlpha* inst = new CBotExprAlpha();
inst->SetToken(p);
p = p->GetNext();
CBotVar* var = CBotVar::Create(static_cast<CBotToken*>(nullptr), CBotTypString);
pStk->SetVar(var);
return pStack->Return(inst, pStk);
}
////////////////////////////////////////////////////////////////////////////////
bool CBotExprAlpha::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this);
if (pile->IfStep()) return false;
CBotVar* var = CBotVar::Create(static_cast<CBotToken*>(nullptr), CBotTypString);
CBotString chaine = m_token.GetString();
chaine = chaine.Mid(1, chaine.GetLength()-2); // removes the quotes
var->SetValString(chaine); // value of the number
pile->SetVar(var); // put on the stack
return pj->Return(pile);
}
////////////////////////////////////////////////////////////////////////////////
void CBotExprAlpha::RestoreState(CBotStack* &pj, bool bMain)
{
if (bMain) pj->RestoreStack(this);
}

View File

@ -0,0 +1,67 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotExprAlpha class Expression representing a string.
*/
class CBotExprAlpha : public CBotInstr
{
public:
/*!
* \brief CBotExprAlpha
*/
CBotExprAlpha();
/*!
* \brief CBotExprAlpha
*/
~CBotExprAlpha();
/*!
* \brief Compile
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute Execute, returns the corresponding string.
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
};

View File

@ -0,0 +1,84 @@
/*
* 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 "CBot/CBotInstr/CBotExprBool.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotExprBool::CBotExprBool()
{
name = "CBotExprBool";
}
////////////////////////////////////////////////////////////////////////////////
CBotExprBool::~CBotExprBool()
{
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotExprBool::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotCStack* pStk = pStack->TokenStack();
CBotExprBool* inst = nullptr;
if ( p->GetType() == ID_TRUE ||
p->GetType() == ID_FALSE )
{
inst = new CBotExprBool();
inst->SetToken(p); // stores the operation false or true
p = p->GetNext();
CBotVar* var = CBotVar::Create(static_cast<CBotToken*>(nullptr), CBotTypBoolean);
pStk->SetVar(var);
}
return pStack->Return(inst, pStk);
}
////////////////////////////////////////////////////////////////////////////////
bool CBotExprBool::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this);
if (pile->IfStep()) return false;
CBotVar* var = CBotVar::Create(static_cast<CBotToken*>(nullptr), CBotTypBoolean);
if (GetTokenType() == ID_TRUE) var->SetValInt(1);
else var->SetValInt(0);
pile->SetVar(var); // put on the stack
return pj->Return(pile); // forwards below
}
////////////////////////////////////////////////////////////////////////////////
void CBotExprBool::RestoreState(CBotStack* &pj, bool bMain)
{
if (bMain) pj->RestoreStack(this);
}

View File

@ -0,0 +1,68 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotExprBool class Compile a token representing true or false.
*/
class CBotExprBool : public CBotInstr
{
public:
/*!
* \brief CBotExprBool
*/
CBotExprBool();
/*!
* \brief ~CBotExprBool
*/
~CBotExprBool();
/*!
* \brief Compile
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute Executes, returns true or false.
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
};

View File

@ -0,0 +1,59 @@
/*
* 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 "CBot/CBotInstr/CBotExprNan.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotExprNan::CBotExprNan()
{
name = "CBotExprNan";
}
////////////////////////////////////////////////////////////////////////////////
CBotExprNan::~CBotExprNan()
{
}
////////////////////////////////////////////////////////////////////////////////
bool CBotExprNan::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this);
if (pile->IfStep()) return false;
CBotVar* var = CBotVar::Create(static_cast<CBotToken*>(nullptr), CBotTypInt);
var->SetInit(CBotVar::InitType::IS_NAN); // nan
pile->SetVar(var); // put on the stack
return pj->Return(pile); // forward below
}
////////////////////////////////////////////////////////////////////////////////
void CBotExprNan::RestoreState(CBotStack* &pj, bool bMain)
{
if (bMain) pj->RestoreStack(this);
}

View File

@ -0,0 +1,59 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotExprNan class Management of the operand "nan".
*/
class CBotExprNan : public CBotInstr
{
public:
/*!
* \brief CBotExprNan
*/
CBotExprNan();
/*!
* \brief ~CBotExprNan
*/
~CBotExprNan();
/*!
* \brief Execute Executes, returns null pointer.
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
};

View File

@ -0,0 +1,60 @@
/*
* 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 "CBot/CBotInstr/CBotExprNull.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotExprNull::CBotExprNull()
{
name = "CBotExprNull";
}
////////////////////////////////////////////////////////////////////////////////
CBotExprNull::~CBotExprNull()
{
}
////////////////////////////////////////////////////////////////////////////////
bool CBotExprNull::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this);
if (pile->IfStep()) return false;
CBotVar* var = CBotVar::Create(static_cast<CBotToken*>(nullptr), CBotTypNullPointer);
var->SetInit(CBotVar::InitType::DEF); // null pointer valid
pile->SetVar(var); // place on the stack
return pj->Return(pile); // forwards below
}
////////////////////////////////////////////////////////////////////////////////
void CBotExprNull::RestoreState(CBotStack* &pj, bool bMain)
{
if (bMain) pj->RestoreStack(this);
}

View File

@ -0,0 +1,60 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotExprNull class Management of the operand "null".
*/
class CBotExprNull : public CBotInstr
{
public:
/*!
* \brief CBotExprNull
*/
CBotExprNull();
/*!
* \brief ~CBotExprNull
*/
~CBotExprNull();
/*!
* \brief Execute Executes, returns an empty pointer.
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
};

View File

@ -0,0 +1,117 @@
/*
* 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 "CBot/CBotInstr/CBotExprNum.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotExprNum::CBotExprNum()
{
name = "CBotExprNum";
}
////////////////////////////////////////////////////////////////////////////////
CBotExprNum::~CBotExprNum()
{
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotExprNum::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotCStack* pStk = pStack->TokenStack();
CBotExprNum* inst = new CBotExprNum();
inst->SetToken(p);
CBotString s = p->GetString();
inst->m_numtype = CBotTypInt;
if (p->GetType() == TokenTypDef)
{
inst->m_valint = p->GetIdKey();
}
else
{
if (s.Find('.') >= 0 || ( s.Find('x') < 0 && ( s.Find('e') >= 0 || s.Find('E') >= 0 ) ))
{
inst->m_numtype = CBotTypFloat;
inst->m_valfloat = GetNumFloat(s);
}
else
{
inst->m_valint = GetNumInt(s);
}
}
if (pStk->NextToken(p))
{
CBotVar* var = CBotVar::Create(static_cast<CBotToken*>(nullptr), inst->m_numtype);
pStk->SetVar(var);
return pStack->Return(inst, pStk);
}
delete inst;
return pStack->Return(nullptr, pStk);
}
////////////////////////////////////////////////////////////////////////////////
bool CBotExprNum::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this);
if (pile->IfStep()) return false;
CBotVar* var = CBotVar::Create(static_cast<CBotToken*>(nullptr), m_numtype);
CBotString nombre ;
if (m_token.GetType() == TokenTypDef)
{
nombre = m_token.GetString();
}
switch (m_numtype)
{
case CBotTypShort:
case CBotTypInt:
var->SetValInt(m_valint, nombre);
break;
case CBotTypFloat:
var->SetValFloat(m_valfloat);
break;
}
pile->SetVar(var); // place on the stack
return pj->Return(pile); // it's ok
}
////////////////////////////////////////////////////////////////////////////////
void CBotExprNum::RestoreState(CBotStack* &pj, bool bMain)
{
if (bMain) pj->RestoreStack(this);
}

View File

@ -0,0 +1,78 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotExprNum class Expression representing a number.
*/
class CBotExprNum : public CBotInstr
{
public:
/*!
* \brief CBotExprNum
*/
CBotExprNum();
/*!
* \brief ~CBotExprNum
*/
~CBotExprNum();
/*!
* \brief Compile
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute Execute, returns the corresponding number.
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! The type of number.
int m_numtype;
//! Value for an int.
long m_valint;
//! Value for a float.
float m_valfloat;
};

View File

@ -0,0 +1,124 @@
/*
* 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 "CBot/CBotInstr/CBotExprUnaire.h"
#include "CBot/CBotInstr/CBotParExpr.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotExprUnaire::CBotExprUnaire()
{
m_Expr = nullptr;
name = "CBotExprUnaire";
}
////////////////////////////////////////////////////////////////////////////////
CBotExprUnaire::~CBotExprUnaire()
{
delete m_Expr;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotExprUnaire::Compile(CBotToken* &p, CBotCStack* pStack)
{
int op = p->GetType();
CBotToken* pp = p;
if (!IsOfTypeList( p, ID_ADD, ID_SUB, ID_LOG_NOT, ID_TXT_NOT, ID_NOT, 0 )) return nullptr;
CBotCStack* pStk = pStack->TokenStack(pp);
CBotExprUnaire* inst = new CBotExprUnaire();
inst->SetToken(pp);
if (nullptr != (inst->m_Expr = CBotParExpr::Compile( p, pStk )))
{
if (op == ID_ADD && pStk->GetType() < CBotTypBoolean) // only with the number
return pStack->Return(inst, pStk);
if (op == ID_SUB && pStk->GetType() < CBotTypBoolean) // only with the numer
return pStack->Return(inst, pStk);
if (op == ID_NOT && pStk->GetType() < CBotTypFloat) // only with an integer
return pStack->Return(inst, pStk);
if (op == ID_LOG_NOT && pStk->GetTypResult().Eq(CBotTypBoolean))// only with boolean
return pStack->Return(inst, pStk);
if (op == ID_TXT_NOT && pStk->GetTypResult().Eq(CBotTypBoolean))// only with boolean
return pStack->Return(inst, pStk);
pStk->SetError(TX_BADTYPE, &inst->m_token);
}
delete inst;
return pStack->Return(nullptr, pStk);
}
// executes unary expression
////////////////////////////////////////////////////////////////////////////////
bool CBotExprUnaire::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this);
if (pile->GetState() == 0)
{
if (!m_Expr->Execute(pile)) return false; // interrupted ?
pile->IncState();
}
CBotStack* pile2 = pile->AddStack();
if (pile2->IfStep()) return false;
CBotVar* var = pile->GetVar(); // get the result on the stack
switch (GetTokenType())
{
case ID_ADD:
break;
case ID_SUB:
var->Neg(); // change the sign
break;
case ID_NOT:
case ID_LOG_NOT:
case ID_TXT_NOT:
var->Not();
break;
}
return pj->Return(pile); // forwards below
}
////////////////////////////////////////////////////////////////////////////////
void CBotExprUnaire::RestoreState(CBotStack* &pj, bool bMain)
{
if (!bMain) return;
CBotStack* pile = pj->RestoreStack(this);
if ( pile == nullptr) return;
if (pile->GetState() == 0)
{
m_Expr->RestoreState(pile, bMain); // interrupted here!
return;
}
}

View File

@ -0,0 +1,73 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotExprUnaire class Unary expression. Compile an unary expression
* eg : (+, * -, not, !, ~)
*/
class CBotExprUnaire : public CBotInstr
{
public:
/*!
* \brief CBotExprUnaire
*/
CBotExprUnaire();
/*!
* \brief ~CBotExprUnaire
*/
~CBotExprUnaire();
/*!
* \brief Compile
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute
* \param pStack
* \return
*/
bool Execute(CBotStack* &pStack) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! Expression to be evaluated.
CBotInstr* m_Expr;
};

View File

@ -0,0 +1,310 @@
/*
* 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 "CBot/CBotInstr/CBotExprVar.h"
#include "CBot/CBotInstr/CBotInstrMethode.h"
#include "CBot/CBotInstr/CBotExpression.h"
#include "CBot/CBotInstr/CBotIndexExpr.h"
#include "CBot/CBotInstr/CBotFieldExpr.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVarArray.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotExprVar::CBotExprVar()
{
name = "CBotExprVar";
m_nIdent = 0;
}
////////////////////////////////////////////////////////////////////////////////
CBotExprVar::~CBotExprVar()
{
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotExprVar::Compile(CBotToken* &p, CBotCStack* pStack, int privat)
{
// CBotToken* pDebut = p;
CBotCStack* pStk = pStack->TokenStack();
pStk->SetStartError(p->GetStart());
// is it a variable?
if (p->GetType() == TokenTypVar)
{
CBotInstr* inst = new CBotExprVar(); // create the object
inst->SetToken(p);
CBotVar* var;
if (nullptr != (var = pStk->FindVar(p))) // seek if known variable
{
int ident = var->GetUniqNum();
(static_cast<CBotExprVar*>(inst))->m_nIdent = ident; // identifies variable by its number
if (ident > 0 && ident < 9000)
{
if ( var->IsPrivate(privat) &&
!pStk->GetBotCall()->m_bCompileClass)
{
pStk->SetError(TX_PRIVATE, p);
goto err;
}
// This is an element of the current class
// ads the equivalent of this. before
CBotToken token("this");
inst->SetToken(&token);
(static_cast<CBotExprVar*>(inst))->m_nIdent = -2; // identificator for this
CBotFieldExpr* i = new CBotFieldExpr(); // new element
i->SetToken(p); // keeps the name of the token
i->SetUniqNum(ident);
inst->AddNext3(i); // added after
}
p = p->GetNext(); // next token
while (true)
{
if (var->GetType() == CBotTypArrayPointer)
{
if (IsOfType( p, ID_OPBRK )) // check if there is an aindex
{
CBotIndexExpr* i = new CBotIndexExpr();
i->m_expr = CBotExpression::Compile(p, pStk); // compile the formula
inst->AddNext3(i); // add to the chain
var = (static_cast<CBotVarArray*>(var))->GetItem(0,true); // gets the component [0]
if (i->m_expr == nullptr)
{
pStk->SetError(TX_BADINDEX, p->GetStart());
goto err;
}
if (!pStk->IsOk() || !IsOfType( p, ID_CLBRK ))
{
pStk->SetError(TX_CLBRK, p->GetStart());
goto err;
}
continue;
}
}
if (var->GetType(1) == CBotTypPointer) // for classes
{
if (IsOfType(p, ID_DOT))
{
CBotToken* pp = p;
if (p->GetType() == TokenTypVar) // must be a name
{
if (p->GetNext()->GetType() == ID_OPENPAR) // a method call?
{
CBotInstr* i = CBotInstrMethode::Compile(p, pStk, var);
if (!pStk->IsOk()) goto err;
inst->AddNext3(i); // added after
return pStack->Return(inst, pStk);
}
else
{
CBotFieldExpr* i = new CBotFieldExpr(); // new element
i->SetToken(pp); // keeps the name of the token
inst->AddNext3(i); // add after
var = var->GetItem(p->GetString()); // get item correspondent
if (var != nullptr)
{
i->SetUniqNum(var->GetUniqNum());
if ( var->IsPrivate() &&
!pStk->GetBotCall()->m_bCompileClass)
{
pStk->SetError(TX_PRIVATE, pp);
goto err;
}
}
}
if (var != nullptr)
{
p = p->GetNext(); // skips the name
continue;
}
pStk->SetError(TX_NOITEM, p);
goto err;
}
pStk->SetError(TX_DOT, p->GetStart());
goto err;
}
}
break;
}
pStk->SetCopyVar(var); // place the copy of the variable on the stack (for type)
if (pStk->IsOk()) return pStack->Return(inst, pStk);
}
pStk->SetError(TX_UNDEFVAR, p);
err:
delete inst;
return pStack->Return(nullptr, pStk);
}
return pStack->Return(nullptr, pStk);
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotExprVar::CompileMethode(CBotToken* &p, CBotCStack* pStack)
{
CBotToken* pp = p;
CBotCStack* pStk = pStack->TokenStack();
pStk->SetStartError(pp->GetStart());
// is it a variable ?
if (pp->GetType() == TokenTypVar)
{
CBotToken pthis("this");
CBotVar* var = pStk->FindVar(pthis);
if (var == nullptr) return pStack->Return(nullptr, pStk);
CBotInstr* inst = new CBotExprVar();
// this is an element of the current class
// adds the equivalent of this. before
inst->SetToken(&pthis);
(static_cast<CBotExprVar*>(inst))->m_nIdent = -2; // ident for this
CBotToken* pp = p;
if (pp->GetType() == TokenTypVar)
{
if (pp->GetNext()->GetType() == ID_OPENPAR) // a method call?
{
CBotInstr* i = CBotInstrMethode::Compile(pp, pStk, var);
if (pStk->IsOk())
{
inst->AddNext3(i); // add after
p = pp; // previous instruction
return pStack->Return(inst, pStk);
}
pStk->SetError(0,0); // the error is not adressed here
}
}
delete inst;
}
return pStack->Return(nullptr, pStk);
}
////////////////////////////////////////////////////////////////////////////////
bool CBotExprVar::Execute(CBotStack* &pj)
{
CBotVar* pVar = nullptr;
CBotStack* pile = pj->AddStack(this);
CBotStack* pile1 = pile;
if (pile1->GetState() == 0)
{
if (!ExecuteVar(pVar, pile, nullptr, true)) return false; // Get the variable fields and indexes according
if (pVar) pile1->SetCopyVar(pVar); // place a copy on the stack
else
{
return pj->Return(pile1);
}
pile1->IncState();
}
pVar = pile1->GetVar();
if (pVar == nullptr)
{
return pj->Return(pile1);
}
if (pVar->IsUndefined())
{
CBotToken* pt = &m_token;
while (pt->GetNext() != nullptr) pt = pt->GetNext();
pile1->SetError(TX_NOTINIT, pt);
return pj->Return(pile1);
}
return pj->Return(pile1); // operation completed
}
////////////////////////////////////////////////////////////////////////////////
void CBotExprVar::RestoreState(CBotStack* &pj, bool bMain)
{
if (!bMain) return;
CBotStack* pile = pj->RestoreStack(this);
if (pile == nullptr) return;
CBotStack* pile1 = pile;
if (pile1->GetState() == 0)
{
RestoreStateVar(pile, bMain); // retrieves the variable fields and indexes according
return;
}
}
////////////////////////////////////////////////////////////////////////////////
bool CBotExprVar::ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* prevToken, bool bStep)
{
CBotStack* pile = pj;
pj = pj->AddStack(this);
if (bStep && m_nIdent>0 && pj->IfStep()) return false;
pVar = pj->FindVar(m_nIdent, true); // tries with the variable update if necessary
if (pVar == nullptr)
{
#ifdef _DEBUG
assert(0);
#endif
pj->SetError(1, &m_token);
return false;
}
if ( m_next3 != nullptr &&
!m_next3->ExecuteVar(pVar, pj, &m_token, bStep, false) )
return false; // field of an instance, table, methode
return pile->ReturnKeep(pj); // does not put on stack but get the result if a method was called
}
////////////////////////////////////////////////////////////////////////////////
void CBotExprVar::RestoreStateVar(CBotStack* &pj, bool bMain)
{
pj = pj->RestoreStack(this);
if (pj == nullptr) return;
if (m_next3 != nullptr)
m_next3->RestoreStateVar(pj, bMain);
}

View File

@ -0,0 +1,103 @@
/*
* 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/CBotDefines.h"
#include "CBot/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotExprVar class Expression for the variable name. Compile a
* variable name check that it is known on the stack and it has been initialized.
*/
class CBotExprVar : public CBotInstr
{
public:
/*!
* \brief CBotExprVar
*/
CBotExprVar();
/*!
* \brief ~CBotExprVar
*/
~CBotExprVar();
/*!
* \brief Compile
* \param p
* \param pStack
* \param privat
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, int privat=PR_PROTECT);
/*!
* \brief CompileMethode
* \param p
* \param pStack
* \return
*/
static CBotInstr* CompileMethode(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute Execute, making the value of a variable.
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
/*!
* \brief ExecuteVar Fetch a variable at runtime.
* \param pVar
* \param pile
* \param prevToken
* \param bStep
* \return
*/
bool ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, bool bStep);
/*!
* \brief RestoreStateVar Fetch variable at runtime.
* \param pj
* \param bMain
*/
void RestoreStateVar(CBotStack* &pj, bool bMain) override;
private:
long m_nIdent;
friend class CBotPostIncExpr;
friend class CBotPreIncExpr;
};

View File

@ -0,0 +1,298 @@
/*
* 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 "CBot/CBotInstr/CBotExpression.h"
#include "CBot/CBotInstr/CBotInstrUtils.h"
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVar.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;
}
}
}

View File

@ -0,0 +1,87 @@
/*
* 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/CBotInstr/CBotLeftExpr.h"
#include "CBot/CBotInstr/CBotInstr.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;
};

View File

@ -0,0 +1,130 @@
/*
* 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 "CBot/CBotInstr/CBotFieldExpr.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotClass.h"
#include "CBot/CBotVar/CBotVarClass.h"
// Local include
// Global include
#include <cassert>
////////////////////////////////////////////////////////////////////////////////
CBotFieldExpr::CBotFieldExpr()
{
name = "CBotFieldExpr";
m_nIdent = 0;
}
////////////////////////////////////////////////////////////////////////////////
CBotFieldExpr::~CBotFieldExpr()
{
}
////////////////////////////////////////////////////////////////////////////////
void CBotFieldExpr::SetUniqNum(int num)
{
m_nIdent = num;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotFieldExpr::ExecuteVar(CBotVar* &pVar, CBotCStack* &pile)
{
if (pVar->GetType(1) != CBotTypPointer)
assert(0);
pVar = pVar->GetItemRef(m_nIdent);
if (pVar == nullptr)
{
pile->SetError(TX_NOITEM, &m_token);
return false;
}
if ( m_next3 != nullptr &&
!m_next3->ExecuteVar(pVar, pile) ) return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotFieldExpr::ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, bool bStep, bool bExtend)
{
CBotStack* pj = pile;
pile = pile->AddStack(this); // changes in output stack
if (pile == EOX) return true;
if (pVar->GetType(1) != CBotTypPointer)
assert(0);
CBotVarClass* pItem = pVar->GetPointer();
if (pItem == nullptr)
{
pile->SetError(TX_NULLPT, prevToken);
return pj->Return(pile);
}
if (pItem->GetUserPtr() == OBJECTDELETED)
{
pile->SetError(TX_DELETEDPT, prevToken);
return pj->Return(pile);
}
if (bStep && pile->IfStep()) return false;
pVar = pVar->GetItemRef(m_nIdent);
if (pVar == nullptr)
{
pile->SetError(TX_NOITEM, &m_token);
return pj->Return(pile);
}
if (pVar->IsStatic())
{
// for a static variable, takes it in the class itself
CBotClass* pClass = pItem->GetClass();
pVar = pClass->GetItem(m_token.GetString());
}
// request the update of the element, if applicable
pVar->Maj(pile->GetPUser(), true);
if ( m_next3 != nullptr &&
!m_next3->ExecuteVar(pVar, pile, &m_token, bStep, bExtend) ) return false;
// does not release the stack
// to maintain the state SetState () corresponding to step
return true;
}
////////////////////////////////////////////////////////////////////////////////
void CBotFieldExpr::RestoreStateVar(CBotStack* &pj, bool bMain)
{
pj = pj->RestoreStack(this);
if (pj == nullptr) return;
if (m_next3 != nullptr)
m_next3->RestoreStateVar(pj, bMain);
}

View File

@ -0,0 +1,83 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotFieldExpr class Management of the fields of an instance
* (dot operator) eg : toto.x
*/
class CBotFieldExpr : public CBotInstr
{
public:
/*!
* \brief CBotFieldExpr
*/
CBotFieldExpr();
/*!
* \brief ~CBotFieldExpr
*/
~CBotFieldExpr();
/*!
* \brief SetUniqNum
* \param num
*/
void SetUniqNum(int num);
/*!
* \brief ExecuteVar Find a field from the instance at compile.
* \param pVar
* \param pile
* \return
*/
bool ExecuteVar(CBotVar* &pVar, CBotCStack* &pile) override;
/*!
* \brief ExecuteVar
* \param pVar
* \param pile
* \param prevToken
* \param bStep
* \param bExtend
* \return
*/
bool ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, bool bStep, bool bExtend) override;
/*!
* \brief RestoreStateVar
* \param pj
* \param bMain
*/
void RestoreStateVar(CBotStack* &pj, bool bMain) override;
private:
friend class CBotExpression;
int m_nIdent;
};

View File

@ -0,0 +1,176 @@
/*
* 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 "CBot/CBotInstr/CBotFloat.h"
#include "CBot/CBotInstr/CBotLeftExprVar.h"
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
#include "CBot/CBotInstr/CBotInstArray.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotFloat::CBotFloat()
{
m_var =
m_expr = nullptr;
name = "CBotFloat";
}
////////////////////////////////////////////////////////////////////////////////
CBotFloat::~CBotFloat()
{
delete m_var;
delete m_expr;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, bool noskip)
{
CBotToken* pp = cont ? nullptr : p;
if (!cont && !IsOfType(p, ID_FLOAT)) return nullptr;
CBotFloat* inst = static_cast<CBotFloat*>(CompileArray(p, pStack, CBotTypFloat));
if (inst != nullptr || !pStack->IsOk()) return inst;
CBotCStack* pStk = pStack->TokenStack(pp);
inst = new CBotFloat();
inst->m_expr = nullptr;
CBotToken* vartoken = p;
CBotVar* var = nullptr;
inst->SetToken(vartoken);
if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )))
{
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = CBotTypFloat;
if (pStk->CheckVarLocal(vartoken)) // redefinition of a variable
{
pStk->SetStartError(vartoken->GetStart());
pStk->SetError(TX_REDEFVAR, vartoken->GetEnd());
goto error;
}
if (IsOfType(p, ID_OPBRK))
{
delete inst;
p = vartoken;
inst = static_cast<CBotFloat*>(CBotInstArray::Compile(p, pStk, CBotTypFloat));
if (!pStk->IsOk() )
{
pStk->SetError(TX_CLBRK, p->GetStart());
goto error;
}
goto suite; // no assignment, variable already created
}
if (IsOfType(p, ID_ASS))
{
if (nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )))
{
goto error;
}
if (pStk->GetType() >= CBotTypBoolean)
{
pStk->SetError(TX_BADTYPE, p->GetStart());
goto error;
}
}
var = CBotVar::Create(vartoken, CBotTypFloat);
var->SetInit(inst->m_expr != nullptr ? CBotVar::InitType::DEF : CBotVar::InitType::UNDEF);
var->SetUniqNum(
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
pStack->AddVar(var);
suite:
if (IsOfType(p, ID_COMMA))
{
if (nullptr != ( inst->m_next2b = CBotFloat::Compile(p, pStk, true, noskip)))
{
return pStack->Return(inst, pStk);
}
}
if (noskip || IsOfType(p, ID_SEP))
{
return pStack->Return(inst, pStk);
}
pStk->SetError(TX_ENDOF, p->GetStart());
}
error:
delete inst;
return pStack->Return(nullptr, pStk);
}
////////////////////////////////////////////////////////////////////////////////
bool CBotFloat::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this);
if ( pile->GetState()==0)
{
if (m_expr && !m_expr->Execute(pile)) return false;
m_var->Execute(pile);
if (!pile->SetState(1)) return false;
}
if (pile->IfStep()) return false;
if ( m_next2b &&
!m_next2b->Execute(pile)) return false;
return pj->Return(pile);
}
////////////////////////////////////////////////////////////////////////////////
void CBotFloat::RestoreState(CBotStack* &pj, bool bMain)
{
CBotStack* pile = pj;
if (bMain)
{
pile = pj->RestoreStack(this);
if (pile == nullptr) return;
if ( pile->GetState()==0)
{
if (m_expr) m_expr->RestoreState(pile, bMain);
return;
}
}
m_var->RestoreState(pile, bMain);
if (m_next2b)
m_next2b->RestoreState(pile, bMain);
}

View File

@ -0,0 +1,76 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotFloat class Definition of a real/float variable int a, b = 12.4;
*/
class CBotFloat : public CBotInstr
{
public:
/*!
* \brief CBotFloat
*/
CBotFloat();
/*!
* \brief ~CBotFloat
*/
~CBotFloat();
/*!
* \brief Compile
* \param p
* \param pStack
* \param cont
* \param noskip
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool cont = false, bool noskip=false);
/*!
* \brief Execute Executes the definition of a real variable.
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! Variable to initialise.
CBotInstr* m_var;
//! A value to put, if there is.
CBotInstr* m_expr;
};

View File

@ -0,0 +1,214 @@
/*
* 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 "CBot/CBotInstr/CBotFor.h"
#include "CBot/CBotInstr/CBotListExpression.h"
#include "CBot/CBotInstr/CBotBlock.h"
#include "CBot/CBotInstr/CBotBoolExpr.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotFor::CBotFor()
{
m_Init =
m_Test =
m_Incr =
m_Block = nullptr; // nullptr so that delete is not possible further
name = "CBotFor"; // debug
}
////////////////////////////////////////////////////////////////////////////////
CBotFor::~CBotFor()
{
delete m_Init;
delete m_Test;
delete m_Incr;
delete m_Block; // frees the instruction block
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotFor::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotFor* inst = new CBotFor(); // creates the object
CBotToken* pp = p; // preserves at the ^ token (starting position)
if ( IsOfType( p, TokenTypVar ) &&
IsOfType( p, ID_DOTS ) )
{
inst->m_label = pp->GetString(); // register the name of label
}
inst->SetToken(p);
if (!IsOfType(p, ID_FOR)) return nullptr; // should never happen
if ( !IsOfType(p, ID_OPENPAR)) // missing parenthesis ?
{
pStack->SetError(TX_OPENPAR, p->GetStart());
return nullptr;
}
CBotCStack* pStk = pStack->TokenStack(pp, true); // un petit bout de pile svp
// compiles instructions for initialization
inst->m_Init = CBotListExpression::Compile( p, pStk );
if ( pStk->IsOk() )
{
if ( !IsOfType(p, ID_SEP)) // lack the semicolon?
{
pStack->SetError(TX_OPENPAR, p->GetStart());
delete inst;
return pStack->Return(nullptr, pStk); // no object, the error is on the stack
}
inst->m_Test = CBotBoolExpr::Compile( p, pStk );
if ( pStk->IsOk() )
{
if ( !IsOfType(p, ID_SEP)) // lack the semicolon?
{
pStack->SetError(TX_OPENPAR, p->GetStart());
delete inst;
return pStack->Return(nullptr, pStk); // no object, the error is on the stack
}
inst->m_Incr = CBotListExpression::Compile( p, pStk );
if ( pStk->IsOk() )
{
if ( IsOfType(p, ID_CLOSEPAR)) // missing parenthesis ?
{
IncLvl(inst->m_label);
inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk, true );
DecLvl();
if ( pStk->IsOk() )
return pStack->Return(inst, pStk);;
}
pStack->SetError(TX_CLOSEPAR, p->GetStart());
}
}
}
delete inst; // error, frees up
return pStack->Return(nullptr, pStk); // no object, the error is on the stack
}
// execution of instruction "for"
////////////////////////////////////////////////////////////////////////////////
bool CBotFor :: Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this, true); // adds an item to the stack (variables locales)
// or find in case of recovery
// if ( pile == EOX ) return true;
if ( pile->IfStep() ) return false;
while( true ) switch( pile->GetState() ) // executes the loop
{ // there are four possible states (depending on recovery)
case 0:
// initialize
if ( m_Init != nullptr &&
!m_Init->Execute(pile) ) return false; // interrupted here ?
if (!pile->SetState(1)) return false; // ready for further
case 1:
// evaluates the condition
if ( m_Test != nullptr ) // no strings attached? -> True!
{
if (!m_Test->Execute(pile) ) return false; // interrupted here ?
// the result of the condition is on the stack
// terminates if an error or if the condition is false
if ( !pile->IsOk() || pile->GetVal() != true )
{
return pj->Return(pile); // sends the results and releases the stack
}
}
// la condition est vrai, passe à la suite
if (!pile->SetState(2)) return false; // ready for further
case 2:
// evaluates the associated statement block
if ( m_Block != nullptr &&
!m_Block->Execute(pile) )
{
if (pile->IfContinue(3, m_label)) continue; // if continued, going on to incrementation
return pj->BreakReturn(pile, m_label); // sends the results and releases the stack
}
// terminates if there is an error
if ( !pile->IsOk() )
{
return pj->Return(pile); // sends the results and releases the stack
}
if (!pile->SetState(3)) return false; // ready for further
case 3:
// evalutate the incrementation
if ( m_Incr != nullptr &&
!m_Incr->Execute(pile) ) return false; // interrupted here ?
// returns to the test again
if (!pile->SetState(1, 0)) return false; // returns to the test
continue;
}
}
////////////////////////////////////////////////////////////////////////////////
void CBotFor :: RestoreState(CBotStack* &pj, bool bMain)
{
if ( !bMain ) return;
CBotStack* pile = pj->RestoreStack(this); // adds an item to the stack (variables locales)
if ( pile == nullptr ) return;
switch( pile->GetState() )
{ // there are four possible states (depending on recovery)
case 0:
// initialize
if ( m_Init != nullptr ) m_Init->RestoreState(pile, true); // interrupted here !
return;
case 1:
if ( m_Init != nullptr ) m_Init->RestoreState(pile, false); // variables definitions
// evaluates the condition
if ( m_Test != nullptr ) m_Test->RestoreState(pile, true); // interrupted here !
return;
case 2:
if ( m_Init != nullptr ) m_Init->RestoreState(pile, false); // variable definitions
// evaluates the associated statement block
if ( m_Block != nullptr ) m_Block->RestoreState(pile, true);
return;
case 3:
if ( m_Init != nullptr ) m_Init->RestoreState(pile, false); // variable definitions
// evaluate the incrementation
if ( m_Incr != nullptr ) m_Incr->RestoreState(pile, true); // interrupted here !
return;
}
}

View File

@ -0,0 +1,81 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotFor class
*/
class CBotFor : public CBotInstr
{
public:
/*!
* \brief CBotFor
*/
CBotFor();
/*!
* \brief CBotFor
*/
~CBotFor();
/*!
* \brief Compile Compiles instruction "for"
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! Initial intruction
CBotInstr* m_Init;
//! Test Condition
CBotInstr* m_Test;
//! instruction for increment
CBotInstr* m_Incr;
//! Instructions
CBotInstr* m_Block;
//! A label if there is
CBotString m_label;
};

View File

@ -17,18 +17,33 @@
* along with this program. If not, see http://gnu.org/licenses
*/
///////////////////////////////////////////////////////////////////////
// compilation of various functions declared by the user
//
#include "CBot.h"
// Modules inlcude
#include "CBot/CBotInstr/CBotFunction.h"
#include "CBot/CBotInstr/CBotInstrUtils.h"
#include "CBot/CBotInstr/CBotBlock.h"
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
#include "CBot/CBotInstr/CBotExpression.h"
#include "CBot/CBotInstr/CBotEmpty.h"
#include "CBot/CBotInstr/CBotListArray.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotClass.h"
#include "CBot/CBotDefParam.h"
#include "CBot/CBotUtils.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
#include <cassert>
// various constructors / destructors
// \TODO translation:to liberate all according to esteblished tree
// pour libérer tout selon l'arbre établi
////////////////////////////////////////////////////////////////////////////////
CBotFunction::CBotFunction()
{
m_Param = nullptr; // empty parameter list
@ -44,8 +59,10 @@ CBotFunction::CBotFunction()
m_bSynchro = false;
}
////////////////////////////////////////////////////////////////////////////////
CBotFunction* CBotFunction::m_listPublic = nullptr;
////////////////////////////////////////////////////////////////////////////////
CBotFunction::~CBotFunction()
{
delete m_Param; // empty parameter list
@ -71,16 +88,19 @@ CBotFunction::~CBotFunction()
}
}
////////////////////////////////////////////////////////////////////////////////
bool CBotFunction::IsPublic()
{
return m_bPublic;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotFunction::IsExtern()
{
return m_bExtern;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotFunction::GetPosition(int& start, int& stop, CBotGet modestart, CBotGet modestop)
{
start = m_extern.GetStart();
@ -122,61 +142,7 @@ bool CBotFunction::GetPosition(int& start, int& stop, CBotGet modestart, CBotGet
return true;
}
CBotTypResult ArrayType(CBotToken* &p, CBotCStack* pile, CBotTypResult type)
{
while ( IsOfType( p, ID_OPBRK ) )
{
if ( !IsOfType( p, ID_CLBRK ) )
{
pile->SetError(TX_CLBRK, p->GetStart());
return CBotTypResult( -1 );
}
type = CBotTypResult( CBotTypArrayPointer, type );
}
return type;
}
CBotTypResult TypeParam(CBotToken* &p, CBotCStack* pile)
{
CBotClass* pClass = nullptr;
switch (p->GetType())
{
case ID_INT:
p = p->GetNext();
return ArrayType(p, pile, CBotTypResult( CBotTypInt ));
case ID_FLOAT:
p = p->GetNext();
return ArrayType(p, pile, CBotTypResult( CBotTypFloat ));
case ID_BOOLEAN:
case ID_BOOL:
p = p->GetNext();
return ArrayType(p, pile, CBotTypResult( CBotTypBoolean ));
case ID_STRING:
p = p->GetNext();
return ArrayType(p, pile, CBotTypResult( CBotTypString ));
case ID_VOID:
p = p->GetNext();
return CBotTypResult( 0 );
case TokenTypVar:
pClass = CBotClass::Find(p);
if ( pClass != nullptr)
{
p = p->GetNext();
return ArrayType(p, pile,
pClass->IsIntrinsic() ?
CBotTypResult( CBotTypIntrinsic, pClass ) :
CBotTypResult( CBotTypPointer, pClass ) );
}
}
return CBotTypResult( -1 );
}
// compiles a new function
// bLocal allows of the declaration of parameters on the same level
// as the elements belonging to the class for methods
////////////////////////////////////////////////////////////////////////////////
CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunction* finput, bool bLocal)
{
CBotToken* pp;
@ -289,7 +255,7 @@ bad:
return pStack->ReturnFunc(nullptr, pStk);
}
// pre-compile a new function
////////////////////////////////////////////////////////////////////////////////
CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClass* pClass)
{
CBotFunction* func = new CBotFunction();
@ -376,6 +342,7 @@ bad:
static int xx = 0;
#endif
////////////////////////////////////////////////////////////////////////////////
bool CBotFunction::Execute(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance)
{
CBotStack* pile = pj->AddStack(this, 2); // one end of stack local to this function
@ -425,7 +392,7 @@ bool CBotFunction::Execute(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance)
return pj->Return(pile);
}
////////////////////////////////////////////////////////////////////////////////
void CBotFunction::RestoreState(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance)
{
CBotStack* pile = pj->RestoreStack(this); // one end of stack local to this function
@ -454,6 +421,7 @@ void CBotFunction::RestoreState(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInst
m_Block->RestoreState(pile2, true);
}
////////////////////////////////////////////////////////////////////////////////
void CBotFunction::AddNext(CBotFunction* p)
{
CBotFunction* pp = this;
@ -462,7 +430,7 @@ void CBotFunction::AddNext(CBotFunction* p)
pp->m_next = p;
}
////////////////////////////////////////////////////////////////////////////////
CBotTypResult CBotFunction::CompileCall(const char* name, CBotVar** ppVars, long& nIdent)
{
nIdent = 0;
@ -473,10 +441,7 @@ CBotTypResult CBotFunction::CompileCall(const char* name, CBotVar** ppVars, long
return type;
}
// is a function according to its unique identifier
// if the identifier is not found, looking by name and parameters
////////////////////////////////////////////////////////////////////////////////
CBotFunction* CBotFunction::FindLocalOrPublic(long& nIdent, const char* name, CBotVar** ppVars, CBotTypResult& TypeOrError, bool bPublic)
{
TypeOrError.SetType(TX_UNDEFCALL); // no routine of the name
@ -629,9 +594,7 @@ CBotFunction* CBotFunction::FindLocalOrPublic(long& nIdent, const char* name, CB
return nullptr;
}
// fait un appel à une fonction
////////////////////////////////////////////////////////////////////////////////
int CBotFunction::DoCall(long& nIdent, const char* name, CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken)
{
CBotTypResult type;
@ -701,6 +664,7 @@ int CBotFunction::DoCall(long& nIdent, const char* name, CBotVar** ppVars, CBotS
return -1;
}
////////////////////////////////////////////////////////////////////////////////
void CBotFunction::RestoreCall(long& nIdent, const char* name, CBotVar** ppVars, CBotStack* pStack)
{
CBotTypResult type;
@ -757,11 +721,7 @@ void CBotFunction::RestoreCall(long& nIdent, const char* name, CBotVar** ppVars,
}
}
// makes call of a method
// note: this is already on the stack, the pointer pThis is just to simplify
////////////////////////////////////////////////////////////////////////////////
int CBotFunction::DoCall(long& nIdent, const char* name, CBotVar* pThis, CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken, CBotClass* pClass)
{
CBotTypResult type;
@ -842,6 +802,7 @@ int CBotFunction::DoCall(long& nIdent, const char* name, CBotVar* pThis, CBotVar
return -1;
}
////////////////////////////////////////////////////////////////////////////////
void CBotFunction::RestoreCall(long& nIdent, const char* name, CBotVar* pThis, CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass)
{
CBotTypResult type;
@ -874,7 +835,7 @@ void CBotFunction::RestoreCall(long& nIdent, const char* name, CBotVar* pThis, C
}
}
// see if the "signature" of parameters is identical
////////////////////////////////////////////////////////////////////////////////
bool CBotFunction::CheckParam(CBotDefParam* pParam)
{
CBotDefParam* pp = m_Param;
@ -889,11 +850,13 @@ bool CBotFunction::CheckParam(CBotDefParam* pParam)
return ( pp == nullptr && pParam == nullptr );
}
////////////////////////////////////////////////////////////////////////////////
CBotString CBotFunction::GetName()
{
return m_token.GetString();
}
////////////////////////////////////////////////////////////////////////////////
CBotString CBotFunction::GetParams()
{
if ( m_Param == nullptr ) return CBotString("()");
@ -912,11 +875,13 @@ CBotString CBotFunction::GetParams()
return params;
}
////////////////////////////////////////////////////////////////////////////////
CBotFunction* CBotFunction::Next()
{
return m_next;
}
////////////////////////////////////////////////////////////////////////////////
void CBotFunction::AddPublic(CBotFunction* func)
{
if ( m_listPublic != nullptr )
@ -926,748 +891,3 @@ void CBotFunction::AddPublic(CBotFunction* func)
}
m_listPublic = func;
}
/////////////////////////////////////////////////////////////////////////
// management of parameters
CBotDefParam::CBotDefParam()
{
m_next = nullptr;
m_nIdent = 0;
}
CBotDefParam::~CBotDefParam()
{
delete m_next;
}
// compiles a list of parameters
CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack)
{
// mainly not pStack->TokenStack here
// declared variables must remain visible thereafter
pStack->SetStartError(p->GetStart());
if (IsOfType(p, ID_OPENPAR))
{
CBotDefParam* list = nullptr;
while (!IsOfType(p, ID_CLOSEPAR))
{
CBotDefParam* param = new CBotDefParam();
if (list == nullptr) list = param;
else list->AddNext(param); // added to the list
// CBotClass* pClass = nullptr;//= CBotClass::Find(p);
param->m_typename = p->GetString();
CBotTypResult type = param->m_type = TypeParam(p, pStack);
// if ( type == CBotTypPointer ) type = CBotTypClass; // we must create a new object
if (param->m_type.GetType() > 0)
{
CBotToken* pp = p;
param->m_token = *p;
if (pStack->IsOk() && IsOfType(p, TokenTypVar) )
{
// variable already declared?
if (pStack->CheckVarLocal(pp))
{
pStack->SetError(TX_REDEFVAR, pp);
break;
}
if ( type.Eq(CBotTypArrayPointer) ) type.SetType(CBotTypArrayBody);
CBotVar* var = CBotVar::Create(pp->GetString(), type); // creates the variable
// if ( pClass ) var->SetClass(pClass);
var->SetInit(CBotVar::InitType::IS_POINTER); // mark initialized
param->m_nIdent = CBotVar::NextUniqNum();
var->SetUniqNum(param->m_nIdent);
pStack->AddVar(var); // place on the stack
if (IsOfType(p, ID_COMMA) || p->GetType() == ID_CLOSEPAR)
continue;
}
pStack->SetError(TX_CLOSEPAR, p->GetStart());
}
pStack->SetError(TX_NOTYP, p);
delete list;
return nullptr;
}
return list;
}
pStack->SetError(TX_OPENPAR, p->GetStart());
return nullptr;
}
void CBotDefParam::AddNext(CBotDefParam* p)
{
CBotDefParam* pp = this;
while (pp->m_next != nullptr) pp = pp->m_next;
pp->m_next = p;
}
bool CBotDefParam::Execute(CBotVar** ppVars, CBotStack* &pj)
{
int i = 0;
CBotDefParam* p = this;
while ( p != nullptr )
{
// creates a local variable on the stack
CBotVar* newvar = CBotVar::Create(p->m_token.GetString(), p->m_type);
// serves to make the transformation of types:
if ( ppVars != nullptr && ppVars[i] != nullptr )
{
switch (p->m_type.GetType())
{
case CBotTypInt:
newvar->SetValInt(ppVars[i]->GetValInt());
break;
case CBotTypFloat:
newvar->SetValFloat(ppVars[i]->GetValFloat());
break;
case CBotTypString:
newvar->SetValString(ppVars[i]->GetValString());
break;
case CBotTypBoolean:
newvar->SetValInt(ppVars[i]->GetValInt());
break;
case CBotTypIntrinsic:
(static_cast<CBotVarClass*>(newvar))->Copy(ppVars[i], false);
break;
case CBotTypPointer:
case CBotTypArrayPointer:
{
newvar->SetPointer(ppVars[i]->GetPointer());
}
break;
default:
assert(0);
}
}
newvar->SetUniqNum(p->m_nIdent);
pj->AddVar(newvar); // add a variable
p = p->m_next;
i++;
}
return true;
}
void CBotDefParam::RestoreState(CBotStack* &pj, bool bMain)
{
// int i = 0;
CBotDefParam* p = this;
while ( p != nullptr )
{
// creates a local variable on the stack
CBotVar* var = pj->FindVar(p->m_token.GetString());
var->SetUniqNum(p->m_nIdent);
p = p->m_next;
}
}
int CBotDefParam::GetType()
{
return m_type.GetType();
}
CBotTypResult CBotDefParam::GetTypResult()
{
return m_type;
}
CBotDefParam* CBotDefParam::GetNext()
{
return m_next;
}
CBotString CBotDefParam::GetParamString()
{
CBotString param;
param = m_typename;
param += ' ';
param += m_token.GetString();
return param;
}
//////////////////////////////////////////////////////////////////////////
// return parameters
CBotReturn::CBotReturn()
{
m_Instr = nullptr;
name = "CBotReturn"; // debug
}
CBotReturn::~CBotReturn()
{
delete m_Instr;
}
CBotInstr* CBotReturn::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotToken* pp = p;
if (!IsOfType(p, ID_RETURN)) return nullptr; // should never happen
CBotReturn* inst = new CBotReturn(); // creates the object
inst->SetToken( pp );
CBotTypResult type = pStack->GetRetType();
if ( type.GetType() == 0 ) // returned void ?
{
if ( IsOfType( p, ID_SEP ) ) return inst;
pStack->SetError( TX_BADTYPE, pp );
return nullptr;
}
inst->m_Instr = CBotExpression::Compile(p, pStack);
if ( pStack->IsOk() )
{
CBotTypResult retType = pStack->GetTypResult(2);
if (TypeCompatible(retType, type, ID_ASS))
{
if ( IsOfType( p, ID_SEP ) )
return inst;
pStack->SetError(TX_ENDOF, p->GetStart());
}
pStack->SetError(TX_BADTYPE, p->GetStart());
}
delete inst;
return nullptr; // no object, the error is on the stack
}
bool CBotReturn::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this);
// if ( pile == EOX ) return true;
if ( pile->GetState() == 0 )
{
if ( m_Instr != nullptr && !m_Instr->Execute(pile) ) return false; // evaluate the result
// the result is on the stack
pile->IncState();
}
if ( pile->IfStep() ) return false;
pile->SetBreak(3, CBotString());
return pj->Return(pile);
}
void CBotReturn::RestoreState(CBotStack* &pj, bool bMain)
{
if ( !bMain ) return;
CBotStack* pile = pj->RestoreStack(this);
if ( pile == nullptr ) return;
if ( pile->GetState() == 0 )
{
if ( m_Instr != nullptr ) m_Instr->RestoreState(pile, bMain); // evaluate the result
return;
}
}
////////////////////////////////////////////////////////////////////////////////
// Calls of these functions
CBotInstrCall::CBotInstrCall()
{
m_Parameters = nullptr;
m_nFuncIdent = 0;
name = "CBotInstrCall";
}
CBotInstrCall::~CBotInstrCall()
{
delete m_Parameters;
}
CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotVar* ppVars[1000];
int i = 0;
CBotToken* pp = p;
p = p->GetNext();
pStack->SetStartError(p->GetStart());
CBotCStack* pile = pStack;
if ( IsOfType(p, ID_OPENPAR) )
{
int start, end;
CBotInstrCall* inst = new CBotInstrCall();
inst->SetToken(pp);
// compile la list of parameters
if (!IsOfType(p, ID_CLOSEPAR)) while (true)
{
start = p->GetStart();
pile = pile->TokenStack(); // keeps the results on the stack
CBotInstr* param = CBotExpression::Compile(p, pile);
end = p->GetStart();
if ( inst->m_Parameters == nullptr ) inst->m_Parameters = param;
else inst->m_Parameters->AddNext(param); // constructs the list
if ( !pile->IsOk() )
{
delete inst;
return pStack->Return(nullptr, pile);
}
if ( param != nullptr )
{
if ( pile->GetTypResult().Eq(99) )
{
delete pStack->TokenStack();
pStack->SetError(TX_VOID, p->GetStart());
delete inst;
return nullptr;
}
ppVars[i] = pile->GetVar();
ppVars[i]->GetToken()->SetPos(start, end);
i++;
if (IsOfType(p, ID_COMMA)) continue; // skips the comma
if (IsOfType(p, ID_CLOSEPAR)) break;
}
pStack->SetError(TX_CLOSEPAR, p->GetStart());
delete pStack->TokenStack();
delete inst;
return nullptr;
}
ppVars[i] = nullptr;
// the routine is known?
// CBotClass* pClass = nullptr;
inst->m_typRes = pStack->CompileCall(pp, ppVars, inst->m_nFuncIdent);
if ( inst->m_typRes.GetType() >= 20 )
{
// if (pVar2!=nullptr) pp = pVar2->RetToken();
pStack->SetError( inst->m_typRes.GetType(), pp );
delete pStack->TokenStack();
delete inst;
return nullptr;
}
delete pStack->TokenStack();
if ( inst->m_typRes.GetType() > 0 )
{
CBotVar* pRes = CBotVar::Create("", inst->m_typRes);
pStack->SetVar(pRes); // for knowing the type of the result
}
else pStack->SetVar(nullptr); // routine returns void
return inst;
}
p = pp;
delete pStack->TokenStack();
return nullptr;
}
bool CBotInstrCall::Execute(CBotStack* &pj)
{
CBotVar* ppVars[1000];
CBotStack* pile = pj->AddStack(this);
if ( pile->StackOver() ) return pj->Return( pile );
// CBotStack* pile1 = pile;
int i = 0;
CBotInstr* p = m_Parameters;
// evaluates parameters
// and places the values on the stack
// for allow of interruption at any time
if ( p != nullptr) while ( true )
{
pile = pile->AddStack(); // place on the stack for the results
if ( pile->GetState() == 0 )
{
if (!p->Execute(pile)) return false; // interrupted here?
pile->SetState(1); // mark as special for reknowed parameters \TODO marque spéciale pour reconnaîre parameters
}
ppVars[i++] = pile->GetVar();
p = p->GetNext();
if ( p == nullptr) break;
}
ppVars[i] = nullptr;
CBotStack* pile2 = pile->AddStack();
if ( pile2->IfStep() ) return false;
if ( !pile2->ExecuteCall(m_nFuncIdent, GetToken(), ppVars, m_typRes)) return false; // interrupt
return pj->Return(pile2); // release the entire stack
}
void CBotInstrCall::RestoreState(CBotStack* &pj, bool bMain)
{
if ( !bMain ) return;
CBotStack* pile = pj->RestoreStack(this);
if ( pile == nullptr ) return;
// CBotStack* pile1 = pile;
int i = 0;
CBotVar* ppVars[1000];
CBotInstr* p = m_Parameters;
// evaluate parameters
// and place the values on the stack
// for allow of interruption at any time
if ( p != nullptr) while ( true )
{
pile = pile->RestoreStack(); // place on the stack for the results
if ( pile == nullptr ) return;
if ( pile->GetState() == 0 )
{
p->RestoreState(pile, bMain); // interrupt here!
return;
}
ppVars[i++] = pile->GetVar(); // constructs the list of parameters
p = p->GetNext();
if ( p == nullptr) break;
}
ppVars[i] = nullptr;
CBotStack* pile2 = pile->RestoreStack();
if ( pile2 == nullptr ) return;
pile2->RestoreCall(m_nFuncIdent, GetToken(), ppVars);
}
//////////////////////////////////////////////////////////////////////////////
// statement of user classes
// pre-compile a new class
// analysis is complete except the body of routines
CBotClass* CBotClass::Compile1(CBotToken* &p, CBotCStack* pStack)
{
if ( !IsOfType(p, ID_PUBLIC) )
{
pStack->SetError(TX_NOPUBLIC, p);
return nullptr;
}
if ( !IsOfType(p, ID_CLASS) ) return nullptr;
CBotString name = p->GetString();
CBotClass* pOld = CBotClass::Find(name);
if ( pOld != nullptr && pOld->m_IsDef )
{
pStack->SetError( TX_REDEFCLASS, p );
return nullptr;
}
// a name of the class is there?
if (IsOfType(p, TokenTypVar))
{
CBotClass* pPapa = nullptr;
if ( IsOfType( p, ID_EXTENDS ) )
{
CBotString name = p->GetString();
pPapa = CBotClass::Find(name);
if (!IsOfType(p, TokenTypVar) || pPapa == nullptr )
{
pStack->SetError( TX_NOCLASS, p );
return nullptr;
}
}
CBotClass* classe = (pOld == nullptr) ? new CBotClass(name, pPapa) : pOld;
classe->Purge(); // emptythe old definitions
classe->m_IsDef = false; // current definition
if ( !IsOfType( p, ID_OPBLK) )
{
pStack->SetError(TX_OPENBLK, p);
return nullptr;
}
while ( pStack->IsOk() && !IsOfType( p, ID_CLBLK ) )
{
classe->CompileDefItem(p, pStack, false);
}
if (pStack->IsOk()) return classe;
}
pStack->SetError(TX_ENDOF, p);
return nullptr;
}
bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
{
bool bStatic = false;
int mProtect = PR_PUBLIC;
bool bSynchro = false;
while (IsOfType(p, ID_SEP)) ;
CBotTypResult type( -1 );
if ( IsOfType(p, ID_SYNCHO) ) bSynchro = true;
CBotToken* pBase = p;
if ( IsOfType(p, ID_STATIC) ) bStatic = true;
if ( IsOfType(p, ID_PUBLIC) ) mProtect = PR_PUBLIC;
if ( IsOfType(p, ID_PRIVATE) ) mProtect = PR_PRIVATE;
if ( IsOfType(p, ID_PROTECTED) ) mProtect = PR_PROTECT;
if ( IsOfType(p, ID_STATIC) ) bStatic = true;
// CBotClass* pClass = nullptr;
type = TypeParam(p, pStack); // type of the result
if ( type.Eq(-1) )
{
pStack->SetError(TX_NOTYP, p);
return false;
}
while (pStack->IsOk())
{
CBotToken* pp = p;
IsOfType(p, ID_NOT); // skips ~ eventual (destructor)
if (IsOfType(p, TokenTypVar))
{
CBotInstr* limites = nullptr;
while ( IsOfType( p, ID_OPBRK ) ) // a table?
{
CBotInstr* i = nullptr;
if ( p->GetType() != ID_CLBRK )
i = CBotExpression::Compile( p, pStack ); // expression for the value
else
i = new CBotEmpty(); // special if not a formula
type = CBotTypResult(CBotTypArrayPointer, type);
if (!pStack->IsOk() || !IsOfType( p, ID_CLBRK ) )
{
pStack->SetError(TX_CLBRK, p->GetStart());
return false;
}
/* CBotVar* pv = pStack->GetVar();
if ( pv->GetType()>= CBotTypBoolean )
{
pStack->SetError(TX_BADTYPE, p->GetStart());
return false;
}*/
if (limites == nullptr) limites = i;
else limites->AddNext3(i);
}
if ( p->GetType() == ID_OPENPAR )
{
if ( !bSecond )
{
p = pBase;
CBotFunction* f =
CBotFunction::Compile1(p, pStack, this);
if ( f == nullptr ) return false;
if (m_pMethod == nullptr) m_pMethod = f;
else m_pMethod->AddNext(f);
}
else
{
// return a method precompiled in pass 1
CBotFunction* pf = m_pMethod;
CBotFunction* prev = nullptr;
while ( pf != nullptr )
{
if (pf->GetName() == pp->GetString()) break;
prev = pf;
pf = pf->Next();
}
bool bConstructor = (pp->GetString() == GetName());
CBotCStack* pile = pStack->TokenStack(nullptr, true);
// make "this" known
CBotToken TokenThis(CBotString("this"), CBotString());
CBotVar* pThis = CBotVar::Create(&TokenThis, CBotTypResult( CBotTypClass, this ) );
pThis->SetUniqNum(-2);
pile->AddVar(pThis);
if ( m_pParent )
{
// makes "super" known
CBotToken TokenSuper(CBotString("super"), CBotString());
CBotVar* pThis = CBotVar::Create(&TokenSuper, CBotTypResult( CBotTypClass, m_pParent ) );
pThis->SetUniqNum(-3);
pile->AddVar(pThis);
}
// int num = 1;
CBotClass* my = this;
while (my != nullptr)
{
// places a copy of variables of a class (this) on a stack
CBotVar* pv = my->m_pVar;
while (pv != nullptr)
{
CBotVar* pcopy = CBotVar::Create(pv);
CBotVar::InitType initType = CBotVar::InitType::UNDEF;
if (!bConstructor || pv->IsStatic())
initType = CBotVar::InitType::DEF;
pcopy->SetInit(initType);
pcopy->SetUniqNum(pv->GetUniqNum());
pile->AddVar(pcopy);
pv = pv->GetNext();
}
my = my->m_pParent;
}
// compiles a method
p = pBase;
CBotFunction* f =
CBotFunction::Compile(p, pile, nullptr/*, false*/);
if ( f != nullptr )
{
f->m_pProg = pStack->GetBotCall();
f->m_bSynchro = bSynchro;
// replaces the element in the chain
f->m_next = pf->m_next;
pf->m_next = nullptr;
delete pf;
if (prev == nullptr) m_pMethod = f;
else prev->m_next = f;
}
pStack->Return(nullptr, pile);
}
return pStack->IsOk();
}
// definition of an element
if (type.Eq(0))
{
pStack->SetError(TX_ENDOF, p);
return false;
}
CBotInstr* i = nullptr;
if ( IsOfType(p, ID_ASS ) )
{
if ( type.Eq(CBotTypArrayPointer) )
{
i = CBotListArray::Compile(p, pStack, type.GetTypElem());
}
else
{
// it has an assignmet to calculate
i = CBotTwoOpExpr::Compile(p, pStack);
}
if ( !pStack->IsOk() ) return false;
}
if ( !bSecond )
{
CBotVar* pv = CBotVar::Create(pp->GetString(), type);
pv -> SetStatic( bStatic );
pv -> SetPrivate( mProtect );
AddItem( pv );
pv->m_InitExpr = i;
pv->m_LimExpr = limites;
if ( pv->IsStatic() && pv->m_InitExpr != nullptr )
{
CBotStack* pile = CBotStack::FirstStack(); // independent stack
while(pile->IsOk() && !pv->m_InitExpr->Execute(pile)); // evaluates the expression without timer
pv->SetVal( pile->GetVar() ) ;
pile->Delete();
}
}
else
delete i;
if ( IsOfType(p, ID_COMMA) ) continue;
if ( IsOfType(p, ID_SEP) ) break;
}
pStack->SetError(TX_ENDOF, p);
}
return pStack->IsOk();
}
CBotClass* CBotClass::Compile(CBotToken* &p, CBotCStack* pStack)
{
if ( !IsOfType(p, ID_PUBLIC) ) return nullptr;
if ( !IsOfType(p, ID_CLASS) ) return nullptr;
CBotString name = p->GetString();
// a name for the class is there?
if (IsOfType(p, TokenTypVar))
{
// the class was created by Compile1
CBotClass* pOld = CBotClass::Find(name);
if ( IsOfType( p, ID_EXTENDS ) )
{
// TODO: Not sure how correct is that - I have no idea how the precompilation (Compile1 method) works ~krzys_h
CBotString name = p->GetString();
CBotClass* pPapa = CBotClass::Find(name);
if (!IsOfType(p, TokenTypVar) || pPapa == nullptr)
{
pStack->SetError( TX_NOCLASS, p );
return nullptr;
}
pOld->m_pParent = pPapa;
}
else
{
if (pOld != nullptr)
{
pOld->m_pParent = nullptr;
}
}
IsOfType( p, ID_OPBLK); // necessarily
while ( pStack->IsOk() && !IsOfType( p, ID_CLBLK ) )
{
pOld->CompileDefItem(p, pStack, true);
}
pOld->m_IsDef = true; // complete definition
if (pStack->IsOk()) return pOld;
}
pStack->SetError(TX_ENDOF, p);
return nullptr;
}

View File

@ -0,0 +1,282 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotFunction class A function declaration. Compilation of various
* functions declared by the user
*/
class CBotFunction : public CBotInstr
{
public:
/*!
* \brief CBotFunction
*/
CBotFunction();
/*!
* \brief ~CBotFunction
*/
~CBotFunction();
/*!
* \brief Compile Compiles a new function
* \param p
* \param pStack
* \param pFunc
* \param bLocal allows of the declaration of parameters on the same level
* as the elements belonging to the class for methods.
* \return
*/
static CBotFunction* Compile(CBotToken* &p,
CBotCStack* pStack,
CBotFunction* pFunc,
bool bLocal = true);
/*!
* \brief Compile1 Pre-compile a new function.
* \param p
* \param pStack
* \param pClass
* \return
*/
static CBotFunction* Compile1(CBotToken* &p,
CBotCStack* pStack,
CBotClass* pClass);
/*!
* \brief Execute
* \param ppVars
* \param pj
* \param pInstance
* \return
*/
bool Execute(CBotVar** ppVars,
CBotStack* &pj,
CBotVar* pInstance = nullptr);
/*!
* \brief RestoreState
* \param ppVars
* \param pj
* \param pInstance
*/
void RestoreState(CBotVar** ppVars,
CBotStack* &pj,
CBotVar* pInstance = nullptr);
/*!
* \brief AddNext
* \param p
*/
void AddNext(CBotFunction* p);
/*!
* \brief CompileCall
* \param name
* \param ppVars
* \param nIdent
* \return
*/
CBotTypResult CompileCall(const char* name,
CBotVar** ppVars,
long& nIdent);
/*!
* \brief FindLocalOrPublic Is a function according to its unique identifier
* if the identifier is not found, looking by name and parameters.
* \param nIdent
* \param name
* \param ppVars
* \param TypeOrError
* \param bPublic
* \return
*/
CBotFunction* FindLocalOrPublic(long& nIdent, const char* name,
CBotVar** ppVars,
CBotTypResult& TypeOrError,
bool bPublic = true);
/*!
* \brief DoCall Fait un appel à une fonction.
* \param nIdent
* \param name
* \param ppVars
* \param pStack
* \param pToken
* \return
*/
int DoCall(long& nIdent,
const char* name,
CBotVar** ppVars,
CBotStack* pStack,
CBotToken* pToken);
/*!
* \brief RestoreCall
* \param nIdent
* \param name
* \param ppVars
* \param pStack
*/
void RestoreCall(long& nIdent,
const char* name,
CBotVar** ppVars,
CBotStack* pStack);
/*!
* \brief DoCall Makes call of a method note: this is already on the stack,
* the pointer pThis is just to simplify.
* \param nIdent
* \param name
* \param pThis
* \param ppVars
* \param pStack
* \param pToken
* \param pClass
* \return
*/
int DoCall(long& nIdent,
const char* name,
CBotVar* pThis,
CBotVar** ppVars,
CBotStack* pStack,
CBotToken* pToken,
CBotClass* pClass);
/*!
* \brief RestoreCall
* \param nIdent
* \param name
* \param pThis
* \param ppVars
* \param pStack
* \param pClass
*/
void RestoreCall(long& nIdent,
const char* name,
CBotVar* pThis,
CBotVar** ppVars,
CBotStack* pStack,
CBotClass* pClass);
/*!
* \brief CheckParam See if the "signature" of parameters is identical.
* \param pParam
* \return
*/
bool CheckParam(CBotDefParam* pParam);
/*!
* \brief AddPublic
* \param pfunc
*/
static void AddPublic(CBotFunction* pfunc);
/*!
* \brief GetName
* \return
*/
CBotString GetName();
/*!
* \brief GetParams
* \return
*/
CBotString GetParams();
/*!
* \brief IsPublic
* \return
*/
bool IsPublic();
/*!
* \brief IsExtern
* \return
*/
bool IsExtern();
/*!
* \brief Next
* \return
*/
CBotFunction* Next();
/*!
* \brief GetPosition
* \param start
* \param stop
* \param modestart
* \param modestop
* \return
*/
bool GetPosition(int& start, int& stop,
CBotGet modestart,
CBotGet modestop);
private:
CBotFunction* m_nextpublic;
CBotFunction* m_prevpublic;
long m_nFuncIdent;
//! Synchronized method.
bool m_bSynchro;
//! Parameter list.
CBotDefParam* m_Param;
//! The instruction block.
CBotInstr* m_Block;
CBotFunction* m_next;
//! If returns CBotTypClass.
CBotToken m_retToken;
//! Complete type of the result.
CBotTypResult m_retTyp;
//! Public function.
bool m_bPublic;
//! Extern function.
bool m_bExtern;
//! Name of the class we derive.
CBotString m_MasterClass;
CBotProgram* m_pProg;
//! For the position of the word "extern".
CBotToken m_extern;
CBotToken m_openpar;
CBotToken m_closepar;
CBotToken m_openblk;
CBotToken m_closeblk;
//! Management of list of (static) public functions.
static CBotFunction* m_listPublic;
friend class CBotProgram;
friend class CBotClass;
friend class CBotCStack;
};

View File

@ -0,0 +1,161 @@
/*
* 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 "CBot/CBotInstr/CBotIString.h"
#include "CBot/CBotInstr/CBotLeftExprVar.h"
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotIString::CBotIString()
{
m_var =
m_expr = nullptr;
name = "CBotIString";
}
////////////////////////////////////////////////////////////////////////////////
CBotIString::~CBotIString()
{
delete m_var;
delete m_expr;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotIString::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, bool noskip)
{
CBotToken* pp = cont ? nullptr : p;
if (!cont && !IsOfType(p, ID_STRING)) return nullptr;
CBotIString* inst = static_cast<CBotIString*>(CompileArray(p, pStack, CBotTypString));
if (inst != nullptr || !pStack->IsOk()) return inst;
CBotCStack* pStk = pStack->TokenStack(pp);
inst = new CBotIString();
inst->m_expr = nullptr;
CBotToken* vartoken = p;
inst->SetToken(vartoken);
if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )))
{
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = CBotTypString;
if (pStk->CheckVarLocal(vartoken))
{
pStk->SetStartError(vartoken->GetStart());
pStk->SetError(TX_REDEFVAR, vartoken->GetEnd());
goto error;
}
if (IsOfType(p, ID_ASS))
{
if (nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )))
{
goto error;
}
/* if (!pStk->GetTypResult().Eq(CBotTypString)) // type compatible ?
{
pStk->SetError(TX_BADTYPE, p->GetStart());
goto error;
}*/
}
CBotVar* var = CBotVar::Create(vartoken, CBotTypString);
var->SetInit(inst->m_expr != nullptr ? CBotVar::InitType::DEF : CBotVar::InitType::UNDEF);
var->SetUniqNum(
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
pStack->AddVar(var);
if (IsOfType(p, ID_COMMA))
{
if (nullptr != ( inst->m_next2b = CBotIString::Compile(p, pStk, true, noskip)))
{
return pStack->Return(inst, pStk);
}
}
if (noskip || IsOfType(p, ID_SEP))
{
return pStack->Return(inst, pStk);
}
pStk->SetError(TX_ENDOF, p->GetStart());
}
error:
delete inst;
return pStack->Return(nullptr, pStk);
}
////////////////////////////////////////////////////////////////////////////////
bool CBotIString::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this);
if ( pile->GetState()==0)
{
if (m_expr && !m_expr->Execute(pile)) return false;
m_var->Execute(pile);
if (!pile->SetState(1)) return false;
}
if (pile->IfStep()) return false;
if ( m_next2b &&
!m_next2b->Execute(pile)) return false;
return pj->Return(pile);
}
////////////////////////////////////////////////////////////////////////////////
void CBotIString::RestoreState(CBotStack* &pj, bool bMain)
{
CBotStack* pile = pj;
if (bMain)
{
pile = pj->RestoreStack(this);
if (pile == nullptr) return;
if ( pile->GetState()==0)
{
if (m_expr) m_expr->RestoreState(pile, bMain);
return;
}
}
m_var->RestoreState(pile, bMain);
if (m_next2b)
m_next2b->RestoreState(pile, bMain);
}

View File

@ -0,0 +1,76 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotIString class Define a string variable eg : int a, b = "salut";
*/
class CBotIString : public CBotInstr
{
public:
/*!
* \brief CBotIString
*/
CBotIString();
/*!
* \brief ~CBotIString
*/
~CBotIString();
/*!
* \brief Compile
* \param p
* \param pStack
* \param cont
* \param noskip
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool cont = false, bool noskip=false);
/*!
* \brief Execute Executes the definition of the string variable.
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! Variable to initialise.
CBotInstr* m_var;
//! A value to put, if there is.
CBotInstr* m_expr;
};

View File

@ -17,12 +17,20 @@
* along with this program. If not, see http://gnu.org/licenses
*/
///////////////////////////////////////////////////////////////////////
// instruction if (condition) operation1 else operation2;
// Modules inlcude
#include "CBot/CBotInstr/CBotIf.h"
#include "CBot/CBotInstr/CBotBlock.h"
#include "CBot/CBotInstr/CBotCondition.h"
#include "CBot.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
// various constructors / destructors
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotIf::CBotIf()
{
m_Condition =
@ -31,6 +39,7 @@ CBotIf::CBotIf()
name = "CBotIf"; // debug
}
////////////////////////////////////////////////////////////////////////////////
CBotIf::~CBotIf()
{
delete m_Condition; // frees the condition
@ -38,9 +47,7 @@ CBotIf::~CBotIf()
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)
@ -86,9 +93,7 @@ CBotInstr* CBotIf::Compile(CBotToken* &p, CBotCStack* pStack)
return pStack->Return(nullptr, pStk);
}
// execution of the instruction
////////////////////////////////////////////////////////////////////////////////
bool CBotIf :: Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this); // adds an item to the stack
@ -131,7 +136,7 @@ bool CBotIf :: Execute(CBotStack* &pj)
return pj->Return(pile);
}
////////////////////////////////////////////////////////////////////////////////
void CBotIf :: RestoreState(CBotStack* &pj, bool bMain)
{
if ( !bMain ) return;

View File

@ -0,0 +1,77 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotIf class Instruction if (condition) operation1 else operation2;
*/
class CBotIf : public CBotInstr
{
public:
/*!
* \brief CBotIf
*/
CBotIf();
/*!
* \brief ~CBotIf
*/
~CBotIf();
/*!
* \brief Compile Compilation (static routine) called when the token "if"
* has been found
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute Execution of the instruction.
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! Condition
CBotInstr* m_Condition;
//! Instruction
CBotInstr* m_Block;
//! Instruction
CBotInstr* m_BlockElse;
};

View File

@ -0,0 +1,120 @@
/*
* 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 "CBot/CBotInstr/CBotIndexExpr.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVarArray.h"
// Local include
// Global include
#include <cassert>
////////////////////////////////////////////////////////////////////////////////
CBotIndexExpr::CBotIndexExpr()
{
m_expr = nullptr;
name = "CBotIndexExpr";
}
////////////////////////////////////////////////////////////////////////////////
CBotIndexExpr::~CBotIndexExpr()
{
delete m_expr;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotIndexExpr::ExecuteVar(CBotVar* &pVar, CBotCStack* &pile)
{
if (pVar->GetType(1) != CBotTypArrayPointer)
assert(0);
pVar = (static_cast<CBotVarArray*>(pVar))->GetItem(0, false); // at compile time makes the element [0]
if (pVar == nullptr)
{
pile->SetError(TX_OUTARRAY, m_token.GetEnd());
return false;
}
if (m_next3 != nullptr) return m_next3->ExecuteVar(pVar, pile);
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotIndexExpr::ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, bool bStep, bool bExtend)
{
CBotStack* pj = pile;
if (pVar->GetType(1) != CBotTypArrayPointer)
assert(0);
pile = pile->AddStack();
if (pile->GetState() == 0)
{
if (!m_expr->Execute(pile)) return false;
pile->IncState();
}
// handles array
CBotVar* p = pile->GetVar(); // result on the stack
if (p == nullptr || p->GetType() > CBotTypDouble)
{
pile->SetError(TX_BADINDEX, prevToken);
return pj->Return(pile);
}
int n = p->GetValInt(); // position in the table
pVar = (static_cast<CBotVarArray*>(pVar))->GetItem(n, bExtend);
if (pVar == nullptr)
{
pile->SetError(TX_OUTARRAY, prevToken);
return pj->Return(pile);
}
pVar->Maj(pile->GetPUser(), true);
if ( m_next3 != nullptr &&
!m_next3->ExecuteVar(pVar, pile, prevToken, bStep, bExtend) ) return false;
// does not release the stack
// to avoid recalculation of the index twice where appropriate
return true;
}
////////////////////////////////////////////////////////////////////////////////
void CBotIndexExpr::RestoreStateVar(CBotStack* &pile, bool bMain)
{
pile = pile->RestoreStack();
if (pile == nullptr) return;
if (bMain && pile->GetState() == 0)
{
m_expr->RestoreState(pile, true);
return;
}
if (m_next3)
m_next3->RestoreStateVar(pile, bMain);
}

View File

@ -0,0 +1,81 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotIndexExpr class Index management for arrays
* eg :
* - array [ expression ]
*/
class CBotIndexExpr : public CBotInstr
{
public:
/*!
* \brief CBotIndexExpr
*/
CBotIndexExpr();
/*!
* \brief ~CBotIndexExpr
*/
~CBotIndexExpr();
/*!
* \brief ExecuteVar Finds a field from the instance at compile time.
* \param pVar
* \param pile
* \return
*/
bool ExecuteVar(CBotVar* &pVar, CBotCStack* &pile) override;
/*!
* \brief ExecuteVar Warning, changes the pointer to the stack intentionally
* place the index calculated on the additional stack.
* \param pVar
* \param pile
* \param prevToken
* \param bStep
* \param bExtend
* \return
*/
bool ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, bool bStep, bool bExtend) override;
/*!
* \brief RestoreStateVar
* \param pj
* \param bMain
*/
void RestoreStateVar(CBotStack* &pj, bool bMain) override;
private:
//! Expression for calculating the index.
CBotInstr* m_expr;
friend class CBotLeftExpr;
friend class CBotExprVar;
};

View File

@ -0,0 +1,231 @@
/*
* 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 "CBot/CBotInstr/CBotInstArray.h"
#include "CBot/CBotInstr/CBotLeftExprVar.h"
#include "CBot/CBotInstr/CBotExpression.h"
#include "CBot/CBotInstr/CBotListArray.h"
#include "CBot/CBotInstr/CBotEmpty.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotDefines.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotInstArray::CBotInstArray()
{
m_var = nullptr;
m_listass = nullptr;
name = "CBotInstArray";
}
////////////////////////////////////////////////////////////////////////////////
CBotInstArray::~CBotInstArray()
{
delete m_var;
delete m_listass;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotInstArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResult type)
{
CBotCStack* pStk = pStack->TokenStack(p);
CBotInstArray* inst = new CBotInstArray();
CBotToken* vartoken = p;
inst->SetToken(vartoken);
// determinse the expression is valid for the item on the left side
if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )))
{
if (pStk->CheckVarLocal(vartoken)) // redefinition of the variable?
{
pStk->SetError(TX_REDEFVAR, vartoken);
goto error;
}
CBotInstr* i;
while (IsOfType(p, ID_OPBRK))
{
if (p->GetType() != ID_CLBRK)
i = CBotExpression::Compile(p, pStk); // expression for the value
else
i = new CBotEmpty(); // if no special formula
inst->AddNext3b(i); // construct a list
type = CBotTypResult(CBotTypArrayPointer, type);
if (!pStk->IsOk() || !IsOfType(p, ID_CLBRK ))
{
pStk->SetError(TX_CLBRK, p->GetStart());
goto error;
}
}
CBotVar* var = CBotVar::Create(vartoken, type); // create an instance
inst->m_typevar = type;
var->SetUniqNum(
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
pStack->AddVar(var); // place it on the stack
if (IsOfType(p, ID_ASS)) // with an assignment
{
inst->m_listass = CBotListArray::Compile(p, pStk, type.GetTypElem());
}
if (pStk->IsOk()) return pStack->Return(inst, pStk);
}
error:
delete inst;
return pStack->Return(nullptr, pStk);
}
////////////////////////////////////////////////////////////////////////////////
bool CBotInstArray::Execute(CBotStack* &pj)
{
CBotStack* pile1 = pj->AddStack(this);
CBotStack* pile = pile1;
if (pile1->GetState() == 0)
{
// seek the maximum dimension of the table
CBotInstr* p = GetNext3b(); // the different formulas
int nb = 0;
while (p != nullptr)
{
pile = pile->AddStack(); // little room to work
nb++;
if (pile->GetState() == 0)
{
if (!p->Execute(pile)) return false; // size calculation //interrupted?
pile->IncState();
}
p = p->GetNext3b();
}
p = GetNext3b();
pile = pile1; // returns to the stack
int n = 0;
int max[100];
while (p != nullptr)
{
pile = pile->AddStack();
CBotVar* v = pile->GetVar(); // result
max[n] = v->GetValInt(); // value
if (max[n]>MAXARRAYSIZE)
{
pile->SetError(TX_OUTARRAY, &m_token);
return pj->Return (pile);
}
n++;
p = p->GetNext3b();
}
while (n<100) max[n++] = 0;
m_typevar.SetArray(max); // store the limitations
// create simply a nullptr pointer
CBotVar* var = CBotVar::Create(m_var->GetToken(), m_typevar);
var->SetPointer(nullptr);
var->SetUniqNum((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent);
pj->AddVar(var);
#if STACKMEM
pile1->AddStack()->Delete();
#else
delete pile1->AddStack(); // need more indices
#endif
pile1->IncState();
}
if (pile1->GetState() == 1)
{
if (m_listass != nullptr) // there is the assignment for this table
{
CBotVar* pVar = pj->FindVar((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent);
if (!m_listass->Execute(pile1, pVar)) return false;
}
pile1->IncState();
}
if (pile1->IfStep()) return false;
if ( m_next2b &&
!m_next2b->Execute(pile1 )) return false;
return pj->Return(pile1);
}
////////////////////////////////////////////////////////////////////////////////
void CBotInstArray::RestoreState(CBotStack* &pj, bool bMain)
{
CBotStack* pile1 = pj;
CBotVar* var = pj->FindVar(m_var->GetToken()->GetString());
if (var != nullptr) var->SetUniqNum((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent);
if (bMain)
{
pile1 = pj->RestoreStack(this);
CBotStack* pile = pile1;
if (pile == nullptr) return;
if (pile1->GetState() == 0)
{
// seek the maximum dimension of the table
CBotInstr* p = GetNext3b();
while (p != nullptr)
{
pile = pile->RestoreStack();
if (pile == nullptr) return;
if (pile->GetState() == 0)
{
p->RestoreState(pile, bMain);
return;
}
p = p->GetNext3b();
}
}
if (pile1->GetState() == 1 && m_listass != nullptr)
{
m_listass->RestoreState(pile1, bMain);
}
}
if (m_next2b ) m_next2b->RestoreState( pile1, bMain);
}

View File

@ -0,0 +1,82 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotInstArray class Definition of an array.
* Defining an array of any type
* int a[12];
* point x[];
*/
class CBotInstArray : public CBotInstr
{
public:
/*!
* \brief CBotInstArray
*/
CBotInstArray();
/*!
* \brief ~CBotInstArray
*/
~CBotInstArray();
/*!
* \brief Compile
* \param p
* \param pStack
* \param type
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResult type);
/*!
* \brief Execute Executes the definition of an array.
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! The variables to initialize.
CBotInstr* m_var;
//! List of assignments for array.
CBotInstr* m_listass;
//! Type of elements.
CBotTypResult m_typevar;
};

View File

@ -0,0 +1,374 @@
/*
* 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 "CBot/CBotInstr/CBotInstr.h"
#include "CBot/CBotInstr/CBotFor.h"
#include "CBot/CBotInstr/CBotDo.h"
#include "CBot/CBotInstr/CBotBreak.h"
#include "CBot/CBotInstr/CBotSwitch.h"
#include "CBot/CBotInstr/CBotTry.h"
#include "CBot/CBotInstr/CBotThrow.h"
#include "CBot/CBotInstr/CBotInt.h"
#include "CBot/CBotInstr/CBotFloat.h"
#include "CBot/CBotInstr/CBotWhile.h"
#include "CBot/CBotInstr/CBotIString.h"
#include "CBot/CBotInstr/CBotBoolean.h"
#include "CBot/CBotInstr/CBotIf.h"
#include "CBot/CBotInstr/CBotReturn.h"
#include "CBot/CBotInstr/CBotClassInst.h"
#include "CBot/CBotInstr/CBotExpression.h"
#include "CBot/CBotInstr/CBotInstArray.h"
#include "CBot/CBotVar/CBotVar.h"
#include "CBot/CBotClass.h"
#include "CBot/CBotStack.h"
// Local include
// Global include
#include <cassert>
////////////////////////////////////////////////////////////////////////////////
int CBotInstr::m_LoopLvl = 0;
CBotStringArray CBotInstr::m_labelLvl = CBotStringArray();
////////////////////////////////////////////////////////////////////////////////
CBotInstr::CBotInstr()
{
name = "CBotInstr";
m_next = nullptr;
m_next2b = nullptr;
m_next3 = nullptr;
m_next3b = nullptr;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr::~CBotInstr()
{
delete m_next;
delete m_next2b;
delete m_next3;
delete m_next3b;
}
////////////////////////////////////////////////////////////////////////////////
void CBotInstr::IncLvl(CBotString& label)
{
m_labelLvl.SetSize(m_LoopLvl+1);
m_labelLvl[m_LoopLvl] = label;
m_LoopLvl++;
}
////////////////////////////////////////////////////////////////////////////////
void CBotInstr::IncLvl()
{
m_labelLvl.SetSize(m_LoopLvl+1);
m_labelLvl[m_LoopLvl] = "#SWITCH";
m_LoopLvl++;
}
////////////////////////////////////////////////////////////////////////////////
void CBotInstr::DecLvl()
{
m_LoopLvl--;
m_labelLvl[m_LoopLvl].Empty();
}
////////////////////////////////////////////////////////////////////////////////
bool CBotInstr::ChkLvl(const CBotString& label, int type)
{
int i = m_LoopLvl;
while (--i>=0)
{
if ( type == ID_CONTINUE && m_labelLvl[i] == "#SWITCH") continue;
if (label.IsEmpty()) return true;
if (m_labelLvl[i] == label) return true;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotInstr::IsOfClass(CBotString n)
{
return name == n;
}
////////////////////////////////////////////////////////////////////////////////
void CBotInstr::SetToken(CBotToken* p)
{
m_token = *p;
}
////////////////////////////////////////////////////////////////////////////////
int CBotInstr::GetTokenType()
{
return m_token.GetType();
}
////////////////////////////////////////////////////////////////////////////////
CBotToken* CBotInstr::GetToken()
{
return &m_token;
}
////////////////////////////////////////////////////////////////////////////////
void CBotInstr::AddNext(CBotInstr* n)
{
CBotInstr* p = this;
while (p->m_next != nullptr) p = p->m_next;
p->m_next = n;
}
////////////////////////////////////////////////////////////////////////////////
void CBotInstr::AddNext3(CBotInstr* n)
{
CBotInstr* p = this;
while (p->m_next3 != nullptr) p = p->m_next3;
p->m_next3 = n;
}
////////////////////////////////////////////////////////////////////////////////
void CBotInstr::AddNext3b(CBotInstr* n)
{
CBotInstr* p = this;
while (p->m_next3b != nullptr) p = p->m_next3b;
p->m_next3b = n;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotInstr::GetNext()
{
return m_next;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotInstr::GetNext3()
{
return m_next3;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotInstr::GetNext3b()
{
return m_next3b;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotInstr::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotToken* pp = p;
if (p == nullptr) return nullptr;
int type = p->GetType(); // what is the next token
// is it a lable?
if (IsOfType(pp, TokenTypVar) &&
IsOfType(pp, ID_DOTS))
{
type = pp->GetType();
// these instructions accept only lable
if (!IsOfTypeList(pp, ID_WHILE, ID_FOR, ID_DO, 0))
{
pStack->SetError(TX_LABEL, pp->GetStart());
return nullptr;
}
}
// call routine corresponding to the compilation token found
switch (type)
{
case ID_WHILE:
return CBotWhile::Compile(p, pStack);
case ID_FOR:
return CBotFor::Compile(p, pStack);
case ID_DO:
return CBotDo::Compile(p, pStack);
case ID_BREAK:
case ID_CONTINUE:
return CBotBreak::Compile(p, pStack);
case ID_SWITCH:
return CBotSwitch::Compile(p, pStack);
case ID_TRY:
return CBotTry::Compile(p, pStack);
case ID_THROW:
return CBotThrow::Compile(p, pStack);
case ID_INT:
return CBotInt::Compile(p, pStack);
case ID_FLOAT:
return CBotFloat::Compile(p, pStack);
case ID_STRING:
return CBotIString::Compile(p, pStack);
case ID_BOOLEAN:
case ID_BOOL:
return CBotBoolean::Compile(p, pStack);
case ID_IF:
return CBotIf::Compile(p, pStack);
case ID_RETURN:
return CBotReturn::Compile(p, pStack);
case ID_ELSE:
pStack->SetStartError(p->GetStart());
pStack->SetError(TX_ELSEWITHOUTIF, p->GetEnd());
return nullptr;
case ID_CASE:
pStack->SetStartError(p->GetStart());
pStack->SetError(TX_OUTCASE, p->GetEnd());
return nullptr;
}
pStack->SetStartError(p->GetStart());
// should not be a reserved word DefineNum
if (p->GetType() == TokenTypDef)
{
pStack->SetError(TX_RESERVED, p);
return nullptr;
}
// this might be an instance of class definnition
CBotToken* ppp = p;
if (IsOfType(ppp, TokenTypVar))
{
if (CBotClass::Find(p) != nullptr)
{
// yes, compiles the declaration of the instance
return CBotClassInst::Compile(p, pStack);
}
}
// this can be an arythmetic instruction
CBotInstr* inst = CBotExpression::Compile(p, pStack);
if (IsOfType(p, ID_SEP))
{
return inst;
}
pStack->SetError(TX_ENDOF, p->GetStart());
delete inst;
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotInstr::Execute(CBotStack* &pj)
{
CBotString ClassManquante = name;
assert(0); // should never go through this routine
// but use the routines of the subclasses
return false;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotInstr::Execute(CBotStack* &pj, CBotVar* pVar)
{
if (!Execute(pj)) return false;
pVar->SetVal(pj->GetVar());
return true;
}
////////////////////////////////////////////////////////////////////////////////
void CBotInstr::RestoreState(CBotStack* &pj, bool bMain)
{
CBotString ClassManquante = name;
assert(0); // should never go through this routine
// but use the routines of the subclasses
}
////////////////////////////////////////////////////////////////////////////////
bool CBotInstr::ExecuteVar(CBotVar* &pVar, CBotCStack* &pile)
{
assert(0); // dad do not know, see the girls
return false;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotInstr::ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, bool bStep, bool bExtend)
{
assert(0); // dad do not know, see the girls
return false;
}
////////////////////////////////////////////////////////////////////////////////
void CBotInstr::RestoreStateVar(CBotStack* &pile, bool bMain)
{
assert(0); // dad do not know, see the girls
}
////////////////////////////////////////////////////////////////////////////////
bool CBotInstr::CompCase(CBotStack* &pj, int val)
{
return false;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotInstr::CompileArray(CBotToken* &p, CBotCStack* pStack, CBotTypResult type, bool first)
{
if (IsOfType(p, ID_OPBRK))
{
if (!IsOfType(p, ID_CLBRK))
{
pStack->SetError(TX_CLBRK, p->GetStart());
return nullptr;
}
CBotInstr* inst = CompileArray(p, pStack, CBotTypResult(CBotTypArrayPointer, type), false);
if (inst != nullptr || !pStack->IsOk()) return inst;
}
// compiles an array declaration
if (first) return nullptr ;
CBotInstr* inst = CBotInstArray::Compile(p, pStack, type);
if (inst == nullptr) return nullptr;
if (IsOfType(p, ID_COMMA)) // several definitions
{
if (nullptr != ( inst->m_next2b = CBotInstArray::CompileArray(p, pStack, type, false))) // compiles next one
{
return inst;
}
delete inst;
return nullptr;
}
if (IsOfType(p, ID_SEP)) // end of instruction
{
return inst;
}
delete inst;
pStack->SetError(TX_ENDOF, p->GetStart());
return nullptr;
}

View File

@ -0,0 +1,266 @@
/*
* 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/CBotToken.h"
#include "CBot/CBotCStack.h"
// Local include
// Global include
/*
for example, the following program
int x[]; x[1] = 4;
int y[x[1]][10], z;
is generated
CBotInstrArray
m_next3b-> CBotEmpty
m_next->
CBotExpression ....
m_next->
CBotInstrArray
m_next3b-> CBotExpression ('x') ( m_next3-> CBotIndexExpr ('1') )
m_next3b-> CBotExpression ('10')
m_next2-> 'z'
m_next->...
*/
/*!
* \brief The CBotInstr class Class defining an instruction.
*/
class CBotInstr
{
public:
/*!
* \brief CBotInstr
*/
CBotInstr();
/*!
* \brief ~CBotInstr
*/
virtual ~CBotInstr();
/*!
* \brief Compile Compile an instruction which can be while, do, try,
* throw, if, for, switch, break, continue, return, int, float, boolean,
* string, declaration of an instance of a class, arbitrary expression.
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p,
CBotCStack* pStack);
/*!
* \brief CompileArray
* \param p
* \param pStack
* \param type
* \param first
* \return
*/
static CBotInstr* CompileArray(CBotToken* &p,
CBotCStack* pStack,
CBotTypResult type,
bool first = true);
/*!
* \brief Execute
* \param pj
* \return
*/
virtual bool Execute(CBotStack* &pj);
/*!
* \brief Execute
* \param pj
* \param pVar
* \return
*/
virtual bool Execute(CBotStack* &pj,
CBotVar* pVar);
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
virtual void RestoreState(CBotStack* &pj,
bool bMain);
/*!
* \brief ExecuteVar
* \param pVar
* \param pile
* \return
*/
virtual bool ExecuteVar(CBotVar* &pVar,
CBotCStack* &pile);
/*!
* \brief ExecuteVar
* \param pVar
* \param pile
* \param prevToken
* \param bStep
* \param bExtend
* \return
*/
virtual bool ExecuteVar(CBotVar* &pVar,
CBotStack* &pile,
CBotToken* prevToken,
bool bStep,
bool bExtend);
/*!
* \brief RestoreStateVar
* \param pile
* \param bMain
*/
virtual void RestoreStateVar(CBotStack* &pile,
bool bMain);
/*!
* \brief CompCase This routine is defined only for the subclass CBotCase
* this allows to make the call on all instructions CompCase to see if it's
* a case to the desired value..
* \param pj
* \param val
* \return
*/
virtual bool CompCase(CBotStack* &pj,
int val);
/*!
* \brief SetToken Set the token corresponding to the instruction.
* \param p
*/
void SetToken(CBotToken* p);
/*!
* \brief GetTokenType Return the type of the token assicated with the
* instruction.
* \return
*/
int GetTokenType();
/*!
* \brief GetToken Return associated token.
* \return
*/
CBotToken* GetToken();
/*!
* \brief AddNext Adds the statement following the other.
* \param n
*/
void AddNext(CBotInstr* n);
/*!
* \brief GetNext Returns next statement.
* \return
*/
CBotInstr* GetNext();
/*!
* \brief AddNext3
* \param n
*/
void AddNext3(CBotInstr* n);
/*!
* \brief GetNext3
* \return
*/
CBotInstr* GetNext3();
/*!
* \brief AddNext3b
* \param n
*/
void AddNext3b(CBotInstr* n);
/*!
* \brief GetNext3b
* \return
*/
CBotInstr* GetNext3b();
/*!
* \brief IncLvl Adds a level with a label.
* \param label
*/
static void IncLvl(CBotString& label);
/*!
* \brief IncLvl Adds a level (switch statement).
*/
static void IncLvl();
/*!
* \brief DecLvl Free a level.
*/
static void DecLvl();
/*!
* \brief ChkLvl Control validity of break and continue.
* \param label
* \param type
* \return
*/
static bool ChkLvl(const CBotString& label, int type);
/*!
* \brief IsOfClass
* \param name
* \return
*/
bool IsOfClass(CBotString name);
protected:
//! Keeps the token.
CBotToken m_token;
//! Debug.
CBotString name;
//! Linked command.
CBotInstr* m_next;
//! Second list definition chain.
CBotInstr* m_next2b;
//! Third list for indices and fields.
CBotInstr* m_next3;
//! Necessary for reporting tables.
CBotInstr* m_next3b;
//! Counter of nested loops, to determine the break and continue valid.
static int m_LoopLvl;
friend class CBotClassInst;
friend class CBotInt;
friend class CBotListArray;
private:
//! List of labels used.
static CBotStringArray m_labelLvl;
};

View File

@ -0,0 +1,207 @@
/*
* 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 "CBotInstrCall.h"
#include "CBot/CBotInstr/CBotExpression.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotInstrCall::CBotInstrCall()
{
m_Parameters = nullptr;
m_nFuncIdent = 0;
name = "CBotInstrCall";
}
////////////////////////////////////////////////////////////////////////////////
CBotInstrCall::~CBotInstrCall()
{
delete m_Parameters;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotVar* ppVars[1000];
int i = 0;
CBotToken* pp = p;
p = p->GetNext();
pStack->SetStartError(p->GetStart());
CBotCStack* pile = pStack;
if ( IsOfType(p, ID_OPENPAR) )
{
int start, end;
CBotInstrCall* inst = new CBotInstrCall();
inst->SetToken(pp);
// compile la list of parameters
if (!IsOfType(p, ID_CLOSEPAR)) while (true)
{
start = p->GetStart();
pile = pile->TokenStack(); // keeps the results on the stack
CBotInstr* param = CBotExpression::Compile(p, pile);
end = p->GetStart();
if ( inst->m_Parameters == nullptr ) inst->m_Parameters = param;
else inst->m_Parameters->AddNext(param); // constructs the list
if ( !pile->IsOk() )
{
delete inst;
return pStack->Return(nullptr, pile);
}
if ( param != nullptr )
{
if ( pile->GetTypResult().Eq(99) )
{
delete pStack->TokenStack();
pStack->SetError(TX_VOID, p->GetStart());
delete inst;
return nullptr;
}
ppVars[i] = pile->GetVar();
ppVars[i]->GetToken()->SetPos(start, end);
i++;
if (IsOfType(p, ID_COMMA)) continue; // skips the comma
if (IsOfType(p, ID_CLOSEPAR)) break;
}
pStack->SetError(TX_CLOSEPAR, p->GetStart());
delete pStack->TokenStack();
delete inst;
return nullptr;
}
ppVars[i] = nullptr;
// the routine is known?
// CBotClass* pClass = nullptr;
inst->m_typRes = pStack->CompileCall(pp, ppVars, inst->m_nFuncIdent);
if ( inst->m_typRes.GetType() >= 20 )
{
// if (pVar2!=nullptr) pp = pVar2->RetToken();
pStack->SetError( inst->m_typRes.GetType(), pp );
delete pStack->TokenStack();
delete inst;
return nullptr;
}
delete pStack->TokenStack();
if ( inst->m_typRes.GetType() > 0 )
{
CBotVar* pRes = CBotVar::Create("", inst->m_typRes);
pStack->SetVar(pRes); // for knowing the type of the result
}
else pStack->SetVar(nullptr); // routine returns void
return inst;
}
p = pp;
delete pStack->TokenStack();
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotInstrCall::Execute(CBotStack* &pj)
{
CBotVar* ppVars[1000];
CBotStack* pile = pj->AddStack(this);
if ( pile->StackOver() ) return pj->Return( pile );
// CBotStack* pile1 = pile;
int i = 0;
CBotInstr* p = m_Parameters;
// evaluates parameters
// and places the values on the stack
// for allow of interruption at any time
if ( p != nullptr) while ( true )
{
pile = pile->AddStack(); // place on the stack for the results
if ( pile->GetState() == 0 )
{
if (!p->Execute(pile)) return false; // interrupted here?
pile->SetState(1); // mark as special for reknowed parameters \TODO marque spéciale pour reconnaîre parameters
}
ppVars[i++] = pile->GetVar();
p = p->GetNext();
if ( p == nullptr) break;
}
ppVars[i] = nullptr;
CBotStack* pile2 = pile->AddStack();
if ( pile2->IfStep() ) return false;
if ( !pile2->ExecuteCall(m_nFuncIdent, GetToken(), ppVars, m_typRes)) return false; // interrupt
return pj->Return(pile2); // release the entire stack
}
////////////////////////////////////////////////////////////////////////////////
void CBotInstrCall::RestoreState(CBotStack* &pj, bool bMain)
{
if ( !bMain ) return;
CBotStack* pile = pj->RestoreStack(this);
if ( pile == nullptr ) return;
// CBotStack* pile1 = pile;
int i = 0;
CBotVar* ppVars[1000];
CBotInstr* p = m_Parameters;
// evaluate parameters
// and place the values on the stack
// for allow of interruption at any time
if ( p != nullptr) while ( true )
{
pile = pile->RestoreStack(); // place on the stack for the results
if ( pile == nullptr ) return;
if ( pile->GetState() == 0 )
{
p->RestoreState(pile, bMain); // interrupt here!
return;
}
ppVars[i++] = pile->GetVar(); // constructs the list of parameters
p = p->GetNext();
if ( p == nullptr) break;
}
ppVars[i] = nullptr;
CBotStack* pile2 = pile->RestoreStack();
if ( pile2 == nullptr ) return;
pile2->RestoreCall(m_nFuncIdent, GetToken(), ppVars);
}

View File

@ -0,0 +1,76 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotInstrCall class Calls of these functions.
*/
class CBotInstrCall : public CBotInstr
{
public:
/*!
* \brief CBotInstrCall
*/
CBotInstrCall();
/*!
* \brief ~CBotInstrCall
*/
~CBotInstrCall();
/*!
* \brief Compile
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! The parameters to be evaluated.
CBotInstr* m_Parameters;
//! Complete type of the result.
CBotTypResult m_typRes;
//! Id of a function.
long m_nFuncIdent;
};

View File

@ -0,0 +1,281 @@
/*
* 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 "CBot/CBotInstr/CBotInstrMethode.h"
#include "CBot/CBotInstr/CBotInstrUtils.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotClass.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotInstrMethode::CBotInstrMethode()
{
m_Parameters = nullptr;
m_MethodeIdent = 0;
name = "CBotInstrMethode";
}
////////////////////////////////////////////////////////////////////////////////
CBotInstrMethode::~CBotInstrMethode()
{
delete m_Parameters;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotInstrMethode::Compile(CBotToken* &p, CBotCStack* pStack, CBotVar* var)
{
CBotInstrMethode* inst = new CBotInstrMethode();
inst->SetToken(p); // corresponding token
if (nullptr != var)
{
CBotToken* pp = p;
p = p->GetNext();
if (p->GetType() == ID_OPENPAR)
{
inst->m_NomMethod = pp->GetString();
// compiles the list of parameters
CBotVar* ppVars[1000];
inst->m_Parameters = CompileParams(p, pStack, ppVars);
if (pStack->IsOk())
{
CBotClass* pClass = var->GetClass(); // pointer to the class
inst->m_ClassName = pClass->GetName(); // name of the class
CBotTypResult r = pClass->CompileMethode(inst->m_NomMethod, var, ppVars,
pStack, inst->m_MethodeIdent);
delete pStack->TokenStack(); // release parameters on the stack
inst->m_typRes = r;
if (inst->m_typRes.GetType() > 20)
{
pStack->SetError(inst->m_typRes.GetType(), pp);
delete inst;
return nullptr;
}
// put the result on the stack to have something
if (inst->m_typRes.GetType() > 0)
{
CBotVar* pResult = CBotVar::Create("", inst->m_typRes);
if (inst->m_typRes.Eq(CBotTypClass))
{
pResult->SetClass(inst->m_typRes.GetClass());
}
pStack->SetVar(pResult);
}
return inst;
}
delete inst;
return nullptr;
}
}
pStack->SetError(1234, p);
delete inst;
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotInstrMethode::ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* prevToken, bool bStep, bool bExtend)
{
CBotVar* ppVars[1000];
CBotStack* pile1 = pj->AddStack(this, true); // a place for the copy of This
if (pVar->GetPointer() == nullptr)
{
pj->SetError(TX_NULLPT, prevToken);
}
if (pile1->IfStep()) return false;
CBotStack* pile2 = pile1->AddStack(); // for the next parameters
if ( pile1->GetState() == 0)
{
CBotVar* pThis = CBotVar::Create(pVar);
pThis->Copy(pVar);
// this value should be taken before the evaluation parameters
// Test.Action (Test = Other);
// action must act on the value before test = Other!
pThis->SetName("this");
pThis->SetUniqNum(-2);
pile1->AddVar(pThis);
pile1->IncState();
}
int i = 0;
CBotInstr* p = m_Parameters;
// evaluate the parameters
// and places the values on the stack
// to be interrupted at any time
if (p != nullptr) while ( true)
{
if (pile2->GetState() == 0)
{
if (!p->Execute(pile2)) return false; // interrupted here?
if (!pile2->SetState(1)) return false; // special mark to recognize parameters
}
ppVars[i++] = pile2->GetVar(); // construct the list of pointers
pile2 = pile2->AddStack(); // space on the stack for the result
p = p->GetNext();
if ( p == nullptr) break;
}
ppVars[i] = nullptr;
CBotClass* pClass = CBotClass::Find(m_ClassName);
CBotVar* pThis = pile1->FindVar(-2);
CBotVar* pResult = nullptr;
if (m_typRes.GetType() > 0) pResult = CBotVar::Create("", m_typRes);
if (m_typRes.Eq(CBotTypClass))
{
pResult->SetClass(m_typRes.GetClass());
}
CBotVar* pRes = pResult;
if ( !pClass->ExecuteMethode(m_MethodeIdent, m_NomMethod,
pThis, ppVars,
pResult, pile2, GetToken())) return false;
if (pRes != pResult) delete pRes;
pVar = nullptr; // does not return value for this
return pj->Return(pile2); // release the entire stack
}
////////////////////////////////////////////////////////////////////////////////
void CBotInstrMethode::RestoreStateVar(CBotStack* &pile, bool bMain)
{
if (!bMain) return;
CBotVar* ppVars[1000];
CBotStack* pile1 = pile->RestoreStack(this); // place for the copy of This
if (pile1 == nullptr) return;
CBotStack* pile2 = pile1->RestoreStack(); // and for the parameters coming
if (pile2 == nullptr) return;
CBotVar* pThis = pile1->FindVar("this");
pThis->SetUniqNum(-2);
int i = 0;
CBotInstr* p = m_Parameters;
// evaluate the parameters
// and places the values on the stack
// to be interrupted at any time
if (p != nullptr) while ( true)
{
if (pile2->GetState() == 0)
{
p->RestoreState(pile2, true); // interrupted here!
return;
}
ppVars[i++] = pile2->GetVar(); // construct the list of pointers
pile2 = pile2->RestoreStack();
if (pile2 == nullptr) return;
p = p->GetNext();
if ( p == nullptr) break;
}
ppVars[i] = nullptr;
CBotClass* pClass = CBotClass::Find(m_ClassName);
// CBotVar* pResult = nullptr;
// CBotVar* pRes = pResult;
pClass->RestoreMethode(m_MethodeIdent, m_NomMethod,
pThis, ppVars, pile2);
}
////////////////////////////////////////////////////////////////////////////////
bool CBotInstrMethode::Execute(CBotStack* &pj)
{
CBotVar* ppVars[1000];
CBotStack* pile1 = pj->AddStack(this, true); // place for the copy of This
if (pile1->IfStep()) return false;
CBotStack* pile2 = pile1->AddStack(); // and for the parameters coming
if ( pile1->GetState() == 0)
{
CBotVar* pThis = pile1->CopyVar(m_token);
// this value should be taken before the evaluation parameters
// Test.Action (Test = Other);
// Action must act on the value before test = Other!
pThis->SetName("this");
pile1->AddVar(pThis);
pile1->IncState();
}
int i = 0;
CBotInstr* p = m_Parameters;
// evaluate the parameters
// and places the values on the stack
// to be interrupted at any time
if (p != nullptr) while ( true)
{
if (pile2->GetState() == 0)
{
if (!p->Execute(pile2)) return false; // interrupted here?
if (!pile2->SetState(1)) return false; // special mark to recognize parameters
}
ppVars[i++] = pile2->GetVar(); // construct the list of pointers
pile2 = pile2->AddStack(); // space on the stack for the results
p = p->GetNext();
if ( p == nullptr) break;
}
ppVars[i] = nullptr;
CBotClass* pClass = CBotClass::Find(m_ClassName);
CBotVar* pThis = pile1->FindVar("this");
CBotVar* pResult = nullptr;
if (m_typRes.GetType()>0) pResult = CBotVar::Create("", m_typRes);
if (m_typRes.Eq(CBotTypClass))
{
pResult->SetClass(m_typRes.GetClass());
}
CBotVar* pRes = pResult;
if ( !pClass->ExecuteMethode(m_MethodeIdent, m_NomMethod,
pThis, ppVars,
pResult, pile2, GetToken())) return false; // interupted
// set the new value of this in place of the old variable
CBotVar* old = pile1->FindVar(m_token);
old->Copy(pThis, false);
if (pRes != pResult) delete pRes;
return pj->Return(pile2); // release the entire stack
}

View File

@ -0,0 +1,92 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotInstrMethode class A call of method. Compile a method call.
*/
class CBotInstrMethode : public CBotInstr
{
public:
/*!
* \brief CBotInstrMethode
*/
CBotInstrMethode();
/*!
* \brief ~CBotInstrMethode
*/
~CBotInstrMethode();
/*!
* \brief Compile
* \param p
* \param pStack
* \param pVar
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, CBotVar* pVar);
/*!
* \brief Execute
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief ExecuteVar Execute the method call.
* \param pVar
* \param pj
* \param prevToken
* \param bStep
* \param bExtend
* \return
*/
bool ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* prevToken, bool bStep, bool bExtend) override;
/*!
* \brief RestoreStateVar
* \param pj
* \param bMain
*/
void RestoreStateVar(CBotStack* &pj, bool bMain) override;
private:
//! The parameters to be evaluated.
CBotInstr *m_Parameters;
//! Complete type of the result.
CBotTypResult m_typRes;
//! Name of the method.
CBotString m_NomMethod;
//! Identifier of the method.
long m_MethodeIdent;
//! Name of the class.
CBotString m_ClassName;
};

View File

@ -0,0 +1,165 @@
/*
* 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 "CBot/CBotInstr/CBotInstrUtils.h"
#include "CBot/CBotToken.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotTypResult.h"
#include "CBot/CBotInstr/CBotExpression.h"
#include "CBot/CBotClass.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars)
{
bool first = true;
CBotInstr* ret = nullptr; // to return to the list
CBotCStack* pile = pStack;
int i = 0;
if (IsOfType(p, ID_OPENPAR))
{
int start, end;
if (!IsOfType(p, ID_CLOSEPAR)) while (true)
{
start = p->GetStart();
pile = pile->TokenStack(); // keeps the result on the stack
if (first) pStack->SetStartError(start);
first = false;
CBotInstr* param = CBotExpression::Compile(p, pile);
end = p->GetStart();
if (!pile->IsOk())
{
return pStack->Return(nullptr, pile);
}
if (ret == nullptr) ret = param;
else ret->AddNext(param); // construct the list
if (param != nullptr)
{
if (pile->GetTypResult().Eq(99))
{
delete pStack->TokenStack();
pStack->SetError(TX_VOID, p->GetStart());
return nullptr;
}
ppVars[i] = pile->GetVar();
ppVars[i]->GetToken()->SetPos(start, end);
i++;
if (IsOfType(p, ID_COMMA)) continue; // skips the comma
if (IsOfType(p, ID_CLOSEPAR)) break;
}
pStack->SetError(TX_CLOSEPAR, p->GetStart());
delete pStack->TokenStack();
return nullptr;
}
}
ppVars[i] = nullptr;
return ret;
}
////////////////////////////////////////////////////////////////////////////////
bool TypeCompatible(CBotTypResult& type1, CBotTypResult& type2, int op)
{
int t1 = type1.GetType();
int t2 = type2.GetType();
int max = (t1 > t2) ? t1 : t2;
if (max == 99) return false; // result is void?
// special case for strin concatenation
if (op == ID_ADD && max >= CBotTypString) return true;
if (op == ID_ASSADD && max >= CBotTypString) return true;
if (op == ID_ASS && t1 == CBotTypString) return true;
if (max >= CBotTypBoolean)
{
if ( (op == ID_EQ || op == ID_NE) &&
(t1 == CBotTypPointer && t2 == CBotTypNullPointer)) return true;
if ( (op == ID_EQ || op == ID_NE || op == ID_ASS) &&
(t2 == CBotTypPointer && t1 == CBotTypNullPointer)) return true;
if ( (op == ID_EQ || op == ID_NE) &&
(t1 == CBotTypArrayPointer && t2 == CBotTypNullPointer)) return true;
if ( (op == ID_EQ || op == ID_NE || op == ID_ASS) &&
(t2 == CBotTypArrayPointer && t1 == CBotTypNullPointer)) return true;
if (t2 != t1) return false;
if (t1 == CBotTypArrayPointer) return type1.Compare(type2);
if (t1 == CBotTypPointer ||
t1 == CBotTypClass ||
t1 == CBotTypIntrinsic )
{
CBotClass* c1 = type1.GetClass();
CBotClass* c2 = type2.GetClass();
return c1->IsChildOf(c2) || c2->IsChildOf(c1);
// accept the case in reverse
// the transaction will be denied at runtime if the pointer is not
// compatible
}
return true;
}
type1.SetType(max);
type2.SetType(max);
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool TypesCompatibles(const CBotTypResult& type1, const CBotTypResult& type2)
{
int t1 = type1.GetType();
int t2 = type2.GetType();
if (t1 == CBotTypIntrinsic) t1 = CBotTypClass;
if (t2 == CBotTypIntrinsic) t2 = CBotTypClass;
int max = (t1 > t2) ? t1 : t2;
if (max == 99) return false; // result is void?
if (max >= CBotTypBoolean)
{
if (t2 != t1) return false;
if (max == CBotTypArrayPointer)
return TypesCompatibles(type1.GetTypElem(), type2.GetTypElem());
if (max == CBotTypClass || max == CBotTypPointer)
return type1.GetClass() == type2.GetClass() ;
return true ;
}
return true;
}

View File

@ -0,0 +1,61 @@
/*
* 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
// Local include
// Global include
// Forward declaration
class CBotInstr;
class CBotToken;
class CBotCStack;
class CBotVar;
class CBotTypResult;
/*!
* \brief CompileParams Compile a list of parameters.
* \param p
* \param pStack
* \param ppVars
* \return
*/
CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars);
/*!
* \brief TypeCompatible Check if two results are consistent to make an
* operation.
* \param type1
* \param type2
* \param op
* \return
*/
bool TypeCompatible(CBotTypResult& type1, CBotTypResult& type2, int op = 0);
/*!
* \brief TypesCompatibles Check if two variables are compatible for parameter
* passing.
* \param type1
* \param type2
* \return
*/
bool TypesCompatibles(const CBotTypResult& type1, const CBotTypResult& type2);

View File

@ -0,0 +1,190 @@
/*
* 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 "CBot/CBotInstr/CBotInt.h"
#include "CBot/CBotInstr/CBotLeftExprVar.h"
#include "CBot/CBotInstr/CBotInstArray.h"
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotInt::CBotInt()
{
m_next = nullptr; // for multiple definitions
m_var =
m_expr = nullptr;
name = "CBotInt";
}
////////////////////////////////////////////////////////////////////////////////
CBotInt::~CBotInt()
{
delete m_var;
delete m_expr;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, bool noskip)
{
CBotToken* pp = cont ? nullptr : p; // no repetition of the token "int"
if (!cont && !IsOfType(p, ID_INT)) return nullptr;
CBotInt* inst = static_cast<CBotInt*>(CompileArray(p, pStack, CBotTypInt));
if (inst != nullptr || !pStack->IsOk()) return inst;
CBotCStack* pStk = pStack->TokenStack(pp);
inst = new CBotInt();
inst->m_expr = nullptr;
CBotToken* vartoken = p;
inst->SetToken(vartoken);
// determines the expression is valid for the item on the left side
if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )))
{
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = CBotTypInt;
if (pStk->CheckVarLocal(vartoken)) // redefinition of the variable
{
pStk->SetError(TX_REDEFVAR, vartoken);
goto error;
}
if (IsOfType(p, ID_OPBRK))
{
delete inst; // type is not CBotInt
p = vartoken; // returns the variable name
// compiles an array declaration
CBotInstr* inst2 = CBotInstArray::Compile(p, pStk, CBotTypInt);
if (!pStk->IsOk() )
{
pStk->SetError(TX_CLBRK, p->GetStart());
goto error;
}
if (IsOfType(p, ID_COMMA)) // several definition chained
{
if (nullptr != ( inst2->m_next2b = CBotInt::Compile(p, pStk, true, noskip))) // compile the next one
{
return pStack->Return(inst2, pStk);
}
}
inst = static_cast<CBotInt*>(inst2);
goto suite; // no assignment, variable already created
}
if (IsOfType(p, ID_ASS)) // with an assignment?
{
if (nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )))
{
goto error;
}
if (pStk->GetType() >= CBotTypBoolean) // compatible type ?
{
pStk->SetError(TX_BADTYPE, p->GetStart());
goto error;
}
}
{
CBotVar* var = CBotVar::Create(vartoken, CBotTypInt);// create the variable (evaluated after the assignment)
var->SetInit(inst->m_expr != nullptr ? CBotVar::InitType::DEF : CBotVar::InitType::UNDEF); // if initialized with assignment
var->SetUniqNum( //set it with a unique number
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
pStack->AddVar(var); // place it on the stack
}
if (IsOfType(p, ID_COMMA)) // chained several definitions
{
if (nullptr != ( inst->m_next2b = CBotInt::Compile(p, pStk, true, noskip))) // compile next one
{
return pStack->Return(inst, pStk);
}
}
suite:
if (noskip || IsOfType(p, ID_SEP)) // instruction is completed
{
return pStack->Return(inst, pStk);
}
pStk->SetError(TX_ENDOF, p->GetStart());
}
error:
delete inst;
return pStack->Return(nullptr, pStk);
}
////////////////////////////////////////////////////////////////////////////////
bool CBotInt::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this); // essential for SetState()
if ( pile->GetState()==0)
{
if (m_expr && !m_expr->Execute(pile)) return false; // initial value // interrupted?
m_var->Execute(pile); // creates and assign the result
if (!pile->SetState(1)) return false;
}
if (pile->IfStep()) return false;
if ( m_next2b &&
!m_next2b->Execute(pile)) return false; // other(s) definition(s)
return pj->Return(pile); // forward below
}
////////////////////////////////////////////////////////////////////////////////
void CBotInt::RestoreState(CBotStack* &pj, bool bMain)
{
CBotStack* pile = pj;
if (bMain)
{
pile = pj->RestoreStack(this);
if (pile == nullptr) return;
if ( pile->GetState()==0)
{
if (m_expr) m_expr->RestoreState(pile, bMain); // initial value // interrupted?
return;
}
}
m_var->RestoreState(pile, bMain);
if (m_next2b) m_next2b->RestoreState(pile, bMain); // other(s) definition(s)
}

View File

@ -0,0 +1,78 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotInt class Definition of an integer variable
* int a, b = 12;
*/
class CBotInt : public CBotInstr
{
public:
/*!
* \brief CBotInt
*/
CBotInt();
/*!
* \brief ~CBotInt
*/
~CBotInt();
/*!
* \brief Compile
* \param p
* \param pStack
* \param cont
* \param noskip
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool cont = false, bool noskip = false);
/*!
* \brief Execute Execute the definition of the integer variable.
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! The variable to initialize.
CBotInstr* m_var;
//! A value to put, if there is.
CBotInstr* m_expr;
};

View File

@ -0,0 +1,248 @@
/*
* 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 "CBot/CBotInstr/CBotLeftExpr.h"
#include "CBot/CBotInstr/CBotFieldExpr.h"
#include "CBot/CBotInstr/CBotIndexExpr.h"
#include "CBot/CBotInstr/CBotExpression.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotClass.h"
#include "CBot/CBotVar/CBotVarArray.h"
// Local include
// Global include
//////////////////////////////////////////////////////////////////////////////////////
CBotLeftExpr::CBotLeftExpr()
{
name = "CBotLeftExpr";
m_nIdent = 0;
}
////////////////////////////////////////////////////////////////////////////////
CBotLeftExpr::~CBotLeftExpr()
{
}
////////////////////////////////////////////////////////////////////////////////
CBotLeftExpr* CBotLeftExpr::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotCStack* pStk = pStack->TokenStack();
pStk->SetStartError(p->GetStart());
// is it a variable name?
if (p->GetType() == TokenTypVar)
{
CBotLeftExpr* inst = new CBotLeftExpr(); // creates the object
inst->SetToken(p);
CBotVar* var;
if (nullptr != (var = pStk->FindVar(p))) // seek if known variable
{
inst->m_nIdent = var->GetUniqNum();
if (inst->m_nIdent > 0 && inst->m_nIdent < 9000)
{
if ( var->IsPrivate(PR_READ) &&
!pStk->GetBotCall()->m_bCompileClass)
{
pStk->SetError(TX_PRIVATE, p);
goto err;
}
// this is an element of the current class
// adds the equivalent of this. before
CBotToken pthis("this");
inst->SetToken(&pthis);
inst->m_nIdent = -2; // indent for this
CBotFieldExpr* i = new CBotFieldExpr(); // new element
i->SetToken(p); // keeps the name of the token
inst->AddNext3(i); // add after
var = pStk->FindVar(pthis);
var = var->GetItem(p->GetString());
i->SetUniqNum(var->GetUniqNum());
}
p = p->GetNext(); // next token
while (true)
{
if (var->GetType() == CBotTypArrayPointer)
{
if (IsOfType( p, ID_OPBRK ))
{
CBotIndexExpr* i = new CBotIndexExpr();
i->m_expr = CBotExpression::Compile(p, pStk);
inst->AddNext3(i); // add to the chain
var = (static_cast<CBotVarArray*>(var))->GetItem(0,true); // gets the component [0]
if (i->m_expr == nullptr)
{
pStk->SetError(TX_BADINDEX, p->GetStart());
goto err;
}
if (!pStk->IsOk() || !IsOfType( p, ID_CLBRK ))
{
pStk->SetError(TX_CLBRK, p->GetStart());
goto err;
}
continue;
}
}
if (var->GetType(1) == CBotTypPointer) // for classes
{
if (IsOfType(p, ID_DOT))
{
CBotToken* pp = p;
CBotFieldExpr* i = new CBotFieldExpr(); // new element
i->SetToken(pp); // keeps the name of the token
inst->AddNext3(i); // adds after
if (p->GetType() == TokenTypVar) // must be a name
{
var = var->GetItem(p->GetString()); // get item correspondent
if (var != nullptr)
{
if ( var->IsPrivate(PR_READ) &&
!pStk->GetBotCall()->m_bCompileClass)
{
pStk->SetError(TX_PRIVATE, pp);
goto err;
}
i->SetUniqNum(var->GetUniqNum());
p = p->GetNext(); // skips the name
continue;
}
pStk->SetError(TX_NOITEM, p);
}
pStk->SetError(TX_DOT, p->GetStart());
goto err;
}
}
break;
}
if (pStk->IsOk()) return static_cast<CBotLeftExpr*> (pStack->Return(inst, pStk));
}
pStk->SetError(TX_UNDEFVAR, p);
err:
delete inst;
return static_cast<CBotLeftExpr*> ( pStack->Return(nullptr, pStk));
}
return static_cast<CBotLeftExpr*> ( pStack->Return(nullptr, pStk));
}
////////////////////////////////////////////////////////////////////////////////
bool CBotLeftExpr::Execute(CBotStack* &pj, CBotStack* array)
{
CBotStack* pile = pj->AddStack();
CBotVar* var1 = nullptr;
CBotVar* var2 = nullptr;
// fetch a variable (not copy)
if (!ExecuteVar(var1, array, nullptr, false)) return false;
if (pile->IfStep()) return false;
if (var1)
{
var2 = pj->GetVar(); // result on the input stack
if (var2)
{
CBotTypResult t1 = var1->GetTypResult();
CBotTypResult t2 = var2->GetTypResult();
if (t2.Eq(CBotTypPointer))
{
CBotClass* c1 = t1.GetClass();
CBotClass* c2 = t2.GetClass();
if ( !c2->IsChildOf(c1))
{
CBotToken* pt = &m_token;
pile->SetError(TX_BADTYPE, pt);
return pj->Return(pile); // operation performed
}
}
var1->SetVal(var2); // do assignment
}
pile->SetCopyVar(var1); // replace the stack with the copy of the variable
// (for name)
}
return pj->Return(pile); // operation performed
}
////////////////////////////////////////////////////////////////////////////////
bool CBotLeftExpr::ExecuteVar(CBotVar* &pVar, CBotCStack* &pile)
{
pVar = pile->FindVar(m_token);
if (pVar == nullptr) return false;
if ( m_next3 != nullptr &&
!m_next3->ExecuteVar(pVar, pile) ) return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotLeftExpr::ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, bool bStep)
{
pile = pile->AddStack(this);
pVar = pile->FindVar(m_nIdent);
if (pVar == nullptr)
{
#ifdef _DEBUG
assert(0);
#endif
pile->SetError(2, &m_token);
return false;
}
if (bStep && m_next3 == nullptr && pile->IfStep()) return false;
if ( m_next3 != nullptr &&
!m_next3->ExecuteVar(pVar, pile, &m_token, bStep, true) ) return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////
void CBotLeftExpr::RestoreStateVar(CBotStack* &pile, bool bMain)
{
pile = pile->RestoreStack(this);
if (pile == nullptr) return;
if (m_next3 != nullptr)
m_next3->RestoreStateVar(pile, bMain);
}

View File

@ -0,0 +1,101 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotLeftExpr class Accept the expressions that be to the left of
* assignment.
*/
class CBotLeftExpr : public CBotInstr
{
public:
/*!
* \brief CBotLeftExpr
*/
CBotLeftExpr();
/*!
* \brief ~CBotLeftExpr
*/
~CBotLeftExpr();
/*!
* \brief Compile Compiles an expression for a left-operand
* (left of an assignment).
* eg :
* - toto
* - toto[ 3 ]
* - toto.x
* - toto.pos.x
* - toto[2].pos.x
* - toto[1].pos[2].x
* - toto[1][2][3]
*
* \param p
* \param pStack
* \return
*/
static CBotLeftExpr* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute Runs, is a variable and assigns the result to the stack.
* \param pStack
* \param array
* \return
*/
bool Execute(CBotStack* &pStack, CBotStack* array);
/*!
* \brief ExecuteVar Fetch a variable during compilation.
* \param pVar
* \param pile
* \return
*/
bool ExecuteVar(CBotVar* &pVar, CBotCStack* &pile) override;
/*!
* \brief ExecuteVar Fetch the variable at runtume.
* \param pVar
* \param pile
* \param prevToken
* \param bStep
* \return
*/
bool ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, bool bStep);
/*!
* \brief RestoreStateVar
* \param pile
* \param bMain
*/
void RestoreStateVar(CBotStack* &pile, bool bMain) override;
private:
long m_nIdent;
};

View File

@ -0,0 +1,88 @@
/*
* 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 "CBot/CBotInstr/CBotLeftExprVar.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
#include <assert.h>
////////////////////////////////////////////////////////////////////////////////
CBotLeftExprVar::CBotLeftExprVar()
{
name = "CBotLeftExprVar";
m_typevar = -1;
m_nIdent = 0;
}
////////////////////////////////////////////////////////////////////////////////
CBotLeftExprVar::~CBotLeftExprVar()
{
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotLeftExprVar::Compile(CBotToken* &p, CBotCStack* pStack)
{
// verifies that the token is a variable name
if (p->GetType() != TokenTypVar)
{
pStack->SetError( TX_NOVAR, p->GetStart());
return nullptr;
}
CBotLeftExprVar* inst = new CBotLeftExprVar();
inst->SetToken(p);
p = p->GetNext();
return inst;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotLeftExprVar::Execute(CBotStack* &pj)
{
CBotVar* var1;
CBotVar* var2;
var1 = CBotVar::Create(m_token.GetString(), m_typevar);
var1->SetUniqNum(m_nIdent); // with the unique identifier
pj->AddVar(var1); // place it on the stack
var2 = pj->GetVar(); // result on the stack
if (var2) var1->SetVal(var2); // do the assignment
return true;
}
////////////////////////////////////////////////////////////////////////////////
void CBotLeftExprVar::RestoreState(CBotStack* &pj, bool bMain)
{
CBotVar* var1;
var1 = pj->FindVar(m_token.GetString());
if (var1 == nullptr) assert(0);
var1->SetUniqNum(m_nIdent); // with the unique identifier
}

View File

@ -0,0 +1,75 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotLeftExprVar class Compilation of an element to the left of an assignment.
*/
class CBotLeftExprVar : public CBotInstr
{
public:
/*!
* \brief CBotLeftExprVar
*/
CBotLeftExprVar();
/*!
* \brief ~CBotLeftExprVar
*/
~CBotLeftExprVar();
/*!
* \brief Compile
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute Creates a variable and assigns the result to the stack.
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
public:
//! Type of variable declared.
CBotTypResult m_typevar;
//! Unique identifier for that variable.
long m_nIdent;
};

View File

@ -0,0 +1,182 @@
/*
* 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 "CBot/CBotInstr/CBotListArray.h"
#include "CBot/CBotInstr/CBotInstrUtils.h"
#include "CBot/CBotInstr/CBotExprNull.h"
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotListArray::CBotListArray()
{
m_expr = nullptr;
name = "CBotListArray";
}
////////////////////////////////////////////////////////////////////////////////
CBotListArray::~CBotListArray()
{
delete m_expr;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotListArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResult type)
{
CBotCStack* pStk = pStack->TokenStack(p);
CBotToken* pp = p;
if (IsOfType( p, ID_NULL ))
{
CBotInstr* inst = new CBotExprNull ();
inst->SetToken(pp);
return pStack->Return(inst, pStk); // ok with empty element
}
CBotListArray* inst = new CBotListArray();
if (IsOfType( p, ID_OPENPAR ))
{
// each element takes the one after the other
if (type.Eq( CBotTypArrayPointer ))
{
type = type.GetTypElem();
pStk->SetStartError(p->GetStart());
if (nullptr == ( inst->m_expr = CBotListArray::Compile( p, pStk, type ) ))
{
goto error;
}
while (IsOfType( p, ID_COMMA )) // other elements?
{
pStk->SetStartError(p->GetStart());
CBotInstr* i = CBotListArray::Compile(p, pStk, type);
if (nullptr == i)
{
goto error;
}
inst->m_expr->AddNext3(i);
}
}
else
{
pStk->SetStartError(p->GetStart());
if (nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )))
{
goto error;
}
CBotVar* pv = pStk->GetVar(); // result of the expression
if (pv == nullptr || !TypesCompatibles( type, pv->GetTypResult())) // compatible type?
{
pStk->SetError(TX_BADTYPE, p->GetStart());
goto error;
}
while (IsOfType( p, ID_COMMA )) // other elements?
{
pStk->SetStartError(p->GetStart());
CBotInstr* i = CBotTwoOpExpr::Compile(p, pStk) ;
if (nullptr == i)
{
goto error;
}
CBotVar* pv = pStk->GetVar(); // result of the expression
if (pv == nullptr || !TypesCompatibles( type, pv->GetTypResult())) // compatible type?
{
pStk->SetError(TX_BADTYPE, p->GetStart());
goto error;
}
inst->m_expr->AddNext3(i);
}
}
if (!IsOfType(p, ID_CLOSEPAR) )
{
pStk->SetError(TX_CLOSEPAR, p->GetStart());
goto error;
}
return pStack->Return(inst, pStk);
}
error:
delete inst;
return pStack->Return(nullptr, pStk);
}
////////////////////////////////////////////////////////////////////////////////
bool CBotListArray::Execute(CBotStack* &pj, CBotVar* pVar)
{
CBotStack* pile1 = pj->AddStack();
CBotVar* pVar2;
CBotInstr* p = m_expr;
int n = 0;
for (; p != nullptr ; n++, p = p->GetNext3())
{
if (pile1->GetState() > n) continue;
pVar2 = pVar->GetItem(n, true);
if (!p->Execute(pile1, pVar2)) return false; // evaluate expression
pile1->IncState();
}
return pj->Return(pile1);
}
////////////////////////////////////////////////////////////////////////////////
void CBotListArray::RestoreState(CBotStack* &pj, bool bMain)
{
if (bMain)
{
CBotStack* pile = pj->RestoreStack(this);
if (pile == nullptr) return;
CBotInstr* p = m_expr;
int state = pile->GetState();
while(state-- > 0) p = p->GetNext3() ;
p->RestoreState(pile, bMain); // size calculation //interrupted!
}
}

View File

@ -0,0 +1,76 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotListArray class Definition of a assignment list for a table
* int [ ] a [ ] = ( ( 1, 2, 3 ) , ( 3, 2, 1 ) ) ;
*/
class CBotListArray : public CBotInstr
{
public:
/*!
* \brief CBotListArray
*/
CBotListArray();
/*!
* \brief ~CBotListArray
*/
~CBotListArray();
/*!
* \brief Compile
* \param p
* \param pStack
* \param type
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResult type);
/*!
* \brief Execute Executes the definition of an array.
* \param pj
* \param pVar
* \return
*/
bool Execute(CBotStack* &pj, CBotVar* pVar) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! An expression for an element others are linked with CBotInstr :: m_next3;
CBotInstr* m_expr;
};

View File

@ -0,0 +1,131 @@
/*
* 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 "CBot/CBotInstr/CBotListExpression.h"
#include "CBot/CBotInstr/CBotExpression.h"
#include "CBot/CBotInstr/CBotIString.h"
#include "CBot/CBotInstr/CBotFloat.h"
#include "CBotBoolean.h"
#include "CBot/CBotInstr/CBotInt.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
/// Seeks a declaration of variable or expression
static CBotInstr* CompileInstrOrDefVar(CBotToken* &p, CBotCStack* pStack)
{
CBotInstr* i = CBotInt::Compile( p, pStack, false, true ); // Is this a declaration of an integer?
if ( i== nullptr ) i = CBotFloat::Compile( p, pStack, false, true ); // or a real number?
if ( i== nullptr ) i = CBotBoolean::Compile( p, pStack, false, true ); // or a boolean?
if ( i== nullptr ) i = CBotIString::Compile( p, pStack, false, true ); // ar a string?
if ( i== nullptr ) i = CBotExpression::Compile( p, pStack ); // compiles an expression
return i;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
CBotListExpression::CBotListExpression()
{
m_Expr = nullptr;
name = "CBotListExpression";
}
////////////////////////////////////////////////////////////////////////////////
CBotListExpression::~CBotListExpression()
{
delete m_Expr;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotListExpression::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotListExpression* inst = new CBotListExpression();
inst->m_Expr = CompileInstrOrDefVar( p, pStack ); // compile the first expression in a list
if (pStack->IsOk())
{
while ( IsOfType(p, ID_COMMA) ) // more instructions?
{
CBotInstr* i = CompileInstrOrDefVar( p, pStack ); // Is this a declaration of an integer?
inst->m_Expr->AddNext(i); // added after
if ( !pStack->IsOk() )
{
delete inst;
return nullptr; // no object, the error is on the stack
}
}
return inst;
}
delete inst;
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotListExpression::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(); // essential
CBotInstr* p = m_Expr; // the first expression
int state = pile->GetState();
while (state-->0) p = p->GetNext(); // returns to the interrupted operation
if ( p != nullptr ) while (true)
{
if ( !p->Execute(pile) ) return false;
p = p->GetNext();
if ( p == nullptr ) break;
if (!pile->IncState()) return false; // ready for next
}
return pj->Return(pile);
}
////////////////////////////////////////////////////////////////////////////////
void CBotListExpression::RestoreState(CBotStack* &pj, bool bMain)
{
CBotStack* pile = pj;
int state = 0x7000;
if ( bMain )
{
pile = pj->RestoreStack();
if ( pile == nullptr ) return;
state = pile->GetState();
}
CBotInstr* p = m_Expr; // the first expression
while (p != nullptr && state-->0)
{
p->RestoreState(pile, false);
p = p->GetNext(); // returns to the interrupted operation
}
if ( p != nullptr )
{
p->RestoreState(pile, bMain);
}
}

View File

@ -0,0 +1,72 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotListExpression class. Compiles a list of expressions is used
* only in "for" statement in incrementing and intitialisation.
*/
class CBotListExpression : public CBotInstr
{
public:
/*!
* \brief CBotListExpression
*/
CBotListExpression();
/*!
* \brief CBotListExpression
*/
~CBotListExpression();
/*!
* \brief Compile
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute
* \param pStack
* \return
*/
bool Execute(CBotStack* &pStack) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! The first expression to be evaluated
CBotInstr* m_Expr;
};

View File

@ -0,0 +1,121 @@
/*
* 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 "CBot/CBotInstr/CBotListInstr.h"
#include "CBot/CBotInstr/CBotBlock.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotListInstr::CBotListInstr()
{
m_Instr = nullptr;
name = "CBotListInstr";
}
////////////////////////////////////////////////////////////////////////////////
CBotListInstr::~CBotListInstr()
{
delete m_Instr;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotListInstr::Compile(CBotToken* &p, CBotCStack* pStack, bool bLocal)
{
CBotCStack* pStk = pStack->TokenStack(p, bLocal); // variables are local
CBotListInstr* inst = new CBotListInstr();
while (true)
{
if (p == nullptr) break;
if (IsOfType(p, ID_SEP)) continue; // empty statement ignored
if (p->GetType() == ID_CLBLK) break;
if (IsOfType(p, 0))
{
pStack->SetError(TX_CLOSEBLK, p->GetStart());
delete inst;
return pStack->Return(nullptr, pStk);
}
CBotInstr* i = CBotBlock::CompileBlkOrInst(p, pStk); // compiles next
if (!pStk->IsOk())
{
delete inst;
return pStack->Return(nullptr, pStk);
}
if (inst->m_Instr == nullptr) inst->m_Instr = i;
else inst->m_Instr->AddNext(i); // added a result
}
return pStack->Return(inst, pStk);
}
////////////////////////////////////////////////////////////////////////////////
bool CBotListInstr::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this, true); //needed for SetState()
if (pile->StackOver() ) return pj->Return( pile);
CBotInstr* p = m_Instr; // the first expression
int state = pile->GetState();
while (state-->0) p = p->GetNext(); // returns to the interrupted operation
if (p != nullptr) while (true)
{
if (!p->Execute(pile)) return false;
p = p->GetNext();
if (p == nullptr) break;
(void)pile->IncState(); // ready for next
}
return pj->Return(pile);
}
////////////////////////////////////////////////////////////////////////////////
void CBotListInstr::RestoreState(CBotStack* &pj, bool bMain)
{
if (!bMain) return;
CBotStack* pile = pj->RestoreStack(this);
if (pile == nullptr) return;
CBotInstr* p = m_Instr; // the first expression
int state = pile->GetState();
while ( p != nullptr && state-- > 0)
{
p->RestoreState(pile, false);
p = p->GetNext(); // returns to the interrupted operation
}
if (p != nullptr) p->RestoreState(pile, true);
}

View File

@ -0,0 +1,74 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotListInstr class Compiles a list of instructions separated by
* semicolons eg : ... ; ... ; ... ; ... ;
*/
class CBotListInstr : public CBotInstr
{
public:
/*!
* \brief CBotListInstr
*/
CBotListInstr();
/*!
* \brief ~CBotListInstr
*/
~CBotListInstr();
/*!
* \brief Compile
* \param p
* \param pStack
* \param bLocal
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool bLocal = true);
/*!
* \brief Execute Executes a set of instructions.
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! Instructions to do.
CBotInstr* m_Instr;
};

View File

@ -0,0 +1,94 @@
/*
* 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 "CBot/CBotInstr/CBotLogicExpr.h"
#include "CBot/CBotStack.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotLogicExpr::CBotLogicExpr()
{
m_condition =
m_op1 =
m_op2 = nullptr; // nullptr to be able to delete without other
name = "CBotLogicExpr"; // debug
}
////////////////////////////////////////////////////////////////////////////////
CBotLogicExpr::~CBotLogicExpr()
{
delete m_condition;
delete m_op1;
delete m_op2;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotLogicExpr::Execute(CBotStack* &pStack)
{
CBotStack* pStk1 = pStack->AddStack(this); // adds an item to the stack
// or return in case of recovery
// if ( pStk1 == EOX ) return true;
if ( pStk1->GetState() == 0 )
{
if ( !m_condition->Execute(pStk1) ) return false;
if (!pStk1->SetState(1)) return false;
}
if ( pStk1->GetVal() == true )
{
if ( !m_op1->Execute(pStk1) ) return false;
}
else
{
if ( !m_op2->Execute(pStk1) ) return false;
}
return pStack->Return(pStk1); // transmits the result
}
////////////////////////////////////////////////////////////////////////////////
void CBotLogicExpr::RestoreState(CBotStack* &pStack, bool bMain)
{
if ( !bMain ) return;
CBotStack* pStk1 = pStack->RestoreStack(this); // adds an item to the stack
if ( pStk1 == nullptr ) return;
if ( pStk1->GetState() == 0 )
{
m_condition->RestoreState(pStk1, bMain);
return;
}
if ( pStk1->GetVal() == true )
{
m_op1->RestoreState(pStk1, bMain);
}
else
{
m_op2->RestoreState(pStk1, bMain);
}
}

View File

@ -0,0 +1,70 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotLogicExpr class
*/
class CBotLogicExpr : public CBotInstr
{
public:
/*!
* \brief CBotLogicExpr
*/
CBotLogicExpr();
/*!
* \brief ~CBotLogicExpr
*/
~CBotLogicExpr();
/*!
* \brief Execute
* \param pStack
* \return
*/
bool Execute(CBotStack* &pStack) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! Test to evaluate
CBotInstr* m_condition;
//! Left element
CBotInstr* m_op1;
//! Right element
CBotInstr* m_op2;
friend class CBotTwoOpExpr;
};

View File

@ -0,0 +1,249 @@
/*
* 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 "CBot/CBotInstr/CBotNew.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotClass.h"
#include "CBot/CBotInstr/CBotInstrUtils.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotNew::CBotNew()
{
name = "CBotNew";
m_Parameters = nullptr;
m_nMethodeIdent = 0;
}
////////////////////////////////////////////////////////////////////////////////
CBotNew::~CBotNew()
{
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotNew::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotToken* pp = p;
if (!IsOfType(p, ID_NEW)) return nullptr;
// verifies that the token is a class name
if (p->GetType() != TokenTypVar) return nullptr;
CBotClass* pClass = CBotClass::Find(p);
if (pClass == nullptr)
{
pStack->SetError(TX_BADNEW, p);
return nullptr;
}
CBotNew* inst = new CBotNew();
inst->SetToken(pp);
inst->m_vartoken = p;
p = p->GetNext();
// creates the object on the "job"
// with a pointer to the object
CBotVar* pVar = CBotVar::Create("", pClass);
// do the call of the creator
CBotCStack* pStk = pStack->TokenStack();
{
// check if there are parameters
CBotVar* ppVars[1000];
inst->m_Parameters = CompileParams(p, pStk, ppVars);
if (!pStk->IsOk()) goto error;
// constructor exist?
CBotTypResult r = pClass->CompileMethode(pClass->GetName(), pVar, ppVars, pStk, inst->m_nMethodeIdent);
delete pStk->TokenStack(); // release extra stack
int typ = r.GetType();
// if there is no constructor, and no parameters either, it's ok
if (typ == TX_UNDEFCALL && inst->m_Parameters == nullptr) typ = 0;
pVar->SetInit(CBotVar::InitType::DEF); // mark the instance as init
if (typ>20)
{
pStk->SetError(typ, inst->m_vartoken.GetEnd());
goto error;
}
// if the constructor does not exist, but there are parameters
if (typ<0 && inst->m_Parameters != nullptr)
{
pStk->SetError(TX_NOCONST, &inst->m_vartoken);
goto error;
}
// makes pointer to the object on the stack
pStk->SetVar(pVar);
return pStack->Return(inst, pStk);
}
error:
delete inst;
return pStack->Return(nullptr, pStk);
}
////////////////////////////////////////////////////////////////////////////////
bool CBotNew::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this); //main stack
if (pile->IfStep()) return false;
CBotStack* pile1 = pj->AddStack2(); //secondary stack
CBotVar* pThis = nullptr;
CBotToken* pt = &m_vartoken;
CBotClass* pClass = CBotClass::Find(pt);
// create the variable "this" pointer type to the stack
if ( pile->GetState()==0)
{
// create an instance of the requested class
// and initialize the pointer to that object
pThis = CBotVar::Create("this", pClass);
pThis->SetUniqNum(-2) ;
pile1->SetVar(pThis); // place on stack1
pile->IncState();
}
// fetch the this pointer if it was interrupted
if ( pThis == nullptr)
{
pThis = pile1->GetVar(); // find the pointer
}
// is there an assignment or parameters (constructor)
if ( pile->GetState()==1)
{
// evaluates the constructor of the instance
CBotVar* ppVars[1000];
CBotStack* pile2 = pile;
int i = 0;
CBotInstr* p = m_Parameters;
// evaluate the parameters
// and places the values on the stack
// to be interrupted at any time
if (p != nullptr) while ( true)
{
pile2 = pile2->AddStack(); // space on the stack for the result
if (pile2->GetState() == 0)
{
if (!p->Execute(pile2)) return false; // interrupted here?
pile2->SetState(1);
}
ppVars[i++] = pile2->GetVar();
p = p->GetNext();
if ( p == nullptr) break;
}
ppVars[i] = nullptr;
// create a variable for the result
CBotVar* pResult = nullptr; // constructos still void
if ( !pClass->ExecuteMethode(m_nMethodeIdent, pClass->GetName(),
pThis, ppVars,
pResult, pile2, GetToken())) return false; // interrupt
pThis->ConstructorSet(); // indicates that the constructor has been called
}
return pj->Return(pile1); // passes below
}
////////////////////////////////////////////////////////////////////////////////
void CBotNew::RestoreState(CBotStack* &pj, bool bMain)
{
if (!bMain) return;
CBotStack* pile = pj->RestoreStack(this); //primary stack
if (pile == nullptr) return;
CBotStack* pile1 = pj->AddStack2(); //secondary stack
CBotToken* pt = &m_vartoken;
CBotClass* pClass = CBotClass::Find(pt);
// create the variable "this" pointer type to the object
if ( pile->GetState()==0)
{
return;
}
CBotVar* pThis = pile1->GetVar(); // find the pointer
pThis->SetUniqNum(-2);
// is ther an assignment or parameters (constructor)
if ( pile->GetState()==1)
{
// evaluates the constructor of the instance
CBotVar* ppVars[1000];
CBotStack* pile2 = pile;
int i = 0;
CBotInstr* p = m_Parameters;
// evaluate the parameters
// and places the values on the stack
// to be interrupted at any time
if (p != nullptr) while ( true)
{
pile2 = pile2->RestoreStack(); // space on the stack for the result
if (pile2 == nullptr) return;
if (pile2->GetState() == 0)
{
p->RestoreState(pile2, bMain); // interrupt here!
return;
}
ppVars[i++] = pile2->GetVar();
p = p->GetNext();
if ( p == nullptr) break;
}
ppVars[i] = nullptr;
pClass->RestoreMethode(m_nMethodeIdent, m_vartoken.GetString(), pThis,
ppVars, pile2) ; // interrupt here!
}
}

View File

@ -0,0 +1,75 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotNew class Compile an instruction "new".
*/
class CBotNew : public CBotInstr
{
public:
/*!
* \brief CBotNew
*/
CBotNew();
/*!
* \brief ~CBotNew
*/
~CBotNew();
/*!
* \brief Compile
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute Executes instruction "new".
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
//! The parameters to be evaluated
CBotInstr* m_Parameters;
long m_nMethodeIdent;
CBotToken m_vartoken;
};

View File

@ -0,0 +1,193 @@
/*
* 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 "CBot/CBotInstr/CBotParExpr.h"
#include "CBot/CBotInstr/CBotExprUnaire.h"
#include "CBot/CBotInstr/CBotExprVar.h"
#include "CBot/CBotInstr/CBotInstrCall.h"
#include "CBot/CBotInstr/CBotPostIncExpr.h"
#include "CBot/CBotInstr/CBotPreIncExpr.h"
#include "CBot/CBotInstr/CBotExprNum.h"
#include "CBot/CBotInstr/CBotExprAlpha.h"
#include "CBot/CBotInstr/CBotExprBool.h"
#include "CBot/CBotInstr/CBotNew.h"
#include "CBot/CBotInstr/CBotExprNull.h"
#include "CBot/CBotInstr/CBotExprNan.h"
#include "CBot/CBotInstr/CBotExpression.h"
#include "CBot/CBotVar/CBotVar.h"
#include "CBot/CBotCStack.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotCStack* pStk = pStack->TokenStack();
pStk->SetStartError(p->GetStart());
// is it an expression in parentheses?
if (IsOfType(p, ID_OPENPAR))
{
CBotInstr* inst = CBotExpression::Compile(p, pStk);
if (nullptr != inst)
{
if (IsOfType(p, ID_CLOSEPAR))
{
return pStack->Return(inst, pStk);
}
pStk->SetError(TX_CLOSEPAR, p->GetStart());
}
delete inst;
return pStack->Return(nullptr, pStk);
}
// is this a unary operation?
CBotInstr* inst = CBotExprUnaire::Compile(p, pStk);
if (inst != nullptr || !pStk->IsOk())
return pStack->Return(inst, pStk);
// is it a variable name?
if (p->GetType() == TokenTypVar)
{
// this may be a method call without the "this." before
inst = CBotExprVar::CompileMethode(p, pStk);
if (inst != nullptr) return pStack->Return(inst, pStk);
// is it a procedure call?
inst = CBotInstrCall::Compile(p, pStk);
if (inst != nullptr || !pStk->IsOk())
return pStack->Return(inst, pStk);
CBotToken* pvar = p;
// no, it an "ordinaty" variable
inst = CBotExprVar::Compile(p, pStk);
CBotToken* pp = p;
// post incremented or decremented?
if (IsOfType(p, ID_INC, ID_DEC))
{
if (pStk->GetType() >= CBotTypBoolean)
{
pStk->SetError(TX_BADTYPE, pp);
delete inst;
return pStack->Return(nullptr, pStk);
}
// recompile the variable for read-only
delete inst;
p = pvar;
inst = CBotExprVar::Compile(p, pStk, PR_READ);
p = p->GetNext();
CBotPostIncExpr* i = new CBotPostIncExpr();
i->SetToken(pp);
i->m_Instr = inst; // associated statement
return pStack->Return(i, pStk);
}
return pStack->Return(inst, pStk);
}
// pre increpemted or pre decremented?
CBotToken* pp = p;
if (IsOfType(p, ID_INC, ID_DEC))
{
CBotPreIncExpr* i = new CBotPreIncExpr();
i->SetToken(pp);
if (p->GetType() == TokenTypVar)
{
if (nullptr != (i->m_Instr = CBotExprVar::Compile(p, pStk, PR_READ)))
{
if (pStk->GetType() >= CBotTypBoolean)
{
pStk->SetError(TX_BADTYPE, pp);
delete inst;
return pStack->Return(nullptr, pStk);
}
return pStack->Return(i, pStk);
}
delete i;
return pStack->Return(nullptr, pStk);
}
}
// is it a number or DefineNum?
if (p->GetType() == TokenTypNum ||
p->GetType() == TokenTypDef )
{
CBotInstr* inst = CBotExprNum::Compile(p, pStk);
return pStack->Return(inst, pStk);
}
// is this a chaine?
if (p->GetType() == TokenTypString)
{
CBotInstr* inst = CBotExprAlpha::Compile(p, pStk);
return pStack->Return(inst, pStk);
}
// is a "true" or "false"
if (p->GetType() == ID_TRUE ||
p->GetType() == ID_FALSE )
{
CBotInstr* inst = CBotExprBool::Compile(p, pStk);
return pStack->Return(inst, pStk);
}
// is an object to be created with new
if (p->GetType() == ID_NEW)
{
CBotInstr* inst = CBotNew::Compile(p, pStk);
return pStack->Return(inst, pStk);
}
// is a null pointer
if (IsOfType(p, ID_NULL))
{
CBotInstr* inst = new CBotExprNull ();
inst->SetToken(pp);
CBotVar* var = CBotVar::Create("", CBotTypNullPointer);
pStk->SetVar(var);
return pStack->Return(inst, pStk);
}
// is a number nan
if (IsOfType(p, ID_NAN))
{
CBotInstr* inst = new CBotExprNan ();
inst->SetToken(pp);
CBotVar* var = CBotVar::Create("", CBotTypInt);
var->SetInit(CBotVar::InitType::IS_NAN);
pStk->SetVar(var);
return pStack->Return(inst, pStk);
}
return pStack->Return(nullptr, pStk);
}

View File

@ -0,0 +1,62 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
// possibly an expression in parentheses ( ... )
// there is never an instance of this class
// being the object returned inside the parenthesis
////////////////////////////////////////////////////////////////////////////////
// compile either:
// instruction in parentheses (...)
// a unary expression (negative, not)
// variable name
// variables pre and post-incremented or decremented
// a given number DefineNum
// a constant
// procedure call
// new statement
//
// this class has no constructor, because there is never an instance of this class
// the object returned by Compile is the class corresponding to the instruction
////////////////////////////////////////////////////////////////////////////////
/*!
* \brief The CBotParExpr class
*/
class CBotParExpr : public CBotInstr
{
public:
/*!
* \brief Compile
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
};

View File

@ -0,0 +1,90 @@
/*
* 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 "CBot/CBotInstr/CBotPostIncExpr.h"
#include "CBot/CBotInstr/CBotExprVar.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotPostIncExpr::CBotPostIncExpr()
{
m_Instr = nullptr;
name = "CBotPostIncExpr";
}
////////////////////////////////////////////////////////////////////////////////
CBotPostIncExpr::~CBotPostIncExpr()
{
delete m_Instr;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotPostIncExpr::Execute(CBotStack* &pj)
{
CBotStack* pile1 = pj->AddStack(this);
CBotStack* pile2 = pile1;
CBotVar* var1 = nullptr;
// retrieves the variable fields and indexes according
if (!(static_cast<CBotExprVar*>(m_Instr))->ExecuteVar(var1, pile2, nullptr, true)) return false;
pile1->SetState(1);
pile1->SetCopyVar(var1); // places the result (before incrementation);
CBotStack* pile3 = pile2->AddStack(this);
if (pile3->IfStep()) return false;
if (var1->IsNAN())
{
pile1->SetError(TX_OPNAN, &m_token);
}
if (!var1->IsDefined())
{
pile1->SetError(TX_NOTINIT, &m_token);
}
if (GetTokenType() == ID_INC) var1->Inc();
else var1->Dec();
return pj->Return(pile1); // operation done, result on pile2
}
////////////////////////////////////////////////////////////////////////////////
void CBotPostIncExpr::RestoreState(CBotStack* &pj, bool bMain)
{
if (!bMain) return;
CBotStack* pile1 = pj->RestoreStack(this);
if (pile1 == nullptr) return;
(static_cast<CBotExprVar*>(m_Instr))->RestoreStateVar(pile1, bMain);
if (pile1 != nullptr) pile1->RestoreStack(this);
}

View File

@ -0,0 +1,69 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
//////////////////////////////////////////////////////////////////////////////////////
// Management of pre-and post increment / decrement
// There is no routine Compiles, the object is created directly
// Compiles in CBotParExpr ::
/*!
* \brief The CBotPostIncExpr class
*/
class CBotPostIncExpr : public CBotInstr
{
public:
/*!
* \brief CBotPostIncExpr
*/
CBotPostIncExpr();
/*!
* \brief ~CBotPostIncExpr
*/
~CBotPostIncExpr();
/*!
* \brief Execute
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
CBotInstr* m_Instr;
friend class CBotParExpr;
};

View File

@ -0,0 +1,97 @@
/*
* 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 "CBot/CBotInstr/CBotPreIncExpr.h"
#include "CBot/CBotInstr/CBotExprVar.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotVar/CBotVar.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotPreIncExpr::CBotPreIncExpr()
{
m_Instr = nullptr;
name = "CBotPreIncExpr";
}
////////////////////////////////////////////////////////////////////////////////
CBotPreIncExpr::~CBotPreIncExpr()
{
delete m_Instr;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotPreIncExpr::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this);
if (pile->IfStep()) return false;
CBotVar* var1;
if (pile->GetState() == 0)
{
CBotStack* pile2 = pile;
// retrieves the variable fields and indexes according
// pile2 is modified on return
if (!(static_cast<CBotExprVar*>(m_Instr))->ExecuteVar(var1, pile2, nullptr, true)) return false;
if (var1->IsNAN())
{
pile->SetError(TX_OPNAN, &m_token);
return pj->Return(pile); // operation performed
}
if (!var1->IsDefined())
{
pile->SetError(TX_NOTINIT, &m_token);
return pj->Return(pile); // operation performed
}
if (GetTokenType() == ID_INC) var1->Inc();
else var1->Dec(); // ((CBotVarInt*)var1)->m_val
pile->IncState();
}
if (!m_Instr->Execute(pile)) return false;
return pj->Return(pile); // operation performed
}
////////////////////////////////////////////////////////////////////////////////
void CBotPreIncExpr::RestoreState(CBotStack* &pj, bool bMain)
{
if (!bMain) return;
CBotStack* pile = pj->RestoreStack(this);
if (pile == nullptr) return;
if (pile->GetState() == 0)
{
return;
}
m_Instr->RestoreState(pile, bMain);
}

View File

@ -0,0 +1,65 @@
/*
* 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/CBotInstr/CBotInstr.h"
// Local include
// Global include
/*!
* \brief The CBotPreIncExpr class Management of pre increment. There is no
* routine Compiles, the object is created directly. Compiles in CBotParExpr
*/
class CBotPreIncExpr : public CBotInstr
{
public:
/*!
* \brief CBotPreIncExpr
*/
CBotPreIncExpr();
/*!
* \brief ~CBotPreIncExpr
*/
~CBotPreIncExpr();
/*!
* \brief Execute
* \param pj
* \return
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
* \param pj
* \param bMain
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
private:
CBotInstr* m_Instr;
friend class CBotParExpr;
};

View File

@ -0,0 +1,116 @@
/*
* 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 "CBot/CBotInstr/CBotReturn.h"
#include "CBot/CBotInstr/CBotInstrUtils.h"
#include "CBot/CBotInstr/CBotExpression.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
// Local include
// Global include
////////////////////////////////////////////////////////////////////////////////
CBotReturn::CBotReturn()
{
m_Instr = nullptr;
name = "CBotReturn"; // debug
}
////////////////////////////////////////////////////////////////////////////////
CBotReturn::~CBotReturn()
{
delete m_Instr;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotReturn::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotToken* pp = p;
if (!IsOfType(p, ID_RETURN)) return nullptr; // should never happen
CBotReturn* inst = new CBotReturn(); // creates the object
inst->SetToken( pp );
CBotTypResult type = pStack->GetRetType();
if ( type.GetType() == 0 ) // returned void ?
{
if ( IsOfType( p, ID_SEP ) ) return inst;
pStack->SetError( TX_BADTYPE, pp );
return nullptr;
}
inst->m_Instr = CBotExpression::Compile(p, pStack);
if ( pStack->IsOk() )
{
CBotTypResult retType = pStack->GetTypResult(2);
if (TypeCompatible(retType, type, ID_ASS))
{
if ( IsOfType( p, ID_SEP ) )
return inst;
pStack->SetError(TX_ENDOF, p->GetStart());
}
pStack->SetError(TX_BADTYPE, p->GetStart());
}
delete inst;
return nullptr; // no object, the error is on the stack
}
////////////////////////////////////////////////////////////////////////////////
bool CBotReturn::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this);
// if ( pile == EOX ) return true;
if ( pile->GetState() == 0 )
{
if ( m_Instr != nullptr && !m_Instr->Execute(pile) ) return false; // evaluate the result
// the result is on the stack
pile->IncState();
}
if ( pile->IfStep() ) return false;
pile->SetBreak(3, CBotString());
return pj->Return(pile);
}
////////////////////////////////////////////////////////////////////////////////
void CBotReturn::RestoreState(CBotStack* &pj, bool bMain)
{
if ( !bMain ) return;
CBotStack* pile = pj->RestoreStack(this);
if ( pile == nullptr ) return;
if ( pile->GetState() == 0 )
{
if ( m_Instr != nullptr ) m_Instr->RestoreState(pile, bMain); // evaluate the result
return;
}
}

Some files were not shown because too many files have changed in this diff Show More