1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 03:52:19 +02:00

Added 'interface' and 'enum' constraints

This commit is contained in:
Brian Fiete 2020-11-10 05:44:23 -08:00
parent f63b9236d0
commit f41365a58e
8 changed files with 110 additions and 27 deletions

View file

@ -363,6 +363,9 @@ bool BfModule::AreConstraintsSubset(BfGenericParamInstance* checkInner, BfGeneri
{
// If the outer had a type flag and the inner has a specific type constraint, then see if those are compatible
auto outerFlags = checkOuter->mGenericParamFlags;
if ((outerFlags & BfGenericParamFlag_Enum) != 0)
outerFlags |= BfGenericParamFlag_Struct;
if (checkOuter->mTypeConstraint != NULL)
{
if (checkOuter->mTypeConstraint->IsStruct())
@ -371,9 +374,17 @@ bool BfModule::AreConstraintsSubset(BfGenericParamInstance* checkInner, BfGeneri
outerFlags |= BfGenericParamFlag_StructPtr;
else if (checkOuter->mTypeConstraint->IsObject())
outerFlags |= BfGenericParamFlag_Class;
else if (checkOuter->mTypeConstraint->IsEnum())
outerFlags |= BfGenericParamFlag_Enum | BfGenericParamFlag_Struct;
else if (checkOuter->mTypeConstraint->IsInterface())
outerFlags |= BfGenericParamFlag_Interface;
}
if (((checkInner->mGenericParamFlags | outerFlags) & ~BfGenericParamFlag_Var) != (outerFlags & ~BfGenericParamFlag_Var))
auto innerFlags = checkInner->mGenericParamFlags;
if ((innerFlags & BfGenericParamFlag_Enum) != 0)
innerFlags |= BfGenericParamFlag_Struct;
if (((innerFlags | outerFlags) & ~BfGenericParamFlag_Var) != (outerFlags & ~BfGenericParamFlag_Var))
return false;
}
@ -8481,7 +8492,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
{
auto genericParam = GetGenericParamInstance((BfGenericParamType*)resolvedType);
if (((genericParam->mTypeConstraint != NULL) && (genericParam->mTypeConstraint->IsValueType())) ||
((genericParam->mGenericParamFlags & (BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr)) != 0))
((genericParam->mGenericParamFlags & (BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr | BfGenericParamFlag_Enum)) != 0))
{
resolvedType = CreatePointerType(resolvedType);
}
@ -9970,7 +9981,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
// Generic constrained with class or pointer type -> void*
if (toType->IsVoidPtr())
{
if ((genericParamInst->mGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_StructPtr)) ||
if (((genericParamInst->mGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_StructPtr | BfGenericParamFlag_Interface)) != 0) ||
((genericParamInst->mTypeConstraint != NULL) &&
((genericParamInst->mTypeConstraint->IsPointer()) ||
(genericParamInst->mTypeConstraint->IsInstanceOf(mCompiler->mFunctionTypeDef)) ||
@ -9980,6 +9991,14 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
}
}
if (toType->IsInteger())
{
if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Enum) != 0)
{
return mBfIRBuilder->GetFakeVal();
}
}
return BfIRValue();
};
@ -10029,7 +10048,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
if (typedVal.mType->IsNull())
{
bool allowCast = (genericParamInst->mGenericParamFlags & BfGenericParamFlag_Class) || (genericParamInst->mGenericParamFlags & BfGenericParamFlag_StructPtr);
bool allowCast = (genericParamInst->mGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_StructPtr | BfGenericParamFlag_Interface)) != 0;
if ((!allowCast) && (genericParamInst->mTypeConstraint != NULL))
allowCast = genericParamInst->mTypeConstraint->IsObject() || genericParamInst->mTypeConstraint->IsPointer();
if (allowCast)
@ -10052,7 +10071,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
if (explicitCast)
{
if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_StructPtr) ||
if (((genericParamInst->mGenericParamFlags & BfGenericParamFlag_StructPtr) != 0) ||
((genericParamInst->mTypeConstraint != NULL) && genericParamInst->mTypeConstraint->IsInstanceOf(mCompiler->mFunctionTypeDef)))
{
auto voidPtrType = CreatePointerType(GetPrimitiveType(BfTypeCode_None));
@ -10061,6 +10080,24 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
return castedVal;
}
}
if ((typedVal.mType->IsIntegral()) && ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Enum) != 0))
{
bool allowCast = explicitCast;
if ((!allowCast) && (typedVal.mType->IsIntegral()))
{
// Allow implicit cast of zero
auto constant = mBfIRBuilder->GetConstant(typedVal.mValue);
if ((constant != NULL) && (mBfIRBuilder->IsInt(constant->mTypeCode)))
{
allowCast = constant->mInt64 == 0;
}
}
if (allowCast)
{
return mBfIRBuilder->GetFakeVal();
}
}
}
if ((typedVal.mType->IsTypeInstance()) && (toType->IsTypeInstance()))