Rework the main API"s that implement the calling convention. Provide utility methods to get arguments that were supplied, and provide return values. Add a VM interface to clarify the relationship between the VM, things that call the VM, and things that are called by the VM. Make the code more closely aligned with the C++ version.
This commit is contained in:
@@ -37,41 +37,35 @@ final class Builtin extends LFunction {
|
||||
}
|
||||
|
||||
// perform a lua call
|
||||
public void luaStackCall(CallFrame call, int base, int top, int nresults) {
|
||||
public void luaStackCall(VM vm) {
|
||||
switch ( id ) {
|
||||
case PRINT:
|
||||
if ( base+1<top )
|
||||
stdout.print( call.stack[base+1].luaAsString() );
|
||||
for ( int i=base+2; i<top; i++ ) {
|
||||
stdout.print( "\t" );
|
||||
stdout.print( call.stack[i].luaAsString() );
|
||||
int n = vm.getArgCount();
|
||||
for ( int i=0; i<n; i++ ) {
|
||||
if ( i > 0 )
|
||||
stdout.print( "\t" );
|
||||
stdout.print( vm.getArg(i).luaAsString() );
|
||||
}
|
||||
stdout.println();
|
||||
call.top = base;
|
||||
vm.setResult();
|
||||
break;
|
||||
case PAIRS:
|
||||
LValue value = call.stack[base+1].luaPairs();
|
||||
call.stack[base] = value;
|
||||
call.top = base+1;
|
||||
vm.setResult( vm.getArg(0).luaPairs() );
|
||||
break;
|
||||
case GETMETATABLE:
|
||||
call.stack[base] = call.stack[base+1].luaGetMetatable();
|
||||
call.top = base+1;
|
||||
vm.setResult( vm.getArg(0).luaGetMetatable() );
|
||||
break;
|
||||
case SETMETATABLE:
|
||||
call.stack[base+1].luaSetMetatable(call.stack[base+2]);
|
||||
call.stack[base] = call.stack[base+1];
|
||||
call.top = base+1;
|
||||
LValue t = vm.getArg(0);
|
||||
t.luaSetMetatable(vm.getArg(1));
|
||||
vm.setResult( t );
|
||||
break;
|
||||
case TYPE:
|
||||
call.stack[base] = call.stack[base+1].luaGetType();
|
||||
call.top = base+1;
|
||||
vm.setResult( vm.getArg(0).luaGetType() );
|
||||
break;
|
||||
default:
|
||||
luaUnsupportedOperation();
|
||||
}
|
||||
if (nresults >= 0)
|
||||
call.adjustTop(base + nresults);
|
||||
}
|
||||
|
||||
static void redirectOutput( OutputStream newStdOut ) {
|
||||
|
||||
@@ -1,457 +0,0 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
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;
|
||||
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;
|
||||
public final Closure cl;
|
||||
public final Proto p;
|
||||
private final LValue[] k;
|
||||
private final int nresults;
|
||||
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;
|
||||
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].getValue();
|
||||
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].setValue( 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 == (a == 0))
|
||||
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;
|
||||
|
||||
close( base ); // Close open upvals
|
||||
|
||||
// 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;
|
||||
close( base ); // close open upvals
|
||||
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 ) {
|
||||
CallFrame call = state.calls[state.cc];
|
||||
call.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);
|
||||
int listBase = base + a;
|
||||
if (b == 0) {
|
||||
b = top - listBase - 1;
|
||||
}
|
||||
if (c == 0) {
|
||||
c = code[pc++];
|
||||
}
|
||||
table = this.stack[base + a];
|
||||
for (int index = 1; index <= b; index++) {
|
||||
val = this.stack[listBase + index];
|
||||
table.luaSetTable(this, this.state.avail, table,
|
||||
new LInteger(index), val);
|
||||
}
|
||||
top = base + a - 1;
|
||||
continue;
|
||||
}
|
||||
case StackState.OP_CLOSE: {
|
||||
close( a ); // close upvals higher in the stack than position a
|
||||
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];
|
||||
} else if (o == StackState.OP_MOVE) {
|
||||
newClosure.upVals[j] = findUpVal( proto.upvalues[j], base + b );
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
114
src/main/java/lua/VM.java
Normal file
114
src/main/java/lua/VM.java
Normal file
@@ -0,0 +1,114 @@
|
||||
package lua;
|
||||
|
||||
import lua.io.Closure;
|
||||
import lua.value.LTable;
|
||||
import lua.value.LValue;
|
||||
|
||||
public interface VM {
|
||||
|
||||
// ================ interfaces for performing calls
|
||||
|
||||
/** Push an argument or return value onto the stack
|
||||
*/
|
||||
public void push( LValue value );
|
||||
|
||||
/** Push an int argument or return value onto the stack
|
||||
*/
|
||||
public void push( int value );
|
||||
|
||||
/** Push a double argument or return value onto the stack
|
||||
*/
|
||||
public void push( double value );
|
||||
|
||||
/** Push a boolean argument or return value onto the stack
|
||||
*/
|
||||
public void push( boolean value );
|
||||
|
||||
/** Push a String argument or return value onto the stack
|
||||
*/
|
||||
public void push( String value );
|
||||
|
||||
/**
|
||||
* Perform a call that has been set up on the stack.
|
||||
* The first value on the stack must be a Closure,
|
||||
* and subsequent values are arguments to the closure.
|
||||
*/
|
||||
public void stackCall();
|
||||
|
||||
/**
|
||||
* Execute bytecodes until the current call completes
|
||||
* or the vm yields.
|
||||
*/
|
||||
public void exec();
|
||||
|
||||
/**
|
||||
* Put the closure on the stack with arguments,
|
||||
* then perform the call. Leave return values
|
||||
* on the stack for later querying.
|
||||
*
|
||||
* @param c
|
||||
* @param values
|
||||
*/
|
||||
public void doCall(Closure c, LValue[] values);
|
||||
|
||||
// ================ interfaces for getting arguments when called
|
||||
|
||||
/**
|
||||
* Get the number of argumnets supplied in the call.
|
||||
*/
|
||||
public int getArgCount();
|
||||
|
||||
/**
|
||||
* Get the index-th argument supplied, or NIL if fewer than index were supplied.
|
||||
* @param index
|
||||
* @return
|
||||
*/
|
||||
public LValue getArg(int index);
|
||||
|
||||
/**
|
||||
* Get the index-th argument as an int value, or 0 if fewer than index arguments were supplied.
|
||||
* @param index
|
||||
* @return
|
||||
*/
|
||||
public int getArgAsInt( int index );
|
||||
|
||||
/**
|
||||
* Get the index-th argument as a double value, or 0 if fewer than index arguments were supplied.
|
||||
* @param index
|
||||
* @return
|
||||
*/
|
||||
public double getArgAsDouble( int index );
|
||||
|
||||
/**
|
||||
* Get the index-th argument as a boolean value, or false if fewer than index arguments were supplied.
|
||||
* @param index
|
||||
* @return
|
||||
*/
|
||||
public boolean getArgAsBoolean( int index );
|
||||
|
||||
/**
|
||||
* Get the index-th argument as a String value, or "" if fewer than index arguments were supplied.
|
||||
* @param index
|
||||
* @return
|
||||
*/
|
||||
public String getArgAsString( int index );
|
||||
|
||||
/** Set top to base in preparation for pushing return values.
|
||||
* Can be used when returning no values.
|
||||
*
|
||||
* Once this is called, calls to getArg() are undefined.
|
||||
*
|
||||
* @see push() to push additional results once result is reset.
|
||||
*/
|
||||
public void setResult();
|
||||
|
||||
/** Convenience utility to set val to stack[base] and top to base + 1
|
||||
* in preparation for returning one value
|
||||
*
|
||||
* Once this is called, calls to getArg() are undefined.
|
||||
*
|
||||
* @param val value to provide as the only result.
|
||||
*/
|
||||
public void setResult(LValue val);
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package lua.io;
|
||||
|
||||
import lua.CallFrame;
|
||||
import lua.StackState;
|
||||
import lua.VM;
|
||||
import lua.value.LFunction;
|
||||
import lua.value.LValue;
|
||||
|
||||
@@ -9,14 +9,18 @@ public class Closure extends LFunction {
|
||||
public LValue env;
|
||||
public Proto p;
|
||||
public UpVal[] upVals;
|
||||
|
||||
// TODO: change arg type to VM?
|
||||
public Closure(StackState state, Proto p) {
|
||||
this.env = state._G;
|
||||
this.p = p;
|
||||
upVals = new UpVal[p.nups];
|
||||
}
|
||||
|
||||
// perform a lua call
|
||||
public void luaStackCall(CallFrame call, int base, int top, int nresults) {
|
||||
call.state.stackCall( this, base, top, nresults );
|
||||
// called by vm when there is an OP_CALL
|
||||
// in this case, we are on the stack,
|
||||
// and simply need to cue the VM to treat it as a stack call
|
||||
public void luaStackCall(VM vm) {
|
||||
vm.stackCall();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import lua.StackState;
|
||||
import lua.VM;
|
||||
import lua.value.LBoolean;
|
||||
import lua.value.LDouble;
|
||||
import lua.value.LInteger;
|
||||
@@ -44,15 +44,14 @@ public class LoadState {
|
||||
private int luacSizeofLuaNumber;
|
||||
private boolean luacIsNumberIntegral;
|
||||
|
||||
/** The lua state that is loading the code */
|
||||
private StackState L;
|
||||
|
||||
/** input stream from which we are loading */
|
||||
private DataInputStream is;
|
||||
|
||||
/** Name of what is being loaded? */
|
||||
String name;
|
||||
|
||||
/** The VM doing the loading */
|
||||
VM L;
|
||||
|
||||
private static final int LUA_TNONE = (-1);
|
||||
|
||||
@@ -65,76 +64,11 @@ public class LoadState {
|
||||
private static final int LUA_TFUNCTION = 6;
|
||||
private static final int LUA_TUSERDATA = 7;
|
||||
private static final int LUA_TTHREAD = 8;
|
||||
|
||||
// /*
|
||||
// ** $Id$
|
||||
// ** load precompiled Lua chunks
|
||||
// ** See Copyright Notice in lua.h
|
||||
// */
|
||||
//
|
||||
// #include <string.h>
|
||||
//
|
||||
// #define lundump_c
|
||||
// #define LUA_CORE
|
||||
//
|
||||
// #include "lua.h"
|
||||
//
|
||||
// #include "ldebug.h"
|
||||
// #include "ldo.h"
|
||||
// #include "lfunc.h"
|
||||
// #include "lmem.h"
|
||||
// #include "lobject.h"
|
||||
// #include "lstring.h"
|
||||
// #include "lundump.h"
|
||||
// #include "lzio.h"
|
||||
//
|
||||
// typedef struct {
|
||||
// lua_State* L;
|
||||
// ZIO* Z;
|
||||
// Mbuffer* b;
|
||||
// const char* name;
|
||||
// } LoadState;
|
||||
//
|
||||
// #ifdef LUAC_TRUST_BINARIES
|
||||
// #define IF(c,s)
|
||||
// #else
|
||||
// #define IF(c,s) if (c) error(S,s)
|
||||
//
|
||||
// static void error(LoadState* S, const char* why)
|
||||
// {
|
||||
// luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why);
|
||||
// luaD_throw(S->L,LUA_ERRSYNTAX);
|
||||
// }
|
||||
// #endif
|
||||
//
|
||||
// #define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
|
||||
// #define LoadByte(S) (lu_byte)LoadChar(S)
|
||||
// #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
|
||||
// #define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
|
||||
//
|
||||
// static void LoadBlock(LoadState* S, void* b, size_t size)
|
||||
// {
|
||||
// size_t r=luaZ_read(S->Z,b,size);
|
||||
// IF (r!=0, "unexpected end");
|
||||
// }
|
||||
//
|
||||
// static int LoadChar(LoadState* S)
|
||||
// {
|
||||
// char x;
|
||||
// LoadVar(S,x);
|
||||
// return x;
|
||||
// }
|
||||
|
||||
int loadByte() throws IOException {
|
||||
return is.readUnsignedByte();
|
||||
}
|
||||
//
|
||||
// static int LoadInt(LoadState* S)
|
||||
// {
|
||||
// int x;
|
||||
// LoadVar(S,x);
|
||||
// IF (x<0, "bad integer");
|
||||
// return x;
|
||||
// }
|
||||
|
||||
int loadInt() throws IOException {
|
||||
if ( this.luacLittleEndian ) {
|
||||
int a = is.readUnsignedByte();
|
||||
@@ -158,27 +92,7 @@ public class LoadState {
|
||||
}
|
||||
return (((long)b)<<32) | (((long)a)&0xffffffffL);
|
||||
}
|
||||
//
|
||||
// static lua_Number LoadNumber(LoadState* S)
|
||||
// {
|
||||
// lua_Number x;
|
||||
// LoadVar(S,x);
|
||||
// return x;
|
||||
// }
|
||||
//
|
||||
// static TString* LoadString(LoadState* S)
|
||||
// {
|
||||
// size_t size;
|
||||
// LoadVar(S,size);
|
||||
// if (size==0)
|
||||
// return NULL;
|
||||
// else
|
||||
// {
|
||||
// char* s=luaZ_openspace(S->L,S->b,size);
|
||||
// LoadBlock(S,s,size);
|
||||
// return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
|
||||
// }
|
||||
// }
|
||||
|
||||
LString loadString() throws IOException {
|
||||
int size = loadInt();
|
||||
if ( size == 0 )
|
||||
@@ -218,14 +132,7 @@ public class LoadState {
|
||||
return longBitsToLuaNumber( loadInt64() );
|
||||
}
|
||||
}
|
||||
//
|
||||
// static void LoadCode(LoadState* S, Proto* f)
|
||||
// {
|
||||
// int n=LoadInt(S);
|
||||
// f->code=luaM_newvector(S->L,n,Instruction);
|
||||
// f->sizecode=n;
|
||||
// LoadVector(S,f->code,n,sizeof(Instruction));
|
||||
// }
|
||||
|
||||
public void loadCode( Proto f ) throws IOException {
|
||||
int n = loadInt();
|
||||
int[] code = new int[n];
|
||||
@@ -233,45 +140,7 @@ public class LoadState {
|
||||
code[i] = loadInt();
|
||||
f.code = code;
|
||||
}
|
||||
//
|
||||
// static Proto* LoadFunction(LoadState* S, TString* p);
|
||||
//
|
||||
// static void LoadConstants(LoadState* S, Proto* f)
|
||||
// {
|
||||
// int i,n;
|
||||
// n=LoadInt(S);
|
||||
// f->k=luaM_newvector(S->L,n,TValue);
|
||||
// f->sizek=n;
|
||||
// for (i=0; i<n; i++) setnilvalue(&f->k[i]);
|
||||
// for (i=0; i<n; i++)
|
||||
// {
|
||||
// TValue* o=&f->k[i];
|
||||
// int t=LoadChar(S);
|
||||
// switch (t)
|
||||
// {
|
||||
// case LUA_TNIL:
|
||||
// setnilvalue(o);
|
||||
// break;
|
||||
// case LUA_TBOOLEAN:
|
||||
// setbvalue(o,LoadChar(S));
|
||||
// break;
|
||||
// case LUA_TNUMBER:
|
||||
// setnvalue(o,LoadNumber(S));
|
||||
// break;
|
||||
// case LUA_TSTRING:
|
||||
// setsvalue2n(S->L,o,LoadString(S));
|
||||
// break;
|
||||
// default:
|
||||
// IF (1, "bad constant");
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// n=LoadInt(S);
|
||||
// f->p=luaM_newvector(S->L,n,Proto*);
|
||||
// f->sizep=n;
|
||||
// for (i=0; i<n; i++) f->p[i]=NULL;
|
||||
// for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);
|
||||
// }
|
||||
|
||||
void loadConstants(Proto f) throws IOException {
|
||||
int n = loadInt();
|
||||
LValue[] values = new LValue[n];
|
||||
@@ -301,32 +170,7 @@ public class LoadState {
|
||||
protos[i] = loadFunction(f.source);
|
||||
f.p = protos;
|
||||
}
|
||||
//
|
||||
// static void LoadDebug(LoadState* S, Proto* f)
|
||||
// {
|
||||
// int i,n;
|
||||
// n=LoadInt(S);
|
||||
// f->lineinfo=luaM_newvector(S->L,n,int);
|
||||
// f->sizelineinfo=n;
|
||||
// LoadVector(S,f->lineinfo,n,sizeof(int));
|
||||
|
||||
// n=LoadInt(S);
|
||||
// f->locvars=luaM_newvector(S->L,n,LocVar);
|
||||
// f->sizelocvars=n;
|
||||
// for (i=0; i<n; i++) f->locvars[i].varname=NULL;
|
||||
// for (i=0; i<n; i++)
|
||||
// {
|
||||
// f->locvars[i].varname=LoadString(S);
|
||||
// f->locvars[i].startpc=LoadInt(S);
|
||||
// f->locvars[i].endpc=LoadInt(S);
|
||||
// }
|
||||
|
||||
// n=LoadInt(S);
|
||||
// f->upvalues=luaM_newvector(S->L,n,TString*);
|
||||
// f->sizeupvalues=n;
|
||||
// for (i=0; i<n; i++) f->upvalues[i]=NULL;
|
||||
// for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
|
||||
// }
|
||||
|
||||
void loadDebug( Proto f ) throws IOException {
|
||||
int n = loadInt();
|
||||
f.lineinfo = new int[n];
|
||||
@@ -348,27 +192,9 @@ public class LoadState {
|
||||
f.upvalues[i] = loadString();
|
||||
}
|
||||
}
|
||||
//
|
||||
// static Proto* LoadFunction(LoadState* S, TString* p)
|
||||
// {
|
||||
// Proto* f=luaF_newproto(S->L);
|
||||
// setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
|
||||
// f->source=LoadString(S); if (f->source==NULL) f->source=p;
|
||||
// f->linedefined=LoadInt(S);
|
||||
// f->lastlinedefined=LoadInt(S);
|
||||
// f->nups=LoadByte(S);
|
||||
// f->numparams=LoadByte(S);
|
||||
// f->is_vararg=LoadByte(S);
|
||||
// f->maxstacksize=LoadByte(S);
|
||||
// LoadCode(S,f);
|
||||
// LoadConstants(S,f);
|
||||
// LoadDebug(S,f);
|
||||
// IF (!luaG_checkcode(f), "bad code");
|
||||
// S->L->top--;
|
||||
// return f;
|
||||
// }
|
||||
|
||||
public Proto loadFunction(LString p) throws IOException {
|
||||
Proto f = new Proto(this.L);
|
||||
Proto f = new Proto();
|
||||
// this.L.push(f);
|
||||
f.source = loadString();
|
||||
f.linedefined = loadInt();
|
||||
@@ -410,27 +236,8 @@ public class LoadState {
|
||||
if ( sig != LUAC_HEADER_SIGNATURE )
|
||||
throw new IllegalArgumentException("bad signature");
|
||||
}
|
||||
//
|
||||
// /*
|
||||
// ** load precompiled chunk
|
||||
// */
|
||||
// Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
|
||||
// {
|
||||
// LoadState S;
|
||||
// if (*name=='@' || *name=='=')
|
||||
// S.name=name+1;
|
||||
// else if (*name==LUA_SIGNATURE[0])
|
||||
// S.name="binary string";
|
||||
// else
|
||||
// S.name=name;
|
||||
// S.L=L;
|
||||
// S.Z=Z;
|
||||
// S.b=buff;
|
||||
// LoadHeader(&S);
|
||||
// return LoadFunction(&S,luaS_newliteral(L,"=?"));
|
||||
// }
|
||||
|
||||
public static Proto undump( StackState L, InputStream stream, String name ) throws IOException {
|
||||
public static Proto undump( VM L, InputStream stream, String name ) throws IOException {
|
||||
String sname = name;
|
||||
if ( name.startsWith("@") || name.startsWith("=") )
|
||||
sname = name.substring(1);
|
||||
@@ -438,12 +245,12 @@ public class LoadState {
|
||||
sname = "binary string";
|
||||
LoadState s = new LoadState( L, stream, sname );
|
||||
s.loadHeader();
|
||||
LString literal = new LString(L, "=?");
|
||||
LString literal = new LString("=?");
|
||||
return s.loadFunction( literal );
|
||||
}
|
||||
|
||||
/** Private constructor for create a load state */
|
||||
private LoadState( StackState L, InputStream stream, String name ) {
|
||||
private LoadState( VM L, InputStream stream, String name ) {
|
||||
this.L = L;
|
||||
this.name = name;
|
||||
this.is = new DataInputStream( stream );
|
||||
|
||||
@@ -8,9 +8,7 @@ import lua.value.LString;
|
||||
** Function Prototypes
|
||||
*/
|
||||
public class Proto {
|
||||
public Proto(StackState l) {
|
||||
}
|
||||
public Proto() {
|
||||
public Proto() {
|
||||
}
|
||||
|
||||
public LValue[] k; /* constants used by the function */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package lua.value;
|
||||
|
||||
import lua.CallFrame;
|
||||
import lua.VM;
|
||||
|
||||
|
||||
public class LFunction extends LValue {
|
||||
@@ -11,21 +11,19 @@ public class LFunction extends LValue {
|
||||
return "function: "+hashCode();
|
||||
}
|
||||
|
||||
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 luaSetTable(VM vm, LValue table, LValue key, LValue val) {
|
||||
vm.push( this );
|
||||
vm.push( table );
|
||||
vm.push( key );
|
||||
vm.push( val );
|
||||
this.luaStackCall(vm);
|
||||
}
|
||||
|
||||
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);
|
||||
public void luaGetTable(VM vm, LValue table, LValue key) {
|
||||
vm.push( this );
|
||||
vm.push( table );
|
||||
vm.push( key );
|
||||
this.luaStackCall(vm);
|
||||
}
|
||||
|
||||
public LString luaGetType() {
|
||||
|
||||
@@ -27,11 +27,6 @@ public class LString extends LValue {
|
||||
return m_hash;
|
||||
}
|
||||
|
||||
// TODO: what to do with LuaState?
|
||||
public LString(StackState l, String string) {
|
||||
this(string);
|
||||
}
|
||||
|
||||
public boolean luaBinCmpUnknown(int opcode, LValue lhs) {
|
||||
return lhs.luaBinCmpString(opcode, m_string);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package lua.value;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import lua.CallFrame;
|
||||
import lua.VM;
|
||||
|
||||
public class LTable extends LValue {
|
||||
|
||||
@@ -39,12 +39,12 @@ public class LTable extends LValue {
|
||||
return (LValue) m_hash.get( new LString(key) );
|
||||
}
|
||||
|
||||
public void luaSetTable(CallFrame call, int base, LValue table, LValue key, LValue val) {
|
||||
public void luaSetTable(VM vm, 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( call, base, table, key, val );
|
||||
event.luaSetTable( vm, table, key, val );
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -52,19 +52,21 @@ public class LTable extends LValue {
|
||||
m_hash.put( key, val );
|
||||
}
|
||||
|
||||
public void luaGetTable(CallFrame call, int base, LValue table, LValue key) {
|
||||
public void luaGetTable(VM vm, 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( call, base, table, key );
|
||||
event.luaGetTable( vm, table, key );
|
||||
return;
|
||||
}
|
||||
}
|
||||
val = LNil.NIL;
|
||||
}
|
||||
call.stack[base] = val;
|
||||
|
||||
// stack.stack[base] = val;
|
||||
vm.push(val);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@@ -107,19 +109,14 @@ public class LTable extends LValue {
|
||||
}
|
||||
|
||||
// perform a lua call
|
||||
public void luaStackCall(CallFrame call, int base, int top, int nresults) {
|
||||
public void luaStackCall(VM vm) {
|
||||
if ( e.hasMoreElements() ) {
|
||||
LValue key = (LValue) e.nextElement();
|
||||
LValue val = (LValue) t.m_hash.get(key);
|
||||
call.stack[base] = key;
|
||||
call.stack[base+1] = val;
|
||||
call.top = base+2;
|
||||
} else {
|
||||
call.stack[base] = LNil.NIL;
|
||||
call.top = base+1;
|
||||
vm.setResult();
|
||||
vm.push( key );
|
||||
vm.push( val );
|
||||
}
|
||||
if ( nresults >= 0 )
|
||||
call.adjustTop(base + nresults);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package lua.value;
|
||||
|
||||
import lua.CallFrame;
|
||||
import lua.Lua;
|
||||
import lua.VM;
|
||||
|
||||
abstract
|
||||
public class LValue {
|
||||
@@ -20,7 +20,7 @@ public class LValue {
|
||||
}
|
||||
|
||||
// perform a lua call, return number of results actually produced
|
||||
public void luaStackCall(CallFrame call, int base, int top, int nresults) {
|
||||
public void luaStackCall(VM vm) {
|
||||
luaUnsupportedOperation();
|
||||
}
|
||||
|
||||
@@ -72,20 +72,21 @@ public class LValue {
|
||||
}
|
||||
|
||||
/** set a value in a table
|
||||
* @param call the stack state
|
||||
* @param base the base of the stack, in case a function is put on the stack
|
||||
* @param vm the calling vm
|
||||
* @param table the table to operate on
|
||||
* @param the key to set
|
||||
* @param the value to set
|
||||
*/
|
||||
public void luaSetTable(CallFrame call, int base, LValue table, LValue key, LValue val) {
|
||||
public void luaSetTable(VM vm, LValue table, LValue key, LValue val) {
|
||||
luaUnsupportedOperation();
|
||||
}
|
||||
|
||||
/** Get a value from a table
|
||||
* @param base TODO
|
||||
* @param table TODO*/
|
||||
public void luaGetTable(CallFrame call, int base, LValue table, LValue key) {
|
||||
* @param vm the calling vm
|
||||
* @param table the table from which to get the value
|
||||
* @param key the key to look up
|
||||
*/
|
||||
public void luaGetTable(VM vm, LValue table, LValue key) {
|
||||
luaUnsupportedOperation();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user