/*
* 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 java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import polyglot.ast.CompoundStmt;
import polyglot.ast.Expr;
import polyglot.ast.Node;
import polyglot.ast.Stmt;
import polyglot.ast.Term;
import polyglot.ast.Stmt_c;
import polyglot.types.SemanticException;
import polyglot.types.TypeSystem;
import polyglot.util.CodeWriter;
import polyglot.util.Position;
import polyglot.util.TypedList;
import polyglot.visit.CFGBuilder;
import polyglot.visit.ContextVisitor;
import polyglot.visit.FlowGraph;
import polyglot.visit.NodeVisitor;
import polyglot.visit.PrettyPrinter;
import polyglot.types.Context;
import x10.errors.Errors;
/**
* An immutable representation of the when statement.
* [IP] Implements CompoundStmt, since it can be unreachable.
*/
public class When_c extends Stmt_c implements CompoundStmt, When {
protected List<Position> positions;
protected List<Expr> exprs;
protected List<Stmt> stmts;
protected Expr expr;
protected Stmt stmt;
public Expr expr() { return this.expr; }
public Stmt stmt() { return this.stmt; }
public When_c(Position p, Expr expr, Stmt stmt) {
super(p);
this.expr = expr;
this.stmt = stmt;
this.positions = new TypedList<Position>(new LinkedList<Position>(), Position.class, false);
this.exprs = new TypedList<Expr>(new LinkedList<Expr>(), Expr.class, false);
this.stmts = new TypedList<Stmt>(new LinkedList<Stmt>(), Stmt.class, false);
}
public void addBranch(Position p, Expr e, Stmt s) {
this.positions.add(p);
this.exprs.add(e);
this.stmts.add(s);
}
public List<Expr> exprs() {
return exprs;
}
public List<Stmt> stmts() {
return stmts;
}
private <T> boolean isSame(List<T> a, List<T> b) {
if (a.size() != b.size()) return false;
Iterator<T> i = a.iterator();
Iterator<T> j = b.iterator();
while (i.hasNext())
if (i.next() != j.next()) return false;
return true;
}
/** Reconstruct the statement. */
public When reconstruct(Expr expr, Stmt stmt, List<Expr> exprs, List<Stmt> stmts) {
if (expr == this.expr && stmt == this.stmt &&
isSame(exprs, this.exprs) && isSame(stmts, this.stmts))
{
return this;
}
When_c n = (When_c) copy();
n.expr = expr;
n.stmt = stmt;
n.exprs = TypedList.copyAndCheck(exprs, Expr.class, true);
n.stmts = TypedList.copyAndCheck(stmts, Stmt.class, true);
return n;
}
/** Visit the children of the statement. */
public Node visitChildren(NodeVisitor v) {
Expr e = (Expr) visitChild(expr, v);
Stmt s = (Stmt) visitChild(stmt, v);
List<Expr> es = visitList(exprs, v);
List<Stmt> ss = visitList(stmts, v);
return reconstruct(e, s, es, ss);
}
public String toString() {
return "when (" + expr + ")" + stmt + (exprs.size() > 0 ? "..." : "");
}
/** Write the statement to an output file. */
public void prettyPrint(CodeWriter w, PrettyPrinter tr) {
w.write("when (");
printBlock(expr, w, tr);
w.write(") ");
printSubStmt(stmt, w, tr);
if (exprs.size() > 0) {
Iterator<Expr> es = exprs.iterator();
Iterator<Stmt> ss = stmts.iterator();
while (es.hasNext()) {
Expr e = (Expr) es.next();
Stmt s = (Stmt) ss.next();
w.write("or (");
printBlock(e, w, tr);
w.write(") ");
printSubStmt(s, w, tr);
}
}
}
@Override
public Node typeCheck(ContextVisitor tc) {
if (!expr().type().isBoolean()) {
Errors.issue(tc.job(), new Errors.ArgumentOfWhenMustBeBoolean(position()));
}
return this;
}
/**
* Return the first (sub)term performed when evaluating this
* term.
*/
public Term firstChild() {
return expr;
}
/**
* Visit this term in evaluation order.
* Each expression goes to the corresponding statement if true or to the
* next expression if false. The last expression wraps around to the
* first. Each statement goes to this "when".
*/
public <S> List<S> acceptCFG(CFGBuilder v, List<S> succs) {
Expr e = expr;
Stmt s = stmt;
Expr ne = null;
Iterator<Expr> es = exprs.iterator();
Iterator<Stmt> ss = stmts.iterator();
while (es.hasNext()) {
ne = (Expr) es.next();
v.visitCFG(e, FlowGraph.EDGE_KEY_TRUE, s,
ENTRY, FlowGraph.EDGE_KEY_FALSE, ne, ENTRY);
v.visitCFG(s, this, EXIT);
e = ne;
s = (Stmt) ss.next();
}
v.visitCFG(e, FlowGraph.EDGE_KEY_TRUE, s,
ENTRY, FlowGraph.EDGE_KEY_FALSE, expr, ENTRY);
v.visitCFG(s, this, EXIT);
return succs;
}
}