/// <summary> /// Gets the type instance for the specified symbol. /// </summary> /// <param name="parentType">The user type from which this symbol comes from (examples: field type, template type...).</param> /// <param name="symbol">The original type.</param> /// <param name="bitLength">Number of bits used for this symbol.</param> internal virtual TypeInstance GetSymbolTypeInstance(UserType parentType, Symbol symbol, int bitLength = 0) { switch (symbol.Tag) { case CodeTypeTag.BuiltinType: if (bitLength == 1) { return(new BasicTypeInstance(CodeNaming, typeof(bool))); } switch (symbol.BasicType) { case BasicType.Bit: case BasicType.Bool: return(new BasicTypeInstance(CodeNaming, typeof(bool))); case BasicType.Char: case BasicType.WChar: case BasicType.Char16: case BasicType.Char32: return(new BasicTypeInstance(CodeNaming, typeof(char))); case BasicType.BSTR: return(new BasicTypeInstance(CodeNaming, typeof(string))); case BasicType.Void: case BasicType.NoType: return(new BasicTypeInstance(CodeNaming, typeof(VoidType))); case BasicType.Float: return(new BasicTypeInstance(CodeNaming, symbol.Size <= 4 ? typeof(float) : typeof(double))); case BasicType.Int: case BasicType.Long: switch (symbol.Size) { case 0: return(new BasicTypeInstance(CodeNaming, typeof(VoidType))); case 1: return(new BasicTypeInstance(CodeNaming, typeof(sbyte))); case 2: return(new BasicTypeInstance(CodeNaming, typeof(short))); case 4: return(new BasicTypeInstance(CodeNaming, typeof(int))); case 8: return(new BasicTypeInstance(CodeNaming, typeof(long))); default: throw new Exception($"Unexpected type length {symbol.Size}"); } case BasicType.UInt: case BasicType.ULong: switch (symbol.Size) { case 0: return(new BasicTypeInstance(CodeNaming, typeof(VoidType))); case 1: return(new BasicTypeInstance(CodeNaming, typeof(byte))); case 2: return(new BasicTypeInstance(CodeNaming, typeof(ushort))); case 4: return(new BasicTypeInstance(CodeNaming, typeof(uint))); case 8: return(new BasicTypeInstance(CodeNaming, typeof(ulong))); default: throw new Exception($"Unexpected type length {symbol.Size}"); } case BasicType.Hresult: return(new BasicTypeInstance(CodeNaming, typeof(uint))); // TODO: Create Hresult type default: throw new Exception($"Unexpected basic type {symbol.BasicType}"); } case CodeTypeTag.Pointer: { Symbol pointerType = symbol.ElementType; UserType pointerUserType; // When exporting pointer from Global Modules, always export types as code pointer. if (parentType is GlobalsUserType && GetUserType(pointerType, out pointerUserType)) { return(new PointerTypeInstance(UserTypeInstance.Create(pointerUserType, this))); } TypeInstance innerType = GetSymbolTypeInstance(parentType, pointerType); if (innerType is TemplateArgumentTypeInstance) { return(new PointerTypeInstance(innerType)); } switch (pointerType.Tag) { case CodeTypeTag.BuiltinType: case CodeTypeTag.Enum: { if ((innerType as BasicTypeInstance)?.BasicType == typeof(VoidType)) { return(new BasicTypeInstance(CodeNaming, typeof(NakedPointer))); } return(new PointerTypeInstance(innerType)); } case CodeTypeTag.Class: case CodeTypeTag.Structure: case CodeTypeTag.Union: return(innerType); default: return(new PointerTypeInstance(innerType)); } } case CodeTypeTag.Enum: case CodeTypeTag.Class: case CodeTypeTag.Structure: case CodeTypeTag.Union: case CodeTypeTag.TemplateArgumentConstant: { // Try to apply transformation on the type UserTypeTransformation transformation = FindTransformation(symbol, parentType); if (transformation != null) { return(new TransformationTypeInstance(CodeNaming, transformation)); } // Try to find user type that represents current type UserType userType; if (GetUserType(symbol, out userType)) { TypeInstance type = UserTypeInstance.Create(userType, this); TemplateTypeInstance genericsTree = type as TemplateTypeInstance; if (genericsTree != null && !genericsTree.CanInstantiate) { return(new VariableTypeInstance(CodeNaming)); } return(type); } // We were unable to find user type. If it is enum, use its basic type if (symbol.Tag == CodeTypeTag.Enum) { return(new BasicTypeInstance(CodeNaming, EnumUserType.GetEnumBasicType(symbol))); } // Is it template argument constant? if (symbol.Tag == CodeTypeTag.TemplateArgumentConstant && symbol.UserType is TemplateArgumentConstantUserType constantArgument) { return(new TemplateArgumentConstantTypeInstance(constantArgument)); } // Fall-back to Variable return(new VariableTypeInstance(CodeNaming)); } case CodeTypeTag.Array: return(new ArrayTypeInstance(GetSymbolTypeInstance(parentType, symbol.ElementType))); case CodeTypeTag.Function: return(new FunctionTypeInstance(CodeNaming)); case CodeTypeTag.BaseClass: { symbol = symbol.Module.GetSymbol(symbol.Name); return(GetSymbolTypeInstance(parentType, symbol, bitLength)); } default: throw new Exception("Unexpected type tag " + symbol.Tag); } }
/// <summary> /// Function that should evaluate <see cref="BaseClass"/> and <see cref="BaseClassOffset"/> properties. /// </summary> protected virtual Tuple <TypeInstance, int> GetBaseClass(Symbol symbol) { Symbol[] baseClasses = symbol.BaseClasses; TypeInstance baseClass = null; int baseClassOffset = 0; // Check if we are exporting only static fields if (ExportOnlyStaticFields) { baseClass = new StaticClassTypeInstance(CodeNaming); return(Tuple.Create(baseClass, baseClassOffset)); } // Check if it is inheriting one of its own template arguments foreach (Symbol baseClassSymbol in baseClasses) { TypeInstance typeInstance = Factory.GetSymbolTypeInstance(this, baseClassSymbol); if (typeInstance is TemplateArgumentTypeInstance) { baseClass = new MultiClassInheritanceTypeInstance(CodeNaming); return(Tuple.Create(baseClass, baseClassOffset)); } } // Check if it is recursively inheriting itself foreach (Symbol baseClassSymbol in baseClasses) { UserType userType; if (Factory.GetUserType(baseClassSymbol, out userType)) { if (userType != this && userType is SpecializedTemplateUserType specialization) { userType = specialization.TemplateType; } if (userType == this || (this is SpecializedTemplateUserType specThis && specThis.TemplateType == userType)) { baseClass = new MultiClassInheritanceTypeInstance(CodeNaming); return(Tuple.Create(baseClass, baseClassOffset)); } } } // Check if it is multi class inheritance if (baseClasses.Length > 1) { int emptyTypes = baseClasses.Count(t => t.IsEmpty); if (emptyTypes == baseClasses.Length - 1) { UserType userType; Symbol baseClassSymbol = baseClasses.First(t => !t.IsEmpty); if (!baseClassSymbol.IsVirtualInheritance && Factory.GetUserType(baseClassSymbol, out userType) && !(Factory.GetSymbolTypeInstance(this, baseClassSymbol) is TemplateArgumentTypeInstance)) { baseClassOffset = baseClassSymbol.Offset; baseClass = new SingleClassInheritanceWithInterfacesTypeInstance(userType, Factory); return(Tuple.Create(baseClass, baseClassOffset)); } } baseClass = new MultiClassInheritanceTypeInstance(CodeNaming); return(Tuple.Create(baseClass, baseClassOffset)); } // Single class inheritance if (baseClasses.Length == 1) { // Check if base class type is virtual inheritance Symbol baseClassType = baseClasses[0]; if (baseClassType.IsVirtualInheritance) { baseClass = new MultiClassInheritanceTypeInstance(CodeNaming); return(Tuple.Create(baseClass, baseClassOffset)); } // Check if base class type should be transformed UserTypeTransformation transformation = Factory.FindTransformation(baseClassType, this); if (transformation != null) { baseClass = new TransformationTypeInstance(CodeNaming, transformation); return(Tuple.Create(baseClass, baseClassOffset)); } // Try to find base class user type UserType baseUserType; if (Factory.GetUserType(baseClassType, out baseUserType)) { baseClass = UserTypeInstance.Create(baseUserType, Factory); TemplateTypeInstance genericsInstance = baseClass as TemplateTypeInstance; if (genericsInstance != null && !genericsInstance.CanInstantiate) { // We cannot instantiate the base class, so we must use UserType as the base class. baseClass = new VariableTypeInstance(CodeNaming, false); return(Tuple.Create(baseClass, baseClassOffset)); } baseClassOffset = baseClassType.Offset; return(Tuple.Create(baseClass, baseClassOffset)); } // We weren't able to find base class user type. Continue the search. return(GetBaseClass(baseClassType)); } // Class doesn't inherit any type baseClass = new VariableTypeInstance(CodeNaming, false); return(Tuple.Create(baseClass, baseClassOffset)); }