From 7a9bc5ae75e06e94d5348aa3b67340ee172ddbe0 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 7 Oct 2026 00:03:58 +0800 Subject: [PATCH] =?UTF-8?q?chore(messages):=20TransPyV=20=E8=BF=90?= =?UTF-8?q?=E8=A1=8C=E6=97=B6=E4=B8=AD=E6=96=87=E5=AD=97=E7=AC=A6=E4=B8=B2?= =?UTF-8?q?=E8=8B=B1=E6=96=87=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 把 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/日志输出已为英文。 --- App/lib/Phase/BuildPipeline.vp | 166 +++++++++--------- App/lib/Phase/Phase1/Phase1Main.vp | 106 ++++++------ App/lib/Phase/Phase1/Phase1Scan.vp | 12 +- App/lib/Phase/Phase2/__init__.vp | 136 +++++++-------- App/lib/Stub/StubGen/Converter.vp | 24 +-- App/lib/Stub/StubGen/VpiReader.vp | 56 +++--- App/lib/Stub/StubMerger/StubMergerBuild.vp | 20 +-- App/lib/Stub/StubMerger/StubMergerIR.vp | 18 +- App/lib/Stub/StubMerger/StubMergerStore.vp | 4 +- App/lib/core/Gen/AssignGenMixin.vp | 192 ++++++++++----------- App/lib/core/Gen/AsyncGenMixin.vp | 14 +- App/lib/core/Gen/Call/CallGenBase.vp | 8 +- App/lib/core/Gen/Call/CallGenCBuiltin.vp | 22 +-- App/lib/core/Gen/Call/CallGenCall.vp | 56 +++--- App/lib/core/Gen/Call/CallGenCtor.vp | 40 ++--- App/lib/core/Gen/Call/CallGenDispatch.vp | 32 ++-- App/lib/core/Gen/Call/CallGenLeafKit.vp | 24 +-- App/lib/core/Gen/Call/CallGenLib.vp | 4 +- App/lib/core/Gen/Call/CallGenMixin.vp | 34 ++-- App/lib/core/Gen/Call/CallGenProp.vp | 2 +- App/lib/core/Gen/Call/CallGenVa.vp | 2 +- App/lib/core/Gen/Class/ClassGenDef.vp | 8 +- App/lib/core/Gen/Class/ClassGenEnum.vp | 38 ++-- App/lib/core/Gen/Class/ClassGenGeneric.vp | 20 +-- App/lib/core/Gen/Class/ClassGenVTable.vp | 28 +-- App/lib/core/Gen/DebugInfoGen.vp | 44 ++--- App/lib/core/Gen/Expr/ExprGenAttr.vp | 20 +-- App/lib/core/Gen/Expr/ExprGenBase.vp | 30 ++-- App/lib/core/Gen/Expr/ExprGenCdef.vp | 10 +- App/lib/core/Gen/Expr/ExprGenConst.vp | 4 +- App/lib/core/Gen/Expr/ExprGenFstr.vp | 10 +- App/lib/core/Gen/Expr/ExprGenMixin.vp | 2 +- App/lib/core/Gen/Expr/ExprGenName.vp | 14 +- App/lib/core/Gen/Expr/ExprGenOps.vp | 18 +- App/lib/core/Gen/Func/FuncGenBase.vp | 4 +- App/lib/core/Gen/Func/FuncGenDef.vp | 32 ++-- App/lib/core/Gen/Func/FuncGenMixin.vp | 10 +- App/lib/core/Gen/GenApi.vp | 2 +- App/lib/core/Gen/ImportsGenMixin.vp | 10 +- App/lib/core/Gen/MatchGenMixin.vp | 88 +++++----- App/lib/core/Gen/Stmt/StmtGenCifMixin.vp | 110 ++++++------ App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp | 14 +- App/lib/core/Gen/Stmt/StmtGenMixin.vp | 4 +- App/lib/core/Gen/StructGenMixin.vp | 32 ++-- App/lib/core/Gen/Translator.vp | 20 +-- App/lib/core/Gen/TranslatorGenMixin.vp | 32 ++-- App/lib/core/Gen/Type/TypeGenCDef.vp | 28 +-- App/lib/core/Gen/Type/TypeGenCType.vp | 6 +- App/lib/core/Gen/Type/TypeGenErr.vp | 6 +- App/lib/core/Gen/Type/TypeGenResolve.vp | 70 ++++---- App/lib/core/Gen/Type/TypeSpec.vp | 2 +- App/lib/core/Gen/VarGenMixin.vp | 82 ++++----- App/lib/core/IncludesScanner.vp | 8 +- App/lib/core/Repl.vp | 192 ++++++++++----------- App/lib/core/VLogger.vp | 16 +- App/lib/core/builtin/ViperBuild.vp | 96 +++++------ App/main.vp | 102 +++++------ 57 files changed, 1092 insertions(+), 1092 deletions(-) diff --git a/App/lib/Phase/BuildPipeline.vp b/App/lib/Phase/BuildPipeline.vp index 677d89c..40c5577 100644 --- a/App/lib/Phase/BuildPipeline.vp +++ b/App/lib/Phase/BuildPipeline.vp @@ -85,7 +85,7 @@ def _append_traceback_dbghelp(linker_flags: str) -> str: need: sizet = string.strlen(linker_flags) + 16 buf: str = _mbuddy.alloc(need) if buf is None: - VLogger.error("--traceback: -ldbghelp 链接参数缓冲分配失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to allocate -ldbghelp linker argument buffer, aborting compilation", "TRACEBACK") return linker_flags viperlib.snprintf(buf, need, "%s -ldbghelp", linker_flags) return buf @@ -105,11 +105,11 @@ def _tb_register_vpcall(path: str) -> int: if _tb_vpcall_buf is None: _tb_vpcall_buf = stdlib.malloc(sizet(TB_VPCALL_MAX) * 8) if _tb_vpcall_buf is None: - VLogger.error("--traceback: .vpcall 路径表分配失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to allocate .vpcall path table, aborting compilation", "TRACEBACK") return 1 _tb_vpcall_n = 0 if _tb_vpcall_n >= TB_VPCALL_MAX: - VLogger.error("--traceback: .vpcall 路径表溢出(模块数超上限),终止编译", "TRACEBACK") + VLogger.error("--traceback: .vpcall path table overflow (module count exceeds limit), aborting compilation", "TRACEBACK") return 1 slot: str* = (str*)(uint64(_tb_vpcall_buf) + sizet(_tb_vpcall_n) * 8) slot[0] = path @@ -122,11 +122,11 @@ def WriteCallSidecar(temp_dir: str, sha1: str, text: str) -> int: if temp_dir is None or sha1 is None or text is None: return 0 vpath: str = StubMergerCollect._sliced_path(temp_dir, string.strlen(temp_dir), sha1, "vpcall") if vpath is None: - VLogger.error(f"--traceback: .vpcall 路径构造失败(sha1={sha1}),终止编译", "TRACEBACK") + VLogger.error(f"--traceback: failed to build .vpcall path (sha1={sha1}), aborting compilation", "TRACEBACK") return 1 vf: fileio.File* = fileio.File(vpath, fileio.MODE.W) if vf.closed: - VLogger.error(f"--traceback: 写出 .vpcall 失败(无法打开 {vpath}),终止编译", "TRACEBACK") + VLogger.error(f"--traceback: failed to write .vpcall (cannot open {vpath}), aborting compilation", "TRACEBACK") stdlib.free(vpath) return 1 vf.write(text, string.strlen(text)) @@ -154,7 +154,7 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy*, file_path: str, sha1_val: str, c # read_all's capacity includes the terminator (reads cap-1 bytes max) and silently # truncates longer files; reject by size first, else parsing gets confusing syntax errors. if f.size() >= SRC_BUF_SIZE: - VLogger.error(f"源文件超过 {SRC_BUF_SIZE} 字节上限, 拒绝读取: {file_path}", "fileio") + VLogger.error(f"source file exceeds {SRC_BUF_SIZE} byte limit, refusing to read: {file_path}", "fileio") f.close() return None src_buf: bytes = stdlib.malloc(SRC_BUF_SIZE) @@ -179,7 +179,7 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy*, file_path: str, sha1_val: str, c GenApi.dump_parse_traceback(file_path) err_line: int = ast.get_parse_err_line() err_col: int = ast.get_parse_err_col() - VLogger.error(f"解析失败: {file_path} (line {err_line} col {err_col})", "PARSE") + VLogger.error(f"parse failed: {file_path} (line {err_line} col {err_col})", "PARSE") return None # Generate the .vpi stub from the AST before tr.translate (same as Phase1); it lets # other modules query function signatures and CTypedef definitions. @@ -247,7 +247,7 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy*, file_path: str, sha1_val: str, c if gen is not None: gen.ExprGenCls.extract_module_docstrings(tree, sha1_val) ret: int = tr.translate(tree) if ret != 0: - VLogger.error(f"文件翻译失败: {file_path}", "Translate") + VLogger.error(f"file translation failed: {file_path}", "Translate") return None # --traceback: for includes/traceback.vp, inject the startup Install() ctor into its IR. # The injector lives in the Gen layer, so no new cross-module mlirlite dependency. @@ -385,11 +385,11 @@ def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: s else: mo_rc: int = _run_cmd_wait(cmd_mo) if mo_rc != 0: - VLogger.error(f"mlir-opt 失败 (module={module_name}, exit={mo_rc}, cmd={cmd_mo})", "MLIR") + VLogger.error(f"mlir-opt failed (module={module_name}, exit={mo_rc}, cmd={cmd_mo})", "MLIR") return 1 mt_rc: int = _run_cmd_wait(cmd_mt) if mt_rc != 0: - VLogger.error(f"mlir-translate 失败 (module={module_name}, exit={mt_rc}, cmd={cmd_mt})", "MLIR") + VLogger.error(f"mlir-translate failed (module={module_name}, exit={mt_rc}, cmd={cmd_mt})", "MLIR") return 1 compile_input = ll_local_path @@ -422,7 +422,7 @@ def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: s viperlib.snprintf(opt_cmd, opt_cmd_len, "opt -passes=forceattrs,asan -force-attribute=sanitize_address -asan-globals=false -o %s %s", asan_path, compile_input) opt_ret: int = stdlib.system(opt_cmd) if opt_ret != 0: - VLogger.error(f"opt ASan 插桩失败 (module={module_name})", "ASAN") + VLogger.error(f"opt ASan instrumentation failed (module={module_name})", "ASAN") return 1 compile_input = asan_path @@ -437,7 +437,7 @@ def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: s # inherits the console. On failure, log module sha1 + exit code + full command. sys_ret: int = _run_cmd_wait(cmd) if sys_ret != 0: - VLogger.error(f"编译失败 (module={module_name}, exit={sys_ret}, cmd={cmd})", "LLC") + VLogger.error(f"compilation failed (module={module_name}, exit={sys_ret}, cmd={cmd})", "LLC") return 1 return 0 @@ -545,7 +545,7 @@ def _phase2_write_cmd(cmd: str) -> None: if _phase2_cmd_path is None or cmd is None: return f: fileio.File* = fileio.File(_phase2_cmd_path, fileio.MODE.A) if f.closed: - VLogger.error("phase2command: bat 打开失败", "phase2cmd") + VLogger.error("phase2command: failed to open bat", "phase2cmd") return if _phase2_bat_init == 0: _phase2_bat_init = 1 @@ -584,7 +584,7 @@ def _run_cmd_wait(cmd: str) -> int: # it). Use warning, not error (error would sys.exit in a worker thread). if ok == 0: cp_err: uint32 = w32.win32base.GetLastError() - VLogger.warning(f"CreateProcessA 失败 (GetLastError={cp_err}) 外部命令未启动: cmd={cmd}", "LLC") + VLogger.warning(f"CreateProcessA failed (GetLastError={cp_err}) external command not started: cmd={cmd}", "LLC") stdlib.free(cmd_line) if ok == 0: return -1 win32sync.WaitForSingleObject(pi.hProcess, w32.win32base.INFINITE) @@ -644,14 +644,14 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int: if tsk_p.MlirTranslateCmd is not None: _phase2_write_cmd(tsk_p.MlirTranslateCmd) if tsk_p.OptCmd is not None: _phase2_write_cmd(tsk_p.OptCmd) if tsk_p.LlcCmd is not None: _phase2_write_cmd(tsk_p.LlcCmd) - VLogger.info(f"phase2command 模式:{task_count} 条 llc 命令已写入 {_phase2_cmd_path}", "phase2cmd") + VLogger.info(f"phase2command mode: {task_count} llc commands written to {_phase2_cmd_path}", "phase2cmd") return 0 if max_threads <= 0: max_threads = 1 # Thread-handle array: list[str] (str=bytes=i8*, explicit elem_size=8) stores handles; # list[t.CPtr] append crashes reading page zero. Grab the handle right after start(). handles: list[str]* = list[str](_mbuddy, 8) if handles is None: - VLogger.error("run_llc_parallel: 线程句柄数组分配失败", "PhaseB") + VLogger.error("run_llc_parallel: failed to allocate thread handle array", "PhaseB") return 1 slot_size: sizet = LlcTask.__sizeof__() ret: int = 0 @@ -670,7 +670,7 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int: for j in range(batch_n): h_j: t.CPtr = t.CPtr(handles.get(batch_start + j)) wr: uint32 = win32sync.WaitForSingleObject(h_j, 600000) - if wr != 0: VLogger.error("llc 线程 join 超时/失败(600 秒未完成)", "PhaseB") + if wr != 0: VLogger.error("llc thread join timeout/failure (not finished within 600 seconds)", "PhaseB") w32.win32base.CloseHandle(h_j) # check this batch's results for j in range(batch_n): @@ -679,21 +679,21 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int: # Failure: use FailStage to pinpoint the step and print that step's command. # Previously everything printed the LlcCmd as "llc failed", misdirecting MLIR failures. st: int = tsk2.FailStage - stage_name: str = "未知阶段(worker 未跑完)" + stage_name: str = "unknown stage (worker did not finish)" stage_cmd: bytes = tsk2.LlcCmd if st == LLC_STAGE_MLIR_OPT: - stage_name = "mlir-opt 校验" + stage_name = "mlir-opt validation" stage_cmd = tsk2.MlirOptCmd elif st == LLC_STAGE_MLIR_TRANSLATE: - stage_name = "mlir-translate 降级" + stage_name = "mlir-translate lowering" stage_cmd = tsk2.MlirTranslateCmd elif st == LLC_STAGE_ASAN_OPT: - stage_name = "opt ASan 插桩" + stage_name = "opt ASan instrumentation" stage_cmd = tsk2.OptCmd elif st == LLC_STAGE_LLC: - stage_name = "llc 编译" + stage_name = "llc compile" stage_cmd = tsk2.LlcCmd - VLogger.error(f"{stage_name}失败: {(tsk2.ModuleSha1 if tsk2.ModuleSha1 is not None else "?")} (exit={tsk2.ExitCode} cmd={(stage_cmd if stage_cmd is not None else "?")})", "LLC") + VLogger.error(f"{stage_name} failed: {(tsk2.ModuleSha1 if tsk2.ModuleSha1 is not None else "?")} (exit={tsk2.ExitCode} cmd={(stage_cmd if stage_cmd is not None else "?")})", "LLC") ret = 1 return ret @@ -702,20 +702,20 @@ def _CollectObjFilesImpl(base_dir: str, bd_len: sizet, out_buf: bytes, out_pos: """Recursively scan base_dir, collect .obj paths into out_buf, return the new out_pos.""" find_data: w32.win32file.WIN32_FIND_DATAA* = _mbuddy.alloc(w32.win32file.WIN32_FIND_DATAA.__sizeof__()) if find_data is None: - VLogger.warning("_CollectObjFilesImpl 分配 find_data 失败,少收集 .obj", "collect") + VLogger.warning("_CollectObjFilesImpl failed to allocate find_data, fewer .obj collected", "collect") return out_pos string.memset(find_data, 0, w32.win32file.WIN32_FIND_DATAA.__sizeof__()) pattern: bytes = _mbuddy.alloc(bd_len + 8) if pattern is None: - VLogger.warning("_CollectObjFilesImpl 分配 pattern 失败,少收集 .obj", "collect") + VLogger.warning("_CollectObjFilesImpl failed to allocate pattern, fewer .obj collected", "collect") return out_pos viperlib.snprintf(pattern, bd_len + 8, "%s/*", base_dir) handle: w32.win32base.HANDLE = w32.win32file.FindFirstFileA(pattern, find_data) _mbuddy.free(pattern) if handle == w32.win32base.INVALID_HANDLE_VALUE: - VLogger.warning("_CollectObjFilesImpl 无法打开目录,少收集 .obj", "collect") + VLogger.warning("_CollectObjFilesImpl cannot open directory, fewer .obj collected", "collect") return out_pos while True: @@ -774,10 +774,10 @@ def _append_host_export_implib(linker_flags: str, implib_path: str) -> str: extra: sizet = string.strlen(" -Wl,--out-implib=") + string.strlen(implib_path) + 1 buf: str = _mbuddy.alloc(string.strlen(linker_flags) + extra) if buf is None: - VLogger.warning("宿主导出:import lib 参数缓冲分配失败(片段将无法导入宿主符号)", "link") + VLogger.warning("host export: failed to allocate import lib argument buffer (fragments cannot import host symbols)", "link") return linker_flags viperlib.snprintf(buf, string.strlen(linker_flags) + extra, "%s -Wl,--out-implib=%s", linker_flags, implib_path) - VLogger.info(f"宿主导出:产出 import lib {implib_path}", "link") + VLogger.info(f"host export: produced import lib {implib_path}", "link") return buf @@ -808,8 +808,8 @@ def link_obj_to_exe(output_dir: str, module_name: str, linker_cmd: str, linker_f extra_len: sizet = 0 if includes_binary_dir is not None: extra_len = collect_obj_files(includes_binary_dir, extra_objs, EXTRA_BUF_SIZE) - if extra_len > 0: VLogger.info(f"附加 {extra_len} 字节的 includes.binary .obj 文件", "link") - else: VLogger.warning(f"includes.binary 无 .obj 文件: {includes_binary_dir}", "link") + if extra_len > 0: VLogger.info(f"appended {extra_len} bytes of includes.binary .obj files", "link") + else: VLogger.warning(f"includes.binary has no .obj files: {includes_binary_dir}", "link") # Command: clang++ {obj_path} extra_objs [libs] -o {...}/{linker_output} linker_flags. Objects # and explicit libs must precede -l flags. The ASan runtime is declared in project.vpj, not hardcoded. @@ -846,15 +846,15 @@ def link_obj_to_exe(output_dir: str, module_name: str, linker_cmd: str, linker_f result: subprocess.CompletedProcess* = subprocess.run(cmd, True, True) if result is None: - VLogger.error("subprocess.run 返回 None", "link") + VLogger.error("subprocess.run returned None", "link") return 1 if result.returncode != 0: - VLogger.error(f"链接失败,返回码: {result.returncode}", "link") - VLogger.error(f"命令: {cmd}", "link") + VLogger.error(f"link failed, return code: {result.returncode}", "link") + VLogger.error(f"command: {cmd}", "link") # Show linker error output. # Note: subprocess merges stderr into stdout on Windows, so result.stderr is always None. if result.stdout is not None: VLogger.error(result.stdout, "link") - else: VLogger.error("无输出捕获", "link") + else: VLogger.error("no output captured", "link") if result.stderr is not None: VLogger.error(result.stderr, "link") return 1 return 0 @@ -879,12 +879,12 @@ def asm_to_obj(asm_path: str, sha1_val: str, output_dir: str, triple: str) -> in result: subprocess.CompletedProcess* = subprocess.run(cmd, True, True) if result is None: - VLogger.error("llvm-mc subprocess.run 返回 None", "asm") + VLogger.error("llvm-mc subprocess.run returned None", "asm") return 1 if result.returncode != 0: if result.stdout is not None: stdio.printf("%s\n", result.stdout) if result.stderr is not None: stdio.printf("%s\n", result.stderr) - VLogger.error(f"llvm-mc 汇编失败,返回码: {result.returncode}, 命令: {cmd}", "asm") + VLogger.error(f"llvm-mc assembly failed, return code: {result.returncode}, command: {cmd}", "asm") return 1 return 0 @@ -896,7 +896,7 @@ def compile_module_to_obj(ir_buf: bytes, ir_len: sizet, temp_dir: str, output_di # Step 1: write the .ll file ret: int = write_ir_to_file(ir_buf, ir_len, temp_dir, module_name) if ret != 0: - VLogger.error(f"写 .ll 失败: {module_name}", "compile") + VLogger.error(f"failed to write .ll: {module_name}", "compile") return 1 # Step 2: build the sliced .ll path and compile -> .obj @@ -905,7 +905,7 @@ def compile_module_to_obj(ir_buf: bytes, ir_len: sizet, temp_dir: str, output_di ret = compile_ll_to_obj(ir_path, output_dir, module_name, cc_cmd, cc_flags) if ret != 0: - VLogger.error(f"llc 编译失败: {module_name}", "compile") + VLogger.error(f"llc compilation failed: {module_name}", "compile") return 1 return 0 @@ -1008,15 +1008,15 @@ def link_objs_to_exe(obj_paths: str, obj_paths_len: sizet, linker_cmd: str, link return 0 result: subprocess.CompletedProcess* = subprocess.run(cmd, True, True) if result is None: - VLogger.error("subprocess.run 返回 None", "link") + VLogger.error("subprocess.run returned None", "link") return 1 if result.returncode != 0: # First print clang++'s full error output (incl. undefined reference) with stdio.printf; # it must precede VLogger.error, which calls sys.exit(1) and terminates the process. - if result.stdout is not None: stdio.printf("=== clang++ 链接错误输出 ===\n%s\n", result.stdout) + if result.stdout is not None: stdio.printf("=== clang++ link error output ===\n%s\n", result.stdout) if result.stderr is not None: stdio.printf("=== clang++ stderr ===\n%s\n", result.stderr) - VLogger.error(f"链接失败,返回码: {result.returncode}, 命令: {cmd}", "link") + VLogger.error(f"link failed, return code: {result.returncode}, command: {cmd}", "link") return 1 return 0 @@ -1347,7 +1347,7 @@ def _tb_emit_row(mb: memhub.MemBuddy*, d: TbDump*, addr: uint64, path: str, line ncap: int = d.RowCap * 2 nb: bytes = _tb_grow_rec(mb, d.RowBuf, d.RowCap, TB_ROW_SIZE, ncap) if nb is None: - VLogger.error("--traceback: DWARF 行记录表扩容失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to grow DWARF line record table, aborting compilation", "TRACEBACK") return 1 d.RowBuf = nb d.RowCap = ncap @@ -1369,7 +1369,7 @@ def _tb_emit_func(mb: memhub.MemBuddy*, d: TbDump*, low: uint64, high: uint64, n ncap: int = d.FuncCap * 2 nb: bytes = _tb_grow_rec(mb, d.FuncBuf, d.FuncCap, TB_FUNC_SIZE, ncap) if nb is None: - VLogger.error("--traceback: DWARF 子程序表扩容失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to grow DWARF subprogram table, aborting compilation", "TRACEBACK") return 1 d.FuncBuf = nb d.FuncCap = ncap @@ -1478,7 +1478,7 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump*: files: bytes = mb.alloc(sizet(TB_FILE_CAP) * TB_FILE_SIZE) linebuf: bytes = mb.alloc(LINE_CAP) if d.RowBuf is None or d.FuncBuf is None or dirs is None or files is None or linebuf is None: - VLogger.error("--traceback: dwarfdump 解析缓冲分配失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to allocate dwarfdump parse buffer, aborting compilation", "TRACEBACK") return None in_line: int = 0 @@ -1778,7 +1778,7 @@ def _tb_cp_add_cr(mb: memhub.MemBuddy*, cp: TbCallParse*, caller: str, callee: s ncap: int = cp.CrCap * 2 nb: bytes = _tb_grow_rec(mb, cp.Cr, cp.CrCap, TB_CR_SIZE, ncap) if nb is None: - VLogger.error("--traceback: 调用记录表扩容失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to grow call record table, aborting compilation", "TRACEBACK") return 1 cp.Cr = nb cp.CrCap = ncap @@ -1797,7 +1797,7 @@ def _tb_cp_add_fr(mb: memhub.MemBuddy*, cp: TbCallParse*, sym: str, file: str, d ncap: int = cp.FrCap * 2 nb: bytes = _tb_grow_rec(mb, cp.Fr, cp.FrCap, TB_FR_SIZE, ncap) if nb is None: - VLogger.error("--traceback: 函数记录表扩容失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to grow function record table, aborting compilation", "TRACEBACK") return 1 cp.Fr = nb cp.FrCap = ncap @@ -1877,7 +1877,7 @@ def _tb_parse_c_line(mb: memhub.MemBuddy*, s: str, a: sizet, b: sizet, cp: TbCal def _tb_parse_vpcall_file(mb: memhub.MemBuddy*, path: str, cp: TbCallParse*) -> int: whole: str = _tb_read_whole(mb, path) if whole is None: - VLogger.error(f"--traceback: 读取 .vpcall 失败:{path},终止编译", "TRACEBACK") + VLogger.error(f"--traceback: failed to read .vpcall: {path}, aborting compilation", "TRACEBACK") return 1 n: sizet = string.strlen(whole) pos: sizet = 0 @@ -1912,7 +1912,7 @@ def _tb_build_groups(mb: memhub.MemBuddy*, cp: TbCallParse*) -> int: cp.GrpCap = _tb_next_pow2(cp.CrN * 2 + 16) cp.Grp = mb.alloc(sizet(cp.GrpCap) * TB_GRP_SIZE) if cp.Grp is None: - VLogger.error("--traceback: 调用点分组表分配失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to allocate call-site group table, aborting compilation", "TRACEBACK") return 1 string.memset(cp.Grp, 0, sizet(cp.GrpCap) * TB_GRP_SIZE) for i in range(cp.CrN): @@ -1921,7 +1921,7 @@ def _tb_build_groups(mb: memhub.MemBuddy*, cp: TbCallParse*) -> int: callee: str = rawptr(_tb_rd_u64(cp.Cr, off + TB_CR_OFF_CALLEE)) slot: int = _tb_grp_get(cp.Grp, cp.GrpCap, caller, callee, 1) if slot < 0: - VLogger.error("--traceback: 调用点分组哈希表溢出,终止编译", "TRACEBACK") + VLogger.error("--traceback: call-site group hash table overflow, aborting compilation", "TRACEBACK") return 1 goff: sizet = sizet(slot) * TB_GRP_SIZE tailv: uint64 = uint64(_tb_rd_u32(cp.Grp, goff + TB_GRP_OFF_TAIL)) @@ -1981,18 +1981,18 @@ def _tb_run_objdump(mb: memhub.MemBuddy*, exe_path: str) -> str: cl: sizet = string.strlen(exe_path) + 64 cmd: bytes = mb.alloc(cl) if cmd is None: - VLogger.error("--traceback: objdump 命令缓冲分配失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to allocate objdump command buffer, aborting compilation", "TRACEBACK") return None viperlib.snprintf(cmd, cl, "llvm-objdump -d \"%s\"", exe_path) res: subprocess.CompletedProcess* = subprocess.run(cmd, True, True) if res is None or res.returncode != 0: rc: int = -1 if res is not None: rc = res.returncode - VLogger.error(f"--traceback: 调用 llvm-objdump 失败(返回码 {rc};请确认 PATH 内含 LLVM 工具),终止编译", "TRACEBACK") + VLogger.error(f"--traceback: failed to run llvm-objdump (return code {rc}; ensure LLVM tools are in PATH), aborting compilation", "TRACEBACK") return None dump: str = res.stdout if dump is None: - VLogger.error("--traceback: llvm-objdump 无输出,终止编译", "TRACEBACK") + VLogger.error("--traceback: llvm-objdump produced no output, aborting compilation", "TRACEBACK") return None return dump @@ -2087,16 +2087,16 @@ def _tb_scan_objdump(mb: memhub.MemBuddy*, dump: str, img_lo: uint64, d: TbDump* def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: """--traceback: export .stackmap after a successful link. 0 = ok.""" if mb is None or exe_path is None: - VLogger.error("--traceback: WriteStackMap 参数为空,终止编译", "TRACEBACK") + VLogger.error("--traceback: WriteStackMap argument is null, aborting compilation", "TRACEBACK") return 1 lay: TbPeLayout* = _tb_read_pe_layout(mb, exe_path) if lay is None or lay.Ok == 0: - VLogger.error(f"--traceback: 只支持 Windows PE 产物,但 {exe_path} 不是有效 PE(这是 --traceback 的要求)", "TRACEBACK") + VLogger.error(f"--traceback: only Windows PE output is supported, but {exe_path} is not a valid PE (required by --traceback)", "TRACEBACK") return 1 size_of_image: uint64 = lay.SizeOfImage if size_of_image == 0: - VLogger.error(f"--traceback: 读到的 PE.SizeOfImage 非正({size_of_image}),无法界定 RVA 域(这是 --traceback 的要求)", "TRACEBACK") + VLogger.error(f"--traceback: read PE.SizeOfImage is not positive ({size_of_image}), cannot bound RVA range (required by --traceback)", "TRACEBACK") return 1 img_lo: uint64 = lay.ImageBase img_hi: uint64 = lay.ImageBase + size_of_image @@ -2106,18 +2106,18 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: cmd_len: sizet = string.strlen(exe_path) + 64 cmd: bytes = mb.alloc(cmd_len) if cmd is None: - VLogger.error("--traceback: dwarfdump 命令缓冲分配失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to allocate dwarfdump command buffer, aborting compilation", "TRACEBACK") return 1 viperlib.snprintf(cmd, cmd_len, "llvm-dwarfdump --debug-line --debug-info \"%s\"", exe_path) res: subprocess.CompletedProcess* = subprocess.run(cmd, True, True) if res is None or res.returncode != 0: rc: int = -1 if res is not None: rc = res.returncode - VLogger.error(f"--traceback: 调用 llvm-dwarfdump 失败(返回码 {rc};请确认 PATH 内含 LLVM 工具),终止编译", "TRACEBACK") + VLogger.error(f"--traceback: failed to run llvm-dwarfdump (return code {rc}; ensure LLVM tools are in PATH), aborting compilation", "TRACEBACK") return 1 dump: str = res.stdout if dump is None: - VLogger.error("--traceback: llvm-dwarfdump 无输出,终止编译", "TRACEBACK") + VLogger.error("--traceback: llvm-dwarfdump produced no output, aborting compilation", "TRACEBACK") return 1 d: TbDump* = _tb_parse_dump(mb, dump) @@ -2128,7 +2128,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: if _tb_vpcall_n > 0: cp: TbCallParse* = _tb_cp_init(mb) if cp is None: - VLogger.error("--traceback: 调用点解析状态分配失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to allocate call-site parse state, aborting compilation", "TRACEBACK") return 1 if _tb_load_vpcalls(mb, cp) != 0: return 1 if _tb_build_groups(mb, cp) != 0: return 1 @@ -2137,12 +2137,12 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: our_before: int = d.RowCount if _tb_scan_objdump(mb, odump, img_lo, d, cp) != 0: return 1 our_added: int = d.RowCount - our_before - if our_added > 0: VLogger.success(f"--traceback: 从 {_tb_vpcall_n} 个 .vpcall 生成 {our_added} 条我方调用点记录(F={cp.FrN} 函数, C={cp.CrN} 调用)", "TRACEBACK") - else: VLogger.warning(f"--traceback: 读到 {_tb_vpcall_n} 个 .vpcall(F={cp.FrN}, C={cp.CrN})但未匹配到任何 objdump 调用点——我方帧行号仍缺,退化到 DWARF", "TRACEBACK") - else: VLogger.warning("--traceback: 未登记任何 .vpcall(我方模块无调用点记录),退化到 DWARF 行为", "TRACEBACK") + if our_added > 0: VLogger.success(f"--traceback: from {_tb_vpcall_n} .vpcall files generated {our_added} own call-site records (F={cp.FrN} functions, C={cp.CrN} calls)", "TRACEBACK") + else: VLogger.warning(f"--traceback: read {_tb_vpcall_n} .vpcall files (F={cp.FrN}, C={cp.CrN}) but matched no objdump call sites -- own frame line numbers still missing, falling back to DWARF", "TRACEBACK") + else: VLogger.warning("--traceback: no .vpcall registered (own modules have no call-site records), falling back to DWARF behavior", "TRACEBACK") if d.RawRowCount == 0: - VLogger.error(f"--traceback: 未能从 {exe_path} 解析出任何行记录(DWARF .debug_line 为空且无我方 .vpcall 记录,这是 --traceback 的要求)", "TRACEBACK") + VLogger.error(f"--traceback: could not parse any line records from {exe_path} (DWARF .debug_line is empty and there are no own .vpcall records; required by --traceback)", "TRACEBACK") return 1 # ---- 2) rows: normalise to RVA, same rva keeps the largest line ---- @@ -2166,7 +2166,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: i += 1 tmp: bytes = mb.alloc(TB_ROW_SIZE) if tmp is None: - VLogger.error("--traceback: 行记录排序缓冲分配失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to allocate line record sort buffer, aborting compilation", "TRACEBACK") return 1 si2: int = 1 while si2 < kept: @@ -2200,9 +2200,9 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: _tb_wr_u64(d.RowBuf, sizet(uniq) * TB_ROW_SIZE + TB_ROW_OFF_FUNC, bf) uniq += 1 i = j - if dropped_rows > 0: VLogger.warning(f"--traceback: 丢弃 {dropped_rows} 条无法归一化的 DWARF 行记录(地址不在影像 VA 区间,多为 COMDAT 去重副本)", "TRACEBACK") + if dropped_rows > 0: VLogger.warning(f"--traceback: dropped {dropped_rows} DWARF line records that cannot be normalised (address not in image VA range, mostly COMDAT dedup copies)", "TRACEBACK") if uniq == 0: - VLogger.error(f"--traceback: 从 {exe_path} 得到的行记录全部无法归一到运行期 RVA 域,终止编译", "TRACEBACK") + VLogger.error(f"--traceback: all line records from {exe_path} cannot be normalised to runtime RVA range, aborting compilation", "TRACEBACK") return 1 # ---- 3) subprograms: normalise + sort by low_rva ---- @@ -2228,7 +2228,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: fi += 1 ftmp: bytes = mb.alloc(TB_FUNC_SIZE) if ftmp is None: - VLogger.error("--traceback: 子程序排序缓冲分配失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to allocate subprogram sort buffer, aborting compilation", "TRACEBACK") return 1 fj: int = 1 while fj < fkept: @@ -2240,7 +2240,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: fk -= 1 string.memcpy(d.FuncBuf + sizet(fk) * TB_FUNC_SIZE, ftmp, TB_FUNC_SIZE) fj += 1 - if dropped_funcs > 0: VLogger.warning(f"--traceback: 丢弃 {dropped_funcs} 个无法归一化的 DWARF 子程序(low_pc 不在影像 VA 区间)", "TRACEBACK") + if dropped_funcs > 0: VLogger.warning(f"--traceback: dropped {dropped_funcs} DWARF subprograms that cannot be normalised (low_pc not in image VA range)", "TRACEBACK") # ---- 4) string pool: exact upper bound, then intern (offset 0 = sentinel) ---- pool_need: sizet = 1 @@ -2264,12 +2264,12 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: i += 1 p: TbPool* = TbPool() if p is None: - VLogger.error("--traceback: 字符串池对象分配失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to allocate string pool object, aborting compilation", "TRACEBACK") return 1 p.Pool = mb.alloc(pool_need) p.Offs = mb.alloc((sizet(uniq) * 2 + sizet(fkept)) * 8 + 64) if p.Pool is None or p.Offs is None: - VLogger.error("--traceback: 字符串池缓冲分配失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to allocate string pool buffer, aborting compilation", "TRACEBACK") return 1 p.Pool[0] = '\0' p.PoolLen = 1 @@ -2278,7 +2278,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: # file_off / func_off per unique row (u32 each) ro: bytes = mb.alloc(sizet(uniq) * 8 + 8) if ro is None: - VLogger.error("--traceback: 记录偏移缓冲分配失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to allocate record offset buffer, aborting compilation", "TRACEBACK") return 1 for i in range(uniq): pth2: str = rawptr(_tb_rd_u64(d.RowBuf, sizet(i) * TB_ROW_SIZE + TB_ROW_OFF_FILE)) @@ -2301,31 +2301,31 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: while ci < uniq: cv: uint64 = _tb_rd_u64(d.RowBuf, sizet(ci) * TB_ROW_SIZE) if ci > 0 and cv <= prev_rva: - VLogger.error(f"--traceback 自检失败:记录 RVA 非严格升序(第 {ci} 条会破坏运行期二分查找),终止编译", "TRACEBACK") + VLogger.error(f"--traceback self-check failed: record RVAs not strictly ascending (record {ci} would break runtime binary search), aborting compilation", "TRACEBACK") return 1 prev_rva = cv if cv >= size_of_image: outside += 1 if cv >= text_rva and cv < size_of_image: plausible += 1 ci += 1 if outside > 0: - VLogger.error(f"--traceback 自检失败:有 {outside} 条记录的 RVA 落在 [0, SizeOfImage=0x{size_of_image:x}) 之外,终止编译", "TRACEBACK") + VLogger.error(f"--traceback self-check failed: {outside} records have RVA outside [0, SizeOfImage=0x{size_of_image:x}), aborting compilation", "TRACEBACK") return 1 if plausible <= 0: - VLogger.error("--traceback 自检失败:没有任何记录的 RVA 落在运行期可能出现的区间(RVA 口径疑似错误),终止编译", "TRACEBACK") + VLogger.error("--traceback self-check failed: no record RVA falls in the range possible at runtime (RVA basis likely wrong), aborting compilation", "TRACEBACK") return 1 # file_off must be >= 1: offset 0 is the empty-string sentinel and the runtime # rejects a whole map whose record file_off is 0. for ci in range(uniq): fo: uint64 = uint64(_tb_rd_u32(ro, sizet(ci) * 8)) if fo == 0: - VLogger.error("--traceback 自检失败:存在 file_off==0 的记录(空路径,运行期会拒绝该旁文件),终止编译", "TRACEBACK") + VLogger.error("--traceback self-check failed: a record has file_off==0 (empty path; runtime would reject that sidecar file), aborting compilation", "TRACEBACK") return 1 # ---- 6) serialise and write .stackmap ---- total: sizet = 20 + sizet(uniq) * 20 + sizet(p.PoolLen) out: bytes = mb.alloc(total) if out is None: - VLogger.error("--traceback: 旁文件输出缓冲分配失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to allocate sidecar output buffer, aborting compilation", "TRACEBACK") return 1 out[0] = 'T' out[1] = 'P' @@ -2348,16 +2348,16 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: map_len: sizet = string.strlen(exe_path) + 16 map_path: str = mb.alloc(map_len) if map_path is None: - VLogger.error("--traceback: 旁文件路径缓冲分配失败,终止编译", "TRACEBACK") + VLogger.error("--traceback: failed to allocate sidecar path buffer, aborting compilation", "TRACEBACK") return 1 viperlib.snprintf(map_path, map_len, "%s.stackmap", exe_path) mf: fileio.File* = fileio.File(map_path, fileio.MODE.W) if mf.closed: - VLogger.error(f"--traceback: 写出旁文件失败(无法打开 {map_path}),终止编译", "TRACEBACK") + VLogger.error(f"--traceback: failed to write sidecar file (cannot open {map_path}), aborting compilation", "TRACEBACK") return 1 mf.write(out, total) mf.close() - VLogger.success(f"--traceback: 已写出地址→源行旁文件 {map_path}({uniq} 条记录,{total} 字节)", "TRACEBACK") + VLogger.success(f"--traceback: wrote address-to-source-line sidecar {map_path} ({uniq} records, {total} bytes)", "TRACEBACK") return 0 @@ -2374,7 +2374,7 @@ def run_pipeline(ir_buf: bytes, ir_len: sizet, temp_dir: str, output_dir: str, m ret: int = write_ir_to_file(ir_buf, ir_len, temp_dir, module_name) if ret != 0: result.Success = 0 - result.ErrorMsg = "写 .ll 文件失败" + result.ErrorMsg = "failed to write .ll file" return result # Step 2: llc-compile .ll -> .obj. @@ -2382,20 +2382,20 @@ def run_pipeline(ir_buf: bytes, ir_len: sizet, temp_dir: str, output_dir: str, m ir_path: str = build_sliced_path(temp_dir, module_name, "ll") if ir_path is None: result.Success = 0 - result.ErrorMsg = "内存分配失败" + result.ErrorMsg = "memory allocation failed" return result ret = compile_ll_to_obj(ir_path, output_dir, module_name, cc_cmd, cc_flags) if ret != 0: result.Success = 0 - result.ErrorMsg = "llc 编译失败" + result.ErrorMsg = "llc compilation failed" return result # Step 3: clang++ link .obj -> .exe (plus includes.binary prebuilt .obj and static/dynamic libs) ret = link_obj_to_exe(output_dir, module_name, linker_cmd, linker_flags, linker_output, includes_binary_dir, linker_static_libs, linker_dynamic_libs) if ret != 0: result.Success = 0 - result.ErrorMsg = "链接失败" + result.ErrorMsg = "link failed" return result result.Success = 1 diff --git a/App/lib/Phase/Phase1/Phase1Main.vp b/App/lib/Phase/Phase1/Phase1Main.vp index d9025c3..35afa7c 100644 --- a/App/lib/Phase/Phase1/Phase1Main.vp +++ b/App/lib/Phase/Phase1/Phase1Main.vp @@ -247,7 +247,7 @@ def _BuildReachableResult(mb: memhub.MemBuddy*, includes_dir: str) -> IncludesSc def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogger.Logger*) -> int: """Phase1: scan the includes directory and translate/generate stubs on demand""" if includes_dir is None or temp_dir is None: - VLogger.error("includes_dir 或 temp_dir 为空,无法运行 Phase1", "Phase1") + VLogger.error("includes_dir or temp_dir is empty; cannot run Phase1", "Phase1") return 1 # Set the global temp_dir (used for cross-module CDefine lookup) @@ -259,7 +259,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg # Ensure the temp dir exists (build_dir/temp may not exist yet) BuildPipeline.ensure_dir(temp_dir) - log.banner("Phase1: 扫描 includes(按需翻译)") + log.banner("Phase1: scanning includes (on-demand translation)") # Init the AST tables once, before the dependency-graph BFS: if _init_tables first runs # after the BFS file-level mark, reset_to frees the tables and later tokenize crashes. @@ -277,30 +277,30 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg string.memset(reachable_set, 0, StubMerger.MAX_INCLUDES_SHA1 * 17) reachable_count = StubMergerBuild._BuildReachableSha1Set(mb, Config.SourceDir, temp_dir, reachable_set, None, includes_dir) if reachable_count < 0: - VLogger.error("可达集合构建失败(依赖图扫描失败),终止编译", "Phase1") + VLogger.error("failed to build the reachable set (dependency-graph scan failed); aborting compilation", "Phase1") return 1 if reachable_count <= 0: - VLogger.warning("App 无可达 includes 依赖,跳过 Phase1", "Phase1") + VLogger.warning("App has no reachable includes dependencies; skipping Phase1", "Phase1") stdlib.free(reachable_set) reachable_set = None return 0 use_reachable = 1 else: - VLogger.error("reachable_set 分配失败,终止编译", "Phase1") + VLogger.error("failed to allocate reachable_set; aborting compilation", "Phase1") return 1 else: - VLogger.warning("SourceDir 不可用,无法构建依赖图,跳过 Phase1", "Phase1") + VLogger.warning("SourceDir unavailable; cannot build the dependency graph; skipping Phase1", "Phase1") return 0 t_scan1: uint64 = w32.win32base.GetTickCount64() - VLogger.info(f"依赖图扫描总耗时: {t_scan1 - t_scan0} ms(可达 {reachable_count} 个 includes)", "Phase1") + VLogger.info(f"dependency-graph scan total time: {t_scan1 - t_scan0} ms (reachable {reachable_count} includes)", "Phase1") # Build the reachable FileEntry list from the Sha1Store; 1a/1b-pre/1b iterate result # (non-empty incdir = includes). use_reachable filtering is idempotent. result: IncludesScanner.ScanResult* = _BuildReachableResult(mb, includes_dir) if result is None: - VLogger.error("可达 FileEntry 列表构建失败,终止编译", "Phase1") + VLogger.error("failed to build the reachable FileEntry list; aborting compilation", "Phase1") return 1 - VLogger.info(f"可达 includes 条目: {result.Count}", "Phase1") + VLogger.info(f"reachable includes entries: {result.Count}", "Phase1") # After scanning, clear _list/_dict injection cycle edges (e.g. _list<->memhub) so the # graph has none and Phase A converges; deps.txt is rewritten in sync. @@ -332,7 +332,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg # dump_stats, so skip dump_stats when self_check returns 4 (cycle). p1_sc: int = mb.self_check() if p1_sc != 4: mb.dump_stats("phase1-pre") - else: VLogger.info("[取证] self_check=4(free list 成环),跳过 dump_stats 防死循环", "Phase1") + else: VLogger.info("[EVIDENCE] self_check=4 (free list cycle); skipping dump_stats to prevent an infinite loop", "Phase1") p1_mo: int = mb.max_order if p1_mo < 0 or p1_mo > 32: p1_mo = 32 # Clamp: prevents this probe from out-of-bounds reading free_lists if max_order is corrupted @@ -341,8 +341,8 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg p1_base_addr: uint64 = uint64(mb.base) p1_usable_addr: uint64 = uint64(mb.usable) p1_chkbase_addr: uint64 = uint64(mb.chk_base) - VLogger.info(f"[取证] mb={p1_mb_addr} base={p1_base_addr} usable={p1_usable_addr} " f"usable_size={mb.usable_size} max_order={mb.max_order} self_check={p1_sc} " f"detection={mb.detection}", "Phase1") - VLogger.info(f"[取证] chk_base={p1_chkbase_addr} chk_depth={mb.chk_depth} " f"chk_cap={mb.chk_cap} free_lists[clamp={p1_mo}]={p1_fl_head}", "Phase1") + VLogger.info(f"[EVIDENCE] mb={p1_mb_addr} base={p1_base_addr} usable={p1_usable_addr} " f"usable_size={mb.usable_size} max_order={mb.max_order} self_check={p1_sc} " f"detection={mb.detection}", "Phase1") + VLogger.info(f"[EVIDENCE] chk_base={p1_chkbase_addr} chk_depth={mb.chk_depth} " f"chk_cap={mb.chk_cap} free_lists[clamp={p1_mo}]={p1_fl_head}", "Phase1") p1_sz_cn: sizet = sizet(Phase1.MAX_CLASSES * Phase1.CLASS_NAME_LEN) p1_sz_ds: sizet = sizet(Phase1.MAX_CLASSES * Phase1.SHA1_LEN) p1_sz_tp: sizet = sizet(4 * Phase1.MAX_FILE_DEPS) @@ -353,7 +353,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg p1_o_bx: int = mb._order_for_size(p1_sz_bx + 16) p1_fl_cn: uint64 = uint64(mb.free_lists[p1_o_cn]) p1_fl_ds: uint64 = uint64(mb.free_lists[p1_o_ds]) - VLogger.info(f"[取证] order(class_names {p1_sz_cn}B+16)={p1_o_cn} fl={p1_fl_cn} " f"order(def_sha1s {p1_sz_ds}B+16)={p1_o_ds} fl={p1_fl_ds} " f"order(topo {p1_sz_tp}B+16)={p1_o_tp} order(box {p1_sz_bx}B+16)={p1_o_bx} " f"(fl==0 只说明该阶空、仍可由更高阶拆分;若 alloc 失败而 dump_stats 的 free>0 才是元数据损坏铁证," f"任一 order>max_order={mb.max_order} 则是 size 异常)", "Phase1") + VLogger.info(f"[EVIDENCE] order(class_names {p1_sz_cn}B+16)={p1_o_cn} fl={p1_fl_cn} " f"order(def_sha1s {p1_sz_ds}B+16)={p1_o_ds} fl={p1_fl_ds} " f"order(topo {p1_sz_tp}B+16)={p1_o_tp} order(box {p1_sz_bx}B+16)={p1_o_bx} " f"(fl==0 only means that order is empty and can still be split by a higher order; if alloc fails while dump_stats shows free>0 that is the definitive proof of metadata corruption; " f"any order>max_order={mb.max_order} means an abnormal size)", "Phase1") # Pre-scan class inheritance and build the topo order (flat byte arrays avoid str-pointer NULL crashes) class_names_buf: bytes = mb.alloc(Phase1.MAX_CLASSES * Phase1.CLASS_NAME_LEN) @@ -369,9 +369,9 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg # These three flat buffers are Phase1Scan._ScanClassInheritance's contract pre-buffers; it # fails fast on NULL, so report and abort per buffer on allocation failure (never fall back). - if class_names_buf is None: VLogger.error("类继承预扫描扁平缓冲分配失败:class_names_buf 为 NULL,终止编译", "Phase1") - if parent_names_buf is None: VLogger.error("类继承预扫描扁平缓冲分配失败:parent_names_buf 为 NULL,终止编译", "Phase1") - if def_sha1s_buf is None: VLogger.error("类继承预扫描扁平缓冲分配失败:def_sha1s_buf 为 NULL,终止编译", "Phase1") + if class_names_buf is None: VLogger.error("class-inheritance pre-scan flat buffer allocation failed: class_names_buf is NULL; aborting compilation", "Phase1") + if parent_names_buf is None: VLogger.error("class-inheritance pre-scan flat buffer allocation failed: parent_names_buf is NULL; aborting compilation", "Phase1") + if def_sha1s_buf is None: VLogger.error("class-inheritance pre-scan flat buffer allocation failed: def_sha1s_buf is NULL; aborting compilation", "Phase1") string.memset(class_names_buf, 0, Phase1.MAX_CLASSES * Phase1.CLASS_NAME_LEN) string.memset(parent_names_buf, 0, Phase1.MAX_CLASSES * Phase1.CLASS_NAME_LEN) @@ -389,12 +389,12 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg if ret_topo == 0: tc_ptr: t.CPtr = (int*)(topo_count_box) if tc_ptr is not None: topo_count = tc_ptr[0] - VLogger.info(f"拓扑排序: {class_count_scanned} 个类, {topo_count} 个文件按依赖顺序处理", "Phase1") + VLogger.info(f"topological sort: {class_count_scanned} classes, {topo_count} files processed in dependency order", "Phase1") else: - VLogger.error("拓扑排序失败(类继承依赖无法解析),终止编译", "Phase1") + VLogger.error("topological sort failed (class-inheritance dependencies could not be resolved); aborting compilation", "Phase1") return 1 else: - VLogger.warning("类继承预扫描无结果,回退到字母序", "Phase1") + VLogger.warning("class-inheritance pre-scan produced no result; falling back to alphabetical order", "Phase1") topo_count = 0 # ============================================================ @@ -455,7 +455,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg # read_all's capacity includes the terminator (reads at most cap-1 bytes); longer files are truncated if f_r.size() >= Phase1.SRC_BUF_SIZE: - VLogger.error(f"源文件超过 {Phase1.SRC_BUF_SIZE} 字节上限, 拒绝读取: {file_path_r}", "Phase1") + VLogger.error(f"source file exceeds the {Phase1.SRC_BUF_SIZE}-byte limit, refusing to read: {file_path_r}", "Phase1") f_r.close() p1a_fl += 1 continue @@ -525,7 +525,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg if mb.deep_detect != 0: chk_rc_1a: int = mb.check_alive_blocks(p1a_mark) if chk_rc_1a != 0: - VLogger.error(f"内存损坏(1a 每文件后续, rc={chk_rc_1a}): {file_path_r}", "Phase1") + VLogger.error(f"memory corruption (1a per-file post-check, rc={chk_rc_1a}): {file_path_r}", "Phase1") stdlib.exit(1) # Reclaim this file's transient AST/lexer/token/IR (registered data is in perm_pool, so @@ -534,10 +534,10 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg # 1a total time (struct/enum/union registration, incl. per-file read+parse+declaration) t_a1: uint64 = w32.win32base.GetTickCount64() - VLogger.info(f"1a 总耗时: {t_a1-t_a0} ms (注册 struct/enum, reg={p1a_reg} skp={p1a_skp})", "Phase1") + VLogger.info(f"1a total time: {t_a1-t_a0} ms (registering struct/enum, reg={p1a_reg} skp={p1a_skp})", "Phase1") if p1a_fl > 0: - VLogger.error(f"Phase 1a 有 {p1a_fl} 个文件 struct 注册失败", "Phase1") + VLogger.error(f"Phase 1a: {p1a_fl} files failed to register struct", "Phase1") return 1 # Release topo-sort resources (topo_order/topo_count_box stay until Phase 1b ends; @@ -576,7 +576,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg vpi_path_pv: str = StubMergerCollect._sliced_path(temp_dir, dir_len_pv, sha1_pv, "vpi") if vpi_path_pv is None: p1bpre_failed += 1 - VLogger.error(f"[Phase 1b-pre] {entry_pv.Path} | vpi 路径生成失败", "Phase1") + VLogger.error(f"[Phase 1b-pre] {entry_pv.Path} | failed to generate the vpi path", "Phase1") continue vf_pv: fileio.File* = fileio.File(vpi_path_pv, fileio.MODE.R) if not vf_pv.closed: @@ -589,33 +589,33 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg f_pv: fileio.File* = fileio.File(file_path_pv, fileio.MODE.R) if f_pv.closed: p1bpre_failed += 1 - VLogger.error(f"[Phase 1b-pre] {file_path_pv} | 无法打开源文件", "Phase1") + VLogger.error(f"[Phase 1b-pre] {file_path_pv} | cannot open the source file", "Phase1") continue # read_all's capacity includes the terminator (reads at most cap-1 bytes); longer files are truncated if f_pv.size() >= Phase1.SRC_BUF_SIZE: p1bpre_failed += 1 - VLogger.error(f"[Phase 1b-pre] {file_path_pv} | 源文件超过 {Phase1.SRC_BUF_SIZE} 字节上限", "Phase1") + VLogger.error(f"[Phase 1b-pre] {file_path_pv} | source file exceeds the {Phase1.SRC_BUF_SIZE}-byte limit", "Phase1") f_pv.close() continue src_buf_pv: bytes = stdlib.malloc(Phase1.SRC_BUF_SIZE) if src_buf_pv is None: f_pv.close() p1bpre_failed += 1 - VLogger.error(f"[Phase 1b-pre] {file_path_pv} | 源文件缓冲分配失败(OOM)", "Phase1") + VLogger.error(f"[Phase 1b-pre] {file_path_pv} | source buffer allocation failed (OOM)", "Phase1") continue bytes_read_pv: LONG = f_pv.read_all(src_buf_pv, Phase1.SRC_BUF_SIZE) f_pv.close() if bytes_read_pv <= 0: stdlib.free(src_buf_pv) p1bpre_failed += 1 - VLogger.error(f"[Phase 1b-pre] {file_path_pv} | 文件读取失败或为空", "Phase1") + VLogger.error(f"[Phase 1b-pre] {file_path_pv} | file read failed or is empty", "Phase1") continue if bytes_read_pv < Phase1.SRC_BUF_SIZE: src_buf_pv[bytes_read_pv] = 0 lx_pv: ast.Lexer* = ast.new_lexer(mb) if lx_pv is None: stdlib.free(src_buf_pv) p1bpre_failed += 1 - VLogger.error(f"[Phase 1b-pre] {file_path_pv} | 词法器分配失败(OOM)", "Phase1") + VLogger.error(f"[Phase 1b-pre] {file_path_pv} | lexer allocation failed (OOM)", "Phase1") continue ast._lexer_init(lx_pv, src_buf_pv, mb) tokens_pv: ast.Token* = ast.tokenize(lx_pv) @@ -625,7 +625,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg p1bpre_failed += 1 # Parse failure: the log line inlines line/col + reason, plus a full Python-style # traceback (same reporting path as the single-file BuildPipeline). - VLogger.error(f"[Phase 1b-pre] {file_path_pv} | AST 解析失败(第 {ast.get_parse_err_line()} 行第 {ast.get_parse_err_col()} 列: {ast.get_parse_err_msg()})", "Phase1") + VLogger.error(f"[Phase 1b-pre] {file_path_pv} | AST parse failed (line {ast.get_parse_err_line()} col {ast.get_parse_err_col()}: {ast.get_parse_err_msg()})", "Phase1") GenApi.dump_parse_traceback(file_path_pv) continue pyi_buf_pv: bytes = stdlib.malloc(Phase1.PYI_BUF_SIZE) @@ -642,14 +642,14 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg stdlib.free(pyi_buf_pv) else: p1bpre_failed += 1 - VLogger.error(f"[Phase 1b-pre] {file_path_pv} | pyi 缓冲分配失败(OOM)", "Phase1") + VLogger.error(f"[Phase 1b-pre] {file_path_pv} | pyi buffer allocation failed (OOM)", "Phase1") stdlib.free(src_buf_pv) # [TEMP-DIAG] 1b-pre per-file sentinel (as above): check the tail canary of live blocks # in [mark1, chk_depth). Must run before reset_to(mark1); only under --detection-deep. if mb.deep_detect != 0: chk_rc_pv: int = mb.check_alive_blocks(mark1) if chk_rc_pv != 0: - VLogger.error(f"内存损坏(1b-pre 每文件后续, rc={chk_rc_pv}): {file_path_pv}", "Phase1") + VLogger.error(f"memory corruption (1b-pre per-file post-check, rc={chk_rc_pv}): {file_path_pv}", "Phase1") stdlib.exit(1) # Reclaim this file's AST (the vpi is written; nothing else persists after mark1) @@ -657,10 +657,10 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg # 1b-pre total time (vpi pre-generation) t_pv1: uint64 = w32.win32base.GetTickCount64() - VLogger.info(f"1b-pre 总耗时: {t_pv1-t_pv0} ms (vpi 预生成)", "Phase1") + VLogger.info(f"1b-pre total time: {t_pv1-t_pv0} ms (vpi pre-generation)", "Phase1") if p1bpre_failed > 0: - VLogger.error(f"Phase 1b-pre 有 {p1bpre_failed} 个文件 vpi 预生成失败(失败文件与原因见上方逐条 [Phase 1b-pre] 日志)", "Phase1") + VLogger.error(f"Phase 1b-pre: {p1bpre_failed} files failed vpi pre-generation (see the per-file [Phase 1b-pre] log lines above for failures and causes)", "Phase1") return 1 # Iterate each file (topo order preferred so base-class files translate first and their @@ -740,7 +740,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg if force_translate == 1: # Has class: force translation (overwrite stub/text, re-register classes) rp: str = entry.RelPath - VLogger.info(f"含 class 定义,强制翻译: {rp}(sha1={sha1})", "Phase1") + VLogger.info(f"contains a class definition, forcing translation: {rp}(sha1={sha1})", "Phase1") else: # Skip already-existing stubs (on-demand translation) sf: fileio.File* = fileio.File(stub_path, fileio.MODE.R) @@ -777,11 +777,11 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg stdlib.free(text_path) # text.ll missing, re-translate rp: str = entry.RelPath - VLogger.info(f"text.ll 不存在,重新翻译: {rp}(sha1={sha1})", "Phase1") + VLogger.info(f"text.ll not found, re-translating: {rp}(sha1={sha1})", "Phase1") else: # stub missing, translate rp: str = entry.RelPath - VLogger.info(f"翻译: {rp}(sha1={sha1})", "Phase1") + VLogger.info(f"translating: {rp}(sha1={sha1})", "Phase1") stdlib.free(stub_path) @@ -792,17 +792,17 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg file_path: str = entry.Path f: fileio.File* = fileio.File(file_path, fileio.MODE.R) if f is None: - VLogger.error(f"无法打开(f=None): {file_path}", "Phase1") + VLogger.error(f"cannot open (f=None): {file_path}", "Phase1") failed += 1 continue if f.closed: - VLogger.error(f"无法打开: {file_path}", "Phase1") + VLogger.error(f"cannot open: {file_path}", "Phase1") failed += 1 continue # read_all's capacity includes the terminator (reads at most cap-1 bytes); longer files are truncated if f.size() >= Phase1.SRC_BUF_SIZE: - VLogger.error(f"源文件超过 {Phase1.SRC_BUF_SIZE} 字节上限, 拒绝读取: {file_path}", "Phase1") + VLogger.error(f"source file exceeds the {Phase1.SRC_BUF_SIZE}-byte limit, refusing to read: {file_path}", "Phase1") f.close() failed += 1 continue @@ -816,7 +816,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg bytes_read: LONG = f.read_all(src_buf, Phase1.SRC_BUF_SIZE) f.close() if bytes_read <= 0: - VLogger.error(f"读取失败: {file_path}", "Phase1") + VLogger.error(f"read failed: {file_path}", "Phase1") stdlib.free(src_buf) failed += 1 continue @@ -834,7 +834,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg if tree is None: # Parse failure: line/col + reason go into the log line (reason supplied by parser.vp's # _record_* / parse_tokens fallback). - VLogger.error(f"AST 解析失败: {file_path}(第 {ast.get_parse_err_line()} 行第 {ast.get_parse_err_col()} 列: {ast.get_parse_err_msg()})", "Phase1") + VLogger.error(f"AST parse failed: {file_path} (line {ast.get_parse_err_line()} col {ast.get_parse_err_col()}: {ast.get_parse_err_msg()})", "Phase1") stdlib.free(src_buf) failed += 1 continue @@ -889,7 +889,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg # corrupts a live block header is pinned to the current file (deterministic crash location). pre_rc: int = mb.check_alive_blocks(mark1) if pre_rc != 0: - VLogger.error(f"内存损坏(翻译前存活块, rc={pre_rc}): {file_path}", "Phase1") + VLogger.error(f"memory corruption (live blocks before translate, rc={pre_rc}): {file_path}", "Phase1") stdlib.exit(1) ret: int = tr.translate(tree) @@ -897,9 +897,9 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg t_f2: uint64 = w32.win32base.GetTickCount64() # Diagnostic: translate returned normally (if it hangs inside, this line is not printed, # distinguishing an internal hang from a later dump hang). - if ret == 0: VLogger.info(f"翻译完成(translate返回): {file_path}", "Phase1") + if ret == 0: VLogger.info(f"translation complete (translate returned): {file_path}", "Phase1") if ret != 0: - VLogger.error(f"翻译失败: {file_path}", "Phase1") # error terminates + VLogger.error(f"translation failed: {file_path}", "Phase1") # error terminates stdlib.free(src_buf) if tr._global_names is not None: stdlib.free(tr._global_names) if tr._nonlocal_names is not None: stdlib.free(tr._nonlocal_names) @@ -913,7 +913,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg # Diagnostic: the pre-translate sentinel misses write-throughs during translate, so check # live block headers/canaries before dump (rc=6 means a tail canary was overwritten). post_rc: int = mb.check_alive_blocks(mark1) - if post_rc != 0: VLogger.error(f"内存损坏(translate后存活块, rc={post_rc}): {file_path}", "Phase1") + if post_rc != 0: VLogger.error(f"memory corruption (live blocks after translate, rc={post_rc}): {file_path}", "Phase1") # Dump stub IR (declarations only). 1MB is not enough: ast/parser.vp's text.ll exceeds it # and is truncated (opt: "end of file in global variable name"), so use 8MB. @@ -968,7 +968,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg # save {sha1}.full.ll (the online FULL artifact: a self-contained single-module IR for # Phase B to compile directly, replacing the stub + dependency text merge). full_buf_p1: bytes = stdlib.malloc(PHASE1_FULL_SIZE) - if full_buf_p1 is None: VLogger.error("full.ll 缓冲区分配失败", "Phase1") + if full_buf_p1 is None: VLogger.error("full.ll buffer allocation failed", "Phase1") tr.dump_ir(full_buf_p1, PHASE1_FULL_SIZE, mlirlite.OUTPUT_FULL) full_len_p1: sizet = string.strlen(full_buf_p1) full_path_p1: str = StubMergerCollect._sliced_path(temp_dir, dir_len_p1, sha1, "full.ll") @@ -990,7 +990,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg # Timer 3: dump (stub+text) done; print the per-file three-segment timing t_f3: uint64 = w32.win32base.GetTickCount64() - VLogger.info(f"[{i+1}/{loop_n_b}] 翻译: {file_path} (parse={t_f1-t_f0} ms, translate={t_f2-t_f1} ms, dump={t_f3-t_f2} ms, total={t_f3-t_f0} ms)", "Phase1") + VLogger.info(f"[{i+1}/{loop_n_b}] translating: {file_path} (parse={t_f1-t_f0} ms, translate={t_f2-t_f1} ms, dump={t_f3-t_f2} ms, total={t_f3-t_f0} ms)", "Phase1") # save dependencies(_imported_modules) for Phase B deps_path_p1: str = StubMergerCollect._sliced_path(temp_dir, dir_len_p1, sha1, "deps.txt") @@ -1015,25 +1015,25 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg # OOM reclamation: free this file's transient AST/tokens/lexer/IR/dump data (persistent # tables moved to stdlib). Memory sentinels locate overruns deterministically. chk_rc: int = mb.check_alive_blocks(mark1) - if chk_rc != 0: VLogger.error(f"内存损坏(存活块 header, rc={chk_rc}): {file_path}", "Phase1") + if chk_rc != 0: VLogger.error(f"memory corruption (live block header, rc={chk_rc}): {file_path}", "Phase1") # Out-of-bounds writes are the crash root cause (unrelated to reclamation/UAF, confirmed # by A/B tests); reset_to plus the tail canary pins the offending file. mb.reset_to(mark1) sc_rc: int = mb.self_check() - if sc_rc != 0: VLogger.error(f"内存损坏(free list, rc={sc_rc}): {file_path}", "Phase1") + if sc_rc != 0: VLogger.error(f"memory corruption (free list, rc={sc_rc}): {file_path}", "Phase1") # 1b total time (full translation + dump) t_b1: uint64 = w32.win32base.GetTickCount64() - VLogger.info(f"1b 总耗时: {t_b1-t_b0} ms (全量翻译, trans={translated} skip={skipped} fail={failed})", "Phase1") + VLogger.info(f"1b total time: {t_b1-t_b0} ms (full translation, trans={translated} skip={skipped} fail={failed})", "Phase1") # Release the topo-sort resources used by Phase 1b if topo_order is not None: mb.free(topo_order) if topo_count_box is not None: mb.free(topo_count_box) - VLogger.info(f"完成: 翻译={translated} 跳过={skipped} 失败={failed}", "Phase1") + VLogger.info(f"done: translated={translated} skipped={skipped} failed={failed}", "Phase1") if failed > 0: - VLogger.error(f"Phase1 有 {failed} 个文件翻译失败", "Phase1") + VLogger.error(f"Phase1: {failed} files failed to translate", "Phase1") return 1 # Release the reachable SHA1 set (if allocated) diff --git a/App/lib/Phase/Phase1/Phase1Scan.vp b/App/lib/Phase/Phase1/Phase1Scan.vp index 39f5155..9e90042 100644 --- a/App/lib/Phase/Phase1/Phase1Scan.vp +++ b/App/lib/Phase/Phase1/Phase1Scan.vp @@ -45,7 +45,7 @@ def _ScanClassInheritance(mb: memhub.MemBuddy*, result: IncludesScanner.ScanResu if result is None: return -1 # The three flat buffers are mb.alloc'ed by the caller; a NULL buffer would make # strcpy write the zero page, so fail-fast abort instead of returning -1 silently. - if class_names_buf is None or parent_names_buf is None or def_sha1s_buf is None: VLogger.error("类继承预扫描扁平缓冲分配失败(class_names_buf/parent_names_buf/def_sha1s_buf 为 NULL)", "Phase1") + if class_names_buf is None or parent_names_buf is None or def_sha1s_buf is None: VLogger.error("class-inheritance pre-scan flat buffer allocation failed (class_names_buf/parent_names_buf/def_sha1s_buf is NULL)", "Phase1") entry_size: sizet = IncludesScanner.FileEntry.__sizeof__() class_count: int = 0 @@ -74,7 +74,7 @@ def _ScanClassInheritance(mb: memhub.MemBuddy*, result: IncludesScanner.ScanResu # read_all's capacity includes the terminator (reads at most cap-1 bytes); longer files are truncated if f.size() >= Phase1.SRC_BUF_SIZE: - VLogger.error(f"源文件超过 {Phase1.SRC_BUF_SIZE} 字节上限, 拒绝读取: {file_path}", "Phase1") + VLogger.error(f"source file exceeds the {Phase1.SRC_BUF_SIZE}-byte limit, refusing to read: {file_path}", "Phase1") f.close() continue @@ -236,7 +236,7 @@ def _PreRegisterAllGenericTemplates(mb: memhub.MemBuddy*, result: IncludesScanne if f_pg.closed: continue # read_all's capacity includes the terminator (reads at most cap-1 bytes); longer files are truncated if f_pg.size() >= Phase1.SRC_BUF_SIZE: - VLogger.error(f"源文件超过 {Phase1.SRC_BUF_SIZE} 字节上限, 拒绝读取: {file_path_pg}", "Phase1") + VLogger.error(f"source file exceeds the {Phase1.SRC_BUF_SIZE}-byte limit, refusing to read: {file_path_pg}", "Phase1") f_pg.close() continue src_buf_pg: bytes = stdlib.malloc(Phase1.SRC_BUF_SIZE) @@ -290,8 +290,8 @@ def _PreRegisterAllGenericTemplates(mb: memhub.MemBuddy*, result: IncludesScanne GenApi._register_generic_func_template(perm, fd_pg, entry_pg.Sha1) handled_count += 1 stdlib.free(src_buf_pg) - if handled_count > 0: VLogger.info(f"mark1 前永久池预注册 {handled_count} 个 includes 泛型模板(类+函数)", "Phase1") - else: VLogger.info(f"mark1 前永久池预注册 0 个泛型模板(扫描 {result.Count} 个文件,可能 marker 未命中或全量扫描失败)", "Phase1") + if handled_count > 0: VLogger.info(f"pre-registered {handled_count} includes generic templates (classes and functions) in the permanent pool before mark1", "Phase1") + else: VLogger.info(f"pre-registered 0 generic templates in the permanent pool before mark1 (scanned {result.Count} files; the marker may not have matched or the full scan failed)", "Phase1") return handled_count # _FindClassDefSha1 - look up a class name's defining file SHA1 in the flat arrays; # returns a pointer into def_sha1s_buf, or None if not found. @@ -326,7 +326,7 @@ def _ScanTreeForContainers(node: ast.AST*, need_list_box: t.CPtr, need_dict_box: """Recursively scan the AST for list/dict container usage.""" # Recursion depth guard: a self-referential AST cycle would recurse until the # stack is exhausted; fail-fast abort. - if depth > 128: VLogger.error("容器扫描递归过深(AST 环或嵌套超过 128 层)", "Phase1") + if depth > 128: VLogger.error("container scan recursion too deep (AST cycle or nesting over 128 levels)", "Phase1") if node is None: return k_s: int = node.kind() if k_s == ast.ASTKind.Name: diff --git a/App/lib/Phase/Phase2/__init__.vp b/App/lib/Phase/Phase2/__init__.vp index faf3508..bc2199f 100644 --- a/App/lib/Phase/Phase2/__init__.vp +++ b/App/lib/Phase/Phase2/__init__.vp @@ -222,7 +222,7 @@ def _PreRegisterAppGenericTemplates(mb: memhub.MemBuddy*, entries: SrcFileEntry* if f_pa.closed: continue # read_all's capacity includes the terminator (reads at most cap-1 bytes); longer files are truncated if f_pa.size() >= SRC_BUF_SIZE: - VLogger.error(f"源文件超过 {SRC_BUF_SIZE} 字节上限, 拒绝读取: {ent_pa.Path}", "PhaseA") + VLogger.error(f"source file exceeds {SRC_BUF_SIZE} byte limit, refusing to read: {ent_pa.Path}", "PhaseA") f_pa.close() continue src_buf_pa: bytes = stdlib.malloc(SRC_BUF_SIZE) @@ -273,7 +273,7 @@ def _PreRegisterAppGenericTemplates(mb: memhub.MemBuddy*, entries: SrcFileEntry* GenApi._register_generic_func_template(perm_pa, fd_pa, ent_pa.Sha1) handled += 1 stdlib.free(src_buf_pa) - if handled > 0: VLogger.info(f"mark2 前预注册 {handled} 个 App 泛型模板(类+函数)", "PhaseA") + if handled > 0: VLogger.info(f"pre-registered {handled} App generic templates before mark2 (classes + functions)", "PhaseA") return handled @@ -511,10 +511,10 @@ def _PhaseADumpFailGraph(temp_dir: str, td_len: sizet, path: str, sha1: str) -> def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, output_dir: str, cc_cmd: str, cc_flags: str, linker_cmd: str, linker_flags: str, linker_output: str, includes_binary_dir: str, includes_dir: str, do_phase1: int, do_phase2: int, log: VLogger.Logger*, args: argparse.ParsedArgs*, linker_static_libs: str = None, linker_dynamic_libs: str = None) -> int: """Compile a multi-file project; return 0 on success, non-zero on failure""" if source_dir is None: - VLogger.error("source_dir 为空", "project") + VLogger.error("source_dir is empty", "project") return 1 - VLogger.info(f"多文件项目编译: {source_dir}", "project") + VLogger.info(f"multi-file project compilation: {source_dir}", "project") # === 1. Recursively scan .vp/.py files under source_dir (including subdirectories) === entry_size: sizet = SrcFileEntry.__sizeof__() @@ -523,7 +523,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou string.memset(entries, 0, MAX_SRC_FILES * entry_size) file_count: int = _ScanDirForPyFiles(mb, source_dir, entries, entry_size, 0, MAX_SRC_FILES) - VLogger.info(f"共 {file_count} 个源文件", "project") + VLogger.info(f"{file_count} source files in total", "project") # Scan .s assembly files (separate array; not translated in Phase A, assembled by llvm-mc after Phase B) asm_entries: SrcFileEntry* = stdlib.malloc(MAX_SRC_FILES * entry_size) @@ -532,7 +532,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou return 1 string.memset(asm_entries, 0, MAX_SRC_FILES * entry_size) asm_file_count: int = _ScanDirForAsmFiles(mb, source_dir, asm_entries, entry_size, 0, MAX_SRC_FILES) - if asm_file_count > 0: VLogger.info(f"汇编文件 {asm_file_count} 个(llvm-mc 汇编参与链接)", "project") + if asm_file_count > 0: VLogger.info(f"{asm_file_count} assembly files (assembled by llvm-mc and linked)", "project") if file_count == 0: stdlib.free(entries) @@ -561,12 +561,12 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou if includes_dir is not None: if StubMergerStore.GetSha1StoreCount() == 0: rs_05: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES_SHA1 * 17) - if rs_05 is None: VLogger.error("reachable_set 分配失败,无法填充 Sha1Store", "project") + if rs_05 is None: VLogger.error("reachable_set allocation failed, cannot fill Sha1Store", "project") else: string.memset(rs_05, 0, StubMerger.MAX_INCLUDES_SHA1 * 17) rc_05: int = StubMergerBuild._BuildReachableSha1Set(mb, source_dir, temp_dir, rs_05, None, includes_dir) - if rc_05 < 0: VLogger.error("依赖图扫描失败,无法填充 Sha1Store", "project") - elif rc_05 > 0: VLogger.info(f"Phase2 依赖图按需填充 Sha1Store: {rc_05} 个", "project") + if rc_05 < 0: VLogger.error("dependency graph scan failed, cannot fill Sha1Store", "project") + elif rc_05 > 0: VLogger.info(f"Phase2 dependency graph filled Sha1Store on demand: {rc_05} entries", "project") stdlib.free(rs_05) # Append App source SHA1s to _sha1_map.txt (human-readable only; format {sha1}:{rel_path}) and to the @@ -592,7 +592,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou if string.strncmp(p_str, source_dir, src_dir_len_am) == 0: rel_path_am = p_str + src_dir_len_am + 1 # Also append to the in-memory store (for cross-module CDefine lookups) # rel_path_am looks like "lib/core/StubMerger.vp", matching _sha1_map.txt - if StubMergerStore.AppendToSha1MapStore(ent_am.Sha1, rel_path_am) != 0: VLogger.error(f"AppendToSha1MapStore 失败: {rel_path_am}", "project") + if StubMergerStore.AppendToSha1MapStore(ent_am.Sha1, rel_path_am) != 0: VLogger.error(f"AppendToSha1MapStore failed: {rel_path_am}", "project") app_filled += 1 # Write _sha1_map.txt (human-readable output) if not mf.closed and line_am is not None: @@ -602,7 +602,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou if line_am is not None: stdlib.free(line_am) if not mf.closed: mf.close() - VLogger.info(f"已追加 {app_filled} 个 App 文件到 _sha1_map.txt 和内存存储器", "project") + VLogger.info(f"appended {app_filled} App files to _sha1_map.txt and the in-memory store", "project") stdlib.free(map_path_am) # The module SHA1 map is filled into the StubMerger global store by PopulateSha1MapStore + @@ -619,13 +619,13 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou ent_vp2: SrcFileEntry* = (SrcFileEntry*)(ea_vp2) if ent_vp2 is None or ent_vp2.Path is None or ent_vp2.Sha1 is None: vpi_failed_p2 += 1 - VLogger.error("[Phase A-pre-vpi] 源文件条目无效(Path/Sha1 缺失),跳过", "PhaseA") + VLogger.error("[Phase A-pre-vpi] invalid source entry (Path/Sha1 missing), skipping", "PhaseA") continue # Skip if the vpi already exists (sha1 is content-based, so a same-named vpi is valid; cross-run cache) vpi_path_vp2: str = StubMergerCollect._sliced_path(temp_dir, td_len_vpa, ent_vp2.Sha1, "vpi") if vpi_path_vp2 is None: vpi_failed_p2 += 1 - VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | vpi 路径生成失败", "PhaseA") + VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | failed to build vpi path", "PhaseA") continue vf_vp2: fileio.File* = fileio.File(vpi_path_vp2, fileio.MODE.R) if not vf_vp2.closed: @@ -638,33 +638,33 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou f_vp2: fileio.File* = fileio.File(ent_vp2.Path, fileio.MODE.R) if f_vp2.closed: vpi_failed_p2 += 1 - VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | 无法打开源文件", "PhaseA") + VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | cannot open source file", "PhaseA") continue # read_all's capacity includes the terminator (reads at most cap-1 bytes); longer files are truncated if f_vp2.size() >= SRC_BUF_SIZE: vpi_failed_p2 += 1 - VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | 源文件超过 {SRC_BUF_SIZE} 字节上限", "PhaseA") + VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | source file exceeds {SRC_BUF_SIZE} byte limit", "PhaseA") f_vp2.close() continue src_buf_vp2: bytes = stdlib.malloc(SRC_BUF_SIZE) if src_buf_vp2 is None: f_vp2.close() vpi_failed_p2 += 1 - VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | 源文件缓冲分配失败(OOM)", "PhaseA") + VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | source buffer allocation failed (OOM)", "PhaseA") continue bytes_read_vp2: LONG = f_vp2.read_all(src_buf_vp2, SRC_BUF_SIZE) f_vp2.close() if bytes_read_vp2 <= 0: stdlib.free(src_buf_vp2) vpi_failed_p2 += 1 - VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | 文件读取失败或为空", "PhaseA") + VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | file read failed or empty", "PhaseA") continue if bytes_read_vp2 < SRC_BUF_SIZE: src_buf_vp2[bytes_read_vp2] = 0 lx_vp2: ast.Lexer* = ast.new_lexer(mb) if lx_vp2 is None: stdlib.free(src_buf_vp2) vpi_failed_p2 += 1 - VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | 词法器分配失败(OOM)", "PhaseA") + VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | lexer allocation failed (OOM)", "PhaseA") continue ast._lexer_init(lx_vp2, src_buf_vp2, mb) tokens_vp2: ast.Token* = ast.tokenize(lx_vp2) @@ -674,7 +674,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou vpi_failed_p2 += 1 # Parse failure: inline the line/column + reason in the log line (same source as the full # Python-style traceback below), since "AST parse failed" alone gives no location or cause. - VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | AST 解析失败(第 {ast.get_parse_err_line()} 行第 {ast.get_parse_err_col()} 列: {ast.get_parse_err_msg()})", "PhaseA") + VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | AST parse failed (line {ast.get_parse_err_line()} col {ast.get_parse_err_col()}: {ast.get_parse_err_msg()})", "PhaseA") GenApi.dump_parse_traceback(ent_vp2.Path) continue pyi_buf_vp2: bytes = stdlib.malloc(PYI_BUF_SIZE_P2) @@ -691,12 +691,12 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou stdlib.free(pyi_buf_vp2) else: vpi_failed_p2 += 1 - VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | pyi 缓冲分配失败(OOM)", "PhaseA") + VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | pyi buffer allocation failed (OOM)", "PhaseA") stdlib.free(src_buf_vp2) # OOM cleanup: free this file's AST (the vpi is already on disk; persistent data is stdlib-allocated) mb.reset_to(mark2) if vpi_failed_p2 > 0: - VLogger.error(f"Phase A-pre-vpi 有 {vpi_failed_p2} 个文件 vpi 预生成失败(失败文件与原因见上方逐条 [Phase A-pre-vpi] 日志)", "PhaseA") + VLogger.error(f"Phase A-pre-vpi: {vpi_failed_p2} files failed vpi pre-generation (see the per-file [Phase A-pre-vpi] logs above for failing files and causes)", "PhaseA") return 1 @@ -706,7 +706,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou app_deps_buf: bytes = None app_deps_len: sizet = 0 if do_phase1 != 0: - log.banner("Phase A: 生成 stub + text") + log.banner("Phase A: generate stub + text") # Initialize the Phase A convergence-failure diagnostic table (stdlib, survives reset) _PhaseADiagInit(sizet(file_count) + StubMerger.MAX_INCLUDES) @@ -772,13 +772,13 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou for si_inc_f in range(store_count_inc_pre): if inc_fail_flags[si_inc_f] != 0: rel_f: str = store_rel_inc_pre + sizet(si_inc_f) * StubMerger.MAX_REL_PATH_LEN - VLogger.error(f"includes 预注册失败: {rel_f}(文件无法翻译,可能是语法/解析/编译错误),终止编译", "prePhaseA") + VLogger.error(f"includes pre-registration failed: {rel_f} (file cannot be translated; possible syntax/parse/compile error), aborting compilation", "prePhaseA") stdlib.free(inc_fail_flags) - VLogger.info(f"includes 预注册 + 依赖填充: {deps_filled_pre}/{store_count_inc_pre}", "prePhaseA") + VLogger.info(f"includes pre-registration + dependency fill: {deps_filled_pre}/{store_count_inc_pre}", "prePhaseA") # === Phase A-pre: pre-register struct/enum/union for all sources === # Registers declarations only (declare_only=1), no method bodies; multi-pass resolves cross-file ordering. - VLogger.info("预注册 struct/enum/union...", "PhaseA") + VLogger.info("pre-registering struct/enum/union...", "PhaseA") src_dir_len_pre: sizet = string.strlen(source_dir) PHASE_A_PRE_MAX_PASSES: int = 3 for pass_i in range(PHASE_A_PRE_MAX_PASSES): @@ -794,13 +794,13 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou # App pre-registration passes pre_allow_dep_inject=1: imports and dep vpi injection happen at # declaration time so field annotations share Phase A's context (else struct layouts diverge). tr_pre: HandlesTranslator.Translator* = BuildPipeline.TranslateFileGetTrans(mb, ent_pre.Path, ent_pre.Sha1, pkg_pre, 1, None, 1) - if tr_pre is None: VLogger.error(f"预注册失败: {ent_pre.Path}", "PhaseA") + if tr_pre is None: VLogger.error(f"pre-registration failed: {ent_pre.Path}", "PhaseA") # OOM cleanup: free this App file's transient pre-registration data mb.reset_to(mark2) struct_count_after: int = GenApi.get_struct_count() # Convergence check: no new struct registered this pass -> all classes are registered if struct_count_after == struct_count_before: break - VLogger.info("预注册完成", "PhaseA") + VLogger.info("pre-registration complete", "PhaseA") # Phase A IR buffer: 1MB is not enough, ast/parser.vp's text.ll exceeds 1MB and got truncated -> # merged IR lost the tail (opt: "end of file in global variable name"). @@ -823,7 +823,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou # (filesystem order); failed files are retried next pass, converging in at most file_count passes. done_flags: bytes = stdlib.malloc(file_count) if done_flags is None: - VLogger.error("Phase A done_flags 分配失败", "PhaseA") + VLogger.error("Phase A done_flags allocation failed", "PhaseA") stdlib.free(entries) return 1 string.memset(done_flags, 0, file_count) @@ -887,7 +887,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou stdlib.free(im_mod_buf) # dump stub IR (declarations only) stub_buf_a: bytes = stdlib.malloc(PHASE_A_IR_SIZE) - if stub_buf_a is None: VLogger.error("stub 缓冲区分配失败", "PhaseA") + if stub_buf_a is None: VLogger.error("stub buffer allocation failed", "PhaseA") tr_a.dump_ir(stub_buf_a, PHASE_A_IR_SIZE, mlirlite.OUTPUT_STUB) stub_len_a: sizet = string.strlen(stub_buf_a) @@ -903,7 +903,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou # dump text IR (definitions only) text_buf_a: bytes = stdlib.malloc(PHASE_A_IR_SIZE) - if text_buf_a is None: VLogger.error("text 缓冲区分配失败", "PhaseA") + if text_buf_a is None: VLogger.error("text buffer allocation failed", "PhaseA") tr_a.dump_ir(text_buf_a, PHASE_A_IR_SIZE, mlirlite.OUTPUT_TEXT) text_len_a: sizet = string.strlen(text_buf_a) @@ -922,7 +922,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou # Save {sha1}.full.ll (in-memory FULL artifact: a self-contained single-module IR) full_buf_a: bytes = stdlib.malloc(PHASE_A_FULL_SIZE) - if full_buf_a is None: VLogger.error("full.ll 缓冲区分配失败", "PhaseA") + if full_buf_a is None: VLogger.error("full.ll buffer allocation failed", "PhaseA") tr_a.dump_ir(full_buf_a, PHASE_A_FULL_SIZE, mlirlite.OUTPUT_FULL) full_len_a: sizet = string.strlen(full_buf_a) full_path_a: str = StubMergerCollect._sliced_path(temp_dir, td_len_pa, ent.Sha1, "full.ll") @@ -980,7 +980,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou if ent_err.Sha1 is not None: _PhaseADumpFailGraph(temp_dir, td_len_fail, ent_err.Path, ent_err.Sha1) stdlib.free(done_flags) _PhaseADiagFree() - VLogger.error("Phase A 多遍收敛失败,终止编译", "PhaseA") + VLogger.error("Phase A multi-pass convergence failed, aborting compilation", "PhaseA") stdlib.free(entries) return 1 stdlib.free(done_flags) @@ -988,14 +988,14 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou _PhaseADiagFree() if do_phase2 == 0: - VLogger.info("Phase A 完成(仅 stub 生成)", "project") + VLogger.info("Phase A complete (stub generation only)", "project") if app_deps_buf is not None: stdlib.free(app_deps_buf) stdlib.free(entries) return 0 # === 3. Phase B: compile each file to .obj === if do_phase2 != 0: - log.banner("Phase B: 编译 .obj") + log.banner("Phase B: compile .obj") # Collect .obj paths (64KB to avoid includes .obj path overflow dropping link symbols). # reachable_set/reachable_count: filled by Phase B+, used by Phase C for on-demand linking. @@ -1020,7 +1020,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou # only writes .ll + builds tasks, then run_llc_parallel runs llc in parallel batches. llc_tasks: bytes = stdlib.malloc(sizet(file_count) * BuildPipeline.LlcTask.__sizeof__()) if llc_tasks is None: - VLogger.error("llc 任务表分配失败", "PhaseB") + VLogger.error("llc task table allocation failed", "PhaseB") return 1 llc_task_count: int = 0 @@ -1033,11 +1033,11 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou # Read the in-memory FULL artifact {sha1}.full.ll -> complete IR (replaces merging stub + dep stub/text) combined_ir: bytes = stdlib.malloc(COMBINED_IR_SIZE) if combined_ir is None: - VLogger.error(f"combined_ir 分配失败: {ent.Path}", "PhaseB") + VLogger.error(f"combined_ir allocation failed: {ent.Path}", "PhaseB") continue combined_len: sizet = StubMergerBuild.LoadFullIR(temp_dir, ent.Sha1, combined_ir, COMBINED_IR_SIZE) if combined_len == 0: - VLogger.error(f"读 full.ll 失败: {ent.Path}", "PhaseB") + VLogger.error(f"failed to read full.ll: {ent.Path}", "PhaseB") stdlib.free(combined_ir) continue # Timing point 1: full.ll read done @@ -1047,7 +1047,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou ret_w: int = BuildPipeline.write_ir_to_file(combined_ir, combined_len, temp_dir, ent.Sha1) stdlib.free(combined_ir) if ret_w != 0: - VLogger.error(f"写 .ll 失败: {ent.Path}", "PhaseB") + VLogger.error(f"failed to write .ll: {ent.Path}", "PhaseB") sys.exit(1) # Timing point 2: .ll write done t_pb2: uint64 = w32.win32base.GetTickCount64() @@ -1055,11 +1055,11 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou # Build the llc task (command string is stdlib.malloc'd so threads' lifetimes are not reset-reclaimed) llc_ir_path: str = BuildPipeline.build_sliced_path(temp_dir, ent.Sha1, "ll") if llc_ir_path is None: - VLogger.error("llc 输入路径构造失败", "PhaseB") + VLogger.error("failed to build llc input path", "PhaseB") sys.exit(1) tslot: BuildPipeline.LlcTask* = BuildPipeline.LlcTask*(uint64(llc_tasks) + sizet(llc_task_count) * BuildPipeline.LlcTask.__sizeof__()) if BuildPipeline.init_llc_task(tslot, llc_ir_path, output_dir, ent.Sha1, cc_cmd, cc_flags) != 0: - VLogger.error(f"llc 任务构造失败: {ent.Path}", "PhaseB") + VLogger.error(f"failed to build llc task: {ent.Path}", "PhaseB") sys.exit(1) # Timing point 3: llc task construction done t_pb3: uint64 = w32.win32base.GetTickCount64() @@ -1067,7 +1067,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou compiled_count += 1 # Show files submitted to llc (with the three timings: merge stub / write .ll / build task) - VLogger.info(f"[{i+1}/{file_count}] llc 已提交: {ent.Path} (merge={t_pb1-t_pb0} ms, write={t_pb2-t_pb1} ms, task={t_pb3-t_pb2} ms, total={t_pb3-t_pb0} ms)", "PhaseB") + VLogger.info(f"[{i+1}/{file_count}] llc submitted: {ent.Path} (merge={t_pb1-t_pb0} ms, write={t_pb2-t_pb1} ms, task={t_pb3-t_pb2} ms, total={t_pb3-t_pb0} ms)", "PhaseB") # Build the .obj path and detect the main module (test_main.vp or main.vp; .py no longer recognized) od_len: sizet = string.strlen(output_dir) is_main_mod: int = 0 @@ -1081,7 +1081,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou if is_main_mod != 0: # main module: copy to main_obj_path (so main is first at link time) if op_sliced_len < 512: string.strcpy(main_obj_path, obj_path_sliced) - else: VLogger.error("main_obj_path 缓冲区不足,终止编译", "PhaseB") + else: VLogger.error("main_obj_path buffer too small, aborting compilation", "PhaseB") else: # Other modules: append to obj_paths if obj_pos + op_sliced_len + 2 < OBJ_PATHS_SIZE: @@ -1091,13 +1091,13 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou string.strcpy(obj_paths + obj_pos, obj_path_sliced) obj_pos += op_sliced_len obj_paths[obj_pos] = '\0' - else: VLogger.error(".obj 路径缓冲区不足", "PhaseB") + else: VLogger.error(".obj path buffer too small", "PhaseB") stdlib.free(obj_path_sliced) # Run all llc jobs in parallel (batched at LLC_MAX_THREADS threads) ret_p: int = BuildPipeline.run_llc_parallel(llc_tasks, llc_task_count, BuildPipeline.LLC_MAX_THREADS) if ret_p != 0: - VLogger.error("llc 编译失败,终止编译", "PhaseB") + VLogger.error("llc compilation failed, aborting compilation", "PhaseB") sys.exit(1) # Free the llc tasks (command strings + records) @@ -1118,7 +1118,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou if ent_as is None or ent_as.Path is None or ent_as.Sha1 is None: continue aret_as: int = BuildPipeline.asm_to_obj(ent_as.Path, ent_as.Sha1, output_dir, Config.TargetTriple) if aret_as != 0: - VLogger.error(f"llvm-mc 汇编失败,终止编译: {ent_as.Path}", "PhaseB") + VLogger.error(f"llvm-mc assembly failed, aborting compilation: {ent_as.Path}", "PhaseB") sys.exit(1) obj_path_asm: str = StubMergerCollect._sliced_path(output_dir, od_len_as, ent_as.Sha1, "obj") if obj_path_asm is not None: @@ -1132,12 +1132,12 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou obj_paths[obj_pos] = '\0' stdlib.free(obj_path_asm) asm_compiled += 1 - VLogger.info(f"[asm {asm_compiled}] 汇编完成: {ent_as.Path}", "PhaseB") + VLogger.info(f"[asm {asm_compiled}] assembly complete: {ent_as.Path}", "PhaseB") - VLogger.success(f"编译完成: {compiled_count}/{file_count}", "PhaseB") + VLogger.success(f"compilation complete: {compiled_count}/{file_count}", "PhaseB") if compiled_count == 0: - VLogger.error("无成功编译的文件", "PhaseB") + VLogger.error("no files compiled successfully", "PhaseB") stdlib.free(entries) stdlib.free(asm_entries) return 1 @@ -1149,7 +1149,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou td_len_mi: sizet = string.strlen(temp_dir) # Diagnostic log: confirm the Phase B+ entry and Sha1Store state - VLogger.info(f"PhaseB+ 入口: store_count={StubMergerStore.GetSha1StoreCount()} includes_binary_dir={includes_binary_dir}", "PhaseB+") + VLogger.info(f"PhaseB+ entry: store_count={StubMergerStore.GetSha1StoreCount()} includes_binary_dir={includes_binary_dir}", "PhaseB+") # Create includes_binary_dir (so .obj files can be written and collect_obj_files can scan them) BuildPipeline.ensure_dir(includes_binary_dir) @@ -1165,13 +1165,13 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou if reachable_set is not None: string.memset(reachable_set, 0, REACHABLE_SET_SIZE) reachable_count = StubMergerBuild._BuildReachableSha1Set(mb, source_dir, temp_dir, reachable_set, app_deps_buf, includes_dir) - VLogger.info(f"可达 includes SHA1: {reachable_count} 个", "PhaseB+") + VLogger.info(f"reachable includes SHA1: {reachable_count} entries", "PhaseB+") # fast-fail: reachable-set construction failed (deps not found); never fall back, abort if reachable_count < 0: - VLogger.error("可达集合构建失败(fast-fail),终止编译", "PhaseB+") + VLogger.error("reachable set construction failed (fast-fail), aborting compilation", "PhaseB+") return 1 else: - VLogger.error("reachable_set 分配失败,终止编译", "PhaseB+") + VLogger.error("reachable_set allocation failed, aborting compilation", "PhaseB+") return 1 # Free app_deps_buf (reachable_set is built, no longer needed) @@ -1196,7 +1196,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou topo_idx: sizet* = (sizet*)(stdlib.malloc(8 * (store_count_mi + 1))) topo_count: int = 0 if topo_idx is None: - VLogger.error("拓扑排序索引分配失败,终止编译", "PhaseB+") + VLogger.error("topological sort index allocation failed, aborting compilation", "PhaseB+") topo_count = 0 else: topo_count = StubMergerTopo.BuildTopoSortedIndices(store_count_mi, store_sha1_arr_mi, store_mod_arr_mi, reachable_set, reachable_count, topo_idx) @@ -1244,7 +1244,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou if src_fp_mi is None: stdlib.free(check_pat_mi) if check_fd_mi is not None: stdlib.free(check_fd_mi) - VLogger.error("includes 源路径分配失败,终止编译", "PhaseB+") + VLogger.error("includes source path allocation failed, aborting compilation", "PhaseB+") viperlib.snprintf(src_fp_mi, inc_dir_len_mi + 1 + rel_path_len_mi + 1, "%s/%s", incdir_mi, inc_rel_mi) # Check whether it is a declaration-only file (read {sha1}.meta: no FUNC ... DEF means pure declaration) @@ -1306,7 +1306,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou StubMergerIR.WriteModuleMeta(tr_mi.Module, temp_dir, td_len_mi, inc_sha1_mi) # Save {sha1}.full.ll (in-memory FULL artifact) inc_full_buf: bytes = stdlib.malloc(PBP_FULL_SIZE) - if inc_full_buf is None: VLogger.error("full.ll 缓冲区分配失败", "PhaseB+") + if inc_full_buf is None: VLogger.error("full.ll buffer allocation failed", "PhaseB+") tr_mi.dump_ir(inc_full_buf, PBP_FULL_SIZE, mlirlite.OUTPUT_FULL) inc_full_len: sizet = string.strlen(inc_full_buf) inc_full_path: str = StubMergerCollect._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "full.ll") @@ -1355,7 +1355,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou diag_text_ex = 1 df_diag_t.close() stdlib.free(diag_text) - VLogger.error(f"读 full.ll 失败: {src_fp_mi} (full={diag_full_ex} stub={diag_stub_ex} text={diag_text_ex} is_decl={is_decl_mi})", "PhaseB+") + VLogger.error(f"failed to read full.ll: {src_fp_mi} (full={diag_full_ex} stub={diag_stub_ex} text={diag_text_ex} is_decl={is_decl_mi})", "PhaseB+") if inc_combined_mi is not None: stdlib.free(inc_combined_mi) stdlib.free(check_pat_mi) if check_fd_mi is not None: stdlib.free(check_fd_mi) @@ -1367,12 +1367,12 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou stdlib.free(inc_combined_mi) if inc_cret_mi != 0: - VLogger.error(f"llc 编译失败,终止编译: {src_fp_mi}", "PhaseB+") + VLogger.error(f"llc compilation failed, aborting compilation: {src_fp_mi}", "PhaseB+") sys.exit(1) inc_compiled += 1 # Show the compiled includes file - VLogger.info(f"[includes {inc_compiled}] 编译完成: {src_fp_mi}", "PhaseB+") + VLogger.info(f"[includes {inc_compiled}] compilation complete: {src_fp_mi}", "PhaseB+") # Add to obj_paths (sliced path, taken from includes_binary_dir) ibd_len_mi2: sizet = string.strlen(includes_binary_dir) @@ -1387,7 +1387,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou string.strcpy(obj_paths + obj_pos, inc_obj_sliced) obj_pos += inc_obj_len obj_paths[obj_pos] = '\0' - else: VLogger.error("includes .obj 路径缓冲区溢出,终止编译", "PhaseB+") + else: VLogger.error("includes .obj path buffer overflow, aborting compilation", "PhaseB+") stdlib.free(inc_obj_sliced) # Free this iteration's temporary memory @@ -1402,7 +1402,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou if store_sha1_arr_mi is not None: stdlib.free(store_sha1_arr_mi) if store_mod_arr_mi is not None: stdlib.free(store_mod_arr_mi) - VLogger.info(f"编译缺失 includes: {inc_compiled} 个", "PhaseB+") + VLogger.info(f"compiled missing includes: {inc_compiled} entries", "PhaseB+") # Free app_deps_buf (fallback when the Phase B+ block did not run) if app_deps_buf is not None: @@ -1410,7 +1410,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou app_deps_buf = None # === 4. Phase C: link all .obj -> .exe === - log.banner("Phase C: 链接") + log.banner("Phase C: link") od_len2: sizet = string.strlen(output_dir) lo_len: sizet = string.strlen(linker_output) @@ -1418,7 +1418,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou if exe_path is not None: viperlib.snprintf(exe_path, od_len2 + lo_len + 2, "%s/%s", output_dir, linker_output) else: exe_path = linker_output - VLogger.error("exe_path 分配失败,终止编译", "PhaseC") + VLogger.error("exe_path allocation failed, aborting compilation", "PhaseC") # Build the final .obj path list: main_obj_path first, reachable .objs after final_obj_paths: bytes = stdlib.malloc(OBJ_PATHS_SIZE + 512) @@ -1490,7 +1490,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou string.strcpy(final_obj_paths + fop_pos, obj_path_pc) fop_pos += op_len_p2 final_obj_paths[fop_pos] = '\0' - elif StubMergerIR.IsDeclOnlyModule(temp_dir, td_len_pc, rsha1_pc) != 1: VLogger.error(f"可达模块 .obj 缺失: {obj_path_pc}", "PhaseC") + elif StubMergerIR.IsDeclOnlyModule(temp_dir, td_len_pc, rsha1_pc) != 1: VLogger.error(f"reachable module .obj missing: {obj_path_pc}", "PhaseC") stdlib.free(obj_path_pc) final_obj_paths[fop_pos] = '\0' @@ -1505,19 +1505,19 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou lret: int = BuildPipeline.link_objs_to_exe(final_obj_paths, obj_paths_len, linker_cmd, linker_flags, exe_path, None, linker_static_libs, linker_dynamic_libs) if lret == 0: - VLogger.success(f"输出: {exe_path}", "PhaseC") + VLogger.success(f"output: {exe_path}", "PhaseC") # --traceback: export .stackmap (skipped under --phase2command, # where nothing was actually linked). if BuildPipeline._traceback_mode != 0 and BuildPipeline._phase2_cmd_path is None: BuildPipeline.WriteStackMap(mb, exe_path) if args.get_bool("run") and BuildPipeline._phase2_cmd_path is not None: # phase2command mode: the exe is not linked yet (the command is in the bat); skip --run - VLogger.info("phase2command 模式:跳过 --run(exe 尚未链接)", "phase2cmd") + VLogger.info("phase2command mode: skipping --run (exe not linked yet)", "phase2cmd") elif args.get_bool("run"): - VLogger.info(f"执行: {exe_path}", "run") + VLogger.info(f"run: {exe_path}", "run") rp: subprocess.CompletedProcess* = subprocess.run(exe_path, False, False) - if rp is not None: VLogger.info(f"退出码: {rp.returncode}", "run") + if rp is not None: VLogger.info(f"exit code: {rp.returncode}", "run") else: - VLogger.error("链接失败", "PhaseC") + VLogger.error("link failed", "PhaseC") stdlib.free(entries) stdlib.free(asm_entries) return 1 diff --git a/App/lib/Stub/StubGen/Converter.vp b/App/lib/Stub/StubGen/Converter.vp index b921705..85498c8 100644 --- a/App/lib/Stub/StubGen/Converter.vp +++ b/App/lib/Stub/StubGen/Converter.vp @@ -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 ") diff --git a/App/lib/Stub/StubGen/VpiReader.vp b/App/lib/Stub/StubGen/VpiReader.vp index 69671aa..65e3552 100644 --- a/App/lib/Stub/StubGen/VpiReader.vp +++ b/App/lib/Stub/StubGen/VpiReader.vp @@ -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 "%.", 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 diff --git a/App/lib/Stub/StubMerger/StubMergerBuild.vp b/App/lib/Stub/StubMerger/StubMergerBuild.vp index d86e543..ebad062 100644 --- a/App/lib/Stub/StubMerger/StubMergerBuild.vp +++ b/App/lib/Stub/StubMerger/StubMergerBuild.vp @@ -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() diff --git a/App/lib/Stub/StubMerger/StubMergerIR.vp b/App/lib/Stub/StubMerger/StubMergerIR.vp index b679147..627dc2c 100644 --- a/App/lib/Stub/StubMerger/StubMergerIR.vp +++ b/App/lib/Stub/StubMerger/StubMergerIR.vp @@ -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)) diff --git a/App/lib/Stub/StubMerger/StubMergerStore.vp b/App/lib/Stub/StubMerger/StubMergerStore.vp index b428c5e..ce6200e 100644 --- a/App/lib/Stub/StubMerger/StubMergerStore.vp +++ b/App/lib/Stub/StubMerger/StubMergerStore.vp @@ -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. diff --git a/App/lib/core/Gen/AssignGenMixin.vp b/App/lib/core/Gen/AssignGenMixin.vp index 78881b4..fbb1b2c 100644 --- a/App/lib/core/Gen/AssignGenMixin.vp +++ b/App/lib/core/Gen/AssignGenMixin.vp @@ -52,7 +52,7 @@ novirtual class AssignGenMixin: if cn.const_kind == ast.CONST_BOOL: return 1 if cn.int_val != 0 else 0 if cn.const_kind != ast.CONST_INT: # Non-INT constant: fail fast - self.Gen.TypeGenErr.fatal_error(val_node, "CDefine 值提取失败:无法从表达式解析编译期常量", "TypeError") + self.Gen.TypeGenErr.fatal_error(val_node, "CDefine value extraction failed: cannot parse a compile-time constant from the expression", "TypeError") return cn.int_val # Case 2: BinOp - e.g. FOREGROUND_RED | FOREGROUND_GREEN, (1 << N) @@ -72,7 +72,7 @@ novirtual class AssignGenMixin: if bop.op == ast.OpKind.FloorDiv: return left_val // right_val if bop.op == ast.OpKind.Mod: return left_val % right_val # Unknown BinOp operator: fail fast - self.Gen.TypeGenErr.fatal_error(val_node, "CDefine 值提取失败:无法从表达式解析编译期常量", "TypeError") + self.Gen.TypeGenErr.fatal_error(val_node, "CDefine value extraction failed: cannot parse a compile-time constant from the expression", "TypeError") # Case 3: Name - a registered CDefine constant or True/False literal if k == ast.ASTKind.Name: @@ -84,7 +84,7 @@ novirtual class AssignGenMixin: looked_up: int64 = self.Gen.TypeGenCDef.lookup_cdefine_constant(nm.id) if self.Gen.TypeGenCDef.is_cdefine_found() != 0: return looked_up # Unregistered reference: fail fast - self.Gen.TypeGenErr.fatal_error(val_node, "CDefine 值提取失败:无法从表达式解析编译期常量", "TypeError") + self.Gen.TypeGenErr.fatal_error(val_node, "CDefine value extraction failed: cannot parse a compile-time constant from the expression", "TypeError") # Case 4: Call - e.g. t.CUnsignedLong(-11) if k == ast.ASTKind.Call: @@ -96,7 +96,7 @@ novirtual class AssignGenMixin: arg_val: int64 = self.extract_cdefine_int_value(first_arg) return arg_val # Call with no args: fail fast - self.Gen.TypeGenErr.fatal_error(val_node, "CDefine 值提取失败:无法从表达式解析编译期常量", "TypeError") + self.Gen.TypeGenErr.fatal_error(val_node, "CDefine value extraction failed: cannot parse a compile-time constant from the expression", "TypeError") # Case 5: UnaryOp - e.g. -11 if k == ast.ASTKind.UnaryOp: @@ -106,10 +106,10 @@ novirtual class AssignGenMixin: if uop.op == ast.OpKind.UAdd: return operand_val if uop.op == ast.OpKind.Invert: return ~operand_val # Unknown UnaryOp operator: fail fast - self.Gen.TypeGenErr.fatal_error(val_node, "CDefine 值提取失败:无法从表达式解析编译期常量", "TypeError") + self.Gen.TypeGenErr.fatal_error(val_node, "CDefine value extraction failed: cannot parse a compile-time constant from the expression", "TypeError") # Unknown node kind: fail fast - self.Gen.TypeGenErr.fatal_error(val_node, "CDefine 值提取失败:无法从表达式解析编译期常量", "TypeError") + self.Gen.TypeGenErr.fatal_error(val_node, "CDefine value extraction failed: cannot parse a compile-time constant from the expression", "TypeError") # After fatal_error add an explicit return so the block is properly terminated return 0 @@ -309,7 +309,7 @@ novirtual class AssignGenMixin: bits: int = self._define_annot_bits(pool, annot) wmin: int = self.define_min_width(value) if self._int_text_exceeds_64(text) != 0: - self.Gen.TypeGenErr.fatal_error(node, f"[TPV] define 常量数值不可存储: 常量 '{name}' 的初始值 {text} 超出 64 位" f"(本语言最宽的整数类型为 64 位,按有符号/无符号两种解释的可存储范围为 " f"-9223372036854775808..18446744073709551615,不存在更宽的整数类型 ⇒ 需要扩容)。" f"禁止静默截断/降级,已终止编译。可用整数类型: int8/uint8、" f"int16/uint16、int32/uint32、int64/uint64" f"(或 int8/uint8/…/uint64、char、sizet)。" f"修法: 把值改到 64 位范围内,或为该数字引入更大的整数类型(扩容)。", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"[TPV] define constant value not storable: the initial value {text} of constant '{name}' exceeds 64 bits " f"(the widest integer type in this language is 64 bits; the storable range under both signed and unsigned interpretations is " f"-9223372036854775808..18446744073709551615; no wider integer type exists => widening is required). " f"Silent truncation/downgrade is forbidden; compilation aborted. Available integer types: int8/uint8, " f"int16/uint16, int32/uint32, int64/uint64 " f"(or int8/uint8/.../uint64, char, sizet). " f"Fix: move the value into the 64-bit range, or introduce a larger integer type for this number (widen).", "TypeError") return if bits == 0: return # Build the 32-bit bounds from overflow-safe literals (see define_min_width) @@ -324,7 +324,7 @@ novirtual class AssignGenMixin: hi = 65535 elif bits == 64: return if value < lo or value > hi: - self.Gen.TypeGenErr.fatal_error(node, f"[TPV] define 常量数值不可存储: 常量 '{name}' 的初始值 {value} 不可存储。" f"最小可容纳宽度 W_min: {wmin} 位;声明类型位宽 {bits} 位," f"该声明可存储范围: {lo}..{hi}。" f"禁止静默截断/降级,已终止编译。" f"修法: 把显式类型改为更宽的类型(如 int32 / int64 / uint64)," f"或修正该字面量。", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"[TPV] define constant value not storable: the initial value {value} of constant '{name}' is not storable. " f"Minimal storable width W_min: {wmin} bits; declared type width {bits} bits, " f"storable range of this declaration: {lo}..{hi}. " f"Silent truncation/downgrade is forbidden; compilation aborted. " f"Fix: widen the explicit type to a wider type (such as int32 / int64 / uint64), " f"or correct the literal.", "TypeError") def require_cdefine_use_width(self, pool: memhub.MemBuddy*, trans: HT.Translator*, target_annot: ast.AST*, value_node: ast.AST*) -> None: """Fail fast when a define constant is wider than its use-site type.""" @@ -340,7 +340,7 @@ novirtual class AssignGenMixin: if bits == 0: return wmin: int = self.define_min_width(cdef_val) if bits >= wmin: return - self.Gen.TypeGenErr.fatal_error(value_node, f"[TPV] define 常量使用处宽度不足: 常量 '{rn.id}' 的实际值 {cdef_val} " f"需要至少 {wmin} 位(最小可容纳宽度 W_min)," f"但使用处(变量声明注解)只提供 {bits} 位。" f"禁止静默截断/降级,已终止编译。" f"修法: 把变量声明注解加宽到至少 {wmin} 位(如 int{wmin}T / CUInt{wmin}T)," f"或改用更小的常量值。", "TypeError") + self.Gen.TypeGenErr.fatal_error(value_node, f"[TPV] define constant use-site width insufficient: the actual value {cdef_val} of constant '{rn.id}' " f"needs at least {wmin} bits (minimal storable width W_min), " f"but the use site (variable declaration annotation) provides only {bits} bits. " f"Silent truncation/downgrade is forbidden; compilation aborted. " f"Fix: widen the variable declaration annotation to at least {wmin} bits (such as int{wmin}T / CUInt{wmin}T), " f"or use a smaller constant value.", "TypeError") # _register_cdefine_from_value - register a CDefine constant (float or int) def _register_cdefine_from_value(self, pool: memhub.MemBuddy*, name: str, val_node: ast.AST*, annot: ast.AST* = None) -> None: @@ -373,13 +373,13 @@ novirtual class AssignGenMixin: if self._recover_cdefine_float(name, &rec_d) != 0: use_val = rec_d else: # Source recovery failed: fail fast to avoid registering a corrupted float - self.Gen.TypeGenErr.fatal_error(val_node, "CDefine 浮点值源文件恢复失败", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(val_node, "CDefine float value source-file recovery failed", "InternalCompilerError") return self.Gen.TypeGenCDef.register_cdefine_double(pool, name, use_val) return if val_node is None: # CDefine declaration without a value node: fail fast - self.Gen.TypeGenErr.fatal_error(None, f"CDefine 值提取失败:'{name}' 缺少初始值", "TypeError") + self.Gen.TypeGenErr.fatal_error(None, f"CDefine value extraction failed: '{name}' is missing an initial value", "TypeError") return val_fp: int64 = self.extract_cdefine_int_value(val_node) # Check storability before registering (source text >64-bit or explicit T too narrow => fail) @@ -729,7 +729,7 @@ novirtual class AssignGenMixin: if sv_s is not None: n_s: sizet = string.strlen(sv_s) if sizet(arr_count) < n_s: - self.Gen.TypeGenErr.fatal_error(list_node, f"字符串字面量长度 {n_s} 超过字符数组声明长度 {arr_count},不允许越界写入", "OverflowError") + self.Gen.TypeGenErr.fatal_error(list_node, f"string literal length {n_s} exceeds the declared char array length {arr_count}; out-of-bounds writes are forbidden", "OverflowError") for bi_s in range(n_s): bidx_s: mlirlite.Value* = mlirlite.const_int32(pool, bi_s) bp_s: mlirlite.Value* = mlirlite.build_gep_array(builder, arr_ty, elem_ty, array_alloca, bidx_s) @@ -741,7 +741,7 @@ novirtual class AssignGenMixin: # Element count exceeds declared length: fail fast (avoid out-of-range GEP writes) if arr_count > 0 and sizet(arr_count) < elts_count: - self.Gen.TypeGenErr.fatal_error(list_node, f"数组初始化元素数 {elts_count} 超过数组声明长度 {arr_count},不允许越界写入", "OverflowError") + self.Gen.TypeGenErr.fatal_error(list_node, f"array initializer element count {elts_count} exceeds the declared array length {arr_count}; out-of-bounds writes are forbidden", "OverflowError") # Emit GEP + store for each element for i in range(elts_count): @@ -756,7 +756,7 @@ novirtual class AssignGenMixin: if list_node is not None: src_line = list_node.lineno src_col = list_node.col_offset - self.Gen.TypeGenErr.fatal_error(list_node, f"全局数组初始化遇到空 AST 元素:{ctx_dbg}第 {i} 个元素为裸空指针(0)," f"但列表元素计数为 {elts_count}(元素与计数不一致)。" f"上层某处产生了空 AST 元素(列表字面量节点 {src_line}:{src_col} 的第 {i} 槽未被填充)," f"拒绝静默跳过/补零,已终止编译。", "ValueError") + self.Gen.TypeGenErr.fatal_error(list_node, f"global array initialization hit a null AST element: {ctx_dbg}element {i} is a bare null pointer (0), " f"but the list element count is {elts_count} (element and count mismatch). " f"somewhere upstream produced a null AST element (slot {i} of list-literal node {src_line}:{src_col} was not filled), " f"silently skipping/padding with zero is refused; compilation aborted.", "ValueError") return 1 # Object validity check (nonzero vptr): a zero vptr makes any virtual call read address 0 elem_vptr: uint64 = *((uint64*)(elem_node)) @@ -768,7 +768,7 @@ novirtual class AssignGenMixin: if list_node is not None: vt_line = list_node.lineno vt_col = list_node.col_offset - self.Gen.TypeGenErr.fatal_error(list_node, f"全局数组初始化遇到【对象无效】的 AST 元素(vptr 为 0):{ctx_vt}" f"第 {i} 个元素指针非 0(地址 {uint64(elem_node)})但其对象首字(vtable 指针)为 0," f"对它的任何虚调用(kind()/dump()/…) 都会在 `load [0+slot]` 处读地址 0。" f"列表字面量节点位置 {vt_line}:{vt_col},元素计数 {elts_count}。" f"上层某处产生了「未初始化 vptr 的 AST 节点」(典型源:深拷贝/整块拷贝只搬字段未搬 vptr)," f"拒绝继续,已终止编译。", "ValueError", vt_col) + self.Gen.TypeGenErr.fatal_error(list_node, f"global array initialization hit an invalid-object AST element (vptr is 0): {ctx_vt}" f"element {i} has a nonzero pointer (address {uint64(elem_node)}) but its object header (vtable pointer) is 0, " f"and any virtual call on it (kind()/dump()/...) reads address 0 at `load [0+slot]`. " f"list-literal node position {vt_line}:{vt_col}, element count {elts_count}. " f"somewhere upstream produced an AST node with an uninitialized vptr (typical source: a deep/block copy that moved only fields, not the vptr), " f"refusing to continue; compilation aborted.", "ValueError", vt_col) return 1 idx_val: mlirlite.Value* = mlirlite.const_int32(pool, i) elem_ptr: mlirlite.Value* = mlirlite.build_gep_array(builder, arr_ty, elem_ty, array_alloca, idx_val) @@ -784,7 +784,7 @@ novirtual class AssignGenMixin: elem_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, elem_node, None, 0, trans) if elem_val is None: # Element translation failed: fail fast to expose the upstream cause - self.Gen.TypeGenErr.fatal_error(elem_node, "全局数组初始化元素翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(elem_node, "global array initializer element translation failed", "TypeError") # Type coercion (e.g. i32 -> i8); Pointee is statically i64 so compare with != 0 store_val: mlirlite.Value* = elem_val if elem_ptr.Ty is not None and elem_ptr.Ty.Pointee != 0: store_val = self.Gen.ExprGenBase.coerce_to_type(builder, elem_val, elem_ptr.Ty.Pointee, elem_node) @@ -865,9 +865,9 @@ novirtual class AssignGenMixin: # translate_augassign - translate augmented assignment statements def const_assign_msg(self, kind: str, name: str, src_name: str) -> str: """Build the const-assignment error message used by const_assign_fail.""" - decl: str = "(注解含 t.CConst,声明处来源名未记录)" + decl: str = "(annotation contains t.CConst; the source name at the declaration was not recorded)" if src_name is not None: decl = f"t.CConst | {src_name}" - return GenApi.escape_fstring_copy(f"不能对 const 变量 '{name}' {kind}" f"(声明处类型(含 const):{decl}" f";修法:删掉该声明里的 const 描述符 / t.CConst,或改为声明时一次赋值、" f"之后只用非 const 的副本/中间量;const 对象在其作用域内禁止赋值、" f"增量赋值与元素赋值,且不会降级为警告)") + return GenApi.escape_fstring_copy(f"cannot assign to const variable '{name}' ({kind}); " f"declaration type (including const): {decl}" f"; fix: remove the const descriptor / t.CConst from the declaration, or assign once at the declaration " f"and afterwards use only non-const copies/temporaries; a const object forbids assignment, " f"augmented assignment and element assignment within its scope, and this never degrades to a warning") def const_assign_fail(self, node: ast.AST*, kind: str, name: str, src_name: str) -> int: """Fail fast when a const target is written.""" @@ -896,7 +896,7 @@ novirtual class AssignGenMixin: at_ca: ast.Attribute* = ast.Attribute*(target) if at_ca is not None and at_ca.attr is not None: if self.Gen.ExprGenAttr.attr_field_is_const(pool, trans, target) != 0: - self.const_assign_fail(target, "字段赋值", at_ca.attr, self.Gen.ExprGenAttr.attr_field_decl_src(pool, trans, target)) + self.const_assign_fail(target, "field assignment", at_ca.attr, self.Gen.ExprGenAttr.attr_field_decl_src(pool, trans, target)) # 1. Get the field pointer field_ptr: mlirlite.Value* = self.Gen.ExprGenAttr.get_attribute_ptr(builder, pool, mod, target, trans) @@ -909,7 +909,7 @@ novirtual class AssignGenMixin: if field_ptr.Ty is not None and field_ptr.Ty.Pointee != 0: target_ty = field_ptr.Ty.Pointee if target_ty is None: # fail-fast: field type missing, no i32 fallback - self.Gen.TypeGenErr.fatal_error(target, "字段类型信息缺失", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "field type information missing", "TypeError") # t.CVolatile field: both load and store carry the volatile qualifier vol_fa: int = self.Gen.ExprGenAttr.attr_field_is_volatile(pool, trans, target) # rawptr[t.CVolatile|T] base: field load/store also carry volatile @@ -919,25 +919,25 @@ novirtual class AssignGenMixin: cur_val: mlirlite.Value* = mlirlite.build_load(builder, target_ty, field_ptr, vol_fa) if cur_val is None: # fail-fast: attribute current value load failed - self.Gen.TypeGenErr.fatal_error(target, "无法加载 attribute 当前值", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "cannot load the current value of the attribute", "TypeError") # 3. Translate the RHS value rhs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, aug.value, None, 0, trans) if rhs_val is None: # fail-fast: RHS translation failed - self.Gen.TypeGenErr.fatal_error(target, "rhs 翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "rhs translation failed", "TypeError") # 4. Apply the binary op result: mlirlite.Value* = self._apply_aug_op(pool, builder, aug.op, cur_val, rhs_val, node, trans, target) if result is None: # fail-fast: attribute binary op failed - self.Gen.TypeGenErr.fatal_error(target, f"attribute 二元运算失败 op={aug.op}", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, f"attribute binary op failed op={aug.op}", "TypeError") # 5. Coerce the type and store result = self.Gen.ExprGenBase.coerce_to_type(builder, result, target_ty, node) if result is None: # fail-fast: type coercion failed - self.Gen.TypeGenErr.fatal_error(target, "类型对齐失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "type coercion failed", "TypeError") mlirlite.build_store(builder, result, field_ptr, vol_fa) return 0 @@ -955,12 +955,12 @@ novirtual class AssignGenMixin: if nm_ca.id is not None: ve_ca: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm_ca.id) if self.Gen.VarGen.var_is_const(ve_ca) != 0: - self.const_assign_fail(target, "的元素赋值", nm_ca.id, self.Gen.VarGen.var_annot_class_name(ve_ca)) + self.const_assign_fail(target, "element assignment", nm_ca.id, self.Gen.VarGen.var_annot_class_name(ve_ca)) elif sub_ca.value.kind() == ast.ASTKind.Attribute: at_ca2: ast.Attribute* = ast.Attribute*(sub_ca.value) if at_ca2.attr is not None: if self.Gen.ExprGenAttr.attr_field_is_const(pool, trans, sub_ca.value) != 0: - self.const_assign_fail(target, "的元素赋值", at_ca2.attr, self.Gen.ExprGenAttr.attr_field_decl_src(pool, trans, sub_ca.value)) + self.const_assign_fail(target, "element assignment", at_ca2.attr, self.Gen.ExprGenAttr.attr_field_decl_src(pool, trans, sub_ca.value)) # 1. Get the element pointer elem_ptr: mlirlite.Value* = self.Gen.ExprGenName.get_subscript_ptr(builder, pool, mod, target, trans) @@ -973,7 +973,7 @@ novirtual class AssignGenMixin: if elem_ptr.Ty is not None and elem_ptr.Ty.Pointee != 0: target_ty = elem_ptr.Ty.Pointee if target_ty is None: # fail-fast: element type missing, no i32 fallback - self.Gen.TypeGenErr.fatal_error(target, "元素类型信息缺失", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "element type information missing", "TypeError") # rawptr[t.CVolatile|T] base: p[i] load/store carry volatile when the base is resolvable vol_sa: int = 0 sub_aug: ast.Subscript* = ast.Subscript*(target) @@ -981,57 +981,57 @@ novirtual class AssignGenMixin: cur_val: mlirlite.Value* = mlirlite.build_load(builder, target_ty, elem_ptr, vol_sa) if cur_val is None: # fail-fast: element current value load failed - self.Gen.TypeGenErr.fatal_error(target, "无法加载 subscript 元素当前值", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "cannot load the current value of the subscript element", "TypeError") # 3. Translate the RHS value rhs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, aug.value, None, 0, trans) if rhs_val is None: # fail-fast: RHS translation failed - self.Gen.TypeGenErr.fatal_error(target, "rhs 翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "rhs translation failed", "TypeError") # 4. Apply the binary op result: mlirlite.Value* = self._apply_aug_op(pool, builder, aug.op, cur_val, rhs_val, node, trans, target) if result is None: # fail-fast: subscript binary op failed - self.Gen.TypeGenErr.fatal_error(target, f"subscript 二元运算失败 op={aug.op}", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, f"subscript binary op failed op={aug.op}", "TypeError") # 5. Coerce the type and store result = self.Gen.ExprGenBase.coerce_to_type(builder, result, target_ty, node) if result is None: # fail-fast: type coercion failed - self.Gen.TypeGenErr.fatal_error(target, "类型对齐失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "type coercion failed", "TypeError") mlirlite.build_store(builder, result, elem_ptr, vol_sa) return 0 # UnaryOp target: *p += v (deref augmented assignment: load, op, store back) if tk == ast.ASTKind.UnaryOp: uo_ag: ast.UnaryOp* = ast.UnaryOp*(target) - if uo_ag is None or uo_ag.operand is None: self.Gen.TypeGenErr.fatal_error(target, "增量赋值目标单目运算缺少操作数", "TypeError") + if uo_ag is None or uo_ag.operand is None: self.Gen.TypeGenErr.fatal_error(target, "augmented-assignment target unary op is missing an operand", "TypeError") if uo_ag.op != ast.OpKind.Deref: - self.Gen.TypeGenErr.fatal_error(target, "增量赋值目标只支持单目 '*' 解引用(&x / -x / ~x 不是合法左值)", "SyntaxError") + self.Gen.TypeGenErr.fatal_error(target, "augmented-assignment target supports only the unary '*' dereference (&x / -x / ~x are not valid lvalues)", "SyntaxError") pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder mod: mlirlite.LLVMModule* = trans.Module ptr_ag: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, uo_ag.operand, None, 0, trans) if ptr_ag is None or ptr_ag.Ty is None or self.Gen.ExprGenBase.is_ptr_type(ptr_ag.Ty) == 0: - self.Gen.TypeGenErr.fatal_error(target, "增量赋值 '*' 的操作数必须是指针类型(类型推断退化)", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "the operand of augmented-assignment '*' must be a pointer type (type inference degraded)", "TypeError") ty_ag: mlirlite.LLVMType* = ptr_ag.Ty.Pointee if ty_ag is None: - self.Gen.TypeGenErr.fatal_error(target, "解引用增量赋值的目标类型缺失(pointee 为空)", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "deref augmented-assignment target type missing (pointee is empty)", "TypeError") old_ag: mlirlite.Value* = mlirlite.build_load(builder, ty_ag, ptr_ag, 0) - if old_ag is None: self.Gen.TypeGenErr.fatal_error(target, "无法加载解引用当前值", "TypeError") + if old_ag is None: self.Gen.TypeGenErr.fatal_error(target, "cannot load the current dereferenced value", "TypeError") rhs_ag: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, aug.value, None, 0, trans) - if rhs_ag is None: self.Gen.TypeGenErr.fatal_error(target, "rhs 翻译失败", "TypeError") + if rhs_ag is None: self.Gen.TypeGenErr.fatal_error(target, "rhs translation failed", "TypeError") res_ag: mlirlite.Value* = self._apply_aug_op(pool, builder, aug.op, old_ag, rhs_ag, node, trans, target) - if res_ag is None: self.Gen.TypeGenErr.fatal_error(target, f"解引用二元运算失败 op={aug.op}", "TypeError") + if res_ag is None: self.Gen.TypeGenErr.fatal_error(target, f"deref binary op failed op={aug.op}", "TypeError") res_ag = self.Gen.ExprGenBase.coerce_to_type(builder, res_ag, ty_ag, node, trans) - if res_ag is None: self.Gen.TypeGenErr.fatal_error(target, "类型对齐失败", "TypeError") + if res_ag is None: self.Gen.TypeGenErr.fatal_error(target, "type coercion failed", "TypeError") mlirlite.build_store(builder, res_ag, ptr_ag, 0) return 0 if tk != ast.ASTKind.Name: # fail-fast: unsupported AugAssign target kind - self.Gen.TypeGenErr.fatal_error(target, "AugAssign 目标类型不支持,仅支持 Name/Attribute/Subscript/*解引用", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "AugAssign target type unsupported; only Name/Attribute/Subscript/*dereference are supported", "TypeError") nm: ast.Name* = ast.Name*(target) if nm is None or nm.id is None: return 0 @@ -1039,7 +1039,7 @@ novirtual class AssignGenMixin: # const variable: fail fast immediately ve_aug: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id) if self.Gen.VarGen.var_is_const(ve_aug) != 0: - self.const_assign_fail(target, "增量赋值", nm.id, self.Gen.VarGen.var_annot_class_name(ve_aug)) + self.const_assign_fail(target, "augmented assignment", nm.id, self.Gen.VarGen.var_annot_class_name(ve_aug)) # REPL session variable aug-assign: read slot, apply op, write slot and result area if trans.ReplCtx is not None and self.Gen.VarGen.repl_in_frag_entry_scope(trans) != 0: @@ -1068,7 +1068,7 @@ novirtual class AssignGenMixin: if target_alloca is not None: if target_alloca.Ty is None: # fail-fast: variable type missing, no i32 fallback - self.Gen.TypeGenErr.fatal_error(target, "变量类型信息缺失", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "variable type information missing", "TypeError") target_ty = target_alloca.Ty.Pointee cur_val = mlirlite.build_load(builder, target_ty, target_alloca, vol_aa) elif scope_type == 2: @@ -1081,19 +1081,19 @@ novirtual class AssignGenMixin: if target_alloca is not None: if target_alloca.Ty is None: # fail-fast: variable type missing, no i32 fallback - self.Gen.TypeGenErr.fatal_error(target, "变量类型信息缺失", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "variable type information missing", "TypeError") target_ty = target_alloca.Ty.Pointee cur_val = mlirlite.build_load(builder, target_ty, target_alloca, vol_aa) if cur_val is None: # fail-fast: target variable current value load failed - self.Gen.TypeGenErr.fatal_error(target, f"无法加载目标变量 '{nm.id}' 的当前值", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, f"cannot load the current value of target variable '{nm.id}'", "TypeError") # 3. Translate the RHS value rhs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, aug.value, None, 0, trans) if rhs_val is None: # fail-fast: RHS translation failed - self.Gen.TypeGenErr.fatal_error(target, "rhs 翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "rhs translation failed", "TypeError") # 3b. Operator overload: object += -> __iadd__, fall back to __add__ (locals only) if scope_type == 0 and target_alloca is not None: @@ -1124,7 +1124,7 @@ novirtual class AssignGenMixin: if coerced_aug is not None: aug_res = coerced_aug if aug_res is None or target_ty is None or self.Gen.ExprGenBase._same_agg_ty(pool, aug_res.Ty, target_ty) == 0: # fail-fast: overload return type mismatch, do not corrupt memory silently - self.Gen.TypeGenErr.fatal_error(node, "增量赋值运算符重载返回值类型与目标变量不匹配", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "augmented-assignment operator overload return type does not match the target variable", "TypeError") mlirlite.build_store(builder, aug_res, target_alloca, vol_aa) return 0 @@ -1132,13 +1132,13 @@ novirtual class AssignGenMixin: result: mlirlite.Value* = self._apply_aug_op(pool, builder, aug.op, cur_val, rhs_val, node, trans, target) if result is None: # fail-fast: binary op failed - self.Gen.TypeGenErr.fatal_error(target, f"对变量 '{nm.id}' 应用二元运算失败 op={aug.op}", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, f"applying binary op to variable '{nm.id}' failed op={aug.op}", "TypeError") # 5. Store the result result = self.Gen.ExprGenBase.coerce_to_type(builder, result, target_ty, node) if result is None: # fail-fast: type coercion failed - self.Gen.TypeGenErr.fatal_error(target, "类型对齐失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "type coercion failed", "TypeError") if scope_type == 1: # global variable @@ -1217,9 +1217,9 @@ novirtual class AssignGenMixin: msg_len: sizet = 640 msg_buf: str = stdlib.malloc(msg_len) if msg_buf is None: return ann_txt_x - if btd_nm_x is not None and btd_rs_x is not None: viperlib.snprintf(msg_buf, msg_len, "变量类型注解解析失败,变量名: %s,注解: %s。builtins 最后匹配: %s 展开为 %s,仍无法解析", nm_id, ann_txt_x, btd_nm_x, btd_rs_x) - elif btd_nm_x is not None: viperlib.snprintf(msg_buf, msg_len, "变量类型注解解析失败,变量名: %s,注解: %s。builtins 最后匹配: %s 未命中(builtins.vp 无该 typedef 或扫描未运行)", nm_id, ann_txt_x, btd_nm_x) - else: viperlib.snprintf(msg_buf, msg_len, "变量类型注解解析失败,变量名: %s,注解: %s。builtins 最后匹配: 未触发", nm_id, ann_txt_x) + if btd_nm_x is not None and btd_rs_x is not None: viperlib.snprintf(msg_buf, msg_len, "variable type annotation resolution failed, variable name: %s, annotation: %s. last builtins match: %s expanded to %s, still unresolvable", nm_id, ann_txt_x, btd_nm_x, btd_rs_x) + elif btd_nm_x is not None: viperlib.snprintf(msg_buf, msg_len, "variable type annotation resolution failed, variable name: %s, annotation: %s. last builtins match: %s missed (builtins.vp has no such typedef, or the scan did not run)", nm_id, ann_txt_x, btd_nm_x) + else: viperlib.snprintf(msg_buf, msg_len, "variable type annotation resolution failed, variable name: %s, annotation: %s. last builtins match: not triggered", nm_id, ann_txt_x) return msg_buf # translate_annassign_prescan - pre-create alloca for annotated vars @@ -1282,7 +1282,7 @@ novirtual class AssignGenMixin: self.Gen.TypeGenErr.fatal_error(aa, self._build_ann_fail_msg(pool, annot, nm.id), "TypeError") else: # fail-fast: AnnAssign must have an annotation - self.Gen.TypeGenErr.fatal_error(aa, f"AnnAssign 缺少类型注解,变量名: {nm.id}", "SyntaxError") + self.Gen.TypeGenErr.fatal_error(aa, f"AnnAssign is missing a type annotation, variable name: {nm.id}", "SyntaxError") # Ensure the full cross-module struct definition is available (for alloca) self.Gen.StructGen.ensure_struct_def_in_module(pool, trans.Module, var_ty) @@ -1352,7 +1352,7 @@ novirtual class AssignGenMixin: vt_short_ff: str = vt_nm_ff + vt_pf_ff if vt_pf_ff != 0 else vt_nm_ff if string.strchr(vt_short_ff, '[') is not None: return 0 # With type args: not degraded - self.Gen.TypeGenErr.fatal_error(aa, f"变量 '{var_name}' 的泛型注解 '{base_nm_ff.id}[...]' 解析成了裸基类 " f"'{vt_nm_ff}*'(丢失类型实参);后续 .get()/.set() 会按错误元素类型" f"特化(如 list[int].get 返回 i32)→ inttoptr 截断指针崩溃。" f"禁止静默继续——请检查该注解在 resolve_annotation_type 中的退化点。", "TypeError") + self.Gen.TypeGenErr.fatal_error(aa, f"the generic annotation '{base_nm_ff.id}[...]' of variable '{var_name}' resolved to a bare base class " f"'{vt_nm_ff}*' (type arguments lost); subsequent .get()/.set() will specialize by the wrong element " f"type (such as list[int].get returning i32) -> inttoptr truncates the pointer and crashes. " f"Silent continuation is forbidden -- check the degradation point of this annotation in resolve_annotation_type.", "TypeError") return 0 def translate_annassign(self, trans: HT.Translator*, node: ast.AST*) -> int: @@ -1395,9 +1395,9 @@ novirtual class AssignGenMixin: dup_decl: int = 0 if GenApi.is_global_name(trans, nm.id) != 0 or GenApi.is_nonlocal_name(trans, nm.id) != 0: dup_decl = 1 if dup_decl != 0: - self.Gen.TypeGenErr.fatal_error(aa, f"重复声明:'{nm.id}' 已是模块级变量,此处声明 global/nonlocal 之后" f"又用类型注解重新声明。请删除本行的类型注解,直接赋值即可修改全局", "TypeError") + self.Gen.TypeGenErr.fatal_error(aa, f"duplicate declaration: '{nm.id}' is already a module-level variable; after declaring global/nonlocal here " f"it is re-declared with a type annotation. Remove the type annotation on this line; a plain assignment modifies the global", "TypeError") else: - self.Gen.TypeGenErr.fatal_error(aa, f"重复声明:'{nm.id}' 已是模块级变量,函数内未声明 global 时不得再用" f"类型注解声明同名变量(会把全局遮蔽为局部)。如需独立局部变量请换名;" f"如需修改全局请在函数内加 global 声明并删除本行注解", "TypeError") + self.Gen.TypeGenErr.fatal_error(aa, f"duplicate declaration: '{nm.id}' is already a module-level variable; without a global declaration in a function, a type annotation must not re-declare " f"the same name (it would shadow the global with a local). For an independent local, use another name; " f"to modify the global, add a global declaration in the function and remove this annotation", "TypeError") pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder @@ -1416,11 +1416,11 @@ novirtual class AssignGenMixin: self.Gen.TypeGenErr.fatal_error(aa, self._build_ann_fail_msg(pool, annot, nm.id), "TypeError") else: # fail-fast: AnnAssign must have an annotation - self.Gen.TypeGenErr.fatal_error(aa, f"AnnAssign 缺少类型注解,变量名: {nm.id}", "SyntaxError") + self.Gen.TypeGenErr.fatal_error(aa, f"AnnAssign is missing a type annotation, variable name: {nm.id}", "SyntaxError") # void cannot be a variable type (only void* and opaque-struct typedef) if var_ty is not None and self.Gen.StmtGenDecl._is_void_type(var_ty) != 0: - self.Gen.TypeGenErr.fatal_error(aa, f"不能声明 void 类型的变量 '{nm.id}'(void 只能用于 void* 与 typedef 别名)", "TypeError") + self.Gen.TypeGenErr.fatal_error(aa, f"cannot declare a variable of void type '{nm.id}' (void may only be used for void* and typedef aliases)", "TypeError") # t.Callable function pointer: register the return-type signature callable_ret: mlirlite.LLVMType* = self.Gen.TypeGenErr.try_extract_callable_ret(pool, annot, trans._imported_modules, trans._from_imports, trans) @@ -1442,7 +1442,7 @@ novirtual class AssignGenMixin: # Set CurAssignAnnot/CurAssignNode before translating the RHS (kept in sync across all four branches) trans.CurAssignAnnot = aa.annotation trans.CurAssignNode = aa.value - rhs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, aa.value, None, 0, trans, aa_glob_ty, "模块级全局") + rhs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, aa.value, None, 0, trans, aa_glob_ty, "module-level global") if rhs_val is not None: # Object global with static storage: bind storage and copy the object stg_ref_aa: mlirlite.Value* = None @@ -1492,12 +1492,12 @@ novirtual class AssignGenMixin: # Set CurAssignAnnot/CurAssignNode before translating the RHS (sync across all four branches) trans.CurAssignAnnot = aa.annotation trans.CurAssignNode = aa.value - rhs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, aa.value, None, 0, trans, nl_target_ty, "闭包变量(nonlocal)") + rhs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, aa.value, None, 0, trans, nl_target_ty, "closure variable (nonlocal)") if rhs_val is not None: if nl_ptr is not None: if nl_target_ty is None: # fail-fast: nl_ptr type lost, cannot store safely - VLogger.error(f"nonlocal 变量类型信息丢失,无法写入: {nm.id}", "HandlesAnnAssign") + VLogger.error(f"nonlocal variable type information lost, cannot write: {nm.id}", "HandlesAnnAssign") # Clear the assignment context before returning (avoid leaking into later statements) trans.CurAssignAnnot = None trans.CurAssignNode = None @@ -1524,7 +1524,7 @@ novirtual class AssignGenMixin: # Set CurAssignAnnot/CurAssignNode before translating the RHS (sync across all four branches) trans.CurAssignAnnot = aa.annotation trans.CurAssignNode = aa.value - rhs_val_mg: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, aa.value, None, 0, trans, mg_val_ty, "模块级全局") + rhs_val_mg: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, aa.value, None, 0, trans, mg_val_ty, "module-level global") if rhs_val_mg is not None: # Object global with static storage: bind storage and copy the object stg_ref_mg: mlirlite.Value* = None @@ -1572,7 +1572,7 @@ novirtual class AssignGenMixin: alloca: mlirlite.Value* = self.Gen.VarGen.get_or_create_sym(trans.SymTab, pool, builder, nm.id, var_ty) if alloca is None: # fail-fast: storage creation failed - self.Gen.TypeGenErr.fatal_error(aa, f"无法为变量 {nm.id} 创建存储", "TypeError") + self.Gen.TypeGenErr.fatal_error(aa, f"cannot create storage for variable {nm.id}", "TypeError") # A reused alloca type must match the resolved annotation type (compare struct names) if alloca is not None and alloca.Ty is not None and var_ty is not None: av_pt_d: mlirlite.LLVMType* = alloca.Ty.Pointee @@ -1589,7 +1589,7 @@ novirtual class AssignGenMixin: if string.strchr(av_short, '[') is None: av_tpl: ast.ClassDef* = self.Gen.ClassGenGeneric._find_generic_template(av_short) if av_tpl is not None: - self.Gen.TypeGenErr.fatal_error(aa, f"变量 '{nm.id}' 复用到的存储类型为裸泛型基类 '{av_nm_d}*'" f"(丢了类型实参),与注解解析类型 '{vt_nm_d}*' 不一致;" f"禁止静默混用——方法调用会按错误元素类型特化并截断指针", "TypeError") + self.Gen.TypeGenErr.fatal_error(aa, f"the reused storage type of variable '{nm.id}' is the bare generic base class '{av_nm_d}*'" f" (type arguments lost), inconsistent with the annotation-resolved type '{vt_nm_d}*'; " f"silent mixing is forbidden -- method calls would specialize by the wrong element type and truncate the pointer", "TypeError") # FakeDuck: a str variable gets a shadow struct {var}__meta__ for per-instance fields fd_str_ty: mlirlite.LLVMType* = None @@ -1608,7 +1608,7 @@ novirtual class AssignGenMixin: fd_meta_alloca = self.Gen.VarGen.get_or_create_sym(trans.SymTab, pool, builder, fd_meta_name, fd_str_ty) if fd_meta_alloca is None: # fail-fast: shadow storage creation failed - self.Gen.TypeGenErr.fatal_error(aa, f"无法为 str 影子变量 {fd_meta_name} 创建存储", "TypeError") + self.Gen.TypeGenErr.fatal_error(aa, f"cannot create storage for the str shadow variable {fd_meta_name}", "TypeError") # Store the annotation's class name; pass pool so generic Subscript yields the mangled name if annot is not None: cls_nm_hd: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(annot, trans._imported_modules, pool, trans._from_imports) @@ -1656,7 +1656,7 @@ novirtual class AssignGenMixin: # P1-A: use the local alloca pointee as the target type so integer literals materialize at target width lv_target_ty: mlirlite.LLVMType* = None if alloca.Ty is not None: lv_target_ty = alloca.Ty.Pointee - rhs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, aa.value, None, 0, trans, lv_target_ty, "局部变量注解") + rhs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, aa.value, None, 0, trans, lv_target_ty, "local variable annotation") if rhs_val is not None: # Fix degraded annotation: rebuild the alloca with the precise RHS struct type precise_rhs_ty: mlirlite.LLVMType* = None @@ -1785,12 +1785,12 @@ novirtual class AssignGenMixin: if nm_c.id is None: continue ve_c: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm_c.id) if self.Gen.VarGen.var_is_const(ve_c) != 0: - self.const_assign_fail(tgt_c, "赋值", nm_c.id, self.Gen.VarGen.var_annot_class_name(ve_c)) + self.const_assign_fail(tgt_c, "assignment", nm_c.id, self.Gen.VarGen.var_annot_class_name(ve_c)) elif tgt_c.kind() == ast.ASTKind.Attribute: at_c: ast.Attribute* = ast.Attribute*(tgt_c) if at_c.attr is None: continue if self.Gen.ExprGenAttr.attr_field_is_const(pool, trans, tgt_c) != 0: - self.const_assign_fail(tgt_c, "字段赋值", at_c.attr, self.Gen.ExprGenAttr.attr_field_decl_src(pool, trans, tgt_c)) + self.const_assign_fail(tgt_c, "field assignment", at_c.attr, self.Gen.ExprGenAttr.attr_field_decl_src(pool, trans, tgt_c)) elif tgt_c.kind() == ast.ASTKind.Subscript: sub_c: ast.Subscript* = ast.Subscript*(tgt_c) if sub_c.value is None: continue @@ -1799,23 +1799,23 @@ novirtual class AssignGenMixin: if nm_c2.id is None: continue ve_c2: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm_c2.id) if self.Gen.VarGen.var_is_const(ve_c2) != 0: - self.const_assign_fail(tgt_c, "的元素赋值", nm_c2.id, self.Gen.VarGen.var_annot_class_name(ve_c2)) + self.const_assign_fail(tgt_c, "element assignment", nm_c2.id, self.Gen.VarGen.var_annot_class_name(ve_c2)) elif sub_c.value.kind() == ast.ASTKind.Attribute: at_c2: ast.Attribute* = ast.Attribute*(sub_c.value) if at_c2.attr is None: continue if self.Gen.ExprGenAttr.attr_field_is_const(pool, trans, sub_c.value) != 0: - self.const_assign_fail(tgt_c, "的元素赋值", at_c2.attr, self.Gen.ExprGenAttr.attr_field_decl_src(pool, trans, sub_c.value)) + self.const_assign_fail(tgt_c, "element assignment", at_c2.attr, self.Gen.ExprGenAttr.attr_field_decl_src(pool, trans, sub_c.value)) # f-string escape: results are function-local temporaries; writing them out is dangling for ti_f in range(len(targets)): tgt_f: ast.AST* = targets.get(ti_f) if tgt_f is None: continue tk_f: int = tgt_f.kind() - if tk_f == ast.ASTKind.Attribute: GenApi.fail_if_fstring_escape(asgn.value, "字段赋值") - elif tk_f == ast.ASTKind.Subscript: GenApi.fail_if_fstring_escape(asgn.value, "元素赋值") + if tk_f == ast.ASTKind.Attribute: GenApi.fail_if_fstring_escape(asgn.value, "field assignment") + elif tk_f == ast.ASTKind.Subscript: GenApi.fail_if_fstring_escape(asgn.value, "element assignment") elif tk_f == ast.ASTKind.Name: nm_f: ast.Name* = ast.Name*(tgt_f) - if nm_f.id is not None and GenApi.is_global_name(trans, nm_f.id) != 0: GenApi.fail_if_fstring_escape(asgn.value, "全局变量赋值") + if nm_f.id is not None and GenApi.is_global_name(trans, nm_f.id) != 0: GenApi.fail_if_fstring_escape(asgn.value, "global variable assignment") # Translate the RHS; clear CurAssignAnnot/CurAssignNode (no target type to infer here) trans.CurAssignAnnot = None @@ -1839,8 +1839,8 @@ novirtual class AssignGenMixin: # RHS is None usually means allocation failure; dump both pool statistics mb_diag: memhub.MemBuddy* = CompilerFactory.factory.Pool pp_diag: memhub.MemBuddy* = CompilerFactory.factory.PermPool - if mb_diag is not None: mb_diag.dump_stats("主池(Pool)") - if pp_diag is not None: pp_diag.dump_stats("常驻池(PermPool)") + if mb_diag is not None: mb_diag.dump_stats("Main Pool(Pool)") + if pp_diag is not None: pp_diag.dump_stats("Permanent Pool(PermPool)") stdio.fflush(None) # Enhanced error message: file name + lineno + AST node details if asgn.value is not None: @@ -1859,12 +1859,12 @@ novirtual class AssignGenMixin: if at_nv.value.kind() == ast.ASTKind.Name: tn_nm: ast.Name* = ast.Name*(at_nv.value) target_nm = tn_nm.id - if rel_path is not None: VLogger.error(f"赋值右侧为 None: {rel_path}:{val_line} '{target_nm}.{attr_nm}' 属性访问失败", "ASGN") - else: VLogger.error(f"赋值右侧为 None: sha1={sha1}:{val_line} '{target_nm}.{attr_nm}' 属性访问失败", "ASGN") + if rel_path is not None: VLogger.error(f"assignment rhs is None: {rel_path}:{val_line} attribute access of '{target_nm}.{attr_nm}' failed", "ASGN") + else: VLogger.error(f"assignment rhs is None: sha1={sha1}:{val_line} attribute access of '{target_nm}.{attr_nm}' failed", "ASGN") elif val_kind == ast.ASTKind.Name: nm_nv: ast.Name* = ast.Name*(asgn.value) - if rel_path is not None: VLogger.error(f"赋值右侧为 None: {rel_path}:{val_line} 变量 '{nm_nv.id}' 未找到", "ASGN") - else: VLogger.error(f"赋值右侧为 None: sha1={sha1}:{val_line} 变量 '{nm_nv.id}' 未找到", "ASGN") + if rel_path is not None: VLogger.error(f"assignment rhs is None: {rel_path}:{val_line} variable '{nm_nv.id}' not found", "ASGN") + else: VLogger.error(f"assignment rhs is None: sha1={sha1}:{val_line} variable '{nm_nv.id}' not found", "ASGN") elif val_kind == ast.ASTKind.Call: cl_nv: ast.Call* = ast.Call*(asgn.value) func_nm: str = "?" @@ -1872,12 +1872,12 @@ novirtual class AssignGenMixin: if cl_nv.func.kind() == ast.ASTKind.Name: fn_nm: ast.Name* = ast.Name*(cl_nv.func) func_nm = fn_nm.id - if rel_path is not None: VLogger.error(f"赋值右侧为 None: {rel_path}:{val_line} 调用 '{func_nm}(...)' 返回 None", "ASGN") - else: VLogger.error(f"赋值右侧为 None: sha1={sha1}:{val_line} 调用 '{func_nm}(...)' 返回 None", "ASGN") + if rel_path is not None: VLogger.error(f"assignment rhs is None: {rel_path}:{val_line} call '{func_nm}(...)' returned None", "ASGN") + else: VLogger.error(f"assignment rhs is None: sha1={sha1}:{val_line} call '{func_nm}(...)' returned None", "ASGN") else: - if rel_path is not None: VLogger.error(f"赋值右侧为 None: {rel_path}:{val_line} [kind={val_kind}]") - else: VLogger.error(f"赋值右侧为 None: sha1={sha1}:{val_line} [kind={val_kind}]") - else: VLogger.error("赋值右侧为 None (asgn.value 为空)", "ASGN") + if rel_path is not None: VLogger.error(f"assignment rhs is None: {rel_path}:{val_line} [kind={val_kind}]") + else: VLogger.error(f"assignment rhs is None: sha1={sha1}:{val_line} [kind={val_kind}]") + else: VLogger.error("assignment rhs is None (asgn.value is empty)", "ASGN") return 0 new_vars: int = 0 @@ -1910,7 +1910,7 @@ novirtual class AssignGenMixin: fcur = mlirlite.paramnode_get_next(fcur) if fty is None: # fail-fast: field type missing - self.Gen.TypeGenErr.fatal_error(target, "元组解包字段类型缺失", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "tuple-unpack field type missing", "TypeError") # Guard: skip non-Name elements (cannot unpack) if tgt_elt.kind() != ast.ASTKind.Name: continue tgt_nm2: ast.Name* = ast.Name*(tgt_elt) @@ -1939,7 +1939,7 @@ novirtual class AssignGenMixin: list_idx_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub_node.slice, None, 0, trans) if list_idx_val is None: # fail-fast: list index translation failed - self.Gen.TypeGenErr.fatal_error(target, "list 下标翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "list index translation failed", "TypeError") self.Gen.ExprGenName.list_setitem_inline(builder, pool, list_obj, list_idx_val, rhs_val, target) continue # Ordinary Subscript assignment @@ -2038,15 +2038,15 @@ novirtual class AssignGenMixin: # UnaryOp target: *p = val (deref write); only Deref is a valid lvalue, others fail fast if tk == ast.ASTKind.UnaryOp: uo_w: ast.UnaryOp* = ast.UnaryOp*(target) - if uo_w is None or uo_w.operand is None: self.Gen.TypeGenErr.fatal_error(target, "赋值目标单目运算缺少操作数", "TypeError") + if uo_w is None or uo_w.operand is None: self.Gen.TypeGenErr.fatal_error(target, "assignment target unary op is missing an operand", "TypeError") if uo_w.op != ast.OpKind.Deref: - self.Gen.TypeGenErr.fatal_error(target, "赋值目标只支持单目 '*' 解引用(&x / -x / ~x 不是合法左值)", "SyntaxError") + self.Gen.TypeGenErr.fatal_error(target, "assignment target supports only the unary '*' dereference (&x / -x / ~x are not valid lvalues)", "SyntaxError") ptr_w: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, uo_w.operand, None, 0, trans) if ptr_w is None or ptr_w.Ty is None or self.Gen.ExprGenBase.is_ptr_type(ptr_w.Ty) == 0: - self.Gen.TypeGenErr.fatal_error(target, "单目 '*' 赋值的操作数必须是指针类型(类型推断退化)", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "the operand of unary '*' assignment must be a pointer type (type inference degraded)", "TypeError") pointee_w: mlirlite.LLVMType* = ptr_w.Ty.Pointee if pointee_w is None: - self.Gen.TypeGenErr.fatal_error(target, "解引用写入的目标类型缺失(pointee 为空)", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, "deref write target type missing (pointee is empty)", "TypeError") sv_w: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, pointee_w, node, trans) mlirlite.build_store(builder, sv_w, ptr_w) continue @@ -2118,7 +2118,7 @@ novirtual class AssignGenMixin: mod_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm.id) if mod_alloca is None: # fail-fast: global variable not registered - self.Gen.TypeGenErr.fatal_error(target, f"global 变量 '{nm.id}' 未注册,无法赋值", "NameError") + self.Gen.TypeGenErr.fatal_error(target, f"global variable '{nm.id}' is not registered; cannot assign", "NameError") # Object global with static storage: bind to storage and copy the object (else dangling/NULL) stg_ref_as: mlirlite.Value* = None if nm.id is not None: @@ -2155,13 +2155,13 @@ novirtual class AssignGenMixin: nl_ptr: mlirlite.Value* = self.Gen.StmtGenDecl.get_nonlocal_var_ptr(trans, nm.id) if nl_ptr is None: # fail-fast: nonlocal variable pointer resolution failed - self.Gen.TypeGenErr.fatal_error(target, f"nonlocal 变量 '{nm.id}' 指针解析失败", "NameError") + self.Gen.TypeGenErr.fatal_error(target, f"nonlocal variable '{nm.id}' pointer resolution failed", "NameError") # Infer the nonlocal type from nl_ptr instead of forcing i32 nl_target_ty: mlirlite.LLVMType* = None if nl_ptr.Ty is not None: nl_target_ty = nl_ptr.Ty.Pointee if nl_target_ty is None: # fail-fast: nl_ptr type lost, cannot store safely - self.Gen.TypeGenErr.fatal_error(target, f"nonlocal 变量 '{nm.id}' 类型信息丢失,无法写入", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, f"nonlocal variable '{nm.id}' type information lost; cannot write", "TypeError") rhs_coerced: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, nl_target_ty, node, trans) mlirlite.build_store(builder, rhs_coerced, nl_ptr) continue @@ -2176,7 +2176,7 @@ novirtual class AssignGenMixin: # Block assignment to a module-level global inside a function without a global declaration if self.Gen.VarGen.is_module_scope(trans.SymTab) == 0: mod_gv: mlirlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm.id) - if mod_gv is not None: self.Gen.TypeGenErr.fatal_error(target, f"变量 '{nm.id}' 是模块级全局变量,函数内赋值需用 global 声明(否则创建局部变量遮蔽全局,导致全局保持 null 崩溃)", "SyntaxError") + if mod_gv is not None: self.Gen.TypeGenErr.fatal_error(target, f"variable '{nm.id}' is a module-level global; assignment inside a function requires a global declaration (otherwise a local variable shadows the global, leaving it null and crashing)", "SyntaxError") # Ordinary local variable alloca: mlirlite.Value* = self.Gen.VarGen.get_or_create_sym(trans.SymTab, pool, builder, nm.id, rhs_val.Ty) @@ -2196,7 +2196,7 @@ novirtual class AssignGenMixin: if existing is None: new_vars += 1 else: # fail-fast: variable storage creation failed - self.Gen.TypeGenErr.fatal_error(target, f"变量 '{nm.id}' 存储创建失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(target, f"variable '{nm.id}' storage creation failed", "TypeError") return new_vars @@ -2228,7 +2228,7 @@ novirtual class AssignGenMixin: # Array slots (t.CArray[T,N]) are legal; only block when the base is a pointer store if self.Gen.ExprGenName.subscript_base_store_kind(pool, trans, target) != 0: return elem_nm_wo: str = mlirlite.get_struct_name(elem_ty) - if elem_nm_wo is None: elem_nm_wo = "<匿名结构体>" + if elem_nm_wo is None: elem_nm_wo = "" rhs_nm_wo: str = mlirlite.get_struct_name(rhs_inner_wo) if rhs_nm_wo is None: rhs_nm_wo = elem_nm_wo elem_sz_wo: int = self.Gen.ClassGenEnum._get_type_size(elem_ty) @@ -2240,7 +2240,7 @@ novirtual class AssignGenMixin: if target is not None: col_s_wo = target.col_offset + 1 col_e_wo = target.end_col_offset + 1 - self.Gen.TypeGenErr.fatal_error(target, f"下标赋值的左值元素是对象 '{elem_nm_wo}'({elem_sz_wo} 字节)," f"右值却是指向 '{rhs_nm_wo}' 的指针:编译器会静默生成整对象拷贝" f"(load {elem_nm_wo} + store {elem_nm_wo},写 {elem_sz_wo} 字节)," f"而不是按指针写 {ptr_sz_wo} 字节。若该地址实际按 8 字节槽存放指针" f"(如 rawptr[T] 缓冲/空闲链表),每写一个元素就越界 {over_wo} 字节," f"直接写穿相邻块。修法:把指针槽的基座类型写成指针元素形态" f"(`rawptr[T]*` 或 `rawptr[rawptr[T]]`)后再赋值;" f"或把基座显式转为 t.CPtr(无类型指针)后按 8 字节指针语义写入。", "TypeError", col_s_wo, col_e_wo) + self.Gen.TypeGenErr.fatal_error(target, f"the lvalue element of the subscript assignment is object '{elem_nm_wo}' ({elem_sz_wo} bytes), " f"but the rhs is a pointer to '{rhs_nm_wo}': the compiler would silently emit a whole-object copy " f"(load {elem_nm_wo} + store {elem_nm_wo}, writing {elem_sz_wo} bytes), " f"instead of writing {ptr_sz_wo} bytes as a pointer. If that address actually stores pointers in 8-byte slots " f"(such as a rawptr[T] buffer/free list), every element written overflows by {over_wo} bytes, " f"writing through adjacent blocks. Fix: declare the base type of the pointer slot in pointer-element form " f"(`rawptr[T]*` or `rawptr[rawptr[T]]`) before assigning; " f"or explicitly cast the base to t.CPtr (untyped pointer) and write with 8-byte pointer semantics.", "TypeError", col_s_wo, col_e_wo) # _infer_rhs_annot - infer a variable's annotation class name from the RHS expression def _infer_rhs_annot(self, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, trans: HT.Translator*, rhs_val: mlirlite.Value* = None) -> str: diff --git a/App/lib/core/Gen/AsyncGenMixin.vp b/App/lib/core/Gen/AsyncGenMixin.vp index 9348f1d..723743b 100644 --- a/App/lib/core/Gen/AsyncGenMixin.vp +++ b/App/lib/core/Gen/AsyncGenMixin.vp @@ -277,7 +277,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if self._is_range_for(stmt) == 0: err_b2: str = trans.Pool.alloc(256) if err_b2 is not None: - viperlib.snprintf(err_b2, 256, "[coro-M3] 协程内 For 仅支持 range 迭代(含 await)") + viperlib.snprintf(err_b2, 256, "[coro-M3] For inside a coroutine supports only range iteration (including await)") self.Gen.TypeGenErr.fatal_error(stmt, err_b2, "SyntaxError") return # fill __f_idx_N / __f_len_N (i32) @@ -961,7 +961,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if call_name is None: call_name = "(unknown)" err_buf: str = pool.alloc(256) if err_buf is not None: - viperlib.snprintf(err_buf, 256, "[coro-M2] await 目标 '%s' 不是 async 函数", call_name) + viperlib.snprintf(err_buf, 256, "[coro-M2] await target '%s' is not an async function", call_name) self.Gen.TypeGenErr.fatal_error(stmt, err_buf, "SyntaxError") continue # nested await in the statement -> hoist to __await_N @@ -979,7 +979,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if self._find_expr_await(ifn.test) is not None: err_b: str = pool.alloc(256) if err_b is not None: - viperlib.snprintf(err_b, 256, "[coro-M2] if 条件中不支持 await") + viperlib.snprintf(err_b, 256, "[coro-M2] await is not supported in an if condition") self.Gen.TypeGenErr.fatal_error(stmt, err_b, "SyntaxError") return cond: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, ifn.test, None, 0, trans) @@ -1013,7 +1013,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if whn.test is not None and self._find_expr_await(whn.test) is not None: err_c: str = pool.alloc(256) if err_c is not None: - viperlib.snprintf(err_c, 256, "[coro-M2] while 条件中不支持 await") + viperlib.snprintf(err_c, 256, "[coro-M2] await is not supported in a while condition") self.Gen.TypeGenErr.fatal_error(stmt, err_c, "SyntaxError") return func: mlirlite.Function* = trans._cur_func @@ -1421,7 +1421,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if nhandlers == 0: err_t: str = pool.alloc(256) if err_t is not None: - viperlib.snprintf(err_t, 256, "[coro-M6] 协程内 try 需要 except 子句") + viperlib.snprintf(err_t, 256, "[coro-M6] try inside a coroutine requires an except clause") self.Gen.TypeGenErr.fatal_error(stmt, err_t, "SyntaxError") return func: mlirlite.Function* = trans._cur_func @@ -1531,7 +1531,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if tr.finalbody is not None and self._stmts_deep_await(tr.finalbody) != 0: err_f: str = pool.alloc(256) if err_f is not None: - viperlib.snprintf(err_f, 256, "[coro-M7] finally 内暂不支持 await") + viperlib.snprintf(err_f, 256, "[coro-M7] await is not yet supported inside finally") self.Gen.TypeGenErr.fatal_error(stmt, err_f, "SyntaxError") return func: mlirlite.Function* = trans._cur_func @@ -1566,7 +1566,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if self._is_range_for(stmt) == 0: err_g: str = pool.alloc(256) if err_g is not None: - viperlib.snprintf(err_g, 256, "[coro-M3] 协程内 For 仅支持 range 迭代(含 await)") + viperlib.snprintf(err_g, 256, "[coro-M3] For inside a coroutine supports only range iteration (including await)") self.Gen.TypeGenErr.fatal_error(stmt, err_g, "SyntaxError") return fn: ast.For* = ast.For*(stmt) diff --git a/App/lib/core/Gen/Call/CallGenBase.vp b/App/lib/core/Gen/Call/CallGenBase.vp index e03e917..b49b94b 100644 --- a/App/lib/core/Gen/Call/CallGenBase.vp +++ b/App/lib/core/Gen/Call/CallGenBase.vp @@ -502,7 +502,7 @@ novirtual class CallGenBase: while existing is not None: existing_steps += 1 if existing_steps > DECLARE_CHAIN_LIMIT: - stdio.printf("[CALLGEN] 链表异常: module funcs(call_name=%s,遍历超限,终止)\n", call_name) + stdio.printf("[CALLGEN] linked-list anomaly: module funcs (call_name=%s, traversal limit exceeded, aborting)\n", call_name) # converge: longjmp back to the REPL loop (diagnostic already printed) VLogger.repl_abort() if existing.Name is not None: @@ -519,7 +519,7 @@ novirtual class CallGenBase: while cur_p is not None: cur_count += 1 if cur_count > DECLARE_CHAIN_LIMIT: - stdio.printf("[CALLGEN] 链表异常: func params(call_name=%s,参数链遍历超限,终止)\n", call_name) + stdio.printf("[CALLGEN] linked-list anomaly: func params (call_name=%s, param chain traversal limit exceeded, aborting)\n", call_name) # converge: longjmp back to the REPL loop (diagnostic already printed) VLogger.repl_abort() cur_p = cur_p.Next @@ -665,8 +665,8 @@ novirtual class CallGenBase: # ============================================================ def _fail_method_ret_ty(self, method_name: str, node: ast.AST* = None) -> mlirlite.LLVMType*: """Fail fast when a method return type cannot be resolved precisely (module function, text.ll define, then vpi cache); never default to i32.""" - VLogger.error(f"方法返回类型无法精确获取(函数/text.ll/vpi stub 均未命中): {method_name}", "HandlesExprCall") - self.Gen.TypeGenErr.fatal_error(node, f"方法返回类型无法精确获取,默认 i32 会截断指针/i64: {method_name}", "TypeError") + VLogger.error(f"method return type cannot be obtained precisely (function/text.ll/vpi stub all missed): {method_name}", "HandlesExprCall") + self.Gen.TypeGenErr.fatal_error(node, f"method return type cannot be obtained precisely; defaulting to i32 would truncate pointers/i64: {method_name}", "TypeError") return None # SetTempDir: set the temp dir path (called before Phase A to read dependency text.ll) diff --git a/App/lib/core/Gen/Call/CallGenCBuiltin.vp b/App/lib/core/Gen/Call/CallGenCBuiltin.vp index 88b5162..a1b1401 100644 --- a/App/lib/core/Gen/Call/CallGenCBuiltin.vp +++ b/App/lib/core/Gen/Call/CallGenCBuiltin.vp @@ -48,7 +48,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): pointee: mlirlite.LLVMType* = ptr_val.Ty.Pointee if pointee is not None: return mlirlite.build_load(builder, pointee, ptr_val, vol_deref) # Non-pointer arg means degraded type inference: fail-fast, never read as i8. - self.Gen.TypeGenErr.fatal_error(cl, "c.Deref 参数不是指针类型(类型推断退化)", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, "c.Deref argument is not a pointer type (type inference degraded)", "TypeError") return None @@ -114,10 +114,10 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if ptr_expr is not None: ptr_a: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, ptr_expr, None, 0, trans) if ptr_a is None or ptr_a.Ty is None or self.Gen.ExprGenBase.is_ptr_type(ptr_a.Ty) == 0: - self.Gen.TypeGenErr.fatal_error(a_node, "c.Set 的解引用目标必须是指针类型(类型推断退化)", "TypeError") + self.Gen.TypeGenErr.fatal_error(a_node, "c.Set dereference target must be a pointer type (type inference degraded)", "TypeError") pointee_a: mlirlite.LLVMType* = ptr_a.Ty.Pointee if pointee_a is None: - self.Gen.TypeGenErr.fatal_error(a_node, "c.Set 解引用目标的 pointee 类型缺失", "TypeError") + self.Gen.TypeGenErr.fatal_error(a_node, "c.Set dereference target pointee type missing", "TypeError") sv_a: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, b_val, pointee_a, a_node, trans) if sv_a is not None: mlirlite.build_store(builder, sv_a, ptr_a) return b_val @@ -411,7 +411,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # Other arg0 forms fail-fast: c.Addr is a compile-time instruction and must # never fall through to a runtime call @Addr. - self.Gen.TypeGenErr.fatal_error(cl, f"c.Addr 不支持的操作数形式(kind={arg0.kind()}),c.Addr 仅支持 变量/全局/函数/数组元素/字段", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, f"c.Addr unsupported operand form (kind={arg0.kind()}); c.Addr only supports variable/global/function/array element/field", "TypeError") return None @@ -488,7 +488,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if prev_ok != 0 and next_ok != 0: # fail-fast: an asm template referencing a SHA1-mangled # global cannot be used in LLVM MC; mark it t.CExport. - self.Gen.TypeGenErr.fatal_error(None, f"asm 模板引用的全局符号 '{bare_g}' 带 SHA1 混淆头({gname}),内联汇编必须引用裸名符号,请将该全局定义标记为 t.CExport", "TypeError") + self.Gen.TypeGenErr.fatal_error(None, f"Global symbol '{bare_g}' referenced by the asm template has a SHA1 mangling prefix ({gname}); inline assembly must reference bare-name symbols, so mark that global definition as t.CExport", "TypeError") return asm_text cur = cur.Next if matched == 0: @@ -723,7 +723,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # fail-fast: AsmInp/AsmOut operands must not carry SHA1-mangled symbols; # LLVM MC cannot parse digit-leading names, so mark them t.CExport. if val is not None and val.Name is not None: - if self._asm_name_is_mangled(val.Name) != 0: self.Gen.TypeGenErr.fatal_error(None, f"__asm__ 操作数(AsmInp/AsmOut)不允许带 SHA1 混淆头的符号 '{val.Name}',请将对应函数/全局定义标记为 t.CExport(裸名)", "TypeError") + if self._asm_name_is_mangled(val.Name) != 0: self.Gen.TypeGenErr.fatal_error(None, f"__asm__ operand (AsmInp/AsmOut) does not allow a symbol with a SHA1 mangling prefix '{val.Name}'; mark the corresponding function/global definition as t.CExport (bare name)", "TypeError") if val is not None: for ei in range(count): eop: GenTypes.AsmOperand* = self._asm_get_operand(operands, ei) @@ -1010,7 +1010,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): out_pn_n += 1 if out_pn_head is not None and out_pn_n > 0: ret_ty = mlirlite.Struct(pool, out_pn_head, out_pn_n, None) else: - self.Gen.TypeGenErr.fatal_error(cl, "__asm__ 输出操作数类型缺失(变量 alloca 类型退化)", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, "__asm__ output operand type missing (variable alloca type degraded)", "TypeError") ret_ty = mlirlite.Int32(pool) else: out_op: GenTypes.AsmOperand* = self._asm_get_operand(operands, first_output_idx) @@ -1020,7 +1020,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): elif out_op is not None and out_op.Value is not None and out_op.Value.Ty is not None and out_op.Value.Ty.Pointee != 0: out_pt = out_op.Value.Ty.Pointee if out_pt is not None: ret_ty = out_pt else: - self.Gen.TypeGenErr.fatal_error(cl, "__asm__ 输出操作数类型缺失(变量 alloca 类型退化)", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, "__asm__ output operand type missing (variable alloca type degraded)", "TypeError") ret_ty = mlirlite.Int32(pool) # Determine void directly from output_count to avoid match type issues @@ -1039,7 +1039,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if re_op.Value is not None and re_op.Value.Ty is not None and re_op.Value.Ty.Pointee != 0: ret_re = re_op.Value.Ty.Pointee break - if ret_re is None: self.Gen.TypeGenErr.fatal_error(cl, "__asm__ 输出操作数类型缺失(变量 alloca 类型退化)", "TypeError") + if ret_re is None: self.Gen.TypeGenErr.fatal_error(cl, "__asm__ output operand type missing (variable alloca type degraded)", "TypeError") ret_ty = ret_re case _: pass @@ -1227,7 +1227,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if cl is None or builder is None or pool is None or trans is None: return None cargs: list[ast.AST*]* = cl.args - if cargs is None or len(cargs) < 1: self.Gen.TypeGenErr.fatal_error(cl, "c.LLVMIR 缺少模板参数", "TypeError") + if cargs is None or len(cargs) < 1: self.Gen.TypeGenErr.fatal_error(cl, "c.LLVMIR missing template argument", "TypeError") # LOut writeback records (alloca pointer + register name), up to LLVMIR_MAX_OPS out_alloca: sizet* = pool.alloc(8 * LLVMIR_MAX_OPS) @@ -1288,7 +1288,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): nm: ast.Name* = ast.Name*(val_node) if nm.id is not None: alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id) - if alloca is None or out_count >= LLVMIR_MAX_OPS: self.Gen.TypeGenErr.fatal_error(fcall, f"c.LOut 变量 '{nm.id}' 未定义或输出数超过 {LLVMIR_MAX_OPS}", "TypeError") + if alloca is None or out_count >= LLVMIR_MAX_OPS: self.Gen.TypeGenErr.fatal_error(fcall, f"c.LOut variable '{nm.id}' is undefined or the output count exceeds {LLVMIR_MAX_OPS}", "TypeError") self.Gen.CallGenBase.LLVMIRRegSeq += 1 reg_buf: str = pool.alloc(32) if reg_buf is not None: diff --git a/App/lib/core/Gen/Call/CallGenCall.vp b/App/lib/core/Gen/Call/CallGenCall.vp index 0232368..284ae03 100644 --- a/App/lib/core/Gen/Call/CallGenCall.vp +++ b/App/lib/core/Gen/Call/CallGenCall.vp @@ -181,13 +181,13 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if cls_sha1 is None: # [D6 truncation] Allocate by exact length instead of a fixed 256 # buffer so long class/method names are not silently truncated. - msg_fmt: str = "类 '%s' 方法 '%s' 找不到模块 SHA1" + msg_fmt: str = "Class '%s' method '%s': module SHA1 not found" msg_size: sizet = string.strlen(msg_fmt) + string.strlen(class_name) + string.strlen(method_name) - 4 + 1 err_msg: str = pool.alloc(msg_size) if err_msg is not None: viperlib.snprintf(err_msg, msg_size, msg_fmt, class_name, method_name) self.Gen.TypeGenErr.fatal_error(node, err_msg) - self.Gen.TypeGenErr.fatal_error(node, "找不到模块 SHA1") + self.Gen.TypeGenErr.fatal_error(node, "Module SHA1 not found") # Build the call name: {cls_sha1}.{lookup_name}. mangled2: str = pool.alloc(string.strlen(cls_sha1) + string.strlen(lookup_name) + 2) if mangled2 is not None: @@ -203,13 +203,13 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): elif string.strcmp(method_name, "__getitem__") == 0 or string.strcmp(method_name, "__new__") == 0: # fail-fast: __getitem__/__new__ must return a pointer; a missing # return type means a broken stub declare (silent ptr truncation). - msg_fmt1: str = "方法 '%s' 返回类型无法确定(stub declare 返回类型缺失)" + msg_fmt1: str = "Cannot determine return type of method '%s' (stub declare return type missing)" msg_size1: sizet = string.strlen(msg_fmt1) + string.strlen(method_name) - 2 + 1 err_cm1: str = pool.alloc(msg_size1) if err_cm1 is not None: viperlib.snprintf(err_cm1, msg_size1, msg_fmt1, method_name) self.Gen.TypeGenErr.fatal_error(node, err_cm1) - self.Gen.TypeGenErr.fatal_error(node, "方法返回类型无法确定") + self.Gen.TypeGenErr.fatal_error(node, "Cannot determine method return type") else: # found_func is None (stub not injected): cannot read the return type # from the declare. __before_init__/__init__ always return void. @@ -220,22 +220,22 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if cmop_struct_ty is not None: call_ret_ty = mlirlite.Ptr(pool, cmop_struct_ty) else: # [D6 truncation] Use exact length instead of a fixed 256 buffer. - msg_fmt2: str = "方法 '%s' 的 self 结构体类型未知(字段类型退化,依赖模块未预注册?)" + msg_fmt2: str = "Unknown self struct type of method '%s' (field type degraded, dependency module not preregistered?)" msg_size2: sizet = string.strlen(msg_fmt2) + string.strlen(method_name) - 2 + 1 err_cm2: str = pool.alloc(msg_size2) if err_cm2 is not None: viperlib.snprintf(err_cm2, msg_size2, msg_fmt2, method_name) self.Gen.TypeGenErr.fatal_error(node, err_cm2) - self.Gen.TypeGenErr.fatal_error(node, "self 结构体类型未知") + self.Gen.TypeGenErr.fatal_error(node, "Unknown self struct type") elif string.strcmp(method_name, "__getitem__") == 0: # [D6 truncation] Use exact length instead of a fixed 256 buffer. - msg_fmt3: str = "方法 '%s.__getitem__' 的 stub declare 未注入(依赖模块 vpi 缺失或拓扑顺序错误),无法确定返回类型" + msg_fmt3: str = "Method '%s.__getitem__': stub declare not injected (dependency module vpi missing or wrong topological order); cannot determine return type" msg_size3: sizet = string.strlen(msg_fmt3) + string.strlen(class_name) - 2 + 1 err_cm3: str = pool.alloc(msg_size3) if err_cm3 is not None: viperlib.snprintf(err_cm3, msg_size3, msg_fmt3, class_name) self.Gen.TypeGenErr.fatal_error(node, err_cm3) - self.Gen.TypeGenErr.fatal_error(node, "__getitem__ stub declare 未注入") + self.Gen.TypeGenErr.fatal_error(node, "__getitem__ stub declare not injected") else: # Other cross-module methods: resolve the return type precisely via # text.ll / vpi; fail fast rather than silently keeping void. @@ -263,9 +263,9 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): else: err_cm4: str = pool.alloc(256) if err_cm4 is not None: - viperlib.snprintf(err_cm4, 256, "方法 '%s.%s' 返回类型无法确定(text.ll/vpi 均未命中,跨模块 stub 未注入)", class_name, method_name) + viperlib.snprintf(err_cm4, 256, "Cannot determine return type of method '%s.%s' (neither text.ll nor vpi hit, cross-module stub not injected)", class_name, method_name) self.Gen.TypeGenErr.fatal_error(node, err_cm4) - self.Gen.TypeGenErr.fatal_error(node, "方法返回类型无法确定") + self.Gen.TypeGenErr.fatal_error(node, "Cannot determine method return type") # __new__'s signature may be shorter than __init__'s, so trim trailing # args to the callee's non-self param count (__init__ consumes them). @@ -361,7 +361,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if mdf_val is None: # Use node (this function's line-info node), not cl which is # undefined here and would report "line 0". - self.Gen.TypeGenErr.fatal_error(node, f"跨模块默认参数无法重建(快照缺失,默认值需为简单常量): {lookup_name}", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"Cross-module default argument cannot be rebuilt (snapshot missing, the default value must be a simple constant): {lookup_name}", "TypeError") continue mlirlite.value_set_next(mdf_val, None) mlirlite.value_set_next(tail, mdf_val) @@ -556,7 +556,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if cm_bare is not None and string.strchr(cm_bare, '[') is None: cm_tpl: ast.ClassDef* = self.Gen.ClassGenGeneric._find_generic_template(cm_bare) if cm_tpl is not None: - self.Gen.TypeGenErr.fatal_error(cl, f"泛型类 '{cm_bare}' 的方法 '{method_name}' 调用缺少类型实参" f"(接收者静态类型是裸泛型基类,元素类型未知);" f"禁止静默按默认 list[int] 特化(元素按 i32 处理会截断指针)," f"请让该变量的注解/类型带上实参(如 list[ast.AST*])", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, f"Generic class '{cm_bare}' method '{method_name}' call is missing type arguments" f" (receiver static type is a bare generic base, element type unknown); " f"silent specialization as the default list[int] is forbidden (treating elements as i32 truncates pointers), " f"annotate the variable type with arguments (e.g. list[ast.AST*])", "TypeError") # Fetch the struct entry early (find_struct_by_type avoids cross-module # same-name collisions) for MRO walking, SHA1 lookup and vtable dispatch. @@ -861,7 +861,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): elif ret_anc_name is not None and ret_anc_sha1 is None: # fail-fast: the defining class's SHA1 is unresolvable and type-name # extraction failed; never emit a silent bare name. - self.Gen.TypeGenErr.fatal_error(cl, f"方法 '{method_name}' 所属类 '{ret_anc_name}' 无法解析模块 SHA1(text.ll/vpi/类型名均未命中),跨模块调用名构造失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, f"Cannot resolve module SHA1 for class '{ret_anc_name}' of method '{method_name}' (neither text.ll/vpi nor type name hit); cross-module call name construction failed", "TypeError") # Translate the call arguments. cargs: list[ast.AST*]* = cl.args @@ -931,10 +931,10 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): self_arg = mlirlite.build_bitcast(builder, adj_th2, anc_ptr_ty_th2) else: # Defining class struct size unavailable (opaque/unloaded): fail fast. - self.Gen.TypeGenErr.fatal_error(cl, f"this-adjust 兄弟 Mixin 定义类大小未知: 方法'{method_name}'定义类'{mc_anc}'的 struct 大小计算失败", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(cl, f"this-adjust sibling Mixin defining class size unknown: struct size computation failed for method '{method_name}' defining class '{mc_anc}'", "InternalCompilerError") elif is_first_parent_th == 0: - self.Gen.TypeGenErr.fatal_error(cl, f"this-adjust 字段查找失败: 方法'{method_name}'定义类'{mc_anc}'首字段'{anc_first_name_th}'在类'{class_name}'/'{mc_anc}'布局中未找到", "InternalCompilerError") - elif is_first_parent_th == 0: self.Gen.TypeGenErr.fatal_error(cl, f"this-adjust 子类结构体未注册: 方法'{method_name}'定义类'{mc_anc}',接收类'{class_name}'的 struct 未找到", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(cl, f"this-adjust field lookup failed: first field '{anc_first_name_th}' of method '{method_name}' defining class '{mc_anc}' not found in the layout of class '{class_name}'/'{mc_anc}'", "InternalCompilerError") + elif is_first_parent_th == 0: self.Gen.TypeGenErr.fatal_error(cl, f"this-adjust subclass struct not registered: method '{method_name}' defining class '{mc_anc}', struct of receiver class '{class_name}' not found", "InternalCompilerError") else: # Parent has only the __vtable__ field: the method body reads no # layout fields, so no adjustment is needed. @@ -945,7 +945,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): elif is_first_parent_th == 0: # Parent struct not registered: fail fast, never use an unadjusted # obj_ptr as self. - self.Gen.TypeGenErr.fatal_error(cl, f"this-adjust 父类结构体未注册: 方法'{method_name}'定义类'{mc_anc}'的 struct 未找到", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(cl, f"this-adjust parent struct not registered: struct of method '{method_name}' defining class '{mc_anc}' not found", "InternalCompilerError") # Coerce self to the declared first-param type: the object pointer may be # i8* or an adjusted ancestor pointer and needs a bitcast to match. if found_func is not None: @@ -990,7 +990,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if arg_node_k is not None: # (a) The arg node exists but translated to None: fail fast; # never substitute a zero value for an unresolved argument. - self.Gen.TypeGenErr.fatal_error(arg_node_k, f"方法调用 '{class_name}.{method_name}' 第 {pi_k + 1} 个形参的实参表达式翻译失败(返回 None,禁止按类型零值兜底)","TypeError") + self.Gen.TypeGenErr.fatal_error(arg_node_k, f"Method call '{class_name}.{method_name}': argument expression for parameter {pi_k + 1} translation failed (returned None, zero-value fallback by type forbidden)","TypeError") continue # (b)/(c) Neither keyword nor positional supplied this param: insert a # typed zero placeholder to keep positions (not a failure fallback). @@ -1012,7 +1012,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if arg_node is None: # (a) Missing arg node (AST list hole): fail fast, never skip silently # (skipping would reduce arg_count_eff and get zero-filled later). - self.Gen.TypeGenErr.fatal_error(cl, f"方法调用 '{class_name}.{method_name}' 第 {ai + 1} 个实参节点缺失(AST 参数列表空洞,无法翻译)", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, f"Method call '{class_name}.{method_name}': argument node {ai + 1} missing (hole in the AST argument list, cannot translate)", "TypeError") continue # Fetch the param type first: a CONST_CHAR passed to a str/pointer param # must be materialized, else inttoptr treats the char as a pointer. @@ -1030,7 +1030,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if arg_val is None: # (a) The arg expression translated to None: fail fast, never continue; # skipping would reduce arg_count_eff and get zero-filled later. - self.Gen.TypeGenErr.fatal_error(arg_node, f"方法调用 '{class_name}.{method_name}' 第 {ai + 1} 个实参表达式翻译失败(返回 None,禁止按类型零值兜底)", "TypeError") + self.Gen.TypeGenErr.fatal_error(arg_node, f"Method call '{class_name}.{method_name}': argument expression {ai + 1} translation failed (returned None, zero-value fallback by type forbidden)", "TypeError") continue # Coerce to the param type (self is param 0, arg ai maps to param ai+1); # an i32 constant passed to an i64 param would read garbage high bits. @@ -1119,7 +1119,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): mdf_val: mlirlite.Value* = None if mdf_gd is not None: mdf_val = self.Gen.CallGenLeafKit._build_const_from_snapshot(pool, mod, mdf_gd, mdf_di, trans, builder) if mdf_val is None: - self.Gen.TypeGenErr.fatal_error(cl, f"跨模块默认参数无法重建(快照缺失,默认值需为简单常量): {lookup_name}", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, f"Cross-module default argument cannot be rebuilt (snapshot missing, the default value must be a simple constant): {lookup_name}", "TypeError") continue mlirlite.value_set_next(mdf_val, None) mlirlite.value_set_next(tail, mdf_val) @@ -1130,7 +1130,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # (c) A known default region and this param index before it means a # missing required arg: fail fast instead of a silent zero fill. if mdf_default_count > 0 and mdf_pi < mdf_offset: - self.Gen.TypeGenErr.fatal_error(cl, f"方法调用 '{lookup_name}' 漏传必需实参:第 {mdf_pi + 1} 个形参无默认值(调用点仅提供 {arg_count_eff} 个实参,该函数前 {mdf_offset} 个形参为必需)", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, f"Method call '{lookup_name}': missing required argument: parameter {mdf_pi + 1} has no default (call site provides only {arg_count_eff} arguments; the first {mdf_offset} parameters are required)", "TypeError") mdf_pi += 1 continue # (b) Other missing params come from missing default info (a missing @@ -1319,7 +1319,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if ap_sha1 is None: # Dependency module not compiled (_list not in the build chain): fail # fast, never silently skip append. - self.Gen.TypeGenErr.fatal_error(cl, "list.append: 找不到 _list 模块 SHA1(依赖模块未编译)", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(cl, "list.append: _list module SHA1 not found (dependency module not compiled)", "InternalCompilerError") if ap_sha1 is not None: # Extract the specialized class name: list.append's symbol is # {sha1}.list[AST*].append, not {sha1}.list.append. @@ -1391,11 +1391,11 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): self_entry: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, "self") if self_entry is None: self_entry = self.Gen.VarGen.lookup_var_entry(trans.SymTab, "cls") if self_entry is None: - self.Gen.TypeGenErr.fatal_error(cl, "super(): 当前作用域无 self 变量(静态方法内不可用)", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, "super(): no self variable in the current scope (unavailable inside a static method)", "TypeError") return None cur_class: str = self.Gen.VarGen.var_annot_class_name(self_entry) if cur_class is None: - self.Gen.TypeGenErr.fatal_error(cl, "super() 只能在类方法内使用(self 无注解类名)") + self.Gen.TypeGenErr.fatal_error(cl, "super() can only be used inside a class method (self has no annotated class name)") return None # 2. Walk the MRO, skipping self, for the first ancestor defining the method. anc: str = None @@ -1414,13 +1414,13 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if anc is None: err_sp: str = pool.alloc(256) if err_sp is not None: - viperlib.snprintf(err_sp, 256, "super(): 当前类 %s 的父类链未定义方法 %s", cur_class, method_name) + viperlib.snprintf(err_sp, 256, "super(): the parent chain of current class %s does not define method %s", cur_class, method_name) self.Gen.TypeGenErr.fatal_error(cl, err_sp, "TypeError") - self.Gen.TypeGenErr.fatal_error(cl, "super(): 父类链未定义方法", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, "super(): the parent chain does not define the method", "TypeError") return None # 3. self pointer (load from the self variable's alloca). if self_entry.Alloca is None or self_entry.Alloca.Ty is None: - self.Gen.TypeGenErr.fatal_error(cl, "super(): 当前作用域无 self 变量(静态方法内不可用)", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, "super(): no self variable in the current scope (unavailable inside a static method)", "TypeError") return None self_ptr: mlirlite.Value* = None match self_entry.Alloca.Ty: diff --git a/App/lib/core/Gen/Call/CallGenCtor.vp b/App/lib/core/Gen/Call/CallGenCtor.vp index e79e793..4b6aa43 100644 --- a/App/lib/core/Gen/Call/CallGenCtor.vp +++ b/App/lib/core/Gen/Call/CallGenCtor.vp @@ -27,13 +27,13 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_type(struct_ty) if entry is None: # fail-fast: struct type unregistered; a silent return would leave fields uninitialized - VLogger.error(f"结构体类型未注册,无法应用默认值: {class_name}", "HandlesExprCall") + VLogger.error(f"Struct type not registered, cannot apply defaults: {class_name}", "HandlesExprCall") return for fi in range(entry.FieldCount): fe: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(entry, fi) if fe is None: # fail-fast: field index out of range (entry.FieldCount mismatch) - VLogger.error(f"字段索引越界,无法获取字段 entry: {class_name}", "HandlesExprCall") + VLogger.error(f"Field index out of range, cannot get field entry: {class_name}", "HandlesExprCall") continue if fe.DefaultVal is None: continue # reasonable skip: field without a default # Static array field with a list-literal default: zero then per-element GEP+store @@ -48,18 +48,18 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if sd_ctx is not None: fname_sd: str = fe.Name if fname_sd is None: fname_sd = "?" - viperlib.snprintf(sd_ctx, 192, "类 %s 字段 %s(结构体构造默认值):", class_name, fname_sd) + viperlib.snprintf(sd_ctx, 192, "Class %s field %s (struct ctor defaults):", class_name, fname_sd) self.Gen.AssignGen._init_global_array_from_list(builder, pool, mod, field_ptr_arr2, fe.DefaultVal, trans, sd_ctx) continue default_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fe.DefaultVal, None, 0, trans, fe.Ty) if default_val is None: # fail-fast: default value translation failed (e.g. undefined symbol) - VLogger.error(f"字段默认值翻译失败: {class_name}", "HandlesExprCall") + VLogger.error(f"Field default value translation failed: {class_name}", "HandlesExprCall") continue field_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, fe.Ty, tmp, fe.Index) if field_ptr is None: # fail-fast: GEP failed (struct_ty and fe.Ty mismatch) - VLogger.error(f"字段 GEP 失败,类型不匹配: {class_name}", "HandlesExprCall") + VLogger.error(f"Field GEP failed, type mismatch: {class_name}", "HandlesExprCall") continue default_val = self.Gen.ExprGenBase.coerce_to_type(builder, default_val, fe.Ty, fe.DefaultVal) mlirlite.build_store(builder, default_val, field_ptr, is_volatile) @@ -185,17 +185,17 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): else: fe = self.Gen.StructGen.get_field_by_index(class_name, ai) if fe is None: # fail-fast: field index out of range (too many args passed) - VLogger.error(f"构造函数参数过多,字段索引越界: {class_name}", "HandlesExprCall") + VLogger.error(f"Too many constructor arguments, field index out of range: {class_name}", "HandlesExprCall") continue arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, fe.Ty) if arg_val is None: # fail-fast: argument translation failed - VLogger.error(f"构造函数参数翻译失败: {class_name}", "HandlesExprCall") + VLogger.error(f"Constructor argument translation failed: {class_name}", "HandlesExprCall") continue field_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, fe.Ty, storage_ptr, fe.Index) if field_ptr is None: # fail-fast: GEP failed (struct_ty and fe.Ty mismatch) - VLogger.error(f"构造函数字段 GEP 失败: {class_name}", "HandlesExprCall") + VLogger.error(f"Constructor field GEP failed: {class_name}", "HandlesExprCall") continue arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fe.Ty, arg) mlirlite.build_store(builder, arg_val, field_ptr, is_volatile) @@ -220,18 +220,18 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): else: fe = self.Gen.StructGen.get_field_by_index(class_name, ai) if fe is None: # fail-fast: field index out of range (too many args passed) - VLogger.error(f"构造函数参数过多,字段索引越界: {class_name}", "HandlesExprCall") + VLogger.error(f"Too many constructor arguments, field index out of range: {class_name}", "HandlesExprCall") continue arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, fe.Ty) if arg_val is None: # fail-fast: argument translation failed - VLogger.error(f"构造函数参数翻译失败: {class_name}", "HandlesExprCall") + VLogger.error(f"Constructor argument translation failed: {class_name}", "HandlesExprCall") continue # GEP to field ai field_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, fe.Ty, tmp, fe.Index) if field_ptr is None: # fail-fast: GEP failed (struct_ty and fe.Ty mismatch) - VLogger.error(f"构造函数字段 GEP 失败: {class_name}", "HandlesExprCall") + VLogger.error(f"Constructor field GEP failed: {class_name}", "HandlesExprCall") continue # coerce and store arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fe.Ty, arg) @@ -445,7 +445,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): else: fe = self.Gen.StructGen.get_field_by_index(class_name, ai) if fe is None: # positional arg out of range (no matching field): fail-fast, never skip silently - self.Gen.TypeGenErr.fatal_error(arg, f"结构体 '{class_name}' 位置参数越界(无对应字段)", "TypeError") + self.Gen.TypeGenErr.fatal_error(arg, f"Struct '{class_name}': positional argument out of range (no matching field)", "TypeError") continue arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, fe.Ty) if arg_val is None: continue @@ -464,7 +464,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): fe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field_by_class(class_name, kw.arg, kw_sha1, kw, trans._from_imports) if fe is None: # keyword field missing: fail-fast (AttributeError), never skip silently - self.Gen.TypeGenErr.fatal_error(kw, f"结构体 '{class_name}' 无字段 '{kw.arg}'", "AttributeError") + self.Gen.TypeGenErr.fatal_error(kw, f"Struct '{class_name}' has no field '{kw.arg}'", "AttributeError") continue kw_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, kw.value, None, 0, trans, fe.Ty) if kw_val is None: continue @@ -583,7 +583,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): def _infer_generic_ctor_type_arg(self, pool: memhub.MemBuddy*, arg_node: ast.AST*, class_name: str, trans: HT.Translator*) -> str: """Infer a generic type-arg name from a ctor arg AST (static AST only, no IR)""" if pool is None or arg_node is None: - self.Gen.TypeGenErr.fatal_error(None, f"无法从实参推断泛型类 '{class_name}' 的类型实参,请显式标注如 {class_name}[类型](...)", "TypeError") + self.Gen.TypeGenErr.fatal_error(None, f"Cannot infer the type argument of generic class '{class_name}' from the argument; annotate explicitly, e.g. {class_name}[Type](...)", "TypeError") return None k: int = arg_node.kind() # constant: 42->int, 3.14->double, "abc"->str, 'x'->char @@ -614,7 +614,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if ta_c is not None: return ta_c # A cast call whose callee does not resolve to a scalar type: fail-fast # (return None -> caller fail-fasts). - self.Gen.TypeGenErr.fatal_error(arg_node, f"无法从实参推断泛型类 '{class_name}' 的类型实参,请显式标注如 {class_name}[类型](...)", "TypeError") + self.Gen.TypeGenErr.fatal_error(arg_node, f"Cannot infer the type argument of generic class '{class_name}' from the argument; annotate explicitly, e.g. {class_name}[Type](...)", "TypeError") return None # Plain variable (Name) arg: take the var's annotation class name (same source as # VarGen.set_var_annot_class_name). Lookup only (Spec.SourceName), no IR emitted. @@ -772,7 +772,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # find the struct entry to get the type struct_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(spec_name) if struct_entry is None: - self.Gen.TypeGenErr.fatal_error(cl, "泛型类构造调用: 特化类未注册") + self.Gen.TypeGenErr.fatal_error(cl, "Generic class ctor call: specialized class not registered") return None struct_ty: mlirlite.LLVMType* = struct_entry.Ty if struct_ty is None: return None @@ -805,7 +805,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): for ai in range(can): if ai >= 32: # fixed 8*32 slots: writing past 32 args would corrupt adjacent pool blocks; fail-fast - self.Gen.TypeGenErr.fatal_error(cl, "泛型构造实参超过 32 个上限", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, "Generic construction arguments exceed the limit of 32", "TypeError") break arg_node: ast.AST* = cargs.get(ai) if arg_node is not None: @@ -822,12 +822,12 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if kw_slot is None or kw_slot.arg is None or kw_slot.value is None: continue slot_kw: int = self._ctor_init_arg_slot_by_name(tmpl_name, kw_slot.arg) if slot_kw >= 32: - self.Gen.TypeGenErr.fatal_error(kw_slot, "泛型构造实参超过 32 个上限", "TypeError") + self.Gen.TypeGenErr.fatal_error(kw_slot, "Generic construction arguments exceed the limit of 32", "TypeError") continue if slot_kw < 0: # fail-fast: the keyword name is not an __init__ param (or the template has no # __init__/name). Silent drop would pass misaligned args to __init__. - self.Gen.TypeGenErr.fatal_error(kw_slot, f"泛型类 '{tmpl_name}' 的关键字实参 '{kw_slot.arg}' 无法定位到 __init__ 形参", "TypeError") + self.Gen.TypeGenErr.fatal_error(kw_slot, f"Generic class '{tmpl_name}': keyword argument '{kw_slot.arg}' cannot be mapped to an __init__ parameter", "TypeError") continue if arg_filled[sizet(slot_kw)] != 0: # This param slot is already taken by a positional/earlier keyword arg: @@ -842,7 +842,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # got neither positional nor keyword arg. Never pass the hole as 0; fail-fast. for ci_hole in range(arg_max_filled + 1): if arg_filled[sizet(ci_hole)] == 0: - self.Gen.TypeGenErr.fatal_error(cl, f"泛型类 '{tmpl_name}' 的关键字构造缺少前置形参(第 {ci_hole + 1} 个实参位置既无位置实参也无关键字实参)", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, f"Generic class '{tmpl_name}': keyword construction is missing preceding parameters (argument slot {ci_hole + 1} has neither positional nor keyword argument)", "TypeError") break arg_count: int = 0 if arg_max_filled >= 0: arg_count = arg_max_filled + 1 diff --git a/App/lib/core/Gen/Call/CallGenDispatch.vp b/App/lib/core/Gen/Call/CallGenDispatch.vp index 0a6424a..6a75ce9 100644 --- a/App/lib/core/Gen/Call/CallGenDispatch.vp +++ b/App/lib/core/Gen/Call/CallGenDispatch.vp @@ -86,7 +86,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if explicit_slice is not None: type_args = self.Gen.CallGenCtor._extract_type_args_from_slice(pool, explicit_slice, trans._from_imports) if type_args is None or len(type_args) != tp_count: - self.Gen.TypeGenErr.fatal_error(cl, f"泛型函数 '{tpl_name}' 显式类型实参个数不匹配(需要 {tp_count}):请写 {tpl_name}[类型1, 类型2](...)", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, f"Generic function '{tpl_name}': explicit type argument count mismatch (expected {tp_count}); write {tpl_name}[Type1, Type2](...)", "TypeError") return None else: # Implicit inference: align by the template signature's param annotated with T @@ -107,13 +107,13 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if kwn is not None and kwn.value is not None: ta = self.Gen.ClassGenGeneric._infer_generic_func_type_arg(pool, kwn.value, tpl_name, trans) if ta is None and ctx_args is not None and sizet(tpi) < len(ctx_args): ta = ctx_args.get(tpi) if ta is None: - self.Gen.TypeGenErr.fatal_error(cl, f"无法从实参推断泛型函数 '{tpl_name}' 的第 {tpi + 1} 个类型实参(类型形参 {tp_name});" f"禁止静默默认 int。请显式标注如 {tpl_name}[类型](...) 或为对应实参标注类型", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, f"Cannot infer type argument {tpi + 1} of generic function '{tpl_name}' from the arguments (type parameter {tp_name});" f"silent default to int is forbidden. Annotate explicitly, e.g. {tpl_name}[Type](...), or annotate the corresponding argument", "TypeError") return None type_args.append(ta) # ---- Specialize ---- spec_name: str = self.Gen.ClassGenGeneric._specialize_generic_function(trans, tpl_key, type_args) if spec_name is None: - self.Gen.TypeGenErr.fatal_error(cl, f"泛型函数 '{tpl_name}' 特化失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, f"Generic function '{tpl_name}': specialization failed", "TypeError") return None # ---- Emit call ---- return self._emit_generic_func_call(pool, builder, mod, trans, cl, spec_name, cargs, can, hit_box) @@ -152,11 +152,11 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): """Emit the specialized-function call, coercing args to the specialized param types.""" func: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, spec_name) if func is None: - self.Gen.TypeGenErr.fatal_error(cl, f"泛型函数特化符号未在当前模块注册: {spec_name}", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(cl, f"Generic function specialization symbol not registered in the current module: {spec_name}", "InternalCompilerError") return None kw: list[ast.AST*]* = cl.keywords if kw is not None and len(kw) > 0: - self.Gen.TypeGenErr.fatal_error(cl, "泛型函数调用暂不支持关键字实参,请改用位置实参", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, "Generic function calls do not support keyword arguments yet; use positional arguments", "TypeError") return None if hit_box is not None: hit_box[0] = 1 param_count: int = 0 @@ -165,7 +165,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): param_count += 1 pp = mlirlite.param_get_next(pp) if int(can) < param_count: - self.Gen.TypeGenErr.fatal_error(cl, "泛型函数调用实参个数少于形参个数(默认参数暂不支持),请补齐实参", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, "Generic function call has fewer arguments than parameters (default parameters are not supported yet); supply the missing arguments", "TypeError") return None ret_ty: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(func) head: mlirlite.Value* = None @@ -176,7 +176,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): fpty: mlirlite.LLVMType* = None if fp is not None: fpty = mlirlite.param_get_ty(fp) if arg is not None: - av: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, fpty, "形参") + av: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, fpty, "param") if av is not None: if fpty is not None: av = self.Gen.ExprGenBase.coerce_to_type(builder, av, fpty, arg, trans) av.Next = None @@ -726,10 +726,10 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): sz_val: int = self.Gen.ClassGenEnum._get_type_size(sz_resolved_ty) if sz_val > 0: return mlirlite.const_int64(pool, sz_val) # Type registered but size 0 (opaque struct or unfilled field list): fail with a Python-style error - self.Gen.TypeGenErr.fatal_error(sz_at, f"类型 '{sz_resolved_name}' 已注册但大小为 0(字段链表未填充),无法计算大小", "TypeError") + self.Gen.TypeGenErr.fatal_error(sz_at, f"Type '{sz_resolved_name}' is registered but its size is 0 (field list not filled); cannot compute size", "TypeError") # Type unregistered: fail with a Python-style error instead of returning 0 (would cause malloc(0)/alloc(0)) if sz_resolved_name is None: sz_resolved_name = "(unknown)" - self.Gen.TypeGenErr.fatal_error(sz_at, f"类型 '{sz_resolved_name}' 未在结构体表中注册,无法计算大小", "TypeError") + self.Gen.TypeGenErr.fatal_error(sz_at, f"Type '{sz_resolved_name}' is not registered in the struct table; cannot compute size", "TypeError") # Detect len(obj) on a list object: return its __count__ field (offset 8, i64). __len__ is a # builtin of list[T]. Use translate_value, since len_at.value may be an Attribute (not a Name). @@ -743,7 +743,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # i32 (misparsed CDefine constant, module-attr fallback), llc reports a non-pointer GEP base. if self.Gen.ExprGenBase.is_ptr_type(obj_val.Ty) == 0: # Type inference failed (not a pointer/struct): fail fast rather than return 0 - self.Gen.TypeGenErr.fatal_error(len_at.value, "len() 参数类型推断失败(非指针/结构体)", "TypeError") + self.Gen.TypeGenErr.fatal_error(len_at.value, "len() argument type inference failed (not a pointer/struct)", "TypeError") i64_ty_len: mlirlite.LLVMType* = mlirlite.Int64(pool) # Must use const_int64, not ConstInt(...,"0"): ConstInt's name is emitted as IR text, # so GEP would index 0 (__data__) instead of 1 (__count__). @@ -786,7 +786,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): len_struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(len_val) if len_struct_ty is not None: len_cls_nm: str = self.Gen.StructGen.get_class_name_by_type(pool, len_struct_ty) - if len_cls_nm is None: self.Gen.TypeGenErr.fatal_error(len_arg_node, "len() 参数类型推断失败(结构体类名未知)", "TypeError") + if len_cls_nm is None: self.Gen.TypeGenErr.fatal_error(len_arg_node, "len() argument type inference failed (unknown struct class name)", "TypeError") # list builtin __len__: read __count__ (GEP offset 1, i64). Narrow len_arg_node # to ast.Call* explicitly, since passing a base pointer to a derived param is banned. len_arg_cl: ast.Call* = ast.Call*(len_arg_node) @@ -832,7 +832,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): return mlirlite.build_call(builder, len_mangled_x, len_self_x, 1, len_ret_x, 0) # fail-fast: the class has no __len__ (compile-time error, matching TPC # HandlesExprBuiltin._FailFastLenUnsupported wording). - self.Gen.TypeGenErr.fatal_error(len_arg_node, f"len() 参数类型 '{len_cls_nm}' 没有 __len__ 方法。len() 只支持定长数组/数组指针(t.CArray[T, N])、i8*(str/bytes)或带 __len__ 的结构体;非 i8 裸指针/标量指针没有长度语义:字符串请用 str/bytes,需要元素个数请自行记录长度,或改用 t.CPtr[元素] 并显式维护元素计数", "TypeError") + self.Gen.TypeGenErr.fatal_error(len_arg_node, f"len() argument type '{len_cls_nm}' has no __len__ method. len() only supports fixed-size arrays/array pointers (t.CArray[T, N]), i8* (str/bytes), or structs with __len__; non-i8 bare pointers/scalar pointers have no length semantics: use str/bytes for strings, record the length yourself when the element count is needed, or use t.CPtr[Element] and maintain the element count explicitly", "TypeError") # Non-struct: str (Ptr(Int8)) uses strlen; other types fail fast len_arg_ty: mlirlite.LLVMType* = mlirlite.value_get_ty(len_val) len_is_str: int = 0 @@ -865,7 +865,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): return mlirlite.build_call(builder, "strlen", len_coerced, 1, i64_ty_ln2, 0) # fail-fast: not a string/array/object, so length is unavailable (matching TPC # HandlesExprBuiltin._FailFastLenUnsupported wording). - self.Gen.TypeGenErr.fatal_error(len_arg_node, "len() 参数类型不支持(非字符串/数组/对象)。len() 只支持定长数组/数组指针(t.CArray[T, N])、i8*(str/bytes)或带 __len__ 的结构体;非 i8 裸指针/标量指针没有长度语义:字符串请用 str/bytes,需要元素个数请自行记录长度,或改用 t.CPtr[元素] 并显式维护元素计数", "TypeError") + self.Gen.TypeGenErr.fatal_error(len_arg_node, "len() argument type not supported (not a string/array/object). len() only supports fixed-size arrays/array pointers (t.CArray[T, N]), i8* (str/bytes), or structs with __len__; non-i8 bare pointers/scalar pointers have no length semantics: use str/bytes for strings, record the length yourself when the element count is needed, or use t.CPtr[Element] and maintain the element count explicitly", "TypeError") # Detect isinstance(): runtime vtable subclass-set comparison. obj's head vtable pointer must # be in {Cls and all subclass vtables}; NoVTable targets fall back to a compile-time check. @@ -988,7 +988,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if rk_val is None: # fail-fast: REnum was determined but the one-level load of a double pointer # produced no value; never skip silently, or .kind() falls into the generic call path. - self.Gen.TypeGenErr.fatal_error(cl, f"REnum.kind() 翻译失败:接收者已判定为 REnum(变体表/__tag 判据命中)," f"但接收者指针解一层 load 失败(rk_load={rk_load})", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, f"REnum.kind() translation failed: the receiver was determined to be a REnum (variant table/__tag criterion hit), " f"but loading one level from the receiver pointer failed (rk_load={rk_load})", "TypeError") if hit_box is not None: hit_box[0] = 1 # Layer 2: address and load using __tag's field declaration type, no hardcoded i32. # Width coercion is left to coerce_to_type on the assignment side. @@ -1359,7 +1359,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if lm_obj.Ty is None or self.Gen.ExprGenBase.is_ptr_type(lm_obj.Ty) == 0: # translate_value type inference failed (target is not a pointer): fail fast, # never swallow it silently. - self.Gen.TypeGenErr.fatal_error(lm_at.value, f"list 方法 '{lm_name}' 目标对象非指针", "TypeError") + self.Gen.TypeGenErr.fatal_error(lm_at.value, f"list method '{lm_name}': target object is not a pointer", "TypeError") # Confirm the object really is a list (the branch matches by method name only, and # get/set are not list-specific); skip otherwise to avoid wrong GEP offsets. lm_conf_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(lm_obj) @@ -1471,7 +1471,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if ap_sha1 is None: # Dependency module not compiled (_list not in the chain): fail fast, never # silently skip append (elements would never be added). - self.Gen.TypeGenErr.fatal_error(cl, "list.append: 找不到 _list 模块 SHA1(依赖模块未编译)", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(cl, "list.append: _list module SHA1 not found (dependency module not compiled)", "InternalCompilerError") if ap_sha1 is not None: # The append symbol is {sha1}.list[AST*].append (specialized name), not # {sha1}.list.append; derive the specialized name from lm_obj's type. diff --git a/App/lib/core/Gen/Call/CallGenLeafKit.vp b/App/lib/core/Gen/Call/CallGenLeafKit.vp index 4ac1202..0782369 100644 --- a/App/lib/core/Gen/Call/CallGenLeafKit.vp +++ b/App/lib/core/Gen/Call/CallGenLeafKit.vp @@ -203,11 +203,11 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): """isinstance(obj, Cls): runtime vtable subclass-set comparison; returns i1""" if obj_node is None or cls_node is None: # missing args is a call error: fail fast, never hide it by returning True - self.Gen.TypeGenErr.fatal_error(cls_node, "isinstance() 参数类型推断失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(cls_node, "isinstance() argument type inference failed", "TypeError") obj_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, obj_node, None, 0, trans) if obj_val is None or obj_val.Ty is None: # obj type inference failed: fail fast, never hide it by returning True - self.Gen.TypeGenErr.fatal_error(cls_node, "isinstance() 参数类型推断失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(cls_node, "isinstance() argument type inference failed", "TypeError") # normalize the object pointer: load through a pointer-to-pointer (var alloca / Class*) obj_ptr: mlirlite.Value* = obj_val match obj_val.Ty: @@ -229,7 +229,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): cls_names: sizet* = self._extract_isinstance_class_names(pool, cls_node) if cls_names is None: # class-name extraction failed: fail fast, never hide it by returning True - self.Gen.TypeGenErr.fatal_error(cls_node, "isinstance() 参数类型推断失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(cls_node, "isinstance() argument type inference failed", "TypeError") ci: int = 0 while cls_names[ci] != 0: cn: str = rawptr(cls_names[ci]) @@ -263,7 +263,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): ci += 1 if res is None: # no comparison produced (obj non-pointer, all classes CVTable): fail fast - self.Gen.TypeGenErr.fatal_error(cls_node, "isinstance() 参数类型推断失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(cls_node, "isinstance() argument type inference failed", "TypeError") return res @@ -542,16 +542,16 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): if typed_buf[0] != '\0': ret_str = typed_buf msg_buf: str = pool.alloc(1024) if msg_buf is not None: - viperlib.snprintf(msg_buf, 1024, "函数指针签名表登记失败:变量 '%s'(返回类型 %s)——%s。" "当前上限 MAX_FUNC_PTR_SIGS=%d,已登记 %d 条。" "同名同返回类型的重复登记已做原地命中、不占新槽位;" "若确实需要更多函数指针变量,请上调 CallGenBase.vp 的 " "MAX_FUNC_PTR_SIGS(全仓唯一来源,改此一处即全仓生效)", name, ret_str, reason, cap, self.FuncptrCount) + viperlib.snprintf(msg_buf, 1024, "Function pointer signature table registration failed: variable '%s' (return type %s) -- %s. " "Current limit MAX_FUNC_PTR_SIGS=%d, %d entries registered. " "Duplicate registration with the same name and return type hits in place and does not occupy a new slot; " "if more function pointer variables are really needed, raise the " "MAX_FUNC_PTR_SIGS (the single repo-wide source; changing this one place takes effect everywhere)", name, ret_str, reason, cap, self.FuncptrCount) self.Gen.TypeGenErr.fatal_error(node, msg_buf, "TypeError") return - self.Gen.TypeGenErr.fatal_error(node, "函数指针签名表登记失败(签名表已满或变量名冲突)", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "Function pointer signature table registration failed (table full or variable name conflict)", "TypeError") def register_func_ptr_sig(self, pool: memhub.MemBuddy*, name: str, ret_ty: mlirlite.LLVMType*, node: ast.AST* = None) -> int: """Register a function-pointer variable's return type; 0 = success, 1 = failed (already reported)""" if name is None or ret_ty is None: return 1 if self._ensure_funcptr_sigs() == 0: - self._func_ptr_sig_fatal(pool, node, name, ret_ty, "签名表分配失败(PermPool 内存不足)") + self._func_ptr_sig_fatal(pool, node, name, ret_ty, "Signature table allocation failed (PermPool out of memory)") return 1 # idempotence/conflict check: linear scan of registered bare names (cap 64, cheap) i: sizet @@ -560,10 +560,10 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): if string.strcmp(self.FuncptrNames + idx_hit, name) == 0: prev_ret: mlirlite.LLVMType* = (mlirlite.LLVMType*)(self.FuncptrRets[i]) if prev_ret is not None and self.Gen.AssignGen._stg_ty_equal(pool, prev_ret, ret_ty) != 0: return 0 - self._func_ptr_sig_fatal(pool, node, name, ret_ty, "该名字已按另一种返回类型登记过") + self._func_ptr_sig_fatal(pool, node, name, ret_ty, "This name is already registered with a different return type") return 1 if self.FuncptrCount >= CallGenBase.MAX_FUNC_PTR_SIGS: - self._func_ptr_sig_fatal(pool, node, name, ret_ty, "签名表已满") + self._func_ptr_sig_fatal(pool, node, name, ret_ty, "Signature table is full") return 1 idx: sizet = sizet(self.FuncptrCount) * 64 # slot is 64 bytes fixed; use strncpy clamping like register_closure_name @@ -616,7 +616,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): # 3. build the signature from arg types + registered ret type (missing = fail fast) ret_ty: mlirlite.LLVMType* = self.lookup_func_ptr_ret(func_name) if ret_ty is None: - self.Gen.TypeGenErr.fatal_error(None, f"函数指针变量 '{func_name}' 的返回类型未注册(t.Callable 注解缺失)", "TypeError") + self.Gen.TypeGenErr.fatal_error(None, f"Return type of function pointer variable '{func_name}' is not registered (t.Callable annotation missing)", "TypeError") ret_ty = i32_ty fp_first: mlirlite.ParamNode* = None fp_prev: mlirlite.ParamNode* = None @@ -715,8 +715,8 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): if arg_val is None or arg_val.Ty is None: # fail fast: a failed print-arg translation must abort, never write a # misleading format string that hides a compiler bug as a data problem. - VLogger.error(f"print 参数翻译失败(表达式返回 None): [arg={ai}]", "PRINT") - self.Gen.TypeGenErr.fatal_error(arg, "print 参数翻译失败(表达式返回 None)", "TypeError") + VLogger.error(f"print argument translation failed (expression returned None): [arg={ai}]", "PRINT") + self.Gen.TypeGenErr.fatal_error(arg, "print argument translation failed (expression returned None)", "TypeError") return # object defines __str__ -> print its i8* return via %s (TPC-aligned) diff --git a/App/lib/core/Gen/Call/CallGenLib.vp b/App/lib/core/Gen/Call/CallGenLib.vp index 9fcdb13..8aea5ad 100644 --- a/App/lib/core/Gen/Call/CallGenLib.vp +++ b/App/lib/core/Gen/Call/CallGenLib.vp @@ -383,7 +383,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): return mlirlite.Ptr(pool, mlirlite.Int8(pool)) # Default i32 placeholder: fatal_if_unknown=1 fails fast; =0 (Phase A mid-pass) stays silent. - if fatal_if_unknown != 0: self.Gen.TypeGenErr.fatal_error(node, f"外部函数返回类型未登记且无法收敛推断(默认 i32 会截断指针/i64,需提供 stub 声明或加入白名单): {func_name}", "TypeError") + if fatal_if_unknown != 0: self.Gen.TypeGenErr.fatal_error(node, f"external function return type is unregistered and cannot be inferred conclusively (defaulting to i32 would truncate pointers/i64; provide a stub declaration or add it to the whitelist): {func_name}", "TypeError") return mlirlite.Int32(pool) def _get_external_func_param_ty(self, pool: memhub.MemBuddy*, func_name: str, param_idx: int) -> mlirlite.LLVMType*: """Return the expected type of an external function's param_idx-th parameter, or None (fallback only)""" @@ -552,7 +552,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): if arg_val is None: kw_node: ast.AST* = None if keywords is not None and kw_count > 0: kw_node = keywords.get(0) - self.Gen.TypeGenErr.fatal_error(kw_node, f"调用 '{func_name}' 的某个形参既未按位置/关键字传入," f"定义处也无默认值可填充(拒绝静默漏参/填零)", "TypeError") + self.Gen.TypeGenErr.fatal_error(kw_node, f"a parameter of call '{func_name}' is passed neither positionally nor by keyword, " f"and the definition has no default value to fill in (refusing to silently drop/zero a parameter)", "TypeError") if arg_val is not None: # Coerce by parameter type (via accessor) diff --git a/App/lib/core/Gen/Call/CallGenMixin.vp b/App/lib/core/Gen/Call/CallGenMixin.vp index 49d5a56..d2f9352 100644 --- a/App/lib/core/Gen/Call/CallGenMixin.vp +++ b/App/lib/core/Gen/Call/CallGenMixin.vp @@ -56,7 +56,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if sc_sha1 is None: return 0 if string.strncmp(sc_sha1, trans.ModuleSha1, 16) == 0: return 0 if self.Gen.CallGenBase.IsStaticSymbol(sc_sha1, sc_at.attr) == 0: return 0 - self.Gen.TypeGenErr.fatal_error(cl, f"'{sc_mod}.{sc_at.attr}' 是 static 符号,禁止跨模块使用(static 仅限定义模块内可见)", "NameError") + self.Gen.TypeGenErr.fatal_error(cl, f"'{sc_mod}.{sc_at.attr}' is a static symbol; cross-module use is forbidden (static is visible only inside its defining module)", "NameError") return 0 @@ -135,9 +135,9 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # Generic class template not found: the defining module may not be imported. gt_err: str = pool.alloc(256) if gt_err is not None: - viperlib.snprintf(gt_err, 256, "泛型类 '%s' 未找到模板,可能未 import 定义模块", gen_class_name) + viperlib.snprintf(gt_err, 256, "Generic class '%s': template not found; the defining module may not be imported", gen_class_name) self.Gen.TypeGenErr.fatal_error(gen_nm_node, gt_err) - self.Gen.TypeGenErr.fatal_error(gen_nm_node, "泛型类模板未找到") + self.Gen.TypeGenErr.fatal_error(gen_nm_node, "Generic class template not found") if func_name is None: # BinOp as the Call func: a union-type annotation used as a type cast, (A*)(value). if cl.func is not None and cl.func.kind() == ast.ASTKind.BinOp and trans is not None: @@ -339,7 +339,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # [C1] The annotation already gives type args (e.g. s: Stack[int] = Stack()): specialize with them. ta_bare = ctx_args_bare.get(tpi_bare) if ta_bare is None: - self.Gen.TypeGenErr.fatal_error(cl, f"无法从实参推断泛型类 '{func_name}' 的第 {tpi_bare + 1} 个类型实参," f"禁止静默默认 int(会产生 list[int] 等错误特化 → 元素按 4 字节/i32 处理 → 指针截断崩溃);" f"请为该实参标注类型或显式标注如 {func_name}[类型](...)", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, f"Cannot infer type argument {tpi_bare + 1} of generic class '{func_name}' from the arguments, " f"silent default to int is forbidden (it produces wrong specializations such as list[int] -> elements treated as 4 bytes/i32 -> pointer truncation crash); " f"annotate the argument type or annotate explicitly, e.g. {func_name}[Type](...)", "TypeError") inferred_args_bare.append(ta_bare) spec_name_bare: str = self.Gen.ClassGenGeneric._specialize_generic_class(trans, func_name, inferred_args_bare) if spec_name_bare is not None: return self.Gen.CallGenCtor._translate_generic_ctor_call(pool, builder, mod, spec_name_bare, cl, trans, func_name) @@ -359,7 +359,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): rc_tag: int = self.Gen.ClassGenEnum._lookup_renum_variant_in_class(rc_cls_name, func_name) if rc_tag < 0: # [D32 fail-fast] It is an REnum but the variant is missing: the table is incomplete; report it here. - self.Gen.TypeGenErr.fatal_error(cl, f"REnum 类 '{rc_cls_name}' 的变体 '{func_name}' 未在变体表中找到" f"({self.Gen.ClassGenEnum.RenumTableDump()});" f"变体表未注册或变体名不匹配", "NameError") + self.Gen.TypeGenErr.fatal_error(cl, f"REnum class '{rc_cls_name}': variant '{func_name}' not found in the variant table" f" ({self.Gen.ClassGenEnum.RenumTableDump()}); " f"the variant table is not registered or the variant name does not match", "NameError") if rc_tag >= 0: return self.Gen.CallGenCtor._translate_renum_construct(pool, builder, mod, rc_cls_name, func_name, rc_tag, cargs, can, trans, cl.IsVolatile) elif rc_at.value is not None and rc_at.value.kind() == ast.ASTKind.Attribute: # Module-qualified REnum variant: mod.Class.Variant(args...), e.g. mlirlite.LLVMType.Struct(...). @@ -758,7 +758,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): fp = mlirlite.param_get_next(fp) fpi += 1 if fp is not None: fpty = mlirlite.param_get_ty(fp) - arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, fpty, "形参") + arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, fpty, "param") if arg_val is not None: # Arg promotion: when found_func is None (stub not injected), infer the expected type from # the external signature and promote literals (e.g. i32->i64) to avoid declare/call mismatches. @@ -978,9 +978,9 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if is_xmod_imported == 0: err_ni: str = pool.alloc(256) if err_ni is not None: - viperlib.snprintf(err_ni, 256, "跨模块调用 '%s.%s':模块 '%s' 未导入(请先 import %s)", xmod_path, func_name, xmod_path, xmod_path) + viperlib.snprintf(err_ni, 256, "Cross-module call '%s.%s': module '%s' not imported (import %s first)", xmod_path, func_name, xmod_path, xmod_path) self.Gen.TypeGenErr.fatal_error(xmod_at, err_ni) - self.Gen.TypeGenErr.fatal_error(xmod_at, "跨模块调用:模块未导入") + self.Gen.TypeGenErr.fatal_error(xmod_at, "Cross-module call: module not imported") # Check whether it is a re-export function (e.g. ast._lexer_init actually defined in ast.lexer). reexport_src: str = self.Gen.ImportsGen.lookup_reexport(mod_sha1, func_name) if reexport_src is None: @@ -1069,9 +1069,9 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # Imported module but SHA1 unregistered: the module was not compiled, so error out immediately. err_msg_imp: str = pool.alloc(256) if err_msg_imp is not None: - viperlib.snprintf(err_msg_imp, 256, "模块 '%s' 已导入但 SHA1 未注册(该模块未被编译)", xmod_path) + viperlib.snprintf(err_msg_imp, 256, "Module '%s' is imported but its SHA1 is not registered (the module was not compiled)", xmod_path) self.Gen.TypeGenErr.fatal_error(xmod_at, err_msg_imp) - self.Gen.TypeGenErr.fatal_error(xmod_at, "已导入模块 SHA1 未注册") + self.Gen.TypeGenErr.fatal_error(xmod_at, "Imported module SHA1 not registered") else: # Check whether it is a from-import name (e.g. from .__types import LLVMType): LLVMType is a # class, not a module, but Ptr is a module-level function of __types; disable star-import fallback. @@ -1089,9 +1089,9 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): else: err_msg2: str = pool.alloc(256) if err_msg2 is not None: - viperlib.snprintf(err_msg2, 256, "跨模块调用 '%s.%s' 找不到模块 SHA1", xmod_path, func_name) + viperlib.snprintf(err_msg2, 256, "Cross-module call '%s.%s': module SHA1 not found", xmod_path, func_name) self.Gen.TypeGenErr.fatal_error(xmod_at, err_msg2) - self.Gen.TypeGenErr.fatal_error(xmod_at, "跨模块调用找不到模块 SHA1") + self.Gen.TypeGenErr.fatal_error(xmod_at, "Cross-module call: module SHA1 not found") else: # Bare-name call (not Attribute): check from_imports. Star-import fallback is disabled for calls # (star import is for types/constants); a missed function then fails fast at compile time instead of linking wrong. @@ -1134,15 +1134,15 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): else: err_msg3: str = pool.alloc(256) if err_msg3 is not None: - viperlib.snprintf(err_msg3, 256, "裸名调用 '%s' 未定义且未导入", func_name) + viperlib.snprintf(err_msg3, 256, "Bare-name call '%s' is undefined and not imported", func_name) self.Gen.TypeGenErr.fatal_error(node, err_msg3) - self.Gen.TypeGenErr.fatal_error(node, "裸名调用未定义且未导入") + self.Gen.TypeGenErr.fatal_error(node, "Bare-name call undefined and not imported") else: err_msg4: str = pool.alloc(256) if err_msg4 is not None: - viperlib.snprintf(err_msg4, 256, "裸名调用 '%s' 未定义且未导入", func_name) + viperlib.snprintf(err_msg4, 256, "Bare-name call '%s' is undefined and not imported", func_name) self.Gen.TypeGenErr.fatal_error(node, err_msg4) - self.Gen.TypeGenErr.fatal_error(node, "裸名调用未定义且未导入") + self.Gen.TypeGenErr.fatal_error(node, "Bare-name call undefined and not imported") # Direct call. memcpy -> @llvm.memcpy intrinsic (avoids a missing cross-module @memcpy declaration during monomorphization). if string.strcmp(func_name, "memcpy") == 0 and can >= 3: return self.Gen.CallGenLib._emit_llvm_memcpy_intrinsic(pool, builder, mod, mc_dst2, mc_src2, mc_num2) @@ -1184,7 +1184,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): else: # Dependency text.ll does not exist (module not yet translated): Phase A translates files # in order (main.vp before its imported mbuddytest.vp), so keep the default type without fail-fast. - if self._dep_text_ll_exists(pool, cf_sha1) != 0: self.Gen.TypeGenErr.fatal_error(node, f"跨模块函数返回类型无法精确获取(vpi/text.ll 均未命中),默认 i32 会截断指针: {call_name}", "TypeError") + if self._dep_text_ll_exists(pool, cf_sha1) != 0: self.Gen.TypeGenErr.fatal_error(node, f"Cannot obtain the cross-module function return type precisely (neither vpi nor text.ll hit); the default i32 will truncate pointers: {call_name}", "TypeError") stdlib.free(cf_sha1) stdlib.free(cf_bare) # Bare C library function (string.memset -> @memset): promote args to the standard signature diff --git a/App/lib/core/Gen/Call/CallGenProp.vp b/App/lib/core/Gen/Call/CallGenProp.vp index 86b2c82..bbac388 100644 --- a/App/lib/core/Gen/Call/CallGenProp.vp +++ b/App/lib/core/Gen/Call/CallGenProp.vp @@ -282,7 +282,7 @@ novirtual class CallGenProp(CallGenBase.CallGenBase): if self.Gen.ClassGenGeneric._find_generic_template(base_nm) is None: return None if lb is not None: return short_nm # Bare generic base (no type args): element type unknown -> fail-fast (D25) - self.Gen.TypeGenErr.fatal_error(cl, f"方法 '{method_name}' 的接收者实际结构体类型是裸泛型基类 " f"'{short_nm}*'(丢失类型实参),元素类型未知;" f"禁止静默按默认元素类型处理(元素按 i32 处理会截断指针)," f"请让该变量的注解/类型带上实参(如 list[ast.AST*])", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, f"the actual struct type of the receiver of method '{method_name}' is a bare generic base " f"'{short_nm}*' (type arguments lost), so the element type is unknown; " f"silently using the default element type is forbidden (treating elements as i32 would truncate pointers); " f"make the variable annotation/type carry type arguments (e.g. list[ast.AST*])", "TypeError") return None # _is_list_builtin_receiver - test list builtin methods from the receiver's actual type. diff --git a/App/lib/core/Gen/Call/CallGenVa.vp b/App/lib/core/Gen/Call/CallGenVa.vp index 5e1a4f1..daac42f 100644 --- a/App/lib/core/Gen/Call/CallGenVa.vp +++ b/App/lib/core/Gen/Call/CallGenVa.vp @@ -35,7 +35,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase): resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, type_node, trans._imported_modules, trans._from_imports, trans, 0) if resolved is not None: return resolved # Type node present but unresolvable: fail-fast, never fall back to i32 (would read the vararg slot at the wrong width) - self.Gen.TypeGenErr.fatal_error(type_node, "va_arg 类型解析失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(type_node, "va_arg type resolution failed", "TypeError") return mlirlite.Int32(pool) def _translate_va_arg_sugar(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, cargs: list[ast.AST*]*, can: sizet, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator*) -> mlirlite.Value*: """Emit a va_arg instruction reading the next variadic argument from the va_list.""" diff --git a/App/lib/core/Gen/Class/ClassGenDef.vp b/App/lib/core/Gen/Class/ClassGenDef.vp index 79c40e2..fd79264 100644 --- a/App/lib/core/Gen/Class/ClassGenDef.vp +++ b/App/lib/core/Gen/Class/ClassGenDef.vp @@ -31,8 +31,8 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): if trans.ModuleSha1 is None: # fail-fast: ModuleSha1 missing while translating a class (namespace isolation depends on it) - VLogger.error("翻译类时 ModuleSha1 缺失", "CLASS") - self.Gen.TypeGenErr.fatal_error(cd, "翻译类时 ModuleSha1 缺失", "TypeError") + VLogger.error("ModuleSha1 missing while translating a class", "CLASS") + self.Gen.TypeGenErr.fatal_error(cd, "ModuleSha1 missing while translating a class", "TypeError") # Namespace isolation: mark as visible in the current file. Must precede # the existing check, or Phase B's early return would never mark it. @@ -45,7 +45,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): # takes priority over CEnum/CUnion, whose semantics are mutually exclusive. if self.Gen.ClassGenBase._is_enum_class(cd, trans) == 1: if self.Gen.ClassGenBase._is_renum_class(cd, trans) == 1: - self.Gen.TypeGenErr.fatal_error(cd, f"类 '{class_name}' 同时被判定为 CEnum 与 REnum(分派歧义)," f"REnum 变体表将无法注册", "TypeError") + self.Gen.TypeGenErr.fatal_error(cd, f"class '{class_name}' is classified as both CEnum and REnum (dispatch ambiguity), " f"the REnum variant table cannot be registered", "TypeError") return self.Gen.ClassGenEnum._translate_enum_def(trans, cd) # Union class: handled by the union path @@ -275,7 +275,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): field_ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, aa.annotation, trans._imported_modules, trans._from_imports, trans, 0) # void is not a valid field type (only for `void*` and opaque typedefs); letting # it through builds an illegal layout, so fail-fast at compile time here. - if field_ty is not None and self.Gen.StmtGenDecl._is_void_type(field_ty) != 0: self.Gen.TypeGenErr.fatal_error(aa, f"字段 '{tgt.id}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError") + if field_ty is not None and self.Gen.StmtGenDecl._is_void_type(field_ty) != 0: self.Gen.TypeGenErr.fatal_error(aa, f"field '{tgt.id}' cannot be void type (void is only allowed for void* and typedef aliases)", "TypeError") # Single-arg t.CArray[elem] with a list literal -> static array [N x elem] (like # local AnnAssign); otherwise it stays Ptr(elem) and for-in iterates pointers wrongly. if field_ty is not None: field_ty = self.Gen.AssignGen._infer_static_array_ty_from_literal(pool, aa.annotation, aa.value, field_ty) diff --git a/App/lib/core/Gen/Class/ClassGenEnum.vp b/App/lib/core/Gen/Class/ClassGenEnum.vp index 4fc2d75..2005488 100644 --- a/App/lib/core/Gen/Class/ClassGenEnum.vp +++ b/App/lib/core/Gen/Class/ClassGenEnum.vp @@ -36,7 +36,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): at: ast.Attribute* = ast.Attribute*(ann_node) if at.attr is None: # [S4 fail-fast] Attribute missing the member name (corrupt AST); no silent i32 fallback - self.Gen.TypeGenErr.fatal_error(ann_node, "枚举成员类型注解 Attribute 缺失成员名", "TypeError") + self.Gen.TypeGenErr.fatal_error(ann_node, "enum member type annotation Attribute is missing the member name", "TypeError") return mlirlite.Int32(pool) # unreachable (fatal_error already exited) # t.State -> default i32 if string.strcmp(at.attr, "State") == 0: return mlirlite.Int32(pool) @@ -47,7 +47,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_typedef_or_map(pool, at.attr, imported_modules, from_imports) if ty is not None: return ty # [S4 fail-fast] annotated but unresolvable -> no silent i32 fallback - self.Gen.TypeGenErr.fatal_error(ann_node, f"枚举成员类型注解解析失败: t.{at.attr}", "NameError") + self.Gen.TypeGenErr.fatal_error(ann_node, f"failed to resolve enum member type annotation: t.{at.attr}", "NameError") return mlirlite.Int32(pool) # unreachable (fatal_error already exited) # Name node: from-import form (State / CInt) @@ -55,7 +55,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): nm: ast.Name* = ast.Name*(ann_node) if nm.id is None: # [S4 fail-fast] Name missing the identifier (corrupt AST); no silent i32 fallback - self.Gen.TypeGenErr.fatal_error(ann_node, "枚举成员类型注解 Name 缺失标识符", "TypeError") + self.Gen.TypeGenErr.fatal_error(ann_node, "enum member type annotation Name is missing the identifier", "TypeError") return mlirlite.Int32(pool) # unreachable (fatal_error already exited) if string.strcmp(nm.id, "State") == 0: return mlirlite.Int32(pool) # Builtin bare integer types (same rule as resolve_annotation_type's Name branch): enum members are @@ -69,7 +69,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): ty2: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_typedef_or_map(pool, nm.id, imported_modules, from_imports) if ty2 is not None: return ty2 # [S4 fail-fast] annotated but unresolvable -> no silent i32 fallback - self.Gen.TypeGenErr.fatal_error(ann_node, f"枚举成员类型注解解析失败: {nm.id}", "NameError") + self.Gen.TypeGenErr.fatal_error(ann_node, f"failed to resolve enum member type annotation: {nm.id}", "NameError") return mlirlite.Int32(pool) # unreachable (fatal_error already exited) # BinOp node: t.State | int8 (recurse to find the concrete type) @@ -87,11 +87,11 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): if left_bits >= right_bits: return left_ty return right_ty # fail-fast: BinOp but not BitOr (unknown union op); no silent i32 fallback - self.Gen.TypeGenErr.fatal_error(ann_node, f"枚举成员类型注解解析失败: {self.Gen.TypeGenResolve.annotation_to_str(ann_node)}", "TypeError") + self.Gen.TypeGenErr.fatal_error(ann_node, f"failed to resolve enum member type annotation: {self.Gen.TypeGenResolve.annotation_to_str(ann_node)}", "TypeError") return mlirlite.Int32(pool) # unreachable (fatal_error already exited) # fail-fast: unknown annotation node kind; no silent i32 fallback - self.Gen.TypeGenErr.fatal_error(ann_node, f"枚举成员类型注解解析失败: {self.Gen.TypeGenResolve.annotation_to_str(ann_node)}", "TypeError") + self.Gen.TypeGenErr.fatal_error(ann_node, f"failed to resolve enum member type annotation: {self.Gen.TypeGenResolve.annotation_to_str(ann_node)}", "TypeError") return mlirlite.Int32(pool) # unreachable (fatal_error already exited) def _is_state_annotation(self, node: ast.AST*) -> int: """Check whether an annotation node is t.State, 1=yes / 0=no""" @@ -268,7 +268,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # [enum spec fail-fast] Members may not be pointer types: t.CPtr / CNeedPtr / # CAutoPtr / rawptr[...] / str / bytes and unions carrying a pointer. Checked before type resolution. if self._enum_member_annotation_is_ptr(aa.annotation) == 1: - self.Gen.TypeGenErr.fatal_error(aa, f"枚举成员 '{tgt.id}' 不能是指针类型(枚举值只支持整数成员类型)", "TypeError") + self.Gen.TypeGenErr.fatal_error(aa, f"enum member '{tgt.id}' cannot be a pointer type (enum values only support integer member types)", "TypeError") return 0 # unreachable (fatal_error already exited) # Resolve the member type @@ -278,7 +278,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # width 0 and cannot drive "enum width = widest member"; no silent downgrade. member_bits: int = self.Gen.TypeGenErr.get_llvm_type_bits(member_ty) if member_bits <= 0: - self.Gen.TypeGenErr.fatal_error(aa, f"枚举成员 '{tgt.id}' 的类型必须为整数类型(不允许指针/浮点/void/结构体/数组),无法推导枚举宽度", "TypeError") + self.Gen.TypeGenErr.fatal_error(aa, f"the type of enum member '{tgt.id}' must be an integer type (pointers/floats/void/structs/arrays are not allowed), cannot infer enum width", "TypeError") return 0 # unreachable (fatal_error already exited) # Resolve the member value @@ -335,9 +335,9 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): if visible_count != member_count: diff_count: int = visible_count - member_count bad: ast.AST* = self._enum_first_unregistered_node(children) - bad_desc: str = "(无法定位到具体语句,请检查枚举体)" + bad_desc: str = "(cannot locate the specific statement, check the enum body)" if bad is not None: bad_desc = bad.type_name() - self.Gen.TypeGenErr.fatal_error(bad if bad is not None else cd, f"枚举 '{class_name}' 成员登记数不一致:源码里可见的成员名 {visible_count} 个," f"实际只登记 {member_count} 个(差额 {diff_count} 个会被静默丢弃)。" f"未识别的成员写法(首个): {bad_desc} 形态的语句——如逗号组带值 `A, B = 1`、" f"逗号组带注解 `A, B: T`、单名尾随逗号 `A,`。" f"期望形态: 每行一个 `Name` / `Name: T` / `Name = 值`," f"或多个简单标识符用逗号分隔(`A, B, C`,可带尾随逗号)。" f"修法: 把该行改写为逐个成员一行,或改写为纯标识符逗号组(去掉 `= 值` / `: T`)。" f"(本判据在注册处比对『可见名数 vs 登记数』,任何未识别形态都会命中," f"不再静默丢成员)", "TypeError") + self.Gen.TypeGenErr.fatal_error(bad if bad is not None else cd, f"enum '{class_name}' member registration count mismatch: {visible_count} member names visible in source, " f"but only {member_count} registered ({diff_count} difference would be silently dropped). " f"first unrecognized member form: a statement of shape {bad_desc} -- e.g. comma group with value `A, B = 1`, " f"comma group with annotation `A, B: T`, single name with trailing comma `A,`. " f"expected forms: one `Name` / `Name: T` / `Name = value` per line, " f"or multiple simple identifiers separated by commas (`A, B, C`, trailing comma allowed). " f"fix: rewrite that line as one member per line, or as a plain identifier comma group (remove `= value` / `: T`). " f"(this check compares the number of visible names vs registered names at the registrar, so any unrecognized form hits it, " f"no more members are silently dropped)", "TypeError") return 0 if member_count == 0: @@ -650,7 +650,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): if children is None: # [D32 fail-fast] Previously only warned and returned: the variant table was silently unregistered, # so _is_renum_class_name stayed 0 and variant construction lost its tag. No silent skip here. - self.Gen.TypeGenErr.fatal_error(cd, f"REnum 类 '{class_name}' 缺少类体(children 为 None),无法注册变体表", "TypeError") + self.Gen.TypeGenErr.fatal_error(cd, f"REnum class '{class_name}' has no class body (children is None), cannot register the variant table", "TypeError") return 0 cn: sizet = len(children) @@ -718,7 +718,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): if variant_count == 0: # [D32 fail-fast] Same as above: variant_count 0 previously returned silently, skipping registration. # For `class X(t.REnum)` the count must be > 0; 0 means the AST variant classes were lost. - self.Gen.TypeGenErr.fatal_error(cd, f"REnum 类 '{class_name}' 的变体数为 0(嵌套变体类丢失),无法注册变体表", "TypeError") + self.Gen.TypeGenErr.fatal_error(cd, f"REnum class '{class_name}' has 0 variants (nested variant classes lost), cannot register the variant table", "TypeError") return 0 # Compute the max field size for each position. @@ -881,7 +881,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # A None table means the perm-pool request failed; returning here left the table empty while the # caller still reported "registered", so every REnum case in match dispatch was silently lost. self.RenumClassNames = None - self.Gen.TypeGenErr.fatal_error(cd, f"REnum 变体表分配失败(class='{class_name}'):PermPool 返回 NULL,变体表不可用", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(cd, f"failed to allocate REnum variant table (class='{class_name}'): PermPool returned NULL, variant table unavailable", "InternalCompilerError") return string.memset(self.RenumClassNames, 0, 8 * RENUM_CLASS_MAX) string.memset(self.RenumClassVariantCounts, 0, 8 * RENUM_CLASS_MAX) @@ -908,7 +908,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): if self.RenumClassCount >= RENUM_CLASS_MAX: # Silently dropping the class made its later `match` lose every case; a # real limit breach must be reported instead. - self.Gen.TypeGenErr.fatal_error(cd, f"REnum 类数超过上限 {RENUM_CLASS_MAX}:无法注册 class='{class_name}'", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(cd, f"REnum class count exceeds the limit {RENUM_CLASS_MAX}: cannot register class='{class_name}'", "InternalCompilerError") return # Register the class name (strcpy into perm_pool: after each file's 1a reset the AST raw pointer @@ -917,7 +917,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): cn_len_rv: sizet = string.strlen(class_name) cn_buf_rv: str = CompilerFactory.factory.PermPool.alloc(cn_len_rv + 1) if cn_buf_rv is None: - self.Gen.TypeGenErr.fatal_error(cd, f"REnum 类名副本分配失败(class='{class_name}'):PermPool 返回 NULL", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(cd, f"failed to allocate REnum class name copy (class='{class_name}'): PermPool returned NULL", "InternalCompilerError") return string.strcpy(cn_buf_rv, class_name) self.RenumClassNames[idx] = sizet(cn_buf_rv) @@ -950,7 +950,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): if slot >= variant_count: break if slot >= RENUM_VARIANT_PER_CLASS: # Fixed 32 slots per class: exceeding it would overflow into the next class's slots; report fail-fast - VLogger.error(f"REnum 变体数超过上限 {RENUM_VARIANT_PER_CLASS}: {class_name}", "RENUM") + VLogger.error(f"REnum variant count exceeds the limit {RENUM_VARIANT_PER_CLASS}: {class_name}", "RENUM") break stmt: ast.AST* = children.get(ci) if stmt is None: continue @@ -989,7 +989,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): if vn_buf_rv is None: # Breaking here registered a partial variant table: the class would # keep some variants and silently lose every later one. - self.Gen.TypeGenErr.fatal_error(cd, f"REnum 变体名副本分配失败(class='{class_name}'):PermPool 返回 NULL", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(cd, f"failed to allocate REnum variant name copy (class='{class_name}'): PermPool returned NULL", "InternalCompilerError") break string.strcpy(vn_buf_rv, vname_src) self.RenumVariantNames[name_offset] = sizet(vn_buf_rv) @@ -1074,7 +1074,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # Same as the variant table: a silent bail left the alias table empty, # so match bindings later failed with an unrelated NameError. self.RenumAliasClass = None - self.Gen.TypeGenErr.fatal_error(None, f"REnum 字段别名表分配失败(class='{class_name}'):PermPool 返回 NULL", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(None, f"failed to allocate REnum field alias table (class='{class_name}'): PermPool returned NULL", "InternalCompilerError") return string.memset(self.RenumAliasClass, 0, 8 * RENUM_ALIAS_MAX) string.memset(self.RenumAliasField, 0, 8 * RENUM_ALIAS_MAX) @@ -1093,7 +1093,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): if self.RenumAliasCount >= RENUM_ALIAS_MAX: # Dropping the record silently made the variant field bind to a wrong-typed # slot (or fail with NameError) instead of reporting the limit breach. - self.Gen.TypeGenErr.fatal_error(None, f"REnum 字段别名数超过上限 {RENUM_ALIAS_MAX}:无法注册 {class_name}.{field_name}", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(None, f"REnum field alias count exceeds the limit {RENUM_ALIAS_MAX}: cannot register {class_name}.{field_name}", "InternalCompilerError") return # Dedupe check (pointer-free): the class slot holds a perm_pool string copy compared with strcmp, diff --git a/App/lib/core/Gen/Class/ClassGenGeneric.vp b/App/lib/core/Gen/Class/ClassGenGeneric.vp index 1e4674e..d21d5c9 100644 --- a/App/lib/core/Gen/Class/ClassGenGeneric.vp +++ b/App/lib/core/Gen/Class/ClassGenGeneric.vp @@ -416,7 +416,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): """Specialize a generic function and return its mangled name.""" if trans is None or template_key is None or type_args is None: return None self.GenericSpecDepth += 1 - if self.GenericSpecDepth > GENERIC_SPEC_MAX_DEPTH: self.Gen.TypeGenErr.fatal_error(None, "泛型函数特化递归过深(疑似泛型循环套用)", "InternalCompilerError") + if self.GenericSpecDepth > GENERIC_SPEC_MAX_DEPTH: self.Gen.TypeGenErr.fatal_error(None, "generic function specialization recursion too deep (suspected generic loop)", "InternalCompilerError") pool: memhub.MemBuddy* = trans.Pool template_fd: ast.FunctionDef* = self._find_generic_func_template(template_key) if template_fd is None: @@ -443,14 +443,14 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): if len(tp_names) != len(type_args): err_tp: str = pool.alloc(256) if err_tp is not None: - viperlib.snprintf(err_tp, 256, "泛型函数 '%s' 类型实参个数不匹配(需要 %d,给定 %d)", template_fd.name, len(tp_names), len(type_args)) + viperlib.snprintf(err_tp, 256, "generic function '%s' type argument count mismatch (expected %d, given %d)", template_fd.name, len(tp_names), len(type_args)) self.Gen.TypeGenErr.fatal_error(None, err_tp, "TypeError") self.GenericSpecDepth -= 1 return None # Generic functions with CExport/CExtern/State markers are unsupported (specialized names bypass bare-name export) if template_fd.returns is not None: if self.Gen.TypeGenErr.has_decorator_marker(template_fd.returns, "CExport", 0) != 0 or self.Gen.TypeGenErr.has_decorator_marker(template_fd.returns, "CExtern", 0) != 0 or self.Gen.TypeGenErr.has_decorator_marker(template_fd.returns, "State", 0) != 0: - self.Gen.TypeGenErr.fatal_error(template_fd, "泛型函数暂不支持 t.CExport/t.CExtern/t.State 存储标记", "TypeError") + self.Gen.TypeGenErr.fatal_error(template_fd, "generic functions do not yet support t.CExport/t.CExtern/t.State storage markers", "TypeError") # Generate the specialized name (the single generator normalizes each arg so bare/prefixed forms converge) spec_base: str = self._mangle_generic_class_name(pool, template_fd.name, type_args, trans._from_imports) if spec_base is None: @@ -821,7 +821,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): tp: list[str]* = self._find_generic_template_tp_params(pool, class_name) if tp is not None and len(tp) > 0: return tp if template_cd is not None and template_cd.type_params is not None and len(template_cd.type_params) > 0: return template_cd.type_params - self.Gen.TypeGenErr.fatal_error(None, f"泛型类模板 '{class_name}' 的类型参数名缺失(GenericClassTpParams 对应槽为空," f"模板节点也无 type_params)——拒绝用空泛型上下文特化", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(None, f"generic class template '{class_name}' is missing type param names (GenericClassTpParams slot is empty, " f"and the template node has no type_params) -- refusing to specialize with an empty generic context", "InternalCompilerError") return None def _specialize_generic_class(self, trans: HT.Translator*, class_name: str, type_args: list[str]*) -> str: @@ -836,9 +836,9 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): if self.GenericSpecDepth > GENERIC_SPEC_MAX_DEPTH: err_spec: str = trans.Pool.alloc(256) if err_spec is not None: - viperlib.snprintf(err_spec, 256, "泛型特化递归过深(疑似泛型循环套用),类: %s 深度=%d", class_name, self.GenericSpecDepth) + viperlib.snprintf(err_spec, 256, "generic specialization recursion too deep (suspected generic loop), class: %s depth=%d", class_name, self.GenericSpecDepth) self.Gen.TypeGenErr.fatal_error(None, err_spec, "InternalCompilerError") - self.Gen.TypeGenErr.fatal_error(None, "泛型特化递归过深(疑似泛型循环套用)", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(None, "generic specialization recursion too deep (suspected generic loop)", "InternalCompilerError") # Defensive: unresolved type-parameter names (e.g. "T") left in type_args are replaced with the # concrete type name to avoid ndarray[T] double-recursion crashes; in-place edits are side-effect free. ta_cnt_g: sizet = len(type_args) @@ -960,11 +960,11 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): tp_n_c: sizet = len(tp_names) if tp_names is not None else 0 ta_n_c: sizet = len(type_args) if type_args is not None else 0 if tp_n_c == 0 or ta_n_c != tp_n_c: - self.Gen.TypeGenErr.fatal_error(None, f"泛型类 '{class_name}' 的类型实参个数({ta_n_c})与模板类型形参个数({tp_n_c})不匹配," f"无法建立特化上下文(特化键 {spec_key})", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(None, f"generic class '{class_name}' type argument count ({ta_n_c}) does not match the template type param count ({tp_n_c}), " f"cannot build the specialization context (spec key {spec_key})", "InternalCompilerError") probe_tp: str = tp_names.get(0) if probe_tp is not None: if string.strcmp(self.Gen.TypeGenBase.resolve_generic_type_name(probe_tp), probe_tp) == 0: - self.Gen.TypeGenErr.fatal_error(None, f"泛型类 '{class_name}' 的特化上下文装不上:类型形参 '{probe_tp}' 解析不到具体类型" f"(特化键 {spec_key})——类型实参缺失/为空", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(None, f"cannot install the specialization context of generic class '{class_name}': type param '{probe_tp}' does not resolve to a concrete type" f"(spec key {spec_key}) -- type args missing/empty", "InternalCompilerError") # 7. Translate the specialized class: switch trans.ModuleSha1 to the template-defining module so # struct type names and method symbols use its SHA1 prefix; also merge its imports. @@ -1009,8 +1009,8 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): if rfe is not None: rfn: str = self.Gen.StructGen.get_field_name_ptr(rfe) if rfn is None: - VLogger.error("SPEC 字段名缺失(字段表损坏)", "SPEC") - self.Gen.TypeGenErr.fatal_error(None, "SPEC 字段名缺失(字段表损坏)", "TypeError") + VLogger.error("SPEC field name missing (field table corrupted)", "SPEC") + self.Gen.TypeGenErr.fatal_error(None, "SPEC field name missing (field table corrupted)", "TypeError") self._record_spec_trigger(pool, spec_name, spec_trigger_sha1) self.GenericSpecDepth -= 1 diff --git a/App/lib/core/Gen/Class/ClassGenVTable.vp b/App/lib/core/Gen/Class/ClassGenVTable.vp index ce20077..ff95395 100644 --- a/App/lib/core/Gen/Class/ClassGenVTable.vp +++ b/App/lib/core/Gen/Class/ClassGenVTable.vp @@ -277,7 +277,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): continue func_ty_buf[0] = '\0' if ge is None or ge.Spec is None or TSpec.SpecToLLVMText(ge.Spec, func_ty_buf, 1024) != 0: - self.Gen.TypeGenErr.fatal_error(cd, f"vtable 方法 '{full_name}' 找不到函数类型", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(cd, f"vtable method '{full_name}' has no function type", "InternalCompilerError") continue # Build the bitcast string: i8* bitcast (func_ty* @mangled to i8*). @@ -434,8 +434,8 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): method_name: str = fd.name if method_name is None: # fail-fast: method name is missing (the parser cannot produce a nameless def). - VLogger.error("方法名缺失(fd.name is None)", "OOP") - self.Gen.TypeGenErr.fatal_error(fd, "方法名缺失(fd.name is None)", "TypeError") + VLogger.error("method name missing (fd.name is None)", "OOP") + self.Gen.TypeGenErr.fatal_error(fd, "method name missing (fd.name is None)", "TypeError") # Extract decorator metadata (@property/@staticmethod/@classmethod/@x.setter/@x.deleter). func_meta: int = self.Gen.ClassGenBase._extract_func_meta(fd.decorator_list) @@ -478,7 +478,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): ret_ty = mlirlite.Void(pool) else: # [S4 fail-fast] return annotation failed to resolve: do not fall back to infer_return_type (silent mismatch). - self.Gen.TypeGenErr.fatal_error(fd, f"方法 '{class_name}.{method_name}' 返回类型注解解析失败", "NameError") + self.Gen.TypeGenErr.fatal_error(fd, f"method '{class_name}.{method_name}' return type annotation failed to resolve", "NameError") return 0 if ret_ty is None: # __init__ and __before_init__ return void. @@ -564,7 +564,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, imported_modules, from_imports, trans, 0) if resolved is None: # [S4 fail-fast] annotation present but failed to resolve: no silent i32 (signature/call/impl mismatch). - self.Gen.TypeGenErr.fatal_error(arg, f"方法 '{class_name}.{method_name}' 形参 '{arg.arg}' 类型注解解析失败", "NameError") + self.Gen.TypeGenErr.fatal_error(arg, f"method '{class_name}.{method_name}' param '{arg.arg}' type annotation failed to resolve", "NameError") return 0 # Bare-class param -> Ptr(struct) (objects are pointers; by-value would dangle after append). # CArray param -> element pointer ty* (C array decay, same as function params). @@ -572,7 +572,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): case mlirlite.LLVMType.Void(): # void is not a legal param type (only void* and typedef opaque structs); void* # is already merged into i8* upstream, so fail fast at compile time instead of emitting invalid IR. - self.Gen.TypeGenErr.fatal_error(arg, f"方法 '{class_name}.{method_name}' 形参 '{arg.arg}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError") + self.Gen.TypeGenErr.fatal_error(arg, f"method '{class_name}.{method_name}' param '{arg.arg}' cannot be void type (void is only allowed for void* and typedef aliases)", "TypeError") return 0 case mlirlite.LLVMType.Struct(_, _, _): param_ty = mlirlite.Ptr(pool, resolved) @@ -697,14 +697,14 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): resolved2: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg2.annotation, imported_modules, from_imports, trans, 0) if resolved2 is None: # fail-fast: param has an annotation but type resolution failed; no silent i32. - self.Gen.TypeGenErr.fatal_error(arg2, f"方法 '{class_name}.{method_name}' 参数 '{arg2.arg}' 类型解析失败", "NameError") + self.Gen.TypeGenErr.fatal_error(arg2, f"method '{class_name}.{method_name}' argument '{arg2.arg}' failed to resolve type", "NameError") resolved2 = i32_ty # Unreachable (fatal_error already exits). if resolved2 is not None: # Keep in sync with add_param: bare class -> Ptr(struct) (objects are pointers); CArray -> element pointer ty*. match resolved2: case mlirlite.LLVMType.Void(): # void is not a legal param type (same rule as above). - self.Gen.TypeGenErr.fatal_error(arg2, f"方法 '{class_name}.{method_name}' 形参 '{arg2.arg}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError") + self.Gen.TypeGenErr.fatal_error(arg2, f"method '{class_name}.{method_name}' param '{arg2.arg}' cannot be void type (void is only allowed for void* and typedef aliases)", "TypeError") return 0 case mlirlite.LLVMType.Struct(_, _, _): param_ty2 = mlirlite.Ptr(pool, resolved2) @@ -811,8 +811,8 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): if ret_ty is not None: _m_zero_val: mlirlite.Value* = mlirlite.ConstZero(pool, ret_ty) if _m_zero_val is not None: mlirlite.build_ret(func_builder, _m_zero_val) - else: self.Gen.TypeGenErr.fatal_error(fd, "方法流程掉出末尾但未显式 return", "TypeError") - else: self.Gen.TypeGenErr.fatal_error(fd, "方法流程掉出末尾但未显式 return", "TypeError") + else: self.Gen.TypeGenErr.fatal_error(fd, "method flow falls off the end without an explicit return", "TypeError") + else: self.Gen.TypeGenErr.fatal_error(fd, "method flow falls off the end without an explicit return", "TypeError") else: # fail-fast: has a -> annotation but control truly falls off the end (traceback-style). if ret_ty is not None: @@ -822,10 +822,10 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): if rt_name_m[0] == '\0': rt_name_m = "?" err_fn_m: str = pool.alloc(256) if err_fn_m is not None: - viperlib.snprintf(err_fn_m, 256, "方法 '%s' 流程掉出末尾但未显式 return(返回类型 %s),请补显式 return(如 return 0 / return null)", method_name, rt_name_m) + viperlib.snprintf(err_fn_m, 256, "method '%s' flow falls off the end without an explicit return (return type %s), please add an explicit return (e.g. return 0 / return null)", method_name, rt_name_m) self.Gen.TypeGenErr.fatal_error(fd, err_fn_m, "TypeError") - self.Gen.TypeGenErr.fatal_error(fd, "方法流程掉出末尾但未显式 return", "TypeError") - else: self.Gen.TypeGenErr.fatal_error(fd, "方法流程掉出末尾但未显式 return", "TypeError") + self.Gen.TypeGenErr.fatal_error(fd, "method flow falls off the end without an explicit return", "TypeError") + else: self.Gen.TypeGenErr.fatal_error(fd, "method flow falls off the end without an explicit return", "TypeError") # Restore the module-level scope. self.Gen.VarGen.exit_scope(trans.SymTab) @@ -982,7 +982,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): if arr_ctx is not None: fname_dbg_v: str = fe.Name if fname_dbg_v is None: fname_dbg_v = "?" - viperlib.snprintf(arr_ctx, 192, "类 %s 字段 %s:", class_name, fname_dbg_v) + viperlib.snprintf(arr_ctx, 192, "class %s field %s: ", class_name, fname_dbg_v) self.Gen.AssignGen._init_global_array_from_list(func_builder, pool, mod, field_ptr_arr, fe.DefaultVal, trans, arr_ctx) continue # Translate the default-value expression. diff --git a/App/lib/core/Gen/DebugInfoGen.vp b/App/lib/core/Gen/DebugInfoGen.vp index c7ac939..032e56b 100644 --- a/App/lib/core/Gen/DebugInfoGen.vp +++ b/App/lib/core/Gen/DebugInfoGen.vp @@ -68,7 +68,7 @@ def _EnsureStorage() -> int: rbuf: bytes = stdlib.malloc(DBG_LOC_SLOTS * 8) ubuf: bytes = stdlib.malloc(DBG_LOC_SLOTS) if sbuf1 is None or sbuf2 is None or sbuf3 is None or kbuf is None or rbuf is None or ubuf is None: - VLogger.error("--traceback: DWARF 元数据缓冲分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate DWARF metadata buffer, aborting compilation", "DWARF") return 1 string.memset(sbuf1, 0, DBG_STACK_MAX * 8) string.memset(sbuf2, 0, DBG_STACK_MAX * 8) @@ -132,7 +132,7 @@ def _EnsureModuleNodes(pool: memhub.MemBuddy*) -> int: cap_n: sizet = slen + 4112 nbuf: str = pool.alloc(cap_n) if nbuf is None: - VLogger.error("--traceback: DIFile 路径缓冲分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate DIFile path buffer, aborting compilation", "DWARF") return 1 if slen > 0: string.strncpy(nbuf, src, slen) nbuf[slen] = '\0' @@ -167,38 +167,38 @@ def _EnsureModuleNodes(pool: memhub.MemBuddy*) -> int: dsize: sizet = string.strlen(fname) + string.strlen(directory) + 96 dbuf: str = pool.alloc(dsize) if dbuf is None: - VLogger.error("--traceback: DIFile 节点缓冲分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate DIFile node buffer, aborting compilation", "DWARF") return 1 viperlib.snprintf(dbuf, dsize, "!DIFile(filename: \"%s\", directory: \"%s\")", fname, directory) fid: int = mlirlite.module_add_di_node(mod, pool, dbuf) if fid < 0: - VLogger.error("--traceback: DIFile 元数据节点分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate DIFile metadata node, aborting compilation", "DWARF") return 1 _g_file_id = fid # types: !{ null } placeholder list, then DISubroutineType referencing it nid: int = mlirlite.module_add_di_node(mod, pool, "!{ null }") if nid < 0: - VLogger.error("--traceback: DISubroutineType 类型表分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate DISubroutineType type table, aborting compilation", "DWARF") return 1 _g_null_id = nid tbuf: str = pool.alloc(64) if tbuf is None: - VLogger.error("--traceback: DISubroutineType 缓冲分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate DISubroutineType buffer, aborting compilation", "DWARF") return 1 viperlib.snprintf(tbuf, 64, "!DISubroutineType(types: !%d)", _g_null_id) tid: int = mlirlite.module_add_di_node(mod, pool, tbuf) if tid < 0: - VLogger.error("--traceback: DISubroutineType 元数据节点分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate DISubroutineType metadata node, aborting compilation", "DWARF") return 1 _g_subtype_id = tid cbuf: str = pool.alloc(256) if cbuf is None: - VLogger.error("--traceback: DICompileUnit 缓冲分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate DICompileUnit buffer, aborting compilation", "DWARF") return 1 viperlib.snprintf(cbuf, 256, "distinct !DICompileUnit(language: DW_LANG_C99, file: !%d, producer: \"TPC\", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)", _g_file_id) cid: int = mlirlite.module_add_di_node(mod, pool, cbuf) if cid < 0: - VLogger.error("--traceback: DICompileUnit 元数据节点分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate DICompileUnit metadata node, aborting compilation", "DWARF") return 1 _g_cu_id = cid return 0 @@ -230,11 +230,11 @@ def _EnsureLocation(pool: memhub.MemBuddy*, sp: int, line: int, col: int) -> str viperlib.snprintf(lbuf, 96, "!DILocation(line: %d, column: %d, scope: !%d)", line, c, sp) lid: int = mlirlite.module_add_di_node(_g_mod, pool, lbuf) if lid < 0: - VLogger.error("--traceback: DILocation 元数据节点分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate DILocation metadata node, aborting compilation", "DWARF") return None lref: str = _RefOf(pool, lid) if lref is None: - VLogger.error("--traceback: DILocation 引用缓冲分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate DILocation reference buffer, aborting compilation", "DWARF") return None if pi < DBG_LOC_PROBE: slot2: int = int((h + uint64(pi)) & uint64(DBG_LOC_SLOTS - 1)) @@ -255,12 +255,12 @@ def PushFunction(pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, func: mli if _g_enabled == 0: return 0 if pool is None or builder is None or func is None or _g_mod is None: return 0 if _g_depth >= DBG_STACK_MAX: - VLogger.error("--traceback: DWARF 函数嵌套深度超上限,终止编译", "DWARF") + VLogger.error("--traceback: DWARF function nesting depth exceeds the limit, aborting compilation", "DWARF") return 0 if _EnsureModuleNodes(pool) != 0: return 0 name: str = mlirlite.function_get_name(func) if name is None: - VLogger.error("--traceback: 函数名为空,无法发射 DISubprogram,终止编译", "DWARF") + VLogger.error("--traceback: function name is empty, cannot emit DISubprogram, aborting compilation", "DWARF") return 0 dline: int = line if dline <= 0: dline = 1 @@ -269,16 +269,16 @@ def PushFunction(pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, func: mli ssize: sizet = string.strlen(name) + 320 spbuf: str = pool.alloc(ssize) if spbuf is None: - VLogger.error("--traceback: DISubprogram 缓冲分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate DISubprogram buffer, aborting compilation", "DWARF") return 0 viperlib.snprintf(spbuf, ssize, "distinct !DISubprogram(name: \"%s\", scope: !%d, file: !%d, type: !%d, line: %d, scopeLine: %d, unit: !%d, spFlags: DISPFlagDefinition)", name, _g_file_id, _g_file_id, _g_subtype_id, dline, dline, _g_cu_id) sp_id: int = mlirlite.module_add_di_node(_g_mod, pool, spbuf) if sp_id < 0: - VLogger.error("--traceback: DISubprogram 元数据节点分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate DISubprogram metadata node, aborting compilation", "DWARF") return 0 sp_ref: str = _RefOf(pool, sp_id) if sp_ref is None: - VLogger.error("--traceback: DISubprogram 引用缓冲分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate DISubprogram reference buffer, aborting compilation", "DWARF") return 0 mlirlite.function_set_dbg(func, sp_ref) # save the enclosing function's DI context (LIFO), then switch to this one @@ -292,7 +292,7 @@ def PushFunction(pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, func: mli _g_cur_builder = builder entry_ref: str = _EnsureLocation(pool, sp_id, dline, dcol) if entry_ref is None: - VLogger.error("--traceback: 入口 DILocation 生成失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to generate entry DILocation, aborting compilation", "DWARF") return 0 _g_cur_entry_ref = entry_ref mlirlite.builder_set_debug_location(builder, entry_ref) @@ -355,25 +355,25 @@ def Finalize(pool: memhub.MemBuddy*) -> int: _g_finalized = 1 # Self-check (mirrors TPC Phase2Translator.py:3444): a module that emits a # define but carries no DI at all loses line info for its frames. - if mod.DIMetaCount == 0 and _ModuleHasDefine(mod) != 0: VLogger.warning("--traceback: 本模块发射了 define 但 IR 未携带 DWARF (!llvm.dbg.cu)——该模块帧在 Ctrl+C 栈里将只显示地址", "DWARF") + if mod.DIMetaCount == 0 and _ModuleHasDefine(mod) != 0: VLogger.warning("--traceback: this module emits a define but its IR carries no DWARF (!llvm.dbg.cu); its frames will show only addresses in the Ctrl+C stack", "DWARF") if _g_cu_id < 0: return 0 cu_ref: str = _RefOf(pool, _g_cu_id) if cu_ref is None: - VLogger.error("--traceback: DICompileUnit 引用缓冲分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate DICompileUnit reference buffer, aborting compilation", "DWARF") return 1 mlirlite.module_add_named_metadata(mod, pool, "llvm.dbg.cu", cu_ref) fbuf: str = pool.alloc(64) if fbuf is None: - VLogger.error("--traceback: 模块级调试标志缓冲分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate module-level debug flags buffer, aborting compilation", "DWARF") return 1 viperlib.snprintf(fbuf, 64, "!{i32 2, !\"Debug Info Version\", i32 3}") flags_id: int = mlirlite.module_add_di_node(mod, pool, fbuf) if flags_id < 0: - VLogger.error("--traceback: llvm.module.flags 元数据节点分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate llvm.module.flags metadata node, aborting compilation", "DWARF") return 1 fl_ref: str = _RefOf(pool, flags_id) if fl_ref is None: - VLogger.error("--traceback: llvm.module.flags 引用缓冲分配失败,终止编译", "DWARF") + VLogger.error("--traceback: failed to allocate llvm.module.flags reference buffer, aborting compilation", "DWARF") return 1 mlirlite.module_add_named_metadata(mod, pool, "llvm.module.flags", fl_ref) return 0 diff --git a/App/lib/core/Gen/Expr/ExprGenAttr.vp b/App/lib/core/Gen/Expr/ExprGenAttr.vp index 472f0cd..121aa5f 100644 --- a/App/lib/core/Gen/Expr/ExprGenAttr.vp +++ b/App/lib/core/Gen/Expr/ExprGenAttr.vp @@ -152,7 +152,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if cs_sha1 is None: return 0 if string.strncmp(cs_sha1, trans.ModuleSha1, 16) == 0: return 0 if self.Gen.CallGenBase.IsStaticSymbol(cs_sha1, at.attr) == 0: return 0 - self.Gen.TypeGenErr.fatal_error(at, f"'{cs_path}.{at.attr}' 是 static 符号,禁止跨模块使用(static 仅限定义模块内可见)", "NameError") + self.Gen.TypeGenErr.fatal_error(at, f"'{cs_path}.{at.attr}' is a static symbol, cross-module use is forbidden (static is only visible inside its defining module)", "NameError") return 0 def _resolve_module_attribute_global(self, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, trans: HT.Translator*, at: ast.Attribute*, ty_hint: mlirlite.LLVMType*) -> mlirlite.Value*: """Resolve a module attribute access to a global variable reference for cross-module use.""" @@ -272,7 +272,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if at is not None: if at.value is None: missing_an = "value" elif at.attr is None: missing_an = "attr" - viperlib.snprintf(diag_buf_an, 256, "属性访问失败: AST 节点字段缺失 (%s sha1=%s:%d)", missing_an, trans.ModuleSha1 if trans is not None and trans.ModuleSha1 is not None else "?", at.lineno if at is not None and at.lineno is not None else 0) + viperlib.snprintf(diag_buf_an, 256, "attribute access failed: AST node field missing (%s sha1=%s:%d)", missing_an, trans.ModuleSha1 if trans is not None and trans.ModuleSha1 is not None else "?", at.lineno if at is not None and at.lineno is not None else 0) VLogger.error(diag_buf_an, "ATTR") return None @@ -318,7 +318,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): return mlirlite.ConstInt(pool, base_ty, member.Value, name_buf) return mlirlite.const_int32(pool, member.Value) # fast-fail: enum member not found - VLogger.error(f"枚举成员未找到: {enum_nm.id}.{at.attr}", "ATTR") + VLogger.error(f"enum member not found: {enum_nm.id}.{at.attr}", "ATTR") return None # nested enum member access: Module.EnumName.MemberName → constant, when value is an Attribute at any @@ -339,7 +339,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): dbg_ee: GenTypes.EnumEntry* = self.Gen.StmtGenDecl.find_enum(inner_at_e.attr) dbg_mc: int = -1 if dbg_ee is not None: dbg_mc = dbg_ee.MemberCount - VLogger.error(f"嵌套枚举成员未找到: {inner_at_e.attr}.{at.attr} (enum_members={dbg_mc})", "ATTR") + VLogger.error(f"nested enum member not found: {inner_at_e.attr}.{at.attr} (enum_members={dbg_mc})", "ATTR") return None # REnum variant reference as a value: ClassName.Variant / Module.ClassName.Variant → the variant tag @@ -461,7 +461,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): # module defines a same-named global (e.g. PA_DEPS_MAX_STR); else fail-fast (undefined value). if self.Gen.ExprGenCdef._is_cdefine_name_pattern(at.attr) != 0: if self.find_global_in_module(mod, at.attr) is None: - self.Gen.TypeGenErr.fatal_error(at, f"跨模块 CDefine 未找到: '{nm_ma.id}.{at.attr}'(CDefine cross-module lookup failed)", "TypeError") + self.Gen.TypeGenErr.fatal_error(at, f"cross-module CDefine not found: '{nm_ma.id}.{at.attr}' (CDefine cross-module lookup failed)", "TypeError") # hit a cross-module global → fall through to the cross-module global load path # not a CDefine: use i8* as the type hint (module-level variables usually hold pointers) i8_ptr_hint: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) @@ -538,7 +538,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): # CDefine not found: fail-fast and stop compiling (no more undefined global # references, which would make llc report "use of undefined value"). if self.Gen.ExprGenCdef._is_cdefine_name_pattern(at.attr) != 0: - self.Gen.TypeGenErr.fatal_error(at, f"嵌套属性跨模块 CDefine 未找到: '{qual_buf}.{at.attr}'(CDefine cross-module lookup failed)", "TypeError") + self.Gen.TypeGenErr.fatal_error(at, f"nested attribute cross-module CDefine not found: '{qual_buf}.{at.attr}' (CDefine cross-module lookup failed)", "TypeError") return None # for a Name obj, look up the alloca directly (no struct load); nonlocal variables (hoisted @@ -734,7 +734,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if dbg_bp is not None: diag_base_txt = dbg_bp sha1_attr: str = "?" if trans.ModuleSha1 is not None: sha1_attr = trans.ModuleSha1 - self.Gen.TypeGenErr.fatal_error(at, f"属性访问失败: .{at.attr} (var={diag_var_txt} annot={diag_annot_txt} base={diag_base_txt} sha1={sha1_attr})", "TypeError") + self.Gen.TypeGenErr.fatal_error(at, f"attribute access failed: .{at.attr} (var={diag_var_txt} annot={diag_annot_txt} base={diag_base_txt} sha1={sha1_attr})", "TypeError") return None case _: # fast-fail: attribute access on a non-pointer type (e.g. i32.x) aborts immediately via a @@ -745,7 +745,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if trans is not None and trans.ModuleSha1 is not None: sha1_ap = trans.ModuleSha1 ln_ap: int = 0 if at is not None and at.lineno is not None: ln_ap = at.lineno - self.Gen.TypeGenErr.fatal_error(at, f"属性访问失败: .{attr_nm_ap} (base=非指针类型,无法做属性访问 sha1={sha1_ap}:{ln_ap})", "TypeError") + self.Gen.TypeGenErr.fatal_error(at, f"attribute access failed: .{attr_nm_ap} (base=non-pointer type, cannot do attribute access sha1={sha1_ap}:{ln_ap})", "TypeError") # explicit return after fatal_error: the final match arm must be terminated, else falling off # the end is misjudged by the function tail as fail-fast return None @@ -1075,7 +1075,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if dbg_bp_g is not None: diag_base_txt_g = dbg_bp_g sha1_attr_g: str = "?" if trans.ModuleSha1 is not None: sha1_attr_g = trans.ModuleSha1 - self.Gen.TypeGenErr.fatal_error(at, f"属性写入失败: .{at.attr} (var={diag_var_txt_g} annot={diag_annot_txt_g} base={diag_base_txt_g} sha1={sha1_attr_g})", "TypeError") + self.Gen.TypeGenErr.fatal_error(at, f"attribute write failed: .{at.attr} (var={diag_var_txt_g} annot={diag_annot_txt_g} base={diag_base_txt_g} sha1={sha1_attr_g})", "TypeError") return None case _: # fast-fail: attribute write on a non-pointer type (e.g. i32.x = ...) aborts immediately via a @@ -1086,6 +1086,6 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if trans is not None and trans.ModuleSha1 is not None: sha1_gp = trans.ModuleSha1 ln_gp: int = 0 if at is not None and at.lineno is not None: ln_gp = at.lineno - self.Gen.TypeGenErr.fatal_error(at, f"属性写入失败: .{attr_nm_gp} (base=非指针类型,无法做属性写入 sha1={sha1_gp}:{ln_gp})", "TypeError") + self.Gen.TypeGenErr.fatal_error(at, f"attribute write failed: .{attr_nm_gp} (base=non-pointer type, cannot do attribute write sha1={sha1_gp}:{ln_gp})", "TypeError") # explicit return after fatal_error: the final match arm must be terminated return None \ No newline at end of file diff --git a/App/lib/core/Gen/Expr/ExprGenBase.vp b/App/lib/core/Gen/Expr/ExprGenBase.vp index e20b623..68651e0 100644 --- a/App/lib/core/Gen/Expr/ExprGenBase.vp +++ b/App/lib/core/Gen/Expr/ExprGenBase.vp @@ -301,7 +301,7 @@ novirtual class ExprGenBase: """Fail fast (return 1) when a bare str/bytes annotation holds an aggregate pointer.""" if annot_is_str == 0 or val is None or val.Ty is None: return 0 if self._str_rejects_ptr_kind(val) == 0: return 0 - self.Gen.TypeGenErr.fatal_error(self._value_node_of(node), "str/bytes 不接受指向非基本类型(结构体/类/非字符数组/函数)的指针:两者在 IR 层" "同为 i8*,但语义不同(str/bytes 不是通用指针通配)。若确需传递指针," "请改用 t.CPtr/rawptr 形参,或显式转换(如 t.CPtr(p))", "CastError") + self.Gen.TypeGenErr.fatal_error(self._value_node_of(node), "str/bytes does not accept a pointer to a non-basic type (struct/class/non-char array/function): both are" "i8* at the IR level, but with different semantics (str/bytes is not a general pointer wildcard). If a pointer must be passed, " "use a t.CPtr/rawptr parameter instead, or cast explicitly (e.g. t.CPtr(p))", "CastError") return 1 def fail_if_str_annot_ast_agg_ptr(self, val: mlirlite.Value*, annot: ast.AST*, node: ast.AST* = None) -> int: """AST-annotation entry: fail fast when a bare str/bytes annotation holds an aggregate pointer.""" @@ -421,13 +421,13 @@ novirtual class ExprGenBase: # Names the level and why, plus source/target types; result is heap-copied. def _ptr_cast_reason_text(self, code: int, pool: memhub.MemBuddy*, src_ty: mlirlite.LLVMType*, dst_ty: mlirlite.LLVMType*) -> str: """Human-readable reason for a forbidden ptr -> ptr cast (includes source/target types).""" - why: str = "原因未知" - if code == PC_DEPTH: why = f"指针层数不同(源 {self.get_ptr_level(src_ty)} 级 → 目标 {self.get_ptr_level(dst_ty)} 级)" - elif code == PC_NONBASIC: why = "被指类型是非基本类型(结构体/类/联合/数组等):非基本类型与其指针之间、以及不同非基本类型的指针之间一律不允许隐式转换" - elif code == PC_LOSSY: why = "被指类型之间的转换有损(整数→浮点位宽不足 / 浮点→整数)" + why: str = "unknown reason" + if code == PC_DEPTH: why = f"pointer level differs (source level {self.get_ptr_level(src_ty)} -> target level {self.get_ptr_level(dst_ty)})" + elif code == PC_NONBASIC: why = "the pointee type is a non-basic type (struct/class/union/array etc.): implicit conversion is never allowed between a non-basic type and its pointer, or between pointers of different non-basic types" + elif code == PC_LOSSY: why = "conversion between the pointee types is lossy (int -> float with insufficient width / float -> int)" s_txt: str = self._type_text(pool, src_ty) d_txt: str = self._type_text(pool, dst_ty) - return GenApi.escape_fstring_copy(f"指针隐式转指针已禁止:{why};源类型 {s_txt} → 目标类型 {d_txt}") + return GenApi.escape_fstring_copy(f"implicit pointer-to-pointer conversion is forbidden: {why}; source type {s_txt} -> target type {d_txt}") # _ctor_call_agg_ty - aggregate type if node is a class/struct constructor call. # The only exception to rule 3 ("construction materialization"); else None. def _ctor_call_agg_ty(self, node: ast.AST*) -> mlirlite.LLVMType*: @@ -478,7 +478,7 @@ novirtual class ExprGenBase: # fails fast instead of emitting illegal IR (load void / bitcast void). if self.Gen.StmtGenDecl._is_void_type(val.Ty) != 0: if self.Gen.StmtGenDecl._is_void_type(target_ty) == 0: - self.Gen.TypeGenErr.fatal_error(self._value_node_of(node), "void 类型的值不能参与任何操作(void 只能用于 void* 与 typedef 别名)", "TypeError") + self.Gen.TypeGenErr.fatal_error(self._value_node_of(node), "a void value cannot take part in any operation (void is only allowed for void* and typedef aliases)", "TypeError") return val # func -> ptr: bitcast (function Values have Func type, handled before # the integer/float conversions). @@ -497,13 +497,13 @@ novirtual class ExprGenBase: # [FIX 2026-08-31] C null pointer constant exemption: compile-time 0 # assigned to a pointer becomes a null pointer (widen to i64, then inttoptr). if val.IsConst == 1 and val.IntVal == 0: return mlirlite.build_inttoptr(builder, mlirlite.const_int64(builder.Pool, 0), target_ty) - m_i2p: str = "整数隐式转指针已禁止:必须显式强转为指针(如 t.CPtr(x))才能把整数赋给指针类型" + m_i2p: str = "implicit integer-to-pointer conversion is forbidden: an explicit cast to pointer (e.g. t.CPtr(x)) is required to assign an integer to a pointer type" self.Gen.TypeGenErr.fatal_error(self._value_node_of(node), m_i2p, "CastError") return val # Pointer -> integer: rejected (symmetric with the int -> ptr rule above). # An explicit cast is required; the old code silently did ptrtoint. if self.is_ptr_type(val.Ty) != 0 and target_bits != 0 and self.is_ptr_type(target_ty) == 0: - m_p2i: str = "指针隐式转整数已禁止:必须显式强转(如 uint64(p) / int64(p) / int(p))才能把指针赋给整数类型" + m_p2i: str = "implicit pointer-to-integer conversion is forbidden: an explicit cast (e.g. uint64(p) / int64(p) / int(p)) is required to assign a pointer to an integer type" self.Gen.TypeGenErr.fatal_error(self._value_node_of(node), m_p2i, "CastError") return val if val_bits != 0 and target_bits != 0: @@ -524,7 +524,7 @@ novirtual class ExprGenBase: target_max_u: uint64 = (uint64(1) << target_bits) - 1 if uint64(val.IntVal) > target_max_u: max_print: int64 = int64(target_max_u) - self.Gen.TypeGenErr.fatal_error(node, f"窄化截断溢出:常量 {val.IntVal} 超出目标类型 {target_bits} 位范围 [0, {max_print}],赋值将被静默截断", "OverflowError") + self.Gen.TypeGenErr.fatal_error(node, f"narrowing truncation overflow: constant {val.IntVal} exceeds the {target_bits}-bit range [0, {max_print}] of the target type, the assignment would be silently truncated", "OverflowError") return mlirlite.build_trunc(builder, val, target_ty) # Float conversion. val_fbits: int = self.get_llvm_float_bits(val.Ty) @@ -550,8 +550,8 @@ novirtual class ExprGenBase: # forbidden, except "construction materialization" (see _ctor_call_agg_ty). ctor_v2p: mlirlite.LLVMType* = self._ctor_call_agg_ty(node) if self._same_agg_ty(builder.Pool, ctor_v2p, val.Ty) == 0: - m_v2p: str = "非基本类型的值/指针隐式转换已禁止(构造物化除外):不能把非基本类型值隐式转为指针(Foo → Foo*),如需取址请显式 c.addr(...) / &v,或显式强转" - v2p_txt: str = GenApi.escape_fstring_copy(f";源值类型 {self._type_text(builder.Pool, val.Ty)} → 目标类型 {self._type_text(builder.Pool, target_ty)}") + m_v2p: str = "implicit value/pointer conversion for non-basic types is forbidden (except construction materialization): a non-basic value cannot be implicitly converted to a pointer (Foo -> Foo*); to take its address use c.addr(...) / &v explicitly, or cast explicitly" + v2p_txt: str = GenApi.escape_fstring_copy(f"; source value type {self._type_text(builder.Pool, val.Ty)} -> target type {self._type_text(builder.Pool, target_ty)}") self.Gen.TypeGenErr.fatal_error(self._value_node_of(node), f"{m_v2p}{v2p_txt}", "CastError") return val tmp_agg: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, val.Ty) @@ -574,12 +574,12 @@ novirtual class ExprGenBase: # forbidden, except "construction materialization" (see _ctor_call_agg_ty). ctor_p2v: mlirlite.LLVMType* = self._ctor_call_agg_ty(node) if self._same_agg_ty(builder.Pool, ctor_p2v, target_ty) == 0: - m_p2v: str = "非基本类型的值/指针隐式转换已禁止(构造物化除外):不能把指针类型隐式转为非基本类型值(Foo* → Foo),如需解引用请显式 c.deref(p) / *p,或显式强转" - p2v_txt: str = GenApi.escape_fstring_copy(f";源类型 {self._type_text(builder.Pool, val.Ty)} → 目标值类型 {self._type_text(builder.Pool, target_ty)}") + m_p2v: str = "implicit value/pointer conversion for non-basic types is forbidden (except construction materialization): a pointer type cannot be implicitly converted to a non-basic value (Foo* -> Foo); to dereference use c.deref(p) / *p explicitly, or cast explicitly" + p2v_txt: str = GenApi.escape_fstring_copy(f"; source type {self._type_text(builder.Pool, val.Ty)} -> target value type {self._type_text(builder.Pool, target_ty)}") self.Gen.TypeGenErr.fatal_error(self._value_node_of(node), f"{m_p2v}{p2v_txt}", "CastError") return val return mlirlite.build_load(builder, target_ty, val) - self.Gen.TypeGenErr.fatal_error(self._value_node_of(node), f"指针隐式转非指针值已禁止:必须显式解引用(*p / *p)或显式强转(uint64(p))", "CastError") + self.Gen.TypeGenErr.fatal_error(self._value_node_of(node), f"implicit pointer-to-non-pointer-value conversion is forbidden: an explicit dereference (*p / *p) or explicit cast (uint64(p)) is required", "CastError") return val # ptr -> ptr: implicit conversion must satisfy the new rules (see # _ptr_cast_reason); violators fail fast with a CastError. diff --git a/App/lib/core/Gen/Expr/ExprGenCdef.vp b/App/lib/core/Gen/Expr/ExprGenCdef.vp index 630cc01..8633fd6 100644 --- a/App/lib/core/Gen/Expr/ExprGenCdef.vp +++ b/App/lib/core/Gen/Expr/ExprGenCdef.vp @@ -104,9 +104,9 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): if depth > 32: err_buf: str = pool.alloc(256) if err_buf is not None: - viperlib.snprintf(err_buf, 256, "跨模块 CDefine 查找递归过深(疑似模块循环 import/re-export): %s (depth=%d fi=%s)", name, depth, from_imports if from_imports is not None else "(nil)") + viperlib.snprintf(err_buf, 256, "cross-module CDefine lookup recursion too deep (suspected module import/re-export cycle): %s (depth=%d fi=%s)", name, depth, from_imports if from_imports is not None else "(nil)") self.Gen.TypeGenErr.fatal_error(node, err_buf, "InternalCompilerError") - self.Gen.TypeGenErr.fatal_error(node, "跨模块 CDefine 查找递归过深(疑似模块循环 import/re-export)", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(node, "cross-module CDefine lookup recursion too deep (suspected module import/re-export cycle)", "InternalCompilerError") # clear the found flag at entry so every early return reports "not found", # avoiding a stale success flag left over from a previous recursive call. self.Gen.TypeGenCDef.set_cdefine_found(0) @@ -262,7 +262,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): # report and abort instead of silently returning -1 (avoids bad @UNDEFINED refs). err_buf: str = pool.alloc(512) if err_buf is not None: - viperlib.snprintf(err_buf, 512, "跨模块 CDefine 查找失败:SHA1 %s 不在存储器中(base_mod=%s name=%s)。" "Phase1/Phase2 未正确填充 PopulateSha1MapStore/AppendToSha1MapStore", sha1, base_mod, name) + viperlib.snprintf(err_buf, 512, "cross-module CDefine lookup failed: SHA1 %s is not in the store (base_mod=%s name=%s). " "Phase1/Phase2 did not correctly populate PopulateSha1MapStore/AppendToSha1MapStore", sha1, base_mod, name) VLogger.error(err_buf, "XMOD-CD") stdlib.free(pyi_buf) return -1 @@ -861,7 +861,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): if use_ctx is not None: # this language's str is i8* with no `str + str`: `+` degrades to pointer add. # Build strings with f-string interpolation / string.strcat / viperlib.snprintf. - ctx = f"({use_ctx})" - self.Gen.TypeGenErr.fatal_error(node, f"[TPV] define 常量使用处宽度不足: 常量 '{name}' 的实际值 {value} " f"需要至少 {wmin} 位(最小可容纳宽度 W_min)," f"但使用处{ctx}只提供 {bits} 位" f"(该位宽按有符号/无符号两种解释可接受的范围: {lo}..{hi})。" f"禁止静默截断/降级,已终止编译。" f"修法: 把使用处{ctx}的类型加宽到至少 {wmin} 位" f"(如 int{wmin}T / CUInt{wmin}T 及更宽类型),或改用更小的常量值。", "TypeError") + ctx = f"({use_ctx})" + self.Gen.TypeGenErr.fatal_error(node, f"[TPV] define constant use site width insufficient: constant '{name}' actual value {value} " f"needs at least {wmin} bits (minimum representable width W_min), " f"but the use site{ctx} provides only {bits} bits " f"(the acceptable range for this bit width under both signed/unsigned interpretation: {lo}..{hi}). " f"silent truncation/downgrade is forbidden, compilation aborted. " f"fix: widen the type of the use site{ctx} to at least {wmin} bits " f"(e.g. int{wmin}T / CUInt{wmin}T or wider types), or use a smaller constant value.", "TypeError") return None return mlirlite.const_int(pool, bits, self._cdefine_bits_value(value, bits)) \ No newline at end of file diff --git a/App/lib/core/Gen/Expr/ExprGenConst.vp b/App/lib/core/Gen/Expr/ExprGenConst.vp index 0cc948b..c6427b7 100644 --- a/App/lib/core/Gen/Expr/ExprGenConst.vp +++ b/App/lib/core/Gen/Expr/ExprGenConst.vp @@ -188,11 +188,11 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): first_elem_val = self.Gen.ExprGen.translate_value(builder, pool, mod, first_elem_node, None, 0, trans) if first_elem_val is None or first_elem_val.Ty is None: # fail-fast: first-element translation failed/Value type missing -> abort now (surface root cause) - self.Gen.TypeGenErr.fatal_error(first_elem_node, "list 字面量元素类型推断失败(Value 类型缺失)", "TypeError") + self.Gen.TypeGenErr.fatal_error(first_elem_node, "list literal element type inference failed (Value type missing)", "TypeError") inferred_type_name = self._infer_elem_type_from_value(pool, first_elem_val) if inferred_type_name is None: # fail-fast: first-element Value type cannot map to a list element type -> abort now - self.Gen.TypeGenErr.fatal_error(first_elem_node, "list 字面量元素类型推断失败(Value 类型缺失)", "TypeError") + self.Gen.TypeGenErr.fatal_error(first_elem_node, "list literal element type inference failed (Value type missing)", "TypeError") else: # Empty list has no element to infer, keep default str (list[str]) inferred_type_name = "str" diff --git a/App/lib/core/Gen/Expr/ExprGenFstr.vp b/App/lib/core/Gen/Expr/ExprGenFstr.vp index 311e75e..6a250c4 100644 --- a/App/lib/core/Gen/Expr/ExprGenFstr.vp +++ b/App/lib/core/Gen/Expr/ExprGenFstr.vp @@ -52,7 +52,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fv.value, None, 0, trans) if val is None: # fail-fast: a failed formatted-value translation must abort compilation - self.Gen.TypeGenErr.fatal_error(fv.value, "f-string 格式化值翻译失败(表达式返回 None)", "TypeError") + self.Gen.TypeGenErr.fatal_error(fv.value, "f-string formatted value translation failed (expression returned None)", "TypeError") continue # Object defines __str__ and no format is given -> use its returned string (like TPC) if fv.format_spec is None: @@ -64,7 +64,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): if c_fmt is None: c_fmt = self._fstr_infer_c_fmt(pool, val, fv.value, trans) if c_fmt is None: # fail-fast: cannot infer the f-string format (missing value type); abort - self.Gen.TypeGenErr.fatal_error(fv.value, "f-string 格式无法推断(值类型缺失)", "TypeError") + self.Gen.TypeGenErr.fatal_error(fv.value, "f-string format cannot be inferred (value type missing)", "TypeError") # Append the format specifier if string.strlen(fmt_buf) + string.strlen(c_fmt) < FSTR_BUF_SIZE - 1: string.strcat(fmt_buf, c_fmt) # Convert the argument type (i8/i16->i32, bool->i32, f32->f64) @@ -91,7 +91,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fv.value, None, 0, trans) if val is None: # fail-fast: a failed bare FormattedValue translation must abort compilation - self.Gen.TypeGenErr.fatal_error(fv.value, "f-string 格式化值翻译失败(表达式返回 None)", "TypeError") + self.Gen.TypeGenErr.fatal_error(fv.value, "f-string formatted value translation failed (expression returned None)", "TypeError") else: # Object defines __str__ and no format is given -> use its returned string (like TPC) if fv.format_spec is None: @@ -102,7 +102,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): if c_fmt is None: c_fmt = self._fstr_infer_c_fmt(pool, val, fv.value, trans) if c_fmt is None: # fail-fast: cannot infer the f-string format (missing value type); abort - self.Gen.TypeGenErr.fatal_error(fv.value, "f-string 格式无法推断(值类型缺失)", "TypeError") + self.Gen.TypeGenErr.fatal_error(fv.value, "f-string format cannot be inferred (value type missing)", "TypeError") if string.strlen(fmt_buf) + string.strlen(c_fmt) < FSTR_BUF_SIZE - 1: string.strcat(fmt_buf, c_fmt) cast_val: mlirlite.Value* = self._fstr_cast_value(builder, pool, val, c_fmt, fv.value, trans) if cast_val is None: cast_val = val @@ -343,7 +343,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): if fbits != 0: return "%f" if self.Gen.ExprGenBase.is_ptr_type(val.Ty) != 0: return "%s" # fail-fast: missing value type (not int/float/pointer); cannot infer the C format - self.Gen.TypeGenErr.fatal_error(arg_node, "f-string 格式无法推断(值类型缺失)", "TypeError") + self.Gen.TypeGenErr.fatal_error(arg_node, "f-string format cannot be inferred (value type missing)", "TypeError") return None def _fstr_cast_value(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, val: mlirlite.Value*, c_fmt: str, arg_node: ast.AST*, trans: HT.Translator*) -> mlirlite.Value*: """Cast the value to the type required by the C format specifier.""" diff --git a/App/lib/core/Gen/Expr/ExprGenMixin.vp b/App/lib/core/Gen/Expr/ExprGenMixin.vp index 4dcad80..1b0d7a6 100644 --- a/App/lib/core/Gen/Expr/ExprGenMixin.vp +++ b/App/lib/core/Gen/Expr/ExprGenMixin.vp @@ -32,7 +32,7 @@ novirtual class ExprGenMixin(ExprGenBase.ExprGenBase): """Translate a value expression to an LLVM Value (depth-guard wrapper; see _translate_value_impl). target_ty = assignment/parameter type context; use_ctx = real call site for CDefine width checks.""" if trans is not None: - if trans.TranslateDepth >= HT.TRANSLATE_MAX_DEPTH: self.Gen.TypeGenErr.fatal_error(node, "表达式翻译嵌套过深(疑似 AST 自引用环或翻译 bug)", "RecursionError") + if trans.TranslateDepth >= HT.TRANSLATE_MAX_DEPTH: self.Gen.TypeGenErr.fatal_error(node, "expression translation nested too deep (suspected AST self-reference cycle or translation bug)", "RecursionError") trans.TranslateDepth += 1 rv: mlirlite.Value* = self._translate_value_impl(builder, pool, mod, node, funcs_ptr, func_count, trans, target_ty, use_ctx) if trans is not None: trans.TranslateDepth -= 1 diff --git a/App/lib/core/Gen/Expr/ExprGenName.vp b/App/lib/core/Gen/Expr/ExprGenName.vp index 9db3ab1..bebef01 100644 --- a/App/lib/core/Gen/Expr/ExprGenName.vp +++ b/App/lib/core/Gen/Expr/ExprGenName.vp @@ -49,7 +49,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # string (i8*) for `return ZLIB_VERSION`. cdef_sv: str = self.Gen.TypeGenCDef.lookup_cdefine_string(nm_id) if cdef_sv is not None: return self.Gen.ExprGenConst.create_global_string(builder, pool, mod, cdef_sv, trans) - self.Gen.TypeGenErr.fatal_error(node, f"CDefine 字符串值缺失: {nm_id}", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(node, f"CDefine string value missing: {nm_id}", "InternalCompilerError") if self.Gen.TypeGenCDef.is_cdefine_double() != 0: return mlirlite.ConstFloat(pool, mlirlite.Double(pool), cdef_val_d) # Integer CDefine: re-look-up the full 64-bit value (a double round-trip loses # precision and would generate a wrong constant). @@ -72,7 +72,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if self.Gen.TypeGenCDef.is_cdefine_str() != 0: cdef_sv2: str = self.Gen.TypeGenCDef.lookup_cdefine_string(nm_id) if cdef_sv2 is not None: return self.Gen.ExprGenConst.create_global_string(builder, pool, mod, cdef_sv2, trans) - self.Gen.TypeGenErr.fatal_error(node, f"CDefine 字符串值缺失: {nm_id}", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(node, f"CDefine string value missing: {nm_id}", "InternalCompilerError") # Cross-module float CDefine is cached as double; return a float constant # rather than a truncated integer. dchk_nm: double = self.Gen.TypeGenCDef.lookup_cdefine_double(nm_id) @@ -115,7 +115,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if mod_alloca.Ty is not None: load_ty = mod_alloca.Ty.Pointee if load_ty is None: # fail-fast: a global with a missing storage type aborts compilation - self.Gen.TypeGenErr.fatal_error(node, f"变量 '{nm_id}' 存储类型缺失", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"variable '{nm_id}' storage type missing", "TypeError") # Global arrays decay to the base address per C semantics; otherwise a loaded # array value passed as i8* loses writes (test_pyzlib "error message is empty"). match load_ty: @@ -147,7 +147,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if alloca.Ty is not None: load_ty = alloca.Ty.Pointee if load_ty is None: # fail-fast: a local with a missing storage type aborts compilation - self.Gen.TypeGenErr.fatal_error(node, f"变量 '{nm_id}' 存储类型缺失", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"variable '{nm_id}' storage type missing", "TypeError") # Struct-value variable (alloca of Struct): rvalues return its address by default; # a value is loaded only when the use site demands a same-type struct value. match load_ty: @@ -195,7 +195,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): fn_ret_ty: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(fn_ref) if fn_ret_ty is None: # fail-fast: a missing function return type prevents building the function pointer - self.Gen.TypeGenErr.fatal_error(node, f"函数 '{nm_id}' 返回类型缺失,无法构造函数指针", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"function '{nm_id}' return type missing, cannot build the function pointer", "TypeError") fn_pp: mlirlite.Param* = mlirlite.function_get_param_head(fn_ref) fn_first_node: mlirlite.ParamNode* = None fn_prev_node: mlirlite.ParamNode* = None @@ -278,8 +278,8 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): ctp_n: sizet = len(trans.GenericTypeParamNames) cta_n: sizet = 0 if trans.GenericTypeArgs is not None: cta_n = len(trans.GenericTypeArgs) - ctx_txt = f"(当前泛型上下文: 类型形参 {ctp_n} 个 / 类型实参 {cta_n} 个)" - self.Gen.TypeGenErr.fatal_error(node, f"未定义名称 '{nm_id}'{ctx_txt}", "NameError") + ctx_txt = f"(current generic context: {ctp_n} type params / {cta_n} type args)" + self.Gen.TypeGenErr.fatal_error(node, f"undefined name '{nm_id}'{ctx_txt}", "NameError") return None # list_getitem_inline - inline list[T] __getitem__; returns the element address (i8*). # Layout (6 fields x 8 bytes): __data__(0) __count__(8) __capacity__(16) __pool__(24) __elem_size__(32) __iter_index__(40). diff --git a/App/lib/core/Gen/Expr/ExprGenOps.vp b/App/lib/core/Gen/Expr/ExprGenOps.vp index a7a7df0..3295fa8 100644 --- a/App/lib/core/Gen/Expr/ExprGenOps.vp +++ b/App/lib/core/Gen/Expr/ExprGenOps.vp @@ -57,7 +57,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): then_blk_for_phi: mlirlite.BasicBlock* = trans._cur_builder.CurBlock if body_val is None: # fail-fast: ternary then-branch translation failed; abort compilation (expose the upstream root cause) - self.Gen.TypeGenErr.fatal_error(ie.body, "三元表达式分支翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(ie.body, "ternary expression branch translation failed", "TypeError") # Do not br yet; br after type alignment # 5. else branch. When the then-branch is a pointer, pass its type as the else target-type context: a single-quoted @@ -69,7 +69,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): else_blk_for_phi: mlirlite.BasicBlock* = trans._cur_builder.CurBlock if orelse_val is None: # fail-fast: ternary else-branch translation failed; abort compilation (expose the upstream root cause) - self.Gen.TypeGenErr.fatal_error(ie.orelse, "三元表达式分支翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(ie.orelse, "ternary expression branch translation failed", "TypeError") # Do not br yet; br after type alignment # Type alignment (the two branches may differ): coerce_to_type must run inside each branch so the merge block's @@ -110,7 +110,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): phi_ty: mlirlite.LLVMType* = body_val.Ty if phi_ty is None: # fail-fast: ternary branch type missing; abort compilation (expose the upstream root cause) - self.Gen.TypeGenErr.fatal_error(node, "三元表达式分支类型缺失", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "ternary expression branch type missing", "TypeError") inc1: mlirlite.PhiIncoming* = mlirlite.new_phi_incoming(pool, body_val, then_blk_for_phi) inc2: mlirlite.PhiIncoming* = mlirlite.new_phi_incoming(pool, orelse_val, else_blk_for_phi) @@ -438,7 +438,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): elif rhs_ptr_level != 0 and lhs_ptr_level == 0: rhs = mlirlite.build_ptrtoint(builder, rhs, lhs.Ty) else: # Different-level pointers (1 vs 2 etc.) -> forbidden (fail-fast) - self.Gen.TypeGenErr.fatal_error(cmp, f"比较类型不匹配: 不同级指针比较 (lhs 层级={lhs_ptr_level}, rhs 层级={rhs_ptr_level})", "TypeError") + self.Gen.TypeGenErr.fatal_error(cmp, f"comparison type mismatch: pointers of different levels compared (lhs level={lhs_ptr_level}, rhs level={rhs_ptr_level})", "TypeError") else: # None comparison: the None side is implicitly 0/null, its form decided by the other side. # pointer -> same-type null pointer (icmp eq/ne); integer -> 0 (x == 0); struct value -> never None (== false, != true). @@ -576,7 +576,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): d_pointee: mlirlite.LLVMType* = operand.Ty.Pointee if d_pointee is not None: return mlirlite.build_load(builder, d_pointee, operand) # Non-pointer means type inference degraded: fail-fast, never fall back to reading as i8 - self.Gen.TypeGenErr.fatal_error(node, "单目 '*' 解引用的操作数必须是指针类型(类型推断退化)", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "the operand of unary '*' dereference must be a pointer type (type inference degraded)", "TypeError") return None elif uo.op == ast.OpKind.AddrOf: # &x -> lvalue address (no load): Name alloca / module global / module function / Attribute field GEP / Subscript element address. @@ -649,7 +649,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # a ctor call would re-run __before_init__/__init__). See _addrof_of_call. ac_ao: mlirlite.Value* = self._addrof_of_call(builder, pool, operand) if ac_ao is not None: return ac_ao - self.Gen.TypeGenErr.fatal_error(node, "单目 '&' 取地址的操作数必须是左值(Name/Attribute/Subscript)或构造调用/函数调用结果", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "the operand of unary '&' address-of must be an lvalue (Name/Attribute/Subscript) or a constructor/function call result", "TypeError") return None return operand @@ -1055,7 +1055,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if is_aug != 0: # Augmented assignment: build the "+=" form with an f-string (this language's str has no `+` concatenation). op_lbl = f"{op_ch}=" - aug_note = "(增量赋值)" + aug_note = "(augmented assignment)" lty_buf: str = pool.alloc(512) rty_buf: str = pool.alloc(512) lty_lbl: str = "?" @@ -1070,7 +1070,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if string.strcmp(rty_buf, "i8*") == 0: rty_lbl = "str(i8*)" col_s: int = 0 if node is not None: col_s = node.col_offset + 1 - self.Gen.TypeGenErr.fatal_error(node, f"[TPV] 双指针运算类型非法: op = '{op_lbl}'{aug_note}," f"左操作数类型 = {lty_lbl},右操作数类型 = {rty_lbl}。" f"本语言的 str 是 i8*,没有 `+` 拼接语义(`str + str` 与指针 ± 指针" f"都会退化成裸指针 add/sub ⇒ 非法 IR: opt 报 " f"invalid operand type for instruction)。" f"禁止静默降级,已终止编译。" f"修法: 用 f-string 插值、string.strcat 或 viperlib.snprintf 构建字符串。", "TypeError", col_s, col_s) + self.Gen.TypeGenErr.fatal_error(node, f"[TPV] illegal double-pointer arithmetic type: op = '{op_lbl}'{aug_note}, " f"left operand type = {lty_lbl}, right operand type = {rty_lbl}. " f"in this language str is i8*, with no `+` concatenation semantics (`str + str` and pointer +/- pointer " f"both degrade to raw pointer add/sub => illegal IR: opt reports " f"invalid operand type for instruction). " f"silent degradation is forbidden, compilation aborted. " f"fix: build strings with f-string interpolation, string.strcat, or viperlib.snprintf.", "TypeError", col_s, col_s) return 1 # translate_binop - binary operations with automatic type promotion # ============================================================ @@ -1179,7 +1179,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if lhs_bits == 0 and rhs_bits == 0: if op == ast.OpKind.BitOr or op == ast.OpKind.BitAnd or op == ast.OpKind.BitXor or op == ast.OpKind.LShift or op == ast.OpKind.RShift: # fail-fast: illegal bitwise operand types; abort compilation (expose the upstream root cause) - self.Gen.TypeGenErr.fatal_error(node, "位运算操作数类型非法: lhs/rhs 均为非整数类型(指针或结构体),无法执行位运算", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "illegal bitwise operand types: both lhs/rhs are non-integer types (pointer or struct), cannot perform bitwise operations", "TypeError") if op == ast.OpKind.Add: return mlirlite.build_add(builder, lhs, rhs) elif op == ast.OpKind.Sub: return mlirlite.build_sub(builder, lhs, rhs) diff --git a/App/lib/core/Gen/Func/FuncGenBase.vp b/App/lib/core/Gen/Func/FuncGenBase.vp index 8368996..b4bcebb 100644 --- a/App/lib/core/Gen/Func/FuncGenBase.vp +++ b/App/lib/core/Gen/Func/FuncGenBase.vp @@ -251,7 +251,7 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase): elif rcr_deco.kind() == ast.ASTKind.Attribute: rcr_attr = ast.Attribute*(rcr_deco) if rcr_attr is None or rcr_attr.attr is None: continue if string.strcmp(rcr_attr.attr, "CReturn") == 0: - self.Gen.TypeGenErr.fatal_error(node, "`@c.CReturn` 已移除:请改用返回注解 `-> tuple[ty1, ty2, ...]`(多返回值打包为 struct 返回)", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "`@c.CReturn` removed: use a return annotation `-> tuple[ty1, ty2, ...]` instead (multiple return values are packed into a struct return)", "TypeError") return 1 return 0 # Create LLVM function (simple version, declaration only) @@ -282,7 +282,7 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase): if resolved is None: # [S4 fail-fast] Annotation present but unresolvable: no silent i32 fallback. # This fn lacks trans/imports context, so failure surfaces upstream. - self.Gen.TypeGenErr.fatal_error(arg, f"函数 '{name}' 形参 '{arg.arg}' 类型注解解析失败", "NameError") + self.Gen.TypeGenErr.fatal_error(arg, f"function '{name}' param '{arg.arg}' type annotation failed to resolve", "NameError") return None param_ty = resolved pname: str = pool.alloc(32) diff --git a/App/lib/core/Gen/Func/FuncGenDef.vp b/App/lib/core/Gen/Func/FuncGenDef.vp index 43f9baa..ead0f36 100644 --- a/App/lib/core/Gen/Func/FuncGenDef.vp +++ b/App/lib/core/Gen/Func/FuncGenDef.vp @@ -93,7 +93,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): if ret_ty is None and fd.returns is not None: # Return annotation present but unresolvable: compile-time error, no silent i32 fallback # (that forced return i32 and misaligned cross-module return types). No annotation keeps i32. - self.Gen.TypeGenErr.fatal_error(fd, "函数返回类型解析失败:注解不可解析", "TypeError") + self.Gen.TypeGenErr.fatal_error(fd, "function return type resolution failed: annotation is not resolvable", "TypeError") return 0 if ret_ty is None: ret_ty = i32_ty @@ -178,7 +178,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): if resolved is None: # [S4 fail-fast] Annotation present but unresolvable: no silent i32 # (declare/define signature mismatch -> ABI misalignment, runtime reads garbage from the stack) - self.Gen.TypeGenErr.fatal_error(arg, f"前向声明形参 '{arg.arg}' 类型注解解析失败", "NameError") + self.Gen.TypeGenErr.fatal_error(arg, f"forward declaration param '{arg.arg}' type annotation failed to resolve", "NameError") return 0 # Bare class param -> Ptr(struct) (object is a pointer); CArray param -> element pointer ty* (C array decay). # Exception (keep in sync in 3 places): C ABI extern bare struct params pass by value %Struct with a full definition. @@ -186,7 +186,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): case mlirlite.LLVMType.Void(): # void is not a legal param type (void is only for void* and typedef of an opaque struct); # fail-fast at compile time instead of emitting invalid IR. `void*` is already i8* upstream. - self.Gen.TypeGenErr.fatal_error(arg, f"形参 '{arg.arg}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError") + self.Gen.TypeGenErr.fatal_error(arg, f"param '{arg.arg}' cannot be void type (void is only allowed for void* and typedef aliases)", "TypeError") return 0 case mlirlite.LLVMType.Struct(_, _, _): if is_extern_decl != 0 and self.Gen.StructGen.find_struct_by_type(resolved) is not None: @@ -268,10 +268,10 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): if self.Gen.TypeGenErr.body_has_value_return(pool, fd.children) != 0: rtn_err: str = pool.alloc(256) if rtn_err is not None: - viperlib.snprintf(rtn_err, 256, "函数 '%s' 无返回类型注解却返回了非 None 值,请添加显式返回类型注解(如 -> int)", fd.name) + viperlib.snprintf(rtn_err, 256, "function '%s' has no return type annotation but returns a non-None value, add an explicit return type annotation (e.g. -> int)", fd.name) self.Gen.TypeGenErr.fatal_error(fd, rtn_err, "TypeError") return 0 - self.Gen.TypeGenErr.fatal_error(fd, "函数无返回类型注解却返回了非 None 值", "TypeError") + self.Gen.TypeGenErr.fatal_error(fd, "function has no return type annotation but returns a non-None value", "TypeError") return 0 param_types_str: str = self.Gen.TypeGenErr.build_param_types_str(pool, fd.args) ret_ty = self.Gen.TypeGenErr.infer_return_type(pool, fd.children, param_types_str) @@ -375,7 +375,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): if resolved_e is None: # fail-fast: extern function param has an annotation but is unresolvable; no silent i32 # (a wrong declare signature shows up at the ABI layer) - self.Gen.TypeGenErr.fatal_error(arg_e, f"参数 '{arg_e.arg}' 类型解析失败: {self.Gen.TypeGenResolve.annotation_to_str(arg_e.annotation)}", "NameError") + self.Gen.TypeGenErr.fatal_error(arg_e, f"argument '{arg_e.arg}' failed to resolve type: {self.Gen.TypeGenResolve.annotation_to_str(arg_e.annotation)}", "NameError") resolved_e = i32_ty # unreachable (fatal_error already exited) if resolved_e is not None: # Bare class param -> Ptr(struct); CArray param -> element pointer ty* (C decay). This branch is @@ -383,7 +383,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): match resolved_e: case mlirlite.LLVMType.Void(): # void is not a legal param type (see the same rule above) - self.Gen.TypeGenErr.fatal_error(arg_e, f"形参 '{arg_e.arg}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError") + self.Gen.TypeGenErr.fatal_error(arg_e, f"param '{arg_e.arg}' cannot be void type (void is only allowed for void* and typedef aliases)", "TypeError") case mlirlite.LLVMType.Struct(_, _, _): if self.Gen.StructGen.find_struct_by_type(resolved_e) is not None: self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, resolved_e) @@ -473,14 +473,14 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): if resolved is None: # [S4 fail-fast] Annotation present but unresolvable: no silent i32 # (wrong param type -> ABI misalignment / wrong field access) - self.Gen.TypeGenErr.fatal_error(arg, f"形参 '{arg.arg}' 类型注解解析失败", "NameError") + self.Gen.TypeGenErr.fatal_error(arg, f"param '{arg.arg}' type annotation failed to resolve", "NameError") return 0 # Bare class param -> Ptr(struct); CArray param -> element pointer ty* (C array decay). Passing # Ptr(array) would make out[i]'s GEP stride by the whole array (garbage summary root cause). match resolved: case mlirlite.LLVMType.Void(): # void is not a legal param type (see the same rule above) - self.Gen.TypeGenErr.fatal_error(arg, f"形参 '{arg.arg}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError") + self.Gen.TypeGenErr.fatal_error(arg, f"param '{arg.arg}' cannot be void type (void is only allowed for void* and typedef aliases)", "TypeError") return 0 case mlirlite.LLVMType.Struct(_, _, _): param_ty = mlirlite.Ptr(pool, resolved) @@ -596,7 +596,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): resolved2: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg2.annotation, imported_modules, from_imports, trans, 0) if resolved2 is None: # fail-fast: param has an annotation but is unresolvable; no silent i32 - self.Gen.TypeGenErr.fatal_error(arg2, f"参数 '{arg2.arg}' 类型解析失败: {self.Gen.TypeGenResolve.annotation_to_str(arg2.annotation)}", "NameError") + self.Gen.TypeGenErr.fatal_error(arg2, f"argument '{arg2.arg}' failed to resolve type: {self.Gen.TypeGenResolve.annotation_to_str(arg2.annotation)}", "NameError") resolved2 = i32_ty # unreachable (fatal_error already exited) if resolved2 is not None: # Consistent with add_param: bare class param -> Ptr(struct); CArray param -> element pointer ty* @@ -604,7 +604,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): match resolved2: case mlirlite.LLVMType.Void(): # void is not a legal param type (see the same rule above) - self.Gen.TypeGenErr.fatal_error(arg2, f"形参 '{arg2.arg}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError") + self.Gen.TypeGenErr.fatal_error(arg2, f"param '{arg2.arg}' cannot be void type (void is only allowed for void* and typedef aliases)", "TypeError") return 0 case mlirlite.LLVMType.Struct(_, _, _): param_ty2 = mlirlite.Ptr(pool, resolved2) @@ -781,8 +781,8 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): if ret_ty is not None: zero_val: mlirlite.Value* = mlirlite.ConstZero(pool, ret_ty) if zero_val is not None: mlirlite.build_ret(func_builder, zero_val) - else: self.Gen.TypeGenErr.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError") - else: self.Gen.TypeGenErr.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError") + else: self.Gen.TypeGenErr.fatal_error(node, "function flow falls off the end without an explicit return", "TypeError") + else: self.Gen.TypeGenErr.fatal_error(node, "function flow falls off the end without an explicit return", "TypeError") else: # fail-fast: has a -> annotation but the flow falls off the end (pointing at the function definition # node; fatal_error prints a traceback-style error). @@ -795,10 +795,10 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): if rt_name[0] == '\0': rt_name = "?" err_fn: str = pool.alloc(256) if err_fn is not None: - viperlib.snprintf(err_fn, 256, "函数 '%s' 流程掉出函数末尾但未显式 return(返回类型 %s),请补显式 return(如 return 0 / return null)", fd.name, rt_name) + viperlib.snprintf(err_fn, 256, "function '%s' flow falls off the end of the function without an explicit return (return type %s), please add an explicit return (e.g. return 0 / return null)", fd.name, rt_name) self.Gen.TypeGenErr.fatal_error(node, err_fn, "TypeError") - self.Gen.TypeGenErr.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError") - else: self.Gen.TypeGenErr.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "function flow falls off the end without an explicit return", "TypeError") + else: self.Gen.TypeGenErr.fatal_error(node, "function flow falls off the end without an explicit return", "TypeError") # Restore module-level scope (exit the function scope) self.Gen.VarGen.exit_scope(trans.SymTab) diff --git a/App/lib/core/Gen/Func/FuncGenMixin.vp b/App/lib/core/Gen/Func/FuncGenMixin.vp index 8ea1d0f..b5be157 100644 --- a/App/lib/core/Gen/Func/FuncGenMixin.vp +++ b/App/lib/core/Gen/Func/FuncGenMixin.vp @@ -674,7 +674,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): """Compute an LLVM type's byte size recursively""" if ty is None: # [S4 fail-fast] Missing type -> no longer assume 8 bytes (under-allocation overruns neighbors) - self.Gen.TypeGenErr.fatal_error(None, "nonlocal 共享存储:类型缺失,无法计算尺寸", "TypeError") + self.Gen.TypeGenErr.fatal_error(None, "nonlocal shared storage: type missing, cannot compute size", "TypeError") return 0 match ty: case mlirlite.LLVMType.Int(bits): @@ -869,7 +869,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg_n.annotation, trans._imported_modules, trans._from_imports, trans, 0) if resolved is None: # fail-fast: annotated lambda param failed to resolve; do not silently keep i32 - self.Gen.TypeGenErr.fatal_error(arg_n, f"参数 '{arg_n.arg}' 类型解析失败: {self.Gen.TypeGenResolve.annotation_to_str(arg_n.annotation)}", "NameError") + self.Gen.TypeGenErr.fatal_error(arg_n, f"argument '{arg_n.arg}' failed to resolve type: {self.Gen.TypeGenResolve.annotation_to_str(arg_n.annotation)}", "NameError") resolved = i32_ty # unreachable (fatal_error already exited) if resolved is not None: match resolved: @@ -980,7 +980,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): p_ty3: mlirlite.LLVMType* = (mlirlite.LLVMType*)(ty_slot4[0]) if p_ty3 is None: # fail-fast: lambda param type slot missing (inconsistent state); do not keep i32 - self.Gen.TypeGenErr.fatal_error(lam, f"lambda 参数 '{param_names + pi3 * 32}' 类型信息缺失", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(lam, f"lambda param '{param_names + pi3 * 32}' type info missing", "InternalCompilerError") p_ty3 = i32_ty # unreachable (fatal_error already exited) pname_ref: str = pool.alloc(32) if pname_ref is not None: @@ -1000,10 +1000,10 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): if ret_val is not None: mlirlite.build_ret(func_builder, ret_val) else: # fail-fast: lambda body coercion failed; do not silently return 0 - self.Gen.TypeGenErr.fatal_error(lam.body, "lambda 体表达式翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(lam.body, "lambda body expression translation failed", "TypeError") else: # fail-fast: lambda body translation failed; do not silently return 0 - self.Gen.TypeGenErr.fatal_error(lam.body, "lambda 体表达式翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(lam.body, "lambda body expression translation failed", "TypeError") # 12. Leave the lambda scope and restore the parent state self.Gen.VarGen.exit_scope(trans.SymTab) diff --git a/App/lib/core/Gen/GenApi.vp b/App/lib/core/Gen/GenApi.vp index f6ec333..4affb59 100644 --- a/App/lib/core/Gen/GenApi.vp +++ b/App/lib/core/Gen/GenApi.vp @@ -443,7 +443,7 @@ def fail_if_fstring_escape(node: ast.AST*, where: str) -> int: break if hit == 0: return 0 if _g_gen is not None: - _g_gen.TypeGenErr.fatal_error(node, f"f-string 结果不能用于{where}(逃逸):f-string 指向**当前函数的栈缓冲**," f"函数返回即失效,把这个指针带出函数会读到已弹栈的帧" f"(历史事故:ASan stack-buffer-underflow in vsnprintf)。" f"需要带出函数时显式分配后拷贝:" f"tmp: str = f\"...\";out: str = GenApi.escape_fstring_copy(tmp);return out。", "TypeError") + _g_gen.TypeGenErr.fatal_error(node, f"f-string result cannot be used in {where} (escape): f-string points at **the stack buffer of the current function**, " f"which becomes invalid once the function returns; carrying this pointer out of the function reads an already-popped frame" f"(historical incident: ASan stack-buffer-underflow in vsnprintf). " f"when the value must outlive the function, allocate and copy explicitly: " f"tmp: str = f\"...\"; out: str = GenApi.escape_fstring_copy(tmp); return out.", "TypeError") return 0 diff --git a/App/lib/core/Gen/ImportsGenMixin.vp b/App/lib/core/Gen/ImportsGenMixin.vp index 60f0bd6..93949de 100644 --- a/App/lib/core/Gen/ImportsGenMixin.vp +++ b/App/lib/core/Gen/ImportsGenMixin.vp @@ -401,7 +401,7 @@ novirtual class ImportsGenMixin: # Truncate at the last '.' new_pkg: str = pool.alloc(last_dot + 1) if new_pkg is None: - self.Gen.TypeGenErr.fatal_error(None, f"相对导入解析失败:level={level} module='{module}'", "ImportError") + self.Gen.TypeGenErr.fatal_error(None, f"relative import resolution failed: level={level} module='{module}'", "ImportError") return module string.strncpy(new_pkg, pkg, last_dot) new_pkg[last_dot] = '\0' @@ -419,7 +419,7 @@ novirtual class ImportsGenMixin: mod_len: sizet = string.strlen(module) buf: str = pool.alloc(pkg_len2 + 1 + mod_len + 1) if buf is None: - self.Gen.TypeGenErr.fatal_error(None, f"相对导入解析失败:level={level} module='{module}'", "ImportError") + self.Gen.TypeGenErr.fatal_error(None, f"relative import resolution failed: level={level} module='{module}'", "ImportError") return module string.strcpy(buf, pkg) buf[pkg_len2] = '.' @@ -549,9 +549,9 @@ novirtual class ImportsGenMixin: if self._is_local_module_file(mod_name) != 0: return 1 err_buf: str = stdlib.malloc(256) if err_buf is not None: - viperlib.snprintf(err_buf, 256, "模块 '%s' 未注册 SHA1(includes 扫描未找到该模块,请检查 project.json 的 includes 路径配置)", mod_name) + viperlib.snprintf(err_buf, 256, "module '%s' has no registered SHA1 (the includes scan did not find this module; check the includes path configuration in project.json)", mod_name) self._report_import_error(node, err_buf) - else: self._report_import_error(node, "导入模块 SHA1 未注册(includes 扫描未找到该模块)") + else: self._report_import_error(node, "imported module SHA1 not registered (the includes scan did not find this module)") return 1 # translate_import - handle import statements and update trans._imported_modules @@ -623,7 +623,7 @@ novirtual class ImportsGenMixin: if sf_sha1 is None: return 0 if string.strncmp(sf_sha1, trans.ModuleSha1, 16) == 0: return 0 if self.Gen.CallGenBase.IsStaticSymbol(sf_sha1, orig_name) == 0: return 0 - self.Gen.TypeGenErr.fatal_error(node, f"'{fi_target}.{orig_name}' 是 static 符号,禁止跨模块使用(static 仅限定义模块内可见)", "NameError") + self.Gen.TypeGenErr.fatal_error(node, f"'{fi_target}.{orig_name}' is a static symbol; cross-module use is forbidden (static is visible only within the defining module)", "NameError") return 0 diff --git a/App/lib/core/Gen/MatchGenMixin.vp b/App/lib/core/Gen/MatchGenMixin.vp index 43de567..772752b 100644 --- a/App/lib/core/Gen/MatchGenMixin.vp +++ b/App/lib/core/Gen/MatchGenMixin.vp @@ -46,7 +46,7 @@ novirtual class MatchGenMixin: def translate_match(self, trans: HT.Translator*, node: ast.AST*) -> int: """Translate one match statement; wraps _translate_match_impl with a depth guard.""" if trans is not None: - if trans.MatchTranslateDepth >= MATCH_TRANSLATE_MAX_DEPTH: self.Gen.TypeGenErr.fatal_error(node, "match 翻译嵌套过深(疑似 AST 自引用环或翻译 bug)", "RecursionError") + if trans.MatchTranslateDepth >= MATCH_TRANSLATE_MAX_DEPTH: self.Gen.TypeGenErr.fatal_error(node, "match translation nested too deeply (suspected AST self-reference cycle or translation bug)", "RecursionError") trans.MatchTranslateDepth += 1 mret: int = self._translate_match_impl(trans, node) if trans is not None: trans.MatchTranslateDepth -= 1 @@ -91,11 +91,11 @@ novirtual class MatchGenMixin: if dcase2 is not None and dcase2.kind() == ast.ASTKind.MatchCase: dpat2: ast.AST* = ast.MatchCase*(dcase2).pattern if self._case_label_same(dpat, dpat2) != 0: - self.Gen.TypeGenErr.fatal_error(dcase2, f"match 出现重名 case:第 {dci} 与第 {dcj} 个 case 的标签相同(match 不允许重复 case 标签)", "SyntaxError") + self.Gen.TypeGenErr.fatal_error(dcase2, f"match has duplicate case names: case {dci} and case {dcj} carry the same label (match does not allow duplicate case labels)", "SyntaxError") dcj = dcj + 1 dci = dci + 1 if default_cnt > 1: - self.Gen.TypeGenErr.fatal_error(node, f"{kind_label} 出现 {default_cnt} 个{default_label}(无 guard 的通配/default 只允许一个;带 guard 的 `case _ if ...` / `default if ...` 可有多个)", "SyntaxError") + self.Gen.TypeGenErr.fatal_error(node, f"{kind_label} has {default_cnt} {default_label} arms (only one guardless wildcard/default is allowed; guarded `case _ if ...` / `default if ...` may appear multiple times)", "SyntaxError") # 1. Evaluate the subject. subject_node: ast.AST* = m_node.subject @@ -106,7 +106,7 @@ novirtual class MatchGenMixin: subject_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, subject_node, trans._funcs, trans._func_count, trans) if subject_val is None: # fail-fast: match subject translation failed. - self.Gen.TypeGenErr.fatal_error(subject_node, "match subject 翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(subject_node, "match subject translation failed", "TypeError") # 2. Detect whether this is a REnum match. is_renum: int = 0 @@ -280,7 +280,7 @@ novirtual class MatchGenMixin: rn_case: ast.AST* = rn_cases.get(rn_i) if rn_case is not None and rn_case.kind() == ast.ASTKind.MatchCase: if ast.MatchCase*(rn_case).guard is not None: - self.Gen.TypeGenErr.fatal_error(rn_case, "REnum match 暂不支持 guard 守卫(该臂会被 switch(tag) 静默忽略);请改为普通 match 或去掉 guard", "NotImplementedError") + self.Gen.TypeGenErr.fatal_error(rn_case, "REnum match does not yet support a guard (that arm would be silently ignored by switch(tag)); use a plain match or remove the guard", "NotImplementedError") rn_i = rn_i + 1 # 0. Normalize subject_ptr to a pointer to the REnum struct (aligns TPC HandlesMatch.py:238-259 _HandleRenumMatchLlvm). @@ -297,7 +297,7 @@ novirtual class MatchGenMixin: if renum_se is not None: renum_sty = renum_se.Ty if renum_sty is None: # fail-fast: REnum struct not registered, cannot construct. - self.Gen.TypeGenErr.fatal_error(node, f"REnum 结构体 '{renum_name}' 未注册", "NameError") + self.Gen.TypeGenErr.fatal_error(node, f"REnum struct '{renum_name}' not registered", "NameError") i64_ty0: mlirlite.LLVMType* = mlirlite.Int64(pool) int_val: mlirlite.Value* = subject_ptr # Widen/truncate non-i64 integers to i64 (inttoptr requires equal width); only when subj_ty is a known integer type. @@ -319,11 +319,11 @@ novirtual class MatchGenMixin: tag_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, subject_ptr, tag_ptr_ty) if tag_ptr is None: # fail-fast: REnum tag pointer cast failed. - self.Gen.TypeGenErr.fatal_error(node, "REnum tag 指针转换失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "REnum tag pointer cast failed", "TypeError") tag_val: mlirlite.Value* = mlirlite.build_load(builder, tag_ty, tag_ptr) if tag_val is None: # fail-fast: REnum tag load failed. - self.Gen.TypeGenErr.fatal_error(node, "REnum tag 读取失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "REnum tag read failed", "TypeError") # 2. Create the default/end BBs. cnt: int = trans._label_counter @@ -331,7 +331,7 @@ novirtual class MatchGenMixin: name_buf: str = pool.alloc(32) if name_buf is None: # fail-fast: label buffer allocation failed. - self.Gen.TypeGenErr.fatal_error(node, "标签缓冲区分配失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "label buffer allocation failed", "TypeError") viperlib.snprintf(name_buf, 32, "match.default.%d", cnt) default_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf) viperlib.snprintf(name_buf, 32, "match.end.%d", cnt) @@ -341,7 +341,7 @@ novirtual class MatchGenMixin: cases_list: list[ast.AST*]* = node.cases if cases_list is None: # fail-fast: match cases missing. - self.Gen.TypeGenErr.fatal_error(node, "match cases 缺失", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "match cases missing", "TypeError") case_count: sizet = len(cases_list) # BB pointer array, case-value pointer array, default-flag array, nobreak-flag array. @@ -353,7 +353,7 @@ novirtual class MatchGenMixin: mc_arr: sizet* = pool.alloc(8 * MAX_MATCH_CASES) if bb_arr is None or cv_arr is None or def_arr is None or nb_arr is None or mc_arr is None: # fail-fast: match dispatch array allocation failed. - self.Gen.TypeGenErr.fatal_error(node, "match 分派数组分配失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "match dispatch array allocation failed", "TypeError") collected: int = 0 has_default: int = 0 @@ -372,7 +372,7 @@ novirtual class MatchGenMixin: diag_tmp: str = pool.alloc(128) if miss_buf is None or diag_tmp is None: # fail-fast: diagnostics buffer allocation failed (same handling as name_buf above). - self.Gen.TypeGenErr.fatal_error(node, "match 诊断缓冲区分配失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "match diagnostics buffer allocation failed", "TypeError") miss_buf[0] = '\0' miss_cnt: int = 0 # The variant table registers bare class names (ClassDef.name) while renum_name comes from the annotation form (Spec.SourceName; an Attribute may carry a module prefix like "mod.LLVMType"), so an exact strcmp would always miss and silently drop the arm. Strip the module prefix first. @@ -478,7 +478,7 @@ novirtual class MatchGenMixin: # 5. Emit the switch. No silent case dropping: the number of must-submit arms (non-default MatchClass/MatchValue) must equal sw_count; a mismatch fail-fasts with class/lookup name/expected/actual and each missing arm's index(variant,tag). if need_case != sw_count: - self.Gen.TypeGenErr.fatal_error(node, f"REnum match 分派丢失 case:class='{renum_name}'(查表名='{tag_cls_bare}')应提交 {need_case} 个 case,实际提交 {sw_count} 个;未取到值的臂:{miss_buf}", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(node, f"REnum match dispatch dropped cases: class='{renum_name}' (lookup name='{tag_cls_bare}') should submit {need_case} cases, actually submitted {sw_count}; arms with no value: {miss_buf}", "InternalCompilerError") mlirlite.build_switch(builder, tag_val, default_bb, sw_head, sw_count) # 6. Find the REnum struct type (for variant-field GEP). Fall back to the bare class name because renum_name may carry a module prefix, and scan for an entry with a valid Ty since find_struct may hit a neutralized old entry (Ty=None). @@ -542,7 +542,7 @@ novirtual class MatchGenMixin: ent_fc = renum_entry.FieldCount ty_present: int = 0 if renum_ty is not None: ty_present = 1 - self.Gen.TypeGenErr.fatal_error(pat, f"REnum match 变体字段绑定失败:class='{tag_cls_bare}'(查表名='{renum_name}')" f" entry='{ent_nm}' FieldCount={ent_fc} ty_present={ty_present};" f"变体表已登记该类,说明结构体条目或 Ty 缺失(已不再静默跳过绑定," f"否则绑定名未定义只会在下游报 NameError)", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(pat, f"REnum match variant field binding failed: class='{tag_cls_bare}' (lookup name='{renum_name}')" f" entry='{ent_nm}' FieldCount={ent_fc} ty_present={ty_present}; " f"the variant table has registered this class, so the struct entry or its Ty is missing (binding is no longer silently skipped, " f"otherwise an undefined binding name would only surface as a NameError downstream)", "InternalCompilerError") # Translate the case body. body_list: list[ast.AST*]* = mc.children @@ -647,19 +647,19 @@ novirtual class MatchGenMixin: else: # fail-fast: payload out of range and alias lookup failed. # (node is not available here; locate via sub_pat. Under TPC Python an undefined name errors only at runtime, but TPV lazily compiling the method body raises NameError immediately.) - self.Gen.TypeGenErr.fatal_error(sub_pat, f"REnum 变体字段 '{bind_name}' 在结构体 '{renum_name}' 中越界且别名查找失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(sub_pat, f"REnum variant field '{bind_name}' is out of range in struct '{renum_name}' and alias lookup failed", "TypeError") # Get the field type. fe: GenTypes.FieldEntry* = (self.Gen.StructGen._get_field_entry(renum_entry, payload_idx)) field_ty: mlirlite.LLVMType* = None if fe is not None: field_ty = fe.Ty if field_ty is None: # fail-fast: variant field type missing; no i8 fallback allowed. - self.Gen.TypeGenErr.fatal_error(sub_pat, f"REnum 变体字段类型缺失: {bind_name}", "TypeError") + self.Gen.TypeGenErr.fatal_error(sub_pat, f"REnum variant field type missing: {bind_name}", "TypeError") # GEP to the field address. elem_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, renum_ty, field_ty,casted_ptr, payload_idx) if elem_ptr is None: # fail-fast: variant field address computation failed. - self.Gen.TypeGenErr.fatal_error(sub_pat, f"REnum 变体字段 '{bind_name}' 地址计算失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(sub_pat, f"REnum variant field '{bind_name}' address computation failed", "TypeError") # Actual variant-member type (aligns TPC class_members): the alias table stores the annotation-resolved member type, used to bitcast the slot address to Ptr(member type) so the binding reads the payload as the member type (otherwise i64 slot reads break is-comparison/index/strlen). # Must be located by (class, variant name, position): a MatchAs name is a local variable name, not a field name, so field-name lookup never matches, and the same payload position differs across variants. Falls back to the slot type when a self-referential type fails to resolve. mem_ty_m: mlirlite.LLVMType* = None @@ -721,7 +721,7 @@ novirtual class MatchGenMixin: elts_inl: list[ast.AST*]* = elts elt: ast.AST* = elts_inl.get(ei) sv: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, elt, trans._funcs, trans._func_count, trans) - if sv is None: self.Gen.TypeGenErr.fatal_error(elt, f"match 序列元素 {ei} 翻译失败", "TypeError") + if sv is None: self.Gen.TypeGenErr.fatal_error(elt, f"match sequence element {ei} translation failed", "TypeError") subj_vals[ei] = sizet(sv) # 2. Create the default/end BBs. @@ -754,7 +754,7 @@ novirtual class MatchGenMixin: # Capacity guard (aligns the `collected < MAX_MATCH_CASES` check in the match-list paths): the default (case _) branch must also validate collected before writing check_arr/body_arr/def_arr/nb_arr/guard_arr, else too many cases overflow into adjacent pool blocks. # Over-limit fail-fasts, never silently dropping a case. if collected >= MAX_MATCH_CASES: - self.Gen.TypeGenErr.fatal_error(node, f"match case 数量超过上限 MAX_MATCH_CASES={MAX_MATCH_CASES}", "OverflowError") + self.Gen.TypeGenErr.fatal_error(node, f"match case count exceeds the limit MAX_MATCH_CASES={MAX_MATCH_CASES}", "OverflowError") break case_node: ast.AST* = cases_list.get(i) if case_node is None or case_node.kind() != ast.ASTKind.MatchCase: @@ -770,11 +770,11 @@ novirtual class MatchGenMixin: if ma0.pattern is None: # A top-level `case _ if `: this sequence path treats `_` as default (always true) and would silently ignore the guard; fail-fast before any IR is produced. if mc.guard is not None: - self.Gen.TypeGenErr.fatal_error(pat, "序列匹配的顶层 `case _ if ` 暂不支持 guard 守卫", "NotImplementedError") + self.Gen.TypeGenErr.fatal_error(pat, "the top-level `case _ if ` of a sequence match does not yet support a guard", "NotImplementedError") is_def = 1 elif pk != ast.ASTKind.MatchSequence: # fail-fast: sequence matching accepts only MatchSequence / a top-level `_` wildcard. - self.Gen.TypeGenErr.fatal_error(pat, "序列匹配 case 只支持 (元素) 或 _ 模式", "TypeError") + self.Gen.TypeGenErr.fatal_error(pat, "a sequence-match case supports only an (element) or _ pattern", "TypeError") if is_def == 1: has_default = 1 default_case_node = case_node @@ -836,10 +836,10 @@ novirtual class MatchGenMixin: if pk1 == ast.ASTKind.MatchValue: mv: ast.MatchValue* = (ast.MatchValue*)(pat1) pv: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, mv.value, trans._funcs, trans._func_count, trans) - if pv is None: self.Gen.TypeGenErr.fatal_error(pat1, f"序列模式元素 {pi} 翻译失败", "TypeError") + if pv is None: self.Gen.TypeGenErr.fatal_error(pat1, f"sequence pattern element {pi} translation failed", "TypeError") sv1: mlirlite.Value* = mlirlite.Value*(subj_vals[pi]) c1: mlirlite.Value* = self._seq_cmp_eq(trans, builder, sv1, pv) - if c1 is None: self.Gen.TypeGenErr.fatal_error(pat1, "序列模式元素比较失败", "TypeError") + if c1 is None: self.Gen.TypeGenErr.fatal_error(pat1, "sequence pattern element comparison failed", "TypeError") if cond is None: cond = c1 else: cond = mlirlite.build_and(builder, cond, c1) elif pk1 == ast.ASTKind.MatchAs: @@ -848,16 +848,16 @@ novirtual class MatchGenMixin: continue # `_` wildcard: always true if ma2.name is not None: # fail-fast: sequence-pattern variable binding not supported. - self.Gen.TypeGenErr.fatal_error(pat1, "序列模式变量绑定暂不支持", "NotImplementedError") + self.Gen.TypeGenErr.fatal_error(pat1, "sequence-pattern variable binding is not yet supported", "NotImplementedError") elif pk1 == ast.ASTKind.MatchStar: continue # remaining elements wildcard: always true - else: self.Gen.TypeGenErr.fatal_error(pat1, "序列模式不支持的 pattern 类型", "TypeError") + else: self.Gen.TypeGenErr.fatal_error(pat1, "unsupported pattern type in a sequence pattern", "TypeError") # guard (if any): match holds and guard is non-zero. g_addr: sizet = guard_arr[ci] if g_addr != 0: gnode: ast.AST* = (ast.AST*)(g_addr) gv: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, gnode, trans._funcs, trans._func_count, trans) - if gv is None: self.Gen.TypeGenErr.fatal_error(gnode, "match guard 翻译失败", "TypeError") + if gv is None: self.Gen.TypeGenErr.fatal_error(gnode, "match guard translation failed", "TypeError") gbits: int = self.Gen.ExprGenBase.get_llvm_type_bits(gv.Ty) if gbits == 1: g1: mlirlite.Value* = gv else: @@ -979,7 +979,7 @@ novirtual class MatchGenMixin: subj_val = mlirlite.build_ptrtoint(builder, subject_val, i32_ty) if subj_val is None: # fail-fast: subject-to-i32 conversion failed. - self.Gen.TypeGenErr.fatal_error(node, "match subject 转换为 i32 失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "match subject conversion to i32 failed", "TypeError") # 1b. Guard pre-scan: any guarded arm switches to the in-order if-else chain (_handle_guarded_simple_match, Python match semantics). # Without guards, the existing switch path below stays byte-identical (no behavior change). @@ -1001,7 +1001,7 @@ novirtual class MatchGenMixin: name_buf: str = pool.alloc(32) if name_buf is None: # fail-fast: label buffer allocation failed. - self.Gen.TypeGenErr.fatal_error(node, "标签缓冲区分配失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "label buffer allocation failed", "TypeError") viperlib.snprintf(name_buf, 32, "match.default.%d", cnt) default_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf) viperlib.snprintf(name_buf, 32, "match.end.%d", cnt) @@ -1011,7 +1011,7 @@ novirtual class MatchGenMixin: cases_list: list[ast.AST*]* = node.cases if cases_list is None: # fail-fast: match cases missing. - self.Gen.TypeGenErr.fatal_error(node, "match cases 缺失", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "match cases missing", "TypeError") case_count: sizet = len(cases_list) bb_arr: sizet* = pool.alloc(8 * MAX_MATCH_CASES) @@ -1022,7 +1022,7 @@ novirtual class MatchGenMixin: mo_arr: sizet* = pool.alloc(8 * MAX_MATCH_CASES) if bb_arr is None or cv_arr is None or def_arr is None or nb_arr is None or mo_arr is None: # fail-fast: match dispatch array allocation failed. - self.Gen.TypeGenErr.fatal_error(node, "match 分派数组分配失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "match dispatch array allocation failed", "TypeError") collected: int = 0 has_default: int = 0 @@ -1073,7 +1073,7 @@ novirtual class MatchGenMixin: # If the class-pattern actually points to a registered REnum, REnum dispatch mismatched; fail-fast instead of silently dropping the case. rnm_nr: str = self._extract_renum_name_from_cls(pat) if rnm_nr is not None and (self.Gen.ClassGenEnum._is_renum_class_name(rnm_nr) != 0 or self.Gen.ClassGenEnum._is_renum_by_entry(rnm_nr) != 0): - self.Gen.TypeGenErr.fatal_error(pat, f"非 REnum 路径收到 REnum 变体模式 'case {rnm_nr}.*':case 值无法产出,该臂会被静默丢弃(REnum 分派失配)", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(pat, f"the non-REnum path received a REnum variant pattern 'case {rnm_nr}.*': no case value can be produced, so the arm would be silently dropped (REnum dispatch mismatch)", "InternalCompilerError") if is_def == 0: if collected >= MAX_MATCH_CASES: break @@ -1100,7 +1100,7 @@ novirtual class MatchGenMixin: # MatchOr arm: emit one case value per alternative, all pointing to the same bb (equivalent to C `case 1: case 2:` sharing a body); non-MatchValue/MatchSingleton alternatives fail-fast. mo2: ast.MatchOr* = (ast.MatchOr*)(mo_addr) pats2: list[ast.AST*]* = mo2.patterns - if pats2 is None or len(pats2) == 0: self.Gen.TypeGenErr.fatal_error(pat, "switch OR 模式无备选子模式", "TypeError") + if pats2 is None or len(pats2) == 0: self.Gen.TypeGenErr.fatal_error(pat, "switch OR pattern has no alternative sub-patterns", "TypeError") pats2_n: sizet = len(pats2) pats2_i: int = 0 while pats2_i < pats2_n: @@ -1113,7 +1113,7 @@ novirtual class MatchGenMixin: elif alt_pat.kind() == ast.ASTKind.MatchSingleton: # None -> 0 (same as the single-value/guard paths). alt_cv = mlirlite.const_int32(pool, 0) - else: self.Gen.TypeGenErr.fatal_error(alt_pat, "switch OR 模式备选不是值模式", "TypeError") + else: self.Gen.TypeGenErr.fatal_error(alt_pat, "a switch OR pattern alternative is not a value pattern", "TypeError") if alt_cv is not None: sc2: mlirlite.SwitchCase* = mlirlite.new_switch_case(pool, alt_cv, bb) if sc2 is not None: @@ -1254,7 +1254,7 @@ novirtual class MatchGenMixin: cnt: int = trans._label_counter trans._label_counter = cnt + 1 name_buf: str = pool.alloc(32) - if name_buf is None: self.Gen.TypeGenErr.fatal_error(node, "标签缓冲区分配失败", "TypeError") + if name_buf is None: self.Gen.TypeGenErr.fatal_error(node, "label buffer allocation failed", "TypeError") viperlib.snprintf(name_buf, 32, "match.guard.default.%d", cnt) default_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf) viperlib.snprintf(name_buf, 32, "match.guard.end.%d", cnt) @@ -1262,7 +1262,7 @@ novirtual class MatchGenMixin: # 2. Collect case info (check/body BBs, default flag, nobreak, mc, cv). cases_list: list[ast.AST*]* = node.cases - if cases_list is None: self.Gen.TypeGenErr.fatal_error(node, "match cases 缺失", "TypeError") + if cases_list is None: self.Gen.TypeGenErr.fatal_error(node, "match cases missing", "TypeError") case_count: sizet = len(cases_list) check_arr: sizet* = pool.alloc(8 * MAX_MATCH_CASES) body_arr: sizet* = pool.alloc(8 * MAX_MATCH_CASES) @@ -1273,7 +1273,7 @@ novirtual class MatchGenMixin: # MatchOr node pointer per collected arm (0 = not MatchOr): the check chain turns `case 1 | 2` into an OR of subj_val == cv_i per alternative, so record the node and expand alternatives when emitting checks; non-MatchOr stays 0 on the single-cv path. or_arr: sizet* = pool.alloc(8 * MAX_MATCH_CASES) if check_arr is None or body_arr is None or def_arr is None or nb_arr is None or mc_arr is None or cv_arr is None or or_arr is None: - self.Gen.TypeGenErr.fatal_error(node, "match 分派数组分配失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "match dispatch array allocation failed", "TypeError") collected: int = 0 has_default: int = 0 # The single guardless wildcard arm (default): its body is default_bb, the fall-through when all checks miss. @@ -1283,7 +1283,7 @@ novirtual class MatchGenMixin: i: int = 0 while i < case_count: if collected >= MAX_MATCH_CASES: - self.Gen.TypeGenErr.fatal_error(node, f"match case 数量超过上限 MAX_MATCH_CASES={MAX_MATCH_CASES}", "OverflowError") + self.Gen.TypeGenErr.fatal_error(node, f"match case count exceeds the limit MAX_MATCH_CASES={MAX_MATCH_CASES}", "OverflowError") break case_node: ast.AST* = cases_list.get(i) if case_node is None or case_node.kind() != ast.ASTKind.MatchCase: @@ -1315,7 +1315,7 @@ novirtual class MatchGenMixin: or_node = pat else: # No silent fallback: the guard branch only supports value/None/wildcard/OR patterns. - self.Gen.TypeGenErr.fatal_error(pat, "guard 分支不支持的 case 模式", "TypeError") + self.Gen.TypeGenErr.fatal_error(pat, "unsupported case pattern in the guard branch", "TypeError") if is_def == 1: has_default = 1 default_case_node = case_node @@ -1364,7 +1364,7 @@ novirtual class MatchGenMixin: # MatchOr arm: cond = (subj_val == cv_0) OR (subj_val == cv_1) OR ...; each alternative is compared then ORed (non-MatchValue/MatchSingleton alternatives cannot produce a value -> fail-fast). mo4: ast.MatchOr* = (ast.MatchOr*)(or_addr) pats4: list[ast.AST*]* = mo4.patterns - if pats4 is None or len(pats4) == 0: self.Gen.TypeGenErr.fatal_error(node, "guard OR 模式无备选子模式", "TypeError") + if pats4 is None or len(pats4) == 0: self.Gen.TypeGenErr.fatal_error(node, "guard OR pattern has no alternative sub-patterns", "TypeError") pats4_n: sizet = len(pats4) pats4_i: int = 0 while pats4_i < pats4_n: @@ -1377,25 +1377,25 @@ novirtual class MatchGenMixin: elif alt_pat2.kind() == ast.ASTKind.MatchSingleton: # None -> 0 (same as the single-value path). alt_cv2 = mlirlite.const_int32(pool, 0) - else: self.Gen.TypeGenErr.fatal_error(alt_pat2, "guard OR 模式备选不是值模式", "TypeError") + else: self.Gen.TypeGenErr.fatal_error(alt_pat2, "a guard OR pattern alternative is not a value pattern", "TypeError") if alt_cv2 is not None: cc: mlirlite.Value* = self._seq_cmp_eq(trans, builder, subj_val, alt_cv2) - if cc is None: self.Gen.TypeGenErr.fatal_error(node, "match OR 备选值比较失败", "TypeError") + if cc is None: self.Gen.TypeGenErr.fatal_error(node, "match OR alternative value comparison failed", "TypeError") if cond is None: cond = cc else: cond = mlirlite.build_or(builder, cond, cc) pats4_i = pats4_i + 1 - if cond is None: self.Gen.TypeGenErr.fatal_error(node, "guard OR 模式未能产出任何比较条件", "TypeError") + if cond is None: self.Gen.TypeGenErr.fatal_error(node, "the guard OR pattern produced no comparison condition", "TypeError") elif cv_addr != 0: cv2: mlirlite.Value* = (mlirlite.Value*)(cv_addr) c1: mlirlite.Value* = self._seq_cmp_eq(trans, builder, subj_val, cv2) - if c1 is None: self.Gen.TypeGenErr.fatal_error(node, "match case 值比较失败", "TypeError") + if c1 is None: self.Gen.TypeGenErr.fatal_error(node, "match case value comparison failed", "TypeError") cond = c1 # guard (if any): match holds and guard is non-zero (normalized to i1, same as the sequence path). g_addr: sizet = sizet(mc2.guard) if g_addr != 0: gnode: ast.AST* = (ast.AST*)(g_addr) gv: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, gnode, trans._funcs, trans._func_count, trans) - if gv is None: self.Gen.TypeGenErr.fatal_error(gnode, "match guard 翻译失败", "TypeError") + if gv is None: self.Gen.TypeGenErr.fatal_error(gnode, "match guard translation failed", "TypeError") gbits: int = self.Gen.ExprGenBase.get_llvm_type_bits(gv.Ty) if gbits == 1: g1: mlirlite.Value* = gv else: diff --git a/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp b/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp index 4c69a3e..eba2e47 100644 --- a/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp +++ b/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp @@ -365,7 +365,7 @@ novirtual class StmtGenCifMixin: if rt.value is not None: # f-string escape (return f"..."): its buffer lives on this frame's stack and dies on # return; copy it out explicitly (GenApi.escape_fstring_copy) before returning it. - GenApi.fail_if_fstring_escape(rt.value, "函数返回值") + GenApi.fail_if_fstring_escape(rt.value, "function return value") # return a, b → pack an anonymous struct value (multi-return, return type tuple[T1,T2]) if rt.value.kind() == ast.ASTKind.Tuple: rtp: ast.Tuple* = ast.Tuple*(rt.value) @@ -439,7 +439,7 @@ novirtual class StmtGenCifMixin: # [C1] return-annotation context: record this return's direct value node so a bare # generic ctor (`return Stack()` in `-> Stack[int]`) specializes via CurFuncRetAnnot. trans.CurRetNode = rt.value - val = self.Gen.ExprGen.translate_value(builder, pool, mod, rt.value, trans._funcs, trans._func_count, trans, ret_val_ty, "返回注解") + val = self.Gen.ExprGen.translate_value(builder, pool, mod, rt.value, trans._funcs, trans._func_count, trans, ret_val_ty, "return annotation") trans.CurRetNode = None # val is None (bare return): emit per the function return type - void→ret void, @@ -473,11 +473,11 @@ novirtual class StmtGenCifMixin: return 0 if ret_ty is None: # fail-fast: bare return with unknown return type; no hard-coded i32 fallback - self.Gen.TypeGenErr.fatal_error(rt, "函数返回类型无法确定", "TypeError") + self.Gen.TypeGenErr.fatal_error(rt, "cannot determine the function return type", "TypeError") val = mlirlite.ConstZero(pool, ret_ty) if val is None: # fail-fast: cannot build a zero value for the return type - self.Gen.TypeGenErr.fatal_error(rt, "函数返回类型无法确定", "TypeError") + self.Gen.TypeGenErr.fatal_error(rt, "cannot determine the function return type", "TypeError") # coerce val to the function return type: i1→i8 etc. use zext (bool semantics, 1 stays 1); # int→ptr must use inttoptr even at equal bit width, else llc rejects the return type. @@ -587,7 +587,7 @@ novirtual class StmtGenCifMixin: # 2. coerce to i1 (prefer __bool__; Compare/Not already return i1) if cond_val is None: # fail-fast: if condition expression failed to translate - self.Gen.TypeGenErr.fatal_error(if_node.test, "if 条件表达式翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(if_node.test, "failed to translate the if condition expression", "TypeError") cond_i1: mlirlite.Value* = self.Gen.ExprGenOps.coerce_cond_to_bool(pool, builder, trans.Module, cond_val, trans) # 3. create blocks (unique labels from trans._label_counter, not shared with SSA names) @@ -738,7 +738,7 @@ novirtual class StmtGenCifMixin: cond_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, while_node.test, trans._funcs, trans._func_count, trans) if cond_val is None: # fail-fast: while condition expression failed to translate - self.Gen.TypeGenErr.fatal_error(while_node.test, "while 条件表达式翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(while_node.test, "failed to translate the while condition expression", "TypeError") # coerce to i1 (prefer __bool__; Compare/Not already return i1) cond_i1: mlirlite.Value* = self.Gen.ExprGenOps.coerce_cond_to_bool(pool, builder, trans.Module, cond_val, trans) @@ -857,9 +857,9 @@ novirtual class StmtGenCifMixin: else: err_msg: str = pool.alloc(256) if err_msg is not None: - viperlib.snprintf(err_msg, 256, "仅支持 range()/enumerate()/zip() 或指针迭代,got call '%s'", fn_pre) + viperlib.snprintf(err_msg, 256, "only range()/enumerate()/zip() or pointer iteration is supported, got call '%s'", fn_pre) self.Gen.TypeGenErr.fatal_error(iter_node, err_msg) - self.Gen.TypeGenErr.fatal_error(iter_node, "仅支持 range()/enumerate()/zip() 或指针迭代") + self.Gen.TypeGenErr.fatal_error(iter_node, "only range()/enumerate()/zip() or pointer iteration is supported") # non-range iteration: pointer / array / list-literal / container / multi-var paths if is_range_iter == 0: @@ -870,24 +870,24 @@ novirtual class StmtGenCifMixin: call_mi: ast.Call* = ast.Call*(iter_node) fn_mi: str = self.Gen.ExprGenBase.get_func_name(call_mi.func) if fn_mi is not None and string.strcmp(fn_mi, "enumerate") == 0: - if tk != ast.ASTKind.Tuple: self.Gen.TypeGenErr.fatal_error(iter_node, "enumerate 迭代需要两个循环变量 (for i, v in enumerate(x))") + if tk != ast.ASTKind.Tuple: self.Gen.TypeGenErr.fatal_error(iter_node, "enumerate iteration requires two loop variables (for i, v in enumerate(x))") tup_ie: ast.Tuple* = ast.Tuple*(target) t1_buf_ie: bytes = pool.alloc(128) t2_buf_ie: bytes = pool.alloc(128) if t1_buf_ie is None or t2_buf_ie is None: return 0 t1_buf_ie[0] = '\0' t2_buf_ie[0] = '\0' - if self._extract_tuple_names(tup_ie, t1_buf_ie, t2_buf_ie) == 0: self.Gen.TypeGenErr.fatal_error(iter_node, "enumerate 迭代变量必须是简单名称") + if self._extract_tuple_names(tup_ie, t1_buf_ie, t2_buf_ie) == 0: self.Gen.TypeGenErr.fatal_error(iter_node, "enumerate iteration variables must be simple names") return self._handle_enumerate_iter(trans, for_node, t1_buf_ie, t2_buf_ie, call_mi) if fn_mi is not None and string.strcmp(fn_mi, "zip") == 0: - if tk != ast.ASTKind.Tuple: self.Gen.TypeGenErr.fatal_error(iter_node, "zip 迭代需要两个循环变量 (for a, b in zip(...))") + if tk != ast.ASTKind.Tuple: self.Gen.TypeGenErr.fatal_error(iter_node, "zip iteration requires two loop variables (for a, b in zip(...))") tup_iz: ast.Tuple* = ast.Tuple*(target) t1_buf_iz: bytes = pool.alloc(128) t2_buf_iz: bytes = pool.alloc(128) if t1_buf_iz is None or t2_buf_iz is None: return 0 t1_buf_iz[0] = '\0' t2_buf_iz[0] = '\0' - if self._extract_tuple_names(tup_iz, t1_buf_iz, t2_buf_iz) == 0: self.Gen.TypeGenErr.fatal_error(iter_node, "zip 迭代变量必须是简单名称") + if self._extract_tuple_names(tup_iz, t1_buf_iz, t2_buf_iz) == 0: self.Gen.TypeGenErr.fatal_error(iter_node, "zip iteration variables must be simple names") return self._handle_zip_iter(trans, for_node, t1_buf_iz, t2_buf_iz, call_mi) # list[T] container variable: iterate by dynamic __count__ if iter_node.kind() == ast.ASTKind.Name and trans is not None: @@ -929,9 +929,9 @@ novirtual class StmtGenCifMixin: ik: int = iter_node.kind() if ik == ast.ASTKind.Constant: cn_ik: ast.Constant* = ast.Constant*(iter_node) - if cn_ik.const_kind != ast.CONST_STR: self.Gen.TypeGenErr.fatal_error(iter_node, "for 迭代不支持该常量(仅支持字符串、数组、列表字面量、range())") + if cn_ik.const_kind != ast.CONST_STR: self.Gen.TypeGenErr.fatal_error(iter_node, "for iteration does not support this constant (only strings, arrays, list literals, range())") elif ik == ast.ASTKind.Dict or ik == ast.ASTKind.Set or ik == ast.ASTKind.Tuple or ik == ast.ASTKind.SetComp or ik == ast.ASTKind.DictComp: - self.Gen.TypeGenErr.fatal_error(iter_node, "for 迭代不支持字典/集合/元组字面量,请使用 range()、t.CArray 数组或列表字面量") + self.Gen.TypeGenErr.fatal_error(iter_node, "for iteration does not support dict/set/tuple literals; use range(), a t.CArray array, or a list literal") return self._handle_ptr_iter(trans, for_node, var_name) call: ast.Call* = ast.Call*(iter_node) @@ -948,26 +948,26 @@ novirtual class StmtGenCifMixin: if arg_count == 0: # fail-fast: range needs at least one argument - self.Gen.TypeGenErr.fatal_error(call, "range 需要至少一个参数", "SyntaxError") + self.Gen.TypeGenErr.fatal_error(call, "range requires at least one argument", "SyntaxError") elif arg_count == 1: stop_val = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, args.get(0), trans._funcs, trans._func_count, trans) if stop_val is None: # fail-fast: range argument failed to translate - self.Gen.TypeGenErr.fatal_error(args.get(0), "range 参数翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(args.get(0), "failed to translate the range argument", "TypeError") elif arg_count >= 2: start_val = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, args.get(0), trans._funcs, trans._func_count, trans) if start_val is None: # fail-fast: range argument failed to translate - self.Gen.TypeGenErr.fatal_error(args.get(0), "range 参数翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(args.get(0), "failed to translate the range argument", "TypeError") stop_val = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, args.get(1), trans._funcs, trans._func_count, trans) if stop_val is None: # fail-fast: range argument failed to translate - self.Gen.TypeGenErr.fatal_error(args.get(1), "range 参数翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(args.get(1), "failed to translate the range argument", "TypeError") if arg_count >= 3: step_val = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, args.get(2), trans._funcs, trans._func_count, trans) if step_val is None: # fail-fast: range argument failed to translate - self.Gen.TypeGenErr.fatal_error(args.get(2), "range 参数翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(args.get(2), "failed to translate the range argument", "TypeError") # a negative literal step inverts the loop test (TPC HandlesFor.py L86-94): range(a,b,-1) # uses i > stop. Only negative literals are detected; variable steps default to positive. step_neg_const: int = 0 @@ -1208,7 +1208,7 @@ novirtual class StmtGenCifMixin: # ---- source 1 setup ---- kind1: int = self._seq_kind(trans, src1) - if kind1 == 0: self.Gen.TypeGenErr.fatal_error(for_node, "序列迭代: 源 1 类型不支持") + if kind1 == 0: self.Gen.TypeGenErr.fatal_error(for_node, "sequence iteration: source 1 type is not supported") r1_start: mlirlite.Value* = None r1_stop: mlirlite.Value* = None r1_step: mlirlite.Value* = None @@ -1231,28 +1231,28 @@ novirtual class StmtGenCifMixin: sv: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs1.get(0), trans._funcs, trans._func_count, trans) if sv is None: # fail-fast: range argument failed to translate - self.Gen.TypeGenErr.fatal_error(cargs1.get(0), "range 参数翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(cargs1.get(0), "failed to translate the range argument", "TypeError") r1_stop = self.Gen.ExprGenBase.coerce_to_type(builder, sv, i64_ty, cargs1.get(0)) if n1 >= 2: sv2: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs1.get(1), trans._funcs, trans._func_count, trans) if sv2 is None: # fail-fast: range argument failed to translate - self.Gen.TypeGenErr.fatal_error(cargs1.get(1), "range 参数翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(cargs1.get(1), "failed to translate the range argument", "TypeError") r1_start = self.Gen.ExprGenBase.coerce_to_type(builder, sv2, i64_ty, cargs1.get(1)) if n1 >= 3: sv3: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs1.get(2), trans._funcs, trans._func_count, trans) if sv3 is None: # fail-fast: range argument failed to translate - self.Gen.TypeGenErr.fatal_error(cargs1.get(2), "range 参数翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(cargs1.get(2), "failed to translate the range argument", "TypeError") r1_step = self.Gen.ExprGenBase.coerce_to_type(builder, sv3, i64_ty, cargs1.get(2)) elif kind1 == GenTypes.SEQ_KIND_STR: elem1_ty = i8_ty s1_ptr = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, src1, trans._funcs, trans._func_count, trans) - if s1_ptr is None: self.Gen.TypeGenErr.fatal_error(for_node, "序列迭代: 字符串源翻译失败") + if s1_ptr is None: self.Gen.TypeGenErr.fatal_error(for_node, "sequence iteration: failed to translate the string source") elif kind1 == GenTypes.SEQ_KIND_LIST: elem1_ty = i8_ptr_ty l1_obj: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, src1, trans._funcs, trans._func_count, trans) - if l1_obj is None or l1_obj.Ty is None or self.Gen.ExprGenBase.is_ptr_type(l1_obj.Ty) == 0: self.Gen.TypeGenErr.fatal_error(for_node, "序列迭代: list 源不是指针类型") + if l1_obj is None or l1_obj.Ty is None or self.Gen.ExprGenBase.is_ptr_type(l1_obj.Ty) == 0: self.Gen.TypeGenErr.fatal_error(for_node, "sequence iteration: list source is not a pointer type") l1_count = mlirlite.build_load(builder, i64_ty, mlirlite.build_gep(builder, i64_ty, l1_obj, mlirlite.const_int64(pool, 1))) l1_data = mlirlite.build_load(builder, i8_ptr_ty, mlirlite.build_gep(builder, i64_ty, l1_obj, mlirlite.const_int64(pool, 0))) l1_esize = mlirlite.build_load(builder, i64_ty, mlirlite.build_gep(builder, i64_ty, l1_obj, mlirlite.const_int64(pool, 4))) @@ -1269,7 +1269,7 @@ novirtual class StmtGenCifMixin: r2_step: mlirlite.Value* = None if n_srcs >= 2: kind2 = self._seq_kind(trans, src2) - if kind2 == 0: self.Gen.TypeGenErr.fatal_error(for_node, "序列迭代: 源 2 类型不支持") + if kind2 == 0: self.Gen.TypeGenErr.fatal_error(for_node, "sequence iteration: source 2 type is not supported") if kind2 == GenTypes.SEQ_KIND_RANGE: elem2_ty = i32_ty r2_start = mlirlite.const_int64(pool, 0) @@ -1284,28 +1284,28 @@ novirtual class StmtGenCifMixin: svz: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs2.get(0), trans._funcs, trans._func_count, trans) if svz is None: # fail-fast: range argument failed to translate - self.Gen.TypeGenErr.fatal_error(cargs2.get(0), "range 参数翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(cargs2.get(0), "failed to translate the range argument", "TypeError") r2_stop = self.Gen.ExprGenBase.coerce_to_type(builder, svz, i64_ty, cargs2.get(0)) if n2 >= 2: svz2: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs2.get(1), trans._funcs, trans._func_count, trans) if svz2 is None: # fail-fast: range argument failed to translate - self.Gen.TypeGenErr.fatal_error(cargs2.get(1), "range 参数翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(cargs2.get(1), "failed to translate the range argument", "TypeError") r2_start = self.Gen.ExprGenBase.coerce_to_type(builder, svz2, i64_ty, cargs2.get(1)) if n2 >= 3: svz3: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, cargs2.get(2), trans._funcs, trans._func_count, trans) if svz3 is None: # fail-fast: range argument failed to translate - self.Gen.TypeGenErr.fatal_error(cargs2.get(2), "range 参数翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(cargs2.get(2), "failed to translate the range argument", "TypeError") r2_step = self.Gen.ExprGenBase.coerce_to_type(builder, svz3, i64_ty, cargs2.get(2)) elif kind2 == GenTypes.SEQ_KIND_STR: elem2_ty = i8_ty s2_ptr = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, src2, trans._funcs, trans._func_count, trans) - if s2_ptr is None: self.Gen.TypeGenErr.fatal_error(for_node, "序列迭代: 字符串源 2 翻译失败") + if s2_ptr is None: self.Gen.TypeGenErr.fatal_error(for_node, "sequence iteration: failed to translate string source 2") elif kind2 == GenTypes.SEQ_KIND_LIST: elem2_ty = i8_ptr_ty l2_obj: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, src2, trans._funcs, trans._func_count, trans) - if l2_obj is None or l2_obj.Ty is None or self.Gen.ExprGenBase.is_ptr_type(l2_obj.Ty) == 0: self.Gen.TypeGenErr.fatal_error(for_node, "序列迭代: list 源 2 不是指针类型") + if l2_obj is None or l2_obj.Ty is None or self.Gen.ExprGenBase.is_ptr_type(l2_obj.Ty) == 0: self.Gen.TypeGenErr.fatal_error(for_node, "sequence iteration: list source 2 is not a pointer type") l2_count = mlirlite.build_load(builder, i64_ty, mlirlite.build_gep(builder, i64_ty, l2_obj, mlirlite.const_int64(pool, 1))) l2_data = mlirlite.build_load(builder, i8_ptr_ty, mlirlite.build_gep(builder, i64_ty, l2_obj, mlirlite.const_int64(pool, 0))) l2_esize = mlirlite.build_load(builder, i64_ty, mlirlite.build_gep(builder, i64_ty, l2_obj, mlirlite.const_int64(pool, 4))) @@ -1465,17 +1465,17 @@ novirtual class StmtGenCifMixin: # translate the iterator expression to get the pointer value ptr_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, for_node.iter, trans._funcs, trans._func_count, trans) - if ptr_val is None: self.Gen.TypeGenErr.fatal_error(for_node, "指针迭代: 无法翻译迭代器表达式") + if ptr_val is None: self.Gen.TypeGenErr.fatal_error(for_node, "pointer iteration: failed to translate the iterator expression") # check the iterator type if self.Gen.ExprGenBase.is_ptr_type(ptr_val.Ty) == 0: # array iteration: for k in arr (fixed length, elements of any type) if self.Gen.ExprGenBase.is_array_type(ptr_val.Ty) != 0: return self._handle_array_iter(trans, for_node, var_name, ptr_val) - self.Gen.TypeGenErr.fatal_error(for_node, "指针迭代: 迭代器不是指针类型") + self.Gen.TypeGenErr.fatal_error(for_node, "pointer iteration: iterator is not a pointer type") # get the element type elem_ty: mlirlite.LLVMType* = ptr_val.Ty.Pointee - if elem_ty is None: self.Gen.TypeGenErr.fatal_error(for_node, "指针迭代: 无法获取元素类型") + if elem_ty is None: self.Gen.TypeGenErr.fatal_error(for_node, "pointer iteration: failed to get the element type") # element type is an array (Ptr([N x T]), e.g. a decayed t.CArray): load it and iterate by length (no null terminator) if self.Gen.ExprGenBase.is_array_type(elem_ty) != 0: @@ -1487,7 +1487,7 @@ novirtual class StmtGenCifMixin: elem_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(elem_ty) elem_is_ptr2: int = self.Gen.ExprGenBase.is_ptr_type(elem_ty) elem_fbits2: int = self.Gen.ExprGenBase.get_llvm_float_bits(elem_ty) - if elem_bits == 0 and elem_is_ptr2 == 0 and elem_fbits2 == 0: self.Gen.TypeGenErr.fatal_error(for_node, "指针迭代: 元素类型不是整数/指针/浮点,无法检查空终止符") + if elem_bits == 0 and elem_is_ptr2 == 0 and elem_fbits2 == 0: self.Gen.TypeGenErr.fatal_error(for_node, "pointer iteration: element type is not integer/pointer/float; cannot check the null terminator") i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) @@ -1597,12 +1597,12 @@ novirtual class StmtGenCifMixin: case mlirlite.LLVMType.Array(et, n): elem_ty = et elem_count = n - if elem_ty is None or elem_count <= 0: self.Gen.TypeGenErr.fatal_error(for_node, "数组迭代: 无法解析数组类型") + if elem_ty is None or elem_count <= 0: self.Gen.TypeGenErr.fatal_error(for_node, "array iteration: failed to resolve the array type") # array value → temp alloca (arrays are not pointers, copy then GEP-iterate); it must live # in the entry block, else LLVM treats it as dynamic alloca and deep stacks can fault. arr_tmp: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, arr_ty) - if arr_tmp is None: self.Gen.TypeGenErr.fatal_error(for_node, "数组迭代: 临时存储分配失败") + if arr_tmp is None: self.Gen.TypeGenErr.fatal_error(for_node, "array iteration: failed to allocate temporary storage") mlirlite.build_store(builder, array_val, arr_tmp) i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) @@ -1717,30 +1717,30 @@ novirtual class StmtGenCifMixin: builder: mlirlite.IRBuilder* = trans._cur_builder lst: ast.List* = ast.List*(list_node) - if lst is None or lst.elts is None: self.Gen.TypeGenErr.fatal_error(for_node, "列表字面量迭代: 空列表") + if lst is None or lst.elts is None: self.Gen.TypeGenErr.fatal_error(for_node, "list literal iteration: empty list") elts: list[ast.AST*]* = lst.elts elts_count: sizet = len(elts) - if elts_count <= 0: self.Gen.TypeGenErr.fatal_error(for_node, "列表字面量迭代: 空列表") + if elts_count <= 0: self.Gen.TypeGenErr.fatal_error(for_node, "list literal iteration: empty list") # translate the first element to determine the element type first_el: ast.AST* = elts.get(0) # explicit null check (repo convention: pointer null tests always use `is None`): a list # element count above the actual fill means a bare 0 slot, i.e. an empty AST element upstream. if first_el is None: - self.Gen.TypeGenErr.fatal_error(for_node, f"列表字面量迭代遇到空 AST 元素:第 0 个元素为裸空指针(0)," f"但元素计数为 {elts_count}(元素与计数不一致);上层某处产生了空 AST 元素,已终止编译。", "ValueError") + self.Gen.TypeGenErr.fatal_error(for_node, f"list literal iteration encountered an empty AST element: element 0 is a bare null pointer (0), " f"but the element count is {elts_count} (element and count mismatch); something upstream produced an empty AST element, compilation aborted.", "ValueError") # validate the object (vptr non-zero, see AssignGenMixin.vp:1174-1183): for @t.CVTable class # objects the first word is the vptr; if 0, any later virtual call reads address 0. if *((uint64*)(first_el)) == 0: - self.Gen.TypeGenErr.fatal_error(for_node, f"列表字面量迭代遇到【对象无效】的 AST 元素(vptr 为 0):第 0 个元素指针非 0" f"(地址 {uint64(first_el)})但其对象首字(vtable 指针)为 0,元素计数 {elts_count};" f"上层某处产生了「未初始化 vptr 的 AST 节点」(典型源:深拷贝只搬字段未搬 vptr),已终止编译。", "ValueError") + self.Gen.TypeGenErr.fatal_error(for_node, f"list literal iteration encountered an [INVALID OBJECT] AST element (vptr is 0): element 0 pointer is nonzero" f"(address {uint64(first_el)}) but the first word of its object (vtable pointer) is 0, element count {elts_count};" f"something upstream produced an [uninitialized vptr AST node] (typical source: a deep copy that moved fields but not the vptr), compilation aborted.", "ValueError") first_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, first_el, trans._funcs, trans._func_count, trans) - if first_val is None or first_val.Ty is None: self.Gen.TypeGenErr.fatal_error(first_el, "列表字面量迭代: 无法确定元素类型") + if first_val is None or first_val.Ty is None: self.Gen.TypeGenErr.fatal_error(first_el, "list literal iteration: failed to determine the element type") elem_ty: mlirlite.LLVMType* = first_val.Ty # build an [N x elem_ty] array value: write elements into a temp alloca then load it; this # too must live in the entry block to avoid a dynamic alloca (see _handle_array_iter). arr_ty: mlirlite.LLVMType* = mlirlite.Array(pool, elem_ty, elts_count) tmp_alloca: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, arr_ty) - if tmp_alloca is None: self.Gen.TypeGenErr.fatal_error(for_node, "列表字面量迭代: 临时数组分配失败") + if tmp_alloca is None: self.Gen.TypeGenErr.fatal_error(for_node, "list literal iteration: failed to allocate the temporary array") first_ptr: mlirlite.Value* = mlirlite.build_gep_array(builder, arr_ty, elem_ty, tmp_alloca, mlirlite.const_int32(pool, 0)) if first_ptr is not None: mlirlite.build_store(builder, first_val, first_ptr) # write the remaining elements (coerce to elem_ty) @@ -1749,10 +1749,10 @@ novirtual class StmtGenCifMixin: el_node: ast.AST* = elts.get(i) # explicit null check (as above, `is None`): never let the translate_value guard swallow it if el_node is None: - self.Gen.TypeGenErr.fatal_error(for_node, f"列表字面量迭代遇到空 AST 元素:第 {i} 个元素为裸空指针(0)," f"但元素计数为 {elts_count}(元素与计数不一致);上层某处产生了空 AST 元素,已终止编译。", "ValueError") + self.Gen.TypeGenErr.fatal_error(for_node, f"list literal iteration encountered an empty AST element: element {i} is a bare null pointer (0), " f"but the element count is {elts_count} (element and count mismatch); something upstream produced an empty AST element, compilation aborted.", "ValueError") # object validity check (vptr non-zero), same as element 0: same "take element then use" path if *((uint64*)(el_node)) == 0: - self.Gen.TypeGenErr.fatal_error(for_node, f"列表字面量迭代遇到【对象无效】的 AST 元素(vptr 为 0):第 {i} 个元素指针非 0" f"(地址 {uint64(el_node)})但其对象首字(vtable 指针)为 0,元素计数 {elts_count};" f"上层某处产生了「未初始化 vptr 的 AST 节点」(典型源:深拷贝只搬字段未搬 vptr),已终止编译。", "ValueError") + self.Gen.TypeGenErr.fatal_error(for_node, f"list literal iteration encountered an [INVALID OBJECT] AST element (vptr is 0): element {i} pointer is nonzero" f"(address {uint64(el_node)}) but the first word of its object (vtable pointer) is 0, element count {elts_count};" f"something upstream produced an [uninitialized vptr AST node] (typical source: a deep copy that moved fields but not the vptr), compilation aborted.", "ValueError") el_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, el_node, trans._funcs, trans._func_count, trans) if el_val is not None: el_val = self.Gen.ExprGenBase.coerce_to_type(builder, el_val, elem_ty, el_node) @@ -1761,7 +1761,7 @@ novirtual class StmtGenCifMixin: i += 1 # load the array value back and reuse array iteration arr_val: mlirlite.Value* = mlirlite.build_load(builder, arr_ty, tmp_alloca) - if arr_val is None: self.Gen.TypeGenErr.fatal_error(for_node, "列表字面量迭代: 数组加载失败") + if arr_val is None: self.Gen.TypeGenErr.fatal_error(for_node, "list literal iteration: failed to load the array") return self._handle_array_iter(trans, for_node, var_name, arr_val) # _handle_list_iter - list[T] container iteration `for v in lst:` (migrated from ForHandleIter): @@ -1778,7 +1778,7 @@ novirtual class StmtGenCifMixin: # read __count__ (offset 8, GEP index 1) cnt_ptr: mlirlite.Value* = mlirlite.build_gep(builder, i64_ty, list_val, mlirlite.const_int64(pool, 1)) - if cnt_ptr is None: self.Gen.TypeGenErr.fatal_error(for_node, "list 迭代: 无法定位 __count__") + if cnt_ptr is None: self.Gen.TypeGenErr.fatal_error(for_node, "list iteration: failed to locate __count__") count_val: mlirlite.Value* = mlirlite.build_load(builder, i64_ty, cnt_ptr) # loop-var alloca (element type i8*, matching inline list.get) @@ -1876,7 +1876,7 @@ novirtual class StmtGenCifMixin: # read __count__ (slot 2, byte offset 16) cnt_ptr: mlirlite.Value* = mlirlite.build_gep(builder, i64_ty, dict_val, mlirlite.const_int64(pool, 2)) - if cnt_ptr is None: self.Gen.TypeGenErr.fatal_error(for_node, "dict 迭代: 无法定位 __count__") + if cnt_ptr is None: self.Gen.TypeGenErr.fatal_error(for_node, "dict iteration: failed to locate __count__") count_val: mlirlite.Value* = mlirlite.build_load(builder, i64_ty, cnt_ptr) # loop-var alloca (element type i8*, matching dict.__next__ returning str) @@ -1971,15 +1971,15 @@ novirtual class StmtGenCifMixin: mod: mlirlite.LLVMModule* = trans.Module if builder is None or func is None or mod is None: return 0 - if obj_val is None or obj_val.Ty is None: self.Gen.TypeGenErr.fatal_error(for_node, "OOP 迭代: 迭代源对象类型未知") - if self.Gen.ExprGenBase.is_ptr_type(obj_val.Ty) == 0: self.Gen.TypeGenErr.fatal_error(for_node, "OOP 迭代: 迭代源对象不是指针类型") + if obj_val is None or obj_val.Ty is None: self.Gen.TypeGenErr.fatal_error(for_node, "OOP iteration: the iteration source object type is unknown") + if self.Gen.ExprGenBase.is_ptr_type(obj_val.Ty) == 0: self.Gen.TypeGenErr.fatal_error(for_node, "OOP iteration: the iteration source object is not a pointer type") # 1. find {Class}.__iter__ and call it to get the iterator iter_lookup: str = pool.alloc(128) if iter_lookup is None: return 0 viperlib.snprintf(iter_lookup, 128, "%s.__iter__", class_name) iter_fn: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, iter_lookup) - if iter_fn is None: self.Gen.TypeGenErr.fatal_error(for_node, f"OOP 迭代: 类 '{class_name}' 没有 __iter__ 方法") + if iter_fn is None: self.Gen.TypeGenErr.fatal_error(for_node, f"OOP iteration: class {class_name} has no __iter__ method") iter_ret_ty: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(iter_fn) iter_fn_name: str = mlirlite.function_get_name(iter_fn) if iter_ret_ty is None or iter_fn_name is None: return 0 @@ -1999,7 +1999,7 @@ novirtual class StmtGenCifMixin: if next_lookup is None: return 0 viperlib.snprintf(next_lookup, 128, "%s.__next__", class_name) next_fn: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, next_lookup) - if next_fn is None: self.Gen.TypeGenErr.fatal_error(for_node, f"OOP 迭代: 类 '{class_name}' 没有 __next__ 方法") + if next_fn is None: self.Gen.TypeGenErr.fatal_error(for_node, f"OOP iteration: class {class_name} has no __next__ method") next_ret_ty: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(next_fn) next_fn_name: str = mlirlite.function_get_name(next_fn) if next_ret_ty is None or next_fn_name is None: return 0 @@ -2092,16 +2092,16 @@ novirtual class StmtGenCifMixin: """Iterate enumerate(x) as for i, v in enumerate(x).""" if call is None or call.args is None: return 0 cargs: list[ast.AST*]* = call.args - if len(cargs) < 1: self.Gen.TypeGenErr.fatal_error(for_node, "enumerate 需要至少一个参数") + if len(cargs) < 1: self.Gen.TypeGenErr.fatal_error(for_node, "enumerate requires at least one argument") return self._build_seq_loop(trans, for_node, t1, t2, cargs.get(0), None, 1) def _handle_zip_iter(self, trans: HT.Translator*, for_node: ast.For*, t1: str, t2: str, call: ast.Call*) -> int: """Iterate zip(x, y) as for a, b in zip(x, y).""" if call is None or call.args is None: # fail-fast: zip argument missing - self.Gen.TypeGenErr.fatal_error(call, "zip 参数缺失", "SyntaxError") + self.Gen.TypeGenErr.fatal_error(call, "zip arguments are missing", "SyntaxError") cargs: list[ast.AST*]* = call.args - if len(cargs) < 2: self.Gen.TypeGenErr.fatal_error(for_node, "zip 需要至少两个参数") + if len(cargs) < 2: self.Gen.TypeGenErr.fatal_error(for_node, "zip requires at least two arguments") return self._build_seq_loop(trans, for_node, t1, t2, cargs.get(0), cargs.get(1), 2) diff --git a/App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp b/App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp index 7126700..2ca1c9e 100644 --- a/App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp +++ b/App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp @@ -66,7 +66,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): if var_ty is not None: match var_ty: case mlirlite.LLVMType.Void(): - self.Gen.TypeGenErr.fatal_error(nm_node, f"nonlocal 变量 '{nm.id}' 类型无效(Void/无法解析)", "TypeError") + self.Gen.TypeGenErr.fatal_error(nm_node, f"nonlocal variable {nm.id} has an invalid type (Void/unresolvable)", "TypeError") case _: pass GenApi.add_nonlocal_name(trans, nm.id, var_ty) @@ -92,7 +92,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): func_name: str = self.Gen.ExprGenBase.get_func_name(func_node) if func_name is None: # Function name resolution failed: report and abort (fail-fast) - self.Gen.TypeGenErr.fatal_error(call_node, "表达式语句的函数名解析失败", "SyntaxError") + self.Gen.TypeGenErr.fatal_error(call_node, "failed to resolve the function name of the expression statement", "SyntaxError") # printf / print take special paths (print is type-aware formatting, not mapped to printf) if string.strcmp(func_name, "printf") == 0: self.Gen.CallGenLeafKit.translate_printf_call(trans.Pool, trans._cur_builder, trans.Module, cl, trans) @@ -204,7 +204,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): # Emit br to the break target (_break_bb set by the loop / switch / match case side) if trans._break_bb is None: # fail-fast: with no loop / switch / match there is nowhere to jump; never silently no-op - self.Gen.TypeGenErr.fatal_error(node, "break 只能用在循环或 switch/match 的 case 体内(当前没有可跳出的目标)", "SyntaxError") + self.Gen.TypeGenErr.fatal_error(node, "break is only allowed inside a loop or a switch/match case body (there is no target to break out of)", "SyntaxError") if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, trans._break_bb) # Create a dead-code BB for following statements (code after break is unreachable) @@ -220,7 +220,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): """Translate a fallthrough statement: emits no IR, consumed by the switch side""" if trans is None: return 0 if trans._in_switch_case == 0: - self.Gen.TypeGenErr.fatal_error(node, "fallthrough 只能用在 switch 的 case 体内(match 完全禁止 fallthrough," "语义是落到下一个 case)", "SyntaxError") + self.Gen.TypeGenErr.fatal_error(node, "fallthrough is only allowed inside a switch case body (fallthrough is completely forbidden in match; " "the semantics are falling through to the next case)", "SyntaxError") return 0 def translate_continue(self, trans: HT.Translator*, node: ast.AST*) -> int: @@ -234,7 +234,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): # Emit br to the continue target if trans._continue_bb is None: # fail-fast: a continue outside a loop has nowhere to jump; never silently no-op - self.Gen.TypeGenErr.fatal_error(node, "continue 只能用在循环体内(当前没有可继续的循环)", "SyntaxError") + self.Gen.TypeGenErr.fatal_error(node, "continue is only allowed inside a loop body (there is no enclosing loop to continue)", "SyntaxError") if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, trans._continue_bb) # Create a dead-code BB for following statements @@ -316,7 +316,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): var_ty: mlirlite.LLVMType* = GenApi.get_nonlocal_type(trans, name) if var_ty is None or self._is_void_type(var_ty) != 0: # fail-fast on a missing/invalid type, avoiding illegal IR like "load void, void*" - self.Gen.TypeGenErr.fatal_error(None, f"nonlocal 变量 '{name}' 类型缺失,无法 load", "TypeError") + self.Gen.TypeGenErr.fatal_error(None, f"nonlocal variable {name} is missing its type; cannot load", "TypeError") # bitcast raw i8* to var_ty* var_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, var_ty) @@ -336,7 +336,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): var_ty: mlirlite.LLVMType* = GenApi.get_nonlocal_type(trans, name) if var_ty is None or self._is_void_type(var_ty) != 0: # Missing/invalid type aborts (fail-fast) to avoid illegal "bitcast ... to void*" IR - self.Gen.TypeGenErr.fatal_error(None, f"nonlocal 变量 '{name}' 类型缺失,无法 load", "TypeError") + self.Gen.TypeGenErr.fatal_error(None, f"nonlocal variable {name} is missing its type; cannot load", "TypeError") # bitcast raw i8* to var_ty* var_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, var_ty) diff --git a/App/lib/core/Gen/Stmt/StmtGenMixin.vp b/App/lib/core/Gen/Stmt/StmtGenMixin.vp index e712920..bd088e6 100644 --- a/App/lib/core/Gen/Stmt/StmtGenMixin.vp +++ b/App/lib/core/Gen/Stmt/StmtGenMixin.vp @@ -32,7 +32,7 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): # define). Every instruction then carries ", !dbg !N". if node is not None and trans._cur_builder is not None: DebugInfoGen.SetStatement(trans.Pool, trans._cur_builder, node.lineno, node.col_offset + 1) - if trans.TranslateDepth >= HT.TRANSLATE_MAX_DEPTH: self.Gen.TypeGenErr.fatal_error(node, "语句翻译嵌套过深(疑似 AST 自引用环或翻译 bug)", "RecursionError") + if trans.TranslateDepth >= HT.TRANSLATE_MAX_DEPTH: self.Gen.TypeGenErr.fatal_error(node, "statement translation nested too deeply (likely an AST self-reference cycle or a translation bug)", "RecursionError") trans.TranslateDepth += 1 mret: int = self._translate_stmt_impl(trans, node) if trans is not None: trans.TranslateDepth -= 1 @@ -71,7 +71,7 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): elif k == ast.ASTKind.Try: return self.translate_try(trans, node) elif k == ast.ASTKind.With: return self.translate_with(trans, node) # unknown statement type: fail-fast to expose an upstream parse problem - self.Gen.TypeGenErr.fatal_error(node, f"未知语句类型 kind={k}", "SyntaxError") + self.Gen.TypeGenErr.fatal_error(node, f"unknown statement type kind={k}", "SyntaxError") return 0 def translate_delete(self, trans: HT.Translator*, node: ast.AST*) -> int: diff --git a/App/lib/core/Gen/StructGenMixin.vp b/App/lib/core/Gen/StructGenMixin.vp index 690f1b0..94c328f 100644 --- a/App/lib/core/Gen/StructGenMixin.vp +++ b/App/lib/core/Gen/StructGenMixin.vp @@ -681,11 +681,11 @@ novirtual class StructGenMixin: # Explicit null check (repo hard rule: null-check pointers with `is None`). An earlier revision compared `elem_src_l == 0` and noted it was equivalent to `is None`: the IR fact was right but the conclusion misleading. # A null element in the source list means the producer is corrupted (count > actual fill) -> fail loudly, never backfill 0. if elem_src_l is None: - self.Gen.TypeGenErr.fatal_error(default_val, f"字段默认值深拷贝:列表字面量第 {li_l} 个元素为空 AST 元素(指针为 0)。" f"上层某处产生了空 AST 元素(元素计数与实际填充不一致)," f"拒绝静默补 0 生成残缺的默认值;已终止编译。", "ValueError") + self.Gen.TypeGenErr.fatal_error(default_val, f"field default deep copy: element {li_l} of the list literal is an empty AST element (pointer is 0). " f"Something upstream produced an empty AST element (element count and actual fill disagree); " f"refusing to silently backfill 0 and generate a broken default; compilation aborted.", "ValueError") return None elem_dst_l: ast.AST* = self._deep_copy_default_ast(pool, elem_src_l) if elem_dst_l is None: - self.Gen.TypeGenErr.fatal_error(elem_src_l, f"字段默认值深拷贝:列表字面量第 {li_l} 个元素(kind={elem_src_l.kind()})" f"既非 Constant 也非 List,无法深拷贝到永久池。若在此静默跳过该槽," f"会形成【计数 > 实际填充数】的空槽(后续 elts.get 读到裸 0 崩溃);" f"若静默截短计数则会改变数组初始化长度。两者都是静默降级,故响亮失败。", "TypeError") + self.Gen.TypeGenErr.fatal_error(elem_src_l, f"field default deep copy: element {li_l} of the list literal (kind={elem_src_l.kind()})" f" is neither Constant nor List, so it cannot be deep-copied into the permanent pool. Silently skipping this slot" f" would create an empty slot [count > actual fill] (a later elts.get reads a raw 0 and crashes);" f" silently shortening the count would change the array initializer length. Both are silent degradation, so fail loudly.", "TypeError") return None # The slot element type must be a pointer: `ast.AST*`'s `[0]` is the object `ast.AST` (48 bytes), so `slot[0] = ` would silently compile as a 48-byte load + 48-byte store and overrun each cnt_l*elem_sz_l slot by 40 bytes, writing over this block's canary and the next free block's first word (root cause of three generations of [FREEFRAME] crashes). # Per the repo merge rule (hashtable.vp:82-85) `X*` = Ptr(resolve(X)), so indexing yields a pointer element -> an 8-byte pointer store matching the allocation width. @@ -730,7 +730,7 @@ novirtual class StructGenMixin: # Pass 1: exact match. # StructCount sanity guard (memory corruption can yield a huge value -> index loop false hang). if self.StructCount < 0 or self.StructCount > 200000: - VLogger.error(f"StructCount 异常: {self.StructCount} (find_struct)", "STRUCT") + VLogger.error(f"abnormal StructCount: {self.StructCount} (find_struct)", "STRUCT") stdlib.exit(1) # Name-index fast path: a hit gives the first registration index (semantics = the original exact-match scan's first hit). fi: int = self._struct_name_idx_find(name) @@ -805,7 +805,7 @@ novirtual class StructGenMixin: if name is None or self.StructTable is None: return None # StructCount sanity guard (memory corruption can yield a huge value -> index loop false hang). if self.StructCount < 0 or self.StructCount > 200000: - VLogger.error(f"StructCount 异常: {self.StructCount} (find_struct_by_module)", "STRUCT") + VLogger.error(f"abnormal StructCount: {self.StructCount} (find_struct_by_module)", "STRUCT") stdlib.exit(1) if sha1 is not None: # Name-index fast path: same-named entries all lie at or after the first same-name index, so scan name+sha1 from that index (equivalent to the original full scan's "first name with sha1 hit"). @@ -830,7 +830,7 @@ novirtual class StructGenMixin: """Clear MethodsEmitted for classes registered by the given module sha1.""" if sha1 is None or self.StructTable is None: return 0 if self.StructCount < 0 or self.StructCount > 200000: - VLogger.error(f"StructCount 异常: {self.StructCount} (reset_module_methods_emitted)", "STRUCT") + VLogger.error(f"abnormal StructCount: {self.StructCount} (reset_module_methods_emitted)", "STRUCT") return 0 reset_count: int = 0 for i in range(self.StructCount): @@ -854,7 +854,7 @@ novirtual class StructGenMixin: if struct_ty is None or self.StructTable is None: return None # StructCount sanity guard (memory corruption can yield a huge value -> index loop false hang). if self.StructCount < 0 or self.StructCount > 200000: - VLogger.error(f"StructCount 异常: {self.StructCount} (find_struct_by_type)", "STRUCT") + VLogger.error(f"abnormal StructCount: {self.StructCount} (find_struct_by_type)", "STRUCT") stdlib.exit(1) st_val: uint64 = uint64(struct_ty) # The Ty index is entirely disabled here (its structure is still maintained by _struct_idx_add but not used): an entry's Ty may be rewritten to a new pointer by deep copy (ClassGenDef), leaving the slot keyed by the registration-time Ty value out of sync. @@ -887,7 +887,7 @@ novirtual class StructGenMixin: fcount: int = mlirlite.get_struct_fcount(struct_ty) if fcount <= 0: return 0 if entry.FieldCount != fcount: - self.Gen.TypeGenErr.fatal_error(None, f"结构体 '{entry.Name}' 的字段表条数({entry.FieldCount})与 LLVM 槽位数({fcount})不一致:" f"字段条目与结构体布局由两条路径产生,错位会让字段访问按错误下标算 GEP" f"(实证:ast.Name.id 落到 ctx 槽 ⇒ 指针被读成整数 1 ⇒ strlen(0x1) 崩溃)。", "TypeError") + self.Gen.TypeGenErr.fatal_error(None, f"struct '{entry.Name}' field table count ({entry.FieldCount}) disagrees with the LLVM slot count ({fcount}): " f"field entries and struct layout come from two paths, and a mismatch makes field access compute GEP with a wrong index" f" (evidence: ast.Name.id landing in the ctx slot => the pointer is read as the integer 1 => strlen(0x1) crashes).", "TypeError") return 0 node: mlirlite.ParamNode* = mlirlite.get_struct_fields(struct_ty) i: int = 0 @@ -902,7 +902,7 @@ novirtual class StructGenMixin: fbits_f: int = self.Gen.ExprGenBase.get_llvm_float_bits(fe.Ty) fbits_s: int = self.Gen.ExprGenBase.get_llvm_float_bits(slot_ty) if ptr_f != ptr_s or bits_f != bits_s or fbits_f != fbits_s: - self.Gen.TypeGenErr.fatal_error(None, f"结构体 '{entry.Name}' 的字段 '{fe.Name}'(条目下标 {i})与其槽位类型不同类:" f"条目 指针性={ptr_f}/整数位宽={bits_f}/浮点位宽={fbits_f}," f"槽位 指针性={ptr_s}/整数位宽={bits_s}/浮点位宽={fbits_s}。" f"字段条目与结构体布局错位(实证:id 落到 ctx 槽 ⇒ 指针被读成整数 1 ⇒ strlen(0x1) 崩溃)。", "TypeError") + self.Gen.TypeGenErr.fatal_error(None, f"field '{fe.Name}' of struct '{entry.Name}' (entry index {i}) is not the same kind as its slot type: " f"entry ptr-ness={ptr_f}/int width={bits_f}/float width={fbits_f}; " f"slot ptr-ness={ptr_s}/int width={bits_s}/float width={fbits_s}. " f"field entries and struct layout are misaligned (evidence: id landing in the ctx slot => the pointer is read as the integer 1 => strlen(0x1) crashes).", "TypeError") return 0 node = mlirlite.paramnode_get_next(node) i += 1 @@ -1046,15 +1046,15 @@ novirtual class StructGenMixin: stdlib.free(mod_buf_q) return rn_fe_q # Class hit but field not found: readable error (traceback format). - self.Gen.TypeGenErr.fatal_error(node, f"lookup_field_by_class: 类 '{class_name}' 已按模块归属解析(ModuleSha1={mod_sha1_q}, FieldCount={mod_entry_q.FieldCount})但字段 '{field_name}' 未找到", "AttributeError") + self.Gen.TypeGenErr.fatal_error(node, f"lookup_field_by_class: class '{class_name}' was resolved by module ownership (ModuleSha1={mod_sha1_q}, FieldCount={mod_entry_q.FieldCount}) but field '{field_name}' was not found", "AttributeError") stdlib.free(mod_buf_q) return None # Module resolvable but class not registered: fail-fast (exposes vpi injection/registration defects; no bare-name cross-library grab of another module's same-named class). - self.Gen.TypeGenErr.fatal_error(node, f"lookup_field_by_class: 类 '{class_name}' 未找到(模块 '{mod_buf_q}' 可解析 sha1={mod_sha1_q},但无同名注册类;请检查 vpi stub 注入或编译顺序)", "AttributeError") + self.Gen.TypeGenErr.fatal_error(node, f"lookup_field_by_class: class '{class_name}' was not found (module '{mod_buf_q}' resolves to sha1={mod_sha1_q}, but no class of that name is registered; check vpi stub injection or compilation order)", "AttributeError") stdlib.free(mod_buf_q) return None # Module name not registered: fail-fast (no more bare-name cross-library fallback). - self.Gen.TypeGenErr.fatal_error(node, f"lookup_field_by_class: 类 '{class_name}' 的模块 '{mod_buf_q}' 无法解析(sha1 映射表未登记,请检查 import 与编译顺序)", "AttributeError") + self.Gen.TypeGenErr.fatal_error(node, f"lookup_field_by_class: module '{mod_buf_q}' of class '{class_name}' cannot be resolved (not registered in the sha1 map; check the imports and compilation order)", "AttributeError") stdlib.free(mod_buf_q) return None stdlib.free(mod_buf_q) @@ -1063,7 +1063,7 @@ novirtual class StructGenMixin: entry = self.find_struct(class_name) if entry is None: # Diagnostic: target class not registered (Python traceback style; terminate compilation immediately). - self.Gen.TypeGenErr.fatal_error(node, f"lookup_field_by_class: 类 '{class_name}' 未注册 (struct_count={self.StructCount})", "AttributeError") + self.Gen.TypeGenErr.fatal_error(node, f"lookup_field_by_class: class '{class_name}' is not registered (struct_count={self.StructCount})", "AttributeError") return None # Dependencies-not-ready tolerance: the caller expects a specific module (sha1 non-None) but the bare-name fallback hit an empty FieldCount==0 stub class (vpi injection without fields / defining module not compiled). # Return None so the caller marks _deps_pending and retranslates (the real definition overrides the stub once the source module compiles). SECURITY_ATTRIBUTES FieldCount=0 root cause (subprocess.vp sa.nLength). @@ -1102,16 +1102,16 @@ novirtual class StructGenMixin: err: str if rn_is_renum_l != 0: # Friendly error: for a REnum class state that variant field alias lookup failed, including entry.Name and the alias slot result, so it is clear whether the alias is unregistered (slot=-1) or the class_name pointer is not unified. - err = f"lookup_field_by_class: 类 '{class_name}' 是 REnum 类(FieldCount={entry.FieldCount}),变体字段 '{field_name}' 别名查找失败(entry.Name='{rn_cls_l}',别名槽位={rn_alias_l},请检查该变体字段是否已注册别名,或 class_name 指针是否统一)" + err = f"lookup_field_by_class: class '{class_name}' is a REnum class (FieldCount={entry.FieldCount}), variant field '{field_name}' alias lookup failed (entry.Name='{rn_cls_l}', alias slot={rn_alias_l}; check whether this variant field has a registered alias, or whether the class_name pointer is unified)" else: # Readability: include entry.Name/ModuleSha1 (cross-module same-name location) + the registered field list + the expected sha1 (caller), to distinguish "cross-module same-named class mismatch" from "incomplete vpi stub injection" from "class definition and access site disagree". sha1_txt: str = "?" if entry.ModuleSha1 is not None: sha1_txt = entry.ModuleSha1 want_sha1_txt: str = "?" if sha1 is not None: want_sha1_txt = sha1 - fld_lst_txt: str = "(无)" + fld_lst_txt: str = "(none)" if fb_flds_lst is not None and string.strlen(fb_flds_lst) > 0: fld_lst_txt = fb_flds_lst - err = f"lookup_field_by_class: 类 '{class_name}' 已注册 (FieldCount={entry.FieldCount}, " f"entry.Name='{entry.Name}', ModuleSha1={sha1_txt}, 调用方期望 sha1={want_sha1_txt}) " f"但字段 '{field_name}' 未找到;注册字段: [{fld_lst_txt}]。可能原因: 跨模块同名类" f"被误匹配 / vpi stub 注入字段不全 / 类定义与访问处不一致" + err = f"lookup_field_by_class: class '{class_name}' is registered (FieldCount={entry.FieldCount}, " f"entry.Name='{entry.Name}', ModuleSha1={sha1_txt}, caller expects sha1={want_sha1_txt}) " f"but field '{field_name}' was not found; registered fields: [{fld_lst_txt}]. Possible causes: cross-module same-named class" f" mis-matched / incomplete vpi stub injection / class definition and access site disagree" # Output in Python traceback style (traceback frame + file:line + error type) and terminate compilation immediately (same semantics as VLogger.error, format aligned with fatal_error). self.Gen.TypeGenErr.fatal_error(node, err, "AttributeError") if fb_flds_lst is not None: stdlib.free(fb_flds_lst) @@ -1537,7 +1537,7 @@ novirtual class StructGenMixin: # Step guard: a cyclic field list (memory corruption) would loop forever (G3 LinkedNode.prepend hang candidate); over the limit, report and abort immediately. cnt_ef += 1 if cnt_ef > 100000: - VLogger.error("字段链表疑似成环(_ensure_field_types_in_module),强制终止", "STRUCT") + VLogger.error("field list is likely cyclic (_ensure_field_types_in_module), forcing termination", "STRUCT") stdlib.exit(1) if fld.Ty is not None: # Value-type sub-structs (e.g. FILETIME) need a full definition. diff --git a/App/lib/core/Gen/Translator.vp b/App/lib/core/Gen/Translator.vp index 9fdbe18..92c11ca 100644 --- a/App/lib/core/Gen/Translator.vp +++ b/App/lib/core/Gen/Translator.vp @@ -850,32 +850,32 @@ def InjectTracebackInstallCtor(tr: Translator*) -> int: if tr._declare_only != 0: return 0 pool: memhub.MemBuddy* = tr.Pool if pool is None: - VLogger.error("--traceback: 内存池未初始化,无法注入 Install 构造器", "TRACEBACK") + VLogger.error("--traceback: memory pool is not initialized, cannot inject the Install constructor", "TRACEBACK") return 1 mod: mlirlite.LLVMModule* = tr.Module if _tb_module_has_global_ctors(mod) != 0: - VLogger.error("--traceback: 模块内已存在 @llvm.global_ctors,无法注入 traceback 启动期构造器(不静默降级)", "TRACEBACK") + VLogger.error("--traceback: @llvm.global_ctors already exists in the module, cannot inject the traceback startup constructor (no silent fallback)", "TRACEBACK") return 1 install_fn: mlirlite.Function* = _tb_find_install_function(mod) if install_fn is None: - VLogger.error("--traceback: 在 traceback 模块内找不到 Install() 函数,无法注入启动期构造器(不静默降级)", "TRACEBACK") + VLogger.error("--traceback: Install() function not found in the traceback module, cannot inject the startup constructor (no silent fallback)", "TRACEBACK") return 1 # 1) ctor: entry { call @Install(); ret void } void_ty: mlirlite.LLVMType* = mlirlite.Void(pool) ctor: mlirlite.Function* = mlirlite.new_function(pool, "__traceback_install_ctor", void_ty) if ctor is None: - VLogger.error("--traceback: 构造器函数分配失败", "TRACEBACK") + VLogger.error("--traceback: failed to allocate the constructor function", "TRACEBACK") return 1 blk: mlirlite.BasicBlock* = mlirlite.new_basic_block(pool, "entry") if blk is None: - VLogger.error("--traceback: 构造器基本块分配失败", "TRACEBACK") + VLogger.error("--traceback: failed to allocate the constructor basic block", "TRACEBACK") return 1 mlirlite.function_add_block(ctor, blk) mlirlite.module_add_function(mod, ctor) builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, ctor) if builder is None: - VLogger.error("--traceback: 构造器 IRBuilder 分配失败", "TRACEBACK") + VLogger.error("--traceback: failed to allocate the constructor IRBuilder", "TRACEBACK") return 1 mlirlite.position_at_end(builder, blk) iname: str = mlirlite.function_get_name(install_fn) @@ -893,23 +893,23 @@ def InjectTracebackInstallCtor(tr: Translator*) -> int: f2: mlirlite.ParamNode* = mlirlite.new_param_node(pool, fnp_ty) f3: mlirlite.ParamNode* = mlirlite.new_param_node(pool, i8p_ty) if f1 is None or f2 is None or f3 is None: - VLogger.error("--traceback: global_ctors 结构体字段分配失败", "TRACEBACK") + VLogger.error("--traceback: failed to allocate global_ctors struct fields", "TRACEBACK") return 1 mlirlite.paramnode_set_next(f1, f2) mlirlite.paramnode_set_next(f2, f3) elem_ty: mlirlite.LLVMType* = mlirlite.Struct(pool, f1, 3, None) arr_ty: mlirlite.LLVMType* = mlirlite.Array(pool, elem_ty, 1) if elem_ty is None or arr_ty is None: - VLogger.error("--traceback: global_ctors 类型构造失败", "TRACEBACK") + VLogger.error("--traceback: failed to build the global_ctors type", "TRACEBACK") return 1 gv: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, "llvm.global_ctors", arr_ty) if gv is None: - VLogger.error("--traceback: @llvm.global_ctors 全局变量分配失败", "TRACEBACK") + VLogger.error("--traceback: failed to allocate the @llvm.global_ctors global variable", "TRACEBACK") return 1 mlirlite.global_set_linkage(gv, "appending") gv.Initializer = "[{ i32, void ()*, i8* } { i32 65535, void ()* @__traceback_install_ctor, i8* null }]" mlirlite.module_add_global(mod, gv) - VLogger.info("--traceback: 已注入启动期 Install() 构造器(@llvm.global_ctors)", "TRACEBACK") + VLogger.info("--traceback: injected the startup Install() constructor (@llvm.global_ctors)", "TRACEBACK") return 0 diff --git a/App/lib/core/Gen/TranslatorGenMixin.vp b/App/lib/core/Gen/TranslatorGenMixin.vp index 317d0ba..f3b5e20 100644 --- a/App/lib/core/Gen/TranslatorGenMixin.vp +++ b/App/lib/core/Gen/TranslatorGenMixin.vp @@ -159,7 +159,7 @@ novirtual class TranslatorGenMixin: # More elements than the declared length -> fail-fast (never silently truncate or drop). if sizet(arr_count) < elts_count: - self.Gen.TypeGenErr.fatal_error(list_node, f"数组初始化元素数 {elts_count} 超过数组声明长度 {arr_count},不允许静默截断", "OverflowError") + self.Gen.TypeGenErr.fatal_error(list_node, f"array initializer has {elts_count} elements, exceeding the declared array length {arr_count}; silent truncation is not allowed", "OverflowError") return None # Non-integer element types (aggregates): only an all-zero list yields the whole @@ -433,7 +433,7 @@ novirtual class TranslatorGenMixin: if hit is None: return None sec_val: str = self.Gen.FuncGenBase._get_attr_call_arg_str(hit) if sec_val is None or sec_val[0] == 0: - self.Gen.TypeGenErr.fatal_error(node, f"模块级变量 '{var_name}' 的 t.attr.section(...) 段名缺失或为空", "ValueError") + self.Gen.TypeGenErr.fatal_error(node, f"section name of t.attr.section(...) for module-level variable '{var_name}' is missing or empty", "ValueError") return None return sec_val def _extract_global_attr_aligned(self, node: ast.AST*, var_name: str) -> int: @@ -442,7 +442,7 @@ novirtual class TranslatorGenMixin: if hit is None: return 0 al_val: int = self.Gen.ClassGenBase._tattr_aligned_int(hit) if al_val <= 0: - self.Gen.TypeGenErr.fatal_error(node, f"模块级变量 '{var_name}' 的 t.attr.aligned(N) 需要正整数字面量 N", "ValueError") + self.Gen.TypeGenErr.fatal_error(node, f"t.attr.aligned(N) for module-level variable '{var_name}' requires a positive integer literal N", "ValueError") return 0 return al_val def _extract_global_attr_weak(self, node: ast.AST*) -> int: @@ -512,7 +512,7 @@ novirtual class TranslatorGenMixin: annot_node = aa.annotation # f-string escape: a module-level initial value is global, but the f-string result # points into the current function's stack buffer -> fail-fast (use escape_fstring_copy). - GenApi.fail_if_fstring_escape(aa.value, "全局变量初始化") + GenApi.fail_if_fstring_escape(aa.value, "global variable initialization") # t.CStatic vars (no cross-module use) are registered as (name, def module SHA1); # the logic stays inside _RegisterStaticModuleVar to avoid disturbing type inference. self._RegisterStaticModuleVar(trans, annot_node, var_name) @@ -551,7 +551,7 @@ novirtual class TranslatorGenMixin: else: # [S4 fail-fast] An annotated module var that fails to resolve errors out instead # of silently using i32 (a wrong type corrupts storage size/field access/ABI). - self.Gen.TypeGenErr.fatal_error(aa.annotation, f"模块级变量 '{var_name}' 类型注解解析失败", "NameError") + self.Gen.TypeGenErr.fatal_error(aa.annotation, f"failed to resolve the type annotation of module-level variable '{var_name}'", "NameError") return 0 # Parse the initial value (integer, negative literal, list literal, string literal) if aa.value is not None: @@ -630,10 +630,10 @@ novirtual class TranslatorGenMixin: case _: pass if is_fty_g == 0: - self.Gen.TypeGenErr.fatal_error(node, f"模块级变量 '{var_name}' 用浮点字面量初始化,但注解不是浮点类型", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"module-level variable '{var_name}' is initialized with a float literal, but its annotation is not a float type", "TypeError") return 0 if self.Gen.AssignGen._recover_float_literal(var_name, &init_fval, 0) != 1: - self.Gen.TypeGenErr.fatal_error(node, f"模块级浮点变量 '{var_name}' 初始化值源文件恢复失败", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(node, f"failed to recover the initializer value of module-level float variable '{var_name}' from the source file", "InternalCompilerError") return 0 # Check whether it is already registered @@ -703,7 +703,7 @@ novirtual class TranslatorGenMixin: if arr_init is not None: gv.Initializer = arr_init else: # Initializer build failed: error out (fail-fast) instead of falling back to zeroinitializer - self.Gen.TypeGenErr.fatal_error(node, f"模块级变量 '{var_name}' 初始化器构建失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"failed to build the initializer of module-level variable '{var_name}'", "TypeError") elif init_kind == 3: # String literal initializer: for array types (t.CArray[char, N]) use a byte-array # initializer (content + zero padding); a string-pointer GEP initializer would mismatch. @@ -716,19 +716,19 @@ novirtual class TranslatorGenMixin: if is_arr_g != 0: arr_str_init: str = self._build_string_array_initializer_text(pool, var_ty, init_str_val) if arr_str_init is not None: gv.Initializer = arr_str_init - else: self.Gen.TypeGenErr.fatal_error(node, f"模块级数组变量 '{var_name}' 字符串初始化器构建失败", "TypeError") + else: self.Gen.TypeGenErr.fatal_error(node, f"failed to build the string initializer of module-level array variable '{var_name}'", "TypeError") else: # Pointer type (e.g. b64_tab: t.CArray[char, None] = "ABC..."): create an internal # string constant global and reference it via a GEP initializer. str_init: str = self._build_string_ptr_initializer(pool, mod, var_name, init_str_val) if str_init is not None: gv.Initializer = str_init - else: self.Gen.TypeGenErr.fatal_error(node, f"模块级变量 '{var_name}' 初始化器构建失败", "TypeError") + else: self.Gen.TypeGenErr.fatal_error(node, f"failed to build the initializer of module-level variable '{var_name}'", "TypeError") elif init_kind == 4: # Float initializer: LLVM float constants must be written as bit-pattern text # (0x%016llx / 0x%08x); decimal text has ulp errors, and omitting this zeroes the global. fc_g: mlirlite.Value* = mlirlite.ConstFloat(pool, var_ty, init_fval) if fc_g is not None and fc_g.Name is not None: gv.Initializer = fc_g.Name - else: self.Gen.TypeGenErr.fatal_error(node, f"模块级变量 '{var_name}' 浮点初始化器构建失败", "TypeError") + else: self.Gen.TypeGenErr.fatal_error(node, f"failed to build the float initializer of module-level variable '{var_name}'", "TypeError") else: # Use zeroinitializer (valid for pointer/integer/aggregate types). Object-class globals # with storage get &@storage below; `= None` lazy globals still need it to stay complete. @@ -930,9 +930,9 @@ novirtual class TranslatorGenMixin: err_buf: str = None if pool_err is not None: err_buf = pool_err.alloc(256) if err_buf is not None: - viperlib.snprintf(err_buf, 256, "global 变量数量超过上限 MAX_GLOBAL_NAMES=%d,请减少 global 声明或增大 MAX_GLOBAL_NAMES", HT.MAX_GLOBAL_NAMES) + viperlib.snprintf(err_buf, 256, "the number of global variables exceeds the limit MAX_GLOBAL_NAMES=%d; reduce global declarations or increase MAX_GLOBAL_NAMES", HT.MAX_GLOBAL_NAMES) VLogger.error(err_buf, "ScopeDecl") - else: VLogger.error("global 变量数量超过上限,请减少 global 声明或增大 MAX_GLOBAL_NAMES", "ScopeDecl") + else: VLogger.error("the number of global variables exceeds the limit; reduce global declarations or increase MAX_GLOBAL_NAMES", "ScopeDecl") return entry_addr: uint64 = uint64(trans._global_names) + trans._global_name_count * 8 slot_ptr: str* = (str*)(entry_addr) @@ -969,9 +969,9 @@ novirtual class TranslatorGenMixin: err_buf_nl: str = None if pool_err_nl is not None: err_buf_nl = pool_err_nl.alloc(256) if err_buf_nl is not None: - viperlib.snprintf(err_buf_nl, 256, "nonlocal 变量数量超过上限 MAX_GLOBAL_NAMES=%d,请减少 nonlocal 声明或增大 MAX_GLOBAL_NAMES", HT.MAX_GLOBAL_NAMES) + viperlib.snprintf(err_buf_nl, 256, "the number of nonlocal variables exceeds the limit MAX_GLOBAL_NAMES=%d; reduce nonlocal declarations or increase MAX_GLOBAL_NAMES", HT.MAX_GLOBAL_NAMES) VLogger.error(err_buf_nl, "ScopeDecl") - else: VLogger.error("nonlocal 变量数量超过上限,请减少 nonlocal 声明或增大 MAX_GLOBAL_NAMES", "ScopeDecl") + else: VLogger.error("the number of nonlocal variables exceeds the limit; reduce nonlocal declarations or increase MAX_GLOBAL_NAMES", "ScopeDecl") return entry_addr: uint64 = uint64(trans._nonlocal_names) + trans._nonlocal_name_count * 8 slot_ptr: str* = (str*)(entry_addr) @@ -983,7 +983,7 @@ novirtual class TranslatorGenMixin: # A None var_ty errors out (fail-fast) instead of defaulting to i32 stored_ty: mlirlite.LLVMType* = var_ty if stored_ty is None: - self.Gen.TypeGenErr.fatal_error(None, f"nonlocal 变量 '{name}' 类型缺失,无法注册", "TypeError") + self.Gen.TypeGenErr.fatal_error(None, f"nonlocal variable '{name}' has no type, cannot register", "TypeError") return ty_slot2[0] = stored_ty trans._nonlocal_name_count += 1 diff --git a/App/lib/core/Gen/Type/TypeGenCDef.vp b/App/lib/core/Gen/Type/TypeGenCDef.vp index 3bbd48d..4909207 100644 --- a/App/lib/core/Gen/Type/TypeGenCDef.vp +++ b/App/lib/core/Gen/Type/TypeGenCDef.vp @@ -113,7 +113,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): # Table build failed (pool unusable/exhausted): report and return, never let the # append below hit None or an uninitialized address (would write NULL/0xCD). if tn is None or tv is None or td is None or tsf is None: - self.Gen.TypeGenErr.fatal_error(None, "CDefine 表分配失败(表本体池不可用或耗尽)", "MemoryError") + self.Gen.TypeGenErr.fatal_error(None, "CDefine table allocation failed (table body pool unavailable or exhausted)", "MemoryError") return self.CDefineNames = tn self.CDefineValues = tv @@ -123,11 +123,11 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): # Table-ready guard: missing/half-initialized body -> fail-fast, no garbage writes # (assert non-null before append). if self.CDefineNames is None or self.CDefineValues is None or self.CDefineDoubleFlags is None or self.CDefineStrFlags is None: - self.Gen.TypeGenErr.fatal_error(None, "CDefine 表未就绪(CDefineNames/Values/Flags 为空)", "MemoryError") + self.Gen.TypeGenErr.fatal_error(None, "CDefine table not ready (CDefineNames/Values/Flags is empty)", "MemoryError") return name_copy: str = pool.alloc(string.strlen(name) + 1) if name_copy is None: - self.Gen.TypeGenErr.fatal_error(None, f"CDefine '{name}' 名称缓冲区分配失败", "MemoryError") + self.Gen.TypeGenErr.fatal_error(None, f"CDefine '{name}' name buffer allocation failed", "MemoryError") return string.strcpy(name_copy, name) self.CDefineNames.append(name_copy) @@ -139,7 +139,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): else: self.CDefineValues.append("0") # fail-fast: a failed CDefine value buffer must abort compilation # (consistent with the double/string branches; do not silently write "0"). - if val_buf is None: self.Gen.TypeGenErr.fatal_error(None, f"CDefine '{name}' 值缓冲区分配失败", "MemoryError") + if val_buf is None: self.Gen.TypeGenErr.fatal_error(None, f"CDefine '{name}' value buffer allocation failed", "MemoryError") if self.CDefineDoubleFlags is not None: self.CDefineDoubleFlags.append(0) if self.CDefineStrFlags is not None: self.CDefineStrFlags.append(0) def register_cdefine_double(self, pool: memhub.MemBuddy*, name: str, value: double) -> None: @@ -152,7 +152,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): td: list[int]* = list[int](tp, 64) tsf: list[int]* = list[int](tp, 64) if tn is None or tv is None or td is None or tsf is None: - self.Gen.TypeGenErr.fatal_error(None, "CDefine 浮点表分配失败(表本体池不可用或耗尽)", "MemoryError") + self.Gen.TypeGenErr.fatal_error(None, "CDefine float table allocation failed (table body pool unavailable or exhausted)", "MemoryError") return self.CDefineNames = tn self.CDefineValues = tv @@ -161,11 +161,11 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): self._cdef_idx_init(tp) # Table-ready guard (same as register_cdefine_constant): assert non-null before append if self.CDefineNames is None or self.CDefineValues is None or self.CDefineDoubleFlags is None or self.CDefineStrFlags is None: - self.Gen.TypeGenErr.fatal_error(None, "CDefine 浮点表未就绪(CDefineNames/Values/Flags 为空)", "MemoryError") + self.Gen.TypeGenErr.fatal_error(None, "CDefine float table not ready (CDefineNames/Values/Flags is empty)", "MemoryError") return name_copy_d: str = pool.alloc(string.strlen(name) + 1) if name_copy_d is None: - self.Gen.TypeGenErr.fatal_error(None, f"CDefine 浮点 '{name}' 名称缓冲区分配失败", "MemoryError") + self.Gen.TypeGenErr.fatal_error(None, f"CDefine float '{name}' name buffer allocation failed", "MemoryError") return string.strcpy(name_copy_d, name) self.CDefineNames.append(name_copy_d) @@ -181,13 +181,13 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): if self.CDefineStrFlags is not None: self.CDefineStrFlags.append(0) # fail-fast: a failed CDefine value buffer must abort compilation if val_buf is None: - VLogger.error("CDefine 浮点值缓冲区分配失败", "CDEF-DBG") - self.Gen.TypeGenErr.fatal_error(None, "CDefine 浮点值缓冲区分配失败", "MemoryError") + VLogger.error("CDefine float value buffer allocation failed", "CDEF-DBG") + self.Gen.TypeGenErr.fatal_error(None, "CDefine float value buffer allocation failed", "MemoryError") def register_cdefine_string(self, pool: memhub.MemBuddy*, name: str, value: str) -> None: """Register a string CDefine constant, deep-copying name and value into pool.""" if pool is None or name is None: return if value is None: - self.Gen.TypeGenErr.fatal_error(None, f"CDefine 字符串值缺失: {name}", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(None, f"CDefine string value missing: {name}", "InternalCompilerError") return if self.CDefineNames is None: tp: memhub.MemBuddy* = self._cdefine_table_pool(pool) @@ -196,7 +196,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): td: list[int]* = list[int](tp, 64) tsf: list[int]* = list[int](tp, 64) if tn is None or tv is None or td is None or tsf is None: - self.Gen.TypeGenErr.fatal_error(None, "CDefine 字符串表分配失败(表本体池不可用或耗尽)", "MemoryError") + self.Gen.TypeGenErr.fatal_error(None, "CDefine string table allocation failed (table body pool unavailable or exhausted)", "MemoryError") return self.CDefineNames = tn self.CDefineValues = tv @@ -205,11 +205,11 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): self._cdef_idx_init(tp) # Table-ready guard (same as register_cdefine_constant): assert non-null before append if self.CDefineNames is None or self.CDefineValues is None or self.CDefineDoubleFlags is None or self.CDefineStrFlags is None: - self.Gen.TypeGenErr.fatal_error(None, "CDefine 字符串表未就绪(CDefineNames/Values/Flags 为空)", "MemoryError") + self.Gen.TypeGenErr.fatal_error(None, "CDefine string table not ready (CDefineNames/Values/Flags is empty)", "MemoryError") return ncopy_s: str = pool.alloc(string.strlen(name) + 1) if ncopy_s is None: - self.Gen.TypeGenErr.fatal_error(None, f"CDefine 字符串 '{name}' 名称缓冲区分配失败", "MemoryError") + self.Gen.TypeGenErr.fatal_error(None, f"CDefine string '{name}' name buffer allocation failed", "MemoryError") return string.strcpy(ncopy_s, name) self.CDefineNames.append(ncopy_s) @@ -217,7 +217,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): vlen: sizet = string.strlen(value) vcopy: str = pool.alloc(vlen + 1) if vcopy is None: - self.Gen.TypeGenErr.fatal_error(None, f"CDefine 字符串值分配失败: {name}", "MemoryError") + self.Gen.TypeGenErr.fatal_error(None, f"CDefine string value allocation failed: {name}", "MemoryError") return string.strcpy(vcopy, value) self.CDefineValues.append(vcopy) diff --git a/App/lib/core/Gen/Type/TypeGenCType.vp b/App/lib/core/Gen/Type/TypeGenCType.vp index b335065..7c79eeb 100644 --- a/App/lib/core/Gen/Type/TypeGenCType.vp +++ b/App/lib/core/Gen/Type/TypeGenCType.vp @@ -131,7 +131,7 @@ class TypeGenCType(TypeGenBase.TypeGenBase): # Table creation failure: report and return; never let append write to # None or uninitialized memory (the old code crashed writing 0xCDCD). if tn is None or ts is None: - VLogger.error("CTypedef 表分配失败(表本体池不可用或耗尽)", "TypeGen") + VLogger.error("CTypedef table allocation failed (table body pool unavailable or exhausted)", "TypeGen") return self.CTypedefNames = tn self.CTypedefTypeStrs = ts @@ -139,7 +139,7 @@ class TypeGenCType(TypeGenBase.TypeGenBase): self._ctypedef_idx_init(tp) # table-ready guard: fail-fast when the table is missing rather than write garbage if self.CTypedefNames is None or self.CTypedefTypeStrs is None: - VLogger.error("CTypedef 表未就绪(CTypedefNames/CTypedefTypeStrs 为空)", "TypeGen") + VLogger.error("CTypedef table not ready (CTypedefNames/CTypedefTypeStrs is empty)", "TypeGen") return # dedup: if a same-named CTypedef exists, update its type string exist_n: sizet = len(self.CTypedefNames) @@ -442,7 +442,7 @@ class TypeGenCType(TypeGenBase.TypeGenBase): self.ConstEvalOk = 0 return 0 # Recursion depth guard: a cyclic BinOp would recurse forever; fail-fast abort. - if depth > 64: self.Gen.TypeGenErr.fatal_type_error(node, "常量表达式递归过深(AST 环或嵌套超过 64 层)") + if depth > 64: self.Gen.TypeGenErr.fatal_type_error(node, "constant expression recursion too deep (AST cycle or nesting over 64 levels)") k: int = node.kind() # Constant: integer literal diff --git a/App/lib/core/Gen/Type/TypeGenErr.vp b/App/lib/core/Gen/Type/TypeGenErr.vp index 6a74153..f7a22be 100644 --- a/App/lib/core/Gen/Type/TypeGenErr.vp +++ b/App/lib/core/Gen/Type/TypeGenErr.vp @@ -89,7 +89,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): stdio.printf("^\n") stdlib.free(src) else: stdio.printf(' File "%s"\n', file_path) - if err_msg is None or err_msg[0] == 0: err_msg = "语法错误" + if err_msg is None or err_msg[0] == 0: err_msg = "syntax error" stdio.printf("SyntaxError: %s\n", err_msg) def fatal_error(self, node: ast.AST*, msg: str, err_type: str = "SyntaxError", col_start: int = 0, col_end: int = 0): """Report an error in Python style and exit (supports multiple frames, error type, column range).""" @@ -129,7 +129,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): src_line = self._read_source_line(file_name, lineno) if src_line is None: line_ok = 0 if line_ok == 0: - stdio.printf(' File "%s", line %d (!! 无法读取该行源码:文件不存在或行号超出范围,错误可能来自被复用的 AST 树,请以错误消息为准)\n', file_name, lineno) + stdio.printf(' File "%s", line %d (!! cannot read that source line: file does not exist or line number out of range; the error may come from a reused AST tree, rely on the error message)\n', file_name, lineno) else: stdio.printf(' File "%s", line %d\n', file_name, lineno) if src_line is not None: @@ -175,7 +175,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): if node is None or marker_name is None: return 0 # Recursion depth guard: vpi stub injection calls this for every function's returns, and # deep vpi nodes may be corrupted into back-pointing cycles (VpiReader L810-813); fail fast. - if depth > 128: self.fatal_type_error(node, "装饰器标记检测递归过深(AST 环或嵌套超过 128 层)") + if depth > 128: self.fatal_type_error(node, "decorator marker detection recursion too deep (AST cycle or nesting over 128 levels)") k: int = node.kind() diff --git a/App/lib/core/Gen/Type/TypeGenResolve.vp b/App/lib/core/Gen/Type/TypeGenResolve.vp index 3ef43d6..6467a50 100644 --- a/App/lib/core/Gen/Type/TypeGenResolve.vp +++ b/App/lib/core/Gen/Type/TypeGenResolve.vp @@ -140,7 +140,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): es3: str = self._subscript_slice_to_str(pool, e3) if es3 is None: # Missing type name: error out immediately (a silent drop builds a wrong type string) - self.Gen.TypeGenErr.fatal_error(e3, "类型注解的元素无法解析为类型名(列表/元组注解)", "NameError") + self.Gen.TypeGenErr.fatal_error(e3, "Type annotation element cannot be resolved to a type name (list/tuple annotation)", "NameError") return None cnt3 += 1 total3 += string.strlen(es3) @@ -319,7 +319,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # [FIX] Out-of-range type-name pointer (garbage from pool overwrite): fail-fast # before dereferencing instead of segfaulting silently in strlen. if uint64(type_name) > 0x00007FFFFFFFFFFF: - VLogger.error(f"_norm_type_arg_name 类型名指针越界 (ptr={uint64(type_name)}),疑似 pool 越界写破坏类型名指针", "TypeGen") + VLogger.error(f"_norm_type_arg_name type name pointer out of range (ptr={uint64(type_name)}); a pool out-of-bounds write likely corrupted the type name pointer", "TypeGen") stdlib.exit(1) # [FIX] Generic-arg split leaves a leading space on the second arg (" 4"); leading # whitespace is dirty data as a type name / table key, so skip it before normalizing. @@ -612,7 +612,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): _w_buf[0] = '\0' mlirlite.TypePrint(_w_buf, 512, _bare_entry.Ty, pool) if _w_buf[0] != '\0': _w_ty = _w_buf - VLogger.error(f"[类型实参归属] 裸类名 '{type_name}' 本次保留裸名(可能与带前缀形式分裂):" f"entry_present={_w_ep} entry.Ty={_w_ty} cur_def_mod={_w_mod} cur_def_cls={_w_cls} " f"is_module_class={_w_imc} find_struct_by_module={_w_fbm} " f"from_imports={_w_fi} file={_w_file}", "TypeGen") + VLogger.error(f"[TypeArgOwnership] bare class name '{type_name}' keeps the bare name this time (may split from the prefixed form):" f"entry_present={_w_ep} entry.Ty={_w_ty} cur_def_mod={_w_mod} cur_def_cls={_w_cls} " f"is_module_class={_w_imc} find_struct_by_module={_w_fbm} " f"from_imports={_w_fi} file={_w_file}", "TypeGen") # ---- 6. not found: keep as-is (builtin type names etc.) ---- return type_name @@ -1858,14 +1858,14 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # gen_mangled; re-query using spec_name_chk, the authoritative name. if gen_spec_ty is None: gen_spec_ty = self.Gen.StructGen.get_struct_type(spec_name_chk) if gen_spec_ty is not None: return gen_spec_ty - else: VLogger.info(f"[GENERIC-DBG] 特化失败(返回 None): {gen_cls_name}[{gen_mangled}]", "Phase1") - else: VLogger.info(f"[GENERIC-DBG] 类型实参提取失败: {gen_cls_name}", "Phase1") - else: VLogger.info(f"[GENERIC-DBG] 模板未注册: {gen_cls_name}", "Phase1") - else: VLogger.info(f"[GENERIC-DBG] trans 为 None: {gen_cls_name}", "Phase1") + else: VLogger.info(f"[GENERIC-DBG] specialization failed (returned None): {gen_cls_name}[{gen_mangled}]", "Phase1") + else: VLogger.info(f"[GENERIC-DBG] type argument extraction failed: {gen_cls_name}", "Phase1") + else: VLogger.info(f"[GENERIC-DBG] template not registered: {gen_cls_name}", "Phase1") + else: VLogger.info(f"[GENERIC-DBG] trans is None: {gen_cls_name}", "Phase1") # In Phase B full translation, if a generic template subscript still cannot resolve, # the annotation would silently degrade and crash; report it instead (template names only). if trans is not None and trans._declare_only == 0 and self.Gen.ClassGenGeneric._find_generic_template(gen_cls_name) is not None: - self.Gen.TypeGenErr.fatal_error(sub, f"泛型下标 '{gen_mangled}' 未解析出特化结构体(泛型模板='{gen_cls_name}');" f"该注解将退化为裸基类/i8* → 后续 .get() 按错误元素类型分派并截断指针", "TypeError") + self.Gen.TypeGenErr.fatal_error(sub, f"Generic subscript '{gen_mangled}' did not resolve to a specialized struct (generic template='{gen_cls_name}'); " f"the annotation will degrade to a bare base class/i8* -> later .get() dispatches on the wrong element type and truncates pointers", "TypeError") # [REPL session] includes generic templates are unregistered, so build an opaque # placeholder "%{template module sha1}.{mangled}" using the registered owner sha1. if trans is not None and trans.ReplCtx is not None: @@ -1893,14 +1893,14 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if base_nm is None: return 0 # Only treat it as a bare generic annotation if the base name is a registered template if self.Gen.ClassGenGeneric._find_generic_template(base_nm) is None: return 0 - self.Gen.TypeGenErr.fatal_error(node, f"泛型类 '{base_nm}' 的注解必须带类型实参(如 {base_nm}[T]);" f"裸名会被当作无实参的裸泛型基类,元素类型丢失后方法调用会按错误元素" f"类型特化并截断指针。正确写法示例:vector.Vector[CInt]、GSList[G5Node]。", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"The annotation of generic class '{base_nm}' must carry type arguments (e.g. {base_nm}[T]); " f"a bare name is treated as a bare generic base class without arguments, and once the element type is lost, method calls specialize on the wrong element " f"type and truncate pointers. Correct examples: vector.Vector[CInt], GSList[G5Node].", "TypeError") return 0 def resolve_annotation_type(self, pool: memhub.MemBuddy*, node: ast.AST*, imported_modules: str, from_imports: str, trans: HT.Translator* = None, depth: int = 0) -> mlirlite.LLVMType*: """Resolve a type-annotation node into an LLVMType.""" if node is None: return None # Recursion-depth guard: a corrupted self-referential AST would recurse until stack # exhaustion; fail-fast beyond 128 levels instead of silently falling back. - if depth > 128: self.Gen.TypeGenErr.fatal_type_error(node, "类型注解递归过深(AST 环或嵌套超过 128 层)") + if depth > 128: self.Gen.TypeGenErr.fatal_type_error(node, "Type annotation recursion too deep (AST cycle or nesting beyond 128 levels)") # Bare generic annotation fail-fast (see _check_bare_generic_annotation): abort when a # registered generic template name appears without type args. @@ -1924,7 +1924,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # Builtin fixed-array constructor array is a soft keyword: only active as # array[E, N] in type/annotation positions; a bare use there is a fail-fast misuse. if string.strcmp(nm.id, "array") == 0: - self.Gen.TypeGenErr.fatal_type_error(nm, "裸用内建定长数组构造子 'array'(缺少下标与参数):'array' 只在类型/注解位置生效,必须写成 array[E, N](元素类型在前、长度在后)。正确示例:state: array[uint32, 4]") + self.Gen.TypeGenErr.fatal_type_error(nm, "Bare use of the built-in fixed-size array constructor 'array' (missing subscript and arguments): 'array' only takes effect in type/annotation position and must be written as array[E, N] (element type first, length second). Correct example: state: array[uint32, 4]") # Generic parameter T substitution: replace T with the concrete type in specialization tpn_g: list[str]* = self.Gen.TypeGenBase.GenericTpNames tpa_g: list[str]* = self.Gen.TypeGenBase.GenericTypeArgs @@ -1941,7 +1941,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if string.strcmp(gp_ta, gp_tpn) == 0: # Generic param self-map (T->T): report a compile error rather # than silently degrade (which causes hard-to-locate runtime corruption). - self.Gen.TypeGenErr.fatal_error(nm, f"泛型类型实参污染:类型参数 '{gp_tpn}' 自映射(实参='{gp_ta}'),无法特化", "TypeError") + self.Gen.TypeGenErr.fatal_error(nm, f"Generic type argument pollution: type parameter '{gp_tpn}' maps to itself (argument='{gp_ta}'); cannot specialize", "TypeError") polluted: int = 0 gp_j: sizet for gp_j in range(gp_n): @@ -1954,7 +1954,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if polluted != 0: # Arg string contains a type-param name (e.g. "T*"/"list[T]"): it # would recurse forever, so report a compile error (was a silent None). - self.Gen.TypeGenErr.fatal_error(nm, f"泛型类型实参污染:实参 '{gp_ta}' 包含类型参数名,无法特化", "TypeError") + self.Gen.TypeGenErr.fatal_error(nm, f"Generic type argument pollution: argument '{gp_ta}' contains a type parameter name; cannot specialize", "TypeError") # Recurse using the concrete type name (supports BinOp/Attribute args) gp_sub_node: ast.AST* = self._parse_type_string(pool, gp_ta, nm.ctx) if gp_sub_node is not None: return self.resolve_annotation_type(pool, gp_sub_node, imported_modules, from_imports, trans, depth + 1) @@ -2417,10 +2417,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # list[int] -> specialized struct type. value is Attribute(Name('t'),'CArray') or Name('list'). if k == ast.ASTKind.Subscript: sub: ast.Subscript* = ast.Subscript*(node) - if sub.value is None: self.Gen.TypeGenErr.fatal_type_error(node, "Subscript 节点缺少 value") + if sub.value is None: self.Gen.TypeGenErr.fatal_type_error(node, "Subscript node missing value") # An empty subscript (t.Callable[]) has slice None: allowed only for unsigned function # pointers (handled as i8* below); other types still require a slice. - if sub.slice is None and self._IsCallableSubscriptValue(sub.value) == 0: self.Gen.TypeGenErr.fatal_type_error(node, "Subscript 节点缺少 value 或 slice") + if sub.slice is None and self._IsCallableSubscriptValue(sub.value) == 0: self.Gen.TypeGenErr.fatal_type_error(node, "Subscript node missing value or slice") # Function pointers (bare callable / Callable) equal t.Callable point-for-point and # map to i8*; must be checked before the Name path (generic/CArray/builtins fallback). if sub.value.kind() == ast.ASTKind.Name and self._IsCallableSubscriptValue(sub.value) != 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) @@ -2432,22 +2432,22 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # active only in type positions; only exactly two args with a positive length. if string.strcmp(gen_nm.id, "array") == 0: if sub.slice.kind() != ast.ASTKind.Tuple: - self.Gen.TypeGenErr.fatal_type_error(node, "内建定长数组构造子 'array' 缺少长度参数(当前仅 1 个参数):必须写成 array[E, N](E=元素类型,N=长度)。正确示例:state: array[uint32, 4]") + self.Gen.TypeGenErr.fatal_type_error(node, "Built-in fixed-size array constructor 'array' missing length argument (currently only 1 argument): must be written as array[E, N] (E=element type, N=length). Correct example: state: array[uint32, 4]") tup_arr: ast.Tuple* = ast.Tuple*(sub.slice) - if tup_arr.elts is None or len(tup_arr.elts) != 2: self.Gen.TypeGenErr.fatal_type_error(node, "内建定长数组构造子 'array' 参数个数错误(期望 2 个):只接受 array[E, N]。正确示例:state: array[uint32, 4]") + if tup_arr.elts is None or len(tup_arr.elts) != 2: self.Gen.TypeGenErr.fatal_type_error(node, "Built-in fixed-size array constructor 'array' has a wrong argument count (expected 2): only array[E, N] is accepted. Correct example: state: array[uint32, 4]") elem_node_arr: ast.AST* = tup_arr.elts.get(0) count_node_arr: ast.AST* = tup_arr.elts.get(1) - if elem_node_arr is None or count_node_arr is None: self.Gen.TypeGenErr.fatal_type_error(node, "内建定长数组构造子 'array' 的元素类型或长度为空:只接受 array[E, N]。正确示例:state: array[uint32, 4]") + if elem_node_arr is None or count_node_arr is None: self.Gen.TypeGenErr.fatal_type_error(node, "Built-in fixed-size array constructor 'array' has an empty element type or length: only array[E, N] is accepted. Correct example: state: array[uint32, 4]") if count_node_arr.kind() == ast.ASTKind.Constant: cnt_arr0: ast.Constant* = ast.Constant*(count_node_arr) if cnt_arr0.const_kind == ast.CONST_NONE: - self.Gen.TypeGenErr.fatal_type_error(count_node_arr, "内建定长数组构造子 'array' 的长度必须是正整型常量(>0),不允许 None(长度自动推导请改用 t.CArray[E])。正确示例:state: array[uint32, 4]") + self.Gen.TypeGenErr.fatal_type_error(count_node_arr, "Built-in fixed-size array constructor 'array' length must be a positive integer constant (>0); None is not allowed (use t.CArray[E] for automatic length inference). Correct example: state: array[uint32, 4]") elem_ty_arr: mlirlite.LLVMType* = self.resolve_annotation_type(pool, elem_node_arr, imported_modules, from_imports, trans, depth + 1) if elem_ty_arr is None: return None count_arr: int = self.Gen.TypeGenCType._eval_const_int_expr(count_node_arr, pool, from_imports, imported_modules) if self.Gen.TypeGenCType.ConstEvalOk == 0: - self.Gen.TypeGenErr.fatal_type_error(count_node_arr, "内建定长数组构造子 'array' 的长度必须是整型常量表达式(字面量 / CDefine 常量名 / 常量算术表达式)。正确示例:state: array[uint8, MAX_LEN]") - if count_arr <= 0: self.Gen.TypeGenErr.fatal_type_error(count_node_arr, "内建定长数组构造子 'array' 的长度必须为正数。正确示例:state: array[uint32, 4]") + self.Gen.TypeGenErr.fatal_type_error(count_node_arr, "Built-in fixed-size array constructor 'array' length must be an integer constant expression (literal / CDefine constant name / constant arithmetic expression). Correct example: state: array[uint8, MAX_LEN]") + if count_arr <= 0: self.Gen.TypeGenErr.fatal_type_error(count_node_arr, "Built-in fixed-size array constructor 'array' length must be positive. Correct example: state: array[uint32, 4]") return mlirlite.Array(pool, elem_ty_arr, count_arr) # Bare CArray (from t import *): equivalent to t.CArray; otherwise generic # lookup fails, the field type degrades to Ptr(i8), and linking fails. @@ -2505,29 +2505,29 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if fb_ty is not None: return fb_ty return None # Check whether value is an Attribute (t.CArray / t.Callable / module-qualified generic like numpy.ndarray[T]) - if sub.value.kind() != ast.ASTKind.Attribute: self.Gen.TypeGenErr.fatal_type_error(node, "不支持的 Subscript 类型注解(仅支持 t.CArray / t.Callable)") + if sub.value.kind() != ast.ASTKind.Attribute: self.Gen.TypeGenErr.fatal_type_error(node, "Unsupported Subscript type annotation (only t.CArray / t.Callable are supported)") arr_at: ast.Attribute* = ast.Attribute*(sub.value) - if arr_at.attr is None: self.Gen.TypeGenErr.fatal_type_error(node, "Subscript Attribute 缺少 attr") + if arr_at.attr is None: self.Gen.TypeGenErr.fatal_type_error(node, "Subscript Attribute missing attr") # Module-qualified generic class: numpy.ndarray[t.CDouble] -> use the bare class name # ndarray for specialization (before the t.CArray / t.Callable checks). if trans is not None: if self.Gen.ClassGenGeneric._find_generic_template(arr_at.attr) is not None: return self._resolve_generic_subscript_ty(pool, sub, arr_at.attr, trans, imported_modules, from_imports, depth + 1) - if arr_at.value is None or arr_at.value.kind() != ast.ASTKind.Name: self.Gen.TypeGenErr.fatal_type_error(node, "t.CArray / t.Callable 必须通过模块名限定") + if arr_at.value is None or arr_at.value.kind() != ast.ASTKind.Name: self.Gen.TypeGenErr.fatal_type_error(node, "t.CArray / t.Callable must be qualified by the module name") arr_val_name: ast.Name* = ast.Name*(arr_at.value) - if arr_val_name.id is None: self.Gen.TypeGenErr.fatal_type_error(node, "Subscript 模块名为 None") + if arr_val_name.id is None: self.Gen.TypeGenErr.fatal_type_error(node, "Subscript module name is None") # Function pointer type: t.Callable[[A, B], Ret] -> i8* (function values are bitcast to # i8* for storage and the signature is rebuilt at calls, matching TPV convention). if string.strcmp(arr_at.attr, "Callable") == 0: # t/c are builtin namespaces (not compiled, not in imported_modules); no import check needed if string.strcmp(arr_val_name.id, "t") != 0 and string.strcmp(arr_val_name.id, "c") != 0 and self.Gen.ImportsGen.is_module_imported(imported_modules, arr_val_name.id) == 0: - self.Gen.TypeGenErr.fatal_type_error(node, "t.Callable 模块未导入") + self.Gen.TypeGenErr.fatal_type_error(node, "t.Callable module not imported") return mlirlite.Ptr(pool, mlirlite.Int8(pool)) # Pointer type: t.CPtr[T] -> Ptr(T); always appends exactly 1 layer, no exceptions # (`t.CPtr[T]` == `T*`). The old "absorb a layer" compensation is removed. if string.strcmp(arr_at.attr, "CPtr") == 0: if string.strcmp(arr_val_name.id, "t") != 0 and string.strcmp(arr_val_name.id, "c") != 0 and self.Gen.ImportsGen.is_module_imported(imported_modules, arr_val_name.id) == 0: - self.Gen.TypeGenErr.fatal_type_error(node, "t.CPtr 模块未导入") + self.Gen.TypeGenErr.fatal_type_error(node, "t.CPtr module not imported") inner_cptr_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1) if inner_cptr_ty is None: # Element type not ready (class not yet registered): prefer a forward declaration @@ -2536,9 +2536,9 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if _fwd_cptr_ty is not None: return _fwd_cptr_ty return None return mlirlite.Ptr(pool, inner_cptr_ty) - if string.strcmp(arr_at.attr, "CArray") != 0: self.Gen.TypeGenErr.fatal_type_error(node, "不支持的 Subscript 类型注解(仅支持 t.CArray / t.Callable)") + if string.strcmp(arr_at.attr, "CArray") != 0: self.Gen.TypeGenErr.fatal_type_error(node, "Unsupported Subscript type annotation (only t.CArray / t.Callable are supported)") if string.strcmp(arr_val_name.id, "t") != 0 and string.strcmp(arr_val_name.id, "c") != 0 and self.Gen.ImportsGen.is_module_imported(imported_modules, arr_val_name.id) == 0: - self.Gen.TypeGenErr.fatal_type_error(node, "t.CArray 模块未导入") + self.Gen.TypeGenErr.fatal_type_error(node, "t.CArray module not imported") # Single-arg form: t.CArray[elem_ty] -> Ptr(elem_ty), equivalent to # t.CArray[elem_ty, None] (statically inferred length array). if sub.slice.kind() != ast.ASTKind.Tuple: @@ -2549,13 +2549,13 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): return mlirlite.Ptr(pool, elem_ty_single) # Two-arg form: t.CArray[elem_ty, count] -> [count x elem_ty] tup: ast.Tuple* = ast.Tuple*(sub.slice) - if tup.elts is None: self.Gen.TypeGenErr.fatal_type_error(node, "t.CArray Tuple 缺少 elts") + if tup.elts is None: self.Gen.TypeGenErr.fatal_type_error(node, "t.CArray Tuple missing elts") elts_list: list[ast.AST*]* = tup.elts elts_n: sizet = len(elts_list) - if elts_n < 2: self.Gen.TypeGenErr.fatal_type_error(node, "t.CArray Tuple 元素不足") + if elts_n < 2: self.Gen.TypeGenErr.fatal_type_error(node, "t.CArray Tuple has too few elements") elem_node: ast.AST* = elts_list.get(0) count_node: ast.AST* = elts_list.get(1) - if elem_node is None or count_node is None: self.Gen.TypeGenErr.fatal_type_error(node, "t.CArray Tuple 元素为 None") + if elem_node is None or count_node is None: self.Gen.TypeGenErr.fatal_type_error(node, "t.CArray Tuple element is None") # Recursively resolve the element type elem_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, elem_node, imported_modules, from_imports, trans, depth + 1) if elem_ty is None: @@ -2571,14 +2571,14 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # Use _eval_const_int_expr for the constant integer expression (Constant/Name/BinOp); # pool/from_imports/imported_modules enable cross-module CDefine lookup. count_val = self.Gen.TypeGenCType._eval_const_int_expr(count_node, pool, from_imports, imported_modules) - if self.Gen.TypeGenCType.ConstEvalOk == 0: self.Gen.TypeGenErr.fatal_type_error(count_node, "t.CArray count 必须是整数常量、None、CDefine 常量名或常量表达式") - if count_val <= 0: self.Gen.TypeGenErr.fatal_type_error(count_node, "t.CArray count 必须为正数") + if self.Gen.TypeGenCType.ConstEvalOk == 0: self.Gen.TypeGenErr.fatal_type_error(count_node, "t.CArray count must be an integer constant, None, a CDefine constant name, or a constant expression") + if count_val <= 0: self.Gen.TypeGenErr.fatal_type_error(count_node, "t.CArray count must be positive") # Create the ArrayType (no Ptr wrapping), so build_alloca allocates the array # and alloca returns [N x elem_ty]*. return mlirlite.Array(pool, elem_ty, count_val) # Unknown AST kind: fail-fast instead of leniently returning None - self.Gen.TypeGenErr.fatal_type_error(node, "不支持的类型注解语法") + self.Gen.TypeGenErr.fatal_type_error(node, "Unsupported type annotation syntax") # Append an explicit return after fatal_type_error (unreachable at runtime) so the # method's final block is properly terminated without a noreturn whitelist. return None \ No newline at end of file diff --git a/App/lib/core/Gen/Type/TypeSpec.vp b/App/lib/core/Gen/Type/TypeSpec.vp index d1608d9..8b791e6 100644 --- a/App/lib/core/Gen/Type/TypeSpec.vp +++ b/App/lib/core/Gen/Type/TypeSpec.vp @@ -627,7 +627,7 @@ def InternSpec(arena: TypeSpecArena*, sp: TypeSpec*) -> TypeSpec*: # Miss: append. Table full = fail-fast (never return None, which would silently # lose type info up the call chain and corrupt signedness -> zext/sext direction). if arena.Count >= arena.Cap: - GenApi.fatal_error(None, f"TypeSpec 驻留表已满(上限 {arena.Cap} 条),无法登记新类型", "InternalCompilerError") + GenApi.fatal_error(None, f"TypeSpec intern table is full (limit {arena.Cap} entries), cannot register a new type", "InternalCompilerError") # Reachable only when fatal_error is a no-op: degrade to "no interning but return a # complete instance", keeping the never-return-None guarantee. return sp diff --git a/App/lib/core/Gen/VarGenMixin.vp b/App/lib/core/Gen/VarGenMixin.vp index 9c6d0a3..5875c87 100644 --- a/App/lib/core/Gen/VarGenMixin.vp +++ b/App/lib/core/Gen/VarGenMixin.vp @@ -114,7 +114,7 @@ novirtual class VarGenMixin: # A ptr-element variable's alloca is Ptr(Ptr(Int8)), so its value type implies Spec PtrLevel>=1. # Violation means an upstream type error; fail-fast, since a silent pass would mis-index by 1 byte. if entry.Spec is None or entry.Spec.PtrLevel < 1: - self.Gen.TypeGenErr.fatal_error(None, f"变量 '{name}' 标记为 ptr-element,但其 Spec 不可承载指针语义", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(None, f"variable '{name}' is marked as ptr-element, but its Spec cannot carry pointer semantics", "InternalCompilerError") return 1 entry.Spec = TSpec.SpecWithElemBits(entry.Spec, 64) return 0 @@ -367,7 +367,7 @@ novirtual class VarGenMixin: if existing is not None: return existing alloca: mlirlite.Value* = self._alloca_at_entry(builder, ty) if alloca is None: return None - if self.define_var(symtab, name, alloca) != 0: self.Gen.TypeGenErr.fatal_error(None, f"变量 '{name}' 注册失败(作用域变量数超过上限 MAX_VARS)", "InternalCompilerError") + if self.define_var(symtab, name, alloca) != 0: self.Gen.TypeGenErr.fatal_error(None, f"failed to register variable '{name}' (scope variable count exceeds the limit MAX_VARS)", "InternalCompilerError") return alloca # REPL mode (M2) - session variable slot read/write; entered only when trans.ReplCtx != None (slots hold the value at ctx + x.Offset). @@ -404,7 +404,7 @@ novirtual class VarGenMixin: symtab: GenTypes.SymbolTable* = trans.SymTab param_alloca: mlirlite.Value* = self.lookup_var(symtab, ctx.CtxParam) if param_alloca is None or param_alloca.Ty is None or param_alloca.Ty.Pointee == 0: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 片段函数缺少 ctx 形参 '{ctx.CtxParam}'(包裹模板与 M2 调用约定不一致)", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: snippet function is missing the ctx parameter '{ctx.CtxParam}' (wrapper template and M2 calling convention disagree)", "InternalCompilerError") return None return mlirlite.build_load(trans._cur_builder, param_alloca.Ty.Pointee, param_alloca) @@ -464,10 +464,10 @@ novirtual class VarGenMixin: if self.repl_in_frag_scope(trans.SymTab) == 0: return None hit[0] = 1 if kw_count != 0: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 不支持关键字实参(M3 仅支持位置实参)", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: session function '{func_name}' does not support keyword arguments (M3 supports positional arguments only)", "TypeError") return None if can != entry.ParamCount: - self.Gen.TypeGenErr.fatal_error( node, f"REPL: 会话函数 '{func_name}' 期待 {entry.ParamCount} 个位置实参,调用处给了 {can} 个(M3 不支持默认参数/缺省补全)", "TypeError") + self.Gen.TypeGenErr.fatal_error( node, f"REPL: session function '{func_name}' expects {entry.ParamCount} positional arguments, but the call site passed {can} (M3 does not support default arguments or default completion)", "TypeError") return None ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, ctx, node) if ctx_val is None: return None @@ -476,11 +476,11 @@ novirtual class VarGenMixin: # (1) Load the function address from the slot: the slot is i8** (Ptr(i8*)); load yields i8* slot: mlirlite.Value* = self.repl_slot_ptr(pool, builder, ctx_val, entry.SlotOff, i8_ptr_ty) if slot is None: - self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话函数指针槽地址生成失败", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(node, "REPL: failed to generate the session function pointer slot address", "InternalCompilerError") return None fn_i8: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, slot) if fn_i8 is None: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的地址读取失败", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: failed to read the address of session function '{func_name}'", "InternalCompilerError") return None # (2) Resolve param types before building the signature (token -> LLVM type; unsupported -> error) ptypes: t.CPtr = pool.alloc(8 * GenTypes.REPL_FUNC_PARAM_MAX) @@ -490,7 +490,7 @@ novirtual class VarGenMixin: for ai_chk in range(entry.ParamCount): pty_chk: mlirlite.LLVMType* = self.repl_func_ty(pool, int(entry.ParamTags[ai_chk]), int(entry.ParamBits[ai_chk])) if pty_chk is None: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 第 {ai_chk + 1} 个形参的类型 token 不受支持(M3 支持 iN/float/double/i8*)", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: type token of parameter {ai_chk + 1} of session function '{func_name}' is not supported (M3 supports iN/float/double/i8*)", "TypeError") return None pty_slot: str* = (str*)(uint64(ptypes) + ai_chk * 8) pty_slot[0] = pty_chk @@ -503,17 +503,17 @@ novirtual class VarGenMixin: for ai in range(entry.ParamCount): arg: ast.AST* = cargs.get(ai) if arg is None: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的第 {ai + 1} 个实参缺失", "SyntaxError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: argument {ai + 1} of session function '{func_name}' is missing", "SyntaxError") return None pty_slot2: str* = (str*)(uint64(ptypes) + ai * 8) pty: mlirlite.LLVMType* = (mlirlite.LLVMType*)(pty_slot2[0]) arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, pty) if arg_val is None: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的第 {ai + 1} 个实参翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: failed to translate argument {ai + 1} of session function '{func_name}'", "TypeError") return None coerced: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, pty, arg, trans) if coerced is None: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的第 {ai + 1} 个实参与签名类型不兼容", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: argument {ai + 1} of session function '{func_name}' is incompatible with the signature type", "TypeError") return None coerced.Next = None tail.Next = coerced @@ -525,7 +525,7 @@ novirtual class VarGenMixin: if entry.RetTag != GenTypes.REPL_TY_VOID: ret_ty = self.repl_func_ty(pool, entry.RetTag, entry.RetBits) if ret_ty is None: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的返回类型 token 不受支持(M3 支持 void/iN/float/double/i8*)", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: return type token of session function '{func_name}' is not supported (M3 supports void/iN/float/double/i8*)", "TypeError") return None # Param list nodes are mlirlite.ParamNode (new_param_node returns rawptr[ParamNode], and # paramnode_set_next / Func params are rawptr[ParamNode] too) - previously mistyped as Function*. @@ -547,7 +547,7 @@ novirtual class VarGenMixin: func_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, func_ty) fn_typed: mlirlite.Value* = mlirlite.build_bitcast(builder, fn_i8, func_ptr_ty) if fn_typed is None: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的地址转换失败", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: failed to convert the address of session function '{func_name}'", "InternalCompilerError") return None return mlirlite.build_call_indirect(builder, fn_typed, head, arg_count, ret_ty) @@ -696,7 +696,7 @@ novirtual class VarGenMixin: if trans is None or entry is None or val_ty is None: return 1 perm: memhub.MemBuddy* = self.repl_perm_pool(trans) if perm is None: - self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话永久池不可用(宿主未注入)", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(node, "REPL: session permanent pool is unavailable (not injected by the host)", "InternalCompilerError") return 1 tag: int = 0 bits: int = 0 @@ -740,17 +740,17 @@ novirtual class VarGenMixin: sz: int = self.repl_type_size(val_ty) al: int = self.repl_type_align(val_ty) if sz <= 0 or al <= 0: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{entry.Name}' 的结构体值 '{sname}' 尺寸/对齐未知" f"(无法判定能否放入 {GenTypes.REPL_SLOT_SIZE} 字节槽)", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: size/alignment of the struct value '{sname}' of session variable '{entry.Name}' is unknown" f" (cannot determine whether it fits in a {GenTypes.REPL_SLOT_SIZE} byte slot)", "TypeError") return 1 if sz > GenTypes.REPL_SLOT_SIZE or al > GenTypes.REPL_SLOT_SIZE: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{entry.Name}' 的结构体值 '{sname}' 体积 {sz} 字节、" f"对齐 {al} 字节,无法放入 {GenTypes.REPL_SLOT_SIZE} 字节槽" f"(M2 结构体值须内联进槽;大对象请改用对象指针/堆分配)", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: struct value '{sname}' of session variable '{entry.Name}' is {sz} bytes and " f"aligned to {al} bytes, so it cannot fit in a {GenTypes.REPL_SLOT_SIZE} byte slot" f" (M2 struct values must be inlined into the slot; use an object pointer or heap allocation for large objects)", "TypeError") return 1 tag = GenTypes.REPL_TY_STRUCT bits = sz * 8 kind = GenTypes.REPL_KIND_SCALAR tname = sname else: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{entry.Name}' 的类型暂不支持" f"(M2 支持 int/bool/浮点/str/bytes/指针/结构体值)", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: the type of session variable '{entry.Name}' is not supported yet" f" (M2 supports int/bool/float/str/bytes/pointer/struct value)", "TypeError") return 1 if entry.Kind == GenTypes.REPL_KIND_UNTYPED: entry.Kind = kind @@ -760,7 +760,7 @@ novirtual class VarGenMixin: if tname is not None: entry.TyName = self.repl_perm_strdup(perm, tname) return 0 if entry.Kind != kind or entry.TyTag != tag: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{entry.Name}' 已定型为 {self.repl_tag_label(entry.TyTag, entry.Bits)}," f"不能再赋成 {self.repl_tag_label(tag, bits)}(如需换型请重启会话)", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: session variable '{entry.Name}' is already typed as {self.repl_tag_label(entry.TyTag, entry.Bits)} and " f"cannot be assigned {self.repl_tag_label(tag, bits)} (restart the session to change its type)", "TypeError") return 1 if tname is not None and entry.TyName is None: entry.TyName = self.repl_perm_strdup(perm, tname) return 0 @@ -804,18 +804,18 @@ novirtual class VarGenMixin: hit: GenTypes.ReplVarEntry* = self.repl_find_entry(ctx, name) if hit is not None: return hit if ctx.Table is None or ctx.Cap <= 0: - self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话变量表未初始化(宿主未建 ctx)", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(node, "REPL: session variable table is not initialized (host did not create ctx)", "InternalCompilerError") return None if ctx.Count >= ctx.Cap: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量已达上限 {ctx.Cap} 个(ctx 槽位用尽)," f"无法为 '{name}' 再分配槽位;请重启会话", "ResourceError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: session variables have reached the limit of {ctx.Cap} (ctx slots exhausted); " f"cannot allocate another slot for '{name}'; restart the session", "ResourceError") return None perm: memhub.MemBuddy* = self.repl_perm_pool(trans) if perm is None: - self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话永久池不可用(宿主未注入)", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(node, "REPL: session permanent pool is unavailable (not injected by the host)", "InternalCompilerError") return None name_copy: str = self.repl_perm_strdup(perm, name) if name_copy is None: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的名字深拷贝失败", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: failed to deep-copy the name of session variable '{name}'", "InternalCompilerError") return None entry_size: sizet = GenTypes.ReplVarEntry.__sizeof__() entry: GenTypes.ReplVarEntry* = GenTypes.ReplVarEntry*(uint64(ctx.Table) + uint64(ctx.Count) * uint64(entry_size)) @@ -918,18 +918,18 @@ novirtual class VarGenMixin: if entry is None: return None if self.repl_in_frag_scope(trans.SymTab) == 0: return None if entry.Kind == GenTypes.REPL_KIND_UNTYPED: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 尚未赋值(未定型,先执行一条 'x = ...' 或 'x: int = ...')", "NameError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: session variable '{name}' has not been assigned yet (untyped; first run a 'x = ...' or 'x: int = ...')", "NameError") return None pool: memhub.MemBuddy* = trans.Pool slot_ty: mlirlite.LLVMType* = self.repl_slot_ty(pool, entry) if slot_ty is None: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的类型 " f"{self.repl_tag_label(entry.TyTag, entry.Bits)} 在当前片段不可用" f"(跨片段类型可见性属 M4)", "NameError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: the type " f"{self.repl_tag_label(entry.TyTag, entry.Bits)} of session variable '{name}' is not available in the current snippet" f" (cross-snippet type visibility belongs to M4)", "NameError") return None ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node) if ctx_val is None: return None slot: mlirlite.Value* = self.repl_slot_ptr(pool, trans._cur_builder, ctx_val, entry.Offset, slot_ty) if slot is None: - self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话槽地址生成失败", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(node, "REPL: failed to generate the session slot address", "InternalCompilerError") return None return mlirlite.build_load(trans._cur_builder, slot_ty, slot) @@ -941,18 +941,18 @@ novirtual class VarGenMixin: if entry is None: return None if self.repl_in_frag_scope(trans.SymTab) == 0: return None if entry.Kind == GenTypes.REPL_KIND_UNTYPED: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 尚未赋值(未定型),无法取址(c.Addr)", "NameError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: session variable '{name}' has not been assigned yet (untyped), cannot take its address (c.Addr)", "NameError") return None pool: memhub.MemBuddy* = trans.Pool slot_ty: mlirlite.LLVMType* = self.repl_slot_ty(pool, entry) if slot_ty is None: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的类型在当前片段不可用(跨片段类型可见性属 M4)", "NameError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: the type of session variable '{name}' is not available in the current snippet (cross-snippet type visibility belongs to M4)", "NameError") return None ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node) if ctx_val is None: return None slot: mlirlite.Value* = self.repl_slot_ptr(pool, trans._cur_builder, ctx_val, entry.Offset, slot_ty) if slot is None: - self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话槽地址生成失败", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(node, "REPL: failed to generate the session slot address", "InternalCompilerError") return None # The value is inlined in the slot (no boxing indirection), so the slot address is the value address return slot @@ -965,22 +965,22 @@ novirtual class VarGenMixin: builder: mlirlite.IRBuilder* = trans._cur_builder slot_ty: mlirlite.LLVMType* = self.repl_slot_ty(pool, entry) if slot_ty is None: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{entry.Name}' 的槽类型不可用" f"(类型在当前片段不可解析,或结构体值体积超出槽容量)", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: the slot type of session variable '{entry.Name}' is not available" f" (the type is unresolvable in the current snippet, or the struct value exceeds the slot capacity)", "TypeError") return 1 store_val: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, slot_ty, node, trans) if store_val is None: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{entry.Name}' 无法把右侧值转换为" f" {self.repl_tag_label(entry.TyTag, entry.Bits)}", "CastError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: cannot convert the right-hand value of session variable '{entry.Name}' to" f" {self.repl_tag_label(entry.TyTag, entry.Bits)}", "CastError") return 1 if self.Gen.ExprGenBase.is_ptr_type(slot_ty) != 0 and store_val.Ty is not None and self.Gen.ExprGenBase.is_ptr_type(store_val.Ty) != 0 and self.Gen.AssignGen._stg_ty_equal(pool, store_val.Ty, slot_ty) == 0: # Pointer same-typing (the slot type and the RHS pointer may be different type instances but the same width). # Skip when types are equal (including both i8*) - LLVM rejects same-type bitcast. store_val = mlirlite.build_bitcast(builder, store_val, slot_ty) if store_val is None: - self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话槽指针同型化失败", "CastError") + self.Gen.TypeGenErr.fatal_error(node, "REPL: failed to unify the type of the session slot pointer", "CastError") return 1 slot: mlirlite.Value* = self.repl_slot_ptr(pool, builder, ctx_val, entry.Offset, slot_ty) if slot is None: - self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话槽写入失败", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(node, "REPL: failed to write the session slot", "InternalCompilerError") return 1 mlirlite.build_store(builder, store_val, slot) self.repl_emit_result(trans, ctx_val, store_val, entry.TyTag, entry.Bits, node) @@ -994,7 +994,7 @@ novirtual class VarGenMixin: if entry is None: return 0 if self.repl_in_frag_entry_scope(trans) == 0: return 0 if rhs_val.Ty is None: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的赋值右侧类型未知", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: the right-hand type of the assignment to session variable '{name}' is unknown", "TypeError") return 1 if self.repl_seal(trans, entry, rhs_val.Ty, rhs_node) != 0: return 1 ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node) @@ -1012,14 +1012,14 @@ novirtual class VarGenMixin: pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder if annot_node is None: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的注解缺失", "SyntaxError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: session variable '{name}' is missing an annotation", "SyntaxError") return 1 # Same rule as ordinary AnnAssign: pre-register the generic specialization first so list[X] does not # degrade to a bare base class (a bare list* makes later .get() misdispatch and truncate pointers). self.Gen.AssignGen._prespecialize_generic_annotation(trans, pool, annot_node) annot_ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, annot_node, trans._imported_modules, trans._from_imports, trans, 0) if annot_ty is None: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的类型注解解析失败" f"(片段无 import;仅内建名 int/str/bytes/bool/float/double/char 等可解析)", "NameError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: failed to resolve the type annotation of session variable '{name}'" f" (the snippet has no import; only built-in names such as int/str/bytes/bool/float/double/char can be resolved)", "NameError") return 1 if self.repl_seal(trans, entry, annot_ty, node) != 0: return 1 if value_node is None: @@ -1033,7 +1033,7 @@ novirtual class VarGenMixin: trans.CurAssignAnnot = None trans.CurAssignNode = None if rhs_val is None: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的初值翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: failed to translate the initial value of session variable '{name}'", "TypeError") return 1 ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node) if ctx_val is None: return 1 @@ -1050,17 +1050,17 @@ novirtual class VarGenMixin: pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder if entry.TyTag == GenTypes.REPL_TY_STRUCT: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 是结构体值,不支持增强赋值", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: session variable '{name}' is a struct value, augmented assignment is not supported", "TypeError") return 1 cur_val: mlirlite.Value* = self.repl_try_read(trans, name, node) if cur_val is None: return 1 rhs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, rhs_node, None, 0, trans) if rhs_val is None: - self.Gen.TypeGenErr.fatal_error(node, "REPL: 增强赋值右侧翻译失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, "REPL: failed to translate the right-hand side of the augmented assignment", "TypeError") return 1 result: mlirlite.Value* = self.Gen.AssignGen._apply_aug_op(pool, builder, op, cur_val, rhs_val, node, trans, node) if result is None: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的增强赋值运算失败 op={op}", "TypeError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: augmented assignment on session variable '{name}' failed op={op}", "TypeError") return 1 # Write back to the slot (reuses the assignment path: typing already exists, so only convert and store) return self.repl_try_assign(trans, name, result, node, node) @@ -1073,14 +1073,14 @@ novirtual class VarGenMixin: builder: mlirlite.IRBuilder* = trans._cur_builder val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, value_node, None, 0, trans) if val is None or val.Ty is None: - self.Gen.TypeGenErr.fatal_error(value_node, "REPL: 表达式片段求值失败", "TypeError") + self.Gen.TypeGenErr.fatal_error(value_node, "REPL: failed to evaluate the expression snippet", "TypeError") return 1 ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, value_node) if ctx_val is None: return 1 # Type classification uses the host's scratch entry (occupies no session slot, not in the table); reset to untyped each time sh: GenTypes.ReplVarEntry* = trans.ReplCtx.Scratch if sh is None: - self.Gen.TypeGenErr.fatal_error(value_node, "REPL: 会话缺少影子条目(宿主未初始化)", "InternalCompilerError") + self.Gen.TypeGenErr.fatal_error(value_node, "REPL: session is missing the shadow entry (host not initialized)", "InternalCompilerError") return 1 sh.Kind = GenTypes.REPL_KIND_UNTYPED sh.TyTag = 0 diff --git a/App/lib/core/IncludesScanner.vp b/App/lib/core/IncludesScanner.vp index 5b0d310..ee450b4 100644 --- a/App/lib/core/IncludesScanner.vp +++ b/App/lib/core/IncludesScanner.vp @@ -232,14 +232,14 @@ def scan_directory_recursive(pool: memhub.MemBuddy*, root_dir: str, rel_prefix: sha1: str = compute_file_sha1(pool, full_path) if sha1 is not None: add_file_entry(result, pool, full_path, rel_path, sha1, inc_dir) - VLogger.debug(f"扫描: {rel_path} -> {sha1}", "scan") - else: VLogger.warning(f"SHA1 计算失败: {full_path}", "scan") + VLogger.debug(f"scan: {rel_path} -> {sha1}", "scan") + else: VLogger.warning(f"SHA1 computation failed: {full_path}", "scan") # continue to the next file if win32file.FindNextFileA(handle, find_data) == 0: break win32file.FindClose(handle) - if subdir_failed > 0: VLogger.error(f"子目录扫描失败 {subdir_failed} 个", "scan") + if subdir_failed > 0: VLogger.error(f"subdirectory scan failed for {subdir_failed} entries", "scan") return 0 @@ -263,7 +263,7 @@ def scan_includes(pool: memhub.MemBuddy*, includes_dirs: str) -> ScanResult*: d_len: sizet = d_i - d_start if d_len == 0: continue dir_buf: bytes = stdlib.malloc(d_len + 1) - if dir_buf is None: VLogger.error("includes 目录分配失败,终止扫描", "scan") + if dir_buf is None: VLogger.error("failed to allocate the includes directory; aborting scan", "scan") string.strncpy(dir_buf, includes_dirs + d_start, d_len) dir_buf[d_len] = '\0' scan_directory_recursive(pool, dir_buf, None, result, dir_buf) diff --git a/App/lib/core/Repl.vp b/App/lib/core/Repl.vp index 969cd44..d848103 100644 --- a/App/lib/core/Repl.vp +++ b/App/lib/core/Repl.vp @@ -171,7 +171,7 @@ def ReplFindProject(Out: bytes, Cap: int, Diag: bytes, DiagCap: int) -> int: stdlib.free(c1) stdlib.free(c2) return 1 - else: string.strcpy(c1, "(GetCurrentDirectoryA 失败)") + else: string.strcpy(c1, "(GetCurrentDirectoryA failed)") # 2) exe-dir/repl.vpj (GetModuleFileNameA(NULL) returns our own full path). n_exe: ULONG = w32file.GetModuleFileNameA(None, c2, ULONG(Cap)) if n_exe > 0: @@ -197,9 +197,9 @@ def ReplFindProject(Out: bytes, Cap: int, Diag: bytes, DiagCap: int) -> int: stdlib.free(c1) stdlib.free(c2) return 1 - else: string.strcpy(c2, "(GetModuleFileNameA 失败)") + else: string.strcpy(c2, "(GetModuleFileNameA failed)") # Not found in either place: emit diagnostics (needs --project + both searched paths). - viperlib.snprintf(Diag, DiagCap, " 已查找(1): %s\n" " 已查找(2): %s\n" " 需要 --project: 未找到 repl.vpj 时 REPL 拿不到工程配置," "请用 --project 指定\n" " 模板位置: 仓库 TransPyV/repl.vpj;拷到 TransPyV.exe 同目录" "或当前工作目录即可被自动找到\n", c1, c2) + viperlib.snprintf(Diag, DiagCap, " Searched(1): %s\n" " Searched(2): %s\n" " --project needed: without repl.vpj the REPL cannot get the project config; " "specify it with --project \n" " Template location: TransPyV/repl.vpj in the repo; copy it next to TransPyV.exe" "or into the current working directory to be found automatically\n", c1, c2) stdlib.free(c1) stdlib.free(c2) return 0 @@ -484,7 +484,7 @@ def _repl_echo_result(frag_name: str, res: GenTypes.ReplResult*) -> int: # REPL_RES_OBJ: result_a != 0 means a non-string pointer (print address); result_a == 0 # means an inline struct value (no address; type name needs the cross-fragment table, M4). if res.A == 0: - stdio.printf("%s => \n", frag_name) + stdio.printf("%s => \n", frag_name) return 0 stdio.printf("%s => \n", frag_name, res.A) return 0 @@ -699,7 +699,7 @@ def ReplInitIncludesClasses(mb: memhub.MemBuddy*, sr: IncludesScanner.ScanResult budget_hit = 1 break if GenApi.get_struct_count() >= _REPL_INC_CLS_STRUCT_GUARD: - stdio.printf("includes 类注册: 结构体表已达 %d 条(上限附近)," "停止注册;未注册的类在会话里不可用(import 其模块" "仍可按需注册)\n", GenApi.get_struct_count()) + stdio.printf("includes class registration: struct table reached %d entries (near the limit); " "stopping registration; unregistered classes are unavailable in the session (importing their module " "can still register on demand)\n", GenApi.get_struct_count()) stdio.fflush(None) return 0 ent: IncludesScanner.FileEntry* = IncludesScanner.FileEntry*(uint64(sr.Entries) + uint64(i) * uint64(es)) @@ -719,7 +719,7 @@ def ReplInitIncludesClasses(mb: memhub.MemBuddy*, sr: IncludesScanner.ScanResult # are unavailable, but the session continues (import degrades the same way). ReplIncClsMissing += 1 if warn_left > 0: - stdio.printf("includes 类注册: 模块 %s 无 .vpi 存根 —— 其类在" "会话中不可用(不影响其它模块;先按 project.vpj " "构建一次宿主可生成全部存根)\n", ent.Sha1) + stdio.printf("includes class registration: module %s has no .vpi stub -- its classes are " "unavailable in the session (other modules unaffected; build the host once with project.vpj " "to generate all stubs)\n", ent.Sha1) warn_left -= 1 else: warn_dropped += 1 stdlib.free(vpi_path) @@ -735,7 +735,7 @@ def ReplInitIncludesClasses(mb: memhub.MemBuddy*, sr: IncludesScanner.ScanResult if rc_m != 0: ReplIncClsFail += 1 if warn_left > 0: - stdio.printf("includes 类注册: 模块 %d 的 .vpi 注入中断" "(其类可能不完整;会话继续)\n", i) + stdio.printf("includes class registration: injection of module %d's .vpi interrupted " "(its classes may be incomplete; session continues)\n", i) warn_left -= 1 else: warn_dropped += 1 mb.reset_to(vm) @@ -748,7 +748,7 @@ def ReplInitIncludesClasses(mb: memhub.MemBuddy*, sr: IncludesScanner.ScanResult else: ReplIncClsFail += 1 if warn_left > 0: - stdio.printf("includes 类注册: 模块 %s 的 .vpi 注入失败" "(该模块的类不完整/不可用;会话继续)\n", ent.Sha1) + stdio.printf("includes class registration: injection of module %s's .vpi failed " "(that module's classes are incomplete/unavailable; session continues)\n", ent.Sha1) warn_left -= 1 else: warn_dropped += 1 stdlib.free(vpi_path) @@ -760,9 +760,9 @@ def ReplInitIncludesClasses(mb: memhub.MemBuddy*, sr: IncludesScanner.ScanResult si: int for si in range(n_mod): if int(st[si]) == 0: skip_cnt += 1 - stdio.printf("includes 类: 已注册 %d 个模块的 vpi 类(失败 %d,缺存根 %d," "未尝试/待重试 %d,省略告警 %d)\n", ReplIncClsMods, ReplIncClsFail, ReplIncClsMissing, skip_cnt, warn_dropped) + stdio.printf("includes classes: registered vpi classes for %d modules (failed %d, missing stub %d, " "not attempted/to retry %d, warnings dropped %d)\n", ReplIncClsMods, ReplIncClsFail, ReplIncClsMissing, skip_cnt, warn_dropped) if budget_hit != 0: - stdio.printf("includes 类: 启动预算 %d ms 用尽,已停止启动期注册(剩余 %d 个" "模块的类在会话里不可用;片段 `import` 该模块时仍按需注册)\n", _REPL_INC_CLS_BUDGET_MS, skip_cnt) + stdio.printf("includes classes: startup budget of %d ms exhausted, stopped startup registration (classes of the remaining %d " "modules are unavailable in the session; a fragment that `import`s such a module still registers on demand)\n", _REPL_INC_CLS_BUDGET_MS, skip_cnt) stdio.fflush(None) return 0 @@ -1010,37 +1010,37 @@ def ReplInitIncludes(mb: memhub.MemBuddy*) -> int: if mb is None: return 1 inc_dirs: str = Config.IncludesDirs if inc_dirs is None or string.strlen(inc_dirs) == 0: - stdio.printf("REPL: 工程未配置 includes 目录(project.vpj 的 includes)," "跳过 includes 初始化;import includes 模块会报未注册 SHA1\n") + stdio.printf("REPL: project has no includes dir configured (project.vpj's includes); " "skipping includes init; importing includes modules will report an unregistered SHA1\n") return 1 # .vpi dir matches the fragment side: prefer the project temp dir, else the session dir. vpi_dir: str = Config.TempDir if vpi_dir is None: vpi_dir = ReplTmpDir if vpi_dir is None: - stdio.printf("REPL: 无可用 .vpi 目录(Config.TempDir 与会话目录均为空)," "跳过 includes 初始化\n") + stdio.printf("REPL: no usable .vpi dir (both Config.TempDir and the session dir are empty); " "skipping includes init\n") return 1 # 1) Scan includes (no reachability: REPL has no SourceDir/deps graph, so scan all). t0: uint64 = win32base.GetTickCount64() sr: IncludesScanner.ScanResult* = IncludesScanner.scan_includes(mb, inc_dirs) if sr is None: - stdio.printf("REPL: includes 扫描失败(目录: %s);" "import includes 模块会报未注册 SHA1\n", inc_dirs) + stdio.printf("REPL: includes scan failed (dir: %s); " "importing includes modules will report an unregistered SHA1\n", inc_dirs) return 1 # 2) Register "module -> SHA1" (same StubMerger global table batch consumers use). n: int = StubMergerStore.PopulateSha1MapStore(sr) ReplIncMs = int(win32base.GetTickCount64() - t0) if n <= 0: - stdio.printf("REPL: includes 扫描未注册任何模块(目录: %s):" "请检查 includes 路径与 .vp 文件\n", inc_dirs) + stdio.printf("REPL: includes scan registered no modules (dir: %s): " "check the includes path and the .vp files\n", inc_dirs) return 1 ReplIncMods = n # 3) Pre-generate .vpi stubs (count failures, do not abort the session). _repl_gen_includes_vpi(mb, sr, vpi_dir) - stdio.printf("includes: 已注册 %d 个模块(扫描耗时 %d ms);" "存根 新生成 %d / 复用 %d / 失败 %d\n", n, ReplIncMs, ReplIncVpiNew, ReplIncVpiReuse, ReplIncVpiFail) + stdio.printf("includes: registered %d modules (scan took %d ms); " "stubs new %d / reused %d / failed %d\n", n, ReplIncMs, ReplIncVpiNew, ReplIncVpiReuse, ReplIncVpiFail) # 3'') Register session generic templates for real: reuse includes sources to register # generic class templates (list/dict/Vector...) so annotations like list[...] specialize. cur_file_saved: str = GenApi.get_current_file() n_gen_tpl: int = Phase1Scan._PreRegisterAllGenericTemplates(mb, sr) if cur_file_saved is not None: GenApi.set_current_file_type(cur_file_saved) if n_gen_tpl <= 0: - stdio.printf("includes 泛型模板: 0 个 —— 注解里的 list[...]/dict[...] 只能按" "\"仅类型\"占位解析(元素布局与方法不可用)\n") + stdio.printf("includes generic templates: 0 -- list[...]/dict[...] in annotations can only be parsed as " "\"type-only\" placeholders (element layout and methods unavailable)\n") # 3') M4.2: enable stub-layout recovery so vpi injection verifies and registers includes # class layouts/vtable indices; also reset the generic-owner table for re-registration. StubMergerStore.ResetGenericOwners() @@ -1118,15 +1118,15 @@ def _repl_lift_add_name(name: str) -> int: pfx: str = GenTypes.REPL_ENTRY_PREFIX pl: int = int(string.strlen(pfx)) if string.strncmp(name, pfx, sizet(pl)) == 0: - stdio.printf("M3: 会话函数名不能以保留前缀 '%s' 开头:%s\n", pfx, name) + stdio.printf("M3: session function name cannot start with the reserved prefix '%s': %s\n", pfx, name) return 1 i: int for i in range(ReplLiftNameCount): if string.strcmp(ReplLiftNames + i * _REPL_FN_NAME_MAX, name) == 0: - stdio.printf("M3: 同一片段内重复定义会话函数 '%s'(请只定义一次)\n", name) + stdio.printf("M3: session function '%s' defined twice in the same fragment (define it only once)\n", name) return 1 if ReplLiftNameCount >= _REPL_LIFT_MAX: - stdio.printf("M3: 单个片段最多提升 %d 个会话函数(本片段已提升 %d 个)\n", _REPL_LIFT_MAX, ReplLiftNameCount) + stdio.printf("M3: a fragment can lift at most %d session functions (this fragment lifted %d)\n", _REPL_LIFT_MAX, ReplLiftNameCount) return 1 string.strcpy(ReplLiftNames + ReplLiftNameCount * _REPL_FN_NAME_MAX, name) ReplLiftNameCount += 1 @@ -1149,10 +1149,10 @@ def _repl_lift_def_header(line: bytes, n: int, name_out: bytes, name_cap: int) - p += 1 nlen: int = p - ns if nlen <= 0: - stdio.printf("M3: def 头缺少函数名:%s\n", _repl_show_line(line, n)) + stdio.printf("M3: def header is missing the function name: %s\n", _repl_show_line(line, n)) return 1 if nlen >= name_cap: - stdio.printf("M3: 会话函数名过长(上限 %d 字节):%s\n", name_cap - 1, _repl_show_line(line, n)) + stdio.printf("M3: session function name too long (limit %d bytes): %s\n", name_cap - 1, _repl_show_line(line, n)) return 1 string.memcpy(name_out, line + ns, sizet(nlen)) name_out[nlen] = 0 @@ -1168,10 +1168,10 @@ def _repl_lift_def_header(line: bytes, n: int, name_out: bytes, name_cap: int) - break p += 1 if d != 0: - stdio.printf("M3: def 头的泛型参数方括号不闭合:%s\n", _repl_show_line(line, n)) + stdio.printf("M3: unclosed generic-parameter bracket in def header: %s\n", _repl_show_line(line, n)) return 1 if p >= n or line[p] != '(': - stdio.printf("M3: def 头在函数名之后缺少 '(':%s\n", _repl_show_line(line, n)) + stdio.printf("M3: def header is missing '(' after the function name: %s\n", _repl_show_line(line, n)) return 1 lp: int = p # Matching ')'. @@ -1188,7 +1188,7 @@ def _repl_lift_def_header(line: bytes, n: int, name_out: bytes, name_cap: int) - break q += 1 if rp < 0: - stdio.printf("M3: def 头的 ')' 缺失(签名必须写在一行内):%s\n", _repl_show_line(line, n)) + stdio.printf("M3: def header is missing ')' (the signature must be on one line): %s\n", _repl_show_line(line, n)) return 1 # ':' must be on the same line (as must the return annotation). has_colon: int = 0 @@ -1199,7 +1199,7 @@ def _repl_lift_def_header(line: bytes, n: int, name_out: bytes, name_cap: int) - break q2 += 1 if has_colon == 0: - stdio.printf("M3: def 头的 ':' 不在同一行(签名必须写在一行内):%s\n", _repl_show_line(line, n)) + stdio.printf("M3: def header ':' is not on the same line (the signature must be on one line): %s\n", _repl_show_line(line, n)) return 1 # Whether the parameter list is empty. empty: int = 1 @@ -1214,7 +1214,7 @@ def _repl_lift_def_header(line: bytes, n: int, name_out: bytes, name_cap: int) - seg: int = lp + 1 while seg + 12 <= rp: if line[seg] == '_' and string.strncmp(line + seg, GenTypes.REPL_CTX_PARAM, sizet(12)) == 0: - stdio.printf("M3: 会话函数 '%s' 不能自定义 %s 形参" "(提升时自动注入为第一个形参)\n", name_out, GenTypes.REPL_CTX_PARAM) + stdio.printf("M3: session function '%s' cannot declare the %s parameter " "(it is auto-injected as the first parameter when lifting)\n", name_out, GenTypes.REPL_CTX_PARAM) return 1 seg += 1 # Emit: "export " + original header [0,lp] + injection + original header [lp+1,n) + '\n'. @@ -1226,7 +1226,7 @@ def _repl_lift_def_header(line: bytes, n: int, name_out: bytes, name_cap: int) - pos = _repl_cat(ReplLiftBuf, _REPL_LIFT_CAP, pos, line + lp + 1, n - lp - 1) pos = _repl_cat_str(ReplLiftBuf, _REPL_LIFT_CAP, pos, "\n") if pos < 0: - stdio.printf("M3: 提升源码缓冲(%d 字节)不足\n", _REPL_LIFT_CAP) + stdio.printf("M3: lift source buffer too small (%d bytes)\n", _REPL_LIFT_CAP) return 2 return 0 @@ -1259,10 +1259,10 @@ def _repl_split_body(body: bytes) -> int: continue if ind > 0: if need_header != 0: - stdio.printf("M3: 装饰器之后必须紧跟 def 头行:%s\n", _repl_show_line(body + i, n)) + stdio.printf("M3: a def header must immediately follow the decorator: %s\n", _repl_show_line(body + i, n)) return 1 if in_body != 0 and _repl_line_has_kw(body + i, n, ind, "raise") != 0: - stdio.printf("M3: 会话函数 '%s' 的函数体含 raise:%s\n" " M3 不支持跨片段异常传播(raise 会给函数追加 " "__eh_msg_out__/__eh_code_out__ 出参," "而经函数指针的间接调用不会补这些实参)——该片段整体不执行\n", name_buf, _repl_show_line(body + i, n)) + stdio.printf("M3: session function '%s' has raise in its body: %s\n" " M3 does not support cross-fragment exception propagation (raise appends the " "__eh_msg_out__/__eh_code_out__ out params to the function, " "but indirect calls through the function pointer do not pass them) -- the whole fragment is skipped\n", name_buf, _repl_show_line(body + i, n)) return 1 lp1: int = int(string.strlen(ReplLiftBuf)) lp1 = _repl_cat(ReplLiftBuf, _REPL_LIFT_CAP, lp1, body + i, n) @@ -1304,7 +1304,7 @@ def _repl_split_body(body: bytes) -> int: i += n + 1 continue if _repl_line_has_kw(body + i, n, 0, "async") != 0 and _repl_line_has_kw(body + i, n, 6, "def") != 0: - stdio.printf("M3: 不支持 async def 会话函数(协程 ABI 与 M3 签名 token " "不相容,请改写成普通 def):%s\n", _repl_show_line(body + i, n)) + stdio.printf("M3: async def session functions are not supported (coroutine ABI is incompatible with " "the M3 signature token; rewrite as a plain def): %s\n", _repl_show_line(body + i, n)) return 1 pos = _repl_cat_str(ReplSrcBuf, _REPL_FRAG_SRC_CAP, pos, " ") pos = _repl_cat(ReplSrcBuf, _REPL_FRAG_SRC_CAP, pos, body + i, n) @@ -1312,7 +1312,7 @@ def _repl_split_body(body: bytes) -> int: if pos < 0: return 2 i += n + 1 if need_header != 0: - stdio.printf("M3: 装饰器之后缺少 def 头行(片段末尾)\n") + stdio.printf("M3: missing def header after decorator (end of fragment)\n") return 1 ReplWrapPos = pos return 0 @@ -1391,7 +1391,7 @@ def _repl_sig_to_text(tag: int, bits: int, pc: int) -> str: def _repl_precheck_session_funcs(mod: mlirlite.LLVMModule*) -> int: if ReplLiftNameCount <= 0: return 0 if ReplCtxObj is None or ReplCtxObj.FuncTable is None or ReplSigResult is None: - stdio.printf("M3: 会话函数表/签名缓冲未初始化(会话初始化失败)\n") + stdio.printf("M3: session function table/signature buffer not initialized (session init failed)\n") return 1 new_cnt: int = 0 idx: int @@ -1400,22 +1400,22 @@ def _repl_precheck_session_funcs(mod: mlirlite.LLVMModule*) -> int: if nm is None: return 1 rc: int = _repl_model_func_sig(mod, nm, ReplSigResult) if rc == 1: - stdio.printf("M3: 定义片段模型里找不到函数 '%s'(提升未生效?)\n", nm) + stdio.printf("M3: function '%s' not found in the defining fragment's model (lift not effective?)\n", nm) return 1 if rc == 2: - stdio.printf("M3: 会话函数 '%s' 的签名含不受支持的类型 '%s'\n" " M3 支持 void / i1 / i8 / i16 / i32 / i64 / float / double / " "i8*(str、bytes、rawptr);结构体值/数组/多级指针请改用指针参数" "或等 M4\n", nm, ReplSigResult.BadType) + stdio.printf("M3: session function '%s' signature has an unsupported type '%s'\n" " M3 supports void / i1 / i8 / i16 / i32 / i64 / float / double / " "i8* (str, bytes, rawptr); for struct values/arrays/multi-level pointers use pointer params " "or wait for M4\n", nm, ReplSigResult.BadType) return 1 if rc == 3: - stdio.printf("M3: 会话函数 '%s' 的签名含异常出参(%%__eh_msg_out__/" "%%__eh_code_out__)——其函数体含 raise\n" " M3 不支持跨片段异常传播:经函数指针的间接调用不会补这两个实参" "(arity 不匹配);该片段整体不执行\n", nm) + stdio.printf("M3: session function '%s' signature has EH out params (%%__eh_msg_out__/" "%%__eh_code_out__) -- its body contains raise\n" " M3 does not support cross-fragment exception propagation: indirect calls through the function pointer do not pass these two args " "(arity mismatch); the whole fragment is skipped\n", nm) return 1 if rc == 4: - stdio.printf("M3: 会话函数 '%s' 的 define 首形参不是 %s(提升模板与调用约定" "不一致)\n", nm, GenTypes.REPL_CTX_PARAM) + stdio.printf("M3: session function '%s' define's first param is not %s (lift template and calling convention " "disagree)\n", nm, GenTypes.REPL_CTX_PARAM) return 1 if rc == 5: - stdio.printf("M3: 会话函数 '%s' 的形参超过 %d 个\n", nm, GenTypes.REPL_FUNC_PARAM_MAX) + stdio.printf("M3: session function '%s' has more than %d params\n", nm, GenTypes.REPL_FUNC_PARAM_MAX) return 1 if rc != 0: - stdio.printf("M3: 会话函数 '%s' 的签名解析失败(rc=%d)\n", nm, rc) + stdio.printf("M3: failed to parse session function '%s' signature (rc=%d)\n", nm, rc) return 1 old: GenTypes.ReplFuncEntry* = _repl_func_entry_find(nm) if old is None: @@ -1431,10 +1431,10 @@ def _repl_precheck_session_funcs(mod: mlirlite.LLVMModule*) -> int: sig_same = 0 break if sig_same == 0: - stdio.printf("M3: 会话函数 '%s' 重定义签名不一致(旧 %s,新 %s)\n" " M3 允许同签名覆盖(只换地址);换签名会让先前片段里已编好的" "调用点按旧 ABI 调新代码 —— 该片段整体不执行,请换名字\n", nm, _repl_entry_sig_text(old), _repl_sig_to_text(ReplSigResult.RetTag, ReplSigResult.RetBits, ReplSigResult.ParamCount)) + stdio.printf("M3: redefinition of session function '%s' has a different signature (old %s, new %s)\n" " M3 allows a same-signature overwrite (address only); a different signature would make call " "sites already compiled in earlier fragments call new code with the old ABI -- the whole fragment is skipped; use another name\n", nm, _repl_entry_sig_text(old), _repl_sig_to_text(ReplSigResult.RetTag, ReplSigResult.RetBits, ReplSigResult.ParamCount)) return 1 if ReplCtxObj.FuncCount + new_cnt > ReplCtxObj.FuncCap: - stdio.printf("M3: 会话函数已达上限 %d 个(ctx 函数指针槽用尽),本次新增 %d 个;" "请重启会话或减少会话函数\n", ReplCtxObj.FuncCap, new_cnt) + stdio.printf("M3: session function limit of %d reached (ctx function pointer slots exhausted); %d added this time; " "restart the session or use fewer session functions\n", ReplCtxObj.FuncCap, new_cnt) return 1 return 0 @@ -1457,7 +1457,7 @@ def _repl_entry_sig_text(e: GenTypes.ReplFuncEntry*) -> str: def _repl_register_session_funcs(h_lib: win32base.HANDLE, frag_no: int, mod: mlirlite.LLVMModule*) -> int: if ReplLiftNameCount <= 0: return 0 if ReplCtxObj is None or ReplCtxObj.FuncTable is None or ReplCtxBuf is None: - stdio.printf("M3: 会话函数表/ctx 未初始化\n") + stdio.printf("M3: session function table/ctx not initialized\n") return 1 idx: int for idx in range(ReplLiftNameCount): @@ -1467,14 +1467,14 @@ def _repl_register_session_funcs(h_lib: win32base.HANDLE, frag_no: int, mod: mli # and -shared without a DEF file exports all symbols automatically. addr: VOIDPTR = win32base.GetProcAddress(h_lib, nm) if addr is None: - stdio.printf("M3: 会话函数 '%s' 未出现在片段 DLL 的导出表" "(GetProcAddress 返回空;本片段不执行)\n", nm) + stdio.printf("M3: session function '%s' is absent from the fragment DLL's export table " "(GetProcAddress returned null; this fragment is skipped)\n", nm) return 1 ent: GenTypes.ReplFuncEntry* = _repl_func_entry_find(nm) if ent is None: # New entry (signature already validated; re-parse to recover the scratch tokens). rc: int = _repl_model_func_sig(mod, nm, ReplSigResult) if rc != 0: - stdio.printf("M3: 会话函数 '%s' 的签名重新解析失败(rc=%d)\n", nm, rc) + stdio.printf("M3: failed to re-parse session function '%s' signature (rc=%d)\n", nm, rc) return 1 j: int = ReplCtxObj.FuncCount es: sizet = GenTypes.ReplFuncEntry.__sizeof__() @@ -1484,7 +1484,7 @@ def _repl_register_session_funcs(h_lib: win32base.HANDLE, frag_no: int, mod: mli tags_b: bytes = _perm_pool.alloc(GenTypes.REPL_FUNC_PARAM_MAX) bits_b: bytes = _perm_pool.alloc(GenTypes.REPL_FUNC_PARAM_MAX) if nm_c is None or nm_s is None or tags_b is None or bits_b is None: - stdio.printf("M3: 会话函数条目内存分配失败('%s')\n", nm) + stdio.printf("M3: failed to allocate the session function entry ('%s')\n", nm) return 1 string.memset(tags_b, 0, GenTypes.REPL_FUNC_PARAM_MAX) string.memset(bits_b, 0, GenTypes.REPL_FUNC_PARAM_MAX) @@ -1507,7 +1507,7 @@ def _repl_register_session_funcs(h_lib: win32base.HANDLE, frag_no: int, mod: mli sv: ReplFuncSlotView* = ReplFuncSlotView*(uint64(ReplCtxBuf) + uint64(ent.SlotOff)) sv.Addr = addr sv.Reserved = None - stdio.printf("会话函数 %s: 导出符号 %s → ctx 槽 +%d(定义片段 %d,签名 %s)\n", nm, nm, ent.SlotOff, frag_no, _repl_entry_sig_text(ent)) + stdio.printf("session function %s: export symbol %s -> ctx slot +%d (defining fragment %d, signature %s)\n", nm, nm, ent.SlotOff, frag_no, _repl_entry_sig_text(ent)) return 0 @@ -1663,11 +1663,11 @@ def _exec_repl_src(mb: memhub.MemBuddy*, src: str) -> int: el: int = ast.get_parse_err_line() ec: int = ast.get_parse_err_col() em: str = ast.get_parse_err_msg() - if em is None: em = "(未知)" - stdio.printf("ParseError: 第 %d 行第 %d 列: %s\n", el, ec, em) + if em is None: em = "(unknown)" + stdio.printf("ParseError: line %d column %d: %s\n", el, ec, em) return 0 if _count_top_stmts(tree) <= 0: - stdio.printf("已解析: 0 个顶层语句(跳过)\n") + stdio.printf("Parsed: 0 top-level statements (skipping)\n") return 0 # M2/M3 execution path: whole block/line runs as one fragment function body; failures only # print the reason (or longjmp back to the recovery point), never kill the process. @@ -1692,13 +1692,13 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: global ReplSavedCDefineCount, ReplSavedCTypedefCount if mb is None or src is None: return 1 if ReplTmpDir is None or ReplNameBuf is None or ReplSrcBuf is None: - stdio.printf("REPL: 会话缓冲未初始化\n") + stdio.printf("REPL: session buffer not initialized\n") return 1 if ReplSrcPath is None or ReplIrBuf is None or ReplNeedleBuf is None: - stdio.printf("REPL: 会话缓冲未初始化\n") + stdio.printf("REPL: session buffer not initialized\n") return 1 if ReplCtxBuf is None or ReplCtxObj is None or ReplVarTable is None: - stdio.printf("REPL: ctx 会话内存未初始化\n") + stdio.printf("REPL: ctx session memory not initialized\n") return 1 # 0) Re-arm the recovery point and snapshot session table watermarks so a failed fragment's @@ -1726,7 +1726,7 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: # template; multi-line lifts top-level defs. Returns 0=ok/1=rejected/2=buffer full. rc_build: int = _build_frag_src(ReplNameBuf, body) if rc_build == 2: - stdio.printf("片段 %s: 包裹源码装配失败(缓冲 %d 字节不足)\n", ReplNameBuf, _REPL_FRAG_SRC_CAP) + stdio.printf("fragment %s: failed to assemble the wrapped source (buffer too small, %d bytes)\n", ReplNameBuf, _REPL_FRAG_SRC_CAP) return 1 if rc_build != 0: # Lift rule rejection (async def / raise / duplicate / non-single-line signature / own @@ -1773,15 +1773,15 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: el: int = ast.get_parse_err_line() ec: int = ast.get_parse_err_col() em: str = ast.get_parse_err_msg() - if em is None: em = "(未知)" - stdio.printf("片段 %s: 包裹源码解析失败(第 %d 行第 %d 列: %s)\n", ReplNameBuf, el, ec, em) + if em is None: em = "(unknown)" + stdio.printf("fragment %s: failed to parse the wrapped source (line %d column %d: %s)\n", ReplNameBuf, el, ec, em) return 1 # 7) Translate to full module IR. ModuleSha1 = session sha1 (types are "."); # ReplCtx enables REPL mode and is cleared after translation. tr: HandlesTranslator.Translator* = mb.alloc(HandlesTranslator.Translator.__sizeof__()) if tr is None: - stdio.printf("片段 %s: Translator 分配失败\n", ReplNameBuf) + stdio.printf("fragment %s: Translator allocation failed\n", ReplNameBuf) return 1 tr.__before_init__() tr.__init__() @@ -1791,7 +1791,7 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: rc_tr: int = tr.translate(tree) tr.ReplCtx = None if rc_tr != 0: - stdio.printf("片段 %s: 翻译失败\n", ReplNameBuf) + stdio.printf("fragment %s: translation failed\n", ReplNameBuf) return 1 tr.dump_ir(ReplIrBuf, _REPL_IR_CAP, mlirlite.OUTPUT_FULL) @@ -1806,7 +1806,7 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: # the wrapper/calling convention is wrong (or raise added EH params), so abort. viperlib.snprintf(ReplNeedleBuf, _REPL_NEEDLE_CAP, "llvm.func @%s(%%%s: !llvm.ptr) -> i32", ReplNameBuf, GenTypes.REPL_CTX_PARAM) if string.strstr(ReplIrBuf, ReplNeedleBuf) is None: - stdio.printf("片段 %s: 未生成约定的导出函数(期望 `llvm.func @%s(%%__repl_ctx__: !llvm.ptr) -> i32`);" "含 raise 的片段会追加异常出参,M2 不支持\n", ReplNameBuf, ReplNameBuf) + stdio.printf("fragment %s: expected export function was not generated (expected `llvm.func @%s(%%__repl_ctx__: !llvm.ptr) -> i32`); " "fragments with raise append EH out params, which M2 does not support\n", ReplNameBuf, ReplNameBuf) return 1 # 8') Session function signature check (M3), before llc/load: any failure skips the whole @@ -1816,11 +1816,11 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: # 9) Write .ll (reusing BuildPipeline: sliced path + ensure_dir). ir_len: sizet = string.strlen(ReplIrBuf) if BuildPipeline.write_ir_to_file(ReplIrBuf, ir_len, ReplTmpDir, ReplNameBuf) != 0: - stdio.printf("片段 %s: 写 .ll 失败(目录 %s)\n", ReplNameBuf, ReplTmpDir) + stdio.printf("fragment %s: failed to write .ll (dir %s)\n", ReplNameBuf, ReplTmpDir) return 1 ir_path: str = BuildPipeline.build_sliced_path(ReplTmpDir, ReplNameBuf, "ll") if ir_path is None: - stdio.printf("片段 %s: .ll 路径构造失败\n", ReplNameBuf) + stdio.printf("fragment %s: failed to build the .ll path\n", ReplNameBuf) return 1 # 10) llc -> .obj (reusing existing machinery; VLogger.error longjmps on failure). @@ -1831,7 +1831,7 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: if BuildPipeline.compile_ll_to_obj(ir_path, ReplTmpDir, ReplNameBuf, cc_cmd, cc_flags) != 0: # This branch is only reached on compile_ll_to_obj's internal allocation failure (real llc # failures longjmp), so print a note instead of silently returning to the prompt. - stdio.printf("片段 %s: llc 编译 .obj 失败(命令/路径缓冲分配失败,见上方诊断)\n", ReplNameBuf) + stdio.printf("fragment %s: llc failed to compile .obj (command/path buffer allocation failed; see diagnostics above)\n", ReplNameBuf) return 1 # 11) clang++ -shared -> .dll (command shape matches BuildPipeline.link_obj_to_exe; process @@ -1839,19 +1839,19 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: obj_path: str = BuildPipeline.build_sliced_path(ReplTmpDir, ReplNameBuf, "obj") dll_path: str = BuildPipeline.build_sliced_path(ReplTmpDir, ReplNameBuf, "dll") if obj_path is None or dll_path is None: - stdio.printf("片段 %s: .obj/.dll 路径构造失败\n", ReplNameBuf) + stdio.printf("fragment %s: failed to build the .obj/.dll path\n", ReplNameBuf) return 1 linker_cmd: str = Config.LinkerCmd if linker_cmd is None: linker_cmd = "clang++" cmd: bytes = mb.alloc(_REPL_CMD_CAP) if cmd is None: - stdio.printf("片段 %s: 命令行缓冲分配失败\n", ReplNameBuf) + stdio.printf("fragment %s: command-line buffer allocation failed\n", ReplNameBuf) return 1 # Cross-module symbols come from the host exe, so add the host import lib (if any) to the link # line; M4 also adds this fragment's --out-implib and prior fragments' import libs. implib_path: str = mb.alloc(_REPL_PATH_CAP) if implib_path is None: - stdio.printf("片段 %s: import lib 路径缓冲分配失败\n", ReplNameBuf) + stdio.printf("fragment %s: import lib path buffer allocation failed\n", ReplNameBuf) return 1 viperlib.snprintf(implib_path, _REPL_PATH_CAP, "%s.dll.a", dll_path) pos_c: int = _repl_cat_str(cmd, _REPL_CMD_CAP, 0, linker_cmd) @@ -1867,35 +1867,35 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: pos_c = _repl_cat_str(cmd, _REPL_CMD_CAP, pos_c, " -Wl,--out-implib=") pos_c = _repl_cat_str(cmd, _REPL_CMD_CAP, pos_c, implib_path) if pos_c < 0: - stdio.printf("片段 %s: 链接命令行超过 %d 字节(已登记的片段 import lib 共 %d " "个)——本片段不执行;可重启会话减少片段数\n", ReplNameBuf, _REPL_CMD_CAP, ReplFragImplibCount) + stdio.printf("fragment %s: link command line exceeds %d bytes (%d registered fragment import libs " "in total) -- this fragment is skipped; restart the session to reduce the fragment count\n", ReplNameBuf, _REPL_CMD_CAP, ReplFragImplibCount) return 1 link_rc: int = BuildPipeline._run_cmd_wait(cmd) if link_rc != 0: - stdio.printf("片段 %s: 生成 .dll 失败 (exit=%d)\n 命令: %s\n", ReplNameBuf, link_rc, cmd) + stdio.printf("fragment %s: failed to generate .dll (exit=%d)\n command: %s\n", ReplNameBuf, link_rc, cmd) if ReplHostImplib is None: - stdio.printf(" 原因提示: 未找到宿主 import lib(.dll.a)——" "跨模块符号(形如 <16位hex>.<函数名>)无法解析;" "宿主需按 TransPyV/project.vpj 构建(含 -Wl,--export-all-symbols)," "且 .dll.a 与 exe 同目录\n") + stdio.printf(" Hint: host import lib (.dll.a) not found -- " "cross-module symbols (of the form <16-hex>.) cannot be resolved; " "build the host with TransPyV/project.vpj (including -Wl,--export-all-symbols), " "and keep .dll.a in the same dir as the exe\n") else: - stdio.printf(" 原因提示: 若输出含 undefined symbol 且形如 <16位hex>.<名>," "则该符号未被宿主定义/导出(宿主构建时未链入对应 includes 模块);" "若该函数在源码里是 `export def`(CExport,裸名定义)却仍带前缀," "多为 include 存根 .vpi 缺失(见会话开头的 includes 扫描行)\n") + stdio.printf(" Hint: if the output contains undefined symbol of the form <16-hex>., " "that symbol is not defined/exported by the host (the corresponding includes module was not linked when building the host); " "if the function is `export def` in source (CExport, bare-name definition) yet still carries a prefix, " "the include stub .vpi is probably missing (see the includes scan line at session start)\n") return 1 # 11') M4: record this fragment's import lib (if it defined session-prefixed symbols) so later # fragments resolve its class/method symbols; recording failure only warns. if needs_implib != 0: if _is_file(implib_path) != 0 and ReplFragImplibRecord(implib_path) != 0: - stdio.printf("片段 %s: 已登记片段 import lib(后续片段可解析本片段定义的" "类型/方法符号): %s\n", ReplNameBuf, implib_path) + stdio.printf("fragment %s: registered fragment import lib (later fragments can resolve types/method " "symbols defined by this fragment): %s\n", ReplNameBuf, implib_path) else: - stdio.printf("片段 %s: 片段 import lib 未登记(已登记 %d 个,上限 %d;或文件" "缺失)——更晚的片段可能解析不到本片段定义的类型/方法符号\n", ReplNameBuf, ReplFragImplibCount, _REPL_FRAG_IMPLIB_MAX) + stdio.printf("fragment %s: fragment import lib not registered (%d registered, limit %d; or the file " "is missing) -- later fragments may fail to resolve types/method symbols defined here\n", ReplNameBuf, ReplFragImplibCount, _REPL_FRAG_IMPLIB_MAX) # 12) Dynamic load + address lookup (LoadLibraryA/GetProcAddress). h_lib: win32base.HANDLE = win32base.LoadLibraryA(dll_path) if h_lib is None: - stdio.printf("片段 %s: LoadLibraryA 失败: %s\n", ReplNameBuf, dll_path) + stdio.printf("fragment %s: LoadLibraryA failed: %s\n", ReplNameBuf, dll_path) if ReplHostImplib is not None: - stdio.printf(" 原因提示: 片段 DLL 的导入表指向宿主 exe(%s);" "若 GetLastError 是 127(找不到指定过程)/ 加载器 0xC0000139," "多为宿主与该 import lib 非同一次构建产物、或宿主缺该导出;" "进程镜像名(%s)与 import lib 记录名不一致时同样会失败\n", ReplHostImplib, dll_path) + stdio.printf(" Hint: the fragment DLL import table points to the host exe (%s); " "if GetLastError is 127 (procedure not found) / loader 0xC0000139, " "the host and this import lib are usually from different builds, or the host lacks that export; " "it also fails when the process image name (%s) differs from the recorded import lib name\n", ReplHostImplib, dll_path) return 1 fp_addr: VOIDPTR = win32base.GetProcAddress(h_lib, ReplNameBuf) if fp_addr is None: - stdio.printf("片段 %s: GetProcAddress 返回空(导出表中无该符号): %s\n", ReplNameBuf, dll_path) + stdio.printf("fragment %s: GetProcAddress returned null (symbol absent from the export table): %s\n", ReplNameBuf, dll_path) return 1 # 12') Session function registration (M3), before calling the entry so a failure skips this @@ -1917,9 +1917,9 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: # 14) Read back from the ctx result area and echo (the fragment return is only a status code). if _repl_echo_result(ReplNameBuf, head) != 0: - stdio.printf("片段 %s: 结果区读取失败\n", ReplNameBuf) + stdio.printf("fragment %s: failed to read the result area\n", ReplNameBuf) return 1 - if r_rc != 0: stdio.printf("片段 %s: 片段返回非零状态码 %d\n", ReplNameBuf, r_rc) + if r_rc != 0: stdio.printf("fragment %s: fragment returned non-zero status %d\n", ReplNameBuf, r_rc) # 14') M4: on success, merge this fragment's new CDefine/CTypedef entries into the session # baseline; failure paths skip this, so the baseline never holds a failed fragment's leftovers. ReplBaselineCapture() @@ -1932,7 +1932,7 @@ def run(mb: memhub.MemBuddy*) -> int: """M2/M3 REPL: read a line/block, parse, compile to a DLL and call it (session vars via ctx slots), then echo; errors never kill the process.""" global ReplJmpBuf, ReplSavedVarCount, ReplSavedFuncCount, ReplInBlock, ReplBlockLen if mb is None or _perm_pool is None: - stdio.printf("REPL: 需要主池与 PermPool(由 main 注入 _perm_pool)\n") + stdio.printf("REPL: need the main pool and PermPool (main injects _perm_pool)\n") return 1 # Parse tables (keywords/operators) go in PermPool: they are ast module-level globals built @@ -1941,7 +1941,7 @@ def run(mb: memhub.MemBuddy*) -> int: jb: rawptr = _perm_pool.alloc(_REPL_JMPBUF_SIZE) if jb is None: - stdio.printf("REPL: jmp_buf 分配失败\n") + stdio.printf("REPL: jmp_buf allocation failed\n") return 1 # Session-level registration: ReplJmpBuf is re-registered per fragment; the VLogger side is set # once and cleared only on run exit (that is what covers the whole pipeline). @@ -1956,7 +1956,7 @@ def run(mb: memhub.MemBuddy*) -> int: # un-armed jmp_buf would be UB; init is the only stage that must succeed, so exit on failure. rc_init: int = _setjmp(jb, None) if rc_init != 0: - stdio.printf("REPL: 会话初始化中断(诊断见上)—— 无常驻缓冲/ctx,REPL 无法启动\n") + stdio.printf("REPL: session init interrupted (see diagnostics above) -- no resident buffers/ctx, REPL cannot start\n") stdio.fflush(None) ReplJmpBuf = None VLogger.clear_repl_jmpbuf() @@ -1965,7 +1965,7 @@ def run(mb: memhub.MemBuddy*) -> int: # Session init: temp dir + permanent buffers + ctx (all PermPool; see ReplInitSession). if ReplInitSession() != 0: - stdio.printf("REPL: 会话初始化失败(临时目录/常驻缓冲/ctx)\n") + stdio.printf("REPL: session init failed (temp dir/resident buffers/ctx)\n") ReplJmpBuf = None VLogger.clear_repl_jmpbuf() if lg is not None: lg.set_jit_flag(False) @@ -1974,23 +1974,23 @@ def run(mb: memhub.MemBuddy*) -> int: h_in: win32base.HANDLE = w32file.GetStdHandle(w32file.STD_INPUT_HANDLE) line: bytes = stdlib.malloc(_REPL_LINE_CAP) if line is None: - stdio.printf("REPL: 行缓冲分配失败\n") + stdio.printf("REPL: line buffer allocation failed\n") ReplJmpBuf = None VLogger.clear_repl_jmpbuf() if lg is not None: lg.set_jit_flag(False) return 1 - stdio.printf("TransPyV REPL (M2/M3/M4) - 会话变量 + 会话函数(跨片段)+ ctx 回传结果;\n") - stdio.printf(" 支持表达式(1+2)、定义(x = 1 / x: int = 5)、引用(x + 1)、\n") - stdio.printf(" 增强赋值(x += 2)、取址(p = &x)等;空行跳过,Ctrl+Z 或 EOF 退出\n") - stdio.printf(" 多行块:行尾 ':' 进入续行(提示符 ...),空行结束并整块执行一次\n") - stdio.printf(" 跨片段函数:块里顶格的 def 会被提升为片段模块的 export def(裸名导出),\n") - stdio.printf(" 后续片段可直接调用(如 def f(x: int) -> int: 换行 +4 空格 return x + 1);\n") - stdio.printf(" 限制:签名须单行、不支持 async def、函数体内不支持 raise、不支持偏函数\n") - stdio.printf(" 跨片段类型(M4):块里的 class 会被翻译进会话(类型名 %s.<类名>),\n", ReplSessionSha1) - stdio.printf(" 后续片段可实例化、读写字段、调用方法;import 的 includes 模块\n") - stdio.printf(" 其类同样注册进会话(缺 .vpi 存根时该模块的类不可用,会话继续)\n") - stdio.printf(" 片段临时目录: %s\n", ReplTmpDir) + stdio.printf("TransPyV REPL (M2/M3/M4) - session variables + session functions (cross-fragment) + ctx result echo;\n") + stdio.printf(" Supports expressions (1+2), definitions (x = 1 / x: int = 5), references (x + 1),\n") + stdio.printf(" augmented assignment (x += 2), address-of (p = &x), etc.; blank lines are skipped, Ctrl+Z or EOF exits\n") + stdio.printf(" Multi-line block: a trailing ':' enters continuation (prompt ...), a blank line ends it and runs the block once\n") + stdio.printf(" Cross-fragment functions: a top-level def in a block is lifted to the fragment module's export def (bare-name export),\n") + stdio.printf(" later fragments can call it directly (e.g. def f(x: int) -> int: newline + 4 spaces return x + 1);\n") + stdio.printf(" Restrictions: signature must be one line, async def is unsupported, raise in the body is unsupported, partial functions are unsupported\n") + stdio.printf(" Cross-fragment types (M4): a class in a block is translated into the session (type name %s.),\n", ReplSessionSha1) + stdio.printf(" later fragments can instantiate it, read/write fields and call methods; imported includes modules\n") + stdio.printf(" have their classes registered into the session too (when the .vpi stub is missing that module's classes are unavailable; the session continues)\n") + stdio.printf(" Fragment temp dir: %s\n", ReplTmpDir) stdio.fflush(None) # === Session-level includes init (once; all failures only degrade includes classes) === @@ -1998,7 +1998,7 @@ def run(mb: memhub.MemBuddy*) -> int: inc_mark: sizet = mb.mark() rc_inc: int = _setjmp(jb, None) if rc_inc != 0: - stdio.printf("REPL: includes 初始化中断(已注册 %d 个模块、存根 %d 个):" "import includes 模块可能失败,其余片段不受影响\n", ReplIncMods, ReplIncVpiNew) + stdio.printf("REPL: includes init interrupted (%d modules registered, %d stubs): " "importing includes modules may fail; other fragments are unaffected\n", ReplIncMods, ReplIncVpiNew) mb.reset_to(inc_mark) else: # Scan results/registry live in stdlib, so mb allocations can be reclaimed after this call, @@ -2009,7 +2009,7 @@ def run(mb: memhub.MemBuddy*) -> int: # calling frame); this puts the finish step and read loop back under this frame's point. rc_arm: int = _setjmp(jb, None) if rc_arm != 0: - stdio.printf("REPL: includes 类布局收尾中断(诊断见上):布局注册可能不完整," "会话继续\n") + stdio.printf("REPL: includes class layout finish interrupted (see diagnostics above): layout registration may be incomplete; " "session continues\n") else: # Finish: converge classes whose parents became ready in later passes + per-class warnings. # Done after re-arming so any longjmp lands in this frame (the dead-frame issue above). @@ -2021,14 +2021,14 @@ def run(mb: memhub.MemBuddy*) -> int: # === Host export symbols: locate the host exe import lib === # If found, fragment link lines include it; otherwise warn and continue (calls may fail to link). if ReplFindHostImplib() != 0: - stdio.printf("宿主符号导入库: %s(片段可跨模块调用 includes 函数/全局)\n", ReplHostImplib) + stdio.printf("Host symbol import lib: %s (fragments can call includes functions/globals across modules)\n", ReplHostImplib) else: - stdio.printf("宿主符号导入库: 未找到 .dll.a;片段调用 includes 模块级" "函数会在链接期报 undefined symbol(会话不终止)。请用 " "TransPyV/project.vpj(已声明 -Wl,--export-all-symbols)构建宿主," "并让 exe 与 .dll.a 同目录\n") + stdio.printf("Host symbol import lib: .dll.a not found; fragment calls to includes module-level " "functions will report undefined symbol at link time (the session does not terminate). Build the host with " "TransPyV/project.vpj (which declares -Wl,--export-all-symbols), " "and keep the exe and .dll.a in the same dir\n") stdio.fflush(None) # === Read loop: single-line fragments + block continuation === # All init failures were absorbed, so the prompt is guaranteed to appear from here on. - stdio.printf("REPL: 初始化完成,进入读行循环\n") + stdio.printf("REPL: init complete, entering the read loop\n") stdio.fflush(None) # Block state is zeroed after every block end/failure/EOF/overflow, so a stale block cannot # pollute the next line (the next append overwrites from index 0). @@ -2080,7 +2080,7 @@ def run(mb: memhub.MemBuddy*) -> int: continue # In continuation: every line is buffered; no state flips on ':' and no indent analysis. if _block_append(line, n) != 0: - stdio.printf("REPL: 块输入超过块缓冲上界 %d 字节:本块已丢弃," "回到 >>> 继续(可减少块体积或分块执行)\n", _REPL_BLOCK_CAP) + stdio.printf("REPL: block input exceeds the block buffer cap of %d bytes: this block was discarded, " "returning to >>> (reduce the block size or run it in chunks)\n", _REPL_BLOCK_CAP) ReplInBlock = 0 ReplBlockLen = 0 mb.reset_to(mark) diff --git a/App/lib/core/VLogger.vp b/App/lib/core/VLogger.vp index 147455c..85c7436 100644 --- a/App/lib/core/VLogger.vp +++ b/App/lib/core/VLogger.vp @@ -158,26 +158,26 @@ novirtual class Logger: def compile_error(self, msg: str, file: str = "", line: int = 0) -> int: """Format a compile error with a red-background header, location and message.""" self._set_color(BACKGROUND_RED | FOREGROUND_WHITE | FOREGROUND_INTENSITY) - stdio.printf(" 编译错误 ") + stdio.printf(" COMPILE ERROR ") self._set_color(FOREGROUND_RED | FOREGROUND_INTENSITY) stdio.printf("\n") if file is not None: - if file[0] != 0 and line > 0: stdio.printf(" 位置: %s:%d\n", file, line) - elif file[0] != 0: stdio.printf(" 文件: %s\n", file) - stdio.printf(" 错误: %s\n", msg) + if file[0] != 0 and line > 0: stdio.printf(" location: %s:%d\n", file, line) + elif file[0] != 0: stdio.printf(" file: %s\n", file) + stdio.printf(" error: %s\n", msg) self._reset_color() return 0 def compile_warning(self, msg: str, file: str = "", line: int = 0) -> int: """Format a compile warning with a yellow background, location and message.""" self._set_color(BACKGROUND_RED | BACKGROUND_GREEN | FOREGROUND_INTENSITY) - stdio.printf(" 编译警告 ") + stdio.printf(" COMPILE WARNING ") self._set_color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY) stdio.printf("\n") if file is not None: - if file[0] != 0 and line > 0: stdio.printf(" 位置: %s:%d\n", file, line) - elif file[0] != 0: stdio.printf(" 文件: %s\n", file) - stdio.printf(" 警告: %s\n", msg) + if file[0] != 0 and line > 0: stdio.printf(" location: %s:%d\n", file, line) + elif file[0] != 0: stdio.printf(" file: %s\n", file) + stdio.printf(" warning: %s\n", msg) self._reset_color() return 0 diff --git a/App/lib/core/builtin/ViperBuild.vp b/App/lib/core/builtin/ViperBuild.vp index 7eb0b33..b965ac5 100644 --- a/App/lib/core/builtin/ViperBuild.vp +++ b/App/lib/core/builtin/ViperBuild.vp @@ -473,16 +473,16 @@ def _ApplyCtorArgs(cl: ast.Call*) -> int: if cl.args is not None: an: sizet = cl.args.__len__() if an > 2: - VLogger.error("viperbuild: Project(...) 位置参数最多 2 个(name, version)", "viperbuild") + VLogger.error("viperbuild: Project(...) accepts at most 2 positional arguments (name, version)", "viperbuild") return 1 if an >= 1: if _EvalStr(cl.args.get(0)) == 0: - VLogger.error("viperbuild: Project(name) 必须是字符串常量", "viperbuild") + VLogger.error("viperbuild: Project(name) must be a string constant", "viperbuild") return 1 _c_name = _DupStd(_g_out_str) if an >= 2: if _EvalStr(cl.args.get(1)) == 0: - VLogger.error("viperbuild: Project(version) 必须是字符串常量", "viperbuild") + VLogger.error("viperbuild: Project(version) must be a string constant", "viperbuild") return 1 _c_version = _DupStd(_g_out_str) if cl.keywords is None: return 0 @@ -492,16 +492,16 @@ def _ApplyCtorArgs(cl: ast.Call*) -> int: if kw is not None and kw.arg is not None and kw.value is not None: if string.strcmp(kw.arg, "name") == 0: if _EvalStr(kw.value) == 0: - VLogger.error("viperbuild: Project(name=...) 必须是字符串常量", "viperbuild") + VLogger.error("viperbuild: Project(name=...) must be a string constant", "viperbuild") return 1 _c_name = _DupStd(_g_out_str) elif string.strcmp(kw.arg, "version") == 0: if _EvalStr(kw.value) == 0: - VLogger.error("viperbuild: Project(version=...) 必须是字符串常量", "viperbuild") + VLogger.error("viperbuild: Project(version=...) must be a string constant", "viperbuild") return 1 _c_version = _DupStd(_g_out_str) else: - VLogger.error(f"viperbuild: Project(...) 不支持的关键字 {kw.arg}", "viperbuild") + VLogger.error(f"viperbuild: unsupported keyword {kw.arg} for Project(...)", "viperbuild") return 1 return 0 @@ -514,31 +514,31 @@ def _SetField(fname: str, vnode: ast.AST*) -> int: # ---- String fields ---- if string.strcmp(fname, "source") == 0: if _EvalStr(vnode) == 0: - VLogger.error("viperbuild: source 必须是字符串常量表达式", "viperbuild") + VLogger.error("viperbuild: source must be a string constant expression", "viperbuild") return 1 _c_source = _DupStd(_g_out_str) return 0 if string.strcmp(fname, "buildroot") == 0: if _EvalStr(vnode) == 0: - VLogger.error("viperbuild: buildroot 必须是字符串常量表达式", "viperbuild") + VLogger.error("viperbuild: buildroot must be a string constant expression", "viperbuild") return 1 _c_buildroot = _DupStd(_g_out_str) return 0 if string.strcmp(fname, "output") == 0: if _EvalStr(vnode) == 0: - VLogger.error("viperbuild: output 必须是字符串常量表达式", "viperbuild") + VLogger.error("viperbuild: output must be a string constant expression", "viperbuild") return 1 _c_output = _DupStd(_g_out_str) return 0 if string.strcmp(fname, "name") == 0: if _EvalStr(vnode) == 0: - VLogger.error("viperbuild: name 必须是字符串常量表达式", "viperbuild") + VLogger.error("viperbuild: name must be a string constant expression", "viperbuild") return 1 _c_name = _DupStd(_g_out_str) return 0 if string.strcmp(fname, "version") == 0: if _EvalStr(vnode) == 0: - VLogger.error("viperbuild: version 必须是字符串常量表达式", "viperbuild") + VLogger.error("viperbuild: version must be a string constant expression", "viperbuild") return 1 _c_version = _DupStd(_g_out_str) return 0 @@ -548,7 +548,7 @@ def _SetField(fname: str, vnode: ast.AST*) -> int: if string.strcmp(fname, "linker") == 0: return _SetListField(2, vnode) if string.strcmp(fname, "static_libs") == 0: return _SetListField(3, vnode) if string.strcmp(fname, "dynamic_libs") == 0: return _SetListField(4, vnode) - VLogger.error(f"viperbuild: 未知字段 proj.{fname}", "viperbuild") + VLogger.error(f"viperbuild: unknown field proj.{fname}", "viperbuild") return 1 @@ -559,7 +559,7 @@ def _SetListField(slot: int, vnode: ast.AST*) -> int: tmp: list[str]* = list[str](_scratch, 8) if tmp is None: return 1 if _EvalList(vnode, tmp) == 0: - VLogger.error("viperbuild: 列表字段必须是 list[str] 常量表达式", "viperbuild") + VLogger.error("viperbuild: list fields must be list[str] constant expressions", "viperbuild") return 1 joined: str = _JoinSpace(tmp) if slot == 0: _c_includes = joined @@ -595,12 +595,12 @@ def _HandleNameBind(tgt: ast.Name*, vnode: ast.AST*) -> int: if tgt is None or vnode is None or tgt.id is None: return 0 # Reading a Project macro object on the RHS is fatal (reading forbidden) if _IsProjRef(vnode) != 0: - VLogger.error(f"viperbuild: 禁止读取 Project 宏对象({tgt.id} = proj ...)", "viperbuild") + VLogger.error(f"viperbuild: reading the Project macro object is forbidden ({tgt.id} = proj ...)", "viperbuild") return 1 # Project instance binding if _IsProjectCtor(vnode) != 0: if _c_has_project != 0: - VLogger.error("viperbuild: 一个依赖闭包内只允许一个 Project 对象", "viperbuild") + VLogger.error("viperbuild: only one Project object is allowed per dependency closure", "viperbuild") return 1 _c_has_project = 1 _proj_vars.append(_DupScratch(tgt.id)) @@ -631,7 +631,7 @@ def _HandleAttrAssign(tgt: ast.Attribute*, vnode: ast.AST*) -> int: if bn is None or bn.id is None: return 0 if _FindInList(_proj_vars, bn.id) < 0: return 0 if _IsProjRef(vnode) != 0: - VLogger.error("viperbuild: 禁止读取 Project 宏对象", "viperbuild") + VLogger.error("viperbuild: reading the Project macro object is forbidden", "viperbuild") return 1 return _SetField(tgt.attr, vnode) @@ -652,7 +652,7 @@ def _HandleBuildCall(cl: ast.Call*) -> int: global _c_triple, _c_datalayout, _c_selfmachine, _c_has_build if cl is None: return 1 if _c_has_build != 0: - VLogger.error("viperbuild: proj.build() 只能调用一次", "viperbuild") + VLogger.error("viperbuild: proj.build() may be called only once", "viperbuild") return 1 _c_has_build = 1 if cl.keywords is None: return 0 @@ -662,22 +662,22 @@ def _HandleBuildCall(cl: ast.Call*) -> int: if kw is not None and kw.arg is not None and kw.value is not None: if string.strcmp(kw.arg, "triple") == 0: if _EvalStr(kw.value) == 0: - VLogger.error("viperbuild: build(triple=...) 必须是字符串常量", "viperbuild") + VLogger.error("viperbuild: build(triple=...) must be a string constant", "viperbuild") return 1 _c_triple = _DupStd(_g_out_str) elif string.strcmp(kw.arg, "datalayout") == 0: if _EvalStr(kw.value) == 0: - VLogger.error("viperbuild: build(datalayout=...) 必须是字符串常量", "viperbuild") + VLogger.error("viperbuild: build(datalayout=...) must be a string constant", "viperbuild") return 1 _c_datalayout = _DupStd(_g_out_str) elif string.strcmp(kw.arg, "selfmachine") == 0: b: int = _EvalBool(kw.value) if b < 0: - VLogger.error("viperbuild: build(selfmachine=...) 必须是布尔常量", "viperbuild") + VLogger.error("viperbuild: build(selfmachine=...) must be a boolean constant", "viperbuild") return 1 _c_selfmachine = b else: - VLogger.error(f"viperbuild: build(...) 不支持的关键字 {kw.arg}", "viperbuild") + VLogger.error(f"viperbuild: unsupported keyword {kw.arg} for build(...)", "viperbuild") return 1 return 0 @@ -708,26 +708,26 @@ def _HandleExprStmt(stmt: ast.Expr*) -> int: # Non-Project method call: if an argument reads the macro object -> fatal (reading forbidden) if cl.func.kind() != ast.ASTKind.Attribute: if _CallArgsHaveProjRef(cl) != 0: - VLogger.error("viperbuild: 禁止读取 Project 宏对象", "viperbuild") + VLogger.error("viperbuild: reading the Project macro object is forbidden", "viperbuild") return 1 return 0 at: ast.Attribute* = ast.Attribute*(cl.func) if at is None or at.attr is None or at.value is None: return 0 if at.value.kind() != ast.ASTKind.Name: if _CallArgsHaveProjRef(cl) != 0: - VLogger.error("viperbuild: 禁止读取 Project 宏对象", "viperbuild") + VLogger.error("viperbuild: reading the Project macro object is forbidden", "viperbuild") return 1 return 0 bn: ast.Name* = ast.Name*(at.value) if bn is None or bn.id is None: return 0 if _FindInList(_proj_vars, bn.id) < 0: if _CallArgsHaveProjRef(cl) != 0: - VLogger.error("viperbuild: 禁止读取 Project 宏对象", "viperbuild") + VLogger.error("viperbuild: reading the Project macro object is forbidden", "viperbuild") return 1 return 0 if string.strcmp(at.attr, "config") == 0: return _HandleConfigCall(cl) if string.strcmp(at.attr, "build") == 0: return _HandleBuildCall(cl) - VLogger.error(f"viperbuild: Project 对象不支持的方法 {at.attr}()", "viperbuild") + VLogger.error(f"viperbuild: unsupported method {at.attr}() on Project object", "viperbuild") return 1 @@ -742,12 +742,12 @@ def _ScanFile(pool: memhub.MemBuddy*, path: str) -> int: src_buf: bytes = Utils.read_file_to_buf(path, VB_SRC_CAP) if src_buf is None: - VLogger.warning(f"viperbuild: 无法读取依赖文件 {path}", "viperbuild") + VLogger.warning(f"viperbuild: cannot read dependency file {path}", "viperbuild") return 2 if _ResetFileTables(pool) != 0: stdlib.free(src_buf) - VLogger.error("viperbuild: 常量表分配失败", "viperbuild") + VLogger.error("viperbuild: constant table allocation failed", "viperbuild") return 1 mark: sizet = pool.mark() @@ -755,20 +755,20 @@ def _ScanFile(pool: memhub.MemBuddy*, path: str) -> int: if lx is None: pool.reset_to(mark) stdlib.free(src_buf) - VLogger.error("viperbuild: lexer 分配失败", "viperbuild") + VLogger.error("viperbuild: lexer allocation failed", "viperbuild") return 1 ast._lexer_init(lx, src_buf, pool) tokens: ast.Token* = ast.tokenize(lx) if tokens is None: pool.reset_to(mark) stdlib.free(src_buf) - VLogger.error(f"viperbuild: 词法失败 {path}", "viperbuild") + VLogger.error(f"viperbuild: tokenization failed {path}", "viperbuild") return 1 tree: ast.AST* = ast.parse_tokens(pool, tokens) if tree is None: pool.reset_to(mark) stdlib.free(src_buf) - VLogger.error(f"viperbuild: 语法失败 {path}", "viperbuild") + VLogger.error(f"viperbuild: parsing failed {path}", "viperbuild") return 1 body: list[ast.AST*]* = tree.children @@ -841,13 +841,13 @@ def _RunBfs(pool: memhub.MemBuddy*, entry_path: str) -> int: if cur is None: continue if _FindInList(_visited, cur) >= 0: continue if _visited.__len__() >= VB_MAX_VISIT: - VLogger.error(f"viperbuild: 依赖闭包超过 {VB_MAX_VISIT} 个文件,疑似成环", "viperbuild") + VLogger.error(f"viperbuild: dependency closure exceeds {VB_MAX_VISIT} files, likely a cycle", "viperbuild") return 1 _visited.append(_DupScratch(cur)) _pending = list[str](_scratch, 8) if _pending is None: - VLogger.error("viperbuild: BFS 队列分配失败", "viperbuild") + VLogger.error("viperbuild: BFS queue allocation failed", "viperbuild") return 1 rc: int = _ScanFile(pool, cur) if rc == 1: return 1 @@ -867,13 +867,13 @@ def _DetectHost() -> int: global _c_triple, _c_datalayout buf: CHARPTR = stdlib.malloc(64) if buf is None: - VLogger.error("viperbuild: selfmachine 探测缓冲分配失败", "viperbuild") + VLogger.error("viperbuild: selfmachine probe buffer allocation failed", "viperbuild") return 1 buf[0] = char(0) n: DWORD = GetEnvironmentVariableA("PROCESSOR_ARCHITECTURE", buf, DWORD(64)) if n == 0 or n >= DWORD(64): stdlib.free(buf) - VLogger.error("viperbuild: selfmachine 探测失败(PROCESSOR_ARCHITECTURE 不可用)", "viperbuild") + VLogger.error("viperbuild: selfmachine probe failed (PROCESSOR_ARCHITECTURE unavailable)", "viperbuild") return 1 buf[int(n)] = char(0) # "AMD64\0" (A=65 M=77 D=68 6=54 4=52) @@ -885,7 +885,7 @@ def _DetectHost() -> int: stdlib.free(buf) return 0 stdlib.free(buf) - VLogger.error("viperbuild: selfmachine 暂不支持本机架构(当前仅支持 AMD64)", "viperbuild") + VLogger.error("viperbuild: selfmachine does not support the host architecture yet (currently only AMD64)", "viperbuild") return 1 @@ -941,10 +941,10 @@ def _FinalizeCfg(entry_path: str) -> int: global _c_selfmachine if _c_has_project == 0: - VLogger.error("viperbuild: 依赖闭包内未找到 vb.Project(...) 定义", "viperbuild") + VLogger.error("viperbuild: no vb.Project(...) definition found in the dependency closure", "viperbuild") return 1 if _c_has_build == 0: - VLogger.error("viperbuild: 未调用 proj.build(...),无法确定构建目标", "viperbuild") + VLogger.error("viperbuild: proj.build(...) was not called, cannot determine the build target", "viperbuild") return 1 # ---- Defaults ---- @@ -953,7 +953,7 @@ def _FinalizeCfg(entry_path: str) -> int: if _c_includes is None: probed: str = _ProbeIncludes() if probed is None: - VLogger.error("viperbuild: 未能探测到 includes 目录(exe 目录向上 0..3 层均无 includes)", "viperbuild") + VLogger.error("viperbuild: could not probe an includes directory (no includes up to 0..3 levels above the exe directory)", "viperbuild") return 1 _c_includes = probed if _c_compiler is None: _c_compiler = _DupStd("llc -filetype=obj -relocation-model=pic") @@ -965,18 +965,18 @@ def _FinalizeCfg(entry_path: str) -> int: # ---- Entry file must be under source ---- if _HasPrefix(entry_path, _c_source) == 0: - VLogger.error(f"viperbuild: 入口文件不在 source 目录之下\n 入口: {entry_path}\n source: {_c_source}", "viperbuild") + VLogger.error(f"viperbuild: entry file is not under the source directory\n entry: {entry_path}\n source: {_c_source}", "viperbuild") return 1 # ---- Target platform ---- explicit_triple: int = 0 if _c_triple is not None or _c_datalayout is not None: explicit_triple = 1 if _c_selfmachine != 0 and explicit_triple != 0: - VLogger.error("viperbuild: build(selfmachine=True) 与显式 triple/datalayout 互斥", "viperbuild") + VLogger.error("viperbuild: build(selfmachine=True) is mutually exclusive with an explicit triple/datalayout", "viperbuild") return 1 if explicit_triple != 0: if _c_triple is None or _c_datalayout is None: - VLogger.error("viperbuild: build() 的 triple 与 datalayout 必须成对给出", "viperbuild") + VLogger.error("viperbuild: build() triple and datalayout must be given as a pair", "viperbuild") return 1 else: # Neither given, or selfmachine=True: detect the host at runtime @@ -1065,7 +1065,7 @@ def DiscoverAndApply(mb: memhub.MemBuddy*, entry_path: str) -> int: global _search_dirs if mb is None or entry_path is None: - VLogger.error("viperbuild: 参数为空", "viperbuild") + VLogger.error("viperbuild: argument is null", "viperbuild") return 1 _ResetAll() @@ -1073,7 +1073,7 @@ def DiscoverAndApply(mb: memhub.MemBuddy*, entry_path: str) -> int: # Entry dir (default source + closure search root) _entry_dir = _DirOf(entry_path) if _entry_dir is None: - VLogger.error(f"viperbuild: 无法解析入口文件目录 {entry_path}", "viperbuild") + VLogger.error(f"viperbuild: cannot resolve the entry file directory {entry_path}", "viperbuild") return 1 # Bare filename (no separator) -> _DirOf returns ""; must normalize to ".", otherwise # ResolveModuleToPath("") tries no candidate and same-dir deps (often the viperbuild config) never resolve. @@ -1084,11 +1084,11 @@ def DiscoverAndApply(mb: memhub.MemBuddy*, entry_path: str) -> int: # Scratch pool (BFS working set; not affected by main-pool reset) arena: bytes = stdlib.malloc(VB_SCRATCH) if arena is None: - VLogger.error("viperbuild: scratch 内存分配失败", "viperbuild") + VLogger.error("viperbuild: scratch memory allocation failed", "viperbuild") return 1 _scratch = memhub.MemBuddy(arena, VB_SCRATCH, 0, 0) if _scratch is None: - VLogger.error("viperbuild: scratch 池初始化失败", "viperbuild") + VLogger.error("viperbuild: scratch pool initialization failed", "viperbuild") return 1 _work = list[str](_scratch, 8) @@ -1096,7 +1096,7 @@ def DiscoverAndApply(mb: memhub.MemBuddy*, entry_path: str) -> int: _pending = list[str](_scratch, 8) _proj_vars = list[str](_scratch, 8) if _work is None or _visited is None or _pending is None or _proj_vars is None: - VLogger.error("viperbuild: 工作集分配失败", "viperbuild") + VLogger.error("viperbuild: working set allocation failed", "viperbuild") return 1 # Keyword/operator tables must be built before the main-pool reset window (else freed -> dangling crash) @@ -1105,8 +1105,8 @@ def DiscoverAndApply(mb: memhub.MemBuddy*, entry_path: str) -> int: if _RunBfs(mb, entry_path) != 0: return 1 if _proj_vars.__len__() == 0: - if _saw_viperbuild == 0: VLogger.error(f"viperbuild: 入口文件依赖闭包内未找到 `import viperbuild`(入口: {entry_path};已扫描 {_visited.__len__()} 个文件)", "viperbuild") - else: VLogger.error(f"viperbuild: 找到 `import viperbuild` 但依赖闭包内没有 `proj = vb.Project(...)` 绑定(入口: {entry_path})", "viperbuild") + if _saw_viperbuild == 0: VLogger.error(f"viperbuild: `import viperbuild` not found in the entry file dependency closure (entry: {entry_path}; scanned {_visited.__len__()} files)", "viperbuild") + else: VLogger.error(f"viperbuild: found `import viperbuild` but the dependency closure has no `proj = vb.Project(...)` binding (entry: {entry_path})", "viperbuild") return 1 if _FinalizeCfg(entry_path) != 0: return 1 diff --git a/App/main.vp b/App/main.vp index 3690710..0cd4b9c 100644 --- a/App/main.vp +++ b/App/main.vp @@ -163,7 +163,7 @@ def main() -> int: # parse command-line arguments args: argparse.ParsedArgs = parser.parse_args(sys._argc, sys._argv) if args is None: - log.error("参数解析失败", "argparse") + log.error("Failed to parse arguments", "argparse") return 1 if args.get_bool("help"): @@ -191,26 +191,26 @@ Target: %s repl_flag: bool = args.get_bool("repl") if repl_flag: if args.get_str("phase2command") is not None: - stdio.printf("FAIL: --repl 与 --phase2command 互斥\n") - stdio.printf(" 原因: --phase2command 下 compile_ll_to_obj 只写 bat 不执行 llc,\n") - stdio.printf(" 片段 .obj 不会生成,随后的 clang++ -shared 必然失败\n") - stdio.printf(" 处理: 去掉 --phase2command(REPL 需要立即产出并加载片段 DLL)\n") + stdio.printf("FAIL: --repl and --phase2command are mutually exclusive\n") + stdio.printf(" Reason: under --phase2command, compile_ll_to_obj only writes the bat and does not run llc,\n") + stdio.printf(" so the fragment .obj is never produced and the subsequent clang++ -shared necessarily fails\n") + stdio.printf(" Fix: drop --phase2command (REPL must produce and load the fragment DLL immediately)\n") argparse.release(args) return 2 if args.get_bool("asan"): - stdio.printf("FAIL: --repl 与 --asan 互斥\n") - stdio.printf(" 原因: --asan 先对片段 .ll 做 ASan 插桩,而片段产物是运行期\n") - stdio.printf(" LoadLibraryA 载入的 DLL,宿主进程未挂 ASan 运行库,插桩语义不明\n") - stdio.printf(" 处理: 去掉 --asan(如需排查内存问题,请用工程模式构建 ASan 版 TransPyV)\n") + stdio.printf("FAIL: --repl and --asan are mutually exclusive\n") + stdio.printf(" Reason: --asan first instruments the fragment .ll with ASan, but the fragment artifact is a runtime\n") + stdio.printf(" DLL loaded by LoadLibraryA, and the host process does not link the ASan runtime; instrumentation semantics are undefined\n") + stdio.printf(" Fix: drop --asan (to debug memory issues, build an ASan TransPyV in project mode)\n") argparse.release(args) return 2 # --traceback is also rejected under --repl: the fragment is a runtime-loaded # DLL (DI metadata / startup ctor semantics undefined) and it has no .stackmap. if args.get_bool("traceback"): - stdio.printf("FAIL: --repl 与 --traceback 互斥\n") - stdio.printf(" 原因: --traceback 依赖启动期构造器注入 + 本模块 DWARF 旁文件,\n") - stdio.printf(" 而片段是运行期 LoadLibraryA 载入的 DLL,二者语义未定义\n") - stdio.printf(" 处理: 去掉 --traceback(如需崩溃栈,请用工程模式构建 --traceback 版 TransPyV)\n") + stdio.printf("FAIL: --repl and --traceback are mutually exclusive\n") + stdio.printf(" Reason: --traceback relies on startup-ctor injection + a per-module DWARF side file,\n") + stdio.printf(" but the fragment is a runtime LoadLibraryA-loaded DLL; the two semantics are undefined\n") + stdio.printf(" Fix: drop --traceback (for crash stacks, build a --traceback TransPyV in project mode)\n") argparse.release(args) return 2 @@ -232,9 +232,9 @@ Target: %s # === --project and --src are mutually exclusive: --project uses project.vpj, # --src uses viperbuild built-in config; giving both fails fast. if project is not None and src is not None: - stdio.printf("FAIL: --project 与 --src 互斥\n") - stdio.printf(" 原因: --project 走 project.vpj 工程模式,--src 走入口文件的 viperbuild 内建配置\n") - stdio.printf(" 处理: 二选一;--src 模式下构建配置写在入口文件依赖闭包的 import viperbuild 里\n") + stdio.printf("FAIL: --project and --src are mutually exclusive\n") + stdio.printf(" Reason: --project uses project.vpj project mode, --src uses the entry file's built-in viperbuild config\n") + stdio.printf(" Fix: choose one; in --src mode the build config goes in 'import viperbuild' within the entry file's dependency closure\n") argparse.release(args) return 2 @@ -242,17 +242,17 @@ Target: %s show_args: bool = args.get_bool("show-args") if show_args: if project is not None: stdio.printf(" --project: %s\n", project) - else: stdio.printf(" --project: (未指定)\n") + else: stdio.printf(" --project: (not specified)\n") if src is not None: stdio.printf(" --src: %s\n", src) - else: stdio.printf(" --src: (未指定)\n") + else: stdio.printf(" --src: (not specified)\n") if temp is not None: stdio.printf(" --temp: %s\n", temp) - else: stdio.printf(" --temp: (未指定)\n") + else: stdio.printf(" --temp: (not specified)\n") if output is not None: stdio.printf(" --output: %s\n", output) - else: stdio.printf(" --output: (未指定)\n") + else: stdio.printf(" --output: (not specified)\n") if phase is not None: stdio.printf(" --phase: %s\n", phase) - else: stdio.printf(" --phase: (未指定,默认 all)\n") + else: stdio.printf(" --phase: (not specified, default all)\n") if cc is not None: stdio.printf(" --cc: %s\n", cc) - else: stdio.printf(" --cc: (未指定)\n") + else: stdio.printf(" --cc: (not specified)\n") if _gb_clean: stdio.printf(" --clean: True\n") else: stdio.printf(" --clean: False\n") if args.get_bool("run"): stdio.printf(" --run: True\n") @@ -261,7 +261,7 @@ Target: %s else: stdio.printf(" --rebuild-includes: False\n") if args.get_bool("clear-cache"): stdio.printf(" --clear-cache: True\n") else: stdio.printf(" --clear-cache: False\n") - stdio.printf("参数解析完成。\n\n") + stdio.printf("Argument parsing complete.\n\n") # Mode switches: isolate includes caches by suffix so mode-specific objects do # not mix (ASan/traceback objects are incompatible); suffix combines both flags. @@ -275,30 +275,30 @@ Target: %s elif gb_traceback: Config._inc_bin_suffix = ".binary_traceback" elif gb_asan: Config._inc_bin_suffix = ".binary_asan" else: Config._inc_bin_suffix = ".binary" - if gb_asan: log.info("ASan 模式已启用(opt -passes=asan 插桩; 运行库需 project.vpj 声明)", "asan") - if gb_traceback: log.info("Traceback 模式已启用(llc 保留帧指针 + 链 dbghelp + Install 构造器 + .stackmap)", "traceback") + if gb_asan: log.info("ASan mode enabled (opt -passes=asan instrumentation; runtime libs must be declared in project.vpj)", "asan") + if gb_traceback: log.info("Traceback mode enabled (llc keep frame pointer + link dbghelp + Install ctor + .stackmap)", "traceback") # Enabling either mode clears that suffix's includes cache to force a rebuild if gb_asan or gb_traceback: mf_inc_bin_mode: str = Config.get_includes_binary_dir() if mf_inc_bin_mode is not None: n_mode: int = Utils.CleanDir(mf_inc_bin_mode) - log.info(f"模式缓存清理: {mf_inc_bin_mode} 删除 {n_mode} 个文件(将按 {Config._inc_bin_suffix} 重建)", "mode") + log.info(f"Mode cache cleanup: {mf_inc_bin_mode} deleted {n_mode} files (will rebuild with {Config._inc_bin_suffix})", "mode") # === --phase2command: only write llc/link commands to a bat, do not execute them === p2c: str = args.get_str("phase2command") if p2c is not None: BuildPipeline._phase2_cmd_path = p2c - log.info(f"--phase2command: 不执行 llc/链接,命令写入 {p2c}", "phase2cmd") + log.info(f"--phase2command: not running llc/link, commands written to {p2c}", "phase2cmd") # --nowarn-register: suppress Phase A dependency WARNs (cross-module text.ll not yet generated) if args.get_bool("nowarn-register"): VLogger._nowarn_register = 1 - log.info("--nowarn-register 已启用:抑制注册类 WARN 输出", "vlogger") + log.info("--nowarn-register enabled: suppress register-class WARN output", "vlogger") # --no-llvmpeephole: disable all local peepholes (T2/T3); FunctionPrint serializes directly if args.get_bool("no-llvmpeephole"): mlirlite.G_PeepEnable = 0 - log.info("--no-llvmpeephole 已启用:关闭 FunctionPrint 本地窥孔(RenumberSSA 保留)", "peep") + log.info("--no-llvmpeephole enabled: disable FunctionPrint local peepholes (RenumberSSA kept)", "peep") # === --repl convenience: without --project, search cwd then the exe dir for # repl.vpj and feed it to Config.Load_project_config; miss fails fast. @@ -308,24 +308,24 @@ Target: %s repl_proj_buf: bytes = stdlib.malloc(REPL_PROJ_PATH_CAP) repl_diag_buf: bytes = stdlib.malloc(REPL_PROJ_DIAG_CAP) if repl_proj_buf is None or repl_diag_buf is None: - stdio.printf("FAIL: --repl 查找 repl.vpj 的路径缓冲分配失败\n") + stdio.printf("FAIL: --repl failed to allocate the path buffer for locating repl.vpj\n") argparse.release(args) return 1 if Repl.ReplFindProject(repl_proj_buf, REPL_PROJ_PATH_CAP, repl_diag_buf, REPL_PROJ_DIAG_CAP) != 0: proj_path = repl_proj_buf - log.info(f"--repl: 未指定 --project,使用查找到的模板工程 {proj_path}", "repl") + log.info(f"--repl: --project not given, using the located template project {proj_path}", "repl") else: - stdio.printf("FAIL: --repl 未找到工程文件 repl.vpj\n") + stdio.printf("FAIL: --repl could not find the project file repl.vpj\n") stdio.printf("%s", repl_diag_buf) - stdio.printf(" 也可用 --project 显式指定工程文件(如本仓库的 TransPyV/project.vpj)\n") + stdio.printf(" You can also pass --project to specify the project file explicitly (e.g. TransPyV/project.vpj in this repo)\n") argparse.release(args) return 1 # load project config (explicit --project / repl.vpj found by --repl) if proj_path is not None: - log.banner("工程配置") + log.banner("Project config") cfg_ret: int = Config.Load_project_config(proj_path) if cfg_ret == 0: proj_loaded = 1 - else: log.warning(f"无法加载 project.vpj: {proj_path}", "config") + else: log.warning(f"Failed to load project.vpj: {proj_path}", "config") else: # try the default project.vpj (current and parent dir); --src mode must not # implicitly load project.vpj (it would pollute the config source). @@ -377,43 +377,43 @@ Target: %s # --asan requires the project to declare the ASan runtime in project.vpj linker.static_libs (no hardcoded paths); missing fails fast if BuildPipeline._asan_mode != 0 and Config.asan_runtime_declared() == 0: - log.error("启用 --asan 需要在 project.vpj 的 linker.static_libs 里声明 ASan 运行库:", "asan") + log.error("Enabling --asan requires declaring the ASan runtime in project.vpj's linker.static_libs:", "asan") log.error(" D:/msys64/clang64/lib/clang/22/lib/windows/libclang_rt.asan_dynamic-x86_64.dll.a", "asan") log.error(" D:/msys64/clang64/lib/clang/22/lib/windows/libclang_rt.asan_dynamic_runtime_thunk-x86_64.a", "asan") - log.error("运行时还需要 PATH 里有 D:/msys64/clang64/bin(libclang_rt.asan_dynamic-x86_64.dll)", "asan") + log.error("At runtime D:/msys64/clang64/bin (libclang_rt.asan_dynamic-x86_64.dll) must also be on PATH", "asan") return 1 # === --clean: remove temp, output and includes.binary directories === if _gb_clean: - log.info("清理临时目录...", "clean") + log.info("Cleaning temp directory...", "clean") if Config.TempDir is not None: n: int = Utils.CleanDir(Config.TempDir) - log.info(f"{Config.TempDir}: 删除 {n} 个文件", "clean") + log.info(f"{Config.TempDir}: deleted {n} files", "clean") if Config.OutputDir is not None: n2: int = Utils.CleanDir(Config.OutputDir) - log.info(f"{Config.OutputDir}: 删除 {n2} 个文件", "clean") + log.info(f"{Config.OutputDir}: deleted {n2} files", "clean") # Clean the includes.binary dir (stale .obj files would skip recompilation) mf_inc_bin_clean: str = Config.get_includes_binary_dir() if mf_inc_bin_clean is not None: n3: int = Utils.CleanDir(mf_inc_bin_clean) - log.info(f"{mf_inc_bin_clean}: 删除 {n3} 个文件", "clean") + log.info(f"{mf_inc_bin_clean}: deleted {n3} files", "clean") # === --rebuild-includes: delete the includes.binary precompile cache === # Forces all includes to recompile next time (temp/output untouched) if args.get_bool("rebuild-includes"): - log.info("重建 includes 缓存...", "rebuild-includes") + log.info("Rebuilding includes cache...", "rebuild-includes") mf_inc_bin_rb: str = Config.get_includes_binary_dir() if mf_inc_bin_rb is not None: n_rb: int = Utils.CleanDir(mf_inc_bin_rb) - log.info(f"{mf_inc_bin_rb}: 删除 {n_rb} 个文件(includes 将重新编译)", "rebuild-includes") + log.info(f"{mf_inc_bin_rb}: deleted {n_rb} files (includes will be recompiled)", "rebuild-includes") # === --clear-cache: clear the temp dir cache (.vpi/.stub.ll/.text.ll) === # Forces Phase1 to regenerate stubs next time (output/includes.binary untouched) if args.get_bool("clear-cache"): - log.info("清除 temp 缓存...", "clear-cache") + log.info("Clearing temp cache...", "clear-cache") if Config.TempDir is not None: n_cc: int = Utils.CleanDir(Config.TempDir) - log.info(f"{Config.TempDir}: 删除 {n_cc} 个文件(.vpi/.stub.ll 缓存)", "clear-cache") + log.info(f"{Config.TempDir}: deleted {n_cc} files (.vpi/.stub.ll cache)", "clear-cache") # === --phase: 1=stub split only; 2=stub merge+compile only; all=both (default) === phase_mode: str = phase @@ -423,7 +423,7 @@ Target: %s # Note: use string.strcmp instead of == to avoid the compiler == semantics bug if string.strcmp(phase_mode, "1") == 0 or string.strcmp(phase_mode, "all") == 0: do_phase1 = 1 if string.strcmp(phase_mode, "2") == 0 or string.strcmp(phase_mode, "all") == 0: do_phase2 = 1 - log.info(f"模式: {phase_mode} (phase1={do_phase1} phase2={do_phase2})", "phase") + log.info(f"Mode: {phase_mode} (phase1={do_phase1} phase2={do_phase2})", "phase") # === Phase1: scan includes (on-demand translation) === # For each .vp/.py file under includes, translate and split the stub if absent @@ -431,11 +431,11 @@ Target: %s ph1_temp: str = Config.TempDir if ph1_temp is None: ph1_temp = "." if Phase1Main.RunPhase1(mb, Config.IncludesDirs, ph1_temp, log) != 0: - VLogger.error("Phase1 失败,终止编译", "Phase1") + VLogger.error("Phase1 failed, aborting compilation", "Phase1") return 1 # Phase1-only (no Phase2): exit right away if do_phase2 == 0: - log.info("Phase1 完成,退出", "phase") + log.info("Phase1 complete, exiting", "phase") return 0 # AST parse: when --src or --project is given, read the file and parse it into an AST @@ -443,7 +443,7 @@ Target: %s # No project config and no --src: fail fast (uninitialized Config fields are garbage pointers -> crash) if proj_loaded == 0 and src_path is None: - log.error("未找到 project.vpj(当前目录/上级目录)且未指定 --src,无法构建", "config") + log.error("project.vpj not found (current/parent dir) and --src not given; cannot build", "config") argparse.release(args) return 1 @@ -463,10 +463,10 @@ Target: %s mf_ret: int = Phase2.RunMultiFileProject(mb, Config.SourceDir, mf_temp, mf_output, mf_cc, mf_cc_flags, mf_linker, mf_linker_flags, mf_linker_out, mf_includes_bin, Config.IncludesDirs, do_phase1, do_phase2, log, args, mf_static_libs, mf_dynamic_libs) argparse.release(args) - log.success("TransPyV 完成") + log.success("TransPyV complete") return mf_ret # Reaching here means no buildable project root (SourceDir missing): fail fast, no silent "done" - log.error("无可构建的工程根:project.vpj 缺 source_dir,或 viperbuild 未提供 source", "config") + log.error("No buildable project root: project.vpj is missing source_dir, or viperbuild provided no source", "config") argparse.release(args) return 1