diff --git a/src/core/org/luaj/vm2/LuaValue.java b/src/core/org/luaj/vm2/LuaValue.java index 7f5aa07a..99aeb05d 100644 --- a/src/core/org/luaj/vm2/LuaValue.java +++ b/src/core/org/luaj/vm2/LuaValue.java @@ -191,7 +191,7 @@ public class LuaValue extends Varargs { public LuaValue getmetatable() { return null; }; public LuaValue setmetatable(LuaValue metatable) { return error("setmetatable not allowed for "+typename()); } public LuaValue getfenv() { typerror("function or thread"); return null; } - public void setfenv(LuaValue env) { typerror("function or thread"); } + public void setfenv(LuaValue env) { typerror("function or thread"); } // function calls public LuaValue call() { return unimplemented("call"); } diff --git a/src/core/org/luaj/vm2/lib/BaseLib.java b/src/core/org/luaj/vm2/lib/BaseLib.java index 225df4a3..d338d798 100644 --- a/src/core/org/luaj/vm2/lib/BaseLib.java +++ b/src/core/org/luaj/vm2/lib/BaseLib.java @@ -47,12 +47,14 @@ import org.luaj.vm2.Varargs; * * @see org.luaj.vm2.lib.jse.JseBaseLib */ -public class BaseLib extends LuaTable implements ResourceFinder { +public class BaseLib extends OneArgFunction implements ResourceFinder { public static final String VERSION = "Luaj 2.0"; - public static InputStream STDIN = null; - public static PrintStream STDOUT = System.out; - public static PrintStream STDERR = System.err; + public static BaseLib instance; + + public InputStream STDIN = null; + public PrintStream STDOUT = System.out; + public PrintStream STDERR = System.err; /** * Singleton file opener for this Java ClassLoader realm. @@ -61,25 +63,32 @@ public class BaseLib extends LuaTable implements ResourceFinder { */ public static ResourceFinder FINDER; + private LuaValue next; + private LuaValue inext; + /** - * Construct a base libarary instance and initialize the functions in it. + * Construct a base libarary instance. */ public BaseLib() { - this.set( "_G", this ); - this.set( "_VERSION", VERSION ); - LibFunction.bind( this, new BaseFunc1().getClass(), new String[] { + instance = this; + } + + public LuaValue call(LuaValue arg) { + env.set( "_G", env ); + env.set( "_VERSION", VERSION ); + bind1( env, new String[] { "getfenv", // ( [f] ) -> env "getmetatable", // ( object ) -> table "tostring", // (e) -> value } ); - LibFunction.bind( this, new BaseFunc2().getClass(), new String[] { + bind2( env, new String[] { "collectgarbage", // ( opt [,arg] ) -> value "error", // ( message [,level] ) -> ERR "rawequal", // (v1, v2) -> boolean "setfenv", // (f, table) -> void "tonumber", // (e [,base]) -> value } ); - LibFunction.bind( this, new BaseFuncV().getClass(), new String[] { + bindv( env, new String[] { "assert", // ( v [,message] ) -> v, message | ERR "dofile", // ( filename ) -> result1, ... "load", // ( func [,chunkname] ) -> chunk | nil, msg @@ -94,22 +103,20 @@ public class BaseLib extends LuaTable implements ResourceFinder { "rawget", // (table, index) -> value "rawset", // (table, index, value) -> table "setmetatable", // (table, metatable) -> table + "pairs", // "pairs" (t) -> iter-func, t, nil + "ipairs", // "ipairs", // (t) -> iter-func, t, 0 + "next", // "next" ( table, [index] ) -> next-index, next-value + "__inext", // "inext" ( table, [int-index] ) -> next-index, next-value } ); - // pairs and ipars need iterator functions - // "next", // ( table, [index] ) -> next-index, next-value - // "inext", // not public ( table, [int-index] ) -> next-index, next-value - // "ipairs", // (t) -> iter-func, t, 0 - // "pairs", // (t) -> iter-func, t, nil - LuaValue next = new BaseIter(0,"next",null); - LuaValue inext = new BaseIter(1,"inext",null); - this.set( "pairs", new BaseIter(2,"pairs",next) ); - this.set( "ipairs", new BaseIter(3,"ipairs",inext) ); - this.set( "next", next ); + // remember next, and inext for use in pairs and ipairs + next = env.get("next"); + inext = env.get("__inext"); // set the default resource finder if not set already if ( FINDER == null ) FINDER = this; + return env; } /** ResourceFinder implementation @@ -121,253 +128,227 @@ public class BaseLib extends LuaTable implements ResourceFinder { return c.getResourceAsStream(filename.startsWith("/")? filename: "/"+filename); } - public static class BaseFunc1 extends OneArgFunction { - public LuaValue call(LuaValue arg) { - switch ( opcode ) { - case 0: { // "getfenv", // ( [f] ) -> env - if ( ! arg.isfunction() ) { - int i = arg.checkint(); - arg = (i==0)? (LuaValue) LuaThread.getRunning(): (LuaValue) LuaThread.getCallstackFunction(i-1); - if ( arg == null ) - LuaValue.argerror(1, "invalid level"); - } - return arg.getfenv(); + protected LuaValue oncall1(int opcode, LuaValue arg) { + switch ( opcode ) { + case 0: { // "getfenv", // ( [f] ) -> env + if ( ! arg.isfunction() ) { + int i = arg.checkint(); + arg = (i==0)? (LuaValue) LuaThread.getRunning(): (LuaValue) LuaThread.getCallstackFunction(i-1); + if ( arg == null ) + LuaValue.argerror(1, "invalid level"); } - case 1: // "getmetatable", // ( object ) -> table - LuaValue mt = arg.getmetatable(); - return mt!=null? mt: NIL; - case 2: // "tostring", // (e) -> value - return arg.type() == LuaValue.TSTRING? arg: valueOf(arg.toString()); - } - return NIL; + return arg.getfenv(); } + case 1: // "getmetatable", // ( object ) -> table + LuaValue mt = arg.getmetatable(); + return mt!=null? mt: NIL; + case 2: // "tostring", // (e) -> value + return arg.type() == LuaValue.TSTRING? arg: valueOf(arg.toString()); + } + return NIL; } - public static class BaseFunc2 extends TwoArgFunction { - public LuaValue call(LuaValue arg1,LuaValue arg2) { - switch ( opcode ) { - case 0: // "collectgarbage", // ( opt [,arg] ) -> value - String s = arg1.optString("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.toString() ); - case 2: // "rawequal", // (v1, v2) -> boolean - return valueOf(arg1 == arg2); - case 3: { // "setfenv", // (f, table) -> void - LuaValue f = arg1; - if ( ! f.isfunction() ) { - int i = arg1.checkint(); - f = (i==0)? (LuaValue) LuaThread.getRunning(): (LuaValue) LuaThread.getCallstackFunction(i-1); - if ( f == null ) - LuaValue.argerror(1, "invalid level"); - } - f.setfenv(arg2); - return f; + protected LuaValue oncall2(int opcode, LuaValue arg1, LuaValue arg2) { + switch ( opcode ) { + case 0: // "collectgarbage", // ( opt [,arg] ) -> value + String s = arg1.optString("collect"); + int result = 0; + if ( "collect".equals(s) ) { + System.gc(); + return ZERO; } - case 4: // "tonumber", // (e [,base]) -> value - final int base = arg2.optint(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; - } + 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.toString() ); + case 2: // "rawequal", // (v1, v2) -> boolean + return valueOf(arg1 == arg2); + case 3: { // "setfenv", // (f, table) -> void + LuaValue f = arg1; + if ( ! f.isfunction() ) { + int i = arg1.checkint(); + f = (i==0)? (LuaValue) LuaThread.getRunning(): (LuaValue) LuaThread.getCallstackFunction(i-1); + if ( f == null ) + LuaValue.argerror(1, "invalid level"); + } + f.setfenv(arg2); + return f; } + case 4: // "tonumber", // (e [,base]) -> value + final int base = arg2.optint(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; + } + } + return NIL; } - public static class BaseFuncV extends VarArgFunction { - private final BaseLib lib; - public BaseFuncV() { - this.lib = null; - } - public BaseFuncV(BaseLib lib) { - this.lib = lib; - } - 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 { - String filename = args.checkString(1); - chunk = loadFile(filename).arg1(); - } catch ( IOException e ) { - return error(e.getMessage()); - } - return chunk.invoke(); + 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.checkString(1); + chunk = loadFile(filename).arg1(); + } catch ( IOException e ) { + return error(e.getMessage()); } - 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.getRunningEnv(env)); - } catch ( Exception e ) { - return varargsOf(NIL, valueOf(e.getMessage())); - } - case 3: // "loadfile", // ( [filename] ) -> chunk | nil, msg - { - try { - String filename = args.checkString(1); - return loadFile(filename); - } catch ( Exception e ) { - return varargsOf(NIL, valueOf(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.getRunningEnv(env)); + } catch ( Exception e ) { + return varargsOf(NIL, valueOf(e.getMessage())); + } + case 3: // "loadfile", // ( [filename] ) -> chunk | nil, msg + { + try { + String filename = args.checkString(1); + return loadFile(filename); + } catch ( Exception e ) { + return varargsOf(NIL, valueOf(e.getMessage())); } - case 4: // "loadstring", // ( string [,chunkname] ) -> chunk | nil, msg + } + 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.getRunningEnv(env)); + } catch ( Exception e ) { + return varargsOf(NIL, valueOf(e.getMessage())); + } + case 5: // "pcall", // (f, arg1, ...) -> status, result1, ... + try { + LuaThread.onCall(this); try { - LuaString script = args.checkstring(1); - String chunkname = args.optString(2, "string"); - return LoadState.load(script.toInputStream(),chunkname,LuaThread.getRunningEnv(env)); - } catch ( Exception e ) { - return varargsOf(NIL, valueOf(e.getMessage())); - } - case 5: // "pcall", // (f, arg1, ...) -> status, result1, ... + return varargsOf(LuaValue.TRUE, args.arg1().invoke(args.subargs(2))); + } 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, ... + try { + LuaThread.onCall(this); try { - LuaThread.onCall(this); + LuaThread thread = LuaThread.getRunning(); + LuaValue olderr = thread.err; try { + thread.err = args.arg(2); return varargsOf(LuaValue.TRUE, args.arg1().invoke(args.subargs(2))); } finally { - LuaThread.onReturn(); + thread.err = olderr; } - } 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())); + } finally { + LuaThread.onReturn(); } - case 6: // "xpcall", // (f, err) -> result1, ... + } catch ( Exception e ) { try { - LuaThread.onCall(this); - try { - LuaThread thread = LuaThread.getRunning(); - LuaValue olderr = thread.err; - try { - thread.err = args.arg(2); - return varargsOf(LuaValue.TRUE, args.arg1().invoke(args.subargs(2))); - } finally { - thread.err = olderr; - } - } finally { - LuaThread.onReturn(); - } - } catch ( Exception e ) { - try { - return args.arg(2).invoke(valueOf(e.getMessage())); - } catch ( Exception f ) { - return varargsOf(FALSE, valueOf(f.getMessage())); - } + return args.arg(2).invoke(valueOf(e.getMessage())); + } catch ( Exception f ) { + return varargsOf(FALSE, valueOf(f.getMessage())); } - case 7: // "print", // (...) -> void - { - LuaValue tostring = env.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 ); - } - 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); - t.setmetatable(mt.isnil()? null: mt.checktable()); - return t; } + case 7: // "print", // (...) -> void + { + LuaValue tostring = env.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 ); } + 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); + t.setmetatable(mt.isnil()? null: mt.checktable()); + return t; + } + case 14: // "pairs" (t) -> iter-func, t, nil + return varargsOf( next, args.checktable(1) ); + case 15: // "ipairs", // (t) -> iter-func, t, 0 + return varargsOf( inext, args.checktable(1), ZERO ); + case 16: // "next" ( table, [index] ) -> next-index, next-value + return args.arg1().next(args.arg(2)); + case 17: // "inext" ( table, [int-index] ) -> next-index, next-value + return args.arg1().inext(args.arg(2)); + } + return NONE; + } - private Varargs loadFile(String filename) throws IOException { - InputStream is = FINDER.findResource(filename); - if ( is == null ) - return varargsOf(NIL, valueOf("not found: "+filename)); - try { - return LoadState.load(is, filename, LuaThread.getRunningEnv(env)); - } finally { - is.close(); - } + private Varargs loadFile(String filename) throws IOException { + InputStream is = FINDER.findResource(filename); + if ( is == null ) + return varargsOf(NIL, valueOf("not found: "+filename)); + try { + return LoadState.load(is, filename, LuaThread.getRunningEnv(env)); + } finally { + is.close(); } } - public static class BaseIter extends VarArgFunction { - final LuaValue aux; - BaseIter(int opcode, String name, LuaValue aux) { - this.name = name; - this.opcode = opcode; - this.aux = aux; - } - public Varargs invoke(Varargs args) { - switch ( opcode ) { - case 0: // "next" ( table, [index] ) -> next-index, next-value - return args.arg1().next(args.arg(2)); - case 1: // "inext" ( table, [int-index] ) -> next-index, next-value - return args.arg1().inext(args.arg(2)); - case 2: // "pairs" (t) -> iter-func, t, nil - return varargsOf( aux, args.checktable(1), NIL ); - case 3: // "ipairs", // (t) -> iter-func, t, 0 - return varargsOf( aux, args.checktable(1), ZERO ); - } - return NONE; - } - } private static class StringInputStream extends InputStream { diff --git a/src/core/org/luaj/vm2/lib/CoroutineLib.java b/src/core/org/luaj/vm2/lib/CoroutineLib.java index 51571dbc..96b52875 100644 --- a/src/core/org/luaj/vm2/lib/CoroutineLib.java +++ b/src/core/org/luaj/vm2/lib/CoroutineLib.java @@ -21,24 +21,13 @@ ******************************************************************************/ package org.luaj.vm2.lib; -import org.luaj.vm2.LuaThread; import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaThread; import org.luaj.vm2.LuaValue; import org.luaj.vm2.Varargs; -public class CoroutineLib extends VarArgFunction { +public class CoroutineLib extends ZeroArgFunction { - private static final String[] NAMES = { - "create", - "resume", - "running", - "status", - "yield", - "wrap", - "wrapped" - }; - - private static final int INIT = -1; private static final int CREATE = 0; private static final int RESUME = 1; private static final int RUNNING = 2; @@ -48,21 +37,18 @@ public class CoroutineLib extends VarArgFunction { private static final int WRAPPED = 6; public CoroutineLib() { - name = "coroutine";; - opcode = INIT; - } - - private CoroutineLib(String name, int opcode, LuaThread thread) { - super(name, opcode, thread); } - public Varargs invoke(Varargs args) { + public LuaValue call() { + LuaTable t = new LuaTable(); + bindv(t, new String[] { + "create", "resume", "running", "status", "yield", "wrap" }); + env.set("coroutine", t); + return t; + } + + protected Varargs oncallv(int opcode, Varargs args) { switch ( opcode ) { - case INIT: { - LuaTable t = new LuaTable(); - LibFunction.bind(t, this.getClass(), NAMES); - return t; - } case CREATE: { final LuaValue func = args.checkfunction(1); return new LuaThread(func, func.getfenv() ); @@ -87,7 +73,9 @@ public class CoroutineLib extends VarArgFunction { case WRAP: { final LuaValue func = args.checkfunction(1); final LuaThread thread = new LuaThread(func, func.getfenv()); - return new CoroutineLib("wrapped",WRAPPED,thread); + CoroutineLib cl = new CoroutineLib(); + cl.setfenv(thread); + return cl.bindv("wrapped",WRAPPED); } case WRAPPED: { final LuaThread t = (LuaThread) env; diff --git a/src/core/org/luaj/vm2/lib/DebugLib.java b/src/core/org/luaj/vm2/lib/DebugLib.java index 00044663..7b515345 100644 --- a/src/core/org/luaj/vm2/lib/DebugLib.java +++ b/src/core/org/luaj/vm2/lib/DebugLib.java @@ -21,20 +21,19 @@ ******************************************************************************/ package org.luaj.vm2.lib; - -import org.luaj.vm2.LuaClosure; import org.luaj.vm2.Lua; +import org.luaj.vm2.LuaClosure; import org.luaj.vm2.LuaError; import org.luaj.vm2.LuaFunction; -import org.luaj.vm2.LuaThread; -import org.luaj.vm2.Print; -import org.luaj.vm2.Prototype; import org.luaj.vm2.LuaString; import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaThread; import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Print; +import org.luaj.vm2.Prototype; import org.luaj.vm2.Varargs; -public class DebugLib extends VarArgFunction { +public class DebugLib extends OneArgFunction { public static final boolean CALLS = (null != System.getProperty("CALLS")); public static final boolean TRACE = (null != System.getProperty("TRACE")); @@ -59,7 +58,6 @@ public class DebugLib extends VarArgFunction { "traceback", }; - private static final int INIT = -1; private static final int DEBUG = 0; private static final int GETFENV = 1; private static final int GETHOOK = 2; @@ -105,49 +103,34 @@ public class DebugLib extends VarArgFunction { private static final LuaString ACTIVELINES = valueOf("activelines"); public DebugLib() { - name = "debug"; - opcode = INIT; + } + + public LuaValue call(LuaValue arg) { + LuaTable t = new LuaTable(); + bindv(t, NAMES); + env.set("debug", t); + if ( ! DEBUG_ENABLED ) + DEBUG_ENABLED = true; + return t; } - public Varargs invoke(Varargs args) { + protected Varargs oncallv(int opcode, Varargs args) { switch ( opcode ) { - case INIT: { - LuaTable t = new LuaTable(0,20); - LibFunction.bind(t, this.getClass(), NAMES); - if ( ! DEBUG_ENABLED ) - DEBUG_ENABLED = true; - return t; - } - 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; + 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; } } diff --git a/src/core/org/luaj/vm2/lib/IoLib.java b/src/core/org/luaj/vm2/lib/IoLib.java index da32b4c9..6987ac70 100644 --- a/src/core/org/luaj/vm2/lib/IoLib.java +++ b/src/core/org/luaj/vm2/lib/IoLib.java @@ -33,7 +33,7 @@ import org.luaj.vm2.Varargs; abstract -public class IoLib extends VarArgFunction { +public class IoLib extends OneArgFunction { abstract protected class File extends LuaValue{ @@ -56,7 +56,7 @@ public class IoLib extends VarArgFunction { // delegate method access to file methods table public LuaValue get( LuaValue key ) { - return env.get(FILEMETHODS).get(key); + return filemethods.get(key); } // essentially a userdata instance @@ -115,41 +115,38 @@ public class IoLib extends VarArgFunction { private File infile = null; private File outfile = null; - private File errfile = null; + private File errfile = null; private static final LuaValue STDIN = valueOf("stdin"); private static final LuaValue STDOUT = valueOf("stdout"); private static final LuaValue STDERR = valueOf("stderr"); private static final LuaValue FILE = valueOf("file"); private static final LuaValue CLOSED_FILE = valueOf("closed file"); - private static final LuaValue FILEMETHODS = valueOf("__filemethods"); - private static final int INIT = 0; - private static final int IO_INDEX = 1; - private static final int IO_CLOSE = 2; - private static final int IO_FLUSH = 3; - private static final int IO_INPUT = 4; - private static final int IO_LINES = 5; - private static final int IO_OPEN = 6; - private static final int IO_OUTPUT = 7; - private static final int IO_POPEN = 8; - private static final int IO_READ = 9; - private static final int IO_TMPFILE = 10; - private static final int IO_TYPE = 11; - private static final int IO_WRITE = 12; + private static final int IO_CLOSE = 0; + private static final int IO_FLUSH = 1; + private static final int IO_INPUT = 2; + private static final int IO_LINES = 3; + private static final int IO_OPEN = 4; + private static final int IO_OUTPUT = 5; + private static final int IO_POPEN = 6; + private static final int IO_READ = 7; + private static final int IO_TMPFILE = 8; + private static final int IO_TYPE = 9; + private static final int IO_WRITE = 10; - private static final int FILE_CLOSE = 13; - private static final int FILE_FLUSH = 14; - private static final int FILE_LINES = 15; - private static final int FILE_READ = 16; - private static final int FILE_SEEK = 17; - private static final int FILE_SETVBUF = 18; - private static final int FILE_WRITE = 19; + private static final int FILE_CLOSE = 11; + private static final int FILE_FLUSH = 12; + private static final int FILE_LINES = 13; + private static final int FILE_READ = 14; + private static final int FILE_SEEK = 15; + private static final int FILE_SETVBUF = 16; + private static final int FILE_WRITE = 17; - private static final int LINES_ITER = 20; + private static final int IO_INDEX = 18; + private static final int LINES_ITER = 19; public static final String[] IO_NAMES = { - "__index", "close", "flush", "input", @@ -172,40 +169,36 @@ public class IoLib extends VarArgFunction { "setvbuf", "write", }; + + LuaTable filemethods; public IoLib() {} - protected LuaTable init() { + public LuaValue call(LuaValue arg) { // io lib functions LuaTable t = new LuaTable(); - LibFunction.bind(t, this.getClass(), IO_NAMES, IO_INDEX ); - - // let t be its own metatable - t.setmetatable( t ); + bindv(t, IO_NAMES ); // create file methods table - LuaTable filemethods = new LuaTable(); - LibFunction.bind(filemethods, this.getClass(), FILE_NAMES, FILE_CLOSE ); - t.set(FILEMETHODS, filemethods); + filemethods = new LuaTable(); + bind(filemethods, FILE_NAMES, -1, FILE_CLOSE ); + // set up file metatable + LuaTable mt = tableOf( new LuaValue[] { INDEX, bindv("__index",IO_INDEX) }); + t.setmetatable( mt ); + // return the table + env.set("io", t); return t; } - - public Varargs invoke(Varargs args) { + + protected Varargs oncallv(int opcode, Varargs args) { File f; int n; LuaValue v; try { switch ( opcode ) { - case INIT: // init - return init(); - case IO_INDEX: // __index, returns a field - v = args.arg(2); - return v.equals(STDOUT)?output(): - v.equals(STDIN)? input(): - v.equals(STDERR)? errput(): NIL; case IO_FLUSH: // io.flush() -> bool checkopen(output()); outfile.flush(); @@ -245,6 +238,7 @@ public class IoLib extends VarArgFunction { case IO_WRITE: // io.write(...) -> void checkopen(output()); return iowrite(outfile,args); + case FILE_CLOSE: // file:close() -> void return ioclose(checkfile(args.arg1())); case FILE_FLUSH: // file:flush() -> void @@ -266,6 +260,12 @@ public class IoLib extends VarArgFunction { case FILE_WRITE: // file:write(...) -> void f = checkfile(args.arg1()); return iowrite(f,args.subargs(2)); + + case IO_INDEX: // __index, returns a field + v = args.arg(2); + return v.equals(STDOUT)?output(): + v.equals(STDIN)? input(): + v.equals(STDERR)? errput(): NIL; case LINES_ITER: // lines iterator(s,var) -> var' f = checkfile(env); return freadline(f); @@ -321,10 +321,8 @@ public class IoLib extends VarArgFunction { private Varargs lines(final File f) throws Exception { IoLib iter = (IoLib) getClass().newInstance(); - iter.opcode = LINES_ITER; - iter.name = "lnext"; - iter.env = f; - return iter; + iter.setfenv(f); + return iter.bindv("lnext",LINES_ITER); } private static Varargs iowrite(File f, Varargs args) throws IOException { diff --git a/src/core/org/luaj/vm2/lib/LibFunction.java b/src/core/org/luaj/vm2/lib/LibFunction.java index 66ef56e9..4efcebc8 100644 --- a/src/core/org/luaj/vm2/lib/LibFunction.java +++ b/src/core/org/luaj/vm2/lib/LibFunction.java @@ -22,59 +22,264 @@ package org.luaj.vm2.lib; import org.luaj.vm2.LuaFunction; -import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaValue; -; - +import org.luaj.vm2.Varargs; abstract public class LibFunction extends LuaFunction { - protected int opcode; - protected String name; - - public LibFunction() { + protected LibFunction() { } - - public LibFunction(String name, int opcode, LuaValue env) { - super(env); - this.name = name; - this.opcode = opcode; + protected void bind0(LuaValue env, String[] names) { + bind(env, names, 0, 0); } - - public String toString() { - return name!=null? name: super.toString(); + protected void bind1(LuaValue env, String[] names) { + bind(env, names, 1, 0); } - - public static LuaTable bind( LuaTable table, Class libFuncClass, String[] names ) { - return bind( table, libFuncClass, names, 0 ); + protected void bind2(LuaValue env, String[] names) { + bind(env, names, 2, 0); } - - /** Bind a set of names to class instances, put values into the table. */ - public static LuaTable bind( LuaTable table, Class libFuncClass, String[] names, int firstOpcode ) { - try { - for ( int i=0, n=names.length; i=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 - Random random = (Random) env.get(RANDOM).optuserdata(Random.class, null); - if ( random == null ) - env.set(RANDOM,userdataOf(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; + public LuaValue oncall2(int opcode,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 ( 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 */ @@ -155,42 +148,40 @@ public class MathLib extends OneArgFunction { return p; } - public static class MathFuncV extends VarArgFunction { - 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); - env.set(RANDOM,userdataOf(new Random(seed))); - return NONE; - } - } + 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); return NONE; } + } + return NONE; } } diff --git a/src/core/org/luaj/vm2/lib/OneArgFunction.java b/src/core/org/luaj/vm2/lib/OneArgFunction.java index 8a351573..e9707d66 100644 --- a/src/core/org/luaj/vm2/lib/OneArgFunction.java +++ b/src/core/org/luaj/vm2/lib/OneArgFunction.java @@ -35,10 +35,6 @@ abstract public class OneArgFunction extends LibFunction { this.env = env; } - public OneArgFunction( String name, int opcode, LuaValue env ) { - super(name, opcode, env); - } - public final LuaValue call() { return call(NIL); } diff --git a/src/core/org/luaj/vm2/lib/OsLib.java b/src/core/org/luaj/vm2/lib/OsLib.java index 52613d2c..09853cd5 100644 --- a/src/core/org/luaj/vm2/lib/OsLib.java +++ b/src/core/org/luaj/vm2/lib/OsLib.java @@ -46,11 +46,10 @@ import org.luaj.vm2.Varargs; * * @see org.luaj.vm2.lib.jse.JseOsLib */ -public class OsLib extends VarArgFunction { +public class OsLib extends OneArgFunction { public static String TMP_PREFIX = ".luaj"; public static String TMP_SUFFIX = "tmp"; - private static final int INIT = -1; private static final int CLOCK = 0; private static final int DATE = 1; private static final int DIFFTIME = 2; @@ -84,18 +83,18 @@ public class OsLib extends VarArgFunction { * Create and OsLib instance. */ public OsLib() { - name = "os"; - opcode = INIT; } - public Varargs invoke(Varargs args) { + public LuaValue call(LuaValue arg) { + LuaTable t = new LuaTable(); + bindv(t, NAMES); + env.set("os", t); + return t; + } + + protected Varargs oncallv(int opcode, Varargs args) { try { switch ( opcode ) { - case INIT: { - LuaTable t = new LuaTable(); - LibFunction.bind(t, getClass(), NAMES); - return t; - } case CLOCK: return valueOf(clock()); case DATE: { diff --git a/src/core/org/luaj/vm2/lib/PackageLib.java b/src/core/org/luaj/vm2/lib/PackageLib.java index 81205508..4a5d9442 100644 --- a/src/core/org/luaj/vm2/lib/PackageLib.java +++ b/src/core/org/luaj/vm2/lib/PackageLib.java @@ -32,87 +32,89 @@ import org.luaj.vm2.LuaValue; import org.luaj.vm2.Varargs; -public class PackageLib extends LuaTable { +public class PackageLib extends OneArgFunction { public static String DEFAULT_LUA_PATH = "?.lua"; - public LuaValue _G = null; - public InputStream STDIN = null; - public PrintStream STDOUT = System.out; - public LuaTable LOADED = null; - public LuaTable PACKAGE = null; + public InputStream STDIN = null; + public PrintStream STDOUT = System.out; + public LuaTable LOADED; + public LuaTable PACKAGE; - private static final LuaString _M = LuaString.valueOf("_M"); - private static final LuaString _NAME = LuaString.valueOf("_NAME"); - private static final LuaString _PACKAGE = LuaString.valueOf("_PACKAGE"); - private static final LuaString _DOT = LuaString.valueOf("."); - private static final LuaString _LOADERS = LuaString.valueOf("loaders"); - private static final LuaString _LOADED = LuaString.valueOf("loaded"); - private static final LuaString _LOADLIB = LuaString.valueOf("loadlib"); - private static final LuaString _PRELOAD = LuaString.valueOf("preload"); - private static final LuaString _PATH = LuaString.valueOf("path"); - private static final LuaString _SEEALL = LuaString.valueOf("seeall"); - private static final LuaValue _SENTINEL = EMPTYSTRING; + private static final LuaString _M = valueOf("_M"); + private static final LuaString _NAME = valueOf("_NAME"); + private static final LuaString _PACKAGE = valueOf("_PACKAGE"); + private static final LuaString _DOT = valueOf("."); + private static final LuaString _LOADERS = valueOf("loaders"); + private static final LuaString _LOADED = valueOf("loaded"); + private static final LuaString _LOADLIB = valueOf("loadlib"); + private static final LuaString _PRELOAD = valueOf("preload"); + private static final LuaString _PATH = valueOf("path"); + private static final LuaString _SEEALL = valueOf("seeall"); + private static final LuaString _LOADFILE = valueOf("loadfile"); + private static final LuaString _SENTINEL = valueOf("\u0001"); - private static final int MODULE = 1; - private static final int REQUIRE = 2; - private static final int LOADLIB = 3; - private static final int SEEALL = 4; - private static final int PRELOAD_LOADER = 5; - private static final int LUA_LOADER = 6; - private static final int JAVA_LOADER = 7; - - - public PackageLib(LuaValue _G) { - this._G = _G; - _G.set( "module", new PackageFuncV(MODULE, "module", _G) ); - _G.set( "require", new PackageFuncV(REQUIRE, "require",_G) ); - _G.set( "package", PACKAGE = tableOf( new LuaValue[] { + private static final int MODULE = 0; + private static final int REQUIRE = 1; + private static final int LOADLIB = 2; + private static final int SEEALL = 3; + private static final int PRELOAD_LOADER = 4; + private static final int LUA_LOADER = 5; + private static final int JAVA_LOADER = 6; + + public PackageLib() { + } + + public LuaValue call(LuaValue arg) { + env.set("require", bind1("require",REQUIRE)); + env.set("module", bindv("module",MODULE)); + env.set( "package", PACKAGE=tableOf( new LuaValue[] { _LOADED, LOADED=tableOf(), _PRELOAD, tableOf(), _PATH, valueOf(DEFAULT_LUA_PATH), - _LOADLIB, new PackageFuncV(LOADLIB, "loadlib",_G), - _SEEALL, new PackageFuncV(SEEALL, "seeall",_G), + _LOADLIB, bindv("loadlib",LOADLIB), + _SEEALL, bind1("seeall",SEEALL), _LOADERS, listOf(new LuaValue[] { - new PackageFuncV(PRELOAD_LOADER,"preload_loader",_G), - new PackageFuncV(LUA_LOADER, "lua_loader",_G), - new PackageFuncV(JAVA_LOADER, "java_loader",_G), - }), - } ) ); + bindv("preload_loader", PRELOAD_LOADER), + bindv("lua_loader", LUA_LOADER), + bindv("java_loader", JAVA_LOADER), + }) }) ); + return env; } - private class PackageFuncV extends VarArgFunction { - public PackageFuncV(int opcode, String name, LuaValue env) { - super(name, opcode, env); - } - public Varargs invoke(Varargs args) { - switch ( opcode ) { - case MODULE: - return module(args); - case REQUIRE: - return require(args); - case LOADLIB: - return loadlib(args); - case SEEALL: { - LuaTable t = args.checktable(1); - LuaValue m = t.getmetatable(); - if ( m == null ) - t.setmetatable(m=tableOf()); - m.set( INDEX, env ); - return NONE; - } - case PRELOAD_LOADER: { - return loader_preload(args); - } - case LUA_LOADER: { - return loader_Lua(args); - } - case JAVA_LOADER: { - return loader_Java(args); - } - } + protected LuaValue oncall1(int opcode, LuaValue arg) { + switch ( opcode ) { + case REQUIRE: + return require(arg); + case SEEALL: { + LuaTable t = arg.checktable(); + LuaValue m = t.getmetatable(); + if ( m == null ) + t.setmetatable(m=tableOf()); + m.set( INDEX, env ); return NONE; - } + } + } + return NIL; + } + + protected Varargs oncallv(int opcode, Varargs args) { + switch ( opcode ) { + case MODULE: + return module(args); + case LOADLIB: + return loadlib(args); + case PRELOAD_LOADER: { + return loader_preload(args); + } + case LUA_LOADER: { + return loader_Lua(args); + } + case JAVA_LOADER: { + return loader_Java(args); + } + } + return NONE; } /** Allow packages to mark themselves as loaded */ @@ -159,7 +161,7 @@ public class PackageLib extends LuaTable { if ( ! value.istable() ) { /* not found? */ /* try global variable (and create one if it does not exist) */ - module = findtable( _G, modname ); + module = findtable( env, modname ); if ( module == null ) error( "name conflict for module '"+modname+"'" ); LOADED.set(modname, module); @@ -249,8 +251,8 @@ public class PackageLib extends LuaTable { * If there is any error loading or running the module, or if it cannot find any loader for * the module, then require signals an error. */ - public Varargs require( Varargs args ) { - LuaString name = args.checkstring(1); + public LuaValue require( LuaValue arg ) { + LuaString name = arg.checkstring(); LuaValue loaded = LOADED.get(name); if ( loaded.toboolean() ) { if ( loaded == _SENTINEL ) @@ -304,7 +306,7 @@ public class PackageLib extends LuaTable { InputStream is = null; // try to use loadfile for the file - LuaValue loadfile = _G.get("loadfile"); + LuaValue loadfile = env.get(_LOADFILE); if ( ! loadfile.isfunction() ) return valueOf("loadfile is not a function" ); @@ -357,7 +359,7 @@ public class PackageLib extends LuaTable { try { c = Class.forName(classname); v = (LuaValue) c.newInstance(); - v.setfenv(_G); + v.setfenv(env); return v; } catch ( ClassNotFoundException cnfe ) { return valueOf("\n\tno class '"+classname+"'" ); diff --git a/src/core/org/luaj/vm2/lib/StringLib.java b/src/core/org/luaj/vm2/lib/StringLib.java index 83377a59..46cd894f 100644 --- a/src/core/org/luaj/vm2/lib/StringLib.java +++ b/src/core/org/luaj/vm2/lib/StringLib.java @@ -37,23 +37,23 @@ public class StringLib extends OneArgFunction { public static LuaTable instance; public StringLib() { - name = "string"; - opcode = -1; } public LuaValue call(LuaValue arg) { - switch ( opcode ) { - case -1: { - LuaTable t = new LuaTable(); - LibFunction.bind( t, getClass(), new String[] { - "dump", "len", "lower", "reverse", "upper", } ); - LibFunction.bind( t, new StringFuncV().getClass(), new String[] { - "byte", "char", "find", "format", - "gmatch", "gsub", "match", "rep", - "sub"} ); - instance = t; - return t; - } + LuaTable t = new LuaTable(); + bind1(t, new String[] { + "dump", "len", "lower", "reverse", "upper", } ); + bindv(t, new String[] { + "byte", "char", "find", "format", + "gmatch", "gsub", "match", "rep", + "sub"} ); + env.set("string", t); + instance = t; + 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) @@ -61,25 +61,24 @@ public class StringLib extends OneArgFunction { case 4: return upper(arg); // upper (function) } return NIL; - } - - public static class StringFuncV 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; - } } - + + + 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 ); + } + return NONE; + } + /** * string.byte (s [, i [, j]]) * diff --git a/src/core/org/luaj/vm2/lib/TableLib.java b/src/core/org/luaj/vm2/lib/TableLib.java index 728223e9..8a0b0938 100644 --- a/src/core/org/luaj/vm2/lib/TableLib.java +++ b/src/core/org/luaj/vm2/lib/TableLib.java @@ -28,68 +28,66 @@ import org.luaj.vm2.Varargs; public class TableLib extends OneArgFunction { public TableLib() { - name = "table"; - opcode = -1; } public LuaValue call(LuaValue arg) { + LuaTable t = new LuaTable(); + bind1(t, new String[] { + "getn", // (table) -> number + "maxn", // (table) -> number + } ); + bindv(t, new String[] { + "remove", // (table [, pos]) -> removed-ele + "concat", // (table [, sep [, i [, j]]]) -> string + "insert", // (table, [pos,] value) -> prev-ele + "sort", // (table [, comp]) -> void + "foreach", // (table, func) -> void + "foreachi", // (table, func) -> void + } ); + env.set("table", t); + return t; + } + + protected LuaValue oncall1(int opcode, LuaValue arg) { switch ( opcode ) { - case -1: { - LuaTable t = new LuaTable(); - LibFunction.bind( t, this.getClass(), new String[] { - "getn", // (table) -> number - "maxn", // (table) -> number - } ); - LibFunction.bind( t, new TableFuncV().getClass(), new String[] { - "remove", // (table [, pos]) -> removed-ele - "concat", // (table [, sep [, i [, j]]]) -> string - "insert", // (table, [pos,] value) -> prev-ele - "sort", // (table [, comp]) -> void - "foreach", // (table, func) -> void - "foreachi", // (table, func) -> void - } ); - return t; - } case 0: return arg.checktable().getn(); case 1: return valueOf( arg.checktable().maxn()); } return NIL; } - public static class TableFuncV 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) ); - } - } + 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 ); 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; } } diff --git a/src/core/org/luaj/vm2/lib/ThreeArgFunction.java b/src/core/org/luaj/vm2/lib/ThreeArgFunction.java index 9d640540..35db1a0b 100644 --- a/src/core/org/luaj/vm2/lib/ThreeArgFunction.java +++ b/src/core/org/luaj/vm2/lib/ThreeArgFunction.java @@ -35,10 +35,6 @@ abstract public class ThreeArgFunction extends LibFunction { this.env = env; } - public ThreeArgFunction( String name, int opcode, LuaValue env ) { - super(name, opcode, env); - } - public final LuaValue call() { return call(NIL, NIL, NIL); } diff --git a/src/core/org/luaj/vm2/lib/TwoArgFunction.java b/src/core/org/luaj/vm2/lib/TwoArgFunction.java index 13304de7..67dab83a 100644 --- a/src/core/org/luaj/vm2/lib/TwoArgFunction.java +++ b/src/core/org/luaj/vm2/lib/TwoArgFunction.java @@ -35,10 +35,6 @@ abstract public class TwoArgFunction extends LibFunction { this.env = env; } - public TwoArgFunction( String name, int opcode, LuaValue env ) { - super(name, opcode, env); - } - public final LuaValue call() { return call(NIL, NIL); } diff --git a/src/core/org/luaj/vm2/lib/VarArgFunction.java b/src/core/org/luaj/vm2/lib/VarArgFunction.java index 7a96b8a3..8349a171 100644 --- a/src/core/org/luaj/vm2/lib/VarArgFunction.java +++ b/src/core/org/luaj/vm2/lib/VarArgFunction.java @@ -33,10 +33,6 @@ abstract public class VarArgFunction extends LibFunction { this.env = env; } - public VarArgFunction( String name, int opcode, LuaValue env ) { - super(name, opcode, env); - } - public final LuaValue call() { return invoke(NONE).arg1(); } diff --git a/src/core/org/luaj/vm2/lib/ZeroArgFunction.java b/src/core/org/luaj/vm2/lib/ZeroArgFunction.java index 1ecb70d5..0ed9ec90 100644 --- a/src/core/org/luaj/vm2/lib/ZeroArgFunction.java +++ b/src/core/org/luaj/vm2/lib/ZeroArgFunction.java @@ -35,10 +35,6 @@ abstract public class ZeroArgFunction extends LibFunction { this.env = env; } - public ZeroArgFunction( String name, int opcode, LuaValue env ) { - super(name, opcode, env); - } - public LuaValue call(LuaValue arg) { return call(); } diff --git a/src/jme/org/luaj/vm2/lib/JmePlatform.java b/src/jme/org/luaj/vm2/lib/JmePlatform.java index 5b5988b8..c00a1b82 100644 --- a/src/jme/org/luaj/vm2/lib/JmePlatform.java +++ b/src/jme/org/luaj/vm2/lib/JmePlatform.java @@ -22,7 +22,12 @@ package org.luaj.vm2.lib; import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.jme.JmeIoLib; +import org.luaj.vm2.lib.jse.JseBaseLib; +import org.luaj.vm2.lib.jse.JseIoLib; +import org.luaj.vm2.lib.jse.JseMathLib; +import org.luaj.vm2.lib.jse.JseOsLib; +import org.luaj.vm2.lib.jse.LuajavaLib; public class JmePlatform { @@ -32,27 +37,24 @@ public class JmePlatform { * @return Table of globals initialized with the standard JME libraries */ public static LuaTable standardGlobals() { - LuaTable _G = new BaseLib(); - new org.luaj.vm2.lib.PackageLib(_G); - set(_G, "coroutine", new org.luaj.vm2.lib.CoroutineLib() ); - set(_G, "io", new org.luaj.vm2.lib.jme.JseIoLib() ); - set(_G, "math", new org.luaj.vm2.lib.MathLib() ); - set(_G, "os", new org.luaj.vm2.lib.OsLib() ); - set(_G, "table", new org.luaj.vm2.lib.TableLib() ); - set(_G, "string", new org.luaj.vm2.lib.StringLib() ); + LuaTable _G = new LuaTable(); + init(_G, new BaseLib()); + init(_G, new PackageLib()); + init(_G, new TableLib()); + init(_G, new StringLib()); + init(_G, new CoroutineLib()); + init(_G, new JmeIoLib()); return _G; } public static LuaTable debugGlobals() { LuaTable _G = standardGlobals(); - set(_G, "string", new org.luaj.vm2.lib.DebugLib() ); + init(_G, new DebugLib()); return _G; } - private static void set( LuaTable _G, String name, LuaValue chunk ) { - chunk.setfenv(_G); - LuaValue pkg = chunk.call(LuaValue.valueOf(name)); - _G.set( name, pkg ); + private static void init(LuaTable _G, LibFunction lib) { + lib.setfenv(_G); + lib.call(); } - } diff --git a/src/jme/org/luaj/vm2/lib/jme/JseIoLib.java b/src/jme/org/luaj/vm2/lib/jme/JmeIoLib.java similarity index 97% rename from src/jme/org/luaj/vm2/lib/jme/JseIoLib.java rename to src/jme/org/luaj/vm2/lib/jme/JmeIoLib.java index 96a2b798..d38e5aec 100644 --- a/src/jme/org/luaj/vm2/lib/jme/JseIoLib.java +++ b/src/jme/org/luaj/vm2/lib/jme/JmeIoLib.java @@ -37,18 +37,18 @@ import org.luaj.vm2.lib.IoLib; * * Seek is not supported. */ -public class JseIoLib extends IoLib { +public class JmeIoLib extends IoLib { - public JseIoLib() { + public JmeIoLib() { super(); } protected File wrapStdin() throws IOException { - return new FileImpl(BaseLib.STDIN); + return new FileImpl(BaseLib.instance.STDIN); } protected File wrapStdout() throws IOException { - return new FileImpl(BaseLib.STDOUT); + return new FileImpl(BaseLib.instance.STDOUT); } protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException { diff --git a/src/jse/org/luaj/vm2/lib/JsePlatform.java b/src/jse/org/luaj/vm2/lib/JsePlatform.java index d764a868..22b15b1b 100644 --- a/src/jse/org/luaj/vm2/lib/JsePlatform.java +++ b/src/jse/org/luaj/vm2/lib/JsePlatform.java @@ -22,8 +22,6 @@ package org.luaj.vm2.lib; import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.lib.CoroutineLib; import org.luaj.vm2.lib.jse.JseBaseLib; import org.luaj.vm2.lib.jse.JseIoLib; import org.luaj.vm2.lib.jse.JseMathLib; @@ -38,22 +36,22 @@ public class JsePlatform { * @return Table of globals initialized with the standard JSE libraries */ public static LuaTable standardGlobals() { - LuaTable _G = new JseBaseLib(); - new org.luaj.vm2.lib.PackageLib(_G); - set(_G, "table", new org.luaj.vm2.lib.TableLib() ); - set(_G, "string", new org.luaj.vm2.lib.StringLib() ); - set(_G, "coroutine", new org.luaj.vm2.lib.CoroutineLib() ); - set(_G, "debug", new org.luaj.vm2.lib.DebugLib() ); - set(_G, "math", new org.luaj.vm2.lib.jse.JseMathLib() ); - set(_G, "io", new org.luaj.vm2.lib.jse.JseIoLib() ); - set(_G, "os", new org.luaj.vm2.lib.jse.JseOsLib() ); - set(_G, "luajava", new org.luaj.vm2.lib.jse.LuajavaLib() ); + LuaTable _G = new LuaTable(); + init(_G, new JseBaseLib()); + init(_G, new PackageLib()); + init(_G, new TableLib()); + init(_G, new StringLib()); + init(_G, new CoroutineLib()); + init(_G, new DebugLib()); + init(_G, new JseMathLib()); + init(_G, new JseIoLib()); + init(_G, new JseOsLib()); + init(_G, new LuajavaLib()); return _G; } - - private static void set( LuaTable _G, String name, LuaValue chunk ) { - chunk.setfenv(_G); - LuaValue pkg = chunk.call(LuaValue.valueOf(name)); - _G.set( name, pkg ); + + private static void init(LuaTable _G, LibFunction lib) { + lib.setfenv(_G); + lib.call(); } } diff --git a/src/jse/org/luaj/vm2/lib/jse/JseBaseLib.java b/src/jse/org/luaj/vm2/lib/jse/JseBaseLib.java index 76baa1e5..3636ec79 100644 --- a/src/jse/org/luaj/vm2/lib/jse/JseBaseLib.java +++ b/src/jse/org/luaj/vm2/lib/jse/JseBaseLib.java @@ -38,12 +38,9 @@ import java.io.InputStream; */ public class JseBaseLib extends org.luaj.vm2.lib.BaseLib { - static { - STDIN = System.in; - } - /** Construct a JSE base library instance */ public JseBaseLib() { + STDIN = System.in; } /** diff --git a/src/jse/org/luaj/vm2/lib/jse/JseIoLib.java b/src/jse/org/luaj/vm2/lib/jse/JseIoLib.java index 4f0f7723..2485a170 100644 --- a/src/jse/org/luaj/vm2/lib/jse/JseIoLib.java +++ b/src/jse/org/luaj/vm2/lib/jse/JseIoLib.java @@ -21,6 +21,7 @@ ******************************************************************************/ package org.luaj.vm2.lib.jse; + import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; @@ -29,6 +30,7 @@ import java.io.RandomAccessFile; import org.luaj.vm2.LuaError; import org.luaj.vm2.LuaString; +import org.luaj.vm2.lib.BaseLib; import org.luaj.vm2.lib.IoLib; /** @@ -42,11 +44,11 @@ public class JseIoLib extends IoLib { } protected File wrapStdin() throws IOException { - return new FileImpl(JseBaseLib.STDIN); + return new FileImpl(BaseLib.instance.STDIN); } protected File wrapStdout() throws IOException { - return new FileImpl(JseBaseLib.STDOUT); + return new FileImpl(BaseLib.instance.STDOUT); } protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException { diff --git a/src/jse/org/luaj/vm2/lib/jse/JseMathLib.java b/src/jse/org/luaj/vm2/lib/jse/JseMathLib.java index e0226693..9fca4f48 100644 --- a/src/jse/org/luaj/vm2/lib/jse/JseMathLib.java +++ b/src/jse/org/luaj/vm2/lib/jse/JseMathLib.java @@ -21,10 +21,8 @@ ******************************************************************************/ package org.luaj.vm2.lib.jse; -import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaValue; -import org.luaj.vm2.lib.LibFunction; -import org.luaj.vm2.lib.TwoArgFunction; +import org.luaj.vm2.lib.MathLib; /** * Math library implementation for use on JSE platform. @@ -36,20 +34,21 @@ public class JseMathLib extends org.luaj.vm2.lib.MathLib { public JseMathLib() {} - protected LuaTable init() { - LuaTable t = super.init(); - LibFunction.bind( t, this.getClass(), new String[] { + public LuaValue call(LuaValue arg) { + MathLib ml = new MathLib(); + ml.setfenv(env); + LuaValue t = ml.call(arg); + bind1( t, new String[] { "acos", "asin", "atan", "cosh", "exp", "log", "log10", "sinh", "tanh" } ); - LibFunction.bind( t, new J2seMathFunc2().getClass(), new String[] { + bind2( t, new String[] { "atan2", "pow", } ); return t; } - public LuaValue call(LuaValue arg) { + public LuaValue oncall1(int opcode, LuaValue arg) { switch ( opcode ) { - case -1: return init(); case 0: return valueOf(Math.acos(arg.todouble())); case 1: return valueOf(Math.asin(arg.todouble())); case 2: return valueOf(Math.atan(arg.todouble())); @@ -62,15 +61,13 @@ public class JseMathLib extends org.luaj.vm2.lib.MathLib { } return NIL; } - - public static class J2seMathFunc2 extends TwoArgFunction { - public LuaValue call(LuaValue arg1,LuaValue arg2) { - switch ( opcode ) { - case 0: return valueOf(Math.atan2(arg1.todouble(), arg2.todouble())); - case 1: return valueOf(Math.pow(arg1.todouble(), arg2.todouble())); - } - return NIL; + + public LuaValue oncall2(int opcode, LuaValue arg1, LuaValue arg2) { + switch ( opcode ) { + case 0: return valueOf(Math.atan2(arg1.todouble(), arg2.todouble())); + case 1: return valueOf(Math.pow(arg1.todouble(), arg2.todouble())); } + return NIL; } /** Faster, better version of pow() used by arithmetic operator ^ */ diff --git a/src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java b/src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java index 3c848a72..83cbd439 100644 --- a/src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java +++ b/src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java @@ -43,23 +43,20 @@ import org.luaj.vm2.LuaUserdata; import org.luaj.vm2.LuaValue; import org.luaj.vm2.Varargs; import org.luaj.vm2.lib.LibFunction; +import org.luaj.vm2.lib.OneArgFunction; import org.luaj.vm2.lib.ThreeArgFunction; import org.luaj.vm2.lib.TwoArgFunction; import org.luaj.vm2.lib.VarArgFunction; -public class LuajavaLib extends VarArgFunction { +public class LuajavaLib extends OneArgFunction { - private static final String LIBNAME = "luajava"; - - private static final int INIT = 0; - private static final int BINDCLASS = 1; - private static final int NEWINSTANCE = 2; - private static final int NEW = 3; - private static final int CREATEPROXY = 4; - private static final int LOADLIB = 5; + private static final int BINDCLASS = 0; + private static final int NEWINSTANCE = 1; + private static final int NEW = 2; + private static final int CREATEPROXY = 3; + private static final int LOADLIB = 4; private static final String[] NAMES = { - LIBNAME, "bindClass", "newInstance", "new", @@ -73,18 +70,18 @@ public class LuajavaLib extends VarArgFunction { } public LuajavaLib() { - name = LIBNAME; - opcode = INIT; } - public Varargs invoke(final Varargs args) { + public LuaValue call(LuaValue arg) { + LuaTable t = new LuaTable(); + bindv( t, NAMES ); + env.set("luajava", t); + return t; + } + + protected Varargs oncallv(int opcode, Varargs args) { try { switch ( opcode ) { - case INIT: { - LuaTable t = new LuaTable(0,8); - LibFunction.bind( t, this.getClass(), NAMES ); - return t; - } case BINDCLASS: { final Class clazz = Class.forName(args.checkString(1)); return toUserdata( clazz, clazz ); diff --git a/test/junit/org/luaj/vm2/LuaOperationsTest.java b/test/junit/org/luaj/vm2/LuaOperationsTest.java index 05ca7108..fd3799da 100644 --- a/test/junit/org/luaj/vm2/LuaOperationsTest.java +++ b/test/junit/org/luaj/vm2/LuaOperationsTest.java @@ -55,7 +55,7 @@ public class LuaOperationsTest extends TestCase { private final LuaValue stringlong = LuaValue.valueOf(samplestringlong); private final LuaValue stringdouble = LuaValue.valueOf(samplestringdouble); private final LuaTable table = LuaValue.listOf( new LuaValue[] { LuaValue.valueOf("aaa"), LuaValue.valueOf("bbb") } ); - private final LuaFunction somefunc = new ZeroArgFunction("sample",0,table) { public LuaValue call() { return NONE;}}; + private final LuaValue somefunc = new ZeroArgFunction(table) { public LuaValue call() { return NONE;}}; private final LuaThread thread = new LuaThread(somefunc,table); private final Prototype proto = new Prototype(); private final LuaClosure someclosure = new LuaClosure(proto,table); @@ -207,7 +207,7 @@ public class LuaOperationsTest extends TestCase { // function tests { - LuaFunction f = new ZeroArgFunction("f",0,_G) { public LuaValue call() { return env.get("a");}}; + LuaFunction f = new ZeroArgFunction(_G) { public LuaValue call() { return env.get("a");}}; assertEquals( aaa, f.call() ); f.setfenv(newenv); assertEquals( newenv, f.getfenv() ); diff --git a/test/junit/org/luaj/vm2/ScriptDrivenTest.java b/test/junit/org/luaj/vm2/ScriptDrivenTest.java index 33ffaa25..53f2cc1f 100644 --- a/test/junit/org/luaj/vm2/ScriptDrivenTest.java +++ b/test/junit/org/luaj/vm2/ScriptDrivenTest.java @@ -70,9 +70,9 @@ public class ScriptDrivenTest extends TestCase { // override print() final ByteArrayOutputStream output = new ByteArrayOutputStream(); - final PrintStream oldps = BaseLib.STDOUT; + final PrintStream oldps = BaseLib.instance.STDOUT; final PrintStream ps = new PrintStream( output ); - BaseLib.STDOUT = ps; + BaseLib.instance.STDOUT = ps; // run the script try { @@ -85,7 +85,7 @@ public class ScriptDrivenTest extends TestCase { assertEquals(expectedOutput, actualOutput); } finally { - BaseLib.STDOUT = oldps; + BaseLib.instance.STDOUT = oldps; ps.close(); } } catch ( IOException ioe ) {