Improve argument type checking.
This commit is contained in:
@@ -96,10 +96,10 @@ public class TableLib extends LFunction {
|
|||||||
*/
|
*/
|
||||||
case CONCAT: {
|
case CONCAT: {
|
||||||
int n = vm.gettop();
|
int n = vm.gettop();
|
||||||
LTable table = vm.totable(2);
|
LTable table = vm.checktable(2);
|
||||||
LString sep = (n>=3? vm.tolstring(3): null);
|
LString sep = (n>=3? vm.checklstring(3): null);
|
||||||
int i = (n>=4? vm.tointeger(4): 1);
|
int i = (n>=4? vm.checkint(4): 1);
|
||||||
int j = (n>=5? vm.tointeger(5): table.luaLength());
|
int j = (n>=5? vm.checkint(5): 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);
|
||||||
@@ -119,8 +119,8 @@ public class TableLib extends LFunction {
|
|||||||
case FOREACH:
|
case FOREACH:
|
||||||
case FOREACHI:
|
case FOREACHI:
|
||||||
{
|
{
|
||||||
LTable table = vm.totable(2);
|
LTable table = vm.checktable(2);
|
||||||
LFunction function = vm.tojavafunction(3);
|
LFunction function = vm.checkfunction(3);
|
||||||
LValue result = table.foreach( vm, function, id==FOREACHI );
|
LValue result = table.foreach( vm, function, id==FOREACHI );
|
||||||
vm.resettop();
|
vm.resettop();
|
||||||
vm.pushlvalue( result );
|
vm.pushlvalue( result );
|
||||||
@@ -132,7 +132,7 @@ public class TableLib extends LFunction {
|
|||||||
* Get length of table t.
|
* Get length of table t.
|
||||||
*/
|
*/
|
||||||
case GETN: {
|
case GETN: {
|
||||||
LTable table = vm.totable(2);
|
LTable table = vm.checktable(2);
|
||||||
vm.resettop();
|
vm.resettop();
|
||||||
vm.pushinteger(table.luaLength());
|
vm.pushinteger(table.luaLength());
|
||||||
break;
|
break;
|
||||||
@@ -146,10 +146,11 @@ public class TableLib extends LFunction {
|
|||||||
*/
|
*/
|
||||||
case INSERT: {
|
case INSERT: {
|
||||||
int n = vm.gettop();
|
int n = vm.gettop();
|
||||||
LTable table = vm.totable(2);
|
LTable table = vm.checktable(2);
|
||||||
int pos = (n>=4? vm.tointeger(3): 0);
|
int pos = (n>=4? vm.checkint(3): 0);
|
||||||
LValue value = vm.topointer(-1);
|
LValue value = vm.topointer(-1);
|
||||||
table.luaInsertPos( pos, value );
|
table.luaInsertPos( pos, value );
|
||||||
|
vm.resettop();
|
||||||
break;
|
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.)
|
* indices. (To do its job this function does a linear traversal of the whole table.)
|
||||||
*/
|
*/
|
||||||
case MAXN: {
|
case MAXN: {
|
||||||
LTable table = vm.totable(2);
|
LTable table = vm.checktable(2);
|
||||||
vm.resettop();
|
vm.resettop();
|
||||||
vm.pushlvalue( table.luaMaxN() );
|
vm.pushlvalue( table.luaMaxN() );
|
||||||
break;
|
break;
|
||||||
@@ -173,8 +174,8 @@ public class TableLib extends LFunction {
|
|||||||
*/
|
*/
|
||||||
case REMOVE: {
|
case REMOVE: {
|
||||||
int n = vm.gettop();
|
int n = vm.gettop();
|
||||||
LTable table = vm.totable(2);
|
LTable table = vm.checktable(2);
|
||||||
int pos = (n>=3? vm.tointeger(3): 0);
|
int pos = (n>=3? vm.checkint(3): 0);
|
||||||
vm.resettop();
|
vm.resettop();
|
||||||
LValue removed = table.luaRemovePos( pos );
|
LValue removed = table.luaRemovePos( pos );
|
||||||
if ( removed != LNil.NIL )
|
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.
|
* 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.totable(2);
|
LTable table = vm.checktable(2);
|
||||||
LValue compare = vm.topointer(3);
|
LValue compare = vm.checkfunction(3);
|
||||||
table.luaSort( vm, compare );
|
table.luaSort( vm, compare );
|
||||||
vm.resettop();
|
vm.resettop();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -45,6 +45,13 @@ public class LNumber extends LValue {
|
|||||||
*/
|
*/
|
||||||
public abstract boolean isInteger();
|
public abstract boolean isInteger();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In lua all numbers are strings !
|
||||||
|
*/
|
||||||
|
public boolean isString() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/** Convert to a Byte value */
|
/** Convert to a Byte value */
|
||||||
public Byte toJavaBoxedByte() {
|
public Byte toJavaBoxedByte() {
|
||||||
return new Byte(toJavaByte());
|
return new Byte(toJavaByte());
|
||||||
|
|||||||
@@ -2614,14 +2614,14 @@ public class LuaState extends Lua {
|
|||||||
|
|
||||||
// ================= Error Reporting Functions =================
|
// ================= Error Reporting Functions =================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report an error with an argument.
|
* Report an error with an argument.
|
||||||
*
|
*
|
||||||
* @param narg
|
* @param narg
|
||||||
* Stack index of the bad argument
|
* Stack index of the bad argument
|
||||||
* @param extramsg
|
* @param extramsg
|
||||||
* String to include in error message
|
* String to include in error message
|
||||||
*/
|
*/
|
||||||
public void argerror(int narg, String extramsg) {
|
public void argerror(int narg, String extramsg) {
|
||||||
// TODO: port ldebug.c and provide mode useful error messages.
|
// TODO: port ldebug.c and provide mode useful error messages.
|
||||||
error("bad argument #" + (narg - 1) + " (" + extramsg + ")");
|
error("bad argument #" + (narg - 1) + " (" + extramsg + ")");
|
||||||
@@ -2651,6 +2651,136 @@ public class LuaState extends Lua {
|
|||||||
public void typerror(int narg, int typenum) {
|
public void typerror(int narg, int typenum) {
|
||||||
typerror(narg, TYPE_NAMES[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,
|
* Check that the type of userdata on the stack matches the required type,
|
||||||
|
|||||||
@@ -52,14 +52,40 @@ local structtypes = {
|
|||||||
['userdata']='<userdata>',
|
['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 = {}
|
local t = {}
|
||||||
for i=1,#arglist do
|
for i=1,#list do
|
||||||
local ai = arglist[i]
|
local ai = list[i]
|
||||||
local ti = type(ai)
|
local fi = pretty[type(ai)]
|
||||||
t[i] = structtypes[ti] or tostring(ai)
|
t[i] = fi and fi(ai) or tostring(ai)
|
||||||
end
|
end
|
||||||
return name..'('..table.concat(t,',')..')'
|
return table.concat(t,',')
|
||||||
|
end
|
||||||
|
|
||||||
|
local function signature(name,arglist)
|
||||||
|
return name..'('..values(arglist)..')'
|
||||||
end
|
end
|
||||||
|
|
||||||
local function dup(t)
|
local function dup(t)
|
||||||
@@ -123,11 +149,12 @@ function checkallpass( name, typesets )
|
|||||||
subbanner('checkallpass')
|
subbanner('checkallpass')
|
||||||
for i,v in arglists(typesets) do
|
for i,v in arglists(typesets) do
|
||||||
local sig = signature(name,v)
|
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
|
if s then
|
||||||
print( ok, sig )
|
print( ok, sig, values(r) )
|
||||||
else
|
else
|
||||||
print( fail, sig, e )
|
print( fail, sig, values(r) )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user