Add xpcall.

This commit is contained in:
James Roseborough
2008-07-22 01:20:25 +00:00
parent 80d8fccd1a
commit 289a0df9f5
2 changed files with 53 additions and 31 deletions

View File

@@ -54,6 +54,7 @@ public class BaseLib extends LFunction {
"load", "load",
"tostring", "tostring",
"unpack", "unpack",
"xpcall",
"next", "next",
"_inext", // not public "_inext", // not public
}; };
@@ -81,8 +82,9 @@ public class BaseLib extends LFunction {
private static final int LOAD = 20; private static final int LOAD = 20;
private static final int TOSTRING = 21; private static final int TOSTRING = 21;
private static final int UNPACK = 22; private static final int UNPACK = 22;
private static final int NEXT = 23; private static final int XPCALL = 23;
private static final int INEXT = 24; private static final int NEXT = 24;
private static final int INEXT = 25;
private static LFunction next; private static LFunction next;
private static LFunction inext; private static LFunction inext;
@@ -190,6 +192,29 @@ public class BaseLib extends LFunction {
} }
break; break;
} }
case XPCALL: {
vm.checkany(3);
LValue errfun = vm.topointer(3);
vm.settop(2);
int s = vm.pcall( 0, Lua.LUA_MULTRET, 0 );
if ( s == 0 ) { // success, results are on stack above the xpcall
vm.pushboolean( true );
vm.replace( 1 );
} else { // error, error message is on the stack
vm.pushlvalue( errfun );
vm.insert( 1 );
s = vm.pcall( vm.gettop()-1, 1, 0 );
if ( s == 0 ) {
vm.pushboolean( false );
vm.insert( 1 );
} else { // error in error handler
vm.resettop();
vm.pushboolean(false);
vm.pushstring("error in error handling");
}
}
break;
}
case ERROR: { case ERROR: {
vm.error(vm.checkstring(2), vm.optint(3,1)); vm.error(vm.checkstring(2), vm.optint(3,1));
break; break;
@@ -197,7 +222,7 @@ public class BaseLib extends LFunction {
case ASSERT: { case ASSERT: {
if ( ! vm.toboolean(2) ) if ( ! vm.toboolean(2) )
vm.error( vm.optstring(3,"assertion failed!") ); vm.error( vm.optstring(3,"assertion failed!") );
vm.resettop(); vm.remove(1);
break; break;
} }
@@ -206,26 +231,20 @@ public class BaseLib extends LFunction {
break; break;
case TONUMBER: { case TONUMBER: {
int base = vm.optint(3, 10);
if (base == 10) { /* standard conversion */
vm.checkany(2); vm.checkany(2);
switch ( vm.type(2) ) { LValue v = vm.tolnumber(2);
case Lua.LUA_TNUMBER: vm.resettop();
break; if ( ! v.isNil() )
case Lua.LUA_TSTRING: vm.pushlvalue(v);
LString s = vm.tolstring(2); } else {
int base = 10;
if ( vm.isnumber(3) ) {
base = vm.tolnumber(3).toJavaInt();
if ( base < 2 || base > 36 ) if ( base < 2 || base > 36 )
vm.error("bad argument #2 to '?' (base out of range)"); vm.typerror(3, "base out of range");
} LString s = vm.checklstring(2);
vm.resettop();
vm.pushlvalue( s.luaToNumber(base) ); vm.pushlvalue( s.luaToNumber(base) );
break;
default:
vm.pushnil();
break;
} }
vm.insert(1);
vm.settop(1);
break; break;
} }
case RAWGET: { case RAWGET: {
@@ -307,10 +326,12 @@ public class BaseLib extends LFunction {
vm.resettop(); vm.resettop();
if ( "collect".equals(s) ) if ( "collect".equals(s) )
System.gc(); System.gc();
else { else if ( "count".equals(s) ) {
Runtime rt = Runtime.getRuntime(); Runtime rt = Runtime.getRuntime();
long used = rt.totalMemory() - rt.freeMemory(); long used = rt.totalMemory() - rt.freeMemory();
result = (int) (used >> 10); result = (int) (used >> 10);
} else {
vm.typerror(2,"gc op");
} }
vm.pushnumber(result); vm.pushnumber(result);
break; break;
@@ -319,7 +340,7 @@ public class BaseLib extends LFunction {
dofile(vm); dofile(vm);
break; break;
case LOADSTRING: case LOADSTRING:
loadstring(vm, vm.topointer(2), vm.tostring(3)); loadstring(vm, vm.checklstring(2), vm.optstring(3,"(string)"));
break; break;
case LOAD: case LOAD:
load(vm); load(vm);
@@ -430,10 +451,8 @@ public class BaseLib extends LFunction {
} }
// return true if loaded, false if error put onto stack // return true if loaded, false if error put onto stack
private boolean loadstring(LuaState vm, LValue string, String chunkname) { private boolean loadstring(LuaState vm, LString string, String chunkname) {
return loadis( vm, return loadis( vm, string.toInputStream(), chunkname );
string.luaAsString().toInputStream(),
("".equals(chunkname)? "(string)": chunkname) );
} }
// return true if loaded, false if error put onto stack // return true if loaded, false if error put onto stack

View File

@@ -12,7 +12,7 @@ checkallerrors('assert',{{nil,false},{'message'}},'message')
-- collectgarbage -- collectgarbage
banner('collectgarbage') banner('collectgarbage')
checkallpass('collectgarbage',{{'collect','count'}}) checkallpass('collectgarbage',{{'collect','count'}},true)
checkallerrors('collectgarbage',{notanil},'bad argument #1') checkallerrors('collectgarbage',{notanil},'bad argument #1')
-- dofile -- dofile
@@ -132,8 +132,10 @@ checkallerrors('tonumber',{somenumber,{1,37,atable,afunction,aboolean}},'bad arg
-- tostring -- tostring
banner('tostring') banner('tostring')
checkallpass('tostring',{notanil}) checkallpass('tostring',{{astring,anumber,aboolean}})
checkallpass('tostring',{anylua,{'anchor'}}) checkallpass('tostring',{{atable,afunction,athread}},true)
checkallpass('tostring',{{astring,anumber,aboolean},{'anchor'}})
checkallpass('tostring',{{atable,afunction,athread},{'anchor'}},true)
checkallerrors('tostring',{},'bad argument #1') checkallerrors('tostring',{},'bad argument #1')
-- type -- type
@@ -153,7 +155,8 @@ checkallerrors('unpack',{sometable,somenumber,nonnumber},'bad argument #3')
-- xpcall -- xpcall
banner('xpcall') banner('xpcall')
checkallpass('xpcall', {notanil,notanil}) checkallpass('xpcall', {notanil,nonfunction})
checkallpass('xpcall', {notanil,{function(...)return 'aaa', 'bbb', #{...} end}})
checkallerrors('xpcall',{anylua},'bad argument #2') checkallerrors('xpcall',{anylua},'bad argument #2')