Improve JSR-223 bindings especially for values that are not primitives.

This commit is contained in:
James Roseborough
2010-12-03 01:37:47 +00:00
parent 7a24e6148a
commit 31f6ffde88
4 changed files with 83 additions and 76 deletions

View File

@@ -25,6 +25,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.util.Iterator;
import javax.script.Bindings;
import javax.script.Compilable;
@@ -44,8 +45,7 @@ import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.lib.ThreeArgFunction;
import org.luaj.vm2.lib.TwoArgFunction;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.lib.jse.JsePlatform;
/**
@@ -168,9 +168,11 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
return new CompiledScript() {
public Object eval(ScriptContext context) throws ScriptException {
Bindings b = context.getBindings(ScriptContext.ENGINE_SCOPE);
LuaValue env = newBindingsBackedEnv(b);
LuaClosure c = new LuaClosure( p, env );
return c.invoke(LuaValue.NONE);
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;
@@ -181,15 +183,17 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
return new CompiledScript() {
public Object eval(ScriptContext context) throws ScriptException {
Bindings b = context.getBindings(ScriptContext.ENGINE_SCOPE);
LuaValue env = newBindingsBackedEnv(b);
BindingsEnv env = new BindingsEnv(b);
LuaFunction lf;
try {
lf = (LuaFunction) c.newInstance();
} catch (Exception e) {
throw new ScriptException("instantiation failed: "+e.toString());
}
lf.setfenv(env);
return lf.invoke(LuaValue.NONE);
lf.setfenv(env.t);
Varargs result = lf.invoke(LuaValue.NONE);
env.copyGlobalsToBindings();
return result;
}
public ScriptEngine getEngine() {
return LuaScriptEngine.this;
@@ -207,58 +211,25 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
}
// ------ lua bindings ----- private static final class BindingsBackedEnv extends LuaTable {
public LuaTable newBindingsBackedEnv(Bindings b) {
LuaTable t = new LuaTable();
LuaTable mt = new LuaTable(0,2);
mt.set(LuaValue.INDEX, new BindindsIndexFunction(b));
mt.set(LuaValue.NEWINDEX, new BindingsNewindexFunction(b));
t.setmetatable(mt);
return t;
}
private static final class BindingsNewindexFunction extends ThreeArgFunction {
private final Bindings b;
private BindingsNewindexFunction(Bindings b) {
public class BindingsEnv {
public final Bindings b;
public final LuaTable t;
public BindingsEnv( Bindings b ) {
this.b = b;
this.t = new LuaTable();
t.setmetatable(LuaTable.tableOf(new LuaValue[] { LuaValue.INDEX, _G }));
this.copyBindingsToGlobals();
}
public LuaValue call(LuaValue tbl, LuaValue key, LuaValue val) {
String k = key.tojstring();
if ( val.isnil() )
b.remove(k);
else
b.put(k, toJava(val));
return NIL;
}
private Object toJava(LuaValue v) {
switch ( v.type() ) {
case LuaValue.TNIL: return null;
case LuaValue.TSTRING: return v.tojstring();
case LuaValue.TUSERDATA: return v.checkuserdata(Object.class);
case LuaValue.TNUMBER: return v.isinttype()? (Object) new Integer(v.toint()): (Object) new Double(v.todouble());
default:
throw new java.lang.UnsupportedOperationException(
"LuaBindings cannot convert lua type '"+v.typename()+"' to Java");
public void copyBindingsToGlobals() {
for ( Iterator<String> i = b.keySet().iterator(); i.hasNext(); ) {
String key = i.next();
Object val = b.get(key);
LuaValue luakey = toLua(key);
LuaValue luaval = toLua(val);
t.set(luakey, luaval);
i.remove();
}
}
}
private final class BindindsIndexFunction extends TwoArgFunction {
private final Bindings b;
private BindindsIndexFunction(Bindings b) {
this.b = b;
}
public LuaValue call(LuaValue tbl, LuaValue key) {
String k = key.tojstring();
if ( b.containsKey(k) )
return toLua(b.get(k));
return _G.get(key);
}
private LuaValue toLua(Object javaValue) {
if ( javaValue instanceof Number ) {
return LuaValue.valueOf(((Number)javaValue).doubleValue());
@@ -266,10 +237,31 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
return LuaValue.valueOf(javaValue.toString());
} else if ( javaValue == null ) {
return LuaValue.NIL;
} else if ( javaValue instanceof LuaValue ) {
return (LuaValue) javaValue;
} else {
return LuaValue.userdataOf(javaValue);
}
}
public void copyGlobalsToBindings() {
LuaValue[] keys = t.keys();
for ( int i=0; i<keys.length; i++ ) {
LuaValue luakey = keys[i];
LuaValue luaval = t.get(luakey);
String key = luakey.tojstring();
Object val = toJava( luaval );
b.put(key,val);
}
}
private Object toJava(LuaValue v) {
switch ( v.type() ) {
case LuaValue.TNIL: return null;
case LuaValue.TSTRING: return v.tojstring();
case LuaValue.TUSERDATA: return v.checkuserdata(Object.class);
case LuaValue.TNUMBER: return v.isinttype()? (Object) new Integer(v.toint()): (Object) new Double(v.todouble());
default: return v;
}
}
}
// ------ convert char stream to byte stream for lua compiler -----