/* * 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.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import polyglot.ast.Block; import polyglot.ast.Expr; import polyglot.ast.Expr_c; import polyglot.ast.Node; import polyglot.ast.Precedence; import polyglot.ast.Stmt; import polyglot.ast.AbstractBlock_c; import polyglot.ast.Block_c; import polyglot.ast.Term; import polyglot.types.Context; import polyglot.types.SemanticException; import polyglot.types.Type; import polyglot.types.TypeSystem; import polyglot.util.CodeWriter; import polyglot.util.CollectionUtil; import x10.types.constants.ConstantValue; import x10.util.CollectionFactory; import polyglot.util.Position; import polyglot.util.TypedList; import polyglot.visit.CFGBuilder; import polyglot.visit.ContextVisitor; import polyglot.visit.NodeVisitor; import polyglot.visit.PrettyPrinter; /** * A StmtExpr is a sequence of statements followed by an expression, the result. * * The result may be null, if the type of the StmtExpr is Void. This is used to * flatten a call to a void method. Such StmtExpr's can only be used in Eval statements. * - Bowen * * @author igor * */ public class StmtExpr_c extends Expr_c implements StmtExpr { protected List<Stmt> statements; protected Expr result; public StmtExpr_c(Position pos, List<Stmt> statements, Expr result) { super(pos); assert(statements != null); //assert(result != null); // result can be null, if the type is Void -- Bowen this.statements = TypedList.copyAndCheck(statements, Stmt.class, true); this.result = result; } /** Visit the children of the statement expression. */ public Node visitChildren(NodeVisitor v) { List<Stmt> statements = visitList(this.statements, v); Expr result = (Expr) visitChild(this.result, v); return reconstruct(statements, result); } /** Type check the expression. */ public Node typeCheck(ContextVisitor tc) { return type(result == null ? tc.typeSystem().Void() : result.type()); } /** Get the result of the statement expression. */ public Expr result() { return this.result; } /** Set the result of the statement expression. */ public StmtExpr result(Expr result) { if (result == this.result) return this; StmtExpr_c n = (StmtExpr_c) copy(); n.result = result; return n; } /** Get the statements of the statement expression. */ public List<Stmt> statements() { return this.statements; } /** Set the statements of the statement expression. */ public Block statements(List<Stmt> statements) { StmtExpr_c n = (StmtExpr_c) copy(); n.statements = TypedList.copyAndCheck(statements, Stmt.class, true); return n; } /** Append a statement to the statement expression (just before the result). */ public Block append(Stmt stmt) { List<Stmt> l = new ArrayList<Stmt>(statements.size()+1); l.addAll(statements); l.add(stmt); return statements(l); } /** Prepend a statement to the statement expression. */ public Block prepend(Stmt stmt) { List<Stmt> l = new ArrayList<Stmt>(statements.size()+1); l.add(stmt); l.addAll(statements); return statements(l); } /** Append a list of statements to the statement expression (just before the result). */ public StmtExpr append(List<Stmt> stmts) { List<Stmt> l = new ArrayList<Stmt>(statements.size()+stmts.size()); l.addAll(statements); l.addAll(stmts); return (StmtExpr) statements(l); } /** Prepend a list of statements to the statement expression. */ public StmtExpr prepend(List<Stmt> stmts) { List<Stmt> l = new ArrayList<Stmt>(statements.size()+stmts.size()); l.addAll(stmts); l.addAll(statements); return (StmtExpr) statements(l); } public Context enterScope(Context c) { return c.pushBlock(); } /** Reconstruct the statement expression. */ protected StmtExpr_c reconstruct(List<Stmt> statements, Expr result) { if (! CollectionUtil.allEqual(statements, this.statements) || result != this.result) { StmtExpr_c n = (StmtExpr_c) copy(); n.statements = TypedList.copyAndCheck(statements, Stmt.class, true); n.result = result; return n; } return this; } /** Write the expression to an output file. */ public void prettyPrint(CodeWriter w, PrettyPrinter tr) { w.begin(0); w.write("({"); w.unifiedBreak(4, 1, " ", 1); w.begin(0); for (Stmt n : statements) { printBlock(n, w, tr); w.newline(); } if (result != null) { printSubExpr(result, w, tr); } w.end(); w.unifiedBreak(0, 1, " ", 1); w.write("})"); w.end(); } public Term firstChild() { return listChild(statements, result); } public <S> List<S> acceptCFG(CFGBuilder v, List<S> succs) { if (result == null) { v.visitCFGList(statements, this, EXIT); } else { v.visitCFGList(statements, result, ENTRY); v.visitCFG(result, this, EXIT); } return succs; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("({"); int count = 0; for (Iterator<Stmt> i = statements.iterator(); i.hasNext(); ) { if (count++ > 2) { sb.append(" ..."); break; } Stmt n = i.next(); sb.append(" "); sb.append(n.toString()); } if (result != null) { sb.append(" "); sb.append(result.toString()); } sb.append(" })"); return sb.toString(); } public ConstantValue constantValue() { return null; } public boolean isConstant() { // StmtExprs are never constants, because we can't eliminate the Stmts because they may have side-effects! return false; } public Precedence precedence() { return Precedence.LITERAL; } }