changeset 512:15ebf4aae2c4

Fixing closed numeric for loops with break statements in 5.4
author tehtmi
date Wed, 15 Nov 2023 14:41:25 -0800
parents 647a2c57229d
children c7e32264b0ee
files src/unluac/decompile/ControlFlowHandler.java src/unluac/decompile/block/ForBlock.java src/unluac/decompile/block/ForBlock51.java src/unluac/test/TestFiles.java test/src/close09.lua test/src/close10.lua test/src/close11.lua test/src/close12.lua
diffstat 8 files changed, 45 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/src/unluac/decompile/ControlFlowHandler.java	Sun Nov 05 03:12:52 2023 -0800
+++ b/src/unluac/decompile/ControlFlowHandler.java	Wed Nov 15 14:41:25 2023 -0800
@@ -527,17 +527,22 @@
           
           int A = code.A(line);
           int target = code.target(line);
+          int begin = line + 1;
+          int end = target + 1;
           
-          boolean forvarClose = false;
+          boolean forvarPreClose = false;
+          boolean forvarPostClose = false;
           int closeLine = target - 1;
           if(closeLine >= line + 1 && is_close(state, closeLine) && code.A(closeLine) == A + 3) {
-            forvarClose = true;
+            forvarPreClose = true;
             closeLine--;
+          } else if(end <= code.length && is_close(state, end) && code.A(end) == A + 3) {
+            forvarPostClose = true;
           }
           
           ForBlock block = new ForBlock51(
-            state.function, line + 1, target + 1, A,
-            get_close_type(state, closeLine), closeLine, forvarClose
+            state.function, begin, end, A,
+            get_close_type(state, closeLine), closeLine, forvarPreClose, forvarPostClose
           );
           
           block.handleVariableDeclarations(r);
--- a/src/unluac/decompile/block/ForBlock.java	Sun Nov 05 03:12:52 2023 -0800
+++ b/src/unluac/decompile/block/ForBlock.java	Wed Nov 15 14:41:25 2023 -0800
@@ -13,17 +13,17 @@
 abstract public class ForBlock extends ContainerBlock {
 
   protected final int register;
-  protected final boolean forvarClose;
+  protected final boolean forvarPreClose;
   
   protected Target target;
   protected Expression start;
   protected Expression stop;
   protected Expression step;
   
-  public ForBlock(LFunction function, int begin, int end, int register, CloseType closeType, int closeLine, boolean forvarClose) {
+  public ForBlock(LFunction function, int begin, int end, int register, CloseType closeType, int closeLine, boolean forvarPreClose) {
     super(function, begin, end, closeType, closeLine, -1);
     this.register = register;
-    this.forvarClose = forvarClose;
+    this.forvarPreClose = forvarPreClose;
   }
 
   abstract public void handleVariableDeclarations(Registers r);
@@ -42,7 +42,7 @@
   @Override
   public int scopeEnd() {
     int scopeEnd = end - 2;
-    if(forvarClose) scopeEnd--;
+    if(forvarPreClose) scopeEnd--;
     if(usingClose && (closeType == CloseType.CLOSE || closeType == CloseType.JMP)) scopeEnd--;
     return scopeEnd;
   }
--- a/src/unluac/decompile/block/ForBlock51.java	Sun Nov 05 03:12:52 2023 -0800
+++ b/src/unluac/decompile/block/ForBlock51.java	Wed Nov 15 14:41:25 2023 -0800
@@ -7,8 +7,11 @@
 
 public class ForBlock51 extends ForBlock {
 
-  public ForBlock51(LFunction function, int begin, int end, int register, CloseType closeType, int closeLine, boolean forvarClose) {
-    super(function, begin, end, register, closeType, closeLine, forvarClose);
+  protected boolean forvarPostClose;
+  
+  public ForBlock51(LFunction function, int begin, int end, int register, CloseType closeType, int closeLine, boolean forvarPreClose, boolean forvarPostClose) {
+    super(function, begin, end, register, closeType, closeLine, forvarPreClose);
+    this.forvarPostClose = forvarPostClose;
   }
 
   @Override
@@ -21,11 +24,13 @@
   
   @Override
   public void handleVariableDeclarations(Registers r) {
-    r.setInternalLoopVariable(register, begin - 2, end - 1);
-    r.setInternalLoopVariable(register + 1, begin - 2, end - 1);
-    r.setInternalLoopVariable(register + 2, begin - 2, end - 1);
+    int implicitEnd = end - 1;
+    if(forvarPostClose) implicitEnd++;
+    r.setInternalLoopVariable(register, begin - 2, implicitEnd);
+    r.setInternalLoopVariable(register + 1, begin - 2, implicitEnd);
+    r.setInternalLoopVariable(register + 2, begin - 2, implicitEnd);
     int explicitEnd = end - 2;
-    if(forvarClose && r.getVersion().closesemantics.get() != Version.CloseSemantics.LUA54) explicitEnd--;
+    if(forvarPreClose && r.getVersion().closesemantics.get() != Version.CloseSemantics.LUA54) explicitEnd--;
     r.setExplicitLoopVariable(register + 3, begin - 1, explicitEnd);
   }
   
--- a/src/unluac/test/TestFiles.java	Sun Nov 05 03:12:52 2023 -0800
+++ b/src/unluac/test/TestFiles.java	Wed Nov 15 14:41:25 2023 -0800
@@ -226,6 +226,10 @@
     new TestFile("close06"),
     new TestFile("close07"),
     new TestFile("close08"),
+    new TestFile("close09"),
+    new TestFile("close10"),
+    new TestFile("close11"),
+    new TestFile("close12"),
     new TestFile("always01"),
     new TestFile("always02"),
     new TestFile("always03"),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/src/close09.lua	Wed Nov 15 14:41:25 2023 -0800
@@ -0,0 +1,3 @@
+for i = 1, 100 do
+  table.insert(t, function() print(i) end)
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/src/close10.lua	Wed Nov 15 14:41:25 2023 -0800
@@ -0,0 +1,4 @@
+for i = 1, 100 do
+  local x = f(i)
+  table.insert(t, function() print(x) end)
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/src/close11.lua	Wed Nov 15 14:41:25 2023 -0800
@@ -0,0 +1,5 @@
+for i = 1, 100 do
+  local x = f(i)
+  table.insert(t, function() print(x) end)
+  break
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/src/close12.lua	Wed Nov 15 14:41:25 2023 -0800
@@ -0,0 +1,5 @@
+for k, v in iter() do
+  local x = f(k, v)
+  table.insert(t, function() print(x) end)
+  break
+end