[colobot] 194/377: CBotCall refactoring
Didier Raboud
odyx at moszumanska.debian.org
Wed Mar 30 13:34:15 UTC 2016
This is an automated email from the git hooks/post-receive script.
odyx pushed a commit to branch debian/master
in repository colobot.
commit 3170395576a582c790a97ce8d997bcdf11230aae
Author: krzys-h <krzys_h at interia.pl>
Date: Thu Dec 24 00:41:33 2015 +0100
CBotCall refactoring
---
src/CBot/CBotCall.cpp | 261 ++++++++++++-----------------------------------
src/CBot/CBotCall.h | 138 +++++++++++--------------
src/CBot/CBotEnums.h | 2 +-
src/CBot/CBotProgram.cpp | 8 +-
4 files changed, 130 insertions(+), 279 deletions(-)
diff --git a/src/CBot/CBotCall.cpp b/src/CBot/CBotCall.cpp
index 2d1ffe7..a141d55 100644
--- a/src/CBot/CBotCall.cpp
+++ b/src/CBot/CBotCall.cpp
@@ -17,7 +17,6 @@
* along with this program. If not, see http://gnu.org/licenses
*/
-// Modules inlcude
#include "CBot/CBotCall.h"
#include "CBot/CBotToken.h"
@@ -28,279 +27,153 @@
#include "CBot/CBotVar/CBotVar.h"
-// Local include
+std::map<std::string, std::unique_ptr<CBotCall>> CBotCall::m_list = std::map<std::string, std::unique_ptr<CBotCall>>();
+void* CBotCall::m_user = nullptr;
-// Global include
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-
-CBotCall* CBotCall::m_ListCalls = nullptr;
-void* CBotCall::m_pUser = nullptr;
-
-////////////////////////////////////////////////////////////////////////////////
-CBotCall::CBotCall(const std::string& name,
- bool rExec(CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
- CBotTypResult rCompile(CBotVar*& pVar, void* pUser))
+CBotCall::CBotCall(const std::string& name, RuntimeFunc rExec, CompileFunc rCompile)
{
- m_name = name;
- m_rExec = rExec;
- m_rComp = rCompile;
- m_nFuncIdent = CBotVar::NextUniqNum();
+ m_name = name;
+ m_rExec = rExec;
+ m_rComp = rCompile;
+ m_ident = CBotVar::NextUniqNum();
}
-////////////////////////////////////////////////////////////////////////////////
CBotCall::~CBotCall()
{
}
-////////////////////////////////////////////////////////////////////////////////
-void CBotCall::Free()
+void CBotCall::Clear()
{
- delete CBotCall::m_ListCalls;
- m_ListCalls = nullptr;
+ m_list.clear();
}
-////////////////////////////////////////////////////////////////////////////////
-bool CBotCall::AddFunction(const std::string& name,
- bool rExec(CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
- CBotTypResult rCompile(CBotVar*& pVar, void* pUser))
+bool CBotCall::AddFunction(const std::string& name, RuntimeFunc rExec, CompileFunc rCompile)
{
- CBotCall* p = m_ListCalls;
- CBotCall* pp = nullptr;
-
- if ( p != nullptr ) while ( p->m_next != nullptr )
- {
- if ( p->GetName() == name )
- {
- // frees redefined function
- if ( pp ) pp->m_next = p->m_next;
- else m_ListCalls = p->m_next;
- pp = p;
- p = p->m_next;
- pp->m_next = nullptr; // not to destroy the following list
- delete pp;
- continue;
- }
- pp = p; // previous pointer
- p = p->m_next;
- }
-
- pp = new CBotCall(name, rExec, rCompile);
-
- if (p) p->m_next = pp;
- else m_ListCalls = pp;
-
+ m_list[name] = std::unique_ptr<CBotCall>(new CBotCall(name, rExec, rCompile));
return true;
}
-////////////////////////////////////////////////////////////////////////////////
CBotTypResult CBotCall::CompileCall(CBotToken* &p, CBotVar** ppVar, CBotCStack* pStack, long& nIdent)
{
nIdent = 0;
- CBotCall* pt = m_ListCalls;
- std::string name = p->GetString();
+ if (m_list.count(p->GetString()) == 0)
+ return -1;
- while ( pt != nullptr )
- {
- if ( pt->m_name == name )
- {
- CBotVar* pVar = MakeListVars(ppVar);
- CBotVar* pVar2 = pVar;
- CBotTypResult r = pt->m_rComp(pVar2, m_pUser);
- int ret = r.GetType();
+ CBotCall* pt = m_list[p->GetString()].get();
+ nIdent = pt->m_ident;
- // if a class is returned, it is actually a pointer
- if ( ret == CBotTypClass ) r.SetType( ret = CBotTypPointer );
+ std::unique_ptr<CBotVar> args = std::unique_ptr<CBotVar>(MakeListVars(ppVar));
+ CBotVar* var = args.get(); // TODO: This shouldn't be a reference
+ CBotTypResult r = pt->m_rComp(var, m_user);
- if ( ret > 20 )
- {
- if (pVar2) pStack->SetError(static_cast<CBotError>(ret), p /*pVar2->GetToken()*/ );
- }
- delete pVar;
- nIdent = pt->m_nFuncIdent;
- return r;
- }
- pt = pt->m_next;
+ // if a class is returned, it is actually a pointer
+ if (r.GetType() == CBotTypClass) r.SetType(CBotTypPointer);
+
+ if (r.GetType() > 20) // error?
+ {
+ pStack->SetError(static_cast<CBotError>(r.GetType()), p);
}
- return -1;
-}
-////////////////////////////////////////////////////////////////////////////////
-void CBotCall::SetPUser(void* pUser)
-{
- m_pUser = pUser;
+ return r;
}
-////////////////////////////////////////////////////////////////////////////////
-bool CBotCall::CheckCall(const std::string& name)
+void CBotCall::SetUserPtr(void* pUser)
{
- CBotCall* p = m_ListCalls;
-
- while ( p != nullptr )
- {
- if ( name == p->GetName() ) return true;
- p = p->m_next;
- }
- return false;
+ m_user = pUser;
}
-////////////////////////////////////////////////////////////////////////////////
-std::string CBotCall::GetName()
+bool CBotCall::CheckCall(const std::string& name)
{
- return m_name;
+ return m_list.count(name) > 0;
}
-////////////////////////////////////////////////////////////////////////////////
int CBotCall::DoCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBotStack* pStack, CBotTypResult& rettype)
{
- CBotCall* pt = m_ListCalls;
-
- if ( nIdent ) while ( pt != nullptr )
- {
- if ( pt->m_nFuncIdent == nIdent )
- {
- goto fund;
- }
- pt = pt->m_next;
- }
-
- pt = m_ListCalls;
+ CBotCall* pt = nullptr;
- if ( token != nullptr )
+ if (nIdent > 0)
{
- std::string name = token->GetString();
- while ( pt != nullptr )
+ for (const auto& it : m_list)
{
- if ( pt->m_name == name )
+ if (it.second->m_ident == nIdent)
{
- nIdent = pt->m_nFuncIdent;
- goto fund;
+ pt = it.second.get();
}
- pt = pt->m_next;
}
}
- return -1;
-
-fund:
-#if !STACKRUN
- // lists the parameters depending on the contents of the stack (pStackVar)
-
- CBotVar* pVar = MakeListVars(ppVar, true);
- CBotVar* pVarToDelete = pVar;
-
- // creates a variable to the result
- CBotVar* pResult = rettype.Eq(0) ? nullptr : CBotVar::Create("", rettype);
-
- CBotVar* pRes = pResult;
- int Exception = 0;
- int res = pt->m_rExec(pVar, pResult, Exception, pStack->GetPUser());
-
- if ( pResult != pRes ) delete pRes; // different result if made
- delete pVarToDelete;
-
- if (res == false)
+ if (pt == nullptr)
{
- if (Exception!=0)
+ if (token != nullptr)
{
- pStack->SetError(Exception, token);
+ if (m_list.count(token->GetString()) > 0)
+ {
+ pt = m_list[token->GetString()].get();
+ nIdent = pt->m_ident;
+ }
}
- delete pResult;
- return false;
}
- pStack->SetVar(pResult);
-
- if ( rettype.GetType() > 0 && pResult == nullptr )
- {
- pStack->SetError(CBotErrNoRetVal, token);
- }
- nIdent = pt->m_nFuncIdent;
- return true;
-#else
+ if (pt == nullptr)
+ return -1;
CBotStack* pile = pStack->AddStackEOX(pt);
- if ( pile == EOX ) return true;
+ if (pile == EOX) return true;
// lists the parameters depending on the contents of the stack (pStackVar)
-
CBotVar* pVar = MakeListVars(ppVar, true);
-// CBotVar* pVarToDelete = pVar;
// creates a variable to the result
- CBotVar* pResult = rettype.Eq(0) ? nullptr : CBotVar::Create("", rettype);
+ CBotVar* pResult = rettype.Eq(CBotTypVoid) ? nullptr : CBotVar::Create("", rettype);
- pile->SetVar( pVar );
+ pile->SetVar(pVar);
CBotStack* pile2 = pile->AddStack();
- pile2->SetVar( pResult );
+ pile2->SetVar(pResult);
- pile->SetError(CBotNoErr, token); // for the position on error + away
- return pt->Run( pStack );
-
-#endif
+ pile->SetError(CBotNoErr, token); // save token for the position in case of error
+ return pt->Run(pStack);
}
-#if STACKRUN
-
-////////////////////////////////////////////////////////////////////////////////
bool CBotCall::RestoreCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBotStack* pStack)
{
- CBotCall* pt = m_ListCalls;
-
- {
- std::string name = token->GetString();
- while ( pt != nullptr )
- {
- if ( pt->m_name == name )
- {
- nIdent = pt->m_nFuncIdent;
+ if (m_list.count(token->GetString()) == 0)
+ return false;
- CBotStack* pile = pStack->RestoreStackEOX(pt);
- if ( pile == nullptr ) return true;
+ CBotCall* pt = m_list[token->GetString()].get();
+ nIdent = pt->m_ident;
- // CBotStack* pile2 = pile->RestoreStack();
- pile->RestoreStack();
- return true;
- }
- pt = pt->m_next;
- }
- }
+ CBotStack* pile = pStack->RestoreStackEOX(pt);
+ if ( pile == nullptr ) return true;
- return false;
+ pile->RestoreStack();
+ return true;
}
-////////////////////////////////////////////////////////////////////////////////
bool CBotCall::Run(CBotStack* pStack)
{
CBotStack* pile = pStack->AddStackEOX(this);
if ( pile == EOX ) return true;
- CBotVar* pVar = pile->GetVar();
+ CBotVar* args = pile->GetVar();
- CBotStack* pile2 = pile->AddStack();
- CBotVar* pResult = pile2->GetVar();
- CBotVar* pRes = pResult;
+ CBotStack* pile2 = pile->AddStack();
- int Exception = 0; // TODO: change this to CBotError
- int res = m_rExec(pVar, pResult, Exception, pStack->GetPUser());
+ CBotVar* result = pile2->GetVar();
- if (res == false)
+ int exception = CBotNoErr; // TODO: Change to CBotError
+ bool res = m_rExec(args, result, exception, pStack->GetPUser());
+
+ if (!res)
{
- if (Exception!=0)
+ if (exception != CBotNoErr)
{
- pStack->SetError(static_cast<CBotError>(Exception));
+ pStack->SetError(static_cast<CBotError>(exception));
}
- if ( pResult != pRes ) delete pResult; // different result if made
return false;
}
- if ( pResult != nullptr ) pStack->SetCopyVar( pResult );
- if ( pResult != pRes ) delete pResult; // different result if made
+ if (result != nullptr) pStack->SetCopyVar(result);
return true;
}
-
-#endif
diff --git a/src/CBot/CBotCall.h b/src/CBot/CBotCall.h
index 26789aa..122a17e 100644
--- a/src/CBot/CBotCall.h
+++ b/src/CBot/CBotCall.h
@@ -20,8 +20,12 @@
#pragma once
#include "CBot/CBotUtils.h"
+#include "CBot/CBotEnums.h"
+#include "CBot/CBotDefines.h"
#include <string>
+#include <map>
+#include <memory>
class CBotStack;
class CBotCStack;
@@ -29,114 +33,92 @@ class CBotVar;
class CBotTypResult;
class CBotToken;
-#define STACKRUN 1 //! \def return execution directly on a suspended routine
-
-/*!
- * \brief The CBotCall class. Class for routine calls (external).
+/**
+ * \brief Class used for external calls
+ *
+ * \see CBotProgram::AddFunction() for information on how to add your functions to this list
*/
class CBotCall : public CBotLinkedList<CBotCall>
{
public:
-
- /*!
- * \brief CBotCall
- * \param name
- * \param rExec
- * \param rCompile
+ typedef bool (*RuntimeFunc)(CBotVar* args, CBotVar* result, int& exception, void* user);
+ typedef CBotTypResult (*CompileFunc)(CBotVar*& args, void* user);
+
+ /**
+ * \brief Constructor
+ * \param name Function name
+ * \param rExec Runtime function
+ * \param rCompile Compilation function
+ * \see CBotProgram::AddFunction()
*/
- CBotCall(const std::string& name,
- bool rExec(CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
- CBotTypResult rCompile(CBotVar*& pVar, void* pUser));
+ CBotCall(const std::string& name, RuntimeFunc rExec, CompileFunc rCompile);
- /*!
- * \brief ~CBotCall
+ /**
+ * \brief Destructor
*/
~CBotCall();
- /*!
- * \brief AddFunction
- * \param name
- * \param rExec
- * \param rCompile
- * \return
+ /**
+ * \brief Add a new function to the list
+ * \param name Function name
+ * \param rExec Runtime function
+ * \param rCompile Compilation function
+ * \return true
*/
- static bool AddFunction(const std::string& name,
- bool rExec(CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
- CBotTypResult rCompile(CBotVar*& pVar, void* pUser));
-
- /*!
- * \brief CompileCall Is acceptable by a call procedure name and given
- * parameters.
- * \param p
- * \param ppVars
- * \param pStack
- * \param nIdent
- * \return
+ static bool AddFunction(const std::string& name, RuntimeFunc rExec, CompileFunc rCompile);
+
+ /**
+ * \brief Find and call compile function
+ *
+ * \todo Document
*/
static CBotTypResult CompileCall(CBotToken* &p, CBotVar** ppVars, CBotCStack* pStack, long& nIdent);
- /*!
- * \brief CheckCall
- * \param name
- * \return
+ /**
+ * \brief Check if function with given name has been defined
+ * \param name Name to check
+ * \return true if function was defined
*/
static bool CheckCall(const std::string& name);
- /*!
- * \brief DoCall
- * \param nIdent
- * \param token
- * \param ppVars
- * \param pStack
- * \param rettype
- * \return
+ /**
+ * \brief Find and call runtime function
+ *
+ * \todo Document
*/
static int DoCall(long& nIdent, CBotToken* token, CBotVar** ppVars, CBotStack* pStack, CBotTypResult& rettype);
-#if STACKRUN
-
- /*!
- * \brief Run
- * \param pStack
- * \return
+ /**
+ * \brief Execute the runtime function
+ * \param pStack Stack to execute the function on
+ * \return false if function requested interruption, true otherwise
*/
bool Run(CBotStack* pStack);
- /*!
- * \brief RestoreCall
- * \param nIdent
- * \param token
- * \param ppVar
- * \param pStack
- * \return
+ /**
+ * \brief Restore execution status after loading saved state
+ *
+ * \todo Document
*/
static bool RestoreCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBotStack* pStack);
-#endif
-
- /*!
- * \brief GetName
- * \return
- */
- std::string GetName();
- /*!
- * \brief SetPUser
- * \param pUser
+ /**
+ * \brief Set user pointer to pass to compile/runtime functions
+ * \param pUser User pointer
*/
- static void SetPUser(void* pUser);
+ static void SetUserPtr(void* pUser);
- /*!
- * \brief Free
+ /**
+ * \brief Reset the list of registered functions
*/
- static void Free();
-
+ static void Clear();
private:
- static CBotCall* m_ListCalls;
- static void* m_pUser;
- long m_nFuncIdent;
+ static std::map<std::string, std::unique_ptr<CBotCall>> m_list;
+ static void* m_user;
+ long m_ident;
std::string m_name;
- bool (*m_rExec) (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser);
- CBotTypResult (*m_rComp) (CBotVar* &pVar, void* pUser);
+ RuntimeFunc m_rExec;
+ CompileFunc m_rComp;
};
diff --git a/src/CBot/CBotEnums.h b/src/CBot/CBotEnums.h
index 6569a93..e453ee3 100644
--- a/src/CBot/CBotEnums.h
+++ b/src/CBot/CBotEnums.h
@@ -186,7 +186,7 @@ enum TokenType {
*
* Also note that these can't overlap with CBotType, see CBotTypResult for explanation
*/
-enum CBotError
+enum CBotError : int
{
CBotNoErr = 0,
diff --git a/src/CBot/CBotProgram.cpp b/src/CBot/CBotProgram.cpp
index a15108d..8961d9e 100644
--- a/src/CBot/CBotProgram.cpp
+++ b/src/CBot/CBotProgram.cpp
@@ -77,7 +77,7 @@ bool CBotProgram::Compile(const std::string& program, std::vector<std::string>&
CBotToken* p = tokens.get()->GetNext(); // skips the first token (separator)
pStack->SetProgram(this); // defined used routines
- CBotCall::SetPUser(pUser);
+ CBotCall::SetUserPtr(pUser);
// Step 2. Find all function and class definitions
while ( pStack->IsOk() && p != nullptr && p->GetType() != 0)
@@ -209,7 +209,6 @@ bool CBotProgram::Run(void* pUser, int timer)
m_pStack->SetBotCall(this); // bases for routines
-#if STACKRUN
// resumes execution on the top of the stack
ok = m_pStack->Execute();
if ( ok )
@@ -217,9 +216,6 @@ bool CBotProgram::Run(void* pUser, int timer)
// returns to normal execution
ok = m_entryPoint->Execute(nullptr, m_pStack, m_thisVar);
}
-#else
- ok = m_pRun->Execute(nullptr, m_pStack, m_thisVar);
-#endif
// completed on a mistake?
if (!ok && !m_pStack->IsOk())
@@ -440,6 +436,6 @@ void CBotProgram::Init()
void CBotProgram::Free()
{
CBotToken::ClearDefineNum() ;
- CBotCall ::Free() ;
+ CBotCall::Clear() ;
CBotClass::Free() ;
}
\ No newline at end of file
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/colobot.git
More information about the Pkg-games-commits
mailing list