package polyglot.ext.pao.visit;
import polyglot.ast.Expr;
import polyglot.ast.Node;
import polyglot.ast.NodeFactory;
import polyglot.ext.pao.extension.PaoExt;
import polyglot.ext.pao.types.PaoTypeSystem;
import polyglot.frontend.Job;
import polyglot.types.SemanticException;
import polyglot.types.Type;
import polyglot.types.TypeSystem;
import polyglot.util.Position;
import polyglot.visit.AscriptionVisitor;
import polyglot.visit.NodeVisitor;
/**
* Visitor that inserts boxing and unboxing code into the AST.
* <code>PaoBoxer</code> accomplishes this task by first inserting explicit
* casts into the AST, where primitive values need to be treated as objects,
* and then uses the {@link PaoExt#rewrite(PaoTypeSystem, NodeFactory) PaoExt.rewrite(PaoTypeSystem, NodeFactory)}
* method to rewrite these explicit casts into appropriate boxing and
* unboxing code.
*/
public class PaoBoxer extends AscriptionVisitor
{
public PaoBoxer(Job job, TypeSystem ts, NodeFactory nf) {
super(job, ts, nf);
}
/**
* Inserts an explicit cast if the type of expressions <code>e</code> is
* a primitive type, and the type <code>toType</code> is a reference type.
* For example, <code>Integer i = 42</code> will be modified to
* <code>Integer i = (Object)42</code>. The <code>leaveCall</code> method
* will ensure that these explicit casts are rewritten to the correct
* boxing and unboxing code.
*/
public Expr ascribe(Expr e, Type toType) {
Type fromType = e.type();
if (toType == null) {
return e;
}
Position p = e.position();
// Insert a cast. Translation of the cast will insert the
// correct boxing/unboxing code.
if (toType.isReference() && fromType.isPrimitive()) {
return nf.Cast(p, nf.CanonicalTypeNode(p, ts.Object()), e);
}
return e;
}
/**
* Calls the
* {@link PaoExt#rewrite(PaoTypeSystem, NodeFactory) PaoExt.rewrite(PaoTypeSystem, NodeFactory)}
* method to rewrite the explicit casts inserted by the
* <code>ascribe</code> method into correct boxing and unboxing code.
*/
public Node leaveCall(Node old, Node n, NodeVisitor v) throws SemanticException {
n = super.leaveCall(old, n, v);
if (n.ext() instanceof PaoExt) {
return ((PaoExt) n.ext()).rewrite((PaoTypeSystem) typeSystem(),
nodeFactory());
}
return n;
}
}