/* * 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 * * This file was originally derived from the Polyglot extensible compiler framework. * * (C) Copyright 2000-2007 Polyglot project group, Cornell University * (C) Copyright IBM Corporation 2007-2012. */ package polyglot.types; import java.util.*; import polyglot.types.TypeSystem_c.TypeEquals; import polyglot.util.*; import x10.types.constraints.CConstraint; import x10.types.constraints.TypeConstraint; import x10.types.ClosureInstance; import x10.types.X10ProcedureInstance; import x10.types.MethodInstance; public abstract class ProcedureInstance_c<T extends ProcedureDef> extends Use_c<T> implements X10ProcedureInstance<T> { private static final long serialVersionUID = -5028005051545234620L; protected ProcedureInstance_c(TypeSystem ts, Position pos, Position errorPos, Ref<? extends T> def) { super(ts, pos,errorPos,def); } protected CConstraint guard; public CConstraint guard() { if (guard == null) return Types.get(def().guard()); return guard; } public ProcedureInstance_c guard(CConstraint guard) { if (guard == this.guard) return this; ProcedureInstance_c n = (ProcedureInstance_c) copy(); n.guard = guard; return n; } protected boolean checkGuardAtRuntime = false; public boolean checkConstraintsAtRuntime() { return checkGuardAtRuntime; } public ProcedureInstance_c checkConstraintsAtRuntime(boolean check) { if (check==checkGuardAtRuntime) return this; ProcedureInstance_c n = (ProcedureInstance_c) copy(); n.checkGuardAtRuntime = check; return n; } /** Constraint on type parameters. */ protected TypeConstraint typeGuard; public TypeConstraint typeGuard() { if (typeGuard == null) return Types.get(def().typeGuard()); return typeGuard; } public ProcedureInstance_c typeGuard(TypeConstraint s) { if (s == this.typeGuard) return this; ProcedureInstance_c n = (ProcedureInstance_c) copy(); n.typeGuard = s; return n; } protected List<Type> formalTypes; protected List<Type> throwTypes; public ProcedureInstance<T> formalTypes(List<Type> formalTypes) { ProcedureInstance_c<T> p = this.<ProcedureInstance_c<T>>copyGeneric(); p.formalTypes = formalTypes; return p; } public ProcedureInstance<T> throwTypes(List<Type> throwTypes) { ProcedureInstance_c<T> p = this.<ProcedureInstance_c<T>>copyGeneric(); p.throwTypes = throwTypes; return p; } public List<Type> formalTypes() { if (this.formalTypes == null) { return new TransformingList<Ref<? extends Type>, Type>(def().formalTypes(), new DerefTransform<Type>()); } return this.formalTypes; } /** * Returns whether <code>this</code> is <i>more specific</i> than * <code>p</code>, where <i>more specific</i> is defined as JLS * 15.12.2.2. *<p> * <b>Note:</b> There is a fair amount of guess work since the JLS * does not include any info regarding Java 1.2, so all inner class * rules are found empirically using jikes and javac. */ public boolean moreSpecific(Type container, ProcedureInstance<T> p, Context context) { // vj: Should never be invoked assert false; ProcedureInstance<T> p1 = this; ProcedureInstance<T> p2 = p; // rule 1: Type t1 = null; Type t2 = null; if (p1 instanceof MemberInstance<?>) { t1 = ((MemberInstance<?>) p1).container(); } if (p2 instanceof MemberInstance<?>) { t2 = ((MemberInstance<?>) p2).container(); } if (t1 != null && t2 != null) { if (t1.isClass() && t2.isClass()) { if (! t1.isSubtype(t2, context) && ! t1.toClass().isEnclosed(t2.toClass())) { return false; } } else { if (! t1.isSubtype(t2, context)) { return false; } } } // rule 2: // if the formal params of p1 can be used to call p2, p1 is more specific return p2.callValid(t1, p1.formalTypes(), context); } /** Returns true if the procedure has the given formal parameter types. */ public boolean hasFormals(List<Type> formalTypes, Context context) { return CollectionUtil.allElementwise(this.formalTypes(), formalTypes, new TypeEquals(context)); } /** Returns true if a call can be made with the given argument types. */ public boolean callValid(Type thisType, List<Type> argTypes, Context context) { List<Type> l1 = this.formalTypes(); List<Type> l2 = argTypes; Iterator<Type> i1 = l1.iterator(); Iterator<Type> i2 = l2.iterator(); while (i1.hasNext() && i2.hasNext()) { Type t1 = (Type) i1.next(); Type t2 = (Type) i2.next(); if (! ts.isImplicitCastValid(t2, t1, context)) { return false; } } return ! (i1.hasNext() || i2.hasNext()); } public String designator() { return def().designator(); } public String signature() { StringBuilder sb = new StringBuilder(); List<String> formals = new ArrayList<String>(); if (formalTypes != null) { for (int i = 0; i < formalTypes.size(); i++) { String s = formalTypes.get(i).toString(); formals.add(s); } } else { for (int i = 0; i < def().formalTypes().size(); i++) { formals.add(def().formalTypes().get(i).toString()); } } sb.append("("); sb.append(CollectionUtil.listToString(formals)); sb.append(")"); return sb.toString(); } public List<Type> throwTypes() { if (this.throwTypes == null) { return new TransformingList<Ref<? extends Type>, Type>(def().throwTypes(), new DerefTransform<Type>()); } return this.throwTypes; } /** Returns true iff <code>this</code> throws fewer exceptions than * <code>p</code>. */ public boolean throwsSubset(ProcedureInstance<T> p) { SubtypeSet s1 = new SubtypeSet(ts.CheckedThrowable()); SubtypeSet s2 = new SubtypeSet(ts.CheckedThrowable()); s1.addAll(this.throwTypes()); s2.addAll(p.throwTypes()); for (Iterator<Type> i = s1.iterator(); i.hasNext(); ) { Type t = (Type) i.next(); if (! ts.isUncheckedException(t) && ! s2.contains(t)) { return false; } } return true; } }