Refactor CBotClass and CBotFunction list to std::list

dev-buzzingcars
krzys-h 2016-11-11 19:35:43 +01:00
parent 266b34d578
commit 191151eb7b
9 changed files with 127 additions and 159 deletions

View File

@ -369,8 +369,7 @@ bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam)
if ( m_prog->GetExternalCalls()->CheckCall(name) ) return true; if ( m_prog->GetExternalCalls()->CheckCall(name) ) return true;
CBotFunction* pp = m_prog->GetFunctions(); for (CBotFunction* pp : m_prog->GetFunctions())
while ( pp != nullptr )
{ {
if ( pToken->GetString() == pp->GetName() ) if ( pToken->GetString() == pp->GetName() )
{ {
@ -378,7 +377,6 @@ bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam)
if ( pp->CheckParam( pParam ) ) if ( pp->CheckParam( pParam ) )
return true; return true;
} }
pp = pp->GetNext();
} }
for (CBotFunction* pp : CBotFunction::m_publicFunctions) for (CBotFunction* pp : CBotFunction::m_publicFunctions)

View File

@ -56,7 +56,6 @@ CBotClass::CBotClass(const std::string& name,
m_name = name; m_name = name;
m_pVar = nullptr; m_pVar = nullptr;
m_pCalls = nullptr; m_pCalls = nullptr;
m_pMethod = nullptr;
m_rUpdate = nullptr; m_rUpdate = nullptr;
m_IsDef = true; m_IsDef = true;
m_bIntrinsic= bIntrinsic; m_bIntrinsic= bIntrinsic;
@ -72,7 +71,6 @@ CBotClass::~CBotClass()
delete m_pVar; delete m_pVar;
delete m_pCalls; delete m_pCalls;
delete m_pMethod;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -98,14 +96,11 @@ void CBotClass::Purge()
m_pVar = nullptr; m_pVar = nullptr;
delete m_pCalls; delete m_pCalls;
m_pCalls = nullptr; m_pCalls = nullptr;
delete m_pMethod; for (CBotFunction* f : m_pMethod) delete f;
m_pMethod = nullptr; m_pMethod.clear();
m_IsDef = false; m_IsDef = false;
m_nbVar = m_parent == nullptr ? 0 : m_parent->m_nbVar; m_nbVar = m_parent == nullptr ? 0 : m_parent->m_nbVar;
if (m_next != nullptr) m_next->Purge();
m_next = nullptr; // no longer belongs to this chain
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -455,8 +450,7 @@ bool CBotClass::CheckCall(CBotProgram* program, CBotDefParam* pParam, CBotToken*
if ( program->GetExternalCalls()->CheckCall(name) ) return true; if ( program->GetExternalCalls()->CheckCall(name) ) return true;
CBotFunction* pp = m_pMethod; for (CBotFunction* pp : m_pMethod)
while ( pp != nullptr )
{ {
if ( pToken->GetString() == pp->GetName() ) if ( pToken->GetString() == pp->GetName() )
{ {
@ -464,7 +458,6 @@ bool CBotClass::CheckCall(CBotProgram* program, CBotDefParam* pParam, CBotToken*
if ( pp->CheckParam( pParam ) ) if ( pp->CheckParam( pParam ) )
return true; return true;
} }
pp = pp->GetNext();
} }
return false; return false;
@ -506,7 +499,7 @@ CBotClass* CBotClass::Compile1(CBotToken* &p, CBotCStack* pStack)
} }
} }
CBotClass* classe = (pOld == nullptr) ? new CBotClass(name, pPapa) : pOld; CBotClass* classe = (pOld == nullptr) ? new CBotClass(name, pPapa) : pOld;
classe->Purge(); // empty the old definitions // TODO: Doesn't this remove all classes of the current program? classe->Purge(); // empty the old definitions
classe->m_IsDef = false; // current definition classe->m_IsDef = false; // current definition
classe->m_pOpenblk = p; classe->m_pOpenblk = p;
@ -536,9 +529,9 @@ CBotClass* CBotClass::Compile1(CBotToken* &p, CBotCStack* pStack)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void CBotClass::DefineClasses(CBotClass* pClass, CBotCStack* pStack) void CBotClass::DefineClasses(std::list<CBotClass*> pClassList, CBotCStack* pStack)
{ {
while (pClass != nullptr) for (CBotClass* pClass : pClassList)
{ {
CBotClass* pParent = pClass->m_parent; CBotClass* pParent = pClass->m_parent;
pClass->m_nbVar = (pParent == nullptr) ? 0 : pParent->m_nbVar; pClass->m_nbVar = (pParent == nullptr) ? 0 : pParent->m_nbVar;
@ -550,8 +543,6 @@ void CBotClass::DefineClasses(CBotClass* pClass, CBotCStack* pStack)
} }
if (!pStack->IsOk()) return; if (!pStack->IsOk()) return;
pClass = pClass->GetNext();
} }
} }
@ -627,28 +618,25 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
if ( !bSecond ) if ( !bSecond )
{ {
p = pBase; p = pBase;
CBotFunction* f = CBotFunction* f = CBotFunction::Compile1(p, pStack, this);
CBotFunction::Compile1(p, pStack, this);
if ( f == nullptr ) return false; if ( f == nullptr ) return false;
if (m_pMethod == nullptr) m_pMethod = f; m_pMethod.push_back(f);
else m_pMethod->AddNext(f);
} }
else else
{ {
// return a method precompiled in pass 1 // return a method precompiled in pass 1
CBotFunction* pf = m_pMethod;
CBotToken* ppp = p; CBotToken* ppp = p;
CBotCStack* pStk = pStack->TokenStack(nullptr, true); CBotCStack* pStk = pStack->TokenStack(nullptr, true);
CBotDefParam* params = CBotDefParam::Compile(p, pStk ); CBotDefParam* params = CBotDefParam::Compile(p, pStk );
delete pStk; delete pStk;
p = ppp; p = ppp;
while ( pf != nullptr ) // search by name and parameters std::list<CBotFunction*>::iterator pfIter = std::find_if(m_pMethod.begin(), m_pMethod.end(), [&pp, &params](CBotFunction* x) {
{ return x->GetName() == pp && x->CheckParam( params );
if (pf->GetName() == pp && pf->CheckParam( params )) break; });
pf = pf->GetNext(); assert(pfIter != m_pMethod.end());
} CBotFunction* pf = *pfIter;
bool bConstructor = (pp == GetName()); bool bConstructor = (pp == GetName());
CBotCStack* pile = pStack->TokenStack(nullptr, true); CBotCStack* pile = pStack->TokenStack(nullptr, true);

View File

@ -26,6 +26,7 @@
#include <string> #include <string>
#include <deque> #include <deque>
#include <set> #include <set>
#include <list>
namespace CBot namespace CBot
{ {
@ -102,7 +103,7 @@ class CBotCStack;
* float y = var->GetValFloat(); * float y = var->GetValFloat();
* \endcode * \endcode
*/ */
class CBotClass : public CBotLinkedList<CBotClass> class CBotClass
{ {
public: public:
/*! /*!
@ -294,10 +295,10 @@ public:
/*! /*!
* \brief DefineClasses Calls CompileDefItem for each class in a list * \brief DefineClasses Calls CompileDefItem for each class in a list
* of classes, defining fields and pre-compiling methods. * of classes, defining fields and pre-compiling methods.
* \param pClass List of classes * \param pClassList List of classes
* \param pStack * \param pStack
*/ */
static void DefineClasses(CBotClass* pClass, CBotCStack* pStack); static void DefineClasses(std::list<CBotClass*> pClassList, CBotCStack* pStack);
/*! /*!
* \brief CompileDefItem * \brief CompileDefItem
@ -389,8 +390,8 @@ private:
CBotVar* m_pVar; CBotVar* m_pVar;
//! Linked list of all class external calls //! Linked list of all class external calls
CBotCallMethode* m_pCalls; CBotCallMethode* m_pCalls;
//! Linked list of all class methods //! List of all class methods
CBotFunction* m_pMethod; std::list<CBotFunction*> m_pMethod{};
void (*m_rUpdate)(CBotVar* thisVar, void* user); void (*m_rUpdate)(CBotVar* thisVar, void* user);
CBotToken* m_pOpenblk; CBotToken* m_pOpenblk;

View File

@ -36,9 +36,8 @@ void CBotDebug::DumpCompiledProgram(CBotProgram* program)
std::stringstream ss; std::stringstream ss;
ss << "digraph {" << std::endl; ss << "digraph {" << std::endl;
CBotFunction* func = program->GetFunctions();
std::map<long, CBotFunction*> funcIdMap; std::map<long, CBotFunction*> funcIdMap;
while (func != nullptr) for (CBotFunction* func : program->GetFunctions())
{ {
funcIdMap[func->m_nFuncIdent] = func; funcIdMap[func->m_nFuncIdent] = func;
func = func->GetNext(); func = func->GetNext();
@ -111,9 +110,8 @@ void CBotDebug::DumpCompiledProgram(CBotProgram* program)
{ {
DumpInstr(program->m_entryPoint); DumpInstr(program->m_entryPoint);
} }
func = program->GetFunctions();
std::string prev = GetPointerAsString(program->m_entryPoint); std::string prev = GetPointerAsString(program->m_entryPoint);
while (func != nullptr) for (CBotFunction* func : program->GetFunctions())
{ {
if (func != program->m_entryPoint) if (func != program->m_entryPoint)
{ {
@ -122,8 +120,6 @@ void CBotDebug::DumpCompiledProgram(CBotProgram* program)
//ss << prev << " -> " << GetPointerAsString(func) << " [style=invis]" << std::endl; //ss << prev << " -> " << GetPointerAsString(func) << " [style=invis]" << std::endl;
prev = GetPointerAsString(func); prev = GetPointerAsString(func);
} }
func = func->GetNext();
} }
ss << "}" << std::endl; ss << "}" << std::endl;

View File

@ -410,7 +410,7 @@ void CBotFunction::RestoreState(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInst
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
CBotTypResult CBotFunction::CompileCall(CBotFunction* localFunctionList, const std::string &name, CBotVar** ppVars, long &nIdent) CBotTypResult CBotFunction::CompileCall(const std::list<CBotFunction*>& localFunctionList, const std::string &name, CBotVar** ppVars, long &nIdent)
{ {
CBotTypResult type; CBotTypResult type;
if (!FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type)) if (!FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type))
@ -422,17 +422,16 @@ CBotTypResult CBotFunction::CompileCall(CBotFunction* localFunctionList, const s
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
CBotFunction* CBotFunction::FindLocalOrPublic(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, bool bPublic)
{ {
TypeOrError.SetType(CBotErrUndefCall); // no routine of the name TypeOrError.SetType(CBotErrUndefCall); // no routine of the name
CBotFunction* pt;
if ( nIdent ) if ( nIdent )
{ {
if ( localFunctionList != nullptr ) for ( pt = localFunctionList ; pt != nullptr ; pt = pt->GetNext() ) for (CBotFunction* pt : localFunctionList)
{ {
if ( pt->m_nFuncIdent == nIdent ) if (pt->m_nFuncIdent == nIdent)
{ {
TypeOrError = pt->m_retTyp; TypeOrError = pt->m_retTyp;
return pt; return pt;
@ -454,62 +453,59 @@ CBotFunction* CBotFunction::FindLocalOrPublic(CBotFunction* localFunctionList, l
std::map<CBotFunction*, int> funcMap; std::map<CBotFunction*, int> funcMap;
if ( localFunctionList != nullptr ) for (CBotFunction* pt : localFunctionList)
{ {
for ( pt = localFunctionList ; pt != nullptr ; pt = pt->GetNext() ) if ( pt->m_token.GetString() == name )
{ {
if ( pt->m_token.GetString() == name ) int 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)
{ {
int i = 0; CBotTypResult paramType = pv->GetTypResult();
int alpha = 0; // signature of parameters CBotTypResult argType = pw->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
// parameters are compatible?
CBotDefParam* pv = pt->m_param; // expected list of parameters
CBotVar* pw = ppVars[i++]; // provided list parameter
while ( pv != nullptr && pw != nullptr)
{
CBotTypResult paramType = pv->GetTypResult();
CBotTypResult argType = pw->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
if (!TypesCompatibles(paramType, argType)) if (!TypesCompatibles(paramType, argType))
{ {
if ( funcMap.empty() ) TypeOrError.SetType(CBotErrBadParam); if ( funcMap.empty() ) TypeOrError.SetType(CBotErrBadParam);
break; break;
} }
if (paramType.Eq(CBotTypPointer) && !argType.Eq(CBotTypNullPointer)) if (paramType.Eq(CBotTypPointer) && !argType.Eq(CBotTypNullPointer))
{
CBotClass* c1 = paramType.GetClass();
CBotClass* c2 = argType.GetClass();
while (c2 != c1 && c2 != nullptr) // implicit cast
{
alpha += 10;
c2 = c2->GetParent();
}
}
else
{
int d = pv->GetType() - pw->GetType(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
alpha += d>0 ? d : -10*d; // quality loss, 10 times more expensive!
}
pv = pv->GetNext();
pw = ppVars[i++];
}
if ( pw != nullptr )
{ {
if ( !funcMap.empty() ) continue; CBotClass* c1 = paramType.GetClass();
if ( TypeOrError.Eq(CBotErrLowParam) ) TypeOrError.SetType(CBotErrNbParam); CBotClass* c2 = argType.GetClass();
if ( TypeOrError.Eq(CBotErrUndefCall)) TypeOrError.SetType(CBotErrOverParam); while (c2 != c1 && c2 != nullptr) // implicit cast
continue; // too many parameters {
alpha += 10;
c2 = c2->GetParent();
}
} }
if ( pv != nullptr ) else
{ {
if ( !funcMap.empty() ) continue; int d = pv->GetType() - pw->GetType(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
if ( TypeOrError.Eq(CBotErrOverParam) ) TypeOrError.SetType(CBotErrNbParam); alpha += d>0 ? d : -10*d; // quality loss, 10 times more expensive!
if ( TypeOrError.Eq(CBotErrUndefCall) ) TypeOrError.SetType(CBotErrLowParam);
continue; // not enough parameters
} }
funcMap.insert( std::pair<CBotFunction*, int>(pt, alpha) ); pv = pv->GetNext();
pw = ppVars[i++];
} }
if ( pw != nullptr )
{
if ( !funcMap.empty() ) continue;
if ( TypeOrError.Eq(CBotErrLowParam) ) TypeOrError.SetType(CBotErrNbParam);
if ( TypeOrError.Eq(CBotErrUndefCall)) TypeOrError.SetType(CBotErrOverParam);
continue; // too many parameters
}
if ( pv != nullptr )
{
if ( !funcMap.empty() ) continue;
if ( TypeOrError.Eq(CBotErrOverParam) ) TypeOrError.SetType(CBotErrNbParam);
if ( TypeOrError.Eq(CBotErrUndefCall) ) TypeOrError.SetType(CBotErrLowParam);
continue; // not enough parameters
}
funcMap.insert( std::pair<CBotFunction*, int>(pt, alpha) );
} }
} }
@ -600,7 +596,7 @@ CBotFunction* CBotFunction::FindLocalOrPublic(CBotFunction* localFunctionList, l
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int CBotFunction::DoCall(CBotProgram* program, CBotFunction* localFunctionList, long &nIdent, const std::string &name, int CBotFunction::DoCall(CBotProgram* program, const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name,
CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken) CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken)
{ {
CBotTypResult type; CBotTypResult type;
@ -674,7 +670,7 @@ int CBotFunction::DoCall(CBotProgram* program, CBotFunction* localFunctionList,
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void CBotFunction::RestoreCall(CBotFunction* localFunctionList, void CBotFunction::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)
{ {
CBotTypResult type; CBotTypResult type;
@ -732,7 +728,7 @@ void CBotFunction::RestoreCall(CBotFunction* localFunctionList,
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int CBotFunction::DoCall(CBotFunction* localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis, int CBotFunction::DoCall(const std::list<CBotFunction*>& localFunctionList, 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;
@ -814,7 +810,7 @@ int CBotFunction::DoCall(CBotFunction* localFunctionList, long &nIdent, const st
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool CBotFunction::RestoreCall(CBotFunction* localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis, bool CBotFunction::RestoreCall(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis,
CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass) CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass)
{ {
CBotTypResult type; CBotTypResult type;

View File

@ -106,7 +106,7 @@ public:
* \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(CBotFunction* localFunctionList, static CBotTypResult CompileCall(const std::list<CBotFunction*>& localFunctionList,
const std::string &name, CBotVar** ppVars, long &nIdent); const std::string &name, CBotVar** ppVars, long &nIdent);
/*! /*!
@ -125,7 +125,7 @@ public:
* \param bPublic Whether to look in public functions or not * \param bPublic Whether to look in public functions or not
* \return Pointer to found CBotFunction instance, or nullptr in case of no match or ambiguity (see TypeOrError for error code) * \return Pointer to found CBotFunction instance, or nullptr in case of no match or ambiguity (see TypeOrError for error code)
*/ */
static CBotFunction* FindLocalOrPublic(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, bool bPublic = true);
/*! /*!
@ -140,7 +140,7 @@ public:
* \return * \return
*/ */
static int DoCall(CBotProgram* program, CBotFunction* localFunctionList, long &nIdent, const std::string &name, static int DoCall(CBotProgram* program, const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name,
CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken); CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken);
/*! /*!
@ -151,7 +151,7 @@ public:
* \param ppVars * \param ppVars
* \param pStack * \param pStack
*/ */
static void RestoreCall(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);
/*! /*!
@ -167,7 +167,7 @@ public:
* \param pClass * \param pClass
* \return * \return
*/ */
static int DoCall(CBotFunction* localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis, static int DoCall(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis,
CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken, CBotClass* pClass); CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken, CBotClass* pClass);
/*! /*!
@ -181,7 +181,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(CBotFunction* localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis, static bool RestoreCall(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis,
CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass); CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass);
/*! /*!

View File

@ -30,6 +30,8 @@
#include "CBot/stdlib/stdlib.h" #include "CBot/stdlib/stdlib.h"
#include <algorithm>
namespace CBot namespace CBot
{ {
@ -47,27 +49,30 @@ CBotProgram::CBotProgram(CBotVar* thisVar)
CBotProgram::~CBotProgram() CBotProgram::~CBotProgram()
{ {
// delete m_classes; // delete m_classes;
if (m_classes != nullptr) m_classes->Purge(); for (CBotClass* c : m_classes)
m_classes = nullptr; c->Purge();
m_classes.clear();
CBotClass::FreeLock(this); CBotClass::FreeLock(this);
delete m_functions; for (CBotFunction* f : m_functions) delete f;
if (m_stack != nullptr) m_stack->Delete(); m_functions.clear();
} }
bool CBotProgram::Compile(const std::string& program, std::vector<std::string>& functions, void* pUser) bool CBotProgram::Compile(const std::string& program, std::vector<std::string>& externFunctions, void* pUser)
{ {
// Cleanup the previously compiled program // Cleanup the previously compiled program
Stop(); Stop();
// delete m_classes; for (CBotClass* c : m_classes)
if (m_classes != nullptr) m_classes->Purge(); // purge the old definitions of classes c->Purge(); // purge the old definitions of classes
// but without destroying the object // but without destroying the object
m_classes = nullptr;
delete m_functions; m_functions = nullptr;
functions.clear(); m_classes.clear();
for (CBotFunction* f : m_functions) delete f;
m_functions.clear();
externFunctions.clear();
m_error = CBotNoErr; m_error = CBotNoErr;
// Step 1. Process the code into tokens // Step 1. Process the code into tokens
@ -88,15 +93,11 @@ bool CBotProgram::Compile(const std::string& program, std::vector<std::string>&
if ( p->GetType() == ID_CLASS || if ( p->GetType() == ID_CLASS ||
( p->GetType() == ID_PUBLIC && p->GetNext()->GetType() == ID_CLASS )) ( p->GetType() == ID_PUBLIC && p->GetNext()->GetType() == ID_CLASS ))
{ {
CBotClass* nxt = CBotClass::Compile1(p, pStack.get()); m_classes.push_back(CBotClass::Compile1(p, pStack.get()));
if (m_classes == nullptr ) m_classes = nxt;
else m_classes->AddNext(nxt);
} }
else else
{ {
CBotFunction* next = CBotFunction::Compile1(p, pStack.get(), nullptr); m_functions.push_back(CBotFunction::Compile1(p, pStack.get(), nullptr));
if (m_functions == nullptr ) m_functions = next;
else m_functions->AddNext(next);
} }
} }
@ -106,17 +107,14 @@ bool CBotProgram::Compile(const std::string& program, std::vector<std::string>&
if ( !pStack->IsOk() ) if ( !pStack->IsOk() )
{ {
m_error = pStack->GetError(m_errorStart, m_errorEnd); m_error = pStack->GetError(m_errorStart, m_errorEnd);
delete m_functions; for (CBotFunction* f : m_functions) delete f;
m_functions = nullptr; m_functions.clear();
return false; return false;
} }
// Step 3. Real compilation // Step 3. Real compilation
// CBotFunction* temp = nullptr; std::list<CBotFunction*>::iterator next = m_functions.begin();
CBotFunction* next = m_functions; // rewind the list
p = tokens.get()->GetNext(); // returns to the beginning p = tokens.get()->GetNext(); // returns to the beginning
while ( pStack->IsOk() && p != nullptr && p->GetType() != 0 ) while ( pStack->IsOk() && p != nullptr && p->GetType() != 0 )
{ {
if ( IsOfType(p, ID_SEP) ) continue; // semicolons lurking if ( IsOfType(p, ID_SEP) ) continue; // semicolons lurking
@ -128,43 +126,37 @@ bool CBotProgram::Compile(const std::string& program, std::vector<std::string>&
} }
else else
{ {
CBotFunction::Compile(p, pStack.get(), next); CBotFunction::Compile(p, pStack.get(), *next);
if (next->IsExtern()) functions.push_back(next->GetName()/* + next->GetParams()*/); if ((*next)->IsExtern()) externFunctions.push_back((*next)->GetName()/* + next->GetParams()*/);
if (next->IsPublic()) CBotFunction::AddPublic(next); if ((*next)->IsPublic()) CBotFunction::AddPublic(*next);
next->m_pProg = this; // keeps pointers to the module (*next)->m_pProg = this; // keeps pointers to the module
next = next->GetNext(); ++next;
} }
} }
// delete m_Prog; // the list of first pass
// m_Prog = temp; // list of the second pass
if ( !pStack->IsOk() ) if ( !pStack->IsOk() )
{ {
m_error = pStack->GetError(m_errorStart, m_errorEnd); m_error = pStack->GetError(m_errorStart, m_errorEnd);
delete m_functions; for (CBotFunction* f : m_functions) delete f;
m_functions = nullptr; m_functions.clear();
} }
return (m_functions != nullptr); return !m_functions.empty();
} }
bool CBotProgram::Start(const std::string& name) bool CBotProgram::Start(const std::string& name)
{ {
Stop(); Stop();
m_entryPoint = m_functions; auto it = std::find_if(m_functions.begin(), m_functions.end(), [&name](CBotFunction* x) {
while (m_entryPoint != nullptr) return x->GetName() == name;
{ });
if (m_entryPoint->GetName() == name ) break; if (it == m_functions.end())
m_entryPoint = m_entryPoint->GetNext();
}
if (m_entryPoint == nullptr)
{ {
m_error = CBotErrNoRun; m_error = CBotErrNoRun;
return false; return false;
} }
m_entryPoint = *it;
m_stack = CBotStack::AllocateStack(); m_stack = CBotStack::AllocateStack();
m_stack->SetProgram(this); m_stack->SetProgram(this);
@ -174,16 +166,12 @@ bool CBotProgram::Start(const std::string& name)
bool CBotProgram::GetPosition(const std::string& name, int& start, int& stop, CBotGet modestart, CBotGet modestop) bool CBotProgram::GetPosition(const std::string& name, int& start, int& stop, CBotGet modestart, CBotGet modestop)
{ {
CBotFunction* p = m_functions; auto it = std::find_if(m_functions.begin(), m_functions.end(), [&name](CBotFunction* x) {
while (p != nullptr) return x->GetName() == name;
{ });
if ( p->GetName() == name ) break; if (it == m_functions.end()) return false;
p = p->GetNext();
}
if ( p == nullptr ) return false; (*it)->GetPosition(start, stop, modestart, modestop);
p->GetPosition(start, stop, modestart, modestop);
return true; return true;
} }
@ -288,7 +276,7 @@ bool CBotProgram::GetError(CBotError& code, int& start, int& end, CBotProgram*&
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
CBotFunction* CBotProgram::GetFunctions() const std::list<CBotFunction*>& CBotProgram::GetFunctions()
{ {
return m_functions; return m_functions;
} }

View File

@ -23,6 +23,7 @@
#include "CBot/CBotEnums.h" #include "CBot/CBotEnums.h"
#include <vector> #include <vector>
#include <list>
namespace CBot namespace CBot
{ {
@ -124,12 +125,12 @@ public:
* 3. Second pass - compiling definitions of all functions and classes * 3. Second pass - compiling definitions of all functions and classes
* *
* \param program Code to compile * \param program Code to compile
* \param[out] functions Returns the names of functions declared as extern * \param[out] externFunctions Returns the names of functions declared as extern
* \param pUser Optional pointer to be passed to compile function (see AddFunction()) * \param pUser Optional pointer to be passed to compile function (see AddFunction())
* \return true if compilation is successful, false if an compilation error occurs * \return true if compilation is successful, false if an compilation error occurs
* \see GetError() to retrieve the error * \see GetError() to retrieve the error
*/ */
bool Compile(const std::string& program, std::vector<std::string>& functions, void* pUser = nullptr); bool Compile(const std::string& program, std::vector<std::string>& externFunctions, void* pUser = nullptr);
/** /**
* \brief Returns the last error * \brief Returns the last error
@ -328,9 +329,9 @@ public:
* *
* This list includes all the functions (not only extern) * This list includes all the functions (not only extern)
* *
* \return Linked list of CBotFunction instances * \return List of CBotFunction instances
*/ */
CBotFunction* GetFunctions(); const std::list<CBotFunction*>& GetFunctions();
/** /**
* \brief Returns static list of all registered external calls * \brief Returns static list of all registered external calls
@ -341,11 +342,11 @@ private:
//! All external calls //! All external calls
static CBotExternalCallList* m_externalCalls; static CBotExternalCallList* m_externalCalls;
//! All user-defined functions //! All user-defined functions
CBotFunction* m_functions = nullptr; std::list<CBotFunction*> m_functions{};
//! The entry point function //! The entry point function
CBotFunction* m_entryPoint = nullptr; CBotFunction* m_entryPoint = nullptr;
//! Classes defined in this program //! Classes defined in this program
CBotClass* m_classes = nullptr; std::list<CBotClass*> m_classes{};
//! Execution stack //! Execution stack
CBotStack* m_stack = nullptr; CBotStack* m_stack = nullptr;
//! "this" variable //! "this" variable

View File

@ -1012,7 +1012,7 @@ TEST_F(CBotUT, ClassInheritanceAssignment)
"public class BaseClass {}\n" "public class BaseClass {}\n"
"public class MidClass extends BaseClass {}\n" "public class MidClass extends BaseClass {}\n"
"public class SubClass extends MidClass {}\n" "public class SubClass extends MidClass {}\n"
"extern void ClassInheritanceVars()\n" "extern void ClassInheritanceAssignment()\n"
"{\n" "{\n"
" BaseClass bc = new MidClass();\n" " BaseClass bc = new MidClass();\n"
" MidClass mc = bc;\n" " MidClass mc = bc;\n"