Improve argument type checking.
This commit is contained in:
@@ -96,10 +96,10 @@ public class TableLib extends LFunction {
|
||||
*/
|
||||
case CONCAT: {
|
||||
int n = vm.gettop();
|
||||
LTable table = vm.totable(2);
|
||||
LString sep = (n>=3? vm.tolstring(3): null);
|
||||
int i = (n>=4? vm.tointeger(4): 1);
|
||||
int j = (n>=5? vm.tointeger(5): table.luaLength());
|
||||
LTable table = vm.checktable(2);
|
||||
LString sep = (n>=3? vm.checklstring(3): null);
|
||||
int i = (n>=4? vm.checkint(4): 1);
|
||||
int j = (n>=5? vm.checkint(5): table.luaLength());
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
for ( int k=i; k<=j; k++ ) {
|
||||
LValue v = table.get(k);
|
||||
@@ -119,8 +119,8 @@ public class TableLib extends LFunction {
|
||||
case FOREACH:
|
||||
case FOREACHI:
|
||||
{
|
||||
LTable table = vm.totable(2);
|
||||
LFunction function = vm.tojavafunction(3);
|
||||
LTable table = vm.checktable(2);
|
||||
LFunction function = vm.checkfunction(3);
|
||||
LValue result = table.foreach( vm, function, id==FOREACHI );
|
||||
vm.resettop();
|
||||
vm.pushlvalue( result );
|
||||
@@ -132,7 +132,7 @@ public class TableLib extends LFunction {
|
||||
* Get length of table t.
|
||||
*/
|
||||
case GETN: {
|
||||
LTable table = vm.totable(2);
|
||||
LTable table = vm.checktable(2);
|
||||
vm.resettop();
|
||||
vm.pushinteger(table.luaLength());
|
||||
break;
|
||||
@@ -146,10 +146,11 @@ public class TableLib extends LFunction {
|
||||
*/
|
||||
case INSERT: {
|
||||
int n = vm.gettop();
|
||||
LTable table = vm.totable(2);
|
||||
int pos = (n>=4? vm.tointeger(3): 0);
|
||||
LTable table = vm.checktable(2);
|
||||
int pos = (n>=4? vm.checkint(3): 0);
|
||||
LValue value = vm.topointer(-1);
|
||||
table.luaInsertPos( pos, value );
|
||||
vm.resettop();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -159,7 +160,7 @@ public class TableLib extends LFunction {
|
||||
* indices. (To do its job this function does a linear traversal of the whole table.)
|
||||
*/
|
||||
case MAXN: {
|
||||
LTable table = vm.totable(2);
|
||||
LTable table = vm.checktable(2);
|
||||
vm.resettop();
|
||||
vm.pushlvalue( table.luaMaxN() );
|
||||
break;
|
||||
@@ -173,8 +174,8 @@ public class TableLib extends LFunction {
|
||||
*/
|
||||
case REMOVE: {
|
||||
int n = vm.gettop();
|
||||
LTable table = vm.totable(2);
|
||||
int pos = (n>=3? vm.tointeger(3): 0);
|
||||
LTable table = vm.checktable(2);
|
||||
int pos = (n>=3? vm.checkint(3): 0);
|
||||
vm.resettop();
|
||||
LValue removed = table.luaRemovePos( pos );
|
||||
if ( removed != LNil.NIL )
|
||||
@@ -192,8 +193,8 @@ 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.
|
||||
*/
|
||||
case SORT: {
|
||||
LTable table = vm.totable(2);
|
||||
LValue compare = vm.topointer(3);
|
||||
LTable table = vm.checktable(2);
|
||||
LValue compare = vm.checkfunction(3);
|
||||
table.luaSort( vm, compare );
|
||||
vm.resettop();
|
||||
break;
|
||||
|
||||
@@ -45,6 +45,13 @@ public class LNumber extends LValue {
|
||||
*/
|
||||
public abstract boolean isInteger();
|
||||
|
||||
/**
|
||||
* In lua all numbers are strings !
|
||||
*/
|
||||
public boolean isString() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Convert to a Byte value */
|
||||
public Byte toJavaBoxedByte() {
|
||||
return new Byte(toJavaByte());
|
||||
|
||||
@@ -2614,14 +2614,14 @@ public class LuaState extends Lua {
|
||||
|
||||
// ================= Error Reporting Functions =================
|
||||
|
||||
/**
|
||||
* Report an error with an argument.
|
||||
*
|
||||
* @param narg
|
||||
* Stack index of the bad argument
|
||||
* @param extramsg
|
||||
* String to include in error message
|
||||
*/
|
||||
/**
|
||||
* Report an error with an argument.
|
||||
*
|
||||
* @param narg
|
||||
* Stack index of the bad argument
|
||||
* @param extramsg
|
||||
* String to include in error message
|
||||
*/
|
||||
public void argerror(int narg, String extramsg) {
|
||||
// TODO: port ldebug.c and provide mode useful error messages.
|
||||
error("bad argument #" + (narg - 1) + " (" + extramsg + ")");
|
||||
@@ -2651,6 +2651,136 @@ public class LuaState extends Lua {
|
||||
public void typerror(int narg, int typenum) {
|
||||
typerror(narg, TYPE_NAMES[typenum]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether the function has an argument of any type (including <b>nil</b>)
|
||||
* at position <code>narg</code>.
|
||||
* @param narg the argument number
|
||||
* @throws LuaErrorException if there is no argument at position narg
|
||||
*/
|
||||
public void checkany(int narg) {
|
||||
if ( gettop() < narg )
|
||||
argerror(narg, "value expected");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the function argument <code>narg</code> is a function and
|
||||
* returns this function.
|
||||
* @see LFunction
|
||||
* @param narg the argument number
|
||||
* @throws LuaErrorException if the value is not a function
|
||||
* @return LFunction value if the argument is a function
|
||||
*/
|
||||
public LFunction checkfunction(int narg) {
|
||||
return (LFunction) checktype(narg, Lua.LUA_TFUNCTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the function argument <code>narg</code> is a number and
|
||||
* returns this number cast to an <code>int</code>.
|
||||
* @param narg the argument number
|
||||
* @throws LuaErrorException if the number cannot be converted to an int
|
||||
* @return int value if the argument is an int or can be converted to one
|
||||
*/
|
||||
public int checkint(int narg) {
|
||||
LValue v = tolnumber(narg);
|
||||
if ( ! v.isInteger() )
|
||||
typerror(narg, Lua.LUA_TNUMBER);
|
||||
return v.toJavaInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the function argument <code>narg</code> is a number and
|
||||
* returns this number cast to a <code>LInteger</code></a>.
|
||||
* @see LInteger
|
||||
* @param narg the argument number
|
||||
* @throws LuaErrorException if the value cannot be converted to an int
|
||||
* @return LInteger value if the argument is an int or can be converted to one
|
||||
*/
|
||||
public LInteger checkinteger(int narg) {
|
||||
return LInteger.valueOf(checkint(narg));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the function argument <code>narg</code> is a number and
|
||||
* returns this number cast to a <code>long</code>.
|
||||
* @param narg the argument number
|
||||
* @throws LuaErrorException if the value cannot be converted to a long
|
||||
* @return long value if the argument is a number or can be converted to long
|
||||
*/
|
||||
public long checklong(int narg) {
|
||||
return checknumber(narg).toJavaLong();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the function argument <code>narg</code> is a number and
|
||||
* returns this number.
|
||||
* @see LNumber
|
||||
* @param narg the argument number
|
||||
* @throws LuaErrorException if the value cannot be converted to a number
|
||||
* @return LNumber value if the argument is a number or can be converted to one
|
||||
*/
|
||||
public LNumber checknumber(int narg) {
|
||||
return (LNumber) checktype(narg, Lua.LUA_TTABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the function argument <code>narg</code> is a string and
|
||||
* returns this string as a lua string.
|
||||
* @see LString
|
||||
* @param narg the argument number
|
||||
* @throws LuaErrorException if the value cannot be converted to a string
|
||||
* @return LString value if the argument is a string or can be converted to one
|
||||
*/
|
||||
public LString checklstring(int narg) {
|
||||
LValue v = topointer(narg);
|
||||
if ( ! v.isString() )
|
||||
typerror(narg, Lua.LUA_TSTRING);
|
||||
return v.luaAsString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the function argument <code>narg</code> is a string and
|
||||
* returns this string as a Java String.
|
||||
* @param narg the argument number
|
||||
* @throws LuaErrorException if the value cannot be converted to a string
|
||||
* @return String value if the argument is a string or can be converted to one
|
||||
*/
|
||||
public String checkstring(int narg) {
|
||||
LValue v = topointer(narg);
|
||||
if ( ! v.isString() )
|
||||
typerror(narg, Lua.LUA_TSTRING);
|
||||
return v.toJavaString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the function argument <code>narg</code> is a table and
|
||||
* returns this table.
|
||||
* @see LTable
|
||||
* @param narg the argument number
|
||||
* @throws LuaErrorException if the value is not a table
|
||||
* @return LTable value if the argument is a table
|
||||
*/
|
||||
public LTable checktable(int narg) {
|
||||
return (LTable) checktype(narg, Lua.LUA_TTABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the function argument <code>narg</code> has type
|
||||
* <code>t</code> and return it as an LValue.
|
||||
* @param narg the argument number
|
||||
* @param t the type number to check against
|
||||
* @return the lua value
|
||||
* @throws LuaErrorException if the value is not of type t
|
||||
*/
|
||||
public LValue checktype(int narg, int t) {
|
||||
LValue v = topointer(narg);
|
||||
if ( v.luaGetType() != t )
|
||||
typerror(narg, t);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check that the type of userdata on the stack matches the required type,
|
||||
|
||||
@@ -52,14 +52,40 @@ local structtypes = {
|
||||
['userdata']='<userdata>',
|
||||
}
|
||||
|
||||
local function signature(name,arglist)
|
||||
local function bracket(v)
|
||||
return "<"..type(v)..">"
|
||||
end
|
||||
|
||||
local function quote(v)
|
||||
return "'"..v.."'"
|
||||
end
|
||||
|
||||
local function ellipses(v)
|
||||
local s = tostring(v)
|
||||
return #s <= 8 and s or string.sub(s,8)..'...'
|
||||
end
|
||||
|
||||
local pretty = {
|
||||
['table']=bracket,
|
||||
['function']=bracket,
|
||||
['thread']=bracket,
|
||||
['userdata']=bracket,
|
||||
['string']= quote,
|
||||
['number']= ellipses,
|
||||
}
|
||||
|
||||
local function values(list)
|
||||
local t = {}
|
||||
for i=1,#arglist do
|
||||
local ai = arglist[i]
|
||||
local ti = type(ai)
|
||||
t[i] = structtypes[ti] or tostring(ai)
|
||||
for i=1,#list do
|
||||
local ai = list[i]
|
||||
local fi = pretty[type(ai)]
|
||||
t[i] = fi and fi(ai) or tostring(ai)
|
||||
end
|
||||
return name..'('..table.concat(t,',')..')'
|
||||
return table.concat(t,',')
|
||||
end
|
||||
|
||||
local function signature(name,arglist)
|
||||
return name..'('..values(arglist)..')'
|
||||
end
|
||||
|
||||
local function dup(t)
|
||||
@@ -123,11 +149,12 @@ function checkallpass( name, typesets )
|
||||
subbanner('checkallpass')
|
||||
for i,v in arglists(typesets) do
|
||||
local sig = signature(name,v)
|
||||
local s,e = invoke( name, v )
|
||||
local r = { invoke( name, v ) }
|
||||
local s = table.remove( r, 1 )
|
||||
if s then
|
||||
print( ok, sig )
|
||||
print( ok, sig, values(r) )
|
||||
else
|
||||
print( fail, sig, e )
|
||||
print( fail, sig, values(r) )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user