Просмотр исходного кода

Fix string stack issue returning from a foreach statement.

Jeff Hutchinson 4 лет назад
Родитель
Сommit
f04aca9def
2 измененных файлов с 157 добавлено и 37 удалено
  1. 24 37
      Engine/source/console/compiledEval.cpp
  2. 133 0
      Engine/source/console/test/ScriptTest.cpp

+ 24 - 37
Engine/source/console/compiledEval.cpp

@@ -1257,9 +1257,9 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
             {
             {
                iterStack[--_ITER].mIsStringIter = false;
                iterStack[--_ITER].mIsStringIter = false;
                --iterDepth;
                --iterDepth;
-            }
 
 
-            _STK--; // this is a pop from foreach()
+               _STK--; // this is a pop from foreach()
+            }
          }
          }
 
 
          returnValue.setEmptyString();
          returnValue.setEmptyString();
@@ -1269,60 +1269,47 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
 
 
       case OP_RETURN:
       case OP_RETURN:
       {
       {
-         if (iterDepth > 0)
+         returnValue = std::move(stack[_STK]);
+         _STK--;
+
+         // Clear iterator state.
+         while (iterDepth > 0)
          {
          {
-            // Clear iterator state.
-            while (iterDepth > 0)
-            {
-               iterStack[--_ITER].mIsStringIter = false;
-               --iterDepth;
-            }
+            iterStack[--_ITER].mIsStringIter = false;
+            --iterDepth;
 
 
-            
-            const char* retVal = stack[_STK].getString();
-            _STK--;
             _STK--;
             _STK--;
-            stack[_STK + 1].setString(retVal);
-            _STK++; // Not nice but works.
          }
          }
 
 
-         returnValue = std::move(stack[_STK]);
-         _STK--;
-
          goto execFinished;
          goto execFinished;
       }
       }
       case OP_RETURN_FLT:
       case OP_RETURN_FLT:
+         returnValue.setFloat(stack[_STK].getFloat());
+         _STK--;
 
 
-         if (iterDepth > 0)
+         // Clear iterator state.
+         while (iterDepth > 0)
          {
          {
-            // Clear iterator state.
-            while (iterDepth > 0)
-            {
-               iterStack[--_ITER].mIsStringIter = false;
-               --iterDepth;
-            }
+            iterStack[--_ITER].mIsStringIter = false;
+            --iterDepth;
 
 
+            _STK--;
          }
          }
 
 
-         returnValue.setFloat(stack[_STK].getFloat());
-         _STK--;
-
          goto execFinished;
          goto execFinished;
 
 
       case OP_RETURN_UINT:
       case OP_RETURN_UINT:
+         returnValue.setInt(stack[_STK].getInt());
+         _STK--;
 
 
-         if (iterDepth > 0)
+         // Clear iterator state.
+         while (iterDepth > 0)
          {
          {
-            // Clear iterator state.
-            while (iterDepth > 0)
-            {
-               iterStack[--_ITER].mIsStringIter = false;
-               --iterDepth;
-            }
-         }
+            iterStack[--_ITER].mIsStringIter = false;
+            --iterDepth;
 
 
-         returnValue.setInt(stack[_STK].getInt());
-         _STK--;
+            _STK--;
+         }
 
 
          goto execFinished;
          goto execFinished;
 
 

+ 133 - 0
Engine/source/console/test/ScriptTest.cpp

@@ -405,6 +405,124 @@ TEST(Script, ForEachLoop)
    )");
    )");
 
 
    ASSERT_EQ(forEach4.getInt(), 5);
    ASSERT_EQ(forEach4.getInt(), 5);
+
+   ConsoleValue forEach5 = RunScript(R"(
+      function SimObject::ret1(%this)
+      {
+         return 1;
+      }
+
+      function SimSet::doForeach5(%this)
+      {
+         %count = 0;
+         foreach (%obj in %this)
+         {
+            %count += %obj.ret1();
+         }
+         return %count;
+      }
+
+      function a()
+      {
+         %set = new SimSet();
+         %set.add(new SimObject());
+         %set.add(new SimObject());
+         %set.add(new SimObject());
+
+         return %set.doForeach5();
+      }
+
+      return a();
+   )");
+
+   ASSERT_EQ(forEach5.getInt(), 3);
+
+   ConsoleValue forEachContinue = RunScript(R"(
+      function SimSet::foreach6(%this)
+      {
+         %count = 0;
+         foreach (%obj in %this)
+         {
+            if (%obj.getName() $= "A")
+               continue;
+
+             %count++;
+         }
+         return %count;
+      }
+
+      function a()
+      {
+         %set = new SimSet();
+         %set.add(new SimObject(A));
+         %set.add(new SimObject());
+         %set.add(new SimObject());
+
+         return %set.foreach6();
+      }
+
+      return a();
+   )");
+
+   ASSERT_EQ(forEachContinue.getInt(), 2);
+
+   ConsoleValue forEachReturn = RunScript(R"(
+      function SimSet::findA(%this)
+      {
+         foreach (%obj in %this)
+         {
+            if (%obj.getName() $= "A")
+               return 76;
+         }
+         return 0;
+      }
+
+      function a()
+      {
+         %set = new SimSet();
+         %set.add(new SimObject(A));
+         %set.add(new SimObject());
+         %set.add(new SimObject());
+
+         return %set.findA();
+      }
+
+      return a();
+   )");
+
+   ASSERT_EQ(forEachReturn.getInt(), 76);
+
+   ConsoleValue forEachNestedReturn = RunScript(R"(
+      function SimSet::findA(%this)
+      {
+         foreach (%obj in %this)
+         {
+            foreach (%innerObj in %this)
+            {
+               if (%innerObj.getName() $= "A")
+                  return 42;
+            }
+         }
+         return 0;
+      }
+
+      function a()
+      {
+         %set = new SimSet();
+         %set.add(new SimObject(A));
+         %set.add(new SimObject());
+         %set.add(new SimObject());
+
+         %group = new SimGroup();
+         %group.add(%set);
+
+         return %set.findA();
+      }
+
+      return a();
+   )");
+
+   ASSERT_EQ(forEachNestedReturn.getInt(), 42);
 }
 }
 
 
 TEST(Script, TorqueScript_Array_Testing)
 TEST(Script, TorqueScript_Array_Testing)
@@ -682,6 +800,21 @@ TEST(Script, Sugar_Syntax)
    )");
    )");
 
 
    ASSERT_EQ(valueSetArray.getInt(), 5);
    ASSERT_EQ(valueSetArray.getInt(), 5);
+
+   ConsoleValue valueStoreCalculated = RunScript(R"(
+      function a()
+      {
+         %extent = 10 SPC 20;
+         %scaling = 1;
+         %size = %extent.x * %scaling;
+         echo("%size = " @ %size @ " calculated = " @ (%extent.x * %scaling)); 
+         return %size;
+      }
+
+      return a();
+   )");
+
+   ASSERT_EQ(valueStoreCalculated.getInt(), 10);
 }
 }
 
 
 TEST(Script, InnerObjectTests)
 TEST(Script, InnerObjectTests)