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

Added constraint test for casting

This commit is contained in:
Brian Fiete 2020-09-19 06:41:36 -07:00
parent 93f5890d6d
commit e4892af4c9
3 changed files with 95 additions and 62 deletions

View file

@ -17943,10 +17943,13 @@ BfTypedValue BfExprEvaluator::PerformUnaryOperation_TryOperator(const BfTypedVal
}
if (isConstraintCheck)
{
operatorConstraintReturnType = mModule->CheckOperator(checkType, operatorDef, inValue, BfTypedValue());
if (operatorConstraintReturnType != NULL)
auto returnType = mModule->CheckOperator(checkType, operatorDef, inValue, BfTypedValue());
if (returnType != NULL)
{
operatorConstraintReturnType = returnType;
methodMatcher.mBestMethodDef = operatorDef;
}
}
else
{
if (methodMatcher.CheckMethod(NULL, checkType, operatorDef, false))
@ -17969,7 +17972,7 @@ BfTypedValue BfExprEvaluator::PerformUnaryOperation_TryOperator(const BfTypedVal
{
if (opConstraint.mUnaryOp == findOp)
{
if (mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType, isConstraintCheck ? BfCastFlags_NoConversionOperator : BfCastFlags_None))
if (mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType, isConstraintCheck ? BfCastFlags_IsConstraintCheck : BfCastFlags_None))
{
return BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
}
@ -17989,7 +17992,7 @@ BfTypedValue BfExprEvaluator::PerformUnaryOperation_TryOperator(const BfTypedVal
{
if (opConstraint.mUnaryOp == findOp)
{
if (mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType, isConstraintCheck ? BfCastFlags_NoConversionOperator : BfCastFlags_None))
if (mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType, isConstraintCheck ? BfCastFlags_IsConstraintCheck : BfCastFlags_None))
{
return BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
}
@ -19329,9 +19332,10 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
{
// We can't do CheckMethod because circular referencing means we may have to evaluate this before our type is complete,
// which means before method processing has occurred
operatorConstraintReturnType = mModule->CheckOperator(checkType, operatorDef, leftValue, rightValue);
if (operatorConstraintReturnType != NULL)
auto returnType = mModule->CheckOperator(checkType, operatorDef, args[0].mTypedValue, args[1].mTypedValue);
if (returnType != NULL)
{
operatorConstraintReturnType = returnType;
methodMatcher.mBestMethodDef = operatorDef;
foundExactMatch = true;
}
@ -19357,9 +19361,10 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
{
if ((flags & BfBinOpFlag_IsConstraintCheck) != 0)
{
operatorConstraintReturnType = mModule->CheckOperator(checkType, oppositeOperatorDef, leftValue, rightValue);
if (operatorConstraintReturnType != NULL)
auto returnType = mModule->CheckOperator(checkType, oppositeOperatorDef, args[0].mTypedValue, args[1].mTypedValue);
if (returnType != NULL)
{
operatorConstraintReturnType = returnType;
methodMatcher.mBestMethodDef = oppositeOperatorDef;
methodMatcher.mSelfType = entry.mSrcType;
}

View file

@ -9686,16 +9686,14 @@ BfType* BfModule::CheckOperator(BfTypeInstance* typeInstance, BfOperatorDef* ope
{
if (operatorInfo->mLHSType == NULL)
return NULL;
// TODO: Make this be a special flag to do CheckOperator conversion checks?
if (!CanCast(lhs, operatorInfo->mLHSType, BfCastFlags_NoConversionOperator))
if (!CanCast(lhs, operatorInfo->mLHSType, BfCastFlags_IsConstraintCheck))
return NULL;
}
if (rhs)
{
if (operatorInfo->mRHSType == NULL)
return NULL;
// TODO: Make this be a special flag to do CheckOperator conversion checks?
if (!CanCast(rhs, operatorInfo->mRHSType, BfCastFlags_NoConversionOperator))
if (!CanCast(rhs, operatorInfo->mRHSType, BfCastFlags_IsConstraintCheck))
return NULL;
}
return operatorInfo->mReturnType;

View file

@ -10557,6 +10557,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
BfIRValue conversionResult;
BfMethodInstance* opMethodInstance = NULL;
BfType* opMethodSrcType = NULL;
BfOperatorInfo* constraintOperatorInfo = NULL;
// Normal, lifted, execute
for (int pass = 0; pass < 3; pass++)
@ -10580,6 +10581,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
break;
}
bool isConstraintCheck = ((castFlags & BfCastFlags_IsConstraintCheck) != 0);
BfBaseClassWalker baseClassWalker(fromType, toType, this);
while (true)
@ -10597,16 +10599,29 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
(operatorDef->mOperatorDeclaration->mExplicitToken->GetToken() == BfToken_Explicit))
continue;
auto methodInst = GetRawMethodInstanceAtIdx(checkInstance, operatorDef->mIdx);
BfType* methodFromType = NULL;
BfType* methodToType = NULL;
if (isConstraintCheck)
{
auto operatorInfo = GetOperatorInfo(checkInstance, operatorDef);
methodFromType = operatorInfo->mLHSType;
methodToType = operatorInfo->mReturnType;
if ((methodFromType == NULL) || (methodToType == NULL))
continue;
}
else
{
auto methodInst = GetRawMethodInstanceAtIdx(checkInstance, operatorDef->mIdx);
if (methodInst->GetParamCount() != 1)
{
AssertErrorState();
continue;
}
auto methodFromType = methodInst->GetParamType(0);
auto methodToType = methodInst->mReturnType;
methodFromType = methodInst->GetParamType(0);
methodToType = methodInst->mReturnType;
}
if (methodFromType->IsSelf())
methodFromType = entry.mSrcType;
@ -10672,16 +10687,22 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
if ((toDist >= 0) && (toDist < bestNegToDist))
{
bestNegToDist = toDist;
bestNegToType = methodInst->mReturnType;
bestNegToType = methodToType;
}
}
}
else if (pass == 2) // Execution Pass
{
if ((methodFromType == bestFromType) && (methodToType == bestToType))
{
if (isConstraintCheck)
{
auto operatorInfo = GetOperatorInfo(checkInstance, operatorDef);
constraintOperatorInfo = operatorInfo;
}
else
{
// Get in native module so our module doesn't get a reference to it - we may not end up calling it at all!
//BfModuleMethodInstance methodInstance = checkInstance->mModule->GetMethodInstanceAtIdx(checkInstance, operatorDef->mIdx);
BfMethodInstance* methodInstance = GetRawMethodInstanceAtIdx(checkInstance, operatorDef->mIdx);
if (opMethodInstance != NULL)
@ -10714,11 +10735,12 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
}
}
}
}
if (isAmbiguousCast)
break;
if (opMethodInstance != NULL)
if ((opMethodInstance != NULL) || (constraintOperatorInfo != NULL))
{
if (mayBeBox)
{
@ -10731,8 +10753,15 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
SetFail();
}
BfType* returnType;
if (isConstraintCheck)
{
returnType = constraintOperatorInfo->mReturnType;
}
else
{
returnType = opMethodInstance->mReturnType;
BfMethodInstance* methodInstance = GetRawMethodInstance(opMethodInstance->GetOwner(), opMethodInstance->mMethodDef);
auto methodDeclaration = methodInstance->mMethodDef->GetMethodDeclaration();
if (methodDeclaration->mBody == NULL)
{
@ -10748,6 +10777,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
return castedVal;
}
}
}
// Actually perform conversion
BfExprEvaluator exprEvaluator(this);
@ -10758,9 +10788,9 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
BfTypedValue operatorOut;
if (ignoreWrites)
{
if (opMethodInstance->mReturnType == toType)
if (returnType == toType)
return mBfIRBuilder->GetFakeVal();
operatorOut = GetDefaultTypedValue(opMethodInstance->mReturnType);
operatorOut = GetDefaultTypedValue(returnType);
}
else
{