1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 04:22:20 +02:00

Added comptype

This commit is contained in:
Brian Fiete 2021-01-15 14:28:21 -08:00
parent bb12a4ec20
commit 4890303508
27 changed files with 382 additions and 157 deletions

View file

@ -588,54 +588,41 @@ bool BfGenericInferContext::InferGenericArgument(BfMethodInstance* methodInstanc
return true;
}
bool BfGenericInferContext::InferGenericArguments(BfMethodInstance* methodInstance, int srcGenericIdx)
{
auto& srcGenericArg = (*mCheckMethodGenericArguments)[srcGenericIdx];
if (srcGenericArg == NULL)
return false;
int startInferCount = mInferredCount;
auto srcGenericParam = methodInstance->mMethodInfoEx->mGenericParams[srcGenericIdx];
for (auto ifaceConstraint : srcGenericParam->mInterfaceConstraints)
{
if ((ifaceConstraint->IsUnspecializedTypeVariation()) && (ifaceConstraint->IsGenericTypeInstance()))
{
InferGenericArgument(methodInstance, srcGenericArg, ifaceConstraint, BfIRValue());
auto typeInstance = srcGenericArg->ToTypeInstance();
if (typeInstance != NULL)
{
for (auto ifaceEntry : typeInstance->mInterfaces)
InferGenericArgument(methodInstance, ifaceEntry.mInterfaceType, ifaceConstraint, BfIRValue());
}
}
}
return mInferredCount != startInferCount;
}
void BfGenericInferContext::InferGenericArguments(BfMethodInstance* methodInstance)
{
// Attempt to infer from other generic args
for (int srcGenericIdx = 0; srcGenericIdx < (int)mCheckMethodGenericArguments->size(); srcGenericIdx++)
{
auto& srcGenericArg = (*mCheckMethodGenericArguments)[srcGenericIdx];
if (srcGenericArg == NULL)
continue;
auto srcGenericParam = methodInstance->mMethodInfoEx->mGenericParams[srcGenericIdx];
for (auto ifaceConstraint : srcGenericParam->mInterfaceConstraints)
{
if ((ifaceConstraint->IsUnspecializedTypeVariation()) && (ifaceConstraint->IsGenericTypeInstance()))
{
InferGenericArgument(methodInstance, srcGenericArg, ifaceConstraint, BfIRValue());
auto typeInstance = srcGenericArg->ToTypeInstance();
if (typeInstance != NULL)
{
for (auto ifaceEntry : typeInstance->mInterfaces)
InferGenericArgument(methodInstance, ifaceEntry.mInterfaceType, ifaceConstraint, BfIRValue());
}
}
}
InferGenericArguments(methodInstance, srcGenericIdx);
}
}
// void BfGenericInferContext::PropogateInference(BfType* resolvedType, BfType* unresovledType)
// {
// if (!unresovledType->IsUnspecializedTypeVariation())
// return;
//
// auto resolvedTypeInstance = resolvedType->ToTypeInstance();
// auto unresolvedTypeInstance = unresovledType->ToTypeInstance();
//
// if ((resolvedTypeInstance == NULL) || (unresolvedTypeInstance == NULL))
// return;
// if (resolvedTypeInstance->mTypeDef != unresolvedTypeInstance->mTypeDef)
// return;
//
// if (unres)
//
// if (resolvedType->IsGenericTypeInstance())
// {
//
//
// }
// }
int BfMethodMatcher::GetMostSpecificType(BfType* lhs, BfType* rhs)
{
if ((lhs->IsRef()) && (rhs->IsRef()))
@ -1440,10 +1427,10 @@ bool BfMethodMatcher::WantsCheckMethod(BfProtectionCheckFlags& flags, BfTypeInst
return true;
}
bool BfMethodMatcher::InferFromGenericConstraints(BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs)
bool BfMethodMatcher::InferFromGenericConstraints(BfMethodInstance* methodInstance, BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs)
{
if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Equals) == 0)
return false;
// if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Equals) == 0)
// return false;
if (!genericParamInst->mExternType->IsGenericParam())
return false;
@ -1490,6 +1477,9 @@ bool BfMethodMatcher::InferFromGenericConstraints(BfGenericParamInstance* generi
if (checkOpConstraint.mBinaryOp != BfBinaryOp_None)
{
if ((leftType == NULL) || (rightType == NULL))
continue;
BfExprEvaluator exprEvaluator(mModule);
BfTypedValue leftValue(mModule->mBfIRBuilder->GetFakeVal(), leftType);
@ -1507,6 +1497,9 @@ bool BfMethodMatcher::InferFromGenericConstraints(BfGenericParamInstance* generi
}
else
{
if (rightType == NULL)
continue;
BfTypedValue rightValue(mModule->mBfIRBuilder->GetFakeVal(), rightType);
StringT<128> failedOpName;
@ -1537,6 +1530,28 @@ bool BfMethodMatcher::InferFromGenericConstraints(BfGenericParamInstance* generi
}
}
if ((checkArgType == NULL) && ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_ComptypeExpr) != 0))
{
for (auto comptypeConstraint : genericParamInst->mComptypeConstraint)
{
BfConstraintState constraintSet;
constraintSet.mPrevState = mModule->mContext->mCurConstraintState;
constraintSet.mGenericParamInstance = genericParamInst;
constraintSet.mMethodInstance = methodInstance;
constraintSet.mMethodGenericArgsOverride = methodGenericArgs;
SetAndRestoreValue<BfConstraintState*> prevConstraintSet(mModule->mContext->mCurConstraintState, &constraintSet);
if (!mModule->CheckConstraintState(NULL))
return false;
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mModule->mCurMethodInstance, methodInstance);
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mModule->mCurTypeInstance, methodInstance->GetOwner());
SetAndRestoreValue<bool> prevIgnoreErrors(mModule->mIgnoreErrors, true);
checkArgType = mModule->ResolveTypeRef(comptypeConstraint);
}
}
if (checkArgType == NULL)
return false;
if (checkArgType->IsVar())
@ -1857,23 +1872,55 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
}
paramIdx++;
}
}
//
for (int genericArgIdx = uniqueGenericStartIdx; genericArgIdx < (int)checkMethod->mGenericParams.size(); genericArgIdx++)
{
auto& genericArg = mCheckMethodGenericArguments[genericArgIdx];
if (genericArg == NULL)
{
auto genericParam = methodInstance->mMethodInfoEx->mGenericParams[genericArgIdx];
InferFromGenericConstraints(genericParam, &mCheckMethodGenericArguments);
if (genericArg != NULL)
continue;
if (!allowEmptyGenericSet.Contains(genericArgIdx))
goto NoMatch;
}
}
// while (true)
// {
//
// }
//
bool failed = false;
bool inferredAllGenericArguments = false;
for (int pass = 0; true; pass++)
{
bool madeProgress = false;
bool hasUninferred = false;
failed = false;
for (int genericArgIdx = uniqueGenericStartIdx; genericArgIdx < (int)checkMethod->mGenericParams.size(); genericArgIdx++)
{
auto& genericArg = mCheckMethodGenericArguments[genericArgIdx];
if (genericArg == NULL)
{
auto genericParam = methodInstance->mMethodInfoEx->mGenericParams[genericArgIdx];
InferFromGenericConstraints(methodInstance, genericParam, &mCheckMethodGenericArguments);
if (genericArg != NULL)
{
if (inferredAllGenericArguments)
genericInferContext.InferGenericArguments(methodInstance, genericArgIdx);
madeProgress = true;
}
hasUninferred = true;
if (!allowEmptyGenericSet.Contains(genericArgIdx))
failed = true;
}
}
if (!hasUninferred)
break;
if (inferredAllGenericArguments)
{
if (!madeProgress)
break;
}
genericInferContext.InferGenericArguments(methodInstance);
inferredAllGenericArguments = true;
}
if (failed)
goto NoMatch;
}
if (checkMethod->mMethodType == BfMethodType_Extension)
@ -2538,7 +2585,7 @@ void BfMethodMatcher::TryDevirtualizeCall(BfTypedValue target, BfTypedValue* ori
if ((mModule->mCompiler->IsAutocomplete()) || (mModule->mContext->mResolvingVarField))
return;
if (mModule->mBfIRBuilder->mIgnoreWrites)
if ((mModule->mBfIRBuilder->mIgnoreWrites) && (!mBestMethodDef->mIsConcrete))
return;
if (mBestMethodTypeInstance->IsInterface())
@ -5169,6 +5216,17 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
auto _GetDefaultReturnValue = [&]()
{
if (methodInstance->mVirtualTableIdx == -1)
{
if (methodInstance->GetOwner()->IsInterface())
{
// We're attempting to directly invoke a non-virtual interface method, if we're return an interface then
// it is a concrete interface
if (returnType->IsInterface())
returnType = mModule->CreateConcreteInterfaceType(returnType->ToTypeInstance());
}
}
if ((returnType->IsVar()) && (mExpectingType != NULL))
returnType = mExpectingType;
if (returnType->IsRef())
@ -5241,19 +5299,8 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
if (wantQuickEval)
{
// In an autocomplete pass we may have stale method references that need to be resolved
// in the full classify pass, and in the full classify pass while just refreshing internals, we
// may have NULL funcs temporarily. We simply skip generating the method call here.
if (methodInstance->mVirtualTableIdx == -1)
{
if (methodInstance->GetOwner()->IsInterface())
{
// We're attempting to directly invoke a non-virtual interface method, if we're return an interface then
// it is a concrete interface
if (returnType->IsInterface())
returnType = mModule->CreateConcreteInterfaceType(returnType->ToTypeInstance());
}
}
// in the full classify pass, and in the full classify pass while just refreshing internals, we
// may have NULL funcs temporarily. We simply skip generating the method call here.
if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0)
{
if (methodInstance->mReturnType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))
@ -5348,6 +5395,15 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
}
else
{
if (returnType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))
{
if (mExpectingType->IsUndefSizedArray())
{
if (returnType->GetUnderlyingType() == mExpectingType->GetUnderlyingType())
return mModule->GetDefaultTypedValue(mExpectingType, true, BfDefaultValueKind_Undef);
}
}
return mModule->GetDefaultTypedValue(returnType, true, BfDefaultValueKind_Undef);
}
@ -6148,7 +6204,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
if (!mModule->mCompiler->mIsResolveOnly)
sCallIdx++;
int callIdx = sCallIdx;
if (callIdx == 1177)
if (callIdx == 0x000020F9)
{
NOP;
}
@ -7594,8 +7650,7 @@ bool BfExprEvaluator::CheckGenericCtor(BfGenericParamType* genericParamType, BfR
{
mModule->Fail(StrFormat("Must add 'where %s : struct' constraint to generic parameter to instantiate type without allocator", genericConstraint->GetGenericParamDef()->mName.c_str()), targetSrc);
success = false;
}
}
return success;
}
@ -7618,9 +7673,12 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
BF_ASSERT(!mFunctionBindResult->mOrigTarget);
mFunctionBindResult->mOrigTarget = origTarget;
}
if (target)
{
if (target.mType->IsConcreteInterfaceType())
target.mType = target.mType->GetUnderlyingType();
// Turn T* into a T, if we can
if ((target.mType->IsPointer()) && (target.mType->GetUnderlyingType()->IsGenericParam()))
{
@ -9790,7 +9848,6 @@ void BfExprEvaluator::Visit(BfTypeOfExpression* typeOfExpr)
}
mModule->AddDependency(type, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
mResult = BfTypedValue(mModule->CreateTypeDataRef(type), typeType);
}
@ -15580,6 +15637,11 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
}
}
}
else if (expectingType->IsVar())
{
// Silently allow
gaveUnqualifiedDotError = true;
}
else
{
gaveUnqualifiedDotError = true;