Clarify role of bindings in script engine.

This commit is contained in:
James Roseborough
2010-12-04 00:47:30 +00:00
parent 81ad4455dc
commit a07d0f7cb4
2 changed files with 46 additions and 37 deletions

View File

@@ -17,6 +17,11 @@ public class ScriptEngineSample {
ScriptEngineManager sem = new ScriptEngineManager(); ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine e = sem.getEngineByExtension(".lua"); ScriptEngine e = sem.getEngineByExtension(".lua");
ScriptEngineFactory f = e.getFactory(); 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 name: " +f.getEngineName() );
System.out.println( "Engine Version: " +f.getEngineVersion() ); System.out.println( "Engine Version: " +f.getEngineVersion() );
System.out.println( "LanguageName: " +f.getLanguageName() ); 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()+"'"); System.out.println("script threw ScriptException as expected, message is '"+se.getMessage()+"'");
} }
testEngineBindings(e);
testClientBindings(e); testClientBindings(e);
testUserClasses(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 { 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( CompiledScript cs = ((Compilable)e).compile(
"print( 'somejavaint', type(somejavaint), somejavaint )\n" + "print( 'somejavaint', type(somejavaint), somejavaint )\n" +
"print( 'somejavadouble', type(somejavadouble), somejavadouble )\n" + "print( 'somejavadouble', type(somejavadouble), somejavadouble )\n" +
@@ -79,7 +91,6 @@ public class ScriptEngineSample {
"someluatable = { 999, 111 }\n" + "someluatable = { 999, 111 }\n" +
"someluafunction = function(x) print( 'hello, world', x ) return 678 end\n" + "someluafunction = function(x) print( 'hello, world', x ) return 678 end\n" +
"" ); "" );
Bindings b = e.createBindings();
b.put("somejavaint", 111); b.put("somejavaint", 111);
b.put("somejavadouble", 222.333); b.put("somejavadouble", 222.333);
b.put("somejavastring", "abc"); b.put("somejavastring", "abc");

View File

@@ -164,40 +164,23 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
try { try {
final LuaFunction f = LoadState.load(ris, "script", null); final LuaFunction f = LoadState.load(ris, "script", null);
if ( f.isclosure() ) { if ( f.isclosure() ) {
LuaClosure c = f.checkclosure(); // most compiled functions are closures with prototypes
final Prototype p = c.p; final Prototype p = f.checkclosure().p;
return new CompiledScript() { return new CompiledScriptImpl() {
public Object eval(ScriptContext context) throws ScriptException { protected LuaFunction newFunctionInstance() {
Bindings b = context.getBindings(ScriptContext.ENGINE_SCOPE); return new LuaClosure( p, null );
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;
} }
}; };
} else { } else {
// when luajc is used, functions are java class instances
final Class c = f.getClass(); final Class c = f.getClass();
return new CompiledScript() { return new CompiledScriptImpl() {
public Object eval(ScriptContext context) throws ScriptException { protected LuaFunction newFunctionInstance() throws ScriptException {
Bindings b = context.getBindings(ScriptContext.ENGINE_SCOPE);
BindingsEnv env = new BindingsEnv(b);
LuaFunction lf;
try { try {
lf = (LuaFunction) c.newInstance(); return (LuaFunction) c.newInstance();
} catch (Exception e) { } catch (Exception e) {
throw new ScriptException("instantiation failed: "+e.toString()); 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 { abstract protected class CompiledScriptImpl extends CompiledScript {
public class BindingsEnv { 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 Bindings b;
public final LuaTable t; public final LuaTable env;
public BindingsEnv( Bindings b ) { public ClientBindings( Bindings b ) {
this.b = b; this.b = b;
this.t = new LuaTable(); this.env = new LuaTable();
t.setmetatable(LuaTable.tableOf(new LuaValue[] { LuaValue.INDEX, _G })); env.setmetatable(LuaTable.tableOf(new LuaValue[] { LuaValue.INDEX, _G }));
this.copyBindingsToGlobals(); this.copyBindingsToGlobals();
} }
public void copyBindingsToGlobals() { public void copyBindingsToGlobals() {
@@ -227,7 +225,7 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
Object val = b.get(key); Object val = b.get(key);
LuaValue luakey = toLua(key); LuaValue luakey = toLua(key);
LuaValue luaval = toLua(val); LuaValue luaval = toLua(val);
t.set(luakey, luaval); env.set(luakey, luaval);
i.remove(); i.remove();
} }
} }
@@ -237,10 +235,10 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
CoerceJavaToLua.coerce(javaValue); CoerceJavaToLua.coerce(javaValue);
} }
public void copyGlobalsToBindings() { public void copyGlobalsToBindings() {
LuaValue[] keys = t.keys(); LuaValue[] keys = env.keys();
for ( int i=0; i<keys.length; i++ ) { for ( int i=0; i<keys.length; i++ ) {
LuaValue luakey = keys[i]; LuaValue luakey = keys[i];
LuaValue luaval = t.get(luakey); LuaValue luaval = env.get(luakey);
String key = luakey.tojstring(); String key = luakey.tojstring();
Object val = toJava( luaval ); Object val = toJava( luaval );
b.put(key,val); b.put(key,val);