package polyglot.ext.jl.ast; import polyglot.ast.*; import polyglot.types.*; import polyglot.visit.*; import polyglot.util.*; import java.util.*; /** * An immutable representation of a Java language <code>for</code> * statement. Contains a statement to be executed and an expression * to be tested indicating whether to reexecute the statement. */ public class For_c extends Loop_c implements For { protected List inits; protected Expr cond; protected List iters; protected Stmt body; public For_c(Position pos, List inits, Expr cond, List iters, Stmt body) { super(pos); this.inits = TypedList.copyAndCheck(inits, ForInit.class, true); this.cond = cond; this.iters = TypedList.copyAndCheck(iters, ForUpdate.class, true); this.body = body; } /** List of initialization statements */ public List inits() { return Collections.unmodifiableList(this.inits); } /** Set the inits of the statement. */ public For inits(List inits) { For_c n = (For_c) copy(); n.inits = TypedList.copyAndCheck(inits, ForInit.class, true); return n; } /** Loop condition */ public Expr cond() { return this.cond; } /** Set the conditional of the statement. */ public For cond(Expr cond) { For_c n = (For_c) copy(); n.cond = cond; return n; } /** List of iterator expressions. */ public List iters() { return Collections.unmodifiableList(this.iters); } /** Set the iterator expressions of the statement. */ public For iters(List iters) { For_c n = (For_c) copy(); n.iters = TypedList.copyAndCheck(iters, ForUpdate.class, true); return n; } /** Loop body */ public Stmt body() { return this.body; } /** Set the body of the statement. */ public For body(Stmt body) { For_c n = (For_c) copy(); n.body = body; return n; } /** Reconstruct the statement. */ protected For_c reconstruct(List inits, Expr cond, List iters, Stmt body) { if (! CollectionUtil.equals(inits, this.inits) || cond != this.cond || ! CollectionUtil.equals(iters, this.iters) || body != this.body) { For_c n = (For_c) copy(); n.inits = TypedList.copyAndCheck(inits, ForInit.class, true); n.cond = cond; n.iters = TypedList.copyAndCheck(iters, ForUpdate.class, true); n.body = body; return n; } return this; } /** Visit the children of the statement. */ public Node visitChildren(NodeVisitor v) { List inits = visitList(this.inits, v); Expr cond = (Expr) visitChild(this.cond, v); List iters = visitList(this.iters, v); Stmt body = (Stmt) visitChild(this.body, v); return reconstruct(inits, cond, iters, body); } public Context enterScope(Context c) { return c.pushBlock(); } /** Type check the statement. */ public Node typeCheck(TypeChecker tc) throws SemanticException { TypeSystem ts = tc.typeSystem(); // Check that all initializers have the same type. // This should be enforced by the parser, but check again here, // just to be sure. Type t = null; for (Iterator i = inits.iterator(); i.hasNext(); ) { ForInit s = (ForInit) i.next(); if (s instanceof LocalDecl) { LocalDecl d = (LocalDecl) s; Type dt = d.type().type(); if (t == null) { t = dt; } else if (! t.equals(dt)) { throw new InternalCompilerError("Local variable " + "declarations in a for loop initializer must all " + "be the same type, in this case " + t + ", not " + dt + ".", d.position()); } } } if (cond != null && ! ts.isImplicitCastValid(cond.type(), ts.Boolean())) { throw new SemanticException( "The condition of a for statement must have boolean type.", cond.position()); } return this; } public Type childExpectedType(Expr child, AscriptionVisitor av) { TypeSystem ts = av.typeSystem(); if (child == cond) { return ts.Boolean(); } return child.type(); } /** Write the statement to an output file. */ public void prettyPrint(CodeWriter w, PrettyPrinter tr) { w.write("for ("); w.begin(0); if (inits != null) { boolean first = true; for (Iterator i = inits.iterator(); i.hasNext(); ) { ForInit s = (ForInit) i.next(); printForInit(s, w, tr, first); first = false; if (i.hasNext()) { w.write(","); w.allowBreak(2, " "); } } } w.write(";"); w.allowBreak(0); if (cond != null) { printBlock(cond, w, tr); } w.write (";"); w.allowBreak(0); if (iters != null) { for (Iterator i = iters.iterator(); i.hasNext();) { ForUpdate s = (ForUpdate) i.next(); printForUpdate(s, w, tr); if (i.hasNext()) { w.write(","); w.allowBreak(2, " "); } } } w.end(); w.write(")"); printSubStmt(body, w, tr); } public String toString() { return "for (...) ..."; } private void printForInit(ForInit s, CodeWriter w, PrettyPrinter tr, boolean printType) { boolean oldSemiColon = tr.appendSemicolon(false); boolean oldPrintType = tr.printType(printType); printBlock(s, w, tr); tr.printType(oldPrintType); tr.appendSemicolon(oldSemiColon); } private void printForUpdate(ForUpdate s, CodeWriter w, PrettyPrinter tr) { boolean oldSemiColon = tr.appendSemicolon(false); printBlock(s, w, tr); tr.appendSemicolon(oldSemiColon); } public Term entry() { return listEntry(inits, (cond != null ? cond.entry() : body.entry())); } public List acceptCFG(CFGBuilder v, List succs) { v.visitCFGList(inits, (cond != null ? cond.entry() : body.entry())); if (cond != null) { if (condIsConstantTrue()) { v.visitCFG(cond, body.entry()); } else { v.visitCFG(cond, FlowGraph.EDGE_KEY_TRUE, body.entry(), FlowGraph.EDGE_KEY_FALSE, this); } } v.push(this).visitCFG(body, continueTarget()); v.visitCFGList(iters, (cond != null ? cond.entry() : body.entry())); return succs; } public Term continueTarget() { return listEntry(iters, (cond != null ? cond.entry() : body.entry())); } }