Esempio n. 1
0
        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);
        }