diff --git a/README.html b/README.html index 097a0848..07c31f85 100644 --- a/README.html +++ b/README.html @@ -117,16 +117,6 @@ in comparison with the standard C distribution. 11.274 Java java -cp luaj-jse-3.0-alpha1.jar;bcel-5.2.jar lua -b fannkuch.lua 10 - - - - -j (lua2java) - 4.463 - 5.884 - 16.701 - 13.789 - - java -cp luaj-jse-3.0-alpha1.jar lua -j fannkuch.lua 10 @@ -179,8 +169,8 @@ in comparison with the standard C distribution. -Luaj in interpreted mode performs well for the benchmarks, and even better when source-to-source (lua2java) -or bytecode-to-bytecode (luajc) compilers are used, +Luaj in interpreted mode performs well for the benchmarks, and even better when +the lua-to-java-bytecode (luajc) compiler is used, and actually executes faster than C-based lua in some cases. It is also faster than Java-lua implementations Jill, Kahlua, and Mochalua for all benchmarks tested. @@ -220,29 +210,8 @@ From the main distribution directory line type:

The compiled output "luac.out" is lua bytecode and should run and produce the same result. -

Compile lua source to java source

-

-Luaj can compile to lua source code to Java source code: - -

-	java -cp lib/luaj-jse-3.0-alpha1.jar lua2java -s examples/lua -d . hello.lua
-	javac -cp lib/luaj-jse-3.0-alpha1.jar hello.java
-	java -cp "lib/luaj-jse-3.0-alpha1.jar;." lua -l hello
-
- -

-The output hello.java is Java source, that implements the logic in hello.lua directly. -Once hello.java is compiled into hello.class it can be required and used in place of the original lua script, but with better performance. -There are no additional dependencies for compiling or running source-to-source compiled lua. - -

-Lua scripts can also be run directly in this mode without precompiling using the lua command with the -j option when run in JDK 1.5 or higher: -

-	java -cp lib/luaj-jse-3.0-alpha1.jar lua -j examples/lua/hello.lua
-
- -

Compile lua bytecode to java bytecode

+

Compile lua source or bytecode to java bytecode

Luaj can compile lua sources or binaries directly to java bytecode if the bcel library is on the class path. From the main distribution directory line type: @@ -372,19 +341,6 @@ that are needed and omitting the line: -

Including the Lua2Java lua-source-to-Java-source compiler

- -

-To compile from lua sources to Java sources for all lua loaded at runtime, -install the Lua2Java compiler after globals have been created using: - -

-	org.luaj.vm2.jse.lua2java.Lua2Java.install();
-
- -This uses the system Java compiler to compile from Java source to Java bytecode, -and cannot compile lua binary files containing lua bytecode at runtime. -

Including the LuaJC lua-bytecode-to-Java-bytecode compiler

@@ -774,6 +730,7 @@ and LuaForge:

  • Fix load(func) when mutiple string fragments are supplied by calls to func
  • Allow access to public members of private inner classes where possible
  • Add line and column info to org.luaj.vm2.ast parse tree elements generated using LuaParser
  • +
  • Drop support for lua source to java surce (lua2java) in favor of direct java bytecode output (luajc)
  • diff --git a/src/core/org/luaj/vm2/LuaClosure.java b/src/core/org/luaj/vm2/LuaClosure.java index c38a32b4..365ca255 100644 --- a/src/core/org/luaj/vm2/LuaClosure.java +++ b/src/core/org/luaj/vm2/LuaClosure.java @@ -132,7 +132,6 @@ public class LuaClosure extends LuaFunction { public final LuaValue call() { LuaValue[] stack = new LuaValue[p.maxstacksize]; - System.arraycopy(NILS, 0, stack, 0, p.maxstacksize); return execute(stack,NONE).arg1(); } @@ -313,12 +312,13 @@ public class LuaClosure extends LuaFunction { case Lua.OP_JMP: /* sBx pc+=sBx */ pc += (i>>>14)-0x1ffff; - if (a > 0) - for (int j = 0; j < openups.length; ++j) - if (openups[j] != null && openups[j].index == a) { - openups[j].close(); - openups[j] = null; + if (a > 0) { + for (--a, b = openups.length; --b>=0; ) + if (openups[b] != null && openups[b].index >= a) { + openups[b].close(); + openups[b] = null; } + } continue; case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ @@ -466,7 +466,7 @@ public class LuaClosure extends LuaFunction { case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx]) */ { Prototype newp = p.p[i>>>14]; - LuaClosure ncl = new LuaClosure(newp); + LuaClosure ncl = new LuaClosure(newp, null); Upvaldesc[] uv = newp.upvalues; for ( int j=0, nup=uv.length; j= args.length ) usageExit(); @@ -139,7 +133,6 @@ public class lua { // new lua state _G = nodebug? JsePlatform.standardGlobals(): JsePlatform.debugGlobals(); if ( luajc ) LuaJC.install(); - if ( lua2java) Lua2Java.install(); for ( int i=0, n=libs!=null? libs.size(): 0; i= args.length ) - usageExit(); - srcdir = args[i]; - break; - case 'd': - if ( ++i >= args.length ) - usageExit(); - destdir = args[i]; - break; - case 'p': - if ( ++i >= args.length ) - usageExit(); - pkgprefix = args[i]; - break; - case 'e': - if ( ++i >= args.length ) - usageExit(); - encoding = args[i]; - break; - case 'r': - recurse = true; - break; - case 'v': - verbose = true; - break; - default: - usageExit(); - break; - } - } - } - - // echo version - if ( verbose ) { - System.out.println(version); - System.out.println("srcdir: "+srcdir); - System.out.println("destdir: "+destdir); - System.out.println("files: "+seeds); - System.out.println("encoding: "+encoding); - System.out.println("recurse: "+recurse); - } - - // need at least one seed - if ( seeds.size() <= 0 ) { - System.err.println(usage); - System.exit(-1); - } - - // collect up files to process - for ( int i=0; i constantDeclarations = new ArrayList(); - Map stringConstants = new HashMap(); - Map numberConstants = new HashMap(); - - - String indent = ""; - void addindent() { - indent+=" "; - } - void subindent() { - indent = indent.substring(3); - } - void out(String s) { - try { - writer.write(s); - } catch (IOException e) { - throw new RuntimeException("write failed: "+e, e); - } - } - void outi(String s) { - out( indent ); - out( s ); - } - void outl(String s) { - outi( s ); - out( "\n" ); - } - void outr(String s) { - out( s ); - out( "\n" ); - } - void outb(String s) { - outl( s ); - addindent(); - } - void oute(String s) { - subindent(); - outl( s ); - } - - public void visit(Chunk chunk) { - if ( packagename != null ) - outl("package "+packagename+";"); - outl("import org.luaj.vm2.*;"); - outl("import org.luaj.vm2.lib.*;"); - outb("public class "+classname+" extends VarArgFunction {"); - outl("public Varargs onInvoke(Varargs $arg) {"); - addindent(); - javascope = JavaScope.newJavaScope( chunk ); - writeBodyBlock(chunk.block); - oute("}"); - for ( int i=0, n=constantDeclarations.size(); i names = stat.names; - List values = stat.values; - int n = names.size(); - int m = values != null? values.size(): 0; - boolean isvarlist = m>0 && m values) { - int n = values!=null? values.size(): 0; - switch ( n ) { - case 0: return "NONE"; - case 1: return evalVarargs((Exp) values.get(0)); - default: - case 2: case 3: - Writer x = pushWriter(); - out( n>3? "varargsOf(new LuaValue[] {":"varargsOf(" ); - for ( int i=1; i3 ) - out( "}," ); - out( evalVarargs((Exp) values.get(n-1))+")" ); - return popWriter(x); - } - } - - Map callerExpects = new HashMap(); - - public String evalLuaValue(Exp exp) { - Writer x = pushWriter(); - callerExpects.put(exp,Integer.valueOf(1)); - exp.accept(this); - return popWriter(x); - } - - public String evalVarargs(Exp exp) { - Writer x = pushWriter(); - callerExpects.put(exp,Integer.valueOf(-1)); - exp.accept(this); - return popWriter(x); - } - - public String evalBoolean(Exp exp) { - Writer x = pushWriter(); - exp.accept(new Visitor() { - public void visit(UnopExp exp) { - switch ( exp.op ) { - case Lua.OP_NOT: - String rhs = evalBoolean( exp.rhs ); - out( "true".equals(rhs)? "false": - "false".equals(rhs)? "true": - "(!"+rhs+")"); - break; - default: out(evalLuaValue(exp)+".toboolean()"); break; - } - } - public void visit(BinopExp exp) { - switch ( exp.op ) { - case Lua.OP_AND: out("("+evalBoolean(exp.lhs)+"&&"+evalBoolean(exp.rhs)+")"); return; - case Lua.OP_OR: out("("+evalBoolean(exp.lhs)+"||"+evalBoolean(exp.rhs)+")"); return; - case Lua.OP_GT: out(evalLuaValue(exp.lhs)+".gt_b("+evalLuaValue(exp.rhs)+")"); return; - case Lua.OP_GE: out(evalLuaValue(exp.lhs)+".gteq_b("+evalLuaValue(exp.rhs)+")"); return; - case Lua.OP_LT: out(evalLuaValue(exp.lhs)+".lt_b("+evalLuaValue(exp.rhs)+")"); return; - case Lua.OP_LE: out(evalLuaValue(exp.lhs)+".lteq_b("+evalLuaValue(exp.rhs)+")"); return; - case Lua.OP_EQ: out(evalLuaValue(exp.lhs)+".eq_b("+evalLuaValue(exp.rhs)+")"); return; - case Lua.OP_NEQ: out(evalLuaValue(exp.lhs)+".neq_b("+evalLuaValue(exp.rhs)+")"); return; - default: out(evalLuaValue(exp)+".toboolean()"); return; - } - } - public void visit(Constant exp) { - switch ( exp.value.type() ) { - case LuaValue.TBOOLEAN: - out(exp.value.toboolean()? "true": "false"); - break; - default: - out(evalLuaValue(exp)+".toboolean()"); - break; - } - } - public void visit(ParensExp exp) { - out(evalBoolean(exp.exp)); - } - public void visit(VarargsExp exp) { - out(evalLuaValue(exp)+".toboolean()"); - } - public void visit(FieldExp exp) { - out(evalLuaValue(exp)+".toboolean()"); - } - public void visit(IndexExp exp) { - out(evalLuaValue(exp)+".toboolean()"); - } - public void visit(NameExp exp) { - if ( exp.name.variable.isConstant() ) { - out ( exp.name.variable.initialValue.toboolean()? "true": "false"); - return; - } - out(evalLuaValue(exp)+".toboolean()"); - } - public void visit(FuncCall exp) { - out(evalLuaValue(exp)+".toboolean()"); - } - public void visit(MethodCall exp) { - out(evalLuaValue(exp)+".toboolean()"); - } - public void visit(TableConstructor exp) { - out(evalLuaValue(exp)+".toboolean()"); - } - }); - return popWriter(x); - } - - public String evalNumber(Exp exp) { - Writer x = pushWriter(); - exp.accept(new Visitor() { - public void visit(UnopExp exp) { - switch ( exp.op ) { - case Lua.OP_LEN: out(evalLuaValue(exp.rhs)+".length()"); break; - case Lua.OP_UNM: out("(-"+evalNumber(exp.rhs)+")"); break; - default: out(evalLuaValue(exp)+".checkdouble()"); break; - } - } - public void visit(BinopExp exp) { - String op; - switch ( exp.op ) { - case Lua.OP_ADD: - case Lua.OP_SUB: - case Lua.OP_MUL: - op = (exp.op==Lua.OP_ADD? "+": exp.op==Lua.OP_SUB? "-": "*"); - out("("+evalNumber(exp.lhs)+op+evalNumber(exp.rhs)+")"); - break; - case Lua.OP_POW: out("MathLib.dpow_d("+evalNumber(exp.lhs)+","+evalNumber(exp.rhs)+")"); break; - case Lua.OP_DIV: out("LuaDouble.ddiv_d("+evalNumber(exp.lhs)+","+evalNumber(exp.rhs)+")"); break; - case Lua.OP_MOD: out("LuaDouble.dmod_d("+evalNumber(exp.lhs)+","+evalNumber(exp.rhs)+")"); break; - default: out(evalLuaValue(exp)+".checkdouble()"); break; - } - } - public void visit(Constant exp) { - switch ( exp.value.type() ) { - case LuaValue.TNUMBER: - out( evalNumberLiteral(exp.value.checkdouble()) ); - break; - default: - out(evalLuaValue(exp)+".checkdouble()"); - break; - } - } - public void visit(ParensExp exp) { - out(evalNumber(exp.exp)); - } - public void visit(VarargsExp exp) { - out(evalLuaValue(exp)+".checkdouble()"); - } - public void visit(FieldExp exp) { - out(evalLuaValue(exp)+".checkdouble()"); - } - public void visit(IndexExp exp) { - out(evalLuaValue(exp)+".checkdouble()"); - } - public void visit(NameExp exp) { - if ( exp.name.variable.isConstant() ) { - if ( exp.name.variable.initialValue.isnumber() ) { - out( evalNumberLiteral(exp.name.variable.initialValue.checkdouble()) ); - return; - } - } - out(evalLuaValue(exp)+".checkdouble()"); - } - public void visit(FuncCall exp) { - out(evalLuaValue(exp)+".checkdouble()"); - } - public void visit(MethodCall exp) { - out(evalLuaValue(exp)+".checkdouble()"); - } - public void visit(TableConstructor exp) { - out(evalLuaValue(exp)+".checkdouble()"); - } - }); - return popWriter(x); - } - - public void visit(FuncCallStat stat) { - outi(""); - stat.funccall.accept(this); - outr(";"); - } - - public void visit(BinopExp exp) { - switch ( exp.op ) { - case Lua.OP_AND: - case Lua.OP_OR: - String not = (exp.op==Lua.OP_AND? "!": ""); - out("("+not+"($b="+evalLuaValue(exp.lhs)+").toboolean()?$b:"+evalLuaValue(exp.rhs)+")"); - return; - } - switch ( exp.op ) { - case Lua.OP_ADD: out("valueOf("+evalNumber(exp.lhs)+"+"+evalNumber(exp.rhs)+")"); return; - case Lua.OP_SUB: out("valueOf("+evalNumber(exp.lhs)+"-"+evalNumber(exp.rhs)+")"); return; - case Lua.OP_MUL: out("valueOf("+evalNumber(exp.lhs)+"*"+evalNumber(exp.rhs)+")"); return; - case Lua.OP_POW: out("MathLib.dpow("+evalNumber(exp.lhs)+","+evalNumber(exp.rhs)+")"); return; - case Lua.OP_DIV: out("LuaDouble.ddiv("+evalNumber(exp.lhs)+","+evalNumber(exp.rhs)+")"); return; - case Lua.OP_MOD: out("LuaDouble.dmod("+evalNumber(exp.lhs)+","+evalNumber(exp.rhs)+")"); return; - case Lua.OP_GT: out(evalLuaValue(exp.lhs)+".gt("+evalLuaValue(exp.rhs)+")"); return; - case Lua.OP_GE: out(evalLuaValue(exp.lhs)+".gteq("+evalLuaValue(exp.rhs)+")"); return; - case Lua.OP_LT: out(evalLuaValue(exp.lhs)+".lt("+evalLuaValue(exp.rhs)+")"); return; - case Lua.OP_LE: out(evalLuaValue(exp.lhs)+".lteq("+evalLuaValue(exp.rhs)+")"); return; - case Lua.OP_EQ: out(evalLuaValue(exp.lhs)+".eq("+evalLuaValue(exp.rhs)+")"); return; - case Lua.OP_NEQ: out(evalLuaValue(exp.lhs)+".neq("+evalLuaValue(exp.rhs)+")"); return; - case Lua.OP_CONCAT: - if ( isConcatExp(exp.rhs) ) { - out( evalLuaValue(exp.lhs) ); - Exp e = exp.rhs; - String close = ""; - for ( ; isConcatExp(e); e=((BinopExp)e).rhs ) { - out( ".concat("+evalLuaValue(((BinopExp)e).lhs) ); - close += ')'; - } - out( ".concat("+evalLuaValue(e)+".buffer())" ); - out( close ); - out( ".value()" ); - } else { - out(evalLuaValue(exp.lhs)+".concat("+evalLuaValue(exp.rhs)+")"); - } - return; - default: throw new IllegalStateException("unknown bin op:"+exp.op); - } - } - - private boolean isConcatExp(Exp e) { - return (e instanceof BinopExp) && (((BinopExp)e).op == Lua.OP_CONCAT); - } - - public void visit(UnopExp exp) { - exp.rhs.accept(this); - switch ( exp.op ) { - case Lua.OP_NOT: out(".not()"); break; - case Lua.OP_LEN: out(".len()"); break; - case Lua.OP_UNM: out(".neg()"); break; - } - } - - public void visit(Constant exp) { - out( evalConstant(exp.value) ); - } - - protected String evalConstant(LuaValue value) { - switch ( value.type() ) { - case LuaValue.TSTRING: - return evalLuaStringConstant(value.checkstring()); - case LuaValue.TNIL: - return "NIL"; - case LuaValue.TBOOLEAN: - return value.toboolean()? "TRUE": "FALSE"; - case LuaValue.TNUMBER: - return evalNumberConstant(value.todouble()); - default: - throw new IllegalStateException("unknown constant type: "+value.typename()); - } - } - - private String evalStringConstant(String str) { - return evalLuaStringConstant( LuaValue.valueOf(str) ); - } - - private String evalLuaStringConstant(LuaString str) { - if ( stringConstants.containsKey(str) ) - return (String) stringConstants.get(str); - String declvalue = quotedStringInitializer(str); - String javaname = javascope.createConstantName(str.tojstring()); - constantDeclarations.add( "static final LuaValue "+javaname+" = valueOf("+declvalue+");" ); - stringConstants.put(str,javaname); - return javaname; - } - - private String evalNumberConstant(double value) { - if ( value == 0 ) return "ZERO"; - if ( value == -1 ) return "MINUSONE"; - if ( value == 1 ) return "ONE"; - if ( numberConstants.containsKey(Double.valueOf(value)) ) - return (String) numberConstants.get(Double.valueOf(value)); - String declvalue = evalNumberLiteral(value); - String javaname = javascope.createConstantName(declvalue); - constantDeclarations.add( "static final LuaValue "+javaname+" = valueOf("+declvalue+");" ); - numberConstants.put(Double.valueOf(value),javaname); - return javaname; - } - - private String evalNumberLiteral(double value) { - int ivalue = (int) value; - String svalue = value==ivalue? String.valueOf(ivalue): String.valueOf(value); - return (value < 0? "("+svalue+")": svalue); - } - - public void visit(FieldExp exp) { - exp.lhs.accept(this); - out(".get("+evalStringConstant(exp.name.name)+")"); - } - - public void visit(IndexExp exp) { - exp.lhs.accept(this); - out(".get("); - exp.exp.accept(this); - out(")"); - } - - public void visit(NameExp exp) { - singleReference( exp.name ); - } - - public void visit(ParensExp exp) { - if ( exp.exp.isvarargexp() ) - out( evalLuaValue(exp.exp) ); - else - exp.exp.accept(this); - } - - public void visit(VarargsExp exp) { - int c = callerExpects.containsKey(exp)? ((Integer)callerExpects.get(exp)).intValue(): 0; - out( c==1? "$arg.arg1()": "$arg" ); - } - - public void visit(MethodCall exp) { - List e = exp.args.exps; - int n = e != null? e.size(): 0; - int c = callerExpects.containsKey(exp)? ((Integer)callerExpects.get(exp)).intValue(): 0; - if ( c == -1 ) - n = -1; - out( evalLuaValue(exp.lhs) ); - switch ( n ) { - case 0: - out(".method("+evalStringConstant(exp.name)+")"); - break; - case 1: case 2: - out(".method("+evalStringConstant(exp.name)+","); - exp.args.accept(this); - out(")"); - break; - default: - out(".invokemethod("+evalStringConstant(exp.name) - +((e==null||e.size()==0)? "": ","+evalListAsVarargs(exp.args.exps))+")"); - if ( c == 1 ) - out(".arg1()"); - break; - } - } - - public void visit(FuncCall exp) { - List e = exp.args.exps; - int n = e != null? e.size(): 0; - if ( n > 0 && ((Exp)e.get(n-1)).isvarargexp() ) - n = -1; - int c = callerExpects.containsKey(exp)? ((Integer)callerExpects.get(exp)).intValue(): 0; - if ( c == -1 ) - n = -1; - out( evalLuaValue(exp.lhs) ); - switch ( n ) { - case 0: case 1: case 2: case 3: - out(".call("); - exp.args.accept(this); - out(")"); - break; - default: - out(".invoke("+((e==null||e.size()==0)? "": evalListAsVarargs(e))+")"); - if ( c == 1 ) - out(".arg1()"); - break; - } - } - - public void tailCall( Exp e ) { - if ( e instanceof MethodCall ) { - MethodCall mc = (MethodCall) e; - outl("return new TailcallVarargs("+evalLuaValue(mc.lhs)+","+evalStringConstant(mc.name)+","+evalListAsVarargs(mc.args.exps)+");"); - } else if ( e instanceof FuncCall ) { - FuncCall fc = (FuncCall) e; - outl("return new TailcallVarargs("+evalLuaValue(fc.lhs)+","+evalListAsVarargs(fc.args.exps)+");"); - } else { - throw new IllegalArgumentException("can't tail call "+e); - } - } - - public void visit(FuncArgs args) { - if ( args.exps != null ) { - int n = args.exps.size(); - if ( n > 0 ) { - for ( int i=1; i=0 && n<=1 && m<=3 && ! body.parlist.isvararg ) { - switch ( m ) { - case 0: - outr("new ZeroArgFunction(env) {"); - addindent(); - outb("public LuaValue call() {"); - break; - case 1: - outr("new OneArgFunction(env) {"); - addindent(); - outb("public LuaValue call(" - +declareArg((Name) body.parlist.names.get(0))+") {"); - assignArg((Name) body.parlist.names.get(0)); - break; - case 2: - outr("new TwoArgFunction(env) {"); - addindent(); - outb("public LuaValue call(" - +declareArg((Name) body.parlist.names.get(0))+"," - +declareArg((Name) body.parlist.names.get(1))+") {"); - assignArg((Name) body.parlist.names.get(0)); - assignArg((Name) body.parlist.names.get(1)); - break; - case 3: - outr("new ThreeArgFunction(env) {"); - addindent(); - outb("public LuaValue call(" - +declareArg((Name) body.parlist.names.get(0))+"," - +declareArg((Name) body.parlist.names.get(1))+"," - +declareArg((Name) body.parlist.names.get(2))+") {"); - assignArg((Name) body.parlist.names.get(0)); - assignArg((Name) body.parlist.names.get(1)); - assignArg((Name) body.parlist.names.get(2)); - break; - } - } else { - outr("new VarArgFunction(env) {"); - addindent(); - outb("public Varargs invoke(Varargs $arg) {"); - for ( int i=0; i0? "$arg.arg("+(i+1)+")": "$arg.arg1()"; - singleLocalDeclareAssign( name, value ); - } - if ( body.parlist.isvararg ) { - Variable arg = body.scope.find("arg"); - javascope.setJavaName(arg,"arg"); - if ( m > 0 ) - outl( "$arg = $arg.subargs("+(m+1)+");" ); - String value = (javascope.usesvarargs? "NIL": "LuaValue.tableOf($arg,1)"); - singleLocalDeclareAssign( arg, value ); - } - } - writeBodyBlock(body.block); - oute("}"); - subindent(); - outi("}"); - javascope = javascope.popJavaScope(); - } - - private String declareArg(Name name) { - String argname = javascope.getJavaName(name.variable); - return "LuaValue "+argname+(name.variable.isupvalue? "$0": ""); - } - - private void assignArg(Name name) { - if ( name.variable.isupvalue ) { - String argname = javascope.getJavaName(name.variable); - singleLocalDeclareAssign(name, argname+"$0"); - } - } - - public void visit(FuncDef stat) { - Writer x = pushWriter(); - stat.body.accept(this); - String value = popWriter(x); - int n = stat.name.dots!=null? stat.name.dots.size(): 0; - boolean m = stat.name.method != null; - if ( n>0 && !m && stat.name.name.variable.isLocal() ) - singleAssign( stat.name.name, value ); - else if ( n==0 && !m ) { - singleAssign( stat.name.name, value ); - } else { - singleReference( stat.name.name ); - for ( int i=0; i0? ("+i+"<="+j+"$limit): ("+i+">="+j+"$limit);" ); - outr( " "+i+"+="+j+"$step ) {" ); - } - addindent(); - singleLocalDeclareAssign(stat.name, "valueOf("+i+")"); - super.visit(stat.block); - oute( "}" ); - } - - private Name tmpJavaVar(String s) { - Name n = new Name(s); - n.variable = javascope.define(s); - return n; - } - - public void visit(GenericFor stat) { - Name f = tmpJavaVar("f"); - Name s = tmpJavaVar("s"); - Name var = tmpJavaVar("var"); - Name v = tmpJavaVar("v"); - String javaf = javascope.getJavaName(f.variable); - String javas = javascope.getJavaName(s.variable); - String javavar = javascope.getJavaName(var.variable); - String javav = javascope.getJavaName(v.variable); - outl("LuaValue "+javaf+","+javas+","+javavar+";"); - outl("Varargs "+javav+";"); - List fsvar = new ArrayList(); - fsvar.add(f); - fsvar.add(s); - fsvar.add(var); - multiAssign(fsvar, stat.exps); - - outb("while (true) {"); - outl( javav+" = "+javaf+".invoke(varargsOf("+javas+","+javavar+"));"); - outl( "if (("+javavar+"="+javav+".arg1()).isnil()) break;"); - singleLocalDeclareAssign((Name) stat.names.get(0),javavar); - for ( int i=1, n=stat.names.size(); i keyed = new ArrayList(); - List list = new ArrayList(); - for ( int i=0; i exps) { - super.visitExps(exps); - } - - public void visitNames(List names) { - super.visitNames(names); - } - - public void visitVars(List vars) { - super.visitVars(vars); - } - } - - private static String quotedStringInitializer(LuaString s) { - byte[] bytes = s.m_bytes; - int o = s.m_offset; - int n = s.m_length; - StringBuffer sb = new StringBuffer(n+2); - - // check for bytes not encodable as utf8 - if ( ! s.isValidUtf8() ) { - sb.append( "new byte[]{" ); - for ( int j=0; j0 ) sb.append(","); - byte b = bytes[o+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= ' ' ) { - sb.append( (char) b ); break; - } else { - // convert from UTF-8 - int u = 0xff & (int) b; - if ( u>=0xc0 && i+1=0xe0 && i+2 SPECIALS = new HashSet(); - - private static final String[] specials = { - // keywords used by our code generator - "name", "opcode", "env", // "arg", - - // 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", - - // java literals - "false", "null", "true", - }; - - static { - for ( int i=0; i staticnames; - final Set javanames = new HashSet(); - final Map astele2javaname = new HashMap(); - - private JavaScope(Set staticnames, JavaScope outerScope) { - super(outerScope); - this.staticnames = staticnames; - } - - public static JavaScope newJavaScope(Chunk chunk) { - return new JavaScope(new HashSet(), null).initialize(chunk.block, -1); - } - - public JavaScope pushJavaScope(FuncBody body) { - return new JavaScope(staticnames, this).initialize(body.block, 0); - } - - public JavaScope popJavaScope() { - return (JavaScope) outerScope; - } - - final String getJavaName(Variable nv) { - for ( JavaScope s = this; s != null; s = (JavaScope) s.outerScope ) - if ( s.astele2javaname.containsKey(nv) ) - return (String) s.astele2javaname.get(nv); - return allocateJavaName( nv, nv.name ); - } - - final private String allocateJavaName(Object astele, String proposal) { - for ( int i=0; true; i++ ) { - String jname = proposal+(i==0? "": "$"+i); - if ( ! isJavanameInScope(jname) && ! SPECIALS.contains(jname) && !staticnames.contains(jname) ) { - javanames.add(jname); - astele2javaname.put(astele,jname); - return jname; - } - } - } - - public void setJavaName(Variable astele, String javaname) { - javanames.add(javaname); - astele2javaname.put(astele,javaname); - } - - private boolean isJavanameInScope(String javaname) { - for ( JavaScope s = this; s != null; s = (JavaScope) s.outerScope ) - if ( s.javanames.contains(javaname) ) - return true; - return false; - } - - public String createConstantName(String proposal) { - proposal = toLegalJavaName(proposal); - for ( int i=0; true; i++ ) { - String jname = proposal+(i==0? "": "$"+i); - if ( ! isJavanameInScope(jname) && ! SPECIALS.contains(jname) && !staticnames.contains(jname) ) { - javanames.add(jname); - staticnames.add(jname); - return jname; - } - } - } - - public static String toLegalJavaName(String string) { - String better = string.replaceAll("[^\\w]", "_"); - if ( better.length() > MAX_CONSTNAME_LEN ) - better = better.substring(0,MAX_CONSTNAME_LEN); - if ( better.length() == 0 || !Character.isJavaIdentifierStart( better.charAt(0) ) ) - better = "_"+better; - return better; - } - - private JavaScope initialize(Block block, int nreturns) { - NewScopeVisitor v = new NewScopeVisitor(nreturns); - block.accept( v ); - this.nreturns = v.nreturns; - this.needsbinoptmp = v.needsbinoptmp; - this.usesvarargs = v.usesvarargs; - return this; - } - - class NewScopeVisitor extends Visitor { - int nreturns = 0; - boolean needsbinoptmp = false; - boolean usesvarargs = false; - NewScopeVisitor(int nreturns) { - this.nreturns = nreturns; - } - public void visit(FuncBody body) {} - public void visit(Return s) { - int n = s.nreturns(); - nreturns = (nreturns<0||n<0? -1: Math.max(n,nreturns)); - super.visit(s); - } - public void visit(BinopExp exp) { - switch ( exp.op ) { - case Lua.OP_AND: case Lua.OP_OR: - needsbinoptmp = true; - break; - } - super.visit(exp); - } - public void visit(VarargsExp exp) { - usesvarargs = true; - } - - } - -} diff --git a/src/jse/org/luaj/vm2/lua2java/Lua2Java.java b/src/jse/org/luaj/vm2/lua2java/Lua2Java.java deleted file mode 100644 index e1aca431..00000000 --- a/src/jse/org/luaj/vm2/lua2java/Lua2Java.java +++ /dev/null @@ -1,165 +0,0 @@ -package org.luaj.vm2.lua2java; - -import java.io.BufferedInputStream; -import java.io.DataInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -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.LoadState; -import org.luaj.vm2.LuaFunction; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.LoadState.LuaCompiler; -import org.luaj.vm2.ast.Chunk; -import org.luaj.vm2.compiler.LuaC; -import org.luaj.vm2.parser.LuaParser; - -public class Lua2Java implements LuaCompiler { - - public static final Lua2Java instance = new Lua2Java(); - - public static final void install() { - LoadState.compiler = instance; - } - - private Lua2Java() { - } - - public LuaFunction load(InputStream stream, String filename, LuaValue env) throws IOException { - - // get first byte - if ( ! stream.markSupported() ) - stream = new BufferedInputStream( stream ); - stream.mark( 1 ); - int firstByte = stream.read(); - stream.reset(); - - // we can only sompile sources - if ( firstByte != '\033' ) { - final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); - if (compiler == null) - LuaValue.error("no java compiler"); - - // break into package and class - if ( filename.endsWith( ".lua") ) - filename = filename.substring(0, filename.length()-4); - String s = filename.replace('\\', '/').replace('/','.').replaceAll("[^\\w]", "_"); - int p = s.lastIndexOf('.'); - final String packageName = p>=0? s.substring(0,p): null; - final String className = toClassname( s.substring(p+1) ); - - // open output file - final String pkgSubdir = (packageName!=null? packageName.replace('.','/'): ""); - final String srcDirRoot = "lua2java/src"; - final String binDirRoot = "lua2java/classes"; - final String srcDirname = srcDirRoot+"/"+pkgSubdir; - final String binDirname = binDirRoot+"/"+pkgSubdir; - final String srcFilename = srcDirname + "/" + className + ".java"; - - // make directories - new File(srcDirname).mkdirs(); - new File(binDirname).mkdirs(); - - // generate java source - try { - LuaParser parser = new LuaParser(stream,"ISO8859-1"); - Chunk chunk = parser.Chunk(); - File source = new File(srcFilename); - Writer writer = new OutputStreamWriter( new FileOutputStream(source) ); - new JavaCodeGen(chunk,writer,packageName,className); - writer.close(); - - // set up output location - StandardJavaFileManager fm = compiler.getStandardFileManager( null, null, null); - fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File[] { new File(binDirRoot) })); - - // compile the file - CompilationTask task = compiler.getTask(null, fm, null, null, null, fm.getJavaFileObjects(source)); - boolean success = task.call().booleanValue(); - - // instantiate, config and return - if (success) { - // create instance - ClassLoader cl = new ClassLoader() { - public Class findClass(String classname) throws ClassNotFoundException { - if ( classname.startsWith(className) ) { - File f = new File( binDirname+"/"+classname+".class"); - long n = f.length(); - byte[] b = new byte[(int) n]; - try { - DataInputStream dis = new DataInputStream( new FileInputStream(f) ); - dis.readFully(b); - } catch ( Exception e ) { - throw new RuntimeException("failed to read class bytes: "+e ); - } - return defineClass(classname, b, 0, b.length); - } - return super.findClass(classname); - } - }; - Class clazz = cl.loadClass(className); - Object instance = clazz.newInstance(); - LuaFunction value = (LuaFunction) instance; - return value; - } else { - } - } catch ( Exception e ) { - LuaValue.error("compile task failed: "+e); - } - - // report compilation error - LuaValue.error("compile task failed:"); - return null; - } - - // fall back to plain compiler - return LuaC.instance.load( stream, filename, env); - } - - /** Convert lua filename to valid class name */ - public static final String toClassname( String filename ) { - int n=filename.length(); - int j=n; - if ( filename.endsWith(".lua") ) - j -= 4; - for ( int k=0; k='a'&&c<='z') || (c>='A'&&c<='Z') || (c>='0'&&c<='9') ) - return true; - switch ( c ) { - case '.': - case '$': - case '_': - return true; - default: - return false; - } - } -} diff --git a/test/junit/org/luaj/vm2/CompatibiltyTest.java b/test/junit/org/luaj/vm2/CompatibiltyTest.java index 8d7bac70..54a42934 100644 --- a/test/junit/org/luaj/vm2/CompatibiltyTest.java +++ b/test/junit/org/luaj/vm2/CompatibiltyTest.java @@ -23,7 +23,6 @@ package org.luaj.vm2; import junit.framework.TestSuite; -import org.luaj.vm2.lua2java.Lua2Java; import org.luaj.vm2.luajc.LuaJC; /** @@ -80,21 +79,9 @@ public class CompatibiltyTest extends TestSuite { suite.addTest( new TestSuite( JseCompatibilityTest.class, "JSE Tests" ) ); suite.addTest( new TestSuite( JmeCompatibilityTest.class, "JME Tests" ) ); suite.addTest( new TestSuite( LuaJCTest.class, "JSE Bytecode Tests" ) ); - suite.addTest( new TestSuite( Lua2JavaTest.class, "Lua2Java Tests" ) ); return suite; } - public static class Lua2JavaTest extends CompatibiltyTestSuite { - public Lua2JavaTest() { - super(ScriptDrivenTest.PlatformType.LUA2JAVA); - } - protected void setUp() throws Exception { - super.setUp(); - System.setProperty("JME", "false"); - Lua2Java.install(); - } - } - public static class JmeCompatibilityTest extends CompatibiltyTestSuite { public JmeCompatibilityTest() { super(ScriptDrivenTest.PlatformType.JME); diff --git a/test/junit/org/luaj/vm2/FragmentsTest.java b/test/junit/org/luaj/vm2/FragmentsTest.java index 72daa032..42029d04 100644 --- a/test/junit/org/luaj/vm2/FragmentsTest.java +++ b/test/junit/org/luaj/vm2/FragmentsTest.java @@ -28,7 +28,6 @@ import junit.framework.TestCase; import junit.framework.TestSuite; import org.luaj.vm2.compiler.LuaC; -import org.luaj.vm2.lua2java.Lua2Java; import org.luaj.vm2.luajc.LuaJC; /** @@ -40,7 +39,6 @@ public class FragmentsTest extends TestSuite { static final int TEST_TYPE_LUAC = 0; static final int TEST_TYPE_LUAJC = 1; - static final int TEST_TYPE_LUA2JAVA = 2; public static class JseFragmentsTest extends FragmentsTestCase { public JseFragmentsTest() { super( TEST_TYPE_LUAC ); } @@ -48,15 +46,10 @@ public class FragmentsTest extends TestSuite { public static class LuaJCFragmentsTest extends FragmentsTestCase { public LuaJCFragmentsTest() { super( TEST_TYPE_LUAJC ); } } - public static class Lua2JavaFragmentsTest extends FragmentsTestCase { - public Lua2JavaFragmentsTest() { super( TEST_TYPE_LUA2JAVA ); } - } - public static TestSuite suite() { TestSuite suite = new TestSuite("Compiler Fragments Tests"); suite.addTest( new TestSuite( JseFragmentsTest.class, "JSE Fragments Tests" ) ); suite.addTest( new TestSuite( LuaJCFragmentsTest.class, "LuaJC Fragments Tests" ) ); - suite.addTest( new TestSuite( Lua2JavaFragmentsTest.class, "Lua2Java Fragments Tests" ) ); return suite; } @@ -75,9 +68,6 @@ public class FragmentsTest extends TestSuite { InputStream is = new ByteArrayInputStream(script.getBytes("UTF-8")); LuaValue chunk ; switch ( TEST_TYPE ) { - case TEST_TYPE_LUA2JAVA: - chunk = Lua2Java.instance.load(is,name,LuaValue._G); - break; case TEST_TYPE_LUAJC: chunk = LuaJC.getInstance().load(is,name,LuaValue._G); break; diff --git a/test/junit/org/luaj/vm2/ScriptDrivenTest.java b/test/junit/org/luaj/vm2/ScriptDrivenTest.java index b7e30260..98973b25 100644 --- a/test/junit/org/luaj/vm2/ScriptDrivenTest.java +++ b/test/junit/org/luaj/vm2/ScriptDrivenTest.java @@ -41,7 +41,7 @@ public class ScriptDrivenTest extends TestCase { public static final boolean nocompile = "true".equals(System.getProperty("nocompile")); public enum PlatformType { - JME, JSE, LUAJIT, LUA2JAVA, + JME, JSE, LUAJIT, } private final PlatformType platform; @@ -59,7 +59,6 @@ public class ScriptDrivenTest extends TestCase { default: case JSE: case LUAJIT: - case LUA2JAVA: _G = org.luaj.vm2.lib.jse.JsePlatform.debugGlobals(); break; case JME: