parent
0102e45855
commit
4a62e9ed76
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "CBot/CBotCStack.h"
|
#include "CBot/CBotCStack.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotClass.h"
|
||||||
#include "CBot/CBotToken.h"
|
#include "CBot/CBotToken.h"
|
||||||
#include "CBot/CBotExternalCall.h"
|
#include "CBot/CBotExternalCall.h"
|
||||||
|
|
||||||
|
@ -320,6 +321,50 @@ void CBotCStack::AddVar(CBotVar* pVar)
|
||||||
*pp = pVar; // added after
|
*pp = pVar; // added after
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void CBotCStack::CreateVarThis(CBotClass* pClass)
|
||||||
|
{
|
||||||
|
if ( pClass == nullptr ) return;
|
||||||
|
|
||||||
|
CBotVar* pThis = CBotVar::Create("this", CBotTypResult(CBotTypClass, pClass));
|
||||||
|
|
||||||
|
pThis->SetUniqNum(-2); // special ID for "this"
|
||||||
|
AddVar(pThis);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void CBotCStack::CreateVarSuper(CBotClass* pClass)
|
||||||
|
{
|
||||||
|
if ( pClass == nullptr ) return;
|
||||||
|
|
||||||
|
CBotVar* pSuper = CBotVar::Create("super", CBotTypResult(CBotTypClass, pClass));
|
||||||
|
|
||||||
|
pSuper->SetUniqNum(-3); // special ID for "super"
|
||||||
|
AddVar(pSuper);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void CBotCStack::CreateMemberVars(CBotClass* pClass, bool setDefined)
|
||||||
|
{
|
||||||
|
while (pClass != nullptr)
|
||||||
|
{
|
||||||
|
CBotVar* pv = pClass->GetVar();
|
||||||
|
while (pv != nullptr)
|
||||||
|
{
|
||||||
|
CBotVar* pcopy = CBotVar::Create(pv);
|
||||||
|
CBotVar::InitType initType = CBotVar::InitType::UNDEF;
|
||||||
|
if (setDefined || pv->IsStatic())
|
||||||
|
initType = CBotVar::InitType::DEF;
|
||||||
|
pcopy->SetInit(initType);
|
||||||
|
pcopy->SetUniqNum(pv->GetUniqNum());
|
||||||
|
pcopy->SetPrivate(pv->GetPrivate());
|
||||||
|
AddVar(pcopy);
|
||||||
|
pv = pv->GetNext();
|
||||||
|
}
|
||||||
|
pClass = pClass->GetParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotCStack::CheckVarLocal(CBotToken* &pToken)
|
bool CBotCStack::CheckVarLocal(CBotToken* &pToken)
|
||||||
{
|
{
|
||||||
|
@ -350,7 +395,7 @@ CBotTypResult CBotCStack::CompileCall(CBotToken* &p, CBotVar** ppVars, long& nId
|
||||||
val = m_prog->GetExternalCalls()->CompileCall(p, nullptr, ppVars, this);
|
val = m_prog->GetExternalCalls()->CompileCall(p, nullptr, ppVars, this);
|
||||||
if (val.GetType() < 0)
|
if (val.GetType() < 0)
|
||||||
{
|
{
|
||||||
val = CBotFunction::CompileCall(m_prog->GetFunctions(), p->GetString(), ppVars, nIdent);
|
val = CBotFunction::CompileCall(p->GetString(), ppVars, nIdent, m_prog);
|
||||||
if ( val.GetType() < 0 )
|
if ( val.GetType() < 0 )
|
||||||
{
|
{
|
||||||
// pVar = nullptr; // the error is not on a particular parameter
|
// pVar = nullptr; // the error is not on a particular parameter
|
||||||
|
@ -363,7 +408,7 @@ CBotTypResult CBotCStack::CompileCall(CBotToken* &p, CBotVar** ppVars, long& nId
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam)
|
bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam, const std::string& className)
|
||||||
{
|
{
|
||||||
std::string name = pToken->GetString();
|
std::string name = pToken->GetString();
|
||||||
|
|
||||||
|
@ -373,6 +418,9 @@ bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam)
|
||||||
{
|
{
|
||||||
if ( pToken->GetString() == pp->GetName() )
|
if ( pToken->GetString() == pp->GetName() )
|
||||||
{
|
{
|
||||||
|
// ignore methods for a different class
|
||||||
|
if ( className != pp->GetClassName() )
|
||||||
|
continue;
|
||||||
// are parameters exactly the same?
|
// are parameters exactly the same?
|
||||||
if ( pp->CheckParam( pParam ) )
|
if ( pp->CheckParam( pParam ) )
|
||||||
return true;
|
return true;
|
||||||
|
@ -383,6 +431,9 @@ bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam)
|
||||||
{
|
{
|
||||||
if ( pToken->GetString() == pp->GetName() )
|
if ( pToken->GetString() == pp->GetName() )
|
||||||
{
|
{
|
||||||
|
// ignore methods for a different class
|
||||||
|
if ( className != pp->GetClassName() )
|
||||||
|
continue;
|
||||||
// are parameters exactly the same?
|
// are parameters exactly the same?
|
||||||
if ( pp->CheckParam( pParam ) )
|
if ( pp->CheckParam( pParam ) )
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -100,6 +100,25 @@ public:
|
||||||
*/
|
*/
|
||||||
void AddVar(CBotVar* p);
|
void AddVar(CBotVar* p);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Create 'this' as a local variable.
|
||||||
|
* \param pClass The current class referred to by 'this'
|
||||||
|
*/
|
||||||
|
void CreateVarThis(CBotClass* pClass);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Create 'super' as a local variable.
|
||||||
|
* \param pClass The parent class referred to by 'super'
|
||||||
|
*/
|
||||||
|
void CreateVarSuper(CBotClass* pClass);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Create member variables of the current class as local variables.
|
||||||
|
* \param pClass The current class.
|
||||||
|
* \param setDefined Whether to mark the variables as initialized.
|
||||||
|
*/
|
||||||
|
void CreateMemberVars(CBotClass* pClass, bool setDefined);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief FindVar Finds a variable. Seeks a variable on the stack the token
|
* \brief FindVar Finds a variable. Seeks a variable on the stack the token
|
||||||
* may be a result of TokenTypVar (object of a class) or a pointer in the
|
* may be a result of TokenTypVar (object of a class) or a pointer in the
|
||||||
|
@ -235,11 +254,12 @@ public:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief CheckCall Test if a procedure name is already defined somewhere.
|
* \brief CheckCall Test if a procedure name is already defined somewhere.
|
||||||
* \param pToken
|
* \param pToken Token representing the name of a function.
|
||||||
* \param pParam
|
* \param pParam List of parameters.
|
||||||
|
* \param className Name of a class when checking for methods.
|
||||||
* \return
|
* \return
|
||||||
*/
|
*/
|
||||||
bool CheckCall(CBotToken* &pToken, CBotDefParam* pParam);
|
bool CheckCall(CBotToken* &pToken, CBotDefParam* pParam, const std::string& className);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief NextToken
|
* \brief NextToken
|
||||||
|
|
|
@ -315,7 +315,7 @@ CBotTypResult CBotClass::CompileMethode(CBotToken* name,
|
||||||
|
|
||||||
// find the methods declared by user
|
// find the methods declared by user
|
||||||
|
|
||||||
r = CBotFunction::CompileCall(m_pMethod, name->GetString(), ppParams, nIdent);
|
r = CBotFunction::CompileMethodCall(name->GetString(), ppParams, nIdent, pStack, this);
|
||||||
if ( r.Eq(CBotErrUndefCall) && m_parent != nullptr )
|
if ( r.Eq(CBotErrUndefCall) && m_parent != nullptr )
|
||||||
return m_parent->CompileMethode(name, pThis, ppParams, pStack, nIdent);
|
return m_parent->CompileMethode(name, pThis, ppParams, pStack, nIdent);
|
||||||
return r;
|
return r;
|
||||||
|
@ -332,7 +332,7 @@ bool CBotClass::ExecuteMethode(long& nIdent,
|
||||||
int ret = m_externalMethods->DoCall(pToken, pThis, ppParams, pStack, pResultType);
|
int ret = m_externalMethods->DoCall(pToken, pThis, ppParams, pStack, pResultType);
|
||||||
if (ret >= 0) return ret;
|
if (ret >= 0) return ret;
|
||||||
|
|
||||||
ret = CBotFunction::DoCall(m_pMethod, nIdent, pToken->GetString(), pThis, ppParams, pStack, pToken, this);
|
ret = CBotFunction::DoCall(nIdent, pToken->GetString(), pThis, ppParams, pStack, pToken, this);
|
||||||
if (ret >= 0) return ret;
|
if (ret >= 0) return ret;
|
||||||
|
|
||||||
if (m_parent != nullptr)
|
if (m_parent != nullptr)
|
||||||
|
@ -355,7 +355,7 @@ void CBotClass::RestoreMethode(long& nIdent,
|
||||||
CBotClass* pClass = this;
|
CBotClass* pClass = this;
|
||||||
while (pClass != nullptr)
|
while (pClass != nullptr)
|
||||||
{
|
{
|
||||||
bool ok = CBotFunction::RestoreCall(pClass->m_pMethod, nIdent, name->GetString(), pThis, ppParams, pStack, pClass);
|
bool ok = CBotFunction::RestoreCall(nIdent, name->GetString(), pThis, ppParams, pStack, pClass);
|
||||||
if (ok) return;
|
if (ok) return;
|
||||||
pClass = pClass->m_parent;
|
pClass = pClass->m_parent;
|
||||||
}
|
}
|
||||||
|
@ -542,6 +542,11 @@ void CBotClass::DefineClasses(std::list<CBotClass*> pClassList, CBotCStack* pSta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::list<CBotFunction*>& CBotClass::GetFunctions()
|
||||||
|
{
|
||||||
|
return m_pMethod;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
||||||
{
|
{
|
||||||
|
@ -609,45 +614,8 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
||||||
CBotFunction* pf = *pfIter;
|
CBotFunction* pf = *pfIter;
|
||||||
delete params;
|
delete params;
|
||||||
|
|
||||||
bool bConstructor = (pp == GetName());
|
|
||||||
CBotCStack* pile = pStack->TokenStack(nullptr, true);
|
CBotCStack* pile = pStack->TokenStack(nullptr, true);
|
||||||
|
|
||||||
// make "this" known
|
|
||||||
CBotToken TokenThis(std::string("this"), std::string());
|
|
||||||
CBotVar* pThis = CBotVar::Create(TokenThis, CBotTypResult( CBotTypClass, this ) );
|
|
||||||
pThis->SetUniqNum(-2);
|
|
||||||
pile->AddVar(pThis);
|
|
||||||
|
|
||||||
if (m_parent)
|
|
||||||
{
|
|
||||||
// makes "super" known
|
|
||||||
CBotToken TokenSuper(std::string("super"), std::string());
|
|
||||||
CBotVar* pThis = CBotVar::Create(TokenSuper, CBotTypResult(CBotTypClass, m_parent) );
|
|
||||||
pThis->SetUniqNum(-3);
|
|
||||||
pile->AddVar(pThis);
|
|
||||||
}
|
|
||||||
|
|
||||||
// int num = 1;
|
|
||||||
CBotClass* my = this;
|
|
||||||
while (my != nullptr)
|
|
||||||
{
|
|
||||||
// places a copy of variables of a class (this) on a stack
|
|
||||||
CBotVar* pv = my->m_pVar;
|
|
||||||
while (pv != nullptr)
|
|
||||||
{
|
|
||||||
CBotVar* pcopy = CBotVar::Create(pv);
|
|
||||||
CBotVar::InitType initType = CBotVar::InitType::UNDEF;
|
|
||||||
if (!bConstructor || pv->IsStatic())
|
|
||||||
initType = CBotVar::InitType::DEF;
|
|
||||||
pcopy->SetInit(initType);
|
|
||||||
pcopy->SetUniqNum(pv->GetUniqNum());
|
|
||||||
pcopy->SetPrivate(pv->GetPrivate());
|
|
||||||
pile->AddVar(pcopy);
|
|
||||||
pv = pv->GetNext();
|
|
||||||
}
|
|
||||||
my = my->m_parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// compiles a method
|
// compiles a method
|
||||||
p = pBase;
|
p = pBase;
|
||||||
CBotFunction* f =
|
CBotFunction* f =
|
||||||
|
|
|
@ -303,6 +303,12 @@ public:
|
||||||
*/
|
*/
|
||||||
static void DefineClasses(std::list<CBotClass*> pClassList, CBotCStack* pStack);
|
static void DefineClasses(std::list<CBotClass*> pClassList, CBotCStack* pStack);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Get the list of user-defined methods in this class.
|
||||||
|
* \return List of methods, can be empty.
|
||||||
|
*/
|
||||||
|
const std::list<CBotFunction*>& GetFunctions();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief CompileDefItem
|
* \brief CompileDefItem
|
||||||
* \param p
|
* \param p
|
||||||
|
|
|
@ -129,12 +129,10 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
|
||||||
{
|
{
|
||||||
CBotToken* pp;
|
CBotToken* pp;
|
||||||
CBotFunction* func = finput;
|
CBotFunction* func = finput;
|
||||||
if ( func == nullptr ) func = new CBotFunction();
|
assert(func != nullptr); // a pre-compiled function is required
|
||||||
|
|
||||||
CBotCStack* pStk = pStack->TokenStack(p, bLocal);
|
CBotCStack* pStk = pStack->TokenStack(p, bLocal);
|
||||||
|
|
||||||
// func->m_nFuncIdent = CBotVar::NextUniqNum();
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if ( IsOfType(p, ID_PUBLIC) )
|
if ( IsOfType(p, ID_PUBLIC) )
|
||||||
|
@ -183,10 +181,23 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pp = p;
|
pp = p;
|
||||||
func->m_token = *p;
|
func->m_token = *p;
|
||||||
if (!IsOfType(p, TokenTypVar)) goto bad;
|
if (!IsOfType(p, TokenTypVar)) goto bad;
|
||||||
|
// check if the class has a method like this
|
||||||
|
if (pClass->CheckCall(pStack->GetProgram(), func->m_param, pp))
|
||||||
|
{
|
||||||
|
pStk->SetStartError(func->m_classToken.GetStart());
|
||||||
|
pStk->SetError(CBotErrRedefFunc, pp->GetEnd());
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
// check if a constructor has return type void
|
||||||
|
if (func->GetName() == pClass->GetName() && !func->m_retTyp.Eq(CBotTypVoid))
|
||||||
|
{
|
||||||
|
pp = &(func->m_retToken);
|
||||||
|
pStk->SetError(CBotErrFuncNotVoid, pp);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
func->m_openpar = *p;
|
func->m_openpar = *p;
|
||||||
delete func->m_param;
|
delete func->m_param;
|
||||||
|
@ -198,28 +209,13 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
|
||||||
|
|
||||||
if (!func->m_MasterClass.empty())
|
if (!func->m_MasterClass.empty())
|
||||||
{
|
{
|
||||||
// return "this" known
|
CBotClass* pClass = CBotClass::Find(func->m_MasterClass);
|
||||||
CBotVar* pThis = CBotVar::Create("this", CBotTypResult( CBotTypClass, func->m_MasterClass ));
|
|
||||||
pThis->SetInit(CBotVar::InitType::IS_POINTER);
|
|
||||||
// pThis->SetUniqNum(func->m_nThisIdent = -2); //CBotVar::NextUniqNum() will not
|
|
||||||
pThis->SetUniqNum(-2);
|
|
||||||
pStk->AddVar(pThis);
|
|
||||||
|
|
||||||
// initialize variables acording to This
|
pStk->CreateVarThis(pClass);
|
||||||
// only saves the pointer to the first,
|
pStk->CreateVarSuper(pClass->GetParent());
|
||||||
// the rest is chained
|
|
||||||
CBotVar* pv = pThis->GetItemList();
|
bool bConstructor = (func->GetName() == func->m_MasterClass);
|
||||||
// int num = 1;
|
pStk->CreateMemberVars(pClass, !bConstructor);
|
||||||
while (pv != nullptr)
|
|
||||||
{
|
|
||||||
CBotVar* pcopy = CBotVar::Create(pv);
|
|
||||||
// pcopy->SetInit(2);
|
|
||||||
pcopy->Copy(pv);
|
|
||||||
pcopy->SetPrivate(pv->GetPrivate());
|
|
||||||
// pcopy->SetUniqNum(pv->GetUniqNum()); //num++);
|
|
||||||
pStk->AddVar(pcopy);
|
|
||||||
pv = pv->GetNext();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// and compiles the following instruction block
|
// and compiles the following instruction block
|
||||||
|
@ -242,7 +238,6 @@ bad:
|
||||||
pStk->SetError(CBotErrNoFunc, p);
|
pStk->SetError(CBotErrNoFunc, p);
|
||||||
}
|
}
|
||||||
pStk->SetError(CBotErrNoType, p);
|
pStk->SetError(CBotErrNoType, p);
|
||||||
if ( finput == nullptr ) delete func;
|
|
||||||
return pStack->ReturnFunc(nullptr, pStk);
|
return pStack->ReturnFunc(nullptr, pStk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,6 +298,7 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
|
||||||
|
|
||||||
if (pStk->IsOk() && pClass != nullptr) // method in a class
|
if (pStk->IsOk() && pClass != nullptr) // method in a class
|
||||||
{
|
{
|
||||||
|
func->m_MasterClass = pClass->GetName();
|
||||||
// check if a constructor has return type void
|
// check if a constructor has return type void
|
||||||
if (func->GetName() == pClass->GetName() && !func->m_retTyp.Eq(CBotTypVoid))
|
if (func->GetName() == pClass->GetName() && !func->m_retTyp.Eq(CBotTypVoid))
|
||||||
{
|
{
|
||||||
|
@ -331,7 +327,7 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
|
||||||
{
|
{
|
||||||
// looks if the function exists elsewhere
|
// looks if the function exists elsewhere
|
||||||
pp = &(func->m_token);
|
pp = &(func->m_token);
|
||||||
if (( pClass != nullptr || !pStack->CheckCall(pp, func->m_param)) &&
|
if (( pClass != nullptr || !pStack->CheckCall(pp, func->m_param, func->m_MasterClass)) &&
|
||||||
( pClass == nullptr || !pClass->CheckCall(pStack->GetProgram(), func->m_param, pp)) )
|
( pClass == nullptr || !pClass->CheckCall(pStack->GetProgram(), func->m_param, pp)) )
|
||||||
{
|
{
|
||||||
if (IsOfType(p, ID_OPBLK))
|
if (IsOfType(p, ID_OPBLK))
|
||||||
|
@ -472,10 +468,10 @@ 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::string &name, CBotVar** ppVars, long &nIdent, CBotProgram* program)
|
||||||
{
|
{
|
||||||
CBotTypResult type;
|
CBotTypResult type;
|
||||||
if (!FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type))
|
if (!FindLocalOrPublic(program->GetFunctions(), nIdent, name, ppVars, type, program))
|
||||||
{
|
{
|
||||||
// Reset the identifier to "not found" value
|
// Reset the identifier to "not found" value
|
||||||
nIdent = 0;
|
nIdent = 0;
|
||||||
|
@ -485,7 +481,7 @@ CBotTypResult CBotFunction::CompileCall(const std::list<CBotFunction*>& localFun
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name,
|
CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name,
|
||||||
CBotVar** ppVars, CBotTypResult &TypeOrError, bool bPublic)
|
CBotVar** ppVars, CBotTypResult &TypeOrError, CBotProgram* baseProg)
|
||||||
{
|
{
|
||||||
TypeOrError.SetType(CBotErrUndefCall); // no routine of the name
|
TypeOrError.SetType(CBotErrUndefCall); // no routine of the name
|
||||||
|
|
||||||
|
@ -515,10 +511,39 @@ CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& lo
|
||||||
|
|
||||||
std::map<CBotFunction*, int> funcMap;
|
std::map<CBotFunction*, int> funcMap;
|
||||||
|
|
||||||
for (CBotFunction* pt : localFunctionList)
|
CBotFunction::SearchList(localFunctionList, name, ppVars, TypeOrError, funcMap);
|
||||||
|
|
||||||
|
CBotFunction::SearchPublic(name, ppVars, TypeOrError, funcMap);
|
||||||
|
|
||||||
|
if (baseProg != nullptr && baseProg->m_thisVar != nullptr)
|
||||||
|
{
|
||||||
|
// find object:: functions
|
||||||
|
CBotClass* pClass = baseProg->m_thisVar->GetClass();
|
||||||
|
CBotFunction::SearchList(localFunctionList, name, ppVars, TypeOrError, funcMap, pClass);
|
||||||
|
CBotFunction::SearchPublic(name, ppVars, TypeOrError, funcMap, pClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CBotFunction::BestFunction(funcMap, nIdent, TypeOrError);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void CBotFunction::SearchList(const std::list<CBotFunction*>& functionList,
|
||||||
|
const std::string& name, CBotVar** ppVars, CBotTypResult& TypeOrError,
|
||||||
|
std::map<CBotFunction*, int>& funcMap, CBotClass* pClass)
|
||||||
|
{
|
||||||
|
for (CBotFunction* pt : functionList)
|
||||||
{
|
{
|
||||||
if ( pt->m_token.GetString() == name )
|
if ( pt->m_token.GetString() == name )
|
||||||
{
|
{
|
||||||
|
if (pClass != nullptr) // looking for a method ?
|
||||||
|
{
|
||||||
|
if (pt->m_MasterClass != pClass->GetName()) continue;
|
||||||
|
}
|
||||||
|
else // looking for a function
|
||||||
|
{
|
||||||
|
if (!pt->m_MasterClass.empty()) continue;
|
||||||
|
}
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int alpha = 0; // signature of parameters
|
int alpha = 0; // signature of parameters
|
||||||
// parameters are compatible?
|
// parameters are compatible?
|
||||||
|
@ -575,13 +600,26 @@ CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& lo
|
||||||
funcMap.insert( std::pair<CBotFunction*, int>(pt, alpha) );
|
funcMap.insert( std::pair<CBotFunction*, int>(pt, alpha) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( bPublic )
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void CBotFunction::SearchPublic(const std::string& name, CBotVar** ppVars, CBotTypResult& TypeOrError,
|
||||||
|
std::map<CBotFunction*, int>& funcMap, CBotClass* pClass)
|
||||||
|
{
|
||||||
{
|
{
|
||||||
for (CBotFunction* pt : m_publicFunctions)
|
for (CBotFunction* pt : m_publicFunctions)
|
||||||
{
|
{
|
||||||
if ( pt->m_token.GetString() == name )
|
if ( pt->m_token.GetString() == name )
|
||||||
{
|
{
|
||||||
|
if (pClass != nullptr) // looking for a method ?
|
||||||
|
{
|
||||||
|
if (pt->m_MasterClass != pClass->GetName()) continue;
|
||||||
|
}
|
||||||
|
else // looking for a function
|
||||||
|
{
|
||||||
|
if (!pt->m_MasterClass.empty()) continue;
|
||||||
|
}
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int alpha = 0; // signature of parameters
|
int alpha = 0; // signature of parameters
|
||||||
// are parameters compatible ?
|
// are parameters compatible ?
|
||||||
|
@ -639,7 +677,12 @@ CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& lo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
CBotFunction* CBotFunction::BestFunction(std::map<CBotFunction*, int>& funcMap,
|
||||||
|
long& nIdent, CBotTypResult& TypeOrError)
|
||||||
|
{
|
||||||
if ( !funcMap.empty() )
|
if ( !funcMap.empty() )
|
||||||
{
|
{
|
||||||
auto it = funcMap.begin();
|
auto it = funcMap.begin();
|
||||||
|
@ -675,7 +718,7 @@ int CBotFunction::DoCall(CBotProgram* program, const std::list<CBotFunction*>& l
|
||||||
CBotFunction* pt = nullptr;
|
CBotFunction* pt = nullptr;
|
||||||
CBotProgram* baseProg = pStack->GetProgram(true);
|
CBotProgram* baseProg = pStack->GetProgram(true);
|
||||||
|
|
||||||
pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type);
|
pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type, baseProg);
|
||||||
|
|
||||||
if ( pt != nullptr )
|
if ( pt != nullptr )
|
||||||
{
|
{
|
||||||
|
@ -766,7 +809,7 @@ void CBotFunction::RestoreCall(const std::list<CBotFunction*>& localFunctionList
|
||||||
CBotStack* pStk3;
|
CBotStack* pStk3;
|
||||||
CBotProgram* baseProg = pStack->GetProgram(true);
|
CBotProgram* baseProg = pStack->GetProgram(true);
|
||||||
|
|
||||||
pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type);
|
pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type, baseProg);
|
||||||
|
|
||||||
if ( pt != nullptr )
|
if ( pt != nullptr )
|
||||||
{
|
{
|
||||||
|
@ -824,13 +867,102 @@ void CBotFunction::RestoreCall(const std::list<CBotFunction*>& localFunctionList
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
int CBotFunction::DoCall(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis,
|
CBotTypResult CBotFunction::CompileMethodCall(const std::string& name, CBotVar** ppVars,
|
||||||
|
long& nIdent, CBotCStack* pStack, CBotClass* pClass)
|
||||||
|
{
|
||||||
|
nIdent = 0;
|
||||||
|
CBotTypResult type;
|
||||||
|
|
||||||
|
CBotFunction* pt = FindMethod(nIdent, name, ppVars, type, pClass, pStack->GetProgram());
|
||||||
|
|
||||||
|
if (pt != nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
CBotFunction* CBotFunction::FindMethod(long& nIdent, const std::string& name,
|
||||||
|
CBotVar** ppVars, CBotTypResult& TypeOrError,
|
||||||
|
CBotClass* pClass, CBotProgram* program)
|
||||||
|
{
|
||||||
|
TypeOrError.SetType(CBotErrUndefCall); // no routine of the name
|
||||||
|
|
||||||
|
auto methods = pClass->GetFunctions();
|
||||||
|
|
||||||
|
if ( nIdent )
|
||||||
|
{
|
||||||
|
// search methods in the class
|
||||||
|
for (CBotFunction* pt : methods)
|
||||||
|
{
|
||||||
|
if ( pt->m_nFuncIdent == nIdent )
|
||||||
|
{
|
||||||
|
TypeOrError = pt->m_retTyp;
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool skipPublic = false;
|
||||||
|
if (program != nullptr)
|
||||||
|
{
|
||||||
|
// search the current program
|
||||||
|
for (CBotFunction* pt : program->GetFunctions())
|
||||||
|
{
|
||||||
|
if ( pt->m_nFuncIdent == nIdent )
|
||||||
|
{
|
||||||
|
// check if the method is inherited
|
||||||
|
if ( pt->GetClassName() != pClass->GetName() )
|
||||||
|
{
|
||||||
|
skipPublic = true;
|
||||||
|
break; // break in case there is an override
|
||||||
|
}
|
||||||
|
TypeOrError = pt->m_retTyp;
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// search the list of public functions
|
||||||
|
if (!skipPublic)
|
||||||
|
{
|
||||||
|
for (CBotFunction* pt : m_publicFunctions)
|
||||||
|
{
|
||||||
|
if (pt->m_nFuncIdent == nIdent)
|
||||||
|
{
|
||||||
|
// check if the method is inherited, break in case there is an override
|
||||||
|
if ( pt->GetClassName() != pClass->GetName() ) break;
|
||||||
|
TypeOrError = pt->m_retTyp;
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( name.empty() ) return nullptr;
|
||||||
|
|
||||||
|
std::map<CBotFunction*, int> funcMap;
|
||||||
|
|
||||||
|
// search methods in the class
|
||||||
|
CBotFunction::SearchList(methods, name, ppVars, TypeOrError, funcMap, pClass);
|
||||||
|
|
||||||
|
// search the current program for methods
|
||||||
|
if (program != nullptr)
|
||||||
|
CBotFunction::SearchList(program->GetFunctions(), name, ppVars, TypeOrError, funcMap, pClass);
|
||||||
|
|
||||||
|
CBotFunction::SearchPublic(name, ppVars, TypeOrError, funcMap, pClass);
|
||||||
|
|
||||||
|
return CBotFunction::BestFunction(funcMap, nIdent, TypeOrError);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int CBotFunction::DoCall(long &nIdent, const std::string &name, CBotVar* pThis,
|
||||||
CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken, CBotClass* pClass)
|
CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken, CBotClass* pClass)
|
||||||
{
|
{
|
||||||
CBotTypResult type;
|
CBotTypResult type;
|
||||||
CBotProgram* pProgCurrent = pStack->GetProgram();
|
CBotProgram* pProgCurrent = pStack->GetProgram();
|
||||||
|
|
||||||
CBotFunction* pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type, false);
|
CBotFunction* pt = FindMethod(nIdent, name, ppVars, type, pClass, pProgCurrent);
|
||||||
|
|
||||||
if ( pt != nullptr )
|
if ( pt != nullptr )
|
||||||
{
|
{
|
||||||
|
@ -925,11 +1057,11 @@ int CBotFunction::DoCall(const std::list<CBotFunction*>& localFunctionList, long
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotFunction::RestoreCall(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis,
|
bool CBotFunction::RestoreCall(long &nIdent, const std::string &name, CBotVar* pThis,
|
||||||
CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass)
|
CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass)
|
||||||
{
|
{
|
||||||
CBotTypResult type;
|
CBotTypResult type;
|
||||||
CBotFunction* pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type);
|
CBotFunction* pt = FindMethod(nIdent, name, ppVars, type, pClass, pStack->GetProgram());
|
||||||
|
|
||||||
if ( pt != nullptr )
|
if ( pt != nullptr )
|
||||||
{
|
{
|
||||||
|
@ -1020,6 +1152,12 @@ std::string CBotFunction::GetParams()
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
const std::string& CBotFunction::GetClassName()
|
||||||
|
{
|
||||||
|
return m_MasterClass;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotFunction::AddPublic(CBotFunction* func)
|
void CBotFunction::AddPublic(CBotFunction* func)
|
||||||
{
|
{
|
||||||
|
|
|
@ -105,21 +105,19 @@ public:
|
||||||
*
|
*
|
||||||
* See FindLocalOrPublic for more detailed explanation
|
* See FindLocalOrPublic for more detailed explanation
|
||||||
*
|
*
|
||||||
* \param localFunctionList Linked list of local functions to search in, can be null
|
|
||||||
* \param name Name of the function
|
* \param name Name of the function
|
||||||
* \param ppVars List of function arguments
|
* \param ppVars List of function arguments
|
||||||
* \param nIdent[in, out] Unique identifier of the function
|
* \param nIdent[in, out] Unique identifier of the function
|
||||||
|
* \param program The current program, to search for functions.
|
||||||
* \return Type returned by the function or error code
|
* \return Type returned by the function or error code
|
||||||
* \see FindLocalOrPublic
|
* \see FindLocalOrPublic
|
||||||
*/
|
*/
|
||||||
static CBotTypResult CompileCall(const std::list<CBotFunction*>& localFunctionList,
|
static CBotTypResult CompileCall(const std::string &name, CBotVar** ppVars,
|
||||||
const std::string &name, CBotVar** ppVars, long &nIdent);
|
long &nIdent, CBotProgram* program);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Finds a local or public function
|
* \brief Finds a local or public function
|
||||||
*
|
*
|
||||||
* <p>Finds a local or (if bPublic is true) public function to call
|
|
||||||
*
|
|
||||||
* <p>First, it looks for a function according to its unique identifier.<br>
|
* <p>First, it looks for a function according to its unique identifier.<br>
|
||||||
* If the identifier is not found, looks by name and parameters.
|
* If the identifier is not found, looks by name and parameters.
|
||||||
*
|
*
|
||||||
|
@ -128,11 +126,46 @@ public:
|
||||||
* \param name Name of the function
|
* \param name Name of the function
|
||||||
* \param ppVars List of function arguments
|
* \param ppVars List of function arguments
|
||||||
* \param TypeOrError Type returned by the function or error code
|
* \param TypeOrError Type returned by the function or error code
|
||||||
* \param bPublic Whether to look in public functions or not
|
* \param baseProg Initial program, for context of the object/bot
|
||||||
* \return Pointer to found CBotFunction instance, or nullptr in case of no match or ambiguity (see TypeOrError for error code)
|
* \return Pointer to found CBotFunction instance, or nullptr in case of no match or ambiguity (see TypeOrError for error code)
|
||||||
*/
|
*/
|
||||||
static CBotFunction* FindLocalOrPublic(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name,
|
static CBotFunction* FindLocalOrPublic(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name,
|
||||||
CBotVar** ppVars, CBotTypResult &TypeOrError, bool bPublic = true);
|
CBotVar** ppVars, CBotTypResult &TypeOrError, CBotProgram* baseProg);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Find all functions that match the name and arguments.
|
||||||
|
* \param functionList List of functions to search, can be empty.
|
||||||
|
* \param name Name of the function to find.
|
||||||
|
* \param ppVars Arguments to compare with parameters.
|
||||||
|
* \param TypeOrError Contains a CBotError when no useable function has been found.
|
||||||
|
* \param funcMap Container for suitable functions and their signature values.
|
||||||
|
* \param pClass Pointer to class when searching for methods.
|
||||||
|
*/
|
||||||
|
static void SearchList(const std::list<CBotFunction*>& functionList,
|
||||||
|
const std::string& name, CBotVar** ppVars, CBotTypResult& TypeOrError,
|
||||||
|
std::map<CBotFunction*, int>& funcMap, CBotClass* pClass = nullptr);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Find all public functions that match the name and arguments.
|
||||||
|
* \param name Name of the function to find.
|
||||||
|
* \param ppVars Arguments to compare with parameters.
|
||||||
|
* \param TypeOrError Contains a CBotError when no useable function has been found.
|
||||||
|
* \param funcMap Container for suitable functions and their signature values.
|
||||||
|
* \param pClass Pointer to class when searching for methods.
|
||||||
|
*/
|
||||||
|
static void SearchPublic(const std::string& name, CBotVar** ppVars, CBotTypResult& TypeOrError,
|
||||||
|
std::map<CBotFunction*, int>& funcMap, CBotClass* pClass = nullptr);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Find the function with the lowest signature value. If there is more
|
||||||
|
* than one of the same signature value, TypeOrError is set to CBotErrAmbiguousCall.
|
||||||
|
* \param funcMap List of functions and their signature values, can be empty.
|
||||||
|
* \param[out] nIdent Unique identifier of the function.
|
||||||
|
* \param TypeOrError Type returned by the function or error code.
|
||||||
|
* \return Pointer to the function with the lowest signature or nullptr.
|
||||||
|
*/
|
||||||
|
static CBotFunction* BestFunction(std::map<CBotFunction*, int>& funcMap,
|
||||||
|
long& nIdent, CBotTypResult& TypeOrError);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief DoCall Fait un appel à une fonction.
|
* \brief DoCall Fait un appel à une fonction.
|
||||||
|
@ -160,10 +193,34 @@ public:
|
||||||
static void RestoreCall(const std::list<CBotFunction*>& localFunctionList,
|
static void RestoreCall(const std::list<CBotFunction*>& localFunctionList,
|
||||||
long &nIdent, const std::string &name, CBotVar** ppVars, CBotStack* pStack);
|
long &nIdent, const std::string &name, CBotVar** ppVars, CBotStack* pStack);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Find a method matching the name and arguments.
|
||||||
|
* \param name Name of the method to find.
|
||||||
|
* \param ppVars Arguments to compare with parameters.
|
||||||
|
* \param[out] nIdent Unique identifier of the method.
|
||||||
|
* \param pStack Current compilation stack frame.
|
||||||
|
* \param pClass Pointer to the class.
|
||||||
|
* \return The return type for the method or a CBotError.
|
||||||
|
*/
|
||||||
|
static CBotTypResult CompileMethodCall(const std::string& name, CBotVar** ppVars,
|
||||||
|
long& nIdent, CBotCStack* pStack, CBotClass* pClass);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Find a method by its unique identifier or by name and parameters.
|
||||||
|
* \param[in,out] nIdent Unique identifier of the method.
|
||||||
|
* \param name Name of the method to find.
|
||||||
|
* \param ppVars Arguments to compare with parameters.
|
||||||
|
* \param TypeOrError The return type for the method or a CBotError.
|
||||||
|
* \param pClass Pointer to the class.
|
||||||
|
* \param program The current program, to search for out-of-class methods.
|
||||||
|
* \return Pointer to the method that best matches the given arguments or nullptr.
|
||||||
|
*/
|
||||||
|
static CBotFunction* FindMethod(long& nIdent, const std::string& name,
|
||||||
|
CBotVar** ppVars, CBotTypResult& TypeOrError,
|
||||||
|
CBotClass* pClass, CBotProgram* program);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief DoCall Makes call of a method
|
* \brief DoCall Makes call of a method
|
||||||
* note: this is already on the stack, the pointer pThis is just to simplify.
|
|
||||||
* \param localFunctionList
|
|
||||||
* \param nIdent
|
* \param nIdent
|
||||||
* \param name
|
* \param name
|
||||||
* \param pThis
|
* \param pThis
|
||||||
|
@ -173,12 +230,11 @@ public:
|
||||||
* \param pClass
|
* \param pClass
|
||||||
* \return
|
* \return
|
||||||
*/
|
*/
|
||||||
static int DoCall(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis,
|
static int DoCall(long &nIdent, const std::string &name, CBotVar* pThis,
|
||||||
CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken, CBotClass* pClass);
|
CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken, CBotClass* pClass);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief RestoreCall
|
* \brief RestoreCall
|
||||||
* \param localFunctionList
|
|
||||||
* \param nIdent
|
* \param nIdent
|
||||||
* \param name
|
* \param name
|
||||||
* \param pThis
|
* \param pThis
|
||||||
|
@ -187,7 +243,7 @@ public:
|
||||||
* \param pClass
|
* \param pClass
|
||||||
* \return Returns true if the method call was restored.
|
* \return Returns true if the method call was restored.
|
||||||
*/
|
*/
|
||||||
static bool RestoreCall(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis,
|
static bool RestoreCall(long &nIdent, const std::string &name, CBotVar* pThis,
|
||||||
CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass);
|
CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -215,6 +271,12 @@ public:
|
||||||
*/
|
*/
|
||||||
std::string GetParams();
|
std::string GetParams();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Get the name of the class for a method.
|
||||||
|
* \return The name of a class or empty string if it's not a method.
|
||||||
|
*/
|
||||||
|
const std::string& GetClassName();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief IsPublic
|
* \brief IsPublic
|
||||||
* \return
|
* \return
|
||||||
|
|
|
@ -2768,3 +2768,303 @@ TEST_F(CBotUT, ParametersWithDefaultValues)
|
||||||
"}\n"
|
"}\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(CBotUT, ClassMethodsOutOfClass_Issue207)
|
||||||
|
{
|
||||||
|
auto publicProgram = ExecuteTest(
|
||||||
|
"public class OtherClass {}\n"
|
||||||
|
"public class TestClass {}\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
ExecuteTest(
|
||||||
|
"extern void TestCallWithoutObject()\n"
|
||||||
|
"{\n"
|
||||||
|
" TestMethod();\n"
|
||||||
|
"}\n"
|
||||||
|
"public void TestClass::TestMethod() {}\n",
|
||||||
|
CBotErrUndefCall
|
||||||
|
);
|
||||||
|
|
||||||
|
ExecuteTest(
|
||||||
|
"extern void TestCallWithWrongObject()\n"
|
||||||
|
"{\n"
|
||||||
|
" OtherClass oc();\n"
|
||||||
|
" oc.TestMethod();\n"
|
||||||
|
"}\n"
|
||||||
|
"public void TestClass::TestMethod() {}\n",
|
||||||
|
CBotErrUndefCall
|
||||||
|
);
|
||||||
|
|
||||||
|
ExecuteTest(
|
||||||
|
"extern void OtherClass::TestCallWithWrongThis()\n"
|
||||||
|
"{\n"
|
||||||
|
" this.TestMethod();\n"
|
||||||
|
"}\n"
|
||||||
|
"public void TestClass::TestMethod() {}\n",
|
||||||
|
CBotErrUndefCall
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CBotUT, ClassMethodsOutOfClass)
|
||||||
|
{
|
||||||
|
auto publicProgram = ExecuteTest(
|
||||||
|
"public class TestClass\n"
|
||||||
|
"{\n"
|
||||||
|
" int i = 123, j = 456, k = 789;\n"
|
||||||
|
" int InsideClass()\n"
|
||||||
|
" {\n"
|
||||||
|
" ASSERT(456 == PublicMethod());\n"
|
||||||
|
" ASSERT(789 == NotPublicMethod());\n"
|
||||||
|
" return this.i;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
"extern void TestMethodsOutOfClass()\n"
|
||||||
|
"{\n"
|
||||||
|
" TestClass tc();\n"
|
||||||
|
" ASSERT(123 == tc.InsideClass());\n"
|
||||||
|
" ASSERT(456 == tc.PublicMethod());\n"
|
||||||
|
" ASSERT(789 == tc.NotPublicMethod());\n"
|
||||||
|
"}\n"
|
||||||
|
"public int TestClass::PublicMethod()\n"
|
||||||
|
"{\n"
|
||||||
|
" return this.j;\n"
|
||||||
|
"}\n"
|
||||||
|
"int TestClass::NotPublicMethod()\n"
|
||||||
|
"{\n"
|
||||||
|
" return k;\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
ExecuteTest(
|
||||||
|
"extern void TestFromOtherProgram()\n"
|
||||||
|
"{\n"
|
||||||
|
" TestClass tc();\n"
|
||||||
|
" ASSERT(123 == tc.InsideClass());\n"
|
||||||
|
" ASSERT(456 == tc.PublicMethod());\n"
|
||||||
|
" ASSERT(789 == tc.MethodInThisProgram());\n"
|
||||||
|
"}\n"
|
||||||
|
"int TestClass::MethodInThisProgram()\n"
|
||||||
|
"{\n"
|
||||||
|
" ASSERT(123 == InsideClass());\n"
|
||||||
|
" ASSERT(456 == PublicMethod());\n"
|
||||||
|
" ASSERT(123 == this.InsideClass());\n"
|
||||||
|
" ASSERT(456 == this.PublicMethod());\n"
|
||||||
|
" ASSERT(i == 123 && this.j == 456);\n"
|
||||||
|
" return this.k;\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CBotUT, ClassInheritanceMethodsOutOfClass)
|
||||||
|
{
|
||||||
|
ExecuteTest(
|
||||||
|
"public class BaseClass {\n"
|
||||||
|
" int a = 123;\n"
|
||||||
|
" int b = 456;\n"
|
||||||
|
" int c = 789;\n"
|
||||||
|
"}\n"
|
||||||
|
"int BaseClass::testOverride() { return 123; }\n"
|
||||||
|
"int BaseClass::testNoOverride() { return 456; }\n"
|
||||||
|
"int BaseClass::testInsideBaseClass() {\n"
|
||||||
|
" ASSERT(a == 123);\n"
|
||||||
|
" ASSERT(b == 456);\n"
|
||||||
|
" ASSERT(c == 789);\n"
|
||||||
|
" ASSERT(456 == testNoOverride());\n"
|
||||||
|
" return c;\n"
|
||||||
|
"}\n"
|
||||||
|
"int BaseClass::testInsideBaseOverride() { return testOverride(); }\n"
|
||||||
|
"\n"
|
||||||
|
"public class MidClass extends BaseClass {\n"
|
||||||
|
" int b = 1011;\n"
|
||||||
|
" int c = 1213;\n"
|
||||||
|
" int d = 1415;\n"
|
||||||
|
"}\n"
|
||||||
|
"int MidClass::testOverride() { return 1011; }\n"
|
||||||
|
"int MidClass::testInsideMidClass() {\n"
|
||||||
|
" ASSERT(a == 123);\n"
|
||||||
|
" ASSERT(b == 1011);\n"
|
||||||
|
" ASSERT(c == 1213);\n"
|
||||||
|
" ASSERT(d == 1415);\n"
|
||||||
|
" ASSERT(456 == testNoOverride());\n"
|
||||||
|
" ASSERT(789 == testInsideBaseClass());\n"
|
||||||
|
" return c;\n"
|
||||||
|
"}\n"
|
||||||
|
"int MidClass::testSuper() {\n"
|
||||||
|
" ASSERT(super.a == 123);\n"
|
||||||
|
" ASSERT(super.b == 456);\n"
|
||||||
|
" ASSERT(super.c == 789);\n"
|
||||||
|
" ASSERT(123 == super.testOverride());\n"
|
||||||
|
" ASSERT(789 == super.testInsideBaseClass());\n"
|
||||||
|
" return super.testInsideBaseOverride();\n"
|
||||||
|
"}\n"
|
||||||
|
"int MidClass::testInsideMidOverride() { return testOverride(); }\n"
|
||||||
|
"\n"
|
||||||
|
"public class SubClass extends MidClass {\n"
|
||||||
|
" int c = 1617;\n"
|
||||||
|
" int d = 1819;\n"
|
||||||
|
" int e = 2021;\n"
|
||||||
|
"}\n"
|
||||||
|
"int SubClass::testOverride() { return 1617; }\n"
|
||||||
|
"int SubClass::testInsideSubClass() {\n"
|
||||||
|
" ASSERT(a == 123);\n"
|
||||||
|
" ASSERT(b == 1011);\n"
|
||||||
|
" ASSERT(c == 1617);\n"
|
||||||
|
" ASSERT(d == 1819);\n"
|
||||||
|
" ASSERT(e == 2021);\n"
|
||||||
|
" ASSERT(456 == testNoOverride());\n"
|
||||||
|
" ASSERT(789 == testInsideBaseClass());\n"
|
||||||
|
" ASSERT(1213 == testInsideMidClass());\n"
|
||||||
|
" return c;\n"
|
||||||
|
"}\n"
|
||||||
|
"int SubClass::testSuper() {\n"
|
||||||
|
" ASSERT(super.a == 123);\n"
|
||||||
|
" ASSERT(super.b == 1011);\n"
|
||||||
|
" ASSERT(super.c == 1213);\n"
|
||||||
|
" ASSERT(super.d == 1415);\n"
|
||||||
|
" ASSERT(1011 == super.testOverride());\n"
|
||||||
|
" ASSERT(789 == super.testInsideBaseClass());\n"
|
||||||
|
" ASSERT(1213 == super.testInsideMidClass());\n"
|
||||||
|
" return super.testSuper();\n"
|
||||||
|
"}\n"
|
||||||
|
"int SubClass::testInsideSubOverride() { return testOverride(); }\n"
|
||||||
|
"\n"
|
||||||
|
"extern void InheritanceMethodsOutOfClass()\n"
|
||||||
|
"{\n"
|
||||||
|
" BaseClass bc();\n"
|
||||||
|
" ASSERT(123 == bc.testOverride());\n"
|
||||||
|
" ASSERT(456 == bc.testNoOverride());\n"
|
||||||
|
" ASSERT(789 == bc.testInsideBaseClass());\n"
|
||||||
|
" ASSERT(123 == bc.testInsideBaseOverride());\n"
|
||||||
|
" MidClass mc();\n"
|
||||||
|
" ASSERT(1011 == mc.testSuper());\n"
|
||||||
|
" ASSERT(1011 == mc.testOverride());\n"
|
||||||
|
" ASSERT(456 == mc.testNoOverride());\n"
|
||||||
|
" ASSERT(789 == mc.testInsideBaseClass());\n"
|
||||||
|
" ASSERT(1213 == mc.testInsideMidClass());\n"
|
||||||
|
" ASSERT(1011 == mc.testInsideBaseOverride());\n"
|
||||||
|
" ASSERT(1011 == mc.testInsideMidOverride());\n"
|
||||||
|
" SubClass sc();\n"
|
||||||
|
" ASSERT(1617 == sc.testSuper());\n"
|
||||||
|
" ASSERT(1617 == sc.testOverride());\n"
|
||||||
|
" ASSERT(456 == sc.testNoOverride());\n"
|
||||||
|
" ASSERT(789 == sc.testInsideBaseClass());\n"
|
||||||
|
" ASSERT(1213 == sc.testInsideMidClass());\n"
|
||||||
|
" ASSERT(1617 == sc.testInsideSubClass());\n"
|
||||||
|
" ASSERT(1617 == sc.testInsideBaseOverride());\n"
|
||||||
|
" ASSERT(1617 == sc.testInsideMidOverride());\n"
|
||||||
|
" ASSERT(1617 == sc.testInsideSubOverride());\n"
|
||||||
|
// Test polymorphism
|
||||||
|
" bc = mc;\n"
|
||||||
|
" ASSERT(1011 == bc.testOverride());\n"
|
||||||
|
" ASSERT(789 == bc.testInsideBaseClass());\n"
|
||||||
|
" ASSERT(1011 == bc.testInsideBaseOverride());\n"
|
||||||
|
" bc = sc;\n"
|
||||||
|
" ASSERT(1617 == bc.testOverride());\n"
|
||||||
|
" ASSERT(789 == bc.testInsideBaseClass());\n"
|
||||||
|
" ASSERT(1617 == bc.testInsideBaseOverride());\n"
|
||||||
|
" mc = sc;\n"
|
||||||
|
" ASSERT(1617 == mc.testSuper());\n"
|
||||||
|
" ASSERT(1617 == mc.testOverride());\n"
|
||||||
|
" ASSERT(789 == mc.testInsideBaseClass());\n"
|
||||||
|
" ASSERT(1213 == mc.testInsideMidClass());\n"
|
||||||
|
" ASSERT(1617 == mc.testInsideBaseOverride());\n"
|
||||||
|
" ASSERT(1617 == mc.testInsideMidOverride());\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CBotUT, ClassInheritanceTestThisOutOfClass)
|
||||||
|
{
|
||||||
|
ExecuteTest(
|
||||||
|
"public class BaseClass {\n"
|
||||||
|
" int a = 123;\n"
|
||||||
|
" int b = 456;\n"
|
||||||
|
" int c = 789;\n"
|
||||||
|
"}\n"
|
||||||
|
"void BaseClass::testBaseMembersAndParams(int a, int b, int c) {\n"
|
||||||
|
" ASSERT(a != 123);\n"
|
||||||
|
" ASSERT(b != 456);\n"
|
||||||
|
" ASSERT(c != 789);\n"
|
||||||
|
" ASSERT(this.a == 123);\n"
|
||||||
|
" ASSERT(this.b == 456);\n"
|
||||||
|
" ASSERT(this.c == 789);\n"
|
||||||
|
"}\n"
|
||||||
|
"BaseClass BaseClass::testSuperReturnThis(){ return this; }\n"
|
||||||
|
"BaseClass BaseClass::testReturnThisFromBaseClass() { return this; }\n"
|
||||||
|
"\n"
|
||||||
|
"public class MidClass extends BaseClass {\n"
|
||||||
|
" int b = 1011;\n"
|
||||||
|
" int c = 1213;\n"
|
||||||
|
" int d = 1415;\n"
|
||||||
|
"}\n"
|
||||||
|
"void MidClass::testMidMembersAndParams(int a, int b, int c, int d) {\n"
|
||||||
|
" ASSERT(a != 123);\n"
|
||||||
|
" ASSERT(b != 1011);\n"
|
||||||
|
" ASSERT(c != 1213);\n"
|
||||||
|
" ASSERT(d != 1415);\n"
|
||||||
|
" ASSERT(this.a == 123);\n"
|
||||||
|
" ASSERT(this.b == 1011);\n"
|
||||||
|
" ASSERT(this.c == 1213);\n"
|
||||||
|
" ASSERT(this.d == 1415);\n"
|
||||||
|
"}\n"
|
||||||
|
"MidClass MidClass::testSuperReturnThis(){ return super.testSuperReturnThis(); }\n"
|
||||||
|
"MidClass MidClass::testReturnThisFromMidClass() { return this; }\n"
|
||||||
|
"\n"
|
||||||
|
"public class SubClass extends MidClass {\n"
|
||||||
|
" int c = 1617;\n"
|
||||||
|
" int d = 1819;\n"
|
||||||
|
" int e = 2021;\n"
|
||||||
|
"}\n"
|
||||||
|
"void SubClass::testSubMembersAndParams(int a, int b, int c, int d, int e) {\n"
|
||||||
|
" ASSERT(a != 123);\n"
|
||||||
|
" ASSERT(b != 1011);\n"
|
||||||
|
" ASSERT(c != 1617);\n"
|
||||||
|
" ASSERT(d != 1819);\n"
|
||||||
|
" ASSERT(e != 2021);\n"
|
||||||
|
" ASSERT(this.a == 123);\n"
|
||||||
|
" ASSERT(this.b == 1011);\n"
|
||||||
|
" ASSERT(this.c == 1617);\n"
|
||||||
|
" ASSERT(this.d == 1819);\n"
|
||||||
|
" ASSERT(this.e == 2021);\n"
|
||||||
|
"}\n"
|
||||||
|
"SubClass SubClass::testSuperReturnThis(){ return super.testSuperReturnThis(); }\n"
|
||||||
|
"SubClass SubClass::testReturnThisFromSubClass() { return this; }\n"
|
||||||
|
"\n"
|
||||||
|
"extern void ClassInheritanceTestThisOutOfClass()\n"
|
||||||
|
"{\n"
|
||||||
|
" BaseClass bc();\n"
|
||||||
|
" MidClass mc();\n"
|
||||||
|
" SubClass sc();\n"
|
||||||
|
" ASSERT(bc == bc.testSuperReturnThis());\n"
|
||||||
|
" ASSERT(bc == bc.testReturnThisFromBaseClass());\n"
|
||||||
|
" bc.testBaseMembersAndParams(-1, -2, -3);\n"
|
||||||
|
" ASSERT(mc == mc.testSuperReturnThis());\n"
|
||||||
|
" ASSERT(mc == mc.testReturnThisFromBaseClass());\n"
|
||||||
|
" ASSERT(mc == mc.testReturnThisFromMidClass());\n"
|
||||||
|
" mc.testBaseMembersAndParams(-1, -2, -3);\n"
|
||||||
|
" mc.testMidMembersAndParams(-1, -2, -3, -4);\n"
|
||||||
|
" ASSERT(sc == sc.testSuperReturnThis());\n"
|
||||||
|
" ASSERT(sc == sc.testReturnThisFromBaseClass());\n"
|
||||||
|
" ASSERT(sc == sc.testReturnThisFromMidClass());\n"
|
||||||
|
" ASSERT(sc == sc.testReturnThisFromSubClass());\n"
|
||||||
|
" sc.testBaseMembersAndParams(-1, -2, -3);\n"
|
||||||
|
" sc.testMidMembersAndParams(-1, -2, -3, -4);\n"
|
||||||
|
" sc.testSubMembersAndParams(-1, -2, -3, -4, -5);\n"
|
||||||
|
// Test polymorphism
|
||||||
|
" bc = mc;\n"
|
||||||
|
" ASSERT(mc == bc.testSuperReturnThis());\n"
|
||||||
|
" ASSERT(mc == bc.testReturnThisFromBaseClass());\n"
|
||||||
|
" bc.testBaseMembersAndParams(-1, -2, -3);\n"
|
||||||
|
" bc = sc;\n"
|
||||||
|
" ASSERT(sc == bc.testSuperReturnThis());\n"
|
||||||
|
" ASSERT(sc == bc.testReturnThisFromBaseClass());\n"
|
||||||
|
" bc.testBaseMembersAndParams(-1, -2, -3);\n"
|
||||||
|
" mc = sc;\n"
|
||||||
|
" ASSERT(sc == mc.testSuperReturnThis());\n"
|
||||||
|
" ASSERT(sc == mc.testReturnThisFromBaseClass());\n"
|
||||||
|
" ASSERT(sc == mc.testReturnThisFromMidClass());\n"
|
||||||
|
" mc.testBaseMembersAndParams(-1, -2, -3);\n"
|
||||||
|
" mc.testMidMembersAndParams(-1, -2, -3, -4);\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue