/// <summary> /// Finds and adds the list of constructor to a BCL type /// </summary> /// <param name="fileName">File name.</param> /// <param name="line">Line number.</param> /// <param name="column">Column number.</param> /// <returns>WriteType obtained</returns> public TypeExpression FindConstructor(Location location) { ConstructorInfo[] constructors = userType.TypeInfo.GetConstructors(); AccessModifier accessModifierInfo; MethodType mt; foreach (ConstructorInfo constructor in constructors) { mt = new MethodType((UserType)userType); // The constructor returns its own class ParameterInfo[] parameters = constructor.GetParameters(); for (int j = 0; j < parameters.GetLength(0); j++) { mt.AddParameter(TypeTable.Instance.GetType(parameters[j].ParameterType.FullName, location)); } List <Modifier> mods = getMethodModifierList(constructor); accessModifierInfo = new AccessModifier(mods, constructor.Name, mt, false); mt.MemberInfo = accessModifierInfo; accessModifierInfo.Class = (UserType)userType; if (userType.Constructors != null) { if (!(userType.Constructors.Type is IntersectionType)) // * It is not an intersection // * An intersection type must be created { userType.Members[userType.Name].Type = new IntersectionMemberType(userType.Members[userType.Name].Type); } // * The type is added ((IntersectionType)userType.Members[userType.Name].Type).AddType(mt); } else { userType.AddMember(userType.Name, accessModifierInfo); } accessModifierInfo.Type.BuildTypeExpressionString(TypeExpression.MAX_DEPTH_LEVEL_TYPE_EXPRESSION); } if (userType.Members.ContainsKey(userType.Name)) { return(userType.Members[userType.Name].Type); } return(null); }
/// <summary> /// Creates a MethodType using the method information. /// </summary> /// <param name="methods">Methods information.</param> /// <param name="fileName">File name.</param> /// <param name="line">Line number.</param> /// <param name="column">Column number.</param> private void createMethods(MethodInfo[] methods, Location location) { AccessModifier accessModifierInfo; MethodType mt; foreach (MethodInfo method in methods) { mt = new MethodType(TypeTable.Instance.GetType(method.ReturnType.FullName, location)); ParameterInfo[] parameters = method.GetParameters(); for (int j = 0; j < parameters.GetLength(0); j++) { if (parameters[j].ParameterType.FullName != null) { mt.AddParameter(TypeTable.Instance.GetType(parameters[j].ParameterType.FullName, location)); } } List <Modifier> mods = getMethodModifierList(method); accessModifierInfo = new AccessModifier(mods, method.Name, mt, false); mt.MemberInfo = accessModifierInfo; accessModifierInfo.Class = (UserType)userType; if (userType.Members.ContainsKey(method.Name)) { if (!(userType.Members[method.Name].Type is IntersectionType)) // * It is not an intersection // * An intersection type must be created { userType.Members[method.Name].Type = new IntersectionMemberType(userType.Members[method.Name].Type); } // * The type is added ((IntersectionType)userType.Members[method.Name].Type).AddType(mt); } else { userType.AddMember(method.Name, accessModifierInfo); } accessModifierInfo.Type.BuildTypeExpressionString(TypeExpression.MAX_DEPTH_LEVEL_TYPE_EXPRESSION); } }
// 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); }