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

View File

@ -56,7 +56,6 @@ CBotClass::CBotClass(const std::string& name,
m_name = name;
m_pVar = nullptr;
m_pCalls = nullptr;
m_pMethod = nullptr;
m_rUpdate = nullptr;
m_IsDef = true;
m_bIntrinsic= bIntrinsic;
@ -72,7 +71,6 @@ CBotClass::~CBotClass()
delete m_pVar;
delete m_pCalls;
delete m_pMethod;
}
////////////////////////////////////////////////////////////////////////////////
@ -98,14 +96,11 @@ void CBotClass::Purge()
m_pVar = nullptr;
delete m_pCalls;
m_pCalls = nullptr;
delete m_pMethod;
m_pMethod = nullptr;
for (CBotFunction* f : m_pMethod) delete f;
m_pMethod.clear();
m_IsDef = false;
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;
CBotFunction* pp = m_pMethod;
while ( pp != nullptr )
for (CBotFunction* pp : m_pMethod)
{
if ( pToken->GetString() == pp->GetName() )
{
@ -464,7 +458,6 @@ bool CBotClass::CheckCall(CBotProgram* program, CBotDefParam* pParam, CBotToken*
if ( pp->CheckParam( pParam ) )
return true;
}
pp = pp->GetNext();
}
return false;
@ -506,7 +499,7 @@ CBotClass* CBotClass::Compile1(CBotToken* &p, CBotCStack* pStack)
}
}
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_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;
pClass->m_nbVar = (pParent == nullptr) ? 0 : pParent->m_nbVar;
@ -550,8 +543,6 @@ void CBotClass::DefineClasses(CBotClass* pClass, CBotCStack* pStack)
}
if (!pStack->IsOk()) return;
pClass = pClass->GetNext();
}
}
@ -627,28 +618,25 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
if ( !bSecond )
{
p = pBase;
CBotFunction* f =
CBotFunction::Compile1(p, pStack, this);
CBotFunction* f = CBotFunction::Compile1(p, pStack, this);
if ( f == nullptr ) return false;
if (m_pMethod == nullptr) m_pMethod = f;
else m_pMethod->AddNext(f);
m_pMethod.push_back(f);
}
else
{
// return a method precompiled in pass 1
CBotFunction* pf = m_pMethod;
CBotToken* ppp = p;
CBotCStack* pStk = pStack->TokenStack(nullptr, true);
CBotDefParam* params = CBotDefParam::Compile(p, pStk );
delete pStk;
p = ppp;
while ( pf != nullptr ) // search by name and parameters
{
if (pf->GetName() == pp && pf->CheckParam( params )) break;
pf = pf->GetNext();
}
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 );
});
assert(pfIter != m_pMethod.end());
CBotFunction* pf = *pfIter;
bool bConstructor = (pp == GetName());
CBotCStack* pile = pStack->TokenStack(nullptr, true);

View File

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

View File

@ -36,9 +36,8 @@ void CBotDebug::DumpCompiledProgram(CBotProgram* program)
std::stringstream ss;
ss << "digraph {" << std::endl;
CBotFunction* func = program->GetFunctions();
std::map<long, CBotFunction*> funcIdMap;
while (func != nullptr)
for (CBotFunction* func : program->GetFunctions())
{
funcIdMap[func->m_nFuncIdent] = func;
func = func->GetNext();
@ -111,9 +110,8 @@ void CBotDebug::DumpCompiledProgram(CBotProgram* program)
{
DumpInstr(program->m_entryPoint);
}
func = program->GetFunctions();
std::string prev = GetPointerAsString(program->m_entryPoint);
while (func != nullptr)
for (CBotFunction* func : program->GetFunctions())
{
if (func != program->m_entryPoint)
{
@ -122,8 +120,6 @@ void CBotDebug::DumpCompiledProgram(CBotProgram* program)
//ss << prev << " -> " << GetPointerAsString(func) << " [style=invis]" << std::endl;
prev = GetPointerAsString(func);
}
func = func->GetNext();
}
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;
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)
{
TypeOrError.SetType(CBotErrUndefCall); // no routine of the name
CBotFunction* pt;
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;
return pt;
@ -454,9 +453,7 @@ CBotFunction* CBotFunction::FindLocalOrPublic(CBotFunction* localFunctionList, l
std::map<CBotFunction*, int> funcMap;
if ( localFunctionList != nullptr )
{
for ( pt = localFunctionList ; pt != nullptr ; pt = pt->GetNext() )
for (CBotFunction* pt : localFunctionList)
{
if ( pt->m_token.GetString() == name )
{
@ -511,7 +508,6 @@ CBotFunction* CBotFunction::FindLocalOrPublic(CBotFunction* localFunctionList, l
funcMap.insert( std::pair<CBotFunction*, int>(pt, alpha) );
}
}
}
if ( bPublic )
{
@ -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)
{
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)
{
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)
{
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)
{
CBotTypResult type;

View File

@ -106,7 +106,7 @@ public:
* \return Type returned by the function or error code
* \see FindLocalOrPublic
*/
static CBotTypResult CompileCall(CBotFunction* localFunctionList,
static CBotTypResult CompileCall(const std::list<CBotFunction*>& localFunctionList,
const std::string &name, CBotVar** ppVars, long &nIdent);
/*!
@ -125,7 +125,7 @@ public:
* \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(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);
/*!
@ -140,7 +140,7 @@ public:
* \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);
/*!
@ -151,7 +151,7 @@ public:
* \param ppVars
* \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);
/*!
@ -167,7 +167,7 @@ public:
* \param pClass
* \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);
/*!
@ -181,7 +181,7 @@ public:
* \param pClass
* \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);
/*!

View File

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

View File

@ -23,6 +23,7 @@
#include "CBot/CBotEnums.h"
#include <vector>
#include <list>
namespace CBot
{
@ -124,12 +125,12 @@ public:
* 3. Second pass - compiling definitions of all functions and classes
*
* \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())
* \return true if compilation is successful, false if an compilation error occurs
* \see GetError() to retrieve the error
*/
bool Compile(const std::string& program, std::vector<std::string>& functions, void* pUser = nullptr);
bool Compile(const std::string& program, std::vector<std::string>& externFunctions, void* pUser = nullptr);
/**
* \brief Returns the last error
@ -328,9 +329,9 @@ public:
*
* 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
@ -341,11 +342,11 @@ private:
//! All external calls
static CBotExternalCallList* m_externalCalls;
//! All user-defined functions
CBotFunction* m_functions = nullptr;
std::list<CBotFunction*> m_functions{};
//! The entry point function
CBotFunction* m_entryPoint = nullptr;
//! Classes defined in this program
CBotClass* m_classes = nullptr;
std::list<CBotClass*> m_classes{};
//! Execution stack
CBotStack* m_stack = nullptr;
//! "this" variable

View File

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