Add a new test case for upvalues, and enhance upvalue handling so that

they pass.
This commit is contained in:
Ian Farmer
2007-07-09 04:10:25 +00:00
parent 45964d7e22
commit f7d6a49acb
6 changed files with 104 additions and 15 deletions

View File

@@ -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);
@@ -426,6 +427,29 @@ 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;
}

View File

@@ -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<p.nups; i++ )
upVals[i] = new UpVal( p.upvalues[i] );
}
// perform a lua call

View File

@@ -6,14 +6,35 @@ import lua.value.LValue;
public class UpVal {
private LString name;
public LValue value;
public LValue[] stack;
public int position;
public UpVal( LString string ) {
public UpVal( LString string, LValue[] stack, int i ) {
this.name = string;
this.stack = stack;
this.position = i;
}
public String toString() {
return "up."+name;
}
public LValue getValue() {
return stack[ position ];
}
public void setValue( LValue value ) {
stack[ position ] = value;
}
public boolean close( int limit ) {
if ( position >= limit ) {
final LValue v = stack[ position ];
stack = new LValue[] { v };
position = 0;
return true;
} else {
return false;
}
}
}

View File

@@ -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();

View File

@@ -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()

BIN
src/test/res/upvalues2.luac Normal file

Binary file not shown.