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 org.luaj.vm2.LuaValue;
import org.luaj.vm2.ast.Exp.Constant;
import org.luaj.vm2.ast.Exp.NameExp;
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.Stat.Assign;
import org.luaj.vm2.ast.Stat.FuncDef;
@@ -88,6 +89,17 @@ public class NameResolver extends Visitor {
public void visit(LocalAssign stat) {
visitExps(stat.values);
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) {

View File

@@ -5,6 +5,8 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.luaj.vm2.LuaValue;
public class NameScope {
private static final Set<String> LUA_KEYWORDS = new HashSet<String>();
@@ -67,6 +69,7 @@ public class NameScope {
public final NameScope definingScope;
public boolean isupvalue;
public boolean hasassignments;
public LuaValue initialValue;
/** Global is named variable not associated with a defining scope */
public NamedVariable(String name) {
this.name = name;
@@ -80,5 +83,8 @@ public class NameScope {
public boolean isLocal() {
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;
if ( n == 1 && m<=1 ) {
Name name = stat.names.get(0);
if ( name.variable.isConstant() )
return;
String value = m>0? evalLuaValue(stat.values.get(0)): "NIL";
singleLocalDeclareAssign(name,value);
} else {
@@ -271,6 +273,8 @@ public class JavaCodeGen {
private void singleAssign(Name name, String valu) {
if ( name.variable.isLocal() ) {
if ( name.variable.isConstant() )
return;
outi( "" );
singleReference( name );
outr( " = "+valu+";" );
@@ -280,6 +284,10 @@ public class JavaCodeGen {
private void singleReference(Name name) {
if ( name.variable.isLocal() ) {
if ( name.variable.isConstant() ) {
out( evalConstant(name.variable.initialValue) );
return;
}
out( javascope.getJavaName(name.variable) );
if ( name.variable.isupvalue && name.variable.hasassignments )
out( "[0]" );
@@ -294,7 +302,9 @@ public class JavaCodeGen {
private void singleLocalDeclareAssign(NamedVariable variable, String value) {
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+"};" );
else if ( variable.isupvalue )
outl( "final LuaValue "+javaname+(value!=null? " = "+value: "")+";" );
@@ -408,6 +418,10 @@ public class JavaCodeGen {
out(evalLuaValue(exp)+".toboolean()");
}
public void visit(NameExp exp) {
if ( exp.name.variable.isConstant() ) {
out ( exp.name.variable.initialValue.toboolean()? "TRUE": "FALSE");
return;
}
out(evalLuaValue(exp)+".toboolean()");
}
public void visit(FuncCall exp) {
@@ -471,6 +485,12 @@ public class JavaCodeGen {
out(evalLuaValue(exp)+".todouble()");
}
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()");
}
public void visit(FuncCall exp) {
@@ -528,23 +548,21 @@ public class JavaCodeGen {
}
public void visit(Constant exp) {
switch ( exp.value.type() ) {
case LuaValue.TSTRING: {
out( evalLuaStringConstant(exp.value.checkstring()) );
break;
}
out( evalConstant(exp.value) );
}
protected String evalConstant(LuaValue value) {
switch ( value.type() ) {
case LuaValue.TSTRING:
return evalLuaStringConstant(value.checkstring());
case LuaValue.TNIL:
out("NIL");
break;
return "NIL";
case LuaValue.TBOOLEAN:
out(exp.value.toboolean()? "TRUE": "FALSE");
break;
case LuaValue.TNUMBER: {
out( evalNumberConstant(exp.value.todouble()) );
break;
}
return value.toboolean()? "TRUE": "FALSE";
case LuaValue.TNUMBER:
return evalNumberConstant(value.todouble());
default:
throw new IllegalStateException("unknown constant type: "+exp.value.typename());
throw new IllegalStateException("unknown constant type: "+value.typename());
}
}