Only store types in compile stack, not variables. Probably introduces bugs because CBotCStack::GetType used to return 99 for void!

cbot-cleanup
immibis 2019-07-01 23:37:45 +12:00
parent 38d0ea520e
commit bb60fceaf2
47 changed files with 702 additions and 821 deletions

View File

@ -116,7 +116,7 @@ CBotInstr* CBotCStack::Return(CBotInstr* inst, CBotCStack* pfils)
assert(pfils == this->m_next); assert(pfils == this->m_next);
assert(pfils->m_next == nullptr); // pfils must be bottom stack level, and this must be the next one above it. assert(pfils->m_next == nullptr); // pfils must be bottom stack level, and this must be the next one above it.
m_var = std::move(pfils->m_var); // result transmitted m_vartype = std::move(pfils->m_vartype); // result transmitted
if (pfils->m_error != CBotNoErr) if (pfils->m_error != CBotNoErr)
{ {
@ -150,39 +150,6 @@ CBotError CBotCStack::GetError()
return m_error; return m_error;
} }
////////////////////////////////////////////////////////////////////////////////
CBotTypResult CBotCStack::GetTypResult(CBotVar::GetTypeMode mode)
{
if (m_var == nullptr)
return CBotTypResult(99);
return m_var->GetTypResult(mode);
}
////////////////////////////////////////////////////////////////////////////////
int CBotCStack::GetType(CBotVar::GetTypeMode 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(CBotVar::GetTypeMode::CLASS_AS_POINTER) != CBotTypPointer ) return nullptr;
return m_var->GetClass();
}
////////////////////////////////////////////////////////////////////////////////
void CBotCStack::SetType(CBotTypResult& type)
{
if (m_var == nullptr) return;
m_var->SetType( type );
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
CBotVariable* CBotCStack::FindVar(CBotToken* &pToken) CBotVariable* CBotCStack::FindVar(CBotToken* &pToken)
{ {
@ -295,27 +262,15 @@ CBotTypResult CBotCStack::GetRetType()
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void CBotCStack::SetVar( std::unique_ptr<CBotVar> var ) void CBotCStack::SetVarType( CBotTypResult type )
{ {
m_var = std::move(var); m_vartype = std::move(type);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void CBotCStack::SetCopyVar( CBotVar* var ) const CBotTypResult& CBotCStack::GetVarType()
{ {
if ( var == nullptr ) return m_vartype;
{
m_var.reset(); // set to null
return;
}
m_var = CBotVar::Create(var->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC));
m_var->Copy( var );
}
////////////////////////////////////////////////////////////////////////////////
CBotVar* CBotCStack::GetVar()
{
return m_var.get();
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -398,14 +353,14 @@ bool CBotCStack::CheckVarLocal(CBotToken* &pToken)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
CBotTypResult CBotCStack::CompileCall(CBotToken* &p, CBotVar** ppVars, long& nIdent) CBotTypResult CBotCStack::CompileCall(CBotToken* &p, const std::vector<CBotTypResult> &ppVars, long& nIdent)
{ {
nIdent = 0; nIdent = 0;
CBotTypResult val(-1); CBotTypResult val(-1);
CBotProgram *prog = GetProgram(); CBotProgram *prog = GetProgram();
val = prog->GetExternalCalls()->CompileCall(p, nullptr, ppVars, this); val = prog->GetExternalCalls()->CompileCall(p, CBotTypResult(CBotTypVoid), ppVars, this);
if (val.GetType() < 0) if (val.GetType() < 0)
{ {
val = CBotFunction::CompileCall(prog->GetFunctions(), p->GetString(), ppVars, nIdent); val = CBotFunction::CompileCall(prog->GetFunctions(), p->GetString(), ppVars, nIdent);

View File

@ -45,9 +45,9 @@ class CBotToken;
* The TokenStack method, which must be called on the innermost level, creates and returns a new inner level. * The TokenStack method, which must be called on the innermost level, creates and returns a new inner level.
* The Return or ReturnFunc method can be used to destroy the innermost level and go back to the level outside it. * The Return or ReturnFunc method can be used to destroy the innermost level and go back to the level outside it.
* *
* Each stack level has a m_var which is used for various purposes. * Each stack level has a m_vartype which is used for various purposes - generally indicating the type of value returned
* by a previous expression.
* It's not clear why we stash these into the stack instead of returning them. * It's not clear why we stash these into the stack instead of returning them.
* The CBotCStack has ownership of the object m_var points to.
* *
* Each stack level has an error start position, end position and error type. * Each stack level has an error start position, end position and error type.
* It's not clear why we stash these into the stack instead of returning them or throwing an exception. * It's not clear why we stash these into the stack instead of returning them or throwing an exception.
@ -119,47 +119,6 @@ public:
*/ */
CBotError GetError(int& start, int& end); CBotError GetError(int& start, int& end);
/*!
* \brief Set m_var's type.
*
* This is identical to GetVar()->\link CBotVar::SetType(CBotTypResult&) SetType(type)\endlink, unless m_var is null in which case it does nothing.
*
* \param type New type
*/
void SetType(CBotTypResult& type);
/*!
* \brief Gets type of m_var.
*
* This is identical to GetVar()->\link CBotVar::GetTypResult(CBotVar::GetTypeMode) GetTypResult(mode)\endlink unless m_var is null.
* If m_var is null, this returns nullptr.
*
* \param mode
* \return m_var's type
*/
CBotTypResult GetTypResult(CBotVar::GetTypeMode mode = CBotVar::GetTypeMode::NORMAL);
/*!
* \brief Gets type of m_var.
*
* This is identical to GetVar()->\link CBotVar::GetType(CBotVar::GetTypeMode) GetType(mode)\endlink unless m_var is null.
* If m_var is null, this returns nullptr.
*
* \param mode
* \return m_var's type
*/
int GetType(CBotVar::GetTypeMode mode = CBotVar::GetTypeMode::NORMAL);
/*!
* \brief Gets type of m_var.
*
* This is identical to GetVar()->\link CBotVar::GetClass() GetClass()\endlink if m_var is not null and has a class type.
* Otherwise, this returns nullptr.
*
* \return m_var's class
*/
CBotClass* GetClass();
/*! /*!
* \brief Adds a local variable. * \brief Adds a local variable.
* *
@ -256,30 +215,20 @@ public:
CBotFunction* ReturnFunc(CBotFunction* p, CBotCStack* pChild); CBotFunction* ReturnFunc(CBotFunction* p, CBotCStack* pChild);
/*! /*!
* \brief Sets m_var. * \brief Sets m_vartype.
* *
* Sets m_var to var. Deletes any previous m_var. * Sets m_vartype to type.
* *
* \param var * \param var
*/ */
void SetVar( std::unique_ptr<CBotVar> var ); void SetVarType( CBotTypResult type );
/*! /*!
* \brief Sets m_var. * \brief Gets m_vartype.
* *
* Sets m_var to a copy of var. Deletes any previous m_var. Does not takes ownership of var. * \return Value of m_vartype, previously set by one of the SetVar or Return functions.
* var must not be null, or else m_var is left in an invalid state!
*
* \param var
*/ */
void SetCopyVar( CBotVar* var ); const CBotTypResult& GetVarType();
/*!
* \brief Gets m_var.
*
* \return Value of m_var, previously set by one of the SetVar or Return functions.
*/
CBotVar* GetVar();
/*! /*!
* \brief Set error start location. * \brief Set error start location.
@ -345,11 +294,11 @@ public:
/*! /*!
* \brief CompileCall * \brief CompileCall
* \param p * \param p
* \param ppVars * \param ppVars Argument types
* \param nIdent * \param nIdent
* \return * \return
*/ */
CBotTypResult CompileCall(CBotToken* &p, CBotVar** ppVars, long& nIdent); CBotTypResult CompileCall(CBotToken* &p, const std::vector<CBotTypResult> &ppVars, long& nIdent);
/*! /*!
* \brief CheckCall Test if a procedure name is already defined somewhere. * \brief CheckCall Test if a procedure name is already defined somewhere.
@ -407,7 +356,7 @@ private:
int m_start; int m_start;
//! Result of the operations. //! Result of the operations.
std::unique_ptr<CBotVar> m_var; CBotTypResult m_vartype;
//! Is part of a block (variables are local to this block). //! Is part of a block (variables are local to this block).
bool m_bBlock; bool m_bBlock;
CBotVariable* m_listVar; CBotVariable* m_listVar;

View File

@ -286,7 +286,7 @@ CBotClass* CBotClass::Find(const std::string& name)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool CBotClass::AddFunction(const std::string& name, bool CBotClass::AddFunction(const std::string& name,
bool rExec(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user), bool rExec(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user),
CBotTypResult rCompile(CBotVar* pThis, CBotVar*& pVar)) CBotTypResult rCompile(CBotTypResult thisType, const std::vector<CBotTypResult> &pVar))
{ {
return m_externalMethods->AddFunction(name, std::unique_ptr<CBotExternalCall>(new CBotExternalCallClass(rExec, rCompile))); return m_externalMethods->AddFunction(name, std::unique_ptr<CBotExternalCall>(new CBotExternalCallClass(rExec, rCompile)));
} }
@ -300,8 +300,8 @@ bool CBotClass::SetUpdateFunc(void rUpdate(CBotVar* thisVar, void* user))
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
CBotTypResult CBotClass::CompileMethode(CBotToken* name, CBotTypResult CBotClass::CompileMethode(CBotToken* name,
CBotVar* pThis, CBotTypResult thisType,
CBotVar** ppParams, const std::vector<CBotTypResult> &ppParams,
CBotCStack* pStack, CBotCStack* pStack,
long &nIdent) long &nIdent)
{ {
@ -309,14 +309,14 @@ CBotTypResult CBotClass::CompileMethode(CBotToken* name,
// find the methods declared by AddFunction // find the methods declared by AddFunction
CBotTypResult r = m_externalMethods->CompileCall(name, pThis, ppParams, pStack); CBotTypResult r = m_externalMethods->CompileCall(name, thisType, ppParams, pStack);
if ( r.GetType() >= 0) return r; if ( r.GetType() >= 0) return r;
// find the methods declared by user // find the methods declared by user
r = CBotFunction::CompileCall(m_pMethod, name->GetString(), ppParams, nIdent); r = CBotFunction::CompileCall(m_pMethod, name->GetString(), ppParams, nIdent);
if ( r.Eq(CBotErrUndefCall) && m_parent != nullptr ) if ( r.Eq(CBotErrUndefCall) && m_parent != nullptr )
return m_parent->CompileMethode(name, pThis, ppParams, pStack, nIdent); return m_parent->CompileMethode(name, thisType, ppParams, pStack, nIdent);
return r; return r;
} }
@ -681,7 +681,7 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
if ( p->GetType() != ID_CLBRK ) if ( p->GetType() != ID_CLBRK )
{ {
i = CBotExpression::Compile( p, pStack ); // expression for the value i = CBotExpression::Compile( p, pStack ); // expression for the value
if (i == nullptr || pStack->GetType() != CBotTypInt) // must be a number if (i == nullptr || pStack->GetVarType().GetType() != CBotTypInt) // must be a number
{ {
pStack->SetError(CBotErrBadIndex, p->GetStart()); pStack->SetError(CBotErrBadIndex, p->GetStart());
} }
@ -716,7 +716,7 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
if (pStack->IsOk()) if (pStack->IsOk())
{ {
i = CBotTwoOpExpr::Compile(p, pStack); i = CBotTwoOpExpr::Compile(p, pStack);
if (i == nullptr || !pStack->GetTypResult().Compare(type2)) if (i == nullptr || !pStack->GetVarType().Compare(type2))
{ {
pStack->SetError(CBotErrBadType1, p->GetStart()); pStack->SetError(CBotErrBadType1, p->GetStart());
return false; return false;
@ -729,8 +729,8 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
// it has an assignmet to calculate // it has an assignmet to calculate
i = CBotTwoOpExpr::Compile(p, pStack); i = CBotTwoOpExpr::Compile(p, pStack);
if ( !(type.Eq(CBotTypPointer) && pStack->GetTypResult().Eq(CBotTypNullPointer)) && if ( !(type.Eq(CBotTypPointer) && pStack->GetVarType().Eq(CBotTypNullPointer)) &&
!TypesCompatibles( type2, pStack->GetTypResult()) ) !TypesCompatibles( type2, pStack->GetVarType()) )
{ {
pStack->SetError(CBotErrBadType1, p->GetStart()); pStack->SetError(CBotErrBadType1, p->GetStart());
return false; return false;

View File

@ -140,7 +140,7 @@ public:
*/ */
bool AddFunction(const std::string& name, bool AddFunction(const std::string& name,
bool rExec(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user), bool rExec(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user),
CBotTypResult rCompile(CBotVar* pThis, CBotVar*& pVar)); CBotTypResult rCompile(CBotTypResult thisType, const std::vector<CBotTypResult> &pVar));
/*! /*!
* \brief SetUpdateFunc Defines routine to be called to update the elements * \brief SetUpdateFunc Defines routine to be called to update the elements
@ -236,15 +236,15 @@ public:
* \brief CompileMethode Compiles a method associated with an instance of * \brief CompileMethode Compiles a method associated with an instance of
* class the method can be declared by the user or AddFunction. * class the method can be declared by the user or AddFunction.
* \param name * \param name
* \param pThis * \param thisType Type of object the method is being called on.
* \param ppParams * \param ppParams Types of parameters
* \param pStack * \param pStack
* \param nIdent * \param nIdent
* \return * \return
*/ */
CBotTypResult CompileMethode(CBotToken* name, CBotTypResult CompileMethode(CBotToken* name,
CBotVar* pThis, CBotTypResult thisType,
CBotVar** ppParams, const std::vector<CBotTypResult> &ppParams,
CBotCStack* pStack, CBotCStack* pStack,
long &nIdent); long &nIdent);

View File

@ -87,7 +87,9 @@ CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack)
CBotCStack* pStk = pStack->TokenStack(nullptr, true); CBotCStack* pStk = pStack->TokenStack(nullptr, true);
if (nullptr != (param->m_expr = CBotParExpr::CompileLitExpr(p, pStk))) if (nullptr != (param->m_expr = CBotParExpr::CompileLitExpr(p, pStk)))
{ {
CBotTypResult valueType = pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC); CBotTypResult valueType = pStk->GetVarType();
if(valueType.GetType() == CBotTypClass)
valueType.SetType(CBotTypIntrinsic);
if (!TypesCompatibles(type, valueType)) if (!TypesCompatibles(type, valueType))
pStack->SetError(CBotErrBadType1, p->GetPrev()); pStack->SetError(CBotErrBadType1, p->GetPrev());

View File

@ -40,15 +40,14 @@ bool CBotExternalCallList::AddFunction(const std::string& name, std::unique_ptr<
return true; return true;
} }
CBotTypResult CBotExternalCallList::CompileCall(CBotToken*& p, CBotVar* thisVar, CBotVar** ppVar, CBotCStack* pStack) CBotTypResult CBotExternalCallList::CompileCall(CBotToken*& p, CBotTypResult thisType, const std::vector<CBotTypResult> &ppVar, CBotCStack* pStack)
{ {
if (m_list.count(p->GetString()) == 0) if (m_list.count(p->GetString()) == 0)
return -1; return -1;
CBotExternalCall* pt = m_list[p->GetString()].get(); CBotExternalCall* pt = m_list[p->GetString()].get();
std::unique_ptr<CBotVar> args = std::unique_ptr<CBotVar>(MakeListVars(ppVar)); CBotTypResult r = pt->Compile(thisType, ppVar, m_user);
CBotTypResult r = pt->Compile(thisVar, args.get(), m_user);
// if a class is returned, it is actually a pointer // if a class is returned, it is actually a pointer
if (r.GetType() == CBotTypClass) r.SetType(CBotTypPointer); if (r.GetType() == CBotTypClass) r.SetType(CBotTypPointer);
@ -136,7 +135,7 @@ CBotExternalCallDefault::~CBotExternalCallDefault()
{ {
} }
CBotTypResult CBotExternalCallDefault::Compile(CBotVar* thisVar, CBotVar* args, void* user) CBotTypResult CBotExternalCallDefault::Compile(CBotTypResult thisType, const std::vector<CBotTypResult> &args, void* user)
{ {
return m_rComp(args, user); return m_rComp(args, user);
} }
@ -180,9 +179,9 @@ CBotExternalCallClass::~CBotExternalCallClass()
{ {
} }
CBotTypResult CBotExternalCallClass::Compile(CBotVar* thisVar, CBotVar* args, void* user) CBotTypResult CBotExternalCallClass::Compile(CBotTypResult thisType, const std::vector<CBotTypResult> &args, void* user)
{ {
return m_rComp(thisVar, args); return m_rComp(thisType, args);
} }
bool CBotExternalCallClass::Run(CBotVar* thisVar, CBotStack* pStack) bool CBotExternalCallClass::Run(CBotVar* thisVar, CBotStack* pStack)

View File

@ -26,6 +26,7 @@
#include <string> #include <string>
#include <map> #include <map>
#include <memory> #include <memory>
#include <vector>
namespace CBot namespace CBot
{ {
@ -59,11 +60,11 @@ public:
/** /**
* \brief Compile the function * \brief Compile the function
* *
* \param thisVar "this" variable for class calls, nullptr for normal calls * \param thisType Type of "this" variable for class calls, void for normal calls
* \param args Arguments (only types!) passed to the function * \param args Arguments (only types!) passed to the function
* \param user User pointer provided to CBotProgram::Compile() * \param user User pointer provided to CBotProgram::Compile()
*/ */
virtual CBotTypResult Compile(CBotVar* thisVar, CBotVar* args, void* user) = 0; virtual CBotTypResult Compile(CBotTypResult thisType, const std::vector<CBotTypResult> &args, void* user) = 0;
/** /**
* \brief Execute the function * \brief Execute the function
@ -82,7 +83,7 @@ class CBotExternalCallDefault : public CBotExternalCall
{ {
public: public:
typedef bool (*RuntimeFunc)(CBotVar* args, CBotVar* result, int& exception, void* user); typedef bool (*RuntimeFunc)(CBotVar* args, CBotVar* result, int& exception, void* user);
typedef CBotTypResult (*CompileFunc)(CBotVar*& args, void* user); typedef CBotTypResult (*CompileFunc)(const std::vector<CBotTypResult> &args, void* user);
/** /**
* \brief Constructor * \brief Constructor
@ -97,7 +98,7 @@ public:
*/ */
virtual ~CBotExternalCallDefault(); virtual ~CBotExternalCallDefault();
virtual CBotTypResult Compile(CBotVar* thisVar, CBotVar* args, void* user) override; virtual CBotTypResult Compile(CBotTypResult thisType, const std::vector<CBotTypResult> &args, void* user) override;
virtual bool Run(CBotVar* thisVar, CBotStack* pStack) override; virtual bool Run(CBotVar* thisVar, CBotStack* pStack) override;
private: private:
@ -112,7 +113,7 @@ class CBotExternalCallClass : public CBotExternalCall
{ {
public: public:
typedef bool (*RuntimeFunc)(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user); typedef bool (*RuntimeFunc)(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user);
typedef CBotTypResult (*CompileFunc)(CBotVar* pThis, CBotVar*& pVar); typedef CBotTypResult (*CompileFunc)(CBotTypResult thisType, const std::vector<CBotTypResult> &pVar);
/** /**
* \brief Constructor * \brief Constructor
@ -127,7 +128,7 @@ public:
*/ */
virtual ~CBotExternalCallClass(); virtual ~CBotExternalCallClass();
virtual CBotTypResult Compile(CBotVar* thisVar, CBotVar* args, void* user) override; virtual CBotTypResult Compile(CBotTypResult thisType, const std::vector<CBotTypResult> &args, void* user) override;
virtual bool Run(CBotVar* thisVar, CBotStack* pStack) override; virtual bool Run(CBotVar* thisVar, CBotStack* pStack) override;
private: private:
@ -158,12 +159,12 @@ public:
* This function sets an error in compilation stack in case of failure * This function sets an error in compilation stack in case of failure
* *
* \param p Token representing the function name * \param p Token representing the function name
* \param thisVar "this" variable for class calls, nullptr for normal calls * \param thisType Type of "this" variable for class calls, void for normal calls
* \param ppVars List of arguments (only types!) * \param ppVars List of arguments (only types!)
* \param pStack Compilation stack * \param pStack Compilation stack
* \return CBotTypResult representing the return type of the function (::CBotType), or an error (::CBotError) * \return CBotTypResult representing the return type of the function (::CBotType), or an error (::CBotError)
*/ */
CBotTypResult CompileCall(CBotToken*& p, CBotVar* thisVar, CBotVar** ppVars, CBotCStack* pStack); CBotTypResult CompileCall(CBotToken*& p, CBotTypResult thisType, const std::vector<CBotTypResult> &ppVars, CBotCStack* pStack);
/** /**
* \brief Check if function with given name has been defined * \brief Check if function with given name has been defined

View File

@ -36,7 +36,7 @@ CBotInstr* CBotBoolExpr::Compile(CBotToken* &p, CBotCStack* pStack)
if (nullptr != inst) if (nullptr != inst)
{ {
if (pStack->GetTypResult().Eq(CBotTypBoolean)) if (pStack->GetVarType().Eq(CBotTypBoolean))
{ {
return inst; return inst;
} }

View File

@ -57,8 +57,8 @@ CBotCatch* CBotCatch::Compile(CBotToken* &p, CBotCStack* pStack)
if (IsOfType(p, ID_OPENPAR)) if (IsOfType(p, ID_OPENPAR))
{ {
inst->m_cond = CBotExpression::Compile(p, pStack); inst->m_cond = CBotExpression::Compile(p, pStack);
if (( pStack->GetType() < CBotTypLong || if (( pStack->GetVarType().GetType() < CBotTypLong ||
pStack->GetTypResult().Eq(CBotTypBoolean) )&& pStack->IsOk() ) pStack->GetVarType().Eq(CBotTypBoolean) )&& pStack->IsOk() )
{ {
if (IsOfType(p, ID_CLOSEPAR)) if (IsOfType(p, ID_CLOSEPAR))
{ {

View File

@ -76,7 +76,7 @@ CBotInstr* CBotDefArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResul
if (p->GetType() != ID_CLBRK) if (p->GetType() != ID_CLBRK)
{ {
i = CBotExpression::Compile(p, pStk); // expression for the value i = CBotExpression::Compile(p, pStk); // expression for the value
if (i == nullptr || pStk->GetType() != CBotTypInt) // must be a number if (i == nullptr || pStk->GetVarType().GetType() != CBotTypInt) // must be a number
{ {
pStk->SetError(CBotErrBadIndex, p->GetStart()); pStk->SetError(CBotErrBadIndex, p->GetStart());
goto error; goto error;
@ -114,7 +114,7 @@ CBotInstr* CBotDefArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResul
if (pStk->IsOk()) if (pStk->IsOk())
{ {
inst->m_listass = CBotTwoOpExpr::Compile(p, pStk); inst->m_listass = CBotTwoOpExpr::Compile(p, pStk);
if (inst->m_listass == nullptr || !pStk->GetTypResult().Compare(type)) // compatible type ? if (inst->m_listass == nullptr || !pStk->GetVarType().Compare(type)) // compatible type ?
{ {
pStk->SetError(CBotErrBadType1, p->GetStart()); pStk->SetError(CBotErrBadType1, p->GetStart());
goto error; goto error;

View File

@ -116,7 +116,7 @@ CBotInstr* CBotDefClass::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* p
// look if there are parameters // look if there are parameters
inst->m_hasParams = (p->GetType() == ID_OPENPAR); inst->m_hasParams = (p->GetType() == ID_OPENPAR);
CBotVar* ppVars[1000]; std::vector<CBotTypResult> ppVars;
inst->m_parameters = CompileParams(p, pStk, ppVars); inst->m_parameters = CompileParams(p, pStk, ppVars);
if ( !pStk->IsOk() ) goto error; if ( !pStk->IsOk() ) goto error;
@ -129,7 +129,7 @@ CBotInstr* CBotDefClass::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* p
{ {
// the constructor is there? // the constructor is there?
// std::string noname; // std::string noname;
CBotTypResult r = pClass->CompileMethode(&token, var->m_value.get(), ppVars, pStk, inst->m_nMethodeIdent); CBotTypResult r = pClass->CompileMethode(&token, var->m_value->GetTypResult(), ppVars, pStk, inst->m_nMethodeIdent);
pStk->DeleteChildLevels(); // releases the supplement stack pStk->DeleteChildLevels(); // releases the supplement stack
int typ = r.GetType(); int typ = r.GetType();
@ -150,14 +150,14 @@ CBotInstr* CBotDefClass::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* p
goto error; goto error;
} }
pStk->SetCopyVar(var->m_value.get()); pStk->SetVarType(var->m_value->GetTypResult());
// chained method ? // chained method ?
if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStk, true, false))) if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStk, true, false)))
{ {
inst->m_exprRetVar->SetToken(vartoken); inst->m_exprRetVar->SetToken(vartoken);
pStk->DeleteChildLevels(); pStk->DeleteChildLevels();
} }
pStk->SetVar(nullptr); pStk->SetVarType(CBotTypResult());
if ( !pStk->IsOk() ) goto error; if ( !pStk->IsOk() ) goto error;
} }
@ -181,12 +181,17 @@ CBotInstr* CBotDefClass::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* p
{ {
goto error; goto error;
} }
CBotClass* result = pStk->GetClass(); CBotClass* result = pStk->GetVarType().GetClass();
if ( !pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_POINTER).Eq(CBotTypNullPointer) &&
( !pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_POINTER).Eq(CBotTypPointer) ||
if ( !pStk->GetVarType().Eq(CBotTypNullPointer) &&
( (!pStk->GetVarType().Eq(CBotTypPointer) &&
!pStk->GetVarType().Eq(CBotTypClass)) ||
( result != nullptr && !(pClass->IsChildOf(result) || ( result != nullptr && !(pClass->IsChildOf(result) ||
result->IsChildOf(pClass))))) // type compatible ? result->IsChildOf(pClass))))) // type compatible ?
{ {
// TODO: pClass->IsChildOf(result) means we can assign from a superclass? what happens if it's not an instance of the subclass at runtime?
pStk->SetError(CBotErrBadType1, p->GetStart()); pStk->SetError(CBotErrBadType1, p->GetStart());
goto error; goto error;
} }

View File

@ -99,7 +99,7 @@ CBotInstr* CBotDefVariable::CompileAfterType(CBotToken* &p, CBotCStack* pStack,
return pStack->Return(nullptr, pStk); return pStack->Return(nullptr, pStk);
} }
CBotTypResult valueType = pStk->GetTypResult(); // TODO: make TypeCompatible take a const& so this variable isn't needed CBotTypResult valueType = pStk->GetVarType(); // TODO: make TypeCompatible take a const& so this variable isn't needed
if (!TypeCompatible(valueType, baseType, ID_ASS)) // first parameter is value type, second is variable type if (!TypeCompatible(valueType, baseType, ID_ASS)) // first parameter is value type, second is variable type
{ {
pStk->SetError(CBotErrBadType1, p->GetStart()); pStk->SetError(CBotErrBadType1, p->GetStart());

View File

@ -50,8 +50,7 @@ CBotInstr* CBotExprLitBool::Compile(CBotToken* &p, CBotCStack* pStack)
inst->SetToken(p); // stores the operation false or true inst->SetToken(p); // stores the operation false or true
p = p->GetNext(); p = p->GetNext();
std::unique_ptr<CBotVar> var = CBotVar::Create(CBotTypBoolean); pStk->SetVarType(CBotTypResult(CBotTypBoolean));
pStk->SetVar(std::move(var));
} }
return pStack->Return(inst, pStk); return pStack->Return(inst, pStk);

View File

@ -70,8 +70,7 @@ CBotInstr* CBotExprLitNum::Compile(CBotToken* &p, CBotCStack* pStack)
if (pStk->NextToken(p)) if (pStk->NextToken(p))
{ {
std::unique_ptr<CBotVar> var = CBotVar::Create(inst->m_numtype); pStk->SetVarType(CBotTypResult(inst->m_numtype));
pStk->SetVar(std::move(var));
return pStack->Return(inst, pStk); return pStack->Return(inst, pStk);
} }

View File

@ -163,8 +163,7 @@ CBotInstr* CBotExprLitString::Compile(CBotToken* &p, CBotCStack* pStack)
inst->SetToken(p); inst->SetToken(p);
p = p->GetNext(); p = p->GetNext();
std::unique_ptr<CBotVar> var = CBotVar::Create(CBotTypString); pStk->SetVarType(CBotTypResult(CBotTypString));
pStk->SetVar(std::move(var));
return pStack->Return(inst, pStk); return pStack->Return(inst, pStk);
} }

View File

@ -26,6 +26,7 @@
#include "CBot/CBotInstr/CBotFieldExpr.h" #include "CBot/CBotInstr/CBotFieldExpr.h"
#include "CBot/CBotStack.h" #include "CBot/CBotStack.h"
#include "CBot/CBotClass.h"
namespace CBot namespace CBot
{ {
@ -45,19 +46,17 @@ CBotInstr* CBotExprRetVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bMeth
{ {
if (p->GetType() == ID_DOT) if (p->GetType() == ID_DOT)
{ {
CBotVar* val = pStack->GetVar(); CBotTypResult val = pStack->GetVarType();
if (val == nullptr) return nullptr; if (val.GetType() == CBotTypVoid) return nullptr;
CBotCStack* pStk = pStack->TokenStack(); CBotCStack* pStk = pStack->TokenStack();
CBotInstr* inst = new CBotExprRetVar(); CBotInstr* inst = new CBotExprRetVar();
CBotVariable *var = nullptr;
while (true) while (true)
{ {
pStk->SetStartError(p->GetStart()); pStk->SetStartError(p->GetStart());
if (val->GetType() == CBotTypArrayPointer) if (val.GetType() == CBotTypArrayPointer)
{ {
if (bMethodsOnly) goto err; if (bMethodsOnly) goto err;
@ -67,10 +66,9 @@ CBotInstr* CBotExprRetVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bMeth
i->m_expr = CBotExpression::Compile(p, pStk); i->m_expr = CBotExpression::Compile(p, pStk);
inst->AddNext3(i); inst->AddNext3(i);
var = val->GetItem(0,true); val = val.GetTypElem();
val = var->m_value.get();
if (i->m_expr == nullptr || pStk->GetType() != CBotTypInt) if (i->m_expr == nullptr || pStk->GetVarType().GetType() != CBotTypInt)
{ {
pStk->SetError(CBotErrBadIndex, p->GetStart()); pStk->SetError(CBotErrBadIndex, p->GetStart());
goto err; goto err;
@ -83,7 +81,7 @@ CBotInstr* CBotExprRetVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bMeth
continue; continue;
} }
} }
if (val->GetType(CBotVar::GetTypeMode::CLASS_AS_POINTER) == CBotTypPointer) if (val.GetType() == CBotTypClass || val.GetType() == CBotTypPointer)
{ {
if (IsOfType(p, ID_DOT)) if (IsOfType(p, ID_DOT))
{ {
@ -105,25 +103,29 @@ CBotInstr* CBotExprRetVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bMeth
} }
else else
{ {
CBotVariable *preVar = var; CBotTypResult preVal = val;
CBotVar* preVal = val; CBotVariable *var = val.GetClass()->GetItem(p->GetString());
var = val->GetItem(p->GetString());
val = var ? var->m_value.get() : nullptr;
if (val != nullptr) if (var != nullptr)
{ {
val = var->m_value->GetTypResult();
CBotFieldExpr* i = new CBotFieldExpr(var->GetFieldPosition()); CBotFieldExpr* i = new CBotFieldExpr(var->GetFieldPosition());
i->SetToken(pp); i->SetToken(pp);
inst->AddNext3(i); inst->AddNext3(i);
if (CBotFieldExpr::CheckProtectionError(pStk, preVal, (preVar ? preVar->GetName() : ""), var)) // TODO: can "super" accesses occur here? Check for them. (3rd parameter)
if (CBotFieldExpr::CheckProtectionError(pStk, preVal, "", var))
{ {
pStk->SetError(CBotErrPrivate, pp); pStk->SetError(CBotErrPrivate, pp);
goto err; goto err;
} }
} }
else
{
val = CBotTypResult(CBotTypVoid); // indicate error
}
} }
if (val != nullptr) if (val.GetType() != CBotTypVoid)
{ {
p = p->GetNext(); p = p->GetNext();
continue; continue;
@ -138,7 +140,7 @@ CBotInstr* CBotExprRetVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bMeth
break; break;
} }
pStk->SetCopyVar(val); pStk->SetVarType(val);
if (pStk->IsOk()) return pStack->Return(inst, pStk); if (pStk->IsOk()) return pStack->Return(inst, pStk);
pStk->SetError(CBotErrUndefVar, p); pStk->SetError(CBotErrUndefVar, p);

View File

@ -57,15 +57,15 @@ CBotInstr* CBotExprUnaire::Compile(CBotToken* &p, CBotCStack* pStack, bool bLite
if (inst->m_expr != nullptr) if (inst->m_expr != nullptr)
{ {
if (op == ID_ADD && pStk->GetType() < CBotTypBoolean) // only with the number if (op == ID_ADD && pStk->GetVarType().GetType() < CBotTypBoolean) // only with the number
return pStack->Return(inst, pStk); return pStack->Return(inst, pStk);
if (op == ID_SUB && pStk->GetType() < CBotTypBoolean) // only with the numer if (op == ID_SUB && pStk->GetVarType().GetType() < CBotTypBoolean) // only with the numer
return pStack->Return(inst, pStk); return pStack->Return(inst, pStk);
if (op == ID_NOT && pStk->GetType() < CBotTypFloat) // only with an integer if (op == ID_NOT && pStk->GetVarType().GetType() < CBotTypFloat) // only with an integer
return pStack->Return(inst, pStk); return pStack->Return(inst, pStk);
if (op == ID_LOG_NOT && pStk->GetTypResult().Eq(CBotTypBoolean))// only with boolean if (op == ID_LOG_NOT && pStk->GetVarType().Eq(CBotTypBoolean))// only with boolean
return pStack->Return(inst, pStk); return pStack->Return(inst, pStk);
if (op == ID_TXT_NOT && pStk->GetTypResult().Eq(CBotTypBoolean))// only with boolean if (op == ID_TXT_NOT && pStk->GetVarType().Eq(CBotTypBoolean))// only with boolean
return pStack->Return(inst, pStk); return pStack->Return(inst, pStk);
pStk->SetError(CBotErrBadType1, &inst->m_token); pStk->SetError(CBotErrBadType1, &inst->m_token);

View File

@ -64,7 +64,7 @@ CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bCheckRe
{ {
if (var->GetContainingClass() != nullptr) // implicit "this" access if (var->GetContainingClass() != nullptr) // implicit "this" access
{ {
if (CBotFieldExpr::CheckProtectionError(pStk, nullptr, "", var, bCheckReadOnly)) if (CBotFieldExpr::CheckProtectionError(pStk, CBotTypVoid, "", var, bCheckReadOnly))
{ {
pStk->SetError(CBotErrPrivate, p); pStk->SetError(CBotErrPrivate, p);
goto err; goto err;
@ -121,7 +121,7 @@ CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bCheckRe
{ {
if (bCheckReadOnly) goto err; // don't allow increment a method call "++" if (bCheckReadOnly) goto err; // don't allow increment a method call "++"
CBotInstr* i = CBotInstrMethode::Compile(p, pStk, var->m_value.get(), false, CBotInstr* i = CBotInstrMethode::Compile(p, pStk, var->m_value->GetTypResult(), false,
var->GetContainingClass() == nullptr && var->GetName() == "super"); var->GetContainingClass() == nullptr && var->GetName() == "super");
if (!pStk->IsOk()) goto err; if (!pStk->IsOk()) goto err;
inst->AddNext3(i); // added after inst->AddNext3(i); // added after
@ -136,7 +136,7 @@ CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bCheckRe
CBotFieldExpr* i = new CBotFieldExpr(var->GetFieldPosition()); // new element CBotFieldExpr* i = new CBotFieldExpr(var->GetFieldPosition()); // new element
i->SetToken(pp); // keeps the name of the token i->SetToken(pp); // keeps the name of the token
inst->AddNext3(i); // add after inst->AddNext3(i); // add after
if (CBotFieldExpr::CheckProtectionError(pStk, preVar->m_value.get(), preVar->GetName(), var, bCheckReadOnly)) if (CBotFieldExpr::CheckProtectionError(pStk, preVar->m_value->GetTypResult(), preVar->GetName(), var, bCheckReadOnly))
{ {
pStk->SetError(CBotErrPrivate, pp); pStk->SetError(CBotErrPrivate, pp);
goto err; goto err;
@ -161,7 +161,7 @@ CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bCheckRe
break; break;
} }
pStk->SetCopyVar(var->m_value.get()); // place the copy of the variable on the stack (for type) pStk->SetVarType(var->m_value->GetTypResult());
if (pStk->IsOk()) return pStack->Return(inst, pStk); if (pStk->IsOk()) return pStack->Return(inst, pStk);
} }
pStk->SetError(CBotErrUndefVar, p); pStk->SetError(CBotErrUndefVar, p);
@ -203,7 +203,7 @@ CBotInstr* CBotExprVar::CompileMethode(CBotToken* &p, CBotCStack* pStack)
{ {
if (pp->GetNext()->GetType() == ID_OPENPAR) // a method call? if (pp->GetNext()->GetType() == ID_OPENPAR) // a method call?
{ {
CBotInstr* i = CBotInstrMethode::Compile(pp, pStk, var->m_value.get(), false, CBotInstr* i = CBotInstrMethode::Compile(pp, pStk, var->m_value->GetTypResult(), false,
var->GetContainingClass() == nullptr && var->GetName() == "super"); var->GetContainingClass() == nullptr && var->GetName() == "super");
if (pStk->IsOk()) if (pStk->IsOk())
{ {

View File

@ -85,7 +85,7 @@ CBotInstr* CBotExpression::Compile(CBotToken* &p, CBotCStack* pStack)
return nullptr; return nullptr;
} }
CBotTypResult type1 = pStack->GetTypResult(); CBotTypResult type1 = pStack->GetVarType();
// get the variable assigned to mark // get the variable assigned to mark
CBotVar* var = nullptr; CBotVar* var = nullptr;

View File

@ -151,7 +151,7 @@ std::string CBotFieldExpr::GetDebugData()
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool CBotFieldExpr::CheckProtectionError(CBotCStack* pStack, CBotVar* pPrev, const std::string &prevName, CBotVariable* pVar, bool bCheckReadOnly) bool CBotFieldExpr::CheckProtectionError(CBotCStack* pStack, CBotTypResult prevType, const std::string &prevName, CBotVariable* pVar, bool bCheckReadOnly)
{ {
CBotVariable::ProtectionLevel varPriv = pVar->GetPrivate(); CBotVariable::ProtectionLevel varPriv = pVar->GetPrivate();
@ -162,8 +162,8 @@ bool CBotFieldExpr::CheckProtectionError(CBotCStack* pStack, CBotVar* pPrev, con
// TODO: can we refactor this? // TODO: can we refactor this?
// implicit 'this.'var, this.var, or super.var // implicit 'this.' var (prevType is void meaning no value), this.var, or super.var
if (pPrev == nullptr || prevName == "this" || prevName == "super") // member of the current class if (prevType.GetType() == CBotTypVoid || prevName == "this" || prevName == "super") // member of the current class
{ {
if (varPriv == CBotVariable::ProtectionLevel::Private) // var is private ? if (varPriv == CBotVariable::ProtectionLevel::Private) // var is private ?
{ {
@ -193,11 +193,12 @@ bool CBotFieldExpr::CheckProtectionError(CBotCStack* pStack, CBotVar* pPrev, con
CBotClass* pClass = pThis->m_value->GetClass(); // the current class CBotClass* pClass = pThis->m_value->GetClass(); // the current class
if (!pClass->IsChildOf(pPrev->GetClass())) // var is member of some other class ? // TODO: Is this rule for 'protected' accurate? See how it works in Java for example.
if (!pClass->IsChildOf(prevType.GetClass())) // var is member of some other class ?
return true; return true;
if (varPriv == CBotVariable::ProtectionLevel::Private && // private member of a parent class if (varPriv == CBotVariable::ProtectionLevel::Private && // private member of a parent class
pClass != pPrev->GetClass()) return true; pClass != prevType.GetClass()) return true;
} }
} }

View File

@ -71,13 +71,13 @@ public:
* This function doesn't set the error flag itself. * This function doesn't set the error flag itself.
* *
* \param pStack Current compilation stack frame * \param pStack Current compilation stack frame
* \param pPrev Class instance which variable to check is part of, or nullptr when compiler inserts 'this.' before * \param prevType Type of class instance which variable to check is part of, or void when compiler inserts 'this.' before
* \param prevName Name of class instance. This is only used to check if it's "this" or "super". * \param prevName Name of class instance. This is only used to check if it's "this" or "super".
* \param pVar Variable to check * \param pVar Variable to check
* \param bCheckReadOnly True for operations that would modify the value of the variable * \param bCheckReadOnly True for operations that would modify the value of the variable
* \return true if pVar is inaccessible in the current context, false if access should be allowed * \return true if pVar is inaccessible in the current context, false if access should be allowed
*/ */
static bool CheckProtectionError(CBotCStack* pStack, CBotVar* pPrev, const std::string &prevName, CBotVariable* pVar, bool bCheckReadOnly = false); static bool CheckProtectionError(CBotCStack* pStack, CBotTypResult prevType, const std::string &prevName, CBotVariable* pVar, bool bCheckReadOnly = false);
protected: protected:
virtual const std::string GetDebugName() override { return "CBotFieldExpr"; } virtual const std::string GetDebugName() override { return "CBotFieldExpr"; }

View File

@ -464,7 +464,7 @@ void CBotFunction::RestoreState(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInst
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
CBotTypResult CBotFunction::CompileCall(const std::list<CBotFunction*>& localFunctionList, const std::string &name, CBotVar** ppVars, long &nIdent) CBotTypResult CBotFunction::CompileCall(const std::list<CBotFunction*>& localFunctionList, const std::string &name, const std::vector<CBotTypResult> &ppVars, long &nIdent)
{ {
CBotTypResult type; CBotTypResult type;
if (!FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type)) if (!FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type))
@ -477,7 +477,7 @@ CBotTypResult CBotFunction::CompileCall(const std::list<CBotFunction*>& localFun
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name, CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name,
CBotVar** ppVars, CBotTypResult &TypeOrError, bool bPublic) const std::vector<CBotTypResult> &ppVars, CBotTypResult &TypeOrError, bool bPublic)
{ {
TypeOrError.SetType(CBotErrUndefCall); // no routine of the name TypeOrError.SetType(CBotErrUndefCall); // no routine of the name
@ -511,20 +511,24 @@ CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& lo
{ {
if ( pt->m_token.GetString() == name ) if ( pt->m_token.GetString() == name )
{ {
int i = 0; size_t i = 0;
int alpha = 0; // signature of parameters int alpha = 0; // signature of parameters
// parameters are compatible? // parameters are compatible?
CBotDefParam* pv = pt->m_param; // expected list of parameters CBotDefParam* pv = pt->m_param; // expected list of parameters
CBotVar* pw = ppVars[i++]; // provided list parameter CBotTypResult pw; // provided list parameter
while ( pv != nullptr && (pw != nullptr || pv->HasDefault()) ) while ( pv != nullptr && (i < ppVars.size() || pv->HasDefault()) )
{ {
if (pw == nullptr) // end of arguments if (i >= ppVars.size()) // end of arguments
{ {
i++;
pv = pv->GetNext(); pv = pv->GetNext();
continue; // skip params with default values continue; // skip params with default values
} }
pw = ppVars[i++];
CBotTypResult paramType = pv->GetTypResult(); CBotTypResult paramType = pv->GetTypResult();
CBotTypResult argType = pw->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC); CBotTypResult argType = pw;
if(argType.GetType() == CBotTypClass)
argType.SetType(CBotTypIntrinsic);
if (!TypesCompatibles(paramType, argType)) if (!TypesCompatibles(paramType, argType))
{ {
@ -544,13 +548,12 @@ CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& lo
} }
else else
{ {
int d = pv->GetType() - pw->GetType(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC); int d = pv->GetType() - argType.GetType();
alpha += d>0 ? d : -10*d; // quality loss, 10 times more expensive! alpha += d>0 ? d : -10*d; // quality loss, 10 times more expensive!
} }
pv = pv->GetNext(); pv = pv->GetNext();
pw = ppVars[i++];
} }
if ( pw != nullptr ) if ( i < ppVars.size() )
{ {
if ( !funcMap.empty() ) continue; if ( !funcMap.empty() ) continue;
if ( TypeOrError.Eq(CBotErrLowParam) ) TypeOrError.SetType(CBotErrNbParam); if ( TypeOrError.Eq(CBotErrLowParam) ) TypeOrError.SetType(CBotErrNbParam);
@ -574,20 +577,24 @@ CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& lo
{ {
if ( pt->m_token.GetString() == name ) if ( pt->m_token.GetString() == name )
{ {
int i = 0; size_t i = 0;
int alpha = 0; // signature of parameters int alpha = 0; // signature of parameters
// parameters sont-ils compatibles ? // parameters sont-ils compatibles ?
CBotDefParam* pv = pt->m_param; // list of expected parameters CBotDefParam* pv = pt->m_param; // list of expected parameters
CBotVar* pw = ppVars[i++]; // list of provided parameters CBotTypResult pw; // list of provided parameters
while ( pv != nullptr && (pw != nullptr || pv->HasDefault()) ) while ( pv != nullptr && (i < ppVars.size() || pv->HasDefault()) )
{ {
if (pw == nullptr) // end of arguments if (i >= ppVars.size()) // end of arguments
{ {
i++;
pv = pv->GetNext(); pv = pv->GetNext();
continue; // skip params with default values continue; // skip params with default values
} }
pw = ppVars[i++];
CBotTypResult paramType = pv->GetTypResult(); CBotTypResult paramType = pv->GetTypResult();
CBotTypResult argType = pw->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC); CBotTypResult argType = pw;
if(argType.GetType() == CBotTypClass)
argType.SetType(CBotTypIntrinsic);
if (!TypesCompatibles(paramType, argType)) if (!TypesCompatibles(paramType, argType))
{ {
@ -607,13 +614,12 @@ CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& lo
} }
else else
{ {
int d = pv->GetType() - pw->GetType(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC); int d = pv->GetType() - argType.GetType();
alpha += d>0 ? d : -10*d; // quality loss, 10 times more expensive! alpha += d>0 ? d : -10*d; // quality loss, 10 times more expensive!
} }
pv = pv->GetNext(); pv = pv->GetNext();
pw = ppVars[i++];
} }
if ( pw != nullptr ) if ( i < ppVars.size() )
{ {
if ( !funcMap.empty() ) continue; // previous useable function if ( !funcMap.empty() ) continue; // previous useable function
if ( TypeOrError.Eq(CBotErrLowParam) ) TypeOrError.SetType(CBotErrNbParam); if ( TypeOrError.Eq(CBotErrLowParam) ) TypeOrError.SetType(CBotErrNbParam);
@ -659,6 +665,26 @@ CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& lo
return nullptr; return nullptr;
} }
////////////////////////////////////////////////////////////////////////////////
static std::vector<CBotTypResult> argTypesToVector(CBotVar** ppVars)
{
int count = 0;
while (ppVars[count] != nullptr)
count++;
std::vector<CBotTypResult> result;
result.reserve(count);
count = 0;
while (ppVars[count] != nullptr)
{
result.emplace_back(ppVars[count]->GetTypResult());
count++;
}
return result;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int CBotFunction::DoCall(CBotProgram* program, const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name, int CBotFunction::DoCall(CBotProgram* program, const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name,
CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken) CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken)
@ -667,7 +693,7 @@ int CBotFunction::DoCall(CBotProgram* program, const std::list<CBotFunction*>& l
CBotFunction* pt = nullptr; CBotFunction* pt = nullptr;
CBotProgram* baseProg = pStack->GetProgram(true); CBotProgram* baseProg = pStack->GetProgram(true);
pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type); pt = FindLocalOrPublic(localFunctionList, nIdent, name, argTypesToVector(ppVars), type);
if ( pt != nullptr ) if ( pt != nullptr )
{ {
@ -757,7 +783,7 @@ void CBotFunction::RestoreCall(const std::list<CBotFunction*>& localFunctionList
CBotStack* pStk3; CBotStack* pStk3;
CBotProgram* baseProg = pStack->GetProgram(true); CBotProgram* baseProg = pStack->GetProgram(true);
pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type); pt = FindLocalOrPublic(localFunctionList, nIdent, name, argTypesToVector(ppVars), type);
if ( pt != nullptr ) if ( pt != nullptr )
{ {
@ -820,7 +846,7 @@ int CBotFunction::DoCall(const std::list<CBotFunction*>& localFunctionList, long
CBotTypResult type; CBotTypResult type;
CBotProgram* pProgCurrent = pStack->GetProgram(); CBotProgram* pProgCurrent = pStack->GetProgram();
CBotFunction* pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type, false); CBotFunction* pt = FindLocalOrPublic(localFunctionList, nIdent, name, argTypesToVector(ppVars), type, false);
if ( pt != nullptr ) if ( pt != nullptr )
{ {
@ -918,7 +944,7 @@ bool CBotFunction::RestoreCall(const std::list<CBotFunction*>& localFunctionList
CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass) CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass)
{ {
CBotTypResult type; CBotTypResult type;
CBotFunction* pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type); CBotFunction* pt = FindLocalOrPublic(localFunctionList, nIdent, name, argTypesToVector(ppVars), type);
if ( pt != nullptr ) if ( pt != nullptr )
{ {

View File

@ -107,13 +107,14 @@ public:
* *
* \param localFunctionList Linked list of local functions to search in, can be null * \param localFunctionList Linked list of local functions to search in, can be null
* \param name Name of the function * \param name Name of the function
* \param ppVars List of function arguments * \param ppVars List of function argument types
* \param nIdent[in, out] Unique identifier of the function * \param nIdent[in, out] Unique identifier of the function
* \return Type returned by the function or error code * \return Type returned by the function or error code
* \see FindLocalOrPublic * \see FindLocalOrPublic
*/ */
static CBotTypResult CompileCall(const std::list<CBotFunction*>& localFunctionList, static CBotTypResult CompileCall(const std::list<CBotFunction*>& localFunctionList,
const std::string &name, CBotVar** ppVars, long &nIdent); const std::string &name,
const std::vector<CBotTypResult> &ppVars, long &nIdent);
/*! /*!
* \brief Finds a local or public function * \brief Finds a local or public function
@ -126,13 +127,13 @@ public:
* \param localFunctionList Linked list of local functions to search in, can be null * \param localFunctionList Linked list of local functions to search in, can be null
* \param nIdent[in, out] Unique identifier of the function * \param nIdent[in, out] Unique identifier of the function
* \param name Name of the function * \param name Name of the function
* \param ppVars List of function arguments * \param ppVars List of function argument types
* \param TypeOrError Type returned by the function or error code * \param TypeOrError Type returned by the function or error code
* \param bPublic Whether to look in public functions or not * \param bPublic Whether to look in public functions or not
* \return Pointer to found CBotFunction instance, or nullptr in case of no match or ambiguity (see TypeOrError for error code) * \return Pointer to found CBotFunction instance, or nullptr in case of no match or ambiguity (see TypeOrError for error code)
*/ */
static CBotFunction* FindLocalOrPublic(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name, static CBotFunction* FindLocalOrPublic(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name,
CBotVar** ppVars, CBotTypResult &TypeOrError, bool bPublic = true); const std::vector<CBotTypResult> &ppVars, CBotTypResult &TypeOrError, bool bPublic = true);
/*! /*!
* \brief DoCall Fait un appel à une fonction. * \brief DoCall Fait un appel à une fonction.

View File

@ -57,7 +57,7 @@ CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
if (p->GetType() == ID_OPENPAR) if (p->GetType() == ID_OPENPAR)
{ {
CBotVar* ppVars[1000]; std::vector<CBotTypResult> ppVars;
CBotInstrCall* inst = new CBotInstrCall(); CBotInstrCall* inst = new CBotInstrCall();
inst->SetToken(pp); inst->SetToken(pp);
@ -86,10 +86,9 @@ CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
pStack->DeleteChildLevels(); pStack->DeleteChildLevels();
if ( inst->m_typRes.GetType() > 0 ) if ( inst->m_typRes.GetType() > 0 )
{ {
std::unique_ptr<CBotVar> pRes = CBotVar::Create(inst->m_typRes); pStack->SetVarType(inst->m_typRes); // for knowing the type of the result
pStack->SetVar(std::move(pRes)); // for knowing the type of the result
} }
else pStack->SetVar(nullptr); // routine returns void else pStack->SetVarType(CBotTypVoid); // routine returns void
if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStack, 0, false))) if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStack, 0, false)))
{ {

View File

@ -49,7 +49,7 @@ CBotInstrMethode::~CBotInstrMethode()
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotInstrMethode::Compile(CBotToken* &p, CBotCStack* pStack, CBotVar* var, bool bMethodChain, bool bIsSuperCall) CBotInstr* CBotInstrMethode::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResult varType, bool bMethodChain, bool bIsSuperCall)
{ {
CBotInstrMethode* inst = new CBotInstrMethode(); CBotInstrMethode* inst = new CBotInstrMethode();
inst->SetToken(p); // corresponding token inst->SetToken(p); // corresponding token
@ -62,15 +62,15 @@ CBotInstr* CBotInstrMethode::Compile(CBotToken* &p, CBotCStack* pStack, CBotVar*
inst->m_methodName = pp->GetString(); inst->m_methodName = pp->GetString();
// compiles the list of parameters // compiles the list of parameters
CBotVar* ppVars[1000]; std::vector<CBotTypResult> ppVars;
inst->m_parameters = CompileParams(p, pStack, ppVars); inst->m_parameters = CompileParams(p, pStack, ppVars);
if (pStack->IsOk()) if (pStack->IsOk())
{ {
CBotClass* pClass = var->GetClass(); // pointer to the class CBotClass* pClass = varType.GetClass(); // pointer to the class
inst->m_className = pClass->GetName(); // name of the class inst->m_className = pClass->GetName(); // name of the class
inst->m_bNonVirtualCall = bIsSuperCall; inst->m_bNonVirtualCall = bIsSuperCall;
CBotTypResult r = pClass->CompileMethode(pp, var, ppVars, pStack, inst->m_MethodeIdent); CBotTypResult r = pClass->CompileMethode(pp, varType, ppVars, pStack, inst->m_MethodeIdent);
pStack->DeleteChildLevels(); // release parameters on the stack pStack->DeleteChildLevels(); // release parameters on the stack
inst->m_typRes = r; inst->m_typRes = r;
@ -83,14 +83,9 @@ CBotInstr* CBotInstrMethode::Compile(CBotToken* &p, CBotCStack* pStack, CBotVar*
// put the result on the stack to have something // put the result on the stack to have something
if (inst->m_typRes.GetType() > 0) if (inst->m_typRes.GetType() > 0)
{ {
std::unique_ptr<CBotVar> pResult = CBotVar::Create(inst->m_typRes); pStack->SetVarType(inst->m_typRes);
if (inst->m_typRes.Eq(CBotTypClass))
{
pResult->SetClass(inst->m_typRes.GetClass());
}
pStack->SetVar(std::move(pResult));
} }
else pStack->SetVar(nullptr); else pStack->SetVarType(CBotTypResult(CBotTypVoid));
pp = p; pp = p;
if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStack, bMethodChain, false))) if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStack, bMethodChain, false)))

View File

@ -37,12 +37,12 @@ public:
* \brief Compile * \brief Compile
* \param p * \param p
* \param pStack * \param pStack
* \param pVar * \param varType Type of object method is being called on
* \param bMethodChain If true, allows chaining methods only * \param bMethodChain If true, allows chaining methods only
* \param bIsSuperCall If true, don't do a virtual call * \param bIsSuperCall If true, don't do a virtual call
* \return * \return
*/ */
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, CBotVar* pVar, bool bMethodChain, bool bIsSuperCall); static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResult varType, bool bMethodChain, bool bIsSuperCall);
/*! /*!
* \brief Execute * \brief Execute

View File

@ -31,13 +31,14 @@ namespace CBot
{ {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars) CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, std::vector<CBotTypResult> &ppVars)
{ {
bool first = true; bool first = true;
CBotInstr* ret = nullptr; // to return to the list CBotInstr* ret = nullptr; // to return to the list
CBotCStack* pile = pStack; CBotCStack* pile = pStack;
int i = 0;
ppVars.clear();
if (IsOfType(p, ID_OPENPAR)) if (IsOfType(p, ID_OPENPAR))
{ {
@ -63,16 +64,15 @@ CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars)
if (param != nullptr) if (param != nullptr)
{ {
if (pile->GetTypResult().Eq(99)) if (pile->GetVarType().Eq(99))
{ {
pStack->DeleteChildLevels(); pStack->DeleteChildLevels();
pStack->SetError(CBotErrVoid, p->GetStart()); pStack->SetError(CBotErrVoid, p->GetStart());
return nullptr; return nullptr;
} }
ppVars[i] = pile->GetVar(); ppVars.emplace_back(pile->GetVarType());
// TODO: was commented out as part of value/variable refactor. What does this do? // TODO: was commented out as part of value/variable refactor. What does this do?
(void)end; //ppVars[i]->GetToken()->SetPos(start, end); (void)end; //ppVars[i]->GetToken()->SetPos(start, end);
i++;
if (IsOfType(p, ID_COMMA)) continue; // skips the comma if (IsOfType(p, ID_COMMA)) continue; // skips the comma
if (IsOfType(p, ID_CLOSEPAR)) break; if (IsOfType(p, ID_CLOSEPAR)) break;
@ -83,7 +83,6 @@ CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars)
return nullptr; return nullptr;
} }
} }
ppVars[i] = nullptr;
return ret; return ret;
} }
@ -93,9 +92,11 @@ bool TypeCompatible(CBotTypResult& type1, CBotTypResult& type2, int op)
int t1 = type1.GetType(); int t1 = type1.GetType();
int t2 = type2.GetType(); int t2 = type2.GetType();
int max = (t1 > t2) ? t1 : t2; // void used to be 99 here due to special handling in CBotCStack; now it's 0
if (t1 == CBotTypVoid || t2 == CBotTypVoid)
return false; // result is void?
if (max == 99) return false; // result is void? int max = (t1 > t2) ? t1 : t2;
// special case for strin concatenation // special case for strin concatenation
if (op == ID_ADD && t1 == CBotTypString) return true; if (op == ID_ADD && t1 == CBotTypString) return true;

View File

@ -19,6 +19,8 @@
#pragma once #pragma once
#include <vector>
namespace CBot namespace CBot
{ {
@ -32,10 +34,10 @@ class CBotTypResult;
* \brief CompileParams Compile a list of parameters. * \brief CompileParams Compile a list of parameters.
* \param p * \param p
* \param pStack * \param pStack
* \param ppVars * \param ppVars [out] types of parameters
* \return * \return
*/ */
CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars); CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, std::vector<CBotTypResult> &ppVars);
/*! /*!
* \brief TypeCompatible Check if two results are consistent to make an * \brief TypeCompatible Check if two results are consistent to make an

View File

@ -62,7 +62,7 @@ CBotLeftExpr* CBotLeftExpr::Compile(CBotToken* &p, CBotCStack* pStack)
{ {
if (var->GetContainingClass() != nullptr) if (var->GetContainingClass() != nullptr)
{ {
if (CBotFieldExpr::CheckProtectionError(pStk, nullptr, "", var, true)) if (CBotFieldExpr::CheckProtectionError(pStk, CBotTypVoid, "", var, true))
{ {
pStk->SetError(CBotErrPrivate, p); pStk->SetError(CBotErrPrivate, p);
goto err; goto err;
@ -122,7 +122,7 @@ CBotLeftExpr* CBotLeftExpr::Compile(CBotToken* &p, CBotCStack* pStack)
var = var->m_value->GetItem(p->GetString()); // get item correspondent var = var->m_value->GetItem(p->GetString()); // get item correspondent
if (var != nullptr) if (var != nullptr)
{ {
if (CBotFieldExpr::CheckProtectionError(pStk, preVar->m_value.get(), preVar->GetName(), var, true)) if (CBotFieldExpr::CheckProtectionError(pStk, preVar->m_value->GetTypResult(), preVar->GetName(), var, true))
{ {
pStk->SetError(CBotErrPrivate, pp); pStk->SetError(CBotErrPrivate, pp);
goto err; goto err;

View File

@ -72,7 +72,7 @@ CBotInstr* CBotListArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResu
if (pStk->IsOk()) if (pStk->IsOk())
{ {
inst->m_expr = CBotTwoOpExpr::Compile(p, pStk); inst->m_expr = CBotTwoOpExpr::Compile(p, pStk);
if (inst->m_expr == nullptr || !pStk->GetTypResult().Compare(type)) // compatible type ? if (inst->m_expr == nullptr || !pStk->GetVarType().Compare(type)) // compatible type ?
{ {
pStk->SetError(CBotErrBadType1, p->GetStart()); pStk->SetError(CBotErrBadType1, p->GetStart());
goto error; goto error;
@ -90,7 +90,7 @@ CBotInstr* CBotListArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResu
if (pStk->IsOk()) if (pStk->IsOk())
{ {
i = CBotTwoOpExpr::Compile(p, pStk); i = CBotTwoOpExpr::Compile(p, pStk);
if (i == nullptr || !pStk->GetTypResult().Compare(type)) // compatible type ? if (i == nullptr || !pStk->GetVarType().Compare(type)) // compatible type ?
{ {
pStk->SetError(CBotErrBadType1, p->GetStart()); pStk->SetError(CBotErrBadType1, p->GetStart());
goto error; goto error;
@ -115,7 +115,9 @@ CBotInstr* CBotListArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResu
goto error; goto error;
} }
CBotTypResult valType = pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC); CBotTypResult valType = pStk->GetVarType();
if(valType.GetType() == CBotTypClass)
valType.SetType(CBotTypIntrinsic);
if (!TypeCompatible(valType, type, ID_ASS) ) if (!TypeCompatible(valType, type, ID_ASS) )
{ {
@ -133,7 +135,9 @@ CBotInstr* CBotListArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResu
goto error; goto error;
} }
CBotTypResult valType = pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC); CBotTypResult valType = pStk->GetVarType();
if(valType.GetType() == CBotTypClass)
valType.SetType(CBotTypIntrinsic);
if (!TypeCompatible(valType, type, ID_ASS) ) if (!TypeCompatible(valType, type, ID_ASS) )
{ {

View File

@ -75,24 +75,23 @@ CBotInstr* CBotNew::Compile(CBotToken* &p, CBotCStack* pStack)
// creates the object on the stack // creates the object on the stack
// with a pointer to the object // with a pointer to the object
std::unique_ptr<CBotVar> pVar = CBotVar::Create(CBotTypResult(CBotTypClass, pClass)); CBotTypResult pVar(CBotTypPointer, pClass);
// do the call of the creator // do the call of the creator
CBotCStack* pStk = pStack->TokenStack(); CBotCStack* pStk = pStack->TokenStack();
{ {
// check if there are parameters // check if there are parameters
CBotVar* ppVars[1000]; std::vector<CBotTypResult> ppVars;
inst->m_parameters = CompileParams(p, pStk, ppVars); inst->m_parameters = CompileParams(p, pStk, ppVars);
if (!pStk->IsOk()) goto error; if (!pStk->IsOk()) goto error;
// constructor exist? // constructor exist?
CBotTypResult r = pClass->CompileMethode(&inst->m_vartoken, pVar.get(), ppVars, pStk, inst->m_nMethodeIdent); CBotTypResult r = pClass->CompileMethode(&inst->m_vartoken, pVar, ppVars, pStk, inst->m_nMethodeIdent);
pStk->DeleteChildLevels(); // release extra stack pStk->DeleteChildLevels(); // release extra stack
int typ = r.GetType(); int typ = r.GetType();
// if there is no constructor, and no parameters either, it's ok // if there is no constructor, and no parameters either, it's ok
if (typ == CBotErrUndefCall && inst->m_parameters == nullptr) typ = 0; if (typ == CBotErrUndefCall && inst->m_parameters == nullptr) typ = 0;
pVar->SetInit(CBotVar::InitType::DEF); // mark the instance as init
if (typ>20) if (typ>20)
{ {
@ -108,7 +107,7 @@ CBotInstr* CBotNew::Compile(CBotToken* &p, CBotCStack* pStack)
} }
// makes pointer to the object on the stack // makes pointer to the object on the stack
pStk->SetVar(std::move(pVar)); pStk->SetVarType(pVar);
pp = p; pp = p;
// chained method ? // chained method ?

View File

@ -94,7 +94,9 @@ CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack)
delete inst; delete inst;
p = pvar; p = pvar;
inst = CBotExprVar::Compile(p, pStk, true); inst = CBotExprVar::Compile(p, pStk, true);
if (pStk->GetType() >= CBotTypBoolean) // TODO: is there a possibility that something like ((((i++)++)++)++)... will recurse exponentially?
// since each X++ parses X twice (once with bCheckReadOnly=false, once with true)
if (pStk->GetVarType().GetType() >= CBotTypBoolean || pStk->GetVarType().GetType() == CBotTypVoid)
{ {
pStk->SetError(CBotErrBadType1, pp); pStk->SetError(CBotErrBadType1, pp);
delete inst; delete inst;
@ -118,7 +120,7 @@ CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack)
{ {
if (nullptr != (inst = CBotExprVar::Compile(p, pStk, true))) if (nullptr != (inst = CBotExprVar::Compile(p, pStk, true)))
{ {
if (pStk->GetType() < CBotTypBoolean) // a number ? if (pStk->GetVarType().GetType() < CBotTypBoolean) // a number ?
{ {
CBotPreIncExpr* i = new CBotPreIncExpr(); CBotPreIncExpr* i = new CBotPreIncExpr();
i->SetToken(pp); i->SetToken(pp);
@ -183,8 +185,7 @@ CBotInstr* CBotParExpr::CompileLitExpr(CBotToken* &p, CBotCStack* pStack)
{ {
CBotInstr* inst = new CBotExprLitNull(); CBotInstr* inst = new CBotExprLitNull();
inst->SetToken(pp); inst->SetToken(pp);
std::unique_ptr<CBotVar> var = CBotVar::Create(CBotTypNullPointer); pStk->SetVarType(CBotTypNullPointer);
pStk->SetVar(std::move(var));
return pStack->Return(inst, pStk); return pStack->Return(inst, pStk);
} }
@ -193,10 +194,7 @@ CBotInstr* CBotParExpr::CompileLitExpr(CBotToken* &p, CBotCStack* pStack)
{ {
CBotInstr* inst = new CBotExprLitNan(); CBotInstr* inst = new CBotExprLitNan();
inst->SetToken(pp); inst->SetToken(pp);
// XXX: Why is NAN an int? pStk->SetVarType(CBotTypInt);
std::unique_ptr<CBotVar> var = CBotVar::Create(CBotTypInt);
var->SetInit(CBotVar::InitType::IS_NAN);
pStk->SetVar(std::move(var));
return pStack->Return(inst, pStk); return pStack->Return(inst, pStk);
} }

View File

@ -63,7 +63,9 @@ CBotInstr* CBotReturn::Compile(CBotToken* &p, CBotCStack* pStack)
inst->m_instr = CBotExpression::Compile(p, pStack); inst->m_instr = CBotExpression::Compile(p, pStack);
if ( pStack->IsOk() ) if ( pStack->IsOk() )
{ {
CBotTypResult retType = pStack->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC); CBotTypResult retType = pStack->GetVarType();
if(retType.GetType() == CBotTypClass)
retType.SetType(CBotTypIntrinsic);
if (TypeCompatible(retType, type, ID_ASS)) if (TypeCompatible(retType, type, ID_ASS))
{ {
if ( IsOfType( p, ID_SEP ) ) if ( IsOfType( p, ID_SEP ) )

View File

@ -57,7 +57,7 @@ CBotInstr* CBotSwitch::Compile(CBotToken* &p, CBotCStack* pStack)
{ {
if ( nullptr != (inst->m_value = CBotExpression::Compile(p, pStk )) ) if ( nullptr != (inst->m_value = CBotExpression::Compile(p, pStk )) )
{ {
if ( pStk->GetType() < CBotTypLong ) if ( pStk->GetVarType().GetType() < CBotTypLong )
{ {
if ( IsOfType(p, ID_CLOSEPAR ) ) if ( IsOfType(p, ID_CLOSEPAR ) )
{ {

View File

@ -52,7 +52,7 @@ CBotInstr* CBotThrow::Compile(CBotToken* &p, CBotCStack* pStack)
inst->m_value = CBotExpression::Compile(p, pStack ); inst->m_value = CBotExpression::Compile(p, pStack );
if (pStack->GetType() < CBotTypLong && pStack->IsOk()) if (pStack->GetVarType().GetType() < CBotTypLong && pStack->IsOk())
{ {
return inst; // return an object to the application return inst; // return an object to the application
} }

View File

@ -156,7 +156,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
if ( IsInList(typeOp, pOperations, typeMask) ) if ( IsInList(typeOp, pOperations, typeMask) )
{ {
CBotTypResult type1, type2; CBotTypResult type1, type2;
type1 = pStk->GetTypResult(); // what kind of the first operand? type1 = pStk->GetVarType(); // what kind of the first operand?
if (typeOp == ID_LOGIC) // special case provided for: ? op1: op2; if (typeOp == ID_LOGIC) // special case provided for: ? op1: op2;
{ {
@ -177,7 +177,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
delete inst; delete inst;
return pStack->Return(nullptr, pStk); return pStack->Return(nullptr, pStk);
} }
type1 = pStk->GetTypResult(); type1 = pStk->GetVarType();
inst->m_op2 = CBotExpression::Compile(p, pStk); inst->m_op2 = CBotExpression::Compile(p, pStk);
if ( inst->m_op2 == nullptr ) if ( inst->m_op2 == nullptr )
@ -186,7 +186,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
delete inst; delete inst;
return pStack->Return(nullptr, pStk); return pStack->Return(nullptr, pStk);
} }
type2 = pStk->GetTypResult(); type2 = pStk->GetVarType();
if (!TypeCompatible(type1, type2)) if (!TypeCompatible(type1, type2))
{ {
pStk->SetError( CBotErrBadType2, pp ); pStk->SetError( CBotErrBadType2, pp );
@ -194,7 +194,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
return pStack->Return(nullptr, pStk); return pStack->Return(nullptr, pStk);
} }
pStk->SetType(type1); // the greatest of 2 types pStk->SetVarType(type1); // the greatest of 2 types
return pStack->Return(inst, pStk); return pStack->Return(inst, pStk);
} }
@ -212,7 +212,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
{ {
// there is an second operand acceptable // there is an second operand acceptable
type2 = pStk->GetTypResult(); // what kind of results? type2 = pStk->GetVarType(); // what kind of results?
if ( type1.Eq(99) || type2.Eq(99) ) // operand is void if ( type1.Eq(99) || type2.Eq(99) ) // operand is void
{ {
@ -265,7 +265,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
p = p->GetNext(); // advance after p = p->GetNext(); // advance after
i->m_rightop = CBotTwoOpExpr::Compile( p, pStk, pOp ); i->m_rightop = CBotTwoOpExpr::Compile( p, pStk, pOp );
type2 = pStk->GetTypResult(); type2 = pStk->GetVarType();
if ( !TypeCompatible (type1, type2, typeOp) ) // the results are compatible if ( !TypeCompatible (type1, type2, typeOp) ) // the results are compatible
{ {
@ -280,9 +280,9 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
} }
CBotTypResult t(type1); CBotTypResult t(type1);
t.SetType(TypeRes); t.SetType(TypeRes);
// is a variable on the stack for the type of result // is a variable on the stack for the type of result
pStk->SetVar(CBotVar::Create(t)); pStk->SetVarType(t);
// and returns the requested object // and returns the requested object
return pStack->Return(inst, pStk); return pStack->Return(inst, pStk);

View File

@ -296,10 +296,11 @@ bool CBotProgram::ClassExists(std::string name)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static CBotTypResult cSizeOf( CBotVar* &pVar, void* pUser ) static CBotTypResult cSizeOf( const std::vector<CBotTypResult> &pVar, void* pUser )
{ {
if ( pVar == nullptr ) return CBotTypResult( CBotErrLowParam ); if ( pVar.size() == 0 ) return CBotTypResult( CBotErrLowParam );
if ( pVar->GetType() != CBotTypArrayPointer ) // TODO: check for too many parameters
if ( pVar[0].GetType() != CBotTypArrayPointer )
return CBotTypResult( CBotErrBadParam ); return CBotTypResult( CBotErrBadParam );
return CBotTypResult( CBotTypInt ); return CBotTypResult( CBotTypInt );
} }
@ -315,7 +316,7 @@ static bool rSizeOf( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool CBotProgram::AddFunction(const std::string& name, bool CBotProgram::AddFunction(const std::string& name,
bool rExec(CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser), bool rExec(CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
CBotTypResult rCompile(CBotVar*& pVar, void* pUser)) CBotTypResult rCompile(const std::vector<CBotTypResult> &pVar, void* pUser))
{ {
return m_externalCalls->AddFunction(name, std::unique_ptr<CBotExternalCall>(new CBotExternalCallDefault(rExec, rCompile))); return m_externalCalls->AddFunction(name, std::unique_ptr<CBotExternalCall>(new CBotExternalCallDefault(rExec, rCompile)));
} }

View File

@ -275,7 +275,7 @@ public:
*/ */
static bool AddFunction(const std::string& name, static bool AddFunction(const std::string& name,
bool rExec(CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser), bool rExec(CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
CBotTypResult rCompile(CBotVar*& pVar, void* pUser)); CBotTypResult rCompile(const std::vector<CBotTypResult> &pVar, void* pUser));
/** /**
* \copydoc CBotToken::DefineNum() * \copydoc CBotToken::DefineNum()

View File

@ -198,7 +198,7 @@ std::string CBotTypResult::ToString()
return ss.str(); return ss.str();
} }
bool CBotTypResult::IsSpecifiedClassOrSubclass(const std::string& name) bool CBotTypResult::IsSpecifiedClassOrSubclass(const std::string& name) const
{ {
if ( m_type != CBotTypPointer && m_type != CBotTypClass ) if ( m_type != CBotTypPointer && m_type != CBotTypClass )
{ {

View File

@ -167,7 +167,7 @@ public:
* \param name Class name to check * \param name Class name to check
* \return true if this type matches the given class or any of its subclasses * \return true if this type matches the given class or any of its subclasses
*/ */
bool IsSpecifiedClassOrSubclass(const std::string& name); bool IsSpecifiedClassOrSubclass(const std::string& name) const;
/** /**
* \brief Copy * \brief Copy

View File

@ -26,216 +26,198 @@ namespace CBot
// Compiling a procedure without any parameters. // Compiling a procedure without any parameters.
CBotTypResult cNull(CBotVar* &var, void* user) CBotTypResult cNull(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var != nullptr ) return CBotErrOverParam; if ( var.size() > 0 ) return CBotErrOverParam;
return CBotTypResult(CBotTypFloat); return CBotTypFloat;
} }
// Compiling a procedure with a single real number. // Compiling a procedure with a single real number.
CBotTypResult cOneFloat(CBotVar* &var, void* user) CBotTypResult cOneFloat(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() < 1 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
var = var->GetNext(); if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat); return CBotTypFloat;
} }
// Compiling a procedure with two real numbers. // Compiling a procedure with two real numbers.
CBotTypResult cTwoFloat(CBotVar* &var, void* user) CBotTypResult cTwoFloat(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() < 2 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); return CBotTypFloat;
return CBotTypResult(CBotTypFloat);
} }
// Compiling a procedure with a single string. // Compiling a procedure with a single string.
CBotTypResult cString(CBotVar* &var, void* user) CBotTypResult cString(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() < 1 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() != CBotTypString && if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); if ( var[0].GetType() != CBotTypString &&
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
return CBotTypResult(CBotTypFloat);
return CBotTypFloat;
} }
// Compiling a procedure with a single string, returning string. // Compiling a procedure with a single string, returning string.
CBotTypResult cStringString(CBotVar* &var, void* user) CBotTypResult cStringString(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() < 1 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() != CBotTypString && if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[0].GetType() != CBotTypString &&
var = var->GetNext(); var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypString); return CBotTypString;
} }
// compilation of instruction with one int returning int // compilation of instruction with one int returning int
CBotTypResult cOneInt(CBotVar* &var, void* user) CBotTypResult cOneInt(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() < 1 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum); if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
var = var->GetNext(); if ( var[0].GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum);
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); return CBotTypInt;
return CBotTypResult(CBotTypInt);
} }
// compilation of instruction with one int returning boolean // compilation of instruction with one int returning boolean
CBotTypResult cOneIntReturnBool(CBotVar* &var, void* user) CBotTypResult cOneIntReturnBool(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() < 1 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum); if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
var = var->GetNext(); if ( var[0].GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum);
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); return CBotTypBoolean;
return CBotTypResult(CBotTypBoolean);
} }
CBotTypResult cStrStr(CBotVar*& var, void* user) CBotTypResult cStrStr(const std::vector<CBotTypResult> &var, void* user)
{ {
// it takes a parameter // it takes a parameter
if ( var == nullptr ) return CBotTypResult( CBotErrLowParam ); if ( var.size() < 1 ) return CBotTypResult(CBotErrLowParam);
// no second parameter
if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
// to be a string // to be a string
if ( var->GetType() != CBotTypString ) if ( var[0].GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString ); return CBotTypResult( CBotErrBadString );
// no second parameter
if ( var->GetNext() != nullptr ) return CBotTypResult( CBotErrOverParam );
// the end result is a string // the end result is a string
return CBotTypResult( CBotTypString ); return CBotTypString;
} }
CBotTypResult cIntStrStr(CBotVar*& var, void* user) CBotTypResult cIntStrStr(const std::vector<CBotTypResult> &var, void* user)
{ {
// it takes a parameter // it takes a parameter
if ( var == nullptr ) return CBotTypResult( CBotErrLowParam );
// to be a string
if ( var->GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
// it takes a second parameter // it takes a second parameter
var = var->GetNext(); if ( var.size() < 2 ) return CBotTypResult(CBotErrLowParam);
if ( var == nullptr ) return CBotTypResult( CBotErrLowParam );
// to be a string
if ( var->GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
// no third parameter // no third parameter
if ( var->GetNext() != nullptr ) return CBotTypResult( CBotErrOverParam ); if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
// the end result is a number
return CBotTypResult( CBotTypInt );
}
CBotTypResult cFloatStr(CBotVar*& var, void* user)
{
// it takes a parameter
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam );
// to be a string // to be a string
if ( var->GetType() != CBotTypString ) if ( var[0].GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString ); return CBotTypResult( CBotErrBadString );
// no second parameter // to be a string
if ( var->GetNext() != nullptr ) return CBotTypResult( CBotErrOverParam ); if ( var[1].GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
// the end result is a number // the end result is a number
return CBotTypResult( CBotTypFloat ); return CBotTypInt;
} }
CBotTypResult cStrStrIntInt(CBotVar*& var, void* user) CBotTypResult cFloatStr(const std::vector<CBotTypResult> &var, void* user)
{ {
// it takes a parameter // it takes a parameter
if ( var == nullptr ) return CBotTypResult( CBotErrLowParam ); if ( var.size() < 1 ) return CBotTypResult(CBotErrLowParam);
// no second parameter
if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
// to be a string // to be a string
if ( var->GetType() != CBotTypString ) if ( var[0].GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
// the end result is a number
return CBotTypFloat;
}
CBotTypResult cStrStrIntInt(const std::vector<CBotTypResult> &var, void* user)
{
// it takes a parameter
// it takes a second parameter
if ( var.size() < 2 ) return CBotTypResult( CBotErrLowParam );
// to be a string
if ( var[0].GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString ); return CBotTypResult( CBotErrBadString );
// it takes a second parameter // it takes a second parameter
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult( CBotErrLowParam );
// which must be a number // which must be a number
if ( var->GetType() > CBotTypDouble ) if ( var[1].GetType() > CBotTypDouble )
return CBotTypResult( CBotErrBadNum ); return CBotTypResult( CBotErrBadNum );
// third parameter optional // third parameter optional
if ( var->GetNext() != nullptr ) if ( var.size() > 2 )
{ {
var = var->GetNext();
// which must be a number // which must be a number
if ( var->GetType() > CBotTypDouble ) if ( var[2].GetType() > CBotTypDouble )
return CBotTypResult( CBotErrBadNum ); return CBotTypResult( CBotErrBadNum );
// no fourth parameter // no fourth parameter
if ( var->GetNext() != nullptr ) return CBotTypResult( CBotErrOverParam ); if ( var.size() > 3 ) return CBotTypResult( CBotErrOverParam );
} }
// the end result is a string // the end result is a string
return CBotTypResult( CBotTypString ); return CBotTypString;
} }
CBotTypResult cStrStrInt(CBotVar*& var, void* user) CBotTypResult cStrStrInt(const std::vector<CBotTypResult> &var, void* user)
{ {
// it takes a parameter // it takes a parameter
if ( var == nullptr ) return CBotTypResult( CBotErrLowParam ); // it takes a second parameter
if ( var.size() < 2 ) return CBotTypResult( CBotErrLowParam );
// no third parameter
if ( var.size() > 2 ) return CBotTypResult( CBotErrOverParam );
// to be a string // to be a string
if ( var->GetType() != CBotTypString ) if ( var[0].GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString ); return CBotTypResult( CBotErrBadString );
// it takes a second parameter // it takes a second parameter
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult( CBotErrLowParam );
// which must be a number // which must be a number
if ( var->GetType() > CBotTypDouble ) if ( var[1].GetType() > CBotTypDouble )
return CBotTypResult( CBotErrBadNum ); return CBotTypResult( CBotErrBadNum );
// no third parameter
if ( var->GetNext() != nullptr ) return CBotTypResult( CBotErrOverParam );
// the end result is a string // the end result is a string
return CBotTypResult( CBotTypString ); return CBotTypString;
} }
CBotTypResult cIntStr(CBotVar*& var, void* user) CBotTypResult cIntStr(const std::vector<CBotTypResult> &var, void* user)
{ {
// it takes a parameter // it takes a parameter
if ( var == nullptr ) return CBotTypResult( CBotErrLowParam ); if ( var.size() < 1 ) return CBotTypResult( CBotErrLowParam );
// no second parameter
if ( var.size() > 1 ) return CBotTypResult( CBotErrOverParam );
// to be a string // to be a string
if ( var->GetType() != CBotTypString ) if ( var[0].GetType() != CBotTypString )
return CBotTypResult( CBotErrBadParam ); return CBotTypResult( CBotErrBadParam );
// no second parameter
if ( var->GetNext() != nullptr ) return CBotTypResult( CBotErrOverParam );
// the end result is an integer // the end result is an integer
return CBotTypResult( CBotTypInt ); return CBotTypInt;
} }
} // namespace CBot } // namespace CBot

View File

@ -20,6 +20,7 @@
#pragma once #pragma once
#include "CBot/CBotTypResult.h" #include "CBot/CBotTypResult.h"
#include <vector>
namespace CBot namespace CBot
{ {
@ -30,32 +31,32 @@ class CBotVar;
// type "number" is anything > CBotTypDouble // type "number" is anything > CBotTypDouble
// float foo() // float foo()
CBotTypResult cNull(CBotVar* &var, void* user); CBotTypResult cNull(const std::vector<CBotTypResult> &var, void* user);
// float foo(number) // float foo(number)
CBotTypResult cOneFloat(CBotVar* &var, void* user); CBotTypResult cOneFloat(const std::vector<CBotTypResult> &var, void* user);
// float foo(number, number) // float foo(number, number)
CBotTypResult cTwoFloat(CBotVar* &var, void* user); CBotTypResult cTwoFloat(const std::vector<CBotTypResult> &var, void* user);
// float foo(string) // float foo(string)
CBotTypResult cString(CBotVar* &var, void* user); CBotTypResult cString(const std::vector<CBotTypResult> &var, void* user);
// string foo(string) // string foo(string)
CBotTypResult cStringString(CBotVar* &var, void* user); CBotTypResult cStringString(const std::vector<CBotTypResult> &var, void* user);
// int foo(int) // int foo(int)
CBotTypResult cOneInt(CBotVar* &var, void* user); CBotTypResult cOneInt(const std::vector<CBotTypResult> &var, void* user);
// bool foo(int) // bool foo(int)
CBotTypResult cOneIntReturnBool(CBotVar* &var, void* user); CBotTypResult cOneIntReturnBool(const std::vector<CBotTypResult> &var, void* user);
// string foo(string) // string foo(string)
CBotTypResult cStrStr(CBotVar*& var, void* user); CBotTypResult cStrStr(const std::vector<CBotTypResult> &var, void* user);
// int foo(string, string) // int foo(string, string)
CBotTypResult cIntStrStr(CBotVar*& var, void* user); CBotTypResult cIntStrStr(const std::vector<CBotTypResult> &var, void* user);
// float foo(string) // float foo(string)
CBotTypResult cFloatStr(CBotVar*& var, void* user); CBotTypResult cFloatStr(const std::vector<CBotTypResult> &var, void* user);
// string foo(string, number[, number]) // string foo(string, number[, number])
CBotTypResult cStrStrIntInt(CBotVar*& var, void* user); CBotTypResult cStrStrIntInt(const std::vector<CBotTypResult> &var, void* user);
// string foo(string, number) // string foo(string, number)
CBotTypResult cStrStrInt(CBotVar*& var, void* user); CBotTypResult cStrStrInt(const std::vector<CBotTypResult> &var, void* user);
// int foo(string) // int foo(string)
CBotTypResult cIntStr(CBotVar*& var, void* user); CBotTypResult cIntStr(const std::vector<CBotTypResult> &var, void* user);
} // namespace CBot } // namespace CBot

View File

@ -97,28 +97,27 @@ bool rfconstruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exceptio
} }
// compilation // compilation
CBotTypResult cfconstruct (CBotVar* pThis, CBotVar* &pVar) CBotTypResult cfconstruct (CBotTypResult pThis, const std::vector<CBotTypResult> &pVar)
{ {
// accepts no parameters // accepts no parameters
if ( pVar == nullptr ) return CBotTypResult( 0 ); if ( pVar.size() == 0 ) return CBotTypResult( 0 );
// must be a character string // must be a character string
if ( pVar->GetType() != CBotTypString ) if ( pVar[0].GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString ); return CBotTypResult( CBotErrBadString );
// there may be a second parameter // there may be a second parameter
pVar = pVar->GetNext(); if ( pVar.size() > 1 )
if ( pVar != nullptr )
{ {
// which must be a string // which must be a string
if ( pVar->GetType() != CBotTypString ) if ( pVar[1].GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString ); return CBotTypResult( CBotErrBadString );
// no third parameter // no third parameter
if ( pVar->GetNext() != nullptr ) return CBotTypResult( CBotErrOverParam ); if ( pVar.size() > 2 ) return CBotTypResult( CBotErrOverParam );
} }
// the result is void (constructor) // the result is void (constructor)
return CBotTypResult( 0 ); return CBotTypVoid;
} }
@ -153,25 +152,24 @@ bool rfopen (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, vo
} }
// compilation // compilation
CBotTypResult cfopen (CBotVar* pThis, CBotVar* &pVar) CBotTypResult cfopen (CBotTypResult pThis, const std::vector<CBotTypResult> &pVar)
{ {
// there must be a parameter // there must be a parameter
if ( pVar == nullptr ) return CBotTypResult( CBotErrLowParam ); if ( pVar.size() == 0 ) return CBotTypResult( CBotErrLowParam );
// which must be a string // which must be a string
if ( pVar->GetType() != CBotTypString ) if ( pVar[0].GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString ); return CBotTypResult( CBotErrBadString );
// there may be a second parameter // there may be a second parameter
pVar = pVar->GetNext(); if ( pVar.size() > 1 )
if ( pVar != nullptr )
{ {
// which must be a string // which must be a string
if ( pVar->GetType() != CBotTypString ) if ( pVar[1].GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString ); return CBotTypResult( CBotErrBadString );
// no third parameter // no third parameter
if ( pVar->GetNext() != nullptr ) return CBotTypResult( CBotErrOverParam ); if ( pVar.size() > 2 ) return CBotTypResult( CBotErrOverParam );
} }
// the result is bool // the result is bool
@ -208,13 +206,13 @@ bool rfclose (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, v
} }
// compilation // compilation
CBotTypResult cfclose (CBotVar* pThis, CBotVar* &pVar) CBotTypResult cfclose (CBotTypResult pThis, const std::vector<CBotTypResult> &pVar)
{ {
// it shouldn't be any parameters // it shouldn't be any parameters
if ( pVar != nullptr ) return CBotTypResult( CBotErrOverParam ); if ( pVar.size() > 0 ) return CBotTypResult( CBotErrOverParam );
// function returns a result "void" // function returns a result "void"
return CBotTypResult( 0 ); return CBotTypVoid;
} }
// process FILE :: writeln // process FILE :: writeln
@ -253,19 +251,19 @@ bool rfwrite (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, v
} }
// compilation // compilation
CBotTypResult cfwrite (CBotVar* pThis, CBotVar* &pVar) CBotTypResult cfwrite (CBotTypResult pThis, const std::vector<CBotTypResult> &pVar)
{ {
// there must be a parameter // there must be a parameter
if ( pVar == nullptr ) return CBotTypResult( CBotErrLowParam ); if ( pVar.size() == 0 ) return CBotTypResult( CBotErrLowParam );
// which must be a character string // which must be a character string
if ( pVar->GetType() != CBotTypString ) return CBotTypResult( CBotErrBadString ); if ( pVar[0].GetType() != CBotTypString ) return CBotTypResult( CBotErrBadString );
// no other parameter // no other parameter
if ( pVar->GetNext() != nullptr ) return CBotTypResult( CBotErrOverParam ); if ( pVar.size() > 1 ) return CBotTypResult( CBotErrOverParam );
// the function returns a void result // the function returns a void result
return CBotTypResult( 0 ); return CBotTypVoid;
} }
// process FILE :: readln // process FILE :: readln
@ -301,13 +299,13 @@ bool rfread(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, voi
} }
// compilation // compilation
CBotTypResult cfread (CBotVar* pThis, CBotVar* &pVar) CBotTypResult cfread (CBotTypResult pThis, const std::vector<CBotTypResult> &pVar)
{ {
// it should not be any parameter // it should not be any parameter
if ( pVar != nullptr ) return CBotTypResult( CBotErrOverParam ); if ( pVar.size() > 0 ) return CBotTypResult( CBotErrOverParam );
// function returns a result "string" // function returns a result "string"
return CBotTypResult( CBotTypString ); return CBotTypString;
} }
// process FILE :: readln // process FILE :: readln
@ -338,13 +336,13 @@ bool rfeof (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, voi
} }
// compilation // compilation
CBotTypResult cfeof (CBotVar* pThis, CBotVar* &pVar) CBotTypResult cfeof (CBotTypResult pThis, const std::vector<CBotTypResult> &pVar)
{ {
// it shouldn't be any parameter // it shouldn't be any parameter
if ( pVar != nullptr ) return CBotTypResult( CBotErrOverParam ); if ( pVar.size() > 0 ) return CBotTypResult( CBotErrOverParam );
// the function returns a boolean result // the function returns a boolean result
return CBotTypResult( CBotTypBoolean ); return CBotTypBoolean;
} }
// Instruction "deletefile(filename)". // Instruction "deletefile(filename)".

View File

@ -69,39 +69,36 @@
using namespace CBot; using namespace CBot;
CBotTypResult CScriptFunctions::cClassNull(CBotVar* thisclass, CBotVar* &var) CBotTypResult CScriptFunctions::cClassNull(CBotTypResult thisType, const std::vector<CBotTypResult> &var)
{ {
return cNull(var, nullptr); return cNull(var, nullptr);
} }
CBotTypResult CScriptFunctions::cClassOneFloat(CBotVar* thisclass, CBotVar* &var) CBotTypResult CScriptFunctions::cClassOneFloat(CBotTypResult thisType, const std::vector<CBotTypResult> &var)
{ {
return cOneFloat(var, nullptr); return cOneFloat(var, nullptr);
} }
// Compile a parameter of type "point". // Compile a parameter of type "point".
static CBotTypResult cPoint(CBotVar* &var, void* user) static CBotTypResult cPoint(const std::vector<CBotTypResult> &var, size_t &pos, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() <= pos ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() <= CBotTypDouble ) if ( var[pos].GetType() <= CBotTypDouble )
{ {
var = var->GetNext(); if ( var.size() < pos+2 ) return CBotTypResult(CBotErrLowParam);
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); pos++;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); pos++;
//? if ( var == 0 ) return CBotTypResult(CBotErrLowParam); return CBotTypVoid;
//? if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
//? var = var->GetNext();
return CBotTypResult(0);
} }
if ( var->GetType() == CBotTypClass ) if ( var[pos].GetType() == CBotTypClass )
{ {
if ( !var->GetTypResult().IsSpecifiedClassOrSubclass("point") ) return CBotTypResult(CBotErrBadParam); if ( !var[pos].IsSpecifiedClassOrSubclass("point") ) return CBotTypResult(CBotErrBadParam);
var = var->GetNext(); pos++;
return CBotTypResult(0); return CBotTypVoid;
} }
return CBotTypResult(CBotErrBadParam); return CBotTypResult(CBotErrBadParam);
@ -109,15 +106,16 @@ static CBotTypResult cPoint(CBotVar* &var, void* user)
// Compiling a procedure with a single "point". // Compiling a procedure with a single "point".
CBotTypResult CScriptFunctions::cOnePoint(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cOnePoint(const std::vector<CBotTypResult> &var, void* user)
{ {
CBotTypResult ret; CBotTypResult ret;
ret = cPoint(var, user); size_t pos = 0;
if ( ret.GetType() != 0 ) return ret; ret = cPoint(var, pos, user);
if ( ret.GetType() != CBotTypVoid ) return ret;
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); if ( pos < var.size() ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat); return CBotTypFloat;
} }
// Gives a parameter of type "point". // Gives a parameter of type "point".
@ -167,16 +165,13 @@ static bool GetPoint(CBotVar* &var, int& exception, Math::Vector& pos)
// Compilation of the instruction "endmission(result, delay)" // Compilation of the instruction "endmission(result, delay)"
CBotTypResult CScriptFunctions::cEndMission(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cEndMission(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() < 2 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
var = var->GetNext(); if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); return CBotTypFloat;
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat);
} }
// Instruction "endmission(result, delay)" // Instruction "endmission(result, delay)"
@ -197,16 +192,13 @@ bool CScriptFunctions::rEndMission(CBotVar* var, CBotVar* result, int& exception
// Compilation of the instruction "playmusic(filename, repeat)" // Compilation of the instruction "playmusic(filename, repeat)"
CBotTypResult CScriptFunctions::cPlayMusic(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cPlayMusic(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() < 2 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadNum); if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
var = var->GetNext(); if ( var[0].GetType() != CBotTypString ) return CBotTypResult(CBotErrBadNum);
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); return CBotTypFloat;
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat);
} }
// Instruction "playmusic(filename, repeat)" // Instruction "playmusic(filename, repeat)"
@ -291,12 +283,11 @@ bool CScriptFunctions::rSetResearchDone(CBotVar* var, CBotVar* result, int& exce
// Compilation of the instruction "retobject(rank)". // Compilation of the instruction "retobject(rank)".
CBotTypResult CScriptFunctions::cGetObject(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cGetObject(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() < 1 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
var = var->GetNext(); if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypPointer, "object"); return CBotTypResult(CBotTypPointer, "object");
} }
@ -345,10 +336,10 @@ bool CScriptFunctions::rGetObject(CBotVar* var, CBotVar* result, int& exception,
} }
// Compilation of instruction "object.busy()" // Compilation of instruction "object.busy()"
CBotTypResult CScriptFunctions::cBusy(CBotVar* thisclass, CBotVar* &var) CBotTypResult CScriptFunctions::cBusy(CBotTypResult thisclass, const std::vector<CBotTypResult> &var)
{ {
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); if ( var.size() > 0 ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypBoolean); return CBotTypBoolean;
} }
// Instruction "object.busy()" // Instruction "object.busy()"
@ -417,16 +408,14 @@ bool CScriptFunctions::rDestroy(CBotVar* thisclass, CBotVar* var, CBotVar* resul
// Compilation of instruction "object.factory(cat, program)" // Compilation of instruction "object.factory(cat, program)"
CBotTypResult CScriptFunctions::cFactory(CBotVar* thisclass, CBotVar* &var) CBotTypResult CScriptFunctions::cFactory(CBotTypResult thisclass, const std::vector<CBotTypResult> &var)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); if ( var.size() > 1 )
if ( var != nullptr )
{ {
if ( var->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadNum); if ( var[1].GetType() != CBotTypString ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
} }
return CBotTypResult(CBotTypFloat); return CBotTypResult(CBotTypFloat);
} }
@ -624,20 +613,18 @@ bool CScriptFunctions::rTakeOff(CBotVar* thisclass, CBotVar* var, CBotVar* resul
// Compilation of the instruction "delete(rank[, exploType])". // Compilation of the instruction "delete(rank[, exploType])".
CBotTypResult CScriptFunctions::cDelete(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cDelete(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum); if ( var[0].GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) if ( var.size() > 1 )
{ {
if ( var->GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum); if ( var[1].GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
} }
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat); return CBotTypResult(CBotTypFloat);
} }
@ -689,46 +676,47 @@ bool CScriptFunctions::rDelete(CBotVar* var, CBotVar* result, int& exception, vo
return false; return false;
} }
static CBotTypResult compileSearch(CBotVar* &var, void* user, CBotTypResult returnValue) static CBotTypResult compileSearch(const std::vector<CBotTypResult> &var, void* user, CBotTypResult returnValue)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); size_t pos = 0;
if ( var->GetType() == CBotTypArrayPointer ) if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
if ( var[pos].GetType() == CBotTypArrayPointer )
{ {
CBotTypResult type = var->GetTypResult().GetTypElem(); CBotTypResult type = var[pos].GetTypElem();
if ( type.GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadParam); // type if ( type.GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadParam); // type
} }
else if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type else if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type
var = var->GetNext(); pos++;
if ( var == nullptr ) return returnValue; if ( pos >= var.size() ) return returnValue;
CBotTypResult ret = cPoint(var, user); // pos CBotTypResult ret = cPoint(var, pos, user); // pos
if ( ret.GetType() != 0 ) return ret; if ( ret.GetType() != 0 ) return ret;
if ( var == nullptr ) return returnValue; if ( pos >= var.size() ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // min if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // min
var = var->GetNext(); pos++;
if ( var == nullptr ) return returnValue; if ( pos >= var.size() ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // max if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // max
var = var->GetNext(); pos++;
if ( var == nullptr ) return returnValue; if ( pos >= var.size() ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // sense if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // sense
var = var->GetNext(); pos++;
if ( var == nullptr ) return returnValue; if ( pos >= var.size() ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // filter if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // filter
var = var->GetNext(); pos++;
if ( var == nullptr ) return returnValue; if ( pos >= var.size() ) return returnValue;
return CBotTypResult(CBotErrOverParam); return CBotTypResult(CBotErrOverParam);
} }
// Compilation of "search(type, pos, min, max, sens, filter)". // Compilation of "search(type, pos, min, max, sens, filter)".
CBotTypResult CScriptFunctions::cSearch(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cSearch(const std::vector<CBotTypResult> &var, void* user)
{ {
return compileSearch(var, user, CBotTypResult(CBotTypPointer, "object")); return compileSearch(var, user, CBotTypResult(CBotTypPointer, "object"));
} }
CBotTypResult CScriptFunctions::cSearchAll(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cSearchAll(const std::vector<CBotTypResult> &var, void* user)
{ {
return compileSearch(var, user, CBotTypResult(CBotTypArrayPointer, CBotTypResult(CBotTypPointer, "object"))); return compileSearch(var, user, CBotTypResult(CBotTypArrayPointer, CBotTypResult(CBotTypPointer, "object")));
} }
@ -837,47 +825,46 @@ bool CScriptFunctions::rSearchAll(CBotVar* var, CBotVar* result, int& exception,
} }
static CBotTypResult compileRadar(CBotVar* &var, void* user, CBotTypResult returnValue) static CBotTypResult compileRadar(const std::vector<CBotTypResult> &var, void* user, CBotTypResult returnValue)
{ {
if ( var == nullptr ) return returnValue; size_t pos = 0;
if ( var->GetType() == CBotTypArrayPointer ) if ( pos >= var.size() ) return returnValue;
if ( var[pos].GetType() == CBotTypArrayPointer )
{ {
CBotVariable *arrayElement = var->GetItem(0, false); if ( var[0].GetTypElem().GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type
if ( arrayElement == nullptr ) return returnValue;
if ( arrayElement->m_value->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type
} }
else if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type else if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type
var = var->GetNext(); pos++;
if ( var == nullptr ) return returnValue; if ( pos >= var.size() ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // angle if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // angle
var = var->GetNext(); pos++;
if ( var == nullptr ) return returnValue; if ( pos >= var.size() ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // focus if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // focus
var = var->GetNext(); pos++;
if ( var == nullptr ) return returnValue; if ( pos >= var.size() ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // min if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // min
var = var->GetNext(); pos++;
if ( var == nullptr ) return returnValue; if ( pos >= var.size() ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // max if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // max
var = var->GetNext(); pos++;
if ( var == nullptr ) return returnValue; if ( pos >= var.size() ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // sense if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // sense
var = var->GetNext(); pos++;
if ( var == nullptr ) return returnValue; if ( pos >= var.size() ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // filter if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // filter
var = var->GetNext(); pos++;
if ( var == nullptr ) return returnValue; if ( pos >= var.size() ) return returnValue;
return CBotTypResult(CBotErrOverParam); return CBotTypResult(CBotErrOverParam);
} }
CBotTypResult CScriptFunctions::cRadarAll(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cRadarAll(const std::vector<CBotTypResult> &var, void* user)
{ {
return compileRadar(var, user, CBotTypResult(CBotTypArrayPointer, CBotTypResult(CBotTypPointer, "object"))); return compileRadar(var, user, CBotTypResult(CBotTypArrayPointer, CBotTypResult(CBotTypPointer, "object")));
} }
// Compilation of instruction "radar(type, angle, focus, min, max, sens)". // Compilation of instruction "radar(type, angle, focus, min, max, sens)".
CBotTypResult CScriptFunctions::cRadar(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cRadar(const std::vector<CBotTypResult> &var, void* user)
{ {
return compileRadar(var, user, CBotTypResult(CBotTypPointer, "object")); return compileRadar(var, user, CBotTypResult(CBotTypPointer, "object"));
} }
@ -1063,12 +1050,11 @@ bool CScriptFunctions::ShouldTaskStop(Error err, int errMode)
// Compilation of the instruction "detect(type)". // Compilation of the instruction "detect(type)".
CBotTypResult CScriptFunctions::cDetect(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cDetect(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() < 1 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
var = var->GetNext(); if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypBoolean); return CBotTypResult(CBotTypBoolean);
} }
@ -1143,16 +1129,17 @@ bool CScriptFunctions::rDetect(CBotVar* var, CBotVar* result, int& exception, vo
// Compilation of the instruction "direction(pos)". // Compilation of the instruction "direction(pos)".
CBotTypResult CScriptFunctions::cDirection(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cDirection(const std::vector<CBotTypResult> &var, void* user)
{ {
CBotTypResult ret; CBotTypResult ret;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, user); size_t pos = 0;
if ( ret.GetType() != 0 ) return ret; ret = cPoint(var, pos, user);
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); if ( ret.GetType() != CBotTypVoid ) return ret;
if ( pos >= var.size() ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat); return CBotTypFloat;
} }
// Instruction "direction(pos)". // Instruction "direction(pos)".
@ -1272,50 +1259,51 @@ bool CScriptFunctions::rBuild(CBotVar* var, CBotVar* result, int& exception, voi
// Compilation of the instruction "produce(pos, angle, type[, scriptName[, power]])" // Compilation of the instruction "produce(pos, angle, type[, scriptName[, power]])"
// or "produce(type[, power])". // or "produce(type[, power])".
CBotTypResult CScriptFunctions::cProduce(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cProduce(const std::vector<CBotTypResult> &var, void* user)
{ {
CBotTypResult ret; CBotTypResult ret;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() <= CBotTypDouble ) size_t pos = 0;
if ( var[pos].GetType() <= CBotTypDouble )
{ {
var = var->GetNext(); pos++;
if ( var != nullptr ) if ( pos < var.size() )
{ {
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); pos++;
} }
} }
else else
{ {
ret = cPoint(var, user); ret = cPoint(var, pos, user);
if ( ret.GetType() != 0 ) return ret; if ( ret.GetType() != CBotTypVoid ) return ret;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); pos++;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); pos++;
if ( var != nullptr ) if ( pos >= var.size() )
{ {
if ( var->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString); if ( var[pos].GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
var = var->GetNext(); pos++;
if ( var != nullptr ) if ( pos >= var.size() )
{ {
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); pos++;
} }
} }
} }
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); if ( pos >= var.size() ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat); return CBotTypFloat;
} }
// Instruction "produce(pos, angle, type[, scriptName[, power]])" // Instruction "produce(pos, angle, type[, scriptName[, power]])"
@ -1430,21 +1418,22 @@ bool CScriptFunctions::rProduce(CBotVar* var, CBotVar* result, int& exception, v
// Compilation of the instruction "distance(p1, p2)". // Compilation of the instruction "distance(p1, p2)".
CBotTypResult CScriptFunctions::cDistance(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cDistance(const std::vector<CBotTypResult> &var, void* user)
{ {
CBotTypResult ret; CBotTypResult ret;
size_t pos = 0;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, user); ret = cPoint(var, pos, user);
if ( ret.GetType() != 0 ) return ret; if ( ret.GetType() != CBotTypVoid ) return ret;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, user); ret = cPoint(var, pos, user);
if ( ret.GetType() != 0 ) return ret; if ( ret.GetType() != CBotTypVoid ) return ret;
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); if ( pos < var.size() ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat); return CBotTypFloat;
} }
// Instruction "distance(p1, p2)". // Instruction "distance(p1, p2)".
@ -1480,27 +1469,28 @@ bool CScriptFunctions::rDistance2d(CBotVar* var, CBotVar* result, int& exception
// Compilation of the instruction "space(center, rMin, rMax, dist)". // Compilation of the instruction "space(center, rMin, rMax, dist)".
CBotTypResult CScriptFunctions::cSpace(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cSpace(const std::vector<CBotTypResult> &var, void* user)
{ {
CBotTypResult ret; CBotTypResult ret;
if ( var == nullptr ) return CBotTypResult(CBotTypIntrinsic, "point"); size_t pos = 0;
ret = cPoint(var, user); if ( pos >= var.size() ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( ret.GetType() != 0 ) return ret; ret = cPoint(var, pos, user);
if ( ret.GetType() != CBotTypVoid ) return ret;
if ( var == nullptr ) return CBotTypResult(CBotTypIntrinsic, "point"); if ( pos >= var.size() ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); pos++;
if ( var == nullptr ) return CBotTypResult(CBotTypIntrinsic, "point"); if ( pos >= var.size() ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); pos++;
if ( var == nullptr ) return CBotTypResult(CBotTypIntrinsic, "point"); if ( pos >= var.size() ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); pos++;
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); if ( pos < var.size() ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypIntrinsic, "point"); return CBotTypResult(CBotTypIntrinsic, "point");
} }
@ -1561,31 +1551,32 @@ bool CScriptFunctions::rSpace(CBotVar* var, CBotVar* result, int& exception, voi
return true; return true;
} }
CBotTypResult CScriptFunctions::cFlatSpace(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cFlatSpace(const std::vector<CBotTypResult> &var, void* user)
{ {
CBotTypResult ret; CBotTypResult ret;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); size_t pos = 0;
ret = cPoint(var, user); if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, pos, user);
if ( ret.GetType() != 0 ) return ret; if ( ret.GetType() != 0 ) return ret;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); pos++;
if ( var == nullptr ) return CBotTypResult(CBotTypIntrinsic, "point"); if ( pos >= var.size() ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); pos++;
if ( var == nullptr ) return CBotTypResult(CBotTypIntrinsic, "point"); if ( pos >= var.size() ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); pos++;
if ( var == nullptr ) return CBotTypResult(CBotTypIntrinsic, "point"); if ( pos >= var.size() ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); pos++;
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); if ( pos < var.size() ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypIntrinsic, "point"); return CBotTypResult(CBotTypIntrinsic, "point");
} }
@ -1644,19 +1635,20 @@ bool CScriptFunctions::rFlatSpace(CBotVar* var, CBotVar* result, int& exception,
// Compilation of the instruction "flatground(center, rMax)". // Compilation of the instruction "flatground(center, rMax)".
CBotTypResult CScriptFunctions::cFlatGround(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cFlatGround(const std::vector<CBotTypResult> &var, void* user)
{ {
CBotTypResult ret; CBotTypResult ret;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); size_t pos = 0;
ret = cPoint(var, user); if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, pos, user);
if ( ret.GetType() != 0 ) return ret; if ( ret.GetType() != 0 ) return ret;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); pos++;
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); if ( pos < var.size() ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat); return CBotTypResult(CBotTypFloat);
} }
@ -1770,27 +1762,28 @@ bool CScriptFunctions::rTurn(CBotVar* var, CBotVar* result, int& exception, void
// Compilation of the instruction "goto(pos, altitude, crash, goal)". // Compilation of the instruction "goto(pos, altitude, crash, goal)".
CBotTypResult CScriptFunctions::cGoto(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cGoto(const std::vector<CBotTypResult> &var, void* user)
{ {
CBotTypResult ret; CBotTypResult ret;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); size_t pos = 0;
ret = cPoint(var, user); if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, pos, user);
if ( ret.GetType() != 0 ) return ret; if ( ret.GetType() != 0 ) return ret;
if ( var == nullptr ) return CBotTypResult(CBotTypFloat); if ( pos >= var.size() ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); pos++;
if ( var == nullptr ) return CBotTypResult(CBotTypFloat); if ( pos >= var.size() ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); pos++;
if ( var == nullptr ) return CBotTypResult(CBotTypFloat); if ( pos >= var.size() ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); pos++;
if ( var == nullptr ) return CBotTypResult(CBotTypFloat); if ( pos < var.size() ) return CBotTypResult(CBotTypFloat);
return CBotTypResult(CBotErrOverParam); return CBotTypResult(CBotErrOverParam);
} }
@ -1850,12 +1843,11 @@ bool CScriptFunctions::rGoto(CBotVar* var, CBotVar* result, int& exception, void
// Compilation "grab/drop(oper)". // Compilation "grab/drop(oper)".
CBotTypResult CScriptFunctions::cGrabDrop(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cGrabDrop(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotTypFloat); if ( var.size() == 0 ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat); return CBotTypResult(CBotTypFloat);
} }
@ -1980,17 +1972,15 @@ bool CScriptFunctions::rSniff(CBotVar* var, CBotVar* result, int& exception, voi
// Compilation of the instruction "receive(nom, power)". // Compilation of the instruction "receive(nom, power)".
CBotTypResult CScriptFunctions::cReceive(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cReceive(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString); if ( var[0].GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult(CBotTypFloat); if ( var.size() == 1 ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat); return CBotTypResult(CBotTypFloat);
} }
@ -2043,21 +2033,16 @@ bool CScriptFunctions::rReceive(CBotVar* var, CBotVar* result, int& exception, v
// Compilation of the instruction "send(nom, value, power)". // Compilation of the instruction "send(nom, value, power)".
CBotTypResult CScriptFunctions::cSend(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cSend(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() < 2 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString); if ( var.size() > 3 ) return CBotTypResult(CBotErrOverParam);
var = var->GetNext(); if ( var[0].GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() == 2 ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[2].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat); return CBotTypResult(CBotTypFloat);
} }
@ -2113,17 +2098,15 @@ CExchangePost* CScriptFunctions::FindExchangePost(CObject* object, float power)
// Compilation of the instruction "deleteinfo(name, power)". // Compilation of the instruction "deleteinfo(name, power)".
CBotTypResult CScriptFunctions::cDeleteInfo(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cDeleteInfo(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString); if ( var[0].GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult(CBotTypBoolean); if ( var.size() == 1 ) return CBotTypResult(CBotTypBoolean);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypBoolean); return CBotTypResult(CBotTypBoolean);
} }
@ -2159,17 +2142,15 @@ bool CScriptFunctions::rDeleteInfo(CBotVar* var, CBotVar* result, int& exception
// Compilation of the instruction "testinfo(nom, power)". // Compilation of the instruction "testinfo(nom, power)".
CBotTypResult CScriptFunctions::cTestInfo(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cTestInfo(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString); if ( var[0].GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult(CBotTypBoolean); if ( var.size() == 1 ) return CBotTypResult(CBotTypBoolean);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypBoolean); return CBotTypResult(CBotTypBoolean);
} }
@ -2258,17 +2239,12 @@ bool CScriptFunctions::rRecycle(CBotVar* var, CBotVar* result, int& exception, v
// Compilation "shield(oper, radius)". // Compilation "shield(oper, radius)".
CBotTypResult CScriptFunctions::cShield(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cShield(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() < 2 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
var = var->GetNext(); if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat); return CBotTypResult(CBotTypFloat);
} }
@ -2338,7 +2314,7 @@ bool CScriptFunctions::rShield(CBotVar* var, CBotVar* result, int& exception, vo
// Compilation "fire(delay)". // Compilation "fire(delay)".
CBotTypResult CScriptFunctions::cFire(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cFire(const std::vector<CBotTypResult> &var, void* user)
{ {
CObject* pThis = static_cast<CScript*>(user)->m_object; CObject* pThis = static_cast<CScript*>(user)->m_object;
ObjectType type; ObjectType type;
@ -2347,25 +2323,25 @@ CBotTypResult CScriptFunctions::cFire(CBotVar* &var, void* user)
if ( type == OBJECT_ANT ) if ( type == OBJECT_ANT )
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
CBotTypResult ret = cPoint(var, user); size_t pos = 0;
if ( ret.GetType() != 0 ) return ret; CBotTypResult ret = cPoint(var, pos, user);
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); if ( ret.GetType() != CBotTypVoid ) return ret;
if ( var.size() > pos ) return CBotTypResult(CBotErrOverParam);
} }
else if ( type == OBJECT_SPIDER ) else if ( type == OBJECT_SPIDER )
{ {
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); if ( var.size() > 0 ) return CBotTypResult(CBotErrOverParam);
} }
else else
{ {
if ( var != nullptr ) if ( var.size() > 0 )
{ {
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
} }
} }
return CBotTypResult(CBotTypFloat); return CBotTypFloat;
} }
// Instruction "fire(delay)". // Instruction "fire(delay)".
@ -2420,17 +2396,15 @@ bool CScriptFunctions::rFire(CBotVar* var, CBotVar* result, int& exception, void
// Compilation of the instruction "aim(x, y)". // Compilation of the instruction "aim(x, y)".
CBotTypResult CScriptFunctions::cAim(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cAim(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult(CBotTypFloat); if ( var.size() == 1 ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat); return CBotTypResult(CBotTypFloat);
} }
@ -2467,17 +2441,12 @@ bool CScriptFunctions::rAim(CBotVar* var, CBotVar* result, int& exception, void*
// Compilation of the instruction "motor(left, right)". // Compilation of the instruction "motor(left, right)".
CBotTypResult CScriptFunctions::cMotor(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cMotor(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() < 2 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
var = var->GetNext(); if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat); return CBotTypResult(CBotTypFloat);
} }
@ -2531,15 +2500,16 @@ bool CScriptFunctions::rJet(CBotVar* var, CBotVar* result, int& exception, void*
// Compilation of the instruction "topo(pos)". // Compilation of the instruction "topo(pos)".
CBotTypResult CScriptFunctions::cTopo(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cTopo(const std::vector<CBotTypResult> &var, void* user)
{ {
CBotTypResult ret; CBotTypResult ret;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, user); size_t pos = 0;
if ( ret.GetType() != 0 ) return ret; ret = cPoint(var, pos, user);
if ( ret.GetType() != CBotTypVoid ) return ret;
if ( var == nullptr ) return CBotTypResult(CBotTypFloat); if ( pos >= var.size() ) return CBotTypResult(CBotTypFloat);
return CBotTypResult(CBotErrOverParam); return CBotTypResult(CBotErrOverParam);
} }
@ -2563,18 +2533,16 @@ bool CScriptFunctions::rTopo(CBotVar* var, CBotVar* result, int& exception, void
// Compilation of the instruction "message(string, type)". // Compilation of the instruction "message(string, type)".
CBotTypResult CScriptFunctions::cMessage(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cMessage(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() != CBotTypString && if ( var[0].GetType() != CBotTypString &&
var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // TODO unhelpful error message
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult(CBotTypFloat); if ( var.size() == 1 ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult(CBotTypFloat); if ( var.size() == 2 ) return CBotTypResult(CBotTypFloat);
return CBotTypResult(CBotErrOverParam); return CBotTypResult(CBotErrOverParam);
} }
@ -2674,17 +2642,15 @@ bool CScriptFunctions::rAbsTime(CBotVar* var, CBotVar* result, int& exception, v
// Compilation of the instruction "pendown(color, width)". // Compilation of the instruction "pendown(color, width)".
CBotTypResult CScriptFunctions::cPenDown(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cPenDown(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotTypFloat); if ( var.size() == 0 ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult(CBotTypFloat); if ( var.size() == 1 ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult(CBotTypFloat); if ( var.size() == 2 ) return CBotTypResult(CBotTypFloat);
return CBotTypResult(CBotErrOverParam); return CBotTypResult(CBotErrOverParam);
} }
@ -2891,11 +2857,11 @@ bool CScriptFunctions::rPenWidth(CBotVar* var, CBotVar* result, int& exception,
// Compilation of the instruction with one object parameter // Compilation of the instruction with one object parameter
CBotTypResult CScriptFunctions::cOneObject(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cOneObject(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
var = var->GetNext(); if ( var.size() == 1 ) return CBotTypResult(CBotTypFloat);
if ( var == nullptr ) return CBotTypResult(CBotTypFloat); // TODO: shouldn't we check parameter type?
return CBotTypResult(CBotErrOverParam); return CBotTypResult(CBotErrOverParam);
} }
@ -2918,30 +2884,27 @@ bool CScriptFunctions::rCameraFocus(CBotVar* var, CBotVar* result, int& exceptio
// Compilation of class "point". // Compilation of class "point".
CBotTypResult CScriptFunctions::cPointConstructor(CBotVar* pThis, CBotVar* &var) CBotTypResult CScriptFunctions::cPointConstructor(CBotTypResult thisType, const std::vector<CBotTypResult> &var)
{ {
if ( !pThis->GetTypResult().IsSpecifiedClassOrSubclass("point") ) return CBotTypResult(CBotErrBadNum); if ( !thisType.IsSpecifiedClassOrSubclass("point") ) return CBotTypResult(CBotErrBadNum);
if ( var == nullptr ) return CBotTypResult(0); // ok if no parameter if ( var.size() == 0 ) return CBotTypResult(0); // ok if no parameter
// First parameter (x): // First parameter (x):
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
// Second parameter (y): // Second parameter (y):
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() == 1 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
// Third parameter (z): // Third parameter (z):
if ( var == nullptr ) // only 2 parameters? if ( var.size() == 2 ) // only 2 parameters?
{ {
return CBotTypResult(0); // this function returns void return CBotTypResult(0); // this function returns void
} }
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var[2].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); if ( var.size() > 3 ) return CBotTypResult(CBotErrOverParam);
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(0); // this function returns void return CBotTypResult(0); // this function returns void
} }

View File

@ -25,6 +25,7 @@
#pragma once #pragma once
#include "CBot/CBot.h" #include "CBot/CBot.h"
#include "CBot/CBotTypResult.h"
#include "common/error.h" #include "common/error.h"
@ -52,37 +53,37 @@ public:
static bool CheckOpenFiles(); static bool CheckOpenFiles();
private: private:
static CBot::CBotTypResult cEndMission(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cEndMission(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cPlayMusic(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cPlayMusic(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cGetObject(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cGetObject(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cDelete(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cDelete(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cSearch(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cSearch(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cSearchAll(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cSearchAll(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cRadar(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cRadar(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cRadarAll(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cRadarAll(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cDetect(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cDetect(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cDirection(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cDirection(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cProduce(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cProduce(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cDistance(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cDistance(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cSpace(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cSpace(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cFlatSpace(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cFlatSpace(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cFlatGround(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cFlatGround(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cGoto(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cGoto(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cGrabDrop(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cGrabDrop(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cReceive(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cReceive(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cSend(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cSend(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cDeleteInfo(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cDeleteInfo(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cTestInfo(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cTestInfo(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cShield(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cShield(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cFire(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cFire(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cAim(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cAim(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cMotor(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cMotor(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cTopo(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cTopo(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cMessage(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cMessage(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cPenDown(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cPenDown(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cOnePoint(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cOnePoint(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cOneObject(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cOneObject(const std::vector<CBot::CBotTypResult> &var, void* user);
static bool rEndMission(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); static bool rEndMission(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user);
static bool rPlayMusic(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); static bool rPlayMusic(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user);
@ -145,18 +146,18 @@ private:
static bool rCameraFocus(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); static bool rCameraFocus(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user);
static CBot::CBotTypResult cBusy(CBot::CBotVar* thisclass, CBot::CBotVar* &var); static CBot::CBotTypResult cBusy(CBot::CBotTypResult thisType, const std::vector<CBot::CBotTypResult> &var);
static CBot::CBotTypResult cFactory(CBot::CBotVar* thisclass, CBot::CBotVar* &var); static CBot::CBotTypResult cFactory(CBot::CBotTypResult thisType, const std::vector<CBot::CBotTypResult> &var);
static CBot::CBotTypResult cClassNull(CBot::CBotVar* thisclass, CBot::CBotVar* &var); static CBot::CBotTypResult cClassNull(CBot::CBotTypResult thisType, const std::vector<CBot::CBotTypResult> &var);
static CBot::CBotTypResult cClassOneFloat(CBot::CBotVar* thisclass, CBot::CBotVar* &var); static CBot::CBotTypResult cClassOneFloat(CBot::CBotTypResult thisType, const std::vector<CBot::CBotTypResult> &var);
static bool rBusy(CBot::CBotVar* thisclass, CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); static bool rBusy(CBot::CBotVar *thisclass, CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user);
static bool rFactory(CBot::CBotVar* thisclass, CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); static bool rFactory(CBot::CBotVar *thisclass, CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user);
static bool rResearch(CBot::CBotVar* thisclass, CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); static bool rResearch(CBot::CBotVar *thisclass, CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user);
static bool rTakeOff(CBot::CBotVar* thisclass, CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); static bool rTakeOff(CBot::CBotVar *thisclass, CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user);
static bool rDestroy(CBot::CBotVar* thisclass, CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); static bool rDestroy(CBot::CBotVar *thisclass, CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user);
static CBot::CBotTypResult cPointConstructor(CBot::CBotVar* pThis, CBot::CBotVar* &var); static CBot::CBotTypResult cPointConstructor(CBot::CBotTypResult thisType, const std::vector<CBot::CBotTypResult> &var);
static bool rPointConstructor(CBot::CBotVar* pThis, CBot::CBotVar* var, CBot::CBotVar* pResult, int& Exception, void* user); static bool rPointConstructor(CBot::CBotVar* pThis, CBot::CBotVar* var, CBot::CBotVar* pResult, int& Exception, void* user);
static void uObject(CBot::CBotVar* botThis, void* user); static void uObject(CBot::CBotVar* botThis, void* user);

View File

@ -29,14 +29,13 @@ using namespace CBot;
namespace namespace
{ {
CBotTypResult cMessage(CBotVar* &var, void* user) CBotTypResult cMessage(const std::vector<CBotTypResult> &var, void* user)
{ {
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() != CBotTypString && if ( var[0].GetType() != CBotTypString &&
var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // TODO: bad error message
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult(CBotTypFloat); if ( var.size() > 1 ) return CBotTypResult(CBotTypFloat);
return CBotTypResult(CBotErrOverParam); return CBotTypResult(CBotErrOverParam);
} }

View File

@ -57,14 +57,13 @@ private:
int cursor2 = -1; int cursor2 = -1;
}; };
static CBotTypResult cFail(CBotVar* &var, void* user) static CBotTypResult cFail(const std::vector<CBotTypResult> &var, void* user)
{ {
if (var != nullptr) if (var.size() > 0)
{ {
if (var->GetType() != CBotTypString) return CBotTypResult(CBotErrBadString); if (var[0].GetType() != CBotTypString) return CBotTypResult(CBotErrBadString);
var = var->GetNext();
} }
if (var != nullptr) return CBotTypResult(CBotErrOverParam); if (var.size() > 1) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypVoid); return CBotTypResult(CBotTypVoid);
} }
@ -79,11 +78,10 @@ private:
throw CBotTestFail(message); throw CBotTestFail(message);
} }
static CBotTypResult cAssert(CBotVar* &var, void* user) static CBotTypResult cAssert(const std::vector<CBotTypResult> &var, void* user)
{ {
if (var == nullptr) return CBotTypResult(CBotErrLowParam); if (var.size() == 0) return CBotTypResult(CBotErrLowParam);
if (var->GetType() != CBotTypBoolean) return CBotTypResult(CBotErrBadString); if (var[0].GetType() != CBotTypBoolean) return CBotTypResult(CBotErrBadString);
var = var->GetNext();
return CBotTypResult(CBotTypVoid); return CBotTypResult(CBotTypVoid);
} }