/* * This file is part of the X10 project (http://x10-lang.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.opensource.org/licenses/eclipse-1.0.php * * (C) Copyright IBM Corporation 2006-2010. */ package x10.ast; import polyglot.ast.AmbAssign_c; import polyglot.ast.ArrayAccess; import polyglot.ast.ArrayAccessAssign; import polyglot.ast.Assign; import polyglot.ast.Call; import polyglot.ast.Expr; import polyglot.ast.Field; import polyglot.ast.FieldAssign; import polyglot.ast.Local; import polyglot.ast.LocalAssign; import polyglot.ast.Node; import polyglot.ast.NodeFactory; import polyglot.ast.Term; import polyglot.types.SemanticException; import polyglot.types.Type; import polyglot.util.CodeWriter; import polyglot.util.Position; import polyglot.visit.CFGBuilder; import polyglot.visit.ContextVisitor; import polyglot.visit.NodeVisitor; import polyglot.visit.PrettyPrinter; import polyglot.types.Context; public class X10AmbAssign_c extends AmbAssign_c { protected Expr left; public X10AmbAssign_c(NodeFactory nf, Position pos, Expr left, Operator op, Expr right) { super(nf, pos, left, op, right); this.left = left; } @Override public Assign visitLeft(NodeVisitor v) { if (v instanceof ContextVisitor) { ContextVisitor cv = (ContextVisitor) v; // Do not update context if within a deptype. // This is an illegal user program -- assignments are not allowed in dep types -- // and the error will be reported separately to the user. if (! ((Context) cv.context()).inDepType()) v = cv.context(((Context) cv.context()).pushAssignment()); } return superVisitLeft(v); } private Assign superVisitLeft(NodeVisitor v) { Expr left = (Expr) visitChild(this.left, v); if (left != this.left) { X10AmbAssign_c n = (X10AmbAssign_c) copy(); n.left = left; return n; } return this; } @Override public Node disambiguate(ContextVisitor ar) { if (left instanceof Call) { Call c = (Call) left; if (c.target() instanceof Expr) { NodeFactory nf = (NodeFactory) ar.nodeFactory(); return nf.SettableAssign(position(), (Expr) c.target(), c.arguments(), operator(), right()); } } return superDisambiguate(ar); } private Node superDisambiguate(ContextVisitor ar) { AmbAssign_c n = this; if (left instanceof Local) { LocalAssign a = ar.nodeFactory().LocalAssign(n.position(), (Local)left, operator(), right()); return a; } else if (left instanceof Field) { FieldAssign a = ar.nodeFactory().FieldAssign(n.position(), ((Field)left).target(), ((Field)left).name(), operator(), right()); a = a.targetImplicit(((Field) left).isTargetImplicit()); a = a.fieldInstance(((Field) left).fieldInstance()); return a; } else if (left instanceof ArrayAccess) { ArrayAccessAssign a = ar.nodeFactory().ArrayAccessAssign(n.position(), ((ArrayAccess)left).array(), ((ArrayAccess)left).index(), operator(), right()); return a; } // LHS is still ambiguous. The pass should get rerun later. return this; // throw new SemanticException("Could not disambiguate left side of assignment!", n.position()); } public Type leftType() { return left.type(); } @Override public Expr left() { return left; } public Term firstChild() { return left; } protected void acceptCFGAssign(CFGBuilder v) { v.visitCFG(left, right(), ENTRY); v.visitCFG(right(), this, EXIT); } protected void acceptCFGOpAssign(CFGBuilder v) { v.visitCFG(left, right(), ENTRY); v.visitCFG(right(), this, EXIT); } public Assign typeCheckLeft(ContextVisitor tc) { // Didn't finish disambiguation; just return. return this; } public Node typeCheck(ContextVisitor tc) { // Didn't finish disambiguation; just return. return this; } public String toString() { return left + " " + op + " " + right; } public void prettyPrint(CodeWriter w, PrettyPrinter tr) { printSubExpr(left, true, w, tr); w.write(" "); w.write(op.toString()); w.allowBreak(2, 2, " ", 1); // miser mode w.begin(0); printSubExpr(right, false, w, tr); w.end(); } }