Identify constant variables during code generation.

This commit is contained in:
James Roseborough
2010-07-28 06:32:12 +00:00
parent bbbae65237
commit 55947437dd
3 changed files with 52 additions and 16 deletions

View File

@@ -2,9 +2,10 @@ package org.luaj.vm2.ast;
import java.util.List; import java.util.List;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.ast.Exp.Constant;
import org.luaj.vm2.ast.Exp.NameExp; 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.Exp.VarargsExp;
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.FuncDef;
@@ -88,6 +89,17 @@ public class NameResolver extends Visitor {
public void visit(LocalAssign stat) { public void visit(LocalAssign stat) {
visitExps(stat.values); visitExps(stat.values);
defineLocalVars( stat.names ); defineLocalVars( stat.names );
if ( stat.values != null ) {
int n = stat.names.size();
int m = stat.values.size();
boolean varlist = m>0 && stat.values.get(m-1).isvarargexp();
for ( int i=0; i<n && i<(varlist?m-1:m); i++ )
if ( stat.values.get(i) instanceof Constant )
stat.names.get(i).variable.initialValue = ((Constant) stat.values.get(i)).value;
if ( !varlist )
for ( int i=m+1; i<n; i++ )
stat.names.get(i).variable.initialValue = LuaValue.NIL;
}
} }
public void visit(ParList pars) { public void visit(ParList pars) {

View File

@@ -5,6 +5,8 @@ import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.luaj.vm2.LuaValue;
public class NameScope { public class NameScope {
private static final Set<String> LUA_KEYWORDS = new HashSet<String>(); private static final Set<String> LUA_KEYWORDS = new HashSet<String>();
@@ -67,6 +69,7 @@ public class NameScope {
public final NameScope definingScope; public final NameScope definingScope;
public boolean isupvalue; public boolean isupvalue;
public boolean hasassignments; public boolean hasassignments;
public LuaValue initialValue;
/** Global is named variable not associated with a defining scope */ /** Global is named variable not associated with a defining scope */
public NamedVariable(String name) { public NamedVariable(String name) {
this.name = name; this.name = name;
@@ -80,5 +83,8 @@ public class NameScope {
public boolean isLocal() { public boolean isLocal() {
return this.definingScope != null; return this.definingScope != null;
} }
public boolean isConstant() {
return ! hasassignments && initialValue != null;
}
} }
} }

View File

@@ -206,6 +206,8 @@ 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);
if ( name.variable.isConstant() )
return;
String value = m>0? evalLuaValue(stat.values.get(0)): "NIL"; String value = m>0? evalLuaValue(stat.values.get(0)): "NIL";
singleLocalDeclareAssign(name,value); singleLocalDeclareAssign(name,value);
} else { } else {
@@ -271,6 +273,8 @@ public class JavaCodeGen {
private void singleAssign(Name name, String valu) { private void singleAssign(Name name, String valu) {
if ( name.variable.isLocal() ) { if ( name.variable.isLocal() ) {
if ( name.variable.isConstant() )
return;
outi( "" ); outi( "" );
singleReference( name ); singleReference( name );
outr( " = "+valu+";" ); outr( " = "+valu+";" );
@@ -280,6 +284,10 @@ public class JavaCodeGen {
private void singleReference(Name name) { private void singleReference(Name name) {
if ( name.variable.isLocal() ) { if ( name.variable.isLocal() ) {
if ( name.variable.isConstant() ) {
out( evalConstant(name.variable.initialValue) );
return;
}
out( javascope.getJavaName(name.variable) ); out( javascope.getJavaName(name.variable) );
if ( name.variable.isupvalue && name.variable.hasassignments ) if ( name.variable.isupvalue && name.variable.hasassignments )
out( "[0]" ); out( "[0]" );
@@ -294,7 +302,9 @@ public class JavaCodeGen {
private void singleLocalDeclareAssign(NamedVariable variable, String value) { private void singleLocalDeclareAssign(NamedVariable variable, String value) {
String javaname = javascope.getJavaName(variable); String javaname = javascope.getJavaName(variable);
if ( variable.isupvalue && variable.hasassignments ) if ( variable.isConstant() )
return;
else if ( variable.isupvalue && variable.hasassignments )
outl( "final LuaValue[] "+javaname+" = {"+value+"};" ); outl( "final LuaValue[] "+javaname+" = {"+value+"};" );
else if ( variable.isupvalue ) else if ( variable.isupvalue )
outl( "final LuaValue "+javaname+(value!=null? " = "+value: "")+";" ); outl( "final LuaValue "+javaname+(value!=null? " = "+value: "")+";" );
@@ -408,6 +418,10 @@ public class JavaCodeGen {
out(evalLuaValue(exp)+".toboolean()"); out(evalLuaValue(exp)+".toboolean()");
} }
public void visit(NameExp exp) { public void visit(NameExp exp) {
if ( exp.name.variable.isConstant() ) {
out ( exp.name.variable.initialValue.toboolean()? "TRUE": "FALSE");
return;
}
out(evalLuaValue(exp)+".toboolean()"); out(evalLuaValue(exp)+".toboolean()");
} }
public void visit(FuncCall exp) { public void visit(FuncCall exp) {
@@ -471,6 +485,12 @@ public class JavaCodeGen {
out(evalLuaValue(exp)+".todouble()"); out(evalLuaValue(exp)+".todouble()");
} }
public void visit(NameExp exp) { public void visit(NameExp exp) {
if ( exp.name.variable.isConstant() ) {
if ( exp.name.variable.initialValue.isnumber() ) {
out( evalNumberLiteral(exp.name.variable.initialValue.todouble()) );
return;
}
}
out(evalLuaValue(exp)+".todouble()"); out(evalLuaValue(exp)+".todouble()");
} }
public void visit(FuncCall exp) { public void visit(FuncCall exp) {
@@ -528,23 +548,21 @@ public class JavaCodeGen {
} }
public void visit(Constant exp) { public void visit(Constant exp) {
switch ( exp.value.type() ) { out( evalConstant(exp.value) );
case LuaValue.TSTRING: { }
out( evalLuaStringConstant(exp.value.checkstring()) );
break; protected String evalConstant(LuaValue value) {
} switch ( value.type() ) {
case LuaValue.TSTRING:
return evalLuaStringConstant(value.checkstring());
case LuaValue.TNIL: case LuaValue.TNIL:
out("NIL"); return "NIL";
break;
case LuaValue.TBOOLEAN: case LuaValue.TBOOLEAN:
out(exp.value.toboolean()? "TRUE": "FALSE"); return value.toboolean()? "TRUE": "FALSE";
break; case LuaValue.TNUMBER:
case LuaValue.TNUMBER: { return evalNumberConstant(value.todouble());
out( evalNumberConstant(exp.value.todouble()) );
break;
}
default: default:
throw new IllegalStateException("unknown constant type: "+exp.value.typename()); throw new IllegalStateException("unknown constant type: "+value.typename());
} }
} }