private List <TypeExpression> GetTypes(TypeExpression typeExpression, bool includeTypeVariables, IDictionary <string, TypeExpression> evaluated = null) { List <TypeExpression> typeSet = new List <TypeExpression>(); if (evaluated == null) { evaluated = new Dictionary <string, TypeExpression>(); } if (evaluated.Keys.Contains(typeExpression.FullName)) { if (evaluated[typeExpression.FullName] is ClassType) { MergeClassType((ClassType)evaluated[typeExpression.FullName], (ClassType)typeExpression); } return(typeSet); } else { evaluated.Add(typeExpression.FullName, typeExpression); } if (typeExpression is UnionType) { UnionType union = typeExpression as UnionType; foreach (var expression in union.TypeSet) { typeSet.AddRange(GetTypes(expression, includeTypeVariables, evaluated)); } } else if (typeExpression.IsValueType() || typeExpression is StringType) { if (typeExpression is TypeVariable) { typeSet.Add(((TypeVariable)typeExpression).Substitution); } else { typeSet.Add(typeExpression); } } else if (typeExpression is TypeVariable) { if (((TypeVariable)typeExpression).Substitution != null) { typeSet.AddRange(GetTypes(((TypeVariable)typeExpression).Substitution, includeTypeVariables, evaluated)); } else if (includeTypeVariables) { typeSet.Add(typeExpression); } } else if (typeExpression is FieldType) { FieldType fieldType = typeExpression as FieldType; typeSet.AddRange(GetTypes(fieldType.FieldTypeExpression, includeTypeVariables, evaluated)); } else if (typeExpression is PropertyType) { PropertyType propertyType = typeExpression as PropertyType; typeSet.AddRange(GetTypes(propertyType.PropertyTypeExpression, includeTypeVariables, evaluated)); } else if (typeExpression is ClassType) { typeSet.Add(typeExpression); } return(typeSet); }
// WriteType inference #region overloadResolution() /// <summary> /// A public method for being used as a global overload resolution process /// </summary> /// <param name="arguments">The ordered types of actual parameters</param> /// <param name="fileName"></param> /// <param name="line"></param> /// <param name="column"></param> /// <returns>The actual method called (a union type if more than one is suitable)</returns> public TypeExpression overloadResolution(TypeExpression[] arguments, Location location) { int aux; int min = -1, index = -1, minNumFreeVariables = Int32.MaxValue; // * We create a dictionary of <index,promotionValue> to remember the promotion values (they could have // repeated values because of type variables) Dictionary <int, int> promotionValues = new Dictionary <int, int>(); if (this.typeSet.Count == 0) { System.Diagnostics.Debug.Assert(false, "There should be no empty intersection types."); return(null); } for (int i = 0; i < this.typeSet.Count; i++) { MethodType mt = TypeExpression.As <MethodType>(this.typeSet[i]); if (mt == null) { ErrorManager.Instance.NotifyError(new OperationNotAllowedError("()", mt.FullName, location)); } aux = mt.Promotion(arguments, location); if (aux != -1) { if ((min >= aux) || (min == -1)) { min = aux; index = i; promotionValues[index] = min; } } } // * No method is suitable if (index == -1) { ErrorManager.Instance.NotifyError(new UnknownMemberError(location)); return(null); } index = -1; // * Gets the min number of free variables foreach (KeyValuePair <int, int> pair in promotionValues) { if (pair.Value == min) { aux = ((MethodType)this.typeSet[pair.Key]).GetNumberFreeVariables(); if (aux < minNumFreeVariables) { minNumFreeVariables = aux; } } } // * Assigns a union of all the best methods TypeExpression bestMethods = null; foreach (KeyValuePair <int, int> pair in promotionValues) { if (pair.Value == min && ((MethodType)this.typeSet[pair.Key]).GetNumberFreeVariables() == minNumFreeVariables) { bestMethods = UnionType.collect(bestMethods, this.typeSet[pair.Key]); } } // * We've got'em return(bestMethods); }
/// <summary> /// To add a new type to the class equivalence. /// </summary> /// <param name="te">The type to be added</param> /// <param name="unification">Indicates if the kind of unification (equivalent, incremental or override).</param> /// <param name="previouslyUnified">To detect infinite loops. The previously unified pairs of type expressions.</param> /// <returns>If the substitution has been correctly applied</returns> public bool add(TypeExpression te, SortOfUnification unification, IList <Pair <TypeExpression, TypeExpression> > previouslyUnified) { TypeVariable tv = te as TypeVariable; if (tv != null) // * Another type variable // * Tries to add its substitution { if (tv.Substitution != null) // * If it has a substitution { if (!this.add(tv.EquivalenceClass.Substitution, unification, previouslyUnified)) // * We try to add it to ourselves { return(false); // * Both susbstitutions are not the same } } // * If no error, we add it to the equivalence class this.typeVariables[tv.Variable] = tv; if (tv.EquivalenceClass != null) // * The parameter already has a equivalence class { IList <int> keys = new List <int>(tv.EquivalenceClass.TypeVariables.Keys); foreach (int pairKey in keys) { if (!this.typeVariables.ContainsKey(pairKey)) { // * We recursively add all the element of the equivalence class this.typeVariables[pairKey] = tv.EquivalenceClass.TypeVariables[pairKey]; this.add(tv.EquivalenceClass.TypeVariables[pairKey], unification, previouslyUnified); } } } // * Finally, we update the equivalence class of tv tv.EquivalenceClass = this; return(true); } // * te is not a type variable if (this.substitution != null) { // * A substitution already exists if (unification == SortOfUnification.Equivalent) { // * They must be equivalent if (!(bool)this.substitution.AcceptOperation(new EquivalentOperation(te), null)) { return(false); } if (te.HasTypeVariables()) { // var1=Array(int) must be unified to Array(var1) return(te.Unify(this.substitution, unification, previouslyUnified)); } return(true); } if (unification == SortOfUnification.Incremental) { // * The incremental behaviour implies a union of all the types this.substitution = UnionType.collect(this.substitution, te); return(true); } // * Override unification (the susbstitution is overridden) this.substitution = te; return(true); } // * We set the type as a susbstitution substitution = te; return(true); }