/// <summary> /// Returns true if the union type contains the specified value type. /// </summary> /// <param name="type">WriteType expression to search.</param> /// <returns>True if the union type contains the specified type expression. Otherwise, false.</returns> public bool ContainsValueType(TypeExpression type) { for (int i = 0; i < this.typeSet.Count; i++) { if (this.typeSet[i].IsValueType()) { if (this.typeSet[i] == type) { return(true); } } } return(false); }
///// <summary> ///// Check if the type can make an assignment operation. ///// </summary> ///// <param name="operand">WriteType expression of the operand of binary expression.</param> ///// <param name="op">Operator.</param> ///// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param> ///// <param name="unification">Indicates if the kind of unification (equivalent, incremental or override).</param> ///// <param name="actualImplicitObject">Only suitable when the assignment is executed as a constraint of a method call. In that case, ///// this parameter represents the actual object used to pass the message; null otherwise.</param> ///// <param name="fileName">File name.</param> ///// <param name="line">Line number.</param> ///// <param name="column">Column number.</param> ///// <returns>WriteType obtained with the operation.</returns> //public override TypeExpression Assignment(TypeExpression operand, AssignmentOperator op, MethodType methodAnalyzed, SortOfUnification unification, // TypeExpression actualImplicitObject, Location location) { // if (op == AssignmentOperator.Assign) { // if (operand.Promotion(this, op, methodAnalyzed, location) == null) // return null; // if (!this.HasTypeVariables()) // return this; // // * If the left expression of the assignment has type variables, // // we must return the concrete type (not the abstract one) // // * Then whe unify the concrete types // FieldType fieldType = TypeExpression.As<FieldType>(operand); // if (fieldType != null) // operand = fieldType.FieldTypeExpression; // if (this.Unify(operand, unification, new List<Pair<TypeExpression, TypeExpression>>())) { // this.ValidTypeExpression = false; // return this; // } // } // ErrorManager.Instance.NotifyError(new OperationNotAllowedError(op.ToString(), this.FullName, operand.FullName, location)); // return null; //} #endregion #region Dot() ANULADA ///// <summary> ///// Check if the type can make an operation of field access. ///// Generates an error if the attribute does not exist. ///// Generates a constraint in case it is applied to a free variable. ///// </summary> ///// <param name="field">Field to access.</param> ///// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param> ///// <param name="previousDot">To detect infinite loops. The types that have been previously passed the dot message. Used for union types.</param> ///// <param name="fileName">File name.</param> ///// <param name="line">Line number.</param> ///// <param name="column">Column number.</param> ///// <returns>WriteType obtained with the operation.</returns> //public override TypeExpression Dot(string memberName, MethodType methodAnalyzed, IList<TypeExpression> previousDot, Location loc) { // TypeExpression member = this.Dot(memberName, previousDot); // if (member == null) { // ErrorManager.Instance.NotifyError(new UnknownMemberError(memberName, loc)); // return null; // } // if (!validAccess(member)) { // ErrorManager.Instance.NotifyError(new ProtectionLevelError(memberName, loc)); // return null; // } // return member; //} ///// <summary> ///// Tries to find a attribute. ///// No error is generated if the attribute does not exist. ///// It does not generate a constraint in case it is applied to a free variable. ///// </summary> ///// <param name="memberName">Member to access.</param> ///// <param name="previousDot">To detect infinite loops. The types that have been previously passed the dot message. Used for union types.</param> ///// <returns>WriteType obtained with the operation.</returns> //public override TypeExpression Dot(string memberName, IList<TypeExpression> previousDot) { // if (this.Members.ContainsKey(memberName)) // return this.Members[memberName].WriteType; // if (this.baseClass != null) // Search in inherit class // return this.baseClass.Dot(memberName, previousDot); // return null; //} /// <summary> /// Validates the correct access to members, taking into account the information hiding level. /// </summary> /// <param name="member">The type of the member</param> /// <returns>If the access has been correct</returns> public bool validAccess(TypeExpression member) { // * Union or Intersection type IList <TypeExpression> typeSet = null; UnionType unionType = member as UnionType; if (member is UnionType) { typeSet = ((UnionType)member).TypeSet; } else if (member is IntersectionType) { typeSet = ((IntersectionType)member).TypeSet; } if (typeSet != null) { bool anyValid = false; foreach (TypeExpression type in typeSet) { if (!this.validAccess(type) && !member.IsDynamic) { return(false); } else { anyValid = true; } return(anyValid); } } // * Member type IMemberType memberType = member as IMemberType; if (memberType == null || memberType.MemberInfo == null) { return(false); } // * Public or Internal if (memberType.MemberInfo.hasModifier(Modifier.Public) || memberType.MemberInfo.hasModifier(Modifier.Internal)) { return(true); } // * Private if (memberType.MemberInfo.hasModifier(Modifier.Private)) { return((bool)this.AcceptOperation(new EquivalentOperation(memberType.MemberInfo.Class), null)); } // * Protected return((bool)this.AcceptOperation(new EquivalentOperation(memberType.MemberInfo.Class), null) || this.InheritsFrom(memberType.MemberInfo.Class)); }
// WriteType Promotion #region Promotion() /// <summary> /// Requires the implicit object to be a subtype of the type parameter /// </summary> /// <param name="type">WriteType to promotion.</param> /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param> /// <param name="op">An optional operator to report error messages.</param> /// <param name="fileName">File name.</param> /// <param name="line">Line number.</param> /// <param name="column">Column number.</param> /// <returns>The supertype; null if there has been some error.</returns> //public override TypeExpression Promotion(TypeExpression type, MethodType methodAnalyzed, Location loc) { // return this.Promotion(type, AssignmentOperator.Assign, methodAnalyzed, loc); //} //public override TypeExpression Promotion(TypeExpression type, Enum op, MethodType methodAnalyzed, Location loc) { // return this.InternalPromotion(type, op, methodAnalyzed, loc); //} //private TypeExpression InternalPromotion(TypeExpression superType, Enum op, MethodType methodAnalyzed, Location loc) { // if (this.IsFreshVariable() && methodAnalyzed != null) { // // * A constraint is added to the method analyzed // PromotionConstraint constraint = new PromotionConstraint(this, superType, op, loc); // methodAnalyzed.AddConstraint(constraint); // return superType; // } // // * Static Behaviour: All the types in typeset must promote // // * Dynamic Behaviour: One of the types in typeset must promote // int aux = 0; // UnionType dynamicUnionType = new UnionType(); // dynamicUnionType.isDynamic = true; // foreach (TypeExpression subType in this.typeSet) { // if (this.IsDynamic) { // // * Dynamic // if (subType.IsFreshVariable()) // dynamicUnionType.AddType(subType); // else { // aux = (int) subType.AcceptOperation(new PromotionLevelOperation(superType)); // if (aux != -1) // return superType; // } // } // if (!this.IsDynamic) { // // * Static // aux = (int)subType.AcceptOperation(new PromotionLevelOperation(superType)); // if (aux == -1) { // ErrorManager.Instance.NotifyError(new TypePromotionError(this.FullName, superType.FullName, op.ToString(), loc)); // return null; // } // } // } // if (dynamicUnionType.Count != 0) { // // * If the union type is dynamic and no type in the type set promotes, then we generate a constraint with one promotion grouping the fresh types in the type set // PromotionConstraint constraint = new PromotionConstraint(dynamicUnionType, superType, op, loc); // methodAnalyzed.AddConstraint(constraint); // return superType; // } // if (this.IsDynamic && aux == -1) { // // * No promotion at all // ErrorManager.Instance.NotifyError(new TypePromotionError(this.FullName, superType.FullName, op.ToString(), loc)); // return null; // } // return superType; //} #endregion #region SuperType() /// <summary> /// The opposite of the promotion method. Indicates if the parameter /// promotes to the implicit object /// T1 <= T1\/T2 /// T2 <= T1\/T2 /// </summary> /// <param name="type">WriteType to promotion.</param> /// <returns>Returns a promotion value.</returns> public int SuperType(TypeExpression subType) { // * Takes the lower promotion level (except -1) int lowerLevelOfPromotion = Int32.MaxValue; foreach (TypeExpression superType in this.typeSet) { int aux = (int)subType.AcceptOperation(new PromotionLevelOperation(superType), null); if (aux != -1 && aux < lowerLevelOfPromotion) { lowerLevelOfPromotion = aux; } } return(lowerLevelOfPromotion == Int32.MaxValue ? -1 : lowerLevelOfPromotion); }
// WriteType Promotion #region PromotionLevel() ANULADA ///// <summary> ///// Returns a value that indicates a promotion level. ///// </summary> ///// <param name="type">WriteType to promotion.</param> ///// <returns>Returns a promotion value.</returns> //public override int PromotionLevel(TypeExpression type) { // // * Bool type and type variable // if (TypeExpression.As<BoolType>(type)!=null) // return 0; // // * WriteType variable // TypeVariable typeVariable = type as TypeVariable; // if (typeVariable != null && typeVariable.Substitution==null) // // * A free variable is complete promotion // return 0; // // * Union type // UnionType unionType = TypeExpression.As<UnionType>(type); // if (unionType != null) // return unionType.SuperType(this); // // * Field type and bounded type variable // FieldType fieldType = TypeExpression.As<FieldType>(type); // if (fieldType != null) // return this.PromotionLevel(fieldType.FieldTypeExpression); // // * Use the BCL object oriented approach // return this.BCLType.PromotionLevel(type); //} #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) { BoolType bt = te as BoolType; if (bt != null) { return(true); } if (te is TypeVariable && unification != SortOfUnification.Incremental) { // * No incremental unification is commutative return(te.Unify(this, unification, previouslyUnified)); } return(false); }
/// <summary> /// Adds a type variable to the object's equivalence class /// </summary> /// <param name="typeExpression">The type variable to add</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 type variable has been actually added</returns> /// EN esta clase se le ha cambiado su visibilidad internal bool addToMyEquivalenceClass(TypeExpression typeExpression, SortOfUnification unification, IList <Pair <TypeExpression, TypeExpression> > previouslyUnified) { // * It the type variable does not have a equivalence class, we create it if (this.equivalenceClass == null) { this.equivalenceClass = new EquivalenceClass(this); } bool added = this.equivalenceClass.add(typeExpression, unification, previouslyUnified); this.ValidTypeExpression = false; if (typeExpression is TypeVariable) { typeExpression.ValidTypeExpression = false; } return(added); }
// 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); bool success = false; ArrayType at = te as ArrayType; if (at != null) { success = this.arrayType.Unify(at.arrayType, unification, previouslyUnified); } else if (te is TypeVariable) { TypeVariable typeVariable = (TypeVariable)te; if (unification != SortOfUnification.Incremental) { // * Incremental is commutative success = typeVariable.Unify(this, unification, previouslyUnified); } else // * Array(var) should unify to Var=Array(int) { if (typeVariable.Substitution != null) { success = this.Unify(typeVariable.Substitution, unification, previouslyUnified); } else { success = false; } } } else if (te is UnionType) { success = te.Unify(this, unification, previouslyUnified); } // * Clears the type expression cache this.ValidTypeExpression = false; te.ValidTypeExpression = false; return(success); }
/// <summary> /// Check if the type can make a method operation. /// </summary> /// <param name="actualImplicitObject">The actual implicit object employed to pass the message</param> /// <param name="arguments">Arguments of the method.</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>WriteType obtained with the operation.</returns> //public override TypeExpression Parenthesis(TypeExpression actualImplicitObject, TypeExpression[] arguments, MethodType methodAnalyzed, // SortOfUnification activeSortOfUnification, Location loc) { // TypeExpression method = overloadResolution(arguments, loc); // if (method == null) // return null; // return method.Parenthesis(actualImplicitObject, arguments, methodAnalyzed, activeSortOfUnification, loc); //} #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); // * Clears the type expression cache this.ValidTypeExpression = false; te.ValidTypeExpression = false; // TODO return(false); }
/// <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) { TypeVariable fieldTypeVariable = this.fieldType as TypeVariable; if (fieldTypeVariable == null) { if (this.fieldType.HasTypeVariables()) { this.fieldType.ReplaceTypeVariables(typeVariableMappings); } return; } if (typeVariableMappings.ContainsKey(fieldTypeVariable)) { this.fieldType = typeVariableMappings[fieldTypeVariable]; } this.ValidTypeExpression = false; }
/// <summary> /// Method that clones each type variable of a type expression. /// Equivalence classes are not cloned (but included in the equivalenceClasses parameter. /// The default implementation is do nothing (for built-in types). /// </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. /// If the variable to be cloned already has a map, we return the latter.</param> /// <param name="equivalenceClasses">Each equivalence class of all the type variables.</param> /// <param name="clonedClasses">This parameter collects the set of all cloned classes. It is used to detect infinite recursion.</param> /// <returns>The new type expression (itself by default)</returns> public override TypeExpression CloneTypeVariables(IDictionary <TypeVariable, TypeVariable> typeVariableMappings, IList <EquivalenceClass> equivalenceClasses, IList <ClassType> clonedClasses) { // * If the variable to be cloned already has a map, we return the latter if (typeVariableMappings.ContainsKey(this)) { return(typeVariableMappings[this]); } TypeVariable newOne = TypeVariable.NewTypeVariable; newOne.IsDynamic = this.IsDynamic; // * Sets the mapping between the old and new one in the typeVariableMappings parameter typeVariableMappings[this] = newOne; EquivalenceClass clonedEquivalenceClass = null; if (this.EquivalenceClass != null) { clonedEquivalenceClass = new EquivalenceClass(); foreach (var typeVariable in this.EquivalenceClass.TypeVariables) { TypeExpression clonedTypeVariable = typeVariable.Value.CloneType(typeVariableMappings); clonedEquivalenceClass.add(clonedTypeVariable, SortOfUnification.Equivalent, new List <Pair <TypeExpression, TypeExpression> >()); } } // * Add both equivalence classes to the equivalenceClasses parameter if (clonedEquivalenceClass != null && !equivalenceClasses.Contains(clonedEquivalenceClass)) { equivalenceClasses.Add(clonedEquivalenceClass); } // * Assigns a clone of the substitution when it previously exists if (this.Substitution != null) { TypeExpression clonedSubstitution = this.Substitution.CloneTypeVariables(typeVariableMappings, equivalenceClasses, clonedClasses); newOne.addToMyEquivalenceClass(clonedSubstitution, SortOfUnification.Equivalent, new List <Pair <TypeExpression, TypeExpression> >()); } else if (clonedEquivalenceClass != null) { newOne.equivalenceClass = clonedEquivalenceClass; } newOne.ValidTypeExpression = false; // * Returns the new type variable return(newOne); }
/// <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) { InterfaceType it = TypeExpression.As <InterfaceType>(te); if (it != null) { bool success = (bool)this.AcceptOperation(new EquivalentOperation(it), null); // * Clears the type expression cache this.ValidTypeExpression = false; te.ValidTypeExpression = false; return(success); } if (te is TypeVariable && unification != SortOfUnification.Incremental) { // * No incremental unification is commutative return(te.Unify(this, unification, previouslyUnified)); } return(false); }
// 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) { DoubleType dt = te as DoubleType; if (dt != null) { return(true); } if (te is TypeVariable && unification != SortOfUnification.Incremental) { // * No incremental unification is commutative return(te.Unify(this, unification, previouslyUnified)); } if (te is FieldType && unification == SortOfUnification.Equivalent) { return(((FieldType)te).FieldTypeExpression.Unify(this, unification, previouslyUnified)); } return(false); }
// 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); }
///// <summary> ///// Check if the type can make an operation of field access. ///// Generates an error if the attribute does not exist. ///// Generates a constraint in case it is applied to a free variable. ///// </summary> ///// <param name="field">Field to access.</param> ///// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param> ///// <param name="previousDot">To detect infinite loops. The types that have been previously passed the dot message. Used for union types.</param> ///// <param name="fileName">File name.</param> ///// <param name="line">Line number.</param> ///// <param name="column">Column number.</param> ///// <returns>WriteType obtained with the operation.</returns> //public override TypeExpression Dot(string field, MethodType methodAnalyzed, IList<TypeExpression> previousDot, Location loc) { // if (this.fieldType != null) { // // * If the field type is a dynamic union type, so it is the union // UnionType unionType = As<UnionType>(this.fieldType); // if (unionType != null) // DynVarOptions.Instance.AssignDynamism(this.fieldType, this.IsDynamic); // return this.fieldType.Dot(field, methodAnalyzed, previousDot, loc); // } // return null; //} ///// <summary> ///// Tries to find a attribute. ///// No error is generated if the attribute does not exist. ///// It does not generate a constraint in case it is applied to a free variable. ///// </summary> ///// <param name="memberName">Member to access.</param> ///// <param name="previousDot">To detect infinite loops. The types that have been previously passed the dot message. Used for union types.</param> ///// <returns>WriteType obtained with the operation.</returns> //public override TypeExpression Dot(string memberName, IList<TypeExpression> previousDot) { // if (this.fieldType != null) // return this.fieldType.Dot(memberName, previousDot); // return null; //} #endregion //#region Bracket() anulada ///// <summary> ///// Check if the type can make an array operation. ///// </summary> ///// <param name="index">TypeExpression of the index.</param> ///// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param> ///// <param name="showErrorMessage">Indicates if an error message should be shown (used for dynamic types)</param> ///// <param name="fileName">File name.</param> ///// <param name="line">Line number.</param> ///// <param name="column">Column number.</param> ///// <returns>WriteType obtained with the operation.</returns> //public override TypeExpression Bracket(TypeExpression index, MethodType methodAnalyzed, bool showErrorMessage, Location loc) { // if (this.fieldType != null) // return this.fieldType.Bracket(index, methodAnalyzed, showErrorMessage, loc); // return null; //} //#endregion #region Assignment() ANULADA /// <summary> /// Check if the type can make an assignment operation. /// </summary> /// <param name="operand">WriteType expression of the operand of binary expression.</param> /// <param name="op">Operator.</param> /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param> /// <param name="unification">Indicates if the kind of unification (equivalent, incremental or override).</param> /// <param name="actualImplicitObject">Only suitable when the assignment is executed as a constraint of a method call. In that case, /// this parameter represents the actual object used to pass the message; null otherwise.</param> /// <param name="location"> Location of the element</param> /// <returns>WriteType obtained with the operation.</returns> //public override TypeExpression Assignment(TypeExpression operand, AssignmentOperator op, MethodType methodAnalyzed, SortOfUnification unification, // TypeExpression actualImplicitObject, Location location) { // // * We check if a constraint must be generated. Is it an assignment of the implicit object's field? // bool found = false; // // * In case it has free variables and the reference used is this, we add a constraint to the method // if (this.HasTypeVariables() && methodAnalyzed != null && ClassType.IsConcreteType(actualImplicitObject) == null) { // // * They should be the same exact (sub)classes. This represent the same instance, not another instance of the same class. // ClassType methodSuperClass = (ClassType)methodAnalyzed.MemberInfo.Class; // while (!(found = (this.MemberInfo.Class == methodSuperClass)) && methodSuperClass != null) // methodSuperClass = methodSuperClass.BaseClass; // if (found) { // // * An assignment constraint is added, postponing the type inference // // * If an actual implicit object is used, we take its field's type // FieldType fieldType = this; // ClassType thisType = TypeExpression.As<ClassType>(actualImplicitObject); // if (thisType == null) { // FieldType field = TypeExpression.As<FieldType>(actualImplicitObject); // if (field != null) // thisType = TypeExpression.As<ClassType>(field.FieldTypeExpression); // } // if (thisType != null) // fieldType = (FieldType)thisType.Fields[this.MemberInfo.MemberIdentifier].WriteType; // methodAnalyzed.AddConstraint(new FieldTypeAssignmentConstraint(fieldType, operand, unification)); // methodAnalyzed.ValidTypeExpression = false; // return this.fieldType; // } // } // if (!found && this.fieldType != null) // return this.fieldType.Assignment(operand, op, null, unification, actualImplicitObject, location); // return null; //} #endregion #region Arithmetic() >NUL>C> /* * /// <summary> * /// Check if the type can make an arithmetic operation. * /// </summary> * /// <param name="operand">WriteType expression of the operand of binary expression.</param> * /// <param name="op">Operator.</param> * /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param> * /// <param name="showErrorMessage">Indicates if an error message should be shown (used for dynamic types)</param> * /// <param name="fileName">File name.</param> * /// <param name="line">Line number.</param> * /// <param name="column">Column number.</param> * /// <returns>WriteType obtained with the operation.</returns> * public override TypeExpression Arithmetic(TypeExpression operand, Enum op, MethodType methodAnalyzed, bool showErrorMessage, Location loc) { * if (this.fieldType != null) * return this.fieldType.Arithmetic(operand, op, methodAnalyzed, showErrorMessage, loc); * return null; * } * * /// <summary> * /// Check if the type can make an arithmetic operation. * /// </summary> * /// <param name="op">Operator.</param> * /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param> * /// <param name="showErrorMessage">Indicates if an error message should be shown (used for dynamic types)</param> * /// <param name="fileName">File name.</param> * /// <param name="line">Line number.</param> * /// <param name="column">Column number.</param> * /// <returns>WriteType obtained with the operation.</returns> * public override TypeExpression Arithmetic(UnaryOperator op, MethodType methodAnalyzed, bool showErrorMessage, Location loc) { * return this.fieldType.Arithmetic(op, methodAnalyzed, showErrorMessage, loc); * } */ #endregion #region Relational()ANULADA /* /// <summary> * /// Check if the type can make an relational operation. * /// </summary> * /// <param name="operand">WriteType expression of the operand of binary expression.</param> * /// <param name="op">Operator.</param> * /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param> * /// <param name="showErrorMessage">Indicates if an error message should be shown (used for dynamic types)</param> * /// <param name="fileName">File name.</param> * /// <param name="line">Line number.</param> * /// <param name="column">Column number.</param> * /// <returns>WriteType obtained with the operation.</returns> * public override TypeExpression Relational(TypeExpression operand, RelationalOperator op, MethodType methodAnalyzed, bool showErrorMessage, Location loc) { * if (this.fieldType != null) * return this.fieldType.Relational(operand, op, methodAnalyzed, showErrorMessage, loc); * return null; * } * */ #endregion #region PromotionLevl()--># /// <summary> /// Returns a value that indicates a promotion level. /// </summary> /// <param name="type">WriteType to promotion.</param> /// <returns>Returns a promotion value.</returns> //public override int PromotionLevel(TypeExpression type) { // if (this.fieldType != null) // return this.fieldType.PromotionLevel(type); // return -1; //} /// <summary> #endregion #region Promotion ANULADA /// Requires the implicit object to be a subtype of the type parameter /// </summary> /// <param name="type">WriteType to promotion.</param> /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param> /// <param name="op">An optional operator to report error messages.</param> /// <param name="fileName">File name.</param> /// <param name="line">Line number.</param> /// <param name="column">Column number.</param> ///// <returns>The supertype; null if there has been some error.</returns> //public override TypeExpression Promotion(TypeExpression type, Enum op, MethodType methodAnalyzed, Location loc) { // if (this.fieldType != null) // return this.fieldType.Promotion(type, op, methodAnalyzed, loc); // return null; //} #endregion #region Cast() ANULADA /// <summary> /// Tells if the type can be cast to the casttype /// </summary> /// <param name="castType">The expected type</param> /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param> /// <param name="fileName">File name.</param> /// <param name="line">Line number.</param> /// <param name="column">Column number.</param> ///// <returns>The returned type expression</returns> //public override TypeExpression Cast(TypeExpression castType, MethodType methodAnalyzed, Location loc) { // if (this.fieldType != null) // return this.fieldType.Cast(castType, methodAnalyzed, loc); // return null; //} #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) { FieldType ft = te as FieldType; if (ft != null) { bool success = this.fieldType.Unify(ft.fieldType, unification, previouslyUnified); if (success) // * Dynamic type { DynVarOptions.Instance.AssignDynamism(this, ft.isDynamic); } // * Clears the type expression cache this.ValidTypeExpression = false; te.ValidTypeExpression = false; return(success); } if (te is TypeVariable && unification != SortOfUnification.Incremental) { // * No incremental unification is commutative return(te.Unify(this, unification, previouslyUnified)); } return(false); }
// 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); // * First checks that all the expression are equivalent. Otherwise substitutions could be // partially applied to type variables that should finally not be unified bool equivalent = true; foreach (TypeExpression type in this.typeSet) { if (!(equivalent = (bool)type.AcceptOperation(new EquivalentOperation(te), null))) { break; } } if (!equivalent) { return(false); } // * Lets unify, incrementing type variables with union types foreach (TypeExpression type in this.typeSet) { // * Unification of union types is incremental te.Unify(type, SortOfUnification.Incremental, previouslyUnified); } // * Clears the type expression cache this.ValidTypeExpression = false; te.ValidTypeExpression = false; return(true); }
/// <summary> /// Returns true if the union type contains method types and this methods returns differents types. (At least, one valut type). /// </summary> /// <returns>True if the union type contains method types and this methods returns differents types. Otherwise, false.</returns> public bool ContainsDifferentReturns() { TypeExpression current = null; TypeExpression aux = null; for (int i = 0; i < this.typeSet.Count; i++) { if (this.typeSet[i] is TypeVariable) { return(true); } MethodType mt = null; if ((mt = TypeExpression.As <MethodType>(this.typeSet[i])) != null) { current = mt.Return; if (aux != null && aux != current) // This comparation searches differents value types. { return(true); } aux = current; } } return(false); }
/// <summary> /// Adds a new type expression. /// </summary> /// <param name="type">WriteType expression to add.</param> /// <returns>If the type has been added</returns> public bool AddType(TypeExpression type) { bool added = true; UnionType union = type as UnionType; if (union != null) { foreach (TypeExpression t in union.typeSet) { added = this.AddType(t) && added; } this.ValidTypeExpression = false; return(added); } TypeExpression existingType = typeSet.Find(type.Equals); if (existingType == null) { this.typeSet.Add(type); this.ValidTypeExpression = false; return(true); } return(false); }
// 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); }
// 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); }
/// <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) { return(false); }
/// <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); }
/// <summary> ///// Check if the type can make an assignment operation. ///// </summary> ///// <param name="operand">WriteType expression of the operand of binary expression.</param> ///// <param name="op">Operator.</param> ///// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param> ///// <param name="unification">Indicates if the kind of unification (equivalent, incremental or override).</param> ///// <param name="actualImplicitObject">Only suitable when the assignment is executed as a constraint of a method call. In that case, ///// this parameter represents the actual object used to pass the message; null otherwise.</param> ///// <param name="fileName">File name.</param> ///// <param name="line">Line number.</param> ///// <param name="column">Column number.</param> ///// <returns>WriteType obtained with the operation.</returns> //public override TypeExpression Assignment(TypeExpression operand, AssignmentOperator op, MethodType methodAnalyzed, SortOfUnification unification, // TypeExpression actualImplicitObject, Location location) { // if (op == AssignmentOperator.Assign) // return operand; // else // ErrorManager.Instance.NotifyError(new AssignmentError(operand.FullName, this.FullName, location)); // return null; //} #endregion #region Arithmetic() ANULADA /* * /// <summary> * /// Check if the type can make an arithmetic operation. * /// </summary> * /// <param name="operand">WriteType expression of the operand of binary expression.</param> * /// <param name="op">Operator.</param> * /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param> * /// <param name="showErrorMessage">Indicates if an error message should be shown (used for dynamic types)</param> * /// <param name="fileName">File name.</param> * /// <param name="line">Line number.</param> * /// <param name="column">Column number.</param> * /// <returns>WriteType obtained with the operation.</returns> * public override TypeExpression Arithmetic(TypeExpression operand, Enum op, MethodType methodAnalyzed, bool showErrorMessage, Location loc) { * if (op.Equals(ArithmeticOperator.Plus) && operand.Equivalent(StringType.Instance)) * return StringType.Instance; * if (showErrorMessage) * ErrorManager.Instance.NotifyError(new TypePromotionError(operand.FullName, this.FullName, op.ToString(), loc)); * return null; * } */ #endregion // WriteType Promotion #region PromotionLevel() ANULADA /// <summary> /// Returns a value that indicates a promotion level. /// </summary> /// <param name="type">WriteType to promotion.</param> /// <returns>Returns a promotion value.</returns> //public override int PromotionLevel(TypeExpression type) { // // * Built-in types: no promotion, except string // if (type is BoolType || type is CharType || type is DoubleType || type is IntType || type is VoidType) // return -1; // // * BCL Value Types (structs): No promotion // BCLClassType bclClass = TypeExpression.As<BCLClassType>(type); // if (bclClass != null) { // if (bclClass.TypeInfo.IsValueType) // return -1; // // * Correct promotion to classes that are not value types // return 0; // } // // * 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; // } // // * Union type // UnionType unionType = TypeExpression.As<UnionType>(type); // if (unionType != null) // return unionType.SuperType(this); // // * Field type and bounded type variable // FieldType fieldType = TypeExpression.As<FieldType>(type); // if (fieldType != null) // return this.PromotionLevel(fieldType.FieldTypeExpression); // // * Correct Promotion // return 0; //} #endregion // WriteType Unification #region Unify /// <summary> /// This method unifies two type expressions (this and te) /// </summary> /// <param name="unification">Indicates if the kind of unification (equivalent, incremental or override).</param> /// <param name="te">The expression to be unfied with this</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) { throw new NotImplementedException("NullType.Unify() Not implemented"); }
/// <summary> /// Constructor of Intersection /// </summary> public IntersectionMemberType(TypeExpression te) : base(te) { }
/// <summary> /// Used to not repeat methods in overload /// </summary> /// <param name="typeExpression">The other type expression</param> /// <returns>If both represent the same type</returns> public virtual bool EqualsForOverload(TypeExpression typeExpression) { return((bool)this.AcceptOperation(new EqualsForOverloadOperation(typeExpression), null)); }
/// <summary> /// Tells if a type expression is a type or a type variable /// unified to a type /// </summary> /// <typeparam name="T">A concrete type expression</typeparam> /// <param name="type">The general type expression</param> /// <returns>If the type is the expected one</returns> public static bool Is <T>(TypeExpression type) where T : TypeExpression { return(TypeExpression.As <T>(type) != null); }
// WriteType Promotion #region PromotionLevel() ANULADA //public virtual int PromotionLevel(TypeExpression type) { // return -1; //} #endregion #region Promotion() ANULADA /// <summary> /// Requires the implicit object to be a subtype of the type parameter /// </summary> /// <param name="type">WriteType to promotion.</param> /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param> /// <param name="op">An optional operator to report error messages.</param> /// <param name="fileName">File name.</param> /// <param name="line">Line number.</param> /// <param name="column">Column number.</param> /// <returns>The supertype; null if there has been some error.</returns> //public virtual TypeExpression Promotion(TypeExpression type, MethodType methodAnalyzed, Location location) { // if ((int) this.AcceptOperation(new PromotionLevelOperation(type)) == -1) { // ErrorManager.Instance.NotifyError(new TypePromotionError(this.FullName, type.FullName, location)); // return null; // } // return type; //} //public virtual TypeExpression Promotion(TypeExpression type, Enum op, MethodType methodAnalyzed, Location location) { // if ((int)this.AcceptOperation( new PromotionLevelOperation(type)) == -1) { // ErrorManager.Instance.NotifyError(new TypePromotionError(this.FullName, type.FullName, op.ToString(), location)); // return null; // } // return type; //} #endregion #region Cast() ANULADA /// <summary> /// Tells if the type can be cast to the casttype /// </summary> /// <param name="castType">The expected type</param> /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param> /// <param name="fileName">File name.</param> /// <param name="line">Line number.</param> /// <param name="column">Column number.</param> /// <returns>The returned type expression</returns> //public virtual TypeExpression Cast(TypeExpression castType, MethodType methodAnalyzed, Location loc) { // if (castType == null) // return null; // if (((int)castType.AcceptOperation(new PromotionLevelOperation(this)) != -1) || ((int)this.AcceptOperation(new PromotionLevelOperation(castType)) != -1)) // return castType; // ErrorManager.Instance.NotifyError(new TypeCastError(this.FullName, castType.FullName, loc)); // return null; //} #endregion #region EqualsForOverload() ANULADA /// <summary> /// Used to not repeat methods in overload /// </summary> /// <param name="typeExpression">The other type expression</param> /// <returns>If both represent the same type</returns> //public virtual bool EqualsForOverload(object typeExpression) { // // * By default, we use the equals comparison // return this.Equals(typeExpression); //} #endregion // WriteType Unification #region Unify() /// <summary> /// Tries to unify the type expression of this and the parameter /// </summary> /// <param name="te">The type expression to be unified together 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 both type expressionas could be unfied</returns> public abstract bool Unify(TypeExpression te, SortOfUnification unification, IList <Pair <TypeExpression, TypeExpression> > previouslyUnified);
/// <summary> /// Adds a new parameter type. /// </summary> /// <param name="paramType">Parameter type.</param> public void AddParameter(TypeExpression paramType) { this.paramList.Add(paramType); }
public IntersectionType(TypeExpression te) { this.AddType(te); this.BuildFullName(); }
// 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); }
// 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) { return(this.RealType.Unify(te, unification, previouslyUnified)); }
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); }