diff --git a/App/lib/Phase/Phase2/__init__.vp b/App/lib/Phase/Phase2/__init__.vp index 8529b54..1b0a4e1 100644 --- a/App/lib/Phase/Phase2/__init__.vp +++ b/App/lib/Phase/Phase2/__init__.vp @@ -740,6 +740,9 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, im_dp_sha1: str = StubMergerStore.LookupSha1ByModName(im_dp_buf) if im_dp_sha1 is None: im_dp_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(im_dp_buf) + if im_dp_sha1 is None: + # 改名别名(import X as Y):从 _from_imports 查 Y→X 再查 SHA1 + im_dp_sha1 = StubMergerStore.LookupSha1ByAlias(tr_a._from_imports, im_dp_buf) im_dp_resolved: int = 0 im_dp_missing: int = 0 if im_dp_sha1 is not None: diff --git a/App/lib/Stub/StubMerger/StubMergerBuild.vp b/App/lib/Stub/StubMerger/StubMergerBuild.vp index d3df509..6e34a0f 100644 --- a/App/lib/Stub/StubMerger/StubMergerBuild.vp +++ b/App/lib/Stub/StubMerger/StubMergerBuild.vp @@ -1204,6 +1204,12 @@ def LoadDepVpiIntoModule(pool: memhub.MemBuddy | t.CPtr, # 用 LookupSha1ByModName 查找模块的 SHA1 sha1_val: str = StubMergerStore.LookupSha1ByModName(mod_nm_buf) + # 改名别名(import X as Y,如 HT→lib.core.Handles.HandlesTranslator): + # 精确/包名回退均失败时从 from_imports 查别名映射再查 SHA1, + # 否则该类模块的 vpi/stub 不注入 → 跨模块符号解析失败 + if sha1_val is None and from_imports is not None: + sha1_val = StubMergerStore.LookupSha1ByAlias(from_imports, mod_nm_buf) + # 如果精确查找失败,尝试包名回退(如 "ast" → "ast.__init__") # LookupSha1ByModName 内部已处理包名回退,此处无需重复 diff --git a/App/lib/Stub/StubMerger/StubMergerStore.vp b/App/lib/Stub/StubMerger/StubMergerStore.vp index 4e6a8f0..9f69656 100644 --- a/App/lib/Stub/StubMerger/StubMergerStore.vp +++ b/App/lib/Stub/StubMerger/StubMergerStore.vp @@ -18,19 +18,15 @@ import lib.Stub.StubGen.VpiReader as VpiReader import lib.Projectrans.Utils as Utils import lib.Projectrans.Config as Config - import lib.Stub.StubMerger.StubMergerCollect as StubMergerCollect import lib.Stub.StubMerger.StubMergerTopo as StubMergerTopo import lib.Stub.StubMerger.StubMergerIR as StubMergerIR import lib.Stub.StubMerger.StubMergerBuild as StubMergerBuild import lib.Stub.StubMerger as StubMerger + # ============================================================ # StubMergerStore - StubMerger 拆分(阶段 E):StubMergerStore -# -# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留 -# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经 -# StubMerger._xxx 访问(main.vp 先例)。 # ============================================================ # ============================================================ @@ -273,6 +269,64 @@ def LookupSha1ByModNameSuffix(mod_suffix: str) -> str: return StubMerger._sha1_store_arr + sidx_rev_sf return None # ============================================================ +# LookupSha1ByAlias - 从 from_imports 别名映射解析模块 SHA1 +# +# from_imports 条目格式: "local:module" 或 "local:module:orig"(空格分隔), +# 由 ImportsGenMixin.add_from_import 写入(import X as Y → "Y:X")。 +# 命中 local==alias 时,对 module 执行 LookupSha1ByModName 返回 SHA1。 +# +# Returns: +# SHA1 字符串指针(指向全局存储器内部),None 未找到 +# ============================================================ +def LookupSha1ByAlias(from_imports: str, alias: str) -> str: + """从 from_imports 别名映射解析模块 SHA1(改名别名 import X as Y 场景)""" + if from_imports is None or alias is None: + return None + alias_len: t.CSizeT = string.strlen(alias) + if alias_len == 0: + return None + total_len: t.CSizeT = string.strlen(from_imports) + ci: t.CSizeT = 0 + while ci < total_len: + # 跳过前导空格 + while ci < total_len and from_imports[ci] == ' ': + ci += 1 + if ci >= total_len: + break + # 条目起点 ci,找 ':'(local_name 结束) + colon: t.CSizeT = ci + while colon < total_len and from_imports[colon] != ':' and from_imports[colon] != ' ': + colon += 1 + local_len: t.CSizeT = colon - ci + if colon < total_len and from_imports[colon] == ':' and local_len == alias_len: + # 比较 local_name == alias + match: int = 1 + li: t.CSizeT = 0 + while li < alias_len: + if from_imports[ci + li] != alias[li]: + match = 0 + break + li += 1 + if match == 1: + # 提取 module(colon+1 到下一个 ':' 或空格) + m_start: t.CSizeT = colon + 1 + m_end: t.CSizeT = m_start + while m_end < total_len and from_imports[m_end] != ':' and from_imports[m_end] != ' ': + m_end += 1 + if m_end > m_start: + mbuf: str = stdlib.malloc(m_end - m_start + 1) + if mbuf is not None: + string.strncpy(mbuf, from_imports + m_start, m_end - m_start) + mbuf[m_end - m_start] = '\0' + res: str = LookupSha1ByModName(mbuf) + stdlib.free(mbuf) + return res + return None + # 跳到下一条目 + while ci < total_len and from_imports[ci] != ' ': + ci += 1 + return None +# ============================================================ # PopulateIncludesDeps - 将 includes 文件的依赖存入内存 # # Phase B+ 前用 declare_only 翻译 includes 文件,提取 _imported_modules @@ -371,7 +425,7 @@ def GetSha1StoreArr(out_sha1_arr: t.CPtr, out_mod_arr: t.CPtr, out_rel_arr: t.CP return -1 if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None: return -1 - sp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_sha1_arr, t.CPtr)) + sp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_sha1_arr, t.CPtr)) # 存疑 if sp is not None: sp[0] = StubMerger._sha1_store_arr mp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_mod_arr, t.CPtr)) @@ -381,6 +435,7 @@ def GetSha1StoreArr(out_sha1_arr: t.CPtr, out_mod_arr: t.CPtr, out_rel_arr: t.CP if rp is not None: rp[0] = StubMerger._sha1_store_rel return StubMerger._sha1_store_count + # ============================================================ # LookupSha1RelPath - 通过 SHA1 查找相对路径 # diff --git a/App/lib/core/Gen/CallGenCall.vp b/App/lib/core/Gen/CallGenCall.vp index edf27e9..b2984d3 100644 --- a/App/lib/core/Gen/CallGenCall.vp +++ b/App/lib/core/Gen/CallGenCall.vp @@ -362,6 +362,11 @@ class CallGenCall(CallGenBase.CallGenBase): 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") # 依赖未就绪:保持默认 i32(build_call(Void) 返回 None 会 # 破坏表达式翻译;pending 文件本遍不写盘,下遍重译) call_ret_ty = llvmlite.Int32(pool) @@ -867,6 +872,12 @@ class CallGenCall(CallGenBase.CallGenBase): 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) # 依赖未就绪:保持默认 i32 继续而非 Void——build_call(Void) # 返回 None,方法调用结果喂进表达式(if 条件/比较)时 fatal # "if 条件表达式翻译失败"(ExprGenAttr._get_cderef_attr_base @@ -898,6 +909,12 @@ class CallGenCall(CallGenBase.CallGenBase): 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") # 依赖未就绪:保持默认 i32(同上,build_call(Void) 返回 # None 会破坏表达式翻译,pending 文件本遍不写盘) call_ret_ty = llvmlite.Int32(pool) @@ -1523,6 +1540,12 @@ class CallGenCall(CallGenBase.CallGenBase): 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") # 依赖未就绪:保持默认 i32(build_call(Void) 返回 None # 会破坏表达式翻译;pending 文件本遍不写盘,下遍重译) ret_ty_sp = llvmlite.Int32(pool) diff --git a/App/lib/core/Gen/CallGenDispatch.vp b/App/lib/core/Gen/CallGenDispatch.vp index 99529b7..5fc5bfb 100644 --- a/App/lib/core/Gen/CallGenDispatch.vp +++ b/App/lib/core/Gen/CallGenDispatch.vp @@ -1097,6 +1097,11 @@ class CallGenDispatch(CallGenBase.CallGenBase): # 中断多遍收敛(对齐追加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") # 依赖未就绪:保持默认 i32(build_call(Void) # 返回 None 破坏表达式翻译;本遍不写盘) ret_ty3 = llvmlite.Int32(pool) @@ -1121,6 +1126,10 @@ class CallGenDispatch(CallGenBase.CallGenBase): 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) if hit_box is not None: hit_box[0] = 1 return self.Gen.CallGenCall._translate_method_call( diff --git a/App/lib/core/Gen/CallGenMixin.vp b/App/lib/core/Gen/CallGenMixin.vp index 3980e2b..0d5a995 100644 --- a/App/lib/core/Gen/CallGenMixin.vp +++ b/App/lib/core/Gen/CallGenMixin.vp @@ -1164,6 +1164,12 @@ class CallGenMixin(CallGenBase.CallGenBase): else: if trans is not None: trans._deps_pending = 1 + # [DEPDBG] 临时诊断:跨模块函数依赖未就绪即 pending 的根因(用后移除) + dbg_ms5: str = trans.ModuleSha1 if (trans is not None and trans.ModuleSha1 is not None) else "?" + stdio.printf("[DEPDBG] pending(cross_fn): mod=%s call=%s sha1=%s text=%d\n", + dbg_ms5, call_name, + cf_sha1 if cf_sha1 is not None else "none", + self._dep_text_ll_exists(pool, cf_sha1) if cf_sha1 is not None else -1) cf_dbg: str = VLogger.fmt_buf() if cf_dbg is not None: viperlib.snprintf( diff --git a/App/lib/core/Gen/CallGenProp.vp b/App/lib/core/Gen/CallGenProp.vp index 7364e91..d008d40 100644 --- a/App/lib/core/Gen/CallGenProp.vp +++ b/App/lib/core/Gen/CallGenProp.vp @@ -125,6 +125,11 @@ class CallGenProp(CallGenBase.CallGenBase): 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") # 依赖未就绪:保持默认 i32(build_call(Void) 返回 None # 会破坏表达式翻译;pending 文件本遍不写盘,下遍重译) call_ret_ty = llvmlite.Int32(pool) diff --git a/App/lib/core/Gen/ExprGenName.vp b/App/lib/core/Gen/ExprGenName.vp index 128e802..b5f62e4 100644 --- a/App/lib/core/Gen/ExprGenName.vp +++ b/App/lib/core/Gen/ExprGenName.vp @@ -337,6 +337,11 @@ class ExprGenName(ExprGenBase.ExprGenBase): # 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") 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