package polyglot.ext.pao.extension;
import polyglot.ast.*;
import polyglot.ext.pao.types.PaoTypeSystem;
import polyglot.types.MethodInstance;
/**
* The <code>PaoExt</code> implementation for the
* <code>Binary</code> AST node.
*/
public class PaoBinaryExt_c extends PaoExt_c {
/**
* Rewrite the binary operators <code>==</code> and <code>!=</code> to
* invoke <code>Primitive.equals(o, p)</code>.
*
* @see PaoExt#rewrite(PaoTypeSystem, NodeFactory)
* @see polyglot.ext.pao.runtime.Primitive#equals(Object, Object)
*/
public Node rewrite(PaoTypeSystem ts, NodeFactory nf) {
Binary b = (Binary) node();
Expr l = b.left();
Expr r = b.right();
if (b.operator() == Binary.EQ || b.operator() == Binary.NE) {
MethodInstance mi = ((PaoTypeSystem) ts).primitiveEquals();
// The container of mi, mi.container(), is the super class of
// the runtime boxed representations of primitive values.
if (ts.isSubtype(l.type(), mi.container()) ||
ts.equals(l.type(), ts.Object())) {
// The left operand is either a subtype of
// polyglot.ext.pao.runtime.Primitive, or it is an
// Object, and thus possibly a subtype of
// polyglot.ext.pao.runtime.Primitive. Either way,
// it may be a boxed primitive.
if (r.type().isReference()) {
// The right operand is a reference type, so replace the
// binary operation with a call to
// Primitive.equals(Object, Object).
TypeNode x = nf.CanonicalTypeNode(b.position(),
mi.container());
Call y = nf.Call(b.position(), x, mi.name(), l, r);
y = (Call) y.type(mi.returnType());
if (b.operator() == Binary.NE) {
return nf.Unary(b.position(), Unary.NOT, y).type(mi.returnType());
}
else {
return y;
}
}
}
}
// we do not need to rewrite the binary operator.
return super.rewrite(ts, nf);
}
}