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>CofferMethodDecl</code> interface.
* <code>ConstructorDecl</code> is extended with pre- and post-conditions.
*/
public class CofferMethodDecl_c extends MethodDecl_c implements CofferMethodDecl
{
protected KeySetNode entryKeys;
protected KeySetNode returnKeys;
protected List throwConstraints;
public CofferMethodDecl_c(Position pos, Flags flags, TypeNode returnType,
String name, List formals, KeySetNode entryKeys, KeySetNode returnKeys,
List throwConstraints, Block body) {
super(pos, flags, returnType, 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 CofferMethodDecl entryKeys(KeySetNode entryKeys) {
CofferMethodDecl_c n = (CofferMethodDecl_c) copy();
n.entryKeys = entryKeys;
return n;
}
public KeySetNode returnKeys() {
return this.returnKeys;
}
public CofferMethodDecl returnKeys(KeySetNode returnKeys) {
CofferMethodDecl_c n = (CofferMethodDecl_c) copy();
n.returnKeys = returnKeys;
return n;
}
public List throwTypes() {
return new CachingTransformingList(throwConstraints, new GetType());
}
public class GetType implements Transformation {
public Object transform(Object o) {
return ((ThrowConstraintNode) o).type();
}
}
public MethodDecl throwTypes(List l) {
throw new InternalCompilerError("unimplemented");
}
public List throwConstraints() {
return this.throwConstraints;
}
public CofferMethodDecl throwConstraints(List throwConstraints) {
CofferMethodDecl_c n = (CofferMethodDecl_c) copy();
n.throwConstraints = TypedList.copyAndCheck(throwConstraints, ThrowConstraintNode.class, true);
return n;
}
/*
public Context enterScope(Context context) {
CofferContext c = (CofferContext) super.enterScope(context);
if (entryKeys != null) {
c = (CofferContext) c.pushBlock();
for (Iterator i = entryKeys.keys().iterator(); i.hasNext(); ) {
Key key = (Key) i.next();
c.addHeldKey(key);
}
}
return c;
}
*/
protected CofferMethodDecl_c reconstruct(TypeNode returnType, List formals, KeySetNode entryKeys, KeySetNode returnKeys, List throwConstraints, Block body) {
if (entryKeys != this.entryKeys || returnKeys != this.returnKeys || ! CollectionUtil.equals(throwConstraints, this.throwConstraints)) {
CofferMethodDecl_c n = (CofferMethodDecl_c) copy();
n.entryKeys = entryKeys;
n.returnKeys = returnKeys;
n.throwConstraints = TypedList.copyAndCheck(throwConstraints, ThrowConstraintNode.class, true);
return (CofferMethodDecl_c) n.reconstruct(returnType, formals, Collections.EMPTY_LIST, body);
}
return (CofferMethodDecl_c) super.reconstruct(returnType, formals, Collections.EMPTY_LIST, body);
}
public Node visitChildren(NodeVisitor v) {
TypeNode returnType = (TypeNode) visitChild(this.returnType, 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(returnType, formals, entryKeys, returnKeys, throwConstraints, body);
}
public Node buildTypes(TypeBuilder tb) throws SemanticException {
CofferNodeFactory nf = (CofferNodeFactory) tb.nodeFactory();
CofferMethodDecl n = (CofferMethodDecl) super.buildTypes(tb);
CofferMethodInstance mi = (CofferMethodInstance) n.methodInstance();
if (n.entryKeys() == null) {
n = n.entryKeys(nf.CanonicalKeySetNode(n.position(),
mi.entryKeys()));
}
if (n.returnKeys() == null) {
n = n.returnKeys(nf.CanonicalKeySetNode(n.position(),
mi.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();
CofferMethodInstance mi = (CofferMethodInstance) this.methodInstance();
if (ct.key() != null) {
if (! mi.entryKeys().contains(ct.key()) &&
mi.returnKeys().contains(ct.key())) {
throw new SemanticException("Method cannot add key \"" +
ct.key() + "\" (associated with " +
"this).", position());
}
}
return super.typeCheck(tc);
}
protected MethodInstance makeMethodInstance(ClassType ct, TypeSystem ts)
throws SemanticException
{
CofferMethodInstance mi = (CofferMethodInstance)
super.makeMethodInstance(ct, ts);
CofferTypeSystem vts = (CofferTypeSystem) ts;
KeySet entryKeys;
KeySet returnKeys;
if (this.entryKeys == null) {
entryKeys = vts.emptyKeySet(position());
if (ct instanceof CofferClassType) {
CofferClassType vct = (CofferClassType) ct;
if (vct.key() != null)
entryKeys = entryKeys.add(vct.key());
}
}
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();
}
mi = (CofferMethodInstance) mi.entryKeys(entryKeys);
mi = (CofferMethodInstance) mi.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 (CofferMethodInstance) mi.throwConstraints(throwConstraints);
}
/** Write the method to an output file. */
public void prettyPrintHeader(Flags flags, CodeWriter w, PrettyPrinter tr) {
w.begin(0);
w.write(flags.translate());
print(returnType, w, tr);
w.write(" " + name + "(");
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();
}
}