refactor(tpv): _deps_pending 置位收敛到唯一入口 _MarkDepsPending(S4 第一步)

- CallGenBase 新增 _MarkDepsPending(trans,kind,cls,method,dep,extra):一处实现「置标志 + 统一格式 [DEPDBG] + 持久化 _phaseA_pending.log」三连

- 14 处置位点(D7-1 清单:attr_read/attr_write/method_ret/mro_ret/mro_anc/special_ret/prop_ret/dispatch_ret/dispatch_sp/func_ret/func_mangled/global_stub/class_parent/class_field_ty)全部改经该入口

- 行为不变;DEPDBG 行格式统一为 pending(<kind>): mod=.. cls=.. method=.. dep=.. extra=..,供下一步按 kind 统计命中数、删除死点
This commit is contained in:
TermiNexus committed 2026-09-12 13:53:20 +08:00
1 parent 7e68e76ec4
commit 967095df5b
8 files changed
+81 -161

No files matched your search

+29
View File
@@ -1,6 +1,7 @@
import lib.core.Gen.GenTypes as GenTypes
import lib.core.Gen.Generator as Generator
import lib.core.Gen.GenApi as GenApi
import lib.core.Gen.Translator as HT
import t, c
from stdint import *
import ast
@@ -1273,6 +1274,34 @@ class CallGenBase:
stdlib.free(line)
pf.close()
# ============================================================
# _MarkDepsPending - `_deps_pending` 置位的**唯一入口**(S4 触发面收敛)
#
# `_Type.md` D7-1 清点的 14 处置位点,此前各自重复「置标志 + [DEPDBG] +
# 持久化 _phaseA_pending.log」三连,触发面散落、无法统一量化/收紧。
# 现全部改经此一处实现;`kind` 即触发面标签:
# attr_read / attr_write / method_ret / mro_ret / mro_anc / special_ret /
# prop_ret / dispatch_ret / dispatch_sp / func_ret / func_mangled /
# global_stub / class_parent / class_field_ty
# ============================================================
def _MarkDepsPending(self, trans: HT.Translator | t.CPtr, kind: str,
cls_name: str, method_name: str,
dep_sha1: str, extra: str) -> None:
"""标记 Phase A 依赖未就绪(下遍重译):置标志 + 滚动 DEPDBG + 持久化明细"""
if trans is None:
return
trans._deps_pending = 1
m_sha: str = trans.ModuleSha1
# [DEPDBG] 临时诊断(用后移除):统一格式,按 kind 过滤统计触发面命中数
stdio.printf("[DEPDBG] pending(%s): mod=%s cls=%s method=%s dep=%s extra=%s\n",
kind, m_sha if m_sha is not None else "?",
cls_name if cls_name is not None else "-",
method_name if method_name is not None else "-",
dep_sha1 if dep_sha1 is not None else "-",
extra if extra is not None else "-")
if m_sha is not None:
self._AppendPhaseAPending(m_sha, kind, cls_name, method_name, dep_sha1, extra)
# ============================================================
# 属性方法(@property/@x.setter/@x.deleter)与静态/类方法调用辅助
#
+13 -47
View File
@@ -389,18 +389,9 @@ class CallGenCall(CallGenBase.CallGenBase):
if cls_sha1 is None \
or (cls_sha1 is not None
and self._dep_text_ll_exists(pool, cls_sha1) == 0):
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:方法返回类型解析依赖未就绪即 pending 的根因(用后移除)
dbg_ms1: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?"
stdio.printf("[DEPDBG] pending(method_ret): mod=%s cls=%s method=%s sha1=%s\n",
dbg_ms1, class_name, method_name,
cls_sha1 if cls_sha1 is not None else "none")
# 持久化(用后移除):供 Phase2 收敛失败最终诊断按调用方过滤
if trans is not None and trans.ModuleSha1 is not None:
self._AppendPhaseAPending(
trans.ModuleSha1, "method_ret", class_name,
method_name, cls_sha1, "-")
# 触发面唯一入口(S4 收敛):置 _deps_pending + 诊断 + 持久化
self._MarkDepsPending(
trans, "method_ret", class_name, method_name, cls_sha1, "-")
# 依赖未就绪:保持默认 i32(build_call(Void) 返回 None 会
# 破坏表达式翻译;pending 文件本遍不写盘,下遍重译)
call_ret_ty = llvmlite.Int32(pool)
@@ -1108,23 +1099,15 @@ class CallGenCall(CallGenBase.CallGenBase):
if ret_anc_sha1 is None \
or (ret_anc_sha1 is not None
and self._dep_text_ll_exists(pool, ret_anc_sha1) == 0):
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:方法祖先模块依赖未就绪即 pending 的根因(用后移除)
dbg_ms2: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?"
stdio.printf("[DEPDBG] pending(mro_ret): mod=%s cls=%s method=%s ret_sha1=%s text=%d\n",
dbg_ms2, class_name, method_name,
ret_anc_sha1 if ret_anc_sha1 is not None else "none",
self._dep_text_ll_exists(pool, ret_anc_sha1) if ret_anc_sha1 is not None else -1)
# 持久化到 _phaseA_pending.log,供 Phase2 收敛失败最终诊断按调用方过滤
txt_s: str = "text=-1"
if ret_anc_sha1 is not None:
txt_s = "text=0"
if self._dep_text_ll_exists(pool, ret_anc_sha1) != 0:
txt_s = "text=1"
self._AppendPhaseAPending(
dbg_ms2, "mro_ret", class_name, method_name,
ret_anc_sha1, txt_s)
# 触发面唯一入口(S4 收敛):置 _deps_pending + 诊断 + 持久化
self._MarkDepsPending(
trans, "mro_ret", class_name, method_name, ret_anc_sha1, txt_s)
# 依赖未就绪:保持默认 i32 继续而非 Void——build_call(Void)
# 返回 None,方法调用结果喂进表达式(if 条件/比较)时 fatal
# "if 条件表达式翻译失败"(ExprGenAttr._get_cderef_attr_base
@@ -1154,17 +1137,9 @@ class CallGenCall(CallGenBase.CallGenBase):
break
mi_p2 += 1
if anc_missing_p2 != 0:
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:MRO 祖先模块依赖未就绪即 pending 的根因(用后移除)
dbg_ms3: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?"
stdio.printf("[DEPDBG] pending(mro_anc): mod=%s cls=%s method=%s anc=%s anc_sha1=%s\n",
dbg_ms3, class_name, method_name,
anc_p2 if anc_p2 is not None else "none",
anc_sha1_p2 if anc_sha1_p2 is not None else "none")
# 持久化到 _phaseA_pending.log,供 Phase2 收敛失败最终诊断按调用方过滤
self._AppendPhaseAPending(
dbg_ms3, "mro_anc", class_name, method_name,
# 触发面唯一入口(S4 收敛):置 _deps_pending + 诊断 + 持久化
self._MarkDepsPending(
trans, "mro_anc", class_name, method_name,
anc_sha1_p2, anc_p2 if anc_p2 is not None else "none")
# 依赖未就绪:保持默认 i32(同上,build_call(Void) 返回
# None 会破坏表达式翻译,pending 文件本遍不写盘)
@@ -2110,19 +2085,10 @@ class CallGenCall(CallGenBase.CallGenBase):
# 绝不 fail-fast 中断多遍收敛;真实错误由收敛检查兜底。
if anc_sha1_sp is None \
or self._dep_text_ll_exists(pool, anc_sha1_sp) == 0:
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:特殊方法依赖未就绪即 pending 的根因(用后移除)
dbg_ms4: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?"
stdio.printf("[DEPDBG] pending(special_ret): mod=%s cls=%s method=%s sha1=%s\n",
dbg_ms4, anc if anc is not None else "?",
method_name,
anc_sha1_sp if anc_sha1_sp is not None else "none")
# 持久化(用后移除):供 Phase2 收敛失败最终诊断按调用方过滤
if trans is not None and trans.ModuleSha1 is not None:
self._AppendPhaseAPending(
trans.ModuleSha1, "special_ret", anc if anc is not None else "-",
method_name, anc_sha1_sp, "-")
# 触发面唯一入口(S4 收敛):置 _deps_pending + 诊断 + 持久化
self._MarkDepsPending(
trans, "special_ret", anc if anc is not None else "-",
method_name, anc_sha1_sp, "-")
# 依赖未就绪:保持默认 i32(build_call(Void) 返回 None
# 会破坏表达式翻译;pending 文件本遍不写盘,下遍重译)
ret_ty_sp = llvmlite.Int32(pool)
+8 -23
View File
@@ -1423,18 +1423,10 @@ class CallGenDispatch(CallGenBase.CallGenBase):
# MRO 链找到 AssignGenMixin → 精确解析。真正不存在的
# 类/方法由 Phase A 收敛检查兜底,绝不在此 fail-fast
# 中断多遍收敛(对齐追加77/77b 类 defer 原则)。
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:方法返回类型解析依赖未就绪即 pending 的根因(用后移除)
dbg_ms6: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?"
stdio.printf("[DEPDBG] pending(dispatch_ret): mod=%s cls=%s method=%s sha1=%s\n",
dbg_ms6, cls_nm2, func_name,
sha1_fc if sha1_fc is not None else "none")
# 持久化(用后移除):供 Phase2 收敛失败最终诊断按调用方过滤
if trans is not None and trans.ModuleSha1 is not None:
self.Gen.CallGenBase._AppendPhaseAPending(
trans.ModuleSha1, "dispatch_ret", cls_nm2,
func_name, sha1_fc, "-")
# 触发面唯一入口(S4 收敛):置 _deps_pending + 诊断 + 持久化
self.Gen.CallGenBase._MarkDepsPending(
trans, "dispatch_ret", cls_nm2,
func_name, sha1_fc, "-")
# 依赖未就绪:保持默认 i32(build_call(Void)
# 返回 None 破坏表达式翻译;本遍不写盘)
ret_ty3 = llvmlite.Int32(pool)
@@ -1460,17 +1452,10 @@ class CallGenDispatch(CallGenBase.CallGenBase):
obj_ptr4: llvmlite.Value | t.CPtr = llvmlite.build_load(
builder, i8_ptr_ty4, obj_var)
if obj_ptr4 is not None:
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:特殊方法依赖未就绪即 pending 的根因(用后移除)
dbg_ms7: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?"
stdio.printf("[DEPDBG] pending(dispatch_sp): mod=%s cls=%s method=%s\n",
dbg_ms7, cls_nm2, func_name)
# 持久化(用后移除):供 Phase2 收敛失败最终诊断按调用方过滤
if trans is not None and trans.ModuleSha1 is not None:
self.Gen.CallGenBase._AppendPhaseAPending(
trans.ModuleSha1, "dispatch_sp", cls_nm2,
func_name, "-", "-")
# 触发面唯一入口(S4 收敛):置 _deps_pending + 诊断 + 持久化
self.Gen.CallGenBase._MarkDepsPending(
trans, "dispatch_sp", cls_nm2,
func_name, "-", "-")
if hit_box is not None:
hit_box[0] = 1
return self.Gen.CallGenCall._translate_method_call(
+6 -21
View File
@@ -891,17 +891,9 @@ class CallGenMixin(CallGenBase.CallGenBase):
else:
if trans is not None and trans._declare_only == 0:
if self._dep_text_ll_exists(pool, mod_ret_sha1) == 0:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:跨模块函数返回类型依赖未就绪即 pending(用后移除)
dbg_fr: str = trans.ModuleSha1 if trans.ModuleSha1 is not None else "?"
stdio.printf("[DEPDBG] pending(func_ret): mod=%s func=%s mod_sha1=%s\n",
dbg_fr, func_name,
mod_ret_sha1 if mod_ret_sha1 is not None else "none")
# 持久化(用后移除):供 Phase2 收敛失败最终诊断按调用方过滤
if trans.ModuleSha1 is not None:
self._AppendPhaseAPending(
trans.ModuleSha1, "func_ret", "-", func_name,
mod_ret_sha1, "-")
# 触发面唯一入口(S4 收敛):置 _deps_pending + 诊断 + 持久化
self._MarkDepsPending(
trans, "func_ret", "-", func_name, mod_ret_sha1, "-")
# 已标记 _deps_pending,下遍重译会收敛(依赖 text.ll 就绪后
# 走精确解析)→ fatal_if_unknown=0,本遍仅临时占位。
call_ret_ty = self.Gen.CallGenLib._infer_external_func_ret_ty(pool, func_name, node, 0)
@@ -1591,16 +1583,9 @@ class CallGenMixin(CallGenBase.CallGenBase):
"TypeError")
else:
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:跨模块 mangled 函数依赖未就绪即 pending(用后移除)
dbg_mg: str = trans.ModuleSha1 if trans.ModuleSha1 is not None else "?"
stdio.printf("[DEPDBG] pending(func_mangled): mod=%s func=%s cf_sha1=%s\n",
dbg_mg, call_name, cf_sha1)
# 持久化(用后移除):供 Phase2 收敛失败最终诊断按调用方过滤
if trans.ModuleSha1 is not None:
self._AppendPhaseAPending(
trans.ModuleSha1, "func_mangled", "-", call_name,
cf_sha1, "-")
# 触发面唯一入口(S4 收敛):置 _deps_pending + 诊断 + 持久化
self._MarkDepsPending(
trans, "func_mangled", "-", call_name, cf_sha1, "-")
if VLogger._nowarn_register == 0:
VLogger.warning(f"跨模块函数 '{call_name}' 依赖模块 text.ll 尚未生成(Phase A 顺序),"
"标记重试,本遍保持默认类型", "HandlesExprCall")
+3 -12
View File
@@ -114,18 +114,9 @@ class CallGenProp(CallGenBase.CallGenBase):
# 绝不 fail-fast 中断多遍收敛;真实错误由收敛检查兜底。
if cls_sha1_rt is None \
or self._dep_text_ll_exists(pool, cls_sha1_rt) == 0:
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:属性方法依赖未就绪即 pending 的根因(用后移除)
dbg_ms8: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?"
stdio.printf("[DEPDBG] pending(prop_ret): mod=%s cls=%s method=%s sha1=%s\n",
dbg_ms8, class_name, method_name,
cls_sha1_rt if cls_sha1_rt is not None else "none")
# 持久化(用后移除):供 Phase2 收敛失败最终诊断按调用方过滤
if trans is not None and trans.ModuleSha1 is not None:
self.Gen.CallGenBase._AppendPhaseAPending(
trans.ModuleSha1, "prop_ret", class_name,
method_name, cls_sha1_rt, "-")
# 触发面唯一入口(S4 收敛):置 _deps_pending + 诊断 + 持久化
self.Gen.CallGenBase._MarkDepsPending(
trans, "prop_ret", class_name, method_name, cls_sha1_rt, "-")
# 依赖未就绪:保持默认 i32(build_call(Void) 返回 None
# 会破坏表达式翻译;pending 文件本遍不写盘,下遍重译)
call_ret_ty = llvmlite.Int32(pool)
+8 -22
View File
@@ -239,17 +239,10 @@ class ClassGenDef(ClassGenBase.ClassGenBase):
# 整类 defer(不注册)+ 标记 _deps_pending 下遍重译;模块级
# 变量/函数参数解析失败静默降级 i32(handle_module_level_var
# L422-426 / FuncGenMixin L482-483),不致命,本遍文件不写盘。
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:父类未注册即 pending(用后移除)
dbg_p: str = trans.ModuleSha1 if trans.ModuleSha1 is not None else "?"
stdio.printf("[DEPDBG] pending(class_parent): mod=%s cls=%s parent=%s\n",
dbg_p, class_name, pname if pname is not None else "none")
# 持久化(用后移除):供 Phase2 收敛失败最终诊断按调用方过滤
if trans.ModuleSha1 is not None:
self.Gen.CallGenBase._AppendPhaseAPending(
trans.ModuleSha1, "class_parent", class_name,
"-", "-", pname if pname is not None else "-")
# 触发面唯一入口(S4 收敛):置 _deps_pending + 诊断 + 持久化
self.Gen.CallGenBase._MarkDepsPending(
trans, "class_parent", class_name,
"-", "-", pname if pname is not None else "-")
return 0
pfc: int = parent_entry.FieldCount
for pfi in range(pfc):
@@ -404,17 +397,10 @@ class ClassGenDef(ClassGenBase.ClassGenBase):
# _deps_pending 下遍重译,不在本遍以残缺字段注册结构体。
# 真正的类型错误由 Phase A 收敛检查暴露("Phase A 无法完成
# 翻译: <file>,请检查依赖模块是否已编译/注册"),不静默掩盖。
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:字段注解类型未注册即 pending(用后移除)
dbg_f: str = trans.ModuleSha1 if trans.ModuleSha1 is not None else "?"
stdio.printf("[DEPDBG] pending(class_field_ty): mod=%s cls=%s field=%s\n",
dbg_f, class_name, tgt.id if tgt.id is not None else "none")
# 持久化(用后移除):供 Phase2 收敛失败最终诊断按调用方过滤
if trans.ModuleSha1 is not None:
self.Gen.CallGenBase._AppendPhaseAPending(
trans.ModuleSha1, "class_field_ty", class_name,
tgt.id if tgt.id is not None else "-", "-", "-")
# 触发面唯一入口(S4 收敛):置 _deps_pending + 诊断 + 持久化
self.Gen.CallGenBase._MarkDepsPending(
trans, "class_field_ty", class_name,
tgt.id if tgt.id is not None else "-", "-", "-")
return 0
# 旧行为:fast-fail NameError(已移除——Phase A 依赖未就绪时
# 误报真实错误,中断多遍收敛;真实错误交给收敛检查兜底)
+8 -22
View File
@@ -973,17 +973,10 @@ class ExprGenAttr(ExprGenBase.ExprGenBase):
# stub 空类 FieldCount=0,如 LARGE_INTEGER)→ 标记 pending 下遍
# 重译(对齐写路径 get_attribute_ptr;lookup_field_by_class 已对
# 空 stub 返回 None 而非 fatal)。真实错误由 Phase A 收敛检查暴露。
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:读属性字段缺失即 pending(用后移除)
dbg_ar: str = trans.ModuleSha1 if trans.ModuleSha1 is not None else "?"
stdio.printf("[DEPDBG] pending(attr_read): mod=%s field=%s\n",
dbg_ar, at.attr if at.attr is not None else "none")
# 持久化(用后移除):供 Phase2 收敛失败最终诊断按调用方过滤
if trans.ModuleSha1 is not None:
self.Gen.CallGenBase._AppendPhaseAPending(
trans.ModuleSha1, "attr_read", "-",
at.attr if at.attr is not None else "-", "-", "-")
# 触发面唯一入口(S4 收敛):置 _deps_pending + 诊断 + 持久化
self.Gen.CallGenBase._MarkDepsPending(
trans, "attr_read", "-",
at.attr if at.attr is not None else "-", "-", "-")
# Phase A 依赖未就绪(_deps_pending,父类/依赖类未注册致字段缺失):
# 跳过本属性访问交给下遍重译(对齐 get_attribute_ptr L5541-5547),
# 避免 fail-fast 中断多遍收敛;依赖就绪后仍缺失则走下方真实报错。
@@ -1265,17 +1258,10 @@ class ExprGenAttr(ExprGenBase.ExprGenBase):
# 下遍重译(对齐 translate_attribute 读路径;lookup_field_by_class
# 已对空 stub 返回 None 而非 fatal)。真实错误由 Phase A 收敛检查
# 暴露("Phase A 无法完成翻译"),不在此 fail-fast 中断多遍收敛。
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:写属性字段缺失即 pending(用后移除)
dbg_aw: str = trans.ModuleSha1 if trans.ModuleSha1 is not None else "?"
stdio.printf("[DEPDBG] pending(attr_write): mod=%s field=%s\n",
dbg_aw, at.attr if at.attr is not None else "none")
# 持久化(用后移除):供 Phase2 收敛失败最终诊断按调用方过滤
if trans.ModuleSha1 is not None:
self.Gen.CallGenBase._AppendPhaseAPending(
trans.ModuleSha1, "attr_write", "-",
at.attr if at.attr is not None else "-", "-", "-")
# 触发面唯一入口(S4 收敛):置 _deps_pending + 诊断 + 持久化
self.Gen.CallGenBase._MarkDepsPending(
trans, "attr_write", "-",
at.attr if at.attr is not None else "-", "-", "-")
# Phase A 依赖未就绪(_deps_pending,父类/依赖类未注册致字段缺失,
# 如 Generator.vp 先于 TypeGenMixin.vp 编译时 self.TraceFrames):
# 跳过本属性写入交给下遍重译(对齐 HandlesAssign L69-78),
+6 -14
View File
@@ -341,20 +341,12 @@ class ExprGenName(ExprGenBase.ExprGenBase):
# 重试(对齐 CallGenMixin 跨模块依赖未就绪处理)。真实错误由
# Phase A 收敛检查暴露,不在此 fail-fast——否则清缓存后
# lexer 先于 tokens 翻译必然误报 "stub 未注入"。
if trans is not None:
trans._deps_pending = 1
# [DEPDBG] 临时诊断:全局 stub 未注入即 pending 的根因(用后移除)
dbg_ms9: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?"
stdio.printf("[DEPDBG] pending(global_stub): mod=%s name=%s mod_src=%s sha1=%s\n",
dbg_ms9, nm_id, fi_mod_cut2,
StubMergerStore.LookupSha1ByModName(fi_mod_cut2) if fi_mod_cut2 is not None else "none")
# 持久化(用后移除):供 Phase2 收敛失败最终诊断按调用方过滤
if trans is not None and trans.ModuleSha1 is not None:
self.Gen.CallGenBase._AppendPhaseAPending(
trans.ModuleSha1, "global_stub", "-", nm_id,
StubMergerStore.LookupSha1ByModName(fi_mod_cut2)
if fi_mod_cut2 is not None else None,
fi_mod_cut2)
# 触发面唯一入口(S4 收敛):置 _deps_pending + 诊断 + 持久化
self.Gen.CallGenBase._MarkDepsPending(
trans, "global_stub", "-", nm_id,
StubMergerStore.LookupSha1ByModName(fi_mod_cut2)
if fi_mod_cut2 is not None else None,
fi_mod_cut2)
return None
if ref_fi is not None and ref_fi.Ty is not None:
lty_fi: llvmlite.LLVMType | t.CPtr = ref_fi.Ty.Pointee