mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-14 14:24:10 +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 hasVariable = false;
|
||||||
bool hasOut = false;
|
bool hasOut = false;
|
||||||
|
@ -2429,12 +2433,19 @@ void BfExprEvaluator::Visit(BfCaseExpression* caseExpr)
|
||||||
if (hasOut)
|
if (hasOut)
|
||||||
clearOutOnMismatch = !CheckVariableDeclaration(caseExpr, true, true, true);
|
clearOutOnMismatch = !CheckVariableDeclaration(caseExpr, true, true, true);
|
||||||
|
|
||||||
|
bool hadConditional = false;
|
||||||
|
if (isPayloadEnum)
|
||||||
|
{
|
||||||
int dscrDataIdx;
|
int dscrDataIdx;
|
||||||
auto dscrType = caseValAddr.mType->ToTypeInstance()->GetDiscriminatorType(&dscrDataIdx);
|
auto dscrType = caseValAddr.mType->ToTypeInstance()->GetDiscriminatorType(&dscrDataIdx);
|
||||||
auto enumTagVal = mModule->LoadValue(mModule->ExtractValue(caseValAddr, NULL, 2));
|
auto enumTagVal = mModule->LoadValue(mModule->ExtractValue(caseValAddr, NULL, 2));
|
||||||
int uncondTagId = -1;
|
int uncondTagId = -1;
|
||||||
bool hadConditional = false;
|
|
||||||
mResult = mModule->TryCaseEnumMatch(caseValAddr, enumTagVal, caseExpr->mCaseExpression, NULL, NULL, NULL, uncondTagId, hadConditional, clearOutOnMismatch);
|
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)
|
if (mResult)
|
||||||
return;
|
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, BfTupleExpression* tupleExpr, BfTypedValue initTupleValue, bool isReadOnly, bool isConst, bool forceAddr, BfIRBlock* declBlock = NULL);
|
||||||
void HandleTupleVariableDeclaration(BfVariableDeclaration* varDecl);
|
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);
|
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 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);
|
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);
|
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)
|
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);
|
auto invocationExpr = BfNodeDynCast<BfInvocationExpression>(expr);
|
||||||
|
@ -2431,6 +2593,8 @@ BfTypedValue BfModule::TryCaseEnumMatch(BfTypedValue enumVal, BfTypedValue tagVa
|
||||||
tupleVal = GetDefaultTypedValue(tupleType);
|
tupleVal = GetDefaultTypedValue(tupleType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
BfAstNode* tooFewRef = invocationExpr->mCloseParen;
|
BfAstNode* tooFewRef = invocationExpr->mCloseParen;
|
||||||
if ((tooFewRef == NULL) && (!invocationExpr->mCommas.IsEmpty()))
|
if ((tooFewRef == NULL) && (!invocationExpr->mCommas.IsEmpty()))
|
||||||
tooFewRef = invocationExpr->mCommas[invocationExpr->mCommas.size() - 1];
|
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);
|
HandleCaseEnumMatch_Tuple(tupleVal, invocationExpr->mArguments, tooFewRef, falseBlock ? BfIRValue() : phiVal, matchedBlock, falseBlock ? falseBlock : doneBlock, hadConditional, clearOutOnMismatch);
|
||||||
|
|
||||||
|
///////
|
||||||
|
|
||||||
if (phiVal)
|
if (phiVal)
|
||||||
{
|
{
|
||||||
auto trueVal = mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 1);
|
auto trueVal = mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 1);
|
||||||
|
@ -4074,6 +4240,21 @@ void BfModule::Visit(BfSwitchStatement* switchStmt)
|
||||||
eqResult = eqTypedResult.mValue;
|
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)
|
if (!eqResult)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue