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;
|
this.args = args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TailcallVarargs(LuaValue object, LuaValue methodname, Varargs args) {
|
||||||
|
this.func = object.get(methodname);
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isTailcall() {
|
public boolean isTailcall() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ public class JavaCodeGen {
|
|||||||
outl("import org.luaj.vm2.*;");
|
outl("import org.luaj.vm2.*;");
|
||||||
outl("import org.luaj.vm2.lib.*;");
|
outl("import org.luaj.vm2.lib.*;");
|
||||||
outb("public class "+classname+" extends VarArgFunction {");
|
outb("public class "+classname+" extends VarArgFunction {");
|
||||||
outl("public Varargs invoke(Varargs $arg) {");
|
outl("public Varargs onInvoke(Varargs $arg) {");
|
||||||
addindent();
|
addindent();
|
||||||
javascope = JavaScope.newJavaScope( chunk );
|
javascope = JavaScope.newJavaScope( chunk );
|
||||||
writeBodyBlock(chunk.block);
|
writeBodyBlock(chunk.block);
|
||||||
@@ -182,9 +182,18 @@ public class JavaCodeGen {
|
|||||||
public void visit(Stat.Return s) {
|
public void visit(Stat.Return s) {
|
||||||
int n = s.nreturns();
|
int n = s.nreturns();
|
||||||
switch ( n ) {
|
switch ( n ) {
|
||||||
case 0: outl( "return NONE;" ); break;
|
case 0:
|
||||||
case 1: outl( "return "+evalLuaValue(s.values.get(0))+";" ); break;
|
outl( "return NONE;" );
|
||||||
default: outl( "return "+evalListAsVarargs(s.values)+";" ); break;
|
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() )
|
if ( exp.name.variable.isLocal() )
|
||||||
singleLocalAssign(exp.name, valu);
|
singleLocalAssign(exp.name, valu);
|
||||||
else
|
else
|
||||||
outl( "env.set("+evalLuaValue(exp)+","+valu+");");
|
outl( "env.set("+evalStringConstant(exp.name.name)+","+valu+");");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if ( varOrName instanceof VarExp )
|
if ( varOrName instanceof VarExp )
|
||||||
@@ -446,7 +455,7 @@ public class JavaCodeGen {
|
|||||||
|
|
||||||
public void visit(VarargsExp exp) {
|
public void visit(VarargsExp exp) {
|
||||||
int c = callerExpects.containsKey(exp)? callerExpects.get(exp): 0;
|
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) {
|
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) {
|
public void visit(FuncArgs args) {
|
||||||
if ( args.exps != null ) {
|
if ( args.exps != null ) {
|
||||||
int n = args.exps.size();
|
int n = args.exps.size();
|
||||||
@@ -551,12 +572,6 @@ public class JavaCodeGen {
|
|||||||
outr("new VarArgFunction(env) {");
|
outr("new VarArgFunction(env) {");
|
||||||
addindent();
|
addindent();
|
||||||
outb("public Varargs invoke(Varargs $arg) {");
|
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++ ) {
|
for ( int i=0; i<m; i++ ) {
|
||||||
Name name = body.parlist.names.get(i);
|
Name name = body.parlist.names.get(i);
|
||||||
String argname = javascope.getJavaName(name.variable);
|
String argname = javascope.getJavaName(name.variable);
|
||||||
@@ -566,6 +581,14 @@ public class JavaCodeGen {
|
|||||||
else
|
else
|
||||||
outl( "LuaValue "+argname+" = "+value+";" );
|
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);
|
writeBodyBlock(body.block);
|
||||||
oute("}");
|
oute("}");
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import org.luaj.vm2.ast.FuncBody;
|
|||||||
import org.luaj.vm2.ast.NameScope;
|
import org.luaj.vm2.ast.NameScope;
|
||||||
import org.luaj.vm2.ast.Visitor;
|
import org.luaj.vm2.ast.Visitor;
|
||||||
import org.luaj.vm2.ast.Exp.BinopExp;
|
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.ast.Stat.Return;
|
||||||
import org.luaj.vm2.lib.LibFunction;
|
import org.luaj.vm2.lib.LibFunction;
|
||||||
|
|
||||||
@@ -72,6 +73,7 @@ public class JavaScope extends NameScope {
|
|||||||
|
|
||||||
public int nreturns;
|
public int nreturns;
|
||||||
public boolean needsbinoptmp;
|
public boolean needsbinoptmp;
|
||||||
|
public boolean usesvarargs;
|
||||||
|
|
||||||
final Set<String> staticnames;
|
final Set<String> staticnames;
|
||||||
final Set<String> javanames = new HashSet<String>();
|
final Set<String> javanames = new HashSet<String>();
|
||||||
@@ -150,12 +152,14 @@ public class JavaScope extends NameScope {
|
|||||||
block.accept( v );
|
block.accept( v );
|
||||||
this.nreturns = v.nreturns;
|
this.nreturns = v.nreturns;
|
||||||
this.needsbinoptmp = v.needsbinoptmp;
|
this.needsbinoptmp = v.needsbinoptmp;
|
||||||
|
this.usesvarargs = v.usesvarargs;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
class NewScopeVisitor extends Visitor {
|
class NewScopeVisitor extends Visitor {
|
||||||
int nreturns = 0;
|
int nreturns = 0;
|
||||||
boolean needsbinoptmp = false;
|
boolean needsbinoptmp = false;
|
||||||
|
boolean usesvarargs = false;
|
||||||
NewScopeVisitor(int nreturns) {
|
NewScopeVisitor(int nreturns) {
|
||||||
this.nreturns = nreturns;
|
this.nreturns = nreturns;
|
||||||
}
|
}
|
||||||
@@ -173,6 +177,10 @@ public class JavaScope extends NameScope {
|
|||||||
}
|
}
|
||||||
super.visit(exp);
|
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 )
|
print( s, e and aliases[tostring(e)] or e )
|
||||||
end
|
end
|
||||||
p(pcall(fib_bad, 30))
|
p(pcall(fib_bad, 30))
|
||||||
p((pcall(fib_bad, 25000)))
|
--p((pcall(fib_bad, 25000)))
|
||||||
p(pcall(fib_good, 30))
|
p(pcall(fib_good, 30))
|
||||||
p(pcall(fib_good, 25000))
|
p(pcall(fib_good, 25000))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user