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: