1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Fixed tuple pattern matching

This commit is contained in:
Brian Fiete 2019-11-27 08:00:15 -08:00
parent 582556dee2
commit c1d1659e2a
3 changed files with 201 additions and 8 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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, &notEqBB, &matchBlock, hadConditional, false);
if (hadConditional)
hadCondCase = true;
if (eqTypedResult)
{
mayHaveMatch = true;
handled = true;
eqResult = eqTypedResult.mValue;
}
}
if (!eqResult)
{