/*
* 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.List;
import polyglot.ast.Expr;
import polyglot.ast.Formal;
import polyglot.ast.Id_c;
import polyglot.ast.Node;
import polyglot.ast.Stmt;
import polyglot.ast.Field_c;
import polyglot.types.CodeDef;
import polyglot.types.Context;
import polyglot.types.Def;
import polyglot.types.FieldDef;
import polyglot.types.Flags;
import polyglot.types.Name;
import polyglot.types.SemanticException;
import polyglot.types.TypeSystem;
import polyglot.types.Types;
import polyglot.util.CodeWriter;
import polyglot.util.InternalCompilerError;
import polyglot.util.Position;
import polyglot.visit.ContextVisitor;
import polyglot.visit.PrettyPrinter;
import polyglot.visit.TypeBuilder;
import x10.ast.X10Loop.LoopKind;
import x10.constraint.XFailure;
import x10.constraint.XTerm;
import x10.types.constraints.ConstraintManager;
import x10.errors.Errors;
import polyglot.types.Context;
import x10.types.AtDef;
import x10.types.X10ClassDef;
import x10.types.X10MemberDef;
import x10.types.checker.PlaceChecker;
import x10.types.constraints.CConstraint;
import x10.types.constraints.CConstraint;
import x10.types.constraints.XConstrainedTerm;
/**
* An immutable representation of the X10 statement: [clocked] ateach (i : D) S
* @author vj Dec 9, 2004
* @author Christian Grothoff
*/
public class AtEach_c extends X10ClockedLoop_c implements AtEach, Clocked {
protected AtDef atDef;
/**
* @param pos
*/
public AtEach_c(Position pos) {
super(pos);
loopKind=LoopKind.ATEACH;
}
/**
* @param pos
* @param formal
* @param domain
* @param clocks
* @param body
*/
public AtEach_c(Position pos, Formal formal, Expr domain, List<Expr> clocks, Stmt body) {
super(pos, formal, domain, clocks, body);
loopKind=LoopKind.ATEACH;
}
public AtEach_c(Position pos, Formal formal, Expr domain, Stmt body) {
super(pos, formal, domain, body);
loopKind=LoopKind.ATEACH;
}
public AtDef atDef() {
return this.atDef;
}
public AtEach atDef(AtDef ci) {
if (ci == this.atDef) return this;
AtEach_c n = (AtEach_c) copy();
n.atDef = ci;
return n;
}
@Override
public Node buildTypesOverride(TypeBuilder tb) {
TypeSystem ts = (TypeSystem) tb.typeSystem();
X10ClassDef ct = (X10ClassDef) tb.currentClass();
assert ct != null;
Def def = tb.def();
if (def instanceof FieldDef) {
// FIXME: is this possible?
FieldDef fd = (FieldDef) def;
def = fd.initializer();
}
if (!(def instanceof CodeDef)) {
Errors.issue(tb.job(),
new Errors.CannotOccurOutsideCodeBody(Errors.CannotOccurOutsideCodeBody.Element.At, position()));
// Fake it
def = ts.initializerDef(position(), Types.ref(ct.asType()), Flags.STATIC);
}
CodeDef code = (CodeDef) def;
AtDef mi = (AtDef) AtStmt_c.createDummyAsync(position(), ts, ct.asType(), code, code.staticContext(), false);
// Unlike methods and constructors, do not create new goals for resolving the signature and body separately;
// since closures don't have names, we'll never have to resolve the signature. Just push the code context.
TypeBuilder tb2 = tb.pushCode(mi);
AtEach_c n = (AtEach_c) this.del().visitChildren(tb2);
n = (AtEach_c) n.del().buildTypes(tb2);
if (code instanceof X10MemberDef) {
assert mi.thisDef() == ((X10MemberDef) code).thisDef();
}
return n.atDef(mi);
}
@Override
public Context enterChildScope(Node child, Context c) {
Context oldC = c;
if (child == this.body) {
c = c.pushAt(atDef);
c.x10Kind = Context.X10Kind.At; // this is an at, not an async
}
if (child == this.body) {
if (c == oldC)
c = c.pushBlock();
c.setPlace(atDef.placeTerm());
}
return c;
}
@Override
public Node typeCheckOverride(Node parent, ContextVisitor tc) {
Context c = tc.context();
AtDef def = this.atDef();
if (def.placeTerm() == null) {
// FIXME: this creates a new place term; ideally, it should be the place associated with each
// point in the ateach distribution
XConstrainedTerm placeTerm = XConstrainedTerm.make(PlaceChecker.makePlace());
XConstrainedTerm finishPlaceTerm = c.currentFinishPlaceTerm();
def.setPlaceTerm(placeTerm);
def.setFinishPlaceTerm(finishPlaceTerm);
}
return super.typeCheckOverride(parent, tc);
}
@Override
public Node typeCheck(ContextVisitor tc) {
AtEach_c n = (AtEach_c) super.typeCheck(tc);
Context c = tc.context();
AtDef def = n.atDef;
//if (!def.capturedEnvironment().isEmpty()) {
// System.out.println(this.position() + ": " + this + " captures "+def.capturedEnvironment());
//}
Closure_c.propagateCapturedEnvironment(c, def);
return n;
}
public String toString() {
return "ateach (" + formal + " in " + domain + ")" + (clocks != null ? " clocked(" + clocks + ")" : "") + body;
}
public void prettyPrint(CodeWriter w, PrettyPrinter tr) {
w.write("ateach(");
printBlock(formal, w, tr);
w.write(" in ");
printBlock(domain, w, tr);
w.write(") ");
if (clocks != null) {
w.write("clocked(");
for (Iterator<Expr> c = clocks.iterator(); c.hasNext(); ) {
print(c.next(), w, tr);
if (c.hasNext()) w.write(", ");
}
w.write(")");
}
printSubStmt(body, w, tr);
}
}