package polyglot.ext.coffer.ast; import polyglot.ext.jl.ast.*; import polyglot.ext.coffer.types.*; import polyglot.ext.coffer.extension.*; import polyglot.ast.*; import polyglot.types.*; import polyglot.visit.*; import polyglot.util.*; import java.util.*; /** An implementation of the <code>CofferConstructorDecl</code> interface. * <code>ConstructorDecl</code> is extended with pre- and post-conditions. */ public class CofferConstructorDecl_c extends ConstructorDecl_c implements CofferConstructorDecl { protected KeySetNode entryKeys; protected KeySetNode returnKeys; protected List throwConstraints; public CofferConstructorDecl_c(Position pos, Flags flags, String name, List formals, KeySetNode entryKeys, KeySetNode returnKeys, List throwConstraints, Block body) { super(pos, flags, name, formals, Collections.EMPTY_LIST, body); this.entryKeys = entryKeys; this.returnKeys = returnKeys; this.throwConstraints = TypedList.copyAndCheck(throwConstraints, ThrowConstraintNode.class, true); } public KeySetNode entryKeys() { return this.entryKeys; } public CofferConstructorDecl entryKeys(KeySetNode entryKeys) { CofferConstructorDecl_c n = (CofferConstructorDecl_c) copy(); n.entryKeys = entryKeys; return n; } public KeySetNode returnKeys() { return this.returnKeys; } public CofferConstructorDecl returnKeys(KeySetNode returnKeys) { CofferConstructorDecl_c n = (CofferConstructorDecl_c) copy(); n.returnKeys = returnKeys; return n; } public List throwConstraints() { return this.throwConstraints; } public List throwTypes() { return new CachingTransformingList(throwConstraints, new GetType()); } public class GetType implements Transformation { public Object transform(Object o) { return ((ThrowConstraintNode) o).type(); } } public ConstructorDecl throwTypes(List l) { throw new InternalCompilerError("unimplemented"); } public CofferConstructorDecl throwConstraints(List throwConstraints) { CofferConstructorDecl_c n = (CofferConstructorDecl_c) copy(); n.throwConstraints = TypedList.copyAndCheck(throwConstraints, ThrowConstraintNode.class, true); return n; } /* public Context enterScope(Context context) { CofferContext c = (CofferContext) super.enterScope(context); c = (CofferContext) c.pushBlock(); if (entryKeys != null) { for (Iterator i = entryKeys.keys().iterator(); i.hasNext(); ) { Key key = (Key) i.next(); c.addHeldKey(key); } } return c; } */ protected CofferConstructorDecl_c reconstruct(List formals, KeySetNode entryKeys, KeySetNode returnKeys, List throwConstraints, Block body) { if (entryKeys != this.entryKeys || returnKeys != this.returnKeys || !CollectionUtil.equals(throwConstraints, this.throwConstraints)) { CofferConstructorDecl_c n = (CofferConstructorDecl_c) copy(); n.entryKeys = entryKeys; n.returnKeys = returnKeys; n.throwConstraints = TypedList.copyAndCheck(throwConstraints, ThrowConstraintNode.class, true); return (CofferConstructorDecl_c) n.reconstruct(formals, Collections.EMPTY_LIST, body); } return (CofferConstructorDecl_c) super.reconstruct(formals, Collections.EMPTY_LIST, body); } public Node visitChildren(NodeVisitor v) { List formals = visitList(this.formals, v); KeySetNode entryKeys = (KeySetNode) visitChild(this.entryKeys, v); KeySetNode returnKeys = (KeySetNode) visitChild(this.returnKeys, v); List throwConstraints = visitList(this.throwConstraints, v); Block body = (Block) visitChild(this.body, v); return reconstruct(formals, entryKeys, returnKeys, throwConstraints, body); } public Node buildTypes(TypeBuilder tb) throws SemanticException { CofferNodeFactory nf = (CofferNodeFactory) tb.nodeFactory(); CofferConstructorDecl n = (CofferConstructorDecl) super.buildTypes(tb); CofferConstructorInstance ci = (CofferConstructorInstance) n.constructorInstance(); if (n.entryKeys() == null) { n = n.entryKeys(nf.CanonicalKeySetNode(position(), ci.entryKeys())); } if (n.returnKeys() == null) { n = n.returnKeys(nf.CanonicalKeySetNode(position(), ci.returnKeys())); } List l = new LinkedList(); boolean changed = false; for (Iterator i = n.throwConstraints().iterator(); i.hasNext(); ) { ThrowConstraintNode cn = (ThrowConstraintNode) i.next(); if (cn.keys() == null) { cn = cn.keys(n.entryKeys()); changed = true; } l.add(cn); } if (changed) { n = n.throwConstraints(l); } return n; } public Node typeCheck(TypeChecker tc) throws SemanticException { CofferClassType ct = (CofferClassType) tc.context().currentClass(); CofferConstructorInstance ci = (CofferConstructorInstance) this.constructorInstance(); if (ct.key() != null) { if (ci.entryKeys().contains(ct.key())) { throw new SemanticException("Constructor cannot hold key \"" + ct.key() + "\" (associated with " + "this) on entry.", position()); } if (! ci.returnKeys().contains(ct.key())) { throw new SemanticException("Constructor must hold key \"" + ct.key() + "\" (associated with " + "this) on exit.", position()); } } return super.typeCheck(tc); } protected ConstructorInstance makeConstructorInstance(ClassType ct, TypeSystem ts) throws SemanticException { CofferConstructorInstance ci = (CofferConstructorInstance) super.makeConstructorInstance(ct, ts); CofferTypeSystem vts = (CofferTypeSystem) ts; KeySet entryKeys; KeySet returnKeys; if (this.entryKeys == null) { entryKeys = vts.emptyKeySet(position()); } else { entryKeys = this.entryKeys.keys(); } if (this.returnKeys == null) { returnKeys = vts.emptyKeySet(position()); if (ct instanceof CofferClassType) { CofferClassType vct = (CofferClassType) ct; if (vct.key() != null) returnKeys = returnKeys.add(vct.key()); } } else { returnKeys = this.returnKeys.keys(); } ci = (CofferConstructorInstance) ci.entryKeys(entryKeys); ci = (CofferConstructorInstance) ci.returnKeys(returnKeys); List throwConstraints = new ArrayList(this.throwConstraints.size()); for (Iterator i = this.throwConstraints.iterator(); i.hasNext(); ) { ThrowConstraintNode cn = (ThrowConstraintNode) i.next(); if (cn.constraint().keys() != null) { throwConstraints.add(cn.constraint()); } else { throwConstraints.add(cn.constraint().keys(entryKeys)); } } return (CofferConstructorInstance) ci.throwConstraints(throwConstraints); } /** Write the constructor to an output file. */ public void prettyPrintHeader(CodeWriter w, PrettyPrinter tr) { w.begin(0); w.write(flags().translate()); w.write(name); w.write("("); w.begin(0); for (Iterator i = formals.iterator(); i.hasNext(); ) { Formal f = (Formal) i.next(); print(f, w, tr); if (i.hasNext()) { w.write(","); w.allowBreak(0, " "); } } w.end(); w.write(")"); if (! throwConstraints.isEmpty()) { w.allowBreak(6); w.write("throws "); for (Iterator i = throwConstraints.iterator(); i.hasNext(); ) { ThrowConstraintNode cn = (ThrowConstraintNode) i.next(); print(cn, w, tr); if (i.hasNext()) { w.write(","); w.allowBreak(4, " "); } } } w.end(); } }