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:
James Roseborough
2007-06-27 06:43:33 +00:00
parent 93fc4699a9
commit c8e1934916
20 changed files with 548 additions and 136 deletions

View File

@@ -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;
}

View File

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

View File

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

View 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;
}
}

View File

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

View File

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

View File

@@ -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;
}
//

View File

@@ -1,6 +1,5 @@
package lua.io;
import lua.value.LNil;
import lua.value.LString;
import lua.value.LValue;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.