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->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)
{
@ -150,39 +150,6 @@ CBotError CBotCStack::GetError()
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)
{
@ -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 )
{
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();
return m_vartype;
}
////////////////////////////////////////////////////////////////////////////////
@ -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;
CBotTypResult val(-1);
CBotProgram *prog = GetProgram();
val = prog->GetExternalCalls()->CompileCall(p, nullptr, ppVars, this);
val = prog->GetExternalCalls()->CompileCall(p, CBotTypResult(CBotTypVoid), ppVars, this);
if (val.GetType() < 0)
{
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 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.
* The CBotCStack has ownership of the object m_var points to.
*
* 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.
@ -119,47 +119,6 @@ public:
*/
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.
*
@ -256,30 +215,20 @@ public:
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
*/
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.
* var must not be null, or else m_var is left in an invalid state!
*
* \param var
* \return Value of m_vartype, previously set by one of the SetVar or Return functions.
*/
void SetCopyVar( CBotVar* var );
/*!
* \brief Gets m_var.
*
* \return Value of m_var, previously set by one of the SetVar or Return functions.
*/
CBotVar* GetVar();
const CBotTypResult& GetVarType();
/*!
* \brief Set error start location.
@ -345,11 +294,11 @@ public:
/*!
* \brief CompileCall
* \param p
* \param ppVars
* \param ppVars Argument types
* \param nIdent
* \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.
@ -407,7 +356,7 @@ private:
int m_start;
//! Result of the operations.
std::unique_ptr<CBotVar> m_var;
CBotTypResult m_vartype;
//! Is part of a block (variables are local to this block).
bool m_bBlock;
CBotVariable* m_listVar;

View File

@ -286,7 +286,7 @@ CBotClass* CBotClass::Find(const std::string& name)
////////////////////////////////////////////////////////////////////////////////
bool CBotClass::AddFunction(const std::string& name,
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)));
}
@ -300,8 +300,8 @@ bool CBotClass::SetUpdateFunc(void rUpdate(CBotVar* thisVar, void* user))
////////////////////////////////////////////////////////////////////////////////
CBotTypResult CBotClass::CompileMethode(CBotToken* name,
CBotVar* pThis,
CBotVar** ppParams,
CBotTypResult thisType,
const std::vector<CBotTypResult> &ppParams,
CBotCStack* pStack,
long &nIdent)
{
@ -309,14 +309,14 @@ CBotTypResult CBotClass::CompileMethode(CBotToken* name,
// 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;
// find the methods declared by user
r = CBotFunction::CompileCall(m_pMethod, name->GetString(), ppParams, nIdent);
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;
}
@ -681,7 +681,7 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
if ( p->GetType() != ID_CLBRK )
{
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());
}
@ -716,7 +716,7 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
if (pStack->IsOk())
{
i = CBotTwoOpExpr::Compile(p, pStack);
if (i == nullptr || !pStack->GetTypResult().Compare(type2))
if (i == nullptr || !pStack->GetVarType().Compare(type2))
{
pStack->SetError(CBotErrBadType1, p->GetStart());
return false;
@ -729,8 +729,8 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
// it has an assignmet to calculate
i = CBotTwoOpExpr::Compile(p, pStack);
if ( !(type.Eq(CBotTypPointer) && pStack->GetTypResult().Eq(CBotTypNullPointer)) &&
!TypesCompatibles( type2, pStack->GetTypResult()) )
if ( !(type.Eq(CBotTypPointer) && pStack->GetVarType().Eq(CBotTypNullPointer)) &&
!TypesCompatibles( type2, pStack->GetVarType()) )
{
pStack->SetError(CBotErrBadType1, p->GetStart());
return false;

View File

@ -140,7 +140,7 @@ public:
*/
bool AddFunction(const std::string& name,
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
@ -236,15 +236,15 @@ public:
* \brief CompileMethode Compiles a method associated with an instance of
* class the method can be declared by the user or AddFunction.
* \param name
* \param pThis
* \param ppParams
* \param thisType Type of object the method is being called on.
* \param ppParams Types of parameters
* \param pStack
* \param nIdent
* \return
*/
CBotTypResult CompileMethode(CBotToken* name,
CBotVar* pThis,
CBotVar** ppParams,
CBotTypResult thisType,
const std::vector<CBotTypResult> &ppParams,
CBotCStack* pStack,
long &nIdent);

View File

@ -87,7 +87,9 @@ CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack)
CBotCStack* pStk = pStack->TokenStack(nullptr, true);
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))
pStack->SetError(CBotErrBadType1, p->GetPrev());

View File

@ -40,15 +40,14 @@ bool CBotExternalCallList::AddFunction(const std::string& name, std::unique_ptr<
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)
return -1;
CBotExternalCall* pt = m_list[p->GetString()].get();
std::unique_ptr<CBotVar> args = std::unique_ptr<CBotVar>(MakeListVars(ppVar));
CBotTypResult r = pt->Compile(thisVar, args.get(), m_user);
CBotTypResult r = pt->Compile(thisType, ppVar, m_user);
// if a class is returned, it is actually a pointer
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);
}
@ -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)

View File

@ -26,6 +26,7 @@
#include <string>
#include <map>
#include <memory>
#include <vector>
namespace CBot
{
@ -59,11 +60,11 @@ public:
/**
* \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 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
@ -82,7 +83,7 @@ class CBotExternalCallDefault : public CBotExternalCall
{
public:
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
@ -97,7 +98,7 @@ public:
*/
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;
private:
@ -112,7 +113,7 @@ class CBotExternalCallClass : public CBotExternalCall
{
public:
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
@ -127,7 +128,7 @@ public:
*/
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;
private:
@ -158,12 +159,12 @@ public:
* This function sets an error in compilation stack in case of failure
*
* \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 pStack Compilation stack
* \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

View File

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

View File

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

View File

@ -76,7 +76,7 @@ CBotInstr* CBotDefArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResul
if (p->GetType() != ID_CLBRK)
{
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());
goto error;
@ -114,7 +114,7 @@ CBotInstr* CBotDefArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResul
if (pStk->IsOk())
{
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());
goto error;

View File

@ -116,7 +116,7 @@ CBotInstr* CBotDefClass::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* p
// look if there are parameters
inst->m_hasParams = (p->GetType() == ID_OPENPAR);
CBotVar* ppVars[1000];
std::vector<CBotTypResult> ppVars;
inst->m_parameters = CompileParams(p, pStk, ppVars);
if ( !pStk->IsOk() ) goto error;
@ -129,7 +129,7 @@ CBotInstr* CBotDefClass::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* p
{
// the constructor is there?
// 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
int typ = r.GetType();
@ -150,14 +150,14 @@ CBotInstr* CBotDefClass::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* p
goto error;
}
pStk->SetCopyVar(var->m_value.get());
pStk->SetVarType(var->m_value->GetTypResult());
// chained method ?
if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStk, true, false)))
{
inst->m_exprRetVar->SetToken(vartoken);
pStk->DeleteChildLevels();
}
pStk->SetVar(nullptr);
pStk->SetVarType(CBotTypResult());
if ( !pStk->IsOk() ) goto error;
}
@ -181,12 +181,17 @@ CBotInstr* CBotDefClass::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* p
{
goto error;
}
CBotClass* result = pStk->GetClass();
if ( !pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_POINTER).Eq(CBotTypNullPointer) &&
( !pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_POINTER).Eq(CBotTypPointer) ||
CBotClass* result = pStk->GetVarType().GetClass();
if ( !pStk->GetVarType().Eq(CBotTypNullPointer) &&
( (!pStk->GetVarType().Eq(CBotTypPointer) &&
!pStk->GetVarType().Eq(CBotTypClass)) ||
( result != nullptr && !(pClass->IsChildOf(result) ||
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());
goto error;
}

View File

@ -99,7 +99,7 @@ CBotInstr* CBotDefVariable::CompileAfterType(CBotToken* &p, CBotCStack* pStack,
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
{
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
p = p->GetNext();
std::unique_ptr<CBotVar> var = CBotVar::Create(CBotTypBoolean);
pStk->SetVar(std::move(var));
pStk->SetVarType(CBotTypResult(CBotTypBoolean));
}
return pStack->Return(inst, pStk);

View File

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

View File

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

View File

@ -26,6 +26,7 @@
#include "CBot/CBotInstr/CBotFieldExpr.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotClass.h"
namespace CBot
{
@ -45,19 +46,17 @@ CBotInstr* CBotExprRetVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bMeth
{
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();
CBotInstr* inst = new CBotExprRetVar();
CBotVariable *var = nullptr;
while (true)
{
pStk->SetStartError(p->GetStart());
if (val->GetType() == CBotTypArrayPointer)
if (val.GetType() == CBotTypArrayPointer)
{
if (bMethodsOnly) goto err;
@ -67,10 +66,9 @@ CBotInstr* CBotExprRetVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bMeth
i->m_expr = CBotExpression::Compile(p, pStk);
inst->AddNext3(i);
var = val->GetItem(0,true);
val = var->m_value.get();
val = val.GetTypElem();
if (i->m_expr == nullptr || pStk->GetType() != CBotTypInt)
if (i->m_expr == nullptr || pStk->GetVarType().GetType() != CBotTypInt)
{
pStk->SetError(CBotErrBadIndex, p->GetStart());
goto err;
@ -83,7 +81,7 @@ CBotInstr* CBotExprRetVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bMeth
continue;
}
}
if (val->GetType(CBotVar::GetTypeMode::CLASS_AS_POINTER) == CBotTypPointer)
if (val.GetType() == CBotTypClass || val.GetType() == CBotTypPointer)
{
if (IsOfType(p, ID_DOT))
{
@ -105,25 +103,29 @@ CBotInstr* CBotExprRetVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bMeth
}
else
{
CBotVariable *preVar = var;
CBotVar* preVal = val;
var = val->GetItem(p->GetString());
val = var ? var->m_value.get() : nullptr;
CBotTypResult preVal = val;
CBotVariable *var = val.GetClass()->GetItem(p->GetString());
if (val != nullptr)
if (var != nullptr)
{
val = var->m_value->GetTypResult();
CBotFieldExpr* i = new CBotFieldExpr(var->GetFieldPosition());
i->SetToken(pp);
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);
goto err;
}
}
else
{
val = CBotTypResult(CBotTypVoid); // indicate error
}
}
if (val != nullptr)
if (val.GetType() != CBotTypVoid)
{
p = p->GetNext();
continue;
@ -138,7 +140,7 @@ CBotInstr* CBotExprRetVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bMeth
break;
}
pStk->SetCopyVar(val);
pStk->SetVarType(val);
if (pStk->IsOk()) return pStack->Return(inst, pStk);
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 (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);
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);
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);
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);
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);
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 (CBotFieldExpr::CheckProtectionError(pStk, nullptr, "", var, bCheckReadOnly))
if (CBotFieldExpr::CheckProtectionError(pStk, CBotTypVoid, "", var, bCheckReadOnly))
{
pStk->SetError(CBotErrPrivate, p);
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 "++"
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");
if (!pStk->IsOk()) goto err;
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
i->SetToken(pp); // keeps the name of the token
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);
goto err;
@ -161,7 +161,7 @@ CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bCheckRe
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);
}
pStk->SetError(CBotErrUndefVar, p);
@ -203,7 +203,7 @@ CBotInstr* CBotExprVar::CompileMethode(CBotToken* &p, CBotCStack* pStack)
{
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");
if (pStk->IsOk())
{

View File

@ -85,7 +85,7 @@ CBotInstr* CBotExpression::Compile(CBotToken* &p, CBotCStack* pStack)
return nullptr;
}
CBotTypResult type1 = pStack->GetTypResult();
CBotTypResult type1 = pStack->GetVarType();
// get the variable assigned to mark
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();
@ -162,8 +162,8 @@ bool CBotFieldExpr::CheckProtectionError(CBotCStack* pStack, CBotVar* pPrev, con
// TODO: can we refactor this?
// implicit 'this.'var, this.var, or super.var
if (pPrev == nullptr || prevName == "this" || prevName == "super") // member of the current class
// implicit 'this.' var (prevType is void meaning no value), this.var, or super.var
if (prevType.GetType() == CBotTypVoid || prevName == "this" || prevName == "super") // member of the current class
{
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
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;
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.
*
* \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 pVar Variable to check
* \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
*/
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:
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;
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,
CBotVar** ppVars, CBotTypResult &TypeOrError, bool bPublic)
const std::vector<CBotTypResult> &ppVars, CBotTypResult &TypeOrError, bool bPublic)
{
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 )
{
int i = 0;
size_t i = 0;
int alpha = 0; // signature of parameters
// parameters are compatible?
CBotDefParam* pv = pt->m_param; // expected list of parameters
CBotVar* pw = ppVars[i++]; // provided list parameter
while ( pv != nullptr && (pw != nullptr || pv->HasDefault()) )
CBotTypResult pw; // provided list parameter
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();
continue; // skip params with default values
}
pw = ppVars[i++];
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))
{
@ -544,13 +548,12 @@ CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& lo
}
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!
}
pv = pv->GetNext();
pw = ppVars[i++];
}
if ( pw != nullptr )
if ( i < ppVars.size() )
{
if ( !funcMap.empty() ) continue;
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 )
{
int i = 0;
size_t i = 0;
int alpha = 0; // signature of parameters
// parameters sont-ils compatibles ?
CBotDefParam* pv = pt->m_param; // list of expected parameters
CBotVar* pw = ppVars[i++]; // list of provided parameters
while ( pv != nullptr && (pw != nullptr || pv->HasDefault()) )
CBotTypResult pw; // list of provided parameters
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();
continue; // skip params with default values
}
pw = ppVars[i++];
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))
{
@ -607,13 +614,12 @@ CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& lo
}
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!
}
pv = pv->GetNext();
pw = ppVars[i++];
}
if ( pw != nullptr )
if ( i < ppVars.size() )
{
if ( !funcMap.empty() ) continue; // previous useable function
if ( TypeOrError.Eq(CBotErrLowParam) ) TypeOrError.SetType(CBotErrNbParam);
@ -659,6 +665,26 @@ CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& lo
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,
CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken)
@ -667,7 +693,7 @@ int CBotFunction::DoCall(CBotProgram* program, const std::list<CBotFunction*>& l
CBotFunction* pt = nullptr;
CBotProgram* baseProg = pStack->GetProgram(true);
pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type);
pt = FindLocalOrPublic(localFunctionList, nIdent, name, argTypesToVector(ppVars), type);
if ( pt != nullptr )
{
@ -757,7 +783,7 @@ void CBotFunction::RestoreCall(const std::list<CBotFunction*>& localFunctionList
CBotStack* pStk3;
CBotProgram* baseProg = pStack->GetProgram(true);
pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type);
pt = FindLocalOrPublic(localFunctionList, nIdent, name, argTypesToVector(ppVars), type);
if ( pt != nullptr )
{
@ -820,7 +846,7 @@ int CBotFunction::DoCall(const std::list<CBotFunction*>& localFunctionList, long
CBotTypResult type;
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 )
{
@ -918,7 +944,7 @@ bool CBotFunction::RestoreCall(const std::list<CBotFunction*>& localFunctionList
CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass)
{
CBotTypResult type;
CBotFunction* pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type);
CBotFunction* pt = FindLocalOrPublic(localFunctionList, nIdent, name, argTypesToVector(ppVars), type);
if ( pt != nullptr )
{

View File

@ -107,13 +107,14 @@ public:
*
* \param localFunctionList Linked list of local functions to search in, can be null
* \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
* \return Type returned by the function or error code
* \see FindLocalOrPublic
*/
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
@ -126,13 +127,13 @@ public:
* \param localFunctionList Linked list of local functions to search in, can be null
* \param nIdent[in, out] Unique identifier 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 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)
*/
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.

View File

@ -57,7 +57,7 @@ CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
if (p->GetType() == ID_OPENPAR)
{
CBotVar* ppVars[1000];
std::vector<CBotTypResult> ppVars;
CBotInstrCall* inst = new CBotInstrCall();
inst->SetToken(pp);
@ -86,10 +86,9 @@ CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
pStack->DeleteChildLevels();
if ( inst->m_typRes.GetType() > 0 )
{
std::unique_ptr<CBotVar> pRes = CBotVar::Create(inst->m_typRes);
pStack->SetVar(std::move(pRes)); // for knowing the type of the result
pStack->SetVarType(inst->m_typRes); // 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)))
{

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();
inst->SetToken(p); // corresponding token
@ -62,15 +62,15 @@ CBotInstr* CBotInstrMethode::Compile(CBotToken* &p, CBotCStack* pStack, CBotVar*
inst->m_methodName = pp->GetString();
// compiles the list of parameters
CBotVar* ppVars[1000];
std::vector<CBotTypResult> ppVars;
inst->m_parameters = CompileParams(p, pStack, ppVars);
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_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
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
if (inst->m_typRes.GetType() > 0)
{
std::unique_ptr<CBotVar> pResult = CBotVar::Create(inst->m_typRes);
if (inst->m_typRes.Eq(CBotTypClass))
{
pResult->SetClass(inst->m_typRes.GetClass());
}
pStack->SetVar(std::move(pResult));
pStack->SetVarType(inst->m_typRes);
}
else pStack->SetVar(nullptr);
else pStack->SetVarType(CBotTypResult(CBotTypVoid));
pp = p;
if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStack, bMethodChain, false)))

View File

@ -37,12 +37,12 @@ public:
* \brief Compile
* \param p
* \param pStack
* \param pVar
* \param varType Type of object method is being called on
* \param bMethodChain If true, allows chaining methods only
* \param bIsSuperCall If true, don't do a virtual call
* \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

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;
CBotInstr* ret = nullptr; // to return to the list
CBotCStack* pile = pStack;
int i = 0;
ppVars.clear();
if (IsOfType(p, ID_OPENPAR))
{
@ -63,16 +64,15 @@ CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars)
if (param != nullptr)
{
if (pile->GetTypResult().Eq(99))
if (pile->GetVarType().Eq(99))
{
pStack->DeleteChildLevels();
pStack->SetError(CBotErrVoid, p->GetStart());
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?
(void)end; //ppVars[i]->GetToken()->SetPos(start, end);
i++;
if (IsOfType(p, ID_COMMA)) continue; // skips the comma
if (IsOfType(p, ID_CLOSEPAR)) break;
@ -83,7 +83,6 @@ CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars)
return nullptr;
}
}
ppVars[i] = nullptr;
return ret;
}
@ -93,9 +92,11 @@ bool TypeCompatible(CBotTypResult& type1, CBotTypResult& type2, int op)
int t1 = type1.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
if (op == ID_ADD && t1 == CBotTypString) return true;

View File

@ -19,6 +19,8 @@
#pragma once
#include <vector>
namespace CBot
{
@ -32,10 +34,10 @@ class CBotTypResult;
* \brief CompileParams Compile a list of parameters.
* \param p
* \param pStack
* \param ppVars
* \param ppVars [out] types of parameters
* \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

View File

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

View File

@ -72,7 +72,7 @@ CBotInstr* CBotListArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResu
if (pStk->IsOk())
{
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());
goto error;
@ -90,7 +90,7 @@ CBotInstr* CBotListArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResu
if (pStk->IsOk())
{
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());
goto error;
@ -115,7 +115,9 @@ CBotInstr* CBotListArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResu
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) )
{
@ -133,7 +135,9 @@ CBotInstr* CBotListArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResu
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) )
{

View File

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

View File

@ -94,7 +94,9 @@ CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack)
delete inst;
p = pvar;
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);
delete inst;
@ -118,7 +120,7 @@ CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack)
{
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();
i->SetToken(pp);
@ -183,8 +185,7 @@ CBotInstr* CBotParExpr::CompileLitExpr(CBotToken* &p, CBotCStack* pStack)
{
CBotInstr* inst = new CBotExprLitNull();
inst->SetToken(pp);
std::unique_ptr<CBotVar> var = CBotVar::Create(CBotTypNullPointer);
pStk->SetVar(std::move(var));
pStk->SetVarType(CBotTypNullPointer);
return pStack->Return(inst, pStk);
}
@ -193,10 +194,7 @@ CBotInstr* CBotParExpr::CompileLitExpr(CBotToken* &p, CBotCStack* pStack)
{
CBotInstr* inst = new CBotExprLitNan();
inst->SetToken(pp);
// XXX: Why is NAN an int?
std::unique_ptr<CBotVar> var = CBotVar::Create(CBotTypInt);
var->SetInit(CBotVar::InitType::IS_NAN);
pStk->SetVar(std::move(var));
pStk->SetVarType(CBotTypInt);
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);
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 ( 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 ( pStk->GetType() < CBotTypLong )
if ( pStk->GetVarType().GetType() < CBotTypLong )
{
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 );
if (pStack->GetType() < CBotTypLong && pStack->IsOk())
if (pStack->GetVarType().GetType() < CBotTypLong && pStack->IsOk())
{
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) )
{
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;
{
@ -177,7 +177,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
delete inst;
return pStack->Return(nullptr, pStk);
}
type1 = pStk->GetTypResult();
type1 = pStk->GetVarType();
inst->m_op2 = CBotExpression::Compile(p, pStk);
if ( inst->m_op2 == nullptr )
@ -186,7 +186,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
delete inst;
return pStack->Return(nullptr, pStk);
}
type2 = pStk->GetTypResult();
type2 = pStk->GetVarType();
if (!TypeCompatible(type1, type2))
{
pStk->SetError( CBotErrBadType2, pp );
@ -194,7 +194,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
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);
}
@ -212,7 +212,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
{
// 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
{
@ -265,7 +265,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
p = p->GetNext(); // advance after
i->m_rightop = CBotTwoOpExpr::Compile( p, pStk, pOp );
type2 = pStk->GetTypResult();
type2 = pStk->GetVarType();
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);
t.SetType(TypeRes);
t.SetType(TypeRes);
// is a variable on the stack for the type of result
pStk->SetVar(CBotVar::Create(t));
pStk->SetVarType(t);
// and returns the requested object
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->GetType() != CBotTypArrayPointer )
if ( pVar.size() == 0 ) return CBotTypResult( CBotErrLowParam );
// TODO: check for too many parameters
if ( pVar[0].GetType() != CBotTypArrayPointer )
return CBotTypResult( CBotErrBadParam );
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 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)));
}

View File

@ -275,7 +275,7 @@ public:
*/
static bool AddFunction(const std::string& name,
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()

View File

@ -198,7 +198,7 @@ std::string CBotTypResult::ToString()
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 )
{

View File

@ -167,7 +167,7 @@ public:
* \param name Class name to check
* \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

View File

@ -26,216 +26,198 @@ namespace CBot
// 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;
return CBotTypResult(CBotTypFloat);
if ( var.size() > 0 ) return CBotErrOverParam;
return CBotTypFloat;
}
// 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->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat);
if ( var.size() < 1 ) return CBotTypResult(CBotErrLowParam);
if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
return CBotTypFloat;
}
// 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->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var.size() < 2 ) return CBotTypResult(CBotErrLowParam);
if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat);
return CBotTypFloat;
}
// 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->GetType() != CBotTypString &&
var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat);
if ( var.size() < 1 ) return CBotTypResult(CBotErrLowParam);
if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
if ( var[0].GetType() != CBotTypString &&
var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
return CBotTypFloat;
}
// 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->GetType() != CBotTypString &&
var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypString);
if ( var.size() < 1 ) return CBotTypResult(CBotErrLowParam);
if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
if ( var[0].GetType() != CBotTypString &&
var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
return CBotTypString;
}
// 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->GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypInt);
if ( var.size() < 1 ) return CBotTypResult(CBotErrLowParam);
if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
if ( var[0].GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum);
return CBotTypInt;
}
// 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->GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypBoolean);
if ( var.size() < 1 ) return CBotTypResult(CBotErrLowParam);
if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
if ( var[0].GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum);
return CBotTypBoolean;
}
CBotTypResult cStrStr(CBotVar*& var, void* user)
CBotTypResult cStrStr(const std::vector<CBotTypResult> &var, void* user)
{
// 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
if ( var->GetType() != CBotTypString )
if ( var[0].GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
// no second parameter
if ( var->GetNext() != nullptr ) return CBotTypResult( CBotErrOverParam );
// 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
if ( var == nullptr ) return CBotTypResult( CBotErrLowParam );
// to be a string
if ( var->GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
// it takes a second parameter
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult( CBotErrLowParam );
// to be a string
if ( var->GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
if ( var.size() < 2 ) return CBotTypResult(CBotErrLowParam);
// no third parameter
if ( var->GetNext() != nullptr ) 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 );
if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
// to be a string
if ( var->GetType() != CBotTypString )
if ( var[0].GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
// no second parameter
if ( var->GetNext() != nullptr ) return CBotTypResult( CBotErrOverParam );
// to be a string
if ( var[1].GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
// 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
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
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 );
// it takes a second parameter
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult( CBotErrLowParam );
// which must be a number
if ( var->GetType() > CBotTypDouble )
if ( var[1].GetType() > CBotTypDouble )
return CBotTypResult( CBotErrBadNum );
// third parameter optional
if ( var->GetNext() != nullptr )
if ( var.size() > 2 )
{
var = var->GetNext();
// which must be a number
if ( var->GetType() > CBotTypDouble )
if ( var[2].GetType() > CBotTypDouble )
return CBotTypResult( CBotErrBadNum );
// no fourth parameter
if ( var->GetNext() != nullptr ) return CBotTypResult( CBotErrOverParam );
if ( var.size() > 3 ) return CBotTypResult( CBotErrOverParam );
}
// 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
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
if ( var->GetType() != CBotTypString )
if ( var[0].GetType() != CBotTypString )
return CBotTypResult( CBotErrBadString );
// it takes a second parameter
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult( CBotErrLowParam );
// which must be a number
if ( var->GetType() > CBotTypDouble )
if ( var[1].GetType() > CBotTypDouble )
return CBotTypResult( CBotErrBadNum );
// no third parameter
if ( var->GetNext() != nullptr ) return CBotTypResult( CBotErrOverParam );
// 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
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
if ( var->GetType() != CBotTypString )
if ( var[0].GetType() != CBotTypString )
return CBotTypResult( CBotErrBadParam );
// no second parameter
if ( var->GetNext() != nullptr ) return CBotTypResult( CBotErrOverParam );
// the end result is an integer
return CBotTypResult( CBotTypInt );
return CBotTypInt;
}
} // namespace CBot

View File

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

View File

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

View File

@ -69,39 +69,36 @@
using namespace CBot;
CBotTypResult CScriptFunctions::cClassNull(CBotVar* thisclass, CBotVar* &var)
CBotTypResult CScriptFunctions::cClassNull(CBotTypResult thisType, const std::vector<CBotTypResult> &var)
{
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);
}
// 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 == nullptr ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
//? if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
//? if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
//? var = var->GetNext();
return CBotTypResult(0);
if ( var.size() < pos+2 ) return CBotTypResult(CBotErrLowParam);
pos++;
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
pos++;
return CBotTypVoid;
}
if ( var->GetType() == CBotTypClass )
if ( var[pos].GetType() == CBotTypClass )
{
if ( !var->GetTypResult().IsSpecifiedClassOrSubclass("point") ) return CBotTypResult(CBotErrBadParam);
var = var->GetNext();
return CBotTypResult(0);
if ( !var[pos].IsSpecifiedClassOrSubclass("point") ) return CBotTypResult(CBotErrBadParam);
pos++;
return CBotTypVoid;
}
return CBotTypResult(CBotErrBadParam);
@ -109,15 +106,16 @@ static CBotTypResult cPoint(CBotVar* &var, void* user)
// 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;
ret = cPoint(var, user);
if ( ret.GetType() != 0 ) return ret;
size_t pos = 0;
ret = cPoint(var, pos, user);
if ( ret.GetType() != CBotTypVoid ) return ret;
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat);
if ( pos < var.size() ) return CBotTypResult(CBotErrOverParam);
return CBotTypFloat;
}
// 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)"
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->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
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);
if ( var.size() < 2 ) return CBotTypResult(CBotErrLowParam);
if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
return CBotTypFloat;
}
// Instruction "endmission(result, delay)"
@ -197,16 +192,13 @@ bool CScriptFunctions::rEndMission(CBotVar* var, CBotVar* result, int& exception
// 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->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
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);
if ( var.size() < 2 ) return CBotTypResult(CBotErrLowParam);
if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
if ( var[0].GetType() != CBotTypString ) return CBotTypResult(CBotErrBadNum);
if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
return CBotTypFloat;
}
// Instruction "playmusic(filename, repeat)"
@ -291,12 +283,11 @@ bool CScriptFunctions::rSetResearchDone(CBotVar* var, CBotVar* result, int& exce
// 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->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( var.size() < 1 ) return CBotTypResult(CBotErrLowParam);
if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
return CBotTypResult(CBotTypPointer, "object");
}
@ -345,10 +336,10 @@ bool CScriptFunctions::rGetObject(CBotVar* var, CBotVar* result, int& exception,
}
// 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);
return CBotTypResult(CBotTypBoolean);
if ( var.size() > 0 ) return CBotTypResult(CBotErrOverParam);
return CBotTypBoolean;
}
// Instruction "object.busy()"
@ -417,16 +408,14 @@ bool CScriptFunctions::rDestroy(CBotVar* thisclass, CBotVar* var, CBotVar* resul
// 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->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr )
if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var.size() > 1 )
{
if ( var->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( var[1].GetType() != CBotTypString ) return CBotTypResult(CBotErrBadNum);
if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
}
return CBotTypResult(CBotTypFloat);
}
@ -624,20 +613,18 @@ bool CScriptFunctions::rTakeOff(CBotVar* thisclass, CBotVar* var, CBotVar* resul
// 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);
var = var->GetNext();
if ( var[0].GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum);
if ( var != nullptr )
if ( var.size() > 1 )
{
if ( var->GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var[1].GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum);
}
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat);
}
@ -689,46 +676,47 @@ bool CScriptFunctions::rDelete(CBotVar* var, CBotVar* result, int& exception, vo
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);
if ( var->GetType() == CBotTypArrayPointer )
size_t pos = 0;
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
}
else if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type
var = var->GetNext();
else if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type
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 ( var == nullptr ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // min
var = var->GetNext();
if ( var == nullptr ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // max
var = var->GetNext();
if ( var == nullptr ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // sense
var = var->GetNext();
if ( var == nullptr ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // filter
var = var->GetNext();
if ( var == nullptr ) return returnValue;
if ( pos >= var.size() ) return returnValue;
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // min
pos++;
if ( pos >= var.size() ) return returnValue;
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // max
pos++;
if ( pos >= var.size() ) return returnValue;
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // sense
pos++;
if ( pos >= var.size() ) return returnValue;
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // filter
pos++;
if ( pos >= var.size() ) return returnValue;
return CBotTypResult(CBotErrOverParam);
}
// 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"));
}
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")));
}
@ -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;
if ( var->GetType() == CBotTypArrayPointer )
size_t pos = 0;
if ( pos >= var.size() ) return returnValue;
if ( var[pos].GetType() == CBotTypArrayPointer )
{
CBotVariable *arrayElement = var->GetItem(0, false);
if ( arrayElement == nullptr ) return returnValue;
if ( arrayElement->m_value->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type
if ( var[0].GetTypElem().GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type
}
else if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type
var = var->GetNext();
if ( var == nullptr ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // angle
var = var->GetNext();
if ( var == nullptr ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // focus
var = var->GetNext();
if ( var == nullptr ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // min
var = var->GetNext();
if ( var == nullptr ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // max
var = var->GetNext();
if ( var == nullptr ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // sense
var = var->GetNext();
if ( var == nullptr ) return returnValue;
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // filter
var = var->GetNext();
if ( var == nullptr ) return returnValue;
else if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type
pos++;
if ( pos >= var.size() ) return returnValue;
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // angle
pos++;
if ( pos >= var.size() ) return returnValue;
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // focus
pos++;
if ( pos >= var.size() ) return returnValue;
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // min
pos++;
if ( pos >= var.size() ) return returnValue;
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // max
pos++;
if ( pos >= var.size() ) return returnValue;
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // sense
pos++;
if ( pos >= var.size() ) return returnValue;
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // filter
pos++;
if ( pos >= var.size() ) return returnValue;
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")));
}
// 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"));
}
@ -1063,12 +1050,11 @@ bool CScriptFunctions::ShouldTaskStop(Error err, int errMode)
// 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->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( var.size() < 1 ) return CBotTypResult(CBotErrLowParam);
if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
return CBotTypResult(CBotTypBoolean);
}
@ -1143,16 +1129,17 @@ bool CScriptFunctions::rDetect(CBotVar* var, CBotVar* result, int& exception, vo
// 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;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, user);
if ( ret.GetType() != 0 ) return ret;
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
size_t pos = 0;
ret = cPoint(var, pos, user);
if ( ret.GetType() != CBotTypVoid ) return ret;
if ( pos >= var.size() ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat);
return CBotTypFloat;
}
// 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]])"
// or "produce(type[, power])".
CBotTypResult CScriptFunctions::cProduce(CBotVar* &var, void* user)
CBotTypResult CScriptFunctions::cProduce(const std::vector<CBotTypResult> &var, void* user)
{
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();
if ( var != nullptr )
pos++;
if ( pos < var.size() )
{
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
pos++;
}
}
else
{
ret = cPoint(var, user);
if ( ret.GetType() != 0 ) return ret;
ret = cPoint(var, pos, user);
if ( ret.GetType() != CBotTypVoid ) return ret;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
pos++;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
pos++;
if ( var != nullptr )
if ( pos >= var.size() )
{
if ( var->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
var = var->GetNext();
if ( var[pos].GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
pos++;
if ( var != nullptr )
if ( pos >= var.size() )
{
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
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]])"
@ -1430,21 +1418,22 @@ bool CScriptFunctions::rProduce(CBotVar* var, CBotVar* result, int& exception, v
// 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;
size_t pos = 0;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, user);
if ( ret.GetType() != 0 ) return ret;
if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, pos, user);
if ( ret.GetType() != CBotTypVoid ) return ret;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, user);
if ( ret.GetType() != 0 ) return ret;
if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
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;
}
// 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)".
CBotTypResult CScriptFunctions::cSpace(CBotVar* &var, void* user)
CBotTypResult CScriptFunctions::cSpace(const std::vector<CBotTypResult> &var, void* user)
{
CBotTypResult ret;
if ( var == nullptr ) return CBotTypResult(CBotTypIntrinsic, "point");
ret = cPoint(var, user);
if ( ret.GetType() != 0 ) return ret;
size_t pos = 0;
if ( pos >= var.size() ) return CBotTypResult(CBotTypIntrinsic, "point");
ret = cPoint(var, pos, user);
if ( ret.GetType() != CBotTypVoid ) return ret;
if ( var == nullptr ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( pos >= var.size() ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
pos++;
if ( var == nullptr ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( pos >= var.size() ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
pos++;
if ( var == nullptr ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( pos >= var.size() ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
pos++;
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( pos < var.size() ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypIntrinsic, "point");
}
@ -1561,31 +1551,32 @@ bool CScriptFunctions::rSpace(CBotVar* var, CBotVar* result, int& exception, voi
return true;
}
CBotTypResult CScriptFunctions::cFlatSpace(CBotVar* &var, void* user)
CBotTypResult CScriptFunctions::cFlatSpace(const std::vector<CBotTypResult> &var, void* user)
{
CBotTypResult ret;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, user);
size_t pos = 0;
if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, pos, user);
if ( ret.GetType() != 0 ) return ret;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
pos++;
if ( var == nullptr ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( pos >= var.size() ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
pos++;
if ( var == nullptr ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( pos >= var.size() ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
pos++;
if ( var == nullptr ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( pos >= var.size() ) return CBotTypResult(CBotTypIntrinsic, "point");
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
pos++;
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( pos < var.size() ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypIntrinsic, "point");
}
@ -1644,19 +1635,20 @@ bool CScriptFunctions::rFlatSpace(CBotVar* var, CBotVar* result, int& exception,
// 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;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, user);
size_t pos = 0;
if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, pos, user);
if ( ret.GetType() != 0 ) return ret;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
pos++;
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( pos < var.size() ) return CBotTypResult(CBotErrOverParam);
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)".
CBotTypResult CScriptFunctions::cGoto(CBotVar* &var, void* user)
CBotTypResult CScriptFunctions::cGoto(const std::vector<CBotTypResult> &var, void* user)
{
CBotTypResult ret;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, user);
size_t pos = 0;
if ( pos >= var.size() ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, pos, user);
if ( ret.GetType() != 0 ) return ret;
if ( var == nullptr ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( pos >= var.size() ) return CBotTypResult(CBotTypFloat);
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
pos++;
if ( var == nullptr ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( pos >= var.size() ) return CBotTypResult(CBotTypFloat);
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
pos++;
if ( var == nullptr ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( pos >= var.size() ) return CBotTypResult(CBotTypFloat);
if ( var[pos].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
pos++;
if ( var == nullptr ) return CBotTypResult(CBotTypFloat);
if ( pos < var.size() ) return CBotTypResult(CBotTypFloat);
return CBotTypResult(CBotErrOverParam);
}
@ -1850,12 +1843,11 @@ bool CScriptFunctions::rGoto(CBotVar* var, CBotVar* result, int& exception, void
// 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->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( var.size() == 0 ) return CBotTypResult(CBotTypFloat);
if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat);
}
@ -1980,17 +1972,15 @@ bool CScriptFunctions::rSniff(CBotVar* var, CBotVar* result, int& exception, voi
// 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->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
var = var->GetNext();
if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
if ( var[0].GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
if ( var == nullptr ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var.size() == 1 ) return CBotTypResult(CBotTypFloat);
if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
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)".
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->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
var = var->GetNext();
if ( var.size() < 2 ) return CBotTypResult(CBotErrLowParam);
if ( var.size() > 3 ) return CBotTypResult(CBotErrOverParam);
if ( var[0].GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
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.size() == 2 ) return CBotTypResult(CBotTypFloat);
if ( var[2].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
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);
}
@ -2113,17 +2098,15 @@ CExchangePost* CScriptFunctions::FindExchangePost(CObject* object, float 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->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
var = var->GetNext();
if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
if ( var[0].GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
if ( var == nullptr ) return CBotTypResult(CBotTypBoolean);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var.size() == 1 ) return CBotTypResult(CBotTypBoolean);
if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypBoolean);
}
@ -2159,17 +2142,15 @@ bool CScriptFunctions::rDeleteInfo(CBotVar* var, CBotVar* result, int& exception
// 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->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
var = var->GetNext();
if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
if ( var[0].GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
if ( var == nullptr ) return CBotTypResult(CBotTypBoolean);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var.size() == 1 ) return CBotTypResult(CBotTypBoolean);
if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypBoolean);
}
@ -2258,17 +2239,12 @@ bool CScriptFunctions::rRecycle(CBotVar* var, CBotVar* result, int& exception, v
// 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->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( var.size() < 2 ) return CBotTypResult(CBotErrLowParam);
if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
return CBotTypResult(CBotTypFloat);
}
@ -2338,7 +2314,7 @@ bool CScriptFunctions::rShield(CBotVar* var, CBotVar* result, int& exception, vo
// 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;
ObjectType type;
@ -2347,25 +2323,25 @@ CBotTypResult CScriptFunctions::cFire(CBotVar* &var, void* user)
if ( type == OBJECT_ANT )
{
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
CBotTypResult ret = cPoint(var, user);
if ( ret.GetType() != 0 ) return ret;
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
size_t pos = 0;
CBotTypResult ret = cPoint(var, pos, user);
if ( ret.GetType() != CBotTypVoid ) return ret;
if ( var.size() > pos ) return CBotTypResult(CBotErrOverParam);
}
else if ( type == OBJECT_SPIDER )
{
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( var.size() > 0 ) return CBotTypResult(CBotErrOverParam);
}
else
{
if ( var != nullptr )
if ( var.size() > 0 )
{
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var.size() > 1 ) return CBotTypResult(CBotErrOverParam);
}
}
return CBotTypResult(CBotTypFloat);
return CBotTypFloat;
}
// Instruction "fire(delay)".
@ -2420,17 +2396,15 @@ bool CScriptFunctions::rFire(CBotVar* var, CBotVar* result, int& exception, void
// 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->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var == nullptr ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var.size() == 1 ) return CBotTypResult(CBotTypFloat);
if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat);
}
@ -2467,17 +2441,12 @@ bool CScriptFunctions::rAim(CBotVar* var, CBotVar* result, int& exception, void*
// 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->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( var.size() < 2 ) return CBotTypResult(CBotErrLowParam);
if ( var.size() > 2 ) return CBotTypResult(CBotErrOverParam);
if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
return CBotTypResult(CBotTypFloat);
}
@ -2531,15 +2500,16 @@ bool CScriptFunctions::rJet(CBotVar* var, CBotVar* result, int& exception, void*
// 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;
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
ret = cPoint(var, user);
if ( ret.GetType() != 0 ) return ret;
if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
size_t pos = 0;
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);
}
@ -2563,18 +2533,16 @@ bool CScriptFunctions::rTopo(CBotVar* var, CBotVar* result, int& exception, void
// 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->GetType() != CBotTypString &&
var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
if ( var[0].GetType() != CBotTypString &&
var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // TODO unhelpful error message
if ( var == nullptr ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var.size() == 1 ) return CBotTypResult(CBotTypFloat);
if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var == nullptr ) return CBotTypResult(CBotTypFloat);
if ( var.size() == 2 ) return CBotTypResult(CBotTypFloat);
return CBotTypResult(CBotErrOverParam);
}
@ -2674,17 +2642,15 @@ bool CScriptFunctions::rAbsTime(CBotVar* var, CBotVar* result, int& exception, v
// 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->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var.size() == 0 ) return CBotTypResult(CBotTypFloat);
if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var == nullptr ) return CBotTypResult(CBotTypFloat);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var.size() == 1 ) return CBotTypResult(CBotTypFloat);
if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var == nullptr ) return CBotTypResult(CBotTypFloat);
if ( var.size() == 2 ) return CBotTypResult(CBotTypFloat);
return CBotTypResult(CBotErrOverParam);
}
@ -2891,11 +2857,11 @@ bool CScriptFunctions::rPenWidth(CBotVar* var, CBotVar* result, int& exception,
// 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);
var = var->GetNext();
if ( var == nullptr ) return CBotTypResult(CBotTypFloat);
if ( var.size() == 0 ) return CBotTypResult(CBotErrLowParam);
if ( var.size() == 1 ) return CBotTypResult(CBotTypFloat);
// TODO: shouldn't we check parameter type?
return CBotTypResult(CBotErrOverParam);
}
@ -2918,30 +2884,27 @@ bool CScriptFunctions::rCameraFocus(CBotVar* var, CBotVar* result, int& exceptio
// 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):
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var[0].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
// Second parameter (y):
if ( var == nullptr ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var.size() == 1 ) return CBotTypResult(CBotErrLowParam);
if ( var[1].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
// Third parameter (z):
if ( var == nullptr ) // only 2 parameters?
if ( var.size() == 2 ) // only 2 parameters?
{
return CBotTypResult(0); // this function returns void
}
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != nullptr ) return CBotTypResult(CBotErrOverParam);
if ( var[2].GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
if ( var.size() > 3 ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(0); // this function returns void
}

View File

@ -25,6 +25,7 @@
#pragma once
#include "CBot/CBot.h"
#include "CBot/CBotTypResult.h"
#include "common/error.h"
@ -52,37 +53,37 @@ public:
static bool CheckOpenFiles();
private:
static CBot::CBotTypResult cEndMission(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cPlayMusic(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cGetObject(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cDelete(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cSearch(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cSearchAll(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cRadar(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cRadarAll(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cDetect(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cDirection(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cProduce(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cDistance(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cSpace(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cFlatSpace(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cFlatGround(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cGoto(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cGrabDrop(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cReceive(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cSend(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cDeleteInfo(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cTestInfo(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cShield(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cFire(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cAim(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cMotor(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cTopo(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cMessage(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cPenDown(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cEndMission(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cPlayMusic(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cGetObject(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cDelete(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cSearch(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cSearchAll(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cRadar(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cRadarAll(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cDetect(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cDirection(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cProduce(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cDistance(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cSpace(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cFlatSpace(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cFlatGround(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cGoto(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cGrabDrop(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cReceive(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cSend(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cDeleteInfo(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cTestInfo(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cShield(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cFire(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cAim(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cMotor(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cTopo(const std::vector<CBot::CBotTypResult> &var, void* user);
static CBot::CBotTypResult cMessage(const std::vector<CBot::CBotTypResult> &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 cOneObject(CBot::CBotVar* &var, void* user);
static CBot::CBotTypResult cOnePoint(const std::vector<CBot::CBotTypResult> &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 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 CBot::CBotTypResult cBusy(CBot::CBotVar* thisclass, CBot::CBotVar* &var);
static CBot::CBotTypResult cFactory(CBot::CBotVar* thisclass, CBot::CBotVar* &var);
static CBot::CBotTypResult cClassNull(CBot::CBotVar* thisclass, CBot::CBotVar* &var);
static CBot::CBotTypResult cClassOneFloat(CBot::CBotVar* thisclass, CBot::CBotVar* &var);
static CBot::CBotTypResult cBusy(CBot::CBotTypResult thisType, const std::vector<CBot::CBotTypResult> &var);
static CBot::CBotTypResult cFactory(CBot::CBotTypResult thisType, const std::vector<CBot::CBotTypResult> &var);
static CBot::CBotTypResult cClassNull(CBot::CBotTypResult thisType, const std::vector<CBot::CBotTypResult> &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 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 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 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 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 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 void uObject(CBot::CBotVar* botThis, void* user);

View File

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

View File

@ -57,14 +57,13 @@ private:
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);
var = var->GetNext();
if (var[0].GetType() != CBotTypString) return CBotTypResult(CBotErrBadString);
}
if (var != nullptr) return CBotTypResult(CBotErrOverParam);
if (var.size() > 1) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypVoid);
}
@ -79,11 +78,10 @@ private:
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->GetType() != CBotTypBoolean) return CBotTypResult(CBotErrBadString);
var = var->GetNext();
if (var.size() == 0) return CBotTypResult(CBotErrLowParam);
if (var[0].GetType() != CBotTypBoolean) return CBotTypResult(CBotErrBadString);
return CBotTypResult(CBotTypVoid);
}