Improve upvalue processing in generated code.

This commit is contained in:
James Roseborough
2010-07-26 15:24:52 +00:00
parent 6364b002e4
commit aa095fef27
4 changed files with 79 additions and 56 deletions

View File

@@ -68,6 +68,9 @@
<include name="org/luaj/vm2/lib/jme/*.class" /> <include name="org/luaj/vm2/lib/jme/*.class" />
<include name="org/luaj/vm2/compiler/*.class" /> <include name="org/luaj/vm2/compiler/*.class" />
<include name="org/luaj/vm2/luajc/*.class" /> <include name="org/luaj/vm2/luajc/*.class" />
<include name="org/luaj/vm2/lua2java/*.class" />
<include name="org/luaj/vm2/parser/*.class" />
<include name="org/luaj/vm2/ast/*.class" />
<exclude name="**/*Test*.class" /> <exclude name="**/*Test*.class" />
</fileset> </fileset>
</cobertura-instrument> </cobertura-instrument>
@@ -101,8 +104,12 @@
</target> </target>
<target name="report"> <target name="report">
<cobertura-report datafile="${cobertura.serfile}" srcdir="src/core" destdir="${coverage.xml.dir}" format="xml" /> <cobertura-report datafile="${cobertura.serfile}" destdir="${coverage.xml.dir}" format="xml" />
<cobertura-report datafile="${cobertura.serfile}" srcdir="src/core" destdir="${coverage.html.dir}" /> <cobertura-report datafile="${cobertura.serfile}" destdir="${coverage.html.dir}">
<fileset dir="src/core"/>
<fileset dir="src/jse"/>
<fileset dir="src/jme"/>
</cobertura-report>
</target> </target>
<target name="coverage" depends="clean,init,compile,instrument,test,report"/> <target name="coverage" depends="clean,init,compile,instrument,test,report"/>

View File

@@ -41,7 +41,7 @@ public class lua2java {
private static final String version = Lua._VERSION + "Copyright (C) 2010 luaj.org"; private static final String version = Lua._VERSION + "Copyright (C) 2010 luaj.org";
private static final String usage = private static final String usage =
"usage: java -cp luaj-jse.jar lua2java [options] [filenames].\n" + "usage: java -cp luaj-jse.jar lua2java [options] fileordir [, fileordir ...]\n" +
"Available options are:\n" + "Available options are:\n" +
" - process stdin\n" + " - process stdin\n" +
" -s src source directory\n" + " -s src source directory\n" +
@@ -129,7 +129,7 @@ public class lua2java {
// check for at least one file // check for at least one file
if ( files.size() <= 0 ) { if ( files.size() <= 0 ) {
System.err.println("no files found in "+seeds); System.err.println(usage);
System.exit(-1); System.exit(-1);
} }

View File

@@ -75,6 +75,7 @@ public class NameResolver extends Visitor {
public void visit(FuncDef stat) { public void visit(FuncDef stat) {
stat.name.name.variable = resolveNameReference(stat.name.name); stat.name.name.variable = resolveNameReference(stat.name.name);
stat.name.name.variable.hasassignments = true;
super.visit(stat); super.visit(stat);
} }

View File

@@ -214,16 +214,18 @@ public class JavaCodeGen {
multiAssign(stat.names, stat.values); multiAssign(stat.names, stat.values);
} }
} }
public void visit(Assign stat) { public void visit(Assign stat) {
multiAssign(stat.vars, stat.exps); multiAssign(stat.vars, stat.exps);
} }
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 vararglist = 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), evalLuaValue(exps.get(i-1)) ); singleVarOrNameAssign( 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( evalLuaValue(exps.get(i-1))+";" ); outl( evalLuaValue(exps.get(i-1))+";" );
} else { } else {
@@ -241,12 +243,13 @@ public class JavaCodeGen {
else if ( i==m ) valu = (vararglist? "$"+i+".arg1()": "$"+i); else if ( i==m ) valu = (vararglist? "$"+i+".arg1()": "$"+i);
else if ( vararglist ) 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 ); singleVarOrNameAssign( varsOrNames.get(i-1), valu );
} }
oute( "}" ); oute( "}" );
} }
} }
private void singleAssign(final Object varOrName, final String valu) {
private void singleVarOrNameAssign(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(evalLuaValue(exp.lhs)+".set("+evalStringConstant(exp.name.name)+","+valu+");"); outl(evalLuaValue(exp.lhs)+".set("+evalStringConstant(exp.name.name)+","+valu+");");
@@ -255,32 +258,50 @@ public class JavaCodeGen {
outl(evalLuaValue(exp.lhs)+".set("+evalLuaValue(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() ) singleAssign( exp.name, valu );
singleLocalAssign(exp.name, valu);
else
outl( "env.set("+evalStringConstant(exp.name.name)+","+valu+");");
} }
}; };
if ( varOrName instanceof VarExp ) if ( varOrName instanceof VarExp )
((VarExp)varOrName).accept(v); ((VarExp)varOrName).accept(v);
else if ( varOrName instanceof Name ) else if ( varOrName instanceof Name )
singleLocalAssign((Name) varOrName, valu); singleAssign((Name) varOrName, valu);
else else
throw new IllegalStateException("can't assign to "+varOrName.getClass()); throw new IllegalStateException("can't assign to "+varOrName.getClass());
} }
private void singleLocalAssign(Name name, String valu) {
outi( javascope.getJavaName(name.variable) ); private void singleAssign(Name name, String valu) {
if ( name.variable.isupvalue ) if ( name.variable.isLocal() ) {
out( "[0]" ); outi( "" );
outr( " = "+valu+";"); singleReference( name );
outr( " = "+valu+";" );
} else
outl( "env.set("+evalStringConstant(name.name)+","+valu+");");
} }
private void singleReference(Name name) {
if ( name.variable.isLocal() ) {
out( javascope.getJavaName(name.variable) );
if ( name.variable.isupvalue && name.variable.hasassignments )
out( "[0]" );
} else {
out( "env.get("+evalStringConstant(name.name)+")");
}
}
private void singleLocalDeclareAssign(Name name, String value) { private void singleLocalDeclareAssign(Name name, String value) {
String javaname = javascope.getJavaName(name.variable); singleLocalDeclareAssign( name.variable, value );
if ( name.variable.isupvalue ) }
private void singleLocalDeclareAssign(NamedVariable variable, String value) {
String javaname = javascope.getJavaName(variable);
if ( variable.isupvalue && variable.hasassignments )
outl( "final LuaValue[] "+javaname+" = {"+value+"};" ); outl( "final LuaValue[] "+javaname+" = {"+value+"};" );
else if ( variable.isupvalue )
outl( "final LuaValue "+javaname+(value!=null? " = "+value: "")+";" );
else else
outl( "LuaValue "+javaname+(value!=null? " = "+value: "")+";" ); outl( "LuaValue "+javaname+(value!=null? " = "+value: "")+";" );
} }
public void visit(Break breakstat) { public void visit(Break breakstat) {
// TODO: wrap in do {} while(false), or add label as nec // TODO: wrap in do {} while(false), or add label as nec
outl( "break;" ); outl( "break;" );
@@ -440,13 +461,7 @@ public class JavaCodeGen {
} }
public void visit(NameExp exp) { public void visit(NameExp exp) {
if ( exp.name.variable.isLocal() ) { singleReference( exp.name );
out( javascope.getJavaName(exp.name.variable) );
if ( exp.name.variable.isupvalue )
out( "[0]" );
} else {
out( "env.get("+evalStringConstant(exp.name.name)+")");
}
} }
public void visit(ParensExp exp) { public void visit(ParensExp exp) {
@@ -574,12 +589,8 @@ public class JavaCodeGen {
outb("public Varargs invoke(Varargs $arg) {"); outb("public Varargs invoke(Varargs $arg) {");
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 value = i>0? "$arg.arg("+(i+1)+")": "$arg.arg1()"; String value = i>0? "$arg.arg("+(i+1)+")": "$arg.arg1()";
if ( name.variable.isupvalue ) singleLocalDeclareAssign( name, value );
outl( "final LuaValue[] "+argname+" = {"+value+"};" );
else
outl( "LuaValue "+argname+" = "+value+";" );
} }
if ( body.parlist.isvararg ) { if ( body.parlist.isvararg ) {
NamedVariable arg = body.scope.find("arg"); NamedVariable arg = body.scope.find("arg");
@@ -587,7 +598,7 @@ public class JavaCodeGen {
if ( m > 0 ) if ( m > 0 )
outl( "$arg = $arg.subargs("+(m+1)+");" ); outl( "$arg = $arg.subargs("+(m+1)+");" );
String value = (javascope.usesvarargs? "NIL": "LuaValue.tableOf($arg,1)"); String value = (javascope.usesvarargs? "NIL": "LuaValue.tableOf($arg,1)");
outl( arg.isupvalue? "final LuaValue[] arg = {"+value+"};": "LuaValue arg = "+value+";" ); singleLocalDeclareAssign( arg, value );
} }
} }
writeBodyBlock(body.block); writeBodyBlock(body.block);
@@ -605,7 +616,7 @@ public class JavaCodeGen {
private void assignArg(Name name) { private void assignArg(Name name) {
if ( name.variable.isupvalue ) { if ( name.variable.isupvalue ) {
String argname = javascope.getJavaName(name.variable); String argname = javascope.getJavaName(name.variable);
outl( "final LuaValue[] "+argname+" = {"+argname+"$0};" ); singleLocalDeclareAssign(name, argname+"$0");
} }
} }
@@ -616,39 +627,43 @@ public class JavaCodeGen {
int n = stat.name.dots!=null? stat.name.dots.size(): 0; int n = stat.name.dots!=null? stat.name.dots.size(): 0;
boolean m = stat.name.method != null; boolean m = stat.name.method != null;
if ( n>0 && !m && stat.name.name.variable.isLocal() ) if ( n>0 && !m && stat.name.name.variable.isLocal() )
singleLocalAssign(stat.name.name,value); singleAssign( stat.name.name, value );
else if ( n==0 && !m ) { else if ( n==0 && !m ) {
if ( stat.name.name.variable.isLocal() ) { singleAssign( stat.name.name, value );
outi( javascope.getJavaName(stat.name.name.variable) );
if ( stat.name.name.variable.isupvalue )
out( "[0]" );
outr( " = "+value+";" );
} else {
outl( "env.set("+evalStringConstant(stat.name.name.name)+","+value+");" );
}
} else { } else {
if ( stat.name.name.variable.isLocal() ) { singleReference( stat.name.name );
outi( javascope.getJavaName(stat.name.name.variable) );
if ( stat.name.name.variable.isupvalue )
out( "[0]" );
} else {
outi( "env.get("+evalStringConstant(stat.name.name.name)+")" );
}
for ( int i=0; i<n-1 || (m&&i<n); i++ ) for ( int i=0; i<n-1 || (m&&i<n); i++ )
out( ".get("+evalStringConstant(stat.name.dots.get(i))+")" ); out( ".get("+evalStringConstant(stat.name.dots.get(i))+")" );
outr( ".set("+evalStringConstant(m? stat.name.method: stat.name.dots.get(n))+", "+value+");" ); outr( ".set("+evalStringConstant(m? stat.name.method: stat.name.dots.get(n))+", "+value+");" );
} }
} }
// functions that use themselves as upvalues require special treatment
public void visit(LocalFuncDef stat) { public void visit(LocalFuncDef stat) {
String javaname = javascope.getJavaName(stat.name.variable); final Name funcname = stat.name;
if ( stat.name.variable.isupvalue ) { final boolean[] isrecursive = { false };
outl("final LuaValue[] "+javaname+" = {null};"); stat.body.accept( new Visitor() {
outi(javaname+"[0] = "); public void visit(Name name) {
} else if ( name.variable == funcname.variable ) {
outi("LuaValue "+javaname+" = "); isrecursive[0] = true;
name.variable.hasassignments = true;
}
}
} );
// write body
Writer x = pushWriter();
super.visit(stat); super.visit(stat);
outr( ";" ); String value = popWriter(x);
// write declaration
if ( isrecursive[0] ) {
String javaname = javascope.getJavaName(funcname.variable);
outl("final LuaValue[] "+javaname+" = new LuaValue[1];");
outl(javaname+"[0] = "+value+";");
} else {
singleLocalDeclareAssign( funcname, value );
}
} }
public void visit(NumericFor stat) { public void visit(NumericFor stat) {