Răsfoiți Sursa

Support System.Compiler values in comptime, SetReturnType, Enum helpers

Brian Fiete 3 ani în urmă
părinte
comite
2a55b5c7bb

+ 10 - 0
BeefLibs/corlib/src/Compiler.bf

@@ -259,6 +259,9 @@ namespace System
 		[LinkName("#CallerExpression")]
 		[LinkName("#CallerExpression")]
 		public static extern String[0x00FFFFFF] CallerExpression;
 		public static extern String[0x00FFFFFF] CallerExpression;
 
 
+		[LinkName("#OrigCalleeType")]
+		public static extern Type OrigCalleeType;
+
 		[LinkName("#ProjectName")]
 		[LinkName("#ProjectName")]
 		public static extern String ProjectName;
 		public static extern String ProjectName;
 
 
@@ -287,6 +290,7 @@ namespace System
 				Runtime.FatalError("Assert failed");
 				Runtime.FatalError("Assert failed");
 		}
 		}
 
 
+		static extern void Comptime_SetReturnType(int32 typeId);
 		static extern void* Comptime_MethodBuilder_EmitStr(void* native, StringView str);
 		static extern void* Comptime_MethodBuilder_EmitStr(void* native, StringView str);
 		static extern void* Comptime_CreateMethod(int32 typeId, StringView methodName, Type returnType, MethodFlags methodFlags);
 		static extern void* Comptime_CreateMethod(int32 typeId, StringView methodName, Type returnType, MethodFlags methodFlags);
 		static extern void Comptime_EmitTypeBody(int32 typeId, StringView text);
 		static extern void Comptime_EmitTypeBody(int32 typeId, StringView text);
@@ -309,6 +313,12 @@ namespace System
 			Comptime_EmitTypeBody((.)owner.TypeId, text);
 			Comptime_EmitTypeBody((.)owner.TypeId, text);
 		}
 		}
 
 
+		[Comptime(OnlyFromComptime=true)]
+		public static void SetReturnType(Type type)
+		{
+			Comptime_SetReturnType((.)type.TypeId);
+		}
+
 		[Comptime(OnlyFromComptime=true)]
 		[Comptime(OnlyFromComptime=true)]
 		public static void EmitAddInterface(Type owner, Type iface)
 		public static void EmitAddInterface(Type owner, Type iface)
 		{
 		{

+ 61 - 0
BeefLibs/corlib/src/Enum.bf

@@ -5,6 +5,67 @@ namespace System
 {
 {
 	struct Enum
 	struct Enum
 	{
 	{
+		public static int Count
+		{
+			[Comptime(ConstEval=true)]
+			get
+			{
+				int count = 0;
+				for (var field in Compiler.OrigCalleeType.GetFields())
+				{
+					if (field.IsEnumCase)
+						count++;
+				}
+				return count;
+			}
+		}
+
+		public static var MinValue
+		{
+			[Comptime(ConstEval=true)]
+			get
+			{
+				Compiler.SetReturnType(Compiler.OrigCalleeType);
+
+				int? minValue = null;
+				for (var field in Compiler.OrigCalleeType.GetFields())
+				{
+					if (field.IsEnumCase)
+					{
+						if (minValue == null)
+							minValue = field.[Friend]mFieldData.mData;
+						else
+							minValue = Math.Min(minValue.Value, field.[Friend]mFieldData.mData);
+					}
+				}
+				return minValue.ValueOrDefault;
+			}
+		}
+
+		public static var MaxValue
+		{
+			[Comptime(ConstEval=true)]
+			get
+			{
+				Compiler.SetReturnType(Compiler.OrigCalleeType);
+
+				int? maxValue = null;
+				for (var field in Compiler.OrigCalleeType.GetFields())
+				{
+					if (field.IsEnumCase)
+					{
+						if (maxValue == null)
+							maxValue = field.[Friend]mFieldData.mData;
+						else
+							maxValue = Math.Max(maxValue.Value, field.[Friend]mFieldData.mData);
+					}
+				}
+				if (maxValue == null)
+					return -1;
+				return maxValue.ValueOrDefault;
+			}
+		}
+
 		public static void EnumToString(Type type, String strBuffer, int64 iVal)
 		public static void EnumToString(Type type, String strBuffer, int64 iVal)
 		{
 		{
 			for (var field in type.GetFields())
 			for (var field in type.GetFields())

+ 1 - 0
BeefLibs/corlib/src/Reflection/FieldInfo.bf

@@ -24,6 +24,7 @@ namespace System.Reflection
 	    public int32 MemberOffset => (int32)mFieldData.mData;
 	    public int32 MemberOffset => (int32)mFieldData.mData;
 	    public Type FieldType => Type.[Friend]GetType(mFieldData.mFieldTypeId);
 	    public Type FieldType => Type.[Friend]GetType(mFieldData.mFieldTypeId);
 		public bool IsConst => mFieldData.mFlags.HasFlag(.Const);
 		public bool IsConst => mFieldData.mFlags.HasFlag(.Const);
+		public bool IsEnumCase => mFieldData.mFlags.HasFlag(.EnumCase);
 		public bool IsReadOnly => mFieldData.mFlags.HasFlag(.ReadOnly);
 		public bool IsReadOnly => mFieldData.mFlags.HasFlag(.ReadOnly);
 		public bool IsStatic => mFieldData.mFlags.HasFlag(.Static);
 		public bool IsStatic => mFieldData.mFlags.HasFlag(.Static);
 		public bool IsPublic => (mFieldData.mFlags & .FieldAccessMask) == .Public;
 		public bool IsPublic => (mFieldData.mFlags & .FieldAccessMask) == .Public;

+ 7 - 1
IDEHelper/Compiler/BfCompiler.cpp

@@ -4691,7 +4691,13 @@ void BfCompiler::ProcessAutocompleteTempType()
 		auto propDeclaration = BfNodeDynCast<BfPropertyDeclaration>(fieldDecl);
 		auto propDeclaration = BfNodeDynCast<BfPropertyDeclaration>(fieldDecl);
 		if (propDeclaration != NULL)
 		if (propDeclaration != NULL)
 			autoComplete->CheckProperty(propDeclaration);
 			autoComplete->CheckProperty(propDeclaration);
-		module->ResolveTypeRef(propDef->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_AllowRef);
+
+		if (BfNodeIsA<BfVarTypeReference>(propDef->mTypeRef))
+		{
+			// This is only valid for ConstEval properties
+		}
+		else
+			module->ResolveTypeRef(propDef->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_AllowRef);
 
 
 		if (auto indexerDeclaration = BfNodeDynCast<BfIndexerDeclaration>(propDef->mFieldDeclaration))
 		if (auto indexerDeclaration = BfNodeDynCast<BfIndexerDeclaration>(propDef->mFieldDeclaration))
 		{
 		{

+ 15 - 1
IDEHelper/Compiler/BfDeferEvalChecker.cpp

@@ -1,12 +1,20 @@
 #include "BfDeferEvalChecker.h"
 #include "BfDeferEvalChecker.h"
+#include "BfUtil.h"
 
 
 USING_NS_BF;
 USING_NS_BF;
 
 
 BfDeferEvalChecker::BfDeferEvalChecker()
 BfDeferEvalChecker::BfDeferEvalChecker()
 {
 {
+	mRootNode = NULL;
 	mNeedsDeferEval = false;
 	mNeedsDeferEval = false;
 	mDeferLiterals = true;
 	mDeferLiterals = true;
-	mDeferDelegateBind = true;
+	mDeferDelegateBind = true;	
+}
+
+void BfDeferEvalChecker::Check(BfAstNode* node)
+{
+	SetAndRestoreValue<BfAstNode*> rootNode(mRootNode, node);
+	node->Accept(this);
 }
 }
 
 
 void BfDeferEvalChecker::Visit(BfAstNode* attribExpr)
 void BfDeferEvalChecker::Visit(BfAstNode* attribExpr)
@@ -174,3 +182,9 @@ void BfDeferEvalChecker::Visit(BfDefaultExpression* defaultExpr)
 		mNeedsDeferEval = true;
 		mNeedsDeferEval = true;
 }
 }
 
 
+void BfDeferEvalChecker::Visit(BfVariableDeclaration* varDecl)
+{
+	if (varDecl != mRootNode)
+		mNeedsDeferEval = true;
+}
+

+ 5 - 1
IDEHelper/Compiler/BfDeferEvalChecker.h

@@ -8,6 +8,7 @@ NS_BF_BEGIN
 class BfDeferEvalChecker : public BfStructuralVisitor
 class BfDeferEvalChecker : public BfStructuralVisitor
 {
 {
 public:
 public:
+	BfAstNode* mRootNode;
 	bool mNeedsDeferEval;
 	bool mNeedsDeferEval;
 	bool mDeferDelegateBind;
 	bool mDeferDelegateBind;
 	bool mDeferLiterals;	
 	bool mDeferLiterals;	
@@ -15,6 +16,8 @@ public:
 public:
 public:
 	BfDeferEvalChecker();
 	BfDeferEvalChecker();
 
 
+	void Check(BfAstNode* node);
+
 	virtual void Visit(BfAstNode* node) override;
 	virtual void Visit(BfAstNode* node) override;
 
 
 	virtual void Visit(BfInitializerExpression* collectionInitExpr);
 	virtual void Visit(BfInitializerExpression* collectionInitExpr);
@@ -29,8 +32,9 @@ public:
 	virtual void Visit(BfConditionalExpression* condExpr) override;
 	virtual void Visit(BfConditionalExpression* condExpr) override;
 	virtual void Visit(BfUnaryOperatorExpression* unaryOpExpr) override;
 	virtual void Visit(BfUnaryOperatorExpression* unaryOpExpr) override;
 	virtual void Visit(BfObjectCreateExpression* objCreateExpr) override;
 	virtual void Visit(BfObjectCreateExpression* objCreateExpr) override;
-	virtual void Visit(BfBinaryOperatorExpression* binOpExpr) override; 	
+	virtual void Visit(BfBinaryOperatorExpression* binOpExpr) override;
 	virtual void Visit(BfDefaultExpression* defaultExpr) override;
 	virtual void Visit(BfDefaultExpression* defaultExpr) override;
+	virtual void Visit(BfVariableDeclaration* varDecl) override;
 };
 };
 
 
 
 

+ 65 - 43
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -4630,7 +4630,7 @@ BfTypedValue BfExprEvaluator::LoadProperty(BfAstNode* targetSrc, BfTypedValue ta
 	bool isBaseLookup = (target.mType) && (typeInstance != target.mType);
 	bool isBaseLookup = (target.mType) && (typeInstance != target.mType);
 	if ((isBaseLookup) && (target.mType->IsWrappableType()))
 	if ((isBaseLookup) && (target.mType->IsWrappableType()))
 		isBaseLookup = false;
 		isBaseLookup = false;
-
+	
 	if (prop->mIsStatic)
 	if (prop->mIsStatic)
 		mPropTarget = BfTypedValue(typeInstance);
 		mPropTarget = BfTypedValue(typeInstance);
 	else if (isBaseLookup)
 	else if (isBaseLookup)
@@ -4655,6 +4655,8 @@ BfTypedValue BfExprEvaluator::LoadProperty(BfAstNode* targetSrc, BfTypedValue ta
 	}
 	}
 
 
 	mOrigPropTarget = mPropTarget;
 	mOrigPropTarget = mPropTarget;
+	if (prop->mIsStatic)
+		mOrigPropTarget = target;
 
 
 	if ((flags & BfLookupFieldFlag_IsAnonymous) == 0)
 	if ((flags & BfLookupFieldFlag_IsAnonymous) == 0)
 	{
 	{
@@ -4742,7 +4744,7 @@ BfTypedValue BfExprEvaluator::LoadProperty(BfAstNode* targetSrc, BfTypedValue ta
 
 
 						mPropDef = NULL;
 						mPropDef = NULL;
 						mPropSrc = NULL;
 						mPropSrc = NULL;
-						mOrigPropTarget = NULL;
+						mOrigPropTarget = BfTypedValue();						
 						return result;
 						return result;
 					}
 					}
 				}
 				}
@@ -5780,7 +5782,7 @@ void BfExprEvaluator::ResolveArgValues(BfResolvedArgs& resolvedArgs, BfResolveAr
 			{
 			{
 				BfDeferEvalChecker deferEvalChecker;
 				BfDeferEvalChecker deferEvalChecker;
 				deferEvalChecker.mDeferDelegateBind = false;
 				deferEvalChecker.mDeferDelegateBind = false;
-				argExpr->Accept(&deferEvalChecker);
+				deferEvalChecker.Check(argExpr);				
 				deferParamEval = deferEvalChecker.mNeedsDeferEval;
 				deferParamEval = deferEvalChecker.mNeedsDeferEval;
 			}
 			}
 		}
 		}
@@ -5938,7 +5940,7 @@ void BfExprEvaluator::PerformCallChecks(BfMethodInstance* methodInstance, BfAstN
 		mModule->CheckErrorAttributes(methodInstance->GetOwner(), methodInstance, customAttributes, targetSrc);	
 		mModule->CheckErrorAttributes(methodInstance->GetOwner(), methodInstance, customAttributes, targetSrc);	
 }
 }
 
 
-BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret, BfCreateCallFlags callFlags)
+BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret, BfCreateCallFlags callFlags, BfType* origTargetType)
 {
 {
 // 	static int sCallIdx = 0;
 // 	static int sCallIdx = 0;
 // 	if (!mModule->mCompiler->mIsResolveOnly)
 // 	if (!mModule->mCompiler->mIsResolveOnly)
@@ -6218,8 +6220,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
 					}
 					}
 				}				
 				}				
 				else
 				else
-				{					
-					auto constRet = mModule->mCompiler->mCeMachine->Call(targetSrc, mModule, methodInstance, irArgs, evalFlags, mExpectingType);
+				{
+					CeCallSource ceCallSource(targetSrc);
+					ceCallSource.mOrigCalleeType = origTargetType;
+					auto constRet = mModule->mCompiler->mCeMachine->Call(ceCallSource, mModule, methodInstance, irArgs, evalFlags, mExpectingType);
 					if (constRet)
 					if (constRet)
 					{
 					{
 						auto constant = mModule->mBfIRBuilder->GetConstant(constRet.mValue);
 						auto constant = mModule->mBfIRBuilder->GetConstant(constRet.mValue);
@@ -7131,6 +7135,31 @@ void BfExprEvaluator::AddCallDependencies(BfMethodInstance* methodInstance)
 //TODO: delete argumentsZ
 //TODO: delete argumentsZ
 BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValue& inTarget, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance moduleMethodInstance, BfCreateCallFlags callFlags, SizedArrayImpl<BfResolvedArg>& argValues, BfTypedValue* argCascade)
 BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValue& inTarget, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance moduleMethodInstance, BfCreateCallFlags callFlags, SizedArrayImpl<BfResolvedArg>& argValues, BfTypedValue* argCascade)
 {
 {
+	SetAndRestoreValue<BfEvalExprFlags> prevEvalExprFlag(mBfEvalExprFlags);
+
+	if ((mModule->mAttributeState != NULL) && (mModule->mAttributeState->mCustomAttributes != NULL) && (mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mConstEvalAttributeTypeDef)))
+	{
+		mModule->mAttributeState->mUsed = true;
+		mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
+	}
+	else if ((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_ConstEval) != 0)
+	{
+		mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
+	}
+	else if (((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_Comptime) != 0) && (!mModule->mIsComptimeModule))
+	{
+		if ((mModule->mCurMethodInstance == NULL) || (mModule->mCurMethodInstance->mComptimeFlags == BfComptimeFlag_None))
+			mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
+	}
+
+	if (((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_OnlyFromComptime) != 0) &&
+		((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) &&
+		((mModule->mCurMethodInstance == NULL) || (mModule->mCurMethodInstance->mComptimeFlags == BfComptimeFlag_None)) &&
+		(!mModule->mIsComptimeModule))
+	{
+		mModule->Fail(StrFormat("Method '%s' can only be invoked at comptime. Consider adding [Comptime] to the current method.", mModule->MethodToString(moduleMethodInstance.mMethodInstance).c_str()), targetSrc);
+	}
+
 	bool bypassVirtual = (callFlags & BfCreateCallFlags_BypassVirtual) != 0;
 	bool bypassVirtual = (callFlags & BfCreateCallFlags_BypassVirtual) != 0;
 	bool skipThis = (callFlags & BfCreateCallFlags_SkipThis) != 0;;
 	bool skipThis = (callFlags & BfCreateCallFlags_SkipThis) != 0;;
 
 
@@ -8194,7 +8223,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
 		physCallFlags = (BfCreateCallFlags)(physCallFlags | BfCreateCallFlags_GenericParamThis);
 		physCallFlags = (BfCreateCallFlags)(physCallFlags | BfCreateCallFlags_GenericParamThis);
 
 
 	auto func = moduleMethodInstance.mFunc;	
 	auto func = moduleMethodInstance.mFunc;	
-	BfTypedValue callResult = CreateCall(targetSrc, methodInstance, func, bypassVirtual, irArgs, NULL, physCallFlags);
+	BfTypedValue callResult = CreateCall(targetSrc, methodInstance, func, bypassVirtual, irArgs, NULL, physCallFlags, origTarget.mType);
 
 
 	if ((methodInstance->mMethodDef->mIsNoReturn) && ((mBfEvalExprFlags & BfEvalExprFlags_IsExpressionBody) != 0) && 
 	if ((methodInstance->mMethodDef->mIsNoReturn) && ((mBfEvalExprFlags & BfEvalExprFlags_IsExpressionBody) != 0) && 
 		(mExpectingType != NULL) && (callResult.mType != mExpectingType))
 		(mExpectingType != NULL) && (callResult.mType != mExpectingType))
@@ -10129,41 +10158,13 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
 
 
 	BfTypedValue result;
 	BfTypedValue result;
 	BfTypedValue argCascade;
 	BfTypedValue argCascade;
-	
-	//
-	{
-		SetAndRestoreValue<BfEvalExprFlags> prevEvalExprFlag(mBfEvalExprFlags);
 		
 		
-		if ((mModule->mAttributeState != NULL) && (mModule->mAttributeState->mCustomAttributes != NULL) && (mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mConstEvalAttributeTypeDef)))
-		{
-			mModule->mAttributeState->mUsed = true;
-			mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
-		}
-		else if ((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_ConstEval) != 0)
-		{
-			mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
-		}
-		else if (((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_Comptime) != 0) && (!mModule->mIsComptimeModule))
-		{
-			if ((mModule->mCurMethodInstance == NULL) || (mModule->mCurMethodInstance->mComptimeFlags == BfComptimeFlag_None))
-				mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
-		}		
-
-		if (((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_OnlyFromComptime) != 0) &&
-			((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) &&
-			((mModule->mCurMethodInstance == NULL) || (mModule->mCurMethodInstance->mComptimeFlags == BfComptimeFlag_None)) &&
-			(!mModule->mIsComptimeModule))
-		{
-			mModule->Fail(StrFormat("Method '%s' can only be invoked at comptime. Consider adding [Comptime] to the current method.", mModule->MethodToString(moduleMethodInstance.mMethodInstance).c_str()), targetSrc);
-		}		
-
-		BfCreateCallFlags subCallFlags = BfCreateCallFlags_None;
-		if (bypassVirtual)
-			subCallFlags = (BfCreateCallFlags)(subCallFlags | BfCreateCallFlags_BypassVirtual);
-		if (skipThis)
-			subCallFlags = (BfCreateCallFlags)(subCallFlags | BfCreateCallFlags_SkipThis);
-		result = CreateCall(targetSrc, callTarget, origTarget, methodDef, moduleMethodInstance, subCallFlags, argValues.mResolvedArgs, &argCascade);
-	}
+	BfCreateCallFlags subCallFlags = BfCreateCallFlags_None;
+	if (bypassVirtual)
+		subCallFlags = (BfCreateCallFlags)(subCallFlags | BfCreateCallFlags_BypassVirtual);
+	if (skipThis)
+		subCallFlags = (BfCreateCallFlags)(subCallFlags | BfCreateCallFlags_SkipThis);
+	result = CreateCall(targetSrc, callTarget, origTarget, methodDef, moduleMethodInstance, subCallFlags, argValues.mResolvedArgs, &argCascade);	
 	
 	
 	if (overrideReturnType != NULL)
 	if (overrideReturnType != NULL)
 	{
 	{
@@ -18409,10 +18410,13 @@ BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* m
 		((!mOrigPropTarget.mType->IsGenericParam()) && (mPropTarget.mType->IsInterface())))
 		((!mOrigPropTarget.mType->IsGenericParam()) && (mPropTarget.mType->IsInterface())))
 	{
 	{
 		auto checkType = mOrigPropTarget.mType;
 		auto checkType = mOrigPropTarget.mType;
+
+		if ((checkType->IsNullable()) && (!mPropTarget.mType->IsNullable()))
+			checkType = checkType->GetUnderlyingType();
 		if (checkType->IsPointer())
 		if (checkType->IsPointer())
 			checkType = ((BfPointerType*)checkType)->mElementType;
 			checkType = ((BfPointerType*)checkType)->mElementType;
 		if (checkType->IsWrappableType())
 		if (checkType->IsWrappableType())
-			checkType = mModule->GetWrappedStructType(checkType);
+			checkType = mModule->GetWrappedStructType(checkType);		
 		if ((checkType != NULL) && (checkType->IsTypeInstance()))
 		if ((checkType != NULL) && (checkType->IsTypeInstance()))
 		{
 		{
 			auto activeTypeDef = mModule->GetActiveTypeDef();
 			auto activeTypeDef = mModule->GetActiveTypeDef();
@@ -23707,6 +23711,24 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
 		}
 		}
 
 
 		auto underlyingType = resultType->GetUnderlyingType();
 		auto underlyingType = resultType->GetUnderlyingType();
+
+		if (binaryOp == BfBinaryOp_Subtract)
+		{
+			intptr maxDist = 0;
+			auto resultTypeInstance = resultType->ToTypeInstance();
+			if ((resultTypeInstance != NULL) && (resultTypeInstance->mTypeInfoEx != NULL))
+				maxDist = resultTypeInstance->mTypeInfoEx->mMaxValue - resultTypeInstance->mTypeInfoEx->mMinValue;
+
+			if (maxDist >= 0x80000000UL)
+				resultType = mModule->GetPrimitiveType(BfTypeCode_Int64);
+			else if (maxDist >= 0x8000)
+				resultType = mModule->GetPrimitiveType(BfTypeCode_Int32);
+			else if (maxDist >= 0x80)
+				resultType = mModule->GetPrimitiveType(BfTypeCode_Int16);
+			else
+				resultType = mModule->GetPrimitiveType(BfTypeCode_Int8);
+			underlyingType = resultType;
+		}
 		
 		
 		BfIRValue convResultValue;
 		BfIRValue convResultValue;
 		if (resultTypedValue->mType == resultType)
 		if (resultTypedValue->mType == resultType)
@@ -23728,7 +23750,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
 		else
 		else
 			PerformBinaryOperation(underlyingType, convOtherValue, convResultValue, binaryOp, opToken);
 			PerformBinaryOperation(underlyingType, convOtherValue, convResultValue, binaryOp, opToken);
 		if (mResult.mType == underlyingType)
 		if (mResult.mType == underlyingType)
-			mResult.mType = resultType;			
+			mResult.mType = resultType;
 		return;
 		return;
 	}
 	}
 	
 	

+ 1 - 1
IDEHelper/Compiler/BfExprEvaluator.h

@@ -476,7 +476,7 @@ public:
 	BfTypedValue LookupIdentifier(BfIdentifierNode* identifierNode, bool ignoreInitialError = false, bool* hadError = NULL);
 	BfTypedValue LookupIdentifier(BfIdentifierNode* identifierNode, bool ignoreInitialError = false, bool* hadError = NULL);
 	void AddCallDependencies(BfMethodInstance* methodInstance);
 	void AddCallDependencies(BfMethodInstance* methodInstance);
 	void PerformCallChecks(BfMethodInstance* methodInstance, BfAstNode* targetSrc);
 	void PerformCallChecks(BfMethodInstance* methodInstance, BfAstNode* targetSrc);
-	BfTypedValue CreateCall(BfAstNode* targetSrc, BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret = NULL, BfCreateCallFlags callFlags = BfCreateCallFlags_None);
+	BfTypedValue CreateCall(BfAstNode* targetSrc, BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret = NULL, BfCreateCallFlags callFlags = BfCreateCallFlags_None, BfType* origTargetType = NULL);
 	BfTypedValue CreateCall(BfAstNode* targetSrc, const BfTypedValue& target, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance methodInstance, BfCreateCallFlags callFlags, SizedArrayImpl<BfResolvedArg>& argValues, BfTypedValue* argCascade = NULL);
 	BfTypedValue CreateCall(BfAstNode* targetSrc, const BfTypedValue& target, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance methodInstance, BfCreateCallFlags callFlags, SizedArrayImpl<BfResolvedArg>& argValues, BfTypedValue* argCascade = NULL);
 	BfTypedValue CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target);
 	BfTypedValue CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target);
 	void MakeBaseConcrete(BfTypedValue& typedValue);
 	void MakeBaseConcrete(BfTypedValue& typedValue);

+ 27 - 3
IDEHelper/Compiler/BfModule.cpp

@@ -11348,7 +11348,7 @@ BfIRType BfModule::CurrentAddToConstHolder(BfIRType irType)
 	if (irType.mKind == BfIRTypeData::TypeKind_SizedArray)
 	if (irType.mKind == BfIRTypeData::TypeKind_SizedArray)
 	{
 	{
 		auto sizedArrayType = (BfConstantSizedArrayType*)mBfIRBuilder->GetConstantById(irType.mId);
 		auto sizedArrayType = (BfConstantSizedArrayType*)mBfIRBuilder->GetConstantById(irType.mId);
-		return mCurTypeInstance->GetOrCreateConstHolder()->GetSizedArrayType(CurrentAddToConstHolder(sizedArrayType->mType), sizedArrayType->mLength);
+		return mCurTypeInstance->GetOrCreateConstHolder()->GetSizedArrayType(CurrentAddToConstHolder(sizedArrayType->mType), (int)sizedArrayType->mLength);
 	}
 	}
 
 
 	return irType;
 	return irType;
@@ -12591,7 +12591,9 @@ BfTypedValue BfModule::LoadValue(BfTypedValue typedValue, BfAstNode* refNode, bo
 						}
 						}
 						return result;
 						return result;
 					}
 					}
-					return GetDefaultTypedValue(typedValue.mType);
+
+					if (!mIsComptimeModule)
+						return GetDefaultTypedValue(typedValue.mType);
 				}
 				}
 			}
 			}
 
 
@@ -14654,6 +14656,25 @@ BfTypedValue BfModule::GetCompilerFieldValue(const StringImpl& str)
 				filePath = mCurMethodState->mMixinState->mInjectFilePosition.mFileInstance->mParser->mFileName;
 				filePath = mCurMethodState->mMixinState->mInjectFilePosition.mFileInstance->mParser->mFileName;
 			return BfTypedValue(GetStringObjectValue(GetFileDir(filePath)), ResolveTypeDef(mCompiler->mStringTypeDef));
 			return BfTypedValue(GetStringObjectValue(GetFileDir(filePath)), ResolveTypeDef(mCompiler->mStringTypeDef));
 		}
 		}
+		else if (str == "#CallerTypeName")
+		{
+			String typeName = "";
+			if (mCurMethodState->mMixinState->mMixinMethodInstance)
+				typeName = TypeToString(mCurMethodState->mMixinState->mMixinMethodInstance->GetOwner());
+			return BfTypedValue(GetStringObjectValue(typeName), ResolveTypeDef(mCompiler->mStringTypeDef));
+		}
+		else if (str == "#CallerType")
+		{
+			auto typeType = ResolveTypeDef(mCompiler->mTypeTypeDef);
+			BfType* type = NULL;
+			if (mCurMethodState->mMixinState->mMixinMethodInstance)
+				type = mCurMethodState->mMixinState->mMixinMethodInstance->GetOwner();
+			if (type != NULL)
+			{
+				AddDependency(type, mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
+				return BfTypedValue(CreateTypeDataRef(type), typeType);
+			}
+		}
 		else if (str == "#CallerMemberName")
 		else if (str == "#CallerMemberName")
 		{
 		{
  			String memberName = "";
  			String memberName = "";
@@ -14668,7 +14689,7 @@ BfTypedValue BfModule::GetCompilerFieldValue(const StringImpl& str)
 			if (project != NULL)
 			if (project != NULL)
 				return BfTypedValue(GetStringObjectValue(mProject->mName), ResolveTypeDef(mCompiler->mStringTypeDef));
 				return BfTypedValue(GetStringObjectValue(mProject->mName), ResolveTypeDef(mCompiler->mStringTypeDef));
 		}
 		}
-	}
+	}	
 
 
 	if (str == "#TimeLocal")
 	if (str == "#TimeLocal")
 	{
 	{
@@ -15099,6 +15120,9 @@ BfIRValue BfModule::AllocLocalVariable(BfType* type, const StringImpl& name, boo
 
 
 void BfModule::DoAddLocalVariable(BfLocalVariable* localVar)
 void BfModule::DoAddLocalVariable(BfLocalVariable* localVar)
 {
 {
+	if ((localVar->mName == "maxValue") && (mIsComptimeModule))
+		BF_ASSERT(!localVar->mAddr.IsFake());
+
 	while (localVar->mName.StartsWith('@'))
 	while (localVar->mName.StartsWith('@'))
 	{
 	{
 		localVar->mNamePrefixCount++;
 		localVar->mNamePrefixCount++;

+ 2 - 1
IDEHelper/Compiler/BfModule.h

@@ -109,7 +109,8 @@ enum BfCastFlags
 	BfCastFlags_WarnOnBox = 0x800,
 	BfCastFlags_WarnOnBox = 0x800,
 	BfCastFlags_IsCastCheck = 0x1000,
 	BfCastFlags_IsCastCheck = 0x1000,
 	BfCastFlags_IsConstraintCheck = 0x2000,
 	BfCastFlags_IsConstraintCheck = 0x2000,
-	BfCastFlags_WantsConst = 0x4000
+	BfCastFlags_WantsConst = 0x4000,
+	BfCastFlags_FromComptimeReturn = 0x8000
 };
 };
 
 
 enum BfCastResultFlags : int8
 enum BfCastResultFlags : int8

+ 18 - 4
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -4328,6 +4328,10 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 		ValidateGenericConstraints(validateEntry.mTypeRef, validateEntry.mGenericType, false);
 		ValidateGenericConstraints(validateEntry.mTypeRef, validateEntry.mGenericType, false);
 	}
 	}
 
 
+	bool isRootSystemType = typeInstance->IsInstanceOf(mCompiler->mValueTypeTypeDef) ||
+		typeInstance->IsInstanceOf(mCompiler->mAttributeTypeDef) ||
+		typeInstance->IsInstanceOf(mCompiler->mEnumTypeDef);
+
 	if (!typeInstance->IsBoxed())
 	if (!typeInstance->IsBoxed())
 	{
 	{
 		if ((typeInstance->mCustomAttributes == NULL) && (typeDef->mTypeDeclaration != NULL) && (typeDef->HasCustomAttributes()))
 		if ((typeInstance->mCustomAttributes == NULL) && (typeDef->mTypeDeclaration != NULL) && (typeDef->HasCustomAttributes()))
@@ -4696,7 +4700,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 			{
 			{
 				// Already handled
 				// Already handled
 			}
 			}
-			else if ((fieldDef != NULL) && (fieldDef->GetFieldDeclaration() != NULL) && (fieldDef->GetFieldDeclaration()->mAttributes != NULL) && (!typeInstance->mTypeFailed))
+			else if ((fieldDef != NULL) && (fieldDef->GetFieldDeclaration() != NULL) && (fieldDef->GetFieldDeclaration()->mAttributes != NULL) && (!typeInstance->mTypeFailed) && (!isRootSystemType))
 			{
 			{
 				if (auto propDecl = BfNodeDynCast<BfPropertyDeclaration>(fieldDef->mFieldDeclaration))
 				if (auto propDecl = BfNodeDynCast<BfPropertyDeclaration>(fieldDef->mFieldDeclaration))
 				{
 				{
@@ -4941,7 +4945,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 				if (propDef->IsExpressionBodied())
 				if (propDef->IsExpressionBodied())
 					target = (BfAttributeTargets)(target | BfAttributeTargets_Method);
 					target = (BfAttributeTargets)(target | BfAttributeTargets_Method);
 
 
-				if ((propDef->GetFieldDeclaration()->mAttributes != NULL) && (!typeInstance->mTypeFailed))
+				if ((propDef->GetFieldDeclaration()->mAttributes != NULL) && (!typeInstance->mTypeFailed) && (!isRootSystemType))
 				{
 				{
 					auto customAttrs = GetCustomAttributes(propDef->GetFieldDeclaration()->mAttributes, target);
 					auto customAttrs = GetCustomAttributes(propDef->GetFieldDeclaration()->mAttributes, target);
 					delete customAttrs;
 					delete customAttrs;
@@ -5523,7 +5527,13 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 			typeState.mCurTypeDef = propDef->mDeclaringType;
 			typeState.mCurTypeDef = propDef->mDeclaringType;
 			typeState.mType = typeInstance;
 			typeState.mType = typeInstance;
 			SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
 			SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
-			ResolveTypeRef(propDef->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_AllowRef);
+
+			if (BfNodeIsA<BfVarTypeReference>(propDef->mTypeRef))
+			{
+				// This is only valid for ConstEval properties
+			}
+			else
+				ResolveTypeRef(propDef->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_AllowRef);
 		}
 		}
 	}
 	}
 
 
@@ -14044,7 +14054,11 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 			"Unable to cast '%s' to '%s'" :
 			"Unable to cast '%s' to '%s'" :
 			"Unable to implicitly cast '%s' to '%s'";
 			"Unable to implicitly cast '%s' to '%s'";
 
 
-		String errStr = StrFormat(errStrF, TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str());
+		if ((castFlags & BfCastFlags_FromComptimeReturn) != 0)
+			errStrF = "Comptime return unable to cast '%s' to '%s'";
+
+		String errStr = StrFormat(errStrF, TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str());		
+
 		auto error = Fail(errStr, srcNode);
 		auto error = Fail(errStr, srcNode);
 		if ((error != NULL) && (srcNode != NULL))
 		if ((error != NULL) && (srcNode != NULL))
 		{
 		{

+ 112 - 6
IDEHelper/Compiler/CeMachine.cpp

@@ -1024,6 +1024,19 @@ int CeBuilder::GetCallTableIdx(BeFunction* beFunction, CeOperand* outOperand)
 		callEntry.mFunctionInfo = ceFunctionInfo;
 		callEntry.mFunctionInfo = ceFunctionInfo;
 		*callIdxPtr = (int)mCeFunction->mCallTable.size();
 		*callIdxPtr = (int)mCeFunction->mCallTable.size();
 		mCeFunction->mCallTable.Add(callEntry);
 		mCeFunction->mCallTable.Add(callEntry);
+
+		if (ceFunctionInfo != NULL)
+		{
+			auto callerType = mCeFunction->mCeFunctionInfo->GetOwner();
+			auto calleeType = ceFunctionInfo->GetOwner();
+
+			if ((callerType != NULL) && (calleeType != NULL))
+			{
+				// This will generally already be set, but there are some error cases (such as duplicate type names)
+				//  where this will not be set yet
+				callerType->mModule->AddDependency(calleeType, callerType, BfDependencyMap::DependencyFlag_Calls);
+			}
+		}
 	}
 	}
 	return *callIdxPtr;
 	return *callIdxPtr;
 }
 }
@@ -5148,7 +5161,8 @@ BfTypedValue CeContext::Call(CeCallSource callSource, BfModule* module, BfMethod
 	mCeMachine->mAppendAllocInfo = NULL;
 	mCeMachine->mAppendAllocInfo = NULL;
 
 
 	BfType* returnType = NULL;
 	BfType* returnType = NULL;
-	bool success = Execute(ceFunction, stackPtr - ceFunction->mFrameSize, stackPtr, returnType);
+	BfType* castReturnType = NULL;
+	bool success = Execute(ceFunction, stackPtr - ceFunction->mFrameSize, stackPtr, returnType, castReturnType);
 	memStart = &mMemory[0];
 	memStart = &mMemory[0];
 
 
 	addr_ce retInstAddr = retAddr;
 	addr_ce retInstAddr = retAddr;
@@ -5228,6 +5242,13 @@ BfTypedValue CeContext::Call(CeCallSource callSource, BfModule* module, BfMethod
 		mCallStack = prevCallStack;
 		mCallStack = prevCallStack;
 	}
 	}
 
 
+	if ((castReturnType != NULL) && (returnValue))
+	{
+		auto castedReturnValue = module->Cast(callSource.mRefNode, returnValue, castReturnType, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_FromComptimeReturn));
+		if (castedReturnValue)
+			return castedReturnValue;
+	}
+
 	return returnValue;
 	return returnValue;
 }
 }
 
 
@@ -5486,7 +5507,7 @@ public:
 	}
 	}
 };
 };
 
 
-bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType)
+bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType, BfType*& castReturnType)
 {
 {
 	auto ceModule = mCeMachine->mCeModule;
 	auto ceModule = mCeMachine->mCeModule;
 	CeFunction* ceFunction = startFunction;
 	CeFunction* ceFunction = startFunction;
@@ -6057,6 +6078,14 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
 				_FixVariables();
 				_FixVariables();
 				CeSetAddrVal(stackPtr + 0, reflectType, ptrSize);
 				CeSetAddrVal(stackPtr + 0, reflectType, ptrSize);
 			}
 			}
+			else if (checkFunction->mFunctionKind == CeFunctionKind_SetReturnType)
+			{
+				int32 typeId = *(int32*)((uint8*)stackPtr);
+				if (returnType->IsVar())
+					castReturnType = GetBfType(typeId);
+				else
+					_Fail("Comptime return types can only be set on methods declared with a 'var' return type");
+			}
 			else if (checkFunction->mFunctionKind == CeFunctionKind_EmitTypeBody)
 			else if (checkFunction->mFunctionKind == CeFunctionKind_EmitTypeBody)
 			{
 			{
 				int32 typeId = *(int32*)((uint8*)stackPtr);
 				int32 typeId = *(int32*)((uint8*)stackPtr);
@@ -7621,7 +7650,7 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
 			auto& ceStaticFieldEntry = ceFunction->mStaticFieldTable[tableIdx];
 			auto& ceStaticFieldEntry = ceFunction->mStaticFieldTable[tableIdx];
 			if (ceStaticFieldEntry.mBindExecuteId != mExecuteId)
 			if (ceStaticFieldEntry.mBindExecuteId != mExecuteId)
 			{
 			{
-				if (mStaticCtorExecSet.TryAdd(ceStaticFieldEntry.mTypeId, NULL))
+				if ((mStaticCtorExecSet.TryAdd(ceStaticFieldEntry.mTypeId, NULL)) && (!ceStaticFieldEntry.mName.StartsWith("#")))
 				{
 				{
 					auto bfType = GetBfType(ceStaticFieldEntry.mTypeId);
 					auto bfType = GetBfType(ceStaticFieldEntry.mTypeId);
 					BfTypeInstance* bfTypeInstance = NULL;
 					BfTypeInstance* bfTypeInstance = NULL;
@@ -7667,6 +7696,74 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
 					if (ceStaticFieldEntry.mSize > 0)
 					if (ceStaticFieldEntry.mSize > 0)
 						memset(ptr, 0, ceStaticFieldEntry.mSize);
 						memset(ptr, 0, ceStaticFieldEntry.mSize);
 					staticFieldInfo->mAddr = (addr_ce)(ptr - memStart);
 					staticFieldInfo->mAddr = (addr_ce)(ptr - memStart);
+
+					if (ceStaticFieldEntry.mName.StartsWith("#"))
+					{
+						addr_ce resultAddr = 0;
+
+						if (ceStaticFieldEntry.mName == "#CallerLineNum")
+						{
+							*(int*)ptr = mCurModule->mCurFilePosition.mCurLine;
+						}
+						else if (ceStaticFieldEntry.mName == "#CallerFilePath")
+						{
+							String filePath;
+							if (mCurModule->mCurFilePosition.mFileInstance != NULL)
+								filePath = mCurModule->mCurFilePosition.mFileInstance->mParser->mFileName;
+							resultAddr = GetString(filePath);
+						}
+						else if (ceStaticFieldEntry.mName == "#CallerFileName")
+						{
+							String filePath;
+							if (mCurModule->mCurFilePosition.mFileInstance != NULL)
+								filePath = mCurModule->mCurFilePosition.mFileInstance->mParser->mFileName;
+							resultAddr = GetString(GetFileName(filePath));
+						}
+						else if (ceStaticFieldEntry.mName == "#CallerFileDir")
+						{
+							String filePath;
+							if (mCurModule->mCurFilePosition.mFileInstance != NULL)
+								filePath = mCurModule->mCurFilePosition.mFileInstance->mParser->mFileName;
+							resultAddr = GetString(GetFileDir(filePath));
+						}
+						else if (ceStaticFieldEntry.mName == "#CallerTypeName")
+						{
+							String typeName = "";
+							typeName = mCeMachine->mCeModule->TypeToString(mCallerTypeInstance);
+							resultAddr = GetString(typeName);
+						}
+						else if (ceStaticFieldEntry.mName == "#CallerType")
+						{
+							addr_ce typeAddr = GetReflectType(mCallerTypeInstance->mTypeId);
+							resultAddr = typeAddr;
+						}
+						else if (ceStaticFieldEntry.mName == "#CallerMemberName")
+						{
+							String memberName = mCeMachine->mCeModule->MethodToString(mCallerMethodInstance);
+							resultAddr = GetString(memberName);
+						}
+						else if (ceStaticFieldEntry.mName == "#CallerProject")
+						{
+							BfProject* project = NULL;
+							project = mCallerTypeInstance->mTypeDef->mProject;
+							if (project != NULL)
+								resultAddr = GetString(project->mName);
+						}
+						else if (ceStaticFieldEntry.mName == "#OrigCalleeType")
+						{
+							if (mCurCallSource->mOrigCalleeType != NULL)
+							{
+								addr_ce typeAddr = GetReflectType(mCurCallSource->mOrigCalleeType->mTypeId);
+								resultAddr = typeAddr;
+							}
+						}
+
+						if (resultAddr != 0)
+						{
+							_FixVariables();
+							CeSetAddrVal(memStart + staticFieldInfo->mAddr, resultAddr, ptrSize);
+						}
+					}
 				}
 				}
 
 
 				ceStaticFieldEntry.mAddr = staticFieldInfo->mAddr;
 				ceStaticFieldEntry.mAddr = staticFieldInfo->mAddr;
@@ -9199,11 +9296,15 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction)
 			}
 			}
 			else if (owner->IsInstanceOf(mCeModule->mCompiler->mCompilerTypeDef))
 			else if (owner->IsInstanceOf(mCeModule->mCompiler->mCompilerTypeDef))
 			{
 			{
-				if (methodDef->mName == "Comptime_EmitTypeBody")
+				if (methodDef->mName == "Comptime_SetReturnType")
+				{
+					ceFunction->mFunctionKind = CeFunctionKind_SetReturnType;
+				}
+				else if (methodDef->mName == "Comptime_EmitTypeBody")
 				{
 				{
 					ceFunction->mFunctionKind = CeFunctionKind_EmitTypeBody;
 					ceFunction->mFunctionKind = CeFunctionKind_EmitTypeBody;
 				}
 				}
-				if (methodDef->mName == "Comptime_EmitAddInterface")
+				else if (methodDef->mName == "Comptime_EmitAddInterface")
 				{
 				{
 					ceFunction->mFunctionKind = CeFunctionKind_EmitAddInterface;
 					ceFunction->mFunctionKind = CeFunctionKind_EmitAddInterface;
 				}
 				}
@@ -9493,7 +9594,7 @@ CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance, BfIRValue f
 	CeFunctionInfo* ceFunctionInfo = NULL;
 	CeFunctionInfo* ceFunctionInfo = NULL;
 	CeFunction* ceFunction = NULL;
 	CeFunction* ceFunction = NULL;
 	if (!mFunctions.TryAdd(methodInstance, NULL, &functionInfoPtr))	
 	if (!mFunctions.TryAdd(methodInstance, NULL, &functionInfoPtr))	
-	{
+	{ 
 		ceFunctionInfo = *functionInfoPtr;		
 		ceFunctionInfo = *functionInfoPtr;		
 		BF_ASSERT(ceFunctionInfo->mCeFunction != NULL);		
 		BF_ASSERT(ceFunctionInfo->mCeFunction != NULL);		
 		return ceFunctionInfo->mCeFunction;
 		return ceFunctionInfo->mCeFunction;
@@ -9524,6 +9625,11 @@ CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance, BfIRValue f
 			else
 			else
 			{
 			{
 				ceFunctionInfo = *namedFunctionInfoPtr;
 				ceFunctionInfo = *namedFunctionInfoPtr;
+				if ((ceFunctionInfo->mMethodInstance != NULL) && (ceFunctionInfo->mMethodInstance != methodInstance))
+				{
+					// This ceFunctionInfo is already taken - probably from a name mangling conflict
+					ceFunctionInfo = new CeFunctionInfo();
+				}
 			}
 			}
 		}
 		}
 		else
 		else

+ 13 - 2
IDEHelper/Compiler/CeMachine.h

@@ -329,8 +329,15 @@ public:
 		mCeFunction = NULL;
 		mCeFunction = NULL;
 		mRefCount = 0;
 		mRefCount = 0;
 	}
 	}
-
+	
 	~CeFunctionInfo();
 	~CeFunctionInfo();
+
+	BfTypeInstance* GetOwner()
+	{
+		if (mMethodInstance != NULL)
+			return mMethodInstance->GetOwner();
+		return mMethodRef.mTypeInstance;
+	}
 };
 };
 
 
 class CeCallEntry
 class CeCallEntry
@@ -440,6 +447,7 @@ enum CeFunctionKind
 	CeFunctionKind_Method_GetParamInfo,
 	CeFunctionKind_Method_GetParamInfo,
 	CeFunctionKind_Method_GetGenericArg,
 	CeFunctionKind_Method_GetGenericArg,
 	
 	
+	CeFunctionKind_SetReturnType,
 	CeFunctionKind_EmitTypeBody,
 	CeFunctionKind_EmitTypeBody,
 	CeFunctionKind_EmitAddInterface,
 	CeFunctionKind_EmitAddInterface,
 	CeFunctionKind_EmitMethodEntry,
 	CeFunctionKind_EmitMethodEntry,
@@ -1050,6 +1058,7 @@ public:
 	Kind mKind;
 	Kind mKind;
 	BfAstNode* mRefNode;
 	BfAstNode* mRefNode;
 	BfFieldInstance* mFieldInstance;
 	BfFieldInstance* mFieldInstance;
+	BfType* mOrigCalleeType;
 
 
 public:
 public:
 	CeCallSource(BfAstNode* refNode)
 	CeCallSource(BfAstNode* refNode)
@@ -1057,6 +1066,7 @@ public:
 		mKind = Kind_Unknown;
 		mKind = Kind_Unknown;
 		mRefNode = refNode;
 		mRefNode = refNode;
 		mFieldInstance = NULL;
 		mFieldInstance = NULL;
+		mOrigCalleeType = NULL;
 	}
 	}
 
 
 	CeCallSource()
 	CeCallSource()
@@ -1064,6 +1074,7 @@ public:
 		mKind = Kind_Unknown;
 		mKind = Kind_Unknown;
 		mRefNode = NULL;
 		mRefNode = NULL;
 		mFieldInstance = NULL;
 		mFieldInstance = NULL;
+		mOrigCalleeType = NULL;
 	}
 	}
 };
 };
 
 
@@ -1135,7 +1146,7 @@ public:
 	BfIRValue CreateConstant(BfModule* module, uint8* ptr, BfType* type, BfType** outType = NULL);	
 	BfIRValue CreateConstant(BfModule* module, uint8* ptr, BfType* type, BfType** outType = NULL);	
 	BfIRValue CreateAttribute(BfAstNode* targetSrc, BfModule* module, BfIRConstHolder* constHolder, BfCustomAttribute* customAttribute, addr_ce ceAttrAddr = 0);
 	BfIRValue CreateAttribute(BfAstNode* targetSrc, BfModule* module, BfIRConstHolder* constHolder, BfCustomAttribute* customAttribute, addr_ce ceAttrAddr = 0);
 
 
-	bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType);
+	bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType, BfType*& castReturnType);
 	BfTypedValue Call(CeCallSource callSource, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags, BfType* expectingType);
 	BfTypedValue Call(CeCallSource callSource, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags, BfType* expectingType);
 };
 };
 
 

+ 4 - 0
IDEHelper/Tests/src/Enums.bf

@@ -137,6 +137,10 @@ namespace Tests
 			EnumG eg = .A;
 			EnumG eg = .A;
 			eg.Set(66);
 			eg.Set(66);
 			Test.Assert(eg == .B);
 			Test.Assert(eg == .B);
+
+			var ea = EnumA.MaxValue;
+			Test.Assert(ea == .B);
+			Test.Assert(EnumA.Count == 2);
 		}
 		}
 	}
 	}
 }
 }