diff --git a/App/lib/Stub/StubMerger/StubMergerStore.vp b/App/lib/Stub/StubMerger/StubMergerStore.vp index 9f69656..1af2be6 100644 --- a/App/lib/Stub/StubMerger/StubMergerStore.vp +++ b/App/lib/Stub/StubMerger/StubMergerStore.vp @@ -163,11 +163,6 @@ def AppendToSha1MapStore(sha1: str, rel_path: str) -> int: StubMerger._sha1_store_count = 0 if StubMerger._sha1_store_count >= StubMerger.MAX_INCLUDES: return 1 - # 去重:若 SHA1 已存在则跳过 - for i in range(StubMerger._sha1_store_count): - sidx_d: t.CSizeT = t.CSizeT(i) * 17 - if string.strcmp(StubMerger._sha1_store_arr + sidx_d, sha1) == 0: - return 0 # 模块名:rel_path "lib/core/StubMerger.vp" → "lib.core.StubMerger" full_path_buf: bytes = stdlib.malloc(string.strlen(rel_path) + 10) if full_path_buf is None: @@ -177,6 +172,18 @@ def AppendToSha1MapStore(sha1: str, rel_path: str) -> int: stdlib.free(full_path_buf) if mod_name is None: return 1 + # 去重:SHA1 与模块名都相同才跳过。同一 SHA1 可能被 includes 扫描先以 + # 全路径模块名注册(如 App 源文件在 includes 目录下 → "Apps.Scene3D.gfx"), + # App 追加的短模块名("gfx")必须保留——否则 import gfx 的精确查找 + # LookupSha1ByModName("gfx") 失败 → 后缀匹配劫持到 VKernel 同名 gfx + # (VKernel/Kernel/drivers/video/vesafb/gfx.vp,类 Scene3D 归属错乱根因)。 + for i in range(StubMerger._sha1_store_count): + sidx_d: t.CSizeT = t.CSizeT(i) * 17 + if string.strcmp(StubMerger._sha1_store_arr + sidx_d, sha1) == 0: + midx_d: t.CSizeT = t.CSizeT(i) * 64 + if string.strcmp(StubMerger._sha1_store_mod + midx_d, mod_name) == 0: + stdlib.free(mod_name) + return 0 # 写入 SHA1 idx_a: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * 17 string.strcpy(StubMerger._sha1_store_arr + idx_a, sha1) @@ -327,6 +334,62 @@ def LookupSha1ByAlias(from_imports: str, alias: str) -> str: ci += 1 return None # ============================================================ +# LookupModNameByAlias - 从 from_imports 别名映射解析模块真名 +# +# import X as Y 时 ImportsGenMixin.add_from_import 写入 "Y:X"(Y=别名, +# X=模块真名)。本函数返回别名 Y 对应的模块真名 X(供限定名解析 +# "Y.Class" → 按 X 模块归属匹配,如 "types.fileinfo" → "fat32_types")。 +# +# Returns: +# 模块名字符串(stdlib 分配,调用方负责 free),None 未找到 +# ============================================================ +def LookupModNameByAlias(from_imports: str, alias: str) -> str: + """从 from_imports 别名映射解析模块真名(import X as Y → Y:X)""" + 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' + return mbuf + return None + # 跳到下一条目 + while ci < total_len and from_imports[ci] != ' ': + ci += 1 + return None +# ============================================================ # PopulateIncludesDeps - 将 includes 文件的依赖存入内存 # # Phase B+ 前用 declare_only 翻译 includes 文件,提取 _imported_modules diff --git a/App/lib/core/Gen/StructGenMixin.vp b/App/lib/core/Gen/StructGenMixin.vp index 2601db4..73b6d07 100644 --- a/App/lib/core/Gen/StructGenMixin.vp +++ b/App/lib/core/Gen/StructGenMixin.vp @@ -512,6 +512,27 @@ class StructGenMixin: string.strncpy(mod_buf_f, name, mod_len_f) mod_buf_f[mod_len_f] = '\0' if string.strcmp(mod_buf_f, "t") != 0 and string.strcmp(mod_buf_f, "c") != 0: + # 模块段是 16 位 hex = SHA1 字面量(如 "{9aab}.Scene3D", + # TypeGenResolve L1397-1402 的 sha1 前缀形态):跳过 store + # 模块名查询(store 键是模块名不是 sha1),直接按 name+sha1 + # 精确匹配。否则 _resolve_module_sha1("9aab") 返回 None → + # 落到第二遍裸名回退 → 跨模块同名类(VKernel gfx 与 App gfx + # 都定义 Scene3D)返回先注册的错误 entry(Scene3D 归属错乱 + # → ret_sha1=0ae → Phase A _deps_pending 死锁根因)。 + mod_hex_ok: int = 1 + if string.strlen(mod_buf_f) == 16: + for hi_f in range(16): + ch_h: t.CChar = mod_buf_f[hi_f] + if not ((ch_h >= 48 and ch_h <= 57) or (ch_h >= 97 and ch_h <= 102)): + mod_hex_ok = 0 + break + else: + mod_hex_ok = 0 + if mod_hex_ok != 0: + me_h: GenTypes.StructEntry | t.CPtr = \ + self.find_struct_by_module(bare_f, mod_buf_f) + stdlib.free(mod_buf_f) + return me_h mod_sha1_f: str = self._resolve_module_sha1(mod_buf_f) if mod_sha1_f is not None: me_f: GenTypes.StructEntry | t.CPtr = \ @@ -539,11 +560,21 @@ class StructGenMixin: if dot_pos is not None: class_name: str = dot_pos + 1 if class_name is not None and class_name[0] != '\0': + # 同名唯一性检查(对齐上方限定名路径 L543-554):跨模块同名类 + # (如 VKernel gfx 与 App gfx 都定义 Scene3D)存在时不得返回 + # 先注册的错误 entry——否则模块段无法解析的限定名(如 + # "9aab.Scene3D")被劫持到错误模块 → 返回类型解析查错 text.ll + # → Phase A _deps_pending 死锁(Scene3D ret_sha1=0ae 根因)。 + same_cnt_b: int = 0 + same_entry_b: GenTypes.StructEntry | t.CPtr = None for i in range(self.StructCount): entry: GenTypes.StructEntry | t.CPtr = self._get_struct_entry(i) if entry is not None and entry.Name is not None: if string.strcmp(entry.Name, class_name) == 0: - return entry + same_cnt_b += 1 + same_entry_b = entry + if same_cnt_b == 1: + return same_entry_b return None def find_struct_by_module(self, name: str, sha1: str) -> GenTypes.StructEntry | t.CPtr: