Fix java code generator including adding tail call support.

This commit is contained in:
James Roseborough
2010-07-26 05:58:34 +00:00
parent 69bbae70a1
commit 6364b002e4
4 changed files with 49 additions and 13 deletions

View File

@@ -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;
}

View File

@@ -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<m; i++ ) {
Name name = body.parlist.names.get(i);
String argname = javascope.getJavaName(name.variable);
@@ -566,6 +581,14 @@ public class JavaCodeGen {
else
outl( "LuaValue "+argname+" = "+value+";" );
}
if ( body.parlist.isvararg ) {
NamedVariable 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)");
outl( arg.isupvalue? "final LuaValue[] arg = {"+value+"};": "LuaValue arg = "+value+";" );
}
}
writeBodyBlock(body.block);
oute("}");

View File

@@ -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<String> staticnames;
final Set<String> javanames = new HashSet<String>();
@@ -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;
}
}
}

View File

@@ -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))