[colobot] 41/100: Fix increment and decrement syntax

Didier Raboud odyx at moszumanska.debian.org
Thu Jun 1 18:10:17 UTC 2017


This is an automated email from the git hooks/post-receive script.

odyx pushed a commit to branch debian/master
in repository colobot.

commit 8fc015144467ef299c2fba83996cdc2bcef0455b
Author: melex750 <melex750 at users.noreply.github.com>
Date:   Mon Jan 16 11:38:34 2017 -0500

    Fix increment and decrement syntax
---
 src/CBot/CBotInstr/CBotExprVar.cpp   |  8 ++++--
 src/CBot/CBotInstr/CBotExprVar.h     | 11 ++++----
 src/CBot/CBotInstr/CBotFieldExpr.cpp |  5 ++--
 src/CBot/CBotInstr/CBotFieldExpr.h   |  7 ++---
 src/CBot/CBotInstr/CBotLeftExpr.cpp  |  5 ++--
 src/CBot/CBotInstr/CBotParExpr.cpp   | 29 +++++++++-----------
 test/unit/CBot/CBot_test.cpp         | 53 ++++++++++++++++++++++++++++++++++++
 7 files changed, 83 insertions(+), 35 deletions(-)

diff --git a/src/CBot/CBotInstr/CBotExprVar.cpp b/src/CBot/CBotInstr/CBotExprVar.cpp
index a15c9c9..ed77d8a 100644
--- a/src/CBot/CBotInstr/CBotExprVar.cpp
+++ b/src/CBot/CBotInstr/CBotExprVar.cpp
@@ -44,7 +44,7 @@ CBotExprVar::~CBotExprVar()
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, CBotVar::ProtectionLevel privat)
+CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bCheckReadOnly)
 {
 //    CBotToken*    pDebut = p;
     CBotCStack* pStk = pStack->TokenStack();
@@ -67,7 +67,7 @@ CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, CBotVar::Prot
 
             if (ident > 0 && ident < 9000)
             {
-                if (CBotFieldExpr::CheckProtectionError(pStk, nullptr, var, privat))
+                if (CBotFieldExpr::CheckProtectionError(pStk, nullptr, var, bCheckReadOnly))
                 {
                     pStk->SetError(CBotErrPrivate, p);
                     goto err;
@@ -122,6 +122,8 @@ CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, CBotVar::Prot
                         {
                             if (p->GetNext()->GetType() == ID_OPENPAR)  // a method call?
                             {
+                                if (bCheckReadOnly) goto err; // don't allow increment a method call "++"
+
                                 CBotInstr* i = CBotInstrMethode::Compile(p, pStk, var);
                                 if (!pStk->IsOk()) goto err;
                                 inst->AddNext3(i);  // added after
@@ -137,7 +139,7 @@ CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, CBotVar::Prot
                                 if (var != nullptr)
                                 {
                                     i->SetUniqNum(var->GetUniqNum());
-                                    if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var, privat))
+                                    if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var, bCheckReadOnly))
                                     {
                                         pStk->SetError(CBotErrPrivate, pp);
                                         goto err;
diff --git a/src/CBot/CBotInstr/CBotExprVar.h b/src/CBot/CBotInstr/CBotExprVar.h
index 9cf6899..2f2e69a 100644
--- a/src/CBot/CBotInstr/CBotExprVar.h
+++ b/src/CBot/CBotInstr/CBotExprVar.h
@@ -40,14 +40,13 @@ public:
     ~CBotExprVar();
 
     /*!
-     * \brief Compile
-     * \param p
-     * \param pStack
-     * \param privat
+     * \brief Compile an expression of a variable, possibly chained with index operators and/or dot operators
+     * \param p[in, out] Pointer to first token of the expression, will be updated to point to first token after the expression
+     * \param pStack Current compilation stack frame
+     * \param bCheckReadOnly True for operations that would modify the value of the variable
      * \return
      */
-    static CBotInstr* Compile(CBotToken*& p, CBotCStack* pStack,
-                              CBotVar::ProtectionLevel privat = CBotVar::ProtectionLevel::Protected);
+    static CBotInstr* Compile(CBotToken*& p, CBotCStack* pStack, bool bCheckReadOnly = false);
 
     /*!
      * \brief CompileMethode
diff --git a/src/CBot/CBotInstr/CBotFieldExpr.cpp b/src/CBot/CBotInstr/CBotFieldExpr.cpp
index 09ac5f8..04635a1 100644
--- a/src/CBot/CBotInstr/CBotFieldExpr.cpp
+++ b/src/CBot/CBotInstr/CBotFieldExpr.cpp
@@ -135,12 +135,11 @@ std::string CBotFieldExpr::GetDebugData()
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-bool CBotFieldExpr::CheckProtectionError(CBotCStack* pStack, CBotVar* pPrev, CBotVar* pVar,
-                                         CBotVar::ProtectionLevel privat)
+bool CBotFieldExpr::CheckProtectionError(CBotCStack* pStack, CBotVar* pPrev, CBotVar* pVar, bool bCheckReadOnly)
 {
     CBotVar::ProtectionLevel varPriv = pVar->GetPrivate();
 
-    if (privat == CBotVar::ProtectionLevel::ReadOnly && varPriv == privat)
+    if (bCheckReadOnly && varPriv == CBotVar::ProtectionLevel::ReadOnly)
         return true;
 
     if (varPriv == CBotVar::ProtectionLevel::Public) return false;
diff --git a/src/CBot/CBotInstr/CBotFieldExpr.h b/src/CBot/CBotInstr/CBotFieldExpr.h
index 67ab2f0..5f093bd 100644
--- a/src/CBot/CBotInstr/CBotFieldExpr.h
+++ b/src/CBot/CBotInstr/CBotFieldExpr.h
@@ -72,13 +72,12 @@ public:
      * This function doesn't set the error flag itself.
      *
      * \param pStack Current compilation stack frame
-     * \param pPrev Class instance which variable to check is part of, or nullptr if not part of a class
+     * \param pPrev Class instance which variable to check is part of, or nullptr when compiler inserts 'this.' before
      * \param pVar Variable to check
-     * \param privat CBotVar::ProtectionLevel::ReadOnly if requesting read-only access, anything else otherwise
+     * \param bCheckReadOnly True for operations that would modify the value of the variable
      * \return true if pVar is inaccessible in the current context, false if access should be allowed
      */
-    static bool CheckProtectionError(CBotCStack* pStack, CBotVar* pPrev, CBotVar* pVar,
-                                     CBotVar::ProtectionLevel privat = CBotVar::ProtectionLevel::Protected);
+    static bool CheckProtectionError(CBotCStack* pStack, CBotVar* pPrev, CBotVar* pVar, bool bCheckReadOnly = false);
 
 protected:
     virtual const std::string GetDebugName() override { return "CBotFieldExpr"; }
diff --git a/src/CBot/CBotInstr/CBotLeftExpr.cpp b/src/CBot/CBotInstr/CBotLeftExpr.cpp
index 4678ff8..4c4400a 100644
--- a/src/CBot/CBotInstr/CBotLeftExpr.cpp
+++ b/src/CBot/CBotInstr/CBotLeftExpr.cpp
@@ -64,7 +64,7 @@ CBotLeftExpr* CBotLeftExpr::Compile(CBotToken* &p, CBotCStack* pStack)
             inst->m_nIdent = var->GetUniqNum();
             if (inst->m_nIdent > 0 && inst->m_nIdent < 9000)
             {
-                if (CBotFieldExpr::CheckProtectionError(pStk, nullptr, var, CBotVar::ProtectionLevel::ReadOnly))
+                if (CBotFieldExpr::CheckProtectionError(pStk, nullptr, var, true))
                 {
                     pStk->SetError(CBotErrPrivate, p);
                     goto err;
@@ -128,8 +128,7 @@ CBotLeftExpr* CBotLeftExpr::Compile(CBotToken* &p, CBotCStack* pStack)
                             var = var->GetItem(p->GetString());            // get item correspondent
                             if (var != nullptr)
                             {
-                                if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var,
-                                                                        CBotVar::ProtectionLevel::ReadOnly))
+                                if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var, true))
                                 {
                                     pStk->SetError(CBotErrPrivate, pp);
                                     goto err;
diff --git a/src/CBot/CBotInstr/CBotParExpr.cpp b/src/CBot/CBotInstr/CBotParExpr.cpp
index 714e68e..a32363f 100644
--- a/src/CBot/CBotInstr/CBotParExpr.cpp
+++ b/src/CBot/CBotInstr/CBotParExpr.cpp
@@ -90,17 +90,16 @@ CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack)
         // post incremented or decremented?
         if (IsOfType(p, ID_INC, ID_DEC))
         {
+            // recompile the variable for read-only
+            delete inst;
+            p = pvar;
+            inst = CBotExprVar::Compile(p, pStk, true);
             if (pStk->GetType() >= CBotTypBoolean)
             {
                 pStk->SetError(CBotErrBadType1, pp);
                 delete inst;
                 return pStack->Return(nullptr, pStk);
             }
-
-            // recompile the variable for read-only
-            delete inst;
-            p = pvar;
-            inst =  CBotExprVar::Compile(p, pStk, CBotVar::ProtectionLevel::ReadOnly);
             p = p->GetNext();
 
             CBotPostIncExpr* i = new CBotPostIncExpr();
@@ -115,24 +114,22 @@ CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack)
     CBotToken* pp = p;
     if (IsOfType(p, ID_INC, ID_DEC))
     {
-        CBotPreIncExpr* i = new CBotPreIncExpr();
-        i->SetToken(pp);
-
         if (p->GetType() == TokenTypVar)
         {
-            if (nullptr != (i->m_instr =  CBotExprVar::Compile(p, pStk, CBotVar::ProtectionLevel::ReadOnly)))
+            if (nullptr != (inst = CBotExprVar::Compile(p, pStk, true)))
             {
-                if (pStk->GetType() >= CBotTypBoolean)
+                if (pStk->GetType() < CBotTypBoolean) // a number ?
                 {
-                    pStk->SetError(CBotErrBadType1, pp);
-                    delete inst;
-                    return pStack->Return(nullptr, pStk);
+                    CBotPreIncExpr* i = new CBotPreIncExpr();
+                    i->SetToken(pp);
+                    i->m_instr = inst;
+                    return pStack->Return(i, pStk);
                 }
-                return pStack->Return(i, pStk);
+                delete inst;
             }
-            delete i;
-            return pStack->Return(nullptr, pStk);
         }
+        pStk->SetError(CBotErrBadType1, pp);
+        return pStack->Return(nullptr, pStk);
     }
 
     // is it a number or DefineNum?
diff --git a/test/unit/CBot/CBot_test.cpp b/test/unit/CBot/CBot_test.cpp
index 6cf2841..e456261 100644
--- a/test/unit/CBot/CBot_test.cpp
+++ b/test/unit/CBot/CBot_test.cpp
@@ -2073,3 +2073,56 @@ TEST_F(CBotUT, ClassTestPrivateMember)
         CBotErrPrivate
     );
 }
+
+TEST_F(CBotUT, IncrementDecrementSyntax)
+{
+    auto publicProgram = ExecuteTest(
+        "public class TestClass {\n"
+        "    int GetInt() { return 1; }\n"
+        "}\n"
+        "extern void TestIncrementDecrement()\n"
+        "{\n"
+        "    int i = 1;\n"
+        "    ASSERT(2 == ++i);\n"
+        "    ASSERT(2 == i++);\n"
+        "    ASSERT(3 ==  i );\n"
+        "    ASSERT(2 == --i);\n"
+        "    ASSERT(2 == i--);\n"
+        "    ASSERT(1 ==  i );\n"
+        "}\n"
+    );
+
+    ExecuteTest(
+        "extern void PreIncrementMethodCall()\n"
+        "{\n"
+        "    TestClass tc();\n"
+        "    ++tc.GetInt();\n"
+        "}\n",
+        CBotErrBadType1
+    );
+
+    ExecuteTest(
+        "extern void PostIncrementMethodCall()\n"
+        "{\n"
+        "    TestClass tc();\n"
+        "    tc.GetInt()++;\n"
+        "}\n",
+        CBotErrBadType1
+    );
+
+    ExecuteTest(
+        "extern void BadPreIncrementEmpty()\n"
+        "{\n"
+        "    ++;\n"
+        "}\n",
+        CBotErrBadType1
+    );
+
+    ExecuteTest(
+        "extern void BadPreIncrementNotAVar()\n"
+        "{\n"
+        "    ++123;\n"
+        "}\n",
+        CBotErrBadType1
+    );
+}

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