diff --git a/App/lib/Stub/StubMerger/StubMergerStore.vp b/App/lib/Stub/StubMerger/StubMergerStore.vp index dea67d6..88ca23f 100644 --- a/App/lib/Stub/StubMerger/StubMergerStore.vp +++ b/App/lib/Stub/StubMerger/StubMergerStore.vp @@ -554,14 +554,14 @@ def LookupSha1ByAlias(from_imports: str, alias: str) -> str: local_len: sizet = colon - ci if colon < total_len and from_imports[colon] == ':' and local_len == alias_len: # 比较 local_name == alias - match: int = 1 + Matched: int = 1 li: sizet = 0 while li < alias_len: if from_imports[ci + li] != alias[li]: - match = 0 + Matched = 0 break li += 1 - if match == 1: + if Matched == 1: # 提取 module(colon+1 到下一个 ':' 或空格) m_start: sizet = colon + 1 m_end: sizet = m_start @@ -609,14 +609,14 @@ def LookupModNameByAlias(from_imports: str, alias: str) -> str: local_len: sizet = colon - ci if colon < total_len and from_imports[colon] == ':' and local_len == alias_len: # 比较 local_name == alias - match: int = 1 + Matched: int = 1 li: sizet = 0 while li < alias_len: if from_imports[ci + li] != alias[li]: - match = 0 + Matched = 0 break li += 1 - if match == 1: + if Matched == 1: # 提取 module(colon+1 到下一个 ':' 或空格) m_start: sizet = colon + 1 m_end: sizet = m_start diff --git a/App/lib/core/Gen/Call/CallGenBase.vp b/App/lib/core/Gen/Call/CallGenBase.vp index f6da577..fb9b1a0 100644 --- a/App/lib/core/Gen/Call/CallGenBase.vp +++ b/App/lib/core/Gen/Call/CallGenBase.vp @@ -603,12 +603,12 @@ novirtual class CallGenBase: if cur_len > name_len + 1: suffix_start: sizet = cur_len - name_len if cur_name[suffix_start - 1] == '.': - match: int = 1 + Matched: int = 1 for i in range(name_len): if cur_name[suffix_start + i] != name[i]: - match = 0 + Matched = 0 break - if match == 1: + if Matched == 1: # 首个任意后缀命中(原第三遍兜底) if any_hit is None: any_hit = cur diff --git a/App/lib/core/Gen/Expr/ExprGenAttr.vp b/App/lib/core/Gen/Expr/ExprGenAttr.vp index e445c2e..eeb8c83 100644 --- a/App/lib/core/Gen/Expr/ExprGenAttr.vp +++ b/App/lib/core/Gen/Expr/ExprGenAttr.vp @@ -50,12 +50,12 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if cur_len > name_len + 1: suffix_start: sizet = cur_len - name_len if cur.Name[suffix_start - 1] == '.': - match: int = 1 + Matched: int = 1 for i in range(name_len): if cur.Name[suffix_start + i] != name[i]: - match = 0 + Matched = 0 break - if match == 1: + if Matched == 1: return cur cur = cur.Next return None diff --git a/App/lib/core/Gen/Func/FuncGenDef.vp b/App/lib/core/Gen/Func/FuncGenDef.vp index 91cbf3c..7016fa0 100644 --- a/App/lib/core/Gen/Func/FuncGenDef.vp +++ b/App/lib/core/Gen/Func/FuncGenDef.vp @@ -896,14 +896,14 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): # 否则嵌套函数体内的 break/continue 会继承外层函数(甚至跨函数)的 br 目标 old_break_bb: rawptr[llvmlite.BasicBlock] = trans._break_bb old_continue_bb: rawptr[llvmlite.BasicBlock] = trans._continue_bb - old_inmc: int = trans._in_match_case + old_insw: int = trans._in_switch_case trans._cur_func = func trans._cur_builder = func_builder trans.CurFuncRetAnnot = fd.returns trans._break_bb = None trans._continue_bb = None - trans._in_match_case = 0 + trans._in_switch_case = 0 # 清空 global/nonlocal 名称集合(新函数作用域) GenApi.clear_scope_names(trans) # 重置链内 nonlocal 堆预建标志(每函数只建一次;多嵌套函数定义 @@ -1050,7 +1050,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): trans._cur_builder = old_builder trans._break_bb = old_break_bb trans._continue_bb = old_continue_bb - trans._in_match_case = old_inmc + trans._in_switch_case = old_insw trans._global_name_count = old_global_count trans._nonlocal_name_count = old_nonlocal_count trans._closure_env_count = old_env_count diff --git a/App/lib/core/Gen/Func/FuncGenMixin.vp b/App/lib/core/Gen/Func/FuncGenMixin.vp index 9a67c4a..c5fec35 100644 --- a/App/lib/core/Gen/Func/FuncGenMixin.vp +++ b/App/lib/core/Gen/Func/FuncGenMixin.vp @@ -185,7 +185,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): # 否则嵌套函数体内的 break/continue 会继承外层函数的跳转目标(跨函数 br) old_break_bb: rawptr[llvmlite.BasicBlock] = trans._break_bb old_continue_bb: rawptr[llvmlite.BasicBlock] = trans._continue_bb - old_inmc: int = trans._in_match_case + old_insw: int = trans._in_switch_case # nonlocal 集合独立缓冲:嵌套函数注册 nonlocal 写入共享缓冲 [0] 会 # 覆盖父函数集合(ClosureTest2 Test 7 不同变量场景:level2 的 b 覆盖 # level1 的 a → level1 env[0] 存错)。嵌套函数用独立缓冲,翻译完恢复。 @@ -199,7 +199,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): GenApi.clear_scope_names(trans) trans._break_bb = None trans._continue_bb = None - trans._in_match_case = 0 + trans._in_switch_case = 0 # 嵌套函数独立 nonlocal 缓冲(避免覆盖父函数集合) trans._nonlocal_names = stdlib.malloc(HT.MAX_GLOBAL_NAMES * 8) trans._nonlocal_types = stdlib.malloc(HT.MAX_GLOBAL_NAMES * 8) @@ -264,7 +264,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): trans._cur_builder = old_builder trans._break_bb = old_break_bb trans._continue_bb = old_continue_bb - trans._in_match_case = old_inmc + trans._in_switch_case = old_insw if dbg_pushed_n != 0: DebugInfoGen.PopFunction(func_builder) # NOTE: _nonlocal_names 和 _nonlocal_name_count 仍为嵌套函数的值 @@ -1163,14 +1163,14 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): # 否则 lambda 体内的 break/continue 会继承外层函数的跳转目标(跨函数 br) old_break_bb: rawptr[llvmlite.BasicBlock] = trans._break_bb old_continue_bb: rawptr[llvmlite.BasicBlock] = trans._continue_bb - old_inmc: int = trans._in_match_case + old_insw: int = trans._in_switch_case trans._cur_func = func trans._cur_builder = func_builder trans._cur_func_name = mangled_promoted GenApi.clear_scope_names(trans) trans._break_bb = None trans._continue_bb = None - trans._in_match_case = 0 + trans._in_switch_case = 0 # 9. 捕获变量:从 env 堆槽加载值到局部 alloca for ci in range(cap_count): @@ -1237,7 +1237,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): trans._cur_builder = old_builder trans._break_bb = old_break_bb trans._continue_bb = old_continue_bb - trans._in_match_case = old_inmc + trans._in_switch_case = old_insw trans._cur_func_name = old_func_name trans._global_name_count = old_global_count trans._nonlocal_name_count = old_nonlocal_count diff --git a/App/lib/core/Gen/ImportsGenMixin.vp b/App/lib/core/Gen/ImportsGenMixin.vp index 834ff78..19c997b 100644 --- a/App/lib/core/Gen/ImportsGenMixin.vp +++ b/App/lib/core/Gen/ImportsGenMixin.vp @@ -220,12 +220,12 @@ novirtual class ImportsGenMixin: ci += 1 word_len: sizet = ci - word_start if word_len == name_len: - match: int = 1 + Matched: int = 1 for ei in range(name_len): if cur[word_start + ei] != name[ei]: - match = 0 + Matched = 0 break - if match == 1: + if Matched == 1: return 1 return 0 @@ -348,14 +348,14 @@ novirtual class ImportsGenMixin: continue # 比较名称 if entry_name_len == name_len: - match: int = 1 + Matched: int = 1 ei: sizet = 0 while ei < name_len: if cur[ci + ei] != local_name[ei]: - match = 0 + Matched = 0 break ei += 1 - if match == 1: + if Matched == 1: # 找到匹配,检查是否有第三个字段(原始名) pos: sizet = colon1 + 1 # 跳过模块名 @@ -440,14 +440,14 @@ novirtual class ImportsGenMixin: star_mod = cur + mod_start # 比较名称 elif entry_name_len == name_len: - match: int = 1 + Matched: int = 1 ei: sizet = 0 while ei < name_len: if cur[ci + ei] != name[ei]: - match = 0 + Matched = 0 break ei += 1 - if match == 1: + if Matched == 1: mod_start2: sizet = colon_pos + 1 mod_end2: sizet = mod_start2 # 模块名结束于: 空格、null、或第二个':'(别名格式的分隔符) diff --git a/App/lib/core/Gen/MatchGenMixin.vp b/App/lib/core/Gen/MatchGenMixin.vp index afe7115..0121786 100644 --- a/App/lib/core/Gen/MatchGenMixin.vp +++ b/App/lib/core/Gen/MatchGenMixin.vp @@ -91,8 +91,14 @@ novirtual class MatchGenMixin: m_node: ast.Match* = ast.Match*(node) # 重名 case 检测(fail-fast):C 的 switch 不允许重复 case 标签(重复标签让 - # 某个臂永远不可达,且常意味着漏改的分支);`case _`(default)只允许一个。 - # 在任何 IR 产出之前检查,保证报错即终止。 + # 某个臂永远不可达,且常意味着漏改的分支);通配臂(match 的 `case _` / + # switch 的 `default`)只允许一个。在任何 IR 产出之前检查,保证报错即终止。 + # 报文前缀按 is_switch 区分(switch / match),便于定位。 + kind_label: str = "match" + default_label: str = "`case _`" + if m_node.is_switch != 0: + kind_label = "switch" + default_label = "`default`" cases_chk: list[ast.AST*]* = m_node.cases if cases_chk is not None: ccn: sizet = len(cases_chk) @@ -114,13 +120,13 @@ novirtual class MatchGenMixin: dpat2: ast.AST* = rawptr[ast.MatchCase](dcase2).pattern if self._case_label_same(dpat, dpat2) != 0: self.Gen.TypeGenErr.fatal_error(dcase2, - f"match 出现重名 case:第 {dci} 与第 {dcj} 个 case 的标签相同(C switch 不允许重复 case 标签)", + f"{kind_label} 出现重名 case:第 {dci} 与第 {dcj} 个 case 的标签相同(C switch 不允许重复 case 标签)", "SyntaxError") dcj = dcj + 1 dci = dci + 1 if default_cnt > 1: self.Gen.TypeGenErr.fatal_error(node, - f"match 出现 {default_cnt} 个 `case _`(default 只允许一个)", "SyntaxError") + f"{kind_label} 出现 {default_cnt} 个 {default_label}(通配/default 只允许一个)", "SyntaxError") # 1. 求值 subject subject_node: ast.AST* = m_node.subject @@ -330,9 +336,9 @@ novirtual class MatchGenMixin: # ============================================================ # _has_no_break - 检测 case body 是否要求 fallthrough(落到下一个 case) # - # 两种写法等价: - # ① 软关键字语句 `fallthrough`(ASTKind.FallThrough) - # ② 兼容写法 `c.NoBreak()`:Expr(Call(Attribute(Name('c'), 'NoBreak'))) + # 只认 `fallthrough` 关键字语句(ASTKind.FallThrough)。该语句只可能在 switch + # 的 case 体内出现(translate_fallthrough 已对 match / switch 之外 fail-fast), + # 故此处无需再判上下文。 # ============================================================ def _has_no_break(self, body_list: list[ast.AST*]*) -> int: if body_list is None: @@ -343,22 +349,6 @@ novirtual class MatchGenMixin: stmt: ast.AST* = body_list.get(i) if stmt is not None and stmt.kind() == ast.ASTKind.FallThrough: return 1 - if stmt is not None and stmt.kind() == ast.ASTKind.Expr: - expr_node: rawptr[ast.Expr] = rawptr[ast.Expr](stmt) - val: ast.AST* = expr_node.value - if val is not None and val.kind() == ast.ASTKind.Call: - call_node: ast.Call* = ast.Call*(val) - fn: ast.AST* = call_node.func - if fn is not None and fn.kind() == ast.ASTKind.Attribute: - at: ast.Attribute* = (ast.Attribute*)(fn) - if at.value is not None \ - and at.value.kind() == ast.ASTKind.Name: - base_nm: ast.Name* = (ast.Name*)(at.value) - if base_nm.id is not None \ - and string.strcmp(base_nm.id, "c") == 0 \ - and at.attr is not None \ - and string.strcmp(at.attr, "NoBreak") == 0: - return 1 i = i + 1 return 0 @@ -681,8 +671,8 @@ novirtual class MatchGenMixin: # break 目标并覆盖为 match 的 end_bb,出 case 时恢复。 rmb_old_break: rawptr[llvmlite.BasicBlock] = trans._break_bb trans._break_bb = end_bb - rmb_old_inmc: int = trans._in_match_case - trans._in_match_case = 1 + rmb_old_inmc: int = trans._in_switch_case + trans._in_switch_case = node.is_switch # 进入 case 作用域(变体字段绑定隔离) self.Gen.VarGen.enter_scope(trans.SymTab, SCOPE_MATCH) @@ -733,7 +723,7 @@ novirtual class MatchGenMixin: # 退出 case 作用域,并恢复 break 目标 / match-case 标记 self.Gen.VarGen.exit_scope(trans.SymTab) trans._break_bb = rmb_old_break - trans._in_match_case = rmb_old_inmc + trans._in_switch_case = rmb_old_inmc # 若未终止:默认跳 end;含 fallthrough(`fallthrough` 标记或兼容的 # c.NoBreak())则落到下一个 case 的 body(跳过其模式检查)。 @@ -774,8 +764,8 @@ novirtual class MatchGenMixin: # default 臂同样按 match-case 语义:break = 跳出 match rmd_old_break: rawptr[llvmlite.BasicBlock] = trans._break_bb trans._break_bb = end_bb - rmd_old_inmc: int = trans._in_match_case - trans._in_match_case = 1 + rmd_old_inmc: int = trans._in_switch_case + trans._in_switch_case = 1 self.Gen.VarGen.enter_scope(trans.SymTab, SCOPE_MATCH) # dbody 预声明+重赋值会使 .get 误分派成 list[int].get # (i32→inttoptr 截断指针 → translate_stmt 读垃圾节点崩溃,gen1 IR 证据)。 @@ -791,7 +781,7 @@ novirtual class MatchGenMixin: dj3 = dj3 + 1 self.Gen.VarGen.exit_scope(trans.SymTab) trans._break_bb = rmd_old_break - trans._in_match_case = rmd_old_inmc + trans._in_switch_case = rmd_old_inmc # 末句控制流全 return → 补 unreachable(不 br end_bb) if llvmlite.builder_cur_block_is_terminated(builder) == 0 \ and self._case_tail_unreachable(trans, builder, dbody3) == 0: @@ -1172,8 +1162,8 @@ novirtual class MatchGenMixin: # case 体内 break = 跳出 match(C switch 语义):暂存/覆盖 _break_bb sqb_old_break: rawptr[llvmlite.BasicBlock] = trans._break_bb trans._break_bb = end_bb - sqb_old_inmc: int = trans._in_match_case - trans._in_match_case = 1 + sqb_old_inmc: int = trans._in_switch_case + trans._in_switch_case = 1 self.Gen.VarGen.enter_scope(trans.SymTab, SCOPE_MATCH) body_list2: list[ast.AST*]* = mc3.children if body_list2 is not None: @@ -1186,7 +1176,7 @@ novirtual class MatchGenMixin: bi = bi + 1 self.Gen.VarGen.exit_scope(trans.SymTab) trans._break_bb = sqb_old_break - trans._in_match_case = sqb_old_inmc + trans._in_switch_case = sqb_old_inmc # 末句控制流全 return → 补 unreachable(不 br end,无 fallthrough) if llvmlite.builder_cur_block_is_terminated(builder) == 0 \ and self._case_tail_unreachable(trans, builder, body_list2) == 0: @@ -1218,8 +1208,8 @@ novirtual class MatchGenMixin: # default 臂同样按 match-case 语义:break = 跳出 match sqd_old_break: rawptr[llvmlite.BasicBlock] = trans._break_bb trans._break_bb = end_bb - sqd_old_inmc: int = trans._in_match_case - trans._in_match_case = 1 + sqd_old_inmc: int = trans._in_switch_case + trans._in_switch_case = 1 self.Gen.VarGen.enter_scope(trans.SymTab, SCOPE_MATCH) # dbody 预声明+重赋值会使 .get 误分派成 list[int].get # (i32→inttoptr 截断指针 → translate_stmt 读垃圾节点崩溃,gen1 IR 证据)。 @@ -1236,7 +1226,7 @@ novirtual class MatchGenMixin: dj3 = dj3 + 1 self.Gen.VarGen.exit_scope(trans.SymTab) trans._break_bb = sqd_old_break - trans._in_match_case = sqd_old_inmc + trans._in_switch_case = sqd_old_inmc # 末句控制流全 return → 补 unreachable(不 br end_bb) if llvmlite.builder_cur_block_is_terminated(builder) == 0 \ and self._case_tail_unreachable(trans, builder, dbody) == 0: @@ -1429,8 +1419,8 @@ novirtual class MatchGenMixin: # case 体内 break = 跳出 match(C switch 语义):暂存/覆盖 _break_bb smb_old_break: rawptr[llvmlite.BasicBlock] = trans._break_bb trans._break_bb = end_bb - smb_old_inmc: int = trans._in_match_case - trans._in_match_case = 1 + smb_old_inmc: int = trans._in_switch_case + trans._in_switch_case = 1 self.Gen.VarGen.enter_scope(trans.SymTab, SCOPE_MATCH) @@ -1446,7 +1436,7 @@ novirtual class MatchGenMixin: self.Gen.VarGen.exit_scope(trans.SymTab) trans._break_bb = smb_old_break - trans._in_match_case = smb_old_inmc + trans._in_switch_case = smb_old_inmc # 若未终止:默认跳 end;含 fallthrough(`fallthrough` 标记或兼容的 # c.NoBreak())则落到下一个 case 的 body(跳过其模式检查)。 @@ -1486,8 +1476,8 @@ novirtual class MatchGenMixin: # default 臂同样按 match-case 语义:break = 跳出 match smd_old_break: rawptr[llvmlite.BasicBlock] = trans._break_bb trans._break_bb = end_bb - smd_old_inmc: int = trans._in_match_case - trans._in_match_case = 1 + smd_old_inmc: int = trans._in_switch_case + trans._in_switch_case = node.is_switch self.Gen.VarGen.enter_scope(trans.SymTab, SCOPE_MATCH) # dbody 预声明+重赋值会使 .get 误分派成 list[int].get # (i32→inttoptr 截断指针 → translate_stmt 读垃圾节点崩溃,gen1 IR 证据)。 @@ -1503,7 +1493,7 @@ novirtual class MatchGenMixin: dj3 = dj3 + 1 self.Gen.VarGen.exit_scope(trans.SymTab) trans._break_bb = smd_old_break - trans._in_match_case = smd_old_inmc + trans._in_switch_case = smd_old_inmc # 末句控制流全 return → 补 unreachable(不 br end_bb) if llvmlite.builder_cur_block_is_terminated(builder) == 0 \ and self._case_tail_unreachable(trans, builder, dbody3) == 0: diff --git a/App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp b/App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp index 5db125e..7984e99 100644 --- a/App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp +++ b/App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp @@ -266,11 +266,11 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): if builder is None or func is None: return 0 - # 发射 br 到 break 目标(_break_bb 由循环或 match-case 生成侧设置) + # 发射 br 到 break 目标(_break_bb 由循环 / switch / match 的 case 生成侧设置) if trans._break_bb is None: - # fail-fast:没有循环 / match-case 时 break 无处可跳,禁止静默无效果 + # fail-fast:没有循环 / switch / match 时 break 无处可跳,禁止静默无效果 self.Gen.TypeGenErr.fatal_error(node, - "break 只能用在循环或 match-case 体内(当前没有可跳出的目标)", "SyntaxError") + "break 只能用在循环或 switch/match 的 case 体内(当前没有可跳出的目标)", "SyntaxError") if llvmlite.builder_cur_block_is_terminated(builder) == 0: llvmlite.build_br(builder, trans._break_bb) @@ -284,17 +284,19 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): return 0 def translate_fallthrough(self, trans: HT.Translator*, node: ast.AST*) -> int: - """翻译 `fallthrough` 标记语句:本身不产出任何 IR + """翻译 `fallthrough` 语句:本身不产出任何 IR - 语义由 match 生成侧消费——case 体含该标记时末尾不自动 break,直接落到 - 下一个 case 体(对齐 C 的 [[fallthrough]])。合法位置只有 match-case - 语句体;出现在别处只会静默无效果,故 fail-fast 暴露。 + 语义由 switch 生成侧消费——case 体含该标记时末尾不自动跳出 switch,直接 + 落到下一个 case 体(对齐 C 的 [[fallthrough]])。合法位置**只有 switch 的 + case 语句体**;写进 match 的 case 体(match 完全禁止 fallthrough)或 + switch 之外一律 fail-fast,绝不静默无效果。 """ if trans is None: return 0 - if trans._in_match_case == 0: + if trans._in_switch_case == 0: self.Gen.TypeGenErr.fatal_error(node, - "fallthrough 只能用在 match-case 语句体内(语义是落到下一个 case)", "SyntaxError") + "fallthrough 只能用在 switch 的 case 体内(match 完全禁止 fallthrough," + "语义是落到下一个 case)", "SyntaxError") return 0 def translate_continue(self, trans: HT.Translator*, node: ast.AST*) -> int: diff --git a/App/lib/core/Gen/Translator.vp b/App/lib/core/Gen/Translator.vp index be24d68..586fb48 100644 --- a/App/lib/core/Gen/Translator.vp +++ b/App/lib/core/Gen/Translator.vp @@ -176,9 +176,11 @@ novirtual class Translator: _break_bb: rawptr[llvmlite.BasicBlock] _continue_bb: rawptr[llvmlite.BasicBlock] - # 是否正处于 match-case 语句体内(1=是)。供 `fallthrough` 语句判定合法性 - # (只在 case 体内合法,别处 fail-fast),由 MatchGenMixin 进出 case 时置位。 - _in_match_case: int + # 当前是否处于 **switch** 的 case 语句体内(1=是)。供 `fallthrough` 语句判定 + # 合法性:只在 switch 的 case 体内合法;写进 match 的 case 体或 switch 之外 + # 一律 fail-fast(match 完全禁止 fallthrough)。由 MatchGenMixin 进出 case 时 + # 置为 `node.is_switch`(真 match=0,switch=1),出 case 恢复。 + _in_switch_case: int # 独立标签计数器(不与 builder.Counter 共享,避免 SSA 编号非单调) _label_counter: int @@ -297,7 +299,7 @@ novirtual class Translator: self._cur_builder = None self._break_bb = None self._continue_bb = None - self._in_match_case = 0 + self._in_switch_case = 0 self._label_counter = 0 self._imported_modules = None self._from_imports = None