Improve arugment type checking.

This commit is contained in:
James Roseborough
2008-07-19 00:53:46 +00:00
parent fdf4dc0d56
commit 467923b86e

View File

@@ -116,27 +116,6 @@ public class BaseLib extends LFunction {
vm.pushnil(); vm.pushnil();
vm.pushstring( message ); vm.pushstring( message );
} }
private void checkargexists(LuaState vm, int index, int type) {
if ( vm.gettop() < index )
vm.error("bad argument #"+(index-1)+" to '?' ("+
(type == Lua.LUA_TVALUE?
"value expected)":
Lua.TYPE_NAMES[type]+" expected, got no value)") );
}
private void checkargtype
(LuaState vm, int index, int type) {
checkargexists( vm, index, type );
int t = vm.type(index);
if ( t != type ) {
if ( type == Lua.LUA_TNUMBER && t == Lua.LUA_TSTRING && vm.isnumber(index) )
return;
vm.error("bad argument #"+(index-1)+" to '?' ("+
Lua.TYPE_NAMES[type]+" expected, got "+vm.typename(index)+")");
}
}
public boolean luaStackCall(LuaState vm) { public boolean luaStackCall(LuaState vm) {
switch ( id ) { switch ( id ) {
case PRINT: { case PRINT: {
@@ -152,8 +131,7 @@ public class BaseLib extends LFunction {
} }
case IPAIRS: case IPAIRS:
case PAIRS: { case PAIRS: {
checkargtype(vm,2,Lua.LUA_TTABLE); LTable t = vm.checktable(2);
LTable t = vm.totable(2);
vm.resettop(); vm.resettop();
vm.pushjavafunction( (id==IPAIRS)? inext: next ); vm.pushjavafunction( (id==IPAIRS)? inext: next );
vm.pushlvalue( t ); vm.pushlvalue( t );
@@ -162,15 +140,14 @@ public class BaseLib extends LFunction {
} }
case INEXT: case INEXT:
case NEXT: { case NEXT: {
checkargtype(vm,2,Lua.LUA_TTABLE); LTable t = vm.checktable(2);
LTable t = vm.totable(2);
LValue v = vm.topointer(3); LValue v = vm.topointer(3);
vm.resettop(); vm.resettop();
t.next(vm,v,(id==INEXT)); t.next(vm,v,(id==INEXT));
break; break;
} }
case GETMETATABLE: { case GETMETATABLE: {
checkargexists(vm,2,Lua.LUA_TVALUE); vm.checkany(2);
if ( ! vm.getmetatable(2) ) { if ( ! vm.getmetatable(2) ) {
vm.resettop(); vm.resettop();
vm.pushnil(); vm.pushnil();
@@ -186,24 +163,21 @@ public class BaseLib extends LFunction {
break; break;
} }
case SETMETATABLE: { case SETMETATABLE: {
checkargtype(vm,2,Lua.LUA_TTABLE); vm.checktable(2);
if ( vm.gettop()<3 || ! (vm.isnil(3) || vm.istable(3)) )
vm.error( "bad argument #2 to '?' (nil or table expected)" );
vm.setmetatable(2); vm.setmetatable(2);
vm.remove(1); vm.remove(1);
vm.settop(1); vm.settop(1);
break; break;
} }
case TYPE: { case TYPE: {
// TODO: generalize, compute location insofar as possible vm.checkany(2);
if ( vm.gettop() < 2 )
vm.error("bad argument #1 to '?' (value expected)");
LValue v = vm.topointer(2); LValue v = vm.topointer(2);
vm.resettop(); vm.resettop();
vm.pushlstring( v.luaGetTypeName() ); vm.pushlstring( v.luaGetTypeName() );
break; break;
} }
case PCALL: { case PCALL: {
vm.checkany(2);
int n = vm.gettop(); int n = vm.gettop();
int s = vm.pcall( n-2, Lua.LUA_MULTRET, 0 ); int s = vm.pcall( n-2, Lua.LUA_MULTRET, 0 );
if ( s == 0 ) { // success, results are on stack above the pcall if ( s == 0 ) { // success, results are on stack above the pcall
@@ -217,22 +191,22 @@ public class BaseLib extends LFunction {
break; break;
} }
case ERROR: { case ERROR: {
vm.error(vm.tostring(2), vm.gettop()>=3? vm.tointeger(3): 1); vm.error(vm.checkstring(2), vm.optint(3,1));
break; break;
} }
case ASSERT: { case ASSERT: {
if ( ! vm.toboolean(2) ) if ( ! vm.toboolean(2) )
vm.error( vm.gettop()>2? vm.tostring(3): "assertion failed!" ); vm.error( vm.optstring(3,"assertion failed!") );
vm.remove(1); vm.resettop();
break; break;
} }
case LOADFILE: case LOADFILE:
loadfile(vm, vm.tostring(2)); loadfile(vm, vm.optstring(2,""));
break; break;
case TONUMBER: { case TONUMBER: {
checkargexists(vm,2,Lua.LUA_TVALUE); vm.checkany(2);
switch ( vm.type(2) ) { switch ( vm.type(2) ) {
case Lua.LUA_TNUMBER: case Lua.LUA_TNUMBER:
break; break;
@@ -255,18 +229,16 @@ public class BaseLib extends LFunction {
break; break;
} }
case RAWGET: { case RAWGET: {
checkargtype(vm,2,Lua.LUA_TTABLE); vm.checkany(3);
checkargexists(vm,3,Lua.LUA_TVALUE); LTable t = vm.checktable(2);
LTable t = vm.totable(2);
LValue k = vm.topointer(3); LValue k = vm.topointer(3);
vm.resettop(); vm.resettop();
vm.pushlvalue( t.get( k ) ); vm.pushlvalue( t.get( k ) );
} break; } break;
case RAWSET: { case RAWSET: {
checkargtype(vm,2,Lua.LUA_TTABLE); vm.checkany(3);
checkargexists(vm,3,Lua.LUA_TVALUE); vm.checkany(4);
checkargexists(vm,4,Lua.LUA_TVALUE); LTable t = vm.checktable(2);
LTable t = vm.totable(2);
LValue k = vm.topointer(3); LValue k = vm.topointer(3);
LValue v = vm.topointer(4); LValue v = vm.topointer(4);
t.put( k, v ); t.put( k, v );
@@ -277,7 +249,7 @@ public class BaseLib extends LFunction {
if ( vm.isfunction(2) ) { if ( vm.isfunction(2) ) {
vm.getfenv(-1); vm.getfenv(-1);
} else { } else {
int i = (vm.isnil(2)? 1: vm.tointeger(2)); int i = vm.optint(2,1);
if ( i <= 0 ) if ( i <= 0 )
vm.pushlvalue(vm._G); vm.pushlvalue(vm._G);
else if ( i-1 <= vm.cc ) else if ( i-1 <= vm.cc )
@@ -290,7 +262,8 @@ public class BaseLib extends LFunction {
break; break;
} }
case SETFENV: { case SETFENV: {
LTable t = vm.totable(-1); LTable t = vm.checktable(-1);
LFunction f = vm.checkfunction(2);
if ( vm.setfenv(2) != 0 ) { if ( vm.setfenv(2) != 0 ) {
vm.remove(1); vm.remove(1);
break; break;
@@ -308,7 +281,7 @@ public class BaseLib extends LFunction {
break; break;
} }
case SELECT: { case SELECT: {
checkargexists(vm,2,Lua.LUA_TNUMBER); vm.checkany(2);
int n = vm.gettop(); int n = vm.gettop();
if ( vm.isnumber(2) ) { if ( vm.isnumber(2) ) {
int index = vm.tolnumber(2).toJavaInt(); int index = vm.tolnumber(2).toJavaInt();
@@ -322,16 +295,14 @@ public class BaseLib extends LFunction {
for ( int i=0; i<=index; i++ ) for ( int i=0; i<=index; i++ )
vm.remove(1); vm.remove(1);
} }
} else if ( vm.tostring(2).equals( "#" ) ) { } else if ( vm.checkstring(2).equals( "#" ) ) {
vm.resettop(); vm.resettop();
vm.pushnumber( n - 2 ); vm.pushnumber( n - 2 );
} else {
vm.error( "bad argument #1 to '?' (number expected, got "+vm.typename(2)+")" );
} }
break; break;
} }
case COLLECTGARBAGE: { case COLLECTGARBAGE: {
String s = vm.tostring(2); String s = vm.checkstring(2);
int result = 0; int result = 0;
vm.resettop(); vm.resettop();
if ( "collect".equals(s) ) if ( "collect".equals(s) )
@@ -351,27 +322,22 @@ public class BaseLib extends LFunction {
loadstring(vm, vm.topointer(2), vm.tostring(3)); loadstring(vm, vm.topointer(2), vm.tostring(3));
break; break;
case LOAD: case LOAD:
load(vm, vm.topointer(2), vm.tostring(3)); load(vm);
break; break;
case TOSTRING: { case TOSTRING: {
checkargexists(vm,2,Lua.LUA_TVALUE); vm.checkany(2);
LValue v = vm.topointer(2); LValue v = vm.topointer(2);
vm.resettop(); vm.resettop();
vm.pushlvalue( v.luaAsString() ); vm.pushlvalue( v.luaAsString() );
break; break;
} }
case UNPACK: { case UNPACK: {
checkargtype(vm,2,Lua.LUA_TTABLE); LTable list = vm.checktable(2);
LTable list = vm.totable(2);
int n = vm.gettop(); int n = vm.gettop();
int i=1,j; int i = vm.optint(3,1);
if ( n >= 3 ) { int j;
checkargtype(vm,3,Lua.LUA_TNUMBER);
i = vm.tolnumber(3).toJavaInt();
}
if ( n >= 4 ) { if ( n >= 4 ) {
checkargtype(vm,4,Lua.LUA_TNUMBER); j = vm.checkint(4);
j = vm.tolnumber(4).toJavaInt();
} else { } else {
j = list.luaLength(); j = list.luaLength();
} }
@@ -454,7 +420,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.tostring(2); String filename = vm.checkstring(2);
if ( loadfile( vm, filename ) ) { if ( loadfile( vm, filename ) ) {
int s = vm.pcall(1, 0, 0); int s = vm.pcall(1, 0, 0);
setResult( vm, LInteger.valueOf( s!=0? 1: 0 ) ); setResult( vm, LInteger.valueOf( s!=0? 1: 0 ) );
@@ -471,10 +437,9 @@ 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 load(LuaState vm, LValue chunkPartLoader, String chunkname) { private boolean load(LuaState vm) {
if ( ! (chunkPartLoader instanceof LClosure) ) { LFunction chunkPartLoader = vm.checkfunction(2);
vm.error("not a closure: "+chunkPartLoader); String chunkname = vm.optstring(3,"=(load)");
}
// load all the parts // load all the parts
LClosure c = (LClosure) chunkPartLoader; LClosure c = (LClosure) chunkPartLoader;
@@ -494,9 +459,7 @@ public class BaseLib extends LFunction {
} }
// load the chunk // load the chunk
return loadis( vm, return loadis( vm, new ByteArrayInputStream( baos.toByteArray() ), chunkname );
new ByteArrayInputStream( baos.toByteArray() ),
("".equals(chunkname)? "=(load)": chunkname) );
} catch (IOException ioe) { } catch (IOException ioe) {
setErrorResult(vm, ioe.getMessage()); setErrorResult(vm, ioe.getMessage());