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/compiler/*.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" />
</fileset>
</cobertura-instrument>
@@ -101,8 +104,12 @@
</target>
<target name="report">
<cobertura-report datafile="${cobertura.serfile}" srcdir="src/core" 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.xml.dir}" format="xml" />
<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 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 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" +
" - process stdin\n" +
" -s src source directory\n" +
@@ -129,7 +129,7 @@ public class lua2java {
// check for at least one file
if ( files.size() <= 0 ) {
System.err.println("no files found in "+seeds);
System.err.println(usage);
System.exit(-1);
}

View File

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

View File

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