Base class for converting symbol name into typed structured tree
        /// <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);
        }
Beispiel #2
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;
            }
        }
        /// <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;
            }
        }