Improve name resolution in java code generator.

This commit is contained in:
James Roseborough
2010-07-21 15:31:15 +00:00
parent 399566a20c
commit ee0271c70d
3 changed files with 55 additions and 16 deletions

View File

@@ -6,6 +6,7 @@ import org.luaj.vm2.ast.Exp.NameExp;
import org.luaj.vm2.ast.Exp.VarExp; import org.luaj.vm2.ast.Exp.VarExp;
import org.luaj.vm2.ast.NameScope.NamedVariable; import org.luaj.vm2.ast.NameScope.NamedVariable;
import org.luaj.vm2.ast.Stat.Assign; import org.luaj.vm2.ast.Stat.Assign;
import org.luaj.vm2.ast.Stat.FuncDef;
import org.luaj.vm2.ast.Stat.GenericFor; import org.luaj.vm2.ast.Stat.GenericFor;
import org.luaj.vm2.ast.Stat.LocalAssign; import org.luaj.vm2.ast.Stat.LocalAssign;
import org.luaj.vm2.ast.Stat.LocalFuncDef; import org.luaj.vm2.ast.Stat.LocalFuncDef;
@@ -41,13 +42,10 @@ public class NameResolver extends Visitor {
pushScope(); pushScope();
scope.functionNestingCount++; scope.functionNestingCount++;
body.scope = scope; body.scope = scope;
if ( body.parlist.names != null )
for ( Name n : body.parlist.names )
defineLocalVar(n);
super.visit(body); super.visit(body);
popScope(); popScope();
} }
public void visit(LocalFuncDef stat) { public void visit(LocalFuncDef stat) {
defineLocalVar(stat.name); defineLocalVar(stat.name);
super.visit(stat); super.visit(stat);
@@ -70,13 +68,22 @@ public class NameResolver extends Visitor {
} }
public void visit(NameExp exp) { public void visit(NameExp exp) {
NamedVariable v = scope.find(exp.name.name); exp.name.variable = resolveNameReference(exp.name);
exp.name.variable = v;
if ( v.isLocal() && scope.functionNestingCount != v.definingScope.functionNestingCount )
v.isupvalue = true;
super.visit(exp); super.visit(exp);
} }
public void visit(FuncDef stat) {
stat.name.name.variable = resolveNameReference(stat.name.name);
super.visit(stat);
}
protected NamedVariable resolveNameReference(Name name) {
NamedVariable v = scope.find(name.name);
if ( v.isLocal() && scope.functionNestingCount != v.definingScope.functionNestingCount )
v.isupvalue = true;
return v;
}
public void visit(Assign stat) { public void visit(Assign stat) {
super.visit(stat); super.visit(stat);
for ( VarExp v : stat.vars ) for ( VarExp v : stat.vars )
@@ -88,6 +95,12 @@ public class NameResolver extends Visitor {
super.visit(stat); super.visit(stat);
} }
public void visit(ParList pars) {
if ( pars.names != null )
defineLocalVars(pars.names);
super.visit(pars);
}
protected void defineLocalVars(List<Name> names) { protected void defineLocalVars(List<Name> names) {
for ( Name n : names ) for ( Name n : names )
defineLocalVar(n); defineLocalVar(n);

View File

@@ -235,7 +235,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("+evalStringConstant(exp.name.name)+","+valu+");"); outl( "env.set("+evalLuaValue(exp)+","+valu+");");
} }
}; };
if ( varOrName instanceof VarExp ) if ( varOrName instanceof VarExp )
@@ -550,9 +550,34 @@ public class JavaCodeGen {
} }
public void visit(FuncDef stat) { public void visit(FuncDef stat) {
outi( "env.set("+evalStringConstant(stat.name.name.name)+","); Writer x = pushWriter();
stat.body.accept(this); stat.body.accept(this);
outr(");"); String value = popWriter(x);
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);
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 {
outi( "env.set("+evalStringConstant(stat.name.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)+")" );
}
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+");" );
}
} }
public void visit(LocalFuncDef stat) { public void visit(LocalFuncDef stat) {

View File

@@ -89,8 +89,9 @@ public class JavaScope extends NameScope {
} }
final String getJavaName(NamedVariable nv) { final String getJavaName(NamedVariable nv) {
if ( astele2javaname.containsKey(nv) ) for ( JavaScope s = this; s != null; s = (JavaScope) s.outerScope )
return astele2javaname.get(nv); if ( s.astele2javaname.containsKey(nv) )
return s.astele2javaname.get(nv);
return allocateJavaName( nv, nv.name ); return allocateJavaName( nv, nv.name );
} }
@@ -129,9 +130,9 @@ public class JavaScope extends NameScope {
String better = string.replaceAll("[^\\w]", "_"); String better = string.replaceAll("[^\\w]", "_");
if ( better.length() > MAX_CONSTNAME_LEN ) if ( better.length() > MAX_CONSTNAME_LEN )
better = better.substring(0,MAX_CONSTNAME_LEN); better = better.substring(0,MAX_CONSTNAME_LEN);
// if ( !Character.isJavaIdentifierStart( better.charAt(0) ) ) if ( better.length() == 0 || !Character.isJavaIdentifierStart( better.charAt(0) ) )
// better = "_"+better; better = "_"+better;
return "$"+better; return better;
} }
private JavaScope initialize(Block block, int nreturns) { private JavaScope initialize(Block block, int nreturns) {