瀏覽代碼

Added reflected TypeDeclaration support for comptime

Brian Fiete 8 月之前
父節點
當前提交
e30972d3af

+ 3 - 3
BeefLibs/corlib/src/Diagnostics/Debug.bf

@@ -25,7 +25,7 @@ namespace System.Diagnostics
 #if !DEBUG
 #if !DEBUG
 		[SkipCall]
 		[SkipCall]
 #endif
 #endif
-		public static void FatalError(String msg = "Fatal error encountered", String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum)
+		public static void FatalError(StringView msg = "Fatal error encountered", String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum)
 		{
 		{
 			String failStr = scope .()..Append(msg, " at line ");
 			String failStr = scope .()..Append(msg, " at line ");
 			line.ToString(failStr);
 			line.ToString(failStr);
@@ -59,7 +59,7 @@ namespace System.Diagnostics
 			Write(sv.[Friend]mPtr, sv.[Friend]mLength);
 			Write(sv.[Friend]mPtr, sv.[Friend]mLength);
 		}
 		}
 
 
-		public static void Write(String fmt, params Span<Object> args)
+		public static void Write(StringView fmt, params Span<Object> args)
 		{
 		{
 			String str = scope String(4096);
 			String str = scope String(4096);
 			str.AppendF(fmt, params args);
 			str.AppendF(fmt, params args);
@@ -86,7 +86,7 @@ namespace System.Diagnostics
 			Write(lineStr.Ptr, lineStr.Length);
 			Write(lineStr.Ptr, lineStr.Length);
 		}
 		}
 
 
-		public static void WriteLine(StringView strFormat, params Object[] args)
+		public static void WriteLine(StringView strFormat, params Span<Object> args)
 		{
 		{
 			String paramStr = scope String(4096);
 			String paramStr = scope String(4096);
 			paramStr.AppendF(strFormat, params args);
 			paramStr.AppendF(strFormat, params args);

+ 191 - 3
BeefLibs/corlib/src/Type.bf

@@ -5,6 +5,163 @@ using System.Diagnostics;
 
 
 namespace System
 namespace System
 {
 {
+	public class TypeDeclaration
+	{
+		protected TypeId mTypeId;
+		protected TypeId mBaseTypeId;
+		protected TypeId mOuterTypeId;
+		protected TypeFlags mTypeFlags;
+		protected TypeCode mTypeCode;
+
+		public TypeCode TypeCode => mTypeCode;
+		public TypeId TypeId => mTypeId;
+		public TypeDeclaration BaseType
+		{
+			get
+			{
+				return Type.[Friend]Comptime_GetTypeDeclarationById((.)mBaseTypeId);
+			}
+		}
+		public TypeDeclaration OuterType
+		{
+			get
+			{
+				return Type.[Friend]Comptime_GetTypeDeclarationById((.)mOuterTypeId);
+			}
+		}
+		public Type ResolvedType => Type.[Friend]Comptime_GetTypeById((.)mTypeId);
+
+		public static Enumerator Types
+		{
+			get
+			{
+				return .();
+			}
+		}
+
+		public void GetFullName(String strBuffer)
+		{
+			strBuffer.Append(Type.[Friend]Comptime_Type_ToString((.)mTypeId));
+		}
+
+		public void GetName(String strBuffer)
+		{
+			strBuffer.Append(Type.[Friend]Comptime_TypeName_ToString((.)mTypeId));
+		}
+
+		public void GetNamespace(String strBuffer)
+		{
+			strBuffer.Append(Type.[Friend]Comptime_Namespace_ToString((.)mTypeId));
+		}
+
+		public bool HasCustomAttribute<T>() where T : Attribute
+		{
+			if (Compiler.IsComptime)
+			{
+				int32 attrIdx = -1;
+				Type attrType = null;
+				repeat
+				{
+					attrType = Type.[Friend]Comptime_Type_GetCustomAttributeType((int32)TypeId, ++attrIdx);
+					if (attrType == typeof(T))
+						return true;
+				}
+				while (attrType != null);
+				return false;
+			}
+			return false;
+		}
+
+		public Result<T> GetCustomAttribute<T>() where T : Attribute
+		{
+			if (Compiler.IsComptime)
+			{
+				int32 attrIdx = -1;
+				Type attrType = null;
+				repeat
+				{
+					attrType = Type.[Friend]Comptime_Type_GetCustomAttributeType((int32)TypeId, ++attrIdx);
+					if (attrType == typeof(T))
+					{
+						T val = ?;
+						if (Type.[Friend]Comptime_Type_GetCustomAttribute((int32)TypeId, attrIdx, &val))
+							return val;
+					}
+				}
+				while (attrType != null);
+				return .Err;
+			}
+			return .Err;
+		}
+
+		[Comptime]
+		public AttributeInfo.ComptimeTypeCustomAttributeEnumerator GetCustomAttributes()
+		{
+			return .((int32)TypeId);
+		}
+
+		public struct Enumerator : IEnumerator<TypeDeclaration>
+		{
+			int32 mCurId;
+
+			public Result<TypeDeclaration> GetNext() mut
+			{
+				while (true)
+				{
+					if (!Compiler.IsComptime)
+					{
+						Runtime.FatalError("Runtime type declarations are not supported");
+					}
+					else
+					{
+						var typeDecl = Type.[Friend]Comptime_GetNextTypeDeclaration(mCurId);
+						if (typeDecl != null)
+						{
+							mCurId = (.)typeDecl.TypeId;
+							return .Ok(typeDecl);
+						}
+						return .Err;
+					}
+				}
+			}
+		}
+
+		public static TypeDeclaration GetById(TypeId typeId) => Type.[Friend]Comptime_GetTypeDeclarationById((.)typeId);
+
+		public static Result<TypeDeclaration> GetByName(StringView typeName)
+		{
+			if (Compiler.IsComptime)
+			{
+				var type = Type.[Friend]Comptime_GetTypeDeclarationByName(typeName);
+				if (type == null)
+					return .Err;
+				return type;
+			}
+
+			return .Err;
+		}
+
+		public override void ToString(String strBuffer)
+		{
+			GetFullName(strBuffer);
+		}
+
+		public bool HasDeclaredField(StringView fieldName)
+		{
+			return Type.[Friend]Comptime_Type_HasDeclaredMember((.)mTypeId, 0, fieldName);
+		}
+
+		public bool HasDeclaredMethod(StringView fieldName)
+		{
+			return Type.[Friend]Comptime_Type_HasDeclaredMember((.)mTypeId, 1, fieldName);
+		}
+
+		public bool HasDeclaredProperty(StringView fieldName)
+		{
+			return Type.[Friend]Comptime_Type_HasDeclaredMember((.)mTypeId, 2, fieldName);
+		}
+	}
+
     struct ClassVData
     struct ClassVData
     {
     {
         public int mType;
         public int mType;
@@ -32,6 +189,21 @@ namespace System
 		protected uint8 mAlign;
 		protected uint8 mAlign;
 		protected uint8 mAllocStackCountOverride;
 		protected uint8 mAllocStackCountOverride;
 
 
+		public TypeDeclaration TypeDeclaration
+		{
+			get
+			{
+				if (!Compiler.IsComptime)
+				{
+					Runtime.FatalError("Runtime type declarations are not supported");
+				}
+				else
+				{
+					return Comptime_GetTypeDeclarationById((.)mTypeId);
+				}
+			}
+		}
+
 		public static TypeId TypeIdEnd
 		public static TypeId TypeIdEnd
 		{
 		{
 			get
 			get
@@ -551,9 +723,15 @@ namespace System
 			public int64 mData;
 			public int64 mData;
 		}
 		}
 
 
+		static extern TypeDeclaration Comptime_GetTypeDeclarationById(int32 typeId);
+		static extern TypeDeclaration Comptime_GetTypeDeclarationByName(StringView name);
+		static extern TypeDeclaration Comptime_GetNextTypeDeclaration(int32 lastTypeId);
+		static extern bool Comptime_Type_HasDeclaredMember(int32 typeId, int32 kind, StringView name);
 		static extern Type Comptime_GetTypeById(int32 typeId);
 		static extern Type Comptime_GetTypeById(int32 typeId);
 		static extern Type Comptime_GetTypeByName(StringView name);
 		static extern Type Comptime_GetTypeByName(StringView name);
 		static extern String Comptime_Type_ToString(int32 typeId);
 		static extern String Comptime_Type_ToString(int32 typeId);
+		static extern String Comptime_TypeName_ToString(int32 typeId);
+		static extern String Comptime_Namespace_ToString(int32 typeId);
 		static extern Type Comptime_GetSpecializedType(Type unspecializedType, Span<Type> typeArgs);
 		static extern Type Comptime_GetSpecializedType(Type unspecializedType, Span<Type> typeArgs);
 		static extern bool Comptime_Type_GetCustomAttribute(int32 typeId, int32 attributeIdx, void* dataPtr);
 		static extern bool Comptime_Type_GetCustomAttribute(int32 typeId, int32 attributeIdx, void* dataPtr);
 		static extern bool Comptime_Field_GetCustomAttribute(int32 typeId, int32 fieldIdx, int32 attributeIdx, void* dataPtr);
 		static extern bool Comptime_Field_GetCustomAttribute(int32 typeId, int32 fieldIdx, int32 attributeIdx, void* dataPtr);
@@ -766,7 +944,7 @@ namespace System
 				while (true)
 				while (true)
 				{
 				{
 					if (Compiler.IsComptime)
 					if (Compiler.IsComptime)
-						Runtime.FatalError("Comptime type enumeration not supported");
+						Runtime.FatalError("Comptime type enumeration not supported. Consider enumerating over TypeDeclaration.Types");
 
 
 					if (mCurId >= sTypeCount)
 					if (mCurId >= sTypeCount)
 						return .Err;
 						return .Err;
@@ -838,7 +1016,13 @@ namespace System
 
 
 namespace System.Reflection
 namespace System.Reflection
 {
 {
-    public struct TypeId : int32 {}
+    public struct TypeId : int32
+	{
+		public override void ToString(String strBuffer)
+		{
+			strBuffer.AppendF($"TypeId#{(int32)this}");
+		}
+	}
 
 
     [Ordered, AlwaysInclude(AssumeInstantiated=true)]
     [Ordered, AlwaysInclude(AssumeInstantiated=true)]
     public class TypeInstance : Type
     public class TypeInstance : Type
@@ -1409,7 +1593,11 @@ namespace System.Reflection
 				{
 				{
 					if (i > 0)
 					if (i > 0)
 						strBuffer.Append(", ");
 						strBuffer.Append(", ");
-					Type.GetType(mResolvedTypeRefs[i]).GetFullName(strBuffer);
+					var genericArg = Type.GetType(mResolvedTypeRefs[i]);
+					if (genericArg != null)
+						genericArg.GetFullName(strBuffer);
+					else
+						strBuffer.Append("???");
 				}
 				}
 				strBuffer.Append('>');
 				strBuffer.Append('>');
 			}
 			}

+ 9 - 0
IDE/mintest/minlib/src/System/Type.bf

@@ -15,6 +15,15 @@ namespace System
         //  including the vtable and interface slots
         //  including the vtable and interface slots
     }
     }
 
 
+	public class TypeDeclaration
+	{
+		protected TypeId mTypeId;
+		protected TypeId mBaseTypeId;
+		protected TypeId mOuterTypeId;
+		protected TypeFlags mTypeFlags;
+		protected TypeCode mTypeCode;
+	}
+
     [Ordered, AlwaysInclude(AssumeInstantiated=true)]
     [Ordered, AlwaysInclude(AssumeInstantiated=true)]
     public class Type
     public class Type
     {
     {

+ 2 - 0
IDEHelper/Compiler/BfCompiler.cpp

@@ -474,6 +474,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
 	mStringTypeDef = NULL;
 	mStringTypeDef = NULL;
 	mStringViewTypeDef = NULL;
 	mStringViewTypeDef = NULL;
 	mThreadStaticAttributeTypeDef = NULL;
 	mThreadStaticAttributeTypeDef = NULL;
+	mTypeTypeDeclDef = NULL;
 	mTypeTypeDef = NULL;
 	mTypeTypeDef = NULL;
 	mUnboundAttributeTypeDef = NULL;
 	mUnboundAttributeTypeDef = NULL;
 	mValueTypeTypeDef = NULL;
 	mValueTypeTypeDef = NULL;
@@ -7326,6 +7327,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
 	mStringViewTypeDef = _GetRequiredType("System.StringView");
 	mStringViewTypeDef = _GetRequiredType("System.StringView");
 	mTestAttributeTypeDef = _GetRequiredType("System.TestAttribute");
 	mTestAttributeTypeDef = _GetRequiredType("System.TestAttribute");
 	mThreadStaticAttributeTypeDef = _GetRequiredType("System.ThreadStaticAttribute");
 	mThreadStaticAttributeTypeDef = _GetRequiredType("System.ThreadStaticAttribute");
+	mTypeTypeDeclDef = _GetRequiredType("System.TypeDeclaration");
 	mTypeTypeDef = _GetRequiredType("System.Type");
 	mTypeTypeDef = _GetRequiredType("System.Type");
 	mUnboundAttributeTypeDef = _GetRequiredType("System.UnboundAttribute");
 	mUnboundAttributeTypeDef = _GetRequiredType("System.UnboundAttribute");
 	mValueTypeTypeDef = _GetRequiredType("System.ValueType");
 	mValueTypeTypeDef = _GetRequiredType("System.ValueType");

+ 1 - 0
IDEHelper/Compiler/BfCompiler.h

@@ -376,6 +376,7 @@ public:
 	BfTypeDef* mEnumTypeDef;
 	BfTypeDef* mEnumTypeDef;
 	BfTypeDef* mStringTypeDef;
 	BfTypeDef* mStringTypeDef;
 	BfTypeDef* mStringViewTypeDef;
 	BfTypeDef* mStringViewTypeDef;
+	BfTypeDef* mTypeTypeDeclDef;
 	BfTypeDef* mTypeTypeDef;
 	BfTypeDef* mTypeTypeDef;
 	BfTypeDef* mValueTypeTypeDef;
 	BfTypeDef* mValueTypeTypeDef;
 	BfTypeDef* mResultTypeDef;
 	BfTypeDef* mResultTypeDef;

+ 175 - 167
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -12005,7 +12005,9 @@ bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifie
 	}
 	}
 
 
 	mModule->AddDependency(type, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
 	mModule->AddDependency(type, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
-	mModule->PopulateType(type);
+
+	// We want to try to avoid triggering OnTypeInit for basic info
+	mModule->PopulateType(type, BfPopulateType_Interfaces_Direct);
 	auto typeInstance = type->ToTypeInstance();
 	auto typeInstance = type->ToTypeInstance();
 
 
 	auto _BoolResult = [&](bool val)
 	auto _BoolResult = [&](bool val)
@@ -12072,214 +12074,220 @@ bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifie
 		auto genericTypeInst = type->ToGenericTypeInstance();
 		auto genericTypeInst = type->ToGenericTypeInstance();
 		_Int32Result((genericTypeInst != NULL) ? (int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size() : 0);
 		_Int32Result((genericTypeInst != NULL) ? (int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size() : 0);
 	}
 	}
-	else if (memberName == "Size")
-		_Int32Result(type->mSize);
-	else if (memberName == "Align")
-		_Int32Result(type->mAlign);
-	else if (memberName == "Stride")
-		_Int32Result(type->GetStride());
-	else if (memberName == "InstanceSize")
-		_Int32Result((typeInstance != NULL) ? typeInstance->mInstSize : type->mSize);
-	else if (memberName == "InstanceAlign")
-		_Int32Result((typeInstance != NULL) ? typeInstance->mInstAlign : type->mSize);
-	else if (memberName == "InstanceStride")
-		_Int32Result((typeInstance != NULL) ? typeInstance->GetInstStride() : type->GetStride());
-	else if (memberName == "UnderlyingType")
+	else
 	{
 	{
-		bool handled = false;
-
-		auto typeType = mModule->ResolveTypeDef(mModule->mCompiler->mTypeTypeDef);
-		if (type->IsGenericParam())
+		// We need full data
+		mModule->PopulateType(type, BfPopulateType_Data);
+
+		if (memberName == "Size")
+			_Int32Result(type->mSize);
+		else if (memberName == "Align")
+			_Int32Result(type->mAlign);
+		else if (memberName == "Stride")
+			_Int32Result(type->GetStride());
+		else if (memberName == "InstanceSize")
+			_Int32Result((typeInstance != NULL) ? typeInstance->mInstSize : type->mSize);
+		else if (memberName == "InstanceAlign")
+			_Int32Result((typeInstance != NULL) ? typeInstance->mInstAlign : type->mSize);
+		else if (memberName == "InstanceStride")
+			_Int32Result((typeInstance != NULL) ? typeInstance->GetInstStride() : type->GetStride());
+		else if (memberName == "UnderlyingType")
 		{
 		{
-			auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)type);
-			if (genericParamInstance->IsEnum())
+			bool handled = false;
+
+			auto typeType = mModule->ResolveTypeDef(mModule->mCompiler->mTypeTypeDef);
+			if (type->IsGenericParam())
 			{
 			{
-				handled = true;
-				mResult = BfTypedValue(mModule->mBfIRBuilder->GetUndefConstValue(mModule->mBfIRBuilder->MapType(typeType)), typeType);
+				auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)type);
+				if (genericParamInstance->IsEnum())
+				{
+					handled = true;
+					mResult = BfTypedValue(mModule->mBfIRBuilder->GetUndefConstValue(mModule->mBfIRBuilder->MapType(typeType)), typeType);
+				}
 			}
 			}
-		}
-		else if (type->IsEnum())
-		{
-			if (type->IsDataIncomplete())
-				mModule->PopulateType(type);
-			auto underlyingType = type->GetUnderlyingType();
-			if (underlyingType != NULL)
+			else if (type->IsEnum())
 			{
 			{
-				handled = true;
-				mModule->AddDependency(underlyingType, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
-				mResult = BfTypedValue(mModule->CreateTypeDataRef(underlyingType), typeType);
+				if (type->IsDataIncomplete())
+					mModule->PopulateType(type);
+				auto underlyingType = type->GetUnderlyingType();
+				if (underlyingType != NULL)
+				{
+					handled = true;
+					mModule->AddDependency(underlyingType, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
+					mResult = BfTypedValue(mModule->CreateTypeDataRef(underlyingType), typeType);
+				}
 			}
 			}
-		}
-
-		if (!handled)
-			mResult = BfTypedValue(mModule->CreateTypeDataRef(mModule->GetPrimitiveType(BfTypeCode_None)), typeType);
-	}
-	else if (memberName == "BitSize")
-	{
-		auto int32Type = mModule->GetPrimitiveType(BfTypeCode_Int32);
-
-		BfType* checkType = type;
-		if (checkType->IsTypedPrimitive())
-			checkType = checkType->GetUnderlyingType();
 
 
-		if (checkType->IsGenericParam())
-		{
-			mResult = mModule->GetDefaultTypedValue(int32Type, false, Beefy::BfDefaultValueKind_Undef);
-			return true;
+			if (!handled)
+				mResult = BfTypedValue(mModule->CreateTypeDataRef(mModule->GetPrimitiveType(BfTypeCode_None)), typeType);
 		}
 		}
-
-		if ((typeInstance != NULL) && (typeInstance->IsEnum()))
+		else if (memberName == "BitSize")
 		{
 		{
-			if (typeInstance->mTypeInfoEx != NULL)
-			{
-				int64 minValue = typeInstance->mTypeInfoEx->mMinValue;
-				if (minValue < 0)
-					minValue = ~minValue;
-				int64 maxValue = typeInstance->mTypeInfoEx->mMaxValue;
-				if (maxValue < 0)
-					maxValue = ~maxValue;
-				uint64 value = (uint64)minValue | (uint64)maxValue;
+			auto int32Type = mModule->GetPrimitiveType(BfTypeCode_Int32);
 
 
-				int bitCount = 1;
-				if (typeInstance->mTypeInfoEx->mMinValue < 0)
-					bitCount++;
+			BfType* checkType = type;
+			if (checkType->IsTypedPrimitive())
+				checkType = checkType->GetUnderlyingType();
 
 
-				while (value >>= 1)
-					bitCount++;
-
-				mModule->AddDependency(typeInstance, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
-				mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, bitCount), int32Type);
+			if (checkType->IsGenericParam())
+			{
+				mResult = mModule->GetDefaultTypedValue(int32Type, false, Beefy::BfDefaultValueKind_Undef);
 				return true;
 				return true;
 			}
 			}
-		}
 
 
-		int bitSize = checkType->mSize * 8;
-		if (checkType->GetTypeCode() == BfTypeCode_Boolean)
-			bitSize = 1;
-		mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, bitSize), int32Type);
-		return true;
-	}
-	else if ((memberName == "MinValue") || (memberName == "MaxValue"))
-	{
-		bool isMin = memberName == "MinValue";
-		bool isBitSize = memberName == "BitSize";
-
-		BfType* checkType = type;
-		if (checkType->IsTypedPrimitive())
-			checkType = checkType->GetUnderlyingType();
+			if ((typeInstance != NULL) && (typeInstance->IsEnum()))
+			{
+				if (typeInstance->mTypeInfoEx != NULL)
+				{
+					int64 minValue = typeInstance->mTypeInfoEx->mMinValue;
+					if (minValue < 0)
+						minValue = ~minValue;
+					int64 maxValue = typeInstance->mTypeInfoEx->mMaxValue;
+					if (maxValue < 0)
+						maxValue = ~maxValue;
+					uint64 value = (uint64)minValue | (uint64)maxValue;
 
 
-		if (checkType->IsGenericParam())
-		{
-			bool foundMatch = false;
+					int bitCount = 1;
+					if (typeInstance->mTypeInfoEx->mMinValue < 0)
+						bitCount++;
 
 
-			auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)checkType);
-			if (((genericParamInstance->mGenericParamFlags & BfGenericParamFlag_Enum) != 0) ||
-				((genericParamInstance->mTypeConstraint != NULL) && (genericParamInstance->mTypeConstraint->IsInstanceOf(mModule->mCompiler->mEnumTypeDef))))
-				foundMatch = true;
+					while (value >>= 1)
+						bitCount++;
 
 
-			else
-			{
-				for (auto constraint : genericParamInstance->mInterfaceConstraints)
-				{
-					if (constraint->IsInstanceOf(mModule->mCompiler->mIIntegerTypeDef))
-						foundMatch = true;
+					mModule->AddDependency(typeInstance, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
+					mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, bitCount), int32Type);
+					return true;
 				}
 				}
 			}
 			}
 
 
-			if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized) && (mModule->mCurMethodInstance->mMethodInfoEx != NULL))
+			int bitSize = checkType->mSize * 8;
+			if (checkType->GetTypeCode() == BfTypeCode_Boolean)
+				bitSize = 1;
+			mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, bitSize), int32Type);
+			return true;
+		}
+		else if ((memberName == "MinValue") || (memberName == "MaxValue"))
+		{
+			bool isMin = memberName == "MinValue";
+			bool isBitSize = memberName == "BitSize";
+
+			BfType* checkType = type;
+			if (checkType->IsTypedPrimitive())
+				checkType = checkType->GetUnderlyingType();
+
+			if (checkType->IsGenericParam())
 			{
 			{
-				for (int genericParamIdx = (int)mModule->mCurMethodInstance->mMethodInfoEx->mMethodGenericArguments.size();
-					genericParamIdx < mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
+				bool foundMatch = false;
+
+				auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)checkType);
+				if (((genericParamInstance->mGenericParamFlags & BfGenericParamFlag_Enum) != 0) ||
+					((genericParamInstance->mTypeConstraint != NULL) && (genericParamInstance->mTypeConstraint->IsInstanceOf(mModule->mCompiler->mEnumTypeDef))))
+					foundMatch = true;
+
+				else
 				{
 				{
-					genericParamInstance = mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
-					if (genericParamInstance->mExternType == type)
+					for (auto constraint : genericParamInstance->mInterfaceConstraints)
 					{
 					{
-						if (((genericParamInstance->mGenericParamFlags & BfGenericParamFlag_Enum) != 0) ||
-							((genericParamInstance->mTypeConstraint != NULL) && (genericParamInstance->mTypeConstraint->IsInstanceOf(mModule->mCompiler->mEnumTypeDef))))
+						if (constraint->IsInstanceOf(mModule->mCompiler->mIIntegerTypeDef))
 							foundMatch = true;
 							foundMatch = true;
 					}
 					}
 				}
 				}
-			}
-
-			if (foundMatch)
-			{
-				mResult = mModule->GetDefaultTypedValue(type, false, Beefy::BfDefaultValueKind_Undef);
-				return true;
-			}
-		}
 
 
-		if (checkType->IsPrimitiveType())
-		{
-			auto primType = (BfPrimitiveType*)checkType;
+				if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized) && (mModule->mCurMethodInstance->mMethodInfoEx != NULL))
+				{
+					for (int genericParamIdx = (int)mModule->mCurMethodInstance->mMethodInfoEx->mMethodGenericArguments.size();
+						genericParamIdx < mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
+					{
+						genericParamInstance = mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
+						if (genericParamInstance->mExternType == type)
+						{
+							if (((genericParamInstance->mGenericParamFlags & BfGenericParamFlag_Enum) != 0) ||
+								((genericParamInstance->mTypeConstraint != NULL) && (genericParamInstance->mTypeConstraint->IsInstanceOf(mModule->mCompiler->mEnumTypeDef))))
+								foundMatch = true;
+						}
+					}
+				}
 
 
-			if ((typeInstance != NULL) && (typeInstance->IsEnum()))
-			{
-				if (typeInstance->mTypeInfoEx != NULL)
+				if (foundMatch)
 				{
 				{
-					mModule->AddDependency(typeInstance, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
-					mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)typeInstance->mTypeInfoEx->mMinValue : (uint64)typeInstance->mTypeInfoEx->mMaxValue), typeInstance);
+					mResult = mModule->GetDefaultTypedValue(type, false, Beefy::BfDefaultValueKind_Undef);
 					return true;
 					return true;
 				}
 				}
 			}
 			}
-			else
+
+			if (checkType->IsPrimitiveType())
 			{
 			{
-				switch (primType->mTypeDef->mTypeCode)
+				auto primType = (BfPrimitiveType*)checkType;
+
+				if ((typeInstance != NULL) && (typeInstance->IsEnum()))
 				{
 				{
-				case BfTypeCode_Int8:
-					mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? -0x80 : 0x7F), primType);
-					return true;
-				case BfTypeCode_Int16:
-					mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? -0x8000 : 0x7FFF), primType);
-					return true;
-				case BfTypeCode_Int32:
-					mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)-0x80000000LL : 0x7FFFFFFF), primType);
-					return true;
-				case BfTypeCode_Int64:
-					mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)-0x8000000000000000LL : (uint64)0x7FFFFFFFFFFFFFFFLL), primType);
-					return true;
-				case BfTypeCode_UInt8:
-				case BfTypeCode_Char8:
-					mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : 0xFF), primType);
-					return true;
-				case BfTypeCode_UInt16:
-				case BfTypeCode_Char16:
-					mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : 0xFFFF), primType);
-					return true;
-				case BfTypeCode_UInt32:
-				case BfTypeCode_Char32:
-					mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : (uint64)0xFFFFFFFFLL), primType);
-					return true;
-				case BfTypeCode_UInt64:
-					mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : (uint64)0xFFFFFFFFFFFFFFFFLL), primType);
-					return true;
-				case BfTypeCode_IntPtr:
-					if (mModule->mSystem->mPtrSize == 8)
-						mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)-0x8000000000000000LL : (uint64)0x7FFFFFFFFFFFFFFFLL), primType);
-					else
+					if (typeInstance->mTypeInfoEx != NULL)
+					{
+						mModule->AddDependency(typeInstance, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
+						mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)typeInstance->mTypeInfoEx->mMinValue : (uint64)typeInstance->mTypeInfoEx->mMaxValue), typeInstance);
+						return true;
+					}
+				}
+				else
+				{
+					switch (primType->mTypeDef->mTypeCode)
+					{
+					case BfTypeCode_Int8:
+						mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? -0x80 : 0x7F), primType);
+						return true;
+					case BfTypeCode_Int16:
+						mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? -0x8000 : 0x7FFF), primType);
+						return true;
+					case BfTypeCode_Int32:
 						mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)-0x80000000LL : 0x7FFFFFFF), primType);
 						mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)-0x80000000LL : 0x7FFFFFFF), primType);
-					return true;
-				case BfTypeCode_UIntPtr:
-					if (mModule->mSystem->mPtrSize == 8)
-						mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : (uint64)0xFFFFFFFFFFFFFFFFLL), primType);
-					else
+						return true;
+					case BfTypeCode_Int64:
+						mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)-0x8000000000000000LL : (uint64)0x7FFFFFFFFFFFFFFFLL), primType);
+						return true;
+					case BfTypeCode_UInt8:
+					case BfTypeCode_Char8:
+						mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : 0xFF), primType);
+						return true;
+					case BfTypeCode_UInt16:
+					case BfTypeCode_Char16:
+						mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : 0xFFFF), primType);
+						return true;
+					case BfTypeCode_UInt32:
+					case BfTypeCode_Char32:
 						mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : (uint64)0xFFFFFFFFLL), primType);
 						mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : (uint64)0xFFFFFFFFLL), primType);
-					return true;
-				default: break;
+						return true;
+					case BfTypeCode_UInt64:
+						mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : (uint64)0xFFFFFFFFFFFFFFFFLL), primType);
+						return true;
+					case BfTypeCode_IntPtr:
+						if (mModule->mSystem->mPtrSize == 8)
+							mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)-0x8000000000000000LL : (uint64)0x7FFFFFFFFFFFFFFFLL), primType);
+						else
+							mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)-0x80000000LL : 0x7FFFFFFF), primType);
+						return true;
+					case BfTypeCode_UIntPtr:
+						if (mModule->mSystem->mPtrSize == 8)
+							mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : (uint64)0xFFFFFFFFFFFFFFFFLL), primType);
+						else
+							mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : (uint64)0xFFFFFFFFLL), primType);
+						return true;
+					default: break;
+					}
 				}
 				}
 			}
 			}
-		}
 
 
-		if (type->IsEnum())
-		{
-			mModule->Fail(StrFormat("'MinValue' cannot be used on enum with payload '%s'", mModule->TypeToString(type).c_str()), propName);
+			if (type->IsEnum())
+			{
+				mModule->Fail(StrFormat("'MinValue' cannot be used on enum with payload '%s'", mModule->TypeToString(type).c_str()), propName);
+			}
+			else
+			{
+				mModule->Fail(StrFormat("'%s' cannot be used on type '%s'", memberName.c_str(), mModule->TypeToString(type).c_str()), propName);
+			}
 		}
 		}
 		else
 		else
-		{
-			mModule->Fail(StrFormat("'%s' cannot be used on type '%s'", memberName.c_str(), mModule->TypeToString(type).c_str()), propName);
-		}
+			return false;
 	}
 	}
-	else
-		return false;
 
 
 	if ((type->IsGenericParam()) && (!mModule->mIsComptimeModule))
 	if ((type->IsGenericParam()) && (!mModule->mIsComptimeModule))
 	{
 	{

+ 118 - 54
IDEHelper/Compiler/BfModule.cpp

@@ -6004,29 +6004,13 @@ void BfModule::CreateSlotOfs(BfTypeInstance* typeInstance)
 		GetConstValue32(virtSlotIdx), slotVarName);
 		GetConstValue32(virtSlotIdx), slotVarName);
 }
 }
 
 
-BfIRValue BfModule::CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, bool forceReflectFields, bool needsTypeData, bool needsTypeNames, bool needsVData)
+BfIRValue BfModule::GetTypeTypeData(BfType* type, BfCreateTypeDataContext& ctx, bool needsTypeData, bool wantsTypeDecl, bool needsTypeNames, int& typeFlags, int& typeCode)
 {
 {
-	if ((IsHotCompile()) && (!type->mDirty))
-		return BfIRValue();
-
-	BfIRValue* irValuePtr = NULL;
-	if (mTypeDataRefs.TryGetValue(type, &irValuePtr))
-	{
-		return *irValuePtr;
-	}
-
 	BfTypeInstance* typeInstance = type->ToTypeInstance();
 	BfTypeInstance* typeInstance = type->ToTypeInstance();
 	BfType* typeInstanceType = ResolveTypeDef(mCompiler->mReflectTypeInstanceTypeDef);
 	BfType* typeInstanceType = ResolveTypeDef(mCompiler->mReflectTypeInstanceTypeDef);
 	mBfIRBuilder->PopulateType(typeInstanceType, BfIRPopulateType_Full_ForceDefinition);
 	mBfIRBuilder->PopulateType(typeInstanceType, BfIRPopulateType_Full_ForceDefinition);
 
 
-	if (typeInstanceType == NULL)
-	{
-		AssertErrorState();
-		return BfIRValue();
-	}
-
-	BfIRValue typeTypeData;
-	int typeFlags = 0;
+	BfIRValue typeTypeData;	 
 	if (needsTypeData)
 	if (needsTypeData)
 	{
 	{
 		BfTypeInstance* typeInstanceTypeInstance = typeInstanceType->ToTypeInstance();
 		BfTypeInstance* typeInstanceTypeInstance = typeInstanceType->ToTypeInstance();
@@ -6069,10 +6053,15 @@ BfIRValue BfModule::CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, b
 		else
 		else
 			typeDataSource = mContext->mBfTypeType;
 			typeDataSource = mContext->mBfTypeType;
 
 
+		if (wantsTypeDecl)
+		{
+			typeDataSource = ResolveTypeDef(mCompiler->mTypeTypeDeclDef)->ToTypeInstance();
+		}
+
 		if ((!mTypeDataRefs.ContainsKey(typeDataSource)) && (typeDataSource != type) && (!mIsComptimeModule))
 		if ((!mTypeDataRefs.ContainsKey(typeDataSource)) && (typeDataSource != type) && (!mIsComptimeModule))
 		{
 		{
 			CreateTypeData(typeDataSource, ctx, false, true, needsTypeNames, true);
 			CreateTypeData(typeDataSource, ctx, false, true, needsTypeNames, true);
-		}
+		}		
 
 
 		typeTypeData = CreateClassVDataGlobal(typeDataSource);
 		typeTypeData = CreateClassVDataGlobal(typeDataSource);
 
 
@@ -6084,40 +6073,6 @@ BfIRValue BfModule::CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, b
 		typeTypeData = mBfIRBuilder->CreateConstNull();
 		typeTypeData = mBfIRBuilder->CreateConstNull();
 	}
 	}
 
 
-	BfType* longType = GetPrimitiveType(BfTypeCode_Int64);
-	BfType* intType = GetPrimitiveType(BfTypeCode_Int32);
-	BfType* intPtrType = GetPrimitiveType(BfTypeCode_IntPtr);
-	BfType* shortType = GetPrimitiveType(BfTypeCode_Int16);
-	BfType* byteType = GetPrimitiveType(BfTypeCode_Int8);
-
-	BfType* typeIdType = intType;
-
-	auto voidPtrType = GetPrimitiveType(BfTypeCode_NullPtr);
-	auto voidPtrIRType = mBfIRBuilder->MapType(voidPtrType);
-	auto voidPtrPtrIRType = mBfIRBuilder->GetPointerTo(voidPtrIRType);
-	auto voidPtrNull = GetDefaultValue(voidPtrType);
-
-	SizedArray<BfIRValue, 4> typeValueParams;
-	GetConstClassValueParam(typeTypeData, typeValueParams);
-
-	FixConstValueParams(mContext->mBfObjectType, typeValueParams);
-	BfIRValue objectData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(mContext->mBfObjectType, BfIRPopulateType_Full), typeValueParams);
-
-	StringT<512> typeDataName;
-	if ((typeInstance != NULL) && (!typeInstance->IsTypeAlias()))
-	{
-		BfMangler::MangleStaticFieldName(typeDataName, mCompiler->GetMangleKind(), typeInstance, "sBfTypeData");
-		if (typeInstance->mTypeDef->IsGlobalsContainer())
-			typeDataName += "`G`" + typeInstance->mTypeDef->mProject->mName;
-	}
-	else
-	{
-		typeDataName += "sBfTypeData.";
-		BfMangler::Mangle(typeDataName, mCompiler->GetMangleKind(), type, mContext->mScratchModule);
-	}
-
-	int typeCode = BfTypeCode_None;
-
 	if (typeInstance != NULL)
 	if (typeInstance != NULL)
 	{
 	{
 		BF_ASSERT((type->mDefineState >= BfTypeDefineState_DefinedAndMethodsSlotted) || mIsComptimeModule);
 		BF_ASSERT((type->mDefineState >= BfTypeDefineState_DefinedAndMethodsSlotted) || mIsComptimeModule);
@@ -6181,7 +6136,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, b
 		typeFlags |= BfTypeFlags_Delegate;
 		typeFlags |= BfTypeFlags_Delegate;
 	if (type->IsFunction())
 	if (type->IsFunction())
 		typeFlags |= BfTypeFlags_Function;
 		typeFlags |= BfTypeFlags_Function;
-	if ((type->mDefineState != BfTypeDefineState_CETypeInit) && (type->WantsGCMarking()))
+	if ((!wantsTypeDecl) && (type->mDefineState != BfTypeDefineState_CETypeInit) && (type->WantsGCMarking()))
 		typeFlags |= BfTypeFlags_WantsMarking;
 		typeFlags |= BfTypeFlags_WantsMarking;
 
 
 	if ((typeInstance != NULL) && (typeInstance->mTypeDef->mIsStatic))
 	if ((typeInstance != NULL) && (typeInstance->mTypeDef->mIsStatic))
@@ -6189,6 +6144,115 @@ BfIRValue BfModule::CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, b
 	if ((typeInstance != NULL) && (typeInstance->mTypeDef->mIsAbstract))
 	if ((typeInstance != NULL) && (typeInstance->mTypeDef->mIsAbstract))
 		typeFlags |= BfTypeFlags_Abstract;
 		typeFlags |= BfTypeFlags_Abstract;
 
 
+	return typeTypeData;
+}
+
+BfIRValue BfModule::CreateTypeDeclData(BfType* type)
+{
+	auto typeDeclType = ResolveTypeDef(mCompiler->mTypeTypeDeclDef)->ToTypeInstance();
+
+	int typeCode = 0;
+	int typeFlags = 0;
+
+	BfCreateTypeDataContext createTypeDataCtx;	
+	BfIRValue typeTypeData = GetTypeTypeData(type, createTypeDataCtx, true, true, true, typeFlags, typeCode);
+
+	SizedArray<BfIRValue, 4> typeValueParams;
+	GetConstClassValueParam(typeTypeData, typeValueParams);
+
+	BfType* longType = GetPrimitiveType(BfTypeCode_Int64);
+	BfType* intType = GetPrimitiveType(BfTypeCode_Int32);
+	BfType* intPtrType = GetPrimitiveType(BfTypeCode_IntPtr);
+	BfType* shortType = GetPrimitiveType(BfTypeCode_Int16);
+	BfType* byteType = GetPrimitiveType(BfTypeCode_Int8);
+
+	BfType* typeIdType = intType;
+
+	auto typeInst = type->ToTypeInstance();
+
+	auto outerType = GetOuterType(type);	
+	BfType* baseType = NULL;
+	if (typeInst != NULL)
+		baseType = typeInst->mBaseType;
+
+	BfIRValue objectData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(mContext->mBfObjectType, BfIRPopulateType_Full), typeValueParams);
+	SizedArray<BfIRValue, 9> typeDataParams =
+	{
+		objectData,
+ 		GetConstValue(type->mTypeId, typeIdType), // mTypeId
+		GetConstValue((baseType != NULL) ? baseType->mTypeId : 0, typeIdType), // mBaseTypeId
+		GetConstValue((outerType != NULL) ? outerType->mTypeId : 0, typeIdType), // mOuterTypeId		
+		GetConstValue(typeFlags, intType), // mTypeFlags
+		GetConstValue(typeCode, byteType), // mTypeCode 		
+	};
+	FixConstValueParams(typeDeclType, typeDataParams);
+	auto typeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(typeDeclType, BfIRPopulateType_Full), typeDataParams);
+
+	String typeDataName = StrFormat("sBfTypeDeclData.%d", type->mTypeId);
+	BfIRValue typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(typeDeclType), true,
+		BfIRLinkageType_External, typeData, typeDataName);
+	mBfIRBuilder->GlobalVar_SetAlignment(typeDataVar, mSystem->mPtrSize);
+
+	return typeDataVar;
+}
+
+BfIRValue BfModule::CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, bool forceReflectFields, bool needsTypeData, bool needsTypeNames, bool needsVData)
+{
+	if ((IsHotCompile()) && (!type->mDirty))
+		return BfIRValue();
+
+	BfIRValue* irValuePtr = NULL;
+	if (mTypeDataRefs.TryGetValue(type, &irValuePtr))
+	{
+		return *irValuePtr;
+	}
+
+	BfTypeInstance* typeInstance = type->ToTypeInstance();
+	BfType* typeInstanceType = ResolveTypeDef(mCompiler->mReflectTypeInstanceTypeDef);
+	mBfIRBuilder->PopulateType(typeInstanceType, BfIRPopulateType_Full_ForceDefinition);
+
+	if (typeInstanceType == NULL)
+	{
+		AssertErrorState();
+		return BfIRValue();
+	}
+
+	int typeCode = BfTypeCode_None;
+	int typeFlags = 0;
+	BfIRValue typeTypeData = GetTypeTypeData(type, ctx, needsTypeData, false, needsTypeNames, typeFlags, typeCode);
+
+	BfType* longType = GetPrimitiveType(BfTypeCode_Int64);
+	BfType* intType = GetPrimitiveType(BfTypeCode_Int32);
+	BfType* intPtrType = GetPrimitiveType(BfTypeCode_IntPtr);
+	BfType* shortType = GetPrimitiveType(BfTypeCode_Int16);
+	BfType* byteType = GetPrimitiveType(BfTypeCode_Int8);
+
+	BfType* typeIdType = intType;
+
+	auto voidPtrType = GetPrimitiveType(BfTypeCode_NullPtr);
+	auto voidPtrIRType = mBfIRBuilder->MapType(voidPtrType);
+	auto voidPtrPtrIRType = mBfIRBuilder->GetPointerTo(voidPtrIRType);
+	auto voidPtrNull = GetDefaultValue(voidPtrType);
+
+	SizedArray<BfIRValue, 4> typeValueParams;
+	GetConstClassValueParam(typeTypeData, typeValueParams);
+
+	FixConstValueParams(mContext->mBfObjectType, typeValueParams);
+	BfIRValue objectData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(mContext->mBfObjectType, BfIRPopulateType_Full), typeValueParams);
+
+	StringT<512> typeDataName;
+	if ((typeInstance != NULL) && (!typeInstance->IsTypeAlias()))
+	{
+		BfMangler::MangleStaticFieldName(typeDataName, mCompiler->GetMangleKind(), typeInstance, "sBfTypeData");
+		if (typeInstance->mTypeDef->IsGlobalsContainer())
+			typeDataName += "`G`" + typeInstance->mTypeDef->mProject->mName;
+	}
+	else
+	{
+		typeDataName += "sBfTypeData.";
+		BfMangler::Mangle(typeDataName, mCompiler->GetMangleKind(), type, mContext->mScratchModule);
+	}
+	
 	int virtSlotIdx = -1;
 	int virtSlotIdx = -1;
 	if ((typeInstance != NULL) && (typeInstance->mSlotNum >= 0))
 	if ((typeInstance != NULL) && (typeInstance->mSlotNum >= 0))
 		virtSlotIdx = typeInstance->mSlotNum + mCompiler->GetVDataPrefixDataCount() + mCompiler->GetDynCastVDataCount();
 		virtSlotIdx = typeInstance->mSlotNum + mCompiler->GetVDataPrefixDataCount() + mCompiler->GetDynCastVDataCount();

+ 2 - 0
IDEHelper/Compiler/BfModule.h

@@ -2093,6 +2093,8 @@ public:
 	void EncodeAttributeData(BfTypeInstance* typeInstance, BfType* argType, BfIRValue arg, SizedArrayImpl<uint8>& data, Dictionary<int, int>& usedStringIdMap);
 	void EncodeAttributeData(BfTypeInstance* typeInstance, BfType* argType, BfIRValue arg, SizedArrayImpl<uint8>& data, Dictionary<int, int>& usedStringIdMap);
 	BfIRValue CreateFieldData(BfFieldInstance* fieldInstance, int customAttrIdx);
 	BfIRValue CreateFieldData(BfFieldInstance* fieldInstance, int customAttrIdx);
 	void CreateSlotOfs(BfTypeInstance* typeInstance);
 	void CreateSlotOfs(BfTypeInstance* typeInstance);
+	BfIRValue GetTypeTypeData(BfType* type, BfCreateTypeDataContext& ctx, bool needsTypeData, bool wantsTypeDecl, bool needsTypeNames, int& typeFlags, int& typeCode);
+	BfIRValue CreateTypeDeclData(BfType* type);
 	BfIRValue CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, bool forceReflectFields, bool needsTypeData, bool needsTypeNames, bool needsVData);
 	BfIRValue CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, bool forceReflectFields, bool needsTypeData, bool needsTypeNames, bool needsVData);
 	BfIRValue FixClassVData(BfIRValue value);
 	BfIRValue FixClassVData(BfIRValue value);
 
 

+ 227 - 6
IDEHelper/Compiler/CeMachine.cpp

@@ -3878,6 +3878,53 @@ addr_ce CeContext::GetConstantData(BeConstant* constant)
 	return (addr_ce)(ptr - mMemory.mVals);
 	return (addr_ce)(ptr - mMemory.mVals);
 }
 }
 
 
+
+addr_ce CeContext::GetReflectTypeDecl(int typeId)
+{
+	addr_ce* addrPtr = NULL;
+	if (!mReflectDeclMap.TryAdd(typeId, NULL, &addrPtr))
+		return *addrPtr;
+
+	auto ceModule = mCeMachine->mCeModule;
+	SetAndRestoreValue<bool> ignoreWrites(ceModule->mBfIRBuilder->mIgnoreWrites, false);
+
+	if (ceModule->mContext->mBfTypeType == NULL)
+		ceModule->mContext->ReflectInit();
+
+	if ((uintptr)typeId >= (uintptr)mCeMachine->mCeModule->mContext->mTypes.mSize)
+		return 0;
+	auto bfType = mCeMachine->mCeModule->mContext->mTypes[typeId];
+	if (bfType == NULL)
+		return 0;
+
+	if (bfType->mDefineState < BfTypeDefineState_HasInterfaces_Direct)
+		ceModule->PopulateType(bfType, BfPopulateType_Interfaces_Direct);
+	
+	BfCreateTypeDataContext createTypeDataCtx;
+	auto irData = ceModule->CreateTypeDeclData(bfType);
+
+	BeValue* beValue = NULL;
+	if (auto constant = mCeMachine->mCeModule->mBfIRBuilder->GetConstant(irData))
+	{
+		if (constant->mConstType == BfConstType_BitCast)
+		{
+			auto bitcast = (BfConstantBitCast*)constant;
+			constant = mCeMachine->mCeModule->mBfIRBuilder->GetConstantById(bitcast->mTarget);
+		}
+		if (constant->mConstType == BfConstType_GlobalVar)
+		{
+			auto globalVar = (BfGlobalVar*)constant;
+			beValue = mCeMachine->mCeModule->mBfIRBuilder->mBeIRCodeGen->GetBeValue(globalVar->mStreamId);
+		}
+	}
+
+	if (auto constant = BeValueDynCast<BeConstant>(beValue))
+		*addrPtr = GetConstantData(constant);
+
+	// We need to 'get' again because we might have resized
+	return *addrPtr;
+}
+
 addr_ce CeContext::GetReflectType(int typeId)
 addr_ce CeContext::GetReflectType(int typeId)
 {
 {
 	addr_ce* addrPtr = NULL;
 	addr_ce* addrPtr = NULL;
@@ -3924,7 +3971,7 @@ addr_ce CeContext::GetReflectType(int typeId)
 	return *addrPtr;
 	return *addrPtr;
 }
 }
 
 
-addr_ce CeContext::GetReflectType(const String& typeName)
+addr_ce CeContext::GetReflectType(const String& typeName, bool useDeclaration)
 {
 {
 	if (mCeMachine->mTempParser == NULL)
 	if (mCeMachine->mTempParser == NULL)
 	{
 	{
@@ -3964,7 +4011,7 @@ addr_ce CeContext::GetReflectType(const String& typeName)
 
 
 	if (type == NULL)
 	if (type == NULL)
 		return 0;
 		return 0;
-	return GetReflectType(type->mTypeId);
+	return useDeclaration ? GetReflectTypeDecl(type->mTypeId) : GetReflectType(type->mTypeId);
 }
 }
 
 
 int CeContext::GetTypeIdFromType(addr_ce typeAddr)
 int CeContext::GetTypeIdFromType(addr_ce typeAddr)
@@ -6036,6 +6083,110 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
 					OutputDebugStrF("Debug Val: %lld %llX\n", intVal, intVal);
 					OutputDebugStrF("Debug Val: %lld %llX\n", intVal, intVal);
 				}
 				}
 			}
 			}
+			else if (checkFunction->mFunctionKind == CeFunctionKind_GetReflectTypeDeclById)
+			{
+				int32 typeId = *(int32*)((uint8*)stackPtr + ceModule->mSystem->mPtrSize);
+				auto reflectType = GetReflectTypeDecl(typeId);
+				_FixVariables();
+				CeSetAddrVal(stackPtr + 0, reflectType, ptrSize);
+			}
+			else if (checkFunction->mFunctionKind == CeFunctionKind_GetReflectTypeDeclByName)
+			{
+				addr_ce strViewPtr = *(addr_ce*)((uint8*)stackPtr + ptrSize);
+				String typeName;
+				if (!GetStringFromStringView(strViewPtr, typeName))
+				{
+					_Fail("Invalid StringView");
+					return false;
+				}
+				auto reflectType = GetReflectType(typeName, true);
+				_FixVariables();
+				CeSetAddrVal(stackPtr + 0, reflectType, ptrSize);
+			}
+			else if (checkFunction->mFunctionKind == CeFunctionKind_GetReflectNextTypeDecl)
+			{
+				int32 typeId = *(int32*)((uint8*)stackPtr + ceModule->mSystem->mPtrSize);
+
+				addr_ce reflectType = 0;
+
+				auto context = mCeMachine->mCeModule->mContext;
+				while (true)
+				{
+					typeId++;
+					if (typeId >= mCeMachine->mCeModule->mContext->mTypes.mSize)
+						break;
+					auto bfType = mCeMachine->mCeModule->mContext->mTypes[typeId];
+					if (bfType != NULL)
+					{
+						if (bfType->IsOnDemand())
+							continue;
+						if (bfType->IsBoxed())
+							continue;
+						if (bfType->IsArray())
+							continue;
+						if (bfType->IsNullable())
+							continue;
+						
+						auto bfTypeInst = bfType->ToTypeInstance();
+						if (bfTypeInst == NULL)
+							continue;
+						
+						if (bfTypeInst->mTypeDef->mTypeDeclaration == NULL)
+							continue;
+
+						if (bfTypeInst->IsGenericTypeInstance())
+						{
+							if (!bfTypeInst->IsUnspecializedType())
+								continue;								
+							if (bfTypeInst->IsUnspecializedTypeVariation())
+								continue;							
+						}
+						
+						auto curProject = mCurModule->mProject;
+						auto declProject = bfTypeInst->mTypeDef->mProject;
+
+						if ((declProject != curProject) && (!curProject->HasDependency(declProject)))
+							continue;
+															
+						reflectType = GetReflectTypeDecl(typeId);
+						if (reflectType != 0)
+							break;						
+					}
+				}
+				
+				_FixVariables();
+				CeSetAddrVal(stackPtr + 0, reflectType, ptrSize);
+			}
+			else if (checkFunction->mFunctionKind == CeFunctionKind_HasDeclaredMember)
+			{
+				int32 typeId = *(int32*)((uint8*)stackPtr + 1);
+				int32 memberKind = *(int32*)((uint8*)stackPtr + 1 + 4);
+				addr_ce strViewPtr = *(addr_ce*)((uint8*)stackPtr + 1 + 4 + 4);				
+
+				bool hasMember;
+
+				String typeName;
+				if (!GetStringFromStringView(strViewPtr, typeName))
+				{
+					_Fail("Invalid StringView");
+					return false;
+				}
+
+				BfType* type = GetBfType(typeId);
+				if ((type != NULL) && (type->IsTypeInstance()))
+				{					
+					auto typeInst = type->ToTypeInstance();
+					typeInst->mTypeDef->PopulateMemberSets();
+					if (memberKind == 0) // Field					
+						hasMember = typeInst->mTypeDef->mFieldSet.ContainsWith((StringImpl&)typeName);
+					else if (memberKind == 1) // Method
+						hasMember = typeInst->mTypeDef->mMethodSet.ContainsWith((StringImpl&)typeName);
+					else if (memberKind == 2) // Property
+						hasMember = typeInst->mTypeDef->mPropertySet.ContainsWith((StringImpl&)typeName);
+				}
+
+				*(addr_ce*)(stackPtr + 0) = hasMember;
+			}
 			else if (checkFunction->mFunctionKind == CeFunctionKind_GetReflectType)
 			else if (checkFunction->mFunctionKind == CeFunctionKind_GetReflectType)
 			{
 			{
 				addr_ce objAddr = *(addr_ce*)((uint8*)stackPtr + ceModule->mSystem->mPtrSize);
 				addr_ce objAddr = *(addr_ce*)((uint8*)stackPtr + ceModule->mSystem->mPtrSize);
@@ -6062,7 +6213,7 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
 					_Fail("Invalid StringView");
 					_Fail("Invalid StringView");
 					return false;
 					return false;
 				}
 				}
-				auto reflectType = GetReflectType(typeName);
+				auto reflectType = GetReflectType(typeName, false);
 				_FixVariables();
 				_FixVariables();
 				CeSetAddrVal(stackPtr + 0, reflectType, ptrSize);
 				CeSetAddrVal(stackPtr + 0, reflectType, ptrSize);
 			}
 			}
@@ -6089,9 +6240,54 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
 
 
 				SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCeMachine->mCeModule->mCurMethodInstance, mCallerMethodInstance);
 				SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCeMachine->mCeModule->mCurMethodInstance, mCallerMethodInstance);
 				SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCeMachine->mCeModule->mCurTypeInstance, mCallerTypeInstance);
 				SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCeMachine->mCeModule->mCurTypeInstance, mCallerTypeInstance);
-				CeSetAddrVal(stackPtr + 0, GetString(mCeMachine->mCeModule->TypeToString(type)), ptrSize);
+
+				String typeName;
+				mCeMachine->mCeModule->DoTypeToString(typeName, type, BfTypeNameFlags_None);
+				CeSetAddrVal(stackPtr + 0, GetString(typeName), ptrSize);
 				_FixVariables();
 				_FixVariables();
 			}
 			}
+			else if (checkFunction->mFunctionKind == CeFunctionKind_TypeName_ToString)
+			{
+				int32 typeId = *(int32*)((uint8*)stackPtr + ptrSize);
+
+				BfType* type = GetBfType(typeId);
+				bool success = false;
+				if (type == NULL)
+				{
+					_Fail("Invalid type");
+					return false;
+				}
+
+				String str;
+				if (auto typeInst = type->ToTypeInstance())
+					str = typeInst->mTypeDef->mName->ToString();
+
+				SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCeMachine->mCeModule->mCurMethodInstance, mCallerMethodInstance);
+				SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCeMachine->mCeModule->mCurTypeInstance, mCallerTypeInstance);
+				CeSetAddrVal(stackPtr + 0, GetString(str), ptrSize);
+				_FixVariables();
+				}
+			else if (checkFunction->mFunctionKind == CeFunctionKind_Namespace_ToString)
+			{
+				int32 typeId = *(int32*)((uint8*)stackPtr + ptrSize);
+
+				BfType* type = GetBfType(typeId);
+				bool success = false;
+				if (type == NULL)
+				{
+					_Fail("Invalid type");
+					return false;
+				}
+
+				String str;
+				if (auto typeInst = type->ToTypeInstance())
+					typeInst->mTypeDef->mNamespace.ToString(str);
+
+				SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCeMachine->mCeModule->mCurMethodInstance, mCallerMethodInstance);
+				SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCeMachine->mCeModule->mCurTypeInstance, mCallerTypeInstance);
+				CeSetAddrVal(stackPtr + 0, GetString(str), ptrSize);
+				_FixVariables();
+				}
 			else if (checkFunction->mFunctionKind == CeFunctionKind_Type_GetCustomAttribute)
 			else if (checkFunction->mFunctionKind == CeFunctionKind_Type_GetCustomAttribute)
 			{
 			{
 				int32 typeId = *(int32*)((uint8*)stackPtr + 1);
 				int32 typeId = *(int32*)((uint8*)stackPtr + 1);
@@ -9650,7 +9846,23 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction)
 			}
 			}
 			else if (owner->IsInstanceOf(mCeModule->mCompiler->mTypeTypeDef))
 			else if (owner->IsInstanceOf(mCeModule->mCompiler->mTypeTypeDef))
 			{
 			{
-				if (methodDef->mName == "Comptime_GetTypeById")
+				if (methodDef->mName == "Comptime_GetTypeDeclarationById")
+				{
+					ceFunction->mFunctionKind = CeFunctionKind_GetReflectTypeDeclById;
+				}
+				if (methodDef->mName == "Comptime_GetTypeDeclarationByName")
+				{
+					ceFunction->mFunctionKind = CeFunctionKind_GetReflectTypeDeclByName;
+				}
+				else if (methodDef->mName == "Comptime_GetNextTypeDeclaration")
+				{
+					ceFunction->mFunctionKind = CeFunctionKind_GetReflectNextTypeDecl;
+				}
+				else if (methodDef->mName == "Comptime_Type_HasDeclaredMember")
+				{
+					ceFunction->mFunctionKind = CeFunctionKind_HasDeclaredMember;
+				}
+				else if (methodDef->mName == "Comptime_GetTypeById")
 				{
 				{
 					ceFunction->mFunctionKind = CeFunctionKind_GetReflectTypeById;
 					ceFunction->mFunctionKind = CeFunctionKind_GetReflectTypeById;
 				}
 				}
@@ -9666,6 +9878,14 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction)
 				{
 				{
 					ceFunction->mFunctionKind = CeFunctionKind_Type_ToString;
 					ceFunction->mFunctionKind = CeFunctionKind_Type_ToString;
 				}
 				}
+				else if (methodDef->mName == "Comptime_TypeName_ToString")
+				{
+					ceFunction->mFunctionKind = CeFunctionKind_TypeName_ToString;
+				}
+				else if (methodDef->mName == "Comptime_Namespace_ToString")
+				{
+					ceFunction->mFunctionKind = CeFunctionKind_Namespace_ToString;
+				}
 				else if (methodDef->mName == "Comptime_Type_GetCustomAttribute")
 				else if (methodDef->mName == "Comptime_Type_GetCustomAttribute")
 				{
 				{
 					ceFunction->mFunctionKind = CeFunctionKind_Type_GetCustomAttribute;
 					ceFunction->mFunctionKind = CeFunctionKind_Type_GetCustomAttribute;
@@ -10259,7 +10479,8 @@ CeContext* CeMachine::AllocContext()
 void CeMachine::ReleaseContext(CeContext* ceContext)
 void CeMachine::ReleaseContext(CeContext* ceContext)
 {
 {
 	ceContext->mStringMap.Clear();
 	ceContext->mStringMap.Clear();
-	ceContext->mReflectMap.Clear();
+	ceContext->mReflectDeclMap.Clear();
+	ceContext->mReflectMap.Clear();	
 	ceContext->mConstDataMap.Clear();
 	ceContext->mConstDataMap.Clear();
 	ceContext->mMemory.Clear();
 	ceContext->mMemory.Clear();
 	if (ceContext->mMemory.mAllocSize > BF_CE_MAX_CARRYOVER_MEMORY)
 	if (ceContext->mMemory.mAllocSize > BF_CE_MAX_CARRYOVER_MEMORY)

+ 10 - 2
IDEHelper/Compiler/CeMachine.h

@@ -428,12 +428,18 @@ enum CeFunctionKind
 	CeFunctionKind_DynCheckFailed,
 	CeFunctionKind_DynCheckFailed,
 	CeFunctionKind_FatalError,
 	CeFunctionKind_FatalError,
 	CeFunctionKind_DebugWrite,
 	CeFunctionKind_DebugWrite,
-	CeFunctionKind_DebugWrite_Int,
+	CeFunctionKind_DebugWrite_Int,	
+	CeFunctionKind_GetReflectTypeDeclById,
+	CeFunctionKind_GetReflectTypeDeclByName,
+	CeFunctionKind_GetReflectNextTypeDecl,
+	CeFunctionKind_HasDeclaredMember,
 	CeFunctionKind_GetReflectType,
 	CeFunctionKind_GetReflectType,
 	CeFunctionKind_GetReflectTypeById,
 	CeFunctionKind_GetReflectTypeById,
 	CeFunctionKind_GetReflectTypeByName,
 	CeFunctionKind_GetReflectTypeByName,
 	CeFunctionKind_GetReflectSpecializedType,
 	CeFunctionKind_GetReflectSpecializedType,
 	CeFunctionKind_Type_ToString,
 	CeFunctionKind_Type_ToString,
+	CeFunctionKind_TypeName_ToString,
+	CeFunctionKind_Namespace_ToString,
 	CeFunctionKind_Type_GetCustomAttribute,
 	CeFunctionKind_Type_GetCustomAttribute,
 	CeFunctionKind_Field_GetCustomAttribute,
 	CeFunctionKind_Field_GetCustomAttribute,
 	CeFunctionKind_Method_GetCustomAttribute,
 	CeFunctionKind_Method_GetCustomAttribute,
@@ -1105,6 +1111,7 @@ public:
 	int mStackSize;
 	int mStackSize;
 	Dictionary<int, addr_ce> mStringMap;
 	Dictionary<int, addr_ce> mStringMap;
 	Dictionary<int, addr_ce> mReflectMap;
 	Dictionary<int, addr_ce> mReflectMap;
+	Dictionary<int, addr_ce> mReflectDeclMap;
 	Dictionary<Val128, addr_ce> mConstDataMap;
 	Dictionary<Val128, addr_ce> mConstDataMap;
 	HashSet<int> mStaticCtorExecSet;
 	HashSet<int> mStaticCtorExecSet;
 	Dictionary<String, CeStaticFieldInfo> mStaticFieldMap;
 	Dictionary<String, CeStaticFieldInfo> mStaticFieldMap;
@@ -1137,8 +1144,9 @@ public:
 	uint8* CeMalloc(int size);
 	uint8* CeMalloc(int size);
 	bool CeFree(addr_ce addr);
 	bool CeFree(addr_ce addr);
 	addr_ce CeAllocArray(BfArrayType* arrayType, int count, addr_ce& elemsAddr);
 	addr_ce CeAllocArray(BfArrayType* arrayType, int count, addr_ce& elemsAddr);
+	addr_ce GetReflectTypeDecl(int typeId);	
 	addr_ce GetReflectType(int typeId);
 	addr_ce GetReflectType(int typeId);
-	addr_ce GetReflectType(const String& typeName);
+	addr_ce GetReflectType(const String& typeName, bool useDeclaration);
 	int GetTypeIdFromType(addr_ce typeAddr);
 	int GetTypeIdFromType(addr_ce typeAddr);
 	addr_ce GetReflectSpecializedType(addr_ce unspecializedType, addr_ce typeArgsSpanAddr);
 	addr_ce GetReflectSpecializedType(addr_ce unspecializedType, addr_ce typeArgsSpanAddr);
 	addr_ce GetString(int stringId);
 	addr_ce GetString(int stringId);