[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