/* * 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.types; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.HashSet; import polyglot.ast.TypeNode; import polyglot.ast.Node; import polyglot.ast.Expr; import polyglot.types.Flags; import polyglot.types.LocalDef; import polyglot.types.MethodDef_c; import polyglot.types.Name; import polyglot.types.QName; import polyglot.types.Ref; import polyglot.types.SemanticException; import polyglot.types.Name; import polyglot.types.ContainerType; import polyglot.types.Type; import polyglot.types.TypeSystem; import polyglot.types.Types; import polyglot.types.UnknownType; import polyglot.util.CollectionUtil; import x10.util.CollectionFactory; import polyglot.util.Position; import polyglot.util.TypedList; import polyglot.visit.NodeVisitor; import x10.constraint.XConstraint; import x10.constraint.XFailure; import x10.types.constraints.ConstraintManager; import x10.constraint.XVar; import x10.constraint.XTerm; import x10.constraint.XVar; import x10.types.constraints.CConstraint; import x10.types.constraints.TypeConstraint; import x10.types.constraints.XConstrainedTerm; import x10.ast.X10Call_c; public class X10MethodDef_c extends MethodDef_c implements X10MethodDef { private static final long serialVersionUID = -9049001281152283179L; Ref<CConstraint> guard; Ref<TypeConstraint> typeGuard; List<ParameterType> typeParameters; List<LocalDef> formalNames; Ref<XTerm> body; Ref<? extends Type> offerType; private HashSet<X10MethodDef_c> propertyMethodTransitivelyCalls = null; //null - haven't calculated it public void calcPropertyMethodTransitivelyCalls(Expr expr) { if (propertyMethodTransitivelyCalls==null) propertyMethodTransitivelyCalls=new HashSet<X10MethodDef_c>(); expr.visit( new NodeVisitor() { @Override public Node override(Node n) { if (n instanceof X10Call_c) { X10Call_c call = (X10Call_c) n; X10MethodDef_c callingDef = (X10MethodDef_c) call.methodInstance().def(); propertyMethodTransitivelyCalls.add(callingDef); if (callingDef.propertyMethodTransitivelyCalls!=null) propertyMethodTransitivelyCalls.addAll(callingDef.propertyMethodTransitivelyCalls); } return null; } }); } public boolean isCircularPropertyMethod(Expr expr) { calcPropertyMethodTransitivelyCalls(expr); return propertyMethodTransitivelyCalls.contains(this); } public X10MethodDef_c(TypeSystem ts, Position pos, Position errorPos, Ref<? extends ContainerType> container, Flags flags, Ref<? extends Type> returnType, Name name, List<ParameterType> typeParams, List<Ref<? extends Type>> formalTypes, List<Ref<? extends Type>> throwTypes, ThisDef thisDef, List<LocalDef> formalNames, Ref<CConstraint> guard, Ref<TypeConstraint> typeGuard, Ref< ? extends Type> offerType, Ref<XTerm> body) { super(ts, pos, errorPos, container, flags, returnType, name, formalTypes, throwTypes); this.typeParameters = TypedList.copyAndCheck(typeParams, ParameterType.class, true); this.formalNames = TypedList.copyAndCheck(formalNames, LocalDef.class, true); this.guard = guard; this.typeGuard = typeGuard; this.thisDef = thisDef; this.body = body; this.offerType = offerType; } public XVar thisVar() { if (this.thisDef != null) return this.thisDef.thisVar(); return ConstraintManager.getConstraintSystem().makeThis(); } ThisDef thisDef; public ThisDef thisDef() { return this.thisDef; } public void setThisDef(ThisDef thisDef) { this.thisDef = thisDef; } protected XConstrainedTerm placeTerm; public XConstrainedTerm placeTerm() { return placeTerm; } public void setPlaceTerm(XConstrainedTerm pt) { if (placeTerm != null) assert (placeTerm == null); placeTerm = pt; } public Ref<? extends Type> offerType() { return this.offerType; } public List<LocalDef> formalNames() { return Collections.unmodifiableList(formalNames); } public void setFormalNames(List<LocalDef> formalNames) { this.formalNames = TypedList.copyAndCheck(formalNames, LocalDef.class, true); } public Ref<XTerm> body() { return body; } public void body(Ref<XTerm> body) { this.body = body; } protected boolean inferReturnType; public boolean inferReturnType() { return inferReturnType; } public void inferReturnType(boolean r) { this.inferReturnType = r; } // BEGIN ANNOTATION MIXIN List<Ref<? extends Type>> annotations; public List<Ref<? extends Type>> defAnnotations() { if (annotations == null) return Collections.<Ref<? extends Type>>emptyList(); return Collections.unmodifiableList(annotations); } public void setDefAnnotations(List<Ref<? extends Type>> annotations) { this.annotations = TypedList.<Ref<? extends Type>>copyAndCheck(annotations, Ref.class, true); } public List<Type> annotations() { return X10TypeObjectMixin.annotations(this); } public List<Type> annotationsMatching(Type t) { return X10TypeObjectMixin.annotationsMatching(this, t); } public List<Type> annotationsNamed(QName fullName) { return X10TypeObjectMixin.annotationsNamed(this, fullName); } // END ANNOTATION MIXIN /** Constraint on formal parameters. */ public Ref<CConstraint> guard() { return guard; } public void setGuard(Ref<CConstraint> s) { this.guard = s; } /** Constraint on type parameters. */ public Ref<TypeConstraint> typeGuard() { return typeGuard; } public void setTypeGuard(Ref<TypeConstraint> s) { this.typeGuard = s; } public void setOfferType(Ref<? extends Type> s) { this.offerType = s; } public List<ParameterType> typeParameters() { return Collections.unmodifiableList(typeParameters); } public void setTypeParameters(List<ParameterType> typeParameters) { this.typeParameters = TypedList.copyAndCheck(typeParameters, ParameterType.class, true); } public String signature() { StringBuilder sb = new StringBuilder(name.toString()); if (! typeParameters.isEmpty()) { sb.append("["); boolean first = true; for (ParameterType p : typeParameters) { if (!first) { sb.append(","); } first = false; sb.append(p); } sb.append("]"); } sb.append('('); boolean first = true; for (LocalDef l : formalNames()) { if (!first) { sb.append(","); } first = false; if (! ((X10LocalDef) l).isUnnamed()) { sb.append(l.name().toString()) .append(":"); } sb.append(l.type().get().toString()); } sb.append(')'); return sb.toString(); } /* public static boolean hasVar(Type type, XVar var) { if (type instanceof ConstrainedType) { XConstraint rc = Types.realX(type); if (rc != null && rc.hasVar(var)) return true; ConstrainedType ct = (ConstrainedType) type; if (hasVar(Types.get(ct.baseType()), var)) return true; } if (type instanceof ParametrizedType) { ParametrizedType mt = (ParametrizedType) type; for (Type t : mt.typeParameters()) { if (hasVar(t, var)) return true; } for (XVar v : mt.formals()) { if (v.hasVar(var)) return true; } } return false; } */ public String toString() { String s = designator() + " " + flags().prettyPrint() + container() + "." + signature() + (guard() != null ? guard() : "") + ":" + returnType(); if (!throwTypes().isEmpty()) { s += " throws " + CollectionUtil.listToString(throwTypes()); } if (body != null && body.getCached() != null) s += " = " + body; return s; } }