[colobot] 42/100: Fix constructor/destructor and field 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 64bc1f1afb0eb00cbd403fe1fbc21bf2e4b84a74
Author: melex750 <melex750 at users.noreply.github.com>
Date:   Mon Jan 16 12:34:18 2017 -0500

    Fix constructor/destructor and field syntax
---
 po/colobot.pot                      |  3 ++
 po/de.po                            |  3 ++
 po/fr.po                            |  3 ++
 po/pl.po                            |  3 ++
 po/ru.po                            |  3 ++
 src/CBot/CBotClass.cpp              | 83 ++++++++++++++++++++++++-------------
 src/CBot/CBotClass.h                |  7 ++++
 src/CBot/CBotEnums.h                |  1 +
 src/CBot/CBotInstr/CBotFunction.cpp | 34 ++++++++++++++-
 src/common/restext.cpp              |  1 +
 test/unit/CBot/CBot_test.cpp        | 59 ++++++++++++++++++++++++--
 11 files changed, 167 insertions(+), 33 deletions(-)

diff --git a/po/colobot.pot b/po/colobot.pot
index a144676..fd5c3de 100644
--- a/po/colobot.pot
+++ b/po/colobot.pot
@@ -1736,6 +1736,9 @@ msgstr ""
 msgid "Ambiguous call to overloaded function"
 msgstr ""
 
+msgid "Function needs return type \"void\""
+msgstr ""
+
 msgid "Dividing by zero"
 msgstr ""
 
diff --git a/po/de.po b/po/de.po
index 653fa66..e4c105a 100644
--- a/po/de.po
+++ b/po/de.po
@@ -616,6 +616,9 @@ msgstr "Diese Funktion gibt es schon"
 msgid "Function name missing"
 msgstr "Hier muss der Name der Funktion stehen"
 
+msgid "Function needs return type \"void\""
+msgstr ""
+
 msgid "Game speed"
 msgstr "Spielgeschwindigkeit"
 
diff --git a/po/fr.po b/po/fr.po
index 6f43267..905a016 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -603,6 +603,9 @@ msgstr "Cette fonction existe déjà"
 msgid "Function name missing"
 msgstr "Nom de la fonction attendu"
 
+msgid "Function needs return type \"void\""
+msgstr ""
+
 msgid "Game speed"
 msgstr "Vitesse du jeu"
 
diff --git a/po/pl.po b/po/pl.po
index f17c817..cd9f37c 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -605,6 +605,9 @@ msgstr "Funkcja już istnieje"
 msgid "Function name missing"
 msgstr "Brakująca nazwa funkcji"
 
+msgid "Function needs return type \"void\""
+msgstr ""
+
 msgid "Game speed"
 msgstr "Prędkość gry"
 
diff --git a/po/ru.po b/po/ru.po
index 7072769..233cb30 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -612,6 +612,9 @@ msgstr "Функция уже существует"
 msgid "Function name missing"
 msgstr "Имя функции отсутствует"
 
+msgid "Function needs return type \"void\""
+msgstr ""
+
 msgid "Game speed"
 msgstr "Скорость игры"
 
diff --git a/src/CBot/CBotClass.cpp b/src/CBot/CBotClass.cpp
index 13fb837..127d6d3 100644
--- a/src/CBot/CBotClass.cpp
+++ b/src/CBot/CBotClass.cpp
@@ -249,6 +249,19 @@ CBotVar* CBotClass::GetItemRef(int nIdent)
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+bool CBotClass::CheckVar(const std::string &name)
+{
+    CBotVar*    p = m_pVar;
+
+    while ( p != nullptr )
+    {
+        if ( p->GetName() == name ) return true;
+        p = p->GetNext();
+    }
+    return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
 bool CBotClass::IsIntrinsic()
 {
     return  m_bIntrinsic;
@@ -556,6 +569,8 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
     while (pStack->IsOk())
     {
         CBotTypResult  type2 = CBotTypResult(type);                     // reset type after comma
+        CBotToken*     varToken = p;
+
         std::string pp = p->GetString();
         if ( IsOfType(p, ID_NOT) )
         {
@@ -564,33 +579,6 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
 
         if (IsOfType(p, TokenTypVar))
         {
-            CBotInstr* limites = nullptr;
-            while ( IsOfType( p, ID_OPBRK ) )   // a table?
-            {
-                CBotInstr* i = nullptr;
-                pStack->SetStartError( p->GetStart() );
-                if ( p->GetType() != ID_CLBRK )
-                {
-                    i = CBotExpression::Compile( p, pStack );           // expression for the value
-                    if (i == nullptr || pStack->GetType() != CBotTypInt) // must be a number
-                    {
-                        pStack->SetError(CBotErrBadIndex, p->GetStart());
-                        return false;
-                    }
-                }
-                else
-                    i = new CBotEmpty();                            // special if not a formula
-
-                type2 = CBotTypResult(CBotTypArrayPointer, type2);
-
-                if (limites == nullptr) limites = i;
-                else limites->AddNext3(i);
-
-                if (IsOfType(p, ID_CLBRK)) continue;
-                pStack->SetError(CBotErrCloseIndex, p->GetStart());
-                return false;
-            }
-
             if ( p->GetType() == ID_OPENPAR )
             {
                 if ( !bSecond )
@@ -673,12 +661,51 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
             }
 
             // definition of an element
-            if (type2.Eq(0))
+            if (type.Eq(0))
             {
                 pStack->SetError(CBotErrNoTerminator, p);
                 return false;
             }
 
+            if (pp[0] == '~' || pp == GetName()) // bad variable name
+            {
+                pStack->SetError(CBotErrNoVar, varToken);
+                return false;
+            }
+
+            if (!bSecond && CheckVar(pp)) // variable already exists
+            {
+                pStack->SetError(CBotErrRedefVar, varToken);
+                return false;
+            }
+
+            CBotInstr* limites = nullptr;
+            while ( IsOfType( p, ID_OPBRK ) )   // an array
+            {
+                CBotInstr* i = nullptr;
+                pStack->SetStartError( p->GetStart() );
+                if ( p->GetType() != ID_CLBRK )
+                {
+                    i = CBotExpression::Compile( p, pStack );           // expression for the value
+                    if (i == nullptr || pStack->GetType() != CBotTypInt) // must be a number
+                    {
+                        pStack->SetError(CBotErrBadIndex, p->GetStart());
+                        return false;
+                    }
+                }
+                else
+                    i = new CBotEmpty();                            // special if not a formula
+
+                type2 = CBotTypResult(CBotTypArrayPointer, type2);
+
+                if (limites == nullptr) limites = i;
+                else limites->AddNext3(i);
+
+                if (IsOfType(p, ID_CLBRK)) continue;
+                pStack->SetError(CBotErrCloseIndex, p->GetStart());
+                return false;
+            }
+
             CBotInstr* i = nullptr;
             if ( IsOfType(p, ID_ASS ) )
             {
diff --git a/src/CBot/CBotClass.h b/src/CBot/CBotClass.h
index 68b61cc..503c62d 100644
--- a/src/CBot/CBotClass.h
+++ b/src/CBot/CBotClass.h
@@ -222,6 +222,13 @@ public:
     CBotVar* GetItemRef(int nIdent);
 
     /*!
+     * \brief Check whether a variable is already defined in a class
+     * \param name Name of the variable
+     * \return True if a variable is defined in the class
+     */
+    bool CheckVar(const std::string &name);
+
+    /*!
      * \brief CompileMethode Compiles a method associated with an instance of
      * class the method can be declared by the user or AddFunction.
      * \param name
diff --git a/src/CBot/CBotEnums.h b/src/CBot/CBotEnums.h
index da0dbea..b7453e5 100644
--- a/src/CBot/CBotEnums.h
+++ b/src/CBot/CBotEnums.h
@@ -237,6 +237,7 @@ enum CBotError : int
     CBotErrNoPublic      = 5042, //!< missing word "public"
     CBotErrNoExpression  = 5043, //!< expression expected after =
     CBotErrAmbiguousCall = 5044, //!< ambiguous call to overloaded function
+    CBotErrFuncNotVoid   = 5045, //!< function needs return type "void"
 
     // Runtime errors
     CBotErrZeroDiv       = 6000, //!< division by zero
diff --git a/src/CBot/CBotInstr/CBotFunction.cpp b/src/CBot/CBotInstr/CBotFunction.cpp
index f86153f..7852c7e 100644
--- a/src/CBot/CBotInstr/CBotFunction.cpp
+++ b/src/CBot/CBotInstr/CBotFunction.cpp
@@ -165,6 +165,7 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
         if ( IsOfType(p, ID_NOT) )
         {
             CBotToken d(std::string("~") + p->GetString());
+            d.SetPos(pp->GetStart(), p->GetEnd());
             func->m_token = d;
         }
 
@@ -268,6 +269,7 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
         if ( IsOfType(p, ID_NOT) )
         {
             CBotToken d(std::string("~") + p->GetString());
+            d.SetPos(pp->GetStart(), p->GetEnd());
             func->m_token = d;
         }
 
@@ -289,10 +291,40 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
                 if (!IsOfType(p, TokenTypVar)) goto bad;
 
             }
-            func->m_param = CBotDefParam::Compile(p, pStk );
+
+            CBotToken* openPar = p;
+            func->m_param = CBotDefParam::Compile(p, pStk); // compile parameters
+
+            if (pStk->IsOk() && pClass != nullptr) // method in a class
+            {
+                // check if a constructor has return type void
+                if (func->GetName() == pClass->GetName() && !func->m_retTyp.Eq(CBotTypVoid))
+                {
+                    pp = &(func->m_retToken);
+                    pStk->SetError(CBotErrFuncNotVoid, pp);
+                }
+
+                if (pStk->IsOk() && pp->GetString() == "~") // destructor
+                {
+                    // check destructor name
+                    if (func->GetName() != ("~" + pClass->GetName()))
+                        pStk->SetError(CBotErrNoFunc, pp);
+                    // confirm no parameters
+                    if (pStk->IsOk() && func->m_param != nullptr)
+                        pStk->SetError(CBotErrClosePar, openPar->GetNext());
+                    // must return void
+                    if (pStk->IsOk() && !func->m_retTyp.Eq(CBotTypVoid))
+                    {
+                        pp = &(func->m_retToken);
+                        pStk->SetError(CBotErrFuncNotVoid, pp);
+                    }
+                }
+            }
+
             if (pStk->IsOk())
             {
                 // looks if the function exists elsewhere
+                pp = &(func->m_token);
                 if (( pClass != nullptr || !pStack->CheckCall(pp, func->m_param)) &&
                     ( pClass == nullptr || !pClass->CheckCall(pStack->GetProgram(), func->m_param, pp)) )
                 {
diff --git a/src/common/restext.cpp b/src/common/restext.cpp
index 5cd6c91..789c68a 100644
--- a/src/common/restext.cpp
+++ b/src/common/restext.cpp
@@ -719,6 +719,7 @@ void InitializeRestext()
     stringsCbot[CBot::CBotErrNoPublic]      = TR("Public required");
     stringsCbot[CBot::CBotErrNoExpression]  = TR("Expression expected after =");
     stringsCbot[CBot::CBotErrAmbiguousCall] = TR("Ambiguous call to overloaded function");
+    stringsCbot[CBot::CBotErrFuncNotVoid]   = TR("Function needs return type \"void\"");
 
     stringsCbot[CBot::CBotErrZeroDiv]       = TR("Dividing by zero");
     stringsCbot[CBot::CBotErrNotInit]       = TR("Variable not initialized");
diff --git a/test/unit/CBot/CBot_test.cpp b/test/unit/CBot/CBot_test.cpp
index e456261..ca9ff91 100644
--- a/test/unit/CBot/CBot_test.cpp
+++ b/test/unit/CBot/CBot_test.cpp
@@ -867,14 +867,13 @@ TEST_F(CBotUT, ClassNullPointer)
     );
 }
 
-// TODO: This doesn't work
-TEST_F(CBotUT, DISABLED_ClassDestructorNaming)
+TEST_F(CBotUT, ClassDestructorNaming)
 {
     ExecuteTest(
         "public class TestClass {\n"
         "    public void ~SomethingElse() {}\n"
         "}\n",
-        static_cast<CBotError>(-1) // TODO: no error for that
+        CBotErrNoFunc
     );
     ExecuteTest(
         "public class SomethingElse {\n"
@@ -882,7 +881,26 @@ TEST_F(CBotUT, DISABLED_ClassDestructorNaming)
         "public class TestClass2 {\n"
         "    public void ~SomethingElse() {}\n"
         "}\n",
-        static_cast<CBotError>(-1) // TODO: no error for that
+        CBotErrNoFunc
+    );
+}
+
+TEST_F(CBotUT, ClassDestructorSyntax)
+{
+    ExecuteTest(
+        "public class TestClass {\n"
+        "    void ~TestClass(int i) {}\n"
+        "}\n"
+        "extern void DestructorNoParams() {}\n",
+        CBotErrClosePar
+    );
+
+    ExecuteTest(
+        "public class TestClass {\n"
+        "    int ~TestClass() {}\n"
+        "}\n"
+        "extern void DestructorReturnTypeVoid() {}\n",
+        CBotErrFuncNotVoid
     );
 }
 
@@ -930,6 +948,39 @@ TEST_F(CBotUT, ClassMethodRedefined)
         "}\n",
         CBotErrRedefFunc
     );
+
+    ExecuteTest(
+        "public class TestClass {\n"
+        "    void ~TestClass() {}\n"
+        "    void ~TestClass() {}\n"
+        "}\n",
+        CBotErrRedefFunc
+    );
+}
+
+TEST_F(CBotUT, ClassFieldNaming)
+{
+    ExecuteTest(
+        "public class TestClass {\n"
+        "    int ~i = 1;\n"
+        "}\n",
+        CBotErrNoVar
+    );
+
+    ExecuteTest(
+        "public class TestClass {\n"
+        "    int TestClass = 1;\n"
+        "}\n",
+        CBotErrNoVar
+    );
+
+    ExecuteTest(
+        "public class TestClass {\n"
+        "    int i = 1;\n"
+        "    int i = 2;\n"
+        "}\n",
+        CBotErrRedefVar
+    );
 }
 
 TEST_F(CBotUT, ClassRedefinedInDifferentPrograms)

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