package polyglot.visit;
import polyglot.ast.*;
import polyglot.types.TypeSystem;
import polyglot.frontend.Job;
import polyglot.util.Position;
/** Visitor which performs constant folding. */
public class ConstantFolder extends NodeVisitor
{
TypeSystem ts;
NodeFactory nf;
public ConstantFolder(TypeSystem ts, NodeFactory nf) {
this.ts = ts;
this.nf = nf;
}
public TypeSystem typeSystem() {
return ts;
}
public NodeFactory nodeFactory() {
return nf;
}
public Node leave(Node old, Node n, NodeVisitor v_) {
if (! (n instanceof Expr)) {
return n;
}
Expr e = (Expr) n;
if (! e.isConstant()) {
return e;
}
// Don't fold String +. Strings are often broken up for better
// formatting.
if (e instanceof Binary) {
Binary b = (Binary) e;
if (b.operator() == Binary.ADD &&
b.left().constantValue() instanceof String &&
b.right().constantValue() instanceof String) {
return b;
}
}
Object v = e.constantValue();
Position pos = e.position();
if (v == null) {
return nf.NullLit(pos).type(ts.Null());
}
if (v instanceof String) {
return nf.StringLit(pos,
(String) v).type(ts.String());
}
if (v instanceof Boolean) {
return nf.BooleanLit(pos,
((Boolean) v).booleanValue()).type(ts.Boolean());
}
if (v instanceof Double) {
return nf.FloatLit(pos, FloatLit.DOUBLE,
((Double) v).doubleValue()).type(ts.Double());
}
if (v instanceof Float) {
return nf.FloatLit(pos, FloatLit.FLOAT,
((Float) v).floatValue()).type(ts.Float());
}
if (v instanceof Long) {
return nf.IntLit(pos, IntLit.LONG,
((Long) v).longValue()).type(ts.Long());
}
if (v instanceof Integer) {
return nf.IntLit(pos, IntLit.INT,
((Integer) v).intValue()).type(ts.Int());
}
if (v instanceof Character) {
return nf.CharLit(pos,
((Character) v).charValue()).type(ts.Char());
}
return e;
}
}