From f7d6a49acb5b5de221a21e48fb2d88a3ed9f0b75 Mon Sep 17 00:00:00 2001 From: Ian Farmer Date: Mon, 9 Jul 2007 04:10:25 +0000 Subject: [PATCH] Add a new test case for upvalues, and enhance upvalue handling so that they pass. --- src/main/java/lua/CallFrame.java | 42 +++++++++++++++++++++++------- src/main/java/lua/io/Closure.java | 2 -- src/main/java/lua/io/UpVal.java | 29 ++++++++++++++++++--- src/test/java/lua/LuaJTest.java | 4 +++ src/test/res/upvalues2.lua | 42 ++++++++++++++++++++++++++++++ src/test/res/upvalues2.luac | Bin 0 -> 1106 bytes 6 files changed, 104 insertions(+), 15 deletions(-) create mode 100644 src/test/res/upvalues2.lua create mode 100644 src/test/res/upvalues2.luac diff --git a/src/main/java/lua/CallFrame.java b/src/main/java/lua/CallFrame.java index 2c76b143..8f4f0858 100644 --- a/src/main/java/lua/CallFrame.java +++ b/src/main/java/lua/CallFrame.java @@ -5,6 +5,7 @@ package lua; import lua.io.Closure; import lua.io.Proto; +import lua.io.UpVal; import lua.value.LBoolean; import lua.value.LInteger; import lua.value.LNil; @@ -121,7 +122,7 @@ public class CallFrame { } case StackState.OP_GETUPVAL: { b = StackState.GETARG_B(i); - this.stack[base + a] = cl.upVals[b].value; + this.stack[base + a] = cl.upVals[b].getValue(); continue; } case StackState.OP_GETGLOBAL: { @@ -148,7 +149,7 @@ public class CallFrame { } case StackState.OP_SETUPVAL: { b = StackState.GETARG_B(i); - cl.upVals[b].value = this.stack[base + a]; + cl.upVals[b].setValue( this.stack[base + a] ); continue; } case StackState.OP_SETTABLE: { @@ -272,6 +273,8 @@ public class CallFrame { if (b != 0) // else use previous instruction set top top = base + a + b; + close( base ); // Close open upvals + // make or set up the call this.stack[base + a].luaStackCall(this, base + a, top, c - 1); @@ -298,6 +301,7 @@ public class CallFrame { b = StackState.GETARG_B(i); // number of return vals if (b != 0) // else use previous top top = base + a + b - 1; + close( base ); // close open upvals n = top - (base + a); // number to copy down System.arraycopy(this.stack, base + a, this.stack, base - 1, n); @@ -379,7 +383,7 @@ public class CallFrame { continue; } case StackState.OP_CLOSE: { - // for java, no need to do anything! + close( a ); // close upvals higher in the stack than position a continue; } case StackState.OP_CLOSURE: { @@ -391,12 +395,9 @@ public class CallFrame { o = StackState.GET_OPCODE(i); b = StackState.GETARG_B(i); if (o == StackState.OP_GETUPVAL) { - newClosure.upVals[j] = cl.upVals[b]; // TODO + newClosure.upVals[j] = cl.upVals[b]; } else if (o == StackState.OP_MOVE) { - newClosure.upVals[j].value = this.stack[base + b]; // TODO: - // what - // to do - // here? + newClosure.upVals[j] = findUpVal( proto.upvalues[j], base + b ); } else { throw new java.lang.IllegalArgumentException( "bad opcode: " + o); @@ -425,7 +426,30 @@ public class CallFrame { } } } - + + private UpVal findUpVal( LString upValName, int target ) { + UpVal up; + int i; + for ( i = this.state.upvals.size() - 1; i >= 0; --i ) { + up = (UpVal) this.state.upvals.elementAt( i ); + if ( up.stack == this.stack && up.position == target ) { + return up; + } else if ( up.position < target ) { + break; + } + } + + up = new UpVal( upValName, this.stack, target ); + this.state.upvals.insertElementAt( up, i + 1 ); + return up; + } + + private void close( int limit ) { + while ( !state.upvals.empty() && ( (UpVal) this.state.upvals.lastElement() ).close( limit ) ) { + this.state.upvals.pop(); + } + } + public void push(LValue value) { stack[top++] = value; } diff --git a/src/main/java/lua/io/Closure.java b/src/main/java/lua/io/Closure.java index 231fc06c..95bb76d5 100644 --- a/src/main/java/lua/io/Closure.java +++ b/src/main/java/lua/io/Closure.java @@ -13,8 +13,6 @@ public class Closure extends LFunction { this.env = state._G; this.p = p; upVals = new UpVal[p.nups]; - for ( int i=0; i= limit ) { + final LValue v = stack[ position ]; + stack = new LValue[] { v }; + position = 0; + return true; + } else { + return false; + } + } } diff --git a/src/test/java/lua/LuaJTest.java b/src/test/java/lua/LuaJTest.java index 2147ae5b..dcbb7957 100644 --- a/src/test/java/lua/LuaJTest.java +++ b/src/test/java/lua/LuaJTest.java @@ -47,6 +47,10 @@ public class LuaJTest extends TestCase { runTest( "upvalues" ); } + public void testUpvalues2() throws IOException, InterruptedException { + runTest( "upvalues2" ); + } + private void runTest( String testName ) throws IOException, InterruptedException { // add LuaJava bindings LuaJava.install(); diff --git a/src/test/res/upvalues2.lua b/src/test/res/upvalues2.lua new file mode 100644 index 00000000..f1c667d9 --- /dev/null +++ b/src/test/res/upvalues2.lua @@ -0,0 +1,42 @@ +-- The point of this test is that when an upvalue is created, it may +-- need to be inserted in the middle of the list, rather than always +-- appended at the end. Otherwise, it may not be found when it is +-- needed by another closure. + +local function test() + local x = 3 + local y = 5 + local z = 7 + + local function f() + print("y=", y) + end + + local function g() + print("z=", z) + end + + local function h() + print("x=", x) + end + + local function setter(x1, y1, z1) + x = x1 + y = y1 + z = z1 + end + + return f, g, h, setter +end + +local f, g, h, setter = test() + +h() +f() +g() + +setter("x", "y", "z") + +h() +f() +g() diff --git a/src/test/res/upvalues2.luac b/src/test/res/upvalues2.luac new file mode 100644 index 0000000000000000000000000000000000000000..41c4946306bb5530ce7c6abf5b9bfe09244ed575 GIT binary patch literal 1106 zcmb7C%TB{E5L_n#S{1~rh(}9>phCa_3GPVljRP0%y;PzPqzYASg4&!C#DNdtL+Foi z;zO9RW11p3bfekvIQH&(?aE!$x)&7$K|$6~bL%jdi)+7-h@d6KSY-wUC7Q`^N3}3Uu(l(g$4K0!; zB3~E_g4B@=rXEtm@;!q9+>95|yz%4~C<;L}R0N;VXdei_dlzfLpZd4GY;eXZ*JZ>;ngY*#l-9 z$5(K6Xu3Kt<9TVH68*$9HWr?B1z_qTz}6G&48g()rp)6I`ZxFx8OvtjQMWQ>vpE%; z!ky}v7vogdL~yESYNBG?Q9BIVLsK57Xe^Csk1`yCiIWU