Class representing user type factory. It is being used to find types.
Пример #1
0
        /// <summary>
        /// Gets the dictionary of generic type constraints per template argument (that has constraint).
        /// </summary>
        /// <param name="factory">The user type factory.</param>
        private Dictionary <string, string> GetGenericTypeConstraintsDictionary(UserTypeFactory factory)
        {
            Dictionary <string, string> result = new Dictionary <string, string>();

#if false
            string[] commonBaseSpecializationTypes = GetCommonBaseTypesForAllSpecializations(factory);

            if (commonBaseSpecializationTypes == null || commonBaseSpecializationTypes.All(r => string.IsNullOrEmpty(r)))
#endif
            {
                // no restrictions
                return(result);
            }

#if false
            StringBuilder sb = new StringBuilder();
            if (commonBaseSpecializationTypes.Count() == 1)
            {
                result.Add(TemplateArgumentsNameBase, commonBaseSpecializationTypes[0]);
            }
            else
            {
                for (int i = 0; i < commonBaseSpecializationTypes.Count(); i++)
                {
                    if (!string.IsNullOrEmpty(commonBaseSpecializationTypes[i]))
                    {
                        result.Add(string.Format("{0}{1}", TemplateArgumentsNameBase, i + 1), commonBaseSpecializationTypes[i]);
                    }
                }
            }
            return(result);
#endif
        }
Пример #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SpecializedTemplateUserType"/> class.
        /// </summary>
        /// <param name="symbol">The symbol we are generating this user type from.</param>
        /// <param name="xmlType">The XML description of the type.</param>
        /// <param name="nameSpace">The namespace it belongs to.</param>
        /// <param name="factory">User type factory that contains this element.</param>
        public SpecializedTemplateUserType(Symbol symbol, XmlType xmlType, string nameSpace, UserTypeFactory factory)
            : base(symbol, xmlType, nameSpace, factory)
        {
            Factory         = CreateFactory(factory);
            OriginalFactory = factory;

            // Enumerate all template arguments as strings
            List <Symbol> allTemplateArguments       = new List <Symbol>();
            List <Symbol> templateArgumentsAsSymbols = new List <Symbol>();

            for (int i = 0; i < Symbol.Namespaces.Count - 1; i++)
            {
                if (!ParseTemplateArguments(Module, Symbol.Namespaces[i], allTemplateArguments))
                {
                    WronglyFormed = true;
                    break;
                }
            }
            if (!WronglyFormed)
            {
                WronglyFormed = !ParseTemplateArguments(Module, Symbol.Namespaces.Last(), templateArgumentsAsSymbols);
                allTemplateArguments.AddRange(templateArgumentsAsSymbols);
            }
            if (!WronglyFormed)
            {
                AllTemplateArguments       = allTemplateArguments;
                TemplateArgumentsAsSymbols = templateArgumentsAsSymbols;
            }
        }
Пример #3
0
        /// <summary>
        /// Creates type tree that represents UserType base on the specified UserType and user type factory.
        /// </summary>
        /// <param name="userType">The user type.</param>
        /// <param name="factory">The user type factory.</param>
        /// <returns>Type tree that represents UserType</returns>
        internal static UserTypeTree Create(UserType userType, UserTypeFactory factory)
        {
            // Check arguments
            if (userType == null)
                throw new ArgumentNullException(nameof(userType));

            // If user type is template or declared in template user type,
            // we need to force template because of possible template types used from "parent" type.
            var type = userType;

            while (type != null)
            {
                var templateType = type as TemplateUserType;

                if (templateType != null)
                    return new TemplateTypeTree(userType, factory);
                type = type.DeclaredInType;
            }

            // Check if user type is enumeration
            var enumType = userType as EnumUserType;

            if (enumType != null)
                return new EnumTreeType(enumType);

            // We are now certain that it is regular user type
            return new UserTypeTree(userType);
        }
Пример #4
0
        /// <summary>
        /// Gets the type tree for the specified field.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param>
        /// <param name="bitLength">Number of bits used for this symbol.</param>
        protected override TypeTree GetFieldTypeTree(SymbolField field, UserTypeFactory factory, bool extractingBaseClass, int bitLength = 0)
        {
            // Do not match specializations when getting type for base class.
            if (extractingBaseClass || NumberOfTemplateArguments == 0)
            {
                return(GetSymbolTypeTree(field.Type, factory, bitLength));
            }

            // Check field in all specializations
            var specializedFields = SpecializedTypes.Select(r => new Tuple <TemplateUserType, SymbolField>(r, r.Symbol.Fields.FirstOrDefault(q => q.Name == field.Name))).ToArray();

            if (specializedFields.Any(r => r.Item2 == null))
            {
                // TODO: Incorrect bucketization. Field does not exist in all specialization.
                return(GetSymbolTypeTree(field.Type, factory, bitLength));
            }

            if (specializedFields.All(r => r.Item2.Type.Name == field.Type.Name))
            {
                // There is no specialization, all types across the specializations are the same.
                return(GetSymbolTypeTree(field.Type, factory, bitLength));
            }

            // Try to get type tree
            TypeTree result = GetSymbolTypeTree(field.Type, factory, bitLength);

            return(FixTypeTree(result, field.Type, factory));
        }
Пример #5
0
        /// <summary>
        /// Extracts all fields from the user type.
        /// </summary>
        /// <param name="factory">The user type factory.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        protected override IEnumerable <UserTypeField> ExtractFields(UserTypeFactory factory, UserTypeGenerationFlags generationFlags)
        {
            ExportStaticFields = true;

            var              fields       = Symbol.Fields.OrderBy(s => s.Name).ToArray();
            bool             useThisClass = generationFlags.HasFlag(UserTypeGenerationFlags.UseDirectClassAccess);
            HashSet <string> usedNames    = new HashSet <string>();

            foreach (var field in fields)
            {
                if (string.IsNullOrEmpty(field.Type.Name))
                {
                    continue;
                }

                if (IsFieldFiltered(field))
                {
                    continue;
                }

                field.PropertyName = NormalizeSymbolNamespace(UserTypeField.GetPropertyName(field, this));
                while (usedNames.Contains(field.PropertyName))
                {
                    field.PropertyName += "_";
                }

                if (field.Name.Contains("@") || field.PropertyName.Length > 511)
                {
                    // Skip names containing '@'
                    continue;
                }

                // Skip fields that are actual values of enum values
                if (field.Type.Tag == CodeTypeTag.Enum && field.Type.EnumValues.Any(t => t.Item1 == field.Name))
                {
                    continue;
                }

                var userField = ExtractField(field, factory, generationFlags, forceIsStatic: true);

                if (field.Type.Tag == CodeTypeTag.Pointer)
                {
                    // Do not use const values for pointers.
                    // We do not allow user type implicit conversion from integers.
                    userField.ConstantValue = string.Empty;
                }

                userField.FieldName    = NormalizeSymbolNamespace(userField.FieldName);
                userField.PropertyName = NormalizeSymbolNamespace(userField.PropertyName);

                yield return(userField);

                usedNames.Add(field.PropertyName);
            }

            foreach (var field in GetAutoGeneratedFields(false, useThisClass))
            {
                yield return(field);
            }
        }
Пример #6
0
        private TypeTree FixTypeTree(TypeTree typeTree, Symbol type, UserTypeFactory factory)
        {
            // Check basic type
            BasicTypeTree basicTypeTree = typeTree as BasicTypeTree;

            if (basicTypeTree != null)
            {
                // Basic type tree is not challenged against template arguments, so try to do that.
                UserType basicUserType;

                if (CreateFactory(factory).GetUserType(type, out basicUserType))
                {
                    TypeTree tree = UserTypeTree.Create(basicUserType, factory);

                    if (tree != null)
                    {
                        return(tree);
                    }
                }

                // Failed to match the type
                // TODO: Look for typedeclared. Class is using different types than in template specialization. We cannot support it right now.
                return(new VariableTypeTree());
            }

            // Check array type
            ArrayTypeTree arrayTypeTree = typeTree as ArrayTypeTree;

            if (arrayTypeTree != null)
            {
                TypeTree elementTypeTree = FixTypeTree(arrayTypeTree.ElementType, type.ElementType, factory);

                if (elementTypeTree != arrayTypeTree.ElementType)
                {
                    return(new ArrayTypeTree(elementTypeTree));
                }

                return(arrayTypeTree);
            }

            // Check pointer type
            PointerTypeTree pointerTypeTree = typeTree as PointerTypeTree;

            if (pointerTypeTree != null)
            {
                TypeTree elementTypeTree = FixTypeTree(pointerTypeTree.ElementType, type.ElementType, factory);

                if (elementTypeTree != pointerTypeTree.ElementType)
                {
                    return(new PointerTypeTree(elementTypeTree));
                }

                return(pointerTypeTree);
            }

            return(typeTree);
        }
Пример #7
0
        /// <summary>
        /// Extracts all fields from the user type.
        /// </summary>
        /// <param name="factory">The user type factory.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        protected override IEnumerable <UserTypeField> ExtractFields(UserTypeFactory factory, UserTypeGenerationFlags generationFlags)
        {
            ExportStaticFields = true;

            var    fields       = Symbol.Fields.OrderBy(s => s.Name).ToArray();
            bool   useThisClass = generationFlags.HasFlag(UserTypeGenerationFlags.UseClassFieldsFromDiaSymbolProvider);
            string previousName = "";

            foreach (var field in fields)
            {
                if (string.IsNullOrEmpty(field.Type.Name))
                {
                    continue;
                }

                if (IsFieldFiltered(field) || field.Name == previousName)
                {
                    continue;
                }

                if (field.Name.Contains("@"))
                {
                    // Skip names contaings '@'
                    continue;
                }

                // Skip fields that are actual values of enum values
                if (field.Type.Tag == Dia2Lib.SymTagEnum.SymTagEnum && field.Type.GetEnumValues().Any(t => t.Item1 == field.Name))
                {
                    continue;
                }

                var userField = ExtractField(field, factory, generationFlags, forceIsStatic: true);

                if (field.Type.Tag == Dia2Lib.SymTagEnum.SymTagPointerType)
                {
                    // Do not use const values for pointers.
                    // We do not allow user type implicit conversion from integers.
                    userField.ConstantValue = string.Empty;
                }

                userField.FieldName    = NormalizeSymbolNamespace(userField.FieldName);
                userField.PropertyName = NormalizeSymbolNamespace(userField.PropertyName);

                yield return(userField);

                previousName = field.Name;
            }

            foreach (var field in GetAutoGeneratedFields(false, useThisClass))
            {
                yield return(field);
            }
        }
Пример #8
0
        /// <summary>
        /// Writes the code for this user type to the specified output.
        /// </summary>
        /// <param name="output">The output.</param>
        /// <param name="error">The error text writer.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="indentation">The current indentation.</param>
        public override void WriteCode(IndentedWriter output, TextWriter error, UserTypeFactory factory, UserTypeGenerationFlags generationFlags, int indentation = 0)
        {
            // Check if we need to write namespace
            string nameSpace     = (DeclaredInType as NamespaceUserType)?.FullClassName ?? Namespace;
            string enumBasicType = GetEnumBasicType(Symbol);

            if ((DeclaredInType == null || (!generationFlags.HasFlag(UserTypeGenerationFlags.SingleFileExport) && DeclaredInType is NamespaceUserType)) && !string.IsNullOrEmpty(nameSpace))
            {
                output.WriteLine(indentation, "namespace {0}", nameSpace);
                output.WriteLine(indentation++, "{{");
            }

            // Write beginning of the enumeration
            if (generationFlags.HasFlag(UserTypeGenerationFlags.GenerateFieldTypeInfoComment))
            {
                output.WriteLine(indentation, "// {0} (original name: {1})", ClassName, Symbol.Name);
            }

            if (AreValuesFlags())
            {
                output.WriteLine(indentation, @"[System.Flags]");
            }
            if (Symbol.Size != 0)
            {
                output.WriteLine(indentation, @"public enum {0} : {1}", ClassName, enumBasicType);
            }
            else
            {
                output.WriteLine(indentation, @"public enum {0}", ClassName);
            }
            output.WriteLine(indentation++, @"{{");

            // Write values
            foreach (var enumValue in Symbol.EnumValues)
            {
                string value = enumValue.Item2;

                if (!FitsBasicType(enumBasicType, ref value))
                {
                    output.WriteLine(indentation, "{0} = ({1}){2},", enumValue.Item1, enumBasicType, value);
                }
                else
                {
                    output.WriteLine(indentation, "{0} = {1},", enumValue.Item1, value);
                }
            }

            // Enumeration end
            output.WriteLine(--indentation, @"}}");
            if ((DeclaredInType == null || (!generationFlags.HasFlag(UserTypeGenerationFlags.SingleFileExport) && DeclaredInType is NamespaceUserType)) && !string.IsNullOrEmpty(nameSpace))
            {
                output.WriteLine(--indentation, "}}");
            }
        }
Пример #9
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UserType"/> class.
 /// </summary>
 /// <param name="symbol">The symbol we are generating this user type from.</param>
 /// <param name="xmlType">The XML description of the type.</param>
 /// <param name="nameSpace">The namespace it belongs to.</param>
 /// <param name="factory">User type factory that contains this element.</param>
 public UserType(Symbol symbol, XmlType xmlType, string nameSpace, UserTypeFactory factory)
 {
     Symbol                  = symbol;
     Factory                 = factory;
     InnerTypes              = new List <UserType>();
     DerivedClasses          = new HashSet <UserType>();
     typeNameCache           = SimpleCache.CreateStruct(() => GetTypeName());
     fullTypeNameCache       = SimpleCache.CreateStruct(() => GetFullTypeName());
     constructorNameCache    = SimpleCache.CreateStruct(() => GetConstructorName());
     namespaceCache          = SimpleCache.CreateStruct(() => GetNamespace(nameSpace));
     membersCache            = SimpleCache.CreateStruct(() => GetMembers().ToArray());
     constructorsCache       = SimpleCache.CreateStruct(() => GetConstructors().ToArray());
     baseClassCache          = SimpleCache.CreateStruct(() => GetBaseClass(Symbol));
     memoryBufferOffsetCache = SimpleCache.CreateStruct(() => GetMemoryBufferOffset());
 }
Пример #10
0
        /// <summary>
        /// Gets the type tree for the specified field.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param>
        /// <param name="bitLength">Number of bits used for this symbol.</param>
        protected override TypeTree GetFieldTypeTree(SymbolField field, UserTypeFactory factory, bool extractingBaseClass, int bitLength = 0)
        {
            // Do not match specializations when getting type for base class.
            if (extractingBaseClass || NumberOfTemplateArguments == 0)
            {
                return(GetSymbolTypeTree(field.Type, factory, bitLength));
            }

            // Check field in all specializations
            var specializedFields = SpecializedTypes.Select(r => new Tuple <TemplateUserType, SymbolField>(r, r.Symbol.Fields.FirstOrDefault(q => q.Name == field.Name))).ToArray();

            if (specializedFields.Any(r => r.Item2 == null))
            {
                // TODO: Incorrect bucketization. Field does not exist in all specialization.
                return(GetSymbolTypeTree(field.Type, factory, bitLength));
            }

            if (specializedFields.All(r => r.Item2.Type.Name == field.Type.Name))
            {
                // There is no specialization, all types across the specializations are the same.
                return(GetSymbolTypeTree(field.Type, factory, bitLength));
            }

            // Try to get type tree
            TypeTree result = GetSymbolTypeTree(field.Type, factory, bitLength);

            if (result is BasicTypeTree)
            {
                // Basic type tree is not challenged against template arguments, so try to do that.
                UserType basicUserType;

                if (CreateFactory(factory).GetUserType(field.Type, out basicUserType))
                {
                    TypeTree tree = UserTypeTree.Create(basicUserType, factory);

                    if (tree != null)
                    {
                        return(tree);
                    }
                }

                // Failed to match the type
                // TODO: Look for typedeclared. Class is using different types than in template specialization. We cannot support it right now.
                return(new VariableTypeTree());
            }

            return(result);
        }
Пример #11
0
        /// <summary>
        /// Extracts all fields from the user type.
        /// </summary>
        /// <param name="factory">The user type factory.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        protected override IEnumerable<UserTypeField> ExtractFields(UserTypeFactory factory, UserTypeGenerationFlags generationFlags)
        {
            ExportStaticFields = true;

            var fields = Symbol.Fields.OrderBy(s => s.Name).ToArray();
            bool useThisClass = generationFlags.HasFlag(UserTypeGenerationFlags.UseClassFieldsFromDiaSymbolProvider);
            string previousName = "";

            foreach (var field in fields)
            {
                if (string.IsNullOrEmpty(field.Type.Name))
                    continue;

                if (IsFieldFiltered(field) || field.Name == previousName)
                    continue;

                if (field.Name.Contains("@"))
                {
                    // Skip names contaings '@'
                    continue;
                }

                // Skip fields that are actual values of enum values
                if (field.Type.Tag == Dia2Lib.SymTagEnum.SymTagEnum && field.Type.GetEnumValues().Any(t => t.Item1 == field.Name))
                    continue;

                var userField = ExtractField(field, factory, generationFlags, forceIsStatic: true);

                if (field.Type.Tag == Dia2Lib.SymTagEnum.SymTagPointerType)
                {
                    // Do not use const values for pointers.
                    // We do not allow user type implicit conversion from integers.
                    userField.ConstantValue = string.Empty;
                }

                userField.FieldName = NormalizeSymbolNamespace(userField.FieldName);
                userField.PropertyName = NormalizeSymbolNamespace(userField.PropertyName);

                yield return userField;
                previousName = field.Name;
            }

            foreach (var field in GetAutoGeneratedFields(false, useThisClass))
                    yield return field;
        }
Пример #12
0
        /// <summary>
        /// Creates the user type factory based on this template user type.
        /// </summary>
        /// <param name="factory">The original user type factory.</param>
        private UserTypeFactory CreateFactory(UserTypeFactory factory)
        {
            // Check if we are trying to create factory from factory that we already created
            var templateFactory = factory as TemplateUserTypeFactory;

            if (templateFactory != null)
            {
                if (templateFactory.TemplateType != this)
                {
                    return(CreateFactory(templateFactory.OriginalFactory));
                }

                // TODO: Verify if we want to keep existing template factory or we want to add our type too
                return(templateFactory);
            }

            return(new TemplateUserTypeFactory(factory, this));
        }
Пример #13
0
        /// <summary>
        /// Updates the template arguments (symbols and user types).
        /// </summary>
        /// <param name="factory">The user type factory.</param>
        /// <returns><c>true</c> if all template arguments are resolved as user types.</returns>
        public bool UpdateTemplateArguments(UserTypeFactory factory)
        {
            bool result = true;

            templateArgumentsAsSymbols = ParseTemplateArguments(factory, Module, Symbol.Namespaces.Last()).ToList();
            templateArgumentsAsUserTypes.Clear();
            foreach (Symbol symbol in templateArgumentsAsSymbols)
            {
                // Try to get user type for the symbol
                UserType specializationUserType = null;

                if (!factory.GetUserType(symbol, out specializationUserType))
                {
                    if (symbol.Tag != CodeTypeTag.Enum && symbol.Tag != CodeTypeTag.Class && symbol.Tag != CodeTypeTag.Structure && symbol.Tag != CodeTypeTag.Union)
                    {
                        try
                        {
                            var typeString = GetSymbolTypeTree(symbol, factory).GetTypeString();

                            specializationUserType = new TemplateArgumentUserType(typeString, symbol);
                        }
                        catch
                        {
                        }
                    }
                }

                templateArgumentsAsUserTypes.Add(specializationUserType);
                result = result && specializationUserType != null;
            }

            // Enumerate all template arguments as strings
            IEnumerable <Symbol> allTemplateArguments = Enumerable.Empty <Symbol>();

            foreach (string symbolName in Symbol.Namespaces)
            {
                allTemplateArguments = allTemplateArguments.Concat(ParseTemplateArguments(factory, Module, symbolName));
            }

            AllTemplateArguments = allTemplateArguments.Select(s => s.Name).ToList();

            // TODO: Unused types should be removed
            return(result);
        }
Пример #14
0
        private static IEnumerable <Symbol> ParseTemplateArguments(UserTypeFactory factory, Module module, string symbolName)
        {
            int templateStart = symbolName.IndexOf('<');

            if (templateStart > 0)
            {
                // Parse template arguments
                List <string> arguments = new List <string>();

                for (int i = templateStart + 1; i < symbolName.Length && symbolName[i] != '>'; i++)
                {
                    string originalyExtractedType = XmlTypeTransformation.ExtractType(symbolName, i);
                    string extractedType          = originalyExtractedType.Trim();

                    i += originalyExtractedType.Length;
                    if (string.IsNullOrEmpty(extractedType))
                    {
                        // This can happen only when list is empty
                        if (arguments.Count > 0)
                        {
                            throw new NotImplementedException("Unexpected empty template argument in symbol " + symbolName);
                        }
                        break;
                    }

                    arguments.Add(extractedType);

                    // Try to see if argument is number (constants are removed from the template arguments as they cannot be used in C#)
                    double constant;

                    if (!double.TryParse(extractedType, out constant))
                    {
                        // Check if type is existing type (symbol)
                        Symbol symbol = GlobalCache.GetSymbol(extractedType, module);

                        if (symbol == null)
                        {
                            throw new Exception("Wrongly formed template argument");
                        }
                        yield return(symbol);
                    }
                }
            }
        }
Пример #15
0
        /// <summary>
        /// Writes the code for this user type to the specified output.
        /// </summary>
        /// <param name="output">The output.</param>
        /// <param name="error">The error text writer.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="indentation">The current indentation.</param>
        public override void WriteCode(IndentedWriter output, TextWriter error, UserTypeFactory factory, UserTypeGenerationFlags generationFlags, int indentation = 0)
        {
            string[] namespaces = this.namespaces;

            if (generationFlags.HasFlag(UserTypeGenerationFlags.GenerateNamespaceAsStaticClass))
            {
                namespaces = NamespaceSymbol.Split(".".ToCharArray());
            }

            // Declared In Type with namespace
            if (DeclaredInType != null || generationFlags.HasFlag(UserTypeGenerationFlags.GenerateNamespaceAsStaticClass))
            {
                foreach (string innerClass in namespaces)
                {
                    output.WriteLine(indentation, "public static partial class {0}", innerClass);
                    output.WriteLine(indentation++, @"{{");
                }
            }
            else
            {
                output.WriteLine(indentation, "namespace {0}", Namespace);
                output.WriteLine(indentation++, @"{{");
            }

            // Inner types
            foreach (var innerType in InnerTypes)
            {
                output.WriteLine();
                innerType.WriteCode(output, error, factory, generationFlags, indentation);
            }

            // Declared In Type with namespace
            if (DeclaredInType != null || generationFlags.HasFlag(UserTypeGenerationFlags.GenerateNamespaceAsStaticClass))
            {
                foreach (string innerClass in namespaces)
                {
                    output.WriteLine(--indentation, "}}");
                }
            }
            else
            {
                output.WriteLine(--indentation, "}}");
            }
        }
Пример #16
0
        /// <summary>
        /// Writes the code for this user type to the specified output.
        /// </summary>
        /// <param name="output">The output.</param>
        /// <param name="error">The error text writer.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="indentation">The current indentation.</param>
        public override void WriteCode(IndentedWriter output, TextWriter error, UserTypeFactory factory, UserTypeGenerationFlags generationFlags, int indentation = 0)
        {
            // Declared In Type with namespace
            if (DeclaredInType != null)
            {
                foreach (string innerClass in namespaces)
                {
                    output.WriteLine(indentation, "public static class {0}", innerClass);
                    output.WriteLine(indentation++, @"{{");
                }
            }
            else
            {
                output.WriteLine(indentation, "namespace {0}", Namespace);
                output.WriteLine(indentation++, @"{{");
            }

            // Inner types
            foreach (var innerType in InnerTypes)
            {
                output.WriteLine();
                innerType.WriteCode(output, error, factory, generationFlags, indentation);
            }

            // Declared In Type with namespace
            if (DeclaredInType != null)
            {
                foreach (string innerClass in namespaces)
                {
                    output.WriteLine(--indentation, "}}");
                }
            }
            else
            {
                output.WriteLine(--indentation, "}}");
            }
        }
Пример #17
0
        /// <summary>
        /// Writes the code for this user type to the specified output.
        /// </summary>
        /// <param name="output">The output.</param>
        /// <param name="error">The error text writer.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="indentation">The current indentation.</param>
        public override void WriteCode(IndentedWriter output, TextWriter error, UserTypeFactory factory, UserTypeGenerationFlags generationFlags, int indentation = 0)
        {
            // Check if we need to write namespace
            string nameSpace = (DeclaredInType as NamespaceUserType)?.FullClassName ?? Namespace;

            if ((DeclaredInType == null || (!generationFlags.HasFlag(UserTypeGenerationFlags.SingleFileExport) && DeclaredInType is NamespaceUserType)) && !string.IsNullOrEmpty(nameSpace))
            {
                output.WriteLine(indentation, "namespace {0}", nameSpace);
                output.WriteLine(indentation++, "{{");
            }

            // Write beginning of the enumeration
            if (generationFlags.HasFlag(UserTypeGenerationFlags.GenerateFieldTypeInfoComment))
                output.WriteLine(indentation, "// {0} (original name: {1})", ClassName, Symbol.Name);

            if (AreValuesFlags())
                output.WriteLine(indentation, @"[System.Flags]");
            if (Symbol.Size != 0)
                output.WriteLine(indentation, @"public enum {0} : {1}", ClassName, GetEnumBasicType(Symbol));
            else
                output.WriteLine(indentation, @"public enum {0}", ClassName);
            output.WriteLine(indentation++, @"{{");

            // Write values
            foreach (var enumValue in Symbol.GetEnumValues())
            {
                output.WriteLine(indentation, "{0} = {1},", enumValue.Item1, enumValue.Item2);
            }

            // Enumeration end
            output.WriteLine(--indentation, @"}}");
            if ((DeclaredInType == null || (!generationFlags.HasFlag(UserTypeGenerationFlags.SingleFileExport) && DeclaredInType is NamespaceUserType)) && !string.IsNullOrEmpty(nameSpace))
            {
                output.WriteLine(--indentation, "}}");
            }
        }
Пример #18
0
        /// <summary>
        /// Gets the type tree for the base class.
        /// If class has multi inheritance, it can return MultiClassInheritanceTypeTree or SingleClassInheritanceWithInterfacesTypeTree.
        /// </summary>
        /// <param name="error">The error text writer.</param>
        /// <param name="type">The type for which we are getting base class.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="baseClassOffset">The base class offset.</param>
        protected override TypeTree GetBaseClassTypeTree(TextWriter error, Symbol type, UserTypeFactory factory, out int baseClassOffset)
        {
            TypeTree baseType = base.GetBaseClassTypeTree(error, type, factory, out baseClassOffset);

            this.baseClassOffset = baseClassOffset;
            return baseType;
        }
Пример #19
0
        /// <summary>
        /// Gets the type tree for the base class.
        /// If class has multi inheritance, it can return MultiClassInheritanceTypeTree or SingleClassInheritanceWithInterfacesTypeTree.
        /// </summary>
        /// <param name="error">The error text writer.</param>
        /// <param name="type">The type for which we are getting base class.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="baseClassOffset">The base class offset.</param>
        protected override TypeTree GetBaseClassTypeTree(TextWriter error, Symbol type, UserTypeFactory factory, out int baseClassOffset)
        {
            TypeTree baseType = base.GetBaseClassTypeTree(error, type, CreateFactory(factory), out baseClassOffset);

            // Check if base type is template argument. It if is, export it as if it is multi class inheritance.
            UserTypeTree userBaseType = baseType as UserTypeTree;
            TemplateArgumentUserType primitiveUserType = userBaseType != null ? userBaseType.UserType as TemplateArgumentUserType : null;
            if (userBaseType != null && primitiveUserType != null)
            {
                var dict = GetGenericTypeConstraintsDictionary(factory);
                string commonBaseClass;

                if (dict.TryGetValue(primitiveUserType.ClassName, out commonBaseClass))
                    return UserTypeTree.Create(new TemplateArgumentUserType(commonBaseClass, null), factory);

                baseClassOffset = 0;
                return new MultiClassInheritanceTypeTree();
            }

            return baseType;
        }
Пример #20
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UserTypeFactory"/> class.
 /// </summary>
 /// <param name="factory">The user type factory.</param>
 public UserTypeFactory(UserTypeFactory factory)
     : this(factory.typeTransformations, factory.CodeNaming)
 {
 }
Пример #21
0
        /// <summary>
        /// Gets the type tree for the specified field.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param>
        /// <param name="bitLength">Number of bits used for this symbol.</param>
        protected override TypeTree GetFieldTypeTree(SymbolField field, UserTypeFactory factory, bool extractingBaseClass, int bitLength = 0)
        {
            // Do not match specializations when getting type for base class.
            if (extractingBaseClass || NumberOfTemplateArguments == 0)
                return GetSymbolTypeTree(field.Type, factory, bitLength);

            // Check field in all specializations
            var specializedFields = SpecializedTypes.Select(r => new Tuple<TemplateUserType, SymbolField>(r, r.Symbol.Fields.FirstOrDefault(q => q.Name == field.Name))).ToArray();

            if (specializedFields.Any(r => r.Item2 == null))
            {
                // TODO: Incorrect bucketization. Field does not exist in all specialization.
                return GetSymbolTypeTree(field.Type, factory, bitLength);
            }

            if (specializedFields.All(r => r.Item2.Type.Name == field.Type.Name))
            {
                // There is no specialization, all types across the specializations are the same.
                return GetSymbolTypeTree(field.Type, factory, bitLength);
            }

            // Try to get type tree
            TypeTree result = GetSymbolTypeTree(field.Type, factory, bitLength);

            if (result is BasicTypeTree)
            {
                // Basic type tree is not challenged against template arguments, so try to do that.
                UserType basicUserType;

                if (CreateFactory(factory).GetUserType(field.Type, out basicUserType))
                {
                    TypeTree tree = UserTypeTree.Create(basicUserType, factory);

                    if (tree != null)
                    {
                        return tree;
                    }
                }

                // Failed to match the type
                // TODO: Look for typedeclared. Class is using different types than in template specialization. We cannot support it right now.
                return new VariableTypeTree();
            }

            return result;
        }
Пример #22
0
 /// <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, TemplateUserType templateType)
     : base(originalFactory)
 {
     TemplateType    = templateType;
     OriginalFactory = originalFactory;
 }
Пример #23
0
 /// <summary>
 /// Initializes a new instance of the <see cref="EnumUserType"/> class.
 /// </summary>
 /// <param name="symbol">The symbol we are generating this user type from.</param>
 /// <param name="nameSpace">The namespace it belongs to.</param>
 /// <param name="factory">User type factory that contains this element.</param>
 public EnumUserType(Symbol symbol, string nameSpace, UserTypeFactory factory)
     : base(symbol, null, nameSpace, factory)
 {
     areValuesFlagsCache = SimpleCache.CreateStruct(CheckIfValuesAreFlags);
     basicTypeCache      = SimpleCache.CreateStruct(() => GetEnumBasicType(Symbol));
 }
Пример #24
0
        private static IEnumerable<Symbol> ParseTemplateArguments(UserTypeFactory factory, Module module, string symbolName)
        {
            int templateStart = symbolName.IndexOf('<');

            if (templateStart > 0)
            {
                // Parse template arguments
                List<string> arguments = new List<string>();

                for (int i = templateStart + 1; i < symbolName.Length && symbolName[i] != '>'; i++)
                {
                    string originalyExtractedType = XmlTypeTransformation.ExtractType(symbolName, i);
                    string extractedType = originalyExtractedType.Trim();

                    i += originalyExtractedType.Length;
                    if (string.IsNullOrEmpty(extractedType))
                    {
                        // This can happen only when list is empty
                        if (arguments.Count > 0)
                            throw new NotImplementedException("Unexpected empty template argument in symbol " + symbolName);
                        break;
                    }

                    arguments.Add(extractedType);

                    // Try to see if argument is number (constants are removed from the template arguments as they cannot be used in C#)
                    double constant;

                    if (!double.TryParse(extractedType, out constant))
                    {
                        // Check if type is existing type (symbol)
                        Symbol symbol = GlobalCache.GetSymbol(extractedType, module);

                        if (symbol == null)
                            throw new Exception("Wrongly formed template argument");
                        yield return symbol;
                    }
                }
            }
        }
Пример #25
0
        /// <summary>
        /// Generates user type field based on the specified symbol field and all other fields that are prepared for this function.
        /// Do not use this function directly, unless you are calling it from overridden function.
        /// </summary>
        /// <param name="field">The symbol field.</param>
        /// <param name="fieldType">The field tree type.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="simpleFieldValue">The code foe "simple field value" used when creating transformation.</param>
        /// <param name="gettingField">The code for getting field variable.</param>
        /// <param name="isStatic">if set to <c>true</c> generated field should be static.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param>
        protected override UserTypeField ExtractFieldInternal(SymbolField field, TypeTree fieldType, UserTypeFactory factory, string simpleFieldValue, string gettingField, bool isStatic, UserTypeGenerationFlags generationFlags, bool extractingBaseClass)
        {
            // Physical code generation make sense only for non-static fields
            if (!isStatic)
            {
                bool lazyCacheUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.LazyCacheUserTypeFields);

                bool                   cacheUserTypeFields       = generationFlags.HasFlag(UserTypeGenerationFlags.CacheUserTypeFields);
                bool                   cacheStaticUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.CacheStaticUserTypeFields);
                string                 constructorText           = "";
                string                 fieldName          = field.Name;
                string                 fieldTypeString    = fieldType.GetTypeString();
                BasicTypeTree          baseType           = fieldType as BasicTypeTree;
                ArrayTypeTree          codeArrayType      = fieldType as ArrayTypeTree;
                UserTypeTree           userType           = fieldType as UserTypeTree;
                TransformationTypeTree transformationType = fieldType as TransformationTypeTree;
                bool                   isEmbedded         = field.Type.Tag != CodeTypeTag.Pointer;

                // Specialization for basic types
                if (baseType != null)
                {
                    if (baseType.BasicType == "string")
                    {
                        int charSize = field.Type.ElementType.Size;

                        constructorText = string.Format("ReadString(GetCodeType().Module.Process, ReadPointer(memoryBuffer, memoryBufferOffset + {0}, {1}), {2})", field.Offset, field.Type.Size, charSize);
                    }
                    else if (baseType.BasicType != "NakedPointer")
                    {
                        if (field.LocationType == LocationType.BitField)
                        {
                            constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, field.Size, field.BitPosition);
                        }
                        else
                        {
                            constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1})", baseType.GetTypeString().UppercaseFirst(), field.Offset);
                        }
                    }
                }
                // Specialization for arrays
                else if (codeArrayType != null)
                {
                    if (codeArrayType.ElementType is BasicTypeTree)
                    {
                        baseType = (BasicTypeTree)codeArrayType.ElementType;
                        if (baseType != null && baseType.BasicType != "string" && baseType.BasicType != "NakedPointer")
                        {
                            int arraySize   = field.Type.Size;
                            int elementSize = field.Type.ElementType.Size;

                            if (baseType.BasicType == "char")
                            {
                                constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize, elementSize);
                            }
                            else
                            {
                                constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize);
                            }
                            fieldTypeString = baseType.GetTypeString() + "[]";
                        }
                    }
                }
                // Specialization for user types
                else if (userType != null && !extractingBaseClass)
                {
                    if (!(userType.UserType is EnumUserType))
                    {
                        string thisClassCodeType;

                        if (IsTypeUsingStaticCodeType(this))
                        {
                            thisClassCodeType = ClassCodeType;
                        }
                        else
                        {
                            thisClassCodeType = "thisClass.Value.GetCodeType()";
                            usedThisClass     = true;
                        }

                        // Check if type is embedded
                        if (!isEmbedded)
                        {
                            // If user type is not embedded, we do have pointer inside of our memory buffer that we can read directly
                            if (IsTypeUsingStaticCodeType(this))
                            {
                                constructorText = string.Format("ReadPointer<{0}>({4}, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size, ClassCodeType);
                            }
                            else
                            {
                                constructorText = string.Format("ReadPointer<{0}>(thisClass, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size);
                                usedThisClass   = true;
                            }

                            // Do downcasting if field has vtable
                            if (userType.UserType.Symbol.HasVTable() && userType.UserType.DerivedClasses.Count > 0)
                            {
                                constructorText += ".DowncastObject()";
                            }
                        }
                        else
                        {
                            // If user type is embedded, we can reuse memory buffer that we already have in this class
                            string fieldAddress  = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset);
                            string fieldCodeType = string.Format("{0}.GetClassFieldType(\"{1}\")", thisClassCodeType, fieldName);

                            if (IsTypeUsingStaticCodeType(userType.UserType))
                            {
                                fieldCodeType = string.Format("{0}.{1}", userType.UserType.FullClassName, ClassCodeType);
                            }
                            else if (IsTypeUsingStaticCodeType(this))
                            {
                                fieldCodeType = AddFieldCodeType(fieldName);
                            }

                            constructorText = string.Format("new {0}(memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress, {2}, {3}, \"{4}\")", fieldTypeString, field.Offset, fieldCodeType, fieldAddress, fieldName);
                        }
                    }
                    else
                    {
                        // TODO: This is enum. Read how much enum base type is big and just cast to enum type...
                    }
                }
                // Specialization for transformations
                else if (transformationType != null)
                {
                    if (!isEmbedded)
                    {
                        string thisClassCodeType;

                        if (IsTypeUsingStaticCodeType(this))
                        {
                            thisClassCodeType = ClassCodeType;
                        }
                        else
                        {
                            thisClassCodeType = "thisClass.Value.GetCodeType()";
                            usedThisClass     = true;
                        }

                        string fieldAddress  = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset);
                        string fieldVariable = string.Format("Variable.CreateNoCast({0}.GetClassFieldType(\"{1}\"), {2}, \"{1}\")", thisClassCodeType, fieldName, fieldAddress);

                        if (transformationType.Transformation.Transformation.HasPhysicalConstructor)
                        {
                            fieldVariable = string.Format("{0}, memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress", fieldVariable, field.Offset);
                        }

                        simpleFieldValue = fieldVariable;
                        constructorText  = string.Format("new {0}({1})", fieldTypeString, fieldVariable);
                    }
                }

                // If we found suitable physical representation, generate the field
                if (!string.IsNullOrEmpty(constructorText))
                {
                    return new UserTypeField()
                           {
                               ConstructorText      = constructorText,
                               FieldName            = "_" + fieldName,
                               FieldType            = fieldTypeString,
                               FieldTypeInfoComment = string.Format("// {0} {1};", field.Type.Name, fieldName),
                               PropertyName         = UserTypeField.GetPropertyName(field, this),
                               Static           = isStatic,
                               UseUserMember    = lazyCacheUserTypeFields,
                               CacheResult      = cacheUserTypeFields || (isStatic && cacheStaticUserTypeFields),
                               SimpleFieldValue = simpleFieldValue,
                           }
                }
                ;
            }

            return(base.ExtractFieldInternal(field, fieldType, factory, simpleFieldValue, gettingField, isStatic, generationFlags, extractingBaseClass));
        }
Пример #26
0
        /// <summary>
        /// Initializes a new instance of the <see cref="TemplateTypeTree"/> class.
        /// </summary>
        /// <param name="templateSpecialization">The template specialization user type.</param>
        /// <param name="factory">The user type factory.</param>
        public TemplateTypeTree(UserType templateSpecialization, UserTypeFactory factory)
            : base(templateSpecialization)
        {
            // Get all "parent" types
            UserType type = templateSpecialization;
            List<UserType> declaredInList = new List<UserType>();

            while (type != null)
            {
                declaredInList.Add(type);
                type = type.DeclaredInType;
            }

            declaredInList.Reverse();
            DeclaredInTypeHierarchy = declaredInList.ToArray();

            // Extract all template types and check if we can instantiate this instance
            CanInstantiate = true;
            SpecializedArguments = new TypeTree[DeclaredInTypeHierarchy.Length][];
            for (int j = 0; j < DeclaredInTypeHierarchy.Length; j++)
            {
                // Check if current type in hierarchy is template type
                TemplateUserType templateType = DeclaredInTypeHierarchy[j] as TemplateUserType;

                if (templateType == null)
                    continue;

                // Try to find specialized arguments for template type
                IReadOnlyList<Symbol> arguments = templateType.TemplateArgumentsAsSymbols;
                TypeTree[] specializedArguments = new TypeTree[arguments.Count];

                for (int i = 0; i < arguments.Count; i++)
                {
                    UserType userType;

                    factory.GetUserType(arguments[i], out userType);
                    if (userType != null)
                    {
                        specializedArguments[i] = UserTypeTree.Create(userType, factory);
                        TemplateTypeTree templateTypeTree = specializedArguments[i] as TemplateTypeTree;

                        if (templateTypeTree != null && !templateTypeTree.CanInstantiate)
                            CanInstantiate = false;
                    }
                    else
                    {
                        // TODO: Check why do we go one more round trip through module for getting argument symbol
                        Symbol symbol = templateSpecialization.Symbol.Module.GetSymbol(arguments[i].Name);

                        if (symbol.Tag != SymTagEnum.SymTagBaseType)
                        {
                            // Base Types (Primitive Types) can be used for specialization
                            CanInstantiate = false;
                        }

                        // #fixme can't deal with it
                        specializedArguments[i] = templateType.GetSymbolTypeTree(arguments[i], factory);
                    }
                }

                SpecializedArguments[j] = specializedArguments;
            }
        }
Пример #27
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UserTypeFactory"/> class.
 /// </summary>
 /// <param name="factory">The user type factory.</param>
 public UserTypeFactory(UserTypeFactory factory)
     : this(factory.typeTransformations)
 {
 }
Пример #28
0
 /// <summary>
 /// Initializes a new instance of the <see cref="NamespaceUserType"/> class.
 /// </summary>
 /// <param name="innerNamespaces">The list of inner namespaces (e.g. chrono in std::chrono).</param>
 /// <param name="topLevelNamespace">The top level namespace (e.g. module name).</param>
 /// <param name="factory">User type factory that contains this element.</param>
 internal NamespaceUserType(IEnumerable <string> innerNamespaces, string topLevelNamespace, UserTypeFactory factory)
     : base(symbol: null, xmlType: null, nameSpace: null, factory: factory)
 {
     namespaces = innerNamespaces.Select(s => CodeNaming.FixUserNaming(s)).ToList();
     if (topLevelNamespace != null)
     {
         namespaces.Insert(0, topLevelNamespace);
     }
 }
Пример #29
0
        /// <summary>
        /// Gets the dictionary of generic type constraints per template argument (that has constraint).
        /// </summary>
        /// <param name="factory">The user type factory.</param>
        private Dictionary<string, string> GetGenericTypeConstraintsDictionary(UserTypeFactory factory)
        {
            Dictionary<string, string> result = new Dictionary<string, string>();
            #if false
            string[] commonBaseSpecializationTypes = GetCommonBaseTypesForAllSpecializations(factory);

            if (commonBaseSpecializationTypes == null || commonBaseSpecializationTypes.All(r => string.IsNullOrEmpty(r)))
            #endif
            {
                // no restrictions
                return result;
            }

            #if false
            StringBuilder sb = new StringBuilder();
            if (commonBaseSpecializationTypes.Count() == 1)
                result.Add(TemplateArgumentsNameBase, commonBaseSpecializationTypes[0]);
            else
                for (int i = 0; i < commonBaseSpecializationTypes.Count(); i++)
                    if (!string.IsNullOrEmpty(commonBaseSpecializationTypes[i]))
                        result.Add(string.Format("{0}{1}", TemplateArgumentsNameBase, i + 1), commonBaseSpecializationTypes[i]);
            return result;
            #endif
        }
Пример #30
0
        /// <summary>
        /// Gets the common base types for all specializations.
        /// </summary>
        /// <param name="factory">The user type factory.</param>
        private string[] GetCommonBaseTypesForAllSpecializations(UserTypeFactory factory)
        {
            // If we don't have specializations, we cannot continue
            if (!SpecializedTypes.Any())
            {
                return null;
            }

            // Do this for every template argument
            string[] results = new string[NumberOfTemplateArguments];

            for (int i = 0; i < NumberOfTemplateArguments; i++)
            {
                // Get all specializations for current template argument
                Symbol[] specializedSymbols = SpecializedTypes.Select(r => r.templateArgumentsAsSymbols[i]).ToArray();
                TypeOfSpecializationType specializationType = TypeOfSpecializationType.Unmatched;
                UserType commonType = null;

                foreach (Symbol type in specializedSymbols)
                {
                    // Check base type
                    if (type.Tag == Dia2Lib.SymTagEnum.SymTagBaseType || type.Tag == Dia2Lib.SymTagEnum.SymTagEnum)
                        if (type.Name != "void")
                        {
                            specializationType = TypeOfSpecializationType.Anything;
                            break;
                        }
                        else
                        {
                            specializationType = TypeOfSpecializationType.Variable;
                            continue;
                        }

                    // Check pointer, array and function types, they inherit Variable
                    if (type.Tag == Dia2Lib.SymTagEnum.SymTagPointerType || type.Tag == Dia2Lib.SymTagEnum.SymTagArrayType || type.Tag == Dia2Lib.SymTagEnum.SymTagFunctionType)
                    {
                        specializationType = TypeOfSpecializationType.Variable;
                        continue;
                    }

                    if (type.Tag != Dia2Lib.SymTagEnum.SymTagUDT)
                    {
                        throw new NotImplementedException("Unexpected symbol type " + type.Tag + ". Symbol name: " + type.Name);
                    }

                    // Check if type has user type
                    UserType userType = type.UserType;

                    if (userType == null)
                    {
                        // TODO: This shouldn't happen
                        specializationType = TypeOfSpecializationType.Variable;
                        continue;
                    }

                    if (specializationType == TypeOfSpecializationType.Variable)
                        continue;

                    // If user type is template, get parent template type (one that describes all specializations)
                    var templateType = userType as TemplateUserType;

                    if (templateType != null)
                        userType = templateType.TemplateType;

                    if (specializationType == TypeOfSpecializationType.Unmatched)
                    {
                        specializationType = TypeOfSpecializationType.UserType;
                        commonType = userType;
                        continue;
                    }

                    // Try to find common type for commonType and userType
                    var commonTypeBases = ExtractAllBaseClasses(commonType);
                    var userTypeBases = ExtractAllBaseClasses(userType);
                    bool found = false;

                    foreach (var ct in commonTypeBases)
                    {
                        foreach (var ut in userTypeBases)
                            if (ut == ct)
                            {
                                found = true;
                                commonType = ut;
                                break;
                            }

                        if (found)
                            break;
                    }

                    if (!found)
                        specializationType = TypeOfSpecializationType.Variable;
                }

                // Save result based on specialization type
                string userTypeName = null;
                var templateCommonType = commonType as TemplateUserType;

                switch (specializationType)
                {
                    case TypeOfSpecializationType.Anything:
                        userTypeName = null;
                        break;
                    case TypeOfSpecializationType.Variable:
                        userTypeName = "Variable";
                        break;
                    case TypeOfSpecializationType.UserType:
                        if (templateCommonType != null)
                        {
                            // Common specialization is template type. In order to use it, we need to take specialization from this type
                            // and not the one that engine picked up as generalization.
                            UserType templateArgumentUserType = templateArgumentsAsUserTypes[i];
                            List<UserType> baseClasses = ExtractAllBaseClasses(templateArgumentUserType);

                            foreach (UserType baseClass in baseClasses)
                            {
                                TemplateUserType templateBaseClass = baseClass as TemplateUserType;

                                if (templateBaseClass != null && templateCommonType == templateBaseClass.TemplateType)
                                {
                                    templateCommonType = templateBaseClass;
                                    break;
                                }
                            }

                            // In order to use template as specialization, we need to have all arguments coming from our template arguments.
                            // If not, we cannot trust them and should continue with the base classes.
                            var tree = new TemplateTypeTree(templateCommonType, factory);
                            bool ok = true;

                            do
                            {
                                // Check if all arguments are coming from our template arguments.
                                ok = true;
                                foreach (var args in tree.SpecializedArguments)
                                    if (args != null)
                                        foreach (var arg in args)
                                            if (!(arg is TemplateArgumentTreeType) && !(arg is UserTypeTree && ((UserTypeTree)arg).UserType is TemplateArgumentUserType))
                                            {
                                                ok = false;
                                                break;
                                            }

                                if (!ok)
                                {
                                    // Find base class that we should continue with
                                    UserType nextBaseClass = null;
                                    Symbol symbol = templateCommonType.Symbol;

                                    while (nextBaseClass == null)
                                    {
                                        if (symbol.BaseClasses == null || symbol.BaseClasses.Length == 0)
                                        {
                                            // We have finished all
                                            break;
                                        }

                                        if (symbol.BaseClasses.Length > 1)
                                        {
                                            // We cannot match common type with multi-inheritance
                                            break;
                                        }

                                        symbol = symbol.BaseClasses[0];
                                        nextBaseClass = symbol?.UserType;
                                    }

                                    // No base class, use Variable
                                    if (nextBaseClass == null)
                                    {
                                        userTypeName = "Variable";
                                        break;
                                    }
                                    else if (nextBaseClass is TemplateUserType)
                                    {
                                        // Base class is template, continue with checks
                                        templateCommonType = (TemplateUserType)nextBaseClass;
                                        tree = new TemplateTypeTree(templateCommonType, factory);
                                    }
                                    else
                                    {
                                        // Base class is not template, so we can stop testing it.
                                        userTypeName = nextBaseClass.FullClassName;
                                        break;
                                    }
                                }
                            }
                            while (!ok);

                            // All checks passed for this template user type, use it.
                            if (ok)
                                userTypeName = tree.GetTypeString();
                        }
                        else
                            userTypeName = commonType.FullClassName;
                        break;
                    case TypeOfSpecializationType.Unmatched:
                    default:
                        throw new NotImplementedException("Unexpected specialization type " + specializationType + " for template type " + ClassName);
                }

                results[i] = userTypeName;
            }

            return results;
        }
Пример #31
0
        /// <summary>
        /// Creates the user type factory based on this template user type.
        /// </summary>
        /// <param name="factory">The original user type factory.</param>
        private UserTypeFactory CreateFactory(UserTypeFactory factory)
        {
            // Check if we are trying to create factory from factory that we already created
            var templateFactory = factory as TemplateUserTypeFactory;

            if (templateFactory != null)
            {
                if (templateFactory.TemplateType != this)
                    return CreateFactory(templateFactory.OriginalFactory);

                // TODO: Verify if we want to keep existing template factory or we want to add our type too
                return templateFactory;
            }

            return new TemplateUserTypeFactory(factory, this);
        }
Пример #32
0
        /// <summary>
        /// Generates user type field based on the specified symbol field and all other fields that are prepared for this function.
        /// Do not use this function directly, unless you are calling it from overridden function.
        /// </summary>
        /// <param name="field">The symbol field.</param>
        /// <param name="fieldType">The field tree type.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="simpleFieldValue">The code foe "simple field value" used when creating transformation.</param>
        /// <param name="gettingField">The code for getting field variable.</param>
        /// <param name="isStatic">if set to <c>true</c> generated field should be static.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param>
        protected override UserTypeField ExtractFieldInternal(SymbolField field, TypeTree fieldType, UserTypeFactory factory, string simpleFieldValue, string gettingField, bool isStatic, UserTypeGenerationFlags generationFlags, bool extractingBaseClass)
        {
            // Physical code generation make sense only for non-static fields
            if (!isStatic)
            {
                bool lazyCacheUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.LazyCacheUserTypeFields);
                bool cacheUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.CacheUserTypeFields);
                bool cacheStaticUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.CacheStaticUserTypeFields);
                string constructorText = "";
                string fieldName = field.Name;
                string fieldTypeString = fieldType.GetTypeString();
                BasicTypeTree baseType = fieldType as BasicTypeTree;
                ArrayTypeTree codeArrayType = fieldType as ArrayTypeTree;
                UserTypeTree userType = fieldType as UserTypeTree;
                TransformationTypeTree transformationType = fieldType as TransformationTypeTree;
                bool isEmbedded = field.Type.Tag != SymTagEnum.SymTagPointerType;

                // Specialization for basic types
                if (baseType != null)
                {
                    if (baseType.BasicType == "string")
                    {
                        int charSize = field.Type.ElementType.Size;

                        constructorText = string.Format("ReadString(GetCodeType().Module.Process, ReadPointer(memoryBuffer, memoryBufferOffset + {0}, {1}), {2})", field.Offset, field.Type.Size, charSize);
                    }
                    else if (baseType.BasicType != "NakedPointer")
                    {
                        if (field.LocationType == LocationType.BitField)
                            constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, field.Size, field.BitPosition);
                        else
                            constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1})", baseType.GetTypeString().UppercaseFirst(), field.Offset);
                    }
                }
                // Specialization for arrays
                else if (codeArrayType != null)
                {
                    if (codeArrayType.ElementType is BasicTypeTree)
                    {
                        baseType = (BasicTypeTree)codeArrayType.ElementType;
                        if (baseType != null && baseType.BasicType != "string" && baseType.BasicType != "NakedPointer")
                        {
                            int arraySize = field.Type.Size;
                            int elementSize = field.Type.ElementType.Size;

                            if (baseType.BasicType == "char")
                                constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize, elementSize);
                            else
                                constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize);
                            fieldTypeString = baseType.GetTypeString() + "[]";
                        }
                    }
                }
                // Specialization for user types
                else if (userType != null && !extractingBaseClass)
                {
                    if (!(userType.UserType is EnumUserType))
                    {
                        string thisClassCodeType;

                        if (IsTypeUsingStaticCodeType(this))
                            thisClassCodeType = ClassCodeType;
                        else
                        {
                            thisClassCodeType = "thisClass.Value.GetCodeType()";
                            usedThisClass = true;
                        }

                        // Check if type is embedded
                        if (!isEmbedded)
                        {
                            // If user type is not embedded, we do have pointer inside of our memory buffer that we can read directly
                            if (IsTypeUsingStaticCodeType(this))
                                constructorText = string.Format("ReadPointer<{0}>({4}, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size, ClassCodeType);
                            else
                            {
                                constructorText = string.Format("ReadPointer<{0}>(thisClass, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size);
                                usedThisClass = true;
                            }

                            // Do downcasting if field has vtable
                            if (userType.UserType.Symbol.HasVTable() && userType.UserType.DerivedClasses.Count > 0)
                                constructorText += ".DowncastObject()";
                        }
                        else
                        {
                            // If user type is embedded, we can reuse memory buffer that we already have in this class
                            string fieldAddress = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset);
                            string fieldCodeType = string.Format("{0}.GetClassFieldType(\"{1}\")", thisClassCodeType, fieldName);

                            if (IsTypeUsingStaticCodeType(userType.UserType))
                            {
                                fieldCodeType = string.Format("{0}.{1}", userType.UserType.FullClassName, ClassCodeType);
                            }
                            else if (IsTypeUsingStaticCodeType(this))
                            {
                                fieldCodeType = AddFieldCodeType(fieldName);
                            }

                            constructorText = string.Format("new {0}(memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress, {2}, {3}, \"{4}\")", fieldTypeString, field.Offset, fieldCodeType, fieldAddress, fieldName);
                        }
                    }
                    else
                    {
                        // TODO: This is enum. Read how much enum base type is big and just cast to enum type...
                    }
                }
                // Specialization for transformations
                else if (transformationType != null)
                {
                    if (!isEmbedded)
                    {
                        string thisClassCodeType;

                        if (IsTypeUsingStaticCodeType(this))
                            thisClassCodeType = ClassCodeType;
                        else
                        {
                            thisClassCodeType = "thisClass.Value.GetCodeType()";
                            usedThisClass = true;
                        }

                        string fieldAddress = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset);
                        string fieldVariable = string.Format("Variable.CreateNoCast({0}.GetClassFieldType(\"{1}\"), {2}, \"{1}\")", thisClassCodeType, fieldName, fieldAddress);

                        if (transformationType.Transformation.Transformation.HasPhysicalConstructor)
                        {
                            fieldVariable = string.Format("{0}, memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress", fieldVariable, field.Offset);
                        }

                        simpleFieldValue = fieldVariable;
                        constructorText = string.Format("new {0}({1})", fieldTypeString, fieldVariable);
                    }
                }

                // If we found suitable physical representation, generate the field
                if (!string.IsNullOrEmpty(constructorText))
                    return new UserTypeField()
                    {
                        ConstructorText = constructorText,
                        FieldName = "_" + fieldName,
                        FieldType = fieldTypeString,
                        FieldTypeInfoComment = string.Format("// {0} {1};", field.Type.Name, fieldName),
                        PropertyName = UserTypeField.GetPropertyName(fieldName, this),
                        Static = isStatic,
                        UseUserMember = lazyCacheUserTypeFields,
                        CacheResult = cacheUserTypeFields || (isStatic && cacheStaticUserTypeFields),
                        SimpleFieldValue = simpleFieldValue,
                    };
            }

            return base.ExtractFieldInternal(field, fieldType, factory, simpleFieldValue, gettingField, isStatic, generationFlags, extractingBaseClass);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="TemplateArgumentTreeType"/> class.
 /// </summary>
 /// <param name="templateArgumentNumber">The template type argument number.</param>
 /// <param name="templateSpecialization">The template specialization user type.</param>
 /// <param name="factory">The user type factory.</param>
 public TemplateArgumentTreeType(int templateArgumentNumber, UserType templateSpecialization, UserTypeFactory factory)
     : base(templateSpecialization, factory)
 {
     ArgumentNumber = templateArgumentNumber;
 }
Пример #34
0
 /// <summary>
 /// Gets the type tree for the base class.
 /// If class has multi inheritance, it can return MultiClassInheritanceTypeTree or SingleClassInheritanceWithInterfacesTypeTree.
 /// </summary>
 /// <param name="error">The error text writer.</param>
 /// <param name="type">The type for which we are getting base class.</param>
 /// <param name="factory">The user type factory.</param>
 /// <param name="baseClassOffset">The base class offset.</param>
 protected override TypeTree GetBaseClassTypeTree(TextWriter error, Symbol type, UserTypeFactory factory, out int baseClassOffset)
 {
     baseClassOffset = 0;
     return new StaticClassTypeTree();
 }
Пример #35
0
 /// <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="SingleClassInheritanceWithInterfacesTypeTree"/> class.
 /// </summary>
 /// <param name="baseClassUserType">The base class user type.</param>
 /// <param name="factory">The user type factory.</param>
 public SingleClassInheritanceWithInterfacesTypeTree(UserType baseClassUserType, UserTypeFactory factory)
 {
     BaseClassUserType = UserTypeTree.Create(baseClassUserType, factory);
 }
Пример #37
0
        /// <summary>
        /// Gets the list of generic type constraints.
        /// </summary>
        /// <param name="factory">The user type factory.</param>
        protected override IEnumerable<string> GetGenericTypeConstraints(UserTypeFactory factory)
        {
            var dict = GetGenericTypeConstraintsDictionary(CreateFactory(factory));

            return dict.Select(t => string.Format("where {0} : {1}", t.Key, t.Value));
        }
Пример #38
0
 public bool UpdateTemplateArguments(UserTypeFactory userTypeFactory)
 {
     // TODO: This looks like it is not needed, verify with some huge example PDBs.
     //throw new NotImplementedException();
     return(true);
 }
Пример #39
0
        /// <summary>
        /// Gets the type tree for the base class.
        /// If class has multi inheritance, it can return MultiClassInheritanceTypeTree or SingleClassInheritanceWithInterfacesTypeTree.
        /// </summary>
        /// <param name="error">The error text writer.</param>
        /// <param name="type">The type for which we are getting base class.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="baseClassOffset">The base class offset.</param>
        protected override TypeTree GetBaseClassTypeTree(TextWriter error, Symbol type, UserTypeFactory factory, out int baseClassOffset)
        {
            TypeTree baseType = base.GetBaseClassTypeTree(error, type, CreateFactory(factory), out baseClassOffset);

            // Check if base type is template argument. It if is, export it as if it is multi class inheritance.
            UserTypeTree             userBaseType      = baseType as UserTypeTree;
            TemplateArgumentUserType primitiveUserType = userBaseType != null ? userBaseType.UserType as TemplateArgumentUserType : null;

            if (userBaseType != null && primitiveUserType != null)
            {
                var    dict = GetGenericTypeConstraintsDictionary(factory);
                string commonBaseClass;

                if (dict.TryGetValue(primitiveUserType.ClassName, out commonBaseClass))
                {
                    return(UserTypeTree.Create(new TemplateArgumentUserType(commonBaseClass, null), factory));
                }

                baseClassOffset = 0;
                return(new MultiClassInheritanceTypeTree());
            }

            return(baseType);
        }
Пример #40
0
 /// <summary>
 /// Gets the type tree for the base class.
 /// If class has multi inheritance, it can return MultiClassInheritanceTypeTree or SingleClassInheritanceWithInterfacesTypeTree.
 /// </summary>
 /// <param name="error">The error text writer.</param>
 /// <param name="type">The type for which we are getting base class.</param>
 /// <param name="factory">The user type factory.</param>
 /// <param name="baseClassOffset">The base class offset.</param>
 protected override TypeTree GetBaseClassTypeTree(TextWriter error, Symbol type, UserTypeFactory factory, out int baseClassOffset)
 {
     baseClassOffset = 0;
     return(new StaticClassTypeTree());
 }
Пример #41
0
        /// <summary>
        /// Gets the common base types for all specializations.
        /// </summary>
        /// <param name="factory">The user type factory.</param>
        private string[] GetCommonBaseTypesForAllSpecializations(UserTypeFactory factory)
        {
            // If we don't have specializations, we cannot continue
            if (!SpecializedTypes.Any())
            {
                return(null);
            }

            // Do this for every template argument
            string[] results = new string[NumberOfTemplateArguments];

            for (int i = 0; i < NumberOfTemplateArguments; i++)
            {
                // Get all specializations for current template argument
                Symbol[] specializedSymbols = SpecializedTypes.Select(r => r.templateArgumentsAsSymbols[i]).ToArray();
                TypeOfSpecializationType specializationType = TypeOfSpecializationType.Unmatched;
                UserType commonType = null;

                foreach (Symbol type in specializedSymbols)
                {
                    // Check base type
                    if (type.Tag == Dia2Lib.SymTagEnum.SymTagBaseType || type.Tag == Dia2Lib.SymTagEnum.SymTagEnum)
                    {
                        if (type.Name != "void")
                        {
                            specializationType = TypeOfSpecializationType.Anything;
                            break;
                        }
                        else
                        {
                            specializationType = TypeOfSpecializationType.Variable;
                            continue;
                        }
                    }

                    // Check pointer, array and function types, they inherit Variable
                    if (type.Tag == Dia2Lib.SymTagEnum.SymTagPointerType || type.Tag == Dia2Lib.SymTagEnum.SymTagArrayType || type.Tag == Dia2Lib.SymTagEnum.SymTagFunctionType)
                    {
                        specializationType = TypeOfSpecializationType.Variable;
                        continue;
                    }

                    if (type.Tag != Dia2Lib.SymTagEnum.SymTagUDT)
                    {
                        throw new NotImplementedException("Unexpected symbol type " + type.Tag + ". Symbol name: " + type.Name);
                    }

                    // Check if type has user type
                    UserType userType = type.UserType;

                    if (userType == null)
                    {
                        // TODO: This shouldn't happen
                        specializationType = TypeOfSpecializationType.Variable;
                        continue;
                    }

                    if (specializationType == TypeOfSpecializationType.Variable)
                    {
                        continue;
                    }

                    // If user type is template, get parent template type (one that describes all specializations)
                    var templateType = userType as TemplateUserType;

                    if (templateType != null)
                    {
                        userType = templateType.TemplateType;
                    }

                    if (specializationType == TypeOfSpecializationType.Unmatched)
                    {
                        specializationType = TypeOfSpecializationType.UserType;
                        commonType         = userType;
                        continue;
                    }

                    // Try to find common type for commonType and userType
                    var  commonTypeBases = ExtractAllBaseClasses(commonType);
                    var  userTypeBases   = ExtractAllBaseClasses(userType);
                    bool found           = false;

                    foreach (var ct in commonTypeBases)
                    {
                        foreach (var ut in userTypeBases)
                        {
                            if (ut == ct)
                            {
                                found      = true;
                                commonType = ut;
                                break;
                            }
                        }

                        if (found)
                        {
                            break;
                        }
                    }

                    if (!found)
                    {
                        specializationType = TypeOfSpecializationType.Variable;
                    }
                }

                // Save result based on specialization type
                string userTypeName       = null;
                var    templateCommonType = commonType as TemplateUserType;

                switch (specializationType)
                {
                case TypeOfSpecializationType.Anything:
                    userTypeName = null;
                    break;

                case TypeOfSpecializationType.Variable:
                    userTypeName = "Variable";
                    break;

                case TypeOfSpecializationType.UserType:
                    if (templateCommonType != null)
                    {
                        // Common specialization is template type. In order to use it, we need to take specialization from this type
                        // and not the one that engine picked up as generalization.
                        UserType        templateArgumentUserType = templateArgumentsAsUserTypes[i];
                        List <UserType> baseClasses = ExtractAllBaseClasses(templateArgumentUserType);

                        foreach (UserType baseClass in baseClasses)
                        {
                            TemplateUserType templateBaseClass = baseClass as TemplateUserType;

                            if (templateBaseClass != null && templateCommonType == templateBaseClass.TemplateType)
                            {
                                templateCommonType = templateBaseClass;
                                break;
                            }
                        }

                        // In order to use template as specialization, we need to have all arguments coming from our template arguments.
                        // If not, we cannot trust them and should continue with the base classes.
                        var  tree = new TemplateTypeTree(templateCommonType, factory);
                        bool ok   = true;

                        do
                        {
                            // Check if all arguments are coming from our template arguments.
                            ok = true;
                            foreach (var args in tree.SpecializedArguments)
                            {
                                if (args != null)
                                {
                                    foreach (var arg in args)
                                    {
                                        if (!(arg is TemplateArgumentTreeType) && !(arg is UserTypeTree && ((UserTypeTree)arg).UserType is TemplateArgumentUserType))
                                        {
                                            ok = false;
                                            break;
                                        }
                                    }
                                }
                            }

                            if (!ok)
                            {
                                // Find base class that we should continue with
                                UserType nextBaseClass = null;
                                Symbol   symbol        = templateCommonType.Symbol;

                                while (nextBaseClass == null)
                                {
                                    if (symbol.BaseClasses == null || symbol.BaseClasses.Length == 0)
                                    {
                                        // We have finished all
                                        break;
                                    }

                                    if (symbol.BaseClasses.Length > 1)
                                    {
                                        // We cannot match common type with multi-inheritance
                                        break;
                                    }

                                    symbol        = symbol.BaseClasses[0];
                                    nextBaseClass = symbol?.UserType;
                                }

                                // No base class, use Variable
                                if (nextBaseClass == null)
                                {
                                    userTypeName = "Variable";
                                    break;
                                }
                                else if (nextBaseClass is TemplateUserType)
                                {
                                    // Base class is template, continue with checks
                                    templateCommonType = (TemplateUserType)nextBaseClass;
                                    tree = new TemplateTypeTree(templateCommonType, factory);
                                }
                                else
                                {
                                    // Base class is not template, so we can stop testing it.
                                    userTypeName = nextBaseClass.FullClassName;
                                    break;
                                }
                            }
                        }while (!ok);

                        // All checks passed for this template user type, use it.
                        if (ok)
                        {
                            userTypeName = tree.GetTypeString();
                        }
                    }
                    else
                    {
                        userTypeName = commonType.FullClassName;
                    }
                    break;

                case TypeOfSpecializationType.Unmatched:
                default:
                    throw new NotImplementedException("Unexpected specialization type " + specializationType + " for template type " + ClassName);
                }

                results[i] = userTypeName;
            }

            return(results);
        }
Пример #42
0
        /// <summary>
        /// Gets the common base types for all specializations.
        /// </summary>
        /// <param name="factory">The user type factory.</param>
        private string[] GetCommonBaseTypesForAllSpecializations(UserTypeFactory factory)
        {
            // If we don't have specializations, we cannot continue
            if (!SpecializedTypes.Any())
            {
                return(null);
            }

            // Do this for every template argument
            string[] results = new string[NumberOfTemplateArguments];

            for (int i = 0; i < NumberOfTemplateArguments; i++)
            {
                // Get all specializations for current template argument
                Symbol[] specializedSymbols = SpecializedTypes.Select(r => r.templateArgumentsAsSymbols[i]).ToArray();
                TypeOfSpecializationType specializationType = TypeOfSpecializationType.Unmatched;
                UserType commonType = null;

                foreach (Symbol type in specializedSymbols)
                {
                    // Check base type
                    if (type.Tag == Dia2Lib.SymTagEnum.SymTagBaseType || type.Tag == Dia2Lib.SymTagEnum.SymTagEnum)
                    {
                        if (type.Name != "void")
                        {
                            specializationType = TypeOfSpecializationType.Anything;
                            break;
                        }
                        else
                        {
                            specializationType = TypeOfSpecializationType.Variable;
                            continue;
                        }
                    }

                    // Check pointer, array and function types, they inherit Variable
                    if (type.Tag == Dia2Lib.SymTagEnum.SymTagPointerType || type.Tag == Dia2Lib.SymTagEnum.SymTagArrayType || type.Tag == Dia2Lib.SymTagEnum.SymTagFunctionType)
                    {
                        specializationType = TypeOfSpecializationType.Variable;
                        continue;
                    }

                    if (type.Tag != Dia2Lib.SymTagEnum.SymTagUDT)
                    {
                        throw new NotImplementedException("Unexpected symbol type " + type.Tag + ". Symbol name: " + type.Name);
                    }

                    // Check if type has user type
                    UserType userType = type.UserType;

                    if (userType == null)
                    {
                        // TODO: This shouldn't happen
                        //specializationType = TypeOfSpecializationType.Variable;
                        //continue;
                        throw new Exception("This should never happen");
                    }

                    if (specializationType == TypeOfSpecializationType.Variable)
                    {
                        continue;
                    }

                    // If user type is template, get parent template type (one that describes all specializations)
                    var templateType = userType as TemplateUserType;

                    if (templateType != null)
                    {
                        userType = templateType.TemplateType;
                    }

                    if (specializationType == TypeOfSpecializationType.Unmatched)
                    {
                        specializationType = TypeOfSpecializationType.UserType;
                        commonType         = userType;
                        continue;
                    }

                    // Try to find common type for commonType and userType
                    var  commonTypeBases = ExtractAllBaseClasses(commonType);
                    var  userTypeBases   = ExtractAllBaseClasses(userType);
                    bool found           = false;

                    foreach (var ct in commonTypeBases)
                    {
                        foreach (var ut in userTypeBases)
                        {
                            if (ut == ct)
                            {
                                found      = true;
                                commonType = ut;
                                break;
                            }
                        }

                        if (found)
                        {
                            break;
                        }
                    }

                    if (!found)
                    {
                        specializationType = TypeOfSpecializationType.Variable;
                    }
                }

                // Save result based on specialization type
                string userTypeName;
                var    templateCommonType = commonType as TemplateUserType;

                switch (specializationType)
                {
                case TypeOfSpecializationType.Anything:
                    userTypeName = null;
                    break;

                case TypeOfSpecializationType.Variable:
                    userTypeName = "Variable";
                    break;

                case TypeOfSpecializationType.UserType:
                    if (templateCommonType != null)
                    {
                        userTypeName = new TemplateTypeTree(templateCommonType, factory).GetTypeString();
                    }
                    else
                    {
                        userTypeName = commonType.FullClassName;
                    }
                    break;

                case TypeOfSpecializationType.Unmatched:
                default:
                    throw new NotImplementedException("Unexpected specialization type " + specializationType + " for template type " + ClassName);
                }

                results[i] = userTypeName;
            }

            return(results);
        }
Пример #43
0
        /// <summary>
        /// Updates the template arguments (symbols and user types).
        /// </summary>
        /// <param name="factory">The user type factory.</param>
        /// <returns><c>true</c> if all template arguments are resolved as user types.</returns>
        public bool UpdateTemplateArguments(UserTypeFactory factory)
        {
            bool result = true;

            templateArgumentsAsSymbols = ParseTemplateArguments(factory, Module, Symbol.Namespaces.Last()).ToList();
            templateArgumentsAsUserTypes.Clear();
            foreach (Symbol symbol in templateArgumentsAsSymbols)
            {
                // Try to get user type for the symbol
                UserType specializationUserType = null;

                if (!factory.GetUserType(symbol, out specializationUserType))
                {
                    if (symbol.Tag != Dia2Lib.SymTagEnum.SymTagEnum && symbol.Tag != Dia2Lib.SymTagEnum.SymTagUDT)
                    {
                        var typeString = GetSymbolTypeTree(symbol, factory).GetTypeString();

                        specializationUserType = new TemplateArgumentUserType(typeString, symbol);
                    }
                }

                templateArgumentsAsUserTypes.Add(specializationUserType);
                result = result && specializationUserType != null;
            }

            // Enumerate all template arguments as strings
            IEnumerable<Symbol> allTemplateArguments = Enumerable.Empty<Symbol>();

            foreach (string symbolName in Symbol.Namespaces)
            {
                allTemplateArguments = allTemplateArguments.Concat(ParseTemplateArguments(factory, Module, symbolName));
            }

            AllTemplateArguments = allTemplateArguments.Select(s => s.Name).ToList();

            // TODO: Unused types should be removed
            return result;
        }
Пример #44
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PhysicalUserType"/> class.
 /// </summary>
 /// <param name="symbol">The symbol we are generating this user type from.</param>
 /// <param name="xmlType">The XML description of the type.</param>
 /// <param name="nameSpace">The namespace it belongs to.</param>
 /// <param name="factory">User type factory that contains this element.</param>
 public PhysicalUserType(Symbol symbol, XmlType xmlType, string nameSpace, UserTypeFactory factory)
     : base(symbol, xmlType, nameSpace, factory)
 {
 }
Пример #45
0
        /// <summary>
        /// Gets the list of generic type constraints.
        /// </summary>
        /// <param name="factory">The user type factory.</param>
        protected override IEnumerable <string> GetGenericTypeConstraints(UserTypeFactory factory)
        {
            var dict = GetGenericTypeConstraintsDictionary(CreateFactory(factory));

            return(dict.Select(t => string.Format("where {0} : {1}", t.Key, t.Value)));
        }
Пример #46
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TemplateUserType" /> class.
 /// </summary>
 /// <param name="symbol">The symbol we are generating this user type from.</param>
 /// <param name="xmlType">The XML description of the type.</param>
 /// <param name="nameSpace">The namespace it belongs to.</param>
 /// <param name="factory">The user type factory.</param>
 public TemplateUserType(Symbol symbol, XmlType xmlType, string nameSpace, UserTypeFactory factory)
     : base(symbol, xmlType, nameSpace)
 {
     UpdateTemplateArguments(factory);
     ExportStaticFields = false;
 }
Пример #47
0
 /// <summary>
 /// Gets the type tree for the specified type (symbol).
 /// </summary>
 /// <param name="type">The type.</param>
 /// <param name="factory">The user type factory.</param>
 /// <param name="bitLength">Number of bits used for this symbol.</param>
 internal override TypeTree GetSymbolTypeTree(Symbol type, UserTypeFactory factory, int bitLength = 0)
 {
     return base.GetSymbolTypeTree(type, CreateFactory(factory), bitLength);
 }
Пример #48
0
        /// <summary>
        /// Writes the code for this user type to the specified output.
        /// </summary>
        /// <param name="output">The output.</param>
        /// <param name="error">The error text writer.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="indentation">The current indentation.</param>
        public override void WriteCode(IndentedWriter output, TextWriter error, UserTypeFactory factory, UserTypeGenerationFlags generationFlags, int indentation = 0)
        {
            // Declared In Type with namespace
            if (DeclaredInType != null)
            {
                foreach (string innerClass in namespaces)
                {
                    output.WriteLine(indentation, "public static partial class {0}", innerClass);
                    output.WriteLine(indentation++, @"{{");
                }
            }
            else
            {
                output.WriteLine(indentation, "namespace {0}", Namespace);
                output.WriteLine(indentation++, @"{{");
            }

            // Inner types
            foreach (var innerType in InnerTypes)
            {
                output.WriteLine();
                innerType.WriteCode(output, error, factory, generationFlags, indentation);
            }

            // Declared In Type with namespace
            if (DeclaredInType != null)
                foreach (string innerClass in namespaces)
                    output.WriteLine(--indentation, "}}");
            else
                output.WriteLine(--indentation, "}}");
        }
Пример #49
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TemplateUserType" /> class.
 /// </summary>
 /// <param name="symbol">The symbol we are generating this user type from.</param>
 /// <param name="xmlType">The XML description of the type.</param>
 /// <param name="nameSpace">The namespace it belongs to.</param>
 /// <param name="factory">The user type factory.</param>
 public TemplateUserType(Symbol symbol, XmlType xmlType, string nameSpace, UserTypeFactory factory)
     : base(symbol, xmlType, nameSpace)
 {
     UpdateTemplateArguments(factory);
     ExportStaticFields = false;
 }
Пример #50
0
        /// <summary>
        /// Gets the type tree for the base class.
        /// If class has multi inheritance, it can return MultiClassInheritanceTypeTree or SingleClassInheritanceWithInterfacesTypeTree.
        /// </summary>
        /// <param name="error">The error text writer.</param>
        /// <param name="type">The type for which we are getting base class.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="baseClassOffset">The base class offset.</param>
        protected override TypeTree GetBaseClassTypeTree(TextWriter error, Symbol type, UserTypeFactory factory, out int baseClassOffset)
        {
            TypeTree baseType = base.GetBaseClassTypeTree(error, type, factory, out baseClassOffset);

            this.baseClassOffset = baseClassOffset;
            return(baseType);
        }
Пример #51
0
 /// <summary>
 /// Gets the type tree for the specified type (symbol).
 /// </summary>
 /// <param name="type">The type.</param>
 /// <param name="factory">The user type factory.</param>
 /// <param name="bitLength">Number of bits used for this symbol.</param>
 internal override TypeTree GetSymbolTypeTree(Symbol type, UserTypeFactory factory, int bitLength = 0)
 {
     return(base.GetSymbolTypeTree(type, CreateFactory(factory), bitLength));
 }