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:
James Roseborough
2007-07-24 05:06:10 +00:00
parent 56f33b373d
commit 8bf4c82a12
17 changed files with 424 additions and 862 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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