From 85273962be75793dd6e892c5931db826bb6fbbe6 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Sat, 16 Dec 2023 07:38:27 -0500 Subject: [PATCH] Added label support to 'fallthrough' --- IDEHelper/Compiler/BfAst.h | 1 + IDEHelper/Compiler/BfElementVisitor.cpp | 1 + IDEHelper/Compiler/BfPrinter.cpp | 6 ++++- IDEHelper/Compiler/BfReducer.cpp | 13 ++++++++++ IDEHelper/Compiler/BfStmtEvaluator.cpp | 33 ++++++++++++++++++++++--- 5 files changed, 49 insertions(+), 5 deletions(-) diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index c21d46fb..ab5650fd 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -3311,6 +3311,7 @@ public: BF_AST_TYPE(BfFallthroughStatement, BfStatement); BfTokenNode* mFallthroughToken; + BfAstNode* mLabel; }; BF_AST_DECL(BfFallthroughStatement, BfStatement); class BfForEachStatement : public BfLabelableStatement diff --git a/IDEHelper/Compiler/BfElementVisitor.cpp b/IDEHelper/Compiler/BfElementVisitor.cpp index aaa007d8..ae457245 100644 --- a/IDEHelper/Compiler/BfElementVisitor.cpp +++ b/IDEHelper/Compiler/BfElementVisitor.cpp @@ -902,6 +902,7 @@ void BfElementVisitor::Visit(BfFallthroughStatement* fallthroughStmt) Visit(fallthroughStmt->ToBase()); VisitChild(fallthroughStmt->mFallthroughToken); + VisitChild(fallthroughStmt->mLabel); } void BfElementVisitor::Visit(BfForStatement* forStmt) diff --git a/IDEHelper/Compiler/BfPrinter.cpp b/IDEHelper/Compiler/BfPrinter.cpp index 638329fa..a29fafc5 100644 --- a/IDEHelper/Compiler/BfPrinter.cpp +++ b/IDEHelper/Compiler/BfPrinter.cpp @@ -2275,7 +2275,11 @@ void BfPrinter::Visit(BfFallthroughStatement* fallthroughStmt) Visit(fallthroughStmt->ToBase()); VisitChild(fallthroughStmt->mFallthroughToken); - + if (fallthroughStmt->mLabel != NULL) + { + ExpectSpace(); + VisitChild(fallthroughStmt->mLabel); + } VisitChild(fallthroughStmt->mTrailingSemicolon); } diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index 1fea9dda..29d5d8be 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -3838,6 +3838,19 @@ BfAstNode* BfReducer::DoCreateStatement(BfAstNode* node, CreateStmtFlags createS auto fallthroughStmt = mAlloc->Alloc(); ReplaceNode(tokenNode, fallthroughStmt); fallthroughStmt->mFallthroughToken = tokenNode; + if (auto label = BfNodeDynCast(mVisitorPos.GetNext())) + { + MEMBER_SET(fallthroughStmt, mLabel, label); + mVisitorPos.MoveNext(); + } + else if (auto tokenNode = BfNodeDynCast(mVisitorPos.GetNext())) + { + if (tokenNode->GetToken() == BfToken_Mixin) + { + MEMBER_SET(fallthroughStmt, mLabel, tokenNode); + mVisitorPos.MoveNext(); + } + } return fallthroughStmt; } else if (token == BfToken_For) diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index a3ea96b8..8ff31bc9 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -5637,11 +5637,27 @@ void BfModule::Visit(BfFallthroughStatement* fallthroughStmt) { UpdateSrcPos(fallthroughStmt); BfBreakData* breakData = mCurMethodState->mBreakData; - while (breakData != NULL) + if (fallthroughStmt->mLabel != NULL) { - if (breakData->mIRFallthroughBlock) - break; - breakData = breakData->mPrevBreakData; + breakData = FindBreakData(fallthroughStmt->mLabel); + } + else + { + while (breakData != NULL) + { + if (breakData->mIRFallthroughBlock) + break; + breakData = breakData->mPrevBreakData; + } + } + + if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL)) + { + BfScopeData* scope = NULL; + if (breakData != NULL) + scope = breakData->mScope; + if (auto identifer = BfNodeDynCast(fallthroughStmt->mLabel)) + mCompiler->mResolvePassData->mAutoComplete->CheckLabel(identifer, fallthroughStmt->mFallthroughToken, scope); } if (mCurMethodState->mInDeferredBlock) @@ -5669,6 +5685,15 @@ void BfModule::Visit(BfFallthroughStatement* fallthroughStmt) mCurMethodState->mLeftBlockUncond = true; // Not really a return, but handled the same way if (mCurMethodState->mDeferredLocalAssignData != NULL) mCurMethodState->mDeferredLocalAssignData->mHadFallthrough = true; + + auto checkBreakData = mCurMethodState->mBreakData; + while (true) + { + if (checkBreakData == breakData) + break; + checkBreakData->mHadBreak = true; + checkBreakData = checkBreakData->mPrevBreakData; + } } void BfModule::Visit(BfUsingStatement* usingStmt)