chore(messages): TransPyV 运行时中文字符串英文化

把 TransPyV/App 下 57 个文件的运行时中文字符串(编译器报错/告警/日志、CLI 帮助与横幅、REPL 提示、Phase1/Phase2 流程日志、Codegen 各 Mixin 的类型与调用报错、Stub/Vpi 诊断等)共 1091 行译为英文。

口径:只改字符串字面量内部文字,行数零变化(+1092/-1092);printf 格式符与转义序列多重集合校验不变(_strcheck 异常 0);译文不引入撇号以免干扰单引号字面量解析。验证:三重重编 SUCCESS(136.20s)+ 全量 77/77 顺序回归通过 + VET 编译 SUCCESS / --search-paths 7 条 exit 0;新产物 help/日志输出已为英文。
This commit is contained in:
TermiNexus committed 2026-10-07 00:03:58 +08:00
1 parent 0cf80632c1
commit 7a9bc5ae75
57 files changed
+1092 -1092

No files matched your search

+12 -12
View File
@@ -177,7 +177,7 @@ def _PyiBinOpOpText(buf: bytes, buf_size: sizet, pos: sizet, op: int, node: ast.
if op == ast.OpKind.Mod: return _PyiEmit(buf, buf_size, pos, " % ")
if op == ast.OpKind.BitAnd: return _PyiEmit(buf, buf_size, pos, " & ")
if op == ast.OpKind.RShift: return _PyiEmit(buf, buf_size, pos, " >> ")
GenApi.fatal_error(node, "vpi 类型注解节点类型未知", "TypeError")
GenApi.fatal_error(node, "unknown vpi type-annotation node type", "TypeError")
return pos # unreachable (fatal_error already exited)
@@ -188,7 +188,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, annot: ast.AST*, depth:
# Recursion guard: a self-referential AST would recurse until stack exhaustion.
# Fail fast instead of silently falling back.
if depth > 64:
VLogger.error("vpi 类型注解递归过深(AST 环或嵌套超过 64 层)", "StubGen")
VLogger.error("vpi type annotation recursion too deep (AST cycle or nesting over 64 levels)", "StubGen")
sys.exit(1)
if annot is None: return _PyiEmit(buf, buf_size, pos, "int")
@@ -234,7 +234,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, annot: ast.AST*, depth:
elif uop_t.op == ast.OpKind.Invert: pos = _PyiEmit(buf, buf_size, pos, "~")
elif uop_t.op == ast.OpKind.USub: pos = _PyiEmit(buf, buf_size, pos, "-")
else:
GenApi.fatal_error(annot, "vpi 类型注解节点类型未知", "TypeError")
GenApi.fatal_error(annot, "unknown vpi type-annotation node type", "TypeError")
return pos # unreachable (fatal_error already exited)
return _PyiTypeStr(buf, buf_size, pos, uop_t.operand, depth + 1)
@@ -338,7 +338,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, annot: ast.AST*, depth:
return pos
# Unknown node type: fail fast rather than silently writing "int" and producing a wrong signature.
GenApi.fatal_error(annot, "vpi 类型注解节点类型未知", "TypeError")
GenApi.fatal_error(annot, "unknown vpi type-annotation node type", "TypeError")
return _PyiEmit(buf, buf_size, pos, "int") # unreachable (fatal_error already exited)
@@ -348,7 +348,7 @@ def _PyiDefaultStr(buf: bytes, buf_size: sizet, pos: sizet, node: ast.AST*, dept
"""Render a default-value expression into buf and return the new pos"""
# Recursion guard: fail fast on a self-referential AST (same as _PyiTypeStr)
if depth > 64:
VLogger.error("vpi 默认值表达式递归过深(AST 环或嵌套超过 64 层)", "StubGen")
VLogger.error("vpi default-value expression recursion too deep (AST cycle or nesting over 64 levels)", "StubGen")
sys.exit(1)
if node is None: return pos
@@ -412,7 +412,7 @@ def _PyiRejectCReturnDecorator(node: ast.AST*, decorators: list[ast.AST*]*) -> i
elif dnode.kind() == ast.ASTKind.Attribute: dattr = ast.Attribute*(dnode)
if dattr is None or dattr.attr is None: continue
if string.strcmp(dattr.attr, "CReturn") == 0:
GenApi.fatal_error(node, "vpi 中仍带 `@c.CReturn`(已移除):请用返回注解 `-> tuple[ty1, ty2, ...]` 重新生成该 .vpi(可加 --clean)", "TypeError")
GenApi.fatal_error(node, "vpi still contains `@c.CReturn` (removed): regenerate the .vpi using a return annotation `-> tuple[ty1, ty2, ...]` (you may add --clean)", "TypeError")
return 1
return 0
@@ -712,7 +712,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf
# fail-fast: an empty alias list would write a broken `import ` line and
# lose all names, breaking package re-export registration.
if imp2.names is None or len(imp2.names) == 0:
GenApi.fatal_error(stmt, "vpi 生成:import 语句别名列表为空(应为 ≥1 个别名)——AST 构造/解析异常", "NameError")
GenApi.fatal_error(stmt, "vpi generation: the import statement alias list is empty (expected >=1 alias) -- AST construction/parse anomaly", "NameError")
if imp2.names is not None:
imp2_names: list[ast.AST*]* = imp2.names
an2: sizet = len(imp2_names)
@@ -722,9 +722,9 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf
# fail-fast: never silently write "import , ". Import names are the
# only input for package re-export registration. Report the two causes separately.
if al2 is None:
GenApi.fatal_error(stmt, "vpi 生成:import 别名**节点指针为空**(Alias(...) 构造未产出对象:" "pool.alloc 失败或 __init__ 未执行)——import 名字丢失会破坏包重导出注册", "NameError")
GenApi.fatal_error(stmt, "vpi generation: import alias **node pointer is null** (Alias(...) construction produced no object: " "pool.alloc failed or __init__ was not run) -- losing the import name breaks package re-export registration", "NameError")
if al2.name is None or al2.name[0] == '\0':
GenApi.fatal_error(stmt, "vpi 生成:import 别名节点存在但 **name 为空**(_copy_str 返回 None / " "__init__ 未赋值 name)——import 名字丢失会破坏包重导出注册", "NameError")
GenApi.fatal_error(stmt, "vpi generation: the import alias node exists but **name is empty** (_copy_str returned None / " "__init__ did not set name) -- losing the import name breaks package re-export registration", "NameError")
pos = _PyiEmit(buf, buf_size, pos, al2.name)
if al2.asname is not None and string.strlen(al2.asname) > 0:
pos = _PyiEmit(buf, buf_size, pos, " as ")
@@ -744,7 +744,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf
# fail-fast: same as Import; `from X import *` uses Alias("*"). An empty
# list or empty name means a broken AST and would break re-export registration.
if ifr.names is None or len(ifr.names) == 0:
GenApi.fatal_error(stmt, "vpi 生成:from-import 语句别名列表为空(应为 ≥1 个别名,含 '*')" "——AST 构造/解析异常", "NameError")
GenApi.fatal_error(stmt, "vpi generation: the from-import statement alias list is empty (expected >=1 alias, including star)" "-- AST construction/parse anomaly", "NameError")
if ifr.names is not None:
ifr_names: list[ast.AST*]* = ifr.names
an3: sizet = len(ifr_names)
@@ -753,9 +753,9 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf
al3: ast.Alias* = ast.Alias*(ifr_names.get(ai3))
# fail-fast: same as Import (report the two causes separately).
if al3 is None:
GenApi.fatal_error(stmt, "vpi 生成:from-import 别名**节点指针为空**(Alias(...) 构造未产出对象:" "pool.alloc 失败或 __init__ 未执行)——包重导出注册会因此失效", "NameError")
GenApi.fatal_error(stmt, "vpi generation: from-import alias **node pointer is null** (Alias(...) construction produced no object: " "pool.alloc failed or __init__ was not run) -- package re-export registration will therefore fail", "NameError")
if al3.name is None or al3.name[0] == '\0':
GenApi.fatal_error(stmt, "vpi 生成:from-import 别名节点存在但 **name 为空**(_copy_str 返回 None / " "__init__ 未赋值 name)——包重导出注册会因此失效", "NameError")
GenApi.fatal_error(stmt, "vpi generation: the from-import alias node exists but **name is empty** (_copy_str returned None / " "__init__ did not set name) -- package re-export registration will therefore fail", "NameError")
pos = _PyiEmit(buf, buf_size, pos, al3.name)
if al3.asname is not None and string.strlen(al3.asname) > 0:
pos = _PyiEmit(buf, buf_size, pos, " as ")
+28 -28
View File
@@ -1391,7 +1391,7 @@ def _vpi_typedef_visited_mark(sha1: str) -> None:
_g_vpi_typedef_visited = stdlib.malloc(_TYPEDEF_VISIT_MAX * 17)
if _g_vpi_typedef_visited is None:
# fail-fast: without the cycle table the closure re-parses and exhausts the pool, so do not continue
stdio.printf("[VPI] 防环访问表分配失败(无表则闭包重解析爆炸,终止)\n")
stdio.printf("[VPI] cycle-proof visit table allocation failed (without the table the closure reparse explodes; aborting)\n")
stdio.fflush(None)
stdlib.exit(1)
string.memset(_g_vpi_typedef_visited, 0, _TYPEDEF_VISIT_MAX * 17)
@@ -1404,7 +1404,7 @@ def _vpi_typedef_visited_mark(sha1: str) -> None:
new_cap: int = old_cap * 2
nb: bytes = stdlib.realloc(_g_vpi_typedef_visited, new_cap * 17)
if nb is None:
stdio.printf("[VPI] 防环访问表扩容失败 cap=%d(丢标记引发重解析爆炸,终止)\n", old_cap)
stdio.printf("[VPI] cycle-proof visit table growth failed cap=%d (lost marks cause a reparse explosion; aborting)\n", old_cap)
stdio.fflush(None)
stdlib.exit(1)
_g_vpi_typedef_visited = nb
@@ -1709,7 +1709,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, v
# [D26 fail-fast] Do not silently skip when a package __init__ from-import cannot
# resolve the submodule sha1: report package and submodule names for diagnosis.
if is_pkg_init_rt != 0 and sub_sha1_rt is None and sifr_mod is not None and sifr_mod[0] != '\0':
GenApi.fatal_error(sifr, f"包 stub 的 from-import 子模块 sha1 查找失败:" f"包={rel_path_rt if rel_path_rt is not None else '?'}," f"子模块='{sifr_mod}'(补前缀后='{sifr_mod_q}');" f"该子模块的类无法注册,引用它们的注解会在后续解析时落空", "NameError")
GenApi.fatal_error(sifr, f"Package stub from-import submodule sha1 lookup failed: " f"package={rel_path_rt if rel_path_rt is not None else '?'}, " f"submodule='{sifr_mod}' (after prefix completion='{sifr_mod_q}'); " f"classes of this submodule cannot be registered, and annotations referencing them will fail to resolve later", "NameError")
if sifr.names is not None:
sifr_nn: sizet = len(sifr.names)
sifri: sizet
@@ -2375,7 +2375,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*,
# [S4 fail-fast] A return annotation that does not resolve is not silently downgraded to i32;
# no annotation (fd.returns is None) is a legitimate default and keeps i32 below.
if ret_ty is None and fd.returns is not None:
GenApi.fatal_error(fd.returns, f"extern 声明 '{fd.name}' 返回类型注解解析失败", "NameError")
GenApi.fatal_error(fd.returns, f"extern declaration '{fd.name}' return type annotation failed to resolve", "NameError")
# default return i32
if ret_ty is None: ret_ty = i32_ty
@@ -2400,7 +2400,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*,
# Param-count upper-bound sentinel (fail-fast): a corrupted vpi tree node makes __len__()
# return a huge value, so add_param runs massively and the Params chain balloons.
if param_count < 0 or param_count > 128:
stdio.printf("[VPIS] 参数数异常: 函数名=%s param_count=%d(fd.args=%llu,tree 可能被覆盖,终止)\n", fd.name, param_count, uint64(fd.args))
stdio.printf("[VPIS] abnormal parameter count: function=%s param_count=%d (fd.args=%llu, tree may be overwritten; aborting)\n", fd.name, param_count, uint64(fd.args))
# convergence point: longjmp back to the REPL loop in a REPL session (diagnostics printed)
VLogger.repl_abort()
pi: sizet
@@ -2439,7 +2439,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*,
else:
# [S4 fail-fast] An annotation that does not resolve is not silently downgraded
# to i8* (no annotation is a legitimate default and keeps i8*).
GenApi.fatal_error(ag.annotation, f"extern 声明 '{fd.name}' 形参 '{pname}' 类型注解解析失败", "NameError")
GenApi.fatal_error(ag.annotation, f"extern declaration '{fd.name}' parameter '{pname}' type annotation failed to resolve", "NameError")
mlirlite.add_param(pool, func, param_ty, pname)
# Text-cache repair: a corrupted vpi tree truncates args, leaving too few declare params;
# complete them from the vpi text param annotations so declare matches define.
@@ -2455,7 +2455,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*,
if fd_default_count < 0 or fd_default_count > 128:
# A corrupted args.defaults node makes len return a huge value, so
# _register_global_defaults would over-allocate and write out of bounds; skip it.
stdio.printf("[VPIS] 默认参数数异常: 函数名=%s default_count=%d(tree 可能被覆盖,跳过默认值注册)\n", fd.name, fd_default_count)
stdio.printf("[VPIS] abnormal default parameter count: function=%s default_count=%d (tree may be overwritten; skipping default value registration)\n", fd.name, fd_default_count)
fd_defaults = None
fd_default_count = 0
else: fd_defaults = fd_dlist
@@ -2512,7 +2512,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, m_
# [S4 fail-fast] A return annotation that does not resolve is not silently downgraded to i32;
# unannotated __new__ / normal methods keep i32 as the legitimate default below.
if ret_ty is None and m_fd.returns is not None:
GenApi.fatal_error(m_fd.returns, f"extern 方法 '{cls_name}.{m_fd.name}' 返回类型注解解析失败", "NameError")
GenApi.fatal_error(m_fd.returns, f"extern method '{cls_name}.{m_fd.name}' return type annotation failed to resolve", "NameError")
# Unannotated __init__ -> Void, matching the definition side (ClassGenVTable always uses Void);
# defaulting to i32 would split declare i32 / define void.
if ret_ty is None and string.strcmp(m_fd.name, "__init__") == 0: ret_ty = mlirlite.Void(pool)
@@ -2534,7 +2534,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, m_
# Param-count upper-bound sentinel (fail-fast): same cause as _inject_function_declare
# (a corrupted vpi tree node makes __len__() return a huge value).
if param_count < 0 or param_count > 128:
stdio.printf("[VPIS] 参数数异常: 方法名=%s.%s param_count=%d(m_fd.args=%llu,tree 可能被覆盖,终止)\n", cls_name, m_fd.name, param_count, uint64(m_fd.args))
stdio.printf("[VPIS] abnormal parameter count: method=%s.%s param_count=%d (m_fd.args=%llu, tree may be overwritten; aborting)\n", cls_name, m_fd.name, param_count, uint64(m_fd.args))
# convergence point: longjmp back to the REPL loop in a REPL session (diagnostics printed)
VLogger.repl_abort()
pi: sizet
@@ -2579,7 +2579,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, m_
else:
# [S4 fail-fast] An annotation that does not resolve is not silently downgraded
# to i8* (no annotation is a legitimate default and keeps i8*).
GenApi.fatal_error(ag.annotation, f"extern 方法 '{cls_name}.{m_fd.name}' 形参 '{pname}' 类型注解解析失败", "NameError")
GenApi.fatal_error(ag.annotation, f"extern method '{cls_name}.{m_fd.name}' parameter '{pname}' type annotation failed to resolve", "NameError")
mlirlite.add_param(pool, func, param_ty, pname)
# Text-cache repair: a corrupted vpi tree truncates args, leaving too few declare params;
@@ -2603,7 +2603,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, m_
if md_default_count < 0 or md_default_count > 128:
# Same as _inject_function_declare: a corrupted tree node makes defaults len huge,
# which would write out of bounds into perm_pool; skip registration.
stdio.printf("[VPIS] 默认参数数异常: 方法名=%s.%s default_count=%d(tree 可能被覆盖,跳过默认值注册)\n", cls_name, m_fd.name, md_default_count)
stdio.printf("[VPIS] abnormal default parameter count: method=%s.%s default_count=%d (tree may be overwritten; skipping default value registration)\n", cls_name, m_fd.name, md_default_count)
md_defaults = None
md_default_count = 0
else: md_defaults = md_dlist
@@ -2902,7 +2902,7 @@ def _repl_stub_warn_refuse(e: ReplStubClass*, why: str, a: int, b: int) -> None:
ReplStubRefused += 1
if ReplStubWarnLeft <= 0: return
ReplStubWarnLeft -= 1
stdio.printf("includes 类布局: %s.%s 布局不可信 ⇒ 明确拒绝(原因=判据拒绝:%s;" "存根字段数=%d ≠ 展平字段数+虚表位=%d)。该类字段访问被明确拒绝" "(方法调用不受影响)\n", e.Sha1, e.ClassName, why, a, b)
stdio.printf("includes class layout: layout of %s.%s is untrusted => explicitly refused (reason=criterion refused: %s; " "stub field count=%d != flattened field count+vtable slots=%d). Field access on this class is explicitly refused " "(method calls are unaffected)\n", e.Sha1, e.ClassName, why, a, b)
def _repl_stub_warn_nodata(e: ReplStubClass*, cause: int) -> None:
@@ -2919,13 +2919,13 @@ def _repl_stub_warn_nodata(e: ReplStubClass*, cause: int) -> None:
ReplStubWarnLeft -= 1
if cause == _REPL_SU_NOSTUB:
# missing data: not even module layout metadata (LayoutCount = -1 is just a "not read" sentinel)
stdio.printf("includes 类布局: %s.%s 布局不可用 ⇒ 明确拒绝(原因=『数据缺失』:" "模块 %s 没有 {sha1}.meta 布局元数据;meta 字段数=无 / 推断字段数=未计算 ⇒ " "两侧都没数据,『未做比较』,不是字段数不符)。该类字段访问被" "拒绝(方法调用不受影响);补上该模块 meta(同一工程先跑一次批处理," "Phase A/B 会落盘 {sha1}.meta)后用同一 --project 重跑 REPL 即恢复\n", e.Sha1, e.ClassName, e.Sha1)
stdio.printf("includes class layout: layout of %s.%s unavailable => explicitly refused (reason=data missing: " "module %s has no {sha1}.meta layout metadata; meta field count=none / inferred field count=not computed => " "no data on either side, no comparison was made, and this is not a field count mismatch). Field access on this class is " "refused (method calls are unaffected); add the module meta (run batch processing once in the same project, " "Phase A/B writes {sha1}.meta), then rerun REPL with the same --project to recover\n", e.Sha1, e.ClassName, e.Sha1)
elif cause == _REPL_SU_OPAQUE:
# refused: the key is OPAQUE in meta (no body, so no field count to compare)
stdio.printf("includes 类布局: %s.%s 布局不可用 ⇒ 明确拒绝(原因=『判据拒绝』:" "meta %s.meta 里键 %s 为 OPAQUE 声明(无 body);meta 字段数=不可得 / " "推断字段数=未计算 ⇒ 『未做比较』)。该类字段访问被拒绝" "(方法调用不受影响)\n", e.Sha1, e.ClassName, e.Sha1, e.Key)
stdio.printf("includes class layout: layout of %s.%s unavailable => explicitly refused (reason=criterion refused: " "key %s in meta %s.meta is declared OPAQUE (no body); meta field count=unavailable / " "inferred field count=not computed => no comparison was made). Field access on this class is refused " "(method calls are unaffected)\n", e.Sha1, e.ClassName, e.Sha1, e.Key)
else:
# refused: meta exists but has no STRUCT line for this class (LayoutCount = -1 is a "not found" sentinel)
stdio.printf("includes 类布局: %s.%s 布局不可用 ⇒ 明确拒绝(原因=『判据拒绝』:" "meta %s.meta 存在但其中没有键 %s 的 `STRUCT … FIELDS n / OPAQUE` 记录;" "meta 字段数=未找到 / 推断字段数=未计算 ⇒ 『未做比较』)。该类字段访问" "被拒绝(方法调用不受影响);若该类确实定义于该模块,说明 meta 陈旧/" "不完整,请重建\n", e.Sha1, e.ClassName, e.Sha1, e.Key)
stdio.printf("includes class layout: layout of %s.%s unavailable => explicitly refused (reason=criterion refused: " "meta %s.meta exists but has no `STRUCT ... FIELDS n / OPAQUE` record for key %s; " "meta field count=not found / inferred field count=not computed => no comparison was made). Field access on this class is " "refused (method calls are unaffected); if this class is indeed defined in that module, the meta is stale/" "incomplete, please rebuild\n", e.Sha1, e.ClassName, e.Sha1, e.Key)
def _repl_stub_warn_parent(e: ReplStubClass*, detail: str, pname: str) -> None:
@@ -2935,7 +2935,7 @@ def _repl_stub_warn_parent(e: ReplStubClass*, detail: str, pname: str) -> None:
ReplStubRefusedParent += 1
if ReplStubWarnLeft <= 0: return
ReplStubWarnLeft -= 1
stdio.printf("includes 类布局: %s.%s 布局不可用 ⇒ 明确拒绝(原因=『上游无数据』:%s," "父类=%s;父类字段与虚表位无法展平 ⇒ 本类未做字段数比较)。该类字段访问" "被拒绝(方法调用不受影响)\n", e.Sha1, e.ClassName, detail, pname)
stdio.printf("includes class layout: layout of %s.%s unavailable => explicitly refused (reason=upstream no data: %s, " "parent=%s; parent fields and vtable slots cannot be flattened => no field count comparison was done for this class). Field access on this class is " "refused (method calls are unaffected)\n", e.Sha1, e.ClassName, detail, pname)
def _repl_stub_try(e: ReplStubClass*, mod: mlirlite.LLVMModule*) -> int:
@@ -2957,13 +2957,13 @@ def _repl_stub_try(e: ReplStubClass*, mod: mlirlite.LLVMModule*) -> int:
if pe.State == _REPL_SS_PENDING: return 0
if pe.State == _REPL_SS_REFUSED:
e.State = _REPL_SS_REFUSED
_repl_stub_warn_parent(e, "父类布局不可信", pe.ClassName)
_repl_stub_warn_parent(e, "Parent layout untrusted", pe.ClassName)
return -1
if pe.State == _REPL_SS_EMPTY and pe.OwnFail != 0:
# The base itself had field-annotation failures, so its Count is only partially parsed:
# the flattened field count is unusable, so neither compare nor allow it (M4.2: refuse).
e.State = _REPL_SS_REFUSED
_repl_stub_warn_parent(e, "父类的字段类型未全部解析(其字段数不完整)", pe.ClassName)
_repl_stub_warn_parent(e, "Not all field types of the parent are resolved (its field count is incomplete)", pe.ClassName)
return -1
first: ReplStubClass* = None
if e.BaseCount > 0: first = _repl_stub_find_base(e, 0)
@@ -3003,7 +3003,7 @@ def _repl_stub_try(e: ReplStubClass*, mod: mlirlite.LLVMModule*) -> int:
# __vtable__ (if any) + flattened field count.
if e.LayoutCount != cn + hv:
e.State = _REPL_SS_REFUSED
_repl_stub_warn_refuse(e, "存根字段数与字段名单不符", e.LayoutCount, cn + hv)
_repl_stub_warn_refuse(e, "Stub field count does not match the field name list", e.LayoutCount, cn + hv)
return -1
# (5) virtual method short-name order (base virtuals first + own eligible methods in class order)
vn: int = 0
@@ -3036,7 +3036,7 @@ def _repl_stub_try(e: ReplStubClass*, mod: mlirlite.LLVMModule*) -> int:
if vn == e.VtArity: e.VtTrust = 1
elif ReplStubWarnLeft > 0:
ReplStubWarnLeft -= 1
stdio.printf("includes 类布局: %s.%s 的虚表槽数与存根不符(%d vs %d)" "——该类不做虚分派(退化为直接调用,会话继续)\n", e.Sha1, e.ClassName, vn, e.VtArity)
stdio.printf("includes class layout: vtable slot count of %s.%s does not match the stub (%d vs %d) " "-- this class skips virtual dispatch (degrades to direct call, session continues)\n", e.Sha1, e.ClassName, vn, e.VtArity)
# (6) build the LLVM struct (named "%<sha1>.<ClassName>", same as the definition side)
total: int = cn + hv
i8_ptr: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
@@ -3255,7 +3255,7 @@ def _repl_stub_collect_module(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*,
ReplStubNoStub += 1
if ReplStubWarnLeft > 0:
ReplStubWarnLeft -= 1
stdio.printf("includes 类布局: 模块 %s 无 .meta 存根(数据缺失)—— 该模块" "带父类/虚表的类将逐个按『数据缺失』明确拒绝(读不到布局元数据 ⇒ 无" "字段数可比,不是字段数不符)。用同一工程先跑一次批处理生成存根," "再 `--project .\\project.vpj --repl`(TransPyV 目录)即可复用\n", src_sha1)
stdio.printf("includes class layout: module %s has no .meta stub (data missing) -- this module " "classes with parent/vtable will each be explicitly refused as data missing (layout metadata cannot be read => no " "field count to compare, not a field count mismatch). First run batch processing once in the same project to generate stubs, " "then reuse them with `--project .\\project.vpj --repl` (in the TransPyV directory)\n", src_sha1)
cnt: int = 0
i: sizet
for i in range(n):
@@ -3298,22 +3298,22 @@ def ReplStubLayoutFinish() -> int:
if e2 is None or e2.State != _REPL_SS_PENDING: continue
e2.State = _REPL_SS_REFUSED
# find the still-unready base class name (to identify the upstream)
pbad: str = "(未定位)"
pbad: str = "(not located)"
bi2: int
for bi2 in range(e2.BaseCount):
peb: ReplStubClass* = _repl_stub_find_base(e2, bi2)
if peb is not None and peb.State == _REPL_SS_OK: continue
if peb is not None and peb.ClassName is not None: pbad = peb.ClassName
break
_repl_stub_warn_parent(e2, "父类未在会话注册或其布局被拒", pbad)
stdio.printf("includes 类布局: 完整布局 %d 个(其中虚表索引可用 %d 个)/ " "被拒 %d 个 / 缺布局元数据模块 %d 个\n", ReplStubOk, ReplStubVtOk, ReplStubRefused, ReplStubNoStub)
stdio.printf(" 拒绝原因分布(自证数据来源):数据缺失-模块无 {sha1}.meta %d 个类 / " "判据拒绝-meta 无此类 %d 个 / 判据拒绝-meta 为 opaque %d 个 / " "上游无数据-父类不可用 %d 个\n", ReplStubRefusedNoStub, ReplStubRefusedNoClass, ReplStubRefusedOpaque, ReplStubRefusedParent)
_repl_stub_warn_parent(e2, "Parent not registered in the session or its layout was refused", pbad)
stdio.printf("includes class layout: %d complete layouts (%d with a usable vtable index) / " "%d refused / %d modules missing layout metadata\n", ReplStubOk, ReplStubVtOk, ReplStubRefused, ReplStubNoStub)
stdio.printf(" refusal reason distribution (self-witnessing data source): data missing-module has no {sha1}.meta %d classes / " "criterion refused-meta has no such class %d / criterion refused-meta is opaque %d / " "upstream no data-parent unavailable %d\n", ReplStubRefusedNoStub, ReplStubRefusedNoClass, ReplStubRefusedOpaque, ReplStubRefusedParent)
if ReplStubRefused > 0 or ReplStubNoStub > 0:
stdio.printf(" 说明:被拒类的字段访问会报『类未注册/属性访问失败』" "(不按错偏移静默访问);方法调用不受影响。\n")
stdio.printf(" Note: field access on refused classes reports class not registered/attribute access failed " "(it does not silently access at a wrong offset); method calls are unaffected.\n")
if ReplStubRefusedNoStub > 0:
stdio.printf(" 其中『数据缺失』的 %d 个类只是没读到模块布局元数据(本会话临时目录 %s " "缺这些 {sha1}.meta):批处理才会落盘 meta(REPL 分支在 Phase1 之前" "返回,故 --repl 自身不生成存根)。修法:用同一个工程跑一次批处理" "(TransPyV 目录:.\\tpv_build\\output\\TransPyV.exe --project " ".\\project.vpj;includes 有改动时加 --rebuild-includes),随后 " "--project .\\project.vpj --repl 复用其临时目录即可\n", ReplStubRefusedNoStub, ReplStubTempDir)
stdio.printf(" Of these, the %d classes with data missing simply failed to read the module layout metadata (the session temp directory %s " "is missing these {sha1}.meta): only batch processing writes meta to disk (the REPL branch runs before Phase1 " "and returns, so --repl itself does not generate stubs). Fix: run batch processing once in the same project " "(TransPyV directory: .\\tpv_build\\output\\TransPyV.exe --project " ".\\project.vpj; add --rebuild-includes when includes changed), then " "reuse its temp directory with --project .\\project.vpj --repl\n", ReplStubRefusedNoStub, ReplStubTempDir)
if ReplStubRefusedNoClass + ReplStubRefusedOpaque > 0:
stdio.printf(" 其中『判据拒绝』的 %d 个类:数据在但不可信(存根里没有该类的字段数、" "或其声明为 opaque),按 M4.2 一律不放行——请确认该类是否本应按结构体" "登记:应按结构体登记而存根里查不到 ⇒ 存根陈旧/不完整(重建 includes " "存根)\n", ReplStubRefusedNoClass + ReplStubRefusedOpaque)
stdio.printf(" Of these, the %d classes with criterion refused: data exists but is untrusted (the stub has no field count for this class, " "or it is declared opaque); per M4.2 none are allowed through -- please confirm whether this class should have been registered as a struct " "in the first place: if it should be registered as a struct but is not found in the stub => the stub is stale/incomplete (rebuild includes " "stubs)\n", ReplStubRefusedNoClass + ReplStubRefusedOpaque)
return ReplStubOk
+10 -10
View File
@@ -72,7 +72,7 @@ def _AppendDepsToWorklist(worklist: bytes, wl_len: sizet, deps_str: str, process
worklist[cur_len] = '\0'
else:
stdlib.free(dmod)
VLogger.error("依赖 worklist 溢出", "StubMerger")
VLogger.error("dependency worklist overflow", "StubMerger")
return -1
stdlib.free(dmod)
return int(cur_len)
@@ -83,7 +83,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
"""Build the reachable SHA1 set by on-demand dependency-graph scanning."""
if source_dir is None or temp_dir is None or reachable_set is None: return -1
if includes_dirs is None:
VLogger.error("includes_dirs 缺失,无法按需解析依赖图", "Reachable")
VLogger.error("includes_dirs is missing; cannot resolve the dependency graph on demand", "Reachable")
return -1
SRC_BUF_SIZE_R: sizet = 1048576
@@ -96,7 +96,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
# 1. App scan (skipped when app_deps is non-empty; use the caller-provided initial queue directly)
if app_deps is None or app_deps[0] == '\0':
VLogger.info("App 扫描:解析 source_dir 的 import 依赖", "Reachable")
VLogger.info("App scan: resolving import dependencies of source_dir", "Reachable")
scan_res_r: IncludesScanner.ScanResult* = IncludesScanner.scan_includes(mb, source_dir)
if scan_res_r is not None:
es_r: sizet = IncludesScanner.FileEntry.__sizeof__()
@@ -176,7 +176,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
string.strcpy(worklist, app_deps)
wl_len = ad_len
else:
VLogger.error("app_deps 过长,无法构建可达集合", "StubMerger")
VLogger.error("app_deps is too long; cannot build the reachable set", "StubMerger")
stdlib.free(worklist)
return -1
@@ -212,7 +212,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
if tb_inc is not None: stdlib.free(tb_inc)
if tb_found != 0:
stdlib.free(worklist)
VLogger.error(f"--traceback: 在 includes 目录中找不到 traceback.vp,无法编译并链接 Install()(请确认 project.vpj 的 includes 包含仓库 includes 目录;已扫描: {includes_dirs})", "Traceback")
VLogger.error(f"--traceback: traceback.vp not found in the includes dirs; cannot compile and link Install() (make sure the includes of project.vpj contains the repository includes directory; scanned: {includes_dirs})", "Traceback")
return -1
tb_wl: int = _AppendDepsToWorklist(worklist, wl_len, "traceback", None)
if tb_wl < 0:
@@ -264,7 +264,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
proc_len = proc_len + 1
processed[proc_len] = '\0'
else:
VLogger.error("依赖 processed 溢出", "StubMerger")
VLogger.error("dependency processed overflow", "StubMerger")
stdlib.free(mod_buf)
continue
@@ -383,7 +383,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
# parse_tokens keeps the error detail (line/col/message) only in the global channel, so print the unified
# parse traceback before the one-line log; without it a reachable-includes syntax error is undiagnosable.
GenApi.dump_parse_traceback(abs_path)
VLogger.error(f"可达 includes 解析失败: {abs_path}", "Reachable")
VLogger.error(f"reachable includes parse failed: {abs_path}", "Reachable")
stdlib.free(abs_path)
stdlib.free(rel_path)
stdlib.free(inc_dir)
@@ -421,7 +421,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
GenApi.reset_visible_structs(mb, 0)
ret_r2: int = tr_r2.translate(tree_r)
if ret_r2 != 0:
VLogger.error(f"import 依赖扫描失败(可达 includes): {abs_path}", "Reachable")
VLogger.error(f"import dependency scan failed (reachable includes): {abs_path}", "Reachable")
stdlib.free(abs_path)
stdlib.free(rel_path)
stdlib.free(inc_dir)
@@ -471,7 +471,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
mb.reset_to(scan_mark_r)
return -1
wl_len = sizet(ret_w)
else: VLogger.debug(f"无依赖: {rel_path}", "Reachable")
else: VLogger.debug(f"no dependencies: {rel_path}", "Reachable")
# Free the Translator's C malloc resources and reclaim this file's AST
if tr_r2._global_names is not None: stdlib.free(tr_r2._global_names)
@@ -506,7 +506,7 @@ def LoadFullIR(temp_dir: str, sha1: str, out_buf: bytes, out_size: sizet) -> siz
if f.closed: return 0
if f.size() >= out_size:
f.close()
VLogger.error("full.ll 超过 IR 缓冲上限", "StubMerger")
VLogger.error("full.ll exceeds the IR buffer limit", "StubMerger")
return 0
rd: int64 = f.read_all(out_buf, out_size)
f.close()
+9 -9
View File
@@ -33,29 +33,29 @@ import lib.Stub.StubMerger as StubMerger
def WriteModuleMeta(mod: mlirlite.LLVMModule*, temp_dir: str, td_len: sizet, sha1: str) -> int:
"""Write the module's func defines, struct layouts and vtables to {sha1}.meta."""
if mod is None or temp_dir is None or sha1 is None:
VLogger.error("meta 写出:参数为空", "Meta")
VLogger.error("meta write: null argument", "Meta")
return 1
mpath: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "meta")
if mpath is None:
VLogger.error("meta 写出:路径构造失败", "Meta")
VLogger.error("meta write: path construction failed", "Meta")
return 1
mf: fileio.File = fileio.File(mpath, fileio.MODE.W)
if mf.closed:
VLogger.error(f"meta 写出:无法打开 {mpath}", "Meta")
VLogger.error(f"meta write: cannot open {mpath}", "Meta")
return 1
cur: mlirlite.Function* = mod.FuncHead
steps: sizet = 0
while cur is not None:
steps += 1
if steps > 100000:
VLogger.error("meta 写出:函数链表成环/超限", "Meta")
VLogger.error("meta write: function list has a cycle or exceeded the limit", "Meta")
break
nm: str = mlirlite.function_get_name(cur)
if nm is not None:
nlen: sizet = string.strlen(nm)
line: bytes = stdlib.malloc(nlen + 16)
if line is None:
VLogger.error("meta 写出:行缓冲分配失败", "Meta")
VLogger.error("meta write: line buffer allocation failed", "Meta")
break
mark: str = "DECL"
if mlirlite.function_is_declared(cur) == 0: mark = "DEF"
@@ -69,14 +69,14 @@ def WriteModuleMeta(mod: mlirlite.LLVMModule*, temp_dir: str, td_len: sizet, sha
while nt is not None:
nt_steps += 1
if nt_steps > 100000:
VLogger.error("meta 写出:命名类型链表成环/超限", "Meta")
VLogger.error("meta write: named-type list has a cycle or exceeded the limit", "Meta")
break
tn: str = mlirlite.get_struct_name(nt.Ty)
if tn is not None and tn[0] != '\0':
tl: sizet = string.strlen(tn)
lb: bytes = stdlib.malloc(tl + 48)
if lb is None:
VLogger.error("meta 写出:行缓冲分配失败", "Meta")
VLogger.error("meta write: line buffer allocation failed", "Meta")
break
fc: int = mlirlite.get_struct_fcount(nt.Ty)
if fc < 0: viperlib.snprintf(lb, tl + 48, "STRUCT %s OPAQUE\n", tn)
@@ -90,7 +90,7 @@ def WriteModuleMeta(mod: mlirlite.LLVMModule*, temp_dir: str, td_len: sizet, sha
while gv is not None:
gv_steps += 1
if gv_steps > 100000:
VLogger.error("meta 写出:全局变量链表成环/超限", "Meta")
VLogger.error("meta write: global-variable list has a cycle or exceeded the limit", "Meta")
break
gn: str = gv.Name
if gn is not None:
@@ -104,7 +104,7 @@ def WriteModuleMeta(mod: mlirlite.LLVMModule*, temp_dir: str, td_len: sizet, sha
ar: int = mlirlite.get_struct_fcount(gv.Ty)
if ar < 0: ar = 0
lb2: bytes = stdlib.malloc(base_len + 40)
if lb2 is None: VLogger.error("meta 写出:行缓冲分配失败", "Meta")
if lb2 is None: VLogger.error("meta write: line buffer allocation failed", "Meta")
else:
viperlib.snprintf(lb2, base_len + 40, "VTABLE %s SLOTS %d\n", base, ar)
mf.write(lb2, string.strlen(lb2))
+2 -2
View File
@@ -147,7 +147,7 @@ def PopulateSha1MapStore(scan_result: IncludesScanner.ScanResult*) -> int:
p_bad: int = 0
entry_size_p: sizet = IncludesScanner.FileEntry.__sizeof__()
for i in range(scan_result.Count):
if StubMerger._sha1_store_count >= StubMerger.MAX_INCLUDES: VLogger.error("includes SHA1 存储超上限,终止", "StubMerger")
if StubMerger._sha1_store_count >= StubMerger.MAX_INCLUDES: VLogger.error("includes SHA1 store exceeded the limit; aborting", "StubMerger")
ea: uint64 = uint64(scan_result.Entries) + i * entry_size_p
ent: IncludesScanner.FileEntry* = IncludesScanner.FileEntry*(ea)
if ent is None or ent.Sha1 is None or ent.RelPath is None:
@@ -187,7 +187,7 @@ def PopulateSha1MapStore(scan_result: IncludesScanner.ScanResult*) -> int:
string.strncpy(StubMerger._sha1_store_incdir + idx_inc, ent.IncDir, StubMerger.MAX_INC_DIR_LEN - 1)
StubMerger._sha1_store_incdir[idx_inc + StubMerger.MAX_INC_DIR_LEN - 1] = '\0'
StubMerger._sha1_store_count += 1
if p_bad > 0: VLogger.error(f"includes SHA1 存储有 {p_bad} 个条目失败", "StubMerger")
if p_bad > 0: VLogger.error(f"includes SHA1 store has {p_bad} failed entries", "StubMerger")
return StubMerger._sha1_store_count
# AppendToSha1MapStore - append an App module entry to the global SHA1 store (Phase2 use);
# auto-initializes if empty, skips on duplicate SHA1. Returns 0 ok, 1 failed.