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:
parent
93f5890d6d
commit
e4892af4c9
3 changed files with 95 additions and 62 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue