Convert most libraries to use standard loading.

This commit is contained in:
James Roseborough
2010-04-01 05:35:54 +00:00
parent 68fbf6cc39
commit 64751f694e
15 changed files with 481 additions and 469 deletions

View File

@@ -200,7 +200,7 @@ public class LuaTable extends LuaValue {
} }
} }
public Varargs remove(int pos) { public LuaValue remove(int pos) {
if ( pos == 0 ) if ( pos == 0 )
pos = length(); pos = length();
if ( pos < 1 || pos > array.length ) if ( pos < 1 || pos > array.length )

View File

@@ -25,13 +25,11 @@ import java.io.InputStream;
import java.io.PrintStream; import java.io.PrintStream;
import org.luaj.vm2.LoadState; import org.luaj.vm2.LoadState;
import org.luaj.vm2.LuaClosure;
import org.luaj.vm2.LuaError; import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaString; import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaThread; import org.luaj.vm2.LuaThread;
import org.luaj.vm2.LuaValue; import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.Varargs; import org.luaj.vm2.Varargs;
/** /**

View File

@@ -27,9 +27,8 @@ import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs; import org.luaj.vm2.Varargs;
public class CoroutineLib extends VarArgFunction { public class CoroutineLib extends VarArgFunction {
private static final String[] NAMES = { private static final String[] NAMES = {
"<coroutine>",
"create", "create",
"resume", "resume",
"running", "running",
@@ -39,36 +38,31 @@ public class CoroutineLib extends VarArgFunction {
"wrapped" "wrapped"
}; };
private static final int INSTALL = 0; private static final int INIT = -1;
private static final int CREATE = 1; private static final int CREATE = 0;
private static final int RESUME = 2; private static final int RESUME = 1;
private static final int RUNNING = 3; private static final int RUNNING = 2;
private static final int STATUS = 4; private static final int STATUS = 3;
private static final int YIELD = 5; private static final int YIELD = 4;
private static final int WRAP = 6; private static final int WRAP = 5;
private static final int WRAPPED = 7; private static final int WRAPPED = 6;
public static void install(LuaValue globals) {
globals.set("coroutine", createInstance());
}
public static final LuaValue createInstance() { public CoroutineLib() {
LuaTable t = new LuaTable(); name = "coroutine";;
CoroutineLib f = new CoroutineLib(); opcode = INIT;
LibFunction.bind(t, f.getClass(), NAMES);
return t;
} }
public CoroutineLib() {}
private CoroutineLib(String name, int opcode, LuaThread thread) { private CoroutineLib(String name, int opcode, LuaThread thread) {
super(name, opcode, thread); super(name, opcode, thread);
} }
public Varargs invoke(Varargs args) { public Varargs invoke(Varargs args) {
switch ( opcode ) { switch ( opcode ) {
case INSTALL: case INIT: {
return createInstance(); LuaTable t = new LuaTable();
LibFunction.bind(t, this.getClass(), NAMES);
return t;
}
case CREATE: { case CREATE: {
final LuaValue func = args.checkfunction(1); final LuaValue func = args.checkfunction(1);
return new LuaThread(func, func.getfenv() ); return new LuaThread(func, func.getfenv() );

View File

@@ -37,12 +37,12 @@ import org.luaj.vm2.Varargs;
public class DebugLib extends VarArgFunction { public class DebugLib extends VarArgFunction {
public static final boolean CALLS = (null != System.getProperty("CALLS")); public static final boolean CALLS = (null != System.getProperty("CALLS"));
public static final boolean TRACE = (null != System.getProperty("TRACE")); public static final boolean TRACE = (null != System.getProperty("TRACE"));
// leave this unset to allow obfuscators to remove it in production builds // leave this unset to allow obfuscators to
// remove it in production builds
public static boolean DEBUG_ENABLED; public static boolean DEBUG_ENABLED;
private static final String[] NAMES = { private static final String[] NAMES = {
"<debug>",
"debug", "debug",
"getfenv", "getfenv",
"gethook", "gethook",
@@ -59,71 +59,65 @@ public class DebugLib extends VarArgFunction {
"traceback", "traceback",
}; };
private static final int INSTALL = 0; private static final int INIT = -1;
private static final int DEBUG = 1; private static final int DEBUG = 0;
private static final int GETFENV = 2; private static final int GETFENV = 1;
private static final int GETHOOK = 3; private static final int GETHOOK = 2;
private static final int GETINFO = 4; private static final int GETINFO = 3;
private static final int GETLOCAL = 5; private static final int GETLOCAL = 4;
private static final int GETMETATABLE = 6; private static final int GETMETATABLE = 5;
private static final int GETREGISTRY = 7; private static final int GETREGISTRY = 6;
private static final int GETUPVALUE = 8; private static final int GETUPVALUE = 7;
private static final int SETFENV = 9; private static final int SETFENV = 8;
private static final int SETHOOK = 10; private static final int SETHOOK = 9;
private static final int SETLOCAL = 11; private static final int SETLOCAL = 10;
private static final int SETMETATABLE = 12; private static final int SETMETATABLE = 11;
private static final int SETUPVALUE = 13; private static final int SETUPVALUE = 12;
private static final int TRACEBACK = 14; private static final int TRACEBACK = 13;
/* maximum stack for a Lua function */ /* maximum stack for a Lua function */
private static final int MAXSTACK = 250; private static final int MAXSTACK = 250;
private static final LuaString LUA = LuaString.valueOf("Lua"); private static final LuaString LUA = valueOf("Lua");
private static final LuaString JAVA = LuaString.valueOf("Java"); private static final LuaString JAVA = valueOf("Java");
private static final LuaString QMARK = LuaString.valueOf("?"); private static final LuaString QMARK = valueOf("?");
private static final LuaString GLOBAL = LuaString.valueOf("global"); private static final LuaString GLOBAL = valueOf("global");
private static final LuaString LOCAL = LuaString.valueOf("local"); private static final LuaString LOCAL = valueOf("local");
private static final LuaString METHOD = LuaString.valueOf("method"); private static final LuaString METHOD = valueOf("method");
private static final LuaString UPVALUE = LuaString.valueOf("upvalue"); private static final LuaString UPVALUE = valueOf("upvalue");
private static final LuaString FIELD = LuaString.valueOf("field"); private static final LuaString FIELD = valueOf("field");
private static final LuaString CALL = LuaString.valueOf("call"); private static final LuaString CALL = valueOf("call");
private static final LuaString LINE = LuaString.valueOf("line"); private static final LuaString LINE = valueOf("line");
private static final LuaString COUNT = LuaString.valueOf("count"); private static final LuaString COUNT = valueOf("count");
private static final LuaString RETURN = LuaString.valueOf("return"); private static final LuaString RETURN = valueOf("return");
private static final LuaString TAILRETURN = LuaString.valueOf("tail return"); private static final LuaString TAILRETURN = valueOf("tail return");
private static final LuaString FUNC = LuaString.valueOf("func"); private static final LuaString FUNC = valueOf("func");
private static final LuaString NUPS = LuaString.valueOf("nups"); private static final LuaString NUPS = valueOf("nups");
private static final LuaString NAME = LuaString.valueOf("name"); private static final LuaString NAME = valueOf("name");
private static final LuaString NAMEWHAT = LuaString.valueOf("namewhat"); private static final LuaString NAMEWHAT = valueOf("namewhat");
private static final LuaString WHAT = LuaString.valueOf("what"); private static final LuaString WHAT = valueOf("what");
private static final LuaString SOURCE = LuaString.valueOf("source"); private static final LuaString SOURCE = valueOf("source");
private static final LuaString SHORT_SRC = LuaString.valueOf("short_src"); private static final LuaString SHORT_SRC = valueOf("short_src");
private static final LuaString LINEDEFINED = LuaString.valueOf("linedefined"); private static final LuaString LINEDEFINED = valueOf("linedefined");
private static final LuaString LASTLINEDEFINED = LuaString.valueOf("lastlinedefined"); private static final LuaString LASTLINEDEFINED = valueOf("lastlinedefined");
private static final LuaString CURRENTLINE = LuaString.valueOf("currentline"); private static final LuaString CURRENTLINE = valueOf("currentline");
private static final LuaString ACTIVELINES = LuaString.valueOf("activelines"); private static final LuaString ACTIVELINES = valueOf("activelines");
public static void install(LuaValue globals) { public DebugLib() {
globals.set("debug", DebugLib.createInstance() ); name = "debug";
opcode = INIT;
} }
public static final LuaValue createInstance() {
LuaTable t = new LuaTable();
DebugLib f = new DebugLib();
LibFunction.bind(t, f.getClass(), NAMES);
if ( ! DEBUG_ENABLED ) {
DEBUG_ENABLED = true;
}
return t;
}
public DebugLib() {}
public Varargs invoke(Varargs args) { public Varargs invoke(Varargs args) {
switch ( opcode ) { switch ( opcode ) {
case INSTALL: case INIT: {
return createInstance(); LuaTable t = new LuaTable(0,20);
LibFunction.bind(t, this.getClass(), NAMES);
if ( ! DEBUG_ENABLED )
DEBUG_ENABLED = true;
return t;
}
case DEBUG: case DEBUG:
return _debug(args); return _debug(args);
case GETFENV: case GETFENV:

View File

@@ -33,7 +33,7 @@ import org.luaj.vm2.Varargs;
abstract abstract
public class IoLib extends LuaTable { public class IoLib extends VarArgFunction {
abstract abstract
protected class File extends LuaValue{ protected class File extends LuaValue{
@@ -56,7 +56,7 @@ public class IoLib extends LuaTable {
// delegate method access to file methods table // delegate method access to file methods table
public LuaValue get( LuaValue key ) { public LuaValue get( LuaValue key ) {
return filemethods.get(key); return env.get(FILEMETHODS).get(key);
} }
// essentially a userdata instance // essentially a userdata instance
@@ -113,11 +113,6 @@ public class IoLib extends LuaTable {
*/ */
abstract protected File openProgram(String prog, String mode) throws IOException; abstract protected File openProgram(String prog, String mode) throws IOException;
//protected final Table filemt;
protected final LuaTable filemethods;
private final LuaValue linesiter;
private File infile = null; private File infile = null;
private File outfile = null; private File outfile = null;
private File errfile = null; private File errfile = null;
@@ -127,128 +122,123 @@ public class IoLib extends LuaTable {
private static final LuaValue STDERR = valueOf("stderr"); private static final LuaValue STDERR = valueOf("stderr");
private static final LuaValue FILE = valueOf("file"); private static final LuaValue FILE = valueOf("file");
private static final LuaValue CLOSED_FILE = valueOf("closed file"); private static final LuaValue CLOSED_FILE = valueOf("closed file");
private static final LuaValue FILEMETHODS = valueOf("__filemethods");
private static final LuaValue LINESITER = valueOf("__linesiter");
public IoLib() { public IoLib() {}
protected LuaTable init() {
// io lib functions // io lib functions
set("flush", new IoFuncV("flush",0)); LuaTable t = new LuaTable();
set("tmpfile", new IoFuncV("tmpfile",1)); LibFunction.bind(t, this.getClass(), new String[] {
set("close", new IoFuncV("close",2)); "flush", "tmpfile", "close", "input", "output",
set("input", new IoFuncV("input",3)); "type", "popen", "open", "lines", "read",
set("output", new IoFuncV("output",4)); "write", "__linesiter" }, 1 );
set("type", new IoFuncV("type",5));
set("popen", new IoFuncV("popen",6));
set("open", new IoFuncV("open",7));
set("lines", new IoFuncV("lines",8));
set("read", new IoFuncV("read",9));
set("write", new IoFuncV("write",10));
setmetatable( tableOf(new LuaValue[] {
valueOf("__index"),new IoFuncV("__index",11),
}) );
// create file metatable // create metatable
filemethods = tableOf(new LuaValue[] { LuaTable idx = new LuaTable();
valueOf("close"), new IoFuncV("close",12), LibFunction.bind(idx, this.getClass(), new String[] {
valueOf("flush"), new IoFuncV("flush",13), "__index", }, 13 );
valueOf("setvbuf"), new IoFuncV("setvbuf",14), t.setmetatable( idx );
valueOf("lines"), new IoFuncV("lines",15),
valueOf("read"), new IoFuncV("read",16),
valueOf("seek"), new IoFuncV("seek",17),
valueOf("write"), new IoFuncV("write",18),
});
//filemt = tableOf(new Value[]{valueOf("__index"),filemethods});
// lines iterator // create file methods table
linesiter = new IoFuncV("linesiter",19); LuaTable filemethods = new LuaTable();
LibFunction.bind(filemethods, this.getClass(), new String[] {
"close", "flush", "setvbuf", "lines", "read",
"seek", "write", }, 14 );
t.set(FILEMETHODS, filemethods);
// return the table
return t;
} }
public class IoFuncV extends VarArgFunction { public Varargs invoke(Varargs args) {
public IoFuncV(String name, int opcode) { File f;
super(name,opcode,IoLib.this); int n;
} LuaValue v;
public Varargs invoke(Varargs args) { try {
File f; switch ( opcode ) {
int n; case 0: // init
LuaValue v; return init();
try { case 1: // io.flush() -> bool
switch ( opcode ) { checkopen(output());
case 0: // io.flush() -> bool outfile.flush();
checkopen(output()); return LuaValue.TRUE;
outfile.flush(); case 2: // io.tmpfile() -> file
return LuaValue.TRUE; return tmpFile();
case 1: // io.tmpfile() -> file case 3: // io.close([file]) -> void
return tmpFile(); f = args.arg1().isnil()? output(): checkfile(args.arg1());
case 2: // io.close([file]) -> void checkopen(f);
f = args.arg1().isnil()? output(): checkfile(args.arg1()); return ioclose(f);
checkopen(f); case 4: // io.input([file]) -> file
return ioclose(f); infile = args.arg1().isnil()? input(): args.arg1().isstring()?
case 3: // io.input([file]) -> file ioopenfile(args.checkString(1),"r"):
infile = args.arg1().isnil()? input(): args.arg1().isstring()? checkfile(args.arg1());
ioopenfile(args.checkString(1),"r"): return infile;
checkfile(args.arg1());
return infile;
case 4: // io.output(filename) -> file
outfile = args.arg1().isnil()? output(): args.arg1().isstring()?
ioopenfile(args.checkString(1),"w"):
checkfile(args.arg1());
return outfile;
case 5: // io.type(obj) -> "file" | "closed file" | nil
if ( (f=optfile(args.arg1())) != null )
return f.isclosed()? CLOSED_FILE: FILE;
return NIL;
case 6: // io.popen(prog, [mode]) -> file
return openProgram(args.checkString(1),args.optString(2,"r"));
case 7: // io.open(filename, [mode]) -> file | nil,err
return rawopenfile(args.checkString(1), args.optString(2,"r"));
case 8: // io.lines(filename) -> iterator
infile = args.arg1().isnil()? input(): ioopenfile(args.checkString(1),"r");
checkopen(infile);
return lines(infile);
case 9: // io.read(...) -> (...)
checkopen(infile);
return ioread(infile,args);
case 10: // io.write(...) -> void
checkopen(output());
return iowrite(outfile,args);
case 11: // __index, returns a field
v = args.arg(2);
return v.equals(STDOUT)?output():
v.equals(STDIN)? input():
v.equals(STDERR)? errput(): NIL;
// ------------ file metatable operations
case 12: // file:close() -> void case 5: // io.output(filename) -> file
return ioclose(checkfile(args.arg1())); outfile = args.arg1().isnil()? output(): args.arg1().isstring()?
case 13: // file:flush() -> void ioopenfile(args.checkString(1),"w"):
checkfile(args.arg1()).flush(); checkfile(args.arg1());
return LuaValue.TRUE; return outfile;
case 14: // file:setvbuf(mode,[size]) -> void case 6: // io.type(obj) -> "file" | "closed file" | nil
f = checkfile(args.arg1()); if ( (f=optfile(args.arg1())) != null )
f.setvbuf(args.checkString(2),args.optint(3, 1024)); return f.isclosed()? CLOSED_FILE: FILE;
return LuaValue.TRUE; return NIL;
case 15: // file:lines() -> iterator case 7: // io.popen(prog, [mode]) -> file
return lines(checkfile(args.arg1())); return openProgram(args.checkString(1),args.optString(2,"r"));
case 16: // file:read(...) -> (...) case 8: // io.open(filename, [mode]) -> file | nil,err
f = checkfile(args.arg1()); return rawopenfile(args.checkString(1), args.optString(2,"r"));
return ioread(f,args.subargs(2)); case 9: // io.lines(filename) -> iterator
case 17: // file:seek([whence][,offset]) -> pos | nil,error infile = args.arg1().isnil()? input(): ioopenfile(args.checkString(1),"r");
f = checkfile(args.arg1()); checkopen(infile);
n = f.seek(args.optString(2,"cur"),args.optint(3,0)); return lines(infile);
return valueOf(n); case 10: // io.read(...) -> (...)
case 18: // file:write(...) -> void checkopen(infile);
f = checkfile(args.arg1()); return ioread(infile,args);
return iowrite(f,args.subargs(2)); case 11: // io.write(...) -> void
case 19: // lines iterator(s,var) -> var' checkopen(output());
f = checkfile(args.arg1()); return iowrite(outfile,args);
return freadline(f); case 12: // lines iterator(s,var) -> var'
} f = checkfile(args.arg1());
} catch ( IOException ioe ) { return freadline(f);
return errorresult(ioe);
// ------------ __index metatable operation
case 13: // __index, returns a field
v = args.arg(2);
return v.equals(STDOUT)?output():
v.equals(STDIN)? input():
v.equals(STDERR)? errput(): NIL;
// ------------ file metatable operations
case 14: // file:close() -> void
return ioclose(checkfile(args.arg1()));
case 15: // file:flush() -> void
checkfile(args.arg1()).flush();
return LuaValue.TRUE;
case 16: // file:setvbuf(mode,[size]) -> void
f = checkfile(args.arg1());
f.setvbuf(args.checkString(2),args.optint(3, 1024));
return LuaValue.TRUE;
case 17: // file:lines() -> iterator
return lines(checkfile(args.arg1()));
case 18: // file:read(...) -> (...)
f = checkfile(args.arg1());
return ioread(f,args.subargs(2));
case 19: // file:seek([whence][,offset]) -> pos | nil,error
f = checkfile(args.arg1());
n = f.seek(args.optString(2,"cur"),args.optint(3,0));
return valueOf(n);
case 20: // file:write(...) -> void
f = checkfile(args.arg1());
return iowrite(f,args.subargs(2));
} }
return NONE; } catch ( IOException ioe ) {
return errorresult(ioe);
} }
return NONE;
} }
private File input() { private File input() {
@@ -296,6 +286,7 @@ public class IoLib extends LuaTable {
// TODO: how to close on finalization // TODO: how to close on finalization
private Varargs lines(final File f) throws IOException { private Varargs lines(final File f) throws IOException {
LuaValue linesiter = env.get(LINESITER);
return varargsOf( linesiter, f ); return varargsOf( linesiter, f );
} }

View File

@@ -45,12 +45,16 @@ abstract public class LibFunction extends LuaFunction {
return name!=null? name: super.toString(); return name!=null? name: super.toString();
} }
/** Bind a set of names to class instances, put values into the table. */
public static LuaTable bind( LuaTable table, Class libFuncClass, String[] names ) { public static LuaTable bind( LuaTable table, Class libFuncClass, String[] names ) {
return bind( table, libFuncClass, names, 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 { try {
for ( int i=0, n=names.length; i<n; i++ ) { for ( int i=0, n=names.length; i<n; i++ ) {
LibFunction f = (LibFunction) libFuncClass.newInstance(); LibFunction f = (LibFunction) libFuncClass.newInstance();
f.opcode = i; f.opcode = firstOpcode + i;
f.name = names[i]; f.name = names[i];
f.env = table; f.env = table;
table.set( names[i], f ); table.set( names[i], f );

View File

@@ -35,48 +35,50 @@ import org.luaj.vm2.Varargs;
* *
* @see org.luaj.vm2.lib.jse.JseMathLib * @see org.luaj.vm2.lib.jse.JseMathLib
*/ */
public class MathLib extends LuaTable { public class MathLib extends OneArgFunction {
public static MathLib MATHLIB = null; public static MathLib MATHLIB = null;
private Random random; private static final LuaValue RANDOM = valueOf("__random");
public MathLib() { public MathLib() {
name = "math";
opcode = -1;
MATHLIB = this; MATHLIB = this;
this.set( "pi", Math.PI ); }
this.set( "huge", LuaDouble.POSINF );
LibFunction.bind( this, new MathFunc1().getClass(), new String[] { protected LuaTable init() {
LuaTable t = new LuaTable(0,30);
t.set( "pi", Math.PI );
t.set( "huge", LuaDouble.POSINF );
LibFunction.bind( t, new MathLib().getClass(), new String[] {
"abs", "ceil", "cos", "deg", "abs", "ceil", "cos", "deg",
"exp", "floor", "rad", "sin", "exp", "floor", "rad", "sin",
"sqrt", "tan" } ); "sqrt", "tan" } );
LibFunction.bind( this, new MathFunc2().getClass(), new String[] { LibFunction.bind( t, new MathFunc2().getClass(), new String[] {
"fmod", "ldexp", "pow", "random", "fmod", "ldexp", "pow", "random",
} ); } );
LibFunction.bind( this, new MathFuncV().getClass(), new String[] { LibFunction.bind( t, new MathFuncV().getClass(), new String[] {
"frexp", "max", "min", "modf", "frexp", "max", "min", "modf",
"randomseed" } ); "randomseed" } );
return t;
} }
public String toString() { public LuaValue call(LuaValue arg) {
return "math"; switch ( opcode ) {
} case -1: return init();
case 0: return valueOf(Math.abs(arg.todouble()));
public static class MathFunc1 extends OneArgFunction { case 1: return valueOf(Math.ceil(arg.todouble()));
public LuaValue call(LuaValue arg) { case 2: return valueOf(Math.cos(arg.todouble()));
switch ( opcode ) { case 3: return valueOf(Math.toDegrees(arg.todouble()));
case 0: return valueOf(Math.abs(arg.todouble())); case 4: return dpow(Math.E,arg.todouble());
case 1: return valueOf(Math.ceil(arg.todouble())); case 5: return valueOf(Math.floor(arg.todouble()));
case 2: return valueOf(Math.cos(arg.todouble())); case 6: return valueOf(Math.toRadians(arg.todouble()));
case 3: return valueOf(Math.toDegrees(arg.todouble())); case 7: return valueOf(Math.sin(arg.todouble()));
case 4: return dpow(Math.E,arg.todouble()); case 8: return valueOf(Math.sqrt(arg.todouble()));
case 5: return valueOf(Math.floor(arg.todouble())); case 9: return valueOf(Math.tan(arg.todouble()));
case 6: return valueOf(Math.toRadians(arg.todouble()));
case 7: return valueOf(Math.sin(arg.todouble()));
case 8: return valueOf(Math.sqrt(arg.todouble()));
case 9: return valueOf(Math.tan(arg.todouble()));
}
return NIL;
} }
return NIL;
} }
public static class MathFunc2 extends TwoArgFunction { public static class MathFunc2 extends TwoArgFunction {
@@ -99,16 +101,16 @@ public class MathLib extends LuaTable {
return dpow(arg1.todouble(), arg2.todouble()); return dpow(arg1.todouble(), arg2.todouble());
} }
case 3: { // random case 3: { // random
MathLib lib = (MathLib) env; Random random = (Random) env.get(RANDOM).optuserdata(Random.class, null);
if ( lib.random == null ) if ( random == null )
lib.random = new Random(); env.set(RANDOM,userdataOf(random = new Random()));
if ( arg1.isnil() ) if ( arg1.isnil() )
return valueOf( lib.random.nextDouble() ); return valueOf( random.nextDouble() );
int m = arg1.toint(); int m = arg1.toint();
if ( arg2.isnil() ) if ( arg2.isnil() )
return valueOf( 1 + lib.random.nextInt(m) ); return valueOf( 1 + random.nextInt(m) );
else else
return valueOf( m + lib.random.nextInt(arg2.toint()-m) ); return valueOf( m + random.nextInt(arg2.toint()-m) );
} }
} }
return NIL; return NIL;
@@ -184,7 +186,7 @@ public class MathLib extends LuaTable {
} }
case 4: { // randomseed case 4: { // randomseed
long seed = args.checklong(1); long seed = args.checklong(1);
((MathLib) env).random = new Random(seed); env.set(RANDOM,userdataOf(new Random(seed)));
return NONE; return NONE;
} }
} }

View File

@@ -46,10 +46,11 @@ import org.luaj.vm2.Varargs;
* *
* @see org.luaj.vm2.lib.jse.JseOsLib * @see org.luaj.vm2.lib.jse.JseOsLib
*/ */
public class OsLib extends LuaTable { public class OsLib extends VarArgFunction {
public static String TMP_PREFIX = ".luaj"; public static String TMP_PREFIX = ".luaj";
public static String TMP_SUFFIX = "tmp"; public static String TMP_SUFFIX = "tmp";
private static final int INIT = -1;
private static final int CLOCK = 0; private static final int CLOCK = 0;
private static final int DATE = 1; private static final int DATE = 1;
private static final int DIFFTIME = 2; private static final int DIFFTIME = 2;
@@ -61,6 +62,20 @@ public class OsLib extends LuaTable {
private static final int SETLOCALE = 8; private static final int SETLOCALE = 8;
private static final int TIME = 9; private static final int TIME = 9;
private static final int TMPNAME = 10; private static final int TMPNAME = 10;
private static final String[] NAMES = {
"clock",
"date",
"difftime",
"execute",
"exit",
"getenv",
"remove",
"rename",
"setlocale",
"time",
"tmpname",
};
private static final long t0 = System.currentTimeMillis(); private static final long t0 = System.currentTimeMillis();
private static long tmpnames = t0; private static long tmpnames = t0;
@@ -69,71 +84,54 @@ public class OsLib extends LuaTable {
* Create and OsLib instance. * Create and OsLib instance.
*/ */
public OsLib() { public OsLib() {
String[] NAMES = { name = "os";
"clock", opcode = INIT;
"date",
"difftime",
"execute",
"exit",
"getenv",
"remove",
"rename",
"setlocale",
"time",
"tmpname",
};
for ( int i=NAMES.length; --i>=0; )
set(NAMES[i], new OsFuncV(NAMES[i], i, this));
} }
public String toString() { public Varargs invoke(Varargs args) {
return "os"; try {
} switch ( opcode ) {
case INIT: {
private class OsFuncV extends VarArgFunction { LuaTable t = new LuaTable();
public OsFuncV(String name, int opcode, OsLib lib) { LibFunction.bind(t, getClass(), NAMES);
super(name, opcode, lib); return t;
}
public Varargs invoke(Varargs args) {
try {
switch ( opcode ) {
case CLOCK:
return valueOf(clock());
case DATE: {
String s = args.optString(1, null);
long t = args.optlong(2,-1);
return valueOf( date(s, t==-1? System.currentTimeMillis(): t) );
}
case DIFFTIME:
return valueOf(difftime(args.checklong(1),args.checklong(2)));
case EXECUTE:
return valueOf(execute(args.optString(1, null)));
case EXIT:
exit(args.optint(1, 0));
return NONE;
case GETENV: {
final String val = getenv(args.checkString(1));
return val!=null? valueOf(val): NIL;
}
case REMOVE:
remove(args.checkString(1));
return LuaValue.TRUE;
case RENAME:
rename(args.checkString(1), args.checkString(2));
return LuaValue.TRUE;
case SETLOCALE: {
String s = setlocale(args.optString(1,null), args.optString(2, "all"));
return s!=null? valueOf(s): NIL;
}
case TIME:
return valueOf(time(args.arg1().isnil()? null: args.checktable(1)));
case TMPNAME:
return valueOf(tmpname());
}
return NONE;
} catch ( IOException e ) {
return varargsOf(NIL, valueOf(e.getMessage()));
} }
case CLOCK:
return valueOf(clock());
case DATE: {
String s = args.optString(1, null);
long t = args.optlong(2,-1);
return valueOf( date(s, t==-1? System.currentTimeMillis(): t) );
}
case DIFFTIME:
return valueOf(difftime(args.checklong(1),args.checklong(2)));
case EXECUTE:
return valueOf(execute(args.optString(1, null)));
case EXIT:
exit(args.optint(1, 0));
return NONE;
case GETENV: {
final String val = getenv(args.checkString(1));
return val!=null? valueOf(val): NIL;
}
case REMOVE:
remove(args.checkString(1));
return LuaValue.TRUE;
case RENAME:
rename(args.checkString(1), args.checkString(2));
return LuaValue.TRUE;
case SETLOCALE: {
String s = setlocale(args.optString(1,null), args.optString(2, "all"));
return s!=null? valueOf(s): NIL;
}
case TIME:
return valueOf(time(args.arg1().isnil()? null: args.checktable(1)));
case TMPNAME:
return valueOf(tmpname());
}
return NONE;
} catch ( IOException e ) {
return varargsOf(NIL, valueOf(e.getMessage()));
} }
} }

View File

@@ -32,33 +32,36 @@ import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs; import org.luaj.vm2.Varargs;
import org.luaj.vm2.compiler.DumpState; import org.luaj.vm2.compiler.DumpState;
public class StringLib extends LuaTable { public class StringLib extends OneArgFunction {
public static StringLib instance; public static LuaTable instance;
public StringLib() { public StringLib() {
LibFunction.bind( this, new StringFunc1().getClass(), new String[] { name = "string";
"dump", "len", "lower", "reverse", opcode = -1;
"upper", } );
LibFunction.bind( this, new StringFuncV().getClass(), new String[] {
"byte", "char", "find", "format",
"gmatch", "gsub", "match", "rep",
"sub"} );
instance = this;
} }
public static class StringFunc1 extends OneArgFunction { public LuaValue call(LuaValue arg) {
public LuaValue call(LuaValue arg) { switch ( opcode ) {
switch ( opcode ) { case -1: {
case 0: return StringLib.dump(arg); // dump (function) LuaTable t = new LuaTable();
case 1: return StringLib.len(arg); // len (function) LibFunction.bind( t, getClass(), new String[] {
case 2: return StringLib.lower(arg); // lower (function) "dump", "len", "lower", "reverse", "upper", } );
case 3: return StringLib.reverse(arg); // reverse (function) LibFunction.bind( t, new StringFuncV().getClass(), new String[] {
case 4: return StringLib.upper(arg); // upper (function) "byte", "char", "find", "format",
} "gmatch", "gsub", "match", "rep",
return NIL; "sub"} );
instance = t;
return t;
}
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)
}
return NIL;
} }
}
public static class StringFuncV extends VarArgFunction { public static class StringFuncV extends VarArgFunction {
public Varargs invoke(Varargs args) { public Varargs invoke(Varargs args) {

View File

@@ -25,34 +25,36 @@ import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue; import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs; import org.luaj.vm2.Varargs;
public class TableLib extends LuaTable { public class TableLib extends OneArgFunction {
public TableLib() { public TableLib() {
LibFunction.bind( this, new TableFunc1().getClass(), new String[] { name = "table";
"getn", // (table) -> number opcode = -1;
"maxn", // (table) -> number
} );
LibFunction.bind( this, 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
} );
} }
public static class TableFunc1 extends OneArgFunction { public LuaValue call(LuaValue arg) {
public LuaValue call(LuaValue arg) { switch ( opcode ) {
switch ( opcode ) { case -1: {
case 0: return arg.checktable().getn(); LuaTable t = new LuaTable();
case 1: return valueOf( arg.checktable().maxn()); LibFunction.bind( t, this.getClass(), new String[] {
} "getn", // (table) -> number
return NIL; "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 static class TableFuncV extends VarArgFunction {
public Varargs invoke(Varargs args) { public Varargs invoke(Varargs args) {

View File

@@ -22,6 +22,7 @@
package org.luaj.vm2.lib; package org.luaj.vm2.lib;
import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
public class JmePlatform { public class JmePlatform {
@@ -33,13 +34,25 @@ public class JmePlatform {
public static LuaTable standardGlobals() { public static LuaTable standardGlobals() {
LuaTable _G = new BaseLib(); LuaTable _G = new BaseLib();
new org.luaj.vm2.lib.PackageLib(_G); new org.luaj.vm2.lib.PackageLib(_G);
_G.set( "io", new org.luaj.vm2.lib.jme.JseIoLib() ); set(_G, "coroutine", new org.luaj.vm2.lib.CoroutineLib() );
_G.set( "math", new org.luaj.vm2.lib.MathLib() ); set(_G, "io", new org.luaj.vm2.lib.jme.JseIoLib() );
_G.set( "os", new org.luaj.vm2.lib.OsLib() ); set(_G, "math", new org.luaj.vm2.lib.MathLib() );
_G.set( "table", new org.luaj.vm2.lib.TableLib() ); set(_G, "os", new org.luaj.vm2.lib.OsLib() );
_G.set( "string", new org.luaj.vm2.lib.StringLib() ); set(_G, "table", new org.luaj.vm2.lib.TableLib() );
CoroutineLib.install( _G ); set(_G, "string", new org.luaj.vm2.lib.StringLib() );
return _G; return _G;
} }
public static LuaTable debugGlobals() {
LuaTable _G = standardGlobals();
set(_G, "string", new org.luaj.vm2.lib.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 );
}
} }

View File

@@ -22,6 +22,7 @@
package org.luaj.vm2.lib; package org.luaj.vm2.lib;
import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.CoroutineLib; import org.luaj.vm2.lib.CoroutineLib;
import org.luaj.vm2.lib.jse.JseBaseLib; import org.luaj.vm2.lib.jse.JseBaseLib;
import org.luaj.vm2.lib.jse.JseIoLib; import org.luaj.vm2.lib.jse.JseIoLib;
@@ -39,15 +40,20 @@ public class JsePlatform {
public static LuaTable standardGlobals() { public static LuaTable standardGlobals() {
LuaTable _G = new JseBaseLib(); LuaTable _G = new JseBaseLib();
new org.luaj.vm2.lib.PackageLib(_G); new org.luaj.vm2.lib.PackageLib(_G);
_G.set( "io", new org.luaj.vm2.lib.jse.JseIoLib() ); set(_G, "table", new org.luaj.vm2.lib.TableLib() );
_G.set( "math", new org.luaj.vm2.lib.jse.JseMathLib() ); set(_G, "string", new org.luaj.vm2.lib.StringLib() );
_G.set( "os", new org.luaj.vm2.lib.jse.JseOsLib() ); set(_G, "coroutine", new org.luaj.vm2.lib.CoroutineLib() );
_G.set( "table", new org.luaj.vm2.lib.TableLib() ); set(_G, "debug", new org.luaj.vm2.lib.DebugLib() );
_G.set( "string", new org.luaj.vm2.lib.StringLib() ); set(_G, "math", new org.luaj.vm2.lib.jse.JseMathLib() );
_G.set( "luajava", new org.luaj.vm2.lib.jse.LuajavaLib() ); set(_G, "io", new org.luaj.vm2.lib.jse.JseIoLib() );
CoroutineLib.install(_G); set(_G, "os", new org.luaj.vm2.lib.jse.JseOsLib() );
DebugLib.install(_G); set(_G, "luajava", new org.luaj.vm2.lib.jse.LuajavaLib() );
return _G; 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 );
}
} }

View File

@@ -21,9 +21,9 @@
******************************************************************************/ ******************************************************************************/
package org.luaj.vm2.lib.jse; package org.luaj.vm2.lib.jse;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue; import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.LibFunction; import org.luaj.vm2.lib.LibFunction;
import org.luaj.vm2.lib.OneArgFunction;
import org.luaj.vm2.lib.TwoArgFunction; import org.luaj.vm2.lib.TwoArgFunction;
/** /**
@@ -34,31 +34,33 @@ import org.luaj.vm2.lib.TwoArgFunction;
*/ */
public class JseMathLib extends org.luaj.vm2.lib.MathLib { public class JseMathLib extends org.luaj.vm2.lib.MathLib {
public JseMathLib() { public JseMathLib() {}
LibFunction.bind( this, new J2seMathFunc1().getClass(), new String[] {
protected LuaTable init() {
LuaTable t = super.init();
LibFunction.bind( t, this.getClass(), new String[] {
"acos", "asin", "atan", "cosh", "acos", "asin", "atan", "cosh",
"exp", "log", "log10", "sinh", "exp", "log", "log10", "sinh",
"tanh" } ); "tanh" } );
LibFunction.bind( this, new J2seMathFunc2().getClass(), new String[] { LibFunction.bind( t, new J2seMathFunc2().getClass(), new String[] {
"atan2", "pow", } ); "atan2", "pow", } );
return t;
} }
public static class J2seMathFunc1 extends OneArgFunction { public LuaValue call(LuaValue arg) {
public LuaValue call(LuaValue arg) { switch ( opcode ) {
switch ( opcode ) { case -1: return init();
case 0: return valueOf(Math.acos(arg.todouble())); case 0: return valueOf(Math.acos(arg.todouble()));
case 1: return valueOf(Math.asin(arg.todouble())); case 1: return valueOf(Math.asin(arg.todouble()));
case 2: return valueOf(Math.atan(arg.todouble())); case 2: return valueOf(Math.atan(arg.todouble()));
case 3: return valueOf(Math.cosh(arg.todouble())); case 3: return valueOf(Math.cosh(arg.todouble()));
case 4: return valueOf(Math.exp(arg.todouble())); case 4: return valueOf(Math.exp(arg.todouble()));
case 5: return valueOf(Math.log(arg.todouble())); case 5: return valueOf(Math.log(arg.todouble()));
case 6: return valueOf(Math.log10(arg.todouble())); case 6: return valueOf(Math.log10(arg.todouble()));
case 7: return valueOf(Math.sinh(arg.todouble())); case 7: return valueOf(Math.sinh(arg.todouble()));
case 8: return valueOf(Math.tanh(arg.todouble())); case 8: return valueOf(Math.tanh(arg.todouble()));
}
return NIL;
} }
return NIL;
} }
public static class J2seMathFunc2 extends TwoArgFunction { public static class J2seMathFunc2 extends TwoArgFunction {

View File

@@ -47,15 +47,19 @@ import org.luaj.vm2.lib.ThreeArgFunction;
import org.luaj.vm2.lib.TwoArgFunction; import org.luaj.vm2.lib.TwoArgFunction;
import org.luaj.vm2.lib.VarArgFunction; import org.luaj.vm2.lib.VarArgFunction;
public class LuajavaLib extends LuaTable { public class LuajavaLib extends VarArgFunction {
private static final int BINDCLASS = 0; private static final String LIBNAME = "luajava";
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 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 String[] NAMES = { private static final String[] NAMES = {
LIBNAME,
"bindClass", "bindClass",
"newInstance", "newInstance",
"new", "new",
@@ -69,89 +73,91 @@ public class LuajavaLib extends LuaTable {
} }
public LuajavaLib() { public LuajavaLib() {
LibFunction.bind( this, LuajavaFuncV.class, NAMES ); name = LIBNAME;
opcode = INIT;
} }
// perform a lua call public Varargs invoke(final Varargs args) {
public static class LuajavaFuncV extends VarArgFunction { try {
switch ( opcode ) {
public Varargs invoke(final Varargs args) { case INIT: {
try { LuaTable t = new LuaTable(0,8);
switch ( opcode ) { LibFunction.bind( t, this.getClass(), NAMES );
case BINDCLASS: { return t;
final Class clazz = Class.forName(args.checkString(1));
return toUserdata( clazz, clazz );
}
case NEWINSTANCE:
case NEW: {
// get constructor
final LuaValue c = args.checkvalue(1);
final Class clazz = (opcode==NEWINSTANCE? Class.forName(c.toString()): (Class) c.checkuserdata(Class.class));
final ParamsList params = new ParamsList( args );
final Constructor con = resolveConstructor( clazz, params );
// coerce args, construct instance
Object[] cargs = CoerceLuaToJava.coerceArgs( params.values, con.getParameterTypes() );
Object o = con.newInstance( cargs );
// return result
return toUserdata( o, clazz );
}
case CREATEPROXY: {
final int niface = args.narg()-1;
if ( niface <= 0 )
throw new LuaError("no interfaces");
final LuaValue lobj = args.checktable(niface+1);
// get the interfaces
final Class[] ifaces = new Class[niface];
for ( int i=0; i<niface; i++ )
ifaces[i] = Class.forName(args.checkString(i+1));
// create the invocation handler
InvocationHandler handler = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
LuaValue func = lobj.get(name);
if ( func.isnil() )
return null;
int n = args!=null? args.length: 0;
LuaValue[] v = new LuaValue[n];
for ( int i=0; i<n; i++ )
v[i] = CoerceJavaToLua.coerce(args[i]);
LuaValue result = func.invoke(v).arg1();
return CoerceLuaToJava.coerceArg(result, method.getReturnType());
}
};
// create the proxy object
Object proxy = Proxy.newProxyInstance(getClass().getClassLoader(), ifaces, handler);
// return the proxy
return LuaValue.userdataOf( proxy );
}
case LOADLIB: {
// get constructor
String classname = args.checkString(1);
String methodname = args.checkString(2);
Class clazz = Class.forName(classname);
Method method = clazz.getMethod(methodname, new Class[] {});
Object result = method.invoke(clazz, new Object[] {});
if ( result instanceof LuaValue ) {
return (LuaValue) result;
} else {
return NIL;
}
}
default:
throw new LuaError("not yet supported: "+this);
}
} catch (LuaError e) {
throw e;
} catch (Exception e) {
throw new LuaError(e);
} }
case BINDCLASS: {
final Class clazz = Class.forName(args.checkString(1));
return toUserdata( clazz, clazz );
}
case NEWINSTANCE:
case NEW: {
// get constructor
final LuaValue c = args.checkvalue(1);
final Class clazz = (opcode==NEWINSTANCE? Class.forName(c.toString()): (Class) c.checkuserdata(Class.class));
final ParamsList params = new ParamsList( args );
final Constructor con = resolveConstructor( clazz, params );
// coerce args, construct instance
Object[] cargs = CoerceLuaToJava.coerceArgs( params.values, con.getParameterTypes() );
Object o = con.newInstance( cargs );
// return result
return toUserdata( o, clazz );
}
case CREATEPROXY: {
final int niface = args.narg()-1;
if ( niface <= 0 )
throw new LuaError("no interfaces");
final LuaValue lobj = args.checktable(niface+1);
// get the interfaces
final Class[] ifaces = new Class[niface];
for ( int i=0; i<niface; i++ )
ifaces[i] = Class.forName(args.checkString(i+1));
// create the invocation handler
InvocationHandler handler = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
LuaValue func = lobj.get(name);
if ( func.isnil() )
return null;
int n = args!=null? args.length: 0;
LuaValue[] v = new LuaValue[n];
for ( int i=0; i<n; i++ )
v[i] = CoerceJavaToLua.coerce(args[i]);
LuaValue result = func.invoke(v).arg1();
return CoerceLuaToJava.coerceArg(result, method.getReturnType());
}
};
// create the proxy object
Object proxy = Proxy.newProxyInstance(getClass().getClassLoader(), ifaces, handler);
// return the proxy
return LuaValue.userdataOf( proxy );
}
case LOADLIB: {
// get constructor
String classname = args.checkString(1);
String methodname = args.checkString(2);
Class clazz = Class.forName(classname);
Method method = clazz.getMethod(methodname, new Class[] {});
Object result = method.invoke(clazz, new Object[] {});
if ( result instanceof LuaValue ) {
return (LuaValue) result;
} else {
return NIL;
}
}
default:
throw new LuaError("not yet supported: "+this);
}
} catch (LuaError e) {
throw e;
} catch (Exception e) {
throw new LuaError(e);
} }
} }

View File

@@ -64,10 +64,9 @@ public class ScriptDrivenTest extends TestCase {
_G = org.luaj.vm2.lib.JsePlatform.standardGlobals(); _G = org.luaj.vm2.lib.JsePlatform.standardGlobals();
break; break;
case JME: case JME:
_G = org.luaj.vm2.lib.JmePlatform.standardGlobals(); _G = org.luaj.vm2.lib.JmePlatform.debugGlobals();
break; break;
} }
DebugLib.install( _G );
// override print() // override print()
final ByteArrayOutputStream output = new ByteArrayOutputStream(); final ByteArrayOutputStream output = new ByteArrayOutputStream();