Просмотр исходного кода

Made delete work with 'where alloctype(T) : delete' constraint

Brian Fiete 8 месяцев назад
Родитель
Сommit
4fa46b6a92
1 измененных файлов с 60 добавлено и 34 удалено
  1. 60 34
      IDEHelper/Compiler/BfStmtEvaluator.cpp

+ 60 - 34
IDEHelper/Compiler/BfStmtEvaluator.cpp

@@ -4167,47 +4167,73 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt)
 	auto val = CreateValueFromExpression(deleteStmt->mExpression);
 	if (!val)
 		return;
+	
+	auto checkType = val.mType;
+	for (int pass = 0; pass < 2; pass++)
+	{
+		BfGenericParamType* genericType = NULL;
+		if (checkType->IsGenericParam())
+			genericType = (BfGenericParamType*)checkType;
+		if ((checkType->IsPointer()) && (checkType->GetUnderlyingType()->IsGenericParam()))
+			genericType = (BfGenericParamType*)checkType->GetUnderlyingType();
+		if ((genericType != NULL) || (checkType->IsUnspecializedType()))
+		{		
+			BfGenericParamFlags genericParamFlags = BfGenericParamFlag_None;
+			BfType* typeConstraint = NULL;
+			BfGenericParamInstance* genericParam = NULL;
+			if (genericType != NULL)
+				genericParam = GetMergedGenericParamData(genericType, genericParamFlags, typeConstraint);
+			if (genericParam == NULL)
+				GetMergedGenericParamData(checkType, genericParamFlags, typeConstraint);
 
-	if (val.mType->IsAllocType())
-		val.mType = val.mType->GetUnderlyingType();
+			if (typeConstraint != NULL)
+				checkType = typeConstraint;
+			bool canAlwaysDelete = checkType->IsDelegate() || checkType->IsFunction() || checkType->IsArray();
+			if (auto checkTypeInst = checkType->ToTypeInstance())
+			{
+				if ((checkTypeInst->IsInstanceOf(mCompiler->mDelegateTypeDef)) ||
+					(checkTypeInst->IsInstanceOf(mCompiler->mFunctionTypeDef)))
+					canAlwaysDelete = true;
+			}
 
-	BfGenericParamType* genericType = NULL;
-	if (val.mType->IsGenericParam())
-		genericType = (BfGenericParamType*)val.mType;
-	if ((val.mType->IsPointer()) && (val.mType->GetUnderlyingType()->IsGenericParam()))
-		genericType = (BfGenericParamType*)val.mType->GetUnderlyingType();
+			if (!canAlwaysDelete)
+			{
+				bool success = false;
+				if (genericParamFlags & (BfGenericParamFlag_Delete | BfGenericParamFlag_Var))
+					success = true;
+				else if (genericParamFlags & BfGenericParamFlag_StructPtr)
+					success = true;
+				else if ((genericParamFlags & BfGenericParamFlag_Struct) && (checkType->IsPointer()))
+					success = true;
 
-	auto checkType = val.mType;
-	if (genericType != NULL)
-	{
-		BfGenericParamFlags genericParamFlags = BfGenericParamFlag_None;
-		BfType* typeConstraint = NULL;
-		auto genericParam = GetMergedGenericParamData(genericType, genericParamFlags, typeConstraint);
+				if (success)
+				{
+					if ((pass == 1) && (genericType != NULL))
+					{
+						auto genericParamInst = GetGenericParamInstance(genericType);
+						Warn(0, StrFormat("Must add 'where alloctype(%s) : delete' constraint to generic parameter to delete generic type '%s'",
+							genericParamInst->GetGenericParamDef()->mName.c_str(), TypeToString(val.mType).c_str()), deleteStmt->mExpression);
+					}
+					return;
+				}
 
-		if (typeConstraint != NULL)
-			checkType = typeConstraint;
-		bool canAlwaysDelete = checkType->IsDelegate() || checkType->IsFunction() || checkType->IsArray();
-		if (auto checkTypeInst = checkType->ToTypeInstance())
-		{
-			if ((checkTypeInst->IsInstanceOf(mCompiler->mDelegateTypeDef)) ||
-				(checkTypeInst->IsInstanceOf(mCompiler->mFunctionTypeDef)))
-				canAlwaysDelete = true;
+				if (genericType != NULL)
+				{
+					auto genericParamInst = GetGenericParamInstance(genericType);
+					Fail(StrFormat("Must add 'where %s : delete' constraint to generic parameter to delete generic type '%s'",
+						genericParamInst->GetGenericParamDef()->mName.c_str(), TypeToString(val.mType).c_str()), deleteStmt->mExpression);
+					return;
+				}
+			}			
 		}
-
-		if (!canAlwaysDelete)
+		if (pass == 0)
 		{
-			if (genericParamFlags & (BfGenericParamFlag_Delete | BfGenericParamFlag_Var))
-				return;
-			if (genericParamFlags & BfGenericParamFlag_StructPtr)
-				return;
-			if ((genericParamFlags & BfGenericParamFlag_Struct) && (checkType->IsPointer()))
-				return;
-			auto genericParamInst = GetGenericParamInstance(genericType);
-			Fail(StrFormat("Must add 'where %s : delete' constraint to generic parameter to delete generic type '%s'",
-				genericParamInst->GetGenericParamDef()->mName.c_str(), TypeToString(val.mType).c_str()), deleteStmt->mExpression);
-			return;
+			if (checkType->IsAllocType())
+				checkType = checkType->GetUnderlyingType();
+			else
+				break;
 		}
-	}
+	}	
 
 	if (checkType->IsVar())
 	{