From 6364b002e41f2fe3d51331b92ecfe740a906438f Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Mon, 26 Jul 2010 05:58:34 +0000 Subject: [PATCH] Fix java code generator including adding tail call support. --- src/core/org/luaj/vm2/TailcallVarargs.java | 5 ++ .../org/luaj/vm2/lua2java/JavaCodeGen.java | 47 ++++++++++++++----- src/jse/org/luaj/vm2/lua2java/JavaScope.java | 8 ++++ test/lua/tailcalls.lua | 2 +- 4 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/core/org/luaj/vm2/TailcallVarargs.java b/src/core/org/luaj/vm2/TailcallVarargs.java index d057cfa3..d55febd7 100644 --- a/src/core/org/luaj/vm2/TailcallVarargs.java +++ b/src/core/org/luaj/vm2/TailcallVarargs.java @@ -32,6 +32,11 @@ public class TailcallVarargs extends Varargs { this.args = args; } + public TailcallVarargs(LuaValue object, LuaValue methodname, Varargs args) { + this.func = object.get(methodname); + this.args = args; + } + public boolean isTailcall() { return true; } diff --git a/src/jse/org/luaj/vm2/lua2java/JavaCodeGen.java b/src/jse/org/luaj/vm2/lua2java/JavaCodeGen.java index 5dc80c46..610dcb43 100644 --- a/src/jse/org/luaj/vm2/lua2java/JavaCodeGen.java +++ b/src/jse/org/luaj/vm2/lua2java/JavaCodeGen.java @@ -135,7 +135,7 @@ public class JavaCodeGen { outl("import org.luaj.vm2.*;"); outl("import org.luaj.vm2.lib.*;"); outb("public class "+classname+" extends VarArgFunction {"); - outl("public Varargs invoke(Varargs $arg) {"); + outl("public Varargs onInvoke(Varargs $arg) {"); addindent(); javascope = JavaScope.newJavaScope( chunk ); writeBodyBlock(chunk.block); @@ -182,9 +182,18 @@ public class JavaCodeGen { public void visit(Stat.Return s) { int n = s.nreturns(); switch ( n ) { - case 0: outl( "return NONE;" ); break; - case 1: outl( "return "+evalLuaValue(s.values.get(0))+";" ); break; - default: outl( "return "+evalListAsVarargs(s.values)+";" ); break; + case 0: + outl( "return NONE;" ); + break; + case 1: + outl( "return "+evalLuaValue(s.values.get(0))+";" ); + break; + default: + if ( s.values.size()==1 && s.values.get(0).isfunccall() ) + tailCall( s.values.get(0) ); + else + outl( "return "+evalListAsVarargs(s.values)+";" ); + break; } } @@ -249,7 +258,7 @@ public class JavaCodeGen { if ( exp.name.variable.isLocal() ) singleLocalAssign(exp.name, valu); else - outl( "env.set("+evalLuaValue(exp)+","+valu+");"); + outl( "env.set("+evalStringConstant(exp.name.name)+","+valu+");"); } }; if ( varOrName instanceof VarExp ) @@ -446,7 +455,7 @@ public class JavaCodeGen { public void visit(VarargsExp exp) { int c = callerExpects.containsKey(exp)? callerExpects.get(exp): 0; - out( c==1? "arg.arg1()": "arg" ); + out( c==1? "$arg.arg1()": "$arg" ); } public void visit(MethodCall exp) { @@ -497,6 +506,18 @@ public class JavaCodeGen { } } + 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(); @@ -551,12 +572,6 @@ public class JavaCodeGen { outr("new VarArgFunction(env) {"); addindent(); outb("public Varargs invoke(Varargs $arg) {"); - if ( body.parlist.isvararg ) { - NamedVariable arg = body.scope.find("arg"); - javascope.setJavaName(arg,"arg"); - String value = "LuaValue.tableOf($arg,"+(m+1)+")"; - outl( arg.isupvalue? "final LuaValue[] arg = {"+value+"};": "LuaValue arg = "+value+";" ); - } for ( int i=0; i 0 ) + outl( "$arg = $arg.subargs("+(m+1)+");" ); + String value = (javascope.usesvarargs? "NIL": "LuaValue.tableOf($arg,1)"); + outl( arg.isupvalue? "final LuaValue[] arg = {"+value+"};": "LuaValue arg = "+value+";" ); + } } writeBodyBlock(body.block); oute("}"); diff --git a/src/jse/org/luaj/vm2/lua2java/JavaScope.java b/src/jse/org/luaj/vm2/lua2java/JavaScope.java index 1460b43d..d6d4fdbf 100644 --- a/src/jse/org/luaj/vm2/lua2java/JavaScope.java +++ b/src/jse/org/luaj/vm2/lua2java/JavaScope.java @@ -32,6 +32,7 @@ import org.luaj.vm2.ast.FuncBody; import org.luaj.vm2.ast.NameScope; import org.luaj.vm2.ast.Visitor; import org.luaj.vm2.ast.Exp.BinopExp; +import org.luaj.vm2.ast.Exp.VarargsExp; import org.luaj.vm2.ast.Stat.Return; import org.luaj.vm2.lib.LibFunction; @@ -72,6 +73,7 @@ public class JavaScope extends NameScope { public int nreturns; public boolean needsbinoptmp; + public boolean usesvarargs; final Set staticnames; final Set javanames = new HashSet(); @@ -150,12 +152,14 @@ public class JavaScope extends NameScope { 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; } @@ -173,6 +177,10 @@ public class JavaScope extends NameScope { } super.visit(exp); } + public void visit(VarargsExp exp) { + usesvarargs = true; + } + } } diff --git a/test/lua/tailcalls.lua b/test/lua/tailcalls.lua index 017b7dbe..7acee53f 100644 --- a/test/lua/tailcalls.lua +++ b/test/lua/tailcalls.lua @@ -135,7 +135,7 @@ local p = function( s,e ) print( s, e and aliases[tostring(e)] or e ) end p(pcall(fib_bad, 30)) -p((pcall(fib_bad, 25000))) +--p((pcall(fib_bad, 25000))) p(pcall(fib_good, 30)) p(pcall(fib_good, 25000))