package polyglot.ext.pao.extension;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import polyglot.ast.*;
import polyglot.ext.pao.types.PaoTypeSystem;
import polyglot.types.ConstructorInstance;
import polyglot.types.MethodInstance;
import polyglot.types.Type;
/**
* The <code>PaoExt</code> implementation for the
* <code>Cast</code> AST node.
*/
public class PaoCastExt_c extends PaoExt_c {
/**
* Insert boxing and unboxing code for the casts inserted by the
* <code>PaoBoxer</code>.
* @see PaoExt_c#rewrite(PaoTypeSystem, NodeFactory)
* @see polyglot.ext.pao.visit.PaoBoxer
*/
public Node rewrite(PaoTypeSystem ts, NodeFactory nf) {
Cast c = (Cast) node();
Type rtype = c.expr().type();
Type ltype = c.castType().type();
if (ltype.isPrimitive() && rtype.isReference()) {
// We have an expression with reference type being cast to
// a primitive type, added by the PaoBoxer visitor.
// We need to unbox.
// e.g., "(int)e", where e is of type Integer gets rewritten to
// "((polyglot.ext.pao.runtime.Integer)e).getInt()"
MethodInstance mi = ts.getter(ltype.toPrimitive());
Cast x = nf.Cast(c.position(),
nf.CanonicalTypeNode(c.position(), mi.container()),
c.expr());
x = (Cast) x.type(mi.container());
Call y = nf.Call(c.position(), x, mi.name(),
Collections.EMPTY_LIST);
y = (Call) y.type(mi.returnType());
return y.methodInstance(mi);
}
else if (ltype.isReference() && rtype.isPrimitive()) {
// We have an expression with primitive type being cast to
// a reference type, added by the PaoBoxer visitor.
// We need to box.
// e.g., "(Integer)e", where e is of type int gets rewritten to
// "new polyglot.ext.pao.runtime.Integer(e)"
ConstructorInstance ci = ts.wrapper(rtype.toPrimitive());
List args = new ArrayList(1);
args.add(c.expr());
New x = nf.New(c.position(),
nf.CanonicalTypeNode(c.position(), ci.container()),
args);
x = (New) x.type(ci.container());
return x.constructorInstance(ci);
}
// Don't need to either box or unbox.
return super.rewrite(ts, nf);
}
}