[colobot] 17/74: Add accessing members to function calls

Didier Raboud odyx at moszumanska.debian.org
Mon Nov 7 07:50:00 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 fad38cd0e9313c6058f5ec7f7027f4904fdccbcc
Author: melex750 <melex750 at users.noreply.github.com>
Date:   Thu Aug 4 03:16:59 2016 -0400

    Add accessing members to function calls
---
 src/CBot/CBotInstr/CBotExprRetVar.cpp   | 183 ++++++++++++++++++++++++++++++++
 src/CBot/CBotInstr/CBotExprRetVar.h     |  45 ++++++++
 src/CBot/CBotInstr/CBotIndexExpr.h      |   1 +
 src/CBot/CBotInstr/CBotInstrCall.cpp    |  93 ++++++++--------
 src/CBot/CBotInstr/CBotInstrCall.h      |   4 +
 src/CBot/CBotInstr/CBotInstrMethode.cpp |  43 +++++++-
 src/CBot/CBotInstr/CBotInstrMethode.h   |   4 +
 src/CBot/CMakeLists.txt                 |   2 +
 8 files changed, 330 insertions(+), 45 deletions(-)

diff --git a/src/CBot/CBotInstr/CBotExprRetVar.cpp b/src/CBot/CBotInstr/CBotExprRetVar.cpp
new file mode 100644
index 0000000..28b0fa8
--- /dev/null
+++ b/src/CBot/CBotInstr/CBotExprRetVar.cpp
@@ -0,0 +1,183 @@
+
+#include <sstream>
+#include "CBot/CBotInstr/CBotExprRetVar.h"
+
+#include "CBot/CBotInstr/CBotExpression.h"
+#include "CBot/CBotInstr/CBotInstrMethode.h"
+#include "CBot/CBotInstr/CBotIndexExpr.h"
+#include "CBot/CBotInstr/CBotFieldExpr.h"
+
+#include "CBot/CBotStack.h"
+
+namespace CBot
+{
+
+////////////////////////////////////////////////////////////////////////////////
+CBotExprRetVar::CBotExprRetVar()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+CBotExprRetVar::~CBotExprRetVar()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+CBotInstr* CBotExprRetVar::Compile(CBotToken*& p, CBotCStack* pStack)
+{
+    if (p->GetType() == ID_DOT)
+    {
+        CBotVar*     var = pStack->GetVar();
+
+        if (var == nullptr)
+        {
+            pStack->SetError(CBotErrNoTerminator, p->GetStart());
+            return nullptr;
+        }
+
+        CBotCStack* pStk = pStack->TokenStack();
+        CBotInstr* inst = new CBotExprRetVar();
+
+        while (true)
+        {
+            pStk->SetStartError(p->GetStart());
+            if (var->GetType() == CBotTypArrayPointer)
+            {
+                if (IsOfType( p, ID_OPBRK ))
+                {
+                    CBotIndexExpr* i = new CBotIndexExpr();
+                    i->m_expr = CBotExpression::Compile(p, pStk);
+                    inst->AddNext3(i);
+
+                    var = var->GetItem(0,true);
+
+                    if (i->m_expr == nullptr || pStk->GetType() != CBotTypInt)
+                    {
+                        pStk->SetError(CBotErrBadIndex, p->GetStart());
+                        goto err;
+                    }
+                    if (!pStk->IsOk() || !IsOfType( p, ID_CLBRK ))
+                    {
+                        pStk->SetError(CBotErrCloseIndex, p->GetStart());
+                        goto err;
+                    }
+                    continue;
+                }
+            }
+            if (var->GetType(CBotVar::GetTypeMode::CLASS_AS_POINTER) == CBotTypPointer)
+            {
+                if (IsOfType(p, ID_DOT))
+                {
+                    CBotToken* pp = p;
+
+                    if (p->GetType() == TokenTypVar)
+                    {
+                        if (p->GetNext()->GetType() == ID_OPENPAR)
+                        {
+                            CBotInstr* i = CBotInstrMethode::Compile(p, pStk, var);
+                            if (!pStk->IsOk()) goto err;
+                            inst->AddNext3(i);
+                            return pStack->Return(inst, pStk);
+                        }
+                        else
+                        {
+                            CBotFieldExpr* i = new CBotFieldExpr();
+                            i->SetToken(pp);
+                            inst->AddNext3(i);
+                            var = var->GetItem(p->GetString());
+                            if (var != nullptr)
+                            {
+                                i->SetUniqNum(var->GetUniqNum());
+                                if ( var->IsPrivate() &&
+                                 !pStk->GetProgram()->m_bCompileClass)
+                                {
+                                    pStk->SetError(CBotErrPrivate, pp);
+                                    goto err;
+                                }
+                            }
+                        }
+
+                        if (var != nullptr)
+                        {
+                            p = p->GetNext();
+                            continue;
+                        }
+                        pStk->SetError(CBotErrUndefItem, p);
+                        goto err;
+                    }
+                    pStk->SetError(CBotErrUndefClass, p);
+                    goto err;
+                }
+            }
+            break;
+        }
+
+        pStk->SetCopyVar(var);
+        if (pStk->IsOk()) return pStack->Return(inst, pStk);
+
+        pStk->SetError(CBotErrUndefVar, p);
+err:
+        delete inst;
+        return pStack->Return(nullptr, pStk);
+    }
+    return nullptr;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool CBotExprRetVar::Execute(CBotStack* &pj)
+{
+
+    CBotStack* pile = pj->AddStack();
+    CBotStack* pile1 = pile;
+    CBotVar* pVar;
+
+    if (pile1->GetState() == 0)
+    {
+        pVar = pj->GetVar();
+        pVar->Update(pj->GetUserPtr());
+
+        if ( !m_next3->ExecuteVar(pVar, pile, &m_token, true, false) )
+                return false;
+
+        if (pVar)
+            pile1->SetCopyVar(pVar);
+        else
+            return pj->Return(pile1);
+
+        pile1->IncState();
+    }
+    pVar = pile1->GetVar();
+
+    if (pVar == nullptr)
+    {
+        return pj->Return(pile1);
+    }
+
+    if (pVar->IsUndefined())
+    {
+        pile1->SetError(CBotErrNotInit, &m_token);
+        return pj->Return(pile1);
+    }
+    return pj->Return(pile1);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void CBotExprRetVar::RestoreState(CBotStack* &pj, bool bMain)
+{
+    if (!bMain) return;
+
+    CBotStack* pile = pj->RestoreStack();
+    if ( pile == nullptr ) return;
+
+    if (pile->GetState() == 0)
+        m_next3->RestoreStateVar(pile, bMain);
+}
+
+std::string CBotExprRetVar::GetDebugData()
+{
+    std::stringstream ss;
+    ss << m_token.GetString() << "func(...).something" << std::endl;
+    return ss.str();
+}
+
+} // namespace CBot
diff --git a/src/CBot/CBotInstr/CBotExprRetVar.h b/src/CBot/CBotInstr/CBotExprRetVar.h
new file mode 100644
index 0000000..79c72ac
--- /dev/null
+++ b/src/CBot/CBotInstr/CBotExprRetVar.h
@@ -0,0 +1,45 @@
+
+#pragma once
+
+#include "CBot/CBotInstr/CBotInstr.h"
+
+namespace CBot
+{
+
+/**
+ * \brief Access a member/element of the variable on the stack
+ *
+ *
+ *
+ */
+class CBotExprRetVar : public CBotInstr
+{
+public:
+    CBotExprRetVar();
+    ~CBotExprRetVar();
+
+    static CBotInstr* Compile(CBotToken*& p, CBotCStack* pStack);
+
+    /*!
+     * \brief Execute
+     * \param pj
+     * \return
+     */
+    bool Execute(CBotStack* &pj) override;
+
+    /*!
+     * \brief RestoreState
+     * \param pj
+     * \param bMain
+     */
+    void RestoreState(CBotStack* &pj, bool bMain) override;
+
+protected:
+    virtual const std::string GetDebugName() override { return "CBotExprRetVar"; }
+    virtual std::string GetDebugData() override;
+
+private:
+
+};
+
+} // namespace CBot
diff --git a/src/CBot/CBotInstr/CBotIndexExpr.h b/src/CBot/CBotInstr/CBotIndexExpr.h
index 15fe2d4..8ac6ed5 100644
--- a/src/CBot/CBotInstr/CBotIndexExpr.h
+++ b/src/CBot/CBotInstr/CBotIndexExpr.h
@@ -69,6 +69,7 @@ private:
     CBotInstr* m_expr;
     friend class CBotLeftExpr;
     friend class CBotExprVar;
+    friend class CBotExprRetVar;
 };
 
 } // namespace CBot
diff --git a/src/CBot/CBotInstr/CBotInstrCall.cpp b/src/CBot/CBotInstr/CBotInstrCall.cpp
index 111ec81..6b45bb5 100644
--- a/src/CBot/CBotInstr/CBotInstrCall.cpp
+++ b/src/CBot/CBotInstr/CBotInstrCall.cpp
@@ -18,7 +18,8 @@
  */
 
 #include "CBot/CBotInstr/CBotInstrCall.h"
-#include "CBot/CBotInstr/CBotExpression.h"
+#include "CBot/CBotInstr/CBotExprRetVar.h"
+#include "CBot/CBotInstr/CBotInstrUtils.h"
 
 #include "CBot/CBotStack.h"
 
@@ -47,62 +48,26 @@ CBotInstrCall::~CBotInstrCall()
 ////////////////////////////////////////////////////////////////////////////////
 CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
 {
-    CBotVar*    ppVars[1000];
-
-    int         i = 0;
 
     CBotToken*  pp = p;
     p = p->GetNext();
 
-    pStack->SetStartError(p->GetStart());
-    CBotCStack* pile = pStack;
-
-    if ( IsOfType(p, ID_OPENPAR) )
+    if (p->GetType() == ID_OPENPAR)
     {
-        int start, end;
+
+        CBotVar*    ppVars[1000];
+
         CBotInstrCall* inst = new CBotInstrCall();
         inst->SetToken(pp);
 
         // compile la list of parameters
-        if (!IsOfType(p, ID_CLOSEPAR)) while (true)
+        inst->m_parameters = CompileParams(p, pStack, ppVars);
+
+        if ( !pStack->IsOk() )
         {
-            start = p->GetStart();
-            pile = pile->TokenStack();                      // keeps the results on the stack
-
-            CBotInstr*  param = CBotExpression::Compile(p, pile);
-            end   = p->GetStart();
-            if (inst->m_parameters == nullptr ) inst->m_parameters = param;
-            else inst->m_parameters->AddNext(param);            // constructs the list
-
-            if ( !pile->IsOk() )
-            {
-                delete inst;
-                return pStack->Return(nullptr, pile);
-            }
-
-            if ( param != nullptr )
-            {
-                if ( pile->GetTypResult().Eq(99) )
-                {
-                    delete pStack->TokenStack();
-                    pStack->SetError(CBotErrVoid, p->GetStart());
-                    delete inst;
-                    return nullptr;
-                }
-                ppVars[i] = pile->GetVar();
-                ppVars[i]->GetToken()->SetPos(start, end);
-                i++;
-
-                if (IsOfType(p, ID_COMMA)) continue;            // skips the comma
-                if (IsOfType(p, ID_CLOSEPAR)) break;
-            }
-
-            pStack->SetError(CBotErrClosePar, p->GetStart());
-            delete pStack->TokenStack();
             delete inst;
             return nullptr;
         }
-        ppVars[i] = nullptr;
 
         // the routine is known?
 //      CBotClass*  pClass = nullptr;
@@ -124,6 +89,17 @@ CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
         }
         else pStack->SetVar(nullptr);          // routine returns void
 
+        if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStack)))
+        {
+            inst->m_exprRetVar->SetToken(&inst->m_token);
+            delete pStack->TokenStack();
+        }
+        if ( !pStack->IsOk() )
+        {
+            delete inst;
+            return nullptr;
+        }
+
         return inst;
     }
     p = pp;
@@ -138,6 +114,17 @@ bool CBotInstrCall::Execute(CBotStack* &pj)
     CBotStack*  pile  = pj->AddStack(this);
     if ( pile->StackOver() ) return pj->Return( pile );
 
+    CBotStack* pile3 = nullptr;
+    if (m_exprRetVar != nullptr) // func().member
+    {
+        pile3 = pile->AddStack2();
+        if (pile3->GetState() == 1) // function call is done?
+        {
+            if (!m_exprRetVar->Execute(pile3)) return false;
+            return pj->Return(pile3);
+        }
+    }
+
 //    CBotStack*  pile1 = pile;
 
     int     i = 0;
@@ -165,6 +152,14 @@ bool CBotInstrCall::Execute(CBotStack* &pj)
 
     if ( !pile2->ExecuteCall(m_nFuncIdent, GetToken(), ppVars, m_typRes)) return false; // interrupt
 
+    if (m_exprRetVar != nullptr) // func().member
+    {
+        pile3->SetCopyVar( pile2->GetVar() ); // copy the result
+        pile2->SetVar(nullptr);
+        pile3->SetState(1);      // set call is done
+        return false;            // go back to the top ^^^
+    }
+
     return pj->Return(pile2);   // release the entire stack
 }
 
@@ -176,6 +171,16 @@ void CBotInstrCall::RestoreState(CBotStack* &pj, bool bMain)
     CBotStack*  pile  = pj->RestoreStack(this);
     if ( pile == nullptr ) return;
 
+    if (m_exprRetVar != nullptr)    // func().member
+    {
+        CBotStack* pile3 = pile->AddStack2();
+        if (pile3->GetState() == 1) // function call is done?
+        {
+            m_exprRetVar->RestoreState(pile3, bMain);
+            return;
+        }
+    }
+
 //    CBotStack*  pile1 = pile;
 
     int         i = 0;
diff --git a/src/CBot/CBotInstr/CBotInstrCall.h b/src/CBot/CBotInstr/CBotInstrCall.h
index 7e8aba0..e39534f 100644
--- a/src/CBot/CBotInstr/CBotInstrCall.h
+++ b/src/CBot/CBotInstr/CBotInstrCall.h
@@ -69,6 +69,10 @@ private:
     CBotTypResult m_typRes;
     //! Id of a function.
     long m_nFuncIdent;
+
+    //! Instruction to return a member of the returned object.
+    CBotInstr* m_exprRetVar;
+
     friend class CBotDebug;
 };
 
diff --git a/src/CBot/CBotInstr/CBotInstrMethode.cpp b/src/CBot/CBotInstr/CBotInstrMethode.cpp
index 3bdf849..78ed6b4 100644
--- a/src/CBot/CBotInstr/CBotInstrMethode.cpp
+++ b/src/CBot/CBotInstr/CBotInstrMethode.cpp
@@ -20,6 +20,7 @@
 #include <sstream>
 #include "CBot/CBotInstr/CBotInstrMethode.h"
 
+#include "CBot/CBotInstr/CBotExprRetVar.h"
 #include "CBot/CBotInstr/CBotInstrUtils.h"
 
 #include "CBot/CBotStack.h"
@@ -86,7 +87,16 @@ CBotInstr* CBotInstrMethode::Compile(CBotToken* &p, CBotCStack* pStack, CBotVar*
                 }
                 pStack->SetVar(pResult);
             }
-            return inst;
+            else pStack->SetVar(nullptr);
+
+            if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStack)))
+            {
+                inst->m_exprRetVar->SetToken(&inst->m_token);
+                delete pStack->TokenStack();
+            }
+
+            if ( pStack->IsOk() )
+                return inst;
         }
         delete inst;
         return nullptr;
@@ -106,6 +116,18 @@ bool CBotInstrMethode::ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* pre
         return pj->Return(pile1);
     }
 
+    CBotStack*    pile3 = nullptr;
+    if (m_exprRetVar != nullptr)    // .func().member
+    {
+        pile3 = pile1->AddStack2();
+        if (pile3->GetState() == 1)
+        {
+            if (!m_exprRetVar->Execute(pile3)) return false;
+            pVar = nullptr;
+            return pj->Return(pile3);
+        }
+    }
+
     if (pile1->IfStep()) return false;
 
     CBotStack*    pile2 = pile1->AddStack();    // for the next parameters
@@ -159,6 +181,15 @@ bool CBotInstrMethode::ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* pre
                                  pResult, pile2, GetToken())) return false;
     if (pRes != pResult) delete pRes;
 
+    if (m_exprRetVar != nullptr) // .func().member
+    {
+        pile3->SetCopyVar( pile2->GetVar() );
+        pile2->SetVar(nullptr);
+        pile3->SetState(1);      // set call is done
+        pVar = nullptr;
+        return false;            // go back to the top ^^^
+    }
+
     pVar = nullptr;                // does not return value for this
     return pj->Return(pile2);   // release the entire stack
 }
@@ -172,6 +203,16 @@ void CBotInstrMethode::RestoreStateVar(CBotStack* &pile, bool bMain)
     CBotStack*    pile1 = pile->RestoreStack(this);     // place for the copy of This
     if (pile1 == nullptr) return;
 
+    if (m_exprRetVar != nullptr)    // .func().member
+    {
+        CBotStack* pile3 = pile1->AddStack2();
+        if (pile3->GetState() == 1) // function call is done?
+        {
+            m_exprRetVar->RestoreState(pile3, bMain);
+            return;
+        }
+    }
+
     CBotStack*    pile2 = pile1->RestoreStack();        // and for the parameters coming
     if (pile2 == nullptr) return;
 
diff --git a/src/CBot/CBotInstr/CBotInstrMethode.h b/src/CBot/CBotInstr/CBotInstrMethode.h
index 6c8d173..fb2b205 100644
--- a/src/CBot/CBotInstr/CBotInstrMethode.h
+++ b/src/CBot/CBotInstr/CBotInstrMethode.h
@@ -83,6 +83,10 @@ private:
     long m_MethodeIdent;
     //! Name of the class.
     std::string m_className;
+
+    //! Instruction to return a member of the returned object.
+    CBotInstr* m_exprRetVar;
+
 };
 
 } // namespace CBot
diff --git a/src/CBot/CMakeLists.txt b/src/CBot/CMakeLists.txt
index b77d0bb..6ac4d13 100644
--- a/src/CBot/CMakeLists.txt
+++ b/src/CBot/CMakeLists.txt
@@ -54,6 +54,8 @@ set(SOURCES
     CBotInstr/CBotExprLitNum.h
     CBotInstr/CBotExprLitString.cpp
     CBotInstr/CBotExprLitString.h
+    CBotInstr/CBotExprRetVar.cpp
+    CBotInstr/CBotExprRetVar.h
     CBotInstr/CBotExprUnaire.cpp
     CBotInstr/CBotExprUnaire.h
     CBotInstr/CBotExprVar.cpp

-- 
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