Improve code generator for varargs.

This commit is contained in:
James Roseborough
2010-07-21 05:25:45 +00:00
parent f4eb4a4e4c
commit 399566a20c
4 changed files with 55 additions and 53 deletions

View File

@@ -49,7 +49,7 @@ public class LuaParser {
private static Exp.VarExp assertvarexp(Exp.PrimaryExp pe) throws ParseException { private static Exp.VarExp assertvarexp(Exp.PrimaryExp pe) throws ParseException {
if (!pe.isvarexp()) if (!pe.isvarexp())
throw new ParseException("exptected variable"); throw new ParseException("expected variable");
return (Exp.VarExp) pe; return (Exp.VarExp) pe;
} }

View File

@@ -169,8 +169,8 @@ public class JavaCodeGen {
int n = s.nreturns(); int n = s.nreturns();
switch ( n ) { switch ( n ) {
case 0: outl( "return NONE;" ); break; case 0: outl( "return NONE;" ); break;
case 1: outl( "return "+eval(s.values.get(0))+";" ); break; case 1: outl( "return "+evalLuaValue(s.values.get(0))+";" ); break;
default: outl( "return "+eval(s.values)+";" ); break; default: outl( "return "+evalVarargs(s.values)+";" ); break;
} }
} }
@@ -183,12 +183,7 @@ public class JavaCodeGen {
int m = stat.values!=null? stat.values.size(): 0; int m = stat.values!=null? stat.values.size(): 0;
if ( n == 1 && m<=1 ) { if ( n == 1 && m<=1 ) {
Name name = stat.names.get(0); Name name = stat.names.get(0);
String javaname = javascope.getJavaName(name.variable); String value = m>0? evalLuaValue(stat.values.get(0)): "NIL";
String value = "NIL";
if ( m > 0 ) {
Exp val= stat.values.get(0);
value = eval(val) + (val.isvarargexp()? ".arg1()": "");
}
singleLocalDeclareAssign(name,value); singleLocalDeclareAssign(name,value);
} else { } else {
for ( Name name : stat.names ) for ( Name name : stat.names )
@@ -202,26 +197,26 @@ public class JavaCodeGen {
private void multiAssign(List varsOrNames, List<Exp> exps) { private void multiAssign(List varsOrNames, List<Exp> exps) {
int n = varsOrNames.size(); int n = varsOrNames.size();
int m = exps != null? exps.size(): 0; int m = exps != null? exps.size(): 0;
boolean varlist = m>0 && exps.get(m-1).isvarargexp() && n>m; boolean vararglist = m>0 && exps.get(m-1).isvarargexp() && n>m;
if ( n<=m ) { if ( n<=m ) {
for ( int i=1; i<=n; i++ ) for ( int i=1; i<=n; i++ )
singleAssign( varsOrNames.get(i-1), eval(exps.get(i-1)) ); singleAssign( varsOrNames.get(i-1), evalLuaValue(exps.get(i-1)) );
for ( int i=n+1; i<=m; i++ ) for ( int i=n+1; i<=m; i++ )
outl( eval(exps.get(i-1))+";" ); outl( evalLuaValue(exps.get(i-1))+";" );
} else { } else {
outb( "{" ); outb( "{" );
for ( int i=1; i<=m; i++ ) { for ( int i=1; i<=m; i++ ) {
boolean vtype = varlist && (i==m);
Exp e = exps.get(i-1); Exp e = exps.get(i-1);
String decl = (vtype? "Varargs": "LuaValue")+" $"+i; if ( vararglist && (i==m) )
String valu = eval(e)+(e.isvarexp() && !vtype? ".arg1()": ""); outl( "Varargs $"+i+" = "+evalVarargs(e)+";" );
outl( decl+"="+valu+";" ); else
outl( "LuaValue $"+i+" = "+evalLuaValue(e)+";" );
} }
for ( int i=1; i<=n; i++ ) { for ( int i=1; i<=n; i++ ) {
String valu; String valu;
if ( i < m ) valu = "$"+i; if ( i < m ) valu = "$"+i;
else if ( i==m ) valu = (varlist? "$"+i+".arg1()": "$"+i); else if ( i==m ) valu = (vararglist? "$"+i+".arg1()": "$"+i);
else if ( varlist ) valu = "$"+m+".arg("+(i-m+1)+")"; else if ( vararglist ) valu = "$"+m+".arg("+(i-m+1)+")";
else valu = "NIL"; else valu = "NIL";
singleAssign( varsOrNames.get(i-1), valu ); singleAssign( varsOrNames.get(i-1), valu );
} }
@@ -231,10 +226,10 @@ public class JavaCodeGen {
private void singleAssign(final Object varOrName, final String valu) { private void singleAssign(final Object varOrName, final String valu) {
Visitor v = new Visitor() { Visitor v = new Visitor() {
public void visit(FieldExp exp) { public void visit(FieldExp exp) {
outl(eval(exp.lhs)+".set("+evalStringConstant(exp.name.name)+","+valu+");"); outl(evalLuaValue(exp.lhs)+".set("+evalStringConstant(exp.name.name)+","+valu+");");
} }
public void visit(IndexExp exp) { public void visit(IndexExp exp) {
outl(eval(exp.lhs)+".set("+eval(exp.exp)+","+valu+");"); outl(evalLuaValue(exp.lhs)+".set("+evalLuaValue(exp.exp)+","+valu+");");
} }
public void visit(NameExp exp) { public void visit(NameExp exp) {
if ( exp.name.variable.isLocal() ) if ( exp.name.variable.isLocal() )
@@ -280,24 +275,30 @@ public class JavaCodeGen {
return c.toString(); return c.toString();
} }
public String eval(List<Exp> values) { public String evalVarargs(List<Exp> values) {
int n = values.size(); int n = values.size();
switch ( n ) { switch ( n ) {
case 0: return "NONE"; case 0: return "NONE";
case 1: return eval(values.get(0)); case 1: return evalVarargs(values.get(0));
default: default:
case 2: case 3:
Writer x = pushWriter(); Writer x = pushWriter();
out( n<=3? "varargsOf(": "varargsOf(new LuaValue[] {" ); out( n>3? "varargsOf(new LuaValue[] {":"varargsOf(" );
for ( int i=0; i<n; i++ ) { for ( int i=1; i<n; i++ )
if ( i>0 ) out( "," ); out( evalLuaValue(values.get(i-1))+"," );
out(eval(values.get(i))); if ( n>3 )
} out( "}," );
out( n<=3? ")": "})" ); out( evalVarargs(values.get(n-1))+")" );
return popWriter(x); return popWriter(x);
} }
} }
public String eval(Exp exp) { public String evalLuaValue(Exp exp) {
String s = evalVarargs(exp);
return exp.isvarargexp()? s+".arg1()": s;
}
public String evalVarargs(Exp exp) {
Writer x = pushWriter(); Writer x = pushWriter();
exp.accept(this); exp.accept(this);
return popWriter(x); return popWriter(x);
@@ -437,15 +438,15 @@ public class JavaCodeGen {
out(")"); out(")");
break; break;
default: default:
out(".invokemethod("+evalStringConstant(exp.name)+",varargsOf(new LuaValue[]{"); out(".invokemethod("+evalStringConstant(exp.name)+","+evalVarargs(exp.args.exps)+")");
exp.args.accept(this);
out("})).arg1()");
break; break;
} }
} }
public void visit(FuncCall exp) { public void visit(FuncCall exp) {
int n = exp.args.exps != null? exp.args.exps.size(): 0; int n = exp.args.exps != null? exp.args.exps.size(): 0;
if ( n > 0 && exp.args.exps.get(n-1).isvarargexp() )
n = -1;
exp.lhs.accept(this); exp.lhs.accept(this);
switch ( n ) { switch ( n ) {
case 0: case 1: case 2: case 3: case 0: case 1: case 2: case 3:
@@ -454,7 +455,7 @@ public class JavaCodeGen {
out(")"); out(")");
break; break;
default: default:
out(".invoke("+eval(exp.args.exps)+").arg1()"); out(".invoke("+evalVarargs(exp.args.exps)+")");
break; break;
} }
} }
@@ -462,11 +463,10 @@ public class JavaCodeGen {
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();
for ( int i=0; i<n; i++ ) { if ( n > 0 ) {
if ( i > 0 ) out(","); for ( int i=1; i<n; i++ )
Exp e = args.exps.get(i); out( evalLuaValue( args.exps.get(i-1) )+"," );
out( eval( e ) ); out( evalVarargs( args.exps.get(n-1) ) );
// TODO: arg1(), varargs
} }
} }
} }
@@ -524,7 +524,7 @@ public class JavaCodeGen {
outl( "LuaValue "+argname+" = "+value+";" ); outl( "LuaValue "+argname+" = "+value+";" );
} }
if ( body.parlist.isvararg && m > 0 ) if ( body.parlist.isvararg && m > 0 )
outl( "arg = arg.arglist("+(m+1)+");" ); outl( "arg = arg.subargs("+(m+1)+");" );
} }
writeBodyBlock(body.block); writeBodyBlock(body.block);
oute("}"); oute("}");
@@ -546,11 +546,13 @@ public class JavaCodeGen {
} }
public void visit(FuncCallStat stat) { public void visit(FuncCallStat stat) {
outl(eval(stat.funccall)+";"); outl(evalVarargs(stat.funccall)+";");
} }
public void visit(FuncDef stat) { public void visit(FuncDef stat) {
super.visit(stat); outi( "env.set("+evalStringConstant(stat.name.name.name)+",");
stat.body.accept(this);
outr(");");
} }
public void visit(LocalFuncDef stat) { public void visit(LocalFuncDef stat) {
@@ -566,11 +568,11 @@ public class JavaCodeGen {
public void visit(NumericFor stat) { public void visit(NumericFor stat) {
String javaname = javascope.getJavaName(stat.name.variable); String javaname = javascope.getJavaName(stat.name.variable);
outi("for ( LuaValue " outi("for ( LuaValue "
+javaname+"="+eval(stat.initial)+", " +javaname+"="+evalLuaValue(stat.initial)+", "
+javaname+"$limit="+eval(stat.limit)); +javaname+"$limit="+evalLuaValue(stat.limit));
String stepname = "ONE"; String stepname = "ONE";
if ( stat.step!=null ) if ( stat.step!=null )
out(", "+(stepname=javaname+"$step")+"="+eval(stat.step)); out(", "+(stepname=javaname+"$step")+"="+evalLuaValue(stat.step));
outr( "; " outr( "; "
+javaname+".testfor_b("+javaname+"$limit,"+stepname+"); " +javaname+".testfor_b("+javaname+"$limit,"+stepname+"); "
+javaname+"="+javaname+".add("+stepname+") ) {" ); +javaname+"="+javaname+".add("+stepname+") ) {" );
@@ -617,12 +619,12 @@ public class JavaCodeGen {
} }
public void visit(IfThenElse stat) { public void visit(IfThenElse stat) {
outb( "if ( "+eval(stat.ifexp)+".toboolean() ) {"); outb( "if ( "+evalLuaValue(stat.ifexp)+".toboolean() ) {");
super.visit(stat.ifblock); super.visit(stat.ifblock);
if ( stat.elseifblocks != null ) if ( stat.elseifblocks != null )
for ( int i=0, n=stat.elseifblocks.size(); i<n; i++ ) { for ( int i=0, n=stat.elseifblocks.size(); i<n; i++ ) {
subindent(); subindent();
outl( "} else if ( "+eval(stat.elseifexps.get(i))+".toboolean() ) {"); outl( "} else if ( "+evalLuaValue(stat.elseifexps.get(i))+".toboolean() ) {");
addindent(); addindent();
super.visit(stat.elseifblocks.get(i)); super.visit(stat.elseifblocks.get(i));
} }
@@ -638,7 +640,7 @@ public class JavaCodeGen {
public void visit(RepeatUntil stat) { public void visit(RepeatUntil stat) {
outb( "do {"); outb( "do {");
super.visit(stat.block); super.visit(stat.block);
oute( "} while (!"+eval(stat.exp)+".toboolean());" ); oute( "} while (!"+evalLuaValue(stat.exp)+".toboolean());" );
} }
public void visit(TableConstructor table) { public void visit(TableConstructor table) {
@@ -654,21 +656,21 @@ public class JavaCodeGen {
if ( f.name != null ) if ( f.name != null )
out( evalStringConstant(f.name)+"," ); out( evalStringConstant(f.name)+"," );
else else
out( eval(f.index)+"," ); out( evalLuaValue(f.index)+"," );
out( eval(f.rhs)+"," ); out( evalLuaValue(f.rhs)+"," );
} }
out("},new LuaValue[] {"); out("},new LuaValue[] {");
for ( int i=0; i<n; i++ ) { for ( int i=0; i<n; i++ ) {
TableField f = table.fields.get(i); TableField f = table.fields.get(i);
if ( f.name == null && f.index == null ) if ( f.name == null && f.index == null )
out( eval(f.rhs)+"," ); out( evalLuaValue(f.rhs)+"," );
} }
out("})"); out("})");
} }
} }
public void visit(WhileDo stat) { public void visit(WhileDo stat) {
outb( "while ("+eval(stat.exp)+") {"); outb( "while ("+evalLuaValue(stat.exp)+".toboolean()) {");
super.visit(stat.block); super.visit(stat.block);
oute( "}" ); oute( "}" );
} }

View File

@@ -42,7 +42,7 @@ public class JavaScope extends NameScope {
private static final String[] specials = { private static final String[] specials = {
// keywords used by our code generator // keywords used by our code generator
"name", "opcode", "env", "name", "opcode", "env", "arg",
// java keywords // java keywords
"abstract", "continue", "for", "new", "switch", "abstract", "continue", "for", "new", "switch",

View File

@@ -13,7 +13,7 @@ public class LuaParser implements LuaParserConstants {
private static Exp.VarExp assertvarexp(Exp.PrimaryExp pe) throws ParseException { private static Exp.VarExp assertvarexp(Exp.PrimaryExp pe) throws ParseException {
if (!pe.isvarexp()) if (!pe.isvarexp())
throw new ParseException("exptected variable"); throw new ParseException("expected variable");
return (Exp.VarExp) pe; return (Exp.VarExp) pe;
} }