mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 04:22:20 +02:00
Fixed tuple pattern matching
This commit is contained in:
parent
582556dee2
commit
c1d1659e2a
3 changed files with 201 additions and 8 deletions
|
@ -2396,7 +2396,11 @@ void BfExprEvaluator::Visit(BfCaseExpression* caseExpr)
|
|||
}
|
||||
}
|
||||
|
||||
if ((caseValAddr) && (caseValAddr.mType->IsPayloadEnum()))
|
||||
bool isPayloadEnum = caseValAddr.mType->IsPayloadEnum();
|
||||
auto tupleExpr = BfNodeDynCast<BfTupleExpression>(caseExpr->mCaseExpression);
|
||||
|
||||
if ((caseValAddr) &&
|
||||
((isPayloadEnum) || (tupleExpr != NULL)))
|
||||
{
|
||||
bool hasVariable = false;
|
||||
bool hasOut = false;
|
||||
|
@ -2429,12 +2433,19 @@ void BfExprEvaluator::Visit(BfCaseExpression* caseExpr)
|
|||
if (hasOut)
|
||||
clearOutOnMismatch = !CheckVariableDeclaration(caseExpr, true, true, true);
|
||||
|
||||
int dscrDataIdx;
|
||||
auto dscrType = caseValAddr.mType->ToTypeInstance()->GetDiscriminatorType(&dscrDataIdx);
|
||||
auto enumTagVal = mModule->LoadValue(mModule->ExtractValue(caseValAddr, NULL, 2));
|
||||
int uncondTagId = -1;
|
||||
bool hadConditional = false;
|
||||
mResult = mModule->TryCaseEnumMatch(caseValAddr, enumTagVal, caseExpr->mCaseExpression, NULL, NULL, NULL, uncondTagId, hadConditional, clearOutOnMismatch);
|
||||
if (isPayloadEnum)
|
||||
{
|
||||
int dscrDataIdx;
|
||||
auto dscrType = caseValAddr.mType->ToTypeInstance()->GetDiscriminatorType(&dscrDataIdx);
|
||||
auto enumTagVal = mModule->LoadValue(mModule->ExtractValue(caseValAddr, NULL, 2));
|
||||
int uncondTagId = -1;
|
||||
mResult = mModule->TryCaseEnumMatch(caseValAddr, enumTagVal, caseExpr->mCaseExpression, NULL, NULL, NULL, uncondTagId, hadConditional, clearOutOnMismatch);
|
||||
}
|
||||
else
|
||||
{
|
||||
mResult = mModule->TryCaseTupleMatch(caseValAddr, tupleExpr, NULL, NULL, NULL, hadConditional, clearOutOnMismatch);
|
||||
}
|
||||
|
||||
if (mResult)
|
||||
return;
|
||||
|
|
|
@ -1638,6 +1638,7 @@ public:
|
|||
void HandleTupleVariableDeclaration(BfVariableDeclaration* varDecl, BfTupleExpression* tupleExpr, BfTypedValue initTupleValue, bool isReadOnly, bool isConst, bool forceAddr, BfIRBlock* declBlock = NULL);
|
||||
void HandleTupleVariableDeclaration(BfVariableDeclaration* varDecl);
|
||||
void HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArray<BfExpression*>& arguments, BfAstNode* tooFewRef, BfIRValue phiVal, BfIRBlock& matchedBlock, BfIRBlock falseBlock, bool& hadConditional, bool clearOutOnMismatch);
|
||||
BfTypedValue TryCaseTupleMatch(BfTypedValue tupleVal, BfTupleExpression* tupleExpr, BfIRBlock* eqBlock, BfIRBlock* notEqBlock, BfIRBlock* matchBlock, bool& hadConditional, bool clearOutOnMismatch);
|
||||
BfTypedValue TryCaseEnumMatch(BfTypedValue enumVal, BfTypedValue tagVal, BfExpression* expr, BfIRBlock* eqBlock, BfIRBlock* notEqBlock, BfIRBlock* matchBlock, int& uncondTagId, bool& hadConditional, bool clearOutOnMismatch);
|
||||
BfTypedValue HandleCaseBind(BfTypedValue enumVal, const BfTypedValue& tagVal, BfEnumCaseBindExpression* bindExpr, BfIRBlock* eqBlock = NULL, BfIRBlock* notEqBlock = NULL, BfIRBlock* matchBlock = NULL, int* outEnumIdx = NULL);
|
||||
void TryInitVar(BfAstNode* checkNode, BfLocalVariable* varDecl, BfTypedValue initValue, BfTypedValue& checkResult);
|
||||
|
|
|
@ -2273,6 +2273,168 @@ void BfModule::HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArr
|
|||
}
|
||||
}
|
||||
|
||||
BfTypedValue BfModule::TryCaseTupleMatch(BfTypedValue tupleVal, BfTupleExpression* tupleExpr, BfIRBlock* eqBlock, BfIRBlock* notEqBlock, BfIRBlock* matchBlock, bool& hadConditional, bool clearOutOnMismatch)
|
||||
{
|
||||
if (!tupleVal.mType->IsTuple())
|
||||
return false;
|
||||
|
||||
auto tupleType = (BfTupleType*)tupleVal.mType;
|
||||
|
||||
BfAstNode* tooFewRef = tupleExpr->mCloseParen;
|
||||
if ((tooFewRef == NULL) && (!tupleExpr->mCommas.IsEmpty()))
|
||||
tooFewRef = tupleExpr->mCommas[tupleExpr->mCommas.size() - 1];
|
||||
else if (tooFewRef == NULL)
|
||||
tooFewRef = tupleExpr->mOpenParen;
|
||||
|
||||
///
|
||||
|
||||
auto autoComplete = mCompiler->GetAutoComplete();
|
||||
|
||||
bool wasCapturingMethodInfo = false;
|
||||
if (autoComplete != NULL)
|
||||
{
|
||||
wasCapturingMethodInfo = autoComplete->mIsCapturingMethodMatchInfo;
|
||||
autoComplete->CheckInvocation(tupleExpr, tupleExpr->mOpenParen, tupleExpr->mCloseParen, tupleExpr->mCommas);
|
||||
|
||||
if (autoComplete->mIsCapturingMethodMatchInfo)
|
||||
{
|
||||
autoComplete->mMethodMatchInfo->mInstanceList.Clear();
|
||||
|
||||
auto methodMatchInfo = autoComplete->mMethodMatchInfo;
|
||||
|
||||
// auto methodDef = tupleType->mTypeDef->mMethods[0];
|
||||
//
|
||||
// BfAutoComplete::MethodMatchEntry methodMatchEntry;
|
||||
// methodMatchEntry.mMethodDef = methodDef;
|
||||
// methodMatchEntry.mTypeInstance = tupleType;
|
||||
// methodMatchEntry.mCurMethodInstance = mCurMethodInstance;
|
||||
// //methodMatchEntry.mPayloadEnumField = fieldInstance;
|
||||
//autoComplete->mMethodMatchInfo->mInstanceList.push_back(methodMatchEntry);
|
||||
|
||||
methodMatchInfo->mBestIdx = 0;
|
||||
methodMatchInfo->mMostParamsMatched = 0;
|
||||
|
||||
int cursorIdx = tupleExpr->GetParser()->mCursorIdx;
|
||||
if ((tupleExpr->mCloseParen == NULL) || (cursorIdx <= tupleExpr->mCloseParen->GetSrcStart()))
|
||||
{
|
||||
int paramIdx = 0;
|
||||
for (int commaIdx = 0; commaIdx < (int)tupleExpr->mCommas.size(); commaIdx++)
|
||||
{
|
||||
auto commaNode = tupleExpr->mCommas[commaIdx];
|
||||
if ((commaNode != NULL) && (cursorIdx >= commaNode->GetSrcStart()))
|
||||
paramIdx = commaIdx + 1;
|
||||
}
|
||||
|
||||
bool isEmpty = true;
|
||||
|
||||
if (paramIdx < (int)tupleExpr->mValues.size())
|
||||
{
|
||||
auto paramNode = tupleExpr->mValues[paramIdx];
|
||||
if (paramNode != NULL)
|
||||
isEmpty = false;
|
||||
}
|
||||
|
||||
if (isEmpty)
|
||||
{
|
||||
if (paramIdx < (int)tupleType->mFieldInstances.size())
|
||||
{
|
||||
auto fieldDef = tupleType->mFieldInstances[paramIdx].GetFieldDef();
|
||||
String insertStr;
|
||||
if (fieldDef->IsUnnamedTupleField())
|
||||
insertStr = "p";
|
||||
insertStr += fieldDef->mName;
|
||||
|
||||
insertStr.Insert(0, "let ");
|
||||
autoComplete->mEntriesSet.Clear();
|
||||
autoComplete->AddEntry(AutoCompleteEntry("paramName", insertStr));
|
||||
autoComplete->mInsertStartIdx = cursorIdx;
|
||||
autoComplete->mInsertEndIdx = cursorIdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defer
|
||||
(
|
||||
if (autoComplete != NULL)
|
||||
autoComplete->mIsCapturingMethodMatchInfo = (wasCapturingMethodInfo) && (!autoComplete->mIsCapturingMethodMatchInfo);
|
||||
);
|
||||
|
||||
///
|
||||
|
||||
//BfIRValue phiVal;
|
||||
auto boolType = GetPrimitiveType(BfTypeCode_Boolean);
|
||||
//phiVal = mBfIRBuilder->CreatePhi(mBfIRBuilder->MapType(boolType), 2);
|
||||
|
||||
auto startBlock = mBfIRBuilder->GetInsertBlock();
|
||||
//auto dscrType = enumType->GetDiscriminatorType();
|
||||
//BfIRValue eqResult = mBfIRBuilder->CreateCmpEQ(tagVal.mValue, mBfIRBuilder->CreateConst(dscrType->mTypeDef->mTypeCode, tagId));
|
||||
|
||||
BfIRBlock falseBlock;
|
||||
BfIRBlock doneBlock;
|
||||
if (notEqBlock != NULL)
|
||||
doneBlock = *notEqBlock;
|
||||
else
|
||||
doneBlock = mBfIRBuilder->CreateBlock("caseDone", false);
|
||||
|
||||
if (clearOutOnMismatch)
|
||||
{
|
||||
falseBlock = mBfIRBuilder->CreateBlock("caseNotEq", false);
|
||||
mBfIRBuilder->AddBlock(falseBlock);
|
||||
}
|
||||
|
||||
BfIRBlock matchedBlock = mBfIRBuilder->CreateBlock("caseMatch", false);
|
||||
if (matchBlock != NULL)
|
||||
*matchBlock = matchedBlock;
|
||||
mBfIRBuilder->CreateBr(matchedBlock);
|
||||
mBfIRBuilder->AddBlock(matchedBlock);
|
||||
|
||||
mBfIRBuilder->SetInsertPoint(doneBlock);
|
||||
BfIRValue phiVal;
|
||||
if (eqBlock == NULL)
|
||||
phiVal = mBfIRBuilder->CreatePhi(mBfIRBuilder->MapType(boolType), 2);
|
||||
if (phiVal)
|
||||
{
|
||||
auto falseVal = mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0);
|
||||
|
||||
if (falseBlock)
|
||||
mBfIRBuilder->AddPhiIncoming(phiVal, falseVal, falseBlock);
|
||||
// else
|
||||
// mBfIRBuilder->AddPhiIncoming(phiVal, falseVal, startBlock);
|
||||
}
|
||||
|
||||
mBfIRBuilder->SetInsertPoint(matchedBlock);
|
||||
|
||||
HandleCaseEnumMatch_Tuple(tupleVal, tupleExpr->mValues, tooFewRef, falseBlock ? BfIRValue() : phiVal, matchedBlock, falseBlock ? falseBlock : doneBlock, hadConditional, clearOutOnMismatch);
|
||||
|
||||
if (phiVal)
|
||||
{
|
||||
auto trueVal = mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 1);
|
||||
mBfIRBuilder->AddPhiIncoming(phiVal, trueVal, matchedBlock);
|
||||
}
|
||||
|
||||
if (eqBlock != NULL)
|
||||
mBfIRBuilder->CreateBr(*eqBlock);
|
||||
else
|
||||
mBfIRBuilder->CreateBr(doneBlock);
|
||||
|
||||
if (falseBlock)
|
||||
{
|
||||
mBfIRBuilder->SetInsertPoint(falseBlock);
|
||||
mBfIRBuilder->CreateBr(doneBlock);
|
||||
//mBfIRBuilder->AddPhiIncoming(phiVal, mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0), falseBlock);
|
||||
}
|
||||
|
||||
mBfIRBuilder->AddBlock(doneBlock);
|
||||
mBfIRBuilder->SetInsertPoint(doneBlock);
|
||||
|
||||
if (phiVal)
|
||||
return BfTypedValue(phiVal, boolType);
|
||||
else
|
||||
return GetDefaultTypedValue(boolType);
|
||||
}
|
||||
|
||||
BfTypedValue BfModule::TryCaseEnumMatch(BfTypedValue enumVal, BfTypedValue tagVal, BfExpression* expr, BfIRBlock* eqBlock, BfIRBlock* notEqBlock, BfIRBlock* matchBlock, int& tagId, bool& hadConditional, bool clearOutOnMismatch)
|
||||
{
|
||||
auto invocationExpr = BfNodeDynCast<BfInvocationExpression>(expr);
|
||||
|
@ -2393,7 +2555,7 @@ BfTypedValue BfModule::TryCaseEnumMatch(BfTypedValue enumVal, BfTypedValue tagVa
|
|||
mBfIRBuilder->CreateCondBr(eqResult, matchedBlock, falseBlock ? falseBlock : doneBlock);
|
||||
|
||||
mBfIRBuilder->AddBlock(matchedBlock);
|
||||
|
||||
|
||||
mBfIRBuilder->SetInsertPoint(doneBlock);
|
||||
BfIRValue phiVal;
|
||||
if (eqBlock == NULL)
|
||||
|
@ -2409,7 +2571,7 @@ BfTypedValue BfModule::TryCaseEnumMatch(BfTypedValue enumVal, BfTypedValue tagVa
|
|||
}
|
||||
|
||||
mBfIRBuilder->SetInsertPoint(matchedBlock);
|
||||
|
||||
|
||||
BfTypedValue tupleVal;
|
||||
if (!enumVal.IsAddr())
|
||||
{
|
||||
|
@ -2431,6 +2593,8 @@ BfTypedValue BfModule::TryCaseEnumMatch(BfTypedValue enumVal, BfTypedValue tagVa
|
|||
tupleVal = GetDefaultTypedValue(tupleType);
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
BfAstNode* tooFewRef = invocationExpr->mCloseParen;
|
||||
if ((tooFewRef == NULL) && (!invocationExpr->mCommas.IsEmpty()))
|
||||
tooFewRef = invocationExpr->mCommas[invocationExpr->mCommas.size() - 1];
|
||||
|
@ -2513,6 +2677,8 @@ BfTypedValue BfModule::TryCaseEnumMatch(BfTypedValue enumVal, BfTypedValue tagVa
|
|||
|
||||
HandleCaseEnumMatch_Tuple(tupleVal, invocationExpr->mArguments, tooFewRef, falseBlock ? BfIRValue() : phiVal, matchedBlock, falseBlock ? falseBlock : doneBlock, hadConditional, clearOutOnMismatch);
|
||||
|
||||
///////
|
||||
|
||||
if (phiVal)
|
||||
{
|
||||
auto trueVal = mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 1);
|
||||
|
@ -4074,6 +4240,21 @@ void BfModule::Visit(BfSwitchStatement* switchStmt)
|
|||
eqResult = eqTypedResult.mValue;
|
||||
}
|
||||
}
|
||||
else if (auto tupleExpr = BfNodeDynCast<BfTupleExpression>(caseExpr))
|
||||
{
|
||||
notEqBB = mBfIRBuilder->CreateBlock(StrFormat("switch.notEq.%d", blockIdx), false);
|
||||
|
||||
BfIRBlock matchBlock;
|
||||
BfTypedValue eqTypedResult = TryCaseTupleMatch(switchValue, tupleExpr, &caseBlock, ¬EqBB, &matchBlock, hadConditional, false);
|
||||
if (hadConditional)
|
||||
hadCondCase = true;
|
||||
if (eqTypedResult)
|
||||
{
|
||||
mayHaveMatch = true;
|
||||
handled = true;
|
||||
eqResult = eqTypedResult.mValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!eqResult)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue