コード例 #1
0
        // 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);
        }
コード例 #2
0
        // SSA

        #region Clone()
        /// <summary>
        /// Clones a type to be used in SSA. It must taken into account that:
        /// - In case it has no type variables, no clone is performed
        /// - WriteType variables, equivalence classes and substitutions are cloned
        /// </summary>
        /// <param name="clonedTypeVariables">WriteType variables that have been cloned.</param>
        /// <param name="equivalenceClasses">Equivalence classes of the type cloned variables. These
        /// equivalence classes need to be updated with the new cloned type variables.</param>
        /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param>
        /// <returns>The cloned type</returns>
        internal override TypeExpression Clone(IDictionary <int, TypeVariable> clonedTypeVariables, IList <EquivalenceClass> equivalenceClasses, MethodType methodAnalyzed)
        {
            if (!this.HasTypeVariables())
            {
                return(this);
            }
            IntersectionType newIntersectionType = (IntersectionType)this.MemberwiseClone();

            newIntersectionType.typeSet = new List <TypeExpression>();
            // * Clones all the types in the union
            foreach (TypeExpression type in this.typeSet)
            {
                newIntersectionType.typeSet.Add(type.Clone(clonedTypeVariables, equivalenceClasses, methodAnalyzed));
            }
            return(newIntersectionType);
        }
コード例 #3
0
        // SSA

        #region Clone()
        /// <summary>
        /// Clones a type to be used in SSA. It must taken into account that:
        /// - In case it has no type variables, no clone is performed
        /// - WriteType variables, equivalence classes and substitutions are cloned
        /// </summary>
        /// <param name="clonedTypeVariables">WriteType variables that have been cloned.</param>
        /// <param name="equivalenceClasses">Equivalence classes of the type cloned variables. These
        /// equivalence classes need to be updated with the new cloned type variables.</param>
        /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param>
        /// <returns>The cloned type</returns>
        internal override TypeExpression Clone(IDictionary <int, TypeVariable> clonedTypeVariables, IList <EquivalenceClass> equivalenceClasses, MethodType methodAnalyzed)
        {
            if (clonedTypeVariables.ContainsKey(this.variable))
            {
                // * Already cloned
                return(clonedTypeVariables[this.variable]);
            }
            if (this.Substitution != null)
            {
                // * Lets clone it
                TypeVariable newTypeVariable = (TypeVariable)this.MemberwiseClone();
                newTypeVariable.variable = TypeVariable.NewTypeVariable.Variable;
                // * We add it to the list
                clonedTypeVariables[this.variable] = newTypeVariable;
                // * We also clone all the type variables of its class equivalence
                if (newTypeVariable.equivalenceClass != null)
                {
                    newTypeVariable.equivalenceClass.CloneTypeVariables(clonedTypeVariables, equivalenceClasses, methodAnalyzed);
                }
                newTypeVariable.BuildFullName();
                newTypeVariable.BuildTypeExpressionString(2);
                return(newTypeVariable);
            }
            if (methodAnalyzed != null)
            {
                // * A clone constraint is added to the method analyzed
                CloneConstraint constraint = new CloneConstraint(this);
                methodAnalyzed.AddConstraint(constraint);
                // * We add it to the list
                clonedTypeVariables[this.variable] = constraint.ReturnType;
                // * We also clone all the type variables of its class equivalence
                if (this.equivalenceClass != null)
                {
                    this.equivalenceClass.CloneTypeVariables(clonedTypeVariables, equivalenceClasses, methodAnalyzed);
                }
                return(constraint.ReturnType);
            }
            return(null);
        }
コード例 #4
0
        // SSA

        #region Clone()
        /// <summary>
        /// Clones a type to be used in SSA. It must taken into account that:
        /// - In case it has no type variables, no clone is performed
        /// - WriteType variables, equivalence classes and substitutions are cloned
        /// </summary>
        /// <param name="clonedTypeVariables">WriteType variables that have been cloned.</param>
        /// <param name="equivalenceClasses">Equivalence classes of the type cloned variables. These
        /// equivalence classes need to be updated with the new cloned type variables.</param>
        /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param>
        /// <returns>The cloned type</returns>
        internal virtual TypeExpression Clone(IDictionary <int, TypeVariable> clonedTypeVariables, IList <EquivalenceClass> equivalenceClasses, MethodType methodAnalyzed)
        {
            if (this.HasTypeVariables())
            {
                throw new InvalidOperationException("The type should implement a Clone method.");
            }
            // * Default implementation (types with no type variables)
            return(this);
        }
コード例 #5
0
        // Loop Detection

        // Helper Methods

        #region methodCall()

        /// <summary>
        /// This method does the type inference in a method call including unification.
        /// It requires that a) the method to be invoked has been previously analyzed with this visitor
        /// b) The formalMethod parameter is the result of the overload resolution
        /// </summary>
        /// <param name="actualImplicitObject">The actual implicit object</param>
        /// <param name="formalMethod">The formal method to be called</param>
        /// <param name="args">The ordered types of the actual parameters</param>
        /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param>
        /// <param name="activeSortOfUnification">The active sort of unification used (Equivalent is the default
        /// one and Incremental is used in the SSA bodies of the while, for and do statements)</param>
        /// <param name="fileName">File name.</param>
        /// <param name="line">Line number.</param>
        /// <param name="column">Column number.</param>
        /// <returns>The type expression of the returned value</returns>
        public static TypeExpression methodCall(TypeExpression actualImplicitObject, MethodType formalMethod, TypeExpression[] args,
                                                MethodType methodAnalyzed, SortOfUnification activeSortOfUnification, Location location)
        {
            UserType   userType     = formalMethod.MemberInfo.Class;
            MethodType actualMethod = null;
            // * We must create a new type with type variables for the object's attributes (the formal implicit object)
            IDictionary <TypeVariable, TypeVariable> typeVariableMappings = new Dictionary <TypeVariable, TypeVariable>();

            // * If the method is an instance one and the actual object is not this, we create a new implicit object to unify
            if (!formalMethod.MemberInfo.hasModifier(Modifier.Static) && actualImplicitObject != null && actualImplicitObject != methodAnalyzed.memberInfo.Class)
            {
                // * Unifies the implicit objects (actual and formal)
                UserType formalImplicitObject = (UserType)userType.CloneType(typeVariableMappings);
                if (!actualImplicitObject.Unify(formalImplicitObject, SortOfUnification.Equivalent, new List <Pair <TypeExpression, TypeExpression> >()))
                {
                    // * If the formal implicit object already has substitution (fields declararion with assignments), we override it with a union type
                    formalImplicitObject.Unify(actualImplicitObject, SortOfUnification.Override, new List <Pair <TypeExpression, TypeExpression> >());
                }
                actualImplicitObject.ValidTypeExpression = false;
            }

            // * If "this" is the actual implicit object, the return type is the original return type of the method
            TypeExpression originalReturnType = formalMethod.Return;

            if (formalMethod.HasTypeVariables() || formalMethod.Constraints.Count > 0)
            {
                // * We must also generate a method with fresh variables (formal method)
                //   when it has parameters with type variables or constraints
                formalMethod = formalMethod.CloneMethodType(typeVariableMappings);
            }

            // * If the method has type variables...
            if (formalMethod.HasTypeVariables())
            {
                // * We create the actual method:
                //   1.- The actual return type
                TypeVariable actualReturnType = TypeVariable.NewTypeVariable;
                //   2.- The actual method
                actualMethod = new MethodType(actualReturnType);
                //   3.- The actual parameters
                foreach (TypeExpression arg in args)
                {
                    actualMethod.AddParameter(arg);
                }

                // * Unifies both methods
                if (!actualMethod.Unify(formalMethod, SortOfUnification.Equivalent, new List <Pair <TypeExpression, TypeExpression> >()))
                {
                    ErrorManager.Instance.NotifyError(new UnificationError(actualMethod.FullName, location));
                    return(null);
                }
            }
            // * Otherwise, arguments promotion must be checked
            else
            {
                if (args.Length != formalMethod.ParameterListCount)
                {
                    ErrorManager.Instance.NotifyError(new ArgumentNumberError(formalMethod.FullName, args.Length, location));
                    return(null);
                }
                for (int i = 0; i < args.Length; i++)
                {
                    if (args[i].AcceptOperation(PromotionOperation.Create(formalMethod.paramList[i], methodAnalyzed, location), null) == null)
                    {
                        return(null);
                    }
                }
            }

            // * Method constraints satisfaction
            if (formalMethod.Constraints.Count > 0)
            {
                formalMethod.Constraints.Check(methodAnalyzed, actualImplicitObject, true, activeSortOfUnification, location);
            }

            // * The returned type is the the actual method if there has been a unification and
            //   in case the method is a instance method, a concrete object has been used (not this) or
            //   a different implicit object (the this reference is changed in the SSA algorithm)
            if (actualMethod != null && (formalMethod.MemberInfo.hasModifier(Modifier.Static) ||
                                         ClassType.IsConcreteType(actualImplicitObject) != null ||
                                         actualImplicitObject != formalMethod.MemberInfo.Class))
            {
                TypeVariable returnType = (TypeVariable)actualMethod.Return;
                if (returnType.Substitution != null)
                {
                    return(returnType.EquivalenceClass.Substitution);
                }
                return(returnType);
            }
            // * The original returned type if there has been no unification or the implicit object is "this"
            return(originalReturnType);
        }
コード例 #6
0
        // SSA

        #region Clone()
        /// <summary>
        /// Clones a type to be used in SSA. It must taken into account that:
        /// - In case it has no type variables, no clone is performed
        /// - WriteType variables, equivalence classes and substitutions are cloned
        /// </summary>
        /// <param name="clonedTypeVariables">WriteType variables that have been cloned.</param>
        /// <param name="equivalenceClasses">Equivalence classes of the type cloned variables. These
        /// equivalence classes need to be updated with the new cloned type variables.</param>
        /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param>
        /// <returns>The cloned type</returns>
        internal override TypeExpression Clone(IDictionary <int, TypeVariable> clonedTypeVariables, IList <EquivalenceClass> equivalenceClasses, MethodType methodAnalyzed)
        {
            // * Methods are not cloned
            return(this);
        }
コード例 #7
0
        // SSA

        #region Clone()
        /// <summary>
        /// Clones a type to be used in SSA. It must taken into account that:
        /// - In case it has no type variables, no clone is performed
        /// - WriteType variables, equivalence classes and substitutions are cloned
        /// </summary>
        /// <param name="clonedTypeVariables">WriteType variables that have been cloned.</param>
        /// <param name="equivalenceClasses">Equivalence classes of the type cloned variables. These
        /// equivalence classes need to be updated with the new cloned type variables.</param>
        /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param>
        /// <returns>The cloned type</returns>
        internal override TypeExpression Clone(IDictionary <int, TypeVariable> clonedTypeVariables, IList <EquivalenceClass> equivalenceClasses, MethodType methodAnalyzed)
        {
            if (!this.HasTypeVariables())
            {
                return(this);
            }
            ArrayType newType = (ArrayType)this.MemberwiseClone();

            newType.arrayType           = newType.arrayType.Clone(clonedTypeVariables, equivalenceClasses, methodAnalyzed);
            newType.ValidTypeExpression = false;
            return(newType);
        }
コード例 #8
0
        internal TypeExpression Clone(IDictionary <int, TypeVariable> clonedTypeVariables, IList <EquivalenceClass> equivalenceClasses, MethodType methodAnalyzed, IDictionary <String, TypeExpression> evaluated)
        {
            if (!this.HasTypeVariables())
            {
                return(this);
            }
            FieldType newFieldType = (FieldType)this.MemberwiseClone();

            if (newFieldType.fieldType is ClassType)
            {
                newFieldType.fieldType = ((ClassType)newFieldType.fieldType).Clone(clonedTypeVariables, equivalenceClasses, methodAnalyzed, evaluated);
            }
            else if (newFieldType.fieldType != null)
            {
                newFieldType.fieldType = newFieldType.fieldType.Clone(clonedTypeVariables, equivalenceClasses, methodAnalyzed);
            }
            newFieldType.ValidTypeExpression = false;
            return(newFieldType);
        }
コード例 #9
0
        // SSA

        #region CloneTypeVariables()
        /// <summary>
        /// Clones a type to be used in SSA. It must taken into account that:
        /// - In case it has no type variables, no clone is performed
        /// - WriteType variables, equivalence classes and substitutions are cloned
        /// </summary>
        /// <param name="clonedTypeVariables">WriteType variables that have been cloned.</param>
        /// <param name="equivalenceClasses">Equivalence classes of the type cloned variables. These
        /// equivalence classes need to be updated with the new cloned type variables.</param>
        /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param>
        /// <returns>The cloned type</returns>
        internal void CloneTypeVariables(IDictionary <int, TypeVariable> clonedTypeVariables, IList <EquivalenceClass> equivalenceClasses, MethodType methodAnalyzed)
        {
            // * Checks if the equivalence class has been already cloned
            if (equivalenceClasses.Contains(this))
            {
                return;
            }
            // * Adds class equivalence
            equivalenceClasses.Add(this);
            // * Clones, but not updates, the substitution
            if (this.substitution != null)
            {
                this.substitution.Clone(clonedTypeVariables, equivalenceClasses, methodAnalyzed);
            }
            // * Clones all the type variables in the equivalence class
            foreach (KeyValuePair <int, TypeVariable> pair in this.typeVariables)
            {
                pair.Value.Clone(clonedTypeVariables, equivalenceClasses, methodAnalyzed);
            }
        }