Fix setfenv(), getfenv(), let threads inherit environment.
This commit is contained in:
@@ -116,9 +116,15 @@ public class LuaThread extends LuaValue implements Runnable {
|
||||
return r == mainthread;
|
||||
}
|
||||
|
||||
/** get environment of the running thread, or defval if not defined */
|
||||
public static LuaValue getRunningEnv(LuaValue defval) {
|
||||
return running_thread.env!=null? running_thread.env: defval;
|
||||
/** Set the globals of the current thread */
|
||||
public static void setGlobals(LuaValue globals) {
|
||||
running_thread.env = globals;
|
||||
}
|
||||
|
||||
/** Get the current thread's environment */
|
||||
public static LuaValue getGlobals() {
|
||||
LuaValue e = running_thread.env;
|
||||
return e!=null? e: LuaValue.error("LuaThread.setGlobals() not initialized");
|
||||
}
|
||||
|
||||
public static final void onCall(LuaFunction function) {
|
||||
@@ -137,9 +143,14 @@ public class LuaThread extends LuaValue implements Runnable {
|
||||
return running_thread.calls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the function called as a specific location on the stack.
|
||||
* @param level 1 for the function calling this one, 2 for the next one.
|
||||
* @return LuaFunction on the call stack, or null if outside of range of active stack
|
||||
*/
|
||||
public static final LuaFunction getCallstackFunction(int level) {
|
||||
return level>=0 && level<running_thread.calls?
|
||||
running_thread.callstack[running_thread.calls-level-1]:
|
||||
return level>0 && level<=running_thread.calls?
|
||||
running_thread.callstack[running_thread.calls-level]:
|
||||
null;
|
||||
}
|
||||
|
||||
@@ -222,4 +233,5 @@ public class LuaThread extends LuaValue implements Runnable {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.io.PrintStream;
|
||||
|
||||
import org.luaj.vm2.LoadState;
|
||||
import org.luaj.vm2.LuaError;
|
||||
import org.luaj.vm2.LuaFunction;
|
||||
import org.luaj.vm2.LuaString;
|
||||
import org.luaj.vm2.LuaTable;
|
||||
import org.luaj.vm2.LuaThread;
|
||||
@@ -131,13 +132,8 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
||||
protected LuaValue oncall1(int opcode, LuaValue arg) {
|
||||
switch ( opcode ) {
|
||||
case 0: { // "getfenv", // ( [f] ) -> env
|
||||
if ( ! arg.isfunction() ) {
|
||||
int i = arg.optint(0);
|
||||
arg = (i==0)? (LuaValue) LuaThread.getRunning(): (LuaValue) LuaThread.getCallstackFunction(i-1);
|
||||
if ( arg == null )
|
||||
LuaValue.argerror(1, "invalid level");
|
||||
}
|
||||
LuaValue e = arg.getfenv();
|
||||
LuaValue f = getfenvobj(arg);
|
||||
LuaValue e = f.getfenv();
|
||||
return e!=null? e: NIL;
|
||||
}
|
||||
case 1: // "getmetatable", // ( object ) -> table
|
||||
@@ -172,15 +168,10 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
||||
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(0);
|
||||
f = (i==0)? (LuaValue) LuaThread.getRunning(): (LuaValue) LuaThread.getCallstackFunction(i-1);
|
||||
if ( f == null )
|
||||
LuaValue.argerror(1, "invalid level");
|
||||
}
|
||||
f.setfenv(arg2);
|
||||
return f;
|
||||
LuaTable t = arg2.checktable();
|
||||
LuaValue f = getfenvobj(arg1);
|
||||
f.setfenv(t);
|
||||
return f.isthread()? NONE: f;
|
||||
}
|
||||
case 4: // "tonumber", // (e [,base]) -> value
|
||||
final int base = arg2.optint(10);
|
||||
@@ -196,6 +187,17 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
||||
return NIL;
|
||||
}
|
||||
|
||||
private LuaValue getfenvobj(LuaValue arg) {
|
||||
if ( arg.isclosure() )
|
||||
return arg;
|
||||
int level = arg.optint(1);
|
||||
if ( level == 0 )
|
||||
return LuaThread.getRunning();
|
||||
LuaValue f = LuaThread.getCallstackFunction(level);
|
||||
arg.argcheck(f != null, 1, "invalid level");
|
||||
return f;
|
||||
}
|
||||
|
||||
protected Varargs oncallv(int opcode, Varargs args) {
|
||||
switch ( opcode ) {
|
||||
case 0: // "assert", // ( v [,message] ) -> v, message | ERR
|
||||
@@ -216,7 +218,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
||||
try {
|
||||
LuaValue func = args.checkfunction(1);
|
||||
String chunkname = args.optString(2, "function");
|
||||
return LoadState.load(new StringInputStream(func), chunkname, LuaThread.getRunningEnv(env));
|
||||
return LoadState.load(new StringInputStream(func), chunkname, LuaThread.getGlobals());
|
||||
} catch ( Exception e ) {
|
||||
return varargsOf(NIL, valueOf(e.getMessage()));
|
||||
}
|
||||
@@ -233,7 +235,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
||||
try {
|
||||
LuaString script = args.checkstring(1);
|
||||
String chunkname = args.optString(2, "string");
|
||||
return LoadState.load(script.toInputStream(),chunkname,LuaThread.getRunningEnv(env));
|
||||
return LoadState.load(script.toInputStream(),chunkname,LuaThread.getGlobals());
|
||||
} catch ( Exception e ) {
|
||||
return varargsOf(NIL, valueOf(e.getMessage()));
|
||||
}
|
||||
@@ -279,7 +281,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
||||
}
|
||||
case 7: // "print", // (...) -> void
|
||||
{
|
||||
LuaValue tostring = env.get("tostring");
|
||||
LuaValue tostring = LuaThread.getGlobals().get("tostring");
|
||||
for ( int i=1, n=args.narg(); i<=n; i++ ) {
|
||||
if ( i>1 ) STDOUT.write( '\t' );
|
||||
LuaString s = tostring.call( args.arg(i) ).strvalue();
|
||||
@@ -347,7 +349,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
||||
if ( is == null )
|
||||
return varargsOf(NIL, valueOf("not found: "+filename));
|
||||
try {
|
||||
return LoadState.load(is, filename, LuaThread.getRunningEnv(env));
|
||||
return LoadState.load(is, filename, LuaThread.getGlobals());
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class CoroutineLib extends ZeroArgFunction {
|
||||
switch ( opcode ) {
|
||||
case CREATE: {
|
||||
final LuaValue func = args.checkfunction(1);
|
||||
return new LuaThread(func, func.getfenv() );
|
||||
return new LuaThread(func, LuaThread.getGlobals() );
|
||||
}
|
||||
case RESUME: {
|
||||
final LuaThread t = args.checkthread(1);
|
||||
|
||||
@@ -25,9 +25,9 @@ import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import org.luaj.vm2.LuaFunction;
|
||||
import org.luaj.vm2.LuaThread;
|
||||
import org.luaj.vm2.LuaString;
|
||||
import org.luaj.vm2.LuaTable;
|
||||
import org.luaj.vm2.LuaThread;
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.Varargs;
|
||||
|
||||
@@ -91,7 +91,7 @@ public class PackageLib extends OneArgFunction {
|
||||
LuaValue m = t.getmetatable();
|
||||
if ( m == null )
|
||||
t.setmetatable(m=tableOf());
|
||||
m.set( INDEX, env );
|
||||
m.set( INDEX, LuaThread.getGlobals() );
|
||||
return NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
package org.luaj.vm2.lib;
|
||||
|
||||
import org.luaj.vm2.LuaTable;
|
||||
import org.luaj.vm2.LuaThread;
|
||||
import org.luaj.vm2.lib.jme.JmeIoLib;
|
||||
|
||||
public class JmePlatform {
|
||||
@@ -41,6 +42,7 @@ public class JmePlatform {
|
||||
_G.load(new StringLib());
|
||||
_G.load(new CoroutineLib());
|
||||
_G.load(new JmeIoLib());
|
||||
LuaThread.setGlobals(_G);
|
||||
return _G;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
package org.luaj.vm2.lib;
|
||||
|
||||
import org.luaj.vm2.LuaTable;
|
||||
import org.luaj.vm2.LuaThread;
|
||||
import org.luaj.vm2.lib.jse.JseBaseLib;
|
||||
import org.luaj.vm2.lib.jse.JseIoLib;
|
||||
import org.luaj.vm2.lib.jse.JseMathLib;
|
||||
@@ -47,6 +48,7 @@ public class JsePlatform {
|
||||
_G.load(new JseIoLib());
|
||||
_G.load(new JseOsLib());
|
||||
_G.load(new LuajavaLib());
|
||||
LuaThread.setGlobals(_G);
|
||||
return _G;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user