Argument type checking on basic lib
This commit is contained in:
@@ -10,6 +10,7 @@ import java.io.InputStream;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import org.luaj.vm.CallInfo;
|
||||||
import org.luaj.vm.LClosure;
|
import org.luaj.vm.LClosure;
|
||||||
import org.luaj.vm.LFunction;
|
import org.luaj.vm.LFunction;
|
||||||
import org.luaj.vm.LInteger;
|
import org.luaj.vm.LInteger;
|
||||||
@@ -43,6 +44,7 @@ public class BaseLib extends LFunction {
|
|||||||
"assert",
|
"assert",
|
||||||
"loadfile",
|
"loadfile",
|
||||||
"tonumber",
|
"tonumber",
|
||||||
|
"rawequal",
|
||||||
"rawget",
|
"rawget",
|
||||||
"rawset",
|
"rawset",
|
||||||
"getfenv",
|
"getfenv",
|
||||||
@@ -71,20 +73,21 @@ public class BaseLib extends LFunction {
|
|||||||
private static final int ASSERT = 9;
|
private static final int ASSERT = 9;
|
||||||
private static final int LOADFILE = 10;
|
private static final int LOADFILE = 10;
|
||||||
private static final int TONUMBER = 11;
|
private static final int TONUMBER = 11;
|
||||||
private static final int RAWGET = 12;
|
private static final int RAWEQUAL = 12;
|
||||||
private static final int RAWSET = 13;
|
private static final int RAWGET = 13;
|
||||||
private static final int GETFENV = 14;
|
private static final int RAWSET = 14;
|
||||||
private static final int SETFENV = 15;
|
private static final int GETFENV = 15;
|
||||||
private static final int SELECT = 16;
|
private static final int SETFENV = 16;
|
||||||
private static final int COLLECTGARBAGE = 17;
|
private static final int SELECT = 17;
|
||||||
private static final int DOFILE = 18;
|
private static final int COLLECTGARBAGE = 18;
|
||||||
private static final int LOADSTRING = 19;
|
private static final int DOFILE = 19;
|
||||||
private static final int LOAD = 20;
|
private static final int LOADSTRING = 20;
|
||||||
private static final int TOSTRING = 21;
|
private static final int LOAD = 21;
|
||||||
private static final int UNPACK = 22;
|
private static final int TOSTRING = 22;
|
||||||
private static final int XPCALL = 23;
|
private static final int UNPACK = 23;
|
||||||
private static final int NEXT = 24;
|
private static final int XPCALL = 24;
|
||||||
private static final int INEXT = 25;
|
private static final int NEXT = 25;
|
||||||
|
private static final int INEXT = 26;
|
||||||
|
|
||||||
private static LFunction next;
|
private static LFunction next;
|
||||||
private static LFunction inext;
|
private static LFunction inext;
|
||||||
@@ -165,15 +168,16 @@ public class BaseLib extends LFunction {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SETMETATABLE: {
|
case SETMETATABLE: {
|
||||||
vm.checktable(2);
|
LTable t = vm.checktable(2);
|
||||||
vm.setmetatable(2);
|
LValue v = vm.checkany(3);
|
||||||
vm.remove(1);
|
vm.argcheck(v.isTable() || v.isNil(), 3, "table or nil expected");
|
||||||
vm.settop(1);
|
t.luaSetMetatable(v);
|
||||||
|
vm.resettop();
|
||||||
|
vm.pushlvalue(t);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TYPE: {
|
case TYPE: {
|
||||||
vm.checkany(2);
|
LValue v = vm.checkany(2);
|
||||||
LValue v = vm.topointer(2);
|
|
||||||
vm.resettop();
|
vm.resettop();
|
||||||
vm.pushlstring( v.luaGetTypeName() );
|
vm.pushlstring( v.luaGetTypeName() );
|
||||||
break;
|
break;
|
||||||
@@ -193,8 +197,7 @@ public class BaseLib extends LFunction {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case XPCALL: {
|
case XPCALL: {
|
||||||
vm.checkany(3);
|
LValue errfun = vm.checkany(3);
|
||||||
LValue errfun = vm.topointer(3);
|
|
||||||
vm.settop(2);
|
vm.settop(2);
|
||||||
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 above the xpcall
|
||||||
@@ -247,56 +250,45 @@ public class BaseLib extends LFunction {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case RAWEQUAL: {
|
||||||
|
LValue a = vm.checkany(2);
|
||||||
|
LValue b = vm.checkany(3);
|
||||||
|
vm.resettop();
|
||||||
|
vm.pushboolean(a == b);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case RAWGET: {
|
case RAWGET: {
|
||||||
vm.checkany(3);
|
|
||||||
LTable t = vm.checktable(2);
|
LTable t = vm.checktable(2);
|
||||||
LValue k = vm.topointer(3);
|
LValue k = vm.checkany(3);
|
||||||
vm.resettop();
|
vm.resettop();
|
||||||
vm.pushlvalue( t.get( k ) );
|
vm.pushlvalue( t.get( k ) );
|
||||||
} break;
|
break;
|
||||||
|
}
|
||||||
case RAWSET: {
|
case RAWSET: {
|
||||||
vm.checkany(3);
|
|
||||||
vm.checkany(4);
|
|
||||||
LTable t = vm.checktable(2);
|
LTable t = vm.checktable(2);
|
||||||
LValue k = vm.topointer(3);
|
LValue k = vm.checkany(3);
|
||||||
LValue v = vm.topointer(4);
|
LValue v = vm.checkany(4);
|
||||||
t.put( k, v );
|
t.put( k, v );
|
||||||
vm.resettop();
|
vm.resettop();
|
||||||
vm.pushlvalue(t);
|
vm.pushlvalue(t);
|
||||||
} break;
|
break;
|
||||||
|
}
|
||||||
case GETFENV: {
|
case GETFENV: {
|
||||||
if ( vm.isfunction(2) ) {
|
LValue f = getfunc(vm, true);
|
||||||
vm.getfenv(-1);
|
vm.resettop();
|
||||||
} else {
|
vm.pushlvalue(f.luaGetEnv(vm._G));
|
||||||
int i = vm.optint(2,1);
|
|
||||||
if ( i <= 0 )
|
|
||||||
vm.pushlvalue(vm._G);
|
|
||||||
else if ( i-1 <= vm.cc )
|
|
||||||
vm.pushlvalue( vm.getStackFrame(i-1).closure.env );
|
|
||||||
else
|
|
||||||
vm.pushnil();
|
|
||||||
}
|
|
||||||
vm.insert(1);
|
|
||||||
vm.settop(1);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SETFENV: {
|
case SETFENV: {
|
||||||
LTable t = vm.checktable(-1);
|
LTable t = vm.checktable(3);
|
||||||
LFunction f = vm.checkfunction(2);
|
LValue f = getfunc(vm, false);
|
||||||
if ( vm.setfenv(2) != 0 ) {
|
if ( vm.isnumber(2) && vm.tointeger(2) == 0 ) {
|
||||||
vm.remove(1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
int i = vm.tointeger(2);
|
|
||||||
if ( i == 0 ) {
|
|
||||||
vm._G = t;
|
vm._G = t;
|
||||||
vm.resettop();
|
} else if ( (!(f instanceof LClosure)) || ! f.luaSetEnv(t) ) {
|
||||||
} else {
|
vm.error( "'setfenv' cannot change environment of given object" );
|
||||||
LClosure c = vm.getStackFrame(i-1).closure;
|
|
||||||
c.luaSetEnv(t);
|
|
||||||
vm.resettop();
|
|
||||||
vm.pushlvalue(c);
|
|
||||||
}
|
}
|
||||||
|
vm.resettop();
|
||||||
|
vm.pushlvalue(f);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SELECT: {
|
case SELECT: {
|
||||||
@@ -307,7 +299,7 @@ public class BaseLib extends LFunction {
|
|||||||
if ( index < 0 )
|
if ( index < 0 )
|
||||||
index += n-1;
|
index += n-1;
|
||||||
if ( index <= 0 )
|
if ( index <= 0 )
|
||||||
vm.error( "bad argument #1 to '?' (index out of range)" );
|
vm.typerror( 2, "index out of range" );
|
||||||
if ( index >= n )
|
if ( index >= n )
|
||||||
vm.resettop();
|
vm.resettop();
|
||||||
else {
|
else {
|
||||||
@@ -317,6 +309,8 @@ public class BaseLib extends LFunction {
|
|||||||
} else if ( vm.checkstring(2).equals( "#" ) ) {
|
} else if ( vm.checkstring(2).equals( "#" ) ) {
|
||||||
vm.resettop();
|
vm.resettop();
|
||||||
vm.pushnumber( n - 2 );
|
vm.pushnumber( n - 2 );
|
||||||
|
} else {
|
||||||
|
vm.typerror(2,"expected number or '#'");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -346,8 +340,7 @@ public class BaseLib extends LFunction {
|
|||||||
load(vm);
|
load(vm);
|
||||||
break;
|
break;
|
||||||
case TOSTRING: {
|
case TOSTRING: {
|
||||||
vm.checkany(2);
|
LValue v = vm.checkany(2);
|
||||||
LValue v = vm.topointer(2);
|
|
||||||
vm.resettop();
|
vm.resettop();
|
||||||
vm.pushlvalue( v.luaAsString() );
|
vm.pushlvalue( v.luaAsString() );
|
||||||
break;
|
break;
|
||||||
@@ -374,6 +367,21 @@ public class BaseLib extends LFunction {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static LValue getfunc (LuaState vm, boolean opt) {
|
||||||
|
if ( vm.isfunction(2) )
|
||||||
|
return vm.tojavafunction(2);
|
||||||
|
else {
|
||||||
|
int level = opt? vm.optint(2, 1): vm.checkint(2);
|
||||||
|
vm.argcheck(level >= 0, 2, "level must be non-negative");
|
||||||
|
vm.argcheck(level-1 <= vm.cc, 2, "invalid level");
|
||||||
|
CallInfo ci = vm.getStackFrame(level-1);
|
||||||
|
if ( ci == null || ci.closure == null )
|
||||||
|
return LNil.NIL;
|
||||||
|
return ci.closure;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void redirectOutput( OutputStream newStdOut ) {
|
public static void redirectOutput( OutputStream newStdOut ) {
|
||||||
STDOUT = new PrintStream( newStdOut );
|
STDOUT = new PrintStream( newStdOut );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,9 +49,9 @@ public class LClosure extends LFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Set the environment if a thread, or closure, and return 1, otherwise return 0 */
|
/** Set the environment if a thread, or closure, and return 1, otherwise return 0 */
|
||||||
public int luaSetEnv(LTable t) {
|
public boolean luaSetEnv(LTable t) {
|
||||||
this.env = t;
|
this.env = t;
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the enviroment for this closure */
|
/** Get the enviroment for this closure */
|
||||||
|
|||||||
@@ -37,18 +37,6 @@ public class LFunction extends LValue {
|
|||||||
return Lua.LUA_TFUNCTION;
|
return Lua.LUA_TFUNCTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the environment of the object if it is a closure, or d if not a closure.
|
|
||||||
*
|
|
||||||
* @param d global environment
|
|
||||||
* @return environment for this object, or d if it is not an LClosure
|
|
||||||
* @see LClosure
|
|
||||||
* @see LTable
|
|
||||||
*/
|
|
||||||
public LTable luaGetEnv(LTable d) {
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up a Java invocation, and leave the results on the stack
|
* Set up a Java invocation, and leave the results on the stack
|
||||||
* starting at base. The default implementation for LFunction
|
* starting at base. The default implementation for LFunction
|
||||||
|
|||||||
@@ -60,9 +60,9 @@ public class LThread extends LValue implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Set the environment if a thread, or closure, and return 1, otherwise return 0 */
|
/** Set the environment if a thread, or closure, and return 1, otherwise return 0 */
|
||||||
public int luaSetEnv(LTable t) {
|
public boolean luaSetEnv(LTable t) {
|
||||||
threadVm._G = t;
|
threadVm._G = t;
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStatus() {
|
public String getStatus() {
|
||||||
|
|||||||
@@ -292,11 +292,19 @@ public class LValue {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the environment if a thread, or closure, and return 1, otherwise return 0 */
|
/** Set the environment if a thread, or closure, and return true, otherwise return false */
|
||||||
public int luaSetEnv(LTable t) {
|
public boolean luaSetEnv(LTable t) {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get the environment of the object if it is a closure, or d if not a closure.
|
||||||
|
* @param d global environment to return if this is not a closure
|
||||||
|
*/
|
||||||
|
public LTable luaGetEnv(LTable d) {
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Convert to a number if possible, or nil otherwise */
|
/** Convert to a number if possible, or nil otherwise */
|
||||||
public LValue luaToNumber() {
|
public LValue luaToNumber() {
|
||||||
return LNil.NIL;
|
return LNil.NIL;
|
||||||
|
|||||||
@@ -1248,9 +1248,9 @@ public class LuaState extends Lua {
|
|||||||
* Pops a table from the stack and sets it as the new environment for the
|
* Pops a table from the stack and sets it as the new environment for the
|
||||||
* value at the given index. If the value at the given index is neither a
|
* value at the given index. If the value at the given index is neither a
|
||||||
* function nor a thread nor a userdata, <a href="#lua_setfenv"><code>lua_setfenv</code></a>
|
* function nor a thread nor a userdata, <a href="#lua_setfenv"><code>lua_setfenv</code></a>
|
||||||
* returns 0. Otherwise it returns 1.
|
* returns false. Otherwise it returns true.
|
||||||
*/
|
*/
|
||||||
public int setfenv(int index) {
|
public boolean setfenv(int index) {
|
||||||
LTable t = totable(-1);
|
LTable t = totable(-1);
|
||||||
LValue f = topointer(index);
|
LValue f = topointer(index);
|
||||||
pop(1);
|
pop(1);
|
||||||
@@ -2661,11 +2661,13 @@ public class LuaState extends Lua {
|
|||||||
* Checks whether the function has an argument of any type (including <b>nil</b>)
|
* Checks whether the function has an argument of any type (including <b>nil</b>)
|
||||||
* at position <code>narg</code>.
|
* at position <code>narg</code>.
|
||||||
* @param narg the argument number
|
* @param narg the argument number
|
||||||
|
* @return the value at the index
|
||||||
* @throws LuaErrorException if there is no argument at position narg
|
* @throws LuaErrorException if there is no argument at position narg
|
||||||
*/
|
*/
|
||||||
public void checkany(int narg) {
|
public LValue checkany(int narg) {
|
||||||
if ( gettop() < narg )
|
if ( gettop() < narg )
|
||||||
argerror(narg, "value expected");
|
argerror(narg, "value expected");
|
||||||
|
return topointer(narg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ checkallerrors('pairs', {notatable}, 'bad argument #1')
|
|||||||
|
|
||||||
-- pcall
|
-- pcall
|
||||||
banner('pcall')
|
banner('pcall')
|
||||||
checkallpass('pcall', {notanil,anylua})
|
checkallpass('pcall', {notanil,anylua}, true)
|
||||||
checkallerrors('pcall',{},'bad argument #1')
|
checkallerrors('pcall',{},'bad argument #1')
|
||||||
|
|
||||||
-- print
|
-- print
|
||||||
@@ -109,9 +109,12 @@ checkallerrors('select', {notanumber}, 'bad argument #1')
|
|||||||
|
|
||||||
-- setfenv
|
-- setfenv
|
||||||
banner('setfenv')
|
banner('setfenv')
|
||||||
|
local g = _G
|
||||||
checkallpass('setfenv', {{function()end},sometable})
|
checkallpass('setfenv', {{function()end},sometable})
|
||||||
checkallerrors('setfenv', {{1.23, '1.33'},{getfenv()}}, 'cannot change environment of given object')
|
checkallerrors('setfenv', {{-1, '-2'},{g}}, 'level must be non-negative')
|
||||||
checkallerrors('setfenv', {{atable,athread,aboolean,astring},sometable}, 'bad argument #1')
|
checkallerrors('setfenv', {{10, '11'},{g}}, 'invalid level')
|
||||||
|
checkallerrors('setfenv', {{rawset},{g}}, 'cannot change environment of given object')
|
||||||
|
checkallerrors('setfenv', {{atable,athread,aboolean,astring},{g}}, 'bad argument #1')
|
||||||
checkallerrors('setfenv', {notafunction}, 'bad argument #2')
|
checkallerrors('setfenv', {notafunction}, 'bad argument #2')
|
||||||
checkallerrors('setfenv', {anylua}, 'bad argument #2')
|
checkallerrors('setfenv', {anylua}, 'bad argument #2')
|
||||||
checkallerrors('setfenv', {{function()end},notatable}, 'bad argument #2')
|
checkallerrors('setfenv', {{function()end},notatable}, 'bad argument #2')
|
||||||
@@ -119,7 +122,7 @@ checkallerrors('setfenv', {{function()end},notatable}, 'bad argument #2')
|
|||||||
-- setmetatable
|
-- setmetatable
|
||||||
banner('setmetatable')
|
banner('setmetatable')
|
||||||
checkallpass('setmetatable', {sometable,sometable})
|
checkallpass('setmetatable', {sometable,sometable})
|
||||||
checkallpass('setmetatable', {sometable,{nil,atable},{'anchor'}})
|
checkallpass('setmetatable', {sometable,{}})
|
||||||
checkallerrors('setmetatable',{notatable,sometable},'bad argument #1')
|
checkallerrors('setmetatable',{notatable,sometable},'bad argument #1')
|
||||||
checkallerrors('setmetatable',{sometable,notatable},'bad argument #2')
|
checkallerrors('setmetatable',{sometable,notatable},'bad argument #2')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user