1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 03:52:19 +02:00

Allow 'ref' on case matching

This commit is contained in:
Brian Fiete 2025-02-04 06:45:05 -08:00
parent b92b561867
commit 8b7dd19f4b

View file

@ -2381,6 +2381,7 @@ void BfModule::HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArr
BfTypedValue mArgValue; BfTypedValue mArgValue;
BfTypedValue mTupleElement; BfTypedValue mTupleElement;
int mFieldIdx; int mFieldIdx;
bool mIsOut;
}; };
Array<DeferredAssign> deferredAssigns; Array<DeferredAssign> deferredAssigns;
@ -2532,7 +2533,7 @@ void BfModule::HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArr
BfExprEvaluator exprEvaluator(this); BfExprEvaluator exprEvaluator(this);
exprEvaluator.mExpectingType = tupleFieldInstance->GetResolvedType(); exprEvaluator.mExpectingType = tupleFieldInstance->GetResolvedType();
exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_AllowOutExpr; exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(BfEvalExprFlags_AllowOutExpr | BfEvalExprFlags_AllowRefExpr);
if (mCurMethodState->mDeferredLocalAssignData != NULL) if (mCurMethodState->mDeferredLocalAssignData != NULL)
{ {
SetAndRestoreValue<bool> prevIsIfCondition(mCurMethodState->mDeferredLocalAssignData->mIsIfCondition, true); SetAndRestoreValue<bool> prevIsIfCondition(mCurMethodState->mDeferredLocalAssignData->mIsIfCondition, true);
@ -2554,25 +2555,30 @@ void BfModule::HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArr
if (argValue.mType->IsRef()) if (argValue.mType->IsRef())
{ {
auto refType = (BfRefType*)argValue.mType; auto refType = (BfRefType*)argValue.mType;
if (refType->mRefKind != BfRefType::RefKind_Out) bool isOut = refType->mRefKind == BfRefType::RefKind_Out;
{ if ((refType->mRefKind != BfRefType::RefKind_Out) && (refType->mRefKind != BfRefType::RefKind_Ref))
BfAstNode* refNode = expr; {
if (auto unaryOperatorExpr = BfNodeDynCast<BfUnaryOperatorExpression>(expr)) BfAstNode* refNode = expr;
refNode = unaryOperatorExpr->mOpToken; if (auto unaryOperatorExpr = BfNodeDynCast<BfUnaryOperatorExpression>(expr))
Fail("Only 'out' refs can be used to assign to an existing value", refNode); refNode = unaryOperatorExpr->mOpToken;
} Fail("Invalid ref type", refNode);
}
DeferredAssign deferredAssign = { expr, argValue, tupleElement, tupleFieldIdx };
DeferredAssign deferredAssign = { expr, argValue, tupleElement, tupleFieldIdx, isOut };
deferredAssigns.push_back(deferredAssign); deferredAssigns.push_back(deferredAssign);
if (mCurMethodState->mDeferredLocalAssignData != NULL)
{ if (isOut)
SetAndRestoreValue<bool> prevIsIfCondition(mCurMethodState->mDeferredLocalAssignData->mIsIfCondition, true); {
SetAndRestoreValue<bool> prevIfMayBeSkipped(mCurMethodState->mDeferredLocalAssignData->mIfMayBeSkipped, true); if (mCurMethodState->mDeferredLocalAssignData != NULL)
exprEvaluator.MarkResultAssigned(); {
} SetAndRestoreValue<bool> prevIsIfCondition(mCurMethodState->mDeferredLocalAssignData->mIsIfCondition, true);
else SetAndRestoreValue<bool> prevIfMayBeSkipped(mCurMethodState->mDeferredLocalAssignData->mIfMayBeSkipped, true);
{ exprEvaluator.MarkResultAssigned();
exprEvaluator.MarkResultAssigned(); }
else
{
exprEvaluator.MarkResultAssigned();
}
} }
continue; continue;
} }
@ -2626,6 +2632,9 @@ void BfModule::HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArr
mBfIRBuilder->SetInsertPoint(falseBlockEnd); mBfIRBuilder->SetInsertPoint(falseBlockEnd);
for (auto& deferredAssign : deferredAssigns) for (auto& deferredAssign : deferredAssigns)
{ {
if (!deferredAssign.mIsOut)
continue;
auto tupleFieldInstance = &tupleType->mFieldInstances[deferredAssign.mFieldIdx]; auto tupleFieldInstance = &tupleType->mFieldInstances[deferredAssign.mFieldIdx];
// We have to re-process the expr because we haven't done it in this branch, and then clear the result out // We have to re-process the expr because we haven't done it in this branch, and then clear the result out
SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, mHadBuildError); // Don't fail twice SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, mHadBuildError); // Don't fail twice