Beispiel #1
0
        // Loop Detection

        #region Remove()
        /// <summary>
        /// When loops are detected, it is necesary to suppress a new extra variable returned in
        /// the return type of recursive functions
        /// </summary>
        /// <param name="toRemove">The type variable to remove</param>
        /// <returns>If it has been actually removed</returns>
        public override bool Remove(TypeVariable toRemove)
        {
            int i;

            for (i = 0; i < this.typeSet.Count; i++)
            {
                TypeVariable typeVariable = this.typeSet[i] as TypeVariable;
                if (typeVariable != null && typeVariable.Variable == toRemove.Variable)
                {
                    this.typeSet.RemoveAt(i);
                    this.ValidTypeExpression = false;
                    break;
                }
                if (this.typeSet[i].Remove(toRemove))
                {
                    this.typeSet[i].ValidTypeExpression = false;
                    break;
                }
            }
            return(i < this.typeSet.Count);
        }
Beispiel #2
0
        // Helper Methods

        #region IsConcreteType()
        /// <summary>
        /// Tells if the parameter is a concrete class type
        /// </summary>
        /// <param name="actualImplicitObject">The object's type</param>
        /// <returns>The appropriate class type if the parameter is a concret object</returns>
        public static ClassType IsConcreteType(TypeExpression actualImplicitObject)
        {
            TypeVariable typeVariable = actualImplicitObject as TypeVariable;

            if (typeVariable != null)
            {
                actualImplicitObject = typeVariable.Substitution;
            }
            ClassType classType = actualImplicitObject as ClassType;

            if (classType != null && classType.ConcreteType)
            {
                return(classType);
            }
            UnionType unionType = actualImplicitObject as UnionType;

            if (unionType != null && unionType.Count > 0)
            {
                return(IsConcreteType(unionType.TypeSet[0]));
            }
            return(null);
        }
Beispiel #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);
        }
Beispiel #4
0
 /// <summary>
 /// Replaces type variables substituting the old type variables for the new ones.
 /// </summary>
 /// <param name="typeVariableMappings">Each new type varaiable represent a copy of another existing one.
 /// This parameter is a mapping between them, wher tmpName=old and value=new.</param>
 public override void ReplaceTypeVariables(IDictionary <TypeVariable, TypeVariable> typeVariableMappings)
 {
     if (!this.HasTypeVariables())
     {
         return;
     }
     for (int i = 0; i < this.typeSet.Count; i++)
     {
         TypeVariable typeVariable = this.typeSet[i] as TypeVariable;
         if (typeVariable == null)
         {
             if (this.typeSet[i].HasTypeVariables())
             {
                 this.typeSet[i].ReplaceTypeVariables(typeVariableMappings);
             }
         }
         else if (typeVariableMappings.ContainsKey(typeVariable))
         {
             this.typeSet[i] = typeVariableMappings[typeVariable];
         }
         this.ValidTypeExpression = false;
     }
 }
        /// <summary>
        /// Replaces the equivalence class substituting the old type variables for the new ones.
        /// The substitution is not altered.
        /// Since equivalence classes and type variables have a bidirectional association,
        /// the new equivalence classes will make type variables update their new equivalence classes.
        /// </summary>
        /// <param name="typeVariableMappings">Each new type varaiable represent a copy of another existing one.
        /// This parameter is a mapping between them, wher tmpName=old and value=new.</param>
        public void UpdateEquivalenceClass(IDictionary <TypeVariable, TypeVariable> typeVariableMappings)
        {
            // * Creates a new equivalence class
            EquivalenceClass newEquivalenceClass = new EquivalenceClass();

            // * We take the existing substitution...
            newEquivalenceClass.substitution = this.substitution;
            //   ... changing old type variables for new ones
            if (newEquivalenceClass.substitution != null)
            {
                newEquivalenceClass.substitution.ReplaceTypeVariables(typeVariableMappings);
            }
            // * We update all the appropiate type variables
            newEquivalenceClass.typeVariables = new Dictionary <int, TypeVariable>();
            foreach (KeyValuePair <int, TypeVariable> oldPair in this.typeVariables)
            {
                // * Is there a new type variable for the existing one?
                if (typeVariableMappings.ContainsKey(oldPair.Value))
                {
                    // * We create a new entry with the new one...
                    TypeVariable newTypeVariable = typeVariableMappings[oldPair.Value];
                    newEquivalenceClass.typeVariables[newTypeVariable.Variable] = newTypeVariable;
                    // * ... and updates the class equivalence of the new type variable
                    newTypeVariable.EquivalenceClass    = newEquivalenceClass;
                    newTypeVariable.ValidTypeExpression = false;
                }
                else // * Otherwise, the old one is kept
                {
                    newEquivalenceClass.typeVariables[oldPair.Key] = oldPair.Value;
                }
            }
            // * Finally, we update all the equivalence classes of the substitution if its exists
            if (newEquivalenceClass.substitution != null)
            {
                newEquivalenceClass.substitution.UpdateEquivalenceClass(typeVariableMappings, new List <TypeExpression>());
            }
        }
        /// <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
                {
                    foreach (KeyValuePair <int, TypeVariable> pair in tv.EquivalenceClass.TypeVariables)
                    {
                        if (!this.typeVariables.ContainsKey(pair.Key))
                        {
                            // * We recursively add all the element of the equivalence class
                            this.typeVariables[pair.Key] = pair.Value;
                            this.add(pair.Value, 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);
        }
        // Loop Detection

        /// <summary>
        /// When loops are detected, it is necesary to suppress a new extra variable returned in
        /// the return type of recursive functions
        /// </summary>
        /// <param name="toRemove">The type variable to remove</param>
        /// <returns>If it has been actually removed</returns>
        public bool Remove(TypeVariable toRemove)
        {
            return(this.typeVariables.Remove(toRemove.Variable));
        }
Beispiel #8
0
        // WriteType Promotion

        #region PromotionLevel()

        /// <summary>
        /// Returns a value thdat indicates a promotion level.
        /// </summary>
        /// <param name="type">WriteType to promotion.</param>
        /// <returns>Returns a promotion value.</returns>
        //public override int PromotionLevel(TypeExpression type) {
        //    int aux, less = -1;

        //    // * The same type
        //    if (this == type)
        //        return 0;
        //    // * Equivalent types
        //    if ((bool)this.AcceptOperation(new EquivalentOperation(type)))
        //        return 0;

        //    // * Field type and bounded type variable
        //    FieldType fieldType = TypeExpression.As<FieldType>(type);
        //    if (fieldType != null)
        //        return this.PromotionLevel(fieldType.FieldTypeExpression);

        //    // * WriteType variable
        //    TypeVariable typeVariable = type as TypeVariable;
        //    if (typeVariable != null) {
        //        if (typeVariable.Substitution != null)
        //            // * If the variable is bounded, the promotion is the one of its substitution
        //            return this.PromotionLevel(typeVariable.EquivalenceClass.Substitution);
        //        // * A free variable is complete promotion
        //        return 0;
        //    }

        //    // * Inheritance
        //    if (this.BaseClass == null)
        //        // * Object only promotes to object
        //        return -1;
        //    if ((bool)this.baseClass.AcceptOperation(new EquivalentOperation(type)))
        //        return 1;
        //    else {
        //        aux = this.baseClass.PromotionLevel(type);
        //        if (aux != -1)
        //            return aux + 1;
        //    }

        //    // * Interfaces
        //    if (this.interfaceList.Count != 0) {
        //        for (int i = 0; i < this.interfaceList.Count; i++) {
        //            if ((bool)this.interfaceList[i].AcceptOperation( new EquivalentOperation(type))) {
        //                if ((less > 1) || (less == -1))
        //                    less = 1;
        //            }
        //            else {
        //                aux = this.interfaceList[i].PromotionLevel(type);
        //                if (aux != -1) {
        //                    if ((less > (aux + 1)) || (less == -1))
        //                        less = aux + 1;
        //                }
        //            }
        //        }
        //    }
        //    if (less != -1)
        //        return less;

        //    // * Union type
        //    UnionType unionType = TypeExpression.As<UnionType>(type);
        //    if (unionType != null)
        //        return unionType.SuperType(this);

        //    // * No promotion
        //    return -1;
        //}

        #endregion

        // WriteType Unification

        #region Unify
        /// <summary>
        /// This method unifies two type expressions (this and te)
        /// </summary>
        /// <param name="te">The expression to be unfied with this</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 unification was successful</returns>
        public override bool Unify(TypeExpression te, SortOfUnification unification, IList <Pair <TypeExpression, TypeExpression> > previouslyUnified)
        {
            // * Infinite recursion detection
            Pair <TypeExpression, TypeExpression> pair = new Pair <TypeExpression, TypeExpression>(this, te);

            if (previouslyUnified.Contains(pair))
            {
                return(true);
            }
            previouslyUnified.Add(pair);

            ClassType ct      = te as ClassType;
            bool      success = true;

            // * Class WriteType
            if (ct != null)
            {
                // * Inheritance is taken into account
                if ((int)ct.AcceptOperation(new PromotionLevelOperation(this), null) == -1)
                {
                    return(false);
                }
                // * Walk upward in the tree till find the correct class
                while (!(bool)ct.AcceptOperation(new EquivalentOperation(this), null))
                {
                    ct = ct.baseClass;
                }
                // * Now we unify the fields
                foreach (string key in this.Fields.Keys)
                {
                    FieldType thisField = (FieldType)this.Fields[key].Type,
                                teField = (FieldType)ct.Fields[key].Type;
                    if (thisField.FieldTypeExpression is ClassTypeProxy || teField.FieldTypeExpression is ClassTypeProxy)
                    {
                        success = thisField.FieldTypeExpression.FullName.Equals(teField.FieldTypeExpression.FullName);
                    }
                    else if (!(thisField.Unify(teField, unification, previouslyUnified)))
                    {
                        success = false;
                    }
                    if (!success)
                    {
                        break;
                    }
                }
                if (success && this.baseClass != null)
                {
                    // * The same with the base class
                    this.baseClass.Unify(ct.baseClass, unification, previouslyUnified);
                }
                // * If one of the classes is a concrete type, so it is the other
                if (success)
                {
                    this.ConcreteType = ct.ConcreteType = this.ConcreteType || ct.ConcreteType;
                }
            }
            // * WriteType variable
            else if (te is TypeVariable)
            {
                TypeVariable typeVariable = (TypeVariable)te;
                if (unification != SortOfUnification.Incremental)
                {
                    // * Incremental is commutative
                    success = typeVariable.Unify(this, unification, previouslyUnified);
                }
                // * Incremental unification (not commutative)
                else if (typeVariable.Substitution != null)
                {
                    // * Class(var) should unify to Var=Class(int)
                    success = this.Unify(typeVariable.Substitution, unification, previouslyUnified);
                }
                else
                {
                    success = false;
                }
            }
            // * Union WriteType
            else if (te is UnionType)
            {
                success = te.Unify(this, unification, previouslyUnified);
            }
            // * Class WriteType Proxy
            else if (te is ClassTypeProxy)
            {
                success = this.Unify(((ClassTypeProxy)te).RealType, unification, previouslyUnified);
            }
            else if (te is FieldType)
            {
                success = this.Unify(((FieldType)te).FieldTypeExpression, unification, previouslyUnified);
            }
            else
            {
                success = false;
            }
            // * Clears the type expression cache
            this.ValidTypeExpression = false;
            te.ValidTypeExpression   = false;
            return(success);
        }
Beispiel #9
0
        // Loop Detection

        #region Remove()
        /// <summary>
        /// When loops are detected, it is necesary to suppress a new extra variable returned in
        /// the return type of recursive functions
        /// </summary>
        /// <param name="toRemove">The type variable to remove</param>
        /// <returns>If it has been actually removed</returns>
        public virtual bool Remove(TypeVariable toRemove)
        {
            return(false);
        }
Beispiel #10
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);
        }