Improve compatibility with lua 5.2.

This commit is contained in:
James Roseborough
2012-09-21 05:24:58 +00:00
parent 9666f40ad7
commit be4a320bf9
7 changed files with 154 additions and 117 deletions

View File

@@ -53,7 +53,6 @@ import org.apache.bcel.generic.Type;
import org.luaj.vm2.Buffer;
import org.luaj.vm2.Lua;
import org.luaj.vm2.LuaBoolean;
import org.luaj.vm2.LuaDouble;
import org.luaj.vm2.LuaInteger;
import org.luaj.vm2.LuaNumber;
import org.luaj.vm2.LuaString;
@@ -73,7 +72,6 @@ public class JavaBuilder {
private static final String STR_LUAVALUE = LuaValue.class.getName();
private static final String STR_LUASTRING = LuaString.class.getName();
private static final String STR_LUAINTEGER = LuaInteger.class.getName();
private static final String STR_LUADOUBLE = LuaDouble.class.getName();
private static final String STR_LUANUMBER = LuaNumber.class.getName();
private static final String STR_LUABOOLEAN = LuaBoolean.class.getName();
private static final String STR_LUATABLE = LuaTable.class.getName();
@@ -84,7 +82,6 @@ public class JavaBuilder {
private static final ObjectType TYPE_LUAVALUE = new ObjectType(STR_LUAVALUE);
private static final ObjectType TYPE_LUASTRING = new ObjectType(STR_LUASTRING);
private static final ObjectType TYPE_LUAINTEGER = new ObjectType(STR_LUAINTEGER);
private static final ObjectType TYPE_LUADOUBLE = new ObjectType(STR_LUADOUBLE);
private static final ObjectType TYPE_LUANUMBER = new ObjectType(STR_LUANUMBER);
private static final ObjectType TYPE_LUABOOLEAN = new ObjectType(STR_LUABOOLEAN);
private static final ObjectType TYPE_LUATABLE = new ObjectType(STR_LUATABLE);
@@ -92,9 +89,8 @@ public class JavaBuilder {
private static final ArrayType TYPE_LOCALUPVALUE = new ArrayType( TYPE_LUAVALUE, 1 );
private static final ArrayType TYPE_CHARARRAY = new ArrayType( Type.CHAR, 1 );
private static final ArrayType TYPE_LUAVALUEARRAY = new ArrayType( TYPE_LUAVALUE, 1 );
private static final Class[] NO_INNER_CLASSES = {};
private static final String STR_FUNCV = VarArgFunction.class.getName();
private static final String STR_FUNC0 = ZeroArgFunction.class.getName();
@@ -108,7 +104,6 @@ public class JavaBuilder {
private static final Type[] ARG_TYPES_DOUBLE = { Type.DOUBLE };
private static final Type[] ARG_TYPES_STRING = { Type.STRING };
private static final Type[] ARG_TYPES_CHARARRAY = { TYPE_CHARARRAY };
private static final Type[] ARG_TYPES_VARARGS_INT = { TYPE_VARARGS, Type.INT };
private static final Type[] ARG_TYPES_INT_LUAVALUE = { Type.INT, TYPE_LUAVALUE };
private static final Type[] ARG_TYPES_INT_VARARGS = { Type.INT, TYPE_VARARGS };
private static final Type[] ARG_TYPES_LUAVALUE_VARARGS = { TYPE_LUAVALUE, TYPE_VARARGS };
@@ -161,10 +156,12 @@ public class JavaBuilder {
private final int[] targets;
private final BranchInstruction[] branches;
private final InstructionHandle[] branchDestHandles;
private final InstructionHandle[] lastInstrHandles;
private InstructionHandle beginningOfLuaInstruction;
// hold vararg result
private LocalVariableGen varresult = null;
private int prev_line = -1;
public JavaBuilder(ProtoInfo pi, String classname, String filename) {
this.pi = pi;
@@ -220,6 +217,7 @@ public class JavaBuilder {
targets = new int[nc];
branches = new BranchInstruction[nc];
branchDestHandles = new InstructionHandle[nc];
lastInstrHandles = new InstructionHandle[nc];
}
public void initializeSlots() {
@@ -339,6 +337,7 @@ public class JavaBuilder {
private Map<Integer,Integer> plainSlotVars = new HashMap<Integer,Integer>();
private Map<Integer,Integer> upvalueSlotVars = new HashMap<Integer,Integer>();
private Map<Integer,LocalVariableGen> localVarGenBySlot = new HashMap<Integer,LocalVariableGen>();
private int findSlot( int slot, Map<Integer,Integer> map, String prefix, Type type ) {
Integer islot = Integer.valueOf(slot);
if ( map.containsKey(islot) )
@@ -347,6 +346,7 @@ public class JavaBuilder {
LocalVariableGen local = mg.addLocalVariable(name, type, null, null);
int index = local.getIndex();
map.put(islot, Integer.valueOf(index));
localVarGenBySlot.put(slot, local);
return index;
}
private int findSlotIndex( int slot, boolean isupvalue ) {
@@ -748,11 +748,25 @@ public class JavaBuilder {
beginningOfLuaInstruction = ih;
}
public void onEndOfLuaInstruction(int pc) {
public void onEndOfLuaInstruction(int pc, int line) {
branchDestHandles[pc] = beginningOfLuaInstruction;
lastInstrHandles[pc] = main.getEnd();
if (line != prev_line)
mg.addLineNumber(beginningOfLuaInstruction, prev_line = line);
beginningOfLuaInstruction = null;
}
public void setVarStartEnd(int slot, int start_pc, int end_pc, String name) {
if (localVarGenBySlot.containsKey(slot)) {
name = name.replaceAll("[^a-zA-Z0-9]", "_");
LocalVariableGen l = localVarGenBySlot.get(slot);
l.setEnd(lastInstrHandles[end_pc-1]);
if (start_pc > 1)
l.setStart(lastInstrHandles[start_pc-2]);
l.setName(name);
}
}
private void resolveBranches() {
int nc = p.code.length;
for (int pc = 0; pc < nc; pc++) {
@@ -798,7 +812,17 @@ public class JavaBuilder {
append(factory.createInvoke(STR_BUFFER, "value", TYPE_LUAVALUE, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
}
public void closeUpvalue(int pc, int i) {
public void closeUpvalue(int pc, int upindex) {
// TODO: assign the upvalue location the value null;
/*
boolean isrw = pi.isReadWriteUpvalue( pi.upvals[upindex] );
append(InstructionConstants.THIS);
append(InstructionConstants.ACONST_NULL);
if ( isrw ) {
append(factory.createFieldAccess(classname, upvalueName(upindex), TYPE_LUAVALUEARRAY, Constants.PUTFIELD));
} else {
append(factory.createFieldAccess(classname, upvalueName(upindex), TYPE_LUAVALUE, Constants.PUTFIELD));
}
*/
}
}

View File

@@ -21,6 +21,7 @@
******************************************************************************/
package org.luaj.vm2.luajc;
import org.luaj.vm2.LocVars;
import org.luaj.vm2.Lua;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.Upvaldesc;
@@ -46,6 +47,10 @@ public class JavaGen {
// build this class
JavaBuilder builder = new JavaBuilder(pi, classname, filename);
scanInstructions(pi, classname, builder);
for (int i = 0; i < pi.prototype.locvars.length; ++i) {
LocVars l = pi.prototype.locvars[i];
builder.setVarStartEnd(i, l.startpc, l.endpc, l.varname.tojstring());
}
this.bytecode = builder.completeClass();
// build sub-prototypes
@@ -80,8 +85,9 @@ public class JavaGen {
for ( int pc=b0.pc0; pc<=b0.pc1; pc++ ) {
int pc0 = pc; // closure changes pc
int ins = p.code[pc];
final int pc0 = pc; // closure changes pc
final int ins = p.code[pc];
final int line = pc < p.lineinfo.length? p.lineinfo[pc]: -1;
final int o = Lua.GET_OPCODE(ins);
int a = Lua.GETARG_A(ins);
int b = Lua.GETARG_B(ins);
@@ -420,7 +426,7 @@ public class JavaGen {
}
// let builder process branch instructions
builder.onEndOfLuaInstruction( pc0 );
builder.onEndOfLuaInstruction( pc0, line );
}
}
}

View File

@@ -97,8 +97,8 @@ public class LuaJC implements LuaCompiler {
public LuaFunction load(InputStream stream, String name, LuaValue env) throws IOException {
Prototype p = LuaC.instance.compile(stream, name);
String classname = toStandardJavaClassName( name );
String luaname = toStandardLuaFileName( name );
String classname = toStandardJavaClassName( luaname );
JavaLoader loader = new JavaLoader();
return loader.load(p, classname, luaname, env);
}
@@ -116,7 +116,7 @@ public class LuaJC implements LuaCompiler {
private static String toStandardLuaFileName( String luachunkname ) {
String stub = toStub( luachunkname );
String filename = stub.replace('.','/')+".lua";
return filename;
return filename.startsWith("@")? filename.substring(1): filename;
}
private static String toStub( String s ) {

View File

@@ -25,7 +25,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.util.Iterator;
import java.util.Map.Entry;
import javax.script.Bindings;
import javax.script.Compilable;
@@ -37,6 +37,7 @@ import javax.script.ScriptException;
import javax.script.SimpleBindings;
import javax.script.SimpleScriptContext;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.Lua;
import org.luaj.vm2.LuaClosure;
@@ -59,7 +60,7 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
private static final String __NAME__ = "Luaj";
private static final String __SHORT_NAME__ = "Luaj";
private static final String __LANGUAGE__ = "lua";
private static final String __LANGUAGE_VERSION__ = "5.1";
private static final String __LANGUAGE_VERSION__ = "5.2";
private static final String __ARGV__ = "arg";
private static final String __FILENAME__ = "?";
@@ -67,12 +68,14 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
private ScriptContext defaultContext;
private final LuaValue _G;
private final Globals _G;
public LuaScriptEngine() {
// create globals
_G = JsePlatform.standardGlobals();
_G = "true".equals(System.getProperty("luaj.debug"))?
JsePlatform.debugGlobals():
JsePlatform.standardGlobals();
// set up context
ScriptContext ctx = new SimpleScriptContext();
@@ -88,9 +91,11 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
put(FILENAME, __FILENAME__);
put(NAME, __SHORT_NAME__);
put("THREADING", null);
// Let globals act as an index metatable
_G.set(LuaValue.INDEX, _G);
}
public Object eval(String script) throws ScriptException {
return eval(new StringReader(script));
}
@@ -162,22 +167,24 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
try {
InputStream ris = new Utf8Encoder(reader);
try {
final LuaFunction f = LoadState.load(ris, "script", "bt", null);
final LuaFunction f = LoadState.load(ris, "script", "bt", _G);
if ( f.isclosure() ) {
// most compiled functions are closures with prototypes
final Prototype p = f.checkclosure().p;
return new CompiledScriptImpl() {
protected LuaFunction newFunctionInstance() {
return new LuaClosure( p, null );
protected LuaFunction newFunctionInstance(LuaTable env) {
return new LuaClosure( p, env );
}
};
} else {
// when luajc is used, functions are java class instances
final Class c = f.getClass();
return new CompiledScriptImpl() {
protected LuaFunction newFunctionInstance() throws ScriptException {
protected LuaFunction newFunctionInstance(LuaTable env) throws ScriptException {
try {
return (LuaFunction) c.newInstance();
LuaFunction f = (LuaFunction) c.newInstance();
f.initupvalue1( env );
return f;
} catch (Exception e) {
throw new ScriptException("instantiation failed: "+e.toString());
}
@@ -195,63 +202,51 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
}
abstract protected class CompiledScriptImpl extends CompiledScript {
abstract protected LuaFunction newFunctionInstance() throws ScriptException;
abstract protected LuaFunction newFunctionInstance(LuaTable env) 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.initupvalue1(cb.env);
Varargs result = f.invoke(LuaValue.NONE);
cb.copyGlobalsToBindings();
return result;
BindingsGlobals env = new BindingsGlobals(b);
LuaFunction f = newFunctionInstance(env);
try {
return f.invoke(LuaValue.NONE);
} finally {
env.copyout();
}
}
}
public class ClientBindings {
public final Bindings b;
public final LuaTable env;
public ClientBindings( Bindings b ) {
class BindingsGlobals extends Globals {
final Bindings b;
BindingsGlobals(Bindings b) {
this.b = b;
this.env = new LuaTable();
env.setmetatable(LuaTable.tableOf(new LuaValue[] { LuaValue.INDEX, _G }));
this.copyBindingsToGlobals();
this.setmetatable(_G);
this.debuglib = _G.debuglib;
for (Entry<String,Object> e : b.entrySet())
rawset(toLua(e.getKey()), toLua(e.getValue()));
}
public void copyBindingsToGlobals() {
for ( Iterator i = b.keySet().iterator(); i.hasNext(); ) {
String key = (String) i.next();
Object val = b.get(key);
LuaValue luakey = toLua(key);
LuaValue luaval = toLua(val);
env.set(luakey, luaval);
i.remove();
}
void copyout() {
b.clear();
for (Varargs v = next(LuaValue.NIL); !v.arg1().isnil(); v = next(v.arg1()))
b.put(toJava(v.arg1()).toString(), toJava(v.arg(2)));
}
private LuaValue toLua(Object javaValue) {
return javaValue == null? LuaValue.NIL:
javaValue instanceof LuaValue? (LuaValue) javaValue:
CoerceJavaToLua.coerce(javaValue);
}
public void copyGlobalsToBindings() {
LuaValue[] keys = env.keys();
for ( int i=0; i<keys.length; i++ ) {
LuaValue luakey = keys[i];
LuaValue luaval = env.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;
}
}
LuaValue toLua(Object javaValue) {
return javaValue == null? LuaValue.NIL:
javaValue instanceof LuaValue? (LuaValue) javaValue:
CoerceJavaToLua.coerce(javaValue);
}
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;
}
}