Improve upvalue processing in generated code.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user