Remove env from LuaFunction, replace with upValiue array, and remove most occurances of setfenv and getfenv.
This commit is contained in:
@@ -34,7 +34,7 @@ public class Lua {
|
||||
|
||||
/** use return values from previous op */
|
||||
public static final int LUA_MULTRET = -1;
|
||||
|
||||
|
||||
// from lopcodes.h
|
||||
|
||||
/*===========================================================================
|
||||
|
||||
@@ -67,7 +67,6 @@ import org.luaj.vm2.lib.DebugLib;
|
||||
* Since a {@link LuaClosure} is a {@link LuaFunction} which is a {@link LuaValue},
|
||||
* all the value operations can be used directly such as:
|
||||
* <ul>
|
||||
* <li>{@link LuaValue#setfenv(LuaValue)}</li>
|
||||
* <li>{@link LuaValue#call()}</li>
|
||||
* <li>{@link LuaValue#call(LuaValue)}</li>
|
||||
* <li>{@link LuaValue#invoke()}</li>
|
||||
@@ -90,24 +89,28 @@ public class LuaClosure extends LuaFunction {
|
||||
private static final UpValue[] NOUPVALUES = new UpValue[0];
|
||||
|
||||
public final Prototype p;
|
||||
public final UpValue[] upValues;
|
||||
|
||||
LuaClosure() {
|
||||
p = null;
|
||||
upValues = null;
|
||||
/** Create a closure around a Prototype with the default global environment.
|
||||
* If the prototype has upvalues, the environment will be written into the first upvalue.
|
||||
* @param p the Prototype to construct this Closure for.
|
||||
* @param env the environment to associate with the closure.
|
||||
*/
|
||||
public LuaClosure(Prototype p) {
|
||||
this(p, LuaValue._G);
|
||||
}
|
||||
/** Supply the initial environment */
|
||||
|
||||
/** Create a closure around a Prototype with a specific environment.
|
||||
* If the prototype has upvalues, the environment will be written into the first upvalue.
|
||||
* @param p the Prototype to construct this Closure for.
|
||||
* @param env the environment to associate with the closure.
|
||||
*/
|
||||
public LuaClosure(Prototype p, LuaValue env) {
|
||||
this(p, p.upvalues.length, env);
|
||||
}
|
||||
|
||||
protected LuaClosure(Prototype p, int nupvalues, LuaValue env) {
|
||||
super( env );
|
||||
this.p = p;
|
||||
switch (nupvalues) {
|
||||
case 0: this.upValues = NOUPVALUES; break;
|
||||
case 1: this.upValues = new UpValue[] { new UpValue(new LuaValue[1], 0) }; this.upValues[0].setValue(env); break;
|
||||
default: this.upValues = new UpValue[nupvalues]; break;
|
||||
if (p.upvalues == null || p.upvalues.length == 0)
|
||||
this.upValues = NOUPVALUES;
|
||||
else {
|
||||
this.upValues = new UpValue[p.upvalues.length];
|
||||
this.upValues[0] = new UpValue(new LuaValue[] {env}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,7 +466,7 @@ public class LuaClosure extends LuaFunction {
|
||||
case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx]) */
|
||||
{
|
||||
Prototype newp = p.p[i>>>14];
|
||||
LuaClosure ncl = new LuaClosure(newp, env);
|
||||
LuaClosure ncl = new LuaClosure(newp);
|
||||
Upvaldesc[] uv = newp.upvalues;
|
||||
for ( int j=0, nup=uv.length; j<nup; ++j ) {
|
||||
if (uv[j].instack) /* upvalue refes to local variable? */
|
||||
|
||||
@@ -38,16 +38,8 @@ public class LuaFunction extends LuaValue {
|
||||
/** Shared static metatable for all functions and closures. */
|
||||
public static LuaValue s_metatable;
|
||||
|
||||
protected LuaValue env;
|
||||
public UpValue[] upValues;
|
||||
|
||||
public LuaFunction() {
|
||||
this.env = NIL;
|
||||
}
|
||||
|
||||
public LuaFunction(LuaValue env) {
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
public int type() {
|
||||
return TFUNCTION;
|
||||
}
|
||||
@@ -71,12 +63,9 @@ public class LuaFunction extends LuaValue {
|
||||
public LuaValue getmetatable() {
|
||||
return s_metatable;
|
||||
}
|
||||
|
||||
public LuaValue getfenv() {
|
||||
return env;
|
||||
}
|
||||
|
||||
public void setfenv(LuaValue env) {
|
||||
this.env = env!=null? env: NIL;
|
||||
public void initupvalue1(LuaValue env) {
|
||||
if (upValues != null && upValues.length > 0)
|
||||
upValues[0] = new UpValue(new LuaValue[] {env}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,6 @@ public class LuaThread extends LuaValue {
|
||||
"normal",
|
||||
"dead",};
|
||||
|
||||
private LuaValue env;
|
||||
private final State state;
|
||||
|
||||
/** Field to hold state of error condition during debug hook function calls. */
|
||||
@@ -112,11 +111,9 @@ public class LuaThread extends LuaValue {
|
||||
/**
|
||||
* Create a LuaThread around a function and environment
|
||||
* @param func The function to execute
|
||||
* @param env The environment to apply to the thread
|
||||
*/
|
||||
public LuaThread(LuaValue func, LuaValue env) {
|
||||
public LuaThread(LuaValue func) {
|
||||
LuaValue.assert_(func != null, "function cannot be null");
|
||||
this.env = env;
|
||||
state = new State(this, func);
|
||||
}
|
||||
|
||||
@@ -144,14 +141,6 @@ public class LuaThread extends LuaValue {
|
||||
return s_metatable;
|
||||
}
|
||||
|
||||
public LuaValue getfenv() {
|
||||
return env;
|
||||
}
|
||||
|
||||
public void setfenv(LuaValue env) {
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return STATUS_NAMES[state.status];
|
||||
}
|
||||
@@ -171,24 +160,6 @@ public class LuaThread extends LuaValue {
|
||||
public static boolean isMainThread(LuaThread r) {
|
||||
return r == main_thread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the globals of the current thread.
|
||||
* <p>
|
||||
* This must be done once before any other code executes.
|
||||
* @param globals The global variables for the main ghread.
|
||||
*/
|
||||
public static void setGlobals(LuaValue globals) {
|
||||
running_thread.env = globals;
|
||||
}
|
||||
|
||||
/** Get the current thread's environment
|
||||
* @return {@link LuaValue} containing the global variables of the current thread.
|
||||
*/
|
||||
public static LuaValue getGlobals() {
|
||||
LuaValue e = running_thread.env;
|
||||
return e!=null? e: LuaValue.error("LuaThread.setGlobals() not initialized");
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used at the beginning of a call to prepare for possible getfenv/setfenv calls
|
||||
|
||||
@@ -109,7 +109,11 @@ package org.luaj.vm2;
|
||||
*/
|
||||
abstract
|
||||
public class LuaValue extends Varargs {
|
||||
|
||||
/** The default global environment. This must be set before lua can be used.
|
||||
* Typically, it is set as a side effect of calling one of
|
||||
* JsePlatform.standardGlobals() or similar functions.
|
||||
*/
|
||||
public static LuaValue _G;
|
||||
|
||||
/** Type enumeration constant for lua numbers that are ints, for compatibility with lua 5.1 number patch only */
|
||||
public static final int TINT = (-2);
|
||||
@@ -1351,13 +1355,23 @@ public class LuaValue extends Varargs {
|
||||
public Varargs inext(LuaValue index) { return typerror("table"); }
|
||||
|
||||
/**
|
||||
* Load a library instance by setting its environment to {@code this}
|
||||
* Load a library instance by setting its environment to the global environment {@code LuaValue._G}
|
||||
* and calling it, which should iniitalize the library instance and
|
||||
* install itself into this instance.
|
||||
* @param library The callable {@link LuaValue} to load into {@code this}
|
||||
* @return {@link LuaValue._G} containing the result of the initialization call.
|
||||
*/
|
||||
public LuaValue load(LuaValue library) { return load(library, _G); }
|
||||
|
||||
/**
|
||||
* Load a library instance by setting its environment to {@code env}
|
||||
* and calling it, which should iniitalize the library instance and
|
||||
* install itself into this instance.
|
||||
* @param library The callable {@link LuaValue} to load into {@code this}
|
||||
* @param env The {@link LuaValue} to use as the environment for the library.
|
||||
* @return {@link LuaValue} containing the result of the initialization call.
|
||||
*/
|
||||
public LuaValue load(LuaValue library) { library.setfenv(this); return library.call(); }
|
||||
public LuaValue load(LuaValue library, LuaValue env) { return library.call(env); }
|
||||
|
||||
// varargs references
|
||||
public LuaValue arg(int index) { return index==1? this: NIL; }
|
||||
@@ -1393,26 +1407,7 @@ public class LuaValue extends Varargs {
|
||||
* @see LuaThread#s_metatable
|
||||
*/
|
||||
public LuaValue setmetatable(LuaValue metatable) { return argerror("table"); }
|
||||
|
||||
/**
|
||||
* Get the environemnt for an instance.
|
||||
* @return {@link LuaValue} currently set as the instances environent.
|
||||
*/
|
||||
public LuaValue getfenv() { typerror("function or thread"); return null; }
|
||||
|
||||
/**
|
||||
* Set the environment on an object.
|
||||
* <p>
|
||||
* Typically the environment is created once per application via a platform
|
||||
* helper method such as {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
|
||||
* However, any object can serve as an environment if it contains suitable metatag
|
||||
* values to implement {@link #get(LuaValue)} to provide the environment values.
|
||||
* @param env {@link LuaValue} (typically a {@link LuaTable}) containing the environment.
|
||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||
*/
|
||||
public void setfenv(LuaValue env) { typerror("function or thread"); }
|
||||
|
||||
|
||||
/** Call {@link this} with 0 arguments, including metatag processing,
|
||||
* and return only the first return value.
|
||||
* <p>
|
||||
|
||||
@@ -51,6 +51,12 @@ public class Prototype {
|
||||
public int is_vararg;
|
||||
public int maxstacksize;
|
||||
|
||||
|
||||
public Prototype() {}
|
||||
|
||||
public Prototype(int n_upvalues) {
|
||||
upvalues = new Upvaldesc[n_upvalues];
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return source + ":" + linedefined+"-"+lastlinedefined;
|
||||
|
||||
@@ -126,7 +126,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
||||
instance = this;
|
||||
}
|
||||
|
||||
public LuaValue call(LuaValue arg) {
|
||||
public LuaValue call(LuaValue env) {
|
||||
env.set( "_G", env );
|
||||
env.set( "_VERSION", Lua._VERSION );
|
||||
bind( env, BaseLib1.class, LIB1_KEYS );
|
||||
@@ -230,8 +230,8 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
||||
args.argcheck(args.isstring(1) || args.isnil(1), 1, "filename must be string or nil");
|
||||
String filename = args.isstring(1)? args.tojstring(1): null;
|
||||
Varargs v = filename == null?
|
||||
BaseLib.loadStream( baselib.STDIN, "=stdin", "bt", LuaThread.getGlobals() ):
|
||||
BaseLib.loadFile( args.checkjstring(1), "bt", LuaThread.getGlobals() );
|
||||
BaseLib.loadStream( baselib.STDIN, "=stdin", "bt",LuaValue._G ):
|
||||
BaseLib.loadFile( args.checkjstring(1), "bt",LuaValue._G );
|
||||
return v.isnil(1)? error(v.tojstring(2)): v.arg1().invoke();
|
||||
}
|
||||
case 2: // "load", // ( ld [, source [, mode [, env]]] ) -> chunk | nil, msg
|
||||
@@ -240,7 +240,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
||||
args.argcheck(ld.isstring() || ld.isfunction(), 1, "ld must be string or function");
|
||||
String source = args.optjstring(2, ld.isstring()? ld.tojstring(): "=(load)");
|
||||
String mode = args.optjstring(3, "bt");
|
||||
LuaValue env = args.optvalue(4, LuaThread.getGlobals());
|
||||
LuaValue env = args.optvalue(4,LuaValue._G);
|
||||
return BaseLib.loadStream(ld.isstring()? ld.strvalue().toInputStream():
|
||||
new StringInputStream(ld.checkfunction()), source, mode, env);
|
||||
}
|
||||
@@ -249,7 +249,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
||||
args.argcheck(args.isstring(1) || args.isnil(1), 1, "filename must be string or nil");
|
||||
String filename = args.isstring(1)? args.tojstring(1): null;
|
||||
String mode = args.optjstring(2, "bt");
|
||||
LuaValue env = args.optvalue(3, LuaThread.getGlobals());
|
||||
LuaValue env = args.optvalue(3,LuaValue._G);
|
||||
return filename == null?
|
||||
BaseLib.loadStream( baselib.STDIN, "=stdin", mode, env ):
|
||||
BaseLib.loadFile( filename, mode, env );
|
||||
@@ -275,7 +275,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
||||
}
|
||||
case 6: // "print", // (...) -> void
|
||||
{
|
||||
LuaValue tostring = LuaThread.getGlobals().get("tostring");
|
||||
LuaValue tostring =LuaValue._G.get("tostring");
|
||||
for ( int i=1, n=args.narg(); i<=n; i++ ) {
|
||||
if ( i>1 ) baselib.STDOUT.write( '\t' );
|
||||
LuaString s = tostring.call( args.arg(i) ).strvalue();
|
||||
|
||||
@@ -65,10 +65,16 @@ public class CoroutineLib extends VarArgFunction {
|
||||
private static final int WRAP = 6;
|
||||
private static final int WRAPPED = 7;
|
||||
|
||||
private LuaThread t;
|
||||
|
||||
public CoroutineLib() {
|
||||
}
|
||||
|
||||
private LuaTable init() {
|
||||
private CoroutineLib(LuaThread t) {
|
||||
this.t = t;
|
||||
}
|
||||
|
||||
private LuaTable init(LuaValue env) {
|
||||
LuaTable t = new LuaTable();
|
||||
bind(t, CoroutineLib.class, new String[] {
|
||||
"create", "resume", "running", "status", "yield", "wrap" },
|
||||
@@ -81,11 +87,11 @@ public class CoroutineLib extends VarArgFunction {
|
||||
public Varargs invoke(Varargs args) {
|
||||
switch ( opcode ) {
|
||||
case INIT: {
|
||||
return init();
|
||||
return init(args.arg1());
|
||||
}
|
||||
case CREATE: {
|
||||
final LuaValue func = args.checkfunction(1);
|
||||
return new LuaThread(func, LuaThread.getGlobals() );
|
||||
return new LuaThread(func);
|
||||
}
|
||||
case RESUME: {
|
||||
final LuaThread t = args.checkthread(1);
|
||||
@@ -103,15 +109,13 @@ public class CoroutineLib extends VarArgFunction {
|
||||
}
|
||||
case WRAP: {
|
||||
final LuaValue func = args.checkfunction(1);
|
||||
final LuaThread thread = new LuaThread(func, func.getfenv());
|
||||
CoroutineLib cl = new CoroutineLib();
|
||||
cl.setfenv(thread);
|
||||
final LuaThread thread = new LuaThread(func);
|
||||
CoroutineLib cl = new CoroutineLib(thread);
|
||||
cl.name = "wrapped";
|
||||
cl.opcode = WRAPPED;
|
||||
return cl;
|
||||
}
|
||||
case WRAPPED: {
|
||||
final LuaThread t = (LuaThread) env;
|
||||
final Varargs result = t.resume( args );
|
||||
if ( result.arg1().toboolean() ) {
|
||||
return result.subargs(2);
|
||||
|
||||
@@ -136,7 +136,7 @@ public class DebugLib extends VarArgFunction {
|
||||
public DebugLib() {
|
||||
}
|
||||
|
||||
private LuaTable init() {
|
||||
private LuaTable init(LuaValue env) {
|
||||
DEBUG_ENABLED = true;
|
||||
LuaTable t = new LuaTable();
|
||||
bind(t, DebugLib.class, NAMES, DEBUG);
|
||||
@@ -147,7 +147,7 @@ public class DebugLib extends VarArgFunction {
|
||||
|
||||
public Varargs invoke(Varargs args) {
|
||||
switch ( opcode ) {
|
||||
case INIT: return init();
|
||||
case INIT: return init(args.arg1());
|
||||
case DEBUG: return _debug(args);
|
||||
case GETHOOK: return _gethook(args);
|
||||
case GETINFO: return _getinfo(args,this);
|
||||
|
||||
@@ -215,7 +215,7 @@ public class IoLib extends OneArgFunction {
|
||||
public IoLib() {
|
||||
}
|
||||
|
||||
public LuaValue call(LuaValue arg) {
|
||||
public LuaValue call(LuaValue env) {
|
||||
|
||||
// io lib functions
|
||||
LuaTable t = new LuaTable();
|
||||
@@ -248,12 +248,13 @@ public class IoLib extends OneArgFunction {
|
||||
}
|
||||
|
||||
static final class IoLibV extends VarArgFunction {
|
||||
private File f;
|
||||
public IoLib iolib;
|
||||
public IoLibV() {
|
||||
}
|
||||
public IoLibV(LuaValue env, String name, int opcode, IoLib iolib) {
|
||||
public IoLibV(File f, String name, int opcode, IoLib iolib) {
|
||||
super();
|
||||
this.env = env;
|
||||
this.f = f;
|
||||
this.name = name;
|
||||
this.opcode = opcode;
|
||||
this.iolib = iolib;
|
||||
@@ -283,7 +284,7 @@ public class IoLib extends OneArgFunction {
|
||||
case FILE_WRITE: return iolib._file_write(args.arg1(),args.subargs(2));
|
||||
|
||||
case IO_INDEX: return iolib._io_index(args.arg(2));
|
||||
case LINES_ITER: return iolib._lines_iter(env);
|
||||
case LINES_ITER: return iolib._lines_iter(f);
|
||||
}
|
||||
} catch ( IOException ioe ) {
|
||||
return errorresult(ioe);
|
||||
|
||||
@@ -169,7 +169,6 @@ abstract public class LibFunction extends LuaFunction {
|
||||
LibFunction f = (LibFunction) factory.newInstance();
|
||||
f.opcode = firstopcode + i;
|
||||
f.name = names[i];
|
||||
f.env = env;
|
||||
env.set(f.name, f);
|
||||
}
|
||||
} catch ( Exception e ) {
|
||||
|
||||
@@ -83,7 +83,7 @@ public class MathLib extends OneArgFunction {
|
||||
MATHLIB = this;
|
||||
}
|
||||
|
||||
public LuaValue call(LuaValue arg) {
|
||||
public LuaValue call(LuaValue env) {
|
||||
LuaTable t = new LuaTable(0,30);
|
||||
t.set( "pi", Math.PI );
|
||||
t.set( "huge", LuaDouble.POSINF );
|
||||
|
||||
@@ -58,7 +58,7 @@ abstract public class OneArgFunction extends LibFunction {
|
||||
* @param env The environment to apply during constructon.
|
||||
*/
|
||||
public OneArgFunction( LuaValue env ) {
|
||||
this.env = env;
|
||||
throw new UnsupportedOperationException("Cannot supply env to constructor");
|
||||
}
|
||||
|
||||
public final LuaValue call() {
|
||||
|
||||
@@ -112,7 +112,7 @@ public class OsLib extends VarArgFunction {
|
||||
public OsLib() {
|
||||
}
|
||||
|
||||
public LuaValue init() {
|
||||
public LuaValue init(LuaValue env) {
|
||||
LuaTable t = new LuaTable();
|
||||
bind(t, this.getClass(), NAMES, CLOCK);
|
||||
env.set("os", t);
|
||||
@@ -124,7 +124,7 @@ public class OsLib extends VarArgFunction {
|
||||
try {
|
||||
switch ( opcode ) {
|
||||
case INIT:
|
||||
return init();
|
||||
return init(args.arg1());
|
||||
case CLOCK:
|
||||
return valueOf(clock());
|
||||
case DATE: {
|
||||
|
||||
@@ -105,18 +105,18 @@ public class PackageLib extends OneArgFunction {
|
||||
instance = this;
|
||||
}
|
||||
|
||||
public LuaValue call(LuaValue arg) {
|
||||
env.set("require", new PkgLib1(env,"require",OP_REQUIRE,this));
|
||||
public LuaValue call(LuaValue env) {
|
||||
env.set("require", new PkgLib1("require",OP_REQUIRE,this));
|
||||
env.set( "package", PACKAGE=tableOf( new LuaValue[] {
|
||||
_LOADED, LOADED=tableOf(),
|
||||
_PRELOAD, tableOf(),
|
||||
_PATH, valueOf(DEFAULT_LUA_PATH),
|
||||
_LOADLIB, new PkgLibV(env,"loadlib",OP_LOADLIB,this),
|
||||
_SEARCHPATH, new PkgLibV(env,"searchpath",OP_SEARCHPATH,this),
|
||||
_LOADLIB, new PkgLibV("loadlib",OP_LOADLIB,this),
|
||||
_SEARCHPATH, new PkgLibV("searchpath",OP_SEARCHPATH,this),
|
||||
_SEARCHERS, listOf(new LuaValue[] {
|
||||
preload_searcher = new PkgLibV(env,"preload_searcher", OP_PRELOAD_SEARCHER,this),
|
||||
lua_searcher = new PkgLibV(env,"lua_searcher", OP_LUA_SEARCHER,this),
|
||||
java_searcher = new PkgLibV(env,"java_searcher", OP_JAVA_SEARCHER,this),
|
||||
preload_searcher = new PkgLibV("preload_searcher",OP_PRELOAD_SEARCHER, this),
|
||||
lua_searcher = new PkgLibV("lua_searcher",OP_LUA_SEARCHER, this),
|
||||
java_searcher = new PkgLibV("java_searcher",OP_JAVA_SEARCHER, this),
|
||||
}) }) );
|
||||
LOADED.set("package", PACKAGE);
|
||||
return env;
|
||||
@@ -124,8 +124,7 @@ public class PackageLib extends OneArgFunction {
|
||||
|
||||
static final class PkgLib1 extends OneArgFunction {
|
||||
PackageLib lib;
|
||||
public PkgLib1(LuaValue env,String name, int opcode, PackageLib lib) {
|
||||
this.env = env;
|
||||
public PkgLib1(String name, int opcode, PackageLib lib) {
|
||||
this.name = name;
|
||||
this.opcode = opcode;
|
||||
this.lib = lib;
|
||||
@@ -141,8 +140,7 @@ public class PackageLib extends OneArgFunction {
|
||||
|
||||
static final class PkgLibV extends VarArgFunction {
|
||||
PackageLib lib;
|
||||
public PkgLibV(LuaValue env,String name, int opcode, PackageLib lib) {
|
||||
this.env = env;
|
||||
public PkgLibV(String name,int opcode, PackageLib lib) {
|
||||
this.name = name;
|
||||
this.opcode = opcode;
|
||||
this.lib = lib;
|
||||
@@ -286,7 +284,7 @@ public class PackageLib extends OneArgFunction {
|
||||
LuaString filename = v.arg1().strvalue();
|
||||
|
||||
// Try to load the file.
|
||||
v = BaseLib.loadFile(filename.tojstring(), "bt", LuaThread.getGlobals());
|
||||
v = BaseLib.loadFile(filename.tojstring(), "bt", LuaValue._G);
|
||||
if ( v.arg1().isfunction() )
|
||||
return LuaValue.varargsOf(v.arg1(), filename);
|
||||
|
||||
@@ -340,7 +338,6 @@ public class PackageLib extends OneArgFunction {
|
||||
try {
|
||||
c = Class.forName(classname);
|
||||
v = (LuaValue) c.newInstance();
|
||||
v.setfenv(env);
|
||||
return v;
|
||||
} catch ( ClassNotFoundException cnfe ) {
|
||||
return valueOf("\n\tno class '"+classname+"'" );
|
||||
|
||||
@@ -66,7 +66,7 @@ public class StringLib extends OneArgFunction {
|
||||
public StringLib() {
|
||||
}
|
||||
|
||||
public LuaValue call(LuaValue arg) {
|
||||
public LuaValue call(LuaValue env) {
|
||||
LuaTable t = new LuaTable();
|
||||
bind(t, StringLib1.class, new String[] {
|
||||
"dump", "len", "lower", "reverse", "upper", } );
|
||||
|
||||
@@ -61,7 +61,7 @@ public class TableLib extends OneArgFunction {
|
||||
public TableLib() {
|
||||
}
|
||||
|
||||
private LuaTable init() {
|
||||
private LuaTable init(LuaValue env) {
|
||||
LuaTable t = new LuaTable();
|
||||
bind(t, TableLib.class, new String[] { "getn", "maxn", }, 1 );
|
||||
bind(t, TableLibV.class, new String[] {
|
||||
@@ -74,7 +74,7 @@ public class TableLib extends OneArgFunction {
|
||||
public LuaValue call(LuaValue arg) {
|
||||
switch ( opcode ) {
|
||||
case 0: // init library
|
||||
return init();
|
||||
return init(arg);
|
||||
case 1: // "getn" (table) -> number
|
||||
return arg.checktable().getn();
|
||||
case 2: // "maxn" (table) -> number
|
||||
|
||||
@@ -58,7 +58,7 @@ abstract public class ThreeArgFunction extends LibFunction {
|
||||
* @param env The environment to apply during constructon.
|
||||
*/
|
||||
public ThreeArgFunction( LuaValue env ) {
|
||||
this.env = env;
|
||||
throw new UnsupportedOperationException("Cannot supply env to constructor");
|
||||
}
|
||||
|
||||
public final LuaValue call() {
|
||||
|
||||
@@ -58,7 +58,7 @@ abstract public class TwoArgFunction extends LibFunction {
|
||||
* @param env The environment to apply during constructon.
|
||||
*/
|
||||
public TwoArgFunction( LuaValue env ) {
|
||||
this.env = env;
|
||||
throw new UnsupportedOperationException("Cannot supply env to constructor");
|
||||
}
|
||||
|
||||
public final LuaValue call() {
|
||||
|
||||
@@ -51,7 +51,7 @@ abstract public class VarArgFunction extends LibFunction {
|
||||
}
|
||||
|
||||
public VarArgFunction( LuaValue env ) {
|
||||
this.env = env;
|
||||
throw new UnsupportedOperationException("Cannot supply env to constructor");
|
||||
}
|
||||
|
||||
public LuaValue call() {
|
||||
@@ -71,30 +71,12 @@ abstract public class VarArgFunction extends LibFunction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Override and implement for the best performance.
|
||||
* Subclass responsibility.
|
||||
* May not have expected behavior for tail calls.
|
||||
* Should not be used if either:
|
||||
* - function needs to be used as a module
|
||||
* Should not be used if:
|
||||
* - function has a possibility of returning a TailcallVarargs
|
||||
* @param args the arguments to the function call.
|
||||
*/
|
||||
public Varargs invoke(Varargs args) {
|
||||
LuaThread.CallStack cs = LuaThread.onCall(this);
|
||||
try {
|
||||
return this.onInvoke(args).eval();
|
||||
} finally {
|
||||
cs.onReturn();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to provide a call implementation that runs in an environment
|
||||
* that can participate in setfenv, and behaves as expected
|
||||
* when returning TailcallVarargs.
|
||||
* @param args the arguments to the function call.
|
||||
*/
|
||||
public Varargs onInvoke(Varargs args) {
|
||||
return invoke(args);
|
||||
}
|
||||
abstract public Varargs invoke(Varargs args);
|
||||
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ abstract public class ZeroArgFunction extends LibFunction {
|
||||
* @param env The environment to apply during constructon.
|
||||
*/
|
||||
public ZeroArgFunction( LuaValue env ) {
|
||||
this.env = env;
|
||||
throw new UnsupportedOperationException("Cannot supply env to constructor");
|
||||
}
|
||||
|
||||
public LuaValue call(LuaValue arg) {
|
||||
|
||||
@@ -101,6 +101,7 @@ public class JmePlatform {
|
||||
*/
|
||||
public static LuaTable standardGlobals() {
|
||||
LuaTable _G = new LuaTable();
|
||||
LuaValue._G = _G;
|
||||
_G.load(new BaseLib());
|
||||
_G.load(new PackageLib());
|
||||
_G.load(new OsLib());
|
||||
@@ -109,7 +110,6 @@ public class JmePlatform {
|
||||
_G.load(new StringLib());
|
||||
_G.load(new CoroutineLib());
|
||||
_G.load(new JmeIoLib());
|
||||
LuaThread.setGlobals(_G);
|
||||
LuaC.install();
|
||||
return _G;
|
||||
}
|
||||
|
||||
@@ -186,7 +186,6 @@ public class lua {
|
||||
try {
|
||||
// load as java class
|
||||
LuaValue v = (LuaValue) Class.forName(libname).newInstance();
|
||||
v.setfenv(_G);
|
||||
v.call(slibname, _G);
|
||||
} catch ( Exception f ) {
|
||||
throw new IOException("loadLibrary("+libname+") failed: "+e+","+f );
|
||||
|
||||
@@ -87,6 +87,7 @@ public class JsePlatform {
|
||||
*/
|
||||
public static LuaTable standardGlobals() {
|
||||
LuaTable _G = new LuaTable();
|
||||
LuaValue._G = _G;
|
||||
_G.load(new JseBaseLib());
|
||||
_G.load(new PackageLib());
|
||||
_G.load(new TableLib());
|
||||
@@ -96,7 +97,6 @@ public class JsePlatform {
|
||||
_G.load(new JseIoLib());
|
||||
_G.load(new JseOsLib());
|
||||
_G.load(new LuajavaLib());
|
||||
LuaThread.setGlobals(_G);
|
||||
LuaC.install();
|
||||
return _G;
|
||||
}
|
||||
|
||||
@@ -98,6 +98,7 @@ public class LuajavaLib extends VarArgFunction {
|
||||
try {
|
||||
switch ( opcode ) {
|
||||
case INIT: {
|
||||
LuaValue env = args.arg1();
|
||||
LuaTable t = new LuaTable();
|
||||
bind( t, LuajavaLib.class, NAMES, BINDCLASS );
|
||||
env.set("luajava", t);
|
||||
|
||||
@@ -112,7 +112,6 @@ public class Lua2Java implements LuaCompiler {
|
||||
Class clazz = cl.loadClass(className);
|
||||
Object instance = clazz.newInstance();
|
||||
LuaFunction value = (LuaFunction) instance;
|
||||
value.setfenv( env );
|
||||
return value;
|
||||
} else {
|
||||
}
|
||||
|
||||
@@ -30,12 +30,9 @@ import org.luaj.vm2.Prototype;
|
||||
******************************************************************************/
|
||||
public class JavaLoader extends ClassLoader {
|
||||
|
||||
private final LuaValue env;
|
||||
|
||||
private Map<String,byte[]> unloaded = new HashMap<String,byte[]>();
|
||||
|
||||
public JavaLoader( LuaValue env ) {
|
||||
this.env = env;
|
||||
public JavaLoader() {
|
||||
}
|
||||
|
||||
public LuaFunction load( Prototype p, String classname, String filename ) {
|
||||
@@ -49,10 +46,14 @@ public class JavaLoader extends ClassLoader {
|
||||
}
|
||||
|
||||
public LuaFunction load(String classname) {
|
||||
return load(classname, LuaValue._G);
|
||||
}
|
||||
|
||||
public LuaFunction load(String classname, LuaValue env) {
|
||||
try {
|
||||
Class c = loadClass( classname );
|
||||
LuaFunction v = (LuaFunction) c.newInstance();
|
||||
v.setfenv(env);
|
||||
v.initupvalue1(env);
|
||||
return v;
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -99,7 +99,7 @@ public class LuaJC implements LuaCompiler {
|
||||
Prototype p = LuaC.instance.compile(stream, name);
|
||||
String classname = toStandardJavaClassName( name );
|
||||
String luaname = toStandardLuaFileName( name );
|
||||
JavaLoader loader = new JavaLoader(env);
|
||||
JavaLoader loader = new JavaLoader();
|
||||
return loader.load(p, classname, luaname);
|
||||
}
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
|
||||
Bindings b = context.getBindings(ScriptContext.ENGINE_SCOPE);
|
||||
LuaFunction f = newFunctionInstance();
|
||||
ClientBindings cb = new ClientBindings(b);
|
||||
f.setfenv(cb.env);
|
||||
f.initupvalue1(cb.env);
|
||||
Varargs result = f.invoke(LuaValue.NONE);
|
||||
cb.copyGlobalsToBindings();
|
||||
return result;
|
||||
|
||||
@@ -60,7 +60,7 @@ public class TestLuaJC {
|
||||
} else {
|
||||
chunk = (LuaValue) Class.forName("script").newInstance();
|
||||
}
|
||||
chunk.setfenv(_G);
|
||||
//chunk.setfenv(_G); // TODO: convert to setupvalue()?
|
||||
|
||||
// call with arguments
|
||||
LuaValue[] vargs = new LuaValue[args.length];
|
||||
|
||||
@@ -71,18 +71,18 @@ public class FragmentsTest extends TestSuite {
|
||||
public void runFragment( Varargs expected, String script ) {
|
||||
try {
|
||||
String name = getName();
|
||||
LuaTable _G = org.luaj.vm2.lib.jse.JsePlatform.debugGlobals();
|
||||
org.luaj.vm2.lib.jse.JsePlatform.debugGlobals();
|
||||
InputStream is = new ByteArrayInputStream(script.getBytes("UTF-8"));
|
||||
LuaValue chunk ;
|
||||
switch ( TEST_TYPE ) {
|
||||
case TEST_TYPE_LUA2JAVA:
|
||||
chunk = Lua2Java.instance.load(is,name,_G);
|
||||
chunk = Lua2Java.instance.load(is,name,LuaValue._G);
|
||||
break;
|
||||
case TEST_TYPE_LUAJC:
|
||||
chunk = LuaJC.getInstance().load(is,name,_G);
|
||||
chunk = LuaJC.getInstance().load(is,name,LuaValue._G);
|
||||
break;
|
||||
default:
|
||||
chunk = LuaC.instance.load( is, name, _G );
|
||||
chunk = LuaC.instance.load( is, name, LuaValue._G );
|
||||
Print.print(((LuaClosure)chunk).p);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -55,9 +55,9 @@ 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 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 LuaValue somefunc = new ZeroArgFunction() { public LuaValue call() { return NONE;}};
|
||||
private final LuaThread thread = new LuaThread(somefunc);
|
||||
private final Prototype proto = new Prototype(1);
|
||||
private final LuaClosure someclosure = new LuaClosure(proto,table);
|
||||
private final LuaUserdata userdataobj = LuaValue.userdataOf(sampleobject);
|
||||
private final LuaUserdata userdatacls = LuaValue.userdataOf(sampledata);
|
||||
@@ -127,55 +127,6 @@ public class LuaOperationsTest extends TestCase {
|
||||
throwsLuaError( "length", userdataobj );
|
||||
throwsLuaError( "length", userdatacls );
|
||||
}
|
||||
|
||||
public void testGetfenv() {
|
||||
throwsLuaError( "getfenv", somenil );
|
||||
throwsLuaError( "getfenv", sometrue );
|
||||
throwsLuaError( "getfenv", somefalse );
|
||||
throwsLuaError( "getfenv", zero );
|
||||
throwsLuaError( "getfenv", intint );
|
||||
throwsLuaError( "getfenv", longdouble );
|
||||
throwsLuaError( "getfenv", doubledouble );
|
||||
throwsLuaError( "getfenv", stringstring );
|
||||
throwsLuaError( "getfenv", stringint );
|
||||
throwsLuaError( "getfenv", stringlong );
|
||||
throwsLuaError( "getfenv", stringdouble );
|
||||
throwsLuaError( "getfenv", table );
|
||||
assertTrue( table == thread.getfenv() );
|
||||
assertTrue( table == someclosure.getfenv() );
|
||||
assertTrue( table == somefunc.getfenv() );
|
||||
throwsLuaError( "getfenv", userdataobj );
|
||||
throwsLuaError( "getfenv", userdatacls );
|
||||
}
|
||||
|
||||
public void testSetfenv() {
|
||||
LuaTable table2 = LuaValue.listOf( new LuaValue[] {
|
||||
LuaValue.valueOf("ccc"),
|
||||
LuaValue.valueOf("ddd") } );
|
||||
throwsLuaError( "setfenv", somenil, table2 );
|
||||
throwsLuaError( "setfenv", sometrue, table2 );
|
||||
throwsLuaError( "setfenv", somefalse, table2 );
|
||||
throwsLuaError( "setfenv", zero, table2 );
|
||||
throwsLuaError( "setfenv", intint, table2 );
|
||||
throwsLuaError( "setfenv", longdouble, table2 );
|
||||
throwsLuaError( "setfenv", doubledouble, table2 );
|
||||
throwsLuaError( "setfenv", stringstring, table2 );
|
||||
throwsLuaError( "setfenv", stringint, table2 );
|
||||
throwsLuaError( "setfenv", stringlong, table2 );
|
||||
throwsLuaError( "setfenv", stringdouble, table2 );
|
||||
throwsLuaError( "setfenv", table, table2 );
|
||||
thread.setfenv(table2);
|
||||
assertTrue( table2 == thread.getfenv() );
|
||||
assertTrue( table == someclosure.getfenv() );
|
||||
assertTrue( table == somefunc.getfenv() );
|
||||
someclosure.setfenv(table2);
|
||||
assertTrue( table2 == someclosure.getfenv() );
|
||||
assertTrue( table == somefunc.getfenv() );
|
||||
somefunc.setfenv(table2);
|
||||
assertTrue( table2 == somefunc.getfenv() );
|
||||
throwsLuaError( "setfenv", userdataobj, table2 );
|
||||
throwsLuaError( "setfenv", userdatacls, table2 );
|
||||
}
|
||||
|
||||
public Prototype createPrototype( String script, String name ) {
|
||||
try {
|
||||
@@ -206,56 +157,20 @@ public class LuaOperationsTest extends TestCase {
|
||||
|
||||
// function tests
|
||||
{
|
||||
LuaFunction f = new ZeroArgFunction(_G) { public LuaValue call() { return env.get("a");}};
|
||||
LuaFunction f = new ZeroArgFunction() { public LuaValue call() { return _G.get("a");}};
|
||||
assertEquals( aaa, f.call() );
|
||||
f.setfenv(newenv);
|
||||
assertEquals( newenv, f.getfenv() );
|
||||
assertEquals( eee, f.call() );
|
||||
}
|
||||
|
||||
// closure tests
|
||||
{
|
||||
Prototype p = createPrototype( "return a\n", "closuretester" );
|
||||
LuaClosure c = new LuaClosure(p, _G);
|
||||
|
||||
// Test that a clusure with a custom enviroment uses that environment.
|
||||
assertEquals( aaa, c.call() );
|
||||
c.setfenv(newenv);
|
||||
assertEquals( newenv, c.getfenv() );
|
||||
c = new LuaClosure(p, newenv);
|
||||
assertEquals( newenv, c.upValues[0].getValue() );
|
||||
assertEquals( eee, c.call() );
|
||||
}
|
||||
|
||||
// thread tests, functions created in threads inherit the thread's environment initially
|
||||
// those closures created not in any other function get the thread's enviroment
|
||||
Prototype p2 = createPrototype( "return loadstring('return a')", "threadtester" );
|
||||
{
|
||||
LuaThread t = new LuaThread(new LuaClosure(p2,_G), _G);
|
||||
Varargs v = t.resume(LuaValue.NONE);
|
||||
assertEquals(LuaValue.TRUE, v.arg(1) );
|
||||
LuaValue f = v.arg(2);
|
||||
assertEquals( LuaValue.TFUNCTION, f.type() );
|
||||
assertEquals( aaa, f.call() );
|
||||
assertEquals( _G, f.getfenv() );
|
||||
}
|
||||
{
|
||||
// change the thread environment after creation!
|
||||
LuaThread t = new LuaThread(new LuaClosure(p2,_G), _G);
|
||||
t.setfenv(newenv);
|
||||
Varargs v = t.resume(LuaValue.NONE);
|
||||
assertEquals(LuaValue.TRUE, v.arg(1) );
|
||||
LuaValue f = v.arg(2);
|
||||
assertEquals( LuaValue.TFUNCTION, f.type() );
|
||||
assertEquals( eee, f.call() );
|
||||
assertEquals( newenv, f.getfenv() );
|
||||
}
|
||||
{
|
||||
// let the closure have a different environment from the thread
|
||||
Prototype p3 = createPrototype( "return function() return a end", "envtester" );
|
||||
LuaThread t = new LuaThread(new LuaClosure(p3,newenv), _G);
|
||||
Varargs v = t.resume(LuaValue.NONE);
|
||||
assertEquals(LuaValue.TRUE, v.arg(1) );
|
||||
LuaValue f = v.arg(2);
|
||||
assertEquals( LuaValue.TFUNCTION, f.type() );
|
||||
assertEquals( eee, f.call() );
|
||||
assertEquals( newenv, f.getfenv() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +38,8 @@ public class MetatableTest extends TestCase {
|
||||
private final LuaValue string = LuaValue.valueOf(samplestring);
|
||||
private final LuaTable table = LuaValue.tableOf();
|
||||
private final LuaFunction function = new ZeroArgFunction() { public LuaValue call() { return NONE;}};
|
||||
private final LuaThread thread = new LuaThread(function,table);
|
||||
private final LuaClosure closure = new LuaClosure();
|
||||
private final LuaThread thread = new LuaThread(function);
|
||||
private final LuaClosure closure = new LuaClosure(new Prototype());
|
||||
private final LuaUserdata userdata = LuaValue.userdataOf(sampleobject);
|
||||
private final LuaUserdata userdatamt = LuaValue.userdataOf(sampledata,table);
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ public class OrphanedThreadTest extends TestCase {
|
||||
}
|
||||
|
||||
private void doTest(LuaValue status2, LuaValue value2) throws Exception {
|
||||
luathread = new LuaThread(function, env);
|
||||
luathread = new LuaThread(function);
|
||||
luathr_ref = new WeakReference(luathread);
|
||||
func_ref = new WeakReference(function);
|
||||
assertNotNull(luathr_ref.get());
|
||||
|
||||
@@ -119,7 +119,6 @@ public class ScriptDrivenTest extends TestCase {
|
||||
case LUAJIT:
|
||||
if ( nocompile ) {
|
||||
LuaValue c = (LuaValue) Class.forName(name).newInstance();
|
||||
c.setfenv(_G);
|
||||
return c;
|
||||
} else {
|
||||
script = new FileInputStream(file);
|
||||
|
||||
@@ -26,8 +26,12 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.luaj.vm2.lib.ZeroArgFunction;
|
||||
import org.luaj.vm2.lib.jse.JsePlatform;
|
||||
|
||||
public class TypeTest extends TestCase {
|
||||
static {
|
||||
JsePlatform.debugGlobals();
|
||||
}
|
||||
|
||||
private final int sampleint = 77;
|
||||
private final long samplelong = 123400000000L;
|
||||
@@ -52,8 +56,8 @@ public class TypeTest extends TestCase {
|
||||
private final LuaValue stringdouble = LuaValue.valueOf(samplestringdouble);
|
||||
private final LuaTable table = LuaValue.tableOf();
|
||||
private final LuaFunction somefunc = new ZeroArgFunction() { public LuaValue call() { return NONE;}};
|
||||
private final LuaThread thread = new LuaThread(somefunc,table);
|
||||
private final LuaClosure someclosure = new LuaClosure();
|
||||
private final LuaThread thread = new LuaThread(somefunc);
|
||||
private final LuaClosure someclosure = new LuaClosure(new Prototype());
|
||||
private final LuaUserdata userdataobj = LuaValue.userdataOf(sampleobject);
|
||||
private final LuaUserdata userdatacls = LuaValue.userdataOf(sampledata);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user