diff --git a/src/core/org/luaj/vm2/lib/BaseLib.java b/src/core/org/luaj/vm2/lib/BaseLib.java index 85ac8fcd..ffd6c72e 100644 --- a/src/core/org/luaj/vm2/lib/BaseLib.java +++ b/src/core/org/luaj/vm2/lib/BaseLib.java @@ -76,17 +76,17 @@ public class BaseLib extends OneArgFunction implements ResourceFinder { public LuaValue call(LuaValue arg) { env.set( "_G", env ); env.set( "_VERSION", VERSION ); - bind1( env, new String[] { + bind( env, BaseLib1.class, new String[] { "getfenv", // ( [f] ) -> env "getmetatable", // ( object ) -> table } ); - bind2( env, new String[] { + bind( env, BaseLib2.class, new String[] { "collectgarbage", // ( opt [,arg] ) -> value "error", // ( message [,level] ) -> ERR "rawequal", // (v1, v2) -> boolean "setfenv", // (f, table) -> void } ); - bindv( env, new String[] { + bind( env, BaseLibV.class, new String[] { "assert", // ( v [,message] ) -> v, message | ERR "dofile", // ( filename ) -> result1, ... "load", // ( func [,chunkname] ) -> chunk | nil, msg @@ -113,6 +113,11 @@ public class BaseLib extends OneArgFunction implements ResourceFinder { next = env.get("next"); inext = env.get("__inext"); + // inject base lib + ((BaseLibV) env.get("print")).baselib = this; + ((BaseLibV) env.get("pairs")).baselib = this; + ((BaseLibV) env.get("ipairs")).baselib = this; + // set the default resource finder if not set already if ( FINDER == null ) FINDER = this; @@ -128,53 +133,57 @@ public class BaseLib extends OneArgFunction implements ResourceFinder { return c.getResourceAsStream(filename.startsWith("/")? filename: "/"+filename); } - protected LuaValue oncall1(int opcode, LuaValue arg) { - switch ( opcode ) { - case 0: { // "getfenv", // ( [f] ) -> env - LuaValue f = getfenvobj(arg); - LuaValue e = f.getfenv(); - return e!=null? e: NIL; - } - case 1: // "getmetatable", // ( object ) -> table - LuaValue mt = arg.getmetatable(); - return mt!=null? mt: NIL; - } - return NIL; - } - - protected LuaValue oncall2(int opcode, LuaValue arg1, LuaValue arg2) { - switch ( opcode ) { - case 0: // "collectgarbage", // ( opt [,arg] ) -> value - String s = arg1.optjstring("collect"); - int result = 0; - if ( "collect".equals(s) ) { - System.gc(); - return ZERO; + public static final class BaseLib1 extends OneArgFunction { + public LuaValue call(LuaValue arg) { + switch ( opcode ) { + case 0: { // "getfenv", // ( [f] ) -> env + LuaValue f = getfenvobj(arg); + LuaValue e = f.getfenv(); + return e!=null? e: NIL; } - else if ( "count".equals(s) ) { - Runtime rt = Runtime.getRuntime(); - long used = rt.totalMemory() - rt.freeMemory(); - return valueOf(used/1024.); - } else if ( "step".equals(s) ) { - System.gc(); - return LuaValue.TRUE; + case 1: // "getmetatable", // ( object ) -> table + LuaValue mt = arg.getmetatable(); + return mt!=null? mt: NIL; } return NIL; - case 1: // "error", // ( message [,level] ) -> ERR - throw new LuaError( arg1.isnil()? null: arg1.tojstring(), arg2.optint(1) ); - case 2: // "rawequal", // (v1, v2) -> boolean - return valueOf(arg1 == arg2); - case 3: { // "setfenv", // (f, table) -> void - LuaTable t = arg2.checktable(); - LuaValue f = getfenvobj(arg1); - f.setfenv(t); - return f.isthread()? NONE: f; } + } + + public static final class BaseLib2 extends TwoArgFunction { + public LuaValue call(LuaValue arg1, LuaValue arg2) { + switch ( opcode ) { + case 0: // "collectgarbage", // ( opt [,arg] ) -> value + String s = arg1.optjstring("collect"); + int result = 0; + if ( "collect".equals(s) ) { + System.gc(); + return ZERO; + } + else if ( "count".equals(s) ) { + Runtime rt = Runtime.getRuntime(); + long used = rt.totalMemory() - rt.freeMemory(); + return valueOf(used/1024.); + } else if ( "step".equals(s) ) { + System.gc(); + return LuaValue.TRUE; + } + return NIL; + case 1: // "error", // ( message [,level] ) -> ERR + throw new LuaError( arg1.isnil()? null: arg1.tojstring(), arg2.optint(1) ); + case 2: // "rawequal", // (v1, v2) -> boolean + return valueOf(arg1 == arg2); + case 3: { // "setfenv", // (f, table) -> void + LuaTable t = arg2.checktable(); + LuaValue f = getfenvobj(arg1); + f.setfenv(t); + return f.isthread()? NONE: f; + } + } + return NIL; } - return NIL; } - private LuaValue getfenvobj(LuaValue arg) { + private static LuaValue getfenvobj(LuaValue arg) { if ( arg.isclosure() ) return arg; int level = arg.optint(1); @@ -185,165 +194,168 @@ public class BaseLib extends OneArgFunction implements ResourceFinder { return f; } - protected Varargs oncallv(int opcode, Varargs args) { - switch ( opcode ) { - case 0: // "assert", // ( v [,message] ) -> v, message | ERR - if ( !args.arg1().toboolean() ) error("assertion failed!"); - return args; - case 1: // "dofile", // ( filename ) -> result1, ... - { - LuaValue chunk; - try { - String filename = args.checkjstring(1); - chunk = loadFile(filename).arg1(); - } catch ( IOException e ) { - return error(e.getMessage()); - } - return chunk.invoke(); - } - case 2: // "load", // ( func [,chunkname] ) -> chunk | nil, msg - try { - LuaValue func = args.checkfunction(1); - String chunkname = args.optString(2, "function"); - return LoadState.load(new StringInputStream(func), chunkname, LuaThread.getGlobals()); - } catch ( Exception e ) { - return varargsOf(NIL, valueOf(e.getMessage())); - } - case 3: // "loadfile", // ( [filename] ) -> chunk | nil, msg - { - try { - String filename = args.checkjstring(1); - return loadFile(filename); - } catch ( Exception e ) { - return varargsOf(NIL, valueOf(e.getMessage())); - } - } - case 4: // "loadstring", // ( string [,chunkname] ) -> chunk | nil, msg - try { - LuaString script = args.checkstring(1); - String chunkname = args.optString(2, "string"); - return LoadState.load(script.toInputStream(),chunkname,LuaThread.getGlobals()); - } catch ( Exception e ) { - return varargsOf(NIL, valueOf(e.getMessage())); - } - case 5: // "pcall", // (f, arg1, ...) -> status, result1, ... - try { - LuaThread.onCall(this); + public static final class BaseLibV extends VarArgFunction { + public BaseLib baselib; + public Varargs invoke(Varargs args) { + switch ( opcode ) { + case 0: // "assert", // ( v [,message] ) -> v, message | ERR + if ( !args.arg1().toboolean() ) error("assertion failed!"); + return args; + case 1: // "dofile", // ( filename ) -> result1, ... + { + LuaValue chunk; try { - return varargsOf(LuaValue.TRUE, args.arg1().invoke(args.subargs(2))); - } finally { - LuaThread.onReturn(); + String filename = args.checkjstring(1); + chunk = loadFile(filename).arg1(); + } catch ( IOException e ) { + return error(e.getMessage()); } - } catch ( LuaError le ) { - String m = le.getMessage(); - return varargsOf(FALSE, m!=null? valueOf(m): NIL); - } catch ( Exception e ) { - String m = e.getMessage(); - return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); + return chunk.invoke(); } - case 6: // "xpcall", // (f, err) -> result1, ... - { - LuaValue errfunc = args.checkvalue(2); - try { - LuaThread.onCall(this); + case 2: // "load", // ( func [,chunkname] ) -> chunk | nil, msg try { - LuaThread thread = LuaThread.getRunning(); - LuaValue olderr = thread.err; + LuaValue func = args.checkfunction(1); + String chunkname = args.optString(2, "function"); + return LoadState.load(new StringInputStream(func), chunkname, LuaThread.getGlobals()); + } catch ( Exception e ) { + return varargsOf(NIL, valueOf(e.getMessage())); + } + case 3: // "loadfile", // ( [filename] ) -> chunk | nil, msg + { + try { + String filename = args.checkjstring(1); + return loadFile(filename); + } catch ( Exception e ) { + return varargsOf(NIL, valueOf(e.getMessage())); + } + } + case 4: // "loadstring", // ( string [,chunkname] ) -> chunk | nil, msg + try { + LuaString script = args.checkstring(1); + String chunkname = args.optString(2, "string"); + return LoadState.load(script.toInputStream(),chunkname,LuaThread.getGlobals()); + } catch ( Exception e ) { + return varargsOf(NIL, valueOf(e.getMessage())); + } + case 5: // "pcall", // (f, arg1, ...) -> status, result1, ... + try { + LuaThread.onCall(this); try { - thread.err = errfunc; return varargsOf(LuaValue.TRUE, args.arg1().invoke(args.subargs(2))); } finally { - thread.err = olderr; + LuaThread.onReturn(); } - } finally { - LuaThread.onReturn(); + } catch ( LuaError le ) { + String m = le.getMessage(); + return varargsOf(FALSE, m!=null? valueOf(m): NIL); + } catch ( Exception e ) { + String m = e.getMessage(); + return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); + } + case 6: // "xpcall", // (f, err) -> result1, ... + { + LuaValue errfunc = args.checkvalue(2); + try { + LuaThread.onCall(this); + try { + LuaThread thread = LuaThread.getRunning(); + LuaValue olderr = thread.err; + try { + thread.err = errfunc; + return varargsOf(LuaValue.TRUE, args.arg1().invoke(args.subargs(2))); + } finally { + thread.err = olderr; + } + } finally { + LuaThread.onReturn(); + } + } catch ( LuaError le ) { + String m = le.getMessage(); + return varargsOf(FALSE, m!=null? valueOf(m): NIL); + } catch ( Exception e ) { + String m = e.getMessage(); + return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); } - } catch ( LuaError le ) { - String m = le.getMessage(); - return varargsOf(FALSE, m!=null? valueOf(m): NIL); - } catch ( Exception e ) { - String m = e.getMessage(); - return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); } - } - case 7: // "print", // (...) -> void - { - LuaValue tostring = LuaThread.getGlobals().get("tostring"); - for ( int i=1, n=args.narg(); i<=n; i++ ) { - if ( i>1 ) STDOUT.write( '\t' ); - LuaString s = tostring.call( args.arg(i) ).strvalue(); - int z = s.indexOf((byte)0, 0); - STDOUT.write( s.m_bytes, s.m_offset, z>=0? z: s.m_length ); + case 7: // "print", // (...) -> void + { + LuaValue tostring = LuaThread.getGlobals().get("tostring"); + for ( int i=1, n=args.narg(); i<=n; i++ ) { + if ( i>1 ) baselib.STDOUT.write( '\t' ); + LuaString s = tostring.call( args.arg(i) ).strvalue(); + int z = s.indexOf((byte)0, 0); + baselib.STDOUT.write( s.m_bytes, s.m_offset, z>=0? z: s.m_length ); + } + baselib.STDOUT.println(); + return NONE; + } + case 8: // "select", // (f, ...) -> value1, ... + { + int n = args.narg()-1; + if ( args.arg1().equals(valueOf("#")) ) + return valueOf(n); + int i = args.checkint(1); + if ( i == 0 || i < -n ) + typerror(1,"index out of range"); + return args.subargs(i<0? n+i+2: i+1); + } + case 9: // "unpack", // (list [,i [,j]]) -> result1, ... + { + int na = args.narg(); + LuaTable t = args.checktable(1); + int n = t.length(); + int i = na>=2? args.checkint(2): 1; + int j = na>=3? args.checkint(3): n; + n = j-i+1; + if ( n<0 ) return NONE; + if ( n==1 ) return t.get(i); + if ( n==2 ) return varargsOf(t.get(i),t.get(j)); + LuaValue[] v = new LuaValue[n]; + for ( int k=0; k value + return valueOf(args.checkvalue(1).typename()); + case 11: // "rawget", // (table, index) -> value + return args.checktable(1).rawget(args.checkvalue(2)); + case 12: { // "rawset", // (table, index, value) -> table + LuaTable t = args.checktable(1); + t.rawset(args.checknotnil(2), args.checkvalue(3)); + return t; + } + case 13: { // "setmetatable", // (table, metatable) -> table + final LuaValue t = args.arg1(); + final LuaValue mt = args.checkvalue(2); + return t.setmetatable(mt.isnil()? null: mt.checktable()); + } + case 14: { // "tostring", // (e) -> value + LuaValue arg = args.checkvalue(1); + return arg.type() == LuaValue.TSTRING? arg: valueOf(arg.tojstring()); + } + case 15: { // "tonumber", // (e [,base]) -> value + LuaValue arg1 = args.checkvalue(1); + final int base = args.optint(2,10); + if (base == 10) { /* standard conversion */ + return arg1.tonumber(); + } else { + if ( base < 2 || base > 36 ) + argerror(2, "base out of range"); + final LuaString str = arg1.optstring(null); + return str!=null? str.tonumber(base): NIL; + } + } + case 16: // "pairs" (t) -> iter-func, t, nil + return varargsOf( baselib.next, args.checktable(1) ); + case 17: // "ipairs", // (t) -> iter-func, t, 0 + return varargsOf( baselib.inext, args.checktable(1), ZERO ); + case 18: // "next" ( table, [index] ) -> next-index, next-value + return args.arg1().next(args.arg(2)); + case 19: // "inext" ( table, [int-index] ) -> next-index, next-value + return args.arg1().inext(args.arg(2)); } - STDOUT.println(); return NONE; } - case 8: // "select", // (f, ...) -> value1, ... - { - int n = args.narg()-1; - if ( args.arg1().equals(valueOf("#")) ) - return valueOf(n); - int i = args.checkint(1); - if ( i == 0 || i < -n ) - typerror(1,"index out of range"); - return args.subargs(i<0? n+i+2: i+1); - } - case 9: // "unpack", // (list [,i [,j]]) -> result1, ... - { - int na = args.narg(); - LuaTable t = args.checktable(1); - int n = t.length(); - int i = na>=2? args.checkint(2): 1; - int j = na>=3? args.checkint(3): n; - n = j-i+1; - if ( n<0 ) return NONE; - if ( n==1 ) return t.get(i); - if ( n==2 ) return varargsOf(t.get(i),t.get(j)); - LuaValue[] v = new LuaValue[n]; - for ( int k=0; k value - return valueOf(args.checkvalue(1).typename()); - case 11: // "rawget", // (table, index) -> value - return args.checktable(1).rawget(args.checkvalue(2)); - case 12: { // "rawset", // (table, index, value) -> table - LuaTable t = args.checktable(1); - t.rawset(args.checknotnil(2), args.checkvalue(3)); - return t; - } - case 13: { // "setmetatable", // (table, metatable) -> table - final LuaValue t = args.arg1(); - final LuaValue mt = args.checkvalue(2); - return t.setmetatable(mt.isnil()? null: mt.checktable()); - } - case 14: { // "tostring", // (e) -> value - LuaValue arg = args.checkvalue(1); - return arg.type() == LuaValue.TSTRING? arg: valueOf(arg.tojstring()); - } - case 15: { // "tonumber", // (e [,base]) -> value - LuaValue arg1 = args.checkvalue(1); - final int base = args.optint(2,10); - if (base == 10) { /* standard conversion */ - return arg1.tonumber(); - } else { - if ( base < 2 || base > 36 ) - argerror(2, "base out of range"); - final LuaString str = arg1.optstring(null); - return str!=null? str.tonumber(base): NIL; - } - } - case 16: // "pairs" (t) -> iter-func, t, nil - return varargsOf( next, args.checktable(1) ); - case 17: // "ipairs", // (t) -> iter-func, t, 0 - return varargsOf( inext, args.checktable(1), ZERO ); - case 18: // "next" ( table, [index] ) -> next-index, next-value - return args.arg1().next(args.arg(2)); - case 19: // "inext" ( table, [int-index] ) -> next-index, next-value - return args.arg1().inext(args.arg(2)); - } - return NONE; } public static Varargs loadFile(String filename) throws IOException { diff --git a/src/core/org/luaj/vm2/lib/DebugLib.java b/src/core/org/luaj/vm2/lib/DebugLib.java index 5daf4465..be7e41c8 100644 --- a/src/core/org/luaj/vm2/lib/DebugLib.java +++ b/src/core/org/luaj/vm2/lib/DebugLib.java @@ -111,28 +111,31 @@ public class DebugLib extends OneArgFunction { public LuaValue call(LuaValue arg) { LuaTable t = new LuaTable(); - bindv(t, NAMES); + bind(t, DebugLibV.class, NAMES); env.set("debug", t); return t; } - protected Varargs oncallv(int opcode, Varargs args) { - switch ( opcode ) { - case DEBUG: return _debug(args); - case GETFENV: return _getfenv(args); - case GETHOOK: return _gethook(args); - case GETINFO: return _getinfo(args); - case GETLOCAL: return _getlocal(args); - case GETMETATABLE: return _getmetatable(args); - case GETREGISTRY: return _getregistry(args); - case GETUPVALUE: return _getupvalue(args); - case SETFENV: return _setfenv(args); - case SETHOOK: return _sethook(args); - case SETLOCAL: return _setlocal(args); - case SETMETATABLE: return _setmetatable(args); - case SETUPVALUE: return _setupvalue(args); - case TRACEBACK: return _traceback(args); - default: return NONE; + public static final class DebugLibV extends VarArgFunction { + protected DebugLib debuglib; + public Varargs invoke(Varargs args) { + switch ( opcode ) { + case DEBUG: return _debug(args); + case GETFENV: return _getfenv(args); + case GETHOOK: return _gethook(args); + case GETINFO: return _getinfo(args,this); + case GETLOCAL: return _getlocal(args); + case GETMETATABLE: return _getmetatable(args); + case GETREGISTRY: return _getregistry(args); + case GETUPVALUE: return _getupvalue(args); + case SETFENV: return _setfenv(args); + case SETHOOK: return _sethook(args); + case SETLOCAL: return _setlocal(args); + case SETMETATABLE: return _setmetatable(args); + case SETUPVALUE: return _setupvalue(args); + case TRACEBACK: return _traceback(args); + default: return NONE; + } } } @@ -406,7 +409,7 @@ public class DebugLib extends OneArgFunction { return object; } - protected Varargs _getinfo(Varargs args) { + protected static Varargs _getinfo(Varargs args, LuaValue level0func) { int a=1; LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning(); LuaValue func = args.arg(a++); @@ -419,7 +422,7 @@ public class DebugLib extends OneArgFunction { int level = func.checkint(); di = level>0? ds.getDebugInfo(level-1): - new DebugInfo( this ); + new DebugInfo( level0func ); } else { di = ds.findDebugInfo( func.checkfunction() ); } diff --git a/src/core/org/luaj/vm2/lib/LibFunction.java b/src/core/org/luaj/vm2/lib/LibFunction.java index 8a3866a4..23868d40 100644 --- a/src/core/org/luaj/vm2/lib/LibFunction.java +++ b/src/core/org/luaj/vm2/lib/LibFunction.java @@ -21,14 +21,42 @@ ******************************************************************************/ package org.luaj.vm2.lib; +import org.luaj.vm2.LuaError; import org.luaj.vm2.LuaFunction; import org.luaj.vm2.LuaValue; import org.luaj.vm2.Varargs; abstract public class LibFunction extends LuaFunction { + protected int opcode; + protected String name; + protected LibFunction() { } + + public String tojstring() { + return name != null? name: super.tojstring(); + } + + protected void bind(LuaValue env, Class factory, String[] names ) { + bind( env, factory, names, 0 ); + } + + protected void bind(LuaValue env, Class factory, String[] names, int firstopcode ) { + try { + for ( int i=0, n=names.length; i=0? Math.floor(q): Math.ceil(q)); - return valueOf( f ); + public static final class MathLib2 extends TwoArgFunction { + protected MathLib mathlib; + public LuaValue call(LuaValue arg1, LuaValue arg2) { + switch ( opcode ) { + case 0: { // fmod + double x = arg1.checkdouble(); + double y = arg2.checkdouble(); + double q = x/y; + double f = x - y * (q>=0? Math.floor(q): Math.ceil(q)); + return valueOf( f ); + } + case 1: { // ldexp + double x = arg1.checkdouble(); + double y = arg2.checkdouble()+1023.5; + long e = (long) ((0!=(1&((int)y)))? Math.floor(y): Math.ceil(y-1)); + return valueOf(x * Double.longBitsToDouble(e << 52)); + } + case 2: { // pow + return dpow(arg1.todouble(), arg2.todouble()); + } + case 3: { // random + if ( mathlib.random == null ) + mathlib.random = new Random(); + if ( arg1.isnil() ) + return valueOf( mathlib.random.nextDouble() ); + int m = arg1.toint(); + if ( arg2.isnil() ) + return valueOf( 1 + mathlib.random.nextInt(m) ); + else + return valueOf( m + mathlib.random.nextInt(arg2.toint()-m) ); + } + } + return NIL; } - case 1: { // ldexp - double x = arg1.checkdouble(); - double y = arg2.checkdouble()+1023.5; - long e = (long) ((0!=(1&((int)y)))? Math.floor(y): Math.ceil(y-1)); - return valueOf(x * Double.longBitsToDouble(e << 52)); - } - case 2: { // pow - return dpow(arg1.todouble(), arg2.todouble()); - } - case 3: { // random - if ( random == null ) - random = new Random(); - if ( arg1.isnil() ) - return valueOf( random.nextDouble() ); - int m = arg1.toint(); - if ( arg2.isnil() ) - return valueOf( 1 + random.nextInt(m) ); - else - return valueOf( m + random.nextInt(arg2.toint()-m) ); - } - } - return NIL; } /** compute power using installed math library, or default if there is no math library installed */ @@ -148,40 +155,43 @@ public class MathLib extends OneArgFunction { return p; } - public Varargs oncallv(int opcode,Varargs args) { - switch ( opcode ) { - case 0: { // frexp - double x = args.checkdouble(1); - if ( x == 0 ) return varargsOf(ZERO,ZERO); - long bits = Double.doubleToLongBits( x ); - double m = ((bits & (~(-1L<<52))) + (1L<<52)) * ((bits >= 0)? (.5 / (1L<<52)): (-.5 / (1L<<52))); - double e = (((int) (bits >> 52)) & 0x7ff) - 1022; - return varargsOf( valueOf(m), valueOf(e) ); - } - case 1: { // max - double m = args.checkdouble(1); - for ( int i=2,n=args.narg(); i<=n; ++i ) - m = Math.max(m,args.checkdouble(i)); - return valueOf(m); - } - case 2: { // min - double m = args.checkdouble(1); - for ( int i=2,n=args.narg(); i<=n; ++i ) - m = Math.min(m,args.checkdouble(i)); - return valueOf(m); - } - case 3: { // modf - double x = args.checkdouble(1); - double intPart = ( x > 0 ) ? Math.floor( x ) : Math.ceil( x ); - double fracPart = x - intPart; - return varargsOf( valueOf(intPart), valueOf(fracPart) ); - } - case 4: { // randomseed - long seed = args.checklong(1); - random = new Random(seed); + public static final class MathLibV extends VarArgFunction { + protected MathLib mathlib; + public Varargs invoke(Varargs args) { + switch ( opcode ) { + case 0: { // frexp + double x = args.checkdouble(1); + if ( x == 0 ) return varargsOf(ZERO,ZERO); + long bits = Double.doubleToLongBits( x ); + double m = ((bits & (~(-1L<<52))) + (1L<<52)) * ((bits >= 0)? (.5 / (1L<<52)): (-.5 / (1L<<52))); + double e = (((int) (bits >> 52)) & 0x7ff) - 1022; + return varargsOf( valueOf(m), valueOf(e) ); + } + case 1: { // max + double m = args.checkdouble(1); + for ( int i=2,n=args.narg(); i<=n; ++i ) + m = Math.max(m,args.checkdouble(i)); + return valueOf(m); + } + case 2: { // min + double m = args.checkdouble(1); + for ( int i=2,n=args.narg(); i<=n; ++i ) + m = Math.min(m,args.checkdouble(i)); + return valueOf(m); + } + case 3: { // modf + double x = args.checkdouble(1); + double intPart = ( x > 0 ) ? Math.floor( x ) : Math.ceil( x ); + double fracPart = x - intPart; + return varargsOf( valueOf(intPart), valueOf(fracPart) ); + } + case 4: { // randomseed + long seed = args.checklong(1); + mathlib.random = new Random(seed); + return NONE; + } + } return NONE; } - } - return NONE; } } diff --git a/src/core/org/luaj/vm2/lib/StringLib.java b/src/core/org/luaj/vm2/lib/StringLib.java index 8be76f5e..51619918 100644 --- a/src/core/org/luaj/vm2/lib/StringLib.java +++ b/src/core/org/luaj/vm2/lib/StringLib.java @@ -41,9 +41,9 @@ public class StringLib extends OneArgFunction { public LuaValue call(LuaValue arg) { LuaTable t = new LuaTable(); - bind1(t, new String[] { + bind(t, StringLib1.class, new String[] { "dump", "len", "lower", "reverse", "upper", } ); - bindv(t, new String[] { + bind(t, StringLibV.class, new String[] { "byte", "char", "find", "format", "gmatch", "gsub", "match", "rep", "sub"} ); @@ -52,31 +52,34 @@ public class StringLib extends OneArgFunction { return t; } - protected LuaValue oncall1(int opcode, LuaValue arg) { - switch ( opcode ) { - case 0: return dump(arg); // dump (function) - case 1: return len(arg); // len (function) - case 2: return lower(arg); // lower (function) - case 3: return reverse(arg); // reverse (function) - case 4: return upper(arg); // upper (function) + public static final class StringLib1 extends OneArgFunction { + public LuaValue call(LuaValue arg) { + switch ( opcode ) { + case 0: return dump(arg); // dump (function) + case 1: return StringLib.len(arg); // len (function) + case 2: return lower(arg); // lower (function) + case 3: return reverse(arg); // reverse (function) + case 4: return upper(arg); // upper (function) + } + return NIL; } - return NIL; } - - protected Varargs oncallv(int opcode, Varargs args) { - switch ( opcode ) { - case 0: return StringLib.byte_( args ); - case 1: return StringLib.char_( args ); - case 2: return StringLib.find( args ); - case 3: return StringLib.format( args ); - case 4: return StringLib.gmatch( args ); - case 5: return StringLib.gsub( args ); - case 6: return StringLib.match( args ); - case 7: return StringLib.rep( args ); - case 8: return StringLib.sub( args ); + public static final class StringLibV extends VarArgFunction { + public Varargs invoke(Varargs args) { + switch ( opcode ) { + case 0: return StringLib.byte_( args ); + case 1: return StringLib.char_( args ); + case 2: return StringLib.find( args ); + case 3: return StringLib.format( args ); + case 4: return StringLib.gmatch( args ); + case 5: return StringLib.gsub( args ); + case 6: return StringLib.match( args ); + case 7: return StringLib.rep( args ); + case 8: return StringLib.sub( args ); + } + return NONE; } - return NONE; } /** diff --git a/src/core/org/luaj/vm2/lib/TableLib.java b/src/core/org/luaj/vm2/lib/TableLib.java index 8a0b0938..8816aba5 100644 --- a/src/core/org/luaj/vm2/lib/TableLib.java +++ b/src/core/org/luaj/vm2/lib/TableLib.java @@ -32,11 +32,11 @@ public class TableLib extends OneArgFunction { public LuaValue call(LuaValue arg) { LuaTable t = new LuaTable(); - bind1(t, new String[] { + bind(t, TableLib1.class, new String[] { "getn", // (table) -> number "maxn", // (table) -> number } ); - bindv(t, new String[] { + bind(t, TableLibV.class, new String[] { "remove", // (table [, pos]) -> removed-ele "concat", // (table [, sep [, i [, j]]]) -> string "insert", // (table, [pos,] value) -> prev-ele @@ -48,46 +48,50 @@ public class TableLib extends OneArgFunction { return t; } - protected LuaValue oncall1(int opcode, LuaValue arg) { - switch ( opcode ) { - case 0: return arg.checktable().getn(); - case 1: return valueOf( arg.checktable().maxn()); + public static final class TableLib1 extends OneArgFunction { + public LuaValue call(LuaValue arg) { + switch ( opcode ) { + case 0: return arg.checktable().getn(); + case 1: return valueOf( arg.checktable().maxn()); + } + return NIL; } - return NIL; } - protected Varargs oncallv(int opcode, Varargs args) { - switch ( opcode ) { - case 0: { // "remove" (table [, pos]) -> removed-ele - LuaTable table = args.checktable(1); - int pos = args.narg()>1? args.checkint(2): 0; - return table.remove(pos); - } - case 1: { // "concat" (table [, sep [, i [, j]]]) -> string - LuaTable table = args.checktable(1); - return table.concat( - args.optstring(2,LuaValue.EMPTYSTRING), - args.optint(3,1), - args.isvalue(4)? args.checkint(4): table.length() ); - } - case 2: { // "insert" (table, [pos,] value) -> prev-ele - final LuaTable table = args.checktable(1); - final int pos = args.narg()>2? args.checkint(2): 0; - final LuaValue value = args.arg( args.narg()>2? 3: 2 ); - table.insert( pos, value ); + public static final class TableLibV extends VarArgFunction { + public Varargs invoke(Varargs args) { + switch ( opcode ) { + case 0: { // "remove" (table [, pos]) -> removed-ele + LuaTable table = args.checktable(1); + int pos = args.narg()>1? args.checkint(2): 0; + return table.remove(pos); + } + case 1: { // "concat" (table [, sep [, i [, j]]]) -> string + LuaTable table = args.checktable(1); + return table.concat( + args.optstring(2,LuaValue.EMPTYSTRING), + args.optint(3,1), + args.isvalue(4)? args.checkint(4): table.length() ); + } + case 2: { // "insert" (table, [pos,] value) -> prev-ele + final LuaTable table = args.checktable(1); + final int pos = args.narg()>2? args.checkint(2): 0; + final LuaValue value = args.arg( args.narg()>2? 3: 2 ); + table.insert( pos, value ); + return NONE; + } + case 3: { // "sort" (table [, comp]) -> void + args.checktable(1).sort( args.optvalue(2,NIL) ); + return NONE; + } + case 4: { // (table, func) -> void + return args.checktable(1).foreach( args.checkfunction(2) ); + } + case 5: { // "foreachi" (table, func) -> void + return args.checktable(1).foreachi( args.checkfunction(2) ); + } + } return NONE; } - case 3: { // "sort" (table [, comp]) -> void - args.checktable(1).sort( args.optvalue(2,NIL) ); - return NONE; - } - case 4: { // (table, func) -> void - return args.checktable(1).foreach( args.checkfunction(2) ); - } - case 5: { // "foreachi" (table, func) -> void - return args.checktable(1).foreachi( args.checkfunction(2) ); - } - } - return NONE; } }