1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 20:12:21 +02:00

Added 'concrete' constraint

This commit is contained in:
Brian Fiete 2021-01-13 09:24:15 -08:00
parent 51ed3df320
commit e3f51e39ed
12 changed files with 90 additions and 72 deletions

View file

@ -17,12 +17,12 @@ namespace System.Collections
Result<T> GetNextRef() mut; Result<T> GetNextRef() mut;
} }
concrete interface IEnumerable<T> interface IEnumerable<T>
{ {
concrete IEnumerator<T> GetEnumerator(); concrete IEnumerator<T> GetEnumerator();
} }
concrete interface IRefEnumerable<T> interface IRefEnumerable<T>
{ {
concrete IRefEnumerator<T> GetEnumerator(); concrete IRefEnumerator<T> GetEnumerator();
} }

View file

@ -28,7 +28,7 @@ namespace System.Collections
Result<T*> GetNextRef() mut; Result<T*> GetNextRef() mut;
} }
concrete interface IEnumerable<T> interface IEnumerable<T>
{ {
concrete IEnumerator<T> GetEnumerator(); concrete IEnumerator<T> GetEnumerator();
} }

View file

@ -286,7 +286,7 @@ void BfDefBuilder::ParseGenericParams(BfGenericParamsDeclaration* genericParamsD
if (!name.empty()) if (!name.empty())
{ {
if ((name == "class") || (name == "struct") || (name == "struct*") || (name == "const") || (name == "var") || (name == "interface") || (name == "enum")) if ((name == "class") || (name == "struct") || (name == "struct*") || (name == "const") || (name == "var") || (name == "concrete") || (name == "interface") || (name == "enum"))
{ {
int prevFlags = constraintDef->mGenericParamFlags & int prevFlags = constraintDef->mGenericParamFlags &
(BfGenericParamFlag_Class | BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr | BfGenericParamFlag_Interface | BfGenericParamFlag_Enum); (BfGenericParamFlag_Class | BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr | BfGenericParamFlag_Interface | BfGenericParamFlag_Enum);
@ -319,6 +319,8 @@ void BfDefBuilder::ParseGenericParams(BfGenericParamsDeclaration* genericParamsD
constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_StructPtr); constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_StructPtr);
else if (name == "const") else if (name == "const")
constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Const); constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Const);
else if (name == "concrete")
constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Concrete);
else if (name == "interface") else if (name == "interface")
constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Interface); constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Interface);
else if (name == "enum") else if (name == "enum")
@ -459,10 +461,7 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio
if (mCurTypeDef->mTypeCode == BfTypeCode_Interface) if (mCurTypeDef->mTypeCode == BfTypeCode_Interface)
{ {
if ((methodDef->mIsConcrete) && (!mCurTypeDef->mIsConcrete)) //
Fail("Only interfaces declared as 'concrete' can be declare methods as 'concrete'. Consider adding 'concrete' to the interface declaration.", methodDeclaration->mVirtualSpecifier);
//if (!methodDef->mIsConcrete)
//Fail(StrFormat("Interfaces methods cannot be declared as '%s'", methodDeclaration->mVirtualSpecifier->ToString().c_str()), methodDeclaration->mVirtualSpecifier);
} }
else else
{ {
@ -1655,7 +1654,6 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
mCurTypeDef->mSource->mRefCount++; mCurTypeDef->mSource->mRefCount++;
mCurTypeDef->mTypeDeclaration = typeDeclaration; mCurTypeDef->mTypeDeclaration = typeDeclaration;
mCurTypeDef->mIsAbstract = (typeDeclaration->mAbstractSpecifier != NULL) && (typeDeclaration->mAbstractSpecifier->GetToken() == BfToken_Abstract); mCurTypeDef->mIsAbstract = (typeDeclaration->mAbstractSpecifier != NULL) && (typeDeclaration->mAbstractSpecifier->GetToken() == BfToken_Abstract);
mCurTypeDef->mIsConcrete = (typeDeclaration->mAbstractSpecifier != NULL) && (typeDeclaration->mAbstractSpecifier->GetToken() == BfToken_Concrete);
mCurTypeDef->mIsStatic = typeDeclaration->mStaticSpecifier != NULL; mCurTypeDef->mIsStatic = typeDeclaration->mStaticSpecifier != NULL;
mCurTypeDef->mIsDelegate = false; mCurTypeDef->mIsDelegate = false;
mCurTypeDef->mIsFunction = false; mCurTypeDef->mIsFunction = false;
@ -1721,15 +1719,6 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
} }
} }
if (mCurTypeDef->mIsConcrete)
{
if (mCurTypeDef->mTypeCode != BfTypeCode_Interface)
{
mPassInstance->Warn(0, StrFormat("Types declared as '%s' cannot be 'concrete'", BfTokenToString(typeToken)).c_str(), typeDeclaration->mAbstractSpecifier);
mCurTypeDef->mIsConcrete = false;
}
}
int outerGenericSize = 0; int outerGenericSize = 0;
if (mCurTypeDef->mOuterType != NULL) if (mCurTypeDef->mOuterType != NULL)
outerGenericSize = (int)mCurTypeDef->mOuterType->mGenericParamDefs.size(); outerGenericSize = (int)mCurTypeDef->mOuterType->mGenericParamDefs.size();

View file

@ -1350,6 +1350,8 @@ void BfModule::StartExtension()
mStaticFieldRefs.Clear(); mStaticFieldRefs.Clear();
for (auto& kv : mInterfaceSlotRefs) for (auto& kv : mInterfaceSlotRefs)
kv.mValue = BfIRValue(); kv.mValue = BfIRValue();
for (auto& pairVal : mDeferredMethodCallData)
delete pairVal.mValue;
mDeferredMethodCallData.Clear(); mDeferredMethodCallData.Clear();
mDeferredMethodIds.Clear(); mDeferredMethodIds.Clear();
@ -5142,11 +5144,6 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
BfMangler::Mangle(typeDataName, mCompiler->GetMangleKind(), type, mContext->mScratchModule); BfMangler::Mangle(typeDataName, mCompiler->GetMangleKind(), type, mContext->mScratchModule);
} }
if (typeDataName == "?sBfTypeData@@bf@@2HA")
{
NOP;
}
int typeCode = BfTypeCode_None; int typeCode = BfTypeCode_None;
if (typeInstance != NULL) if (typeInstance != NULL)
@ -7482,6 +7479,15 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
} }
} }
if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Concrete) &&
((checkGenericParamFlags & (BfGenericParamFlag_Interface | BfGenericParamFlag_Var)) == 0) && (checkArgType->IsInterface()))
{
if (!ignoreErrors)
*errorOut = Fail(StrFormat("The type '%s' must be an concrete type in order to use it as parameter '%s' for '%s'",
TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
return false;
}
if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Interface) && if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Interface) &&
((checkGenericParamFlags & (BfGenericParamFlag_Interface | BfGenericParamFlag_Var)) == 0) && (!checkArgType->IsInterface())) ((checkGenericParamFlags & (BfGenericParamFlag_Interface | BfGenericParamFlag_Var)) == 0) && (!checkArgType->IsInterface()))
{ {
@ -7711,19 +7717,6 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
} }
} }
if ((genericParamInst->mInterfaceConstraints.size() > 0) && (origCheckArgType->IsInterface()))
{
PopulateType(origCheckArgType);
auto checkTypeInst = origCheckArgType->ToTypeInstance();
if (checkTypeInst->mTypeDef->mIsConcrete)
{
if (!ignoreErrors)
*errorOut = Fail(StrFormat("Generic argument '%s', declared to be concrete interface '%s' for '%s', must be a concrete type", genericParamInst->GetName().c_str(),
TypeToString(origCheckArgType).c_str()), checkArgTypeRef);
return false;
}
}
for (auto checkConstraint : genericParamInst->mInterfaceConstraints) for (auto checkConstraint : genericParamInst->mInterfaceConstraints)
{ {
BfType* convCheckConstraint = checkConstraint; BfType* convCheckConstraint = checkConstraint;

View file

@ -7678,7 +7678,7 @@ BfGenericParamInstance* BfModule::GetGenericParamInstance(BfGenericParamType* ty
BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTypeRef, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags) BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTypeRef, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags)
{ {
if (mCompiler->mIsResolveOnly) if ((mCompiler->mIsResolveOnly) && (!IsInSpecializedSection()))
{ {
bool isGetDefinition = false; bool isGetDefinition = false;
BfAutoComplete* autoComplete = NULL; BfAutoComplete* autoComplete = NULL;

View file

@ -8163,7 +8163,6 @@ BfAstNode* BfReducer::CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDi
case BfToken_Sealed: case BfToken_Sealed:
case BfToken_Abstract: case BfToken_Abstract:
case BfToken_Concrete:
case BfToken_Public: case BfToken_Public:
case BfToken_Private: case BfToken_Private:
case BfToken_Protected: case BfToken_Protected:
@ -8241,7 +8240,7 @@ BfAstNode* BfReducer::CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDi
MEMBER_SET(typeDeclaration, mSealedSpecifier, tokenNode); MEMBER_SET(typeDeclaration, mSealedSpecifier, tokenNode);
} }
if ((token == BfToken_Abstract) || (token == BfToken_Concrete)) if (token == BfToken_Abstract)
{ {
if (typeDeclaration->mAbstractSpecifier != NULL) if (typeDeclaration->mAbstractSpecifier != NULL)
{ {
@ -9618,6 +9617,7 @@ BfGenericConstraintsDeclaration* BfReducer::CreateGenericConstraintsDeclaration(
case BfToken_Class: case BfToken_Class:
case BfToken_Struct: case BfToken_Struct:
case BfToken_Const: case BfToken_Const:
case BfToken_Concrete:
case BfToken_Var: case BfToken_Var:
case BfToken_New: case BfToken_New:
case BfToken_Delete: case BfToken_Delete:

View file

@ -6000,6 +6000,22 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
itr = target; itr = target;
bool hadGetEnumeratorType = false; bool hadGetEnumeratorType = false;
if (genericParamInst != NULL)
{
for (auto ifaceConstraint : genericParamInst->mInterfaceConstraints)
{
if (ifaceConstraint->IsInstanceOf(mCompiler->mGenericIEnumerableTypeDef))
{
if (targetTypeInstance != NULL)
{
targetTypeInstance = NULL;
break;
}
targetTypeInstance = ifaceConstraint->ToTypeInstance();
}
}
}
if (targetTypeInstance != NULL) if (targetTypeInstance != NULL)
{ {
PopulateType(targetTypeInstance, BfPopulateType_DataAndMethods); PopulateType(targetTypeInstance, BfPopulateType_DataAndMethods);
@ -6013,19 +6029,29 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
hadGetEnumeratorType = true; hadGetEnumeratorType = true;
Fail(StrFormat("Type '%s' does not contain a non-static 'GetEnumerator' method", TypeToString(targetTypeInstance).c_str()), forEachStmt->mCollectionExpression); Fail(StrFormat("Type '%s' does not contain a non-static 'GetEnumerator' method", TypeToString(targetTypeInstance).c_str()), forEachStmt->mCollectionExpression);
} }
else if (getEnumeratorMethod.mMethodInstance->mMethodDef->mIsConcrete)
{
hadGetEnumeratorType = true;
Fail(StrFormat("Iteration requires a concrete implementation of '%s'", TypeToString(targetTypeInstance).c_str()), forEachStmt->mCollectionExpression);
}
else else
{ {
if (getEnumeratorMethod.mMethodInstance->mMethodDef->mIsConcrete)
{
hadGetEnumeratorType = true;
if (genericParamInst != NULL)
{
if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Concrete) == 0)
Fail(StrFormat("Iteration requires a concrete implementation of '%s', consider adding 'concrete' constraint to '%s'", TypeToString(targetTypeInstance).c_str(), genericParamInst->GetName().c_str()), forEachStmt->mCollectionExpression);
}
else
Fail(StrFormat("Iteration requires a concrete implementation of '%s'", TypeToString(targetTypeInstance).c_str()), forEachStmt->mCollectionExpression);
}
hadGetEnumeratorType = true; hadGetEnumeratorType = true;
BfExprEvaluator exprEvaluator(this); BfExprEvaluator exprEvaluator(this);
SizedArray<BfIRValue, 1> args; SizedArray<BfIRValue, 1> args;
auto castedTarget = Cast(forEachStmt->mCollectionExpression, target, getEnumeratorMethod.mMethodInstance->GetOwner()); auto castedTarget = Cast(forEachStmt->mCollectionExpression, target, getEnumeratorMethod.mMethodInstance->GetOwner());
exprEvaluator.PushThis(forEachStmt->mCollectionExpression, castedTarget, getEnumeratorMethod.mMethodInstance, args); exprEvaluator.PushThis(forEachStmt->mCollectionExpression, castedTarget, getEnumeratorMethod.mMethodInstance, args);
itr = exprEvaluator.CreateCall(forEachStmt->mCollectionExpression, getEnumeratorMethod.mMethodInstance, IsSkippingExtraResolveChecks() ? BfIRValue() : getEnumeratorMethod.mFunc, false, args); itr = exprEvaluator.CreateCall(forEachStmt->mCollectionExpression, getEnumeratorMethod.mMethodInstance, IsSkippingExtraResolveChecks() ? BfIRValue() : getEnumeratorMethod.mFunc, false, args);
if (itr.mType->IsConcreteInterfaceType())
itr.mType = itr.mType->GetUnderlyingType();
} }
} }
@ -6060,6 +6086,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
}; };
auto enumeratorTypeInst = itr.mType->ToTypeInstance(); auto enumeratorTypeInst = itr.mType->ToTypeInstance();
if (enumeratorTypeInst != NULL) if (enumeratorTypeInst != NULL)
{ {
for (auto& interfaceRef : enumeratorTypeInst->mInterfaces) for (auto& interfaceRef : enumeratorTypeInst->mInterfaces)

View file

@ -2734,7 +2734,6 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef)
typeDef->mIsFunction = nextTypeDef->mIsFunction; typeDef->mIsFunction = nextTypeDef->mIsFunction;
typeDef->mIsClosure = nextTypeDef->mIsClosure; typeDef->mIsClosure = nextTypeDef->mIsClosure;
typeDef->mIsAbstract = nextTypeDef->mIsAbstract; typeDef->mIsAbstract = nextTypeDef->mIsAbstract;
typeDef->mIsConcrete = nextTypeDef->mIsConcrete;
typeDef->mIsStatic = nextTypeDef->mIsStatic; typeDef->mIsStatic = nextTypeDef->mIsStatic;
typeDef->mHasAppendCtor = nextTypeDef->mHasAppendCtor; typeDef->mHasAppendCtor = nextTypeDef->mHasAppendCtor;
typeDef->mHasCEOnCompile = nextTypeDef->mHasCEOnCompile; typeDef->mHasCEOnCompile = nextTypeDef->mHasCEOnCompile;
@ -2840,7 +2839,6 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co
typeDef->mProtection = partialTypeDef->mProtection; typeDef->mProtection = partialTypeDef->mProtection;
typeDef->mIsDelegate = partialTypeDef->mIsDelegate; typeDef->mIsDelegate = partialTypeDef->mIsDelegate;
typeDef->mIsAbstract = partialTypeDef->mIsAbstract; typeDef->mIsAbstract = partialTypeDef->mIsAbstract;
typeDef->mIsConcrete = partialTypeDef->mIsConcrete;
typeDef->mIsStatic = partialTypeDef->mIsStatic; typeDef->mIsStatic = partialTypeDef->mIsStatic;
typeDef->mHasAppendCtor = partialTypeDef->mHasAppendCtor; typeDef->mHasAppendCtor = partialTypeDef->mHasAppendCtor;
typeDef->mHasCtorNoBody = partialTypeDef->mHasCtorNoBody; typeDef->mHasCtorNoBody = partialTypeDef->mHasCtorNoBody;
@ -2880,7 +2878,6 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co
// Merge attributes together // Merge attributes together
typeDef->mIsAbstract |= partialTypeDef->mIsAbstract; typeDef->mIsAbstract |= partialTypeDef->mIsAbstract;
typeDef->mIsConcrete |= partialTypeDef->mIsConcrete;
typeDef->mIsStatic |= partialTypeDef->mIsStatic; typeDef->mIsStatic |= partialTypeDef->mIsStatic;
typeDef->mHasAppendCtor |= partialTypeDef->mHasAppendCtor; typeDef->mHasAppendCtor |= partialTypeDef->mHasAppendCtor;
typeDef->mHasCEOnCompile |= partialTypeDef->mHasCEOnCompile; typeDef->mHasCEOnCompile |= partialTypeDef->mHasCEOnCompile;

View file

@ -629,14 +629,15 @@ enum BfGenericParamFlags : uint16
BfGenericParamFlag_StructPtr = 4, BfGenericParamFlag_StructPtr = 4,
BfGenericParamFlag_Enum = 8, BfGenericParamFlag_Enum = 8,
BfGenericParamFlag_Interface = 0x10, BfGenericParamFlag_Interface = 0x10,
BfGenericParamFlag_New = 0x20, BfGenericParamFlag_Concrete = 0x20,
BfGenericParamFlag_Delete = 0x40, BfGenericParamFlag_New = 0x40,
BfGenericParamFlag_Var = 0x80, BfGenericParamFlag_Delete = 0x80,
BfGenericParamFlag_Const = 0x100, BfGenericParamFlag_Var = 0x100,
BfGenericParamFlag_Equals = 0x200, BfGenericParamFlag_Const = 0x200,
BfGenericParamFlag_Equals_Op = 0x400, BfGenericParamFlag_Equals = 0x400,
BfGenericParamFlag_Equals_Type = 0x800, BfGenericParamFlag_Equals_Op = 0x800,
BfGenericParamFlag_Equals_IFace = 0x1000 BfGenericParamFlag_Equals_Type = 0x1000,
BfGenericParamFlag_Equals_IFace = 0x2000
}; };
class BfConstraintDef class BfConstraintDef
@ -995,7 +996,6 @@ public:
bool mIsFunction; bool mIsFunction;
bool mIsClosure; bool mIsClosure;
bool mIsAbstract; bool mIsAbstract;
bool mIsConcrete;
bool mIsStatic; bool mIsStatic;
bool mHasCEOnCompile; bool mHasCEOnCompile;
bool mHasAppendCtor; bool mHasAppendCtor;
@ -1034,7 +1034,6 @@ public:
mHash = 0; mHash = 0;
mPartialIdx = -1; mPartialIdx = -1;
mIsAbstract = false; mIsAbstract = false;
mIsConcrete = false;
mIsDelegate = false; mIsDelegate = false;
mIsFunction = false; mIsFunction = false;
mIsClosure = false; mIsClosure = false;

View file

@ -287,7 +287,7 @@ void CeDumpContext::DumpOperandInfo(CeOperandInfoKind operandInfoKind)
{ {
int64 val = CE_GET(int64); int64 val = CE_GET(int64);
char str[64]; char str[64];
sprintf(str, "%lld", val); sprintf(str, "%lld", (long long)val);
mStr += str; mStr += str;
} }
break; break;

View file

@ -226,9 +226,14 @@ namespace Tests
} }
static int MethodE<T, T2>(T val) where T : IEnumerable<T2> static T2 MethodE<T, T2>(T val) where T : concrete, IEnumerable<T2> where T2 : operator T2 + T2
{ {
return 0; T2 total = default;
for (var v in val)
{
total += v;
}
return total;
} }
static int MethodF<T>(IEnumerable<T> val) static int MethodF<T>(IEnumerable<T> val)
@ -243,6 +248,7 @@ namespace Tests
List<Entry> list = scope .(); List<Entry> list = scope .();
list.Sort(); list.Sort();
List<float> floatList = scope .() {1, 2, 3};
ClassA ca = scope .(); ClassA ca = scope .();
ClassB cb = scope .(); ClassB cb = scope .();
@ -278,8 +284,15 @@ namespace Tests
Test.Assert(ClassE.Instance.CreateSystem<int>() == 999); Test.Assert(ClassE.Instance.CreateSystem<int>() == 999);
MethodE(list); /*IEnumerable<float> ie = floatList;
MethodF(list); Test.Assert(
[IgnoreErrors(true)]
{
Test.Assert(MethodE(ie) == 8);
true
} == false);*/
Test.Assert(MethodE(floatList) == 6);
Test.Assert(MethodF(floatList) == 0);
} }
} }

View file

@ -23,7 +23,7 @@ namespace Tests
} }
} }
concrete interface IFaceC interface IFaceC
{ {
concrete IFaceA GetConcreteIA(); concrete IFaceA GetConcreteIA();
} }