Let all libraries implement invoke() instead of luaStackCall, correct off-by-one error on argument type check functions.

This commit is contained in:
James Roseborough
2009-04-09 16:27:01 +00:00
parent a414314114
commit 1d40b52348
11 changed files with 478 additions and 583 deletions

View File

@@ -120,112 +120,104 @@ public class BaseLib extends LFunction {
vm.pushstring( message ); vm.pushstring( message );
} }
public boolean luaStackCall(LuaState vm) { public int invoke(LuaState vm) {
switch ( id ) { switch ( id ) {
case PRINT: { case PRINT: {
int n = vm.gettop(); int n = vm.gettop();
vm.getglobal("tostring"); vm.getglobal("tostring");
for ( int i=2; i<=n; i++ ) { for ( int i=1; i<=n; i++ ) {
vm.pushvalue(-1); vm.pushvalue(-1);
vm.pushvalue(i); vm.pushvalue(i);
vm.call(1, 1); vm.call(1, 1);
if ( vm.type(-1) != Lua.LUA_TSTRING ) if ( vm.type(-1) != Lua.LUA_TSTRING )
vm.error( "'tostring' must return a string to 'print'" ); vm.error( "'tostring' must return a string to 'print'" );
if ( i > 2 ) if ( i > 1 )
STDOUT.print( "\t" ); STDOUT.print( "\t" );
STDOUT.print( vm.tostring(-1) ); STDOUT.print( vm.tostring(-1) );
vm.poplvalue(); vm.poplvalue();
} }
STDOUT.println(); STDOUT.println();
vm.resettop(); return 0;
break;
} }
case IPAIRS: { case IPAIRS: {
LTable t = vm.checktable(2); LTable t = vm.checktable(1);
vm.resettop();
vm.pushfunction( inext ); vm.pushfunction( inext );
vm.pushlvalue( t ); vm.pushlvalue( t );
vm.pushinteger( 0 ); vm.pushinteger( 0 );
break; return 3;
} }
case PAIRS: { case PAIRS: {
LTable t = vm.checktable(2); LTable t = vm.checktable(1);
vm.resettop();
vm.pushfunction( next ); vm.pushfunction( next );
vm.pushlvalue( t ); vm.pushlvalue( t );
vm.pushnil(); vm.pushnil();
break; return 3;
} }
case INEXT: { case INEXT: {
int i = vm.checkint(3) + 1; int i = vm.checkint(2) + 1;
LTable t = vm.checktable(2); LTable t = vm.checktable(1);
LValue v = t.get(i); LValue v = t.get(i);
vm.resettop();
if ( !v.isNil() ) { if ( !v.isNil() ) {
vm.pushinteger(i); vm.pushinteger(i);
vm.pushlvalue(v); vm.pushlvalue(v);
return 2;
} }
break; return 0;
} }
case NEXT: { case NEXT: {
LTable t = vm.checktable(2); LTable t = vm.checktable(1);
LValue k = vm.topointer(3); LValue k = vm.topointer(2);
vm.resettop(); vm.resettop();
t.next(vm,k,false); t.next(vm,k,false);
break; return -1;
} }
case GETMETATABLE: { case GETMETATABLE: {
vm.checkany(2); vm.checkany(1);
if ( ! vm.getmetatable(2) ) { if ( ! vm.getmetatable(1) ) {
vm.resettop();
vm.pushnil(); vm.pushnil();
return 1;
} else { } else {
vm.replace(1);
vm.settop(1);
vm.getfield(-1,LValue.TM_METATABLE); vm.getfield(-1,LValue.TM_METATABLE);
if ( vm.isnil(-1) ) if ( vm.isnil(-1) )
vm.pop(1); vm.pop(1);
else
vm.remove(1);
} }
break; return 1;
} }
case SETMETATABLE: { case SETMETATABLE: {
LTable t = vm.checktable(2); LTable t = vm.checktable(1);
LValue v = vm.checkany(3); LValue v = vm.checkany(2);
vm.argcheck(v.isTable() || v.isNil(), 3, "table or nil expected"); vm.argcheck(v.isTable() || v.isNil(), 2, "table or nil expected");
t = t.luaSetMetatable(v); t = t.luaSetMetatable(v);
vm.resettop();
vm.pushlvalue(t); vm.pushlvalue(t);
break; return 1;
} }
case TYPE: { case TYPE: {
LValue v = vm.checkany(2); LValue v = vm.checkany(1);
vm.resettop();
vm.pushlstring( v.luaGetTypeName() ); vm.pushlstring( v.luaGetTypeName() );
break; return 1;
} }
case PCALL: { case PCALL: {
vm.checkany(2); vm.checkany(1);
int n = vm.gettop(); int n = vm.gettop();
int s = vm.pcall( n-2, Lua.LUA_MULTRET, 0 ); int s = vm.pcall( n-1, Lua.LUA_MULTRET, 0 );
if ( s == 0 ) { // success, results are on stack above the pcall if ( s == 0 ) { // success, results are on stack
vm.remove( 1 );
vm.pushboolean( true ); vm.pushboolean( true );
vm.insert( 1 ); vm.insert( 1 );
return -1;
} else { // error, error message is on the stack } else { // error, error message is on the stack
vm.pushboolean( false ); vm.pushboolean( false );
vm.insert( 1 ); vm.insert( -2 );
return 2;
} }
break;
} }
case XPCALL: { case XPCALL: {
LValue errfun = vm.checkany(3); LValue errfun = vm.checkany(3);
vm.settop(2); vm.settop(1);
int s = vm.pcall( 0, Lua.LUA_MULTRET, 0 ); int s = vm.pcall( 0, Lua.LUA_MULTRET, 0 );
if ( s == 0 ) { // success, results are on stack above the xpcall if ( s == 0 ) { // success, results are on stack
vm.pushboolean( true ); vm.pushboolean( true );
vm.replace( 1 ); vm.insert( 1 );
return -1;
} else { // error, error message is on the stack } else { // error, error message is on the stack
vm.pushlvalue( errfun ); vm.pushlvalue( errfun );
vm.insert( 1 ); vm.insert( 1 );
@@ -233,113 +225,105 @@ public class BaseLib extends LFunction {
if ( s == 0 ) { if ( s == 0 ) {
vm.pushboolean( false ); vm.pushboolean( false );
vm.insert( 1 ); vm.insert( 1 );
return -1;
} else { // error in error handler } else { // error in error handler
vm.resettop();
vm.pushboolean(false); vm.pushboolean(false);
vm.pushstring("error in error handling"); vm.pushstring("error in error handling");
return 2;
} }
} }
break;
} }
case ERROR: { case ERROR: {
vm.error(vm.optstring(2,null), vm.optint(3,1)); vm.error(vm.optstring(1,null), vm.optint(2,1));
break; return 0;
} }
case ASSERT: { case ASSERT: {
if ( ! vm.toboolean(2) ) if ( ! vm.toboolean(1) )
vm.error( vm.optstring(3,"assertion failed!") ); vm.error( vm.optstring(2,"assertion failed!") );
vm.remove(1); return -1;
break;
} }
case LOADFILE: case LOADFILE:
loadfile(vm, vm.optstring(2,null)); loadfile(vm, vm.optstring(1,null));
break; return -1;
case TONUMBER: { case TONUMBER: {
int base = vm.optint(3, 10); int base = vm.optint(2, 10);
if (base == 10) { /* standard conversion */ if (base == 10) { /* standard conversion */
vm.checkany(2); vm.checkany(1);
LValue v = vm.tolnumber(2); LValue v = vm.tolnumber(1);
vm.resettop();
vm.pushlvalue(v); vm.pushlvalue(v);
return 1;
} else { } else {
if ( base < 2 || base > 36 ) if ( base < 2 || base > 36 )
vm.typerror(3, "base out of range"); vm.argerror(2, "base out of range");
LString s = vm.checklstring(2); LString s = vm.checklstring(1);
vm.resettop();
vm.pushlvalue( s.luaToNumber(base) ); vm.pushlvalue( s.luaToNumber(base) );
return 1;
} }
break;
} }
case RAWEQUAL: { case RAWEQUAL: {
LValue a = vm.checkany(2); LValue a = vm.checkany(1);
LValue b = vm.checkany(3); LValue b = vm.checkany(2);
vm.resettop();
vm.pushboolean(a == b); vm.pushboolean(a == b);
break; return 1;
} }
case RAWGET: { case RAWGET: {
LTable t = vm.checktable(2); LTable t = vm.checktable(1);
LValue k = vm.checkany(3); LValue k = vm.checkany(2);
vm.resettop();
vm.pushlvalue( t.get( k ) ); vm.pushlvalue( t.get( k ) );
break; return 1;
} }
case RAWSET: { case RAWSET: {
LTable t = vm.checktable(2); LTable t = vm.checktable(1);
LValue k = vm.checkany(3); LValue k = vm.checkany(2);
LValue v = vm.checkany(4); LValue v = vm.checkany(3);
t.put( k, v ); t.put( k, v );
vm.resettop();
vm.pushlvalue(t); vm.pushlvalue(t);
break; return 1;
} }
case GETFENV: { case GETFENV: {
LValue f = getfunc(vm, true); LValue f = getfunc(vm, true);
vm.resettop();
vm.pushlvalue(f.luaGetEnv(vm._G)); vm.pushlvalue(f.luaGetEnv(vm._G));
break; return 1;
} }
case SETFENV: { case SETFENV: {
LTable t = vm.checktable(3); LTable t = vm.checktable(2);
LValue f = getfunc(vm, false); if ( vm.isnumber(1) && vm.tointeger(1) == 0 ) {
if ( vm.isnumber(2) && vm.tointeger(2) == 0 ) {
vm._G = t; vm._G = t;
} else if ( (!(f instanceof LClosure)) || ! f.luaSetEnv(t) ) { } else {
vm.error( "'setfenv' cannot change environment of given object" ); LValue f = getfunc(vm, false);
if ( (!(f instanceof LClosure)) || ! f.luaSetEnv(t) )
vm.error( "'setfenv' cannot change environment of given object" );
vm.pushlvalue(f);
return 1;
} }
vm.resettop();
vm.pushlvalue(f);
break;
} }
case SELECT: { case SELECT: {
vm.checkany(2); vm.checkany(1);
int n = vm.gettop(); int n = vm.gettop();
if ( vm.isnumber(2) ) { if ( vm.isnumber(1) ) {
int index = vm.tolnumber(2).toJavaInt(); int index = vm.tolnumber(1).toJavaInt();
if ( index < 0 ) if ( index < 0 )
index += n-1; index += n;
if ( index <= 0 ) if ( index <= 0 )
vm.typerror( 2, "index out of range" ); vm.argerror( 1, "index out of range" );
if ( index >= n ) if ( index >= n )
vm.resettop(); return 0;
else { else {
for ( int i=0; i<=index; i++ ) return n-index;
vm.remove(1);
} }
} else if ( vm.checkstring(2).equals( "#" ) ) { } else if ( vm.checkstring(1).equals( "#" ) ) {
vm.resettop(); vm.pushnumber( n - 1 );
vm.pushnumber( n - 2 ); return 1;
} else { } else {
vm.typerror(2,"expected number or '#'"); vm.typerror(1,"expected number or '#'");
return 0;
} }
break;
} }
case COLLECTGARBAGE: { case COLLECTGARBAGE: {
String s = vm.optstring(2, "collect"); String s = vm.optstring(1, "collect");
int result = 0; int result = 0;
vm.resettop();
if ( "collect".equals(s) ) if ( "collect".equals(s) )
System.gc(); System.gc();
else if ( "count".equals(s) ) { else if ( "count".equals(s) ) {
@@ -347,33 +331,32 @@ public class BaseLib extends LFunction {
long used = rt.totalMemory() - rt.freeMemory(); long used = rt.totalMemory() - rt.freeMemory();
result = (int) (used >> 10); result = (int) (used >> 10);
} else { } else {
vm.typerror(2,"gc op"); vm.argerror(2,"gc op");
} }
vm.pushnumber(result); vm.pushnumber(result);
break; return 1;
} }
case DOFILE: case DOFILE:
dofile(vm); dofile(vm);
break; return -1;
case LOADSTRING: case LOADSTRING:
loadstring(vm, vm.checklstring(2), vm.optstring(3,"(string)")); loadstring(vm, vm.checklstring(1), vm.optstring(2,"(string)"));
break; return -1;
case LOAD: case LOAD:
load(vm); load(vm);
break; return -1;
case TOSTRING: { case TOSTRING: {
LValue v = vm.checkany(2); LValue v = vm.checkany(1);
vm.resettop();
vm.pushlvalue( v.luaAsString() ); vm.pushlvalue( v.luaAsString() );
break; return 1;
} }
case UNPACK: { case UNPACK: {
LTable list = vm.checktable(2); LTable list = vm.checktable(1);
int n = vm.gettop(); int n = vm.gettop();
int i = vm.optint(3,1); int i = vm.optint(2,1);
int j; int j;
if ( n >= 4 ) { if ( n >= 3 ) {
j = vm.checkint(4); j = vm.checkint(3);
} else { } else {
j = list.luaLength(); j = list.luaLength();
} }
@@ -381,21 +364,21 @@ public class BaseLib extends LFunction {
vm.checkstack(j+1-i); vm.checkstack(j+1-i);
for ( int k=i; k<=j; k++ ) for ( int k=i; k<=j; k++ )
vm.pushlvalue(list.get(k)); vm.pushlvalue(list.get(k));
break; return -1;
} }
default: default:
LuaState.vmerror( "bad base id" ); LuaState.vmerror( "bad base id" );
return 0;
} }
return false;
} }
private static LValue getfunc (LuaState vm, boolean opt) { private static LValue getfunc (LuaState vm, boolean opt) {
if ( vm.isfunction(2) ) if ( vm.isfunction(1) )
return vm.tofunction(2); return vm.tofunction(1);
else { else {
int level = opt? vm.optint(2, 1): vm.checkint(2); int level = opt? vm.optint(1, 1): vm.checkint(1);
vm.argcheck(level >= 0, 2, "level must be non-negative"); vm.argcheck(level >= 0, 1, "level must be non-negative");
vm.argcheck(level-1 <= vm.cc, 2, "invalid level"); vm.argcheck(level-1 <= vm.cc, 1, "invalid level");
CallInfo ci = vm.getStackFrame(level-1); CallInfo ci = vm.getStackFrame(level-1);
if ( ci == null || ci.closure == null ) if ( ci == null || ci.closure == null )
return LNil.NIL; return LNil.NIL;
@@ -483,7 +466,7 @@ public class BaseLib extends LFunction {
// if load succeeds, return 0 for success, 1 for error (as per lua spec) // if load succeeds, return 0 for success, 1 for error (as per lua spec)
private void dofile( LuaState vm ) { private void dofile( LuaState vm ) {
String filename = vm.optstring(2,null); String filename = vm.optstring(1,null);
if ( loadfile( vm, filename ) ) { if ( loadfile( vm, filename ) ) {
vm.call(0, 0); vm.call(0, 0);
} else { } else {

View File

@@ -21,7 +21,6 @@
******************************************************************************/ ******************************************************************************/
package org.luaj.lib; package org.luaj.lib;
import org.luaj.vm.LClosure;
import org.luaj.vm.LFunction; import org.luaj.vm.LFunction;
import org.luaj.vm.LTable; import org.luaj.vm.LTable;
import org.luaj.vm.LThread; import org.luaj.vm.LThread;
@@ -79,21 +78,21 @@ public class CoroutineLib extends LFunction {
this.thread = thread; this.thread = thread;
} }
public boolean luaStackCall( LuaState vm ) { public int invoke( LuaState vm ) {
switch ( id ) { switch ( id ) {
case INSTALL: { case INSTALL: {
install(vm._G); install(vm._G);
break; return 0;
} }
case CREATE: { case CREATE: {
LFunction c = vm.checkfunction(2); LFunction c = vm.checkfunction(1);
vm.pushlvalue( new LThread( c, c.luaGetEnv(vm._G) ) ); vm.pushlvalue( new LThread( c, c.luaGetEnv(vm._G) ) );
break; return 1;
} }
case RESUME: { case RESUME: {
LThread t = vm.checkthread(2); LThread t = vm.checkthread(1);
t.resumeFrom( vm, vm.gettop()-2 ); t.resumeFrom( vm, vm.gettop()-1 );
return false; return -1;
} }
case RUNNING: { case RUNNING: {
LThread r = LThread.getRunning(); LThread r = LThread.getRunning();
@@ -102,39 +101,41 @@ public class CoroutineLib extends LFunction {
} else { } else {
vm.pushnil(); vm.pushnil();
} }
break; return 1;
} }
case STATUS: { case STATUS: {
vm.pushstring( vm.checkthread(2).getStatus() ); vm.pushstring( vm.checkthread(1).getStatus() );
break; return 1;
} }
case WRAP: { case WRAP: {
LFunction c = vm.checkfunction(2); LFunction c = vm.checkfunction(1);
vm.pushlvalue( new CoroutineLib(WRAPPED,new LThread(c, c.luaGetEnv(vm._G))) ); vm.pushlvalue( new CoroutineLib(WRAPPED,new LThread(c, c.luaGetEnv(vm._G))) );
break; return 1;
} }
case YIELD: { case YIELD: {
LThread r = LThread.getRunning(); LThread r = LThread.getRunning();
if ( r == null ) if ( r == null ) {
vm.error("main thread can't yield"); vm.error("main thread can't yield");
else { return 0;
return r.yield();
} }
r.yield();
return -1;
} }
case WRAPPED: { case WRAPPED: {
LThread t = this.thread; LThread t = this.thread;
t.resumeFrom( vm, vm.gettop()-1 ); t.resumeFrom( vm, vm.gettop() );
if ( vm.toboolean(1) ) if ( vm.toboolean(1) ) {
vm.remove(1); vm.remove(1);
else return -1;
} else {
vm.error( vm.tostring(2) ); vm.error( vm.tostring(2) );
return false; return 0;
}
}
default: {
LuaState.vmerror( "bad coroutine id" );
return 0;
} }
} }
vm.insert(1);
vm.settop(1);
return false;
} }
} }

View File

@@ -108,88 +108,74 @@ public class DebugLib extends LFunction {
return NAMES[id]+"()"; return NAMES[id]+"()";
} }
public boolean luaStackCall( LuaState vm ) { public int invoke( LuaState vm ) {
switch ( id ) { switch ( id ) {
case INSTALL: case INSTALL:
install(vm); install(vm);
break; return 0;
case DEBUG: case DEBUG:
debug(vm); return debug(vm);
break;
case GETFENV: case GETFENV:
getfenv(vm); return getfenv(vm);
break;
case GETHOOK: case GETHOOK:
gethook(vm); return gethook(vm);
break;
case GETINFO: case GETINFO:
getinfo(vm); return getinfo(vm);
break;
case GETLOCAL: case GETLOCAL:
getlocal(vm); return getlocal(vm);
break;
case GETMETATABLE: case GETMETATABLE:
getmetatable(vm); return getmetatable(vm);
break;
case GETREGISTRY: case GETREGISTRY:
getregistry(vm); return getregistry(vm);
break;
case GETUPVALUE: case GETUPVALUE:
getupvalue(vm); return getupvalue(vm);
break;
case SETFENV: case SETFENV:
setfenv(vm); return setfenv(vm);
break;
case SETHOOK: case SETHOOK:
sethook(vm); return sethook(vm);
break;
case SETLOCAL: case SETLOCAL:
setlocal(vm); return setlocal(vm);
break;
case SETMETATABLE: case SETMETATABLE:
setmetatable(vm); return setmetatable(vm);
break;
case SETUPVALUE: case SETUPVALUE:
setupvalue(vm); return setupvalue(vm);
break;
case TRACEBACK: case TRACEBACK:
traceback(vm); return traceback(vm);
break;
default: default:
LuaState.vmerror( "bad package id" ); LuaState.vmerror( "bad package id" );
return 0;
} }
return false;
} }
// j2se subclass may wish to override and provide actual console here. // j2se subclass may wish to override and provide actual console here.
// j2me platform has not System.in to provide console. // j2me platform has not System.in to provide console.
protected void debug(LuaState vm) { protected int debug(LuaState vm) {
vm.resettop(); return 0;
} }
protected void gethook(LuaState vm) { protected int gethook(LuaState vm) {
LuaState threadVm = vm; LuaState threadVm = vm;
if ( vm.gettop() >= 2 ) if ( vm.gettop() >= 2 )
threadVm = vm.checkthread(2).vm; threadVm = vm.checkthread(1).vm;
vm.resettop();
vm.pushlvalue(threadVm.gethook()); vm.pushlvalue(threadVm.gethook());
vm.pushinteger(threadVm.gethookmask()); vm.pushinteger(threadVm.gethookmask());
vm.pushinteger(threadVm.gethookcount()); vm.pushinteger(threadVm.gethookcount());
return 3;
} }
protected LuaState optthreadvm(LuaState vm, int index) { protected LuaState optthreadvm(LuaState vm, int index) {
if ( ! vm.isthread(2) ) if ( ! vm.isthread(index) )
return vm; return vm;
LuaState threadVm = vm.checkthread(2).vm; LuaState threadVm = vm.checkthread(index).vm;
vm.remove(2); vm.remove(index);
return threadVm; return threadVm;
} }
protected void sethook(LuaState vm) { protected int sethook(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 2); LuaState threadVm = optthreadvm(vm, 1);
LFunction func = vm.isnoneornil(2)? null: vm.checkfunction(2); LFunction func = vm.isnoneornil(1)? null: vm.checkfunction(2);
String str = vm.optstring(3,""); String str = vm.optstring(2,"");
int count = vm.optint(4,0); int count = vm.optint(3,0);
int mask = 0; int mask = 0;
for ( int i=0; i<str.length(); i++ ) for ( int i=0; i<str.length(); i++ )
switch ( str.charAt(i) ) { switch ( str.charAt(i) ) {
@@ -198,41 +184,40 @@ public class DebugLib extends LFunction {
case 'r': mask |= LuaState.LUA_MASKRET; break; case 'r': mask |= LuaState.LUA_MASKRET; break;
} }
threadVm.sethook(func, mask, count); threadVm.sethook(func, mask, count);
vm.resettop(); return 0;
} }
protected void getfenv(LuaState vm) { protected int getfenv(LuaState vm) {
LValue object = vm.topointer(2); LValue object = vm.topointer(1);
LValue env = object.luaGetEnv(null); LValue env = object.luaGetEnv(null);
vm.resettop();
vm.pushlvalue(env!=null? env: LNil.NIL); vm.pushlvalue(env!=null? env: LNil.NIL);
return 1;
} }
protected void setfenv(LuaState vm) { protected int setfenv(LuaState vm) {
LValue object = vm.topointer(2); LValue object = vm.topointer(1);
LTable table = vm.checktable(3); LTable table = vm.checktable(2);
object.luaSetEnv(table); object.luaSetEnv(table);
vm.settop(1); vm.settop(1);
return 1;
} }
protected void getinfo(LuaState vm) { protected int getinfo(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 2); LuaState threadVm = optthreadvm(vm, 1);
String what = vm.optstring(3, "nSluf"); String what = vm.optstring(2, "nSluf");
// find the stack info // find the stack info
StackInfo si; StackInfo si;
if ( vm.isnumber(2) ) { if ( vm.isnumber(1) ) {
int level = vm.tointeger(2); int level = vm.tointeger(1);
si = getstackinfo(threadVm, level, 1)[0]; si = getstackinfo(threadVm, level, 1)[0];
if ( si == null ) { if ( si == null ) {
vm.resettop(); return 0;
return;
} }
} else { } else {
LFunction func = vm.checkfunction(2); LFunction func = vm.checkfunction(1);
si = findstackinfo(threadVm, func); si = findstackinfo(threadVm, func);
} }
vm.resettop();
// look up info // look up info
LTable info = new LTable(); LTable info = new LTable();
@@ -288,75 +273,75 @@ public class DebugLib extends LFunction {
} }
} }
} }
return 1;
} }
protected void getlocal(LuaState vm) { protected int getlocal(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 2); LuaState threadVm = optthreadvm(vm, 1);
int level = vm.checkint(2); int level = vm.checkint(1);
int local = vm.checkint(3); int local = vm.checkint(2);
StackInfo si = getstackinfo(threadVm, level, 1)[0]; StackInfo si = getstackinfo(threadVm, level, 1)[0];
CallInfo ci = (si!=null? si.luainfo: null); CallInfo ci = (si!=null? si.luainfo: null);
LPrototype p = (ci!=null? ci.closure.p: null); LPrototype p = (ci!=null? ci.closure.p: null);
LString name = (p!=null? p.getlocalname(local, ci.pc>0? ci.pc-1: 0): null); LString name = (p!=null? p.getlocalname(local, ci.pc>0? ci.pc-1: 0): null);
if ( name != null ) { if ( name != null ) {
LValue value = threadVm.stack[ci.base+(local-1)]; LValue value = threadVm.stack[ci.base+(local-1)];
vm.resettop();
vm.pushlvalue( name ); vm.pushlvalue( name );
vm.pushlvalue( value ); vm.pushlvalue( value );
return 2;
} else { } else {
vm.resettop();
vm.pushnil(); vm.pushnil();
return 1;
} }
} }
protected void setlocal(LuaState vm) { protected int setlocal(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 2); LuaState threadVm = optthreadvm(vm, 1);
int level = vm.checkint(2); int level = vm.checkint(1);
int local = vm.checkint(3); int local = vm.checkint(2);
LValue value = vm.topointer(4); LValue value = vm.topointer(3);
StackInfo si = getstackinfo(threadVm, level, 1)[0]; StackInfo si = getstackinfo(threadVm, level, 1)[0];
CallInfo ci = (si!=null? si.luainfo: null); CallInfo ci = (si!=null? si.luainfo: null);
LPrototype p = (ci!=null? ci.closure.p: null); LPrototype p = (ci!=null? ci.closure.p: null);
LString name = (p!=null? p.getlocalname(local, ci.pc>0? ci.pc-1: 0): null); LString name = (p!=null? p.getlocalname(local, ci.pc>0? ci.pc-1: 0): null);
if ( name != null ) { if ( name != null ) {
threadVm.stack[ci.base+(local-1)] = value; threadVm.stack[ci.base+(local-1)] = value;
vm.resettop();
vm.pushlvalue(name); vm.pushlvalue(name);
} else { } else {
vm.resettop();
vm.pushnil(); vm.pushnil();
} }
return 1;
} }
protected void getmetatable(LuaState vm) { protected int getmetatable(LuaState vm) {
LValue object = vm.topointer(2); LValue object = vm.topointer(1);
vm.resettop();
LValue mt = object.luaGetMetatable(); LValue mt = object.luaGetMetatable();
if ( mt != null ) if ( mt != null )
vm.pushlvalue( object.luaGetMetatable() ); vm.pushlvalue( object.luaGetMetatable() );
else else
vm.pushnil(); vm.pushnil();
return 1;
} }
protected void setmetatable(LuaState vm) { protected int setmetatable(LuaState vm) {
LValue object = vm.topointer(2); LValue object = vm.topointer(1);
try { try {
if ( ! vm.isnoneornil(3) ) if ( ! vm.isnoneornil(2) )
object.luaSetMetatable(vm.checktable(3)); object.luaSetMetatable(vm.checktable(3));
else else
object.luaSetMetatable(null); object.luaSetMetatable(null);
vm.resettop();
vm.pushboolean(true); vm.pushboolean(true);
return 1;
} catch ( LuaErrorException e ) { } catch ( LuaErrorException e ) {
vm.resettop();
vm.pushboolean(false); vm.pushboolean(false);
vm.pushstring(e.toString()); vm.pushstring(e.toString());
return 2;
} }
} }
protected void getregistry(LuaState vm) { protected int getregistry(LuaState vm) {
vm.resettop();
vm.pushlvalue( new LTable() ); vm.pushlvalue( new LTable() );
return 1;
} }
private LString findupvalue(LClosure c, int up) { private LString findupvalue(LClosure c, int up) {
@@ -369,9 +354,9 @@ public class DebugLib extends LFunction {
return null; return null;
} }
protected void getupvalue(LuaState vm) { protected int getupvalue(LuaState vm) {
LFunction func = vm.checkfunction(2); LFunction func = vm.checkfunction(1);
int up = vm.checkint(3); int up = vm.checkint(2);
vm.resettop(); vm.resettop();
if ( func instanceof LClosure ) { if ( func instanceof LClosure ) {
LClosure c = (LClosure) func; LClosure c = (LClosure) func;
@@ -379,16 +364,17 @@ public class DebugLib extends LFunction {
if ( name != null ) { if ( name != null ) {
vm.pushlstring(name); vm.pushlstring(name);
vm.pushlvalue(c.upVals[up-1].getValue()); vm.pushlvalue(c.upVals[up-1].getValue());
return; return 2;
} }
} }
vm.pushnil(); vm.pushnil();
return 1;
} }
protected void setupvalue(LuaState vm) { protected int setupvalue(LuaState vm) {
LFunction func = vm.checkfunction(2); LFunction func = vm.checkfunction(1);
int up = vm.checkint(3); int up = vm.checkint(2);
LValue value = vm.topointer(4); LValue value = vm.topointer(3);
vm.resettop(); vm.resettop();
if ( func instanceof LClosure ) { if ( func instanceof LClosure ) {
LClosure c = (LClosure) func; LClosure c = (LClosure) func;
@@ -396,18 +382,19 @@ public class DebugLib extends LFunction {
if ( name != null ) { if ( name != null ) {
c.upVals[up-1].setValue(value); c.upVals[up-1].setValue(value);
vm.pushlstring(name); vm.pushlstring(name);
return; return 1;
} }
} }
vm.pushnil(); vm.pushnil();
return 1;
} }
protected void traceback(LuaState vm) { protected int traceback(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 2); LuaState threadVm = optthreadvm(vm, 1);
String message = ""; String message = "";
int level = vm.optint(3,1); int level = vm.optint(2,1);
if ( ! vm.isnoneornil(2) ) if ( ! vm.isnoneornil(1) )
message = vm.checkstring(2)+"\n"; message = vm.checkstring(1)+"\n";
StackInfo[] s = getstackinfo(threadVm, level, 10); StackInfo[] s = getstackinfo(threadVm, level, 10);
StringBuffer sb = new StringBuffer("stack traceback:"); StringBuffer sb = new StringBuffer("stack traceback:");
for ( int i=0; i<s.length; i++ ) { for ( int i=0; i<s.length; i++ ) {
@@ -419,8 +406,8 @@ public class DebugLib extends LFunction {
sb.append( si.tracename() ); sb.append( si.tracename() );
} }
} }
vm.resettop();
vm.pushstring(message+sb); vm.pushstring(message+sb);
return 1;
} }
// ======================================================= // =======================================================

View File

@@ -214,7 +214,7 @@ public class IoLib extends LFunction {
return LNil.NIL; return LNil.NIL;
} }
public boolean luaStackCall( LuaState vm ) { public int invoke( LuaState vm ) {
File f; File f;
int n; int n;
try { try {
@@ -222,49 +222,47 @@ public class IoLib extends LFunction {
/* Load the table library dynamically */ /* Load the table library dynamically */
case INSTALL: case INSTALL:
initialize(vm._G); initialize(vm._G);
break; return 0;
case IO_CLOSE: case IO_CLOSE:
f = vm.isnoneornil(2)? f = vm.isnoneornil(1)?
output(vm): output(vm):
checkfile(vm,2); checkfile(vm,1);
checkopen(vm, f); checkopen(vm, f);
ioclose(vm,f); ioclose(vm,f);
break; break;
case IO_FLUSH: case IO_FLUSH:
checkopen(vm,output(vm)); checkopen(vm,output(vm));
OUTPUT.flush(); OUTPUT.flush();
vm.resettop();
vm.pushboolean(true); vm.pushboolean(true);
break; return 1;
case IO_INPUT: case IO_INPUT:
INPUT = vm.isnoneornil(2)? INPUT = vm.isnoneornil(1)?
input(vm): input(vm):
vm.isstring(2)? vm.isstring(1)?
ioopenfile(vm,vm.checkstring(2),"r"): ioopenfile(vm,vm.checkstring(1),"r"):
checkfile(vm,2); checkfile(vm,1);
setresult(vm, INPUT); setresult(vm, INPUT);
break; break;
case IO_LINES: case IO_LINES:
INPUT = vm.isnoneornil(2)? INPUT = vm.isnoneornil(1)?
input(vm): input(vm):
ioopenfile(vm,vm.checkstring(2),"r"); ioopenfile(vm,vm.checkstring(1),"r");
checkopen(vm, INPUT); checkopen(vm, INPUT);
vm.resettop();
vm.pushlvalue(lines(vm,INPUT)); vm.pushlvalue(lines(vm,INPUT));
break; return 1;
case IO_OPEN: case IO_OPEN:
setresult(vm, rawopenfile(vm.checkstring(2), vm.optstring(3,"r"))); setresult(vm, rawopenfile(vm.checkstring(1), vm.optstring(2,"r")));
break; break;
case IO_OUTPUT: case IO_OUTPUT:
OUTPUT = vm.isnoneornil(2)? OUTPUT = vm.isnoneornil(1)?
output(vm): output(vm):
vm.isstring(2)? vm.isstring(1)?
ioopenfile(vm,vm.checkstring(2),"w"): ioopenfile(vm,vm.checkstring(1),"w"):
checkfile(vm,2); checkfile(vm,1);
setresult(vm, OUTPUT); setresult(vm, OUTPUT);
break; break;
case IO_POPEN: case IO_POPEN:
setresult(vm, openProgram(vm.checkstring(2),vm.optstring(3, "r"))); setresult(vm, openProgram(vm.checkstring(1),vm.optstring(2, "r")));
break; break;
case IO_READ: case IO_READ:
checkopen(vm, INPUT); checkopen(vm, INPUT);
@@ -274,54 +272,49 @@ public class IoLib extends LFunction {
setresult(vm, tmpFile()); setresult(vm, tmpFile());
break; break;
case IO_TYPE: case IO_TYPE:
f = optfile(vm,2); f = optfile(vm,1);
vm.resettop();
if ( f != null ) if ( f != null )
vm.pushstring(f.isclosed()? "closed file": "file"); vm.pushstring(f.isclosed()? "closed file": "file");
else else
vm.pushnil(); vm.pushnil();
break; return 1;
case IO_WRITE: case IO_WRITE:
checkopen(vm, output(vm)); checkopen(vm, output(vm));
iowrite( vm, OUTPUT ); iowrite( vm, OUTPUT );
break; break;
case FILE_CLOSE: case FILE_CLOSE:
f = checkfile(vm,2); f = checkfile(vm,1);
ioclose(vm, f); ioclose(vm, f);
break; break;
case FILE_FLUSH: case FILE_FLUSH:
f = checkfile(vm,2); f = checkfile(vm,1);
f.flush(); f.flush();
vm.resettop();
vm.pushboolean(true); vm.pushboolean(true);
break; return 1;
case FILE_LINES: case FILE_LINES:
f = checkfile(vm,2); f = checkfile(vm,1);
vm.resettop();
vm.pushlvalue(lines(vm,f)); vm.pushlvalue(lines(vm,f));
break; return 1;
case FILE_READ: case FILE_READ:
f = checkfile(vm,2); f = checkfile(vm,1);
vm.remove(2); vm.remove(1);
ioread(vm, f); ioread(vm, f);
break; break;
case FILE_SEEK: case FILE_SEEK:
f = checkfile(vm,2); f = checkfile(vm,1);
vm.remove(2); vm.remove(1);
n = f.seek(vm.optstring(2,"cur"),vm.optint(3, 0)); n = f.seek(vm.optstring(1,"cur"),vm.optint(2, 0));
vm.resettop();
vm.pushinteger(n); vm.pushinteger(n);
break; return 1;
case FILE_SETVBUF: case FILE_SETVBUF:
f = checkfile(vm,2); f = checkfile(vm,1);
vm.remove(2); vm.remove(1);
f.setvbuf(vm.checkstring(2),vm.optint(3, 1024)); f.setvbuf(vm.checkstring(1),vm.optint(2, 1024));
vm.resettop();
vm.pushboolean(true); vm.pushboolean(true);
break; return 1;
case FILE_WRITE: case FILE_WRITE:
f = checkfile(vm,2); f = checkfile(vm,1);
vm.remove(2); vm.remove(1);
iowrite( vm, f ); iowrite( vm, f );
break; break;
default: default:
@@ -330,7 +323,7 @@ public class IoLib extends LFunction {
} catch ( IOException ioe ) { } catch ( IOException ioe ) {
seterrorresult(vm,ioe); seterrorresult(vm,ioe);
} }
return false; return -1;
} }
private static void ioclose(LuaState vm, File f) throws IOException { private static void ioclose(LuaState vm, File f) throws IOException {
@@ -373,7 +366,7 @@ public class IoLib extends LFunction {
} }
private static void iowrite(LuaState vm, File f) throws IOException { private static void iowrite(LuaState vm, File f) throws IOException {
for ( int i=2, n=vm.gettop(); i<=n; i++ ) for ( int i=1, n=vm.gettop(); i<=n; i++ )
f.write( vm.checklstring(i) ); f.write( vm.checklstring(i) );
vm.resettop(); vm.resettop();
vm.pushboolean(true); vm.pushboolean(true);
@@ -381,7 +374,7 @@ public class IoLib extends LFunction {
private static void ioread(LuaState vm, File f) throws IOException { private static void ioread(LuaState vm, File f) throws IOException {
int i,n=vm.gettop(); int i,n=vm.gettop();
for ( i=2; i<=n; i++ ) { for ( i=1; i<=n; i++ ) {
if ( vm.isnumber(i) ) { if ( vm.isnumber(i) ) {
vm.pushlvalue(freadbytes(f,vm.tointeger(i))); vm.pushlvalue(freadbytes(f,vm.tointeger(i)));
} else { } else {

View File

@@ -25,10 +25,7 @@ import java.util.Random;
import org.luaj.vm.LDouble; import org.luaj.vm.LDouble;
import org.luaj.vm.LFunction; import org.luaj.vm.LFunction;
import org.luaj.vm.LInteger;
import org.luaj.vm.LNumber;
import org.luaj.vm.LTable; import org.luaj.vm.LTable;
import org.luaj.vm.LValue;
import org.luaj.vm.LuaState; import org.luaj.vm.LuaState;
import org.luaj.vm.Platform; import org.luaj.vm.Platform;
@@ -142,105 +139,89 @@ public class MathLib extends LFunction {
vm.pushlvalue( LDouble.valueOf(d) ); vm.pushlvalue( LDouble.valueOf(d) );
} }
private static void setResult( LuaState vm, int i ) { public int invoke(LuaState vm) {
vm.resettop();
vm.pushlvalue( LInteger.valueOf(i) );
}
private static void setResult(LuaState vm, LNumber mathop) {
vm.resettop();
vm.pushlvalue( mathop );
}
public boolean luaStackCall( LuaState vm ) {
if ( id > LAST_DOUBLE_ARG ) { if ( id > LAST_DOUBLE_ARG ) {
setResult( vm, platform.mathop(id, vm.checknumber(2) ) ); vm.pushlvalue( platform.mathop(id, vm.checknumber(1) ) );
return 1;
} else if ( id > LAST_IRREGULAR ) { } else if ( id > LAST_IRREGULAR ) {
setResult( vm, platform.mathop(id, vm.checknumber(2), vm.checknumber(3) ) ); vm.pushlvalue( platform.mathop(id, vm.checknumber(1), vm.checknumber(2) ) );
return 1;
} else { } else {
switch ( id ) { switch ( id ) {
case INSTALL: case INSTALL:
install( vm._G ); install( vm._G );
break; return 0;
case MAX: { case MAX: {
int n = vm.gettop(); int n = vm.gettop();
double x = vm.checkdouble(2); double x = vm.checkdouble(1);
for ( int i=3; i<=n; i++ ) for ( int i=2; i<=n; i++ )
x = Math.max(x, vm.checkdouble(i)); x = Math.max(x, vm.checkdouble(i));
setResult( vm, x ); vm.pushnumber( x );
break; return 1;
} }
case MIN: { case MIN: {
int n = vm.gettop(); int n = vm.gettop();
double x = vm.checkdouble(2); double x = vm.checkdouble(1);
for ( int i=3; i<=n; i++ ) for ( int i=2; i<=n; i++ )
x = Math.min(x, vm.checkdouble(i)); x = Math.min(x, vm.checkdouble(i));
setResult(vm,x); vm.pushnumber( x );
break; return 1;
} }
case MODF: { case MODF: {
double x = vm.checkdouble(2); double x = vm.checkdouble(1);
double intPart = ( x > 0 ) ? Math.floor( x ) : Math.ceil( x ); double intPart = ( x > 0 ) ? Math.floor( x ) : Math.ceil( x );
double fracPart = x - intPart; double fracPart = x - intPart;
vm.resettop();
vm.pushnumber( intPart ); vm.pushnumber( intPart );
vm.pushnumber( fracPart ); vm.pushnumber( fracPart );
break; return 2;
} }
case CEIL: case CEIL:
setResult( vm, (int) Math.ceil( vm.checkdouble(2) ) ); vm.pushnumber( Math.ceil( vm.checkdouble(1) ) );
break; return 1;
case FLOOR: case FLOOR:
setResult( vm, (int) Math.floor( vm.checkdouble(2) ) ); vm.pushnumber( Math.floor( vm.checkdouble(1) ) );
break; return 1;
case FREXP: { case FREXP: {
long bits = Double.doubleToLongBits( vm.checkdouble(2) ); long bits = Double.doubleToLongBits( vm.checkdouble(1) );
vm.resettop();
vm.pushnumber( ((bits & (~(-1L<<52))) + (1L<<52)) * ((bits >= 0)? (.5 / (1L<<52)): (-.5 / (1L<<52))) ); vm.pushnumber( ((bits & (~(-1L<<52))) + (1L<<52)) * ((bits >= 0)? (.5 / (1L<<52)): (-.5 / (1L<<52))) );
vm.pushinteger( (((int) (bits >> 52)) & 0x7ff) - 1022 ); vm.pushinteger( (((int) (bits >> 52)) & 0x7ff) - 1022 );
break; return 2;
} }
case LDEXP: { case LDEXP: {
double m = vm.checkdouble(2); double m = vm.checkdouble(1);
int e = vm.checkint(3); int e = vm.checkint(2);
vm.resettop();
vm.pushnumber( m * Double.longBitsToDouble(((long)(e+1023)) << 52) ); vm.pushnumber( m * Double.longBitsToDouble(((long)(e+1023)) << 52) );
break; return 1;
} }
case RANDOM: { case RANDOM: {
if ( random == null ) if ( random == null )
random = new Random(1); random = new Random(1);
switch ( vm.gettop() ) { switch ( vm.gettop() ) {
case 1: case 0:
vm.resettop();
vm.pushnumber(random.nextDouble()); vm.pushnumber(random.nextDouble());
break; return 1;
case 2: { case 1: {
int m = vm.checkint(2); int m = vm.checkint(1);
vm.argcheck(1<=m, 1, "interval is empty"); vm.argcheck(1<=m, 1, "interval is empty");
vm.resettop();
vm.pushinteger(1+random.nextInt(m)); vm.pushinteger(1+random.nextInt(m));
break; return 1;
} }
default: { default: {
int m = vm.checkint(2); int m = vm.checkint(1);
int n = vm.checkint(3); int n = vm.checkint(2);
vm.argcheck(m<=n, 2, "interval is empty"); vm.argcheck(m<=n, 2, "interval is empty");
vm.resettop();
vm.pushinteger(m+random.nextInt(n+1-m)); vm.pushinteger(m+random.nextInt(n+1-m));
break; return 1;
} }
} }
break;
} }
case RSEED: case RSEED:
random = new Random( vm.checkint(2) ); random = new Random( vm.checkint(1) );
vm.resettop(); return 0;
break;
default: default:
LuaState.vmerror( "bad math id" ); LuaState.vmerror( "bad math id" );
return 0;
} }
} }
return false;
} }
} }

View File

@@ -122,7 +122,7 @@ public class OsLib extends LFunction {
return NAMES[id]+"()"; return NAMES[id]+"()";
} }
public boolean luaStackCall( LuaState vm ) { public int invoke( LuaState vm ) {
LValue v; LValue v;
long t,t2; long t,t2;
int c; int c;
@@ -131,72 +131,62 @@ public class OsLib extends LFunction {
switch ( id ) { switch ( id ) {
case INSTALL: case INSTALL:
install(vm._G, this); install(vm._G, this);
break; return 0;
case CLOCK: case CLOCK:
vm.resettop();
vm.pushnumber(clock()); vm.pushnumber(clock());
break; return 1;
case DATE: case DATE:
s = vm.optstring(2, null); s = vm.optstring(1, null);
t = vm.optlong(3,-1); t = vm.optlong(2,-1);
vm.resettop();
vm.pushlvalue( date(s, t==-1? System.currentTimeMillis(): t) ); vm.pushlvalue( date(s, t==-1? System.currentTimeMillis(): t) );
break; return 1;
case DIFFTIME: case DIFFTIME:
t2 = vm.checklong(2); t2 = vm.checklong(1);
t = vm.checklong(3); t = vm.checklong(2);
vm.resettop();
vm.pushnumber(difftime(t2,t)); vm.pushnumber(difftime(t2,t));
break; return 1;
case EXECUTE: case EXECUTE:
c = execute(vm.optstring(2, null)); c = execute(vm.optstring(1, null));
vm.resettop();
vm.pushinteger(c); vm.pushinteger(c);
break; return 1;
case EXIT: case EXIT:
exit(vm.optint(2, 0)); exit(vm.optint(1, 0));
break; return 0;
case GETENV: case GETENV:
s = getenv(vm.checkstring(2)); s = getenv(vm.checkstring(1));
vm.resettop();
vm.pushstring(s); vm.pushstring(s);
break; return 1;
case REMOVE: case REMOVE:
remove(vm.checkstring(2)); remove(vm.checkstring(1));
vm.resettop();
vm.pushboolean(true); vm.pushboolean(true);
break; return 1;
case RENAME: case RENAME:
rename(vm.checkstring(2), vm.checkstring(3)); rename(vm.checkstring(1), vm.checkstring(2));
vm.resettop();
vm.pushboolean(true); vm.pushboolean(true);
break; return 1;
case SETLOCALE: case SETLOCALE:
s = setlocale(vm.optstring(2,null), vm.optstring(3, "all")); s = setlocale(vm.optstring(1,null), vm.optstring(2, "all"));
vm.resettop();
if ( s != null ) if ( s != null )
vm.pushstring(s); vm.pushstring(s);
else else
vm.pushnil(); vm.pushnil();
break; return 1;
case TIME: case TIME:
t = time(vm.isnoneornil(2)? null: vm.checktable(2)); t = time(vm.isnoneornil(1)? null: vm.checktable(1));
vm.resettop();
vm.pushnumber(t); vm.pushnumber(t);
break; return 1;
case TMPNAME: case TMPNAME:
vm.resettop();
vm.pushstring(tmpname()); vm.pushstring(tmpname());
break; return 1;
default: default:
LuaState.vmerror( "bad os id" ); LuaState.vmerror( "bad os id" );
return 0;
} }
} catch ( IOException e ) { } catch ( IOException e ) {
vm.resettop();
vm.pushnil(); vm.pushnil();
vm.pushstring(e.getMessage()); vm.pushstring(e.getMessage());
return 2;
} }
return false;
} }
/** /**

View File

@@ -115,45 +115,38 @@ public class PackageLib extends LFunction {
return NAMES[id]+"()"; return NAMES[id]+"()";
} }
public boolean luaStackCall( LuaState vm ) { public int invoke( LuaState vm ) {
switch ( id ) { switch ( id ) {
case INSTALL: case INSTALL:
install(vm._G); install(vm._G);
break; return 0;
case MODULE: case MODULE:
module(vm); return module(vm);
break;
case REQUIRE: case REQUIRE:
require(vm); return require(vm);
break;
case LOADLIB: case LOADLIB:
loadlib(vm); return loadlib(vm);
break;
case SEEALL: { case SEEALL: {
LTable t = vm.checktable(2); LTable t = vm.checktable(1);
LTable m = t.luaGetMetatable(); LTable m = t.luaGetMetatable();
if ( m == null ) if ( m == null )
t.luaSetMetatable(m = new LTable()); t.luaSetMetatable(m = new LTable());
m.put(__INDEX, vm._G); m.put(__INDEX, vm._G);
vm.resettop(); return 0;
break;
} }
case PRELOAD_LOADER: { case PRELOAD_LOADER: {
loader_preload(vm); return loader_preload(vm);
break;
} }
case LUA_LOADER: { case LUA_LOADER: {
loader_Lua(vm); return loader_Lua(vm);
break;
} }
case JAVA_LOADER: { case JAVA_LOADER: {
loader_Java(vm); return loader_Java(vm);
break;
} }
default: default:
LuaState.vmerror( "bad package id" ); LuaState.vmerror( "bad package id" );
return 0;
} }
return false;
} }
@@ -179,8 +172,8 @@ public class PackageLib extends LFunction {
* This function may receive optional options after the module name, where * This function may receive optional options after the module name, where
* each option is a function to be applied over the module. * each option is a function to be applied over the module.
*/ */
public static void module(LuaState vm) { public static int module(LuaState vm) {
LString modname = vm.checklstring(2); LString modname = vm.checklstring(1);
int n = vm.gettop(); int n = vm.gettop();
LValue value = LOADED.luaGetTable(vm, modname); LValue value = LOADED.luaGetTable(vm, modname);
LTable module; LTable module;
@@ -207,14 +200,14 @@ public class PackageLib extends LFunction {
ci.closure.env = module; ci.closure.env = module;
// apply the functions // apply the functions
for ( int i=3; i<=n; i++ ) { for ( int i=2; i<=n; i++ ) {
vm.pushvalue( i ); /* get option (a function) */ vm.pushvalue( i ); /* get option (a function) */
vm.pushlvalue( module ); /* module */ vm.pushlvalue( module ); /* module */
vm.call( 1, 0 ); vm.call( 1, 0 );
} }
// returns no results // returns no results
vm.resettop(); return 0;
} }
/** /**
@@ -278,30 +271,29 @@ public class PackageLib extends LFunction {
* If there is any error loading or running the module, or if it cannot find any loader for * If there is any error loading or running the module, or if it cannot find any loader for
* the module, then require signals an error. * the module, then require signals an error.
*/ */
public void require( LuaState vm ) { public int require( LuaState vm ) {
LString name = vm.checklstring(2); LString name = vm.checklstring(1);
LValue loaded = LOADED.luaGetTable(vm, name); LValue loaded = LOADED.luaGetTable(vm, name);
if ( loaded.toJavaBoolean() ) { if ( loaded.toJavaBoolean() ) {
if ( loaded == _SENTINEL ) if ( loaded == _SENTINEL )
vm.error("loop or previous error loading module '"+name+"'"); vm.error("loop or previous error loading module '"+name+"'");
vm.resettop();
vm.pushlvalue( loaded ); vm.pushlvalue( loaded );
return; return 1;
} }
vm.resettop();
/* else must load it; iterate over available loaders */ /* else must load it; iterate over available loaders */
LValue val = pckg.luaGetTable(vm, _LOADERS); LValue val = pckg.luaGetTable(vm, _LOADERS);
if ( ! val.isTable() ) if ( ! val.isTable() )
vm.error( "'package.loaders' must be a table" ); vm.error( "'package.loaders' must be a table" );
vm.pushlvalue(val); LTable tbl = (LTable) val;
Vector v = new Vector(); Vector v = new Vector();
for ( int i=1; true; i++ ) { for ( int i=1; true; i++ ) {
vm.rawgeti(1, i); LValue loader = tbl.get(i);
if ( vm.isnil(-1) ) { if ( loader.isNil() ) {
vm.error( "module '"+name+"' not found: "+v ); vm.error( "module '"+name+"' not found: "+v );
} }
/* call loader with module name as argument */ /* call loader with module name as argument */
vm.pushlvalue(loader);
vm.pushlstring(name); vm.pushlstring(name);
vm.call(1, 1); vm.call(1, 1);
if ( vm.isfunction(-1) ) if ( vm.isfunction(-1) )
@@ -321,45 +313,45 @@ public class PackageLib extends LFunction {
if ( result == _SENTINEL ) { /* module did not set a value? */ if ( result == _SENTINEL ) { /* module did not set a value? */
LOADED.luaSetTable(vm, name, result=LBoolean.TRUE ); /* _LOADED[name] = true */ LOADED.luaSetTable(vm, name, result=LBoolean.TRUE ); /* _LOADED[name] = true */
} }
vm.resettop();
vm.pushlvalue(result); vm.pushlvalue(result);
return 1;
} }
public static void loadlib( LuaState vm ) { public static int loadlib( LuaState vm ) {
vm.checkstring(2); vm.checkstring(1);
vm.resettop();
vm.pushnil(); vm.pushnil();
vm.pushstring("dynamic libraries not enabled"); vm.pushstring("dynamic libraries not enabled");
vm.pushstring("absent"); vm.pushstring("absent");
return 3;
} }
private void loader_preload( LuaState vm ) { private int loader_preload( LuaState vm ) {
LString name = vm.tolstring(2); LString name = vm.tolstring(1);
LValue preload = pckg.luaGetTable(vm, _PRELOAD); LValue preload = pckg.luaGetTable(vm, _PRELOAD);
if ( ! preload.isTable() ) if ( ! preload.isTable() )
vm.error("package.preload '"+name+"' must be a table"); vm.error("package.preload '"+name+"' must be a table");
LValue val = preload.luaGetTable(vm, name); LValue val = preload.luaGetTable(vm, name);
if ( val.isNil() ) if ( val.isNil() )
vm.pushstring("\n\tno field package.preload['"+name+"']"); vm.pushstring("\n\tno field package.preload['"+name+"']");
vm.resettop(); else
vm.pushlvalue(val); vm.pushlvalue(val);
return 1;
} }
private void loader_Lua( LuaState vm ) { private int loader_Lua( LuaState vm ) {
String name = vm.tostring(2); String name = vm.tostring(1);
InputStream is = findfile( vm, name, _PATH ); InputStream is = findfile( vm, name, _PATH );
if ( is != null ) { if ( is != null ) {
String filename = vm.tostring(-1); String filename = vm.tostring(-1);
if ( ! BaseLib.loadis(vm, is, filename) ) if ( ! BaseLib.loadis(vm, is, filename) )
loaderror( vm, filename ); loaderror( vm, filename );
} }
vm.insert(1); return 1;
vm.settop(1);
} }
private void loader_Java( LuaState vm ) { private int loader_Java( LuaState vm ) {
String name = vm.tostring(2); String name = vm.tostring(1);
Class c = null; Class c = null;
LValue v = null; LValue v = null;
try { try {
@@ -371,8 +363,7 @@ public class PackageLib extends LFunction {
} catch ( Exception e ) { } catch ( Exception e ) {
vm.pushstring("\n\tjava load failed on '"+name+"', "+e ); vm.pushstring("\n\tjava load failed on '"+name+"', "+e );
} }
vm.insert(1); return 1;
vm.settop(1);
} }
private InputStream findfile(LuaState vm, String name, LString pname) { private InputStream findfile(LuaState vm, String name, LString pname) {

View File

@@ -92,58 +92,44 @@ public class StringLib extends LFunction {
return NAMES[id]+"()"; return NAMES[id]+"()";
} }
public boolean luaStackCall( LuaState vm ) { public int invoke( LuaState vm ) {
switch ( id ) { switch ( id ) {
case INSTALL: case INSTALL:
install( vm._G ); install( vm._G );
break; return 0;
case BYTE: case BYTE:
StringLib.byte_( vm ); return StringLib.byte_( vm );
break;
case CHAR: case CHAR:
StringLib.char_( vm ); return StringLib.char_( vm );
break;
case DUMP: case DUMP:
StringLib.dump( vm ); return StringLib.dump( vm );
break;
case FIND: case FIND:
StringLib.find( vm ); return StringLib.find( vm );
break;
case FORMAT: case FORMAT:
StringLib.format( vm ); return StringLib.format( vm );
break;
case GMATCH: case GMATCH:
StringLib.gmatch( vm ); return StringLib.gmatch( vm );
break;
case GSUB: case GSUB:
StringLib.gsub( vm ); return StringLib.gsub( vm );
break;
case LEN: case LEN:
StringLib.len( vm ); return StringLib.len( vm );
break;
case LOWER: case LOWER:
StringLib.lower( vm ); return StringLib.lower( vm );
break;
case MATCH: case MATCH:
StringLib.match( vm ); return StringLib.match( vm );
break;
case REP: case REP:
StringLib.rep( vm ); return StringLib.rep( vm );
break;
case REVERSE: case REVERSE:
StringLib.reverse( vm ); return StringLib.reverse( vm );
break;
case SUB: case SUB:
StringLib.sub( vm ); return StringLib.sub( vm );
break;
case UPPER: case UPPER:
StringLib.upper( vm ); return StringLib.upper( vm );
break;
default: default:
vm.error( "bad id" ); vm.error( "bad id" );
return 0;
} }
return false;
} }
/** /**
@@ -157,22 +143,22 @@ public class StringLib extends LFunction {
* *
* @param vm the calling vm * @param vm the calling vm
*/ */
static void byte_( LuaState vm ) { static int byte_( LuaState vm ) {
LString s = vm.checklstring(2); LString s = vm.checklstring(1);
int l = s.m_length; int l = s.m_length;
int posi = posrelat( vm.optint(3,1), l ); int posi = posrelat( vm.optint(2,1), l );
int pose = posrelat( vm.optint(4,posi), l ); int pose = posrelat( vm.optint(3,posi), l );
vm.resettop();
int n,i; int n,i;
if (posi <= 0) posi = 1; if (posi <= 0) posi = 1;
if (pose > l) pose = l; if (pose > l) pose = l;
if (posi > pose) return; /* empty interval; return no values */ if (posi > pose) return 0; /* empty interval; return no values */
n = (int)(pose - posi + 1); n = (int)(pose - posi + 1);
if (posi + n <= pose) /* overflow? */ if (posi + n <= pose) /* overflow? */
vm.error("string slice too long"); vm.error("string slice too long");
vm.checkstack(n); vm.checkstack(n);
for (i=0; i<n; i++) for (i=0; i<n; i++)
vm.pushinteger(s.luaByte(posi+i-1)); vm.pushinteger(s.luaByte(posi+i-1));
return n;
} }
/** /**
@@ -186,16 +172,16 @@ public class StringLib extends LFunction {
* *
* @param vm the calling VM * @param vm the calling VM
*/ */
public static void char_( LuaState vm) { public static int char_( LuaState vm) {
int n = vm.gettop()-1; int n = vm.gettop();
byte[] bytes = new byte[n]; byte[] bytes = new byte[n];
for ( int i=0, a=2; i<n; i++, a++ ) { for ( int i=0, a=1; i<n; i++, a++ ) {
int c = vm.checkint(a); int c = vm.checkint(a);
vm.argcheck((c>=0 && c<256), a, "invalid value"); vm.argcheck((c>=0 && c<256), a, "invalid value");
bytes[i] = (byte) c; bytes[i] = (byte) c;
} }
vm.resettop();
vm.pushlstring( bytes ); vm.pushlstring( bytes );
return 1;
} }
/** /**
@@ -207,15 +193,16 @@ public class StringLib extends LFunction {
* *
* TODO: port dumping code as optional add-on * TODO: port dumping code as optional add-on
*/ */
static void dump( LuaState vm ) { static int dump( LuaState vm ) {
LFunction f = vm.checkfunction(2); LFunction f = vm.checkfunction(1);
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
try { try {
DumpState.dump( ((LClosure)f).p, baos, true ); DumpState.dump( ((LClosure)f).p, baos, true );
vm.resettop();
vm.pushlstring(baos.toByteArray()); vm.pushlstring(baos.toByteArray());
return 1;
} catch (IOException e) { } catch (IOException e) {
vm.error( e.getMessage() ); vm.error( e.getMessage() );
return 0;
} }
} }
@@ -235,8 +222,8 @@ public class StringLib extends LFunction {
* If the pattern has captures, then in a successful match the captured values * If the pattern has captures, then in a successful match the captured values
* are also returned, after the two indices. * are also returned, after the two indices.
*/ */
static void find( LuaState vm ) { static int find( LuaState vm ) {
str_find_aux( vm, true ); return str_find_aux( vm, true );
} }
/** /**
@@ -262,11 +249,11 @@ public class StringLib extends LFunction {
* This function does not accept string values containing embedded zeros, * This function does not accept string values containing embedded zeros,
* except as arguments to the q option. * except as arguments to the q option.
*/ */
static void format( LuaState vm ) { static int format( LuaState vm ) {
LString fmt = vm.checklstring( 2 ); LString fmt = vm.checklstring( 1 );
final int n = fmt.length(); final int n = fmt.length();
LBuffer result = new LBuffer(n); LBuffer result = new LBuffer(n);
int arg = 2; int arg = 1;
for ( int i = 0; i < n; ) { for ( int i = 0; i < n; ) {
int c = fmt.luaByte( i++ ); int c = fmt.luaByte( i++ );
@@ -320,8 +307,8 @@ public class StringLib extends LFunction {
} }
} }
vm.resettop();
vm.pushlstring( result.toLuaString() ); vm.pushlstring( result.toLuaString() );
return 1;
} }
private static void addquoted(LBuffer buf, LString s) { private static void addquoted(LBuffer buf, LString s) {
@@ -528,11 +515,11 @@ public class StringLib extends LFunction {
* For this function, a '^' at the start of a pattern does not work as an anchor, * For this function, a '^' at the start of a pattern does not work as an anchor,
* as this would prevent the iteration. * as this would prevent the iteration.
*/ */
static void gmatch( LuaState vm ) { static int gmatch( LuaState vm ) {
LString src = vm.checklstring( 2 ); LString src = vm.checklstring( 1 );
LString pat = vm.checklstring( 3 ); LString pat = vm.checklstring( 2 );
vm.resettop();
vm.pushlvalue( new GMatchAux(vm, src, pat) ); vm.pushlvalue( new GMatchAux(vm, src, pat) );
return 1;
} }
static class GMatchAux extends LFunction { static class GMatchAux extends LFunction {
@@ -544,7 +531,7 @@ public class StringLib extends LFunction {
this.ms = new MatchState(vm, src, pat); this.ms = new MatchState(vm, src, pat);
this.soffset = 0; this.soffset = 0;
} }
public boolean luaStackCall(LuaState vm) { public int invoke(LuaState vm) {
vm.resettop(); vm.resettop();
for ( ; soffset<srclen; soffset++ ) { for ( ; soffset<srclen; soffset++ ) {
ms.reset(); ms.reset();
@@ -553,11 +540,11 @@ public class StringLib extends LFunction {
int soff = soffset; int soff = soffset;
soffset = res; soffset = res;
ms.push_captures( true, soff, res ); ms.push_captures( true, soff, res );
return false; return -1;
} }
} }
vm.pushnil(); vm.pushnil();
return false; return 1;
} }
} }
@@ -607,12 +594,12 @@ public class StringLib extends LFunction {
* x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t) * x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
* --> x="lua-5.1.tar.gz" * --> x="lua-5.1.tar.gz"
*/ */
static void gsub( LuaState vm ) { static int gsub( LuaState vm ) {
LString src = vm.checklstring(2); LString src = vm.checklstring( 1 );
final int srclen = src.length(); final int srclen = src.length();
LString p = vm.checklstring(3); LString p = vm.checklstring( 2 );
LValue repl = vm.topointer( 4 ); LValue repl = vm.topointer( 3 );
int max_s = vm.optint( 5, srclen + 1 ); int max_s = vm.optint( 4, srclen + 1 );
final boolean anchor = p.length() > 0 && p.charAt( 0 ) == '^'; final boolean anchor = p.length() > 0 && p.charAt( 0 ) == '^';
LBuffer lbuf = new LBuffer( srclen ); LBuffer lbuf = new LBuffer( srclen );
@@ -637,9 +624,9 @@ public class StringLib extends LFunction {
break; break;
} }
lbuf.append( src.substring( soffset, srclen ) ); lbuf.append( src.substring( soffset, srclen ) );
vm.resettop();
vm.pushlstring( lbuf.toLuaString() ); vm.pushlstring( lbuf.toLuaString() );
vm.pushinteger( n ); vm.pushinteger( n );
return 2;
} }
/** /**
@@ -648,10 +635,9 @@ public class StringLib extends LFunction {
* Receives a string and returns its length. The empty string "" has length 0. * Receives a string and returns its length. The empty string "" has length 0.
* Embedded zeros are counted, so "a\000bc\000" has length 5. * Embedded zeros are counted, so "a\000bc\000" has length 5.
*/ */
static void len( LuaState vm ) { static int len( LuaState vm ) {
int l = vm.checklstring(2).length(); vm.pushinteger( vm.checklstring(1).length() );
vm.resettop(); return 1;
vm.pushinteger( l );
} }
/** /**
@@ -661,10 +647,9 @@ public class StringLib extends LFunction {
* changed to lowercase. All other characters are left unchanged. * changed to lowercase. All other characters are left unchanged.
* The definition of what an uppercase letter is depends on the current locale. * The definition of what an uppercase letter is depends on the current locale.
*/ */
static void lower( LuaState vm ) { static int lower( LuaState vm ) {
String s = vm.checkstring(2).toLowerCase(); vm.pushstring( vm.checkstring(1).toLowerCase() );
vm.resettop(); return 1;
vm.pushstring( s );
} }
/** /**
@@ -676,8 +661,8 @@ public class StringLib extends LFunction {
* A third, optional numerical argument init specifies where to start the * A third, optional numerical argument init specifies where to start the
* search; its default value is 1 and may be negative. * search; its default value is 1 and may be negative.
*/ */
static void match( LuaState vm ) { static int match( LuaState vm ) {
str_find_aux( vm, false ); return str_find_aux( vm, false );
} }
/** /**
@@ -685,18 +670,16 @@ public class StringLib extends LFunction {
* *
* Returns a string that is the concatenation of n copies of the string s. * Returns a string that is the concatenation of n copies of the string s.
*/ */
static void rep( LuaState vm ) { static int rep( LuaState vm ) {
LString s = vm.checklstring(2); LString s = vm.checklstring( 1 );
int n = vm.checkint( 3 ); int n = vm.checkint( 2 );
vm.resettop(); final byte[] bytes = new byte[ s.length() * n ];
if ( n >= 0 ) { int len = s.length();
final byte[] bytes = new byte[ s.length() * n ]; for ( int offset = 0; offset < bytes.length; offset += len ) {
int len = s.length(); s.copyInto( 0, bytes, offset, len );
for ( int offset = 0; offset < bytes.length; offset += len ) {
s.copyInto( 0, bytes, offset, len );
}
vm.pushlstring( bytes );
} }
vm.pushlstring( bytes );
return 1;
} }
/** /**
@@ -704,14 +687,14 @@ public class StringLib extends LFunction {
* *
* Returns a string that is the string s reversed. * Returns a string that is the string s reversed.
*/ */
static void reverse( LuaState vm ) { static int reverse( LuaState vm ) {
LString s = vm.checklstring(2); LString s = vm.checklstring(1);
int n = s.length(); int n = s.length();
byte[] b = new byte[n]; byte[] b = new byte[n];
for ( int i=0, j=n-1; i<n; i++, j-- ) for ( int i=0, j=n-1; i<n; i++, j-- )
b[j] = (byte) s.luaByte(i); b[j] = (byte) s.luaByte(i);
vm.resettop();
vm.pushlstring( b ); vm.pushlstring( b );
return 1;
} }
/** /**
@@ -725,12 +708,12 @@ public class StringLib extends LFunction {
* string.sub(s, -i) * string.sub(s, -i)
* returns a suffix of s with length i. * returns a suffix of s with length i.
*/ */
static void sub( LuaState vm ) { static int sub( LuaState vm ) {
final LString s = vm.checklstring(2); final LString s = vm.checklstring( 1 );
final int l = s.length(); final int l = s.length();
int start = posrelat( vm.checkint( 3 ), l ); int start = posrelat( vm.checkint( 2 ), l );
int end = posrelat( vm.optint( 4, -1 ), l ); int end = posrelat( vm.optint( 3, -1 ), l );
if ( start < 1 ) if ( start < 1 )
start = 1; start = 1;
@@ -744,6 +727,7 @@ public class StringLib extends LFunction {
} else { } else {
vm.pushstring( "" ); vm.pushstring( "" );
} }
return 1;
} }
/** /**
@@ -753,19 +737,18 @@ public class StringLib extends LFunction {
* changed to uppercase. All other characters are left unchanged. * changed to uppercase. All other characters are left unchanged.
* The definition of what a lowercase letter is depends on the current locale. * The definition of what a lowercase letter is depends on the current locale.
*/ */
static void upper( LuaState vm ) { static int upper( LuaState vm ) {
String s = vm.checkstring(2).toUpperCase(); vm.pushstring(vm.checkstring(1).toUpperCase());
vm.resettop(); return 1;
vm.pushstring(s);
} }
/** /**
* This utility method implements both string.find and string.match. * This utility method implements both string.find and string.match.
*/ */
static void str_find_aux( LuaState vm, boolean find ) { static int str_find_aux( LuaState vm, boolean find ) {
LString s = vm.checklstring(2); LString s = vm.checklstring( 1 );
LString pat = vm.checklstring(3); LString pat = vm.checklstring( 2 );
int init = vm.optint( 4 , 1 ); int init = vm.optint( 3, 1 );
if ( init > 0 ) { if ( init > 0 ) {
init = Math.min( init - 1, s.length() ); init = Math.min( init - 1, s.length() );
@@ -774,14 +757,13 @@ public class StringLib extends LFunction {
} }
boolean fastMatch = find && ( vm.toboolean( 5 ) || pat.indexOfAny( SPECIALS ) == -1 ); boolean fastMatch = find && ( vm.toboolean( 5 ) || pat.indexOfAny( SPECIALS ) == -1 );
vm.resettop();
if ( fastMatch ) { if ( fastMatch ) {
int result = s.indexOf( pat, init ); int result = s.indexOf( pat, init );
if ( result != -1 ) { if ( result != -1 ) {
vm.pushinteger( result + 1 ); vm.pushinteger( result + 1 );
vm.pushinteger( result + pat.length() ); vm.pushinteger( result + pat.length() );
return; return 2;
} }
} else { } else {
MatchState ms = new MatchState( vm, s, pat ); MatchState ms = new MatchState( vm, s, pat );
@@ -794,6 +776,7 @@ public class StringLib extends LFunction {
} }
int soff = init; int soff = init;
vm.resettop();
do { do {
int res; int res;
ms.reset(); ms.reset();
@@ -805,11 +788,12 @@ public class StringLib extends LFunction {
} else { } else {
ms.push_captures( true, soff, res ); ms.push_captures( true, soff, res );
} }
return; return -1;
} }
} while ( soff++ < s.length() && !anchor ); } while ( soff++ < s.length() && !anchor );
} }
vm.pushnil(); vm.pushnil();
return 1;
} }
private static int posrelat( int pos, int len ) { private static int posrelat( int pos, int len ) {

View File

@@ -79,14 +79,14 @@ public class TableLib extends LFunction {
return NAMES[id]+"()"; return NAMES[id]+"()";
} }
public boolean luaStackCall( LuaState vm ) { public int invoke( LuaState vm ) {
switch ( id ) { switch ( id ) {
/* Load the table library dynamically /* Load the table library dynamically
*/ */
case INSTALL: case INSTALL:
install(vm._G); install(vm._G);
break; return 0;
/* table.concat (table [, sep [, i [, j]]]) /* table.concat (table [, sep [, i [, j]]])
@@ -96,25 +96,24 @@ public class TableLib extends LFunction {
* If i is greater than j, returns the empty string. * If i is greater than j, returns the empty string.
*/ */
case CONCAT: { case CONCAT: {
int n = vm.gettop(); // int n = vm.gettop();
LTable table = vm.checktable(2); LTable table = vm.checktable(1);
LString sep = vm.optlstring(3,null); LString sep = vm.optlstring(2,null);
int i = vm.optint(4,1); int i = vm.optint(3,1);
int j = vm.optint(5,-1); int j = vm.optint(4,-1);
if ( j == -1 ) if ( j == -1 )
j = table.luaLength(); j = table.luaLength();
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
for ( int k=i; k<=j; k++ ) { for ( int k=i; k<=j; k++ ) {
LValue v = table.get(k); LValue v = table.get(k);
if ( ! v.isString() ) if ( ! v.isString() )
vm.argerror(2, "table contains non-strings"); vm.argerror(1, "table contains non-strings");
v.luaConcatTo(baos); v.luaConcatTo(baos);
if ( k<j && sep!=null ) if ( k<j && sep!=null )
sep.luaConcatTo( baos ); sep.luaConcatTo( baos );
} }
vm.resettop();
vm.pushlstring( baos.toByteArray() ); vm.pushlstring( baos.toByteArray() );
break; return 1;
} }
/* table.getn (table) /* table.getn (table)
@@ -124,12 +123,10 @@ public class TableLib extends LFunction {
case FOREACH: case FOREACH:
case FOREACHI: case FOREACHI:
{ {
LTable table = vm.checktable(2); LTable table = vm.checktable(1);
LFunction function = vm.checkfunction(3); LFunction function = vm.checkfunction(2);
LValue result = table.foreach( vm, function, id==FOREACHI ); vm.pushlvalue( table.foreach( vm, function, id==FOREACHI ) );
vm.resettop(); return 1;
vm.pushlvalue( result );
break;
} }
/* table.getn (table) /* table.getn (table)
@@ -137,10 +134,9 @@ public class TableLib extends LFunction {
* Get length of table t. * Get length of table t.
*/ */
case GETN: { case GETN: {
LTable table = vm.checktable(2); LTable table = vm.checktable(1);
vm.resettop();
vm.pushinteger(table.luaLength()); vm.pushinteger(table.luaLength());
break; return 1;
} }
/* table.insert (table, [pos,] value) /* table.insert (table, [pos,] value)
@@ -150,20 +146,19 @@ public class TableLib extends LFunction {
* table.insert(t,x) inserts x at the end of table t. * table.insert(t,x) inserts x at the end of table t.
*/ */
case INSERT: { case INSERT: {
LTable table = vm.checktable(2); LTable table = vm.checktable(1);
int pos = 0; int pos = 0;
switch ( vm.gettop() ) { switch ( vm.gettop() ) {
case 3: case 2:
break; break;
case 4: case 3:
pos = vm.checkint(3); pos = vm.checkint(2);
break; break;
default: default:
vm.error( "wrong number of arguments to 'insert'" ); vm.error( "wrong number of arguments to 'insert'" );
} }
table.luaInsertPos( pos, vm.topointer(-1) ); table.luaInsertPos( pos, vm.topointer(-1) );
vm.resettop(); return 0;
break;
} }
/* table.maxn (table) /* table.maxn (table)
@@ -172,10 +167,9 @@ public class TableLib extends LFunction {
* indices. (To do its job this function does a linear traversal of the whole table.) * indices. (To do its job this function does a linear traversal of the whole table.)
*/ */
case MAXN: { case MAXN: {
LTable table = vm.checktable(2); LTable table = vm.checktable(1);
vm.resettop();
vm.pushlvalue( table.luaMaxN() ); vm.pushlvalue( table.luaMaxN() );
break; return 1;
} }
/* table.remove (table [, pos]) /* table.remove (table [, pos])
@@ -185,14 +179,11 @@ public class TableLib extends LFunction {
* so that a call table.remove(t) removes the last element of table t. * so that a call table.remove(t) removes the last element of table t.
*/ */
case REMOVE: { case REMOVE: {
int n = vm.gettop(); LTable table = vm.checktable(1);
LTable table = vm.checktable(2); int pos = vm.optint(2,0);
int pos = vm.optint(3,0); LValue v = table.luaRemovePos( pos );
vm.resettop(); vm.pushlvalue( v );
LValue removed = table.luaRemovePos( pos ); return v.isNil()? 0: 1;
if ( removed != LNil.NIL )
vm.pushlvalue( removed );
break;
} }
/* table.sort (table [, comp]) /* table.sort (table [, comp])
@@ -205,16 +196,15 @@ public class TableLib extends LFunction {
* The sort algorithm is not stable; that is, elements considered equal by the given order may have their relative positions changed by the sort. * The sort algorithm is not stable; that is, elements considered equal by the given order may have their relative positions changed by the sort.
*/ */
case SORT: { case SORT: {
LTable table = vm.checktable(2); LTable table = vm.checktable(1);
LValue compare = (vm.isnoneornil(3)? (LValue) LNil.NIL: (LValue) vm.checkfunction(3)); LValue compare = (vm.isnoneornil(2)? (LValue) LNil.NIL: (LValue) vm.checkfunction(2));
table.luaSort( vm, compare ); table.luaSort( vm, compare );
vm.resettop(); return 0;
break;
} }
default: default:
LuaState.vmerror( "bad table id" ); LuaState.vmerror( "bad table id" );
return 0;
} }
return false;
} }
} }

View File

@@ -84,7 +84,7 @@ public class LThread extends LValue implements Runnable {
} }
} }
public boolean yield() { public void yield() {
synchronized ( this ) { synchronized ( this ) {
if ( status != STATUS_RUNNING ) if ( status != STATUS_RUNNING )
vm.error(this+" not running"); vm.error(this+" not running");
@@ -99,7 +99,6 @@ public class LThread extends LValue implements Runnable {
vm.error(this+" "+e); vm.error(this+" "+e);
} }
} }
return false;
} }
} }
@@ -157,7 +156,7 @@ public class LThread extends LValue implements Runnable {
vm.resettop(); vm.resettop();
if ( this.vm.cc >= 0 ) { if ( this.vm.cc >= 0 ) {
vm.pushboolean(status != STATUS_DEAD); vm.pushboolean(status != STATUS_DEAD);
this.vm.xmove(vm, this.vm.gettop() - 1); this.vm.xmove(vm, this.vm.gettop());
} else { } else {
vm.pushboolean(true); vm.pushboolean(true);
this.vm.base = 0; this.vm.base = 0;

View File

@@ -247,16 +247,12 @@ public class LuaState extends Lua {
* @param javaFunction * @param javaFunction
*/ */
public void invokeJavaFunction(LFunction javaFunction) { public void invokeJavaFunction(LFunction javaFunction) {
int resultbase = base;
int resultsneeded = nresults;
++base; ++base;
int nactual = javaFunction.invoke(this); int nactual = javaFunction.invoke(this);
debugAssert(nactual>=0); if (nactual < 0)
debugAssert(top-nactual>=base); nactual = top - base;
System.arraycopy(stack, top-nactual, stack, base=resultbase, nactual); System.arraycopy(stack, top-nactual, stack, --base, nactual);
settop( nactual ); luaV_settop_fillabove( base+nactual );
if ( resultsneeded >= 0 )
settop( resultsneeded );
} }
// ================== error processing ================= // ================== error processing =================
@@ -1969,7 +1965,7 @@ public class LuaState extends Lua {
* @param extramsg String to include in error message * @param extramsg String to include in error message
*/ */
public void argerror(int narg, String extramsg) { public void argerror(int narg, String extramsg) {
error("bad argument #" + (narg - 1) + " (" + extramsg + ")"); error("bad argument #" + (narg) + " (" + extramsg + ")");
} }
/** /**