Add Compilable interface to LuaScriptEngine and implement it

This commit is contained in:
James Roseborough
2008-06-14 21:17:27 +00:00
parent 59b75d5ce0
commit 76ef91a779

View File

@@ -21,13 +21,19 @@
******************************************************************************/ ******************************************************************************/
package org.luaj.script; package org.luaj.script;
import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.LineNumberInputStream; import java.io.LineNumberInputStream;
import java.io.Reader; import java.io.Reader;
import java.io.StringWriter; import java.io.StringReader;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.script.Bindings; import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptContext; import javax.script.ScriptContext;
import javax.script.ScriptEngine; import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory; import javax.script.ScriptEngineFactory;
@@ -41,6 +47,7 @@ import org.luaj.vm.LClosure;
import org.luaj.vm.LDouble; import org.luaj.vm.LDouble;
import org.luaj.vm.LFunction; import org.luaj.vm.LFunction;
import org.luaj.vm.LInteger; import org.luaj.vm.LInteger;
import org.luaj.vm.LNil;
import org.luaj.vm.LPrototype; import org.luaj.vm.LPrototype;
import org.luaj.vm.LString; import org.luaj.vm.LString;
import org.luaj.vm.LTable; import org.luaj.vm.LTable;
@@ -53,12 +60,12 @@ import org.luaj.vm.LuaState;
import org.luaj.vm.Platform; import org.luaj.vm.Platform;
/** /**
* *
* @author jim_roseborough * @author jim_roseborough
*/ */
public class LuaScriptEngine extends LFunction implements ScriptEngine { public class LuaScriptEngine extends LFunction implements ScriptEngine, Compilable {
private static final String __ENGINE_VERSION__ = "V0.28"; private static final String __ENGINE_VERSION__ = "V0.39";
private static final String __NAME__ = "Luaj"; private static final String __NAME__ = "Luaj";
private static final String __SHORT_NAME__ = "Luaj"; private static final String __SHORT_NAME__ = "Luaj";
private static final String __LANGUAGE__ = "lua"; private static final String __LANGUAGE__ = "lua";
@@ -78,7 +85,10 @@ public class LuaScriptEngine extends LFunction implements ScriptEngine {
private final LuaState luaState; private final LuaState luaState;
public LuaScriptEngine() { public LuaScriptEngine() {
// set up context
setContext(new SimpleScriptContext()); setContext(new SimpleScriptContext());
// set special values // set special values
put(LANGUAGE_VERSION, __LANGUAGE_VERSION__); put(LANGUAGE_VERSION, __LANGUAGE_VERSION__);
put(LANGUAGE, __LANGUAGE__); put(LANGUAGE, __LANGUAGE__);
@@ -89,7 +99,7 @@ public class LuaScriptEngine extends LFunction implements ScriptEngine {
put(NAME, __SHORT_NAME__); put(NAME, __SHORT_NAME__);
put("THREADING", null); put("THREADING", null);
// set lua state // create lua state
luaState = Platform.getInstance().newLuaState(); luaState = Platform.getInstance().newLuaState();
// connect up to bindings // connect up to bindings
@@ -101,47 +111,32 @@ public class LuaScriptEngine extends LFunction implements ScriptEngine {
public Object eval(String script) throws ScriptException { public Object eval(String script) throws ScriptException {
return eval(script, getContext()); return eval(new StringReader(script));
} }
public Object eval(String script, ScriptContext context) throws ScriptException { public Object eval(String script, ScriptContext context) throws ScriptException {
try { return eval(new StringReader(script), context);
byte[] bytes = script.getBytes("UTF-8");
ByteArrayInputStream bais = new ByteArrayInputStream( bytes );
LineNumberInputStream is = new LineNumberInputStream( bais );
try {
LPrototype p = LoadState.undump(luaState, is, "script");
LClosure c = p.newClosure( luaState._G );
luaState.doCall( c, new LValue[0] );
return luaState.topointer(1);
} catch ( LuaErrorException lee ) {
throw new ScriptException(lee.getMessage(), "script", is.getLineNumber() );
} finally {
is.close();
}
} catch ( Throwable t ) {
throw new ScriptException("eval threw "+t.toString());
}
} }
public Object eval(String script, Bindings bindings) throws ScriptException { public Object eval(String script, Bindings bindings) throws ScriptException {
Bindings current = getContext().getBindings(ScriptContext.ENGINE_SCOPE); return eval(new StringReader(script), bindings);
getContext().setBindings(bindings, ScriptContext.ENGINE_SCOPE);
Object result = eval(script);
getContext().setBindings(current, ScriptContext.ENGINE_SCOPE);
return result;
} }
public Object eval(Reader reader) throws ScriptException { public Object eval(Reader reader) throws ScriptException {
return eval(getScriptFromReader(reader)); return eval(reader, getContext());
} }
public Object eval(Reader reader, ScriptContext scriptContext) throws ScriptException { public Object eval(Reader reader, ScriptContext scriptContext) throws ScriptException {
return eval(getScriptFromReader(reader), scriptContext); return compile(reader).eval(scriptContext);
} }
public Object eval(Reader reader, Bindings bindings) throws ScriptException { public Object eval(Reader reader, Bindings bindings) throws ScriptException {
return eval(getScriptFromReader(reader), bindings); ScriptContext c = getContext();
Bindings current = c.getBindings(ScriptContext.ENGINE_SCOPE);
c.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
Object result = eval(reader);
c.setBindings(current, ScriptContext.ENGINE_SCOPE);
return result;
} }
public void put(String key, Object value) { public void put(String key, Object value) {
@@ -176,20 +171,20 @@ public class LuaScriptEngine extends LFunction implements ScriptEngine {
return o; return o;
} }
public void luaSetTable(LuaState vm, LValue table, LValue key, LValue val) { public LValue __index(LuaState vm, LValue table, LValue key) {
Bindings b = getBindings(ScriptContext.ENGINE_SCOPE);
String k = key.toJavaString();
Object v = (val.isNil()? null: val);
b.put(k,v);
}
public LValue luaGetTable(LuaState vm, LValue table, LValue key) {
Bindings b = getBindings(ScriptContext.ENGINE_SCOPE); Bindings b = getBindings(ScriptContext.ENGINE_SCOPE);
String k = key.toJavaString(); String k = key.toJavaString();
Object v = b.get(k); Object v = b.get(k);
return (LValue) v; return (LValue) v;
} }
public void __newindex(LuaState vm, LValue table, LValue key, LValue val) {
Bindings b = getBindings(ScriptContext.ENGINE_SCOPE);
String k = key.toJavaString();
Object v = (val.isNil()? null: val);
b.put(k,v);
}
public Bindings getBindings(int scope) { public Bindings getBindings(int scope) {
return getContext().getBindings(scope); return getContext().getBindings(scope);
} }
@@ -214,21 +209,60 @@ public class LuaScriptEngine extends LFunction implements ScriptEngine {
return myFactory; return myFactory;
} }
/* public CompiledScript compile(String script) throws ScriptException {
* private methods return compile(new StringReader(script));
*/ }
private static String getScriptFromReader(Reader reader) { public CompiledScript compile(Reader reader) throws ScriptException {
try { try {
StringWriter script = new StringWriter(); InputStream ris = new Utf8Encoder(reader);
int data; LineNumberInputStream is = new LineNumberInputStream( ris);
while ((data = reader.read()) != -1) { try {
script.write(data); final LPrototype p = LoadState.undump(luaState, is, "script");
} return new CompiledScript() {
script.flush(); public Object eval(ScriptContext context) throws ScriptException {
return script.toString(); LClosure c = p.newClosure( luaState._G );
} catch (IOException ex) { luaState.doCall( c, new LValue[0] );
} return luaState.topointer(1);
return null; }
} public ScriptEngine getEngine() {
return LuaScriptEngine.this;
}
};
} catch ( LuaErrorException lee ) {
throw new ScriptException(lee.getMessage(), "script", is.getLineNumber() );
} finally {
is.close();
}
} catch ( Throwable t ) {
throw new ScriptException("eval threw "+t.toString());
}
}
private final class Utf8Encoder extends InputStream {
private final Reader r;
private final int[] buf = new int[2];
private int n;
private Utf8Encoder(Reader r) {
this.r = r;
}
public int read() throws IOException {
if ( n > 0 )
return buf[--n];
int c = r.read();
if ( c < 0x80 )
return c;
n = 0;
if ( c < 0x800 ) {
buf[n++] = (0x80 | ( c & 0x3f));
return (0xC0 | ((c>>6) & 0x1f));
} else {
buf[n++] = (0x80 | ( c & 0x3f));
buf[n++] = (0x80 | ((c>>6) & 0x3f));
return (0xE0 | ((c>>12) & 0x0f));
}
}
}
} }