mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-09 03:52:19 +02:00
Added 'concrete' constraint
This commit is contained in:
parent
51ed3df320
commit
e3f51e39ed
12 changed files with 90 additions and 72 deletions
|
@ -17,12 +17,12 @@ namespace System.Collections
|
|||
Result<T> GetNextRef() mut;
|
||||
}
|
||||
|
||||
concrete interface IEnumerable<T>
|
||||
interface IEnumerable<T>
|
||||
{
|
||||
concrete IEnumerator<T> GetEnumerator();
|
||||
}
|
||||
|
||||
concrete interface IRefEnumerable<T>
|
||||
interface IRefEnumerable<T>
|
||||
{
|
||||
concrete IRefEnumerator<T> GetEnumerator();
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace System.Collections
|
|||
Result<T*> GetNextRef() mut;
|
||||
}
|
||||
|
||||
concrete interface IEnumerable<T>
|
||||
interface IEnumerable<T>
|
||||
{
|
||||
concrete IEnumerator<T> GetEnumerator();
|
||||
}
|
||||
|
|
|
@ -286,7 +286,7 @@ void BfDefBuilder::ParseGenericParams(BfGenericParamsDeclaration* genericParamsD
|
|||
|
||||
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 &
|
||||
(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);
|
||||
else if (name == "const")
|
||||
constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Const);
|
||||
else if (name == "concrete")
|
||||
constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Concrete);
|
||||
else if (name == "interface")
|
||||
constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Interface);
|
||||
else if (name == "enum")
|
||||
|
@ -459,10 +461,7 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio
|
|||
|
||||
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
|
||||
{
|
||||
|
@ -1655,7 +1654,6 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
|
|||
mCurTypeDef->mSource->mRefCount++;
|
||||
mCurTypeDef->mTypeDeclaration = typeDeclaration;
|
||||
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->mIsDelegate = 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;
|
||||
if (mCurTypeDef->mOuterType != NULL)
|
||||
outerGenericSize = (int)mCurTypeDef->mOuterType->mGenericParamDefs.size();
|
||||
|
|
|
@ -1350,6 +1350,8 @@ void BfModule::StartExtension()
|
|||
mStaticFieldRefs.Clear();
|
||||
for (auto& kv : mInterfaceSlotRefs)
|
||||
kv.mValue = BfIRValue();
|
||||
for (auto& pairVal : mDeferredMethodCallData)
|
||||
delete pairVal.mValue;
|
||||
mDeferredMethodCallData.Clear();
|
||||
mDeferredMethodIds.Clear();
|
||||
|
||||
|
@ -5142,11 +5144,6 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
BfMangler::Mangle(typeDataName, mCompiler->GetMangleKind(), type, mContext->mScratchModule);
|
||||
}
|
||||
|
||||
if (typeDataName == "?sBfTypeData@@bf@@2HA")
|
||||
{
|
||||
NOP;
|
||||
}
|
||||
|
||||
int typeCode = BfTypeCode_None;
|
||||
|
||||
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) &&
|
||||
((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)
|
||||
{
|
||||
BfType* convCheckConstraint = checkConstraint;
|
||||
|
|
|
@ -7678,7 +7678,7 @@ BfGenericParamInstance* BfModule::GetGenericParamInstance(BfGenericParamType* ty
|
|||
|
||||
BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTypeRef, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags)
|
||||
{
|
||||
if (mCompiler->mIsResolveOnly)
|
||||
if ((mCompiler->mIsResolveOnly) && (!IsInSpecializedSection()))
|
||||
{
|
||||
bool isGetDefinition = false;
|
||||
BfAutoComplete* autoComplete = NULL;
|
||||
|
|
|
@ -8163,7 +8163,6 @@ BfAstNode* BfReducer::CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDi
|
|||
|
||||
case BfToken_Sealed:
|
||||
case BfToken_Abstract:
|
||||
case BfToken_Concrete:
|
||||
case BfToken_Public:
|
||||
case BfToken_Private:
|
||||
case BfToken_Protected:
|
||||
|
@ -8241,7 +8240,7 @@ BfAstNode* BfReducer::CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDi
|
|||
MEMBER_SET(typeDeclaration, mSealedSpecifier, tokenNode);
|
||||
}
|
||||
|
||||
if ((token == BfToken_Abstract) || (token == BfToken_Concrete))
|
||||
if (token == BfToken_Abstract)
|
||||
{
|
||||
if (typeDeclaration->mAbstractSpecifier != NULL)
|
||||
{
|
||||
|
@ -9618,6 +9617,7 @@ BfGenericConstraintsDeclaration* BfReducer::CreateGenericConstraintsDeclaration(
|
|||
case BfToken_Class:
|
||||
case BfToken_Struct:
|
||||
case BfToken_Const:
|
||||
case BfToken_Concrete:
|
||||
case BfToken_Var:
|
||||
case BfToken_New:
|
||||
case BfToken_Delete:
|
||||
|
|
|
@ -6000,6 +6000,22 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
|||
itr = target;
|
||||
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)
|
||||
{
|
||||
PopulateType(targetTypeInstance, BfPopulateType_DataAndMethods);
|
||||
|
@ -6013,19 +6029,29 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
|||
hadGetEnumeratorType = true;
|
||||
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
|
||||
{
|
||||
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;
|
||||
BfExprEvaluator exprEvaluator(this);
|
||||
SizedArray<BfIRValue, 1> args;
|
||||
auto castedTarget = Cast(forEachStmt->mCollectionExpression, target, getEnumeratorMethod.mMethodInstance->GetOwner());
|
||||
exprEvaluator.PushThis(forEachStmt->mCollectionExpression, castedTarget, getEnumeratorMethod.mMethodInstance, 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();
|
||||
|
||||
if (enumeratorTypeInst != NULL)
|
||||
{
|
||||
for (auto& interfaceRef : enumeratorTypeInst->mInterfaces)
|
||||
|
|
|
@ -2734,7 +2734,6 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef)
|
|||
typeDef->mIsFunction = nextTypeDef->mIsFunction;
|
||||
typeDef->mIsClosure = nextTypeDef->mIsClosure;
|
||||
typeDef->mIsAbstract = nextTypeDef->mIsAbstract;
|
||||
typeDef->mIsConcrete = nextTypeDef->mIsConcrete;
|
||||
typeDef->mIsStatic = nextTypeDef->mIsStatic;
|
||||
typeDef->mHasAppendCtor = nextTypeDef->mHasAppendCtor;
|
||||
typeDef->mHasCEOnCompile = nextTypeDef->mHasCEOnCompile;
|
||||
|
@ -2840,7 +2839,6 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co
|
|||
typeDef->mProtection = partialTypeDef->mProtection;
|
||||
typeDef->mIsDelegate = partialTypeDef->mIsDelegate;
|
||||
typeDef->mIsAbstract = partialTypeDef->mIsAbstract;
|
||||
typeDef->mIsConcrete = partialTypeDef->mIsConcrete;
|
||||
typeDef->mIsStatic = partialTypeDef->mIsStatic;
|
||||
typeDef->mHasAppendCtor = partialTypeDef->mHasAppendCtor;
|
||||
typeDef->mHasCtorNoBody = partialTypeDef->mHasCtorNoBody;
|
||||
|
@ -2880,7 +2878,6 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co
|
|||
|
||||
// Merge attributes together
|
||||
typeDef->mIsAbstract |= partialTypeDef->mIsAbstract;
|
||||
typeDef->mIsConcrete |= partialTypeDef->mIsConcrete;
|
||||
typeDef->mIsStatic |= partialTypeDef->mIsStatic;
|
||||
typeDef->mHasAppendCtor |= partialTypeDef->mHasAppendCtor;
|
||||
typeDef->mHasCEOnCompile |= partialTypeDef->mHasCEOnCompile;
|
||||
|
|
|
@ -629,14 +629,15 @@ enum BfGenericParamFlags : uint16
|
|||
BfGenericParamFlag_StructPtr = 4,
|
||||
BfGenericParamFlag_Enum = 8,
|
||||
BfGenericParamFlag_Interface = 0x10,
|
||||
BfGenericParamFlag_New = 0x20,
|
||||
BfGenericParamFlag_Delete = 0x40,
|
||||
BfGenericParamFlag_Var = 0x80,
|
||||
BfGenericParamFlag_Const = 0x100,
|
||||
BfGenericParamFlag_Equals = 0x200,
|
||||
BfGenericParamFlag_Equals_Op = 0x400,
|
||||
BfGenericParamFlag_Equals_Type = 0x800,
|
||||
BfGenericParamFlag_Equals_IFace = 0x1000
|
||||
BfGenericParamFlag_Concrete = 0x20,
|
||||
BfGenericParamFlag_New = 0x40,
|
||||
BfGenericParamFlag_Delete = 0x80,
|
||||
BfGenericParamFlag_Var = 0x100,
|
||||
BfGenericParamFlag_Const = 0x200,
|
||||
BfGenericParamFlag_Equals = 0x400,
|
||||
BfGenericParamFlag_Equals_Op = 0x800,
|
||||
BfGenericParamFlag_Equals_Type = 0x1000,
|
||||
BfGenericParamFlag_Equals_IFace = 0x2000
|
||||
};
|
||||
|
||||
class BfConstraintDef
|
||||
|
@ -995,7 +996,6 @@ public:
|
|||
bool mIsFunction;
|
||||
bool mIsClosure;
|
||||
bool mIsAbstract;
|
||||
bool mIsConcrete;
|
||||
bool mIsStatic;
|
||||
bool mHasCEOnCompile;
|
||||
bool mHasAppendCtor;
|
||||
|
@ -1034,7 +1034,6 @@ public:
|
|||
mHash = 0;
|
||||
mPartialIdx = -1;
|
||||
mIsAbstract = false;
|
||||
mIsConcrete = false;
|
||||
mIsDelegate = false;
|
||||
mIsFunction = false;
|
||||
mIsClosure = false;
|
||||
|
|
|
@ -287,7 +287,7 @@ void CeDumpContext::DumpOperandInfo(CeOperandInfoKind operandInfoKind)
|
|||
{
|
||||
int64 val = CE_GET(int64);
|
||||
char str[64];
|
||||
sprintf(str, "%lld", val);
|
||||
sprintf(str, "%lld", (long long)val);
|
||||
mStr += str;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -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)
|
||||
|
@ -243,6 +248,7 @@ namespace Tests
|
|||
|
||||
List<Entry> list = scope .();
|
||||
list.Sort();
|
||||
List<float> floatList = scope .() {1, 2, 3};
|
||||
|
||||
ClassA ca = scope .();
|
||||
ClassB cb = scope .();
|
||||
|
@ -278,8 +284,15 @@ namespace Tests
|
|||
|
||||
Test.Assert(ClassE.Instance.CreateSystem<int>() == 999);
|
||||
|
||||
MethodE(list);
|
||||
MethodF(list);
|
||||
/*IEnumerable<float> ie = floatList;
|
||||
Test.Assert(
|
||||
[IgnoreErrors(true)]
|
||||
{
|
||||
Test.Assert(MethodE(ie) == 8);
|
||||
true
|
||||
} == false);*/
|
||||
Test.Assert(MethodE(floatList) == 6);
|
||||
Test.Assert(MethodF(floatList) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Tests
|
|||
}
|
||||
}
|
||||
|
||||
concrete interface IFaceC
|
||||
interface IFaceC
|
||||
{
|
||||
concrete IFaceA GetConcreteIA();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue