package polyglot.ext.jl.ast;
import polyglot.ast.*;
import polyglot.types.*;
import polyglot.visit.*;
import polyglot.util.*;
import java.util.*;
/**
* A <code>FieldAssign_c</code> represents a Java assignment expression to
* a field. For instance, <code>this.x = e</code>.
*
* The class of the <code>Expr</code> returned by
* <code>FieldAssign_c.left()</code>is guaranteed to be a <code>Field</code>.
*/
public class FieldAssign_c extends Assign_c implements FieldAssign
{
public FieldAssign_c(Position pos, Field left, Operator op, Expr right) {
super(pos, left, op, right);
}
public Assign left(Expr left) {
FieldAssign_c n = (FieldAssign_c)super.left(left);
n.assertLeftType();
return n;
}
private void assertLeftType() {
if (!(left() instanceof Field)) {
throw new InternalCompilerError("left expression of an FieldAssign must be a field");
}
}
public Term entry() {
Field f = (Field)left();
if (f.target() instanceof Expr) {
return ((Expr) f.target()).entry();
}
else {
if (operator() != Assign.ASSIGN) {
return f;
}
else {
return right().entry();
}
}
}
protected void acceptCFGAssign(CFGBuilder v) {
Field f = (Field)left();
if (f.target() instanceof Expr) {
Expr o = (Expr) f.target();
// o.f = e: visit o -> e -> (o.f = e)
v.visitCFG(o, right().entry());
v.visitCFG(right(), this);
}
else {
// T.f = e: visit e -> (T.f OP= e)
v.visitCFG(right(), this);
}
}
protected void acceptCFGOpAssign(CFGBuilder v) {
Field f = (Field)left();
if (f.target() instanceof Expr) {
Expr o = (Expr) f.target();
// o.f OP= e: visit o -> o.f -> e -> (o.f OP= e)
v.visitCFG(o, f);
v.visitThrow(f);
v.edge(f, right().entry());
v.visitCFG(right(), this);
}
else {
// T.f OP= e: visit T.f -> e -> (T.f OP= e)
v.visitThrow(f);
v.edge(f, right().entry());
v.visitCFG(right(), this);
}
}
public List throwTypes(TypeSystem ts) {
List l = new ArrayList(super.throwTypes(ts));
Field f = (Field)left();
if (f.target() instanceof Expr) {
l.add(ts.NullPointerException());
}
return l;
}
}