Fix java code generator including adding tail call support.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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("}");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user