From a6e1957768c87464eed7a571daa0e82788d325fc Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 8 Oct 2026 12:35:59 +0800 Subject: [PATCH] =?UTF-8?q?feat(gen):=20=E6=8E=A7=E5=88=B6=E6=B5=81?= =?UTF-8?q?=E6=B1=87=E5=90=88=20Meet=EF=BC=88M2.2=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - VarGenMixin:life_capture/life_restore/life_join(作用域链快照,池上 [count,(entry,life)…] 数组)。 - StmtGenCifMixin.translate_if:进分支前快照、then 末快照、else 前复位、出口按 min 合并。 - StmtGenMixin:while/for 统一在语句分派处 capture→run→join(一处覆盖全部迭代形态与解糖,含 0 次迭代路径)。 --- App/lib/core/Gen/Stmt/StmtGenCifMixin.vp | 12 ++++++ App/lib/core/Gen/Stmt/StmtGenMixin.vp | 14 +++++- App/lib/core/Gen/VarGenMixin.vp | 55 ++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp b/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp index b68c0ff..d2a734d 100644 --- a/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp +++ b/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp @@ -708,6 +708,9 @@ novirtual class StmtGenCifMixin: if has_else == 1: mlirlite.build_cond_br(builder, cond_i1, then_bb, else_bb) else: mlirlite.build_cond_br(builder, cond_i1, then_bb, merge_bb) + # 生命期汇合:进入分支前快照(else 分支需从该状态重新开始,见 §11 控制流 Meet) + life_snap0: sizet* = self.Gen.VarGen.life_capture(trans) + # 5. translate the then body; reset the merge-reachable flag first (nested control flow # overwrites it, so the branch-tail check must not see a stale value from before this If). trans._ctrl_merge_reachable = 1 @@ -730,9 +733,14 @@ novirtual class StmtGenCifMixin: mlirlite.build_br(builder, merge_bb) then_branches_merge = 1 + # then 末状态快照(供两端 Meet:先复位到 if 前状态,再与 then 末状态合并) + life_snap1: sizet* = self.Gen.VarGen.life_capture(trans) + # 6. translate the else body (if any) else_branches_merge: int = 0 if has_else == 1: + # 复位到 if 前状态,让 else 分支从同一基线出发(否则会看到 then 分支写入的 Life) + self.Gen.VarGen.life_restore(life_snap0) # as in then: reset the flag to avoid stale values from the then branch trans._ctrl_merge_reachable = 1 mlirlite.position_at_end(builder, else_bb) @@ -748,6 +756,10 @@ novirtual class StmtGenCifMixin: mlirlite.build_br(builder, merge_bb) else_branches_merge = 1 + # 生命期汇合:有 else → 与 then 末状态 Meet;无 else → 与 if 前状态 Meet(else 路径=跳过) + if has_else == 1: self.Gen.VarGen.life_join(life_snap1) + else: self.Gen.VarGen.life_join(life_snap0) + # 7. merge reachability (used by tail-flow checks): without else cond_br always reaches # merge; with else, any branch br reaching merge suffices; only all-return is unreachable. trans._ctrl_merge_reachable = 1 diff --git a/App/lib/core/Gen/Stmt/StmtGenMixin.vp b/App/lib/core/Gen/Stmt/StmtGenMixin.vp index e1324a4..bdaef0e 100644 --- a/App/lib/core/Gen/Stmt/StmtGenMixin.vp +++ b/App/lib/core/Gen/Stmt/StmtGenMixin.vp @@ -51,9 +51,19 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): return self.Gen.FuncGen.translate_nested_function_def(trans, node) elif k == ast.ASTKind.Return: return self.Gen.StmtGenCif.translate_return(trans, node) elif k == ast.ASTKind.If: return self.Gen.StmtGenCif.translate_if(trans, node) - elif k == ast.ASTKind.While: return self.Gen.StmtGenCif.translate_while(trans, node) + elif k == ast.ASTKind.While: + # 循环生命期汇合:循环可能 0 次执行,出口状态须与进入前状态 Meet(见 §11 控制流 Meet) + snap_wh: sizet* = self.Gen.VarGen.life_capture(trans) + rc_wh: int = self.Gen.StmtGenCif.translate_while(trans, node) + self.Gen.VarGen.life_join(snap_wh) + return rc_wh elif k == ast.ASTKind.AugAssign: return self.Gen.AssignGen.translate_augassign(trans, node) - elif k == ast.ASTKind.For: return self.Gen.StmtGenCif.translate_for(trans, node) + elif k == ast.ASTKind.For: + # 同上:for 的各迭代形态(range/指针/数组/容器/解糖)统一在此收口 + snap_fr: sizet* = self.Gen.VarGen.life_capture(trans) + rc_fr: int = self.Gen.StmtGenCif.translate_for(trans, node) + self.Gen.VarGen.life_join(snap_fr) + return rc_fr elif k == ast.ASTKind.ClassDef: return self.Gen.ClassGenDef.translate_class_def(trans, node) elif k == ast.ASTKind.Import: return self.Gen.ImportsGen.translate_import(trans, node) elif k == ast.ASTKind.ImportFrom: diff --git a/App/lib/core/Gen/VarGenMixin.vp b/App/lib/core/Gen/VarGenMixin.vp index d7963b7..590a8e8 100644 --- a/App/lib/core/Gen/VarGenMixin.vp +++ b/App/lib/core/Gen/VarGenMixin.vp @@ -204,6 +204,61 @@ novirtual class VarGenMixin: """Meet of two life tags (min); used where branches join""" return a if a < b else b + # life_capture - 快照当前作用域链上所有变量的 LifeTag(供控制流汇合 Meet)。 + # 返回池上数组:buf[0]=count,其后每项 (entry_ptr, life) 各占一个 sizet 槽;失败返回 None。 + def life_capture(self, trans: HT.Translator*) -> sizet*: + """Snapshot every in-scope variable's LifeTag (control-flow merge support)""" + if trans is None or trans.SymTab is None: return None + pool: memhub.MemBuddy* = trans.Pool + if pool is None: return None + cnt: sizet = 0 + sc_c: GenTypes.Scope* = trans.SymTab.Current + while sc_c is not None: + cnt += sizet(sc_c.VarCount) + sc_c = sc_c.Parent + buf: sizet* = sizet*(pool.alloc(8 * (2 * cnt + 2))) + if buf is None: return None + buf[0] = cnt + idx: sizet = 1 + esz: uint64 = uint64(GenTypes.VarEntry.__sizeof__()) + sc: GenTypes.Scope* = trans.SymTab.Current + while sc is not None: + if sc.Vars is not None and sc.VarCount > 0: + j: int = 0 + while j < sc.VarCount: + ent: GenTypes.VarEntry* = GenTypes.VarEntry*(uint64(sc.Vars) + uint64(j) * esz) + buf[idx * 2] = sizet(uint64(ent)) + buf[idx * 2 + 1] = sizet(ent.Life) + idx += 1 + j += 1 + sc = sc.Parent + return buf + + # life_restore - 把快照写回各变量(让 else 分支从 if 之前的状态开始)。 + def life_restore(self, buf: sizet*) -> int: + """Restore LifeTag values from a snapshot; 0=ok / 1=no snapshot""" + if buf is None: return 1 + cnt: sizet = buf[0] + i: sizet = 1 + while i <= cnt: + ent: GenTypes.VarEntry* = GenTypes.VarEntry*(uint64(buf[i * 2])) + if ent is not None: ent.Life = int(buf[i * 2 + 1]) + i += 1 + return 0 + + # life_join - 当前值与快照逐项 Meet(汇合:任一路径为短命即取短命)。 + def life_join(self, buf: sizet*) -> int: + """Meet the current LifeTags with a snapshot; 0=ok / 1=no snapshot""" + if buf is None: return 1 + cnt: sizet = buf[0] + i: sizet = 1 + while i <= cnt: + ent: GenTypes.VarEntry* = GenTypes.VarEntry*(uint64(buf[i * 2])) + if ent is not None: + ent.Life = self.life_meet(ent.Life, int(buf[i * 2 + 1])) + i += 1 + return 0 + # add_var - add a variable to the variable table # ============================================================ def add_var(self, vars_ptr: GenTypes.VarEntry*, var_count: int, name: str, alloca: mlirlite.Value*) -> int: