/// <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="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; } }