Streamline delegation chain for table event processing.
This commit is contained in:
@@ -188,14 +188,14 @@ public class PackageLib extends LFunction {
|
||||
module = findtable( vm._G, modname );
|
||||
if ( module == null )
|
||||
vm.error( "name conflict for module '"+modname+"'" );
|
||||
LOADED.luaSetTable(vm, LOADED, modname, module);
|
||||
LOADED.luaSetTable(vm, modname, module);
|
||||
} else {
|
||||
module = (LTable) value;
|
||||
}
|
||||
|
||||
|
||||
/* check whether table already has a _NAME field */
|
||||
LValue name = module.luaGetTable(vm, module, _NAME);
|
||||
LValue name = module.luaGetTable(vm, _NAME);
|
||||
if ( name.isNil() ) {
|
||||
modinit( vm, module, modname );
|
||||
}
|
||||
@@ -244,10 +244,10 @@ public class PackageLib extends LFunction {
|
||||
|
||||
private static void modinit(LuaState vm, LTable module, LString modname) {
|
||||
/* module._M = module */
|
||||
module.luaSetTable(vm, module, _M, module);
|
||||
module.luaSetTable(vm, _M, module);
|
||||
int e = modname.lastIndexOf(_DOT);
|
||||
module.luaSetTable(vm, module, _NAME, modname );
|
||||
module.luaSetTable(vm, module, _PACKAGE, (e<0? _EMPTY: modname.substring(0,e+1)) );
|
||||
module.luaSetTable(vm, _NAME, modname );
|
||||
module.luaSetTable(vm, _PACKAGE, (e<0? _EMPTY: modname.substring(0,e+1)) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -289,7 +289,7 @@ public class PackageLib extends LFunction {
|
||||
vm.resettop();
|
||||
|
||||
/* else must load it; iterate over available loaders */
|
||||
LValue val = pckg.luaGetTable(vm, pckg, _LOADERS);
|
||||
LValue val = pckg.luaGetTable(vm, _LOADERS);
|
||||
if ( ! val.isTable() )
|
||||
vm.error( "'package.loaders' must be a table" );
|
||||
vm.pushlvalue(val);
|
||||
@@ -310,14 +310,14 @@ public class PackageLib extends LFunction {
|
||||
}
|
||||
|
||||
// load the module using the loader
|
||||
LOADED.luaSetTable(vm, LOADED, name, _SENTINEL);
|
||||
LOADED.luaSetTable(vm, name, _SENTINEL);
|
||||
vm.pushlstring( name ); /* pass name as argument to module */
|
||||
vm.call( 1, 1 ); /* run loaded module */
|
||||
if ( ! vm.isnil(-1) ) /* non-nil return? */
|
||||
LOADED.luaSetTable(vm, LOADED, name, vm.topointer(-1) ); /* _LOADED[name] = returned value */
|
||||
LValue result = LOADED.luaGetTable(vm, LOADED, name);
|
||||
LOADED.luaSetTable(vm, name, vm.topointer(-1) ); /* _LOADED[name] = returned value */
|
||||
LValue result = LOADED.luaGetTable(vm, name);
|
||||
if ( result == _SENTINEL ) { /* module did not set a value? */
|
||||
LOADED.luaSetTable(vm, LOADED, name, result=LBoolean.TRUE ); /* _LOADED[name] = true */
|
||||
LOADED.luaSetTable(vm, name, result=LBoolean.TRUE ); /* _LOADED[name] = true */
|
||||
}
|
||||
vm.resettop();
|
||||
vm.pushlvalue(result);
|
||||
@@ -330,10 +330,10 @@ public class PackageLib extends LFunction {
|
||||
|
||||
private void loader_preload( LuaState vm ) {
|
||||
LString name = vm.tolstring(2);
|
||||
LValue preload = pckg.luaGetTable(vm, pckg, _PRELOAD);
|
||||
LValue preload = pckg.luaGetTable(vm, _PRELOAD);
|
||||
if ( ! preload.isTable() )
|
||||
vm.error("package.preload '"+name+"' must be a table");
|
||||
LValue val = preload.luaGetTable(vm, preload, name);
|
||||
LValue val = preload.luaGetTable(vm, name);
|
||||
if ( val.isNil() )
|
||||
vm.pushstring("\n\tno field package.preload['"+name+"']");
|
||||
vm.resettop();
|
||||
@@ -371,7 +371,7 @@ public class PackageLib extends LFunction {
|
||||
|
||||
private InputStream findfile(LuaState vm, String name, LString pname) {
|
||||
Platform p = Platform.getInstance();
|
||||
LValue pkg = pckg.luaGetTable(vm, pckg, pname);
|
||||
LValue pkg = pckg.luaGetTable(vm, pname);
|
||||
if ( ! pkg.isString() )
|
||||
vm.error("package."+pname+" must be a string");
|
||||
String path = pkg.toJavaString();
|
||||
|
||||
@@ -667,7 +667,7 @@ public class StringLib extends LFunction {
|
||||
push_onecapture( 0, soffset, end );
|
||||
LValue k = vm.topointer( -1 );
|
||||
vm.pop( 1 );
|
||||
vm.pushlvalue( ((LTable) repl).luaGetTable( vm, repl, k ) );
|
||||
vm.pushlvalue( ((LTable) repl).luaGetTable( vm, k ) );
|
||||
} else {
|
||||
vm.error( "string/function/table expected" );
|
||||
return;
|
||||
|
||||
@@ -65,5 +65,31 @@ public class LFunction extends LValue {
|
||||
public int invoke( LuaState lua ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process lua tag method __index when it points to a function.
|
||||
* Default method calls the function using the vm.
|
||||
*
|
||||
* @param vm
|
||||
* @param table
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public LValue __index(LuaState vm, LValue table, LValue key) {
|
||||
return vm.call(this, table, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process lua tag method __newindex when it points to a function
|
||||
* Default method calls the function using the vm.
|
||||
*
|
||||
* @param vm
|
||||
* @param table
|
||||
* @param key
|
||||
* @param val
|
||||
*/
|
||||
public void __newindex(LuaState vm, LValue table, LValue key, LValue val) {
|
||||
vm.call(this, table, key, val);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -202,6 +202,32 @@ public class LTable extends LValue {
|
||||
array[key-1]:
|
||||
hashGet(LInteger.valueOf(key)) );
|
||||
}
|
||||
|
||||
/** Set a table value, including metatable processing.
|
||||
*
|
||||
* As an optimization for the common case, looks directly in the table first
|
||||
* before delgating to the vm for metatable processing.
|
||||
*/
|
||||
public void luaSetTable(LuaState vm, LValue key, LValue val) {
|
||||
if ( containsKey(key) || m_metatable == null || ! m_metatable.containsKey(TM_NEWINDEX) )
|
||||
put( key, val );
|
||||
else
|
||||
vm.luaV_settable(this, key, val);
|
||||
}
|
||||
|
||||
|
||||
/** Get a table value, including metatable processing.
|
||||
*
|
||||
* As an optimization for the common case, looks directly in the table first
|
||||
* before delgating to the vm for metatable processing.
|
||||
*/
|
||||
public LValue luaGetTable(LuaState vm, LValue key) {
|
||||
LValue val = get(key);
|
||||
return ! val.isNil() || m_metatable == null || ! m_metatable.containsKey(TM_INDEX)?
|
||||
val:
|
||||
vm.luaV_gettable(this, key);
|
||||
}
|
||||
|
||||
|
||||
/** Check for null, and convert to nilor leave alone
|
||||
*/
|
||||
@@ -232,14 +258,6 @@ public class LTable extends LValue {
|
||||
(hashKeys.length>0 && hashKeys[hashFindSlot(LInteger.valueOf(key))]!=null));
|
||||
}
|
||||
|
||||
public LValue luaGetTable(LuaState vm, LValue table, LValue key) {
|
||||
return vm.luaV_gettable(table, key);
|
||||
}
|
||||
|
||||
public void luaSetTable(LuaState vm, LValue table, LValue key, LValue val) {
|
||||
vm.luaV_settable(table, key, val);
|
||||
}
|
||||
|
||||
private static final int MAX_KEY = 0x3fffffff;
|
||||
|
||||
/**
|
||||
|
||||
@@ -39,6 +39,8 @@ public class LValue {
|
||||
/** Metatable tag for setting table mode */
|
||||
public static final LString TM_MODE = new LString("__mode");
|
||||
|
||||
private static final int MAXTAGLOOP = 100;
|
||||
|
||||
protected void conversionError(String target) {
|
||||
throw new LuaErrorException( "bad conversion: "+luaGetTypeName()+" to "+target );
|
||||
}
|
||||
@@ -124,40 +126,19 @@ public class LValue {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** set a value in a table
|
||||
* For non-tables, goes straight to the meta-table.
|
||||
* @param vm the calling vm
|
||||
* @param table the table to operate on
|
||||
* @param the key to set
|
||||
* @param the value to set
|
||||
/** Dispatch a settable operation.
|
||||
* Default method delegates back to the vm for metatable processing.
|
||||
*/
|
||||
public void luaSetTable(LuaState vm, LValue table, LValue key, LValue val) {
|
||||
LTable mt = luaGetMetatable();
|
||||
if ( mt != null ) {
|
||||
LValue event = mt.get( TM_NEWINDEX );
|
||||
if ( event != null && ! event.isNil() ) {
|
||||
event.luaSetTable( vm, table, key, val );
|
||||
return;
|
||||
}
|
||||
}
|
||||
indexError( vm, table );
|
||||
public void luaSetTable(LuaState vm, LValue key, LValue val) {
|
||||
vm.luaV_settable(this, key, val);
|
||||
}
|
||||
|
||||
/** Get a value from a table
|
||||
* @param vm the calling vm
|
||||
* @param table the table from which to get the value
|
||||
* @param key the key to look up
|
||||
* @return TODO
|
||||
|
||||
/** Dispatch a gettable operation.
|
||||
* Default method delegates back to the vm for metatable processing.
|
||||
*/
|
||||
public LValue luaGetTable(LuaState vm, LValue table, LValue key) {
|
||||
LTable mt = luaGetMetatable();
|
||||
if ( mt != null ) {
|
||||
LValue event = mt.get( TM_INDEX );
|
||||
if ( event != null && ! event.isNil() ) {
|
||||
return event.luaGetTable( vm, table, key );
|
||||
}
|
||||
}
|
||||
return indexError( vm, table );
|
||||
public LValue luaGetTable(LuaState vm, LValue key) {
|
||||
return vm.luaV_gettable(this, key);
|
||||
}
|
||||
|
||||
/** Get the value as a LString
|
||||
|
||||
@@ -290,26 +290,28 @@ public class LuaState extends Lua {
|
||||
public void call( int nargs, int nreturns ) {
|
||||
// save stack state
|
||||
int oldbase = base;
|
||||
|
||||
// rb is base of new call frame
|
||||
int rb = this.base = top - 1 - nargs;
|
||||
|
||||
// make or set up the call
|
||||
this.nresults = nreturns;
|
||||
if (this.stack[base].luaStackCall(this)) {
|
||||
// call was set up on the stack,
|
||||
// we still have to execute it
|
||||
execute();
|
||||
try {
|
||||
|
||||
// rb is base of new call frame
|
||||
int rb = this.base = top - 1 - nargs;
|
||||
|
||||
// make or set up the call
|
||||
this.nresults = nreturns;
|
||||
if (this.stack[base].luaStackCall(this)) {
|
||||
// call was set up on the stack,
|
||||
// we still have to execute it
|
||||
execute();
|
||||
}
|
||||
|
||||
// adjustTop only for case when call was completed
|
||||
// and number of args > 0. If call completed but
|
||||
// c == 0, leave top to point to end of results
|
||||
if (nreturns >= 0)
|
||||
luaV_adjusttop(rb + nreturns);
|
||||
|
||||
} finally {
|
||||
this.base = oldbase;
|
||||
}
|
||||
|
||||
// adjustTop only for case when call was completed
|
||||
// and number of args > 0. If call completed but
|
||||
// c == 0, leave top to point to end of results
|
||||
if (nreturns >= 0)
|
||||
luaV_adjusttop(rb + nreturns);
|
||||
|
||||
// restore base
|
||||
this.base = oldbase;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -554,7 +556,7 @@ public class LuaState extends Lua {
|
||||
b = LuaState.GETARG_Bx(i);
|
||||
key = k[b];
|
||||
table = cl.env;
|
||||
val = luaV_gettable(table, key);
|
||||
val = table.luaGetTable(this, key);
|
||||
this.stack[base + a] = val;
|
||||
continue;
|
||||
}
|
||||
@@ -562,7 +564,7 @@ public class LuaState extends Lua {
|
||||
b = LuaState.GETARG_B(i);
|
||||
key = GETARG_RKC(k, i);
|
||||
table = this.stack[base + b];
|
||||
val = luaV_gettable(table, key);
|
||||
val = table.luaGetTable(this, key);
|
||||
this.stack[base + a] = val;
|
||||
continue;
|
||||
}
|
||||
@@ -571,7 +573,7 @@ public class LuaState extends Lua {
|
||||
key = k[b];
|
||||
val = this.stack[base + a];
|
||||
table = cl.env;
|
||||
luaV_settable(table, key, val);
|
||||
table.luaSetTable(this, key, val);
|
||||
continue;
|
||||
}
|
||||
case LuaState.OP_SETUPVAL: {
|
||||
@@ -583,7 +585,7 @@ public class LuaState extends Lua {
|
||||
key = GETARG_RKB(k, i);
|
||||
val = GETARG_RKC(k, i);
|
||||
table = this.stack[base + a];
|
||||
luaV_settable(table, key, val);
|
||||
table.luaSetTable(this, key, val);
|
||||
continue;
|
||||
}
|
||||
case LuaState.OP_NEWTABLE: {
|
||||
@@ -595,7 +597,7 @@ public class LuaState extends Lua {
|
||||
case LuaState.OP_SELF: {
|
||||
rkb = GETARG_RKB(k, i);
|
||||
rkc = GETARG_RKC(k, i);
|
||||
val = luaV_gettable(rkb, rkc);
|
||||
val = rkb.luaGetTable(this, rkc);
|
||||
this.stack[base + a] = val;
|
||||
this.stack[base + a + 1] = rkb;
|
||||
continue;
|
||||
@@ -903,7 +905,7 @@ public class LuaState extends Lua {
|
||||
error( "attempt to index ? (a "+nontable.luaGetTypeName()+" value)", 1 );
|
||||
}
|
||||
|
||||
private LValue luaV_getmetafield(LValue t, LString tag) {
|
||||
public static LValue luaV_getmetafield(LValue t, LString tag) {
|
||||
LTable mt = t.luaGetMetatable();
|
||||
if ( mt == null )
|
||||
return null;
|
||||
@@ -911,6 +913,7 @@ public class LuaState extends Lua {
|
||||
return h.isNil()? null: h;
|
||||
}
|
||||
|
||||
/** Get a key from a table using full metatable processing */
|
||||
public LValue luaV_gettable(LValue table, LValue key) {
|
||||
LValue h=LNil.NIL,t=table;
|
||||
for ( int loop=0; loop<MAXTAGLOOP; loop++ ) {
|
||||
@@ -930,21 +933,7 @@ public class LuaState extends Lua {
|
||||
}
|
||||
}
|
||||
if (h.isFunction()) {
|
||||
int oldtop = top;
|
||||
int oldbase = base;
|
||||
try {
|
||||
base = base + this.calls[cc].closure.p.maxstacksize;
|
||||
top = base;
|
||||
pushlvalue(h);
|
||||
pushlvalue(table);
|
||||
pushlvalue(key);
|
||||
call(2,1);
|
||||
return poplvalue();
|
||||
} finally {
|
||||
resettop();
|
||||
base = oldbase;
|
||||
top = oldtop;
|
||||
}
|
||||
return ((LFunction)h).__index(this, table, key);
|
||||
}
|
||||
t = h;
|
||||
}
|
||||
@@ -952,6 +941,7 @@ public class LuaState extends Lua {
|
||||
return LNil.NIL;
|
||||
}
|
||||
|
||||
/** Get a key from a table using full metatable processing */
|
||||
public void luaV_settable(LValue table, LValue key, LValue val) {
|
||||
LValue h=LNil.NIL,t=table;
|
||||
for ( int loop=0; loop<MAXTAGLOOP; loop++ ) {
|
||||
@@ -973,22 +963,8 @@ public class LuaState extends Lua {
|
||||
}
|
||||
}
|
||||
if (h.isFunction()) {
|
||||
int oldtop = top;
|
||||
int oldbase = base;
|
||||
try {
|
||||
base = base + this.calls[cc].closure.p.maxstacksize;
|
||||
top = base;
|
||||
pushlvalue(h);
|
||||
pushlvalue(table);
|
||||
pushlvalue(key);
|
||||
pushlvalue(val);
|
||||
call(3,0);
|
||||
return;
|
||||
} finally {
|
||||
resettop();
|
||||
base = oldbase;
|
||||
top = oldtop;
|
||||
}
|
||||
((LFunction)h).__newindex(this, table, key, val);
|
||||
return;
|
||||
}
|
||||
t = h;
|
||||
}
|
||||
@@ -1432,7 +1408,7 @@ public class LuaState extends Lua {
|
||||
*/
|
||||
public void getfield(int index, LString k) {
|
||||
LTable t = totable(index);
|
||||
pushlvalue( luaV_gettable(t, k) );
|
||||
pushlvalue( t.luaGetTable(this, k) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1448,7 +1424,7 @@ public class LuaState extends Lua {
|
||||
* </pre>
|
||||
*/
|
||||
public void getglobal(String s) {
|
||||
pushlvalue( luaV_gettable(_G, new LString(s)) );
|
||||
pushlvalue( _G.luaGetTable(this, new LString(s)) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1487,7 +1463,7 @@ public class LuaState extends Lua {
|
||||
public void gettable(int index) {
|
||||
LValue t = totable(index);
|
||||
LValue k = poplvalue();
|
||||
pushlvalue( luaV_gettable(t, k) );
|
||||
pushlvalue( t.luaGetTable(this, k) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2101,7 +2077,7 @@ public class LuaState extends Lua {
|
||||
*/
|
||||
public void setfield(int index, LString k) {
|
||||
LTable t = totable(index);
|
||||
luaV_settable(t, k, poplvalue());
|
||||
t.luaSetTable(this, k, poplvalue());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2118,7 +2094,7 @@ public class LuaState extends Lua {
|
||||
* </pre>
|
||||
*/
|
||||
public void setglobal(String name) {
|
||||
luaV_settable(_G, new LString(name), poplvalue());
|
||||
_G.luaSetTable(this, new LString(name), poplvalue());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2158,7 +2134,7 @@ public class LuaState extends Lua {
|
||||
LTable t = totable(index);
|
||||
LValue v = poplvalue();
|
||||
LValue k = poplvalue();
|
||||
luaV_settable(t, k, v);
|
||||
t.luaSetTable(this, k, v);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2637,4 +2613,84 @@ public class LuaState extends Lua {
|
||||
public static void vmerror(String description) {
|
||||
throw new LuaErrorException( "internal error: "+description );
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a function with no arguments and one return value
|
||||
* @param function
|
||||
* @return
|
||||
*/
|
||||
public LValue call(LFunction function) {
|
||||
int oldtop = top;
|
||||
try {
|
||||
top = base + this.calls[cc].closure.p.maxstacksize;
|
||||
pushlvalue(function);
|
||||
call(0,1);
|
||||
return poplvalue();
|
||||
} finally {
|
||||
top = oldtop;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a function with one argument and one return value
|
||||
* @param function
|
||||
* @param arg0
|
||||
* @return
|
||||
*/
|
||||
public LValue call(LFunction function, LValue arg0) {
|
||||
int oldtop = top;
|
||||
try {
|
||||
top = base + this.calls[cc].closure.p.maxstacksize;
|
||||
pushlvalue(function);
|
||||
pushlvalue(arg0);
|
||||
call(1,1);
|
||||
return poplvalue();
|
||||
} finally {
|
||||
top = oldtop;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a function with two arguments and one return value
|
||||
* @param function
|
||||
* @param arg0
|
||||
* @param arg1
|
||||
* @return
|
||||
*/
|
||||
public LValue call(LFunction function, LValue arg0, LValue arg1) {
|
||||
int oldtop = top;
|
||||
try {
|
||||
top = base + this.calls[cc].closure.p.maxstacksize;
|
||||
pushlvalue(function);
|
||||
pushlvalue(arg0);
|
||||
pushlvalue(arg1);
|
||||
call(2,1);
|
||||
return poplvalue();
|
||||
} finally {
|
||||
top = oldtop;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a function with three arguments and one return value
|
||||
* @param function
|
||||
* @param arg0
|
||||
* @param arg1
|
||||
* @param arg2
|
||||
* @return
|
||||
*/
|
||||
public LValue call(LFunction function, LValue arg0, LValue arg1, LValue arg2) {
|
||||
int oldtop = top;
|
||||
try {
|
||||
top = base + this.calls[cc].closure.p.maxstacksize;
|
||||
pushlvalue(function);
|
||||
pushlvalue(arg0);
|
||||
pushlvalue(arg1);
|
||||
pushlvalue(arg2);
|
||||
call(3,1);
|
||||
return poplvalue();
|
||||
} finally {
|
||||
top = oldtop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user