/// <summary> /// Tries to match the specified type name against template arguments. /// </summary> /// <param name="typeName">The type name.</param> /// <param name="argumentName">The found argument name.</param> /// <returns><c>true</c> if template argument was matched.</returns> public bool TryGetTemplateArgument(string typeName, out string argumentName) { // Does it belong to our template arguments? int index = ((List <Symbol>)TemplateArgumentsAsSymbols).FindIndex(s => s.Name == typeName); if (index >= 0) { argumentName = GetTemplateArgumentName(index); return(true); } // Does it belong to one of the "parent" template types? UserType parentType = DeclaredInType; while (parentType != null) { SpecializedTemplateUserType templateParentType = parentType as SpecializedTemplateUserType; if (templateParentType != null) { return(templateParentType.TryGetTemplateArgument(typeName, out argumentName)); } parentType = parentType.DeclaredInType; } // Template argument wasn't found argumentName = ""; return(false); }
/// <summary> /// Initializes a new instance of the <see cref="TemplateUserType"/> class. /// </summary> /// <param name="template">Specialized template user type that will be used as representative for generating code.</param> /// <param name="specializations"></param> /// <param name="factory">User type factory that contains this element.</param> public TemplateUserType(SpecializedTemplateUserType template, List <SpecializedTemplateUserType> specializations, UserTypeFactory factory) : base(template.Symbol, null, template.Namespace, factory) { Specializations = specializations; SpecializedRepresentative = template; foreach (SpecializedTemplateUserType specialization in specializations) { specialization.TemplateType = this; } }
/// <summary> /// Initializes a new instance of the <see cref="TemplateUserTypeFactory"/> class. /// </summary> /// <param name="originalFactory">The original user type factory.</param> /// <param name="templateType">The template user type.</param> public TemplateUserTypeFactory(UserTypeFactory originalFactory, SpecializedTemplateUserType templateType) : base(originalFactory) { TemplateType = templateType; OriginalFactory = originalFactory; }
/// <summary> /// Adds template symbols to user type factory and generates template user types. /// </summary> /// <param name="symbols">The template symbols grouped around the same template type.</param> /// <param name="nameSpace">The namespace.</param> /// <param name="generationFlags">The user type generation flags.</param> /// <returns>Generated user types for the specified symbols.</returns> internal IEnumerable <UserType> AddTemplateSymbols(IEnumerable <Symbol> symbols, string nameSpace, UserTypeGenerationFlags generationFlags) { // Bucketize template user types based on number of template arguments var buckets = new Dictionary <int, List <SpecializedTemplateUserType> >(); foreach (Symbol symbol in symbols) { UserType userType = null; // We want to ignore "empty" generic classes (for now) if (symbol.Name == null || symbol.Size == 0) { continue; } // Generate template user type SpecializedTemplateUserType templateType = new SpecializedTemplateUserType(symbol, null, nameSpace, this); if (!templateType.WronglyFormed) { List <SpecializedTemplateUserType> templates; symbol.UserType = templateType; if (!buckets.TryGetValue(templateType.AllTemplateArguments.Count, out templates)) { buckets.Add(templateType.AllTemplateArguments.Count, templates = new List <SpecializedTemplateUserType>()); } templates.Add(templateType); } if (userType != null) { yield return(userType); } } // Add newly generated types foreach (List <SpecializedTemplateUserType> templatesInBucket in buckets.Values) { // TODO: Verify that all templates in the list can be described by the same class (also do check for inner-types) // Sort Templates by Class Name. // This removes ambiguity caused by parallel type processing. // List <SpecializedTemplateUserType> templates = templatesInBucket.OrderBy(t => t.Symbol.Name.Count(c => c == '*')) .ThenBy(t => t.Symbol.Name.Count(c => c == '<')) .ThenBy(t => t.Symbol.Name).ToList(); // Select best suited type for template SpecializedTemplateUserType template = templates.First(); int bestScore = int.MaxValue; foreach (var specializedTemplate in templates) { var arguments = specializedTemplate.AllTemplateArguments; int score = 0; for (int i = 0; i < arguments.Count; i++) { var argument = arguments[i]; // Check if this is repeated type bool repeated = false; for (int j = 0; j < i && !repeated; j++) { repeated = argument == arguments[j]; } if (repeated) { score += 100; } // Check if argument is constant if (argument.Tag == CodeTypeTag.TemplateArgumentConstant) { continue; } // Check if argument is simple user type if ((argument.Tag == CodeTypeTag.Class || argument.Tag == CodeTypeTag.Structure || argument.Tag == CodeTypeTag.Union || argument.Tag == CodeTypeTag.Enum) && !argument.Name.Contains("<")) { score += 1; continue; } // Check if argments is function if (argument.Tag == CodeTypeTag.Function) { score += 2; continue; } // Check if argument is template if (argument.Name.Contains("<")) { score += 20; continue; } // All others fall into the same category score += 5; } // Check if this is the best one if (score < bestScore) { bestScore = score; template = specializedTemplate; } } yield return(new TemplateUserType(template, templates, this)); } }