Refactor java code generator.

This commit is contained in:
James Roseborough
2010-04-13 14:31:40 +00:00
parent a8f129b8cf
commit 8ae33e1d08
39 changed files with 1711 additions and 13156 deletions

View File

@@ -74,7 +74,7 @@ public final class Buffer {
this.length = length;
}
public final LuaString tostrvalue() {
public final LuaString tostring() {
return new LuaString( realloc( bytes, length ) );
}

View File

@@ -24,7 +24,6 @@ package org.luaj.vm2;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
/*
** Loader to load compiled function prototypes

View File

@@ -236,7 +236,7 @@ public class LuaClosure extends LuaFunction {
Buffer sb = new Buffer();
for ( ; b<=c; )
sb.append( stack[b++].checkstring() );
stack[a] = sb.tostrvalue();
stack[a] = sb.tostring();
}
continue;

View File

@@ -56,13 +56,17 @@ public class LuaTable extends LuaValue {
rawset(named[i], named[i+1]);
}
public LuaTable(Varargs varargs) {
int n = varargs.narg();
this(varargs,1);
}
public LuaTable(Varargs varargs, int firstarg) {
int nskip = firstarg-1;
int n = Math.max(varargs.narg()-nskip,0);
presize( n, 1 );
set(N, valueOf(n));
for ( int i=1; i<=n; i++ )
set(i, varargs.arg(i));
set(i, varargs.arg(i+nskip));
}
private void presize(int narray, int nhash) {
@@ -232,7 +236,7 @@ public class LuaTable extends LuaValue {
sb.append( get(i).checkstring() );
}
}
return sb.tostrvalue();
return sb.tostring();
}
public LuaValue getn() {

View File

@@ -286,7 +286,7 @@ public class LuaValue extends Varargs {
public LuaValue or( LuaValue rhs ) { return this.toboolean()? this: rhs; }
// for loop helpers
/** test numeric for loop */
/** @deprecated - used during development only */
public boolean testfor_b(LuaValue limit, boolean stepgtzero) { return stepgtzero? lteq_b(limit): gteq_b(limit); }
/** used in for loop only */
public boolean testfor_b(LuaValue limit, LuaValue step) { return step.gt_b(0)? lteq_b(limit): gteq_b(limit); }
@@ -312,7 +312,7 @@ public class LuaValue extends Varargs {
// table initializers
public static LuaTable tableOf() { return new LuaTable(); }
public static LuaTable tableOf(Varargs varargs, int firstarg) { return new LuaTable(varargs.subargs(firstarg)); }
public static LuaTable tableOf(Varargs varargs, int firstarg) { return new LuaTable(varargs,firstarg); }
public static LuaTable tableOf(int narray, int nhash) { return new LuaTable(narray, nhash); }
public static LuaTable listOf(LuaValue[] unnamedValues) { return new LuaTable(null,unnamedValues,null); }
public static LuaTable listOf(LuaValue[] unnamedValues,Varargs lastarg) { return new LuaTable(null,unnamedValues,lastarg); }
@@ -421,8 +421,12 @@ public class LuaValue extends Varargs {
public static Varargs varargsOf(LuaValue v1,LuaValue v2,Varargs v3) {
switch ( v3.narg() ) {
case 0: return new PairVarargs(v1,v2);
default: return new ArrayVarargs(new LuaValue[] {v1,v2},v3); }
default: return new ArrayVarargs(new LuaValue[] {v1,v2},v3);
}
}
public static Varargs tailcallOf(LuaValue func, Varargs args) {
return new TailcallVarargs(func, args);
}
// empty varargs
private static final class None extends LuaNil {

View File

@@ -48,21 +48,18 @@ public class TailcallVarargs extends Varargs {
} while (nextcall != null);
}
@Override
public LuaValue arg( int i ) {
if ( result == null )
eval();
return result.arg(i);
}
@Override
public LuaValue arg1() {
if (result == null)
eval();
return result.arg1();
}
@Override
public int narg() {
if (result == null)
eval();

View File

@@ -143,5 +143,4 @@ public abstract class Varargs {
return end+1-start;
}
}
}

View File

@@ -259,7 +259,7 @@ public class StringLib extends OneArgFunction {
}
}
return result.tostrvalue();
return result.tostring();
}
private static void addquoted(Buffer buf, LuaString s) {
@@ -575,7 +575,7 @@ public class StringLib extends OneArgFunction {
break;
}
lbuf.append( src.substring( soffset, srclen ) );
return varargsOf(lbuf.tostrvalue(), valueOf(n));
return varargsOf(lbuf.tostring(), valueOf(n));
}
/**

View File

@@ -35,7 +35,7 @@ import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.JsePlatform;
import org.luaj.vm2.luajc.JavaBytecodeCompiler;
import org.luaj.vm2.luajc.LuaJC;
/**
@@ -89,7 +89,7 @@ public class lua {
// input script - defer to last stage
break;
case 'j':
JavaBytecodeCompiler.install();
LuaJC.install();
break;
case 'l':
if ( ++i >= args.length )

View File

@@ -30,7 +30,7 @@ import java.util.Hashtable;
import org.luaj.vm2.Lua;
import org.luaj.vm2.compiler.DumpState;
import org.luaj.vm2.luajc.JavaBytecodeCompiler;
import org.luaj.vm2.luajc.LuaJC;
@@ -155,7 +155,7 @@ public class luajc {
private void processScript( InputStream script, String chunkname, OutputStream out ) throws IOException {
try {
// create the chunk
Hashtable t = JavaBytecodeCompiler.loadClasses(script, chunkname);
Hashtable t = LuaJC.getInstance().compileAll(script, chunkname, chunkname);
// write out the chunk
if (!parseonly) {

View File

@@ -0,0 +1,701 @@
/*******************************************************************************
* Copyright (c) 2010 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.bcel.Constants;
import org.apache.bcel.generic.AASTORE;
import org.apache.bcel.generic.ALOAD;
import org.apache.bcel.generic.ANEWARRAY;
import org.apache.bcel.generic.ASTORE;
import org.apache.bcel.generic.ArrayType;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.CompoundInstruction;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.FieldGen;
import org.apache.bcel.generic.GOTO;
import org.apache.bcel.generic.IFEQ;
import org.apache.bcel.generic.IFNE;
import org.apache.bcel.generic.Instruction;
import org.apache.bcel.generic.InstructionConstants;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.LocalVariableGen;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.PUSH;
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;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.lib.OneArgFunction;
import org.luaj.vm2.lib.ThreeArgFunction;
import org.luaj.vm2.lib.TwoArgFunction;
import org.luaj.vm2.lib.VarArgFunction;
import org.luaj.vm2.lib.ZeroArgFunction;
public class JavaBuilder {
private static final String STR_VARARGS = Varargs.class.getName();
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();
private static final String STR_BUFFER = Buffer.class.getName();
private static final String STR_STRING = String.class.getName();
private static final ObjectType TYPE_VARARGS = new ObjectType(STR_VARARGS);
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);
private static final ObjectType TYPE_BUFFER = new ObjectType(STR_BUFFER);
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 Class[] NO_INNER_CLASSES = {};
private static final String STR_FUNCV = VarArgFunction.class.getName();
private static final String STR_FUNC0 = ZeroArgFunction.class.getName();
private static final String STR_FUNC1 = OneArgFunction.class.getName();
private static final String STR_FUNC2 = TwoArgFunction.class.getName();
private static final String STR_FUNC3 = ThreeArgFunction.class.getName();
// names, arg types for main prototype classes
private static final String[] SUPER_NAME_N = { STR_FUNC0, STR_FUNC1, STR_FUNC2, STR_FUNC3, STR_FUNCV, };
private static final ObjectType[] RETURN_TYPE_N = { TYPE_LUAVALUE, TYPE_LUAVALUE, TYPE_LUAVALUE, TYPE_LUAVALUE, TYPE_VARARGS, };
private static final Type[][] ARG_TYPES_N = { {}, {TYPE_LUAVALUE}, {TYPE_LUAVALUE,TYPE_LUAVALUE}, {TYPE_LUAVALUE,TYPE_LUAVALUE,TYPE_LUAVALUE}, {TYPE_VARARGS}, };
private static final String[][] ARG_NAMES_N = { {}, {"arg"}, {"arg1","arg2"}, {"arg1","arg2","arg3"}, {"args"}, };
private static final String[] METH_NAME_N = { "call", "call", "call", "call", "invoke", };
// varable naming
private static final String PREFIX_CONSTANT = "k";
private static final String PREFIX_UPVALUE = "u";
private static final String PREFIX_PLAIN_SLOT = "s";
private static final String PREFIX_UPVALUE_SLOT = "a";
private static final String NAME_VARRESULT = "v";
// basic info
private final Prototype p;
private final String classname;
private final Slots slots;
// bcel variables
private final ClassGen cg;
private final ConstantPoolGen cp;
private final InstructionFactory factory;
// main instruction list for the main function of this class
private final InstructionList init;
private final InstructionList main;
private final MethodGen mg;
// the superclass arg count, 0-3 args, 4=varargs
private int superclassType;
private static int SUPERTYPE_VARARGS = 4;
// storage for goto locations
private final int[] targets;
private final BranchInstruction[] branches;
private final InstructionHandle[] branchDestHandles;
private InstructionHandle beginningOfLuaInstruction;
// hold vararg result
private LocalVariableGen varresult = null;
public JavaBuilder(Prototype p, String classname, String filename) {
this.p = p;
this.classname = classname;
this.slots = new Slots(p);
// what class to inherit from
superclassType = p.numparams;
if ( p.is_vararg != 0 || superclassType >= SUPERTYPE_VARARGS )
superclassType = SUPERTYPE_VARARGS;
for ( int i=0, n=p.code.length; i<n; i++ ) {
int inst = p.code[i];
if ( Lua.GET_OPCODE(inst) == Lua.OP_RETURN && (Lua.GETARG_B(inst) < 1 || Lua.GETARG_B(inst) > 2) )
superclassType = SUPERTYPE_VARARGS;
}
// create class generator
cg = new ClassGen(classname, SUPER_NAME_N[superclassType], filename,
Constants.ACC_PUBLIC | Constants.ACC_SUPER, null);
cp = cg.getConstantPool(); // cg creates constant pool
// main instruction lists
factory = new InstructionFactory(cg);
init = new InstructionList();
main = new InstructionList();
// create the fields
for ( int i=0; i<p.nups; i++ ) {
FieldGen fg = new FieldGen(0, TYPE_LOCALUPVALUE, upvalueName(i), cp);
cg.addField(fg.getField());
}
// create the method
mg = new MethodGen( Constants.ACC_PUBLIC | Constants.ACC_FINAL, // access flags
RETURN_TYPE_N[superclassType], // return type
ARG_TYPES_N[superclassType], // argument types
ARG_NAMES_N[superclassType], // arg names
METH_NAME_N[superclassType],
STR_LUAVALUE, // method, defining class
main, cp);
// initialize the values in the slots
initializeSlots();
// initialize branching
int nc = p.code.length;
targets = new int[nc];
branches = new BranchInstruction[nc];
branchDestHandles = new InstructionHandle[nc];
}
public void initializeSlots() {
int slot = 0;
if ( superclassType == SUPERTYPE_VARARGS ) {
for ( slot=0; slot<p.numparams; slot++ ) {
if ( slots.isInitialValueUsed(slot) ) {
append(new ALOAD(1));
append(new PUSH(cp, slot+1));
append(factory.createInvoke(STR_VARARGS, "arg", TYPE_LUAVALUE, new Type[] { Type.INT }, Constants.INVOKEVIRTUAL));
storeLocal(-1, slot);
}
}
boolean needsarg = ((p.is_vararg & Lua.VARARG_NEEDSARG) != 0);
if ( needsarg ) {
append(new ALOAD(1));
append(new PUSH(cp, 1 + p.numparams));
append(factory.createInvoke(STR_LUAVALUE, "tableOf", TYPE_LUATABLE, new Type[] { TYPE_VARARGS, Type.INT }, Constants.INVOKESTATIC));
storeLocal(-1, slot++ );
}
else if ( p.numparams > 0 ) {
append(new ALOAD(1));
append(new PUSH(cp, 1 + p.numparams));
append(factory.createInvoke(STR_VARARGS, "subargs", TYPE_VARARGS, new Type[] { Type.INT }, Constants.INVOKEVIRTUAL));
append(new ASTORE(1));
}
} else {
// fixed arg function between 0 and 3 arguments
for ( slot=0; slot<p.numparams; slot++ ) {
this.plainSlotVars.put( slot, 1+slot );
if ( slots.isUpvalueCreate(-1, slot) ) {
append(new ALOAD(1+slot));
storeLocal(-1, slot);
}
}
}
// nil parameters
for ( ; slot<p.maxstacksize; slot++ ) {
if ( slots.isInitialValueUsed(slot) ) {
loadNil();
storeLocal(-1, slot);
}
}
}
public byte[] completeClass() {
// add class initializer
if ( ! init.isEmpty() ) {
MethodGen mg = new MethodGen(Constants.ACC_STATIC, Type.VOID,
new Type[] {}, new String[] {}, "<clinit>", cg
.getClassName(), init, cg.getConstantPool());
init.append(InstructionConstants.RETURN);
mg.setMaxStack();
cg.addMethod(mg.getMethod());
init.dispose();
}
// add default constructor
cg.addEmptyConstructor(Constants.ACC_PUBLIC);
// gen method
resolveBranches();
mg.setMaxStack();
cg.addMethod(mg.getMethod());
main.dispose();
// convert to class bytes
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
cg.getJavaClass().dump(baos);
return baos.toByteArray();
} catch ( IOException ioe ) {
throw new RuntimeException("JavaClass.dump() threw "+ioe);
}
}
public void dup() {
append(InstructionConstants.DUP);
}
public void pop() {
append(InstructionConstants.POP);
}
public void loadNil() {
append(factory.createFieldAccess(STR_LUAVALUE, "NIL", TYPE_LUAVALUE, Constants.GETSTATIC));
}
public void loadNone() {
append(factory.createFieldAccess(STR_LUAVALUE, "NONE", TYPE_LUAVALUE, Constants.GETSTATIC));
}
public void loadBoolean(boolean b) {
String field = (b? "TRUE": "FALSE");
append(factory.createFieldAccess(STR_LUAVALUE, field, TYPE_LUABOOLEAN, Constants.GETSTATIC));
}
private Map<Integer,Integer> plainSlotVars = new HashMap<Integer,Integer>();
private Map<Integer,Integer> upvalueSlotVars = new HashMap<Integer,Integer>();
private int findSlot( int slot, Map<Integer,Integer> map, String prefix, Type type ) {
if ( map.containsKey(slot) )
return map.get(slot);
String name = prefix+slot;
LocalVariableGen local = mg.addLocalVariable(name, type, null, null);
int index = local.getIndex();
map.put(slot, index);
return index;
}
private int findSlotIndex( int slot, boolean isupvalue ) {
return isupvalue?
findSlot( slot, upvalueSlotVars, PREFIX_UPVALUE_SLOT, TYPE_LOCALUPVALUE ):
findSlot( slot, plainSlotVars, PREFIX_PLAIN_SLOT, TYPE_LUAVALUE );
}
public void loadLocal(int pc, int slot) {
boolean isupval = slots.isUpvalueRefer(pc, slot);
int index = findSlotIndex( slot, isupval );
append(new ALOAD(index));
if (isupval) {
append(new PUSH(cp, 0));
append(InstructionConstants.AALOAD);
}
}
public void storeLocal(int pc, int slot) {
boolean isupval = slots.isUpvalueAssign(pc, slot);
int index = findSlotIndex( slot, isupval );
if (isupval) {
boolean isupcreate = slots.isUpvalueCreate(pc, slot);
if ( isupcreate ) {
append(new PUSH(cp, 1));
append(new ANEWARRAY(cp.addClass(STR_LUAVALUE)));
append(InstructionConstants.DUP);
append(new ASTORE(index));
} else {
append(new ALOAD(index));
}
append(InstructionConstants.SWAP);
append(new PUSH(cp, 0));
append(InstructionConstants.SWAP);
append(InstructionConstants.AASTORE);
} else {
append(new ASTORE(index));
}
}
private static String upvalueName(int upindex) {
return PREFIX_UPVALUE+upindex;
}
public void loadUpvalue(int upindex) {
append(InstructionConstants.THIS);
append(factory.createFieldAccess(classname, upvalueName(upindex), TYPE_LOCALUPVALUE, Constants.GETFIELD));
append(new PUSH(cp,0));
append(InstructionConstants.AALOAD);
}
public void storeUpvalue(int pc, int upindex, int slot) {
append(InstructionConstants.THIS);
append(factory.createFieldAccess(classname, upvalueName(upindex), TYPE_LOCALUPVALUE, Constants.GETFIELD));
append(new PUSH(cp,0));
loadLocal(pc, slot);
append(InstructionConstants.AASTORE);
}
public void newTable( int b, int c ) {
append(new PUSH(cp, b));
append(new PUSH(cp, c));
append(factory.createInvoke(STR_LUAVALUE, "tableOf", TYPE_LUATABLE, new Type[] { Type.INT, Type.INT }, Constants.INVOKESTATIC));
}
public void loadEnv() {
append(InstructionConstants.THIS);
append(factory.createFieldAccess(classname, "env", TYPE_LUAVALUE, Constants.GETFIELD));
}
public void loadVarargs() {
append(new ALOAD(1));
}
public void loadVarargs(int argindex) {
loadVarargs();
arg(argindex);
}
public void arg(int argindex) {
if ( argindex == 1 ) {
append(factory.createInvoke(STR_VARARGS, "arg1", TYPE_LUAVALUE, new Type[] {}, Constants.INVOKEVIRTUAL));
} else {
append(new PUSH(cp, argindex));
append(factory.createInvoke(STR_VARARGS, "arg", TYPE_LUAVALUE, new Type[] { Type.INT }, Constants.INVOKEVIRTUAL));
}
}
private int getVarresultIndex() {
if ( varresult == null )
varresult = mg.addLocalVariable(NAME_VARRESULT, TYPE_VARARGS, null, null);
return varresult.getIndex();
}
public void loadVarresult() {
append(new ALOAD(getVarresultIndex()));
}
public void storeVarresult() {
append(new ASTORE(getVarresultIndex()));
}
public void subargs(int firstarg) {
append(new PUSH(cp, firstarg));
append(factory.createInvoke(STR_VARARGS, "subargs", TYPE_VARARGS, new Type[] { Type.INT }, Constants.INVOKEVIRTUAL));
}
public void getTable() {
append(factory.createInvoke(STR_LUAVALUE, "get", TYPE_LUAVALUE, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL));
}
public void setTable() {
append(factory.createInvoke(STR_LUAVALUE, "set", Type.VOID, new Type[] { TYPE_LUAVALUE, TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL));
}
public void unaryop(int o) {
String op;
switch (o) {
default:
case Lua.OP_UNM: op = "neg"; break;
case Lua.OP_NOT: op = "not"; break;
case Lua.OP_LEN: op = "len"; break;
}
append(factory.createInvoke(STR_LUAVALUE, op, TYPE_LUAVALUE, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
}
public void binaryop(int o) {
String op;
switch (o) {
default:
case Lua.OP_ADD: op = "add"; break;
case Lua.OP_SUB: op = "sub"; break;
case Lua.OP_MUL: op = "mul"; break;
case Lua.OP_DIV: op = "div"; break;
case Lua.OP_MOD: op = "mod"; break;
case Lua.OP_POW: op = "pow"; break;
}
append(factory.createInvoke(STR_LUAVALUE, op, TYPE_LUAVALUE, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL));
}
public void compareop(int o) {
String op;
switch (o) {
default:
case Lua.OP_EQ: op = "eq_b"; break;
case Lua.OP_LT: op = "lt_b"; break;
case Lua.OP_LE: op = "lteq_b"; break;
}
append(factory.createInvoke(STR_LUAVALUE, op, Type.BOOLEAN, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL));
}
public void areturn() {
append(InstructionConstants.ARETURN);
}
public void toBoolean() {
append(factory.createInvoke(STR_LUAVALUE, "toboolean", Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
}
public void tostring() {
append(factory.createInvoke(STR_BUFFER, "tostring", TYPE_LUASTRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
}
public void isNil() {
append(factory.createInvoke(STR_LUAVALUE, "isnil", Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
}
public void testForLoop() {
append(factory.createInvoke(STR_LUAVALUE, "testfor_b", Type.BOOLEAN, new Type[] { TYPE_LUAVALUE, TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL));
}
public void loadArrayArgs(int pc, int firstslot, int nargs) {
append(new PUSH(cp, nargs));
append(new ANEWARRAY(cp.addClass(STR_LUAVALUE)));
for ( int i=0; i<nargs; i++ ) {
append(InstructionConstants.DUP);
append(new PUSH(cp, i));
loadLocal(pc, firstslot++);
append(new AASTORE());
}
}
public void newVarargs(int pc, int firstslot, int nargs) {
switch ( nargs ) {
case 0: loadNone();
break;
case 1: loadLocal(pc, firstslot);
break;
case 2: loadLocal(pc, firstslot); loadLocal(pc, firstslot+1);
append(factory.createInvoke(STR_LUAVALUE, "varargsOf", TYPE_VARARGS, new Type[] { TYPE_LUAVALUE, TYPE_VARARGS }, Constants.INVOKESTATIC));
break;
case 3: loadLocal(pc, firstslot); loadLocal(pc, firstslot+1); loadLocal(pc, firstslot+2);
append(factory.createInvoke(STR_LUAVALUE, "varargsOf", TYPE_VARARGS, new Type[] { TYPE_LUAVALUE, TYPE_LUAVALUE, TYPE_VARARGS }, Constants.INVOKESTATIC));
break;
default:
loadArrayArgs(pc, firstslot, nargs);
append(factory.createInvoke(STR_LUAVALUE, "varargsOf", TYPE_VARARGS, new Type[] { new ArrayType( TYPE_LUAVALUE, 1 ) }, Constants.INVOKESTATIC));
break;
}
}
public void newVarargsVarresult(int pc, int firstslot, int nslots) {
loadArrayArgs(pc, firstslot, nslots );
loadVarresult();
append(factory.createInvoke(STR_LUAVALUE, "varargsOf", TYPE_VARARGS, new Type[] { new ArrayType( TYPE_LUAVALUE, 1 ), TYPE_VARARGS }, Constants.INVOKESTATIC));
}
public void call(int nargs) {
switch ( nargs ) {
case 0: append(factory.createInvoke(STR_LUAVALUE, "call", TYPE_LUAVALUE, new Type[] {}, Constants.INVOKEVIRTUAL)); break;
case 1: append(factory.createInvoke(STR_LUAVALUE, "call", TYPE_LUAVALUE, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); break;
case 2: append(factory.createInvoke(STR_LUAVALUE, "call", TYPE_LUAVALUE, new Type[] { TYPE_LUAVALUE, TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); break;
case 3: append(factory.createInvoke(STR_LUAVALUE, "call", TYPE_LUAVALUE, new Type[] { TYPE_LUAVALUE, TYPE_LUAVALUE, TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); break;
default: throw new IllegalArgumentException("can't call with "+nargs+" args");
}
}
public void newTailcallVarargs() {
append(factory.createInvoke(STR_LUAVALUE, "tailcallOf", TYPE_VARARGS, new Type[] { TYPE_LUAVALUE, TYPE_VARARGS }, Constants.INVOKESTATIC));
}
public void invoke(int nargs) {
switch ( nargs ) {
case -1: append(factory.createInvoke(STR_LUAVALUE, "invoke", TYPE_VARARGS, new Type[] { TYPE_VARARGS }, Constants.INVOKEVIRTUAL)); break;
case 0: append(factory.createInvoke(STR_LUAVALUE, "invoke", TYPE_VARARGS, new Type[] {}, Constants.INVOKEVIRTUAL)); break;
case 1: append(factory.createInvoke(STR_LUAVALUE, "invoke", TYPE_VARARGS, new Type[] { TYPE_VARARGS }, Constants.INVOKEVIRTUAL)); break;
case 2: append(factory.createInvoke(STR_LUAVALUE, "invoke", TYPE_VARARGS, new Type[] { TYPE_LUAVALUE, TYPE_VARARGS }, Constants.INVOKEVIRTUAL)); break;
case 3: append(factory.createInvoke(STR_LUAVALUE, "invoke", TYPE_VARARGS, new Type[] { TYPE_LUAVALUE, TYPE_LUAVALUE, TYPE_VARARGS }, Constants.INVOKEVIRTUAL)); break;
default: throw new IllegalArgumentException("can't invoke with "+nargs+" args");
}
}
// ------------------------ closures ------------------------
public void closureCreate(String protoname) {
append(factory.createNew(new ObjectType(protoname)));
append(InstructionConstants.DUP);
append(factory.createInvoke(protoname, "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
append(InstructionConstants.DUP);
loadEnv();
append(factory.createInvoke(STR_LUAVALUE, "setfenv", Type.VOID, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL));
}
public void closureInitUpvalueFromUpvalue(String protoname, int newup, int upindex) {
String srcname = upvalueName(upindex);
String destname = upvalueName(newup);
append(InstructionConstants.THIS);
append(factory.createFieldAccess(classname, srcname, TYPE_LOCALUPVALUE, Constants.GETFIELD));
append(factory.createFieldAccess(protoname, destname, TYPE_LOCALUPVALUE, Constants.PUTFIELD));
}
public void closureInitUpvalueFromLocal(String protoname, int newup, int pc, int srcslot) {
String destname = upvalueName(newup);
int index = findSlotIndex( srcslot, true );
append(new ALOAD(index));
append(factory.createFieldAccess(protoname, destname, TYPE_LOCALUPVALUE, Constants.PUTFIELD));
}
private Map<LuaValue,String> constants = new HashMap<LuaValue,String>();
public void loadConstant(LuaValue value) {
String name = constants.get(value);
if ( name == null ) {
name = value.type() == LuaValue.TNUMBER?
value.isinttype()?
createLuaIntegerField(value.checkint()):
createLuaDoubleField(value.checkdouble()):
createLuaStringField(value.checkstring());
constants.put(value, name);
}
append(factory.createGetStatic(classname, name, TYPE_LUAVALUE));
}
private String createLuaIntegerField(int value) {
String name = PREFIX_CONSTANT+constants.size();
FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL,
TYPE_LUAVALUE, name, cp);
cg.addField(fg.getField());
init.append(new PUSH(cp, value));
init.append(factory.createInvoke(STR_LUAVALUE, "valueOf",
TYPE_LUAINTEGER, new Type[] { Type.INT }, Constants.INVOKESTATIC));
init.append(factory.createPutStatic(classname, name, TYPE_LUAVALUE));
return name;
}
private String createLuaDoubleField(double value) {
String name = PREFIX_CONSTANT+constants.size();
FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL,
TYPE_LUAVALUE, name, cp);
cg.addField(fg.getField());
init.append(new PUSH(cp, value));
init.append(factory.createInvoke(STR_LUAVALUE, "valueOf",
TYPE_LUANUMBER, new Type[] { Type.DOUBLE }, Constants.INVOKESTATIC));
init.append(factory.createPutStatic(classname, name, TYPE_LUAVALUE));
return name;
}
private String createLuaStringField(LuaString value) {
String name = PREFIX_CONSTANT+constants.size();
FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL,
TYPE_LUAVALUE, name, cp);
cg.addField(fg.getField());
LuaString ls = value.checkstring();
if ( ls.isValidUtf8() ) {
init.append(new PUSH(cp, value.toString()));
init.append(factory.createInvoke(STR_LUASTRING, "valueOf",
TYPE_LUASTRING, new Type[] { Type.STRING }, Constants.INVOKESTATIC));
} else {
char[] c = new char[ls.m_length];
for ( int j=0; j<ls.m_length; j++ )
c[j] = (char) (0xff & (int) (ls.m_bytes[ls.m_offset+j]));
init.append(new PUSH(cp, new String(c)));
init.append(factory.createInvoke(STR_STRING, "toCharArray",
TYPE_CHARARRAY, Type.NO_ARGS,
Constants.INVOKEVIRTUAL));
init.append(factory.createInvoke(STR_LUASTRING, "valueOf",
TYPE_LUASTRING, new Type[] { TYPE_CHARARRAY },
Constants.INVOKESTATIC));
}
init.append(factory.createPutStatic(classname, name, TYPE_LUAVALUE));
return name;
}
// --------------------- branching support -------------------------
public static final int BRANCH_GOTO = 1;
public static final int BRANCH_IFNE = 2;
public static final int BRANCH_IFEQ = 3;
public void addBranch( int pc, int branchType, int targetpc ) {
switch ( branchType ) {
default:
case BRANCH_GOTO: branches[pc] = new GOTO(null); break;
case BRANCH_IFNE: branches[pc] = new IFNE(null); break;
case BRANCH_IFEQ: branches[pc] = new IFEQ(null); break;
}
targets[pc] = targetpc;
append(branches[pc]);
}
private void append( Instruction i ) {
conditionalSetBeginningOfLua( main.append(i) );
}
private void append( CompoundInstruction i ) {
conditionalSetBeginningOfLua( main.append(i) );
}
private void append( BranchInstruction i ) {
conditionalSetBeginningOfLua( main.append(i) );
}
private void conditionalSetBeginningOfLua(InstructionHandle ih) {
if ( beginningOfLuaInstruction == null )
beginningOfLuaInstruction = ih;
}
public void onEndOfLuaInstruction(int pc) {
branchDestHandles[pc] = beginningOfLuaInstruction;
beginningOfLuaInstruction = null;
}
private void resolveBranches() {
int nc = p.code.length;
for (int pc = 0; pc < nc; pc++) {
if (branches[pc] != null) {
if ( branchDestHandles[targets[pc]] == null )
throw new IllegalArgumentException("no target at "+targets[pc]+" op="+Lua.GET_OPCODE(p.code[targets[pc]]));
branches[pc].setTarget(branchDestHandles[targets[pc]]);
}
}
}
public void setlistStack(int pc, int a0, int index0, int nvals) {
for ( int i=0; i<nvals; i++ ) {
dup();
append(new PUSH(cp, index0+i));
loadLocal( pc, a0+i );
append(factory.createInvoke(STR_LUAVALUE, "rawset", Type.VOID, new Type[] { Type.INT, TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL));
}
}
public void setlistVarargs(int index0, int vresultbase) {
append(new PUSH(cp, index0));
loadVarresult();
append(factory.createInvoke(STR_LUAVALUE, "rawsetlist", Type.VOID, new Type[] { Type.INT, TYPE_VARARGS }, Constants.INVOKEVIRTUAL));
}
public void newBuffer() {
append(factory.createNew(TYPE_BUFFER));
append(InstructionConstants.DUP);
append(factory.createInvoke(STR_BUFFER, "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
}
public void appendBuffer() {
append(factory.createInvoke(STR_LUAVALUE, "checkstring", TYPE_LUASTRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
append(factory.createInvoke(STR_BUFFER, "append", Type.VOID, new Type[] { TYPE_LUASTRING }, Constants.INVOKEVIRTUAL));
}
}

View File

@@ -1,129 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc;
import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.LuaClosure;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.LoadState.LuaCompiler;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.PackageLib;
public class JavaBytecodeCompiler implements LuaCompiler {
private static JavaBytecodeCompiler instance;
private JavaBytecodeGenerator gen;
private LuaC luac;
public static JavaBytecodeCompiler getInstance() {
if ( instance == null )
instance = new JavaBytecodeCompiler();
return instance;
}
/**
* Install the compiler as the main compiler to use.
* Will fall back to the LuaC prototype compiler.
*/
public static final void install() {
LoadState.compiler = getInstance();
}
public JavaBytecodeCompiler() {
luac = new LuaC();
gen = new JavaBytecodeGenerator();
}
/** Compile int a prototype */
public static Prototype compile(InputStream is, String chunkname) throws IOException {
return getInstance().compile(is.read(), is, chunkname);
}
/** Compile and load a chunk
* @throws IOException */
public static LuaValue load(InputStream is, String filename, LuaValue _g) throws IOException {
return getInstance().load(is.read(), is, filename, _g);
}
/** Compile into protoype form. */
public Prototype compile(int firstByte, InputStream stream, String chunkname) throws IOException {
return luac.compile(firstByte, stream, chunkname);
}
/** Compile and load a chunk
* @throws IOException */
public static byte[] loadClass(InputStream is, String filename) throws IOException {
return getInstance().loadClass( is.read(), is, filename );
}
/** Compile into class form. */
public LuaFunction load(int firstByte, InputStream stream, String filename, LuaValue env) throws IOException {
Prototype p = compile( firstByte, stream, filename);
return load( p, filename, env );
}
/** Compile into a class */
private byte[] loadClass(int firstByte, InputStream stream, String filename) throws IOException {
Prototype p = compile(firstByte, stream, filename);
return gen.generateBytecode(p, PackageLib.toClassname(filename), toSourcename(filename));
}
/** Compile all classes produced by a prototype, and put results in a hashtable */
public static Hashtable loadClasses( InputStream stream, String filename ) throws IOException {
if ( LoadState.compiler == null )
install();
Prototype p = LoadState.compile( stream, filename );
Hashtable t = new Hashtable();
getInstance().genClass(t, p, PackageLib.toClassname(filename), toSourcename(filename));
return t;
}
private void genClass( Hashtable t, Prototype p, String classname, String sourceName ) throws IOException {
t.put( classname, gen.generateBytecode( p, classname, sourceName ) );
for ( int i=0, n=p.p!=null? p.p.length: 0; i<n; i++ )
genClass( t, p.p[i], classname + "$" + i, sourceName );
}
public LuaFunction load(Prototype p, String filename, LuaValue env) {
try {
Class c = gen.toJavaBytecode(p, PackageLib.toClassname(filename), toSourcename(filename));
Object o = c.newInstance();
LuaFunction f = (LuaFunction) o;
f.setfenv(env);
return f;
} catch ( Throwable t ) {
t.printStackTrace();
return new LuaClosure( p, env );
}
}
private static final String toSourcename( String filename ) {
return filename.substring( filename.lastIndexOf('/')+1 );
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,785 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import org.luaj.vm2.lib.LibFunction;
import org.luaj.vm2.luajc.lst.LSChunk;
import org.luaj.vm2.luajc.lst.LSExpression;
import org.luaj.vm2.luajc.lst.LSField;
import org.luaj.vm2.luajc.lst.LSFunction;
import org.luaj.vm2.luajc.lst.LSIfStatement;
import org.luaj.vm2.luajc.lst.LSStatement;
import org.luaj.vm2.luajc.lst.LSVariable;
import org.luaj.vm2.luajc.lst.Name;
import org.luaj.vm2.luajc.lst.Scope;
import org.luaj.vm2.luajc.lst.LSExpression.BinopExpr;
import org.luaj.vm2.luajc.lst.LSExpression.FunctionExpr;
import org.luaj.vm2.luajc.lst.LSExpression.NumberConstant;
import org.luaj.vm2.luajc.lst.LSExpression.StringConstant;
import org.luaj.vm2.luajc.lst.LSExpression.TableConstructor;
import org.luaj.vm2.luajc.lst.LSExpression.UnopExpr;
import org.luaj.vm2.luajc.lst.LSExpression.VarargsRef;
import org.luaj.vm2.luajc.lst.LSStatement.BreakStat;
import org.luaj.vm2.luajc.lst.LSStatement.DoBlock;
import org.luaj.vm2.luajc.lst.LSStatement.ForList;
import org.luaj.vm2.luajc.lst.LSStatement.ForLoop;
import org.luaj.vm2.luajc.lst.LSStatement.FunctionCall;
import org.luaj.vm2.luajc.lst.LSStatement.LocalAssign;
import org.luaj.vm2.luajc.lst.LSStatement.LocalFunction;
import org.luaj.vm2.luajc.lst.LSStatement.RepeatUntil;
import org.luaj.vm2.luajc.lst.LSStatement.ReturnStat;
import org.luaj.vm2.luajc.lst.LSStatement.VarAssign;
import org.luaj.vm2.luajc.lst.LSStatement.VarNamedFunction;
import org.luaj.vm2.luajc.lst.LSStatement.WhileLoop;
import org.luaj.vm2.luajc.lst.LSVariable.CallFunction;
import org.luaj.vm2.luajc.lst.LSVariable.CallMethod;
import org.luaj.vm2.luajc.lst.LSVariable.Field;
import org.luaj.vm2.luajc.lst.LSVariable.Index;
import org.luaj.vm2.luajc.lst.LSVariable.Method;
import org.luaj.vm2.luajc.lst.LSVariable.NameReference;
import org.luaj.vm2.luajc.lst.LSVariable.Parentheses;
public class JavaCodeGenerator {
public static String toJava(LSChunk chunk) {
JavaCodeGenerator jcg = new JavaCodeGenerator();
return jcg.writeChunk( chunk );
}
public final Stack<StringBuffer> stringBuffers = new Stack<StringBuffer>();
public StringBuffer sb;
private int indent = 0;
public JavaCodeGenerator() {
this.sb = new StringBuffer();
}
private String writeChunk(LSChunk chunk) {
pushFunctionContext();
writeln( "import org.luaj.vm2.*;" );
writeln( "import org.luaj.vm2.lib.*;" );
writeln();
writeln( "public class "+chunk.chunkname+" extends VarArgFunction {" );
++indent;
writeln( "public Varargs invoke(Varargs $args) {");
++indent;
writeFunctionBody( chunk.function );
--indent;
writeln( "}");
--indent;
// TODO: write out chunk constants
writeln( "}" );
return popFunctionContext();
}
private void pushFunctionContext() {
stringBuffers.push( sb = new StringBuffer() );
}
private String popFunctionContext() {
String v = stringBuffers.pop().toString();
sb = stringBuffers.isEmpty()? null: stringBuffers.lastElement();
return v;
}
private void writeFunctionBody(LSFunction function) {
if ( function.hasandlogic || function.hasorlogic )
writeln( "LuaValue $t;" );
if ( function.hasvarargassign )
writeln( "Varargs $v;" );
writeStatements( function.stats );
if ( LSStatement.isNextStatementReachable( function.stats ) )
writeln( "return NONE;" );
}
private void writeStatements(List<LSStatement> statements) {
for ( LSStatement s : statements ) {
writeStatement( s );
}
}
private void writeStatement(LSStatement s) {
if ( s==null ) return;
switch ( s.type ) {
case functionCall: writeFunctionCall( (LSStatement.FunctionCall) s ); break;
case doBlock: writeDoBlock( (LSStatement.DoBlock) s ); break;
case whileLoop: writeWhileLoop( (LSStatement.WhileLoop) s ); break;
case repeatUntil: writeRepeatUntil( (LSStatement.RepeatUntil) s ); break;
case varAssign: writeVarAssign( (LSStatement.VarAssign) s ); break;
case forLoop: writeForLoop( (LSStatement.ForLoop) s ); break;
case forList: writeForList( (LSStatement.ForList) s ); break;
case varNamedFunction: writeVarNamedFunction((LSStatement.VarNamedFunction) s ); break;
case localFunction: writeLocalFunction( (LSStatement.LocalFunction) s ); break;
case localAssign: writeLocalAssign( (LSStatement.LocalAssign) s ); break;
case returnStat: writeReturnStat( (LSStatement.ReturnStat) s ); break;
case breakStat: writeBreakStat( (LSStatement.BreakStat) s ); break;
case ifStat: writeIfStat( (LSIfStatement) s ); break;
}
}
private void writeFunctionCall(FunctionCall s) {
writeindent();
write( eval(s.variable)+";" );
writeln();
}
private void writeDoBlock(DoBlock s) {
writeln( "{" );
++indent;
writeStatements( s.statements );
--indent;
writeln( "}" );
}
private void writeWhileLoop(WhileLoop s) {
writeln( "while ("+eval(s.condition)+".toboolean()) {" );
++indent;
writeStatements( s.statements );
--indent;
writeln( "}" );
}
private void writeRepeatUntil(RepeatUntil s) {
writeln( "do {" );
++indent;
writeStatements( s.statements );
--indent;
writeln( "} while (!"+eval(s.condition)+");" );
}
private void writeForLoop(ForLoop s) {
writeln( "{" );
++indent;
// TODO: name handling, also upvalues!
String index = javaName( s.index );
String limit = javaName( s.scope.declare("$limit") );
String step = javaName( s.scope.declare("$step") );
writeln( "LuaValue "+index+"="+eval(s.initial)+";" );
writeln( "final LuaValue "+limit+"="+eval(s.limit)+";" );
if ( s.step != null ) {
writeln( "final LuaValue "+step+"="+eval(s.step)+";" );
writeln( "final boolean "+step+"$b="+step+".gt_b(0);" );
}
if ( s.step != null ) {
writeln( "for ( ; "+index+".testfor_b("+limit+","+step+"$b); "+index+"="+index+".add("+step+") ) {" );
} else {
writeln( "for ( ; "+index+".lteq_b("+limit+"); "+index+"="+index+".add(1) ) {" );
}
++indent;
writeStatements( s.statements );
--indent;
writeln( "}" );
--indent;
writeln( "}" );
}
private void writeForList(ForList s) {
writeln( "{" );
++indent;
List<String> exprs = evalExpressions(s.expressions, 3, s.scope);
// TODO: upvalues handling!
String fun = javaName( s.scope.declare("$f") );
String sta = javaName( s.scope.declare("$s") );
String var = javaName( s.scope.declare("$var") );
String res = javaName( s.scope.declare("$res") );
writeln( "LuaValue "+fun+"="+exprs.get(0)+";" );
writeln( "LuaValue "+sta+"="+exprs.get(1)+";" );
writeln( "LuaValue "+var+"="+exprs.get(2)+";" );
writeln( "while ( true ) {" );
++indent;
writeln( "Varargs "+res+" = "+fun+".invoke(varargsOf("+sta+","+var+"));" );
for ( int i=1, n=s.names.size(); i<=n; i++ )
writeln( "LuaValue "+javaName(s.names.get(i-1))+"="+res+".arg("+i+");" );
writeln( var+"="+javaName(s.names.get(0))+";" );
writeln( "if ( "+var+".isnil() ) break;" );
writeStatements( s.statements );
--indent;
writeln( "}" );
--indent;
writeln( "}" );
}
private final static Set<String> reserved = new HashSet<String>();
static {
String[] specials = {
// keywors used by our code generator
"name", "opcode", "env",
// java keywords
"abstract", "continue", "for", "new", "switch",
"assert", "default", "goto", "package", "synchronized",
"boolean", "do", "if", "private", "this",
"break", "double", "implements", "protected", "throw",
"byte", "else", "import", "public", "throws",
"case", "enum", "instanceof", "return", "transient",
"catch", "extends", "int", "short", "try",
"char", "final", "interface", "static", "void",
"class", "finally", "long", "strictfp", "volatile",
"const", "float", "native", "super", "while",
};
for ( int i=0; i<specials.length; i++ )
reserved.add( specials[i] );
java.lang.reflect.Field[] f = LibFunction.class.getFields();
for ( int i=0; i<f.length; i++ )
reserved.add( f[i].getName() );
}
private String javaName(Name name) {
return name.innerrevision>0?
name.luaname+"$"+name.innerrevision:
reserved.contains(name.luaname)? (name.luaname+"$"): name.luaname;
}
private void writeVarNamedFunction(VarNamedFunction s) {
String funcdef = evalFuncbody(s.funcbody);
writeAssign( s.funcname, funcdef );
}
private String evalFuncbody(LSFunction funcbody) {
pushFunctionContext();
int n = funcbody.paramnames!=null? funcbody.paramnames.size(): 0;
boolean isvararg = (funcbody.isvararg || n > 3);
if ( isvararg ) {
write( "new VarArgFunction(env) {\n" );
++indent;
writeln( "public Varargs invoke(Varargs $args) {" );
++indent;
for ( int i=0; i<n; i++ ) {
Name name = funcbody.paramnames.get(i);
if ( name.isupvalue )
writeln( "final LuaValue[] "+javaName(funcbody.paramnames.get(i))+"={$args.arg("+(i+1)+")};" );
else
writeln( "LuaValue "+javaName(funcbody.paramnames.get(i))+"=$args.arg("+(i+1)+");" );
}
if ( (n > 0 && funcbody.usesvarargs) || funcbody.needsarg )
writeln( "$args = $args.subargs("+(n+1)+");" );
if ( funcbody.needsarg )
writeln( "LuaValue arg = new LuaTable($args);" );
else if ( funcbody.hasarg )
writeln( "LuaValue arg = NIL;" );
writeFunctionBody(funcbody);
--indent;
writeln( "}" );
--indent;
writeindent();
write( "}" );
} else {
write(
n==0? "new ZeroArgFunction(env) {\n":
n==1? "new OneArgFunction(env) {\n":
n==2? "new TwoArgFunction(env) {\n":
"new ThreeArgFunction(env) {\n" );
++indent;
writeindent();
write( "public LuaValue call(");
for ( int i=0; i<n; i++ ) {
if (i>0) write( "," );
Name name = funcbody.paramnames.get(i);
if ( name.isupvalue )
write( "LuaValue "+javaName(name)+"$u" );
else
write( "LuaValue "+javaName(name) );
}
write( ") {" );
writeln();
++indent;
// upvalues
for ( int i=0; i<n; i++ ) {
Name name = funcbody.paramnames.get(i);
if ( name.isupvalue )
writeln( "final LuaValue[] "+javaName(name)+"={"+javaName(name)+"$u};" );
}
// function body
writeFunctionBody(funcbody);
--indent;
writeln( "}" );
--indent;
writeindent();
write( "}" );
}
return popFunctionContext();
}
private void writeVarAssign(VarAssign s) {
int nassign = s.variables.size();
List<String> exprs = evalExpressions(s.expressions, nassign, s.scope);
for ( int i=0; i<nassign; i++ )
writeAssign( s.variables.get(i), exprs.get(i) );
for ( int i=nassign; i<exprs.size(); i++ )
writeln( exprs.get(i) );
}
private void writeLocalFunction(LocalFunction s) {
String funcdef = evalFuncbody(s.funcbody);
if ( s.name.isupvalue ) {
writeln( "final LuaValue[] "+javaName(s.name)+"={null};" );
writeln( javaName(s.name)+"[0]="+funcdef+";" );
} else
writeln( "LuaValue "+javaName(s.name)+"="+funcdef+";" );
}
private void writeLocalAssign(LocalAssign s) {
int nassign = s.names.size();
List<String> exprs = evalExpressions(s.expressions, nassign, s.scope);
for ( int i=0; i<nassign; i++ ) {
Name name= s.names.get(i);
if ( name.isupvalue )
writeln( "final LuaValue[] "+javaName(name)+"={"+exprs.get(i)+"};" );
else
writeln( "LuaValue "+javaName(name)+"="+exprs.get(i)+";" );
}
for ( int i=nassign; i<exprs.size(); i++ )
writeln( exprs.get(i)+";" );
}
/** Evaluate expressions for use in assignment
* @param scope */
private List<String> evalExpressions(List<LSExpression> exprs, int nassign, Scope scope) {
int nexpr = (exprs!=null? exprs.size(): 0);
List<String> e = new ArrayList<String>(nexpr);
boolean hasvarargs = false;
for ( int i=0; i<nexpr || i<nassign; i++ ) {
if ( i<nexpr-1 || nassign <= nexpr ) {
e.add( eval( exprs.get(i) ) );
} else if ( i==nexpr-1 ) {
int nr = exprs.get(i).getNumReturns();
hasvarargs = (nr==-1) || (nr>1);
if ( hasvarargs )
e.add( "($v="+eval(exprs.get(i))+").arg1()" );
else
e.add( eval(exprs.get(i)) );
} else if (hasvarargs) {
e.add( "$v.arg("+(i-nexpr+2)+")" );
} else {
e.add( "NIL" );
}
}
return e;
}
private void writeReturnStat(ReturnStat s) {
int n = s.expressions!=null? s.expressions.size(): 0;
if ( ! s.function.isvararg )
writeln( n==0? "return NONE;": "return "+eval(s.expressions.get(0))+";" );
else {
writeindent();
switch ( n ) {
case 0:
write( "return NONE;" );
break;
case 1:
write( "return "+eval( s.expressions.get(0))+";" );
break;
case 2: case 3: {
write( "return varargsOf(" );
for ( int i=0; i<n; i++ ) {
if (i>0) write( "," );
write( eval( s.expressions.get(i)) );
}
write( ");" );
break;
}
default: {
write( "return varargsOf(new LuaValue[] {" );
for ( int i=0; i<n-1; i++ ) {
if (i>0) write( "," );
write( eval( s.expressions.get(i)) );
}
write( "},"+eval(s.expressions.get(n-1))+");" );
break;
}
}
writeln();
}
}
private void writeBreakStat(BreakStat s) {
writeln( "break;" );
}
private void writeIfStat(LSIfStatement s) {
writeln( "if ("+eval_bool(s.condition)+") {" );
++indent;
writeStatements( s.statements );
if ( s.elseifs != null ) {
for ( LSIfStatement.ElseIf elseif : s.elseifs ) {
--indent;
writeln( "} else if ("+eval_bool(elseif.condition)+") {" );
++indent;
writeStatements( elseif.statements );
}
}
if ( s.elsestatements != null ) {
--indent;
writeln( "} else {" );
++indent;
writeStatements( s.elsestatements );
}
--indent;
writeln( "}" );
}
//-------------------------------------------
// assignment using variables
//-------------------------------------------
/** Write assignment of a particular variable value */
private void writeAssign(LSVariable v, String expression) {
switch ( v.type ) {
case nameVariable: writeNameAssign( (LSVariable.NameReference) v, expression); break;
case fieldVariable: writeFieldAssign( (LSVariable.Field) v, expression); break;
case methodVariable: writeMethodAssign( (LSVariable.Method) v, expression); break;
case parenthesesVariable: writeParenAssign( (LSVariable.Parentheses) v, expression); break;
case indexVariable: writeIndexAssign( (LSVariable.Index) v, expression); break;
case callFunctionVariable: writeCallFuncAssign((LSVariable.CallFunction)v, expression); break;
case callMethodVariable: writeCallMethAssign((LSVariable.CallMethod) v, expression); break;
}
}
private void writeNameAssign(NameReference v, String expression) {
if ( v.name.isGlobal() )
writeln( "env.set(\""+v.name.luaname+"\","+expression+");");
else if ( v.name.isupvalue )
writeln( javaName(v.name)+"[0]="+expression+";");
else
writeln( javaName(v.name)+"="+expression+";");
}
private void writeFieldAssign(Field v, String expression) {
String base = eval(v.variable);
writeln( base+".set(\""+v.field+"\","+expression+");");
}
private void writeMethodAssign(Method v, String expression) {
String base = eval(v.variable);
writeln( base+".set(\""+v.method+"\","+expression+");");
}
private void writeParenAssign(Parentheses v, String expression) {
throw new IllegalArgumentException("no assignment for parenthesis expressions");
}
private void writeIndexAssign(Index v, String expression) {
String base = eval(v.variable);
writeln( base+".set("+eval(v.expression)+","+expression+");");
}
private void writeCallFuncAssign(CallFunction v, String expression) {
throw new IllegalArgumentException("no assignment for call function expressions");
}
private void writeCallMethAssign(CallMethod v, String expression) {
throw new IllegalArgumentException("no assignment for call method expressions");
}
//-------------------------------------------
// write out expressions
//-------------------------------------------
private String eval_bool(LSExpression e) {
return eval(e)+".toboolean()";
}
/** evaluate the expression to a particular operand type */
private String eval(LSExpression e) {
if ( e==null ) return "NONE";
switch ( e.type ) {
case nilConstant: return "NIL";
case trueConstant: return "TRUE";
case falseConstant: return "FALSE";
case unop: return evalUnop( (LSExpression.UnopExpr) e);
case binop: return evalBinop( (LSExpression.BinopExpr) e);
case functionExpr: return evalFunction((LSExpression.FunctionExpr) e);
case tableConstructor: return evalTable( (LSExpression.TableConstructor) e);
case numberConstant: return evalNumber( (LSExpression.NumberConstant) e);
case stringConstant: return evalString( (LSExpression.StringConstant) e);
// variable types
case nameVariable: return evalNameRef( (LSVariable.NameReference) e);
case fieldVariable: return evalField( (LSVariable.Field) e);
case methodVariable: return evalMethod( (LSVariable.Method) e);
case parenthesesVariable: return evalParen( (LSVariable.Parentheses) e);
case indexVariable: return evalIndex( (LSVariable.Index) e);
case callFunctionVariable: return evalCallFunc((LSVariable.CallFunction) e);
case callMethodVariable: return evalCallMeth((LSVariable.CallMethod) e);
case varargsRef: return evalVarargs( (LSExpression.VarargsRef) e);
default: throw new IllegalArgumentException("unknown expression type: "+e.type);
}
}
private String evalUnop(UnopExpr e) {
switch ( e.op.type ) {
case neg: return eval( e.rhs )+".neg()";
case not: return eval( e.rhs )+".not()";
case len: return eval( e.rhs )+".len()";
}
throw new IllegalArgumentException("unknown unary operand: "+e.op );
}
private String evalBinop(BinopExpr e) {
switch ( e.op.type ) {
case pow: return eval(e.lhs)+".pow("+eval(e.rhs)+")";
case mul: return eval(e.lhs)+".mul("+eval(e.rhs)+")";
case div: return eval(e.lhs)+".div("+eval(e.rhs)+")";
case mod: return eval(e.lhs)+".mod("+eval(e.rhs)+")";
case add: return eval(e.lhs)+".add("+eval(e.rhs)+")";
case sub: return eval(e.lhs)+".sub("+eval(e.rhs)+")";
case concat: return eval(e.lhs)+".concat("+eval(e.rhs)+")";
case lt: return eval(e.lhs)+".lt("+eval(e.rhs)+")";
case lteq: return eval(e.lhs)+".lteq("+eval(e.rhs)+")";
case gt: return eval(e.lhs)+".gt("+eval(e.rhs)+")";
case gteq: return eval(e.lhs)+".gteq("+eval(e.rhs)+")";
case eq: return eval(e.lhs)+".eq("+eval(e.rhs)+")";
case neq: return eval(e.lhs)+".neq("+eval(e.rhs)+")";
case and: return "(($t="+eval(e.lhs)+").toboolean()? "+eval(e.rhs)+": $t)";
case or: return "(($t="+eval(e.lhs)+").toboolean()? $t: "+eval(e.rhs)+")";
default: throw new IllegalStateException("unknoqn binary operator: "+e.op);
}
}
private String evalFunction(FunctionExpr e) {
return evalFuncbody(e.function);
}
private String evalTable(TableConstructor e) {
StringBuffer named = new StringBuffer();
StringBuffer numbered = new StringBuffer();
LSExpression varargsLastListValue = null;
for ( int i=0, n=e.fields.size(); i<n; i++ ) {
LSField f = e.fields.get(i);
switch ( f.type ) {
case keyValue:
LSField.KeyValue k = (LSField.KeyValue) f;
named.append( eval(k.key)+","+eval(k.value)+",");
break;
case nameValue:
LSField.NameValue nv = (LSField.NameValue) f;
named.append( "valueOf(\""+nv.name+"\"),"+eval(nv.value)+",");
break;
case listValue:
LSField.ListValue l = (LSField.ListValue) f;
int nr = l.value.getNumReturns();
if ( i<n-1 && (nr==1) )
numbered.append( eval(l.value)+",");
else
varargsLastListValue = l.value;
break;
}
}
// TODO: generated more targeted constructor
return "tableOf("
+(named .length()>0? "new LuaValue[] {"+named +"}": "null")+","
+(numbered.length()>0? "new LuaValue[] {"+numbered+"}": "null")
+(varargsLastListValue!=null? ","+eval(varargsLastListValue): "")+")";
}
private String evalNumber(NumberConstant e) {
// TODO: internalize constants
return "valueOf("+e.value+")";
}
private String evalString(StringConstant e) {
// TODO: internalize constants
return "valueOf("+toStrValueInitializer(e.bytes)+")";
}
private String toStrValueInitializer(byte[] bytes) {
int n = bytes.length;
StringBuffer sb = new StringBuffer(n+2);
// check for characters beyond ascii 128
for ( int i=0; i<n; i++ )
if (bytes[i]<0) {
sb.append( "new byte[]{" );
for ( int j=0; j<n; j++ ) {
if ( j>0 ) sb.append(",");
byte b = bytes[j];
switch ( b ) {
case '\n': sb.append( "'\\n'" ); break;
case '\r': sb.append( "'\\r'" ); break;
case '\t': sb.append( "'\\t'" ); break;
case '\\': sb.append( "'\\\\'" ); break;
default:
if ( b >= ' ' ) {
sb.append( '\'');
sb.append( (char) b );
sb.append( '\'');
} else {
sb.append( String.valueOf((int)b) );
}
break;
}
}
sb.append( "}" );
return sb.toString();
}
sb.append('"');
for ( int i=0; i<n; i++ ) {
byte b = bytes[i];
switch ( b ) {
case '\b': sb.append( "\\b" ); break;
case '\f': sb.append( "\\f" ); break;
case '\n': sb.append( "\\n" ); break;
case '\r': sb.append( "\\r" ); break;
case '\t': sb.append( "\\t" ); break;
case '"': sb.append( "\\\"" ); break;
case '\\': sb.append( "\\\\" ); break;
default:
if ( b >= ' ' ) {
sb.append( (char) b ); break;
} else {
// convert from UTF-8
int u = 0xff & (int) b;
if ( u>=0xc0 && i+1<n ) {
if ( u>=0xe0 && i+2<n ) {
u = ((u & 0xf) << 12) | ((0x3f & bytes[i+1]) << 6) | (0x3f & bytes[i+2]);
i+= 2;
} else {
u = ((u & 0x1f) << 6) | (0x3f & bytes[++i]);
}
}
sb.append( "\\u" );
sb.append( Integer.toHexString(0x10000+u).substring(1) );
}
}
}
sb.append('"');
return sb.toString();
}
private String evalNameRef(NameReference v) {
if ( v.name.isGlobal() )
return "env.get(\""+v.name.luaname+"\")";
else if ( v.name.isupvalue )
return javaName(v.name)+"[0]";
else
return javaName(v.name);
}
private String evalField(Field e) {
return eval(e.variable)+".get(\""+e.field+"\")";
}
private String evalMethod(Method e) {
// FIXME: check api, fix this
return eval(e.variable)+".get(\""+e.method+"\")";
}
private String evalParen(Parentheses e) {
return eval(e.expression)+".arg1()";
}
private String evalIndex(Index e) {
return eval(e.variable)+".get("+eval(e.expression)+")";
}
private String evalCallFunc(CallFunction e) {
int n = e.parameters.size();
boolean isVarargsReturn = e.numReturns < 0 || e.numReturns > 1;
boolean isVarargsCall = n>0 && e.parameters.get(n-1).getNumReturns() < 0;
String base = eval(e.variable);
if ( n <= 3 && !isVarargsReturn && !isVarargsCall ) {
return base+".call("+evalParamList(e.parameters)+")";
} else {
String coerce = e.numReturns==1? ".arg1()": "";
switch ( n ) {
case 0:
return base+".invoke()"+coerce;
case 1:
case 2:
case 3:
return base+".invoke("+evalParamList(e.parameters)+")"+coerce;
default:
if ( isVarargsCall ) {
LSExpression last = e.parameters.remove(n-1);
return base+".invoke(new LuaValue[]{"+evalParamList(e.parameters)+"},"+eval(last)+")"+coerce;
} else {
return base+".invoke(new LuaValue[]{"+evalParamList(e.parameters)+"})"+coerce;
}
}
}
}
private String evalCallMeth(CallMethod e) {
int n = e.parameters.size();
String base = eval(e.variable);
if ( n <= 3 && e.numReturns == 0 || e.numReturns == 1 ) {
return base+".method(\""+e.method+"\""+(e.parameters.size()>0? ",": "")+evalParamList(e.parameters)+")";
} else {
return base+".invokemethod(\""+e.method+"\",new LuaValue[]{"+evalParamList(e.parameters)+"})";
}
}
private String evalVarargs(VarargsRef e) {
switch ( e.numReturns ) {
case 0: return "NIL";
case 1: return "$args.arg1()";
default: return "$args";
}
}
private String evalParamList(List<LSExpression> parameters) {
if ( parameters == null || parameters.size() == 0 )
return "";
StringBuffer p = new StringBuffer();
for ( int i=0, n=parameters.size(); i<n; i++ ) {
if (i>0) p.append(",");
p.append( eval( parameters.get(i) ) );
}
return p.toString();
}
//-------------------------------------------
// write individual strings and lines
//-------------------------------------------
private void writeindent() {
for ( int i=0; i<indent; i++ )
sb.append( " " );
}
private void write( String str ) {
sb.append( str );
}
private void writeln() {
sb.append( '\n' );
}
private void writeln( String line ) {
writeindent();
write( line );
writeln();
}
}

View File

@@ -0,0 +1,418 @@
/*******************************************************************************
* Copyright (c) 2010 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc;
import org.luaj.vm2.Lua;
import org.luaj.vm2.Prototype;
/**
* TODO:
* propogate constants
* loader can find inner classes
*/
public class JavaGen {
public String classname;
public byte[] bytecode;
public JavaGen[] inners;
public JavaGen( Prototype p, String classname, String filename ) {
this.classname = classname;
// build this class
JavaBuilder builder = new JavaBuilder(p, classname, filename);
scanInstructions(p, classname, builder);
this.bytecode = builder.completeClass();
// build sub-prototypes
int n = p.p.length;
inners = new JavaGen[n];
for ( int i=0; i<n; i++ )
inners[i] = new JavaGen(p.p[i], closureName(classname,i), filename);
}
private String closureName(String classname, int subprotoindex) {
return classname+"$"+subprotoindex;
}
private void scanInstructions(Prototype p, String classname, JavaBuilder builder) {
int vresultbase = -1;
for ( int pc=0, n=p.code.length; pc<n; pc++ ) {
int ins = p.code[pc];
int o = Lua.GET_OPCODE(ins);
int a = Lua.GETARG_A(ins);
int b = Lua.GETARG_B(ins);
int bx = Lua.GETARG_Bx(ins);
int sbx = Lua.GETARG_sBx(ins);
int c = Lua.GETARG_C(ins);
switch ( o ) {
case Lua.OP_GETUPVAL: /* A B R(A):= UpValue[B] */
builder.loadUpvalue( b );
builder.storeLocal( pc, a );
break;
case Lua.OP_SETUPVAL: /* A B UpValue[B]:= R(A) */
builder.storeUpvalue( pc, b, a );
break;
case Lua.OP_NEWTABLE: /* A B C R(A):= {} (size = B,C) */
builder.newTable( b, c );
builder.storeLocal( pc, a );
break;
case Lua.OP_MOVE:/* A B R(A):= R(B) */
builder.loadLocal( pc, b );
builder.storeLocal( pc, a );
break;
case Lua.OP_UNM: /* A B R(A):= -R(B) */
case Lua.OP_NOT: /* A B R(A):= not R(B) */
case Lua.OP_LEN: /* A B R(A):= length of R(B) */
builder.loadLocal( pc, b );
builder.unaryop( o );
builder.storeLocal( pc, a );
break;
case Lua.OP_LOADK:/* A Bx R(A):= Kst(Bx) */
builder.loadConstant( p.k[bx] );
builder.storeLocal( pc, a );
break;
case Lua.OP_GETGLOBAL: /* A Bx R(A):= Gbl[Kst(Bx)] */
builder.loadEnv();
builder.loadConstant( p.k[bx] );
builder.getTable();
builder.storeLocal( pc, a );
break;
case Lua.OP_SETGLOBAL: /* A Bx Gbl[Kst(Bx)]:= R(A) */
builder.loadEnv();
builder.loadConstant( p.k[bx] );
builder.loadLocal( pc, a );
builder.setTable();
break;
case Lua.OP_LOADNIL: /* A B R(A):= ...:= R(B):= nil */
builder.loadNil();
for ( ; a<=b; a++ ) {
if ( a < b )
builder.dup();
builder.storeLocal( pc, a );
}
break;
case Lua.OP_GETTABLE: /* A B C R(A):= R(B)[RK(C)] */
builder.loadLocal( pc, b );
loadLocalOrConstant( p, builder, pc, c );
builder.getTable();
builder.storeLocal( pc, a );
break;
case Lua.OP_SETTABLE: /* A B C R(A)[RK(B)]:= RK(C) */
builder.loadLocal( pc, a );
loadLocalOrConstant( p, builder, pc, b );
loadLocalOrConstant( p, builder, pc, c );
builder.setTable();
break;
case Lua.OP_ADD: /* A B C R(A):= RK(B) + RK(C) */
case Lua.OP_SUB: /* A B C R(A):= RK(B) - RK(C) */
case Lua.OP_MUL: /* A B C R(A):= RK(B) * RK(C) */
case Lua.OP_DIV: /* A B C R(A):= RK(B) / RK(C) */
case Lua.OP_MOD: /* A B C R(A):= RK(B) % RK(C) */
case Lua.OP_POW: /* A B C R(A):= RK(B) ^ RK(C) */
loadLocalOrConstant( p, builder, pc, b );
loadLocalOrConstant( p, builder, pc, c );
builder.binaryop( o );
builder.storeLocal( pc, a );
break;
case Lua.OP_SELF: /* A B C R(A+1):= R(B): R(A):= R(B)[RK(C)] */
builder.loadLocal(pc,b);
builder.dup();
builder.storeLocal(pc, a+1);
loadLocalOrConstant( p, builder, pc, c );
builder.getTable();
builder.storeLocal(pc, a);
break;
case Lua.OP_CONCAT: /* A B C R(A):= R(B).. ... ..R(C) */
builder.newBuffer();
while ( b<=c ) {
builder.dup();
builder.loadLocal(pc, b++);
builder.appendBuffer();
}
builder.tostring();
builder.storeLocal(pc, a);
break;
case Lua.OP_LOADBOOL:/* A B C R(A):= (Bool)B: if (C) pc++ */
builder.loadBoolean( b!=0 );
builder.storeLocal( pc, a );
//if ( c != 0 ) branchdest[index+2] = true;
break;
case Lua.OP_JMP: /* sBx pc+=sBx */
builder.addBranch(pc, JavaBuilder.BRANCH_GOTO, pc+1+sbx);
break;
case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
loadLocalOrConstant( p, builder, pc, b );
loadLocalOrConstant( p, builder, pc, c );
builder.compareop(o);
builder.addBranch(pc, (a!=0? JavaBuilder.BRANCH_IFEQ: JavaBuilder.BRANCH_IFNE), pc+2);
break;
case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */
builder.loadLocal( pc, a );
builder.toBoolean();
builder.addBranch(pc, (c!=0? JavaBuilder.BRANCH_IFEQ: JavaBuilder.BRANCH_IFNE), pc+2);
break;
case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A):= R(B) else pc++ */
builder.loadLocal( pc, b );
builder.toBoolean();
builder.addBranch(pc, (c!=0? JavaBuilder.BRANCH_IFEQ: JavaBuilder.BRANCH_IFNE), pc+2);
builder.loadLocal( pc, b );
builder.storeLocal( pc, a );
break;
case Lua.OP_CALL: /* A B C R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */
// load function
builder.loadLocal(pc, a);
// load args
int narg = b - 1;
switch ( narg ) {
case 0: case 1: case 2: case 3:
for ( int i=1; i<b; i++ )
builder.loadLocal(pc, a+i);
break;
default: // fixed arg count > 3
builder.newVarargs( pc, a+1, b-1 );
narg = -1;
break;
case -1: // prev vararg result
loadVarargResults( builder, pc, a+1, vresultbase );
narg = -1;
break;
}
// call or invoke
boolean useinvoke = narg<0 || c<1 || c>2;
if ( useinvoke )
builder.invoke(narg);
else
builder.call(narg);
// handle results
switch ( c ) {
case 1:
builder.pop();
break;
case 2:
if ( useinvoke )
builder.arg( 1 );
builder.storeLocal(pc, a);
break;
default: // fixed result count - unpack args
for ( int i=1; i<c; i++ ) {
if ( i+1 < c )
builder.dup();
builder.arg( i );
builder.storeLocal(pc, a+i-1);
}
break;
case 0: // vararg result
vresultbase = a;
builder.storeVarresult();
break;
}
break;
case Lua.OP_TAILCALL: /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
// load function
builder.loadLocal(pc, a);
// load args
switch ( b ) {
case 1:
builder.loadNone();
break;
case 2:
builder.loadLocal(pc, a+1);
break;
default: // fixed arg count > 1
builder.newVarargs( pc, a+1, b-1 );
break;
case 0: // prev vararg result
loadVarargResults( builder, pc, a+1, vresultbase );
break;
}
builder.newTailcallVarargs();
builder.areturn();
break;
case Lua.OP_RETURN: /* A B return R(A), ... ,R(A+B-2) (see note) */
if ( c == 1 )
break;
switch ( b ) {
case 0: loadVarargResults( builder, pc, a, vresultbase ); break;
case 1: builder.loadNone(); break;
case 2: builder.loadLocal(pc, a); break;
default: builder.newVarargs(pc, a, b-1); break;
}
builder.areturn();
break;
case Lua.OP_FORPREP: /* A sBx R(A)-=R(A+2): pc+=sBx */
builder.loadLocal(pc, a);
builder.loadLocal(pc, a+2);
builder.binaryop( Lua.OP_SUB );
builder.storeLocal(pc, a);
builder.addBranch(pc, JavaBuilder.BRANCH_GOTO, pc+1+sbx);
break;
case Lua.OP_FORLOOP: /* A sBx R(A)+=R(A+2): if R(A) <?= R(A+1) then { pc+=sBx: R(A+3)=R(A) }*/
builder.loadLocal(pc, a);
builder.loadLocal(pc, a+2);
builder.binaryop( Lua.OP_ADD );
builder.dup();
builder.dup();
builder.storeLocal(pc, a);
builder.storeLocal(pc, a+3);
builder.loadLocal(pc, a+1); // limit
builder.loadLocal(pc, a+2); // step
builder.testForLoop();
builder.addBranch(pc, JavaBuilder.BRANCH_IFNE, pc+1+sbx);
break;
case Lua.OP_TFORLOOP: /*
* A C R(A+3), ... ,R(A+2+C):= R(A)(R(A+1),
* R(A+2)): if R(A+3) ~= nil then R(A+2)=R(A+3)
* else pc++
*/
builder.loadLocal(pc, a);
builder.loadLocal(pc, a+1);
builder.loadLocal(pc, a+2);
builder.invoke(2);
for ( int i=0; i<c; i++ ) {
if ( i+1 < c )
builder.dup();
builder.arg( i+1 );
builder.storeLocal(pc, a+3+i);
}
builder.loadLocal(pc, a+3);
builder.isNil();
builder.addBranch(pc, JavaBuilder.BRANCH_IFNE, pc+2);
builder.loadLocal(pc, a+3);
builder.storeLocal(pc, a+2);
break;
case Lua.OP_SETLIST: /* A B C R(A)[(C-1)*FPF+i]:= R(A+i), 1 <= i <= B */
int index0 = (c-1)*Lua.LFIELDS_PER_FLUSH + 1;
builder.loadLocal( pc, a );
if ( b == 0 ) {
int nstack = vresultbase - (a+1);
if ( nstack > 0 ) {
builder.setlistStack( pc, a+1, index0, nstack );
index0 += nstack;
}
builder.setlistVarargs( index0, vresultbase );
} else {
builder.setlistStack( pc, a+1, index0, b );
builder.pop();
}
break;
case Lua.OP_CLOSE: /* A close all variables in the stack up to (>=) R(A)*/
break;
case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
{
Prototype newp = p.p[bx];
String protoname = closureName(classname, bx);
int nup = newp.nups;
builder.closureCreate( protoname );
if ( nup > 0 )
builder.dup();
builder.storeLocal( pc, a );
if ( nup > 0 ) {
for ( int up=0; up<nup; ++up ) {
if ( up+1 < nup )
builder.dup();
ins = p.code[++pc];
b = Lua.GETARG_B(ins);
if ( (ins&4) != 0 ) {
builder.closureInitUpvalueFromUpvalue( protoname, up, b );
} else {
builder.closureInitUpvalueFromLocal( protoname, up, pc, b );
}
}
}
break;
}
case Lua.OP_VARARG: /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
if ( b == 0 ) {
builder.loadVarargs();
builder.storeVarresult();
vresultbase = a;
} else {
for ( int i=1; i<b; ++a, ++i ) {
builder.loadVarargs( i );
builder.storeLocal(pc, a);
}
}
break;
}
// let builder process branch instructions
builder.onEndOfLuaInstruction( pc );
}
}
private void loadVarargResults(JavaBuilder builder, int pc, int a, int vresultbase) {
if ( vresultbase <= a ) {
builder.loadVarresult();
builder.subargs( a+1-vresultbase );
} else if ( vresultbase == a ) {
builder.loadVarresult();
} else {
builder.newVarargsVarresult(pc, a, vresultbase-a);
}
}
private void loadLocalOrConstant(Prototype p, JavaBuilder builder, int pc, int borc) {
if ( borc<=0xff )
builder.loadLocal( pc, borc );
else
builder.loadConstant( p.k[borc&0xff] );
}
}

View File

@@ -0,0 +1,83 @@
package org.luaj.vm2.luajc;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.compiler.LuaC;
/*******************************************************************************
* Copyright (c) 2010 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
public class JavaLoader extends ClassLoader {
private final LuaValue env;
private Map<String,byte[]> unloaded = new HashMap<String,byte[]>();
public JavaLoader( LuaValue env ) {
this.env = env;
}
public LuaValue load( InputStream is, String classname, String filename ) throws IOException {
Prototype p = LuaC.compile(is, classname);
return load( p, classname, filename );
}
public LuaValue load( Prototype p, String classname, String filename ) {
JavaGen jg = new JavaGen( p, classname, filename );
return load( jg );
}
public LuaValue load( JavaGen jg ) {
include( jg );
return load( jg.classname );
}
public LuaValue load(String classname) {
try {
Class c = loadClass( classname );
LuaValue v = (LuaValue) c.newInstance();
v.setfenv(env);
return v;
} catch ( Exception e ) {
e.printStackTrace();
throw new IllegalStateException("bad class gen: "+e);
}
}
public void include( JavaGen jg ) {
unloaded.put( jg.classname, jg.bytecode );
for ( int i=0; i<jg.inners.length; i++ )
include( jg.inners[i] );
}
public Class findClass(String classname) throws ClassNotFoundException {
byte[] bytes = unloaded.get(classname);
if ( bytes != null )
return defineClass(classname, bytes, 0, bytes.length);
return super.findClass(classname);
}
}

View File

@@ -0,0 +1,91 @@
/*******************************************************************************
* Copyright (c) 2010 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc;
import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.LoadState.LuaCompiler;
import org.luaj.vm2.compiler.LuaC;
public class LuaJC implements LuaCompiler {
private static LuaJC instance;
private LuaC luac;
public static LuaJC getInstance() {
if ( instance == null )
instance = new LuaJC();
return instance;
}
/**
* Install the compiler as the main compiler to use.
* Will fall back to the LuaC prototype compiler.
*/
public static final void install() {
LoadState.compiler = getInstance();
}
public LuaJC() {
luac = new LuaC();
}
public Hashtable compileAll(InputStream script, String classname, String filename) throws IOException {
Hashtable h = new Hashtable();
Prototype p = luac.compile(script.read(), script, classname);
JavaGen gen = new JavaGen(p, classname, filename);
insert( h, gen );
return h;
}
private void insert(Hashtable h, JavaGen gen) {
h.put(gen.classname, gen.bytecode);
for ( int i=0; i<gen.inners.length; i++ )
insert(h, gen.inners[i]);
}
public Prototype compile(int firstByte, InputStream stream, String name) throws IOException {
return luac.compile(firstByte, stream, name);
}
public LuaFunction load(int firstByte, InputStream stream, String name, LuaValue env) throws IOException {
return load( compile(firstByte, stream, name), name, env );
}
public LuaFunction load(Prototype p, String filename, LuaValue env) {
JavaGen gen = new JavaGen(p, filename, filename);
JavaLoader loader = new JavaLoader(env);
loader.include(gen);
return (LuaFunction) loader.load(p, filename, filename);
}
public LuaValue load(InputStream stream, String name, LuaValue env) throws IOException {
return load(stream.read(), stream, name, env);
}
}

View File

@@ -1,96 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Arrays;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
import org.luaj.vm2.LuaValue;
public class LuaJCompiler {
public static LuaValue compile( InputStream luaSource, String chunkName, LuaValue env ) throws Exception {
String java = compileToJava( luaSource, chunkName );
LuaValue chunk = javaCompile( java, chunkName );
chunk.setfenv(env);
return chunk;
}
public static String compileToJava( InputStream luaSource, String chunkName ) throws Exception {
// return AntlrLuaJCompiler.compile( luaSource, chunkName );
throw new RuntimeException( "not supported" );
}
public static LuaValue javaCompile( String java, String className) throws Exception {
final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
if (compiler == null) {
LuaValue.error("no java compiler");
}
// write the file
new File("jit").mkdirs();
File source = new File("jit/"+className+JavaFileObject.Kind.SOURCE.extension);
PrintStream ps = new PrintStream(new FileOutputStream(source));
ps.print(java);
ps.close();
// set up output location
Iterable<? extends File> dest = Arrays.asList(new File[] { new File("bin") });
StandardJavaFileManager fm = compiler.getStandardFileManager( null, null, null);
fm.setLocation(StandardLocation.CLASS_OUTPUT, dest);
// compile the file
Iterable<? extends JavaFileObject> compilationUnits = fm.getJavaFileObjects(source);
CompilationTask task = compiler.getTask(null, fm, null, null, null, compilationUnits);
boolean success = task.call();
// instantiate, config and return
if (success) {
// compile sub-prototypes
// if ( p.p != null ) {
// for ( int i=0, n=p.p.length; i<n; i++ ) {
// if ( ! (p.p[i] instanceof JitPrototype) )
// p.p[i] = jitCompile( p.p[i] );
// }
// }
// create JitPrototype instance
Class clazz = Class.forName(className);
Object instance = clazz.newInstance();
LuaValue value = (LuaValue) instance;
return value;
}
return LuaValue.error("compile task failed");
}
}

View File

@@ -0,0 +1,387 @@
/*******************************************************************************
* Copyright (c) 2010 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc;
import org.luaj.vm2.Lua;
import org.luaj.vm2.Prototype;
/**
* Analyze slot usage to find:
* - which assignments and references are to upvalue 'u'
* - which slots must be initialized with the implied "nil"
* - which assignment locations need to create upvalue storage 'U'
*
* Eventually add:
* - subexpression sequences that can remain in primitive types
* - assignments of constant values to upvalues that are never modified
*/
public class Slots {
private static final byte ASSIGN = 'a'; // assignment to a slot position
private static final byte REFER = 'r'; // reference to a slot position
private static final byte REFER_ASSIGN = 'b'; // i.e. "both"
private static final byte UPVAL_CREATE = 'U'; // where upvalue must be alloced
private static final byte UPVAL_USE = 'u'; // continuation of existing upvalue
private static final byte UPVAL_USE_ASSIGN = 'c'; // on create closure only
private static final byte UPVAL_USE_CREATE = 'C'; // on create closure only, create new upvalue
private static final byte INVALID = 'x'; // after call, etc
private static final byte INITIAL_NIL = 'n'; // above parameters at initial call
final int n,m;
public final byte[][] slots;
public final boolean[] branchdest;
public boolean isUpvalueCreate(int pc, int slot) {
switch (slots[pc+1][slot]) {
case UPVAL_CREATE:
case UPVAL_USE_CREATE:
return true;
}
return false;
}
public boolean isUpvalueAssign(int pc, int slot) {
switch (slots[pc+1][slot]) {
case UPVAL_CREATE:
case UPVAL_USE_CREATE:
case UPVAL_USE_ASSIGN:
return true;
}
return false;
}
public boolean isUpvalueRefer(int pc, int slot) {
switch (slots[pc+1][slot]) {
case UPVAL_USE:
case UPVAL_USE_ASSIGN:
return true;
}
return false;
}
public boolean isInitialValueUsed(int slot) {
return slots[0][slot] != INVALID;
}
public Slots(Prototype p) {
n = p.code.length;
m = p.maxstacksize;
slots = new byte[n+1][m];
branchdest = new boolean[n+1];
markassignments( p );
markuninitialized( p );
markupvalues( p );
}
public String toString() {
StringBuffer sb = new StringBuffer();
for ( int i=0; i<slots.length; i++ ) {
if ( i > 0 ) sb.append( "\n" );
byte[] s = slots[i];
for ( int j=s.length; --j>=0; ) {
if ( s[j] == 0 )
s[j] = ' ';
}
sb.append( i>0 && branchdest[i]? "D": " " );
sb.append( new String(s) );
}
return sb.toString();
}
private void markassignments( Prototype p ) {
// mark initial assignments and references
int j=0;
for ( ; j<p.numparams; j++ )
slots[0][j] = ASSIGN;
for ( ; j<m; j++ )
slots[0][j] = INITIAL_NIL;
for ( int index=1; index<=n; index++ ) {
byte[] s = slots[index];
int pc = index-1;
int ins = p.code[pc];
int a = Lua.GETARG_A(ins);
int b = Lua.GETARG_B(ins);
int bx = Lua.GETARG_Bx(ins);
int sbx = Lua.GETARG_sBx(ins);
int c = Lua.GETARG_C(ins);
switch ( Lua.GET_OPCODE(ins) ) {
case Lua.OP_GETUPVAL: /* A B R(A):= UpValue[B] */
case Lua.OP_SETUPVAL: /* A B UpValue[B]:= R(A) */
case Lua.OP_NEWTABLE: /* A B C R(A):= {} (size = B,C) */
s[a] = ASSIGN;
break;
case Lua.OP_MOVE:/* A B R(A):= R(B) */
case Lua.OP_UNM: /* A B R(A):= -R(B) */
case Lua.OP_NOT: /* A B R(A):= not R(B) */
case Lua.OP_LEN: /* A B R(A):= length of R(B) */
s[a] = ASSIGN;
s[b] = REFER;
break;
case Lua.OP_LOADK:/* A Bx R(A):= Kst(Bx) */
case Lua.OP_GETGLOBAL: /* A Bx R(A):= Gbl[Kst(Bx)] */
case Lua.OP_SETGLOBAL: /* A Bx Gbl[Kst(Bx)]:= R(A) */
s[a] = ASSIGN;
break;
case Lua.OP_LOADNIL: /* A B R(A):= ...:= R(B):= nil */
while ( a<b )
s[a++] = ASSIGN;
break;
case Lua.OP_GETTABLE: /* A B C R(A):= R(B)[RK(C)] */
s[a] = ASSIGN;
s[b] = REFER;
if (c<=0xff) s[c] = REFER;
break;
case Lua.OP_SETTABLE: /* A B C R(A)[RK(B)]:= RK(C) */
case Lua.OP_ADD: /* A B C R(A):= RK(B) + RK(C) */
case Lua.OP_SUB: /* A B C R(A):= RK(B) - RK(C) */
case Lua.OP_MUL: /* A B C R(A):= RK(B) * RK(C) */
case Lua.OP_DIV: /* A B C R(A):= RK(B) / RK(C) */
case Lua.OP_MOD: /* A B C R(A):= RK(B) % RK(C) */
case Lua.OP_POW: /* A B C R(A):= RK(B) ^ RK(C) */
s[a] = ASSIGN;
if (bx<=0xff) s[bx] = REFER;
if (c<=0xff) s[c] = REFER;
break;
case Lua.OP_SELF: /* A B C R(A+1):= R(B): R(A):= R(B)[RK(C)] */
s[a] = ASSIGN;
s[a+1] = ASSIGN;
s[b] = REFER;
if (c<=0xff) s[c] = REFER;
break;
case Lua.OP_CONCAT: /* A B C R(A):= R(B).. ... ..R(C) */
s[a] = ASSIGN;
while ( b<=c )
s[b++] = REFER;
break;
case Lua.OP_LOADBOOL:/* A B C R(A):= (Bool)B: if (C) pc++ */
s[a] = ASSIGN;
if ( c!=0 ) branchdest[index+2] = true;
break;
case Lua.OP_JMP: /* sBx pc+=sBx */
branchdest[index+1+sbx] = true;
break;
case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
if (bx<=0xff) s[bx] = REFER;
if (c<=0xff) s[c] = REFER;
branchdest[index+2] = true;
break;
case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */
s[a] = REFER;
branchdest[index+2] = true;
break;
case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A):= R(B) else pc++ */
s[a] = REFER;
s[b] = REFER;
branchdest[index+2] = true;
break;
case Lua.OP_CALL: /* A B C R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */
while ( a < c-1 || a < b )
s[a++] = (byte) (a<c-1 && a<b? REFER_ASSIGN: a<c-1? ASSIGN: REFER);
while ( a < m )
s[a++] = INVALID;
break;
case Lua.OP_TAILCALL: /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
while ( a < b )
s[a++] = REFER;
while ( a < m )
s[a++] = INVALID;
break;
case Lua.OP_RETURN: /* A B return R(A), ... ,R(A+B-2) (see note) */
while ( a < b-1 )
s[a++] = REFER;
break;
case Lua.OP_FORPREP: /* A sBx R(A)-=R(A+2): pc+=sBx */
s[a] = REFER_ASSIGN;
s[a+2] = REFER;
branchdest[index+1+sbx] = true;
break;
case Lua.OP_FORLOOP: /* A sBx R(A)+=R(A+2): if R(A) <?= R(A+1) then { pc+=sBx: R(A+3)=R(A) }*/
s[a] = REFER_ASSIGN;
s[a+1] = REFER;
s[a+2] = REFER;
s[a+3] = ASSIGN;
branchdest[index+1+sbx] = true;
break;
case Lua.OP_TFORLOOP: /*
* A C R(A+3), ... ,R(A+2+C):= R(A)(R(A+1),
* R(A+2)): if R(A+3) ~= nil then R(A+2)=R(A+3)
* else pc++
*/
s[a] = REFER;
s[a+1] = REFER;
s[a+2] = REFER_ASSIGN;
for ( int aa=a+3; aa<a+3+c; aa++ )
s[aa] = ASSIGN;
for ( int aa=a+3+c; aa<m; aa++ )
s[aa] = INVALID;
branchdest[index+2] = true;
break;
case Lua.OP_SETLIST: /* A B C R(A)[(C-1)*FPF+i]:= R(A+i), 1 <= i <= B */
s[a] = REFER;
for ( int aa=1; aa<=b; aa++ )
s[aa] = REFER;
break;
case Lua.OP_CLOSE: /* A close all variables in the stack up to (>=) R(A)*/
while ( a<m )
s[a++] = INVALID;
break;
case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
{
Prototype newp = p.p[bx];
for ( int up=0, nup=newp.nups; up<nup; ++up ) {
ins = p.code[++pc];
b = Lua.GETARG_B(ins);
if ( (ins&4) != 0 ) {
// up : ups[b]
} else {
s[b] = UPVAL_USE;
}
}
s[a] = (byte) (s[a] == UPVAL_USE? UPVAL_USE_ASSIGN: ASSIGN);
break;
}
case Lua.OP_VARARG: /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
while ( a<b )
s[a++] = ASSIGN;
break;
}
}
}
private void markuninitialized(Prototype p) {
for ( int j=p.numparams; j<m; j++ )
if ( ! isreferrededtofirst(j) )
slots[0][j] = INVALID;
}
private boolean isreferrededtofirst(int j) {
for ( int i=1; i<=n; i++ ) {
switch (slots[i][j]) {
case REFER_ASSIGN:
case REFER:
case UPVAL_USE:
return true;
case ASSIGN:
case INVALID:
return false;
}
}
return false;
}
private void markupvalues( Prototype p ) {
for ( int pc=0; pc<n; ++pc ) {
if ( Lua.GET_OPCODE(p.code[pc]) == Lua.OP_CLOSURE ) {
int index = pc+1;
byte[] s = slots[index];
for ( int j=0; j<m; j++ )
if ( s[j] == UPVAL_USE || s[j] == UPVAL_USE_ASSIGN ) {
promoteUpvalueBefore( s, index, j );
if ( pc<n-1 )
promoteUpvalueAfter( s, index+1, j );
}
}
}
}
private void promoteUpvalueBefore(byte[] s, int index, int j) {
int begin = prevUndefined(index,j);
int assign = firstAssignAfter(begin,index,j);
slots[assign][j] = slots[assign][j]==UPVAL_USE_ASSIGN? UPVAL_USE_CREATE: UPVAL_CREATE;
while ( index>assign)
slots[index--][j] = UPVAL_USE;
}
private void promoteUpvalueAfter(byte[] s, int index, int j) {
int end = nextUndefined(index,j);
int access = lastAccessBefore(end,index,j);
while ( index<=access )
slots[index++][j] = UPVAL_USE;
}
private int prevUndefined(int index, int j) {
while ( index>0 && slots[index][j] != INVALID )
--index;
return index;
}
private int firstAssignAfter(int index, int limit, int j) {
for ( ; index<limit; ++index ) {
switch (slots[index][j]) {
case ASSIGN:
case REFER_ASSIGN:
return index;
case UPVAL_CREATE:
throw new IllegalStateException("overlapping upvalues");
}
}
return index;
}
private int nextUndefined(int index, int j) {
while ( index+1<slots.length && slots[index+1][j] != INVALID )
++index;
return index;
}
private int lastAccessBefore(int index, int limit, int j) {
for ( ; index>limit; --index ) {
switch (slots[index][j]) {
case ASSIGN:
case REFER_ASSIGN:
case REFER:
return index;
case UPVAL_CREATE:
case UPVAL_USE:
throw new IllegalStateException("overlapping upvalues");
}
}
return index;
}
}

View File

@@ -1,60 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc.antlr;
import java.io.IOException;
import java.io.InputStream;
import org.antlr.runtime.ANTLRInputStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.luaj.vm2.luajc.JavaCodeGenerator;
import org.luaj.vm2.luajc.antlr.LuaLexer;
import org.luaj.vm2.luajc.antlr.LuaParser;
import org.luaj.vm2.luajc.lst.LSChunk;
/**
* Implementation of lua-to-java compiler using antlr
*/
public class AntlrLuaJCompiler {
private final String chunkname;
public AntlrLuaJCompiler(String chunkname) {
this.chunkname = chunkname;
}
public static String compile(InputStream script, String chunkname) throws RecognitionException, IOException {
return new AntlrLuaJCompiler(chunkname).docompile( script );
}
private String docompile(InputStream script) throws RecognitionException, IOException {
ANTLRInputStream input = new ANTLRInputStream(script);
LuaLexer lexer = new LuaLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
LuaParser parser = new LuaParser(tokens);
LSChunk chunk = parser.chunk(chunkname);
return new JavaCodeGenerator().toJava( chunk );
}
}

View File

@@ -1,301 +0,0 @@
/*
* Lua 5.1 grammar producing typed parse tree.
*
* Adapted from the grammar produced by Nicolai Mainiero, May 2007
*
* see http://www.antlr.org/grammar/list
*/
grammar Lua;
options {
backtrack=true;
}
@header {
package org.luaj.vm2.luajc.antlr;
import org.luaj.vm2.luajc.lst.*;
}
@lexer::header {
package org.luaj.vm2.luajc.antlr;
}
@members {
LSChunk CHK = null;
}
chunk [String chunkname] returns [LSChunk c]
@init { CHK = new LSChunk(chunkname); }
: funcblock[CHK.function] {$c=CHK;}
;
funcblock [LSFunction f]
scope { LSFunction func; }
@init { $funcblock::func = $f; }
: {CHK.pushScope("body");} block {$f.setStatements($block.stats); CHK.popScope("body"); }
;
block returns [List<LSStatement> stats]
@init { $stats = new ArrayList<LSStatement>(); }
: (stat {$stats.add($stat.s);} (';')?)*
(laststat {$stats.add($laststat.s);} (';')?)?
;
stat returns [LSStatement s]
@init { Name name=null; List<Name> names=null; }
: varlist1 '=' explist1 { $s=LSStatement.varAssignStatement($varlist1.vars,$explist1.exprs, CHK.peekScope(), $funcblock::func); }
| functioncall { $s=LSStatement.functionCallStatement($functioncall.v); }
| 'do' {CHK.pushScope("do");} block {CHK.popScope("do");} 'end'
{ $s=LSStatement.doBlockStatement($block.stats); }
| 'while' exp 'do' {CHK.pushScope("while");} block {CHK.popScope("while");} 'end'
{ $s=LSStatement.whileLoopStatement($exp.e,$block.stats); }
| 'repeat' {CHK.pushScope("repeat");} block {CHK.popScope("repeat");} 'until' exp
{ $s=LSStatement.repeatUntilStatement($block.stats,$exp.e); }
| ifstat { $s=$ifstat.s; }
| 'for' {CHK.pushScope("fori");} NAME {name=CHK.declare($NAME.text);} '=' e1=exp ',' e2=exp (',' e3=exp)? 'do' {CHK.pushScope("foriblock");} block {CHK.popScope("foriblock");} 'end'
{ $s=LSStatement.forLoopStatement(name,$e1.e,$e2.e,$e3.e,$block.stats,CHK.peekScope()); CHK.popScope("fori"); }
| 'for' {CHK.pushScope("for");} namelist {names=CHK.declare($namelist.names);} 'in' explist1 'do' {CHK.pushScope("forblock");} block {CHK.popScope("forblock");}'end'
{ $s=LSStatement.forListStatement(names,$explist1.exprs,$block.stats,CHK.peekScope(), $funcblock::func); CHK.popScope("for");}
| 'function' funcname funcbody { $s=LSStatement.varFunctionStatement($funcname.v,$funcbody.f); }
| 'local' 'function' NAME {name=CHK.declare($NAME.text);} funcbody
{ $s=LSStatement.localFunctionStatement(name,$funcbody.f); }
| 'local' namelist ('=' explist1)? { $s=LSStatement.localAssignStatement(CHK.declare($namelist.names),$explist1.exprs,CHK.peekScope(), $funcblock::func); }
;
ifstat returns [LSStatement s]
scope { LSIfStatement current; }
: 'if' e1=exp 'then' {CHK.pushScope("if");} b1=block {$ifstat::current=new LSIfStatement($e1.e,$b1.stats); CHK.popScope("if");}
('elseif' e2=exp 'then' {CHK.pushScope("elseif");} b2=block {$ifstat::current.addElseif($e2.e,$b2.stats); CHK.popScope("elseif");})*
('else' {CHK.pushScope("else");} b3=block {$ifstat::current.addElse($b3.stats); CHK.popScope("else");})?
'end'
{ $s=$ifstat::current; }
;
laststat returns [LSStatement s]
: 'return' (e=explist1)? {$s=LSStatement.returnStatement($funcblock::func,$e.exprs);}
| 'break' {$s=LSStatement.breakStatement();}
;
funcname returns [LSVariable v]
: n=NAME {$v = LSVariable.nameVariable(CHK.reference($n.text,$funcblock::func));}
('.' n2=NAME {$v = $v.fieldVariable($n2.text);})*
(':' n3=NAME {$v = $v.methodVariable($n3.text);})?
;
varlist1 returns [List<LSVariable> vars]
@init { $vars = new ArrayList<LSVariable>(); }
: v1=var {$vars.add($v1.v);}
(',' v2=var {$vars.add($v2.v);})*
;
namelist returns [List<String> names]
: n=NAME {$names=new ArrayList<String>(); $names.add($n.text);}
(',' n2=NAME {$names.add($n2.text);})*
;
explist1 returns [List<LSExpression> exprs]
@init { $exprs = new ArrayList<LSExpression>(); }
: (e1=exp ',' {$exprs.add($e1.e);})*
e2=exp {$exprs.add($e2.e);}
;
exp returns [LSExpression e]
: ('nil' { $e=LSExpression.ENIL; }
| 'false' { $e=LSExpression.EFALSE; }
| 'true' { $e=LSExpression.ETRUE; }
| number { $e=LSExpression.numberExpression($number.text); }
| string { $e=$string.e; }
| '...' { $e=LSExpression.varargsRef(); $funcblock::func.setUsesVarargs(); }
| function { $e=LSExpression.functionExpression($function.f); }
| prefixexp { $e=$prefixexp.v; }
| tableconstructor { $e=$tableconstructor.e;}
| unop e1=exp { $e=LSExpression.unopExpression($unop.op,$e1.e,CHK.peekScope());}
) (binop e2=exp { $e=LSExpression.binopExpression($e,$binop.op,$e2.e,CHK.peekScope());})*
;
var returns [LSVariable v]
scope { LSVariable current; }
: (n=NAME {$var::current=LSVariable.nameVariable(CHK.reference($n.text,$funcblock::func));}
| '(' exp ')' {$var::current=LSVariable.parenthesesVariable($exp.e);} varSuffix)
varSuffix*
{$v=$var::current;}
;
varSuffix
: (n=nameAndArgs[$var::current] {$var::current=$n.v;})*
('[' e=exp ']' {$var::current=$var::current.indexVariable($e.e);}
| '.' n2=NAME {$var::current=$var::current.fieldVariable($n2.text);}
)
;
prefixexp returns [LSVariable v]
scope { LSVariable current; }
: e=varOrExp {$prefixexp::current=$e.v;}
(n=nameAndArgs[$prefixexp::current] {$prefixexp::current=$n.v;})*
{$v=$prefixexp::current;}
;
functioncall returns [LSVariable v]
scope { LSVariable current; }
: e=varOrExp {$functioncall::current=$e.v;}
(n=nameAndArgs[$functioncall::current] {$functioncall::current=$n.v;})+
{$v=$functioncall::current;}
;
varOrExp returns [LSVariable v]
: var {$v=$var.v;}
| '(' exp ')' {$v=LSVariable.parenthesesVariable($exp.e);}
;
nameAndArgs [LSVariable vin] returns [LSVariable v]
@init { String method=null; }
: (':' n=NAME {method=$n.text;})?
a=args {$v=((method==null)?
$vin.callFuncVariable($a.exprs):
$vin.callMethVariable(method,$a.exprs));}
;
args returns [List<LSExpression> exprs]
@init { $exprs = new ArrayList<LSExpression>(); }
: '(' (e=explist1 {$exprs=$e.exprs;})? ')'
| t=tableconstructor {$exprs.add($t.e);}
| s=string {$exprs.add($s.e);}
;
function returns [LSFunction f]
: 'function' b=funcbody {$f = $b.f;}
;
funcbody returns [LSFunction f]
@init {
$f = new LSFunction();
$funcblock::func.functions.add($f);
}
: {CHK.pushScope("func",true);} '(' (parlist1 [f])? ')' funcblock[f] 'end' {CHK.popScope("func");}
;
parlist1 [LSFunction f]
: namelist {f.setParameterNames(CHK.declare($namelist.names));} (',' '...' {f.isvararg=true;})?
| '...' {f.isvararg=true;}
;
tableconstructor returns [LSExpression e]
@init { List<LSField> fields = new ArrayList<LSField>(); }
: '{' (fieldlist[fields])? '}' {$e=LSExpression.tableConstructorExpression(fields);}
;
fieldlist [List<LSField> fields]
: field [fields] (fieldsep field [fields])* (fieldsep)?
;
field [List<LSField> fields]
: '[' k=exp ']' '=' e=exp {$fields.add(LSField.keyValueField($k.e,$e.e));}
| n=NAME '=' e=exp {$fields.add(LSField.nameValueField($n.text,$e.e));}
| e=exp {$fields.add(LSField.valueField($e.e));}
;
fieldsep
: ','
| ';'
;
binop returns [BinOp op]
: '+' {$op=BinOp.ADD;}
| '-' {$op=BinOp.SUB;}
| '*' {$op=BinOp.MUL;}
| '/' {$op=BinOp.DIV;}
| '^' {$op=BinOp.POW;}
| '%' {$op=BinOp.MOD;}
| '..' {$op=BinOp.CONCAT;}
| '<' {$op=BinOp.LT;}
| '<=' {$op=BinOp.LTEQ;}
| '>' {$op=BinOp.GT;}
| '>=' {$op=BinOp.GTEQ;}
| '==' {$op=BinOp.EQ;}
| '~=' {$op=BinOp.NEQ;}
| 'and' {$op=BinOp.AND; $funcblock::func.hasandlogic=true;}
| 'or' {$op=BinOp.OR; $funcblock::func.hasorlogic=true;}
;
unop returns [UnOp op]
: '-' {$op=UnOp.NEG;}
| 'not' {$op=UnOp.NOT;}
| '#' {$op=UnOp.LEN;}
;
number
: ('-')? INT
| ('-')? FLOAT1
| ('-')? FLOAT2
| ('-')? FLOAT3
| ('-')? EXP
| HEX
;
string returns [LSExpression e]
: NORMALSTRING {$e=LSExpression.normalStringExpression($NORMALSTRING.text);}
| CHARSTRING {$e=LSExpression.charStringExpression($CHARSTRING.text);}
| LONGSTRING {$e=LSExpression.longStringExpression($LONGSTRING.text);}
;
// LEXER
NAME :('a'..'z'|'A'..'Z'|'_')(options{greedy=true;}: 'a'..'z'|'A'..'Z'|'_'|'0'..'9')*
;
INT : ('0'..'9')+;
FLOAT1 :'.' INT ;
FLOAT2 :INT '.' ;
FLOAT3 :INT '.' INT ;
EXP : (INT | FLOAT1 | FLOAT2 | FLOAT3) ('E'|'e') ('-'|'+')? INT;
HEX :'0' ('x' | 'X') ('0'..'9'| 'a'..'f' | 'A'..'F')+ ;
NORMALSTRING
: '"' ( EscapeSequence | ~('\\'|'"') )* '"'
;
CHARSTRING
: '\'' ( EscapeSequence | ~('\\'|'\'') )* '\''
;
LONGSTRING
: '['('=')*'[' ( EscapeSequence | ~('\\'|']') )* ']'('=')*']'
;
fragment
EscapeSequence
: '\\' ('a'|'b'|'f'|'n'|'r'|'t'|'v'|'\"'|'\''|'\\'|'\n')
| DecimalEscape
;
fragment
DecimalEscape
: '\\' ('0'..'9') (('0'..'9') ('0'..'9')?)?
;
COMMENT
: '--[[' ( options {greedy=false;} : . )* '--]]' {skip();}
| '--[=[' ( options {greedy=false;} : . )* '--]==]' {skip();}
| '--[==[' ( options {greedy=false;} : . )* '--]==]' {skip();}
| '--[===[' ( options {greedy=false;} : . )* '--]===]' {skip();}
;
LINE_COMMENT
: '--' ~('\n'|'\r')* '\r'? '\n' {skip();}
;
WS : (' '|'\t'|'\u000C') {skip();}
;
NEWLINE : ('\r')? '\n' {skip();}
;

View File

@@ -1,110 +0,0 @@
T__66=66
T__64=64
T__29=29
T__65=65
T__28=28
T__62=62
T__27=27
T__63=63
T__26=26
T__25=25
T__24=24
T__23=23
T__22=22
T__21=21
T__20=20
T__61=61
T__60=60
FLOAT3=8
FLOAT2=7
FLOAT1=6
T__55=55
T__56=56
T__57=57
NAME=4
T__58=58
T__51=51
T__52=52
T__53=53
T__54=54
EXP=9
HEX=10
T__59=59
DecimalEscape=15
COMMENT=16
T__50=50
T__42=42
T__43=43
T__40=40
T__41=41
T__46=46
T__47=47
T__44=44
T__45=45
LINE_COMMENT=17
T__48=48
T__49=49
CHARSTRING=12
INT=5
LONGSTRING=13
T__30=30
NORMALSTRING=11
T__31=31
T__32=32
WS=18
T__33=33
T__34=34
NEWLINE=19
T__35=35
T__36=36
T__37=37
T__38=38
T__39=39
EscapeSequence=14
'..'=56
'end'=23
'#'=66
'>='=60
'=='=61
'/'=53
'then'=33
'>'=59
'repeat'=25
';'=20
'='=21
'return'=36
'for'=27
'+'=50
')'=45
'function'=30
'.'=38
'^'=54
'%'=55
'do'=22
'elseif'=34
'true'=42
'}'=49
'else'=35
'and'=63
'break'=37
'{'=48
'...'=43
'~='=62
'nil'=40
'until'=26
'<='=58
'false'=41
'<'=57
'if'=32
'not'=65
':'=39
'('=44
'or'=64
'*'=52
'-'=51
'['=46
'while'=24
'local'=31
','=28
'in'=29
']'=47

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,63 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc.lst;
public class BinOp {
// unary precedence is between POW and MUL
public static final int UNARY_PRECEDENCE = 7;
public enum Type {
pow,mul,div,mod,add,sub,concat,lt,lteq,gt,gteq,eq,neq,and,or,
}
public static final BinOp POW = new BinOp(Type.pow, 8, true, "^");
public static final BinOp MUL = new BinOp(Type.mul, 6, false, "*");
public static final BinOp DIV = new BinOp(Type.div, 6, false, "/");
public static final BinOp MOD = new BinOp(Type.mod, 6, false, "%");
public static final BinOp ADD = new BinOp(Type.add, 5, false, "+");
public static final BinOp SUB = new BinOp(Type.sub, 5, false, "-");
public static final BinOp CONCAT = new BinOp(Type.concat, 4, true, "..");
public static final BinOp LT = new BinOp(Type.lt, 3, false, "<");
public static final BinOp LTEQ = new BinOp(Type.lteq, 3, false, "<=");
public static final BinOp GT = new BinOp(Type.gt, 3, false, ">");
public static final BinOp GTEQ = new BinOp(Type.gteq, 3, false, ">=");
public static final BinOp EQ = new BinOp(Type.eq, 3, false, "==");
public static final BinOp NEQ = new BinOp(Type.neq, 3, false, "~=");
public static final BinOp AND = new BinOp(Type.and, 2, true, "and");
public static final BinOp OR = new BinOp(Type.or, 1, true, "or");
public final Type type;
public final int precedence;
public final boolean isrightassoc;
public final String luaop;
private BinOp(Type type, int precedence, boolean isrightassoc, String luaop) {
super();
this.type = type;
this.precedence = precedence;
this.isrightassoc = isrightassoc;
this.luaop = luaop;
}
public String toString() { return luaop; }
}

View File

@@ -1,106 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc.lst;
import java.util.ArrayList;
import java.util.List;
/* A Lua Source Chunk */
public class LSChunk {
public static final boolean SCOPES = System.getProperty("SCOPES")!=null;
public final String chunkname;
public final LSFunction function;
public Scope scope;
public LSChunk( String chunkname ) {
this.chunkname = chunkname;
this.function = new LSFunction( true );
this.scope = null;
}
public String toString() {
return "@"+chunkname+": "+function;
}
/** push a block scope onto the name scope stack */
public void pushScope(String name) {
scope = new Scope(scope, false);
if(SCOPES)System.out.println(space(scope)+"push "+name+" scope="+scope);
}
/** push a function scope onto the name scope stack */
public void pushScope(String name,boolean isFunction) {
scope = new Scope(scope, isFunction);
if(SCOPES)System.out.println(space(scope)+"push "+name+" scope="+scope);
}
/** pop a scope from the scope stack */
public Scope popScope(String name) {
Scope s = scope;
scope = scope.parent;
if(SCOPES)System.out.println(space(s)+"pop "+name+" scope="+scope);
return s;
}
/** return the current scope */
public Scope peekScope() {
return scope;
}
/** Declare a single name in the current scope, and return the Name element for it */
public Name declare(String name) {
Name n = scope.declare( name );
if(SCOPES)System.out.println(space(scope)+" declared "+n+" scope="+scope);
return n;
}
/** Declare a list of names in the current scope, and return List of Name for them */
public List<Name> declare(List<String> names) {
List<Name> results = new ArrayList<Name>(names.size());
for ( String s : names )
results.add( declare(s) );
return results;
}
/** Reference a name, and find either the local scope within the function, the upvalue, or a global name
* @param func */
public Name reference(String name, LSFunction func) {
Name n = scope.reference(name);
if ("arg".equals(name) && n.isGlobal() && func.isvararg && !scope.isMainChunkScope()) {
n = scope.declare(name);
func.setHasArg();
}
if(SCOPES)System.out.println(space(scope)+" reference "+n+" scope="+scope);
return n;
}
/** Print out indentation for a scope */
private static final String ws = " ";
private String space(Scope i) {
return ws.substring(0,i.level*2);
}
}

View File

@@ -1,267 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc.lst;
import java.io.ByteArrayOutputStream;
import java.util.List;
public class LSExpression {
public enum Type {
unop,
binop,
functionExpr,
tableConstructor,
nilConstant,
trueConstant,
falseConstant,
varargsRef,
numberConstant,
stringConstant,
// variable types
nameVariable,
fieldVariable,
methodVariable,
parenthesesVariable,
indexVariable,
callFunctionVariable,
callMethodVariable,
}
public static final LSExpression ENIL = new LSExpression(Type.nilConstant); // nil
public static final LSExpression EFALSE = new LSExpression(Type.falseConstant); // false
public static final LSExpression ETRUE = new LSExpression(Type.trueConstant); // true
public final Type type;
LSExpression(Type type) {
this.type = type;
}
public static LSExpression functionExpression(LSFunction function) {
return new FunctionExpr(function);
}
public static LSExpression unopExpression(UnOp unop, LSExpression rhs, Scope scope) {
if ( rhs instanceof BinopExpr ) {
BinopExpr b = (BinopExpr) rhs;
if ( BinOp.UNARY_PRECEDENCE > b.op.precedence )
return binopExpression( unopExpression( unop, b.lhs, scope ), b.op, b.rhs, scope );
}
return new UnopExpr( unop, rhs );
}
public static LSExpression binopExpression(LSExpression lhs, BinOp binop, LSExpression rhs, Scope scope) {
if ( lhs instanceof UnopExpr ) {
UnopExpr u = (UnopExpr) lhs;
if ( binop.precedence > BinOp.UNARY_PRECEDENCE )
return unopExpression( u.op, binopExpression( u.rhs, binop, rhs, scope ), scope );
}
// TODO: cumulate string concatenations together
// TODO: constant folding
if ( lhs instanceof BinopExpr ) {
BinopExpr b = (BinopExpr) lhs;
if ( (binop.precedence > b.op.precedence) ||
((binop.precedence == b.op.precedence) && binop.isrightassoc) )
return binopExpression( b.lhs, b.op, binopExpression( b.rhs, binop, rhs, scope ), scope );
}
if ( rhs instanceof BinopExpr ) {
BinopExpr b = (BinopExpr) rhs;
if ( (binop.precedence > b.op.precedence) ||
((binop.precedence == b.op.precedence) && ! binop.isrightassoc) )
return binopExpression( binopExpression( lhs, binop, b.lhs, scope ), b.op, b.rhs, scope );
}
return new BinopExpr( lhs, binop, rhs, scope );
}
public static LSExpression numberExpression(String number) {
return new NumberConstant(number);
}
public static LSExpression tableConstructorExpression(List<LSField> fields) {
return new TableConstructor( fields );
}
public static LSExpression normalStringExpression(String luaSourceString) {
return new StringConstant(luaSourceString.substring(1,luaSourceString.length()-1));
}
public static LSExpression charStringExpression(String luaSourceString) {
return new StringConstant(luaSourceString.substring(1,luaSourceString.length()-1));
}
public static LSExpression longStringExpression(String luaSourceString) {
luaSourceString = luaSourceString.substring(1,luaSourceString.length()-1);
luaSourceString = luaSourceString.substring(luaSourceString.indexOf('[',1)+1, luaSourceString.lastIndexOf(']'));
return new StringConstant(luaSourceString);
}
public static LSExpression varargsRef() {
return new VarargsRef();
}
/** varargs such as "..." */
public static class VarargsRef extends LSExpression {
public int numReturns = -1;
public VarargsRef() {
super( Type.varargsRef );
}
public void setNumReturns(int i) {
this.numReturns = i;
}
public int getNumReturns() {
return numReturns;
}
public String toString() { return "..."; }
}
/** prefix expression such as "(foo)(bar)" ? */
public static class FunctionExpr extends LSExpression {
public final LSFunction function;
public FunctionExpr( LSFunction function) {
super( Type.functionExpr );
this.function = function;
}
public String toString() { return function.toString(); }
}
/** unary operator such as "not foo" */
public static class UnopExpr extends LSExpression {
public final UnOp op;
public final LSExpression rhs;
public UnopExpr( UnOp op, LSExpression rhs ) {
super( Type.unop );
this.op = op;
this.rhs = rhs;
}
public String toString() { return op.luaop+rhs; }
}
/** binary operator such as "a + b" */
public static class BinopExpr extends LSExpression {
public final LSExpression lhs;
public final BinOp op;
public final LSExpression rhs;
public final Scope scope;
public BinopExpr( LSExpression lhs, BinOp op, LSExpression rhs, Scope scope ) {
super( Type.binop );
this.lhs = lhs;
this.op = op;
this.rhs = rhs;
this.scope = scope;
}
public String toString() { return lhs+op.luaop+rhs; }
}
/** table constructor such as "{ 'foo', [0]='bar' }" */
public static class TableConstructor extends LSExpression {
public final List<LSField> fields;
public TableConstructor( List<LSField> fields ) {
super( Type.tableConstructor );
this.fields = fields;
int n = fields.size();
for ( int i=0; i<n-1; i++ )
fields.get(i).setNumReturns(1);
if ( n>0 )
fields.get(n-1).setNumReturns(-1);
}
public String toString() { return "{"+fields+"}"; }
}
/** number constants such as '123', "4.56", "0x11fe */
public static class NumberConstant extends LSExpression {
public final Number value;
public NumberConstant( String number ) {
super( Type.numberConstant );
number = number.toLowerCase();
if ( number.startsWith("0x") ) {
Long l = Long.parseLong(number.substring(2), 16);
value = (l.intValue()==l.longValue()? (Number) Integer.valueOf(l.intValue()): (Number) l);
} else {
Double d = Double.parseDouble(number);
value = (d.doubleValue()==(double)d.intValue()? (Number) Integer.valueOf(d.intValue()): (Number) d);
}
}
public String toString() { return value.toString(); }
}
/** string constants such as 'abc', "def", [[ghi]], and [==[pqr]==] */
public static class StringConstant extends LSExpression {
public final byte[] bytes;
public StringConstant( String luaSourceChars ) {
super( Type.stringConstant );
this.bytes = unquoteLua( luaSourceChars );
}
public String toString() { return "\""+new String(bytes)+"\""; }
}
/** Unquote lua quoted sequences, and convert to the bytes represented by the source string. */
public static byte[] unquoteLua( String luaSourceChars ) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
char[] c = luaSourceChars.toCharArray();
int n = c.length;
for ( int i=0; i<n; i++ ) {
if ( c[i] == '\\' && i<n ) {
switch ( c[++i] ) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
int d=(int) (c[i++]-'0');
for ( int j=0; i<n && j<2 && c[i]>='0' && c[i]<='9'; i++, j++ )
d = d * 10 + (int) (c[i]-'0');
baos.write( (byte) d );
--i;
continue;
case 'a': baos.write( (byte) 7 ); continue;
case 'b': baos.write( (byte) '\b' ); continue;
case 'f': baos.write( (byte) '\f' ); continue;
case 'n': baos.write( (byte) '\n' ); continue;
case 'r': baos.write( (byte) '\r' ); continue;
case 't': baos.write( (byte) '\t' ); continue;
case 'v': baos.write( (byte) 11 ); continue;
case '"': baos.write( (byte) '"' ); continue;
case '\'': baos.write( (byte) '\'' ); continue;
case '\\': baos.write( (byte) '\\' ); continue;
default: baos.write( (byte) c[i] ); break;
}
} else {
baos.write( (byte) c[i] );
}
}
return baos.toByteArray();
}
/** Set number of return values, return actual number of returns in practice.
*
* @param i desired number of returns, or -1 for varargs.
*/
public void setNumReturns(int i) {
}
/** Get actual number of returns for this subexpression, or -1 for varargs.
*
* @return actual number of returns, or -1 for varargs.
*/
public int getNumReturns() {
return 1;
}
}

View File

@@ -1,92 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc.lst;
public class LSField {
public enum Type {
keyValue,
nameValue,
listValue,
}
public final Type type;
LSField(Type type) {
this.type = type;
}
public static LSField keyValueField(LSExpression key, LSExpression value) {
return new KeyValue(key, value);
}
public static LSField nameValueField(String name, LSExpression value) {
return new NameValue(name, value);
}
public static LSField valueField(LSExpression value) {
return new ListValue(value);
}
/** table constructor field with an explicit key index value */
public static class KeyValue extends LSField {
public final LSExpression key;
public final LSExpression value;
public KeyValue(LSExpression key, LSExpression value) {
super( Type.keyValue );
this.key = key;
this.value = value;
value.setNumReturns(1);
}
public String toString() { return "["+key+"]="+value; }
}
/** table constructor field with an named field for key */
public static class NameValue extends LSField {
public final String name;
public final LSExpression value;
public NameValue(String name, LSExpression value) {
super( Type.nameValue );
this.name = name;
this.value = value;
value.setNumReturns(1);
}
public String toString() { return name+"="+value; }
}
/** table constructor field with an implied index key */
public static class ListValue extends LSField {
public final LSExpression value;
public ListValue(LSExpression value) {
super( Type.listValue );
this.value = value;
}
public void setNumReturns(int i) {
value.setNumReturns(i);
}
public String toString() { return value.toString(); }
}
public void setNumReturns(int i) {
}
}

View File

@@ -1,75 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc.lst;
import java.util.ArrayList;
import java.util.List;
public class LSFunction {
public final List<LSStatement> stats = new ArrayList<LSStatement>();
public final List<LSFunction> functions = new ArrayList<LSFunction>();
public final List<Name> paramnames = new ArrayList<Name>();
/** set if this is a vararg function */
public boolean isvararg;
/** needsarg is set if the code is vararg and needs the "arg" table to be created. */
public boolean hasarg,needsarg;
/** max number of returns, or -1 for varargs */
public int maxReturns = 0;
/** set if there are logical subexpressions, or varargs assignment */
public boolean hasandlogic, hasorlogic, hasvarargassign, usesvarargs;
public LSFunction() {
}
public LSFunction(boolean isvararg) {
this.isvararg = isvararg;
}
public void setStatements(List<LSStatement> stats) {
this.stats.clear();
this.stats.addAll(stats);
}
public void setParameterNames(List<Name> list) {
this.paramnames.clear();
this.paramnames.addAll( list );
}
public String toString() { return "function("+paramnames+") "+stats+" end"; }
public void setUsesVarargs() {
this.usesvarargs = true;
if ( this.hasarg )
this.needsarg = false;
}
public void setHasArg() {
this.hasarg = true;
if ( ! this.usesvarargs )
this.needsarg = true;
}
}

View File

@@ -1,76 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc.lst;
import java.util.ArrayList;
import java.util.List;
public class LSIfStatement extends LSStatement {
public final LSExpression condition;
public final List<LSStatement> statements;
public List<ElseIf> elseifs;
public List<LSStatement> elsestatements;
public static class ElseIf {
public final LSExpression condition;
public final List<LSStatement> statements;
public ElseIf(LSExpression condition, List<LSStatement> statements) {
this.condition = condition;
this.statements = statements;
}
}
public LSIfStatement(LSExpression condition, List<LSStatement> statements) {
super( Type.ifStat );
this.condition = condition;
this.statements = statements;
}
public void addElseif(LSExpression condition, List<LSStatement> statements) {
if ( elseifs == null )
elseifs = new ArrayList<ElseIf>();
elseifs.add( new ElseIf( condition, statements ) );
}
public void addElse(List<LSStatement> statements) {
elsestatements = statements;
}
public String toString() {
return "if "+condition+" then "+statements+
(elseifs!=null? elseifs.toString(): "")+
(elsestatements!=null? " else "+elsestatements: "");
}
public boolean isNextStatementReachable() {
if ( isNextStatementReachable(statements) )
return true;
if ( elseifs != null )
for ( ElseIf e : elseifs )
if ( isNextStatementReachable(statements) )
return true;
if ( isNextStatementReachable(elsestatements) )
return true;
return false;
}
}

View File

@@ -1,327 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc.lst;
import java.util.List;
public class LSStatement {
public enum Type {
functionCall,
doBlock,
whileLoop,
repeatUntil,
varAssign,
forLoop,
forList,
varNamedFunction,
localFunction,
localAssign,
returnStat,
breakStat,
ifStat,
}
public final Type type;
LSStatement( Type type ) {
this.type = type;
}
public static LSStatement functionCallStatement(LSVariable variable) {
return new FunctionCall( variable );
}
public static LSStatement doBlockStatement(List<LSStatement> statements) {
return new DoBlock( statements );
}
public static LSStatement whileLoopStatement(LSExpression condition, List<LSStatement> statements) {
return new WhileLoop( condition, statements );
}
public static LSStatement repeatUntilStatement(List<LSStatement> statements, LSExpression condition) {
return new RepeatUntil( statements, condition );
}
public static LSStatement forLoopStatement(Name name, LSExpression initial,
LSExpression limit, LSExpression step, List<LSStatement> statements, Scope scope) {
return new ForLoop( name, initial, limit, step, statements, scope );
}
public static LSStatement forListStatement(List<Name> names,
List<LSExpression> expressions, List<LSStatement> statements, Scope scope, LSFunction function) {
return new ForList( names, expressions, statements, scope, function );
}
public static LSStatement varFunctionStatement(LSVariable funcname, LSFunction funcbody) {
return new VarNamedFunction( funcname, funcbody );
}
public static LSStatement localFunctionStatement(Name name, LSFunction funcbody) {
return new LocalFunction( name, funcbody );
}
public static LSStatement varAssignStatement(List<LSVariable> variables, List<LSExpression> expressions, Scope scope, LSFunction function) {
setExprNumReturns( variables.size(), expressions, function );
return new VarAssign( variables, expressions, scope );
}
public static LSStatement localAssignStatement(List<Name> names, List<LSExpression> expressions, Scope scope, LSFunction function) {
setExprNumReturns( names.size(), expressions, function );
return new LocalAssign( names, expressions, scope );
}
public static void setExprNumReturns( int nassign, List<LSExpression> expressions, LSFunction function ) {
int nexpr = expressions!=null? expressions.size(): 0;
for ( int i=0; i<nexpr; i++ )
expressions.get(i).setNumReturns(
(nassign<=nexpr)?
(i<nassign? 1: 0): // same or more expressions than names
(i<nexpr-1? 1: -1) ); // more names than expressions
if ( nassign > nexpr && nexpr > 0 && expressions.get(nexpr-1).getNumReturns() == -1 )
function.hasvarargassign = true;
}
public static LSStatement returnStatement(LSFunction function, List<LSExpression> expressions) {
int n=expressions!=null? expressions.size(): 0;
// set num returns of subexpressions
for ( int i=0; i<n; i++ )
expressions.get(i).setNumReturns(i<n-1? 1: -1); // last in list returns vararg
int nreturns = 0;
if ( n > 0 ) {
LSExpression last = expressions.get(n-1);
int lastreturns = last.getNumReturns();
nreturns = (lastreturns<0? -1: lastreturns+n-1);
}
// change the containing function to varargs if necessary.
if ( function.maxReturns != -1 && function.maxReturns < nreturns )
function.maxReturns = nreturns;
if ( function.maxReturns == -1 || function.maxReturns > 1 || nreturns < 0 )
function.isvararg = true;
return new ReturnStat( function, expressions );
}
public static LSStatement breakStatement() {
return new BreakStat();
}
/** Statement representing a function call on a variable, such as "foo.bar()" */
public static final class FunctionCall extends LSStatement {
public final LSVariable variable;
FunctionCall(LSVariable variable) {
super( Type.functionCall );
this.variable = variable;
}
public String toString() { return variable.toString()+"();"; }
}
/** do block, such as "do foo = bar end" */
public static final class DoBlock extends LSStatement {
public final List<LSStatement> statements;
DoBlock(List<LSStatement> statements) {
super( Type.doBlock );
this.statements = statements;
}
public String toString() { return "do "+statements+" end;"; }
public boolean isNextStatementReachable() {
return isNextStatementReachable(statements);
}
}
/** while loop, such as "while foo = true do bar() end" */
public static final class WhileLoop extends LSStatement {
public final LSExpression condition;
public final List<LSStatement> statements;
WhileLoop(LSExpression condition, List<LSStatement> statements) {
super( Type.whileLoop );
this.condition = condition;
this.statements = statements;
}
public String toString() { return "while "+condition+" do "+statements+" end;"; }
public boolean isNextStatementReachable() {
return isNextStatementReachable(statements);
}
}
/** repeat loop, such as "repeat foo() until bar == true" */
public static final class RepeatUntil extends LSStatement {
public final List<LSStatement> statements;
public final LSExpression condition;
RepeatUntil(List<LSStatement> statements, LSExpression condition) {
super( Type.repeatUntil );
this.statements = statements;
this.condition = condition;
}
public String toString() { return "repeat "+statements+" until "+condition+";"; }
public boolean isNextStatementReachable() {
return isNextStatementReachable(statements);
}
}
/** assignment to variables, such as "x.a,y.b = foo,bar" */
public static final class VarAssign extends LSStatement {
public final List<LSVariable> variables;
public final List<LSExpression> expressions;
public final Scope scope;
VarAssign(List<LSVariable> variables, List<LSExpression> expressions, Scope scope) {
super( Type.varAssign );
this.variables = variables;
this.expressions = expressions;
this.scope = scope;
}
public String toString() { return variables+"="+expressions+";"; }
}
/** for loop with index, such as "for i=1,10,2 do ... end" */
public static final class ForLoop extends LSStatement {
public final Name index;
public final LSExpression initial;
public final LSExpression limit;
public final LSExpression step;
public final List<LSStatement> statements;
public final Scope scope;
ForLoop(Name name, LSExpression initial, LSExpression limit, LSExpression step, List<LSStatement> statements, Scope scope) {
super( Type.forLoop );
this.index = name;
this.initial = initial;
this.limit = limit;
this.step = step;
this.statements = statements;
this.scope = scope;
initial.setNumReturns(1);
limit.setNumReturns(1);
if ( step != null )
step.setNumReturns(1);
}
public String toString() { return "for "+index+"="+initial+","+limit+","+step+" do "+statements+" end;"; }
public boolean isNextStatementReachable() {
return isNextStatementReachable(statements);
}
}
/** for loop with variable, such as "for i,j,k in foo() do ... end" */
public static final class ForList extends LSStatement {
public final List<Name> names;
public final List<LSExpression> expressions;
public final List<LSStatement> statements;
public final Scope scope;
ForList(List<Name> names, List<LSExpression> expressions, List<LSStatement> statements, Scope scope, LSFunction function) {
super( Type.forList );
this.names = names;
this.expressions = expressions;
this.statements = statements;
this.scope = scope;
// set return value count for each expression in list;
int ne = expressions.size();
for ( int i=0; i<ne-1 && i<3; i++ )
expressions.get(i).setNumReturns(1);
if ( ne<=3 ) {
expressions.get(ne-1).setNumReturns(3-(ne-1));
function.hasvarargassign = true;
}
}
public String toString() { return "for "+names+" in "+expressions+" do "+statements+" end;"; }
public boolean isNextStatementReachable() {
return isNextStatementReachable(statements);
}
}
/** variable function declaration, such as "a.b = function() end" */
public static final class VarNamedFunction extends LSStatement {
public final LSVariable funcname;
public final LSFunction funcbody;
VarNamedFunction(LSVariable funcname, LSFunction funcbody) {
super( Type.varNamedFunction );
this.funcname = funcname;
this.funcbody = funcbody;
}
public String toString() { return funcname+"=f:"+funcbody+";"; }
}
/** simple function declaration, such as "a = function() end" */
public static final class LocalFunction extends LSStatement {
public final Name name;
public final LSFunction funcbody;
LocalFunction(Name name, LSFunction funcbody) {
super( Type.localFunction );
this.name = name;
this.funcbody = funcbody;
}
public String toString() { return name+"=f:"+funcbody+";"; }
}
/** assignment, such as "a,b = foo,bar" */
public static final class LocalAssign extends LSStatement {
public final List<Name> names;
public final List<LSExpression> expressions;
public final Scope scope;
LocalAssign(List<Name> list, List<LSExpression> expressions, Scope scope) {
super( Type.localAssign );
this.names = list;
this.expressions = expressions;
this.scope = scope;
}
public String toString() { return names+"="+expressions+";"; }
}
/** return statement, such as "return foo,bar" */
public static final class ReturnStat extends LSStatement {
public final LSFunction function;
public final List<LSExpression> expressions;
ReturnStat(LSFunction function, List<LSExpression> expressions) {
super( Type.returnStat );
this.function = function;
this.expressions = expressions;
}
public String toString() { return "return "+expressions+";"; }
public boolean isNextStatementReachable() {
return false;
}
}
/** break statement */
public static final class BreakStat extends LSStatement {
BreakStat() {
super( Type.breakStat );
}
public String toString() { return "break;"; }
}
/** True of this statment could return and therefore the next statement is reachable. */
public boolean isNextStatementReachable() {
return true;
}
public static boolean isNextStatementReachable(List<LSStatement> stats) {
if ( stats == null )
return true;
for ( LSStatement s : stats )
if ( ! s.isNextStatementReachable() )
return false;
return true;
}
}

View File

@@ -1,172 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc.lst;
import java.util.List;
public class LSVariable extends LSExpression {
LSVariable(Type type) {
super(type);
}
/** name, such as 'foo' */
public static LSVariable nameVariable(Name name) {
return new NameReference(name);
}
/** table field, such as 'a.b' */
public LSVariable fieldVariable(String field) {
return new Field(this, field);
}
/** method reference, such as foo:bar */
public LSVariable methodVariable(String method) {
return new Method(this, method);
}
/** parenthetical reference, such as '(foo())' */
public static LSVariable parenthesesVariable(LSExpression expression) {
if ( expression != null )
expression.setNumReturns(1);
return new Parentheses(expression);
}
/** table index, such as 'a[b]' */
public LSVariable indexVariable(LSExpression expression) {
return new Index(this, expression);
}
/** Variable is a method, such as 'a(x,y)' */
public LSVariable callFuncVariable(List<LSExpression> parameters) {
int n = parameters.size();
for ( int i=0; i<n; i++ )
parameters.get(i).setNumReturns(i<n-1? 1: -1);
return new CallFunction(this, parameters);
}
/** Variable is a method, such as 'a:b(x,y)' */
public LSVariable callMethVariable(String method, List<LSExpression> parameters) {
int n = parameters.size();
for ( int i=0; i<n; i++ )
parameters.get(i).setNumReturns(i<n-1? 1: -1);
return new CallMethod(this, method, parameters);
}
/** name, such as 'foo' */
public static class NameReference extends LSVariable {
public final Name name;
public NameReference(Name name) {
super( Type.nameVariable );
this.name = name;
}
public String toString() { return name.toString(); }
}
/** field reference, such as foo.bar */
public static class Field extends LSVariable {
public final LSVariable variable;
public final String field;
public Field(LSVariable variable, String field) {
super( Type.fieldVariable );
this.variable = variable;
this.field = field;
}
public String toString() { return variable+"."+field; }
}
/** method reference, such as foo:bar */
public static class Method extends LSVariable {
public final LSVariable variable;
public final String method;
public Method(LSVariable variable, String method) {
super( Type.methodVariable );
this.variable = variable;
this.method = method;
}
public String toString() { return variable+":"+method; }
}
/** parenthetical reference, such as '(foo())' */
public static class Parentheses extends LSVariable {
public final LSExpression expression;
public Parentheses(LSExpression expression) {
super( Type.parenthesesVariable );
this.expression = expression;
}
public String toString() { return "("+expression+")"; }
}
/** table index, such as 'a[b]' */
public static class Index extends LSVariable {
public final LSVariable variable;
public final LSExpression expression;
public Index(LSVariable variable, LSExpression expression) {
super( Type.indexVariable );
this.variable = variable;
this.expression = expression;
}
public String toString() { return variable+"["+expression+"]"; }
}
/** Variable is a function invocation, such as 'a(x,y)' */
public static class CallFunction extends LSVariable {
public final LSVariable variable;
public final List<LSExpression> parameters;
public int numReturns = 0;
public CallFunction(LSVariable variable, List<LSExpression> parameters) {
super( Type.callFunctionVariable );
this.variable = variable;
this.parameters = parameters;
}
public void setNumReturns(int i) {
this.numReturns = i;
}
public int getNumReturns() {
return numReturns;
}
public String toString() { return variable+"("+parameters+")"; }
}
/** Variable is a method invocation, such as 'a:bc()' */
public static class CallMethod extends LSVariable {
public final LSVariable variable;
public final String method;
public final List<LSExpression> parameters;
public int numReturns = 0;
public CallMethod(LSVariable variable, String method, List<LSExpression> parameters) {
super( Type.callMethodVariable );
this.variable = variable;
this.method = method;
this.parameters = parameters;
}
public void setNumReturns(int i) {
this.numReturns = i;
}
public int getNumReturns() {
return numReturns;
}
public String toString() { return variable+":"+method+"("+parameters+")"; }
}
}

View File

@@ -1,73 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc.lst;
/** A name in lua source, which resolves to one of:
* - global reference
* - local that is not an upvalue
* - local that is an upvalue
*/
public class Name {
/** Name in lua source file */
public final String luaname;
/** 0 if in outermost scope, 1 if in next inner scope, ect. */
public final int scopelevel;
/** 0 if first declaration in global program, 1 if second use, etc. */
public final int outerrevision;
/** 0 if first declaration in nearest enclosing function, 1 if second use, etc */
public final int innerrevision;
/** true if used as an upvalue by some enclosed function */
public boolean isupvalue;
/** Construct a name instance */
public Name(String luaname, int scopelevel, int outerrevision, int innterrevision) {
super();
this.luaname = luaname;
this.scopelevel = scopelevel;
this.outerrevision = outerrevision;
this.innerrevision = innterrevision;
}
/** Construct a name reference representing a global reference */
public Name(String name) {
this.luaname = name;
this.scopelevel = -1;
this.outerrevision = -1;
this.innerrevision = -1;
}
public String toString() {
return scopelevel<0?
"_G$"+luaname:
luaname+"$s"+scopelevel+"$v"+outerrevision+"$f"+innerrevision;
}
public boolean isGlobal() {
return -1 == outerrevision;
}
}

View File

@@ -1,103 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc.lst;
import java.util.HashMap;
import java.util.Map;
/** A name scope in lua source terms.
* Combination of function scope and block scope.
*/
public class Scope {
public final Scope parent;
public final int level;
public final boolean isFunctionScope;
public boolean hasAndOrLogic;
public final Map<String,Name> names = new HashMap<String,Name>();
/** Construct a new default scope for a chunk */
public Scope() {
this.parent = null;
this.isFunctionScope = true;
this.level = 0;
}
/** Construct an inner scope
* @param parent the outer scope to fall back to, or null if a global scope
* @param isFunctionScope true if this is a function scope, false otherwise
*/
public Scope(Scope parent, boolean isFunctionScope) {
this.parent = parent;
this.isFunctionScope = isFunctionScope;
this.level = parent!=null? parent.level + 1: 0;
}
/** Declare a single name in the current scope, and return the Name element for it */
public Name declare(String name) {
boolean crossesFunctionBoundary = false;
for ( Scope s=this; s!=null; s=s.parent ) {
Name n = s.names.get(name);
if ( n != null ) {
Name result = new Name(name,
level,
n.outerrevision+1,
crossesFunctionBoundary? 0: n.innerrevision+1);
names.put(name, result);
return result;
}
if ( s.isFunctionScope )
crossesFunctionBoundary = true;
}
Name result = new Name(name, level, 0, 0);
names.put(name, result);
return result;
}
/** Reference a name, and find either the local scope within the function, the upvalue, or a global name */
public Name reference(String name) {
boolean crossesFunctionBoundary = false;
for ( Scope s=this; s!=null; s=s.parent ) {
Name n = s.names.get(name);
if ( n != null ) {
if ( crossesFunctionBoundary ) {
n.isupvalue = true;
}
return n;
}
if ( s.isFunctionScope )
crossesFunctionBoundary = true;
}
// globally scoped name
return new Name(name);
}
public String toString() {
String ours = (isFunctionScope? "F": "")+names;
return (parent==null? ours: ours+"->"+parent.toString());
}
/** Return true iff this scope is part the main chunk */
public boolean isMainChunkScope() {
return isFunctionScope? false: parent==null? true: parent.isMainChunkScope();
}
}

View File

@@ -1,43 +0,0 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc.lst;
public class UnOp {
public enum Type {
neg,not,len
}
public static final UnOp NEG = new UnOp(Type.neg, "-");
public static final UnOp NOT = new UnOp(Type.not, "~");
public static final UnOp LEN = new UnOp(Type.len, "#");
public final Type type;
public final String luaop;
private UnOp(Type type, String luaop) {
super();
this.type = type;
this.luaop = luaop;
}
public String toString() { return luaop; }
}

View File

@@ -28,7 +28,7 @@ import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.lib.JsePlatform;
import org.luaj.vm2.luajc.LuaJCompiler;
import org.luaj.vm2.luajc.LuaJC;
public class TestLuaJC {
// create the script
@@ -48,9 +48,7 @@ public class TestLuaJC {
LuaValue chunk;
if ( ! (args.length>0 && args[0].equals("nocompile")) ) {
InputStream is = new ByteArrayInputStream( script.getBytes() );
String java =LuaJCompiler.compileToJava(is, "script");
System.out.println("java:\n"+java);
chunk = LuaJCompiler.javaCompile(java, "script");
chunk = LuaJC.getInstance().load(is, "script", _G);
} else {
chunk = (LuaValue) Class.forName("script").newInstance();
}

View File

@@ -25,7 +25,7 @@ import junit.framework.Test;
import junit.framework.TestSuite;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.luajc.JavaBytecodeCompiler;
import org.luaj.vm2.luajc.LuaJC;
/**
* Compatibility tests for the Luaj VM
@@ -92,7 +92,7 @@ public class CompatibiltyTest {
protected void setUp() throws Exception {
super.setUp();
System.setProperty("JME", "false");
JavaBytecodeCompiler.install();
LuaJC.install();
}
// not supported on this platform - don't test
public void testDebugLib() {}

View File

@@ -27,7 +27,7 @@ import java.io.InputStream;
import junit.framework.TestCase;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.luajc.JavaBytecodeCompiler;
import org.luaj.vm2.luajc.LuaJC;
/**
* Test compilation of various fragments that have
@@ -43,7 +43,7 @@ public class FragmentsTest extends TestCase {
InputStream is = new ByteArrayInputStream(script.getBytes("UTF-8"));
LuaValue chunk ;
if ( true ) {
chunk = JavaBytecodeCompiler.load(is,name,_G);
chunk = LuaJC.getInstance().load(is,name,_G);
} else {
chunk = (new LuaC()).load( is, name, _G );
}

View File

@@ -32,7 +32,7 @@ import java.io.PrintStream;
import junit.framework.TestCase;
import org.luaj.vm2.lib.BaseLib;
import org.luaj.vm2.luajc.JavaBytecodeCompiler;
import org.luaj.vm2.luajc.LuaJC;
abstract
public class ScriptDrivenTest extends TestCase {
@@ -111,7 +111,7 @@ public class ScriptDrivenTest extends TestCase {
return c;
} else {
script = new FileInputStream(file);
return JavaBytecodeCompiler.load( script, name, _G);
return LuaJC.getInstance().load( script, name, _G);
}
default:
script = new FileInputStream(file);