diff --git a/App/lib/StubGen/VpiReader.vp b/App/lib/StubGen/VpiReader.vp index b6361ce..a7fa503 100644 --- a/App/lib/StubGen/VpiReader.vp +++ b/App/lib/StubGen/VpiReader.vp @@ -437,6 +437,60 @@ def _extract_sha1_from_path(vpi_path: str) -> str: return sha1_buf +# ============================================================ +# _stub_add_imported - 追加模块名到空格分隔列表(stub 上下文收集用) +# +# 与 HandlesImports.add_imported_module 逻辑一致,但内联在本模块, +# 避免 VpiReader → HandlesImports → StubMerger → VpiReader 循环依赖。 +# ============================================================ +def _stub_add_imported(pool: memhub.MemBuddy | t.CPtr, + cur: str, name: str) -> str: + """追加模块名到空格分隔列表(pool 分配),返回新列表""" + if name is None: + return cur + if cur is None: + nlen: t.CSizeT = string.strlen(name) + buf: str = pool.alloc(nlen + 1) + if buf is not None: + string.strcpy(buf, name) + return buf + old_len: t.CSizeT = string.strlen(cur) + name_len: t.CSizeT = string.strlen(name) + buf2: str = pool.alloc(old_len + 1 + name_len + 1) + if buf2 is not None: + string.strcpy(buf2, cur) + buf2[old_len] = ' ' + string.strcpy(buf2 + old_len + 1, name) + return buf2 + + +# ============================================================ +# _stub_add_from - 追加 from-import 映射("local:mod[:orig]" 空格分隔) +# ============================================================ +def _stub_add_from(pool: memhub.MemBuddy | t.CPtr, + cur: str, local: str, mod: str, orig: str) -> str: + """追加 from-import 映射(pool 分配),返回新列表""" + if local is None or mod is None: + return cur + entry: str = pool.alloc(256) + if entry is None: + return cur + if orig is not None and string.strcmp(orig, local) != 0: + viperlib.snprintf(entry, 256, "%s:%s:%s", local, mod, orig) + else: + viperlib.snprintf(entry, 256, "%s:%s", local, mod) + if cur is None: + return entry + old_len: t.CSizeT = string.strlen(cur) + entry_len: t.CSizeT = string.strlen(entry) + buf: str = pool.alloc(old_len + 1 + entry_len + 1) + if buf is not None: + string.strcpy(buf, cur) + buf[old_len] = ' ' + string.strcpy(buf + old_len + 1, entry) + return buf + + # ============================================================ # ParseVpiIntoModule - 解析 .vpi 文件,将函数声明注入到当前模块 # @@ -486,10 +540,6 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy | t.CPtr, if pool is None or mod is None or vpi_path is None or trans is None: return 0 - # 获取当前翻译器的导入信息(供 resolve_annotation_type 使用) - imported_modules: str = trans._imported_modules - from_imports: str = trans._from_imports - # 1. 读取 .vpi 文件 f: fileio.File | t.CPtr = fileio.File(vpi_path, fileio.MODE.R) if f.closed: @@ -539,6 +589,61 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy | t.CPtr, return 1 n: t.CSizeT = ch.__len__() + # 收集 stub 内被读模块自己的 import 语句,构建独立的注解解析上下文。 + # .vpi stub 顶部含被读模块的 import(Converter 已写入,如 string.vp 的 + # "import t, c"),用它替代当前模块的 imported_modules/from_imports 去 + # 解析注解——根治跨上下文误报(如 t.CArray[str] 需要 't' 已导入)。 + stub_imported_modules: str = None + stub_from_imports: str = None + si: t.CSizeT + for si in range(n): + schild: ast.AST | t.CPtr = ch.get(si) + if schild is None: + continue + sk: int = schild.kind() + if sk == ast.ASTKind.Import: + simp: ast.Import | t.CPtr = (ast.Import | t.CPtr)(schild) + if simp.names is not None: + sn_n: t.CSizeT = simp.names.__len__() + sni: t.CSizeT + for sni in range(sn_n): + sal: ast.Alias | t.CPtr = (ast.Alias | t.CPtr)(simp.names.get(sni)) + if sal is not None and sal.name is not None: + stub_imported_modules = _stub_add_imported( + pool, stub_imported_modules, sal.name) + if sal.asname is not None: + stub_imported_modules = _stub_add_imported( + pool, stub_imported_modules, sal.asname) + elif sk == ast.ASTKind.ImportFrom: + sifr: ast.ImportFrom | t.CPtr = (ast.ImportFrom | t.CPtr)(schild) + sifr_mod: str = sifr.module + if sifr_mod is not None: + stub_imported_modules = _stub_add_imported( + pool, stub_imported_modules, sifr_mod) + if sifr.names is not None: + sifr_nn: t.CSizeT = sifr.names.__len__() + sifri: t.CSizeT + for sifri in range(sifr_nn): + sial: ast.Alias | t.CPtr = (ast.Alias | t.CPtr)(sifr.names.get(sifri)) + if sial is not None and sial.name is not None: + # '*' star import 不建 from 映射(lookup 有 star 回退) + if string.strcmp(sial.name, "*") != 0: + slocal: str = sial.name + sorig: str = None + if sial.asname is not None: + slocal = sial.asname + sorig = sial.name + stub_from_imports = _stub_add_from( + pool, stub_from_imports, slocal, sifr_mod, sorig) + + # 用 stub 自己的 imports 替代当前模块的(stub 注解解析上下文正确性) + imported_modules: str = trans._imported_modules + from_imports: str = trans._from_imports + if stub_imported_modules is not None: + imported_modules = stub_imported_modules + if stub_from_imports is not None: + from_imports = stub_from_imports + i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)