Documentation for CBotProgram; some CBotError refactoring

dev-time-step
krzys-h 2015-12-21 21:35:20 +01:00
parent 6fee1ee12b
commit eedf8dacea
24 changed files with 323 additions and 275 deletions

View File

@ -245,7 +245,7 @@ fund:
CBotStack* pile2 = pile->AddStack();
pile2->SetVar( pResult );
pile->SetError(0, token); // for the position on error + away
pile->SetError(CBotNoErr, token); // for the position on error + away
return pt->Run( pStack );
#endif
@ -292,14 +292,14 @@ bool CBotCall::Run(CBotStack* pStack)
CBotVar* pResult = pile2->GetVar();
CBotVar* pRes = pResult;
int Exception = 0;
int Exception = 0; // TODO: change this to CBotError
int res = m_rExec(pVar, pResult, Exception, pStack->GetPUser());
if (res == false)
{
if (Exception!=0)
{
pStack->SetError(Exception);
pStack->SetError(static_cast<CBotError>(Exception));
}
if ( pResult != pRes ) delete pResult; // different result if made
return false;

View File

@ -126,7 +126,7 @@ int CBotCallMethode::DoCall(long& nIdent,
// then calls the routine external to the module
int Exception = 0;
int Exception = 0; // TODO: Change this to CBotError
int res = pt->m_rExec(pThis, pVar, pResult, Exception, pStack->GetPUser());
pStack->SetVar(pResult);
@ -135,7 +135,7 @@ int CBotCallMethode::DoCall(long& nIdent,
if (Exception!=0)
{
// pStack->SetError(Exception, pVar->GetToken());
pStack->SetError(Exception, pToken);
pStack->SetError(static_cast<CBotError>(Exception), pToken);
}
delete pVarToDelete;
return false;
@ -157,7 +157,7 @@ int CBotCallMethode::DoCall(long& nIdent,
CBotVar* pVar = MakeListVars(ppVars, true);
CBotVar* pVarToDelete = pVar;
int Exception = 0;
int Exception = 0; // TODO: Change this to CBotError
int res = pt->m_rExec(pThis, pVar, pResult, Exception, pStack->GetPUser());
pStack->SetVar(pResult);
@ -166,7 +166,7 @@ int CBotCallMethode::DoCall(long& nIdent,
if (Exception!=0)
{
// pStack->SetError(Exception, pVar->GetToken());
pStack->SetError(Exception, pToken);
pStack->SetError(static_cast<CBotError>(Exception), pToken);
}
delete pVarToDelete;
return false;

View File

@ -286,7 +286,7 @@ bool CBotExprVar::ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* prevToke
pVar = pj->FindVar(m_nIdent, true); // tries with the variable update if necessary
if (pVar == nullptr)
{
pj->SetError(1, &m_token);
pj->SetError(static_cast<CBotError>(1), &m_token); // TODO: yeah, don't care that this exception doesn't exist ~krzys_h
return false;
}
if ( m_next3 != nullptr &&

View File

@ -380,7 +380,7 @@ bool CBotFunction::Execute(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance)
if ( !m_Block->Execute(pile) )
{
if ( pile->GetError() < 0 )
pile->SetError( 0 );
pile->SetError( CBotNoErr );
else
return false;
}

View File

@ -222,7 +222,7 @@ bool CBotLeftExpr::ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevT
pVar = pile->FindVar(m_nIdent);
if (pVar == nullptr)
{
pile->SetError(2, &m_token);
pile->SetError(static_cast<CBotError>(2), &m_token); // TODO: yup, another unknown error ~krzys_h
return false;
}

View File

@ -83,7 +83,7 @@ bool CBotThrow::Execute(CBotStack* &pj)
int val = pile->GetVal();
if ( val < 0 ) val = CBotErrBadThrow;
pile->SetError( val, &m_token );
pile->SetError( static_cast<CBotError>(val), &m_token );
return pj->Return( pile );
}

View File

@ -109,7 +109,7 @@ bool CBotTry::Execute(CBotStack* &pj)
pile1->IncState();
pile2->SetState(val); // stores the error number
pile1->SetError(0); // for now there is are more errors!
pile1->SetError(CBotNoErr); // for now there is are more errors!
if ( val == 0 && CBotStack::m_initimer < 0 ) // mode step?
return false; // does not make the catch
@ -158,7 +158,7 @@ bool CBotTry::Execute(CBotStack* &pj)
if (!m_FinalInst->Execute(pile2) && pile2->IsOk()) return false;
if (!pile2->IsOk()) return pj->Return(pile2); // keep this exception
pile2->SetError(pile1->GetState()==-1 ? val : 0); // gives the initial error
pile2->SetError(pile1->GetState()==-1 ? static_cast<CBotError>(val) : CBotNoErr); // gives the initial error
return pj->Return(pile2);
}
@ -167,7 +167,7 @@ bool CBotTry::Execute(CBotStack* &pj)
if ( val != 0 && m_ListCatch == nullptr && m_FinalInst == nullptr )
return pj->Return(pile2); // ends the try without exception
pile1->SetError(val); // gives the error
pile1->SetError(static_cast<CBotError>(val)); // gives the error
return false; // it's not for us
}

View File

@ -287,7 +287,7 @@ bool VarIsNAN(const CBotVar* var)
return var->GetInit() > CBotVar::InitType::DEF;
}
bool IsNan(CBotVar* left, CBotVar* right, int* err = nullptr)
bool IsNan(CBotVar* left, CBotVar* right, CBotError* err = nullptr)
{
if ( VarIsNAN(left) || VarIsNAN(right) )
{
@ -394,7 +394,7 @@ bool CBotTwoOpExpr::Execute(CBotStack* &pStack)
if ( TypeRes == CBotTypClass ) temp = CBotVar::Create( static_cast<CBotToken*>(nullptr), CBotTypResult(CBotTypIntrinsic, type1.GetClass() ) );
else temp = CBotVar::Create( static_cast<CBotToken*>(nullptr), TypeRes );
int err = 0;
CBotError err = CBotNoErr;
// is a operation according to request
CBotVar* left = pStk1->GetVar();
CBotVar* right = pStk2->GetVar();

View File

@ -47,7 +47,7 @@ CBotProgram::CBotProgram()
m_pStack = nullptr;
m_pInstance = nullptr;
m_ErrorCode = 0;
m_ErrorCode = CBotNoErr;
m_Ident = 0;
}
@ -60,7 +60,7 @@ CBotProgram::CBotProgram(CBotVar* pInstance)
m_pStack = nullptr;
m_pInstance = pInstance;
m_ErrorCode = 0;
m_ErrorCode = CBotNoErr;
m_Ident = 0;
}
@ -82,7 +82,7 @@ CBotProgram::~CBotProgram()
}
////////////////////////////////////////////////////////////////////////////////
bool CBotProgram::Compile(const std::string& program, std::vector<std::string>& ListFonctions, void* pUser)
bool CBotProgram::Compile(const std::string& program, std::vector<std::string>& functions, void* pUser)
{
int error = 0;
Stop();
@ -93,8 +93,8 @@ bool CBotProgram::Compile(const std::string& program, std::vector<std::string>&
m_pClass = nullptr;
delete m_Prog; m_Prog= nullptr;
ListFonctions.clear();
m_ErrorCode = 0;
functions.clear();
m_ErrorCode = CBotNoErr;
// transforms the program in Tokens
CBotToken* pBaseToken = CBotToken::CompileTokens(program, error);
@ -154,7 +154,7 @@ bool CBotProgram::Compile(const std::string& program, std::vector<std::string>&
{
m_bCompileClass = false;
CBotFunction::Compile(p, pStack, next);
if (next->IsExtern()) ListFonctions.push_back(next->GetName()/* + next->GetParams()*/);
if (next->IsExtern()) functions.push_back(next->GetName()/* + next->GetParams()*/);
next->m_pProg = this; // keeps pointers to the module
next = next->Next();
}
@ -233,7 +233,7 @@ bool CBotProgram::Run(void* pUser, int timer)
if (m_pStack == nullptr || m_pRun == nullptr) goto error;
m_ErrorCode = 0;
m_ErrorCode = CBotNoErr;
m_pStack->Reset(pUser); // empty the possible previous error, and resets the timer
if ( timer >= 0 ) m_pStack->SetTimer(timer);
@ -286,23 +286,23 @@ void CBotProgram::Stop()
}
////////////////////////////////////////////////////////////////////////////////
bool CBotProgram::GetRunPos(std::string& FunctionName, int& start, int& end)
bool CBotProgram::GetRunPos(std::string& functionName, int& start, int& end)
{
FunctionName = nullptr;
functionName = nullptr;
start = end = 0;
if (m_pStack == nullptr) return false;
m_pStack->GetRunPos(FunctionName, start, end);
m_pStack->GetRunPos(functionName, start, end);
return true;
}
////////////////////////////////////////////////////////////////////////////////
CBotVar* CBotProgram::GetStackVars(std::string& FunctionName, int level)
CBotVar* CBotProgram::GetStackVars(std::string& functionName, int level)
{
FunctionName = nullptr;
functionName.clear();
if (m_pStack == nullptr) return nullptr;
return m_pStack->GetStackVars(FunctionName, level);
return m_pStack->GetStackVars(functionName, level);
}
////////////////////////////////////////////////////////////////////////////////
@ -312,7 +312,7 @@ void CBotProgram::SetTimer(int n)
}
////////////////////////////////////////////////////////////////////////////////
int CBotProgram::GetError()
CBotError CBotProgram::GetError()
{
return m_ErrorCode;
}
@ -330,7 +330,7 @@ long CBotProgram::GetIdent()
}
////////////////////////////////////////////////////////////////////////////////
bool CBotProgram::GetError(int& code, int& start, int& end)
bool CBotProgram::GetError(CBotError& code, int& start, int& end)
{
code = m_ErrorCode;
start = m_ErrorStart;
@ -339,7 +339,7 @@ bool CBotProgram::GetError(int& code, int& start, int& end)
}
////////////////////////////////////////////////////////////////////////////////
bool CBotProgram::GetError(int& code, int& start, int& end, CBotProgram* &pProg)
bool CBotProgram::GetError(CBotError& code, int& start, int& end, CBotProgram*& pProg)
{
code = m_ErrorCode;
start = m_ErrorStart;
@ -348,20 +348,6 @@ bool CBotProgram::GetError(int& code, int& start, int& end, CBotProgram* &pProg)
return code > 0;
}
////////////////////////////////////////////////////////////////////////////////
std::string CBotProgram::GetErrorText(int code)
{
std::string TextError = LoadString(static_cast<EID>(code));
if (TextError.empty())
{
char buf[100];
sprintf(buf, "Exception numéro %d.", code);
TextError = buf;
}
return TextError;
}
////////////////////////////////////////////////////////////////////////////////
CBotFunction* CBotProgram::GetFunctions()
{
@ -472,18 +458,18 @@ int CBotProgram::GetVersion()
////////////////////////////////////////////////////////////////////////////////
void CBotProgram::Init()
{
CBotToken::DefineNum("CBotErrZeroDiv", CBotErrZeroDiv); // division by zero
CBotToken::DefineNum("CBotErrNotInit", CBotErrNotInit); // uninitialized variable
CBotToken::DefineNum("CBotErrBadThrow", CBotErrBadThrow); // throw a negative value
CBotToken::DefineNum("CBotErrNoRetVal", CBotErrNoRetVal); // function did not return results
CBotToken::DefineNum("CBotErrNoRun", CBotErrNoRun); // active Run () without a function // TODO: Is this actually a runtime error?
CBotToken::DefineNum("CBotErrUndefFunc", CBotErrUndefFunc); // Calling a function that no longer exists
CBotToken::DefineNum("CBotErrNotClass", CBotErrNotClass); // Class no longer exists
CBotToken::DefineNum("CBotErrNull", CBotErrNull); // Attempted to use a null pointer
CBotToken::DefineNum("CBotErrNan", CBotErrNan); // Can't do operations on nan
CBotToken::DefineNum("CBotErrOutArray", CBotErrOutArray); // Attempted access out of bounds of an array
CBotToken::DefineNum("CBotErrStackOver", CBotErrStackOver); // Stack overflow
CBotToken::DefineNum("CBotErrDeletedPtr", CBotErrDeletedPtr); // Attempted to use deleted object
CBotToken::DefineNum("CBotErrZeroDiv", CBotErrZeroDiv); // division by zero
CBotToken::DefineNum("CBotErrNotInit", CBotErrNotInit); // uninitialized variable
CBotToken::DefineNum("CBotErrBadThrow", CBotErrBadThrow); // throw a negative value
CBotToken::DefineNum("CBotErrNoRetVal", CBotErrNoRetVal); // function did not return results
CBotToken::DefineNum("CBotErrNoRun", CBotErrNoRun); // active Run () without a function // TODO: Is this actually a runtime error?
CBotToken::DefineNum("CBotErrUndefFunc", CBotErrUndefFunc); // Calling a function that no longer exists
CBotToken::DefineNum("CBotErrNotClass", CBotErrNotClass); // Class no longer exists
CBotToken::DefineNum("CBotErrNull", CBotErrNull); // Attempted to use a null pointer
CBotToken::DefineNum("CBotErrNan", CBotErrNan); // Can't do operations on nan
CBotToken::DefineNum("CBotErrOutArray", CBotErrOutArray); // Attempted access out of bounds of an array
CBotToken::DefineNum("CBotErrStackOver", CBotErrStackOver); // Stack overflow
CBotToken::DefineNum("CBotErrDeletedPtr", CBotErrDeletedPtr); // Attempted to use deleted object
CBotProgram::AddFunction("sizeof", rSizeOf, cSizeOf );

View File

@ -19,205 +19,286 @@
#pragma once
// Modules inlcude
#include "CBot/CBotTypResult.h"
#include "CBot/CBotEnums.h"
// Local include
// Global include
#include <vector>
// Forward declaration
class CBotFunction;
class CBotClass;
class CBotStack;
class CBotVar;
/*!
* \brief The CBotProgram class Main class managing CBot program.
/**
* \brief Class that manages a CBot program. This is the main entry point into the CBot engine.
*
* \section Init Engine initialization / destruction
* To initialize the CBot engine, call CBotProgram::Init(). This function should be only called once.
*
* Afterwards, you can start defining custom functions, constants and classes. See:
* * CBotProgram::AddFunction()
* * CBotProgram::DefineNum()
* * CBotClass::Create()
*
* Next, compile and run programs.
* * Compile()
* * Start()
* * Run()
* * Stop()
*
* After you are finished, free the memory used by the CBot engine by calling CBotProgram::Free().
*
* \section Example Example usage
* \code
* // Initialize the engine
* CBotProgram::Init();
*
* // Add some standard functions
* CBotProgram::AddFunction("message", rMessage, cMessage);
*
* // Compile the program
* std::vector<std::string> externFunctions;
* CBotProgram* program = new CBotProgram();
* bool ok = program->Compile(code.c_str(), externFunctions, nullptr);
* if (!ok)
* {
* CBotError error;
* int cursor1, cursor2;
* program->GetError(error, cursor1, cursor2);
* // Handle the error
* }
*
* // Run the program
* program->Start(externFunctions[0]);
* while (!program->Run());
*
* // Cleanup
* CBotProgram::Free();
* \endcode
*/
class CBotProgram
{
public:
/*!
* \brief CBotProgram
/**
* \brief Constructor
*/
CBotProgram();
/*!
* \brief CBotProgram
* \param pInstance
/**
* \brief Constructor
* \param pInstance Variable to pass to the program as "this"
*/
CBotProgram(CBotVar* pInstance);
/*!
* \brief ~CBotProgram
/**
* \brief Destructor
*/
~CBotProgram();
/*!
* \brief Init Initializes the module (defined keywords for errors) should
* be done once (and only one) at the beginning.
/**
* \brief Initializes the module, should be done once (and only once) at the beginning
*/
static void Init();
/*!
* \brief Free Frees the static memory areas.
/**
* \brief Frees the static memory areas
*/
static void Free();
/*!
* \brief GetVersion Gives the version of the library CBOT.
* \return
/**
* \brief Returns version of the CBot library
* \return A number representing the current library version
*/
static int GetVersion();
/*!
* \brief Compile compiles the program given in text.
* \param program
* \param ListFonctions Returns the names of functions declared as extern.
* \param pUser Can pass a pointer to routines defined by AddFunction.
* \return false if an error at compile.
* \see GetCompileError() to retrieve the error.
/**
* \brief Compile compiles the program given as string
* \param program Code to compile
* \param[out] functions Returns the names of functions declared as extern
* \param pUser Optional pointer to be passed to compile function (see AddFunction())
* \return true if compilation is successful, false if an compilation error occurs
* \see GetError() to retrieve the error
*/
bool Compile(const std::string& program, std::vector<std::string>& ListFonctions, void* pUser = nullptr);
bool Compile(const std::string& program, std::vector<std::string>& functions, void* pUser = nullptr);
/*!
* \brief SetIdent Associates an identifier with the instance CBotProgram.
* \param n
/**
* \brief Associates an identifier with this instance of CBotProgram
*/
void SetIdent(long n);
/*!
* \brief GetIdent Gives the identifier.
* \return
/**
* \brief Returns the identifier
* \see SetIdent
*/
long GetIdent();
/*!
* \brief GetError
* \return
/**
* \brief Returns the last error
* \return Error code
* \see GetError(CBotError&, int&, int&) for error location in the code
*/
int GetError();
CBotError GetError();
/*!
* \brief GetError
* \param code
* \param start
* \param end
* \return
/**
* \brief Returns the last error
* \param[out] code Error code
* \param[out] start Starting position in the code string of this error
* \param[out] end Ending position in the code string of this error
* \return false if no error has occured
*/
bool GetError(int& code, int& start, int& end);
bool GetError(CBotError& code, int& start, int& end);
/*!
* \brief GetError
* \param code
* \param start Delimits the start block where the error occured.
* \param end Delimits the end block where the error occured.
* \param pProg Lets you know what "module" has produced runtime error.
* \return If true gives the error found in the compilation or execution.
/**
* \brief Returns the last error
* \param[out] code Error code
* \param[out] start Starting position in the code string of this error
* \param[out] end Ending position in the code string of this error
* \param[out] pProg Program that caused the error (TODO: This always returns "this"... what?)
* \return false if no error has occured
*/
bool GetError(int& code, int& start, int& end, CBotProgram* &pProg);
bool GetError(CBotError& code, int& start, int& end, CBotProgram*& pProg);
/*!
* \brief GetErrorText
* \param code
* \return
*/
static std::string GetErrorText(int code);
/*!
* \brief Start Defines what function should be executed. The program does
* nothing, we must call Run () for this.
* \param name
* \return false if the funtion name is not found
/**
* \brief Starts the program using given function as an entry point. The function must be declared as "extern"
* \param name Name of function to start
* \return true if the program was started, false if the function name is not found
* \see Compile() returns list of extern functions found in the code
*/
bool Start(const std::string& name);
/*!
* \brief Run Executes the program.
* \param pUser
* \param timer timer = 0 allows to advance step by step.
* \return false if the program was suspended, true if the program ended
* with or without error.
/**
* \brief Executes the program
* \param pUser Custom pointer to be passed to execute function (see AddFunction())
* \param timer
* \parblock
* * timer < 0 do nothing
* * timer >= 0 call SetTimer(int timer) before executing
* \parblockend
* \return true if the program execution finished, false if the program is suspended (you then have to call Run() again)
*/
bool Run(void* pUser = nullptr, int timer = -1);
/*!
* \brief GetRunPos Gives the position in the executing program
* \param FunctionName is a pointer made to the name of the function
* \param start start and end position in the text of the token processing
* \param end
/**
* \brief GetRunPos Gives the current position in the executing program
* \param[out] functionName Name of the currently executed function
* \param[out] start Starting position in the code string of currently executed instruction
* \param[out] end Ending position in the code string of currently executed instruction
* \return false if it is not running (program completion)
*/
bool GetRunPos(std::string& FunctionName, int& start, int& end);
bool GetRunPos(std::string& functionName, int& start, int& end);
/*!
* \brief GetStackVars provides the pointer to the variables on the
* execution stack level is an input parameter, 0 for the last level, -1,
* -2, etc. for the other levels the return value (CBotVar *) is a variable.
* that can be processed as the list of parameters received by a routine
* list (or nullptr)
* \param FunctionName gives the name of the function where are these
* variables. FunctionName == nullptr means that is more in a program
* (depending on level)
* \param level
* \return
/**
* \brief Provides the pointer to the variables on the execution stack
* \param[out] functionName Name of the function that this stack is part of
* \param level 0 for the last level, -1, -2 etc. for previous ones
* \return Variables on the given stack level. Process using CBotVar::GetNext(). If the stack level is invalid, returns nullptr.
*/
CBotVar* GetStackVars(std::string& FunctionName, int level);
CBotVar* GetStackVars(std::string& functionName, int level);
/*!
* \brief Stop stops execution of the program therefore quits "suspend" mode
/**
* \brief Stops execution of the program
*/
void Stop();
/*!
* \brief SetTimer defines the number of steps (parts of instructions) to
* done in Run() before rendering hand "false"
* \TODO avant de rendre la main "false"
* \param n
/**
* \brief Sets the number of steps (parts of instructions) to execute in Run() before suspending the program execution
* \param n new timer value
*
* FIXME: Seems to be currently kind of broken (see issue #410)
*/
static void SetTimer(int n);
//
//
/*!
* \brief AddFunction Call this to add externally a new function used
* by the program CBoT. See (**) at end of this file for more details.
* \param name
* \param rExec
* \param rCompile
* \return
/**
* \brief Add a function that can be called from CBot
*
* To define an external function, proceed as follows:
*
* 1. Define a function for compilation
*
* This function should take a list of function arguments (types only, no values!) and a user-defined void* pointer (can be passed in Compile()) as parameters, and return CBotTypResult.
*
* Usually, name of this function is prefixed with "c".
*
* The function should iterate through the provided parameter list and verify that they match.<br>
* If they don't, then return CBotTypResult with an appropariate error code (see ::CBotError).<br>
* If they do, return CBotTypResult with the function's return type
*
* \code
* CBotTypResult cMessage(CBotVar* &var, void* user)
* {
* if (var == nullptr) return CBotTypResult(CBotErrLowParam); // Not enough parameters
* if (var->GetType() != CBotTypString) return CBotTypResult(CBotErrBadString); // String expected
*
* var = var->GetNext(); // Get the next parameter
* if (var != nullptr) return CBotTypResult(CBotErrOverParam); // Too many parameters
*
* return CBotTypResult(CBotTypFloat); // This function returns float (it may depend on parameters given!)
* }
* \endcode
*
* 2. Define a function for execution
*
* This function should take:
* * a list of parameters
* * pointer to a result variable (a variable of type given at compilation time will be provided)
* * pointer to an exception variable
* * user-defined pointer (can be passed in Run())
*
* This function returns true if execution of this function is finished, or false to suspend the program and call this function again on next Run() cycle.
*
* Usually, execution functions are prefixed with "r".
*
* \code
* bool rMessage(CBotVar* var, CBotVar* result, int& exception, void* user)
* {
* std::string message = var->GetValString();
* std::cout << message << std::endl;
* return true; // Execution finished
* }
* \endcode
*
* 3. Call AddFunction() to register the function in the CBot engine
*
* \code
* AddFunction("message", rMessage, cMessage);
* \endcode
*
*
* \param name Name of the function
* \param rExec Execution function
* \param rCompile Compilation function
* \return true
*/
static bool AddFunction(const std::string& name,
bool rExec(CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
CBotTypResult rCompile(CBotVar*& pVar, void* pUser));
/*!
* \brief DefineNum
* \param name
* \param val
* \return
/**
* \brief Define a new constant
* \param name Name of the constant
* \param val Value of the constant
* \return true on success, false if unable to define (e.g. already defined)
*/
static bool DefineNum(const std::string& name, long val);
/*!
* \brief SaveState Backup the execution status in the file the file must
* have been opened with the fopen call this dll (\TODO this library??)
* if the system crashes
* \param pf
* \return
* \brief Save the current execution status into a file
* \param pf file handle
* \paramblock
* This file handle must have been opened by this library! Otherwise crashes on Windows
* TODO: Verify this
* \endparamblock
* \return true on success, false on write error
*/
bool SaveState(FILE* pf);
/*!
* \brief RestoreState Restores the state of execution from file the
* compiled program must obviously be the same.
* \param pf
* \return
* \brief Restore the execution state from a file
*
* The previous program code must be already recompiled to call this function
*
* \param pf file handle
* \return true on success, false on read error
*/
bool RestoreState(FILE* pf);
@ -225,6 +306,9 @@ public:
* \brief GetPosition Gives the position of a routine in the original text
* the user can select the item to find from the beginning to the end
* see the above modes in CBotGet.
*
* TODO: Document this
*
* \param name
* \param start
* \param stop
@ -239,76 +323,37 @@ public:
CBotGet modestop = GetPosBloc);
/*!
* \brief GetFunctions
* \return
* \brief Returns the list of all user-defined functions in this program as instances of CBotFunction
*
* This list includes all the functions (not only extern)
*
* \return Linked list of CBotFunction instances
*/
CBotFunction* GetFunctions();
/*!
* \brief m_bCompileClass
*
* TODO: document this
*/
bool m_bCompileClass;
private:
//! The user-defined functions.
//! All user-defined functions
CBotFunction* m_Prog;
//! The basic function for the execution.
//! The entry point function
CBotFunction* m_pRun;
//! Classes defined in this part.
//! Classes defined in this program
CBotClass* m_pClass;
//! Execution stack.
//! Execution stack
CBotStack* m_pStack;
//! Instance of the parent class.
//! "this" variable
CBotVar* m_pInstance;
friend class CBotFunction;
int m_ErrorCode;
CBotError m_ErrorCode;
int m_ErrorStart;
int m_ErrorEnd;
//! Associated identifier.
//! Associated identifier
long m_Ident;
};
/*
(**) 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, std::string& 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
}
*/

View File

@ -42,7 +42,7 @@
int CBotStack::m_initimer = ITIMER;
int CBotStack::m_timer = 0;
CBotVar* CBotStack::m_retvar = nullptr;
int CBotStack::m_error = 0;
CBotError CBotStack::m_error = CBotNoErr;
int CBotStack::m_start = 0;
int CBotStack::m_end = 0;
std::string CBotStack::m_labelBreak="";
@ -76,7 +76,7 @@ CBotStack* CBotStack::FirstStack()
pp ++;
}
m_error = 0; // avoids deadlocks because m_error is static
m_error = CBotNoErr; // avoids deadlocks because m_error is static
return p;
}
@ -358,7 +358,7 @@ bool CBotStack::StackOver()
void CBotStack::Reset(void* pUser)
{
m_timer = m_initimer; // resets the timer
m_error = 0;
m_error = CBotNoErr;
// m_start = 0;
// m_end = 0;
m_labelBreak.clear();
@ -402,7 +402,7 @@ bool CBotStack::BreakReturn(CBotStack* pfils, const std::string& name)
if (!m_labelBreak.empty() && (name.empty() || m_labelBreak != name))
return false; // it's not for me
m_error = 0;
m_error = CBotNoErr;
m_labelBreak.clear();
return Return(pfils);
}
@ -416,7 +416,7 @@ bool CBotStack::IfContinue(int state, const std::string& name)
return false; // it's not for me
m_state = state; // where again?
m_error = 0;
m_error = CBotNoErr;
m_labelBreak.clear();
if ( m_next != EOX ) m_next->Delete(); // purge above stack
return true;
@ -425,7 +425,7 @@ bool CBotStack::IfContinue(int state, const std::string& name)
////////////////////////////////////////////////////////////////////////////////
void CBotStack::SetBreak(int val, const std::string& name)
{
m_error = -val; // reacts as an Exception
m_error = static_cast<CBotError>(-val); // reacts as an Exception
m_labelBreak = name;
if (val == 3) // for a return
{
@ -443,14 +443,14 @@ bool CBotStack::GetRetVar(bool bRet)
if ( m_var ) delete m_var;
m_var = m_retvar;
m_retvar = nullptr;
m_error = 0;
m_error = CBotNoErr;
return true;
}
return bRet; // interrupted by something other than return
}
////////////////////////////////////////////////////////////////////////////////
int CBotStack::GetError(int& start, int& end)
CBotError CBotStack::GetError(int& start, int& end)
{
start = m_start;
end = m_end;
@ -584,7 +584,7 @@ bool CBotStack::IncState(int limite)
}
////////////////////////////////////////////////////////////////////////////////
void CBotStack::SetError(int n, CBotToken* token)
void CBotStack::SetError(CBotError n, CBotToken* token)
{
if ( n!= 0 && m_error != 0) return; // does not change existing error
m_error = n;
@ -596,7 +596,7 @@ void CBotStack::SetError(int n, CBotToken* token)
}
////////////////////////////////////////////////////////////////////////////////
void CBotStack::ResetError(int n, int start, int end)
void CBotStack::ResetError(CBotError n, int start, int end)
{
m_error = n;
m_start = start;

View File

@ -22,6 +22,7 @@
// Modules inlcude
#include "CBot/CBotDefines.h"
#include "CBot/CBotTypResult.h"
#include "CBotEnums.h"
// Local include
@ -81,7 +82,7 @@ public:
* \param [out] end end of stack
* \return error number
*/
int GetError(int& start, int& end);
CBotError GetError(int& start, int& end);
/**
* \brief GetError Get error number
@ -201,9 +202,9 @@ public:
bool GetRetVar(bool bRet);
long GetVal();
void SetError(int n, CBotToken* token = nullptr);
void SetError(CBotError n, CBotToken* token = nullptr);
void SetPosError(CBotToken* token);
void ResetError(int n, int start, int end);
void ResetError(CBotError n, int start, int end);
void SetBreak(int val, const std::string& name);
void SetBotCall(CBotProgram* p);
@ -232,7 +233,7 @@ private:
int m_state;
int m_step;
static int m_error;
static CBotError m_error;
static int m_start;
static int m_end;
static

View File

@ -50,6 +50,12 @@ public:
/**
* \brief Constructor for pointer types and intrinsic classes
*
* This is equivalent to calling:
* \code
* CBotTypResult(type, CBotClass::Find(name))
* \endcode
*
* \param type type of created result, see ::CBotType
* \param name name of the class
*/

View File

@ -586,17 +586,17 @@ void CBotVar::Power(CBotVar* left, CBotVar* right)
}
////////////////////////////////////////////////////////////////////////////////
int CBotVar::Div(CBotVar* left, CBotVar* right)
CBotError CBotVar::Div(CBotVar* left, CBotVar* right)
{
assert(0);
return 0;
return CBotNoErr;
}
////////////////////////////////////////////////////////////////////////////////
int CBotVar::Modulo(CBotVar* left, CBotVar* right)
CBotError CBotVar::Modulo(CBotVar* left, CBotVar* right)
{
assert(0);
return 0;
return CBotNoErr;
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -27,6 +27,7 @@
// Global include
#include <string>
#include <CBot/CBotEnums.h>
// Forward declaration
class CBotVarClass;
@ -398,7 +399,7 @@ public:
* \param right
* \return
*/
virtual int Div(CBotVar* left, CBotVar* right);
virtual CBotError Div(CBotVar* left, CBotVar* right);
/*!
* \brief Modulo Remainder of division
@ -406,7 +407,7 @@ public:
* \param right
* \return
*/
virtual int Modulo(CBotVar* left, CBotVar* right);
virtual CBotError Modulo(CBotVar* left, CBotVar* right);
/*!
* \brief Power

View File

@ -411,7 +411,8 @@ void CBotVarClass::DecrementUse()
// m_error is static in the stack
// saves the value for return
int err, start, end;
CBotError err;
int start, end;
CBotStack* pile = nullptr;
err = pile->GetError(start,end); // stack == nullptr it does not bother!

View File

@ -128,7 +128,7 @@ void CBotVarFloat::Power(CBotVar* left, CBotVar* right)
}
////////////////////////////////////////////////////////////////////////////////
int CBotVarFloat::Div(CBotVar* left, CBotVar* right)
CBotError CBotVarFloat::Div(CBotVar* left, CBotVar* right)
{
float r = right->GetValFloat();
if ( r != 0 )
@ -136,11 +136,11 @@ int CBotVarFloat::Div(CBotVar* left, CBotVar* right)
m_val = left->GetValFloat() / r;
m_binit = CBotVar::InitType::DEF;
}
return ( r == 0 ? CBotErrZeroDiv : 0 );
return ( r == 0 ? CBotErrZeroDiv : CBotNoErr );
}
////////////////////////////////////////////////////////////////////////////////
int CBotVarFloat::Modulo(CBotVar* left, CBotVar* right)
CBotError CBotVarFloat::Modulo(CBotVar* left, CBotVar* right)
{
float r = right->GetValFloat();
if ( r != 0 )
@ -148,7 +148,7 @@ int CBotVarFloat::Modulo(CBotVar* left, CBotVar* right)
m_val = static_cast<float>(fmod( left->GetValFloat() , r ));
m_binit = CBotVar::InitType::DEF;
}
return ( r == 0 ? CBotErrZeroDiv : 0 );
return ( r == 0 ? CBotErrZeroDiv : CBotNoErr );
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -20,6 +20,7 @@
#pragma once
// Modules inlcude
#include <CBot/CBotEnums.h>
#include "CBot/CBotVar/CBotVar.h"
// Local include
@ -105,7 +106,7 @@ public:
* \param right
* \return
*/
int Div(CBotVar* left, CBotVar* right) override;
CBotError Div(CBotVar* left, CBotVar* right) override;
/*!
* \brief Modulo Remainder of division.
@ -113,7 +114,7 @@ public:
* \param right
* \return
*/
int Modulo(CBotVar* left, CBotVar* right) override;
CBotError Modulo(CBotVar* left, CBotVar* right) override;
/*!
* \brief Power

View File

@ -131,7 +131,7 @@ void CBotVarInt::Power(CBotVar* left, CBotVar* right)
}
////////////////////////////////////////////////////////////////////////////////
int CBotVarInt::Div(CBotVar* left, CBotVar* right)
CBotError CBotVarInt::Div(CBotVar* left, CBotVar* right)
{
int r = right->GetValInt();
if ( r != 0 )
@ -139,11 +139,11 @@ int CBotVarInt::Div(CBotVar* left, CBotVar* right)
m_val = left->GetValInt() / r;
m_binit = CBotVar::InitType::DEF;
}
return ( r == 0 ? CBotErrZeroDiv : 0 );
return ( r == 0 ? CBotErrZeroDiv : CBotNoErr );
}
////////////////////////////////////////////////////////////////////////////////
int CBotVarInt::Modulo(CBotVar* left, CBotVar* right)
CBotError CBotVarInt::Modulo(CBotVar* left, CBotVar* right)
{
int r = right->GetValInt();
if ( r != 0 )
@ -151,7 +151,7 @@ int CBotVarInt::Modulo(CBotVar* left, CBotVar* right)
m_val = left->GetValInt() % r;
m_binit = CBotVar::InitType::DEF;
}
return ( r == 0 ? CBotErrZeroDiv : 0 );
return ( r == 0 ? CBotErrZeroDiv : CBotNoErr );
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -20,6 +20,7 @@
#pragma once
// Modules inlcude
#include <CBot/CBotEnums.h>
#include "CBot/CBotVar/CBotVar.h"
// Local include
@ -105,7 +106,7 @@ public:
* \param right
* \return
*/
int Div(CBotVar* left, CBotVar* right) override;
CBotError Div(CBotVar* left, CBotVar* right) override;
/*!
* \brief Modulo
@ -113,7 +114,7 @@ public:
* \param right
* \return
*/
int Modulo(CBotVar* left, CBotVar* right) override;
CBotError Modulo(CBotVar* left, CBotVar* right) override;
/*!
* \brief Power

4
src/CBot/README.txt Normal file
View File

@ -0,0 +1,4 @@
/**
* \dir src/CBot
* \brief CBot library
*/

View File

@ -165,7 +165,7 @@ bool CScript::CheckToken()
if ( !m_object->GetCheckToken() ) return true;
m_error = 0;
m_error = CBotNoErr;
m_title[0] = 0;
m_mainFunction[0] = 0;
m_token[0] = 0;
@ -194,7 +194,7 @@ bool CScript::CheckToken()
if ( !m_main->IsProhibitedToken(token.c_str()) )
{
m_error = ERR_PROHIBITEDTOKEN;
m_error = static_cast<CBotError>(ERR_PROHIBITEDTOKEN);
m_cursor1 = cursor1;
m_cursor2 = cursor2;
strcpy(m_title, "<prohibited>");
@ -212,7 +212,7 @@ bool CScript::CheckToken()
if ( used[i] == 0 ) // token not used?
{
strcpy(m_token, m_main->GetObligatoryToken(i));
m_error = ERR_OBLIGATORYTOKEN;
m_error = static_cast<CBotError>(ERR_OBLIGATORYTOKEN);
strcpy(m_title, "<obligatory>");
m_mainFunction[0] = 0;
CBotToken::Delete(allBt);
@ -232,7 +232,7 @@ bool CScript::Compile()
int i;
std::string p;
m_error = 0;
m_error = CBotNoErr;
m_cursor1 = 0;
m_cursor2 = 0;
m_title[0] = 0;
@ -815,7 +815,7 @@ void CScript::GetError(std::string& error)
}
else
{
if ( m_error == ERR_OBLIGATORYTOKEN )
if ( m_error == static_cast<CBotError>(ERR_OBLIGATORYTOKEN) )
{
std::string s;
GetResource(RES_ERR, m_error, s);

View File

@ -123,7 +123,7 @@ protected:
char m_mainFunction[50] = {};
char m_filename[50] = {}; // file name
char m_token[50] = {}; // missing instruction
int m_error = 0; // error (0=ok)
CBotError m_error = CBotNoErr; // error (0=ok)
int m_cursor1 = 0;
int m_cursor2 = 0;
boost::optional<float> m_returnValue = boost::none;

View File

@ -47,7 +47,8 @@ int main(int argc, char* argv[])
std::unique_ptr<CBotProgram> program{new CBotProgram(nullptr)};
if (!program->Compile(code.c_str(), externFunctions, nullptr))
{
int error, cursor1, cursor2;
CBotError error;
int cursor1, cursor2;
program->GetError(error, cursor1, cursor2);
std::string errorStr;
GetResource(RES_CBOT, error, errorStr);
@ -74,7 +75,8 @@ int main(int argc, char* argv[])
while (!program->Run(nullptr)); // Run the program
int error, cursor1, cursor2;
CBotError error;
int cursor1, cursor2;
program->GetError(error, cursor1, cursor2);
if (error != 0)
{