Fix source and class names in generated bytecode.

This commit is contained in:
James Roseborough
2009-10-30 00:39:25 +00:00
parent f729c1b626
commit dd82fe6d2d
3 changed files with 69 additions and 55 deletions

View File

@@ -34,6 +34,7 @@ import org.luaj.vm2.LuaValue;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.DebugLib;
import org.luaj.vm2.lib.JsePlatform;
import org.luaj.vm2.luajc.JavaBytecodeCompiler;
/**
@@ -49,6 +50,7 @@ public class lua {
" -l name require library 'name'\n" +
" -i enter interactive mode after executing 'script'\n" +
" -v show version information\n" +
" -j compile into java bytecode\n" +
" -- stop handling options\n" +
" - execute stdin and stop handling options";
@@ -62,9 +64,9 @@ public class lua {
public static void main( String[] args ) throws IOException {
// new lua state
LuaC.install();
_G = JsePlatform.standardGlobals();
DebugLib.install( _G );
LuaC.install();
// process args
boolean interactive = (args.length == 0);
@@ -97,6 +99,9 @@ public class lua {
case 'v':
versioninfo = true;
break;
case 'j':
JavaBytecodeCompiler.install();
break;
case '-':
if ( args[i].length() > 2 )
usageExit();

View File

@@ -63,11 +63,15 @@ public class JavaBytecodeCompiler implements LuaCompiler {
}
/** Compile into class form. */
public LuaFunction load(int firstByte, InputStream stream, String name, LuaValue env) throws IOException {
Prototype p = compile( firstByte, stream, name);
public LuaFunction load(int firstByte, InputStream stream, String filename, LuaValue env) throws IOException {
Prototype p = compile( firstByte, stream, filename);
try {
System.out.println("compiling "+name);
Class c = gen.toJavaBytecode(p, name);
String classname = filename.endsWith(".lua")? filename.substring(0,filename.length()-4): filename;
classname = classname.replace('/', '.');
classname = classname.replace('\\', '.');
String sourcename = filename.substring( filename.lastIndexOf('/')+1 );
System.out.println("compiling file "+filename+" using sourcename "+sourcename+" and classname "+classname);
Class c = gen.toJavaBytecode(p, classname, sourcename);
Object o = c.newInstance();
System.out.println("instance is: "+o);
LuaFunction f = (LuaFunction) o;

View File

@@ -91,7 +91,7 @@ public class JavaBytecodeGenerator {
private static final Class[] NO_INNER_CLASSES = {};
private static String toLegalLocalName(String string) {
public static String toLegalJavaName(String string) {
String better = string.replaceAll("[^\\w]", "_");
return string.equals(better)? string: "$"+better;
}
@@ -103,8 +103,8 @@ public class JavaBytecodeGenerator {
* @return Java Class that extends LuaValue that can be instatiated via newInstance
* @throws Exception
*/
public static Class toJavaBytecode( Prototype p, String classname ) throws Exception {
return new JavaBytecodeGenerator().loadPrototype( p, classname );
public static Class toJavaBytecode( Prototype p, String classname, String filename ) throws Exception {
return new JavaBytecodeGenerator().loadPrototype( p, classname, filename );
}
private final Hashtable prototypes;
@@ -114,35 +114,38 @@ public class JavaBytecodeGenerator {
// load the file
prototypes = new Hashtable();
classLoader = new ClassLoader() {
public Class findClass(String name) throws ClassNotFoundException {
Object o = prototypes.get(name);
if ( o instanceof Prototype) {
public Class findClass(String classname) throws ClassNotFoundException {
Object o = prototypes.get(classname);
if ( o instanceof Object[]) {
try {
byte[] b = generateBytecode( (Prototype) o, name );
prototypes.put(name, Boolean.TRUE);
return defineClass(name, b, 0, b.length);
Object[] data = (Object[]) o;
Prototype p = (Prototype) data[0];
String filename = (String) data[1];
byte[] b = generateBytecode( p, classname, filename );
prototypes.put(classname, Boolean.TRUE);
return defineClass(classname, b, 0, b.length);
} catch (IOException e) {
e.printStackTrace();
}
}
return super.findClass(name);
return super.findClass(classname);
}
};
}
private Class loadPrototype(Prototype p, String classname) throws ClassNotFoundException {
indexPrototype( p, classname );
private Class loadPrototype(Prototype p, String classname, String filename) throws ClassNotFoundException {
indexPrototype( p, classname, filename );
return classLoader.loadClass(classname);
}
private void indexPrototype(Prototype p, String name) {
if ( prototypes.containsKey(name) )
private void indexPrototype(Prototype p, String classname, String filename) {
if ( prototypes.containsKey(classname) )
return;
prototypes.put(name, p);
prototypes.put(classname, new Object[] { p, filename } );
Class[] inners = (p.p!=null && p.p.length>0? new Class[p.p.length]: NO_INNER_CLASSES);
for ( int i=0, n=inners.length; i<n; i++ )
indexPrototype( p.p[i], name+"$"+i );
indexPrototype( p.p[i], classname+"$"+i, filename );
}
private static final int OP(int i) {
@@ -161,11 +164,11 @@ public class JavaBytecodeGenerator {
return (i >> 14) & 0x1ff;
}
private byte[] generateBytecode(Prototype p, String CLASSNAME)
private byte[] generateBytecode(Prototype p, String classname, String filename)
throws IOException {
// compile our class next
ClassGen cg = new ClassGen(CLASSNAME, STR_FUNCV, "tryit.lua",
ClassGen cg = new ClassGen(classname, STR_FUNCV, filename,
Constants.ACC_PUBLIC | Constants.ACC_SUPER, null);
ConstantPoolGen cp = cg.getConstantPool(); // cg creates constant pool
@@ -197,14 +200,14 @@ public class JavaBytecodeGenerator {
case LuaValue.TNIL:
il.append(factory.createFieldAccess(STR_LUAVALUE, "NIL",
TYPE_LUAVALUE, Constants.GETSTATIC));
il.append(factory.createPutStatic(CLASSNAME,
il.append(factory.createPutStatic(classname,
k[i].getName(), k[i].getType()));
break;
case LuaValue.TBOOLEAN:
String b = ki.toboolean() ? "TRUE" : "FALSE";
il.append(factory.createFieldAccess(STR_LUAVALUE, b,
TYPE_LUABOOLEAN, Constants.GETSTATIC));
il.append(factory.createPutStatic(CLASSNAME,
il.append(factory.createPutStatic(classname,
k[i].getName(), k[i].getType()));
break;
case LuaValue.TSTRING:
@@ -212,7 +215,7 @@ public class JavaBytecodeGenerator {
il.append(factory.createInvoke(STR_LUASTRING, "valueOf",
TYPE_LUASTRING, new Type[] { Type.STRING },
Constants.INVOKESTATIC));
il.append(factory.createPutStatic(CLASSNAME,
il.append(factory.createPutStatic(classname,
k[i].getName(), k[i].getType()));
break;
case LuaValue.TNUMBER:
@@ -223,7 +226,7 @@ public class JavaBytecodeGenerator {
TYPE_LUAINTEGER,
new Type[] { Type.INT },
Constants.INVOKESTATIC));
il.append(factory.createPutStatic(CLASSNAME, k[i]
il.append(factory.createPutStatic(classname, k[i]
.getName(), k[i].getType()));
} else {
il.append(new PUSH(cp, ki.todouble()));
@@ -231,7 +234,7 @@ public class JavaBytecodeGenerator {
"valueOf", TYPE_LUANUMBER,
new Type[] { Type.DOUBLE },
Constants.INVOKESTATIC));
il.append(factory.createPutStatic(CLASSNAME, k[i]
il.append(factory.createPutStatic(classname, k[i]
.getName(), k[i].getType()));
}
break;
@@ -301,7 +304,7 @@ public class JavaBytecodeGenerator {
for (int j = 0; j < nl; j++) {
String name = j < p.locvars.length && p.locvars[j].varname != null ?
toLegalLocalName(p.locvars[j].varname.toString()):
toLegalJavaName(p.locvars[j].varname.toString()):
"r" + j;
locals[j] = mg.addLocalVariable(name, isup[j] ? TYPE_LOCALUPVALUE
@@ -376,7 +379,7 @@ public class JavaBytecodeGenerator {
case Lua.OP_LOADK:/* A Bx R(A):= Kst(Bx) */
ih[pc] =
il.append(factory.createFieldAccess(CLASSNAME, k[Bx(i)].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
il.append(factory.createFieldAccess(classname, k[Bx(i)].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
il_append_new_ASTORE(cp,il, (locals[a]));
break;
@@ -405,7 +408,7 @@ public class JavaBytecodeGenerator {
case Lua.OP_GETUPVAL: /* A B R(A):= UpValue[B] */
ih[pc] =
il.append(InstructionConstants.THIS);
il.append(factory.createFieldAccess(CLASSNAME, u[B(i)].getName(), TYPE_LOCALUPVALUE, Constants.GETFIELD));
il.append(factory.createFieldAccess(classname, u[B(i)].getName(), TYPE_LOCALUPVALUE, Constants.GETFIELD));
il.append(new PUSH(cp,0));
il.append(InstructionConstants.AALOAD);
il_append_new_ASTORE(cp,il, (locals[a]));
@@ -414,8 +417,8 @@ public class JavaBytecodeGenerator {
case Lua.OP_GETGLOBAL: /* A Bx R(A):= Gbl[Kst(Bx)] */
ih[pc] =
il.append(InstructionConstants.THIS);
il.append(factory.createFieldAccess(CLASSNAME, "env", TYPE_LUAVALUE, Constants.GETFIELD));
il.append(factory.createFieldAccess(CLASSNAME, k[Bx(i)].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
il.append(factory.createFieldAccess(classname, "env", TYPE_LUAVALUE, Constants.GETFIELD));
il.append(factory.createFieldAccess(classname, k[Bx(i)].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
il.append(factory.createInvoke(STR_LUAVALUE, "get", TYPE_LUAVALUE, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL));
il_append_new_ASTORE(cp,il, (locals[a]));
break;
@@ -425,7 +428,7 @@ public class JavaBytecodeGenerator {
ih[pc] =
il_append_new_ALOAD(cp,il, (locals[B(i)]));
if ((c=C(i))>0xff)
il.append(factory.createFieldAccess(CLASSNAME, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
il.append(factory.createFieldAccess(classname, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
else
il_append_new_ALOAD(cp,il, (locals[c]));
il.append(factory.createInvoke(STR_LUAVALUE, "get", TYPE_LUAVALUE, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL));
@@ -436,8 +439,8 @@ public class JavaBytecodeGenerator {
// env.set(k[Bx(i)], stack[a]);
ih[pc] =
il.append(InstructionConstants.THIS);
il.append(factory.createFieldAccess(CLASSNAME, "env", TYPE_LUAVALUE, Constants.GETFIELD));
il.append(factory.createFieldAccess(CLASSNAME, k[Bx(i)].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
il.append(factory.createFieldAccess(classname, "env", TYPE_LUAVALUE, Constants.GETFIELD));
il.append(factory.createFieldAccess(classname, k[Bx(i)].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
il_append_new_ALOAD(cp,il, (locals[a]));
il.append(factory.createInvoke(STR_LUAVALUE, "set", Type.VOID, new Type[] { TYPE_LUAVALUE, TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL));
break;
@@ -446,7 +449,7 @@ public class JavaBytecodeGenerator {
// upValues[B(i)].setValue(stack[a]);
ih[pc] =
il.append(InstructionConstants.THIS);
il.append(factory.createFieldAccess(CLASSNAME, u[B(i)].getName(), TYPE_LOCALUPVALUE, Constants.GETFIELD));
il.append(factory.createFieldAccess(classname, u[B(i)].getName(), TYPE_LOCALUPVALUE, Constants.GETFIELD));
il.append(new PUSH(cp,0));
il_append_new_ALOAD(cp,il, (locals[a]));
il.append(InstructionConstants.AASTORE);
@@ -457,11 +460,11 @@ public class JavaBytecodeGenerator {
ih[pc] =
il_append_new_ALOAD(cp,il, (locals[a]));
if ((b=B(i))>0xff)
il.append(factory.createFieldAccess(CLASSNAME, k[b&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
il.append(factory.createFieldAccess(classname, k[b&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
else
il_append_new_ALOAD(cp,il, (locals[b]));
if ((c=C(i))>0xff)
il.append(factory.createFieldAccess(CLASSNAME, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
il.append(factory.createFieldAccess(classname, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
else
il_append_new_ALOAD(cp,il, (locals[c]));
il.append(factory.createInvoke(STR_LUAVALUE, "set", Type.VOID, new Type[] { TYPE_LUAVALUE, TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL));
@@ -483,7 +486,7 @@ public class JavaBytecodeGenerator {
il_append_new_ASTORE(cp,il, (locals[a+1]));
// stack[a] = o.get((c=C(i))>0xff? k[c&0x0ff]: stack[c]);
if ((c=C(i))>0xff)
il.append(factory.createFieldAccess(CLASSNAME, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
il.append(factory.createFieldAccess(classname, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
else
il_append_new_ALOAD(cp,il, (locals[c]));
il.append(factory.createInvoke(STR_LUAVALUE, "get", TYPE_LUAVALUE, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL));
@@ -510,12 +513,12 @@ public class JavaBytecodeGenerator {
// stack[a] = ((b=B(i))>0xff? k[b&0x0ff]: stack[b]).add((c=C(i))>0xff? k[c&0x0ff]: stack[c]);
if ((b=B(i))>0xff)
ih[pc] =
il.append(factory.createFieldAccess(CLASSNAME, k[b&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
il.append(factory.createFieldAccess(classname, k[b&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
else
ih[pc] =
il_append_new_ALOAD(cp,il, (locals[b]));
if ((c=C(i))>0xff)
il.append(factory.createFieldAccess(CLASSNAME, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
il.append(factory.createFieldAccess(classname, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
else
il_append_new_ALOAD(cp,il, (locals[c]));
il.append(factory.createInvoke(STR_LUAVALUE, op, TYPE_LUAVALUE, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL));
@@ -594,12 +597,12 @@ public class JavaBytecodeGenerator {
}
if ((b=B(i))>0xff)
ih[pc] =
il.append(factory.createFieldAccess(CLASSNAME, k[b&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
il.append(factory.createFieldAccess(classname, k[b&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
else
ih[pc] =
il_append_new_ALOAD(cp,il, (locals[b]));
if ((c=C(i))>0xff)
il.append(factory.createFieldAccess(CLASSNAME, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
il.append(factory.createFieldAccess(classname, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC));
else
il_append_new_ALOAD(cp,il, (locals[c]));
il.append(factory.createInvoke(STR_LUAVALUE, op, Type.BOOLEAN, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL));
@@ -915,7 +918,7 @@ public class JavaBytecodeGenerator {
{
b = Bx(i);
Prototype newp = p.p[b];
String protoname = CLASSNAME+"$"+b;
String protoname = classname+"$"+b;
// instantiate the class
ih[pc] =
@@ -926,7 +929,7 @@ public class JavaBytecodeGenerator {
// set the environment
il.append(InstructionConstants.DUP);
il.append(InstructionConstants.THIS);
il.append(factory.createFieldAccess(CLASSNAME, "env", TYPE_LUAVALUE, Constants.GETFIELD));
il.append(factory.createFieldAccess(classname, "env", TYPE_LUAVALUE, Constants.GETFIELD));
il.append(factory.createInvoke(STR_LUAVALUE, "setfenv", Type.VOID, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL));
// initialize upvalues of new instance
@@ -940,7 +943,7 @@ public class JavaBytecodeGenerator {
if ( (i&4) != 0 ) {
il.append(InstructionConstants.THIS);
String srcname = u[b].getName();
il.append(factory.createFieldAccess(CLASSNAME, srcname, TYPE_LOCALUPVALUE, Constants.GETFIELD));
il.append(factory.createFieldAccess(classname, srcname, TYPE_LOCALUPVALUE, Constants.GETFIELD));
} else {
il.append( new ALOAD(locals[b].getIndex()) );
}
@@ -980,12 +983,14 @@ public class JavaBytecodeGenerator {
}
}
// return NONE
il.append(factory.createFieldAccess(STR_LUAVALUE, "NONE",
TYPE_LUAVALUE, Constants.GETSTATIC));
// add line numbers
if ( p.lineinfo != null && p.lineinfo.length >= nc) {
for ( pc=0; pc<nc; pc++ ) {
if ( ih[pc] != null )
mg.addLineNumber( ih[pc], p.lineinfo[pc] );
}
}
// complete method
il.append(InstructionConstants.ARETURN);
mg.setMaxStack();
cg.addMethod(mg.getMethod());
il.dispose(); // Allow instruction handles to be reused
@@ -998,7 +1003,7 @@ public class JavaBytecodeGenerator {
// write the bytes for debugging!
if (DUMPCLASSES) {
FileOutputStream fos = new FileOutputStream(CLASSNAME + ".class");
FileOutputStream fos = new FileOutputStream(classname + ".class");
fos.write(bytes);
fos.close();
}