From 00f8d291f92548f146a3a2d1926939f5c7e57197 Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Sat, 17 Apr 2010 13:15:16 +0000 Subject: [PATCH] Fix setfenv(), getfenv(), let threads inherit environment. --- src/core/org/luaj/vm2/LuaThread.java | 24 ++++++++--- src/core/org/luaj/vm2/lib/BaseLib.java | 44 +++++++++++---------- src/core/org/luaj/vm2/lib/CoroutineLib.java | 2 +- src/core/org/luaj/vm2/lib/PackageLib.java | 4 +- src/jme/org/luaj/vm2/lib/JmePlatform.java | 2 + src/jse/org/luaj/vm2/lib/JsePlatform.java | 2 + 6 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/core/org/luaj/vm2/LuaThread.java b/src/core/org/luaj/vm2/LuaThread.java index 05d1477d..dbcf67bc 100644 --- a/src/core/org/luaj/vm2/LuaThread.java +++ b/src/core/org/luaj/vm2/LuaThread.java @@ -115,10 +115,16 @@ public class LuaThread extends LuaValue implements Runnable { public static boolean isMainThread(LuaThread r) { 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 && level0 && level<=running_thread.calls? + running_thread.callstack[running_thread.calls-level]: null; } @@ -222,4 +233,5 @@ public class LuaThread extends LuaValue implements Runnable { } + } diff --git a/src/core/org/luaj/vm2/lib/BaseLib.java b/src/core/org/luaj/vm2/lib/BaseLib.java index d4ed4716..37936b95 100644 --- a/src/core/org/luaj/vm2/lib/BaseLib.java +++ b/src/core/org/luaj/vm2/lib/BaseLib.java @@ -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 @@ -148,7 +144,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder { } return NIL; } - + protected LuaValue oncall2(int opcode, LuaValue arg1, LuaValue arg2) { switch ( opcode ) { case 0: // "collectgarbage", // ( opt [,arg] ) -> value @@ -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); @@ -195,6 +186,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 ) { @@ -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(); } diff --git a/src/core/org/luaj/vm2/lib/CoroutineLib.java b/src/core/org/luaj/vm2/lib/CoroutineLib.java index 96b52875..e757538c 100644 --- a/src/core/org/luaj/vm2/lib/CoroutineLib.java +++ b/src/core/org/luaj/vm2/lib/CoroutineLib.java @@ -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); diff --git a/src/core/org/luaj/vm2/lib/PackageLib.java b/src/core/org/luaj/vm2/lib/PackageLib.java index efb8d0dc..0ee1e705 100644 --- a/src/core/org/luaj/vm2/lib/PackageLib.java +++ b/src/core/org/luaj/vm2/lib/PackageLib.java @@ -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; } } diff --git a/src/jme/org/luaj/vm2/lib/JmePlatform.java b/src/jme/org/luaj/vm2/lib/JmePlatform.java index a4e2ee97..e43ce7f1 100644 --- a/src/jme/org/luaj/vm2/lib/JmePlatform.java +++ b/src/jme/org/luaj/vm2/lib/JmePlatform.java @@ -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; } diff --git a/src/jse/org/luaj/vm2/lib/JsePlatform.java b/src/jse/org/luaj/vm2/lib/JsePlatform.java index 6e1930bb..fba07241 100644 --- a/src/jse/org/luaj/vm2/lib/JsePlatform.java +++ b/src/jse/org/luaj/vm2/lib/JsePlatform.java @@ -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; } }