Refactor call stack and its use throughout. CallFrame now does all bytecode processing, and the callframe is reinitialized anytime something might have changed, like a function call.
This commit is contained in:
@@ -3,7 +3,7 @@ package lua.addon.luajava;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import lua.StackState;
|
||||
import lua.CallFrame;
|
||||
import lua.addon.luajava.LuaJava.LInstance;
|
||||
import lua.value.LBoolean;
|
||||
import lua.value.LDouble;
|
||||
@@ -105,11 +105,11 @@ public class CoerceLuaToJava {
|
||||
return v;
|
||||
}
|
||||
|
||||
static Object[] coerceArgs(StackState state, int base, int nargs, Class[] parameterTypes) {
|
||||
static Object[] coerceArgs(CallFrame call, int base, int nargs, Class[] parameterTypes) {
|
||||
int n = parameterTypes.length;
|
||||
Object[] args = new Object[n];
|
||||
for ( int i=0; i<n && i<nargs; i++ )
|
||||
args[i] = coerceArg( state.stack[base+i], parameterTypes[i] );
|
||||
args[i] = coerceArg( call.stack[base+i], parameterTypes[i] );
|
||||
return args;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import lua.CallFrame;
|
||||
import lua.GlobalState;
|
||||
import lua.StackState;
|
||||
import lua.value.LFunction;
|
||||
import lua.value.LString;
|
||||
import lua.value.LTable;
|
||||
@@ -21,8 +21,8 @@ public final class LuaJava extends LFunction {
|
||||
public static void install() {
|
||||
LTable luajava = new LTable();
|
||||
for ( int i=0; i<NAMES.length; i++ )
|
||||
luajava.m_hash.put( new LString( NAMES[i] ), new LuaJava(i) );
|
||||
GlobalState.getGlobalsTable().m_hash.put( new LString( "luajava" ), luajava );
|
||||
luajava.put( NAMES[i], new LuaJava(i) );
|
||||
GlobalState.getGlobalsTable().put( "luajava", luajava );
|
||||
}
|
||||
|
||||
private static final int NEWINSTANCE = 0;
|
||||
@@ -48,21 +48,21 @@ public final class LuaJava extends LFunction {
|
||||
}
|
||||
|
||||
// perform a lua call
|
||||
public void luaStackCall(StackState state, int base, int top, int nresults) {
|
||||
public void luaStackCall(CallFrame call, int base, int top, int nresults) {
|
||||
String className;
|
||||
switch ( id ) {
|
||||
case BINDCLASS:
|
||||
className = state.stack[base+1].luaAsString();
|
||||
className = call.stack[base+1].luaAsString();
|
||||
try {
|
||||
Class clazz = Class.forName(className);
|
||||
state.stack[base] = new LInstance( clazz, clazz );
|
||||
state.top = base+1;
|
||||
call.stack[base] = new LInstance( clazz, clazz );
|
||||
call.top = base+1;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
break;
|
||||
case NEWINSTANCE:
|
||||
className = state.stack[base+1].luaAsString();
|
||||
className = call.stack[base+1].luaAsString();
|
||||
try {
|
||||
Class clazz = Class.forName(className);
|
||||
Constructor[] cons = clazz.getConstructors();
|
||||
@@ -70,21 +70,21 @@ public final class LuaJava extends LFunction {
|
||||
Class[] paramTypes = con.getParameterTypes();
|
||||
int paramsBase = base + 2;
|
||||
int nargs = top - paramsBase;
|
||||
int score = CoerceLuaToJava.scoreParamTypes( state.stack, paramsBase, nargs, paramTypes );
|
||||
int score = CoerceLuaToJava.scoreParamTypes( call.stack, paramsBase, nargs, paramTypes );
|
||||
for ( int i=1; i<cons.length; i++ ) {
|
||||
Constructor c = cons[i];
|
||||
Class[] p = c.getParameterTypes();
|
||||
int s = CoerceLuaToJava.scoreParamTypes( state.stack, paramsBase, nargs, p );
|
||||
int s = CoerceLuaToJava.scoreParamTypes( call.stack, paramsBase, nargs, p );
|
||||
if ( s < score ) {
|
||||
con = c;
|
||||
paramTypes = p;
|
||||
score = s;
|
||||
}
|
||||
}
|
||||
Object[] args = CoerceLuaToJava.coerceArgs( state, paramsBase, nargs, paramTypes );
|
||||
Object[] args = CoerceLuaToJava.coerceArgs( call, paramsBase, nargs, paramTypes );
|
||||
Object o = con.newInstance( args );
|
||||
state.stack[base] = new LInstance( o, clazz );
|
||||
state.top = base+1;
|
||||
call.stack[base] = new LInstance( o, clazz );
|
||||
call.top = base+1;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -93,10 +93,10 @@ public final class LuaJava extends LFunction {
|
||||
luaUnsupportedOperation();
|
||||
}
|
||||
if (nresults >= 0)
|
||||
state.adjustTop(base + nresults);
|
||||
call.adjustTop(base + nresults);
|
||||
}
|
||||
|
||||
static class LInstance extends LValue {
|
||||
public static class LInstance extends LValue {
|
||||
Object instance;
|
||||
private Class clazz;
|
||||
public LInstance(Object o, Class clazz) {
|
||||
@@ -106,29 +106,29 @@ public final class LuaJava extends LFunction {
|
||||
public String luaAsString() {
|
||||
return instance.toString();
|
||||
}
|
||||
public void luaGetTable(StackState state, int base, LValue table, LValue key) {
|
||||
public void luaGetTable(CallFrame call, int base, LValue table, LValue key) {
|
||||
final String s = key.luaAsString();
|
||||
try {
|
||||
Field f = clazz.getField(s);
|
||||
Object o = f.get(instance);
|
||||
LValue v = CoerceJavaToLua.coerce( o );
|
||||
state.stack[base] = v;
|
||||
state.top = base + 1;
|
||||
call.stack[base] = v;
|
||||
call.top = base + 1;
|
||||
} catch (NoSuchFieldException nsfe) {
|
||||
state.stack[base] = new LMethod(instance,clazz,s);
|
||||
state.top = base + 1;
|
||||
call.stack[base] = new LMethod(instance,clazz,s);
|
||||
call.top = base + 1;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
public void luaSetTable(StackState state, int base, LValue table, LValue key, LValue val) {
|
||||
public void luaSetTable(CallFrame call, int base, LValue table, LValue key, LValue val) {
|
||||
Class c = instance.getClass();
|
||||
String s = key.luaAsString();
|
||||
try {
|
||||
Field f = c.getField(s);
|
||||
Object v = CoerceLuaToJava.coerceArg(val, f.getType());
|
||||
f.set(instance,v);
|
||||
state.top = base;
|
||||
call.top = base;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -148,7 +148,7 @@ public final class LuaJava extends LFunction {
|
||||
public String toString() {
|
||||
return clazz.getName()+"."+s+"()";
|
||||
}
|
||||
public void luaStackCall(StackState state, int base, int top, int nresults) {
|
||||
public void luaStackCall(CallFrame call, int base, int top, int nresults) {
|
||||
try {
|
||||
Method[] meths = clazz.getMethods();
|
||||
Method meth = null;
|
||||
@@ -161,7 +161,7 @@ public final class LuaJava extends LFunction {
|
||||
String name = m.getName();
|
||||
if ( s.equals(name) ) {
|
||||
Class[] p = m.getParameterTypes();
|
||||
int s = CoerceLuaToJava.scoreParamTypes( state.stack, paramsBase, nargs, p );
|
||||
int s = CoerceLuaToJava.scoreParamTypes( call.stack, paramsBase, nargs, p );
|
||||
if ( s < score ) {
|
||||
meth = m;
|
||||
paramTypes = p;
|
||||
@@ -169,11 +169,11 @@ public final class LuaJava extends LFunction {
|
||||
}
|
||||
}
|
||||
}
|
||||
Object[] args = CoerceLuaToJava.coerceArgs( state, paramsBase, nargs, paramTypes );
|
||||
Object[] args = CoerceLuaToJava.coerceArgs( call, paramsBase, nargs, paramTypes );
|
||||
Object result = meth.invoke( instance, args );
|
||||
state.stack[base] = CoerceJavaToLua.coerce(result);
|
||||
state.top = base + 1;
|
||||
state.adjustTop(base+nresults);
|
||||
call.stack[base] = CoerceJavaToLua.coerce(result);
|
||||
call.top = base + 1;
|
||||
call.adjustTop(base+nresults);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ final class Builtin extends LFunction {
|
||||
|
||||
static void addBuiltins(LTable table) {
|
||||
for ( int i=0; i<NAMES.length; i++ )
|
||||
table.m_hash.put( new LString( NAMES[i] ), new Builtin(i) );
|
||||
table.put( NAMES[i], new Builtin(i) );
|
||||
}
|
||||
|
||||
private static final int PRINT = 0;
|
||||
@@ -32,35 +32,35 @@ final class Builtin extends LFunction {
|
||||
}
|
||||
|
||||
// perform a lua call
|
||||
public void luaStackCall(StackState state, int base, int top, int nresults) {
|
||||
public void luaStackCall(CallFrame call, int base, int top, int nresults) {
|
||||
switch ( id ) {
|
||||
case PRINT:
|
||||
for ( int i=base+1; i<top; i++ ) {
|
||||
System.out.print( state.stack[i].luaAsString() );
|
||||
System.out.print( call.stack[i].luaAsString() );
|
||||
System.out.print( "\t" );
|
||||
}
|
||||
System.out.println();
|
||||
state.top = base;
|
||||
call.top = base;
|
||||
break;
|
||||
case PAIRS:
|
||||
LValue value = state.stack[base+1].luaPairs();
|
||||
state.stack[base] = value;
|
||||
state.top = base+1;
|
||||
LValue value = call.stack[base+1].luaPairs();
|
||||
call.stack[base] = value;
|
||||
call.top = base+1;
|
||||
break;
|
||||
case GETMETATABLE:
|
||||
state.stack[base] = state.stack[base+1].luaGetMetatable();
|
||||
state.top = base+1;
|
||||
call.stack[base] = call.stack[base+1].luaGetMetatable();
|
||||
call.top = base+1;
|
||||
break;
|
||||
case SETMETATABLE:
|
||||
state.stack[base+1].luaSetMetatable(state.stack[base+2]);
|
||||
state.stack[base] = state.stack[base+1];
|
||||
state.top = base+1;
|
||||
call.stack[base+1].luaSetMetatable(call.stack[base+2]);
|
||||
call.stack[base] = call.stack[base+1];
|
||||
call.top = base+1;
|
||||
break;
|
||||
default:
|
||||
luaUnsupportedOperation();
|
||||
}
|
||||
if (nresults >= 0)
|
||||
state.adjustTop(base + nresults);
|
||||
call.adjustTop(base + nresults);
|
||||
}
|
||||
|
||||
}
|
||||
431
src/main/java/lua/CallFrame.java
Normal file
431
src/main/java/lua/CallFrame.java
Normal file
@@ -0,0 +1,431 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package lua;
|
||||
|
||||
import lua.io.Closure;
|
||||
import lua.io.Proto;
|
||||
import lua.value.LBoolean;
|
||||
import lua.value.LInteger;
|
||||
import lua.value.LNil;
|
||||
import lua.value.LString;
|
||||
import lua.value.LTable;
|
||||
import lua.value.LValue;
|
||||
|
||||
public class CallFrame {
|
||||
private final static boolean DEBUG = false;
|
||||
|
||||
public final StackState state;
|
||||
public final LValue[] stack;
|
||||
public int base;
|
||||
public int top;
|
||||
private final Closure cl;
|
||||
private final Proto p;
|
||||
private final LValue[] k;
|
||||
private final int nresults;
|
||||
private int pc = 0;
|
||||
boolean done = false;
|
||||
|
||||
CallFrame(StackState state, Closure c, int base, int nargs, int nresults) {
|
||||
this.state = state;
|
||||
this.stack = state.stack;
|
||||
this.cl = c;
|
||||
this.p = c.p;
|
||||
this.k = p.k;
|
||||
this.base = base;
|
||||
this.nresults = nresults;
|
||||
int nparams = p.numparams;
|
||||
int nvalues = (p.is_vararg && nargs > nparams ? nargs : nparams);
|
||||
for (int i = nargs; i < nvalues; i++)
|
||||
this.state.stack[base + i] = LNil.NIL;
|
||||
this.top = base + nvalues;
|
||||
this.state.calls[++this.state.cc] = this;
|
||||
this.state.avail = base + p.maxstacksize;
|
||||
}
|
||||
|
||||
private LValue RKBC(int bc) {
|
||||
return StackState.ISK(bc) ? k[StackState.INDEXK(bc)]
|
||||
: this.state.stack[base + bc];
|
||||
}
|
||||
|
||||
private LValue GETARG_RKB(int i) {
|
||||
return RKBC(StackState.GETARG_B(i));
|
||||
}
|
||||
|
||||
private LValue GETARG_RKC(int i) {
|
||||
return RKBC(StackState.GETARG_C(i));
|
||||
}
|
||||
|
||||
public void adjustTop(int newTop) {
|
||||
while (top < newTop)
|
||||
this.stack[top++] = LNil.NIL;
|
||||
top = newTop;
|
||||
}
|
||||
|
||||
public void exec() {
|
||||
int i, a, b, c, o, n, cb;
|
||||
LValue rkb, rkc, nvarargs, key, val;
|
||||
StringBuffer sb;
|
||||
LValue i0, step, idx, limit, init, table;
|
||||
boolean back, body;
|
||||
Proto proto;
|
||||
Closure newClosure;
|
||||
|
||||
// reload the current calling context
|
||||
int[] code = p.code;
|
||||
state.avail = base + p.maxstacksize;
|
||||
while (true) {
|
||||
|
||||
if (DEBUG)
|
||||
Print.printState(state, base, top, state.avail, cl, pc);
|
||||
|
||||
i = code[pc++];
|
||||
|
||||
// TODO: implement debug hooks
|
||||
// if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
|
||||
// (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
|
||||
// traceexec(L, pc);
|
||||
// if (L->status == LUA_YIELD) { // did hook yield?
|
||||
// L->savedpc = pc - 1;
|
||||
// return;
|
||||
// }
|
||||
// base = L->base;
|
||||
// }
|
||||
|
||||
a = StackState.GETARG_A(i);
|
||||
switch (StackState.GET_OPCODE(i)) {
|
||||
case StackState.OP_MOVE: {
|
||||
b = StackState.GETARG_B(i);
|
||||
this.stack[base + a] = this.stack[base + b];
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_LOADK: {
|
||||
b = StackState.GETARG_Bx(i);
|
||||
this.stack[base + a] = k[b];
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_LOADBOOL: {
|
||||
b = StackState.GETARG_B(i);
|
||||
c = StackState.GETARG_C(i);
|
||||
this.stack[base + a] = (b != 0 ? LBoolean.TRUE
|
||||
: LBoolean.FALSE);
|
||||
if (c != 0)
|
||||
pc++; /* skip next instruction (if C) */
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_LOADNIL: {
|
||||
b = StackState.GETARG_B(i);
|
||||
do {
|
||||
this.stack[base + b] = LNil.NIL;
|
||||
} while ((--b) >= a);
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_GETUPVAL: {
|
||||
b = StackState.GETARG_B(i);
|
||||
this.stack[base + a] = cl.upVals[b].value;
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_GETGLOBAL: {
|
||||
b = StackState.GETARG_Bx(i);
|
||||
key = k[b];
|
||||
table = cl.env;
|
||||
table.luaGetTable(this, base + a, table, key);
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_GETTABLE: {
|
||||
b = StackState.GETARG_B(i);
|
||||
key = GETARG_RKC(i);
|
||||
table = this.stack[base + b];
|
||||
table.luaGetTable(this, base + a, table, key);
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_SETGLOBAL: {
|
||||
b = StackState.GETARG_Bx(i);
|
||||
key = k[b];
|
||||
val = this.stack[base + a];
|
||||
table = cl.env;
|
||||
table.luaSetTable(this, this.state.avail, table, key, val);
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_SETUPVAL: {
|
||||
b = StackState.GETARG_B(i);
|
||||
cl.upVals[b].value = this.stack[base + a];
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_SETTABLE: {
|
||||
key = GETARG_RKB(i);
|
||||
val = GETARG_RKC(i);
|
||||
table = this.stack[base + a];
|
||||
table.luaSetTable(this, state.avail, table, key, val);
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_NEWTABLE: {
|
||||
b = StackState.GETARG_B(i);
|
||||
c = StackState.GETARG_C(i);
|
||||
this.stack[base + a] = new LTable(b, c);
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_SELF: {
|
||||
rkb = GETARG_RKB(i);
|
||||
rkc = GETARG_RKC(i);
|
||||
this.stack[base + a + 1] = rkb;
|
||||
rkb.luaGetTable(this, base + a, rkb, rkc);
|
||||
// StkId rb = RB(i);
|
||||
// setobjs2s(L, ra+1, rb);
|
||||
// Protect(luaV_gettable(L, rb, RKC(i), ra));
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_ADD:
|
||||
case StackState.OP_SUB:
|
||||
case StackState.OP_MUL:
|
||||
case StackState.OP_DIV:
|
||||
case StackState.OP_MOD:
|
||||
case StackState.OP_POW: {
|
||||
o = StackState.GET_OPCODE(i);
|
||||
rkb = GETARG_RKB(i);
|
||||
rkc = GETARG_RKC(i);
|
||||
this.stack[base + a] = rkc.luaBinOpUnknown(o, rkb);
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_UNM: {
|
||||
rkb = GETARG_RKB(i);
|
||||
this.stack[base + a] = rkb.luaUnaryMinus();
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_NOT: {
|
||||
rkb = GETARG_RKB(i);
|
||||
this.stack[base + a] = (rkb.luaAsBoolean() ? LBoolean.TRUE
|
||||
: LBoolean.FALSE);
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_LEN: {
|
||||
rkb = GETARG_RKB(i);
|
||||
this.stack[base + a] = rkb.luaLength();
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_CONCAT: {
|
||||
b = StackState.GETARG_B(i);
|
||||
c = StackState.GETARG_C(i);
|
||||
sb = new StringBuffer();
|
||||
for (int j = b; j <= c; j++)
|
||||
sb.append(this.stack[base + j].luaAsString());
|
||||
this.stack[base + a] = new LString(sb.toString());
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_JMP: {
|
||||
pc += StackState.GETARG_sBx(i);
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_EQ:
|
||||
case StackState.OP_LT:
|
||||
case StackState.OP_LE: {
|
||||
o = StackState.GET_OPCODE(i);
|
||||
rkb = GETARG_RKB(i);
|
||||
rkc = GETARG_RKC(i);
|
||||
boolean test = rkc.luaBinCmpUnknown(o, rkb);
|
||||
if (test)
|
||||
pc++;
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_TEST: {
|
||||
c = StackState.GETARG_C(i);
|
||||
if (this.stack[base + a].luaAsBoolean() != (c != 0))
|
||||
pc++;
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_TESTSET: {
|
||||
rkb = GETARG_RKB(i);
|
||||
c = StackState.GETARG_C(i);
|
||||
if (rkb.luaAsBoolean() != (c != 0))
|
||||
pc++;
|
||||
else
|
||||
this.stack[base + a] = rkb;
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_CALL: {
|
||||
/* ra is start of result location */
|
||||
b = StackState.GETARG_B(i); // number of stack spaces to reserve
|
||||
// for
|
||||
// closure plus args
|
||||
c = StackState.GETARG_C(i); // num results plus 1
|
||||
if (b != 0) // else use previous instruction set top
|
||||
top = base + a + b;
|
||||
|
||||
// make or set up the call
|
||||
this.stack[base + a].luaStackCall(this, base + a, top, c - 1);
|
||||
|
||||
// force re-entry into current call
|
||||
if (this.state.calls[this.state.cc] != this)
|
||||
return;
|
||||
|
||||
// adjustTop only for case when call was completed
|
||||
if (c > 0)
|
||||
adjustTop(base + a + c - 1);
|
||||
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_TAILCALL: {
|
||||
b = StackState.GETARG_B(i); // number of stack spaces to reserve
|
||||
// for
|
||||
// closure plus args ??
|
||||
c = StackState.GETARG_C(i); // number of return args - must be
|
||||
// LUA_MULTRET
|
||||
if (b != 0) // else use previous instruction set top
|
||||
top = base + a + b;
|
||||
|
||||
// make or set up the call
|
||||
this.stack[base + a].luaStackCall(this, base + a, top, c - 1);
|
||||
|
||||
// adjustTop only for case when call was completed
|
||||
if (this.state.calls[this.state.cc] != this) {
|
||||
// was a vm call, or a Java call that re-entered the stack.
|
||||
// copy down the stack variables and substitute the stack
|
||||
// frame.
|
||||
CallFrame ci = this.state.calls[this.state.cc];
|
||||
n = ci.top - ci.base;
|
||||
System.arraycopy(this.stack, ci.base,
|
||||
this.stack, base, n);
|
||||
ci.base = base;
|
||||
ci.top = base + n;
|
||||
this.state.calls[this.state.cc - 1] = this.state.calls[this.state.cc];
|
||||
--this.state.cc;
|
||||
|
||||
// force a reset of the calling context state
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_RETURN: {
|
||||
b = StackState.GETARG_B(i); // number of return vals
|
||||
if (b != 0) // else use previous top
|
||||
top = base + a + b - 1;
|
||||
n = top - (base + a); // number to copy down
|
||||
System.arraycopy(this.stack, base + a, this.stack,
|
||||
base - 1, n);
|
||||
top = base - 1 + n;
|
||||
|
||||
// adjust results to what caller expected
|
||||
if (nresults >= 0)
|
||||
adjustTop(base + nresults);
|
||||
|
||||
// pop the call stack
|
||||
done = true;
|
||||
if ( --state.cc >= 0 )
|
||||
state.calls[state.cc].top = top;
|
||||
|
||||
// force a reload of the calling context
|
||||
return;
|
||||
}
|
||||
case StackState.OP_FORLOOP: {
|
||||
i0 = this.stack[base + a];
|
||||
step = this.stack[base + a + 2];
|
||||
idx = step.luaBinOpUnknown(Lua.OP_ADD, i0);
|
||||
limit = this.stack[base + a + 1];
|
||||
back = step.luaBinCmpInteger(Lua.OP_LT, 0);
|
||||
body = (back ? idx.luaBinCmpUnknown(Lua.OP_LE, limit) : limit
|
||||
.luaBinCmpUnknown(Lua.OP_LE, idx));
|
||||
if (body) {
|
||||
this.stack[base + a] = idx;
|
||||
this.stack[base + a + 3] = idx;
|
||||
pc += StackState.GETARG_sBx(i);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_FORPREP: {
|
||||
init = this.stack[base + a];
|
||||
step = this.stack[base + a + 2];
|
||||
this.stack[base + a] = step.luaBinOpUnknown(Lua.OP_SUB,
|
||||
init);
|
||||
b = StackState.GETARG_sBx(i);
|
||||
pc += b;
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_TFORLOOP: {
|
||||
cb = a + 3; /* call base */
|
||||
System.arraycopy(this.stack, base + a, this.stack,
|
||||
base + cb, 3);
|
||||
top = base + cb + 3; /* func. + 2 args (state and index) */
|
||||
|
||||
// call the iterator
|
||||
c = StackState.GETARG_C(i);
|
||||
this.stack[base + a].luaStackCall(this, base + cb, top, c - 1);
|
||||
|
||||
// test for continuation
|
||||
if (this.stack[base + cb] != LNil.NIL) { // continue?
|
||||
this.stack[base + cb - 1] = this.stack[base
|
||||
+ cb]; // save control variable
|
||||
} else {
|
||||
pc++; // skip over jump
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_SETLIST: {
|
||||
b = StackState.GETARG_B(i);
|
||||
c = StackState.GETARG_C(i);
|
||||
if (b == 0) {
|
||||
b = top - 1;
|
||||
}
|
||||
if (c == 0) {
|
||||
c = code[pc++];
|
||||
}
|
||||
table = this.stack[base + a];
|
||||
for (int index = 1; index <= b; index++) {
|
||||
val = this.stack[base + a + index];
|
||||
table.luaSetTable(this, this.state.avail, table,
|
||||
new LInteger(index), val);
|
||||
}
|
||||
top = base + a - 1;
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_CLOSE: {
|
||||
// for java, no need to do anything!
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_CLOSURE: {
|
||||
b = StackState.GETARG_Bx(i);
|
||||
proto = cl.p.p[b];
|
||||
newClosure = new Closure(this.state, proto);
|
||||
for (int j = 0; j < newClosure.upVals.length; j++, pc++) {
|
||||
i = code[pc];
|
||||
o = StackState.GET_OPCODE(i);
|
||||
b = StackState.GETARG_B(i);
|
||||
if (o == StackState.OP_GETUPVAL) {
|
||||
newClosure.upVals[j] = cl.upVals[b]; // TODO
|
||||
} else if (o == StackState.OP_MOVE) {
|
||||
newClosure.upVals[j].value = this.stack[base + b]; // TODO:
|
||||
// what
|
||||
// to do
|
||||
// here?
|
||||
} else {
|
||||
throw new java.lang.IllegalArgumentException(
|
||||
"bad opcode: " + o);
|
||||
}
|
||||
}
|
||||
this.stack[base + a] = newClosure;
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_VARARG: {
|
||||
// figure out how many args to copy
|
||||
b = StackState.GETARG_B(i) - 1;
|
||||
nvarargs = this.stack[base - 1];
|
||||
n = nvarargs.luaAsInt();
|
||||
if (b == StackState.LUA_MULTRET) {
|
||||
b = n; // use entire varargs supplied
|
||||
}
|
||||
|
||||
// copy args up to call stack area
|
||||
for (int j = 0; j < b; j++)
|
||||
this.stack[base + a + j] = (j < n ? this.stack[base
|
||||
- n + j - 1]
|
||||
: LNil.NIL);
|
||||
top = base + a + b;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void push(LValue value) {
|
||||
stack[top++] = value;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package lua;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import lua.value.LString;
|
||||
import lua.value.LTable;
|
||||
|
||||
/**
|
||||
@@ -11,27 +10,10 @@ import lua.value.LTable;
|
||||
public class GlobalState {
|
||||
|
||||
// typedef struct global_State {
|
||||
// stringtable strt; /* hash table for strings */
|
||||
Hashtable strt; /* hash table for strings */
|
||||
// lua_Alloc frealloc; /* function to reallocate memory */
|
||||
// void *ud; /* auxiliary data to `frealloc' */
|
||||
// lu_byte currentwhite;
|
||||
// lu_byte gcstate; /* state of garbage collector */
|
||||
// int sweepstrgc; /* position of sweep in `strt' */
|
||||
// GCObject *rootgc; /* list of all collectable objects */
|
||||
// GCObject **sweepgc; /* position of sweep in `rootgc' */
|
||||
// GCObject *gray; /* list of gray objects */
|
||||
// GCObject *grayagain; /* list of objects to be traversed atomically */
|
||||
// GCObject *weak; /* list of weak tables (to be cleared) */
|
||||
// GCObject *tmudata; /* last element of list of userdata to be GC */
|
||||
// Mbuffer buff; /* temporary buffer for string concatentation */
|
||||
StringBuffer buff; /* temporary buffer for string concatentation */
|
||||
// lu_mem GCthreshold;
|
||||
// lu_mem totalbytes; /* number of bytes currently allocated */
|
||||
// lu_mem estimate; /* an estimate of number of bytes actually in use */
|
||||
// lu_mem gcdept; /* how much GC is `behind schedule' */
|
||||
// int gcpause; /* size of pause between successive GCs */
|
||||
// int gcstepmul; /* GC `granularity' */
|
||||
// lua_CFunction panic; /* to be called in unprotected errors */
|
||||
// TValue l_registry;
|
||||
// struct lua_State *mainthread;
|
||||
@@ -45,8 +27,8 @@ public class GlobalState {
|
||||
|
||||
static {
|
||||
_G = new LTable();
|
||||
_G .put( "_G", _G );
|
||||
Builtin.addBuiltins( _G );
|
||||
_G .m_hash.put(new LString("_G"), _G );
|
||||
}
|
||||
|
||||
public static LTable getGlobalsTable() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package lua.io;
|
||||
|
||||
import lua.CallFrame;
|
||||
import lua.StackState;
|
||||
import lua.value.LFunction;
|
||||
import lua.value.LValue;
|
||||
@@ -9,7 +10,7 @@ public class Closure extends LFunction {
|
||||
public Proto p;
|
||||
public UpVal[] upVals;
|
||||
public Closure(StackState state, Proto p) {
|
||||
this.env = state.gt();
|
||||
this.env = state._G;
|
||||
this.p = p;
|
||||
upVals = new UpVal[p.nups];
|
||||
for ( int i=0; i<p.nups; i++ )
|
||||
@@ -17,7 +18,7 @@ public class Closure extends LFunction {
|
||||
}
|
||||
|
||||
// perform a lua call
|
||||
public void luaStackCall(StackState state, int base, int top, int nresults) {
|
||||
state.setupCall( this, base, top );
|
||||
public void luaStackCall(CallFrame call, int base, int top, int nresults) {
|
||||
call.state.stackCall( this, base, top, nresults );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ import lua.value.LDouble;
|
||||
import lua.value.LInteger;
|
||||
import lua.value.LNil;
|
||||
import lua.value.LNumber;
|
||||
import lua.value.LValue;
|
||||
import lua.value.LString;
|
||||
import lua.value.LValue;
|
||||
|
||||
/*
|
||||
** Function Prototypes
|
||||
@@ -350,7 +350,7 @@ public class LoadState {
|
||||
// }
|
||||
public Proto loadFunction(LString p) throws IOException {
|
||||
Proto f = new Proto(this.L);
|
||||
this.L.push(f);
|
||||
// this.L.push(f);
|
||||
f.source = loadString();
|
||||
f.linedefined = loadInt();
|
||||
f.lastlinedefined = loadInt();
|
||||
@@ -366,7 +366,7 @@ public class LoadState {
|
||||
// see ldebug.c
|
||||
// IF (!luaG_checkcode(f), "bad code");
|
||||
|
||||
this.L.pop();
|
||||
// this.L.pop();
|
||||
return f;
|
||||
}
|
||||
//
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package lua.io;
|
||||
|
||||
import lua.value.LNil;
|
||||
import lua.value.LString;
|
||||
import lua.value.LValue;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package lua.value;
|
||||
|
||||
import lua.StackState;
|
||||
import lua.CallFrame;
|
||||
|
||||
|
||||
public class LFunction extends LValue {
|
||||
|
||||
@@ -8,21 +9,21 @@ public class LFunction extends LValue {
|
||||
return "function: "+hashCode();
|
||||
}
|
||||
|
||||
public void luaSetTable(StackState state, int base, LValue table, LValue key, LValue val) {
|
||||
state.top = base;
|
||||
state.push( this );
|
||||
state.push( table );
|
||||
state.push( key );
|
||||
state.push( val );
|
||||
this.luaStackCall(state, base, state.top, 1);
|
||||
public void luaSetTable(CallFrame call, int base, LValue table, LValue key, LValue val) {
|
||||
call.top = base;
|
||||
call.push( this );
|
||||
call.push( table );
|
||||
call.push( key );
|
||||
call.push( val );
|
||||
this.luaStackCall(call, base, call.top, 1);
|
||||
}
|
||||
|
||||
public void luaGetTable(StackState state, int base, LValue table, LValue key) {
|
||||
state.top = base;
|
||||
state.push( this );
|
||||
state.push( table );
|
||||
state.push( key );
|
||||
this.luaStackCall(state, base, state.top, 1);
|
||||
public void luaGetTable(CallFrame call, int base, LValue table, LValue key) {
|
||||
call.top = base;
|
||||
call.push( this );
|
||||
call.push( table );
|
||||
call.push( key );
|
||||
this.luaStackCall(call, base, call.top, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package lua.value;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import lua.StackState;
|
||||
import lua.CallFrame;
|
||||
|
||||
public class LTable extends LValue {
|
||||
|
||||
@@ -13,7 +13,7 @@ public class LTable extends LValue {
|
||||
/** Metatable tag for intercepting table sets */
|
||||
private static final LString TM_NEWINDEX = new LString("__newindex");
|
||||
|
||||
public Hashtable m_hash = new Hashtable();
|
||||
private Hashtable m_hash = new Hashtable();
|
||||
private LTable m_metatable;
|
||||
|
||||
public LTable() {
|
||||
@@ -22,12 +22,17 @@ public class LTable extends LValue {
|
||||
public LTable(int narray, int nhash) {
|
||||
}
|
||||
|
||||
public void luaSetTable(StackState state, int base, LValue table, LValue key, LValue val) {
|
||||
/** Utility method for putting a value directly, typically for initializing a table */
|
||||
public void put(String key, LValue value) {
|
||||
m_hash.put( new LString(key), value );
|
||||
}
|
||||
|
||||
public void luaSetTable(CallFrame call, int base, LValue table, LValue key, LValue val) {
|
||||
if ( m_metatable != null ) {
|
||||
if ( ! m_hash.containsKey(key) ) {
|
||||
LValue event = (LValue) m_metatable.m_hash.get( TM_NEWINDEX );
|
||||
if ( event != null && event != LNil.NIL ) {
|
||||
event.luaSetTable( state, base, table, key, val );
|
||||
event.luaSetTable( call, base, table, key, val );
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -35,19 +40,19 @@ public class LTable extends LValue {
|
||||
m_hash.put( key, val );
|
||||
}
|
||||
|
||||
public void luaGetTable(StackState state, int base, LValue table, LValue key) {
|
||||
public void luaGetTable(CallFrame call, int base, LValue table, LValue key) {
|
||||
LValue val = (LValue) m_hash.get(key);
|
||||
if ( val == null || val == LNil.NIL ) {
|
||||
if ( m_metatable != null ) {
|
||||
LValue event = (LValue) m_metatable.m_hash.get( TM_INDEX );
|
||||
if ( event != null && event != LNil.NIL ) {
|
||||
event.luaGetTable( state, base, table, key );
|
||||
event.luaGetTable( call, base, table, key );
|
||||
return;
|
||||
}
|
||||
}
|
||||
val = LNil.NIL;
|
||||
}
|
||||
state.stack[base] = val;
|
||||
call.stack[base] = val;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@@ -90,19 +95,19 @@ public class LTable extends LValue {
|
||||
}
|
||||
|
||||
// perform a lua call
|
||||
public void luaStackCall(StackState state, int base, int top, int nresults) {
|
||||
public void luaStackCall(CallFrame call, int base, int top, int nresults) {
|
||||
if ( e.hasMoreElements() ) {
|
||||
LValue key = (LValue) e.nextElement();
|
||||
LValue val = (LValue) t.m_hash.get(key);
|
||||
state.stack[base] = key;
|
||||
state.stack[base+1] = val;
|
||||
state.top = base+2;
|
||||
call.stack[base] = key;
|
||||
call.stack[base+1] = val;
|
||||
call.top = base+2;
|
||||
} else {
|
||||
state.stack[base] = LNil.NIL;
|
||||
state.top = base+1;
|
||||
call.stack[base] = LNil.NIL;
|
||||
call.top = base+1;
|
||||
}
|
||||
if ( nresults >= 0 )
|
||||
state.adjustTop(base + nresults);
|
||||
call.adjustTop(base + nresults);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package lua.value;
|
||||
|
||||
import lua.CallFrame;
|
||||
import lua.Lua;
|
||||
import lua.StackState;
|
||||
|
||||
abstract
|
||||
public class LValue {
|
||||
@@ -20,7 +20,7 @@ public class LValue {
|
||||
}
|
||||
|
||||
// perform a lua call, return number of results actually produced
|
||||
public void luaStackCall(StackState state, int base, int top, int nresults) {
|
||||
public void luaStackCall(CallFrame call, int base, int top, int nresults) {
|
||||
luaUnsupportedOperation();
|
||||
}
|
||||
|
||||
@@ -72,20 +72,20 @@ public class LValue {
|
||||
}
|
||||
|
||||
/** set a value in a table
|
||||
* @param state the stack state
|
||||
* @param call the stack state
|
||||
* @param base the base of the stack, in case a function is put on the stack
|
||||
* @param table the table to operate on
|
||||
* @param the key to set
|
||||
* @param the value to set
|
||||
*/
|
||||
public void luaSetTable(StackState state, int base, LValue table, LValue key, LValue val) {
|
||||
public void luaSetTable(CallFrame call, int base, LValue table, LValue key, LValue val) {
|
||||
luaUnsupportedOperation();
|
||||
}
|
||||
|
||||
/** Get a value from a table
|
||||
* @param base TODO
|
||||
* @param table TODO*/
|
||||
public void luaGetTable(StackState state, int base, LValue table, LValue key) {
|
||||
public void luaGetTable(CallFrame call, int base, LValue table, LValue key) {
|
||||
luaUnsupportedOperation();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import lua.GlobalState;
|
||||
import lua.StackState;
|
||||
import lua.addon.luajava.LuaJava;
|
||||
import lua.io.Closure;
|
||||
import lua.io.LoadState;
|
||||
import lua.io.Proto;
|
||||
import lua.value.LString;
|
||||
import lua.value.LValue;
|
||||
|
||||
/**
|
||||
* Program to run a compiled lua chunk for test purposes,
|
||||
@@ -30,20 +30,18 @@ public class LuaJavaAppRunner {
|
||||
// new lua state
|
||||
StackState state = new StackState();
|
||||
|
||||
// push args onto stack
|
||||
// convert args to lua
|
||||
LValue[] vargs = new LValue[args.length];
|
||||
for ( int i=1; i<args.length; i++ )
|
||||
state.push(new LString(args[i]));
|
||||
vargs[i] = new LString(args[i]);
|
||||
|
||||
// load the file
|
||||
InputStream is = LuaJavaAppRunner.class.getResourceAsStream( script );
|
||||
Proto p = LoadState.undump(state, is, script);
|
||||
|
||||
// create closure to execute
|
||||
// create closure and execute
|
||||
Closure c = new Closure( state, p );
|
||||
state.push( c );
|
||||
for ( int i=0; i<args.length; i++ )
|
||||
state.push( new LString(args[i]) );
|
||||
state.docall(args.length, 0);
|
||||
state.doCall(c, vargs, 0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import lua.io.Closure;
|
||||
import lua.io.LoadState;
|
||||
import lua.io.Proto;
|
||||
import lua.value.LString;
|
||||
import lua.value.LValue;
|
||||
|
||||
/**
|
||||
* Program to run a compiled lua chunk for test purposes
|
||||
@@ -24,25 +25,17 @@ public class LuacRunner {
|
||||
// new lua state
|
||||
StackState state = new StackState();
|
||||
|
||||
// push args onto stack
|
||||
// convert args to lua
|
||||
LValue[] vargs = new LValue[args.length];
|
||||
for ( int i=1; i<args.length; i++ )
|
||||
state.push(new LString(args[i]));
|
||||
vargs[i] = new LString(args[i]);
|
||||
|
||||
// load the file
|
||||
InputStream is = LuacRunner.class.getResourceAsStream( script );
|
||||
Proto p = LoadState.undump(state, is, script);
|
||||
|
||||
// create closure to execute
|
||||
// create closure and execute
|
||||
Closure c = new Closure( state, p );
|
||||
state.push( c );
|
||||
for ( int i=0; i<args.length; i++ )
|
||||
state.push( new LString(args[i]) );
|
||||
state.docall(args.length, 0);
|
||||
|
||||
// print result?
|
||||
System.out.println("stack:");
|
||||
for ( int i=0; i<state.top; i++ )
|
||||
System.out.println(" ["+i+"]="+state.stack[i] );
|
||||
|
||||
state.doCall(c, vargs, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
LUA_HOME=/cygdrive/c/programs/lua5.1
|
||||
TESTS="test1 test2 test3 test4 test5 swingapp"
|
||||
TESTS="swingapp"
|
||||
TESTS="test2"
|
||||
for x in $TESTS
|
||||
do
|
||||
echo compiling $x
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
for cycle = 1,100 do
|
||||
|
||||
for cycle = 1,10 do
|
||||
|
||||
a = 123 + 456
|
||||
print( a )
|
||||
@@ -68,17 +69,18 @@ print( func(11, 12, 13) )
|
||||
print( func(23, 22, 21) )
|
||||
print( func(func(32,33,34), func(45,46,47), func(58,59,50)) )
|
||||
|
||||
--[[
|
||||
function p(a,...)
|
||||
print("a",a)
|
||||
-- print("...",...)
|
||||
-- print("...,a",...,a)
|
||||
-- print("a,...",a,...)
|
||||
print("...",...)
|
||||
print("...,a",...,a)
|
||||
print("a,...",a,...)
|
||||
end
|
||||
p()
|
||||
p("q")
|
||||
p("q","r")
|
||||
p("q","r","s")
|
||||
|
||||
--]]
|
||||
|
||||
|
||||
end
|
||||
Binary file not shown.
@@ -26,12 +26,13 @@ end
|
||||
print( myfunc(0.1) )
|
||||
print( myfunc(0.1) )
|
||||
|
||||
--[[
|
||||
|
||||
i = 1
|
||||
table = { "west", "south", "east", "north" }
|
||||
function next()
|
||||
i = (i % 4) + 1
|
||||
if ( i >= 4 ) then
|
||||
i = 0
|
||||
end
|
||||
i = i + 1
|
||||
return table[i]
|
||||
end
|
||||
|
||||
@@ -76,5 +77,4 @@ function room4 ()
|
||||
end
|
||||
|
||||
room1()
|
||||
--]]
|
||||
|
||||
Binary file not shown.
@@ -5,7 +5,7 @@ obj = luajava.newInstance("SampleClass")
|
||||
print( obj )
|
||||
obj.s = "Hello"
|
||||
print( obj.s )
|
||||
print( obj.getS() )
|
||||
print( obj:getS() )
|
||||
|
||||
obj.setS( "World" )
|
||||
obj:setS( "World" )
|
||||
print( obj.s )
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user