From a07d0f7cb4a025dcfd7e0418615205f8673b11b3 Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Sat, 4 Dec 2010 00:47:30 +0000 Subject: [PATCH] Clarify role of bindings in script engine. --- examples/jse/ScriptEngineSample.java | 13 +++- .../org/luaj/vm2/script/LuaScriptEngine.java | 70 +++++++++---------- 2 files changed, 46 insertions(+), 37 deletions(-) diff --git a/examples/jse/ScriptEngineSample.java b/examples/jse/ScriptEngineSample.java index a1fc0793..d3a9d399 100644 --- a/examples/jse/ScriptEngineSample.java +++ b/examples/jse/ScriptEngineSample.java @@ -17,6 +17,11 @@ public class ScriptEngineSample { ScriptEngineManager sem = new ScriptEngineManager(); ScriptEngine e = sem.getEngineByExtension(".lua"); ScriptEngineFactory f = e.getFactory(); + + // uncomment to enable the lua-to-java bytecode compiler + // (require bcel library in class path) + // org.luaj.vm2.luajc.LuaJC.install(); + System.out.println( "Engine name: " +f.getEngineName() ); System.out.println( "Engine Version: " +f.getEngineVersion() ); System.out.println( "LanguageName: " +f.getLanguageName() ); @@ -51,6 +56,7 @@ public class ScriptEngineSample { System.out.println("script threw ScriptException as expected, message is '"+se.getMessage()+"'"); } + testEngineBindings(e); testClientBindings(e); testUserClasses(e); @@ -65,7 +71,13 @@ public class ScriptEngineSample { } } + public static void testEngineBindings(ScriptEngine e) throws ScriptException { + testBindings(e, e.createBindings()); + } public static void testClientBindings(ScriptEngine e) throws ScriptException { + testBindings(e, new SimpleBindings()); + } + public static void testBindings(ScriptEngine e, Bindings b) throws ScriptException { CompiledScript cs = ((Compilable)e).compile( "print( 'somejavaint', type(somejavaint), somejavaint )\n" + "print( 'somejavadouble', type(somejavadouble), somejavadouble )\n" + @@ -79,7 +91,6 @@ public class ScriptEngineSample { "someluatable = { 999, 111 }\n" + "someluafunction = function(x) print( 'hello, world', x ) return 678 end\n" + "" ); - Bindings b = e.createBindings(); b.put("somejavaint", 111); b.put("somejavadouble", 222.333); b.put("somejavastring", "abc"); diff --git a/src/jse/org/luaj/vm2/script/LuaScriptEngine.java b/src/jse/org/luaj/vm2/script/LuaScriptEngine.java index 3ccd1cfb..fc7fd546 100644 --- a/src/jse/org/luaj/vm2/script/LuaScriptEngine.java +++ b/src/jse/org/luaj/vm2/script/LuaScriptEngine.java @@ -157,47 +157,30 @@ public class LuaScriptEngine implements ScriptEngine, Compilable { public CompiledScript compile(String script) throws ScriptException { return compile(new StringReader(script)); } - + public CompiledScript compile(Reader reader) throws ScriptException { try { InputStream ris = new Utf8Encoder(reader); try { final LuaFunction f = LoadState.load(ris, "script", null); if ( f.isclosure() ) { - LuaClosure c = f.checkclosure(); - final Prototype p = c.p; - return new CompiledScript() { - public Object eval(ScriptContext context) throws ScriptException { - Bindings b = context.getBindings(ScriptContext.ENGINE_SCOPE); - BindingsEnv env = new BindingsEnv(b); - LuaClosure c = new LuaClosure( p, env.t ); - Varargs result = c.invoke(LuaValue.NONE); - env.copyGlobalsToBindings(); - return result; - } - public ScriptEngine getEngine() { - return LuaScriptEngine.this; + // most compiled functions are closures with prototypes + final Prototype p = f.checkclosure().p; + return new CompiledScriptImpl() { + protected LuaFunction newFunctionInstance() { + return new LuaClosure( p, null ); } }; } else { + // when luajc is used, functions are java class instances final Class c = f.getClass(); - return new CompiledScript() { - public Object eval(ScriptContext context) throws ScriptException { - Bindings b = context.getBindings(ScriptContext.ENGINE_SCOPE); - BindingsEnv env = new BindingsEnv(b); - LuaFunction lf; + return new CompiledScriptImpl() { + protected LuaFunction newFunctionInstance() throws ScriptException { try { - lf = (LuaFunction) c.newInstance(); + return (LuaFunction) c.newInstance(); } catch (Exception e) { throw new ScriptException("instantiation failed: "+e.toString()); } - lf.setfenv(env.t); - Varargs result = lf.invoke(LuaValue.NONE); - env.copyGlobalsToBindings(); - return result; - } - public ScriptEngine getEngine() { - return LuaScriptEngine.this; } }; } @@ -211,14 +194,29 @@ public class LuaScriptEngine implements ScriptEngine, Compilable { } } - // ------ lua bindings ----- private static final class BindingsBackedEnv extends LuaTable { - public class BindingsEnv { + abstract protected class CompiledScriptImpl extends CompiledScript { + abstract protected LuaFunction newFunctionInstance() throws ScriptException; + public ScriptEngine getEngine() { + return LuaScriptEngine.this; + } + public Object eval(ScriptContext context) throws ScriptException { + Bindings b = context.getBindings(ScriptContext.ENGINE_SCOPE); + LuaFunction f = newFunctionInstance(); + ClientBindings cb = new ClientBindings(b); + f.setfenv(cb.env); + Varargs result = f.invoke(LuaValue.NONE); + cb.copyGlobalsToBindings(); + return result; + } + } + + public class ClientBindings { public final Bindings b; - public final LuaTable t; - public BindingsEnv( Bindings b ) { + public final LuaTable env; + public ClientBindings( Bindings b ) { this.b = b; - this.t = new LuaTable(); - t.setmetatable(LuaTable.tableOf(new LuaValue[] { LuaValue.INDEX, _G })); + this.env = new LuaTable(); + env.setmetatable(LuaTable.tableOf(new LuaValue[] { LuaValue.INDEX, _G })); this.copyBindingsToGlobals(); } public void copyBindingsToGlobals() { @@ -227,7 +225,7 @@ public class LuaScriptEngine implements ScriptEngine, Compilable { Object val = b.get(key); LuaValue luakey = toLua(key); LuaValue luaval = toLua(val); - t.set(luakey, luaval); + env.set(luakey, luaval); i.remove(); } } @@ -237,10 +235,10 @@ public class LuaScriptEngine implements ScriptEngine, Compilable { CoerceJavaToLua.coerce(javaValue); } public void copyGlobalsToBindings() { - LuaValue[] keys = t.keys(); + LuaValue[] keys = env.keys(); for ( int i=0; i