/* * 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.ConstructorDecl_c; import polyglot.ast.FlagsNode; import polyglot.ast.Formal; import polyglot.ast.Id; import polyglot.ast.Node; import polyglot.ast.NodeFactory; import polyglot.ast.TypeNode; import polyglot.ast.ConstructorCall; import polyglot.ast.Stmt; import polyglot.frontend.Globals; import polyglot.types.ClassDef; import polyglot.types.ConstructorDef; import polyglot.types.Context; import polyglot.types.Flags; import polyglot.types.LazyRef; import polyglot.types.LocalDef; import polyglot.types.MethodDef; import polyglot.types.Name; import polyglot.types.QName; import polyglot.types.Ref; import polyglot.types.SemanticException; import polyglot.types.ContainerType; import polyglot.types.Type; import polyglot.types.TypeSystem; import polyglot.types.Types; import polyglot.util.CodeWriter; import polyglot.util.CollectionUtil; import x10.util.AnnotationUtils; import x10.util.CollectionFactory; import polyglot.util.ErrorInfo; import polyglot.util.InternalCompilerError; import polyglot.util.Position; import polyglot.util.TypedList; import polyglot.visit.ContextVisitor; import polyglot.visit.ExceptionChecker; import polyglot.visit.NodeVisitor; import polyglot.visit.PrettyPrinter; import polyglot.visit.TypeBuilder; import polyglot.visit.TypeCheckPreparer; import polyglot.visit.TypeChecker; import x10.constraint.XFailure; import x10.constraint.XVar; import x10.constraint.XTerm; import x10.types.constraints.ConstraintManager; import x10.constraint.XVar; import x10.errors.Errors; import x10.extension.X10Del; import x10.extension.X10Del_c; import x10.extension.X10Ext; import x10.types.X10ClassDef; import x10.types.X10ClassType; import x10.types.X10ConstructorDef; import polyglot.types.Context; import x10.types.X10MemberDef; import x10.types.X10ParsedClassType; import x10.types.X10ProcedureDef; import polyglot.types.TypeSystem; import x10.types.checker.PlaceChecker; import x10.types.checker.ThisChecker; import x10.types.checker.VarChecker; import x10.types.constraints.CConstraint; import x10.types.constraints.TypeConstraint; import x10.types.constraints.XConstrainedTerm; import x10.visit.CheckEscapingThis; import x10.visit.X10TypeChecker; /** * An X10ConstructorDecl differs from a ConstructorDecl in that it has a returnType. * * @author vj */ public class X10ConstructorDecl_c extends ConstructorDecl_c implements X10ConstructorDecl { protected DepParameterExpr guard; protected TypeNode returnType; protected List<TypeParamNode> typeParameters; protected TypeNode hasType; protected TypeNode offerType; protected List<TypeNode> throwsTypes; public X10ConstructorDecl_c(Position pos, FlagsNode flags, Id name, TypeNode returnType, List<TypeParamNode> typeParams, List<Formal> formals, DepParameterExpr guard, TypeNode offerType, List<TypeNode> throwsTypes, Block body) { super(pos, flags, name, formals, body); // null, not unknown. this.returnType = returnType instanceof HasTypeNode_c ? null : returnType; if (returnType instanceof HasTypeNode_c) hasType = ((HasTypeNode_c) returnType).typeNode(); this.guard = guard; this.typeParameters = TypedList.copyAndCheck(typeParams, TypeParamNode.class, true); this.offerType = offerType; this.throwsTypes = throwsTypes; } public TypeNode returnType() { return returnType; } public DepParameterExpr guard() { return guard; } public X10ConstructorDecl_c guard(DepParameterExpr e) { X10ConstructorDecl_c n = (X10ConstructorDecl_c) copy(); n.guard = e; return n; } public TypeNode offerType() { return offerType; } public X10ConstructorDecl_c offerType(TypeNode offerType) { if (this.offerType != offerType) { X10ConstructorDecl_c n = (X10ConstructorDecl_c) copy(); n.offerType = offerType; return n; } return this; } public List<TypeNode> throwsTypes() { return throwsTypes; } public X10ConstructorDecl_c throwsTypes(List<TypeNode> throwsTypes) { if (this.throwsTypes != throwsTypes) { X10ConstructorDecl_c n = (X10ConstructorDecl_c) copy(); n.throwsTypes = throwsTypes; return n; } return this; } protected X10ConstructorDecl_c hasType(TypeNode hasType) { if (this.hasType != hasType) { X10ConstructorDecl_c n = (X10ConstructorDecl_c) copy(); n.hasType = hasType; return n; } return this; } public List<TypeParamNode> typeParameters() { return typeParameters; } public X10ConstructorDecl_c typeParameters(List<TypeParamNode> typeParams) { X10ConstructorDecl_c n = (X10ConstructorDecl_c) copy(); n.typeParameters=TypedList.copyAndCheck(typeParams, TypeParamNode.class, true); return n; } @Override public X10ConstructorDecl_c flags(FlagsNode flags) { return (X10ConstructorDecl_c) super.flags(flags); } @Override public X10ConstructorDecl_c name(Id name) { return (X10ConstructorDecl_c) super.name(name); } @Override public X10ConstructorDecl_c formals(List<Formal> formals) { return (X10ConstructorDecl_c) super.formals(formals); } @Override public X10ConstructorDecl_c constructorDef(ConstructorDef ci) { return (X10ConstructorDecl_c) super.constructorDef(ci); } @Override public X10ConstructorDef constructorDef() { return (X10ConstructorDef) super.constructorDef(); } public X10ConstructorDecl_c returnType(TypeNode returnType) { if (returnType != this.returnType) { X10ConstructorDecl_c n = (X10ConstructorDecl_c) copy(); n.returnType = returnType; return n; } return this; } protected ConstructorDef createConstructorDef(TypeSystem ts, ClassDef ct, Flags flags) { X10ConstructorDef ci = (X10ConstructorDef) ((TypeSystem) ts).constructorDef(position(), name().position(), Types.ref(ct.asType()), flags, Collections.<Ref<? extends Type>>emptyList(), Collections.<Ref<? extends Type>>emptyList(), offerType == null ? null : offerType.typeRef()); ci.setThisDef(((X10ClassDef) ct).thisDef()); ci.setPlaceTerm(PlaceChecker.constructorPlaceTerm(ci)); return ci; } public Node superBuildTypesOverride(TypeBuilder tb) { TypeSystem ts = tb.typeSystem(); ClassDef ct = tb.currentClass(); assert ct != null; Flags flags = this.flags.flags(); if (ct.flags().isInterface()) { flags = flags.Public().Abstract(); } ConstructorDef ci = createConstructorDef(ts, ct, flags); ct.addConstructor(ci); TypeBuilder tbChk = tb.pushCode(ci); final TypeBuilder tbx = tb; final ConstructorDef mix = ci; ConstructorDecl_c n = (ConstructorDecl_c) this.visitSignature(new NodeVisitor() { int key = 0; public Node override(Node n) { return X10ConstructorDecl_c.this.visitChild(n, tbx.pushCode(mix)); } }); List<Ref<? extends Type>> formalTypes = new ArrayList<Ref<? extends Type>>(n.formals().size()); for (Formal f : n.formals()) { formalTypes.add(f.type().typeRef()); } ci.setFormalTypes(formalTypes); Block body = (Block) n.visitChild(n.body, tbChk); n = (ConstructorDecl_c) n.body(body); return n.constructorDef(ci); } @Override public Node buildTypesOverride(TypeBuilder tb) { NodeFactory nf = tb.nodeFactory(); X10ConstructorDecl_c n = this; TypeNode offerType = (TypeNode) n.visitChild(n.offerType, tb); n = (X10ConstructorDecl_c) n.offerType(offerType); n = (X10ConstructorDecl_c) n.superBuildTypesOverride(tb); X10ConstructorDef ci = (X10ConstructorDef) n.constructorDef(); n = (X10ConstructorDecl_c) X10Del_c.visitAnnotations(n, tb); List<AnnotationNode> as = ((X10Del) n.del()).annotations(); if (as != null) { List<Ref<? extends Type>> ats = new ArrayList<Ref<? extends Type>>(as.size()); for (AnnotationNode an : as) { ats.add(an.annotationType().typeRef()); } ci.setDefAnnotations(ats); } ClassDef currentClass = tb.currentClass(); // Set the constructor name to the short name of the class, to shut up the Java type-checker. // The X10 parser has "this" for the name. Position genPos = n.position().markCompilerGenerated(); n = (X10ConstructorDecl_c) n.name(nf.Id(genPos, currentClass.name())); TypeNode htn = (TypeNode) n.visitChild(n.hasType, tb); n = (X10ConstructorDecl_c) n.hasType(htn); TypeNode rtn = (TypeNode) n.visitChild(n.returnType, tb); // Enable return type inference for this constructor declaration. if (rtn == null) { Type rType = currentClass.asType(); rType = Types.instantiateTypeParametersExplicitly(rType); if (ci.derivedReturnType()) { ci.inferReturnType(true); rtn = nf.CanonicalTypeNode(genPos, Types.lazyRef(rType)); } else { rtn = nf.CanonicalTypeNode(genPos, rType); } } n = (X10ConstructorDecl_c) n.returnType(rtn); ci.setReturnType((Ref<? extends X10ClassType>) n.returnType().typeRef()); if (n.guard() != null) { ci.setGuard(n.guard().valueConstraint()); ci.setTypeGuard(n.guard().typeConstraint()); } if (n.typeParameters().size() > 0) { Errors.issue(tb.job(), new Errors.ConstructorsCannotHaveTypeParameters(n.position())); n = (X10ConstructorDecl_c) n.typeParameters(Collections.<TypeParamNode>emptyList()); } List<LocalDef> formalNames = new ArrayList<LocalDef>(n.formals().size()); for (Formal f : n.formals()) { formalNames.add(f.localDef()); } ci.setFormalNames(formalNames); List<Ref<? extends Type>> throw_types = new ArrayList<Ref<? extends Type>>(); for (TypeNode tn : n.throwsTypes()) { throw_types.add(tn.typeRef()); } ci.setThrowTypes(throw_types); // add sythetic super and property call to the body (if there isn't this(...) call) Block body = n.body(); if (body!=null) { ConstructorCall constructorCall = CheckEscapingThis.getConstructorCall(n); if (constructorCall!=null && constructorCall.kind()==ConstructorCall.Kind.THIS) { // the only case where I do not insert super or prop calls } else { class HasPropCall extends NodeVisitor { boolean res = false; @Override public Node override(Node n) { if (n instanceof AssignPropertyCall) res = true; return null; } } HasPropCall hasPropCall = new HasPropCall(); body.visit(hasPropCall); if (!hasPropCall.res || constructorCall==null) { // need to add prop or super call ArrayList<Stmt> newBody = new ArrayList<Stmt>(body.statements()); if (constructorCall==null) { // add super call newBody.add(0,nf.SuperCall(genPos,Collections.EMPTY_LIST)); } if (!hasPropCall.res) { // add super call newBody.add(1,nf.AssignPropertyCall(genPos,Collections.EMPTY_LIST,Collections.EMPTY_LIST)); } n = (X10ConstructorDecl_c)n.body(body.statements(newBody)); } } } return n; } @Override public Context enterScope(Context c) { c = super.enterScope(c); if (!c.inStaticContext() && constructorDef().thisDef() != null) c.addVariable(constructorDef().thisDef().asInstance()); return c; } @Override public Context enterChildScope(Node child, Context c) { // We should have entered the constructor scope already. assert c.currentCode() == this.constructorDef(); Context oldC=c; if (child != body) { // Push formals so they're in scope in the types of the other formals. c = c.pushBlock(); boolean isParam = false; for (TypeParamNode f : typeParameters) { if (child == f) { isParam = true; break; } } for (Formal f : formals) { if (child == f) { isParam = true; break; } } // Push formals so they're in scope in the types of the other formals. for (TypeParamNode f : typeParameters) { f.addDecls(c); } for (int i=0; i < formals.size(); i++) { Formal f = formals.get(i); f.addDecls(c); if (f == child) break; // do not add downstream formals } } // Ensure that the place constraint is set appropriately when // entering the body of the method. c = super.enterChildScope(child, c); TypeSystem xts = (TypeSystem) c.typeSystem(); if (child == body || child == returnType || child == hasType || child == offerType || (formals != null && formals.contains(child))) { if (oldC==c) c = c.pushBlock(); PlaceChecker.setHereIsThisHome(c); } if (child == body && offerType != null && offerType.typeRef()!=null && offerType.typeRef().known()) { if (oldC==c) c = c.pushBlock(); c.setCollectingFinishScope(offerType.type()); } if (child == guard) { TypeSystem ts = c.typeSystem(); c = c.pushDepType(Types.<Type>ref(ts.unknownType(this.position))); } // Add the constructor guard into the environment. if (guard != null) { if (child == body || child == returnType || child == hasType) { Ref<CConstraint> vc = guard.valueConstraint(); Ref<TypeConstraint> tc = guard.typeConstraint(); if (oldC==c && (vc != null || tc != null)) { c = c.pushBlock(); } if (vc != null) c.addConstraint(vc); if (tc != null) c.setTypeConstraintWithContextTerms(tc); } } addInTypeConstraints(c); return c; } public void addInTypeConstraints(Context c) { Ref<TypeConstraint> tc = ((X10ClassType) Types.get(ci.container())).x10Def().typeBounds(); if (tc != null) { c.setTypeConstraintWithContextTerms(tc); } } /** Visit the children of the method. */ public Node visitSignature(NodeVisitor v) { X10ConstructorDecl_c result = (X10ConstructorDecl_c) super.visitSignature(v); TypeNode offerType = (TypeNode) visitChild(result.offerType, v); result = (X10ConstructorDecl_c) result.offerType(offerType); List<TypeParamNode> typeParams = visitList(result.typeParameters, v); if (! CollectionUtil.allEqual(typeParams, result.typeParameters)) result = (X10ConstructorDecl_c) result.typeParameters(typeParams); TypeNode returnType = (TypeNode) visitChild(result.returnType, v); result = (X10ConstructorDecl_c) result.returnType(returnType); DepParameterExpr guard = (DepParameterExpr) visitChild(result.guard, v); result = (X10ConstructorDecl_c) result.guard(guard); TypeNode htn = (TypeNode) result.visitChild(result.hasType, v); result = (X10ConstructorDecl_c) result.hasType(htn); List<TypeNode> throwsTypes = visitList(result.throwsTypes, v); result = (X10ConstructorDecl_c) result.throwsTypes(throwsTypes); return result; } @Override public Node setResolverOverride(Node parent, TypeCheckPreparer v) { if (constructorDef().inferReturnType() && body() != null) { TypeNode tn = returnType(); NodeVisitor childv = v.enter(parent, this); childv = childv.enter(this, returnType()); if (childv instanceof TypeCheckPreparer) { TypeCheckPreparer tcp = (TypeCheckPreparer) childv; final LazyRef<Type> r = (LazyRef<Type>) tn.typeRef(); TypeChecker tc = new X10TypeChecker(v.job(), v.typeSystem(), v.nodeFactory(), v.getMemo(), true); tc = (TypeChecker) tc.context(tcp.context().freeze()); r.setResolver(new TypeCheckReturnTypeGoal(this, new Node[] { guard() }, body(), tc, r, r.getCached())); } } return super.setResolverOverride(parent, v); } public Node typeCheckOverride(Node parent, ContextVisitor tc) { X10ConstructorDecl nn = this; X10ConstructorDecl old = nn; TypeSystem xts = (TypeSystem) tc.typeSystem(); // Step I.a. Check the formals. TypeChecker childtc = (TypeChecker) tc.enter(parent, nn); nn = nn.offerType((TypeNode)nn.visitChild(nn.offerType(), childtc)); // First, record the final status of each of the type params and formals. List<TypeParamNode> processedTypeParams = nn.visitList(nn.typeParameters(), childtc); nn = (X10ConstructorDecl) nn.typeParameters(processedTypeParams); List<Formal> processedFormals = nn.visitList(nn.formals(), childtc); nn = (X10ConstructorDecl) nn.formals(processedFormals); nn = (X10ConstructorDecl) X10Del_c.visitAnnotations(nn, childtc); // [NN]: Don't do this here, do it on lookup of the formal. We don't want spurious self constraints in the signature. // for (Formal n : processedFormals) { // Ref<Type> ref = (Ref<Type>) n.type().typeRef(); // Type newType = ref.get(); // // if (n.localDef().flags().isFinal()) { // CConstraint c = X10TypeMixin.xclause(newType); // if (c == null) c = new CConstraint_c(); // try { // c.addSelfBinding(xts.xtypeTranslator().trans(n.localDef().asInstance())); // } // catch (XFailure e) { // throw new SemanticException(e.getMessage(), position()); // } // newType = X10TypeMixin.xclause(newType, c); // } // // ref.update(newType); // } // Step I.b. Check the guard. if (nn.guard() != null) { ContextVisitor guardtc = childtc.context(childtc.context().pushDepType(Types.<Type>ref(xts.unknownType(nn.guard().position())))); DepParameterExpr processedWhere = (DepParameterExpr) nn.visitChild(nn.guard(), guardtc); nn = (X10ConstructorDecl) nn.guard(processedWhere); // Now build the new formal arg list. // TODO: Add a marker to the TypeChecker which records // whether in fact it changed the type of any formal. List<Formal> formals = processedFormals; //List newFormals = new ArrayList(formals.size()); X10ProcedureDef pi = (X10ProcedureDef) nn.memberDef(); CConstraint c = pi.guard().get(); try { if (c != null) { c = c.copy(); for (Formal n : formals) { Ref<Type> ref = (Ref<Type>) n.type().typeRef(); Type newType = ref.get(); // Fold the formal's constraint into the guard. XVar var = xts.xtypeTranslator().translate(n.localDef().asInstance()); CConstraint dep = Types.xclause(newType); if (dep != null) { dep = dep.copy(); dep = dep.substitute(var, c.self()); /* XPromise p = dep.intern(var); dep = dep.substitute(p.term(), c.self()); */ c.addIn(dep); } ref.update(newType); } } // Report.report(1, "X10MethodDecl_c: typeoverride mi= " + nn.methodInstance()); // Fold this's constraint (the class invariant) into the guard. // Huh???? No -- cannot do this for constructors, since the object // does not yet exist. /* { Type t = tc.context().currentClass(); CConstraint dep = Types.xclause(t); if (c != null && dep != null) { XVar thisVar = constructorDef().thisVar(); if (thisVar != null) dep = dep.substitute(thisVar, c.self()); // dep = dep.copy(); // XPromise p = dep.intern(xts.xtypeTranslator().transThis(t)); // dep = dep.substitute(p.term(), c.self()); c.addIn(dep); } } */ } catch (XFailure e) { tc.errorQueue().enqueue(ErrorInfo.SEMANTIC_ERROR, e.getMessage(), position()); c = null; } // Check if the guard is consistent. if (c != null && ! c.consistent()) { Errors.issue(tc.job(), new Errors.DependentClauseIsInconsistent("constructor", guard), this); // FIXME: [IP] mark constraint clause as invalid } } // Step I.c. Check the throw types List<TypeNode> processedThrowsTypes = nn.visitList(nn.throwsTypes(), childtc); nn = (X10ConstructorDecl) nn.throwsTypes(processedThrowsTypes); X10ConstructorDef nnci = (X10ConstructorDef) nn.constructorDef(); // Step II. Check the return type. // Now visit the returntype to ensure that its depclause, if any is processed. // Visit the formals so that they get added to the scope .. the return type // may reference them. //TypeChecker tc1 = (TypeChecker) tc.copy(); // childtc will have a "wrong" mi pushed in, but that doesnt matter. // we simply need to push in a non-null mi here. TypeChecker childtc1 = (TypeChecker) tc.enter(parent, nn); if (childtc1.context() == tc.context()) childtc1 = (TypeChecker) childtc1.context((Context) tc.context().shallowCopy()); // Add the type params and formals to the context. nn.visitList(nn.typeParameters(),childtc1); nn.visitList(nn.formals(),childtc1); childtc1.context().setVarWhoseTypeIsBeingElaborated(null); TypeNode r = (TypeNode) nn.visitChild(nn.returnType(), childtc1); Ref<? extends Type> ref = r.typeRef(); Type type = Types.get(ref); X10ClassType container = (X10ClassType) Types.instantiateTypeParametersExplicitly(tc.context().currentClass()); CConstraint xclause = Types.xclause(container); if (! tc.typeSystem().isSubtype(type, container, tc.context())) { Errors.issue(tc.job(), new Errors.ConstructorReturnTypeNotSubtypeOfContainer(type, container, position())); r = tc.nodeFactory().CanonicalTypeNode(r.position(), container); } nn = (X10ConstructorDecl) nn.returnType(r); ((Ref<Type>) nnci.returnType()).update(r.type()); //Report.report(1, "X10MethodDecl_c: typeoverride mi= " + nn.methodInstance()); // Step III. Check the body. // We must do it with the correct mi -- the return type will be // checked by property statements in the body. TypeChecker childtc2 = (TypeChecker) tc.enter(parent, nn); // Add the formals to the context. nn.visitList(nn.typeParameters(),childtc2); nn.visitList(nn.formals(),childtc2); //Report.report(1, "X10MethodDecl_c: after visiting formals " + childtc2.context()); // Now process the body. nn = (X10ConstructorDecl) nn.body((Block) nn.visitChild(nn.body(), childtc2)); nn = (X10ConstructorDecl) childtc2.leave(parent, old, nn, childtc2); try { X10MethodDecl_c.dupFormalCheck(typeParameters, formals); } catch (SemanticException e) { Errors.issue(tc.job(), e, this); } { if (hasType != null) { final TypeNode h = (TypeNode) nn.visitChild(((X10ConstructorDecl_c) nn).hasType, childtc1); Type hasType = PlaceChecker.ReplaceHereByPlaceTerm(h.type(), childtc1.context()); nn = (X10ConstructorDecl) ((X10ConstructorDecl_c) nn).hasType(h); if (! tc.typeSystem().isSubtype(nnci.returnType().get(), hasType,tc.context())) { Errors.issue(tc.job(), new Errors.TypeIsNotASubtypeOfTypeBound(type, hasType, position())); } } } return nn; } public NodeVisitor exceptionCheckEnter(ExceptionChecker ec) { return ec.push(new ExceptionChecker.CodeTypeReporter("Constructor " + ci.signature())) .push(constructorDef().asInstance().throwTypes()); } @Override public Node typeCheck(ContextVisitor tc) { X10ConstructorDecl_c n = this; ThisChecker thisC = new ThisChecker(tc.job()); if (formals != null) { visitList(formals, thisC); if (thisC.error()) { Errors.issue(tc.job(), new Errors.ThisNotPermittedInConstructorFormals(formals, position())); } } thisC.clearError(); if (returnType != null) { if (thisC.error()) { Errors.issue(tc.job(), new Errors.ThisNotPermittedInConstructorReturnType(returnType, position())); } } n = (X10ConstructorDecl_c) super.typeCheck(tc); return n; } public Node conformanceCheck(ContextVisitor tc) { X10ConstructorDecl_c n = (X10ConstructorDecl_c) super.conformanceCheck(tc); TypeSystem ts = (TypeSystem) tc.typeSystem(); Type retTypeBase = n.returnType().type(); retTypeBase = Types.baseType(retTypeBase); retTypeBase = Types.instantiateTypeParametersExplicitly(retTypeBase); X10ConstructorDef nnci = (X10ConstructorDef) n.constructorDef(); // Type clazz = ((X10Type) nnci.asInstance().container()).setFlags(X10Flags.ROOTED); Type clazz = nnci.asInstance().container(); clazz = Types.instantiateTypeParametersExplicitly(clazz); if (! ts.typeEquals(retTypeBase, clazz, tc.context())) { Errors.issue(tc.job(), new Errors.ReturnTypeOfConstructorMustBeFromTypeOfClass(retTypeBase, clazz, n.position())); } X10MethodDecl_c.checkVisibility(tc, this); return n; } /** Visit the children of the constructor. */ public Node visitChildren(NodeVisitor v) { X10ConstructorDecl_c n = (X10ConstructorDecl_c) super.visitChildren(v); TypeNode htn = (TypeNode) n.visitChild(n.hasType, v); return n.hasType(htn); } public String toString() { return (flags==null ? "" : flags.flags().translate()) + "this(...)"; } /** Write the constructor to an output file. */ public void prettyPrintHeader(CodeWriter w, PrettyPrinter tr) { w.begin(0); for (Iterator<AnnotationNode> i = (((X10Ext) this.ext()).annotations()).iterator(); i.hasNext(); ) { AnnotationNode an = i.next(); an.prettyPrint(w, tr); w.allowBreak(0, " "); } tr.print(this, flags, w); w.write("def this("); w.begin(0); for (Iterator<Formal> i = formals.iterator(); i.hasNext(); ) { Formal f = i.next(); print(f, w, tr); if (i.hasNext()) { w.write(","); w.allowBreak(0, " "); } } w.end(); w.write(")"); /* if (! throwTypes().isEmpty()) { w.allowBreak(6); w.write("throws "); for (Iterator<TypeNode> i = throwTypes().iterator(); i.hasNext(); ) { TypeNode tn = i.next(); print(tn, w, tr); if (i.hasNext()) { w.write(","); w.allowBreak(4, " "); } } } */ w.end(); } }