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

Added extern constraints to types

This commit is contained in:
Brian Fiete 2020-08-05 05:34:32 -07:00
parent 7724c6ae64
commit c3bc2bc67c
10 changed files with 121 additions and 38 deletions

View file

@ -4012,6 +4012,8 @@ void BfCompiler::ProcessAutocompleteTempType()
module->HandleTypeGenericParamRef(nameNode, tempTypeDef, genericParamIdx); module->HandleTypeGenericParamRef(nameNode, tempTypeDef, genericParamIdx);
} }
//TODO: Do extern constraint stuff here
for (auto fieldDef : tempTypeDef->mFields) for (auto fieldDef : tempTypeDef->mFields)
{ {
BP_ZONE("ProcessAutocompleteTempType.CheckField"); BP_ZONE("ProcessAutocompleteTempType.CheckField");

View file

@ -1629,7 +1629,7 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
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();
ParseGenericParams(typeDeclaration->mGenericParams, typeDeclaration->mGenericConstraintsDeclaration, mCurTypeDef->mGenericParamDefs, NULL, outerGenericSize); ParseGenericParams(typeDeclaration->mGenericParams, typeDeclaration->mGenericConstraintsDeclaration, mCurTypeDef->mGenericParamDefs, &mCurTypeDef->mExternalConstraints, outerGenericSize);
BF_ASSERT(mCurTypeDef->mNameEx == NULL); BF_ASSERT(mCurTypeDef->mNameEx == NULL);

View file

@ -13034,7 +13034,7 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc,
BfTypeVector* typeGenericArguments = NULL; BfTypeVector* typeGenericArguments = NULL;
if (owner->mGenericTypeInfo != NULL) if (owner->mGenericTypeInfo != NULL)
typeGenericArguments = &owner->mGenericTypeInfo->mTypeGenericArguments; typeGenericArguments = &owner->mGenericTypeInfo->mTypeGenericArguments;
genericArg = mModule->ResolveGenericType(genericArg, typeGenericArguments, checkMethodGenericArgs); //genericArg = mModule->ResolveGenericType(genericArg, typeGenericArguments, checkMethodGenericArgs);
} }
if (genericArg->IsVar()) if (genericArg->IsVar())

View file

@ -3897,10 +3897,18 @@ void BfModule::FindSubTypes(BfTypeInstance* classType, SizedArrayImpl<int>* outV
{ {
bool needsExCheck = false; bool needsExCheck = false;
if (ifaceInst.mDeclaringType->mProject != classType->mTypeDef->mProject) if (ifaceInst.mDeclaringType->mProject != classType->mTypeDef->mProject)
{
PopulateType(ifaceInst.mInterfaceType, BfPopulateType_DataAndMethods);
if (ifaceInst.mInterfaceType->mVirtualMethodTableSize > 0)
{ {
exChecks->push_back(ifaceInst.mInterfaceType); exChecks->push_back(ifaceInst.mInterfaceType);
continue; continue;
} }
else
{
// We can only do an 'exCheck' if we're actually going to slot this interface
}
}
} }
outVals->push_back(ifaceInst.mInterfaceType->mTypeId); outVals->push_back(ifaceInst.mInterfaceType->mTypeId);
@ -6878,8 +6886,9 @@ String BfModule::GenericParamSourceToString(const BfGenericParamSource & generic
{ {
if (genericParamSource.mMethodInstance != NULL) if (genericParamSource.mMethodInstance != NULL)
{ {
auto methodInst = GetUnspecializedMethodInstance(genericParamSource.mMethodInstance); auto methodInst = GetUnspecializedMethodInstance(genericParamSource.mMethodInstance, false);
return MethodToString(methodInst); SetAndRestoreValue<BfMethodInstance*> prevMethodInst(methodInst, NULL);
return MethodToString(genericParamSource.mMethodInstance);
} }
else else
{ {
@ -9264,12 +9273,16 @@ BfMethodInstance* BfModule::GetRawMethodByName(BfTypeInstance* typeInstance, con
return NULL; return NULL;
} }
BfMethodInstance* BfModule::GetUnspecializedMethodInstance(BfMethodInstance* methodInstance) BfMethodInstance* BfModule::GetUnspecializedMethodInstance(BfMethodInstance* methodInstance, bool useUnspecializedType)
{ {
if ((methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mMethodGenericArguments.size() != 0)) if ((methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mMethodGenericArguments.size() != 0))
methodInstance = methodInstance->mMethodInstanceGroup->mDefault; methodInstance = methodInstance->mMethodInstanceGroup->mDefault;
auto owner = methodInstance->mMethodInstanceGroup->mOwner; auto owner = methodInstance->mMethodInstanceGroup->mOwner;
if (!useUnspecializedType)
return GetRawMethodInstanceAtIdx(owner, methodInstance->mMethodDef->mIdx);
if (!owner->IsGenericTypeInstance()) if (!owner->IsGenericTypeInstance())
return methodInstance; return methodInstance;
@ -19861,15 +19874,18 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
} }
else else
{ {
if (unspecializedTypeInstance == NULL)
unspecializedTypeInstance = GetUnspecializedTypeInstance(mCurTypeInstance);
auto externConstraintDef = genericParam->GetExternConstraintDef(); auto externConstraintDef = genericParam->GetExternConstraintDef();
// Resolve in the unspecialized type, then resolve the generic later. This fixes ambiguity where the type is specialized by a method generic arg
{ // if (unspecializedTypeInstance == NULL)
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, unspecializedTypeInstance); // unspecializedTypeInstance = GetUnspecializedTypeInstance(mCurTypeInstance);
//
// // Resolve in the unspecialized type, then resolve the generic later. This fixes ambiguity where the type is specialized by a method generic arg
// {
// SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, unspecializedTypeInstance);
// genericParam->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef);
// }
genericParam->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef); genericParam->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef);
}
auto autoComplete = mCompiler->GetAutoComplete(); auto autoComplete = mCompiler->GetAutoComplete();
if (autoComplete != NULL) if (autoComplete != NULL)

View file

@ -1768,7 +1768,7 @@ public:
BfMethodInstance* GetRawMethodInstanceAtIdx(BfTypeInstance* typeInstance, int methodIdx, const char* assertName = NULL); BfMethodInstance* GetRawMethodInstanceAtIdx(BfTypeInstance* typeInstance, int methodIdx, const char* assertName = NULL);
BfMethodInstance* GetRawMethodInstance(BfTypeInstance* typeInstance, BfMethodDef* methodDef); BfMethodInstance* GetRawMethodInstance(BfTypeInstance* typeInstance, BfMethodDef* methodDef);
BfMethodInstance* GetRawMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount = -1, bool checkBase = false, bool allowMixin = false); BfMethodInstance* GetRawMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount = -1, bool checkBase = false, bool allowMixin = false);
BfMethodInstance* GetUnspecializedMethodInstance(BfMethodInstance* methodInstance); // Unspecialized owner type and unspecialized method type BfMethodInstance* GetUnspecializedMethodInstance(BfMethodInstance* methodInstance, bool useUnspecializedType = true); // Unspecialized owner type and unspecialized method type
int GetGenericParamAndReturnCount(BfMethodInstance* methodInstance); int GetGenericParamAndReturnCount(BfMethodInstance* methodInstance);
BfModule* GetSpecializedMethodModule(const SizedArrayImpl<BfProject*>& projectList); BfModule* GetSpecializedMethodModule(const SizedArrayImpl<BfProject*>& projectList);
BfModuleMethodInstance GetMethodInstanceAtIdx(BfTypeInstance* typeInstance, int methodIdx, const char* assertName = NULL, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None); BfModuleMethodInstance GetMethodInstanceAtIdx(BfTypeInstance* typeInstance, int methodIdx, const char* assertName = NULL, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None);

View file

@ -75,6 +75,12 @@ BfGenericExtensionEntry* BfModule::BuildGenericExtensionInfo(BfTypeInstance* gen
genericExEntry->mGenericParams.push_back(genericParamInstance); genericExEntry->mGenericParams.push_back(genericParamInstance);
} }
for (int externConstraintIdx = 0; externConstraintIdx < (int)partialTypeDef->mExternalConstraints.size(); externConstraintIdx++)
{
auto genericParamInstance = new BfGenericTypeParamInstance(partialTypeDef, externConstraintIdx + (int)partialTypeDef->mGenericParamDefs.size());
genericExEntry->mGenericParams.push_back(genericParamInstance);
}
for (int paramIdx = startDefGenericParamIdx; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size(); paramIdx++) for (int paramIdx = startDefGenericParamIdx; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size(); paramIdx++)
{ {
auto genericParamInstance = genericExEntry->mGenericParams[paramIdx]; auto genericParamInstance = genericExEntry->mGenericParams[paramIdx];
@ -124,6 +130,12 @@ bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
genericTypeInst->mGenericTypeInfo->mGenericParams.push_back(genericParamInstance); genericTypeInst->mGenericTypeInfo->mGenericParams.push_back(genericParamInstance);
} }
for (int externConstraintIdx = 0; externConstraintIdx < (int)typeDef->mExternalConstraints.size(); externConstraintIdx++)
{
auto genericParamInstance = new BfGenericTypeParamInstance(typeDef, externConstraintIdx + (int)typeDef->mGenericParamDefs.size());
genericTypeInst->mGenericTypeInfo->mGenericParams.push_back(genericParamInstance);
}
if (!typeDef->mPartials.empty()) if (!typeDef->mPartials.empty())
{ {
for (auto partialTypeDef : typeDef->mPartials) for (auto partialTypeDef : typeDef->mPartials)
@ -172,6 +184,28 @@ bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
for (int paramIdx = startDefGenericParamIdx; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mGenericParams.size(); paramIdx++) for (int paramIdx = startDefGenericParamIdx; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mGenericParams.size(); paramIdx++)
{ {
auto genericParamInstance = genericTypeInst->mGenericTypeInfo->mGenericParams[paramIdx]; auto genericParamInstance = genericTypeInst->mGenericTypeInfo->mGenericParams[paramIdx];
if (paramIdx < (int)typeDef->mGenericParamDefs.size())
{
genericParamInstance->mExternType = GetGenericParamType(BfGenericParamKind_Type, paramIdx);
}
else
{
auto externConstraintDef = genericParamInstance->GetExternConstraintDef();
genericParamInstance->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef);
auto autoComplete = mCompiler->GetAutoComplete();
if (autoComplete != NULL)
autoComplete->CheckTypeRef(externConstraintDef->mTypeRef, false);
if (genericParamInstance->mExternType != NULL)
{
//
}
else
genericParamInstance->mExternType = GetPrimitiveType(BfTypeCode_Var);
}
ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType()); ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType());
auto genericParamDef = genericParamInstance->GetGenericParamDef(); auto genericParamDef = genericParamInstance->GetGenericParamDef();
if (genericParamDef != NULL) if (genericParamDef != NULL)
@ -223,20 +257,30 @@ bool BfModule::ValidateGenericConstraints(BfTypeReference* typeRef, BfTypeInstan
} }
auto typeDef = genericTypeInst->mTypeDef; auto typeDef = genericTypeInst->mTypeDef;
for (int paramIdx = 0; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size(); paramIdx++) //for (int paramIdx = 0; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size(); paramIdx++)
for (int paramIdx = 0; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mGenericParams.size(); paramIdx++)
{ {
auto genericParamInstance = genericTypeInst->mGenericTypeInfo->mGenericParams[paramIdx]; auto genericParamInstance = genericTypeInst->mGenericTypeInfo->mGenericParams[paramIdx];
// Why did we remove this line? This breaks determining compatibility of one unspecialized type to another unspecialized type, called from ResolveTypeResult
//if (!genericTypeInst->mIsUnspecialized) BfType* genericArg;
if (paramIdx < (int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size())
{ {
genericArg = genericTypeInst->mGenericTypeInfo->mTypeGenericArguments[paramIdx];
}
else
{
genericArg = genericParamInstance->mExternType;
}
BfError* error = NULL; BfError* error = NULL;
if (!CheckGenericConstraints(BfGenericParamSource(genericTypeInst), genericTypeInst->mGenericTypeInfo->mTypeGenericArguments[paramIdx], typeRef, genericParamInstance, NULL, &error)) if (!CheckGenericConstraints(BfGenericParamSource(genericTypeInst), genericArg, typeRef, genericParamInstance, NULL, &error))
{ {
genericTypeInst->mGenericTypeInfo->mHadValidateErrors = true; genericTypeInst->mGenericTypeInfo->mHadValidateErrors = true;
return false; return false;
} }
} }
}
return true; return true;
} }
@ -10394,11 +10438,11 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
((explicitCast) && (opConstraint.mCastToken == BfToken_Explicit))) ((explicitCast) && (opConstraint.mCastToken == BfToken_Explicit)))
{ {
// If we can convert OUR fromVal to the constraint's fromVal then we may match // If we can convert OUR fromVal to the constraint's fromVal then we may match
if (CanCast(typedVal, opConstraint.mRightType)) if (CanCast(typedVal, opConstraint.mRightType, BfCastFlags_NoConversionOperator))
{ {
// .. and we can convert the constraint's toType to OUR toType then we're good // .. and we can convert the constraint's toType to OUR toType then we're good
auto opToVal = genericParam->mExternType; auto opToVal = genericParam->mExternType;
if (CanCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType)) if (CanCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType, BfCastFlags_NoConversionOperator))
return mBfIRBuilder->GetFakeVal(); return mBfIRBuilder->GetFakeVal();
} }
} }

View file

@ -1091,7 +1091,7 @@ public:
{ {
if (mGenericIdx < (int)mTypeDef->mGenericParamDefs.size()) if (mGenericIdx < (int)mTypeDef->mGenericParamDefs.size())
return mTypeDef->mGenericParamDefs[mGenericIdx]; return mTypeDef->mGenericParamDefs[mGenericIdx];
return NULL; return &mTypeDef->mExternalConstraints[mGenericIdx - (int)mTypeDef->mGenericParamDefs.size()];
} }
virtual BfGenericParamDef* GetGenericParamDef() override virtual BfGenericParamDef* GetGenericParamDef() override
@ -1105,14 +1105,14 @@ public:
{ {
if (mGenericIdx < (int)mTypeDef->mGenericParamDefs.size()) if (mGenericIdx < (int)mTypeDef->mGenericParamDefs.size())
return NULL; return NULL;
return NULL; return &mTypeDef->mExternalConstraints[mGenericIdx - (int)mTypeDef->mGenericParamDefs.size()];
} }
virtual String GetName() override virtual String GetName() override
{ {
if (mGenericIdx < (int)mTypeDef->mGenericParamDefs.size()) if (mGenericIdx < (int)mTypeDef->mGenericParamDefs.size())
return mTypeDef->mGenericParamDefs[mGenericIdx]->mName; return mTypeDef->mGenericParamDefs[mGenericIdx]->mName;
return "???"; return mTypeDef->mExternalConstraints[mGenericIdx - (int)mTypeDef->mGenericParamDefs.size()].mTypeRef->ToString();
} }
}; };

View file

@ -2662,6 +2662,7 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef)
typeDef->mGenericParamDefs.Clear(); typeDef->mGenericParamDefs.Clear();
typeDef->mGenericParamDefs = nextTypeDef->mGenericParamDefs; typeDef->mGenericParamDefs = nextTypeDef->mGenericParamDefs;
typeDef->mExternalConstraints = nextTypeDef->mExternalConstraints;
nextTypeDef->mGenericParamDefs.Clear(); nextTypeDef->mGenericParamDefs.Clear();
typeDef->mBaseTypes = nextTypeDef->mBaseTypes; typeDef->mBaseTypes = nextTypeDef->mBaseTypes;
@ -2739,6 +2740,7 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co
*newGeneric = *generic; *newGeneric = *generic;
typeDef->mGenericParamDefs.push_back(newGeneric); typeDef->mGenericParamDefs.push_back(newGeneric);
} }
typeDef->mExternalConstraints = partialTypeDef->mExternalConstraints;
typeDef->mBaseTypes = partialTypeDef->mBaseTypes; typeDef->mBaseTypes = partialTypeDef->mBaseTypes;
@ -2756,6 +2758,9 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co
typeDef->mTypeCode = partialTypeDef->mTypeCode; typeDef->mTypeCode = partialTypeDef->mTypeCode;
typeDef->mTypeDeclaration = partialTypeDef->mTypeDeclaration; typeDef->mTypeDeclaration = partialTypeDef->mTypeDeclaration;
} }
for (auto& externConstraint : partialTypeDef->mExternalConstraints)
typeDef->mExternalConstraints.Add(externConstraint);
} }
// Merge attributes together // Merge attributes together

View file

@ -880,6 +880,7 @@ public:
Array<BfOperatorDef*> mOperators; Array<BfOperatorDef*> mOperators;
BfMethodDef* mDtorDef; BfMethodDef* mDtorDef;
Array<BfGenericParamDef*> mGenericParamDefs; Array<BfGenericParamDef*> mGenericParamDefs;
Array<BfExternalConstraintDef> mExternalConstraints;
Array<BfTypeReference*> mBaseTypes; Array<BfTypeReference*> mBaseTypes;
Array<BfTypeDef*> mNestedTypes; Array<BfTypeDef*> mNestedTypes;
Array<BfDirectStrTypeReference*> mDirectAllocNodes; Array<BfDirectStrTypeReference*> mDirectAllocNodes;

View file

@ -176,17 +176,28 @@ namespace Tests
return val + val2; return val + val2;
} }
public static T Complex<T, T2>(T val, T2 val2) public static T Complex<T, T2, T3>(T val, T2 val2, T3 val3)
where T : operator T + T2
where T : operator -T where T : operator -T
where T : operator implicit T2 where T : operator implicit T2
where T : operator T + T2
where int32 : operator T + T3
{ {
T conv = val2; T conv = val2;
T result = val + val2; T result = val + val2;
result = -result; result = -result;
int32 iRes = val + val3;
return result; return result;
} }
struct StructOp3<T, T2> where float : operator T + T2
{
public float Use(T lhs, T2 rhs)
{
float f = lhs + rhs;
return f;
}
}
[Test] [Test]
public static void TestBasics() public static void TestBasics()
{ {
@ -212,7 +223,7 @@ namespace Tests
float val = Op((int32)100, (int16)23); float val = Op((int32)100, (int16)23);
Test.Assert(val == 123); Test.Assert(val == 123);
int32 i32res = Complex((int32)100, (int16)23); int32 i32res = Complex((int32)100, (int16)23, (int8)4);
Test.Assert(i32res == -123); Test.Assert(i32res == -123);
StructOp<StructA, StructB> sOp; StructOp<StructA, StructB> sOp;
@ -231,6 +242,10 @@ namespace Tests
Test.Assert(rsc == rsc2); Test.Assert(rsc == rsc2);
Test.Assert(rsc !== rsc2); Test.Assert(rsc !== rsc2);
StructOp3<int16, int32> so3 = .();
float f = so3.Use(1, 2);
Test.Assert(f == 3);
/*let oai = OuterOp<float>.InnerOp<int>.Op(1.0f, 100); /*let oai = OuterOp<float>.InnerOp<int>.Op(1.0f, 100);
Test.Assert(oai == 101.0f); Test.Assert(oai == 101.0f);