From fb4175736fe6b7a7d538e5fe5ce098b03a19f179 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Fri, 2 Oct 2026 22:35:26 +0800 Subject: [PATCH] =?UTF-8?q?fix(flow):=20=E5=BE=AA=E7=8E=AF/match=20?= =?UTF-8?q?=E5=A4=96=E7=9A=84=20break/continue=20=E6=94=B9=E4=B8=BA=20fail?= =?UTF-8?q?-fast?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - StmtGenDeclMixin:translate_break / translate_continue 增加 node 形参,目标块 缺失(_break_bb / _continue_bb 为 None)时 fatal_error,不再静默不发跳转 - StmtGenMixin:Break / Continue 分派传入 node(供错误定位) --- App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp | 26 ++++++++++++++--------- App/lib/core/Gen/Stmt/StmtGenMixin.vp | 4 ++-- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp b/App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp index 5a28340..5db125e 100644 --- a/App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp +++ b/App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp @@ -257,8 +257,8 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): return self.translate_nonlocal(trans, node) return 0 - def translate_break(self, trans: HT.Translator*) -> int: - """翻译 break 语句:跳转到循环 end 块""" + def translate_break(self, trans: HT.Translator*, node: ast.AST*) -> int: + """翻译 break 语句:跳转到 break 目标(循环 end / match end)""" builder: llvmlite.IRBuilder* = trans._cur_builder func: llvmlite.Function* = trans._cur_func pool: memhub.MemBuddy* = trans.Pool @@ -266,10 +266,13 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): if builder is None or func is None: return 0 - # 发射 br 到 break 目标 - if trans._break_bb is not None: - if llvmlite.builder_cur_block_is_terminated(builder) == 0: - llvmlite.build_br(builder, trans._break_bb) + # 发射 br 到 break 目标(_break_bb 由循环或 match-case 生成侧设置) + if trans._break_bb is None: + # fail-fast:没有循环 / match-case 时 break 无处可跳,禁止静默无效果 + self.Gen.TypeGenErr.fatal_error(node, + "break 只能用在循环或 match-case 体内(当前没有可跳出的目标)", "SyntaxError") + if llvmlite.builder_cur_block_is_terminated(builder) == 0: + llvmlite.build_br(builder, trans._break_bb) # 创建死代码 BB,用于后续语句(break 后面的代码不可达) cnt: int = trans._label_counter @@ -294,7 +297,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): "fallthrough 只能用在 match-case 语句体内(语义是落到下一个 case)", "SyntaxError") return 0 - def translate_continue(self, trans: HT.Translator*) -> int: + def translate_continue(self, trans: HT.Translator*, node: ast.AST*) -> int: """翻译 continue 语句:跳转到循环 cond/incr 块""" builder: llvmlite.IRBuilder* = trans._cur_builder func: llvmlite.Function* = trans._cur_func @@ -304,9 +307,12 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): return 0 # 发射 br 到 continue 目标 - if trans._continue_bb is not None: - if llvmlite.builder_cur_block_is_terminated(builder) == 0: - llvmlite.build_br(builder, trans._continue_bb) + if trans._continue_bb is None: + # fail-fast:循环之外的 continue 无处可跳,禁止静默无效果 + self.Gen.TypeGenErr.fatal_error(node, + "continue 只能用在循环体内(当前没有可继续的循环)", "SyntaxError") + if llvmlite.builder_cur_block_is_terminated(builder) == 0: + llvmlite.build_br(builder, trans._continue_bb) # 创建死代码 BB,用于后续语句 cnt: int = trans._label_counter diff --git a/App/lib/core/Gen/Stmt/StmtGenMixin.vp b/App/lib/core/Gen/Stmt/StmtGenMixin.vp index e0a61ec..d605515 100644 --- a/App/lib/core/Gen/Stmt/StmtGenMixin.vp +++ b/App/lib/core/Gen/Stmt/StmtGenMixin.vp @@ -87,9 +87,9 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): elif k == ast.ASTKind.Pass: return 0 elif k == ast.ASTKind.Break: - return self.translate_break(trans) + return self.translate_break(trans, node) elif k == ast.ASTKind.Continue: - return self.translate_continue(trans) + return self.translate_continue(trans, node) elif k == ast.ASTKind.FallThrough: return self.translate_fallthrough(trans, node) elif k == ast.ASTKind.Match: