From 4a685d478fb8ac5aa1396ae961d4c7e08c2ed487 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 5 Oct 2026 03:10:55 +0800 Subject: [PATCH] =?UTF-8?q?refactor(tpv):=20=E6=96=B0=E8=AF=AD=E6=B3=95=20?= =?UTF-8?q?R10=20=E5=8D=95=E8=AF=AD=E5=8F=A5=E5=9D=97=E5=B9=B6=E4=B8=80?= =?UTF-8?q?=E8=A1=8C=EF=BC=887722=20=E5=A4=84=20if/for/while=20=E5=8D=95?= =?UTF-8?q?=E8=AF=AD=E5=8F=A5=E4=BD=93=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/lib/Phase/BuildPipeline.vp | 798 ++++------ App/lib/Phase/Phase1/Phase1Main.vp | 294 ++-- App/lib/Phase/Phase1/Phase1Scan.vp | 171 +- App/lib/Phase/Phase1/Phase1Topo.vp | 120 +- App/lib/Phase/Phase2/__init__.vp | 411 ++--- App/lib/Projectrans/Config.vp | 216 +-- App/lib/Projectrans/Utils.vp | 69 +- App/lib/Stub/StubGen/Converter.vp | 285 ++-- App/lib/Stub/StubGen/VpiReader.vp | 1497 ++++++------------ App/lib/Stub/StubMerger/StubMergerBuild.vp | 147 +- App/lib/Stub/StubMerger/StubMergerCollect.vp | 39 +- App/lib/Stub/StubMerger/StubMergerIR.vp | 78 +- App/lib/Stub/StubMerger/StubMergerStore.vp | 234 +-- App/lib/Stub/StubMerger/StubMergerTopo.vp | 45 +- App/lib/core/Gen/AssignGenMixin.vp | 1137 +++++-------- App/lib/core/Gen/AsyncGenMixin.vp | 993 ++++-------- App/lib/core/Gen/BaseGenMixin.vp | 3 +- App/lib/core/Gen/Call/CallGenBase.vp | 480 ++---- App/lib/core/Gen/Call/CallGenCBuiltin.vp | 468 ++---- App/lib/core/Gen/Call/CallGenCall.vp | 414 ++--- App/lib/core/Gen/Call/CallGenCtor.vp | 288 ++-- App/lib/core/Gen/Call/CallGenDispatch.vp | 384 ++--- App/lib/core/Gen/Call/CallGenFd.vp | 39 +- App/lib/core/Gen/Call/CallGenLeafKit.vp | 369 ++--- App/lib/core/Gen/Call/CallGenLib.vp | 336 ++-- App/lib/core/Gen/Call/CallGenMixin.vp | 465 ++---- App/lib/core/Gen/Call/CallGenProp.vp | 90 +- App/lib/core/Gen/Call/CallGenVa.vp | 117 +- App/lib/core/Gen/Call/CallGenVt.vp | 36 +- App/lib/core/Gen/Class/ClassGenBase.vp | 609 +++---- App/lib/core/Gen/Class/ClassGenDef.vp | 198 +-- App/lib/core/Gen/Class/ClassGenEnum.vp | 495 ++---- App/lib/core/Gen/Class/ClassGenGeneric.vp | 282 ++-- App/lib/core/Gen/Class/ClassGenVTable.vp | 354 ++--- App/lib/core/Gen/DebugInfoGen.vp | 111 +- App/lib/core/Gen/Expr/ExprGenAttr.vp | 387 ++--- App/lib/core/Gen/Expr/ExprGenBase.vp | 255 +-- App/lib/core/Gen/Expr/ExprGenCdef.vp | 339 ++-- App/lib/core/Gen/Expr/ExprGenCls.vp | 90 +- App/lib/core/Gen/Expr/ExprGenConst.vp | 117 +- App/lib/core/Gen/Expr/ExprGenFstr.vp | 156 +- App/lib/core/Gen/Expr/ExprGenMixin.vp | 12 +- App/lib/core/Gen/Expr/ExprGenName.vp | 345 ++-- App/lib/core/Gen/Expr/ExprGenOps.vp | 531 +++---- App/lib/core/Gen/Func/FuncGenBase.vp | 33 +- App/lib/core/Gen/Func/FuncGenDef.vp | 321 ++-- App/lib/core/Gen/Func/FuncGenMixin.vp | 471 ++---- App/lib/core/Gen/GenApi.vp | 261 +-- App/lib/core/Gen/Generator.vp | 3 +- App/lib/core/Gen/ImportsGenMixin.vp | 252 +-- App/lib/core/Gen/MatchGenMixin.vp | 444 ++---- App/lib/core/Gen/Stmt/StmtGenCifMixin.vp | 693 +++----- App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp | 201 +-- App/lib/core/Gen/Stmt/StmtGenMixin.vp | 321 ++-- App/lib/core/Gen/StructGenMixin.vp | 621 +++----- App/lib/core/Gen/Translator.vp | 333 ++-- App/lib/core/Gen/TranslatorGenMixin.vp | 399 ++--- App/lib/core/Gen/Type/TypeGenBase.vp | 3 +- App/lib/core/Gen/Type/TypeGenCDef.vp | 120 +- App/lib/core/Gen/Type/TypeGenCType.vp | 240 +-- App/lib/core/Gen/Type/TypeGenErr.vp | 174 +- App/lib/core/Gen/Type/TypeGenResolve.vp | 1365 ++++++---------- App/lib/core/Gen/Type/TypeSpec.vp | 615 +++---- App/lib/core/Gen/VarGenMixin.vp | 621 +++----- App/lib/core/IncludesScanner.vp | 132 +- App/lib/core/Repl.vp | 621 +++----- App/lib/core/VLogger.vp | 18 +- App/lib/core/builtin/ViperBuild.vp | 534 +++---- App/main.vp | 68 +- 69 files changed, 7723 insertions(+), 15445 deletions(-) diff --git a/App/lib/Phase/BuildPipeline.vp b/App/lib/Phase/BuildPipeline.vp index 87b8917..6fc5c90 100644 --- a/App/lib/Phase/BuildPipeline.vp +++ b/App/lib/Phase/BuildPipeline.vp @@ -67,15 +67,12 @@ def _ir_sibling_path(ir_path: str, suffix: str) -> str: 从 _mbuddy 分配(与 build_sliced_path 同池,随 pool reset 回收,无需手动 free)。 """ - if ir_path is None or suffix is None: - return None + if ir_path is None or suffix is None: return None n: sizet = string.strlen(ir_path) - if n < 3: - return None + if n < 3: return None suf_len: sizet = string.strlen(suffix) buf: str = _mbuddy.alloc(n + suf_len + 1) - if buf is None: - return None + if buf is None: return None string.strncpy(buf, ir_path, n - 3) buf[n - 3] = '\0' string.strcat(buf, suffix) @@ -95,8 +92,7 @@ PYI_BUF_SIZE: sizet = 262144 # byte-identical to the pre-switch behaviour. # ============================================================ def _llc_frame_ptr_flag() -> str: - if _traceback_mode != 0: - return " -frame-pointer=all" + if _traceback_mode != 0: return " -frame-pointer=all" return "" @@ -109,8 +105,7 @@ def _llc_frame_ptr_flag() -> str: # so this is appended to linker_flags (not prepended). # ============================================================ def _append_traceback_dbghelp(linker_flags: str) -> str: - if _traceback_mode == 0 or linker_flags is None: - return linker_flags + if _traceback_mode == 0 or linker_flags is None: return linker_flags need: sizet = string.strlen(linker_flags) + 16 buf: str = _mbuddy.alloc(need) if buf is None: @@ -136,8 +131,7 @@ _tb_vpcall_n: int = 0 def _tb_register_vpcall(path: str) -> int: """把已写出的 .vpcall 路径登记进全局表(供 WriteStackMap 稍后读取)。""" global _tb_vpcall_buf, _tb_vpcall_n - if path is None: - return 0 + if path is None: return 0 if _tb_vpcall_buf is None: _tb_vpcall_buf = stdlib.malloc(sizet(TB_VPCALL_MAX) * 8) if _tb_vpcall_buf is None: @@ -159,8 +153,7 @@ def WriteCallSidecar(temp_dir: str, sha1: str, text: str) -> int: text 为 None 时跳过(该模块无 define/无调用)。路径随后登记到全局表,交由 WriteStackMap 读取;本函数不释放路径(进程生命周期内一直有效)。 """ - if temp_dir is None or sha1 is None or text is None: - return 0 + 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") @@ -179,15 +172,12 @@ def WriteCallSidecar(temp_dir: str, sha1: str, text: str) -> int: # _tb_basename_is_traceback - is this source file includes/traceback.vp # ============================================================ def _tb_basename_is_traceback(file_path: str) -> int: - if file_path is None: - return 0 + if file_path is None: return 0 flen: sizet = string.strlen(file_path) - if flen < 12: - return 0 + if flen < 12: return 0 if flen > 12: prev: char = file_path[flen - 13] - if prev != '/' and prev != '\\': - return 0 + if prev != '/' and prev != '\\': return 0 return 1 if string.strcmp(file_path + (flen - 12), "traceback.vp") == 0 else 0 # ============================================================ @@ -231,8 +221,7 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy*, file_path: str, if bytes_read <= 0: stdlib.free(src_buf) return None - if bytes_read < SRC_BUF_SIZE: - src_buf[bytes_read] = 0 + if bytes_read < SRC_BUF_SIZE: src_buf[bytes_read] = 0 lx: ast.Lexer* = ast.new_lexer(mb) ast._lexer_init(lx, src_buf, mb) tokens: ast.Token* = ast.tokenize(lx) @@ -312,13 +301,11 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy*, file_path: str, GenApi.clear_ctypedefs() # 命名空间隔离:includes 文件宽松模式(全部可见),用户文件严格模式(仅本地+import) strict_mode: int = 1 - if string.strstr(file_path, "includes") is not None: - strict_mode = 0 + if string.strstr(file_path, "includes") is not None: strict_mode = 0 GenApi.reset_visible_structs(mb, strict_mode) # 提取 docstring(预注册阶段所有 App/includes 文件都被翻译,保证跨模块 __doc__ 在正式翻译前已登记;查重幂等) # 必须在 tr.translate 之前扫描:translate 期间 mb 池大量分配 IR 节点,AST 节点所在池块可能被复用覆盖(ASan 下遍历 tree 会崩溃)。 - if gen is not None: - gen.ExprGenCls.extract_module_docstrings(tree, sha1_val) + 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") @@ -327,8 +314,7 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy*, file_path: str, # Install() ctor into its IR (before the caller dumps stub/text.ll). The # injector lives in the Gen layer, which already depends on mlirlite, so # BuildPipeline gains no cross-module mlirlite symbol dependency. - if _traceback_mode != 0 and _tb_basename_is_traceback(file_path) != 0: - HandlesTranslator.InjectTracebackInstallCtor(tr) + if _traceback_mode != 0 and _tb_basename_is_traceback(file_path) != 0: HandlesTranslator.InjectTracebackInstallCtor(tr) return tr @@ -364,8 +350,7 @@ def ensure_dir(path: str) -> int: # 末级目录已存在则直接成功返回,省去 1 次分配 + N+1 次 CreateDirectoryA 系统调用。 # 语义不变:原实现把"目录已存在"(CreateDirectoryA 失败)也视为成功。 attr: ULONG = w32.win32file.GetFileAttributesA(path) - if attr != 0xFFFFFFFF and (attr & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: - return 0 + if attr != 0xFFFFFFFF and (attr & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: return 0 # 复制路径到可写缓冲区(逐级截断用) buf: bytes = _mbuddy.alloc(path_len + 1) @@ -398,8 +383,7 @@ def ensure_dir(path: str) -> int: # ============================================================ def build_sliced_path(base_dir: str, sha1: str, ext: str) -> str: """构建切片路径并确保目录存在""" - if base_dir is None or sha1 is None or ext is None: - return None + if base_dir is None or sha1 is None or ext is None: return None subdir: str = Config.slice_subdir(sha1, Config.Sha1SliceLevel) base_len: sizet = len(base_dir) @@ -469,8 +453,7 @@ def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: s Returns: 0 成功,非 0 失败 """ - if ir_path is None or cc_cmd is None or output_dir is None or module_name is None: - return 1 + if ir_path is None or cc_cmd is None or output_dir is None or module_name is None: return 1 # 构造切片 .obj 路径: output_dir/{sha1前缀}/{module_name}.obj obj_path: str = build_sliced_path(output_dir, module_name, "obj") @@ -485,17 +468,14 @@ def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: s # 必须在 ASan opt 与 llc 之前,并把 compile_input 替换为 <...>.ll.local。 ll_local_path: str = _ir_sibling_path(ir_path, ".ll.local") mlir_opt_out: str = _ir_sibling_path(ir_path, ".mlir.opt") - if ll_local_path is None or mlir_opt_out is None: - return 1 + if ll_local_path is None or mlir_opt_out is None: return 1 mo_len: sizet = len(MLIR_OPT_CMD) + len(ir_path) + len(mlir_opt_out) + 16 cmd_mo: str = _mbuddy.alloc(mo_len) - if cmd_mo is None: - return 1 + if cmd_mo is None: return 1 viperlib.snprintf(cmd_mo, mo_len, "%s %s -o %s", MLIR_OPT_CMD, ir_path, mlir_opt_out) mt_len: sizet = len(MLIR_TRANSLATE_CMD) + len(mlir_opt_out) + len(ll_local_path) + 40 cmd_mt: str = _mbuddy.alloc(mt_len) - if cmd_mt is None: - return 1 + if cmd_mt is None: return 1 viperlib.snprintf(cmd_mt, mt_len, "%s --mlir-to-llvmir %s -o %s", MLIR_TRANSLATE_CMD, mlir_opt_out, ll_local_path) if _phase2_cmd_path is not None: # 只写命令(须排在下面的 ASan/llc 命令之前) @@ -531,20 +511,16 @@ def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: s if p2_cmd is not None: viperlib.snprintf(p2_cmd, p2_clen, "%s %s%s -o %s %s", cc_cmd, cc_flags, llc_fp, obj_path, compile_input) - if p2_opt_cmd is not None: - _phase2_write_cmd(p2_opt_cmd) - if p2_cmd is not None: - _phase2_write_cmd(p2_cmd) + if p2_opt_cmd is not None: _phase2_write_cmd(p2_opt_cmd) + if p2_cmd is not None: _phase2_write_cmd(p2_cmd) return 0 if _asan_mode != 0: asan_path: str = build_sliced_path(output_dir, module_name, "asan.ll") - if asan_path is None: - return 1 + if asan_path is None: return 1 opt_cmd_len: sizet = len(asan_path) + len(compile_input) + 192 opt_cmd: bytes = _mbuddy.alloc(opt_cmd_len) - if opt_cmd is None: - return 1 + if opt_cmd is None: return 1 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) @@ -558,8 +534,7 @@ def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: s llc_fp2: str = _llc_frame_ptr_flag() cmd_len: sizet = len(cc_cmd) + len(cc_flags) + len(llc_fp2) + len(obj_path) + len(compile_input) + 64 cmd: bytes = _mbuddy.alloc(cmd_len) - if cmd is None: - return 1 + if cmd is None: return 1 viperlib.snprintf(cmd, cmd_len, "%s %s%s -o %s %s", cc_cmd, cc_flags, llc_fp2, obj_path, compile_input) @@ -614,18 +589,15 @@ class LlcTask: def init_llc_task(task: LlcTask*, ir_path: str, output_dir: str, module_name: str, cc_cmd: str, cc_flags: str) -> int: """填充 llc 任务(全部 stdlib.malloc,线程运行期不被回收),0 成功""" - if task is None or ir_path is None or output_dir is None or module_name is None: - return 1 + if task is None or ir_path is None or output_dir is None or module_name is None: return 1 string.memset(task, 0, LlcTask.__sizeof__()) task.Result = -1 obj_path: str = build_sliced_path(output_dir, module_name, "obj") - if obj_path is None: - return 1 + if obj_path is None: return 1 # 模块 SHA1 sl: sizet = len(module_name) task.ModuleSha1 = stdlib.malloc(sl + 1) - if task.ModuleSha1 is None: - return 1 + if task.ModuleSha1 is None: return 1 string.strcpy(task.ModuleSha1, module_name) # llc 输入选择:ASan 模式必须喂插桩后的 .asan.ll,与串行路径 # compile_ll_to_obj 的 compile_input 同口径(否则 opt 生成了插桩产物 @@ -635,17 +607,14 @@ def init_llc_task(task: LlcTask*, ir_path: str, output_dir: str, # (降级回 LLVM IR),之后的 ASan OptCmd / LlcCmd 输入必须是 <...>.ll.local。 ll_local_path: str = _ir_sibling_path(ir_path, ".ll.local") mlir_opt_out: str = _ir_sibling_path(ir_path, ".mlir.opt") - if ll_local_path is None or mlir_opt_out is None: - return 1 + if ll_local_path is None or mlir_opt_out is None: return 1 mo_len: sizet = len(MLIR_OPT_CMD) + len(ir_path) + len(mlir_opt_out) + 16 task.MlirOptCmd = stdlib.malloc(mo_len) - if task.MlirOptCmd is None: - return 1 + if task.MlirOptCmd is None: return 1 viperlib.snprintf(task.MlirOptCmd, mo_len, "%s %s -o %s", MLIR_OPT_CMD, ir_path, mlir_opt_out) mt_len: sizet = len(MLIR_TRANSLATE_CMD) + len(mlir_opt_out) + len(ll_local_path) + 40 task.MlirTranslateCmd = stdlib.malloc(mt_len) - if task.MlirTranslateCmd is None: - return 1 + if task.MlirTranslateCmd is None: return 1 viperlib.snprintf(task.MlirTranslateCmd, mt_len, "%s --mlir-to-llvmir %s -o %s", MLIR_TRANSLATE_CMD, mlir_opt_out, ll_local_path) compile_input = ll_local_path @@ -653,12 +622,10 @@ def init_llc_task(task: LlcTask*, ir_path: str, output_dir: str, # 必须指向 asan_path;失败即置 Result) if _asan_mode != 0: asan_path: str = build_sliced_path(output_dir, module_name, "asan.ll") - if asan_path is None: - return 1 + if asan_path is None: return 1 opt_len: sizet = len(asan_path) + len(compile_input) + 192 task.OptCmd = stdlib.malloc(opt_len) - if task.OptCmd is None: - return 1 + if task.OptCmd is None: return 1 viperlib.snprintf(task.OptCmd, opt_len, "opt -passes=forceattrs,asan -force-attribute=sanitize_address" " -asan-globals=false -o %s %s", @@ -668,8 +635,7 @@ def init_llc_task(task: LlcTask*, ir_path: str, output_dir: str, llc_fp3: str = _llc_frame_ptr_flag() cmd_len: sizet = len(cc_cmd) + len(cc_flags) + len(llc_fp3) + len(obj_path) + len(compile_input) + 64 task.LlcCmd = stdlib.malloc(cmd_len) - if task.LlcCmd is None: - return 1 + if task.LlcCmd is None: return 1 viperlib.snprintf(task.LlcCmd, cmd_len, "%s %s%s -o %s %s", cc_cmd, cc_flags, llc_fp3, obj_path, compile_input) return 0 @@ -678,8 +644,7 @@ def init_llc_task(task: LlcTask*, ir_path: str, output_dir: str, def free_llc_task(task: LlcTask*): """释放任务的命令串;记录本身是任务数组的连续槽(非独立 malloc), 由调用方对数组整体 stdlib.free(此前对槽 free 导致 double-free)""" - if task is None: - return + if task is None: return if task.OptCmd is not None: stdlib.free(task.OptCmd) task.OptCmd = None @@ -704,8 +669,7 @@ def _phase2_write_cmd(cmd: str) -> None: 与 cmd.exe 批处理格式一致。bat 路径由模块级 _phase2_cmd_path 指定。 """ global _phase2_bat_init - if _phase2_cmd_path is None or cmd is None: - return + if _phase2_cmd_path is None or cmd is None: return f: rawptr[fileio.File] = fileio.File(_phase2_cmd_path, fileio.MODE.A) if f.closed: VLogger.error("phase2command: bat 打开失败", "phase2cmd") @@ -731,12 +695,10 @@ def _run_cmd_wait(cmd: str) -> int: worker 线程安全。CreateProcessA 返回 0 时立即取 GetLastError 并以 VLogger.warning 打印(外部命令未启动)。 """ - if cmd is None: - return -1 + if cmd is None: return -1 cl_len: sizet = len(cmd) cmd_line: bytes = stdlib.malloc(cl_len + 1) - if cmd_line is None: - return -1 + if cmd_line is None: return -1 string.strcpy(cmd_line, cmd) sa: w32.win32base.SECURITY_ATTRIBUTES = w32.win32base.SECURITY_ATTRIBUTES() si: win32process.STARTUPINFOA = win32process.STARTUPINFOA() @@ -765,8 +727,7 @@ def _run_cmd_wait(cmd: str) -> int: cp_err: uint32 = w32.win32base.GetLastError() VLogger.warning(f"CreateProcessA 失败 (GetLastError={cp_err}) 外部命令未启动: cmd={cmd}", "LLC") stdlib.free(cmd_line) - if ok == 0: - return -1 + if ok == 0: return -1 win32sync.WaitForSingleObject(pi.hProcess, w32.win32base.INFINITE) exit_code: uint32 = 0 win32process.GetExitCodeProcess(pi.hProcess, t.CPtr(&exit_code)) @@ -780,8 +741,7 @@ def _llc_task_worker(arg: t.CPtr) -> t.CPtr: Result 仅在命令链执行完后写入(初始 -1;join 超时保持 -1 → 报失败); ExitCode 记录失败命令的退出码,供主线程打印""" task: LlcTask* = (LlcTask*)(arg) - if task is None: - return t.CPtr(0) + if task is None: return t.CPtr(0) # MLIR 后端:先校验(mlir-opt)→ 降级(mlir-translate),再 ASan opt → llc if task.MlirOptCmd is not None: mo_rc: int = _run_cmd_wait(task.MlirOptCmd) @@ -821,26 +781,19 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int: tasks: LlcTask 记录连续数组(stdlib.malloc),每个记录由 init_llc_task 填充。 Returns: 0 全部成功;非 0 有失败(已打印失败模块与命令) """ - if tasks is None or task_count <= 0: - return 0 + if tasks is None or task_count <= 0: return 0 # --phase2command 模式:不 spawn 线程,把 opt(ASan)+ llc 命令全部写入 bat if _phase2_cmd_path is not None: for pi2 in range(task_count): tsk_p: LlcTask* = (LlcTask*)(uint64(tasks) + sizet(pi2) * LlcTask.__sizeof__()) - if tsk_p is None: - continue - if tsk_p.MlirOptCmd is not None: - _phase2_write_cmd(tsk_p.MlirOptCmd) - 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) + if tsk_p is None: continue + if tsk_p.MlirOptCmd is not None: _phase2_write_cmd(tsk_p.MlirOptCmd) + 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") return 0 - if max_threads <= 0: - max_threads = 1 + if max_threads <= 0: max_threads = 1 # 线程句柄数组:list[str](str=bytes=i8*,elem_size=8 显式)存句柄值;list[t.CPtr] 特化下 append 会读零页崩溃(原因待查),list[str] 全库验证稳定。 # start() 后立即取 handle 存入,join/close 直接对句柄操作,不依赖 Thread 对象存续。 handles: list[str]* = list[str](_mbuddy, 8) @@ -852,8 +805,7 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int: # 分批执行:batch_start 按 max_threads 步进(每批 spawn+join+close 一批句柄)。 for batch_start in range(0, task_count, max_threads): batch_n: int = max_threads - if batch_start + batch_n > task_count: - batch_n = task_count - batch_start + if batch_start + batch_n > task_count: batch_n = task_count - batch_start # 本批 spawn for j in range(batch_n): tsk: LlcTask* = (LlcTask*)(uint64(tasks) + sizet(batch_start + j) * slot_size) @@ -865,8 +817,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 线程 join 超时/失败(600 秒未完成)", "PhaseB") w32.win32base.CloseHandle(h_j) # 本批结果检查 for j in range(batch_n): @@ -927,15 +878,12 @@ def _CollectObjFilesImpl(base_dir: str, bd_len: sizet, if fname_len > 0: # 跳过 . 和 .. is_dot: int = 0 - if fname_len == 1 and fname[0] == '.': - is_dot = 1 - elif fname_len == 2 and fname[0] == '.' and fname[1] == '.': - is_dot = 1 + if fname_len == 1 and fname[0] == '.': is_dot = 1 + elif fname_len == 2 and fname[0] == '.' and fname[1] == '.': is_dot = 1 if is_dot == 0: attrs: ULONG = find_data.dwFileAttributes is_dir: int = 0 - if (attrs & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: - is_dir = 1 + if (attrs & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: is_dir = 1 if is_dir != 0: # 递归扫描子目录 sub_dir: bytes = _mbuddy.alloc(bd_len + fname_len + 2) @@ -948,16 +896,14 @@ def _CollectObjFilesImpl(base_dir: str, bd_len: sizet, # 检查是否是 .obj 文件 if fname_len > 4 and fname[fname_len - 4] == '.' and fname[fname_len - 3] == 'o' and fname[fname_len - 2] == 'b' and fname[fname_len - 1] == 'j': need: sizet = bd_len + 1 + fname_len + 2 - if out_pos + need >= out_size: - break + if out_pos + need >= out_size: break if out_pos > 0: out_buf[out_pos] = ' ' out_pos += 1 viperlib.snprintf(out_buf + out_pos, need, "%s/%s", base_dir, fname) out_pos += bd_len + 1 + fname_len - if w32.win32file.FindNextFileA(handle, find_data) == 0: - break + if w32.win32file.FindNextFileA(handle, find_data) == 0: break w32.win32file.FindClose(handle) return out_pos @@ -976,8 +922,7 @@ def collect_obj_files(includes_binary_dir: str, out_buf: bytes, out_size: sizet) Returns: 写入的字节数(不含 null 终止符),0 表示无文件或错误 """ - if includes_binary_dir is None or out_buf is None or out_size == 0: - return 0 + if includes_binary_dir is None or out_buf is None or out_size == 0: return 0 out_buf[0] = '\0' dir_len: sizet = len(includes_binary_dir) @@ -1002,10 +947,8 @@ def _append_host_export_implib(linker_flags: str, implib_path: str) -> str: 未开启工程的 linker_flags 不含该标志 ⇒ 原样返回,链接命令逐字节不变。 """ - if linker_flags is None or implib_path is None: - return linker_flags - if string.strstr(linker_flags, "--export-all-symbols") is None: - return linker_flags + if linker_flags is None or implib_path is None: return linker_flags + if string.strstr(linker_flags, "--export-all-symbols") is None: return linker_flags 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: @@ -1034,13 +977,11 @@ def link_obj_to_exe(output_dir: str, module_name: str, linker_cmd: str, linker_f Returns: 0 成功,非 0 失败 """ - if output_dir is None or linker_cmd is None or module_name is None: - return 1 + if output_dir is None or linker_cmd is None or module_name is None: return 1 # 构造切片 .obj 路径: output_dir/{sha1前缀}/{module_name}.obj obj_path: str = build_sliced_path(output_dir, module_name, "obj") - if obj_path is None: - return 1 + if obj_path is None: return 1 # 宿主 exe 导出(工程 linker.flags 含 --export-all-symbols 时)同步产出 import lib: # {output_dir}/{linker_output}.dll.a —— REPL 片段链接时把它加进命令行即可导入 @@ -1058,15 +999,12 @@ def link_obj_to_exe(output_dir: str, module_name: str, linker_cmd: str, linker_f # 收集 includes.binary 的 .obj 文件路径 EXTRA_BUF_SIZE: sizet = 32768 extra_objs: bytes = _mbuddy.alloc(EXTRA_BUF_SIZE) - if extra_objs is None: - return 1 + if extra_objs is None: return 1 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"附加 {extra_len} 字节的 includes.binary .obj 文件", "link") + else: VLogger.warning(f"includes.binary 无 .obj 文件: {includes_binary_dir}", "link") # 构造命令: clang++ {obj_path} extra_objs [static_libs/dynamic_libs] -o {output_dir}/{linker_output} linker_flags # 注意: .obj 与显式指定的 .a/.obj/.dll/.so 都必须在 -l 库标志之前,否则链接器无法解析符号依赖。 @@ -1074,8 +1012,7 @@ def link_obj_to_exe(output_dir: str, module_name: str, linker_cmd: str, linker_f # 改由 project.vpj 的 linker.static_libs / linker.dynamic_libs 显式声明,main.vp 在 --asan 下用 Config.asan_runtime_declared 校验。 use_flags: str = linker_flags static_libs: str = linker_static_libs - if static_libs is None: - static_libs = "" + if static_libs is None: static_libs = "" if linker_dynamic_libs is not None and len(linker_dynamic_libs) > 0: # 合并 static + dynamic 为单个空格分隔字符串(Viper str += 拼接 # 会生成非法 add i8* IR,须用 snprintf 构造) @@ -1091,8 +1028,7 @@ def link_obj_to_exe(output_dir: str, module_name: str, linker_cmd: str, linker_f sl_len: sizet = len(static_libs) cmd_len: sizet = len(linker_cmd) + len(obj_path) + len(use_flags) + len(output_dir) + len(linker_output) + extra_len + sl_len + 128 cmd: bytes = _mbuddy.alloc(cmd_len) - if cmd is None: - return 1 + if cmd is None: return 1 if sl_len > 0 and extra_len > 0: viperlib.snprintf(cmd, cmd_len, "%s %s %s %s -o %s/%s %s", linker_cmd, obj_path, extra_objs, static_libs, @@ -1124,12 +1060,9 @@ def link_obj_to_exe(output_dir: str, module_name: str, linker_cmd: str, linker_f VLogger.error(f"命令: {cmd}", "link") # 显示链接器错误输出 # 注意: subprocess 在 Windows 下将 stderr 合并到 stdout,result.stderr 总是 None - if result.stdout is not None: - VLogger.error(result.stdout, "link") - else: - VLogger.error("无输出捕获", "link") - if result.stderr is not None: - VLogger.error(result.stderr, "link") + if result.stdout is not None: VLogger.error(result.stdout, "link") + else: VLogger.error("无输出捕获", "link") + if result.stderr is not None: VLogger.error(result.stderr, "link") return 1 return 0 @@ -1152,18 +1085,14 @@ def asm_to_obj(asm_path: str, sha1_val: str, output_dir: str, Returns: 0 成功,非 0 失败 """ - if asm_path is None or sha1_val is None or output_dir is None: - return 1 + if asm_path is None or sha1_val is None or output_dir is None: return 1 obj_path: str = build_sliced_path(output_dir, sha1_val, "obj") - if obj_path is None: - return 1 + if obj_path is None: return 1 trip: str = triple - if trip is None or trip[0] == '\0': - trip = "x86_64-none-elf" + if trip is None or trip[0] == '\0': trip = "x86_64-none-elf" cmd_len: sizet = len("llvm-mc -triple=") + len(trip) + len(" -filetype=obj -o ") + len(obj_path) + len(asm_path) + 64 cmd: bytes = _mbuddy.alloc(cmd_len) - if cmd is None: - return 1 + if cmd is None: return 1 viperlib.snprintf(cmd, cmd_len, "llvm-mc -triple=%s -filetype=obj -o %s %s", trip, obj_path, asm_path) @@ -1177,10 +1106,8 @@ def asm_to_obj(asm_path: str, sha1_val: str, output_dir: str, VLogger.error("llvm-mc subprocess.run 返回 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) + 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") return 1 return 0 @@ -1203,8 +1130,7 @@ def compile_module_to_obj(ir_buf: bytes, ir_len: sizet, Returns: 0 成功,非 0 失败 """ - if ir_buf is None or temp_dir is None or output_dir is None or module_name is None: - return 1 + if ir_buf is None or temp_dir is None or output_dir is None or module_name is None: return 1 # Step 1: 写 .ll 文件 ret: int = write_ir_to_file(ir_buf, ir_len, temp_dir, module_name) @@ -1214,8 +1140,7 @@ def compile_module_to_obj(ir_buf: bytes, ir_len: sizet, # Step 2: 构造切片 .ll 路径并编译 → .obj ir_path: str = build_sliced_path(temp_dir, module_name, "ll") - if ir_path is None: - return 1 + if ir_path is None: return 1 ret = compile_ll_to_obj(ir_path, output_dir, module_name, cc_cmd, cc_flags) if ret != 0: @@ -1241,8 +1166,7 @@ def link_objs_to_exe(obj_paths: str, obj_paths_len: sizet, Returns: 0 成功,非 0 失败 """ - if obj_paths is None or obj_paths_len == 0 or linker_cmd is None: - return 1 + if obj_paths is None or obj_paths_len == 0 or linker_cmd is None: return 1 # 去重 .obj 路径:同一模块的 obj 可能被多个收集环节加入(Phase B+ 新编译的 obj_paths 与 Phase C reachable 收集指向同一文件); # 同一路径在链接命令中出现两次即重复符号(无 --allow-multiple-definition 的工程会 ld.lld 报错),故保留首次出现、后续跳过。 @@ -1254,25 +1178,19 @@ def link_objs_to_exe(obj_paths: str, obj_paths_len: sizet, dsrc_i: sizet = 0 while dsrc_i < obj_paths_len: # 跳过前导空格 - while dsrc_i < obj_paths_len and obj_paths[dsrc_i] == ' ': - dsrc_i += 1 - if dsrc_i >= obj_paths_len: - break + while dsrc_i < obj_paths_len and obj_paths[dsrc_i] == ' ': dsrc_i += 1 + if dsrc_i >= obj_paths_len: break dstart: sizet = dsrc_i - while dsrc_i < obj_paths_len and obj_paths[dsrc_i] != ' ': - dsrc_i += 1 + while dsrc_i < obj_paths_len and obj_paths[dsrc_i] != ' ': dsrc_i += 1 dtlen: sizet = dsrc_i - dstart # 检查 dedup 中是否已有相同 token ddup: int = 0 dj: sizet = 0 while dj < dpos: - while dj < dpos and dedup[dj] == ' ': - dj += 1 - if dj >= dpos: - break + while dj < dpos and dedup[dj] == ' ': dj += 1 + if dj >= dpos: break ds2: sizet = dj - while dj < dpos and dedup[dj] != ' ': - dj += 1 + while dj < dpos and dedup[dj] != ' ': dj += 1 dt2len: sizet = dj - ds2 if dt2len == dtlen: deq: int = 1 @@ -1299,11 +1217,9 @@ def link_objs_to_exe(obj_paths: str, obj_paths_len: sizet, # 收集 includes.binary 的 .obj 文件路径 EXTRA_BUF_SIZE: sizet = 32768 extra_objs: bytes = _mbuddy.alloc(EXTRA_BUF_SIZE) - if extra_objs is None: - return 1 + if extra_objs is None: return 1 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 includes_binary_dir is not None: extra_len = collect_obj_files(includes_binary_dir, extra_objs, EXTRA_BUF_SIZE) # 构造命令: clang++ obj_paths extra_objs -o linker_output linker_flags # ASan 运行库同样不再由 TPV 注入(在 link_obj_to_exe 里已有说明): @@ -1319,8 +1235,7 @@ def link_objs_to_exe(obj_paths: str, obj_paths_len: sizet, linker_flags = _append_traceback_dbghelp(linker_flags) use_flags: str = linker_flags static_libs2: str = linker_static_libs - if static_libs2 is None: - static_libs2 = "" + if static_libs2 is None: static_libs2 = "" if linker_dynamic_libs is not None and len(linker_dynamic_libs) > 0: # 合并 static + dynamic(Viper str += 拼接生成非法 IR,用 snprintf) merged_sl2: str = _mbuddy.alloc(len(static_libs2) + len(linker_dynamic_libs) + 2) @@ -1335,8 +1250,7 @@ def link_objs_to_exe(obj_paths: str, obj_paths_len: sizet, sl2_len: sizet = len(static_libs2) cmd_len: sizet = len(linker_cmd) + obj_paths_len + len(use_flags) + len(linker_output) + extra_len + sl2_len + 128 cmd: bytes = _mbuddy.alloc(cmd_len) - if cmd is None: - return 1 + if cmd is None: return 1 # linker.static_libs 显式静态链接文件位于 .obj 之后、-o 之前 if sl2_len > 0 and extra_len > 0: viperlib.snprintf(cmd, cmd_len, "%s %s %s %s -o %s %s", @@ -1368,8 +1282,7 @@ def link_objs_to_exe(obj_paths: str, obj_paths_len: sizet, if result.returncode != 0: # 先用 stdio.printf 直接输出 clang++ 的完整错误输出(含 undefined reference) # 必须在 VLogger.error 之前输出,因为 VLogger.error 会调用 sys.exit(1) 终止进程 - if result.stdout is not None: - stdio.printf("=== clang++ 链接错误输出 ===\n%s\n", result.stdout) + if result.stdout is not None: stdio.printf("=== clang++ 链接错误输出 ===\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") @@ -1508,55 +1421,44 @@ def _tb_wr_u64(buf: bytes, off: sizet, v: uint64): # ---- tiny string helpers (no re module) ---- def _tb_cc(s: str, i: sizet) -> int: """Byte value at s[i] as 0..255 (chars in DWARF text are ASCII).""" - if s is None: - return 0 + if s is None: return 0 return int(s[i]) & 0xFF def _tb_contains(s: str, sub: str) -> int: - if s is None or sub is None: - return 0 + if s is None or sub is None: return 0 return 1 if string.strstr(s, sub) is not None else 0 def _tb_startswith(s: str, pfx: str) -> int: - if s is None or pfx is None: - return 0 + if s is None or pfx is None: return 0 pl: sizet = string.strlen(pfx) - if string.strlen(s) < pl: - return 0 + if string.strlen(s) < pl: return 0 return 1 if string.strncmp(s, pfx, pl) == 0 else 0 def _tb_ltrim(s: str) -> str: - if s is None: - return None + if s is None: return None i: sizet = 0 - while _tb_cc(s, i) == 32 or _tb_cc(s, i) == 9: - i += 1 + while _tb_cc(s, i) == 32 or _tb_cc(s, i) == 9: i += 1 return s + i def _tb_len_trimmed(s: str) -> sizet: - if s is None: - return 0 + if s is None: return 0 n: sizet = string.strlen(s) while n > 0: c: int = _tb_cc(s, n - 1) - if c == 32 or c == 9 or c == 13: - n -= 1 - else: - break + if c == 32 or c == 9 or c == 13: n -= 1 + else: break return n def _tb_dup_span(mb: memhub.MemBuddy*, src: str, n: sizet) -> str: """Copy src[0..n) into a fresh NUL-terminated string.""" - if src is None: - return None + if src is None: return None out: str = mb.alloc(n + 1) - if out is None: - return None + if out is None: return None string.strncpy(out, src, n) out[n] = '\0' return out @@ -1564,43 +1466,32 @@ def _tb_dup_span(mb: memhub.MemBuddy*, src: str, n: sizet) -> str: def _tb_unquote(mb: memhub.MemBuddy*, v: str) -> str: """Trim trailing spaces and strip one pair of surrounding quotes (TPC _Unquote).""" - if v is None: - return None + if v is None: return None n: sizet = _tb_len_trimmed(v) - if n >= 2 and _tb_cc(v, 0) == 34 and _tb_cc(v, n - 1) == 34: - return _tb_dup_span(mb, v + 1, n - 2) + if n >= 2 and _tb_cc(v, 0) == 34 and _tb_cc(v, n - 1) == 34: return _tb_dup_span(mb, v + 1, n - 2) return _tb_dup_span(mb, v, n) def _tb_is_abs_path(s: str) -> int: - if s is None: - return 0 + if s is None: return 0 c0: int = _tb_cc(s, 0) - if c0 == 0: - return 0 - if c0 == 47 or c0 == 92: - return 1 - if _tb_cc(s, 1) == 58: - return 1 + if c0 == 0: return 0 + if c0 == 47 or c0 == 92: return 1 + if _tb_cc(s, 1) == 58: return 1 return 0 def _tb_join(mb: memhub.MemBuddy*, base: str, name: str) -> str: """Join base and name with a separator unless base already ends in one.""" - if base is None or string.strlen(base) == 0: - return name - if name is None: - return base + if base is None or string.strlen(base) == 0: return name + if name is None: return base bl: sizet = string.strlen(base) nl: sizet = string.strlen(name) buf: str = mb.alloc(bl + nl + 2) - if buf is None: - return name + if buf is None: return name last: int = _tb_cc(base, bl - 1) - if last == 47 or last == 92: - viperlib.snprintf(buf, bl + nl + 2, "%s%s", base, name) - else: - viperlib.snprintf(buf, bl + nl + 2, "%s/%s", base, name) + if last == 47 or last == 92: viperlib.snprintf(buf, bl + nl + 2, "%s%s", base, name) + else: viperlib.snprintf(buf, bl + nl + 2, "%s/%s", base, name) return buf @@ -1618,8 +1509,7 @@ def _tb_parse_dec(s: str) -> int: """ v: int = 0 i: sizet = 0 - while _tb_cc(s, i) == 32 or _tb_cc(s, i) == 9: - i += 1 + while _tb_cc(s, i) == 32 or _tb_cc(s, i) == 9: i += 1 while _tb_cc(s, i) >= 48 and _tb_cc(s, i) <= 57: v = v * 10 + (_tb_cc(s, i) - 48) i += 1 @@ -1630,8 +1520,7 @@ def _tb_bracket_idx(s: str) -> int: """Parse the N in '[N]' (first bracket group of the line).""" i: sizet = 0 while _tb_cc(s, i) != 0: - if _tb_cc(s, i) == 91: - return _tb_parse_dec(s + i + 1) + if _tb_cc(s, i) == 91: return _tb_parse_dec(s + i + 1) i += 1 return -1 @@ -1639,32 +1528,26 @@ def _tb_bracket_idx(s: str) -> int: def _tb_after_bracket(s: str) -> str: i: sizet = 0 while _tb_cc(s, i) != 0: - if _tb_cc(s, i) == 93: - return s + i + 1 + if _tb_cc(s, i) == 93: return s + i + 1 i += 1 return None def _tb_value_after_sep(s: str) -> str: """Return the text after the first '=' or ':' (left-trimmed), or None.""" - if s is None: - return None + if s is None: return None i: sizet = 0 while _tb_cc(s, i) != 0: c: int = _tb_cc(s, i) - if c == 61 or c == 58: - return _tb_ltrim(s + i + 1) + if c == 61 or c == 58: return _tb_ltrim(s + i + 1) i += 1 return None def _tb_hex_digit(ch: int) -> int: - if ch >= 48 and ch <= 57: - return ch - 48 - if ch >= 97 and ch <= 102: - return ch - 87 - if ch >= 65 and ch <= 70: - return ch - 55 + if ch >= 48 and ch <= 57: return ch - 48 + if ch >= 97 and ch <= 102: return ch - 87 + if ch >= 65 and ch <= 70: return ch - 55 return -1 @@ -1675,18 +1558,13 @@ def _tb_hex_in_parens(s: str, key: str) -> uint64: that way, and a 0 result is harmless (out of the image VA range -> dropped). """ p: str = string.strstr(s, key) - if p is None: - return 0 + if p is None: return 0 p = p + string.strlen(key) - while _tb_cc(p, 0) == 32 or _tb_cc(p, 0) == 9: - p = p + 1 - if _tb_cc(p, 0) != 40: - return 0 + while _tb_cc(p, 0) == 32 or _tb_cc(p, 0) == 9: p = p + 1 + if _tb_cc(p, 0) != 40: return 0 p = p + 1 - while _tb_cc(p, 0) == 32: - p = p + 1 - if _tb_cc(p, 0) != 48 or _tb_cc(p, 1) != 120: - return 0 + while _tb_cc(p, 0) == 32: p = p + 1 + if _tb_cc(p, 0) != 48 or _tb_cc(p, 1) != 120: return 0 q: str = p + 2 v: uint64 = 0 i: sizet = 0 @@ -1701,29 +1579,23 @@ def _tb_hex_in_parens(s: str, key: str) -> uint64: def _tb_quoted_after(mb: memhub.MemBuddy*, s: str, key: str) -> str: """Extract the first double-quoted string following key (DW_AT_name ("...")).""" p: str = string.strstr(s, key) - if p is None: - return None + if p is None: return None p = p + string.strlen(key) q: str = string.strchr(p, 40) - if q is None: - return None + if q is None: return None q = q + 1 - while _tb_cc(q, 0) == 32: - q = q + 1 - if _tb_cc(q, 0) != 34: - return None + while _tb_cc(q, 0) == 32: q = q + 1 + if _tb_cc(q, 0) != 34: return None q = q + 1 start: str = q n: sizet = 0 while _tb_cc(q, n) != 0: c: int = _tb_cc(q, n) if c == 92: - if _tb_cc(q, n + 1) == 0: - break + if _tb_cc(q, n + 1) == 0: break n += 2 continue - if c == 34: - break + if c == 34: break n += 1 return _tb_dup_span(mb, start, n) @@ -1731,8 +1603,7 @@ def _tb_quoted_after(mb: memhub.MemBuddy*, s: str, key: str) -> str: def _tb_dir_lookup(dirs: bytes, count: int, idx: int) -> str: i: int = 0 while i < count: - if int(_tb_rd_u32(dirs, sizet(i) * TB_DIR_SIZE)) == idx: - return rawptr(_tb_rd_u64(dirs, sizet(i) * TB_DIR_SIZE + 8)) + if int(_tb_rd_u32(dirs, sizet(i) * TB_DIR_SIZE)) == idx: return rawptr(_tb_rd_u64(dirs, sizet(i) * TB_DIR_SIZE + 8)) i += 1 return None @@ -1740,8 +1611,7 @@ def _tb_dir_lookup(dirs: bytes, count: int, idx: int) -> str: def _tb_file_rec(files: bytes, count: int, idx: int) -> int: i: int = 0 while i < count: - if int(_tb_rd_u32(files, sizet(i) * TB_FILE_SIZE)) == idx: - return i + if int(_tb_rd_u32(files, sizet(i) * TB_FILE_SIZE)) == idx: return i i += 1 return -1 @@ -1751,8 +1621,7 @@ def _tb_resolve_file(mb: memhub.MemBuddy*, files: bytes, fcount: int, """Resolve a file-table entry to a path (absolute name wins, else dir join).""" roff: sizet = sizet(frec) * TB_FILE_SIZE cached: uint64 = _tb_rd_u64(files, roff + 24) - if cached != 0: - return rawptr(cached) + if cached != 0: return rawptr(cached) name: str = rawptr(_tb_rd_u64(files, roff + 8)) path: str = name if name is not None and _tb_is_abs_path(name) == 0: @@ -1761,11 +1630,9 @@ def _tb_resolve_file(mb: memhub.MemBuddy*, files: bytes, fcount: int, if base is not None and string.strlen(base) > 0: if _tb_is_abs_path(base) == 0: root: str = _tb_dir_lookup(dirs, dcount, 0) - if root is not None and _tb_is_abs_path(root) != 0: - base = _tb_join(mb, root, base) + if root is not None and _tb_is_abs_path(root) != 0: base = _tb_join(mb, root, base) path = _tb_join(mb, base, name) - if path is None or string.strlen(path) == 0: - path = "??" + if path is None or string.strlen(path) == 0: path = "??" _tb_wr_u64(files, roff + 24, uint64(path)) return path @@ -1773,8 +1640,7 @@ def _tb_resolve_file(mb: memhub.MemBuddy*, files: bytes, fcount: int, def _tb_grow_rec(mb: memhub.MemBuddy*, buf: bytes, old_cap: int, rec_size: int, new_cap: int) -> bytes: nb: bytes = mb.alloc(sizet(new_cap) * sizet(rec_size)) - if nb is None: - return None + if nb is None: return None string.memcpy(nb, buf, sizet(old_cap) * sizet(rec_size)) mb.free(buf) return nb @@ -1782,8 +1648,7 @@ def _tb_grow_rec(mb: memhub.MemBuddy*, buf: bytes, old_cap: int, def _tb_emit_row(mb: memhub.MemBuddy*, d: TbDump*, addr: uint64, path: str, line: int, fname: str = None) -> int: - if d is None: - return 1 + if d is None: return 1 if d.RowCount >= d.RowCap: ncap: int = d.RowCap * 2 nb: bytes = _tb_grow_rec(mb, d.RowBuf, d.RowCap, TB_ROW_SIZE, ncap) @@ -1797,8 +1662,7 @@ def _tb_emit_row(mb: memhub.MemBuddy*, d: TbDump*, _tb_wr_u64(d.RowBuf, off + TB_ROW_OFF_FILE, uint64(path)) _tb_wr_u32(d.RowBuf, off + TB_ROW_OFF_LINE, uint64(line)) fv: uint64 = 0 - if fname is not None: - fv = uint64(fname) + if fname is not None: fv = uint64(fname) _tb_wr_u64(d.RowBuf, off + TB_ROW_OFF_FUNC, fv) d.RowCount = d.RowCount + 1 d.RawRowCount = d.RawRowCount + 1 @@ -1807,8 +1671,7 @@ def _tb_emit_row(mb: memhub.MemBuddy*, d: TbDump*, def _tb_emit_func(mb: memhub.MemBuddy*, d: TbDump*, low: uint64, high: uint64, name: str) -> int: - if d is None: - return 1 + if d is None: return 1 if d.FuncCount >= d.FuncCap: ncap: int = d.FuncCap * 2 nb: bytes = _tb_grow_rec(mb, d.FuncBuf, d.FuncCap, TB_FUNC_SIZE, ncap) @@ -1827,35 +1690,28 @@ def _tb_emit_func(mb: memhub.MemBuddy*, d: TbDump*, def _tb_func_name_for(fbuf: bytes, fcount: int, rva: uint64) -> str: """bisect_right over the (sorted) func low_pc table, then range check.""" - if fbuf is None or fcount <= 0: - return None + if fbuf is None or fcount <= 0: return None lo: int = 0 hi: int = fcount while lo < hi: mid: int = lo + (hi - lo) / 2 - if _tb_rd_u64(fbuf, sizet(mid) * TB_FUNC_SIZE) <= rva: - lo = mid + 1 - else: - hi = mid + if _tb_rd_u64(fbuf, sizet(mid) * TB_FUNC_SIZE) <= rva: lo = mid + 1 + else: hi = mid k: int = lo - 1 - if k < 0: - return None + if k < 0: return None low: uint64 = _tb_rd_u64(fbuf, sizet(k) * TB_FUNC_SIZE) high: uint64 = _tb_rd_u64(fbuf, sizet(k) * TB_FUNC_SIZE + 8) - if low <= rva and rva < high: - return rawptr(_tb_rd_u64(fbuf, sizet(k) * TB_FUNC_SIZE + 16)) + if low <= rva and rva < high: return rawptr(_tb_rd_u64(fbuf, sizet(k) * TB_FUNC_SIZE + 16)) return None def _tb_intern(p: TbPool*, s: str) -> uint64: """Intern s into the pool (linear scan; keeps offset 0 as the empty sentinel).""" - if p is None or s is None: - return 0 + if p is None or s is None: return 0 k: int = 0 while k < p.OffCount: o: uint64 = _tb_rd_u64(p.Offs, sizet(k) * 8) - if string.strcmp(p.Pool + sizet(o), s) == 0: - return o + if string.strcmp(p.Pool + sizet(o), s) == 0: return o k += 1 off: uint64 = uint64(p.PoolLen) n: sizet = string.strlen(s) @@ -1870,11 +1726,9 @@ def _tb_intern(p: TbPool*, s: str) -> uint64: def _tb_read_pe_layout(mb: memhub.MemBuddy*, exe_path: str) -> TbPeLayout*: """Read (ImageBase, SizeOfImage, .text RVA) from the PE headers.""" lay: TbPeLayout* = TbPeLayout() - if lay is None: - return None + if lay is None: return None f: rawptr[fileio.File] = fileio.File(exe_path, fileio.MODE.R) - if f.closed: - return lay + if f.closed: return lay HEAD: sizet = 4096 head: bytes = mb.alloc(HEAD) if head is None: @@ -1882,29 +1736,21 @@ def _tb_read_pe_layout(mb: memhub.MemBuddy*, exe_path: str) -> TbPeLayout*: return lay got: LONG = f.read_all(head, HEAD) f.close() - if got < 0x40: - return lay - if _tb_cc(head, 0) != 77 or _tb_cc(head, 1) != 90: - return lay + if got < 0x40: return lay + if _tb_cc(head, 0) != 77 or _tb_cc(head, 1) != 90: return lay e_lfanew: uint64 = uint64(_tb_rd_u32(head, 0x3C)) - if e_lfanew + 24 > uint64(got): - return lay - if _tb_cc(head, sizet(e_lfanew)) != 80 or _tb_cc(head, sizet(e_lfanew) + 1) != 69: - return lay + if e_lfanew + 24 > uint64(got): return lay + if _tb_cc(head, sizet(e_lfanew)) != 80 or _tb_cc(head, sizet(e_lfanew) + 1) != 69: return lay coff: sizet = sizet(e_lfanew) + 4 nsec: uint64 = uint64(_tb_rd_u16(head, coff + 2)) optsz: uint64 = uint64(_tb_rd_u16(head, coff + 16)) opt: sizet = coff + 20 - if uint64(opt) + 32 > uint64(got): - return lay + if uint64(opt) + 32 > uint64(got): return lay magic: uint64 = uint64(_tb_rd_u16(head, opt)) img_base: uint64 = 0 - if magic == 0x20B: - img_base = _tb_rd_u64(head, opt + 24) - elif magic == 0x10B: - img_base = uint64(_tb_rd_u32(head, opt + 28)) - else: - return lay + if magic == 0x20B: img_base = _tb_rd_u64(head, opt + 24) + elif magic == 0x10B: img_base = uint64(_tb_rd_u32(head, opt + 28)) + else: return lay size_img: uint64 = uint64(_tb_rd_u32(head, opt + 56)) sec_off: sizet = opt + sizet(optsz) text_rva: uint64 = 0x1000 @@ -1914,18 +1760,15 @@ def _tb_read_pe_layout(mb: memhub.MemBuddy*, exe_path: str) -> TbPeLayout*: si: uint64 = 0 while si < nsec: base: sizet = sec_off + sizet(si) * 40 - if uint64(base) + 40 > uint64(got): - break + if uint64(base) + 40 > uint64(got): break va: uint64 = uint64(_tb_rd_u32(head, base + 12)) have_sec = 1 - if va < min_rva: - min_rva = va + if va < min_rva: min_rva = va if _tb_cc(head, base) == 46 and _tb_cc(head, base + 1) == 116 and _tb_cc(head, base + 2) == 101 and _tb_cc(head, base + 3) == 120 and _tb_cc(head, base + 4) == 116: text_rva = va found_text = 1 si += 1 - if found_text == 0 and have_sec != 0 and min_rva != 0xFFFFFFFF: - text_rva = min_rva + if found_text == 0 and have_sec != 0 and min_rva != 0xFFFFFFFF: text_rva = min_rva lay.ImageBase = img_base lay.SizeOfImage = size_img lay.TextRva = text_rva @@ -1936,8 +1779,7 @@ def _tb_read_pe_layout(mb: memhub.MemBuddy*, exe_path: str) -> TbPeLayout*: def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump*: """Parse llvm-dwarfdump text into a row table (addr, path, line) and a func table.""" d: TbDump* = TbDump() - if d is None: - return None + if d is None: return None LINE_CAP: sizet = 8192 d.RowBuf = mb.alloc(sizet(TB_ROW_CAP0) * TB_ROW_SIZE) d.RowCap = TB_ROW_CAP0 @@ -1968,18 +1810,13 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump*: pos: sizet = 0 while pos < dlen: ls: sizet = pos - while pos < dlen and _tb_cc(dump, pos) != 10: - pos += 1 + while pos < dlen and _tb_cc(dump, pos) != 10: pos += 1 le: sizet = pos - if pos < dlen: - pos += 1 - if le > ls and _tb_cc(dump, le - 1) == 13: - le -= 1 + if pos < dlen: pos += 1 + if le > ls and _tb_cc(dump, le - 1) == 13: le -= 1 ll: sizet = le - ls - if ll == 0: - continue - if ll >= LINE_CAP: - ll = LINE_CAP - 1 + if ll == 0: continue + if ll >= LINE_CAP: ll = LINE_CAP - 1 string.strncpy(linebuf, dump + ls, ll) linebuf[ll] = '\0' st: str = _tb_ltrim(linebuf) @@ -2036,13 +1873,11 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump*: _tb_wr_u64(dirs, sizet(dir_count) * TB_DIR_SIZE + 8, uint64(_tb_unquote(mb, val))) dir_count += 1 pkind = 0 - else: - pkind = 2 + else: pkind = 2 continue if _tb_startswith(st, "name:") != 0 and pkind != 0: val2: str = _tb_unquote(mb, _tb_ltrim(st + 5)) - if pkind == 1: - pname = val2 + if pkind == 1: pname = val2 else: if dir_count < TB_DIR_CAP and val2 is not None: _tb_wr_u32(dirs, sizet(dir_count) * TB_DIR_SIZE, uint64(pidx)) @@ -2083,18 +1918,14 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump*: addr = (addr << 4) | uint64(hd) ri += 1 hd = _tb_hex_digit(_tb_cc(linebuf, ri)) - while ri < ll and (_tb_cc(linebuf, ri) == 32 or _tb_cc(linebuf, ri) == 9): - ri += 1 + while ri < ll and (_tb_cc(linebuf, ri) == 32 or _tb_cc(linebuf, ri) == 9): ri += 1 lno: int = 0 while ri < ll and _tb_cc(linebuf, ri) >= 48 and _tb_cc(linebuf, ri) <= 57: lno = lno * 10 + (_tb_cc(linebuf, ri) - 48) ri += 1 - while ri < ll and (_tb_cc(linebuf, ri) == 32 or _tb_cc(linebuf, ri) == 9): - ri += 1 - while ri < ll and _tb_cc(linebuf, ri) >= 48 and _tb_cc(linebuf, ri) <= 57: - ri += 1 - while ri < ll and (_tb_cc(linebuf, ri) == 32 or _tb_cc(linebuf, ri) == 9): - ri += 1 + while ri < ll and (_tb_cc(linebuf, ri) == 32 or _tb_cc(linebuf, ri) == 9): ri += 1 + while ri < ll and _tb_cc(linebuf, ri) >= 48 and _tb_cc(linebuf, ri) <= 57: ri += 1 + while ri < ll and (_tb_cc(linebuf, ri) == 32 or _tb_cc(linebuf, ri) == 9): ri += 1 fidx: int = 0 while ri < ll and _tb_cc(linebuf, ri) >= 48 and _tb_cc(linebuf, ri) <= 57: fidx = fidx * 10 + (_tb_cc(linebuf, ri) - 48) @@ -2102,12 +1933,9 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump*: if lno > 0: frec: int = _tb_file_rec(files, file_count, fidx) fpath: str = None - if frec >= 0: - fpath = _tb_resolve_file(mb, files, file_count, dirs, dir_count, frec) - if fpath is None: - fpath = "??" - if _tb_emit_row(mb, d, addr, fpath, lno) != 0: - return None + if frec >= 0: fpath = _tb_resolve_file(mb, files, file_count, dirs, dir_count, frec) + if fpath is None: fpath = "??" + if _tb_emit_row(mb, d, addr, fpath, lno) != 0: return None continue # ---- DWARF debug_info subprogram parsing ---- @@ -2116,22 +1944,18 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump*: hi: uint64 = cur_low + 1 if cur_has_high != 0: hi = cur_high - if hi <= cur_low: - hi = cur_low + cur_high + if hi <= cur_low: hi = cur_low + cur_high if hi > cur_low: - if _tb_emit_func(mb, d, cur_low, hi, cname) != 0: - return None + if _tb_emit_func(mb, d, cur_low, hi, cname) != 0: return None in_prog = 0 cur_low = 0 cur_high = 0 cur_has_low = 0 cur_has_high = 0 cname = None - if _tb_contains(linebuf, "DW_TAG_subprogram") != 0: - in_prog = 1 - continue - if in_prog == 0: + if _tb_contains(linebuf, "DW_TAG_subprogram") != 0: in_prog = 1 continue + if in_prog == 0: continue if _tb_contains(linebuf, "DW_AT_low_pc") != 0: cur_low = _tb_hex_in_parens(linebuf, "DW_AT_low_pc") cur_has_low = 1 @@ -2149,11 +1973,9 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump*: hi2: uint64 = cur_low + 1 if cur_has_high != 0: hi2 = cur_high - if hi2 <= cur_low: - hi2 = cur_low + cur_high + if hi2 <= cur_low: hi2 = cur_low + cur_high if hi2 > cur_low: - if _tb_emit_func(mb, d, cur_low, hi2, cname) != 0: - return None + if _tb_emit_func(mb, d, cur_low, hi2, cname) != 0: return None return d @@ -2222,16 +2044,14 @@ class TbCallParse: def _tb_next_pow2(n: int) -> int: p: int = 16 - while p < n: - p = p * 2 + while p < n: p = p * 2 return p def _tb_strhash(s: str) -> uint64: """FNV-1a(32 位起点 + 64 位素数,仅用于哈希表寻址)。""" h: uint64 = 0x811C9DC5 - if s is None: - return h + if s is None: return h i: sizet = 0 while _tb_cc(s, i) != 0: h = (h ^ uint64(_tb_cc(s, i))) * 0x100000001B3 @@ -2241,8 +2061,7 @@ def _tb_strhash(s: str) -> uint64: def _tb_grp_get(grp: bytes, cap: int, caller: str, callee: str, do_insert: int) -> int: """按 (caller,callee) 查槽;do_insert=1 时未命中就地插入。返回槽号或 -1。""" - if grp is None or cap <= 0 or caller is None or callee is None: - return -1 + if grp is None or cap <= 0 or caller is None or callee is None: return -1 mask: uint64 = uint64(cap - 1) hv: uint64 = (_tb_strhash(caller) * 0x100000001B3 + _tb_strhash(callee)) & mask i: int = 0 @@ -2250,8 +2069,7 @@ def _tb_grp_get(grp: bytes, cap: int, caller: str, callee: str, do_insert: int) slot: int = int((hv + uint64(i)) & mask) off: sizet = sizet(slot) * TB_GRP_SIZE if uint64(_tb_rd_u32(grp, off + TB_GRP_OFF_USED)) == 0: - if do_insert == 0: - return -1 + if do_insert == 0: return -1 _tb_wr_u32(grp, off + TB_GRP_OFF_USED, uint64(1)) _tb_wr_u64(grp, off + TB_GRP_OFF_CALLER, uint64(caller)) _tb_wr_u64(grp, off + TB_GRP_OFF_CALLEE, uint64(callee)) @@ -2261,22 +2079,19 @@ def _tb_grp_get(grp: bytes, cap: int, caller: str, callee: str, do_insert: int) return slot sc: str = rawptr(_tb_rd_u64(grp, off + TB_GRP_OFF_CALLER)) sk: str = rawptr(_tb_rd_u64(grp, off + TB_GRP_OFF_CALLEE)) - if sc is not None and sk is not None and string.strcmp(sc, caller) == 0 and string.strcmp(sk, callee) == 0: - return slot + if sc is not None and sk is not None and string.strcmp(sc, caller) == 0 and string.strcmp(sk, callee) == 0: return slot i += 1 return -1 def _tb_cp_init(mb: memhub.MemBuddy*) -> TbCallParse*: cp: TbCallParse* = TbCallParse() - if cp is None: - return None + if cp is None: return None cp.CrCap = 1024 cp.FrCap = 1024 cp.Cr = mb.alloc(sizet(cp.CrCap) * TB_CR_SIZE) cp.Fr = mb.alloc(sizet(cp.FrCap) * TB_FR_SIZE) - if cp.Cr is None or cp.Fr is None: - return None + if cp.Cr is None or cp.Fr is None: return None cp.CrN = 0 cp.FrN = 0 return cp @@ -2323,8 +2138,7 @@ def _tb_cp_add_fr(mb: memhub.MemBuddy*, cp: TbCallParse*, def _tb_read_whole(mb: memhub.MemBuddy*, path: str) -> str: """读整个文件为 NUL 结尾字符串(失败返回 None)。""" f: rawptr[fileio.File] = fileio.File(path, fileio.MODE.R) - if f.closed: - return None + if f.closed: return None sz: LONGLONG = f.size() if sz < 0: f.close() @@ -2335,8 +2149,7 @@ def _tb_read_whole(mb: memhub.MemBuddy*, path: str) -> str: return None got: LONG = f.read_all(buf, ULONG(sz) + ULONG(2)) f.close() - if got < 0: - return None + if got < 0: return None return buf @@ -2344,28 +2157,21 @@ def _tb_parse_f_line(mb: memhub.MemBuddy*, s: str, a: sizet, b: sizet, cp: TbCallParse*) -> int: """解析 `F\t\t\t`。""" p: sizet = a - while p < b and _tb_cc(s, p) != 9: - p += 1 - if p >= b: - return 0 + while p < b and _tb_cc(s, p) != 9: p += 1 + if p >= b: return 0 p += 1 f2: sizet = p - while f2 < b and _tb_cc(s, f2) != 9: - f2 += 1 - if f2 >= b: - return 0 + while f2 < b and _tb_cc(s, f2) != 9: f2 += 1 + if f2 >= b: return 0 sym: str = _tb_dup_span(mb, s + p, f2 - p) p = f2 + 1 f3: sizet = p - while f3 < b and _tb_cc(s, f3) != 9: - f3 += 1 - if f3 >= b: - return 0 + while f3 < b and _tb_cc(s, f3) != 9: f3 += 1 + if f3 >= b: return 0 defline: int = _tb_parse_dec(s + p) p = f3 + 1 file: str = _tb_dup_span(mb, s + p, b - p) - if sym is None or file is None: - return 0 + if sym is None or file is None: return 0 return _tb_cp_add_fr(mb, cp, sym, file, defline) @@ -2373,35 +2179,26 @@ def _tb_parse_c_line(mb: memhub.MemBuddy*, s: str, a: sizet, b: sizet, cp: TbCallParse*) -> int: """解析 `C\t\t\t\t`。""" p: sizet = a - while p < b and _tb_cc(s, p) != 9: - p += 1 - if p >= b: - return 0 + while p < b and _tb_cc(s, p) != 9: p += 1 + if p >= b: return 0 p += 1 e2: sizet = p - while e2 < b and _tb_cc(s, e2) != 9: - e2 += 1 - if e2 >= b: - return 0 + while e2 < b and _tb_cc(s, e2) != 9: e2 += 1 + if e2 >= b: return 0 caller: str = _tb_dup_span(mb, s + p, e2 - p) p = e2 + 1 e3: sizet = p - while e3 < b and _tb_cc(s, e3) != 9: - e3 += 1 - if e3 >= b: - return 0 + while e3 < b and _tb_cc(s, e3) != 9: e3 += 1 + if e3 >= b: return 0 callee: str = _tb_dup_span(mb, s + p, e3 - p) p = e3 + 1 e4: sizet = p - while e4 < b and _tb_cc(s, e4) != 9: - e4 += 1 - if e4 >= b: - return 0 + while e4 < b and _tb_cc(s, e4) != 9: e4 += 1 + if e4 >= b: return 0 line: int = _tb_parse_dec(s + p) p = e4 + 1 file: str = _tb_dup_span(mb, s + p, b - p) - if caller is None or callee is None or file is None: - return 0 + if caller is None or callee is None or file is None: return 0 return _tb_cp_add_cr(mb, cp, caller, callee, file, line) @@ -2415,42 +2212,34 @@ def _tb_parse_vpcall_file(mb: memhub.MemBuddy*, path: str, pos: sizet = 0 while pos < n: ls: sizet = pos - while pos < n and _tb_cc(whole, pos) != 10: - pos += 1 + while pos < n and _tb_cc(whole, pos) != 10: pos += 1 le: sizet = pos - if pos < n: - pos += 1 - if le > ls and _tb_cc(whole, le - 1) == 13: - le -= 1 + if pos < n: pos += 1 + if le > ls and _tb_cc(whole, le - 1) == 13: le -= 1 if le > ls: typ: int = _tb_cc(whole, ls) if typ == 70: - if _tb_parse_f_line(mb, whole, ls, le, cp) != 0: - return 1 + if _tb_parse_f_line(mb, whole, ls, le, cp) != 0: return 1 elif typ == 67: - if _tb_parse_c_line(mb, whole, ls, le, cp) != 0: - return 1 + if _tb_parse_c_line(mb, whole, ls, le, cp) != 0: return 1 return 0 def _tb_load_vpcalls(mb: memhub.MemBuddy*, cp: TbCallParse*) -> int: - if _tb_vpcall_buf is None or _tb_vpcall_n <= 0: - return 0 + if _tb_vpcall_buf is None or _tb_vpcall_n <= 0: return 0 k: int = 0 while k < _tb_vpcall_n: slot: str* = (str*)(uint64(_tb_vpcall_buf) + sizet(k) * 8) path: str = slot[0] if path is not None: - if _tb_parse_vpcall_file(mb, path, cp) != 0: - return 1 + if _tb_parse_vpcall_file(mb, path, cp) != 0: return 1 k += 1 return 0 def _tb_build_groups(mb: memhub.MemBuddy*, cp: TbCallParse*) -> int: """把所有 C 记录按 (caller,callee) 串成组链表(组槽存 head/tail/cursor)。""" - if cp.CrN <= 0: - return 0 + if cp.CrN <= 0: return 0 cp.GrpCap = _tb_next_pow2(cp.CrN * 2 + 16) cp.Grp = mb.alloc(sizet(cp.GrpCap) * TB_GRP_SIZE) if cp.Grp is None: @@ -2484,15 +2273,12 @@ def _tb_emit_call_row(mb: memhub.MemBuddy*, d: TbDump*, cp: TbCallParse*, img_lo: uint64, caller: str, callee: str, ret_va: uint64) -> int: """按 (caller,callee) 的下一条未消费 C 记录为返回地址生成一条行记录。""" - if caller is None or callee is None or cp.Grp is None or ret_va < img_lo: - return 0 + if caller is None or callee is None or cp.Grp is None or ret_va < img_lo: return 0 slot: int = _tb_grp_get(cp.Grp, cp.GrpCap, caller, callee, 0) - if slot < 0: - return 0 + if slot < 0: return 0 goff: sizet = sizet(slot) * TB_GRP_SIZE curv: uint64 = uint64(_tb_rd_u32(cp.Grp, goff + TB_GRP_OFF_CURSOR)) - if curv == uint64(TB_IDX_NONE): - return 0 + if curv == uint64(TB_IDX_NONE): return 0 ci: int = int(curv) coff: sizet = sizet(ci) * TB_CR_SIZE file: str = rawptr(_tb_rd_u64(cp.Cr, coff + TB_CR_OFF_FILE)) @@ -2506,8 +2292,7 @@ def _tb_emit_entry_row(mb: memhub.MemBuddy*, d: TbDump*, cp: TbCallParse*, img_lo: uint64, addr: uint64, sym: str) -> int: """为 objdump 标签 `sym` 生成函数入口兜底行(文件/定义行取自 F 记录)。""" - if sym is None or cp.Fr is None or cp.FrN <= 0 or addr < img_lo: - return 0 + if sym is None or cp.Fr is None or cp.FrN <= 0 or addr < img_lo: return 0 i: int = 0 while i < cp.FrN: off: sizet = sizet(i) * TB_FR_SIZE @@ -2525,8 +2310,7 @@ def _tb_hex_span(s: str, a: sizet, b: sizet) -> uint64: i: sizet = a while i < b: hd: int = _tb_hex_digit(_tb_cc(s, i)) - if hd < 0: - break + if hd < 0: break v = (v << 4) | uint64(hd) i += 1 return v @@ -2542,8 +2326,7 @@ def _tb_run_objdump(mb: memhub.MemBuddy*, exe_path: str) -> str: res: rawptr[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 + if res is not None: rc = res.returncode VLogger.error(f"--traceback: 调用 llvm-objdump 失败(返回码 {rc};请确认 PATH 内含 LLVM 工具),终止编译", "TRACEBACK") return None dump: str = res.stdout @@ -2565,35 +2348,25 @@ def _tb_scan_objdump(mb: memhub.MemBuddy*, dump: str, img_lo: uint64, prev_func: str = None while pos < dlen: ls: sizet = pos - while pos < dlen and _tb_cc(dump, pos) != 10: - pos += 1 + while pos < dlen and _tb_cc(dump, pos) != 10: pos += 1 le: sizet = pos - if pos < dlen: - pos += 1 - if le > ls and _tb_cc(dump, le - 1) == 13: - le -= 1 - if le <= ls: - continue + if pos < dlen: pos += 1 + if le > ls and _tb_cc(dump, le - 1) == 13: le -= 1 + if le <= ls: continue if _tb_startswith(dump + ls, "Disassembly of section") != 0: # 跨段:上一个段末尾未决的 callq 无有效返回地址,丢弃 prev_is_call = 0 - if _tb_contains(dump + ls, ".text") != 0: - in_text = 1 - else: - in_text = 0 - continue - if in_text == 0: + if _tb_contains(dump + ls, ".text") != 0: in_text = 1 + else: in_text = 0 continue + if in_text == 0: continue c0: int = _tb_cc(dump, ls) is_hex0: int = 0 - if (c0 >= 48 and c0 <= 57) or (c0 >= 97 and c0 <= 102) or (c0 >= 65 and c0 <= 70): - is_hex0 = 1 - if is_hex0 == 0: - continue + if (c0 >= 48 and c0 <= 57) or (c0 >= 97 and c0 <= 102) or (c0 >= 65 and c0 <= 70): is_hex0 = 1 + if is_hex0 == 0: continue # 首个空格 sp: sizet = ls - while sp < le and _tb_cc(dump, sp) != 32: - sp += 1 + while sp < le and _tb_cc(dump, sp) != 32: sp += 1 if sp + 1 < le and _tb_cc(dump, sp + 1) == 60: # ---- 标签行 `ADDR :` ---- laddr: uint64 = _tb_hex_span(dump, ls, sp) @@ -2602,64 +2375,49 @@ def _tb_scan_objdump(mb: memhub.MemBuddy*, dump: str, img_lo: uint64, prev_is_call = 0 lb: sizet = sp + 2 j: sizet = lb - while j < le and _tb_cc(dump, j) != 62: - j += 1 + while j < le and _tb_cc(dump, j) != 62: j += 1 cur_func = _tb_dup_span(mb, dump + lb, j - lb) - if cur_func is not None: - _tb_emit_entry_row(mb, d, cp, img_lo, laddr, cur_func) + if cur_func is not None: _tb_emit_entry_row(mb, d, cp, img_lo, laddr, cur_func) continue # ---- 指令行 `ADDR: bytes mnemonic operands` ---- k: sizet = ls - while k < le and _tb_cc(dump, k) != 58: - k += 1 - if k >= le: - continue + while k < le and _tb_cc(dump, k) != 58: k += 1 + if k >= le: continue iaddr: uint64 = _tb_hex_span(dump, ls, k) if prev_is_call != 0: _tb_emit_call_row(mb, d, cp, img_lo, prev_func, prev_callee, iaddr) prev_is_call = 0 # 跳过字节 token(恰好 2 个 hex 字符),定位 mnemonic 起点 p: sizet = k + 1 - while p < le and (_tb_cc(dump, p) == 32 or _tb_cc(dump, p) == 9): - p += 1 + while p < le and (_tb_cc(dump, p) == 32 or _tb_cc(dump, p) == 9): p += 1 ms: sizet = p while p < le: ts: sizet = p - while p < le and _tb_cc(dump, p) != 32 and _tb_cc(dump, p) != 9: - p += 1 + while p < le and _tb_cc(dump, p) != 32 and _tb_cc(dump, p) != 9: p += 1 tl: sizet = p - ts ishex: int = 0 - if tl == 2 and _tb_hex_digit(_tb_cc(dump, ts)) >= 0 and _tb_hex_digit(_tb_cc(dump, ts + 1)) >= 0: - ishex = 1 + if tl == 2 and _tb_hex_digit(_tb_cc(dump, ts)) >= 0 and _tb_hex_digit(_tb_cc(dump, ts + 1)) >= 0: ishex = 1 ms = ts - if ishex == 0: - break - while p < le and (_tb_cc(dump, p) == 32 or _tb_cc(dump, p) == 9): - p += 1 + if ishex == 0: break + while p < le and (_tb_cc(dump, p) == 32 or _tb_cc(dump, p) == 9): p += 1 me: sizet = p mlen: sizet = me - ms is_call: int = 0 - if mlen == 5 and string.strncmp(dump + ms, "callq", 5) == 0: - is_call = 1 - elif mlen == 4 and string.strncmp(dump + ms, "call", 4) == 0: - is_call = 1 + if mlen == 5 and string.strncmp(dump + ms, "callq", 5) == 0: is_call = 1 + elif mlen == 4 and string.strncmp(dump + ms, "call", 4) == 0: is_call = 1 if is_call != 0: os: sizet = me - while os < le and (_tb_cc(dump, os) == 32 or _tb_cc(dump, os) == 9): - os += 1 + while os < le and (_tb_cc(dump, os) == 32 or _tb_cc(dump, os) == 9): os += 1 if os + 1 < le and _tb_cc(dump, os) == 48 and _tb_cc(dump, os + 1) == 120: # 直接调用:提取 `` ab: sizet = os - while ab < le and _tb_cc(dump, ab) != 60: - ab += 1 + while ab < le and _tb_cc(dump, ab) != 60: ab += 1 if ab < le: cb: sizet = ab + 1 ce: sizet = cb - while ce < le and _tb_cc(dump, ce) != 62: - ce += 1 + while ce < le and _tb_cc(dump, ce) != 62: ce += 1 xe: sizet = cb - while xe < ce and _tb_cc(dump, xe) != 43: - xe += 1 + while xe < ce and _tb_cc(dump, xe) != 43: xe += 1 prev_callee = _tb_dup_span(mb, dump + cb, xe - cb) prev_func = cur_func prev_is_call = 1 @@ -2694,8 +2452,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: res: rawptr[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 + if res is not None: rc = res.returncode VLogger.error(f"--traceback: 调用 llvm-dwarfdump 失败(返回码 {rc};请确认 PATH 内含 LLVM 工具),终止编译", "TRACEBACK") return 1 dump: str = res.stdout @@ -2704,8 +2461,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: return 1 d: TbDump* = _tb_parse_dump(mb, dump) - if d is None: - return 1 + if d is None: return 1 # ---- 1b) 我方调用点行记录:.vpcall + llvm-objdump ---- # DWARF 行仅覆盖链接进来的 mingw CRT(我方 .vp 函数无 .debug_line);这里用编译器 @@ -2715,23 +2471,16 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: if cp is None: VLogger.error("--traceback: 调用点解析状态分配失败,终止编译", "TRACEBACK") return 1 - if _tb_load_vpcalls(mb, cp) != 0: - return 1 - if _tb_build_groups(mb, cp) != 0: - return 1 + if _tb_load_vpcalls(mb, cp) != 0: return 1 + if _tb_build_groups(mb, cp) != 0: return 1 odump: str = _tb_run_objdump(mb, exe_path) - if odump is None: - return 1 + if odump is None: return 1 our_before: int = d.RowCount - if _tb_scan_objdump(mb, odump, img_lo, d, cp) != 0: - return 1 + 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: 从 {_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 d.RawRowCount == 0: VLogger.error(f"--traceback: 未能从 {exe_path} 解析出任何行记录(DWARF .debug_line 为空且无我方 .vpcall 记录,这是 --traceback 的要求)", "TRACEBACK") @@ -2756,8 +2505,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: uint64(_tb_rd_u32(d.RowBuf, sizet(i) * TB_ROW_SIZE + TB_ROW_OFF_LINE))) _tb_wr_u64(d.RowBuf, sizet(kept) * TB_ROW_SIZE + TB_ROW_OFF_FUNC, _tb_rd_u64(d.RowBuf, sizet(i) * TB_ROW_SIZE + TB_ROW_OFF_FUNC)) - else: - _tb_wr_u64(d.RowBuf, sizet(kept) * TB_ROW_SIZE, a - img_lo) + else: _tb_wr_u64(d.RowBuf, sizet(kept) * TB_ROW_SIZE, a - img_lo) kept += 1 i += 1 tmp: bytes = mb.alloc(TB_ROW_SIZE) @@ -2769,8 +2517,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: string.memcpy(tmp, d.RowBuf + sizet(si2) * TB_ROW_SIZE, TB_ROW_SIZE) sj: int = si2 while sj > 0: - if _tb_rd_u64(d.RowBuf, sizet(sj - 1) * TB_ROW_SIZE) <= _tb_rd_u64(tmp, 0): - break + if _tb_rd_u64(d.RowBuf, sizet(sj - 1) * TB_ROW_SIZE) <= _tb_rd_u64(tmp, 0): break string.memcpy(d.RowBuf + sizet(sj) * TB_ROW_SIZE, d.RowBuf + sizet(sj - 1) * TB_ROW_SIZE, TB_ROW_SIZE) sj -= 1 @@ -2798,8 +2545,7 @@ 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_rows} 条无法归一化的 DWARF 行记录(地址不在影像 VA 区间,多为 COMDAT 去重副本)", "TRACEBACK") if uniq == 0: VLogger.error(f"--traceback: 从 {exe_path} 得到的行记录全部无法归一到运行期 RVA 域,终止编译", "TRACEBACK") return 1 @@ -2818,10 +2564,8 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: high: uint64 = _tb_rd_u64(d.FuncBuf, sizet(fi) * TB_FUNC_SIZE + 8) lo_rva: uint64 = low - img_lo hi_rva: uint64 = high - img_lo - if hi_rva <= lo_rva: - hi_rva = lo_rva + 1 - if hi_rva > size_of_image: - hi_rva = size_of_image + if hi_rva <= lo_rva: hi_rva = lo_rva + 1 + if hi_rva > size_of_image: hi_rva = size_of_image _tb_wr_u64(d.FuncBuf, sizet(fkept) * TB_FUNC_SIZE, lo_rva) _tb_wr_u64(d.FuncBuf, sizet(fkept) * TB_FUNC_SIZE + 8, hi_rva) _tb_wr_u64(d.FuncBuf, sizet(fkept) * TB_FUNC_SIZE + 16, @@ -2837,15 +2581,13 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: string.memcpy(ftmp, d.FuncBuf + sizet(fj) * TB_FUNC_SIZE, TB_FUNC_SIZE) fk: int = fj while fk > 0: - if _tb_rd_u64(d.FuncBuf, sizet(fk - 1) * TB_FUNC_SIZE) <= _tb_rd_u64(ftmp, 0): - break + if _tb_rd_u64(d.FuncBuf, sizet(fk - 1) * TB_FUNC_SIZE) <= _tb_rd_u64(ftmp, 0): break string.memcpy(d.FuncBuf + sizet(fk) * TB_FUNC_SIZE, d.FuncBuf + sizet(fk - 1) * TB_FUNC_SIZE, TB_FUNC_SIZE) 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_funcs} 个无法归一化的 DWARF 子程序(low_pc 不在影像 VA 区间)", "TRACEBACK") # ---- 4) string pool: exact upper bound, then intern (offset 0 = sentinel) ---- pool_need: sizet = 1 @@ -2860,14 +2602,12 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: fp: uint64 = _tb_rd_u64(d.RowBuf, sizet(i) * TB_ROW_SIZE + TB_ROW_OFF_FUNC) if fp != 0: fns: str = rawptr(fp) - if fns is not None: - pool_need += string.strlen(fns) + 1 + if fns is not None: pool_need += string.strlen(fns) + 1 i += 1 i = 0 while i < fkept: nm0: str = rawptr(_tb_rd_u64(d.FuncBuf, sizet(i) * TB_FUNC_SIZE + 16)) - if nm0 is not None: - pool_need += string.strlen(nm0) + 1 + if nm0 is not None: pool_need += string.strlen(nm0) + 1 i += 1 p: TbPool* = TbPool() if p is None: @@ -2895,12 +2635,9 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: rv2: uint64 = _tb_rd_u64(d.RowBuf, sizet(i) * TB_ROW_SIZE) fp2: uint64 = _tb_rd_u64(d.RowBuf, sizet(i) * TB_ROW_SIZE + TB_ROW_OFF_FUNC) nm2: str = None - if fp2 != 0: - nm2 = rawptr(fp2) - else: - nm2 = _tb_func_name_for(d.FuncBuf, fkept, rv2) - if nm2 is not None: - noff = _tb_intern(p, nm2) + if fp2 != 0: nm2 = rawptr(fp2) + else: nm2 = _tb_func_name_for(d.FuncBuf, fkept, rv2) + if nm2 is not None: noff = _tb_intern(p, nm2) _tb_wr_u32(ro, sizet(i) * 8, foff) _tb_wr_u32(ro, sizet(i) * 8 + 4, noff) i += 1 @@ -2916,10 +2653,8 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: VLogger.error(f"--traceback 自检失败:记录 RVA 非严格升序(第 {ci} 条会破坏运行期二分查找),终止编译", "TRACEBACK") return 1 prev_rva = cv - if cv >= size_of_image: - outside += 1 - if cv >= text_rva and cv < size_of_image: - plausible += 1 + 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") @@ -3004,8 +2739,7 @@ def run_pipeline(ir_buf: bytes, ir_len: sizet, BuildResult 对象 """ result: BuildResult* = BuildResult() - if result is None: - return None + if result is None: return None # Step 0: 确保 temp/output 目录存在(自动创建,避免写文件失败) ensure_dir(temp_dir) diff --git a/App/lib/Phase/Phase1/Phase1Main.vp b/App/lib/Phase/Phase1/Phase1Main.vp index 09c0fc6..19751e5 100644 --- a/App/lib/Phase/Phase1/Phase1Main.vp +++ b/App/lib/Phase/Phase1/Phase1Main.vp @@ -39,31 +39,23 @@ import lib.core.Gen.DebugInfoGen as DebugInfoGen def _InjectedCreatesCycle(entry: rawptr[IncludesScanner.FileEntry], mod_name: str) -> int: """注入 mod_name 到当前模块前检查是否成环,返回 1=成环需跳过注入""" - if entry is None or entry.RelPath is None or mod_name is None: - return 0 + if entry is None or entry.RelPath is None or mod_name is None: return 0 inj_sha1: str = StubMergerStore.LookupSha1ByModName(mod_name) - if inj_sha1 is None: - return 0 + if inj_sha1 is None: return 0 inj_deps: str = StubMergerStore.LookupIncludesDeps(inj_sha1) - if inj_deps is None: - return 0 + if inj_deps is None: return 0 rp: str = entry.RelPath # 当前模块名 = RelPath 基名(最后 '/' 或 '\\' 之后)去扩展名 base: str = string.strrchr(rp, '/') - if base is None: - base = string.strrchr(rp, '\\') - if base is not None: - base = base + 1 - else: - base = rp + if base is None: base = string.strrchr(rp, '\\') + if base is not None: base = base + 1 + else: base = rp dot: str = string.strchr(base, '.') nm_buf: bytes = stdlib.malloc(128) - if nm_buf is None: - return 0 + if nm_buf is None: return 0 if dot is not None: nm_len: sizet = sizet(uint64(dot) - uint64(base)) - if nm_len > 127: - nm_len = 127 + if nm_len > 127: nm_len = 127 string.strncpy(nm_buf, base, nm_len) nm_buf[nm_len] = '\0' else: @@ -74,11 +66,9 @@ def _InjectedCreatesCycle(entry: rawptr[IncludesScanner.FileEntry], dp: sizet = 0 while dp < d_len: ts: sizet = dp - while dp < d_len and inj_deps[dp] != ' ': - dp += 1 + while dp < d_len and inj_deps[dp] != ' ': dp += 1 tl: sizet = dp - ts - if dp < d_len: - dp += 1 + if dp < d_len: dp += 1 if tl > 0 and tl == nm_len2 and string.strncmp(inj_deps + ts, nm_buf, tl) == 0: stdlib.free(nm_buf) return 1 @@ -88,46 +78,36 @@ def _InjectedCreatesCycle(entry: rawptr[IncludesScanner.FileEntry], def _DepsContainsName(deps: str, name: str) -> int: """deps 字符串(空格分隔模块名)是否含 name token(词边界精确匹配)""" - if deps is None or name is None: - return 0 + if deps is None or name is None: return 0 nl: sizet = string.strlen(name) dl: sizet = string.strlen(deps) dp: sizet = 0 while dp < dl: ts: sizet = dp - while dp < dl and deps[dp] != ' ': - dp += 1 + while dp < dl and deps[dp] != ' ': dp += 1 tl: sizet = dp - ts - if dp < dl: - dp += 1 - if tl == nl and string.strncmp(deps + ts, name, nl) == 0: - return 1 + if dp < dl: dp += 1 + if tl == nl and string.strncmp(deps + ts, name, nl) == 0: return 1 return 0 def _DepsRemoveName(deps: str, name: str) -> int: """从 deps 字符串移除 name token(原地重建,返回 1=有改动)""" - if deps is None or name is None: - return 0 + if deps is None or name is None: return 0 nl: sizet = string.strlen(name) dl: sizet = string.strlen(deps) buf: bytes = stdlib.malloc(StubMerger.MAX_DEPS_STR_LEN) - if buf is None: - return 0 + if buf is None: return 0 buf[0] = '\0' bl: sizet = 0 dp: sizet = 0 while dp < dl: ts: sizet = dp - while dp < dl and deps[dp] != ' ': - dp += 1 + while dp < dl and deps[dp] != ' ': dp += 1 tl: sizet = dp - ts - if dp < dl: - dp += 1 - if tl == 0: - continue - if tl == nl and string.strncmp(deps + ts, name, nl) == 0: - continue + if dp < dl: dp += 1 + if tl == 0: continue + if tl == nl and string.strncmp(deps + ts, name, nl) == 0: continue if bl > 0: buf[bl] = ' ' bl += 1 @@ -141,17 +121,14 @@ def _DepsRemoveName(deps: str, name: str) -> int: def _RewriteDepsTxt(temp_dir: str, sha1: str, deps_str: str) -> None: """重写 {temp_dir}/{sha1前2位}/{sha1}.deps.txt(内存破环后同步磁盘)""" - if temp_dir is None or sha1 is None or deps_str is None: - return + if temp_dir is None or sha1 is None or deps_str is None: return td_len: sizet = string.strlen(temp_dir) dpath: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "deps.txt") - if dpath is None: - return + if dpath is None: return df: rawptr[fileio.File] = fileio.File(dpath, fileio.MODE.W) if not df.closed: dl: sizet = string.strlen(deps_str) - if dl > 0: - df.write(deps_str, dl) + if dl > 0: df.write(deps_str, dl) df.close() stdlib.free(dpath) @@ -168,40 +145,31 @@ def _BreakContainerCyclesInDeps(temp_dir: str) -> int: 内存破环后同步重写 {temp_dir}/deps.txt,保证磁盘与内存一致(Phase2 依赖 图诊断回退读 deps.txt)。 """ - if StubMerger._includes_deps_sha1 is None or StubMerger._includes_deps_str is None: - return 0 + if StubMerger._includes_deps_sha1 is None or StubMerger._includes_deps_str is None: return 0 cnt: sizet = StubMerger._includes_deps_count ci: sizet for ci in range(cnt): sha1_m: str = StubMerger._includes_deps_sha1 + sizet(ci) * 17 deps_m: str = StubMerger._includes_deps_str + sizet(ci) * StubMerger.MAX_DEPS_STR_LEN - if sha1_m is None or deps_m is None: - continue - if string.strstr(deps_m, "_list") is None and string.strstr(deps_m, "_dict") is None: - continue + if sha1_m is None or deps_m is None: continue + if string.strstr(deps_m, "_list") is None and string.strstr(deps_m, "_dict") is None: continue # 该模块名(RelPath 基名去扩展名) rel_m: str = StubMergerStore.LookupSha1RelPath(sha1_m) - if rel_m is None: - continue + if rel_m is None: continue base_m: str = string.strrchr(rel_m, '/') - if base_m is None: - base_m = string.strrchr(rel_m, '\\') - if base_m is not None: - base_m = base_m + 1 - else: - base_m = rel_m + if base_m is None: base_m = string.strrchr(rel_m, '\\') + if base_m is not None: base_m = base_m + 1 + else: base_m = rel_m dot_m: str = string.strchr(base_m, '.') if dot_m is not None: nm_len_m: sizet = sizet(uint64(dot_m) - uint64(base_m)) nm_m: bytes = stdlib.malloc(nm_len_m + 1) - if nm_m is None: - continue + if nm_m is None: continue string.strncpy(nm_m, base_m, nm_len_m) nm_m[nm_len_m] = '\0' else: nm_m: bytes = stdlib.malloc(129) - if nm_m is None: - continue + if nm_m is None: continue string.strncpy(nm_m, base_m, 128) nm_m[128] = '\0' # _list ↔ M 环 @@ -219,8 +187,7 @@ def _BreakContainerCyclesInDeps(temp_dir: str) -> int: if dct_sha1 is not None: dct_deps: str = StubMergerStore.LookupIncludesDeps(dct_sha1) if dct_deps is not None and _DepsContainsName(dct_deps, nm_m) != 0: - if _DepsRemoveName(deps_m, "_dict") != 0: - _RewriteDepsTxt(temp_dir, sha1_m, deps_m) + if _DepsRemoveName(deps_m, "_dict") != 0: _RewriteDepsTxt(temp_dir, sha1_m, deps_m) stdlib.free(nm_m) return 0 @@ -238,32 +205,25 @@ def _BreakContainerCyclesInDeps(temp_dir: str) -> int: def _BuildReachableResult(mb: memhub.MemBuddy*, includes_dir: str) -> rawptr[IncludesScanner.ScanResult]: """从 Sha1Store(仅可达 includes + App)构建可达 FileEntry 列表""" - if mb is None: - return None + if mb is None: return None store_count: sizet = sizet(StubMerger._sha1_store_count) - if store_count <= 0 or StubMerger._sha1_store_arr is None: - return None + if store_count <= 0 or StubMerger._sha1_store_arr is None: return None result: rawptr[IncludesScanner.ScanResult] = IncludesScanner.create_scan_result(mb) - if result is None: - return None + if result is None: return None entry_size: sizet = IncludesScanner.FileEntry.__sizeof__() i: sizet for i in range(store_count): sidx: sizet = sizet(i) * 17 - if StubMerger._sha1_store_arr[sidx] == '\0': - continue + if StubMerger._sha1_store_arr[sidx] == '\0': continue # 仅 includes 条目(incdir 非空);App 条目不进入 result iidx: sizet = sizet(i) * StubMerger.MAX_INC_DIR_LEN - if StubMerger._sha1_store_incdir[iidx] == '\0': - continue + if StubMerger._sha1_store_incdir[iidx] == '\0': continue eaddr: uint64 = uint64(result.Entries) + uint64(result.Count) * entry_size entry: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](eaddr) - if entry is None: - continue + if entry is None: continue # SHA1 深拷贝(store 槽 17 字节) sha1_buf: bytes = stdlib.malloc(17) - if sha1_buf is None: - continue + if sha1_buf is None: continue string.strcpy(sha1_buf, StubMerger._sha1_store_arr + sidx) entry.Sha1 = sha1_buf # RelPath / IncDir 深拷贝 @@ -273,10 +233,8 @@ def _BuildReachableResult(mb: memhub.MemBuddy*, rel_buf: bytes = stdlib.malloc(rel_len + 1) inc_buf: bytes = stdlib.malloc(inc_len + 1) if rel_buf is None or inc_buf is None: - if rel_buf is not None: - stdlib.free(rel_buf) - if inc_buf is not None: - stdlib.free(inc_buf) + if rel_buf is not None: stdlib.free(rel_buf) + if inc_buf is not None: stdlib.free(inc_buf) stdlib.free(sha1_buf) continue string.strcpy(rel_buf, StubMerger._sha1_store_rel + ridx) @@ -419,10 +377,8 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, # free_bytes/free_count 无步数上限会死循环(打点自身卡死),故 # self_check 返回 4(成环)时跳过 dump_stats。 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") + if p1_sc != 4: mb.dump_stats("phase1-pre") + else: VLogger.info("[取证] self_check=4(free list 成环),跳过 dump_stats 防死循环", "Phase1") p1_mo: int = mb.max_order if p1_mo < 0 or p1_mo > 32: p1_mo = 32 # 钳制:max_order 被写坏时防本打点自身越界读 free_lists @@ -465,33 +421,24 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, topo_count_box: t.CPtr = mb.alloc(4) generic_file_indices: t.CPtr = mb.alloc(4 * Phase1.MAX_FILE_DEPS) generic_file_count_box: t.CPtr = mb.alloc(4) - if generic_file_indices is not None: - string.memset(generic_file_indices, 0, 4 * Phase1.MAX_FILE_DEPS) - if generic_file_count_box is not None: - string.memset(generic_file_count_box, 0, 4) + if generic_file_indices is not None: string.memset(generic_file_indices, 0, 4 * Phase1.MAX_FILE_DEPS) + if generic_file_count_box is not None: string.memset(generic_file_count_box, 0, 4) topo_count: int = 0 # 三块扁平缓冲是 Phase1Scan._ScanClassInheritance 的契约前置缓冲:该函数入口对 NULL fail-fast(静默跳过整段会退化为字母序并掩盖 OOM 等内存故障), # 故分配失败时逐块显式报错终止(VLogger.error 内部 sys.exit(1)),绝不静默回退。 # 注:topo_order/topo_count_box 仅供 Phase1Topo._TopoSortFiles 使用,有效性由其入口自身校验(NULL 即返回 -1 并终止),不并入此处终止逻辑。 - 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_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") 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) string.memset(def_sha1s_buf, 0, Phase1.MAX_CLASSES * Phase1.SHA1_LEN) - if topo_order is not None: - string.memset(topo_order, 0, 4 * Phase1.MAX_FILE_DEPS) - if topo_count_box is not None: - string.memset(topo_count_box, 0, 4) - if generic_file_indices is not None: - string.memset(generic_file_indices, 0, 4 * Phase1.MAX_FILE_DEPS) - if generic_file_count_box is not None: - string.memset(generic_file_count_box, 0, 4) + if topo_order is not None: string.memset(topo_order, 0, 4 * Phase1.MAX_FILE_DEPS) + if topo_count_box is not None: string.memset(topo_count_box, 0, 4) + if generic_file_indices is not None: string.memset(generic_file_indices, 0, 4 * Phase1.MAX_FILE_DEPS) + if generic_file_count_box is not None: string.memset(generic_file_count_box, 0, 4) class_count_scanned: int = Phase1Scan._ScanClassInheritance( mb, result, reachable_set, reachable_count, @@ -509,8 +456,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, temp_dir, td_len_ts_call) if ret_topo == 0: tc_ptr: t.CPtr = (int*)(topo_count_box) - if tc_ptr is not None: - topo_count = tc_ptr[0] + if tc_ptr is not None: topo_count = tc_ptr[0] VLogger.info(f"拓扑排序: {class_count_scanned} 个类, {topo_count} 个文件按依赖顺序处理", "Phase1") else: VLogger.error("拓扑排序失败(类继承依赖无法解析),终止编译", "Phase1") @@ -525,10 +471,8 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, # 非可达泛型文件(_list/_dict/linkedlist/mlirlite 等)的模板若在 Phase2(mark2 之后)才注册会被 reset 回收 → list[int]/dict[...] 特化失败。 # 故对全部 includes 轻量预注册,使模板表与节点都落在 mark1 之前(_PreRegisterAllGenericTemplates 内有 generic marker 文本预筛,不 parse 全部 AST,OOM 风险可控)。 full_scan_g: rawptr[IncludesScanner.ScanResult] = IncludesScanner.scan_includes(mb, includes_dir) - if full_scan_g is not None: - Phase1Scan._PreRegisterAllGenericTemplates(mb, full_scan_g) - else: - Phase1Scan._PreRegisterAllGenericTemplates(mb, result) + if full_scan_g is not None: Phase1Scan._PreRegisterAllGenericTemplates(mb, full_scan_g) + else: Phase1Scan._PreRegisterAllGenericTemplates(mb, result) # ============================================================ # Phase 1a: 注册 struct/enum/union(mark1 前,全量 includes) @@ -552,8 +496,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, if topo_count > 0: od_addr: uint64 = uint64(topo_order) + i * 4 od_ptr: t.CPtr = (int*)(t.CPtr(od_addr)) - if od_ptr is not None: - file_idx = od_ptr[0] + if od_ptr is not None: file_idx = od_ptr[0] entry_addr_r: uint64 = uint64(result.Entries) + file_idx * entry_size entry_r: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](entry_addr_r) @@ -606,8 +549,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, stdlib.free(src_buf_r) p1a_fl += 1 continue - if bytes_read_r < Phase1.SRC_BUF_SIZE: - src_buf_r[bytes_read_r] = 0 + if bytes_read_r < Phase1.SRC_BUF_SIZE: src_buf_r[bytes_read_r] = 0 # 解析 AST lx_r: ast.Lexer* = ast.new_lexer(mb) @@ -644,19 +586,15 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, ret_r: int = tr_r.translate(tree_r) # 计时点 2:translate(declare=1) 返回 t_fa2: uint64 = w32.win32base.GetTickCount64() - if ret_r != 0: - p1a_fl += 1 - else: - p1a_reg += 1 + if ret_r != 0: p1a_fl += 1 + else: p1a_reg += 1 # 逐文件进度日志(parse/translate 两段,定位 1a 卡点) VLogger.info(f"[{i+1}/{iter_count}] 1a: {file_path_r} (parse={t_fa1-t_fa0} ms, translate={t_fa2-t_fa1} ms, total={t_fa2-t_fa0} ms)", "Phase1") # 释放 Translator 的 C malloc 资源 - if tr_r._global_names is not None: - stdlib.free(tr_r._global_names) - if tr_r._nonlocal_names is not None: - stdlib.free(tr_r._nonlocal_names) + if tr_r._global_names is not None: stdlib.free(tr_r._global_names) + if tr_r._nonlocal_names is not None: stdlib.free(tr_r._nonlocal_names) stdlib.free(src_buf_r) # [TEMP-DIAG] 1a 每文件哨兵:校验本文件窗口 [p1a_mark, chk_depth) 内所有存活块的块尾 canary。 @@ -683,16 +621,11 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, # 释放拓扑排序资源(topo_order/topo_count_box 保留到 Phase 1b 结束, # 1b 按拓扑序翻译需要它们;class/def 数组 1b 不再使用) - if class_names_buf is not None: - mb.free(class_names_buf) - if parent_names_buf is not None: - mb.free(parent_names_buf) - if def_sha1s_buf is not None: - mb.free(def_sha1s_buf) - if generic_file_indices is not None: - mb.free(generic_file_indices) - if generic_file_count_box is not None: - mb.free(generic_file_count_box) + if class_names_buf is not None: mb.free(class_names_buf) + if parent_names_buf is not None: mb.free(parent_names_buf) + if def_sha1s_buf is not None: mb.free(def_sha1s_buf) + if generic_file_indices is not None: mb.free(generic_file_indices) + if generic_file_count_box is not None: mb.free(generic_file_count_box) # ============================================================ # Phase 1b: 全量翻译(struct 已注册,走 existing 路径翻译方法体) @@ -722,12 +655,9 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, continue sha1_pv: str = entry_pv.Sha1 in_set_pv: int = 0 - if use_reachable != 0: - in_set_pv = StubMergerCollect._is_in_sha1_set(sha1_pv, reachable_set, reachable_count) - else: - in_set_pv = StubMergerCollect._is_in_sha1_set(sha1_pv, sha1_set, set_count) - if in_set_pv == 0: - continue + if use_reachable != 0: in_set_pv = StubMergerCollect._is_in_sha1_set(sha1_pv, reachable_set, reachable_count) + else: in_set_pv = StubMergerCollect._is_in_sha1_set(sha1_pv, sha1_set, set_count) + if in_set_pv == 0: continue # vpi 已存在则跳过 vpi_path_pv: str = StubMergerCollect._sliced_path(temp_dir, dir_len_pv, sha1_pv, "vpi") if vpi_path_pv is None: @@ -766,8 +696,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, p1bpre_failed += 1 VLogger.error(f"[Phase 1b-pre] {file_path_pv} | 文件读取失败或为空", "Phase1") continue - if bytes_read_pv < Phase1.SRC_BUF_SIZE: - src_buf_pv[bytes_read_pv] = 0 + 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) @@ -832,16 +761,14 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, t_b0: uint64 = w32.win32base.GetTickCount64() loop_n_b: int = result.Count - if topo_count > 0: - loop_n_b = topo_count + if topo_count > 0: loop_n_b = topo_count for i in range(loop_n_b): # 获取 entry(拓扑序:file_idx 从 topo_order 取,否则用扫描索引) file_idx_b: int = i if topo_count > 0: od_addr_b: uint64 = uint64(topo_order) + sizet(i) * 4 od_ptr_b: t.CPtr = (int*)(od_addr_b) - if od_ptr_b is not None: - file_idx_b = od_ptr_b[0] + if od_ptr_b is not None: file_idx_b = od_ptr_b[0] entry_addr: uint64 = uint64(result.Entries) + sizet(file_idx_b) * entry_size entry: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](entry_addr) if entry is None: @@ -857,10 +784,8 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, in_set: int = 1 if topo_count == 0: in_set = 0 - if use_reachable != 0: - in_set = StubMergerCollect._is_in_sha1_set(sha1, reachable_set, reachable_count) - else: - in_set = StubMergerCollect._is_in_sha1_set(sha1, sha1_set, set_count) + if use_reachable != 0: in_set = StubMergerCollect._is_in_sha1_set(sha1, reachable_set, reachable_count) + else: in_set = StubMergerCollect._is_in_sha1_set(sha1, sha1_set, set_count) if in_set == 0: skipped += 1 continue @@ -886,26 +811,21 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, vrd_1b: LONG = vf_1b.read_all(vbuf_1b, 1048576) vf_1b.close() if vrd_1b > 0: - if vrd_1b < 1048576: - vbuf_1b[vrd_1b] = 0 + if vrd_1b < 1048576: vbuf_1b[vrd_1b] = 0 vtotal_1b: sizet = string.strlen(vbuf_1b) vpos_1b: sizet = 0 while vpos_1b < vtotal_1b: vls_1b: sizet = vpos_1b - while vpos_1b < vtotal_1b and vbuf_1b[vpos_1b] != '\n': - vpos_1b += 1 + while vpos_1b < vtotal_1b and vbuf_1b[vpos_1b] != '\n': vpos_1b += 1 vll_1b: sizet = vpos_1b - vls_1b - if vpos_1b < vtotal_1b: - vpos_1b += 1 + if vpos_1b < vtotal_1b: vpos_1b += 1 vi2_1b: sizet = vls_1b - while vi2_1b < vls_1b + vll_1b and vbuf_1b[vi2_1b] == ' ': - vi2_1b += 1 + while vi2_1b < vls_1b + vll_1b and vbuf_1b[vi2_1b] == ' ': vi2_1b += 1 if vll_1b >= 6 and string.strncmp(vbuf_1b + vi2_1b, "class ", 6) == 0: force_translate = 1 break stdlib.free(vbuf_1b) - else: - vf_1b.close() + else: vf_1b.close() stdlib.free(vpi_path_1b) if force_translate == 1: # 含 class:强制翻译(覆盖 stub/text,重新注册类) @@ -990,8 +910,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, stdlib.free(src_buf) failed += 1 continue - if bytes_read < Phase1.SRC_BUF_SIZE: - src_buf[bytes_read] = 0 + if bytes_read < Phase1.SRC_BUF_SIZE: src_buf[bytes_read] = 0 # 解析 AST lx: ast.Lexer* = ast.new_lexer(mb) @@ -1073,15 +992,12 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, t_f2: uint64 = w32.win32base.GetTickCount64() # 诊断:translate 正常返回(若挂起在 translate 内部,此行不会打印, # 用于区分"translate 内部挂起"与"后续 dump 挂起") - if ret == 0: - VLogger.info(f"翻译完成(translate返回): {file_path}", "Phase1") + if ret == 0: VLogger.info(f"翻译完成(translate返回): {file_path}", "Phase1") if ret != 0: VLogger.error(f"翻译失败: {file_path}", "Phase1") # error 终止 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) + if tr._global_names is not None: stdlib.free(tr._global_names) + if tr._nonlocal_names is not None: stdlib.free(tr._nonlocal_names) failed += 1 continue @@ -1089,14 +1005,12 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, # (its stub/text.ll below are what Phase2 reuses to build the .obj). The # injector lives in the Gen layer (already depends on mlirlite), so this # module gains no cross-module mlirlite symbol dependency. - if BuildPipeline._traceback_mode != 0 and BuildPipeline._tb_basename_is_traceback(file_path) != 0: - HandlesTranslator.InjectTracebackInstallCtor(tr) + if BuildPipeline._traceback_mode != 0 and BuildPipeline._tb_basename_is_traceback(file_path) != 0: HandlesTranslator.InjectTracebackInstallCtor(tr) # 诊断:pre_rc 哨兵在 translate 前、覆盖不到 translate 期间的 AST/IR 写穿,故 dump 前立即检查存活块 header/canary # (rc=6 块尾 canary 损坏 = 越界写穿数据区),把「dump 时链表成环卡死」变成「定位到 translate 期间写穿发生的文件」。 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"内存损坏(translate后存活块, rc={post_rc}): {file_path}", "Phase1") # dump stub IR(declarations only) # 1MB 不够:ast/parser.vp 的 text.ll 超 1MB 被截断 → 合并 IR 尾部丢字 @@ -1107,10 +1021,8 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, stub_buf: bytes = stdlib.malloc(PHASE1_IR_SIZE) if stub_buf is None: 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) + if tr._global_names is not None: stdlib.free(tr._global_names) + if tr._nonlocal_names is not None: stdlib.free(tr._nonlocal_names) failed += 1 continue tr.dump_ir(stub_buf, PHASE1_IR_SIZE, mlirlite.OUTPUT_STUB) @@ -1131,10 +1043,8 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, text_buf: bytes = stdlib.malloc(PHASE1_IR_SIZE) if text_buf is None: 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) + if tr._global_names is not None: stdlib.free(tr._global_names) + if tr._nonlocal_names is not None: stdlib.free(tr._nonlocal_names) failed += 1 continue tr.dump_ir(text_buf, PHASE1_IR_SIZE, mlirlite.OUTPUT_TEXT) @@ -1156,8 +1066,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, # save {sha1}.full.ll(在线 FULL 产物:模型在线时的自足单模块 IR,供 Phase B 直接编译, # 取代 stub + 依赖 stub/text 文本合并) 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 缓冲区分配失败", "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") @@ -1193,10 +1102,8 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, stdlib.free(deps_path_p1) # 释放 Translator 的 C malloc 资源 - if tr._global_names is not None: - stdlib.free(tr._global_names) - if tr._nonlocal_names is not None: - stdlib.free(tr._nonlocal_names) + if tr._global_names is not None: stdlib.free(tr._global_names) + if tr._nonlocal_names is not None: stdlib.free(tr._nonlocal_names) # 所有 dump_ir 完成,src_buf 不再需要 stdlib.free(src_buf) @@ -1210,23 +1117,19 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, # rc 语义(check_alive_blocks):1=块地址低于 usable,2=高于 usable+size,3=order 为负,4=order 超 max_order,5=块未对齐到 order 大小,6=块尾 canary 损坏(越界写穿数据区) # rc 语义(self_check):1/2=越界,3=对齐错,4=free list 成环/超步数 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"内存损坏(存活块 header, rc={chk_rc}): {file_path}", "Phase1") # 越界写是崩溃根因(与回收/UAF 无关,已由 A/B 实验确认)——恢复 reset_to,改用块尾 canary(check_alive_blocks 校验)把越界写事发地定位到具体文件。 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"内存损坏(free list, rc={sc_rc}): {file_path}", "Phase1") # 1b 阶段总耗时(全量翻译 + dump) t_b1: uint64 = w32.win32base.GetTickCount64() VLogger.info(f"1b 总耗时: {t_b1-t_b0} ms (全量翻译, trans={translated} skip={skipped} fail={failed})", "Phase1") # 释放 Phase 1b 使用的拓扑排序资源 - if topo_order is not None: - mb.free(topo_order) - if topo_count_box is not None: - mb.free(topo_count_box) + 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") @@ -1235,7 +1138,6 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, return 1 # 释放可达 SHA1 集合(如果分配了) - if reachable_set is not None: - stdlib.free(reachable_set) + if reachable_set is not None: stdlib.free(reachable_set) return 0 diff --git a/App/lib/Phase/Phase1/Phase1Scan.vp b/App/lib/Phase/Phase1/Phase1Scan.vp index 9e831a8..3ef0821 100644 --- a/App/lib/Phase/Phase1/Phase1Scan.vp +++ b/App/lib/Phase/Phase1/Phase1Scan.vp @@ -64,12 +64,10 @@ def _ScanClassInheritance(mb: memhub.MemBuddy*, generic_file_indices: t.CPtr, generic_file_count_box: t.CPtr) -> int: """预扫描 includes 文件,收集类继承关系""" - if result is None: - return -1 + if result is None: return -1 # class_names_buf/parent_names_buf/def_sha1s_buf 由调用方 mb.alloc 分配(Phase1Main 预扫描前),本函数把其地址直接作为 strcpy 目的缓冲; # 分配失败返回 NULL 时目的指针为近零地址 → strcpy 写零页(ASan access-violation),故按 fail-fast 显式报错终止(VLogger.error 内部 sys.exit(1)),不静默返回 -1。 - 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_names_buf/parent_names_buf/def_sha1s_buf 为 NULL)", "Phase1") entry_size: sizet = IncludesScanner.FileEntry.__sizeof__() class_count: int = 0 @@ -80,26 +78,21 @@ def _ScanClassInheritance(mb: memhub.MemBuddy*, scan_mark: sizet = mb.mark() entry_addr: uint64 = uint64(result.Entries) + i * entry_size entry: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](entry_addr) - if entry is None or entry.Sha1 is None: - continue + if entry is None or entry.Sha1 is None: continue sha1_e: str = entry.Sha1 file_has_generic: int = 0 # 按需翻译过滤 in_set: int = 0 - if use_reachable != 0: - in_set = StubMergerCollect._is_in_sha1_set(sha1_e, reachable_set, reachable_count) - else: - in_set = StubMergerCollect._is_in_sha1_set(sha1_e, sha1_set, set_count) - if in_set == 0: - continue + if use_reachable != 0: in_set = StubMergerCollect._is_in_sha1_set(sha1_e, reachable_set, reachable_count) + else: in_set = StubMergerCollect._is_in_sha1_set(sha1_e, sha1_set, set_count) + if in_set == 0: continue # 读取文件 file_path: str = entry.Path f: rawptr[fileio.File] = fileio.File(file_path, fileio.MODE.R) - if f.closed: - continue + if f.closed: continue # read_all 的容量参数含终止符(最多读 cap-1 字节), 文件更长会被静默截断 if f.size() >= Phase1.SRC_BUF_SIZE: @@ -117,8 +110,7 @@ def _ScanClassInheritance(mb: memhub.MemBuddy*, if bytes_read <= 0: stdlib.free(src_buf) continue - if bytes_read < Phase1.SRC_BUF_SIZE: - src_buf[bytes_read] = 0 + if bytes_read < Phase1.SRC_BUF_SIZE: src_buf[bytes_read] = 0 # 解析 AST lx: ast.Lexer* = ast.new_lexer(mb) @@ -138,15 +130,12 @@ def _ScanClassInheritance(mb: memhub.MemBuddy*, cn: sizet = len(ch) for ci in range(cn): child: ast.AST* = ch.get(ci) - if child is None: - continue + if child is None: continue kd: int = child.kind() - if kd != ast.ASTKind.ClassDef: - continue + if kd != ast.ASTKind.ClassDef: continue cd: ast.ClassDef* = ast.ClassDef*(child) - if cd is None or cd.name is None: - continue + if cd is None or cd.name is None: continue # 检测泛型类(有 type_params),记录文件索引以供 Phase 1a 预注册 if file_has_generic == 0: @@ -160,12 +149,10 @@ def _ScanClassInheritance(mb: memhub.MemBuddy*, if gfc_scan < Phase1.MAX_FILE_DEPS and generic_file_indices is not None: gi_addr_scan: uint64 = uint64(generic_file_indices) + gfc_scan * 4 gi_ptr_scan: t.CPtr = (int*)(gi_addr_scan) - if gi_ptr_scan is not None: - gi_ptr_scan[0] = i + if gi_ptr_scan is not None: gi_ptr_scan[0] = i gfc_ptr_scan[0] = gfc_scan + 1 - if class_count >= Phase1.MAX_CLASSES: - break + if class_count >= Phase1.MAX_CLASSES: break # 填充扁平数组:类名(偏移 = class_count * Phase1.CLASS_NAME_LEN) name_dst: str = class_names_buf + class_count * Phase1.CLASS_NAME_LEN @@ -173,8 +160,7 @@ def _ScanClassInheritance(mb: memhub.MemBuddy*, if nm_len >= Phase1.CLASS_NAME_LEN: string.strncpy(name_dst, cd.name, Phase1.CLASS_NAME_LEN - 1) name_dst[Phase1.CLASS_NAME_LEN - 1] = '\0' - else: - string.strcpy(name_dst, cd.name) + else: string.strcpy(name_dst, cd.name) # 填充扁平数组:父类名(无父类填 '\0') parent_dst: str = parent_names_buf + class_count * Phase1.CLASS_NAME_LEN @@ -186,8 +172,7 @@ def _ScanClassInheritance(mb: memhub.MemBuddy*, if pnm_len >= Phase1.CLASS_NAME_LEN: string.strncpy(parent_dst, parent_nm, Phase1.CLASS_NAME_LEN - 1) parent_dst[Phase1.CLASS_NAME_LEN - 1] = '\0' - else: - string.strcpy(parent_dst, parent_nm) + else: string.strcpy(parent_dst, parent_nm) # 填充扁平数组:定义 SHA1(偏移 = class_count * Phase1.SHA1_LEN) sha1_dst: str = def_sha1s_buf + class_count * Phase1.SHA1_LEN @@ -209,8 +194,7 @@ def _ScanClassInheritance(mb: memhub.MemBuddy*, # ============================================================ def _BufHasGenericClassMarker(buf: bytes, blen: sizet) -> int: """文本扫描:buf 中是否有 'class 标识符[' 泛型类标记,返回 1/0""" - if buf is None or blen <= 6: - return 0 + if buf is None or blen <= 6: return 0 pos: sizet = 0 while pos + 5 < blen: if buf[pos] == 'c' and buf[pos + 1] == 'l' and buf[pos + 2] == 'a' and buf[pos + 3] == 's' and buf[pos + 4] == 's': @@ -218,13 +202,11 @@ def _BufHasGenericClassMarker(buf: bytes, blen: sizet) -> int: prev_ok: int = 1 if pos > 0: pc: char = buf[pos - 1] - if(pc >= 'a' and pc <= 'z') or(pc >= 'A' and pc <= 'Z') or(pc >= '0' and pc <= '9') or pc == '_': - prev_ok = 0 + if(pc >= 'a' and pc <= 'z') or(pc >= 'A' and pc <= 'Z') or(pc >= '0' and pc <= '9') or pc == '_': prev_ok = 0 if prev_ok != 0: p: sizet = pos + 5 # 跳过空白 - while p < blen and(buf[p] == ' ' or buf[p] == '\t'): - p += 1 + while p < blen and(buf[p] == ' ' or buf[p] == '\t'): p += 1 # 读类名标识符 if p < blen and((buf[p] >= 'a' and buf[p] <= 'z') or(buf[p] >= 'A' and buf[p] <= 'Z') or buf[p] == '_'): @@ -234,13 +216,10 @@ def _BufHasGenericClassMarker(buf: bytes, blen: sizet) -> int: or buf[p] == '_'): p += 1 # 类名后非空白是 '[' → 泛型类 - while p < blen and(buf[p] == ' ' or buf[p] == '\t'): - p += 1 - if p < blen and buf[p] == '[': - return 1 - pos += 1 - else: + while p < blen and(buf[p] == ' ' or buf[p] == '\t'): p += 1 + if p < blen and buf[p] == '[': return 1 pos += 1 + else: pos += 1 return 0 # ============================================================ # _BufHasGenericFuncMarker - 文本扫描检测文件是否含泛型函数标记 @@ -252,8 +231,7 @@ def _BufHasGenericClassMarker(buf: bytes, blen: sizet) -> int: # ============================================================ def _BufHasGenericFuncMarker(buf: bytes, blen: sizet) -> int: """文本扫描:buf 中是否有 'def 标识符[' 泛型函数标记,返回 1/0""" - if buf is None or blen <= 4: - return 0 + if buf is None or blen <= 4: return 0 pos: sizet = 0 while pos + 3 < blen: if buf[pos] == 'd' and buf[pos + 1] == 'e' and buf[pos + 2] == 'f': @@ -261,13 +239,11 @@ def _BufHasGenericFuncMarker(buf: bytes, blen: sizet) -> int: prev_ok: int = 1 if pos > 0: pc: char = buf[pos - 1] - if(pc >= 'a' and pc <= 'z') or(pc >= 'A' and pc <= 'Z') or(pc >= '0' and pc <= '9') or pc == '_': - prev_ok = 0 + if(pc >= 'a' and pc <= 'z') or(pc >= 'A' and pc <= 'Z') or(pc >= '0' and pc <= '9') or pc == '_': prev_ok = 0 if prev_ok != 0: p: sizet = pos + 3 # 跳过空白 - while p < blen and(buf[p] == ' ' or buf[p] == '\t'): - p += 1 + while p < blen and(buf[p] == ' ' or buf[p] == '\t'): p += 1 # 读函数名标识符 if p < blen and((buf[p] >= 'a' and buf[p] <= 'z') or(buf[p] >= 'A' and buf[p] <= 'Z') or buf[p] == '_'): @@ -277,13 +253,10 @@ def _BufHasGenericFuncMarker(buf: bytes, blen: sizet) -> int: or buf[p] == '_'): p += 1 # 函数名后非空白是 '[' → 泛型函数 - while p < blen and(buf[p] == ' ' or buf[p] == '\t'): - p += 1 - if p < blen and buf[p] == '[': - return 1 - pos += 1 - else: + while p < blen and(buf[p] == ' ' or buf[p] == '\t'): p += 1 + if p < blen and buf[p] == '[': return 1 pos += 1 + else: pos += 1 return 0 # ============================================================ # _PreRegisterAllGenericTemplates - 预注册 includes 泛型类模板(mark1 前) @@ -296,24 +269,20 @@ def _BufHasGenericFuncMarker(buf: bytes, blen: sizet) -> int: def _PreRegisterAllGenericTemplates(mb: memhub.MemBuddy*, result: rawptr[IncludesScanner.ScanResult]) -> int: """预注册全部 includes 文件的泛型类模板,返回处理到的泛型类数量""" - if result is None or mb is None: - return 0 + if result is None or mb is None: return 0 perm: memhub.MemBuddy* = CompilerFactory.factory.PermPool - if perm is None: - return 0 + if perm is None: return 0 p1e_size: sizet = IncludesScanner.FileEntry.__sizeof__() handled_count: int = 0 for i in range(result.Count): entry_addr_pg: uint64 = uint64(result.Entries) + i * p1e_size entry_pg: rawptr[IncludesScanner.FileEntry] = ( rawptr[IncludesScanner.FileEntry])(entry_addr_pg) - if entry_pg is None or entry_pg.Sha1 is None: - continue + if entry_pg is None or entry_pg.Sha1 is None: continue # 读取文件 file_path_pg: str = entry_pg.Path f_pg: rawptr[fileio.File] = fileio.File(file_path_pg, fileio.MODE.R) - if f_pg.closed: - continue + if f_pg.closed: continue # read_all 的容量参数含终止符(最多读 cap-1 字节), 文件更长会被静默截断 if f_pg.size() >= Phase1.SRC_BUF_SIZE: VLogger.error(f"源文件超过 {Phase1.SRC_BUF_SIZE} 字节上限, 拒绝读取: {file_path_pg}", "Phase1") @@ -328,8 +297,7 @@ def _PreRegisterAllGenericTemplates(mb: memhub.MemBuddy*, if bytes_read_pg <= 0: stdlib.free(src_buf_pg) continue - if bytes_read_pg < Phase1.SRC_BUF_SIZE: - src_buf_pg[bytes_read_pg] = 0 + if bytes_read_pg < Phase1.SRC_BUF_SIZE: src_buf_pg[bytes_read_pg] = 0 # 文本扫描筛选:非泛型文件跳过(不 parse、不驻留,防 OOM)。 # 泛型类(class X[)与泛型函数(def f[)任一命中即进入 parse。 if _BufHasGenericClassMarker(src_buf_pg, bytes_read_pg) == 0 and _BufHasGenericFuncMarker(src_buf_pg, bytes_read_pg) == 0: @@ -352,34 +320,27 @@ def _PreRegisterAllGenericTemplates(mb: memhub.MemBuddy*, cn_pg: sizet = len(ch_pg) for ci_pg in range(cn_pg): child_pg: ast.AST* = ch_pg.get(ci_pg) - if child_pg is None: - continue + if child_pg is None: continue ck_pg: int = child_pg.kind() if ck_pg == ast.ASTKind.ClassDef: cd_pg: ast.ClassDef* = ast.ClassDef*(child_pg) - if cd_pg is None or cd_pg.name is None: - continue + if cd_pg is None or cd_pg.name is None: continue tp_pg: list[str]* = cd_pg.type_params - if tp_pg is None: - continue + if tp_pg is None: continue GenApi.set_current_file_type(file_path_pg) GenApi._register_generic_template(perm, cd_pg, entry_pg.Sha1) handled_count += 1 elif ck_pg == ast.ASTKind.FunctionDef: fd_pg: ast.FunctionDef* = ast.FunctionDef*(child_pg) - if fd_pg is None or fd_pg.name is None: - continue + if fd_pg is None or fd_pg.name is None: continue tf_pg: list[str]* = fd_pg.type_params - if tf_pg is None: - continue + if tf_pg is None: continue GenApi.set_current_file_type(file_path_pg) 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"mark1 前永久池预注册 {handled_count} 个 includes 泛型模板(类+函数)", "Phase1") + else: VLogger.info(f"mark1 前永久池预注册 0 个泛型模板(扫描 {result.Count} 个文件,可能 marker 未命中或全量扫描失败)", "Phase1") return handled_count # ============================================================ # _FindClassDefSha1 - 在扁平数组中查找类名对应的定义文件 SHA1 @@ -390,12 +351,10 @@ def _PreRegisterAllGenericTemplates(mb: memhub.MemBuddy*, def _FindClassDefSha1(class_names_buf: bytes, def_sha1s_buf: bytes, class_count: int, class_name: str) -> str: """查找类名对应的定义文件 SHA1""" - if class_names_buf is None or def_sha1s_buf is None or class_name is None: - return None + if class_names_buf is None or def_sha1s_buf is None or class_name is None: return None for i in range(class_count): name_ptr: str = class_names_buf + i * Phase1.CLASS_NAME_LEN - if string.strcmp(name_ptr, class_name) == 0: - return def_sha1s_buf + i * Phase1.SHA1_LEN + if string.strcmp(name_ptr, class_name) == 0: return def_sha1s_buf + i * Phase1.SHA1_LEN return None # ============================================================ # _ScanTreeForContainers - 递归扫描 AST 检测 list/dict 容器使用 @@ -416,16 +375,13 @@ def _AnnIsContainer(ann: ast.AST*) -> int: if ak_c == ast.ASTKind.Name: nm_c: ast.Name* = ast.Name*(ann) if nm_c.id is not None: - if string.strcmp(nm_c.id, "list") == 0: - return 1 - if string.strcmp(nm_c.id, "dict") == 0: - return 1 + if string.strcmp(nm_c.id, "list") == 0: return 1 + if string.strcmp(nm_c.id, "dict") == 0: return 1 return 0 elif ak_c == ast.ASTKind.Subscript: sub_c: ast.Subscript* = ast.Subscript*(ann) ann = sub_c.value - else: - return 0 + else: return 0 return 0 @@ -436,18 +392,14 @@ def _ScanTreeForContainers(node: ast.AST*, """递归扫描 AST(字段 + 语句块),检测 list/dict 容器使用""" # 递归深度守卫:AST 损坏成自引用环(字段/children 回指祖先)时无限 # 递归直至栈耗尽(每个 includes 文件 parse 后必执行)。fail-fast 终止。 - if depth > 128: - VLogger.error("容器扫描递归过深(AST 环或嵌套超过 128 层)", "Phase1") - if node is None: - return + if depth > 128: VLogger.error("容器扫描递归过深(AST 环或嵌套超过 128 层)", "Phase1") + if node is None: return k_s: int = node.kind() if k_s == ast.ASTKind.Name: nm_s: ast.Name* = ast.Name*(node) if nm_s.id is not None: - if string.strcmp(nm_s.id, "list") == 0: - need_list_box[0] = 1 - elif string.strcmp(nm_s.id, "dict") == 0: - need_dict_box[0] = 1 + if string.strcmp(nm_s.id, "list") == 0: need_list_box[0] = 1 + elif string.strcmp(nm_s.id, "dict") == 0: need_dict_box[0] = 1 elif k_s == ast.ASTKind.Subscript: sub_s: ast.Subscript* = ast.Subscript*(node) _ScanTreeForContainers(sub_s.value, need_list_box, need_dict_box, depth + 1) @@ -463,16 +415,14 @@ def _ScanTreeForContainers(node: ast.AST*, if cl_args_s is not None: na_s: sizet = len(cl_args_s) i_a2: sizet - for i_a2 in range(na_s): - _ScanTreeForContainers(cl_args_s.get(i_a2), need_list_box, need_dict_box, depth + 1) + for i_a2 in range(na_s): _ScanTreeForContainers(cl_args_s.get(i_a2), need_list_box, need_dict_box, depth + 1) cl_kws_s: list[ast.AST*]* = cl_s2.keywords if cl_kws_s is not None: nk_s: sizet = len(cl_kws_s) i_k2: sizet for i_k2 in range(nk_s): kw_s: rawptr[ast.Keyword] = rawptr[ast.Keyword](cl_kws_s.get(i_k2)) - if kw_s is not None: - _ScanTreeForContainers(kw_s.value, need_list_box, need_dict_box, depth + 1) + if kw_s is not None: _ScanTreeForContainers(kw_s.value, need_list_box, need_dict_box, depth + 1) elif k_s == ast.ASTKind.Assign: asn_s: ast.Assign* = ast.Assign*(node) _ScanTreeForContainers(asn_s.value, need_list_box, need_dict_box, depth + 1) @@ -480,8 +430,7 @@ def _ScanTreeForContainers(node: ast.AST*, if tgts_s is not None: nt_s: sizet = len(tgts_s) i_t2: sizet - for i_t2 in range(nt_s): - _ScanTreeForContainers(tgts_s.get(i_t2), need_list_box, need_dict_box, depth + 1) + for i_t2 in range(nt_s): _ScanTreeForContainers(tgts_s.get(i_t2), need_list_box, need_dict_box, depth + 1) elif k_s == ast.ASTKind.AnnAssign: aa_s2: ast.AnnAssign* = ast.AnnAssign*(node) _ScanTreeForContainers(aa_s2.annotation, need_list_box, need_dict_box, depth + 1) @@ -497,16 +446,14 @@ def _ScanTreeForContainers(node: ast.AST*, i_f2: sizet for i_f2 in range(nf_s): arg_s: ast.Arg* = ast.Arg*(fa_s.get(i_f2)) - if arg_s is not None: - _ScanTreeForContainers(arg_s.annotation, need_list_box, need_dict_box, depth + 1) + if arg_s is not None: _ScanTreeForContainers(arg_s.annotation, need_list_box, need_dict_box, depth + 1) elif k_s == ast.ASTKind.ClassDef: cd_s: ast.ClassDef* = ast.ClassDef*(node) bases_s: list[ast.AST*]* = cd_s.bases if bases_s is not None: nb_s: sizet = len(bases_s) i_b2: sizet - for i_b2 in range(nb_s): - _ScanTreeForContainers(bases_s.get(i_b2), need_list_box, need_dict_box, depth + 1) + for i_b2 in range(nb_s): _ScanTreeForContainers(bases_s.get(i_b2), need_list_box, need_dict_box, depth + 1) elif k_s == ast.ASTKind.Attribute: at_s: ast.Attribute* = ast.Attribute*(node) _ScanTreeForContainers(at_s.value, need_list_box, need_dict_box, depth + 1) @@ -516,8 +463,7 @@ def _ScanTreeForContainers(node: ast.AST*, if elts_s is not None: ne_s: sizet = len(elts_s) i_e2: sizet - for i_e2 in range(ne_s): - _ScanTreeForContainers(elts_s.get(i_e2), need_list_box, need_dict_box, depth + 1) + for i_e2 in range(ne_s): _ScanTreeForContainers(elts_s.get(i_e2), need_list_box, need_dict_box, depth + 1) elif k_s == ast.ASTKind.UnaryOp: uop_s: ast.UnaryOp* = ast.UnaryOp*(node) _ScanTreeForContainers(uop_s.operand, need_list_box, need_dict_box, depth + 1) @@ -534,16 +480,14 @@ def _ScanTreeForContainers(node: ast.AST*, if cps_s is not None: nc_s: sizet = len(cps_s) i_c2: sizet - for i_c2 in range(nc_s): - _ScanTreeForContainers(cps_s.get(i_c2), need_list_box, need_dict_box, depth + 1) + for i_c2 in range(nc_s): _ScanTreeForContainers(cps_s.get(i_c2), need_list_box, need_dict_box, depth + 1) elif k_s == ast.ASTKind.BoolOp: bo_s: rawptr[ast.BoolOp] = rawptr[ast.BoolOp](node) bvs_s: list[ast.AST*]* = bo_s.values if bvs_s is not None: nv_s: sizet = len(bvs_s) i_v2: sizet - for i_v2 in range(nv_s): - _ScanTreeForContainers(bvs_s.get(i_v2), need_list_box, need_dict_box, depth + 1) + for i_v2 in range(nv_s): _ScanTreeForContainers(bvs_s.get(i_v2), need_list_box, need_dict_box, depth + 1) # `[...]`/`{}` 字面量不触发 _list/_dict 导入:字面量广泛用于编译期常量列表(c.Asm 的 op/inp/out CLOBBER 参数)与数组数据初始化,并非容器使用; # 容器的真实使用由类型位置检测覆盖(Name/Subscript 注解、Call.func 构造名)。 # elif k_s == ast.ASTKind.List: @@ -555,5 +499,4 @@ def _ScanTreeForContainers(node: ast.AST*, ch_s: list[ast.AST*]* = node.children n_s: sizet = len(ch_s) ci_s: sizet - for ci_s in range(n_s): - _ScanTreeForContainers(ch_s.get(ci_s), need_list_box, need_dict_box, depth + 1) + for ci_s in range(n_s): _ScanTreeForContainers(ch_s.get(ci_s), need_list_box, need_dict_box, depth + 1) diff --git a/App/lib/Phase/Phase1/Phase1Topo.vp b/App/lib/Phase/Phase1/Phase1Topo.vp index 478f96d..e13ddf1 100644 --- a/App/lib/Phase/Phase1/Phase1Topo.vp +++ b/App/lib/Phase/Phase1/Phase1Topo.vp @@ -55,8 +55,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, out_order: t.CPtr, out_count: t.CPtr, temp_dir: str, td_len_ts: sizet) -> int: """根据类继承关系对文件进行拓扑排序""" - if result is None or out_order is None or out_count is None: - return -1 + if result is None or out_order is None or out_count is None: return -1 entry_size: sizet = IncludesScanner.FileEntry.__sizeof__() @@ -69,16 +68,11 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, file_processed: t.CPtr = mb.alloc(Phase1.MAX_FILE_DEPS * 4) if file_sha1s_buf is None or file_deps_buf is None or file_dep_counts is None or file_indegrees is None or file_processed is None: - if file_sha1s_buf is not None: - mb.free(file_sha1s_buf) - if file_deps_buf is not None: - mb.free(file_deps_buf) - if file_dep_counts is not None: - mb.free(file_dep_counts) - if file_indegrees is not None: - mb.free(file_indegrees) - if file_processed is not None: - mb.free(file_processed) + if file_sha1s_buf is not None: mb.free(file_sha1s_buf) + if file_deps_buf is not None: mb.free(file_deps_buf) + if file_dep_counts is not None: mb.free(file_dep_counts) + if file_indegrees is not None: mb.free(file_indegrees) + if file_processed is not None: mb.free(file_processed) return -1 string.memset(file_sha1s_buf, 0, Phase1.MAX_FILE_DEPS * Phase1.SHA1_LEN) @@ -92,20 +86,15 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, for i in range(result.Count): entry_addr: uint64 = uint64(result.Entries) + i * entry_size entry: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](entry_addr) - if entry is None or entry.Sha1 is None: - continue + if entry is None or entry.Sha1 is None: continue sha1_e: str = entry.Sha1 in_set: int = 0 - if use_reachable != 0: - in_set = StubMergerCollect._is_in_sha1_set(sha1_e, reachable_set, reachable_count) - else: - in_set = StubMergerCollect._is_in_sha1_set(sha1_e, sha1_set, set_count) - if in_set == 0: - continue + if use_reachable != 0: in_set = StubMergerCollect._is_in_sha1_set(sha1_e, reachable_set, reachable_count) + else: in_set = StubMergerCollect._is_in_sha1_set(sha1_e, sha1_set, set_count) + if in_set == 0: continue - if file_count >= Phase1.MAX_FILE_DEPS: - break + if file_count >= Phase1.MAX_FILE_DEPS: break # 初始化扁平数组:文件 SHA1(偏移 = file_count * Phase1.SHA1_LEN) # DepCount/InDegree/Processed 已由 memset 清零 @@ -118,8 +107,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, for ci in range(class_count): # 读取父类名(偏移 = ci * Phase1.CLASS_NAME_LEN) parent_ptr: str = parent_names_buf + ci * Phase1.CLASS_NAME_LEN - if parent_ptr[0] == '\0': - continue + if parent_ptr[0] == '\0': continue # 读取子类定义 SHA1(偏移 = ci * Phase1.SHA1_LEN) child_def_sha1: str = def_sha1s_buf + ci * Phase1.SHA1_LEN @@ -130,20 +118,17 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, continue # 父类不在 includes 中(如 Object、CEnum 等标记基类) # 父类文件 SHA1 不能等于子类文件 SHA1(同文件内继承不需要依赖) - if string.strcmp(parent_sha1, child_def_sha1) == 0: - continue + if string.strcmp(parent_sha1, child_def_sha1) == 0: continue # 找到子类文件对应的索引,添加父文件 SHA1 到依赖列表 for fi in range(file_count): fsha1: str = file_sha1s_buf + fi * Phase1.SHA1_LEN - if string.strcmp(fsha1, child_def_sha1) != 0: - continue + if string.strcmp(fsha1, child_def_sha1) != 0: continue # 读取当前依赖数量 cnt_addr: uint64 = uint64(file_dep_counts) + fi * 4 cnt_ptr: t.CPtr = (int*)(cnt_addr) - if cnt_ptr is None: - break + if cnt_ptr is None: break cur_cnt: int = cnt_ptr[0] # 检查依赖是否已添加(去重) @@ -153,8 +138,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, if string.strcmp(dep_slot, parent_sha1) == 0: already = 1 break - if already != 0: - break + if already != 0: break if cur_cnt < Phase1.MAX_DEP_EDGES: dep_dst: str = file_deps_buf + fi * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + cur_cnt * Phase1.SHA1_LEN @@ -174,44 +158,34 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, map_count_ts = StubMergerIR._BuildIncludesSha1Map( temp_dir, td_len_ts, sha1_arr_ts, mod_arr_ts) for fi_imp in range(file_count): - if map_count_ts <= 0: - break + if map_count_ts <= 0: break fsha1_imp: str = file_sha1s_buf + fi_imp * Phase1.SHA1_LEN deps_imp: str = StubMergerStore.LookupIncludesDeps(fsha1_imp) - if deps_imp is None: - continue + if deps_imp is None: continue dl_imp: sizet = string.strlen(deps_imp) dpos_imp: sizet = 0 while dpos_imp < dl_imp: dstart_imp: sizet = dpos_imp - while dpos_imp < dl_imp and deps_imp[dpos_imp] != ' ': - dpos_imp += 1 + while dpos_imp < dl_imp and deps_imp[dpos_imp] != ' ': dpos_imp += 1 dlen_imp: sizet = dpos_imp - dstart_imp - if dpos_imp < dl_imp: - dpos_imp += 1 - if dlen_imp == 0: - continue + if dpos_imp < dl_imp: dpos_imp += 1 + if dlen_imp == 0: continue dname_imp: bytes = stdlib.malloc(dlen_imp + 1) - if dname_imp is None: - continue + if dname_imp is None: continue string.strncpy(dname_imp, deps_imp + dstart_imp, dlen_imp) dname_imp[dlen_imp] = '\0' dsha1_imp: str = StubMergerIR._FindSha1ByModName( sha1_arr_ts, mod_arr_ts, map_count_ts, dname_imp) stdlib.free(dname_imp) - if dsha1_imp is None: - continue + if dsha1_imp is None: continue # 找依赖文件在列表中的索引(跳过自身) for fj_imp in range(file_count): - if string.strcmp(file_sha1s_buf + fj_imp * Phase1.SHA1_LEN, dsha1_imp) != 0: - continue - if fj_imp == fi_imp: - break + if string.strcmp(file_sha1s_buf + fj_imp * Phase1.SHA1_LEN, dsha1_imp) != 0: continue + if fj_imp == fi_imp: break # 去重 + 加边:fi_imp 依赖 fj_imp(InDegree[fi_imp]++) cnt_addr_imp: uint64 = uint64(file_dep_counts) + fi_imp * 4 cnt_ptr_imp: t.CPtr = (int*)(cnt_addr_imp) - if cnt_ptr_imp is None: - break + if cnt_ptr_imp is None: break cur_cnt_imp: int = cnt_ptr_imp[0] already_imp: int = 0 for di_imp in range(cur_cnt_imp): @@ -226,10 +200,8 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, break # 释放 import 边用的局部映射数组 - if sha1_arr_ts is not None: - stdlib.free(sha1_arr_ts) - if mod_arr_ts is not None: - stdlib.free(mod_arr_ts) + if sha1_arr_ts is not None: stdlib.free(sha1_arr_ts) + if mod_arr_ts is not None: stdlib.free(mod_arr_ts) # 3. Kahn 算法:InDegree = DepCount(依赖多少个父文件) # 依赖为 0 的先处理,处理后减少依赖它的文件入度 @@ -238,8 +210,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, cnt_ptr3: t.CPtr = (int*)(cnt_addr3) ind_addr3: uint64 = uint64(file_indegrees) + fi * 4 ind_ptr3: t.CPtr = (int*)(ind_addr3) - if cnt_ptr3 is not None and ind_ptr3 is not None: - ind_ptr3[0] = cnt_ptr3[0] + if cnt_ptr3 is not None and ind_ptr3 is not None: ind_ptr3[0] = cnt_ptr3[0] # 4. 拓扑排序输出 out_idx: int = 0 @@ -250,13 +221,11 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, # 检查处理状态 proc_addr4: uint64 = uint64(file_processed) + fi * 4 proc_ptr4: t.CPtr = (int*)(proc_addr4) - if proc_ptr4 is None or proc_ptr4[0] != 0: - continue + if proc_ptr4 is None or proc_ptr4[0] != 0: continue # 检查入度 ind_addr4: uint64 = uint64(file_indegrees) + fi * 4 ind_ptr4: t.CPtr = (int*)(ind_addr4) - if ind_ptr4 is None or ind_ptr4[0] > 0: - continue + if ind_ptr4 is None or ind_ptr4[0] > 0: continue # 入度为 0,可以处理 # 找到对应的 result.Entries 索引 @@ -269,8 +238,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, # 写入输出索引数组 out_idx_addr: uint64 = uint64(out_order) + out_idx * 4 out_int_ptr: t.CPtr = (int*)(out_idx_addr) - if out_int_ptr is not None: - out_int_ptr[0] = ri + if out_int_ptr is not None: out_int_ptr[0] = ri out_idx += 1 break @@ -282,21 +250,18 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, for fj in range(file_count): proc_addr5: uint64 = uint64(file_processed) + fj * 4 proc_ptr5: t.CPtr = (int*)(proc_addr5) - if proc_ptr5 is None or proc_ptr5[0] != 0: - continue + if proc_ptr5 is None or proc_ptr5[0] != 0: continue # 读取 fj 的依赖数量 cnt_addr5: uint64 = uint64(file_dep_counts) + fj * 4 cnt_ptr5: t.CPtr = (int*)(cnt_addr5) - if cnt_ptr5 is None: - continue + if cnt_ptr5 is None: continue fj_dep_cnt: int = cnt_ptr5[0] for di in range(fj_dep_cnt): dep_slot5: str = file_deps_buf + fj * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di * Phase1.SHA1_LEN if string.strcmp(dep_slot5, target_sha1) == 0: ind_addr5: uint64 = uint64(file_indegrees) + fj * 4 ind_ptr5: t.CPtr = (int*)(ind_addr5) - if ind_ptr5 is not None: - ind_ptr5[0] = ind_ptr5[0] - 1 + if ind_ptr5 is not None: ind_ptr5[0] = ind_ptr5[0] - 1 break # 处理循环依赖:环内优先输出被依赖者(被其余剩余文件依赖数量多者先)。 @@ -321,12 +286,10 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, target_sha1_a: str = file_sha1s_buf + fi_a * Phase1.SHA1_LEN for i_b in range(rem_count): fi_b: int = rem_idx[i_b] - if fi_b == fi_a: - continue + if fi_b == fi_a: continue cnt_addr_b: uint64 = uint64(file_dep_counts) + fi_b * 4 cnt_ptr_b: t.CPtr = (int*)(cnt_addr_b) - if cnt_ptr_b is None: - continue + if cnt_ptr_b is None: continue cnt_b: int = cnt_ptr_b[0] for di_b in range(cnt_b): dep_slot_b: str = file_deps_buf + fi_b * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di_b * Phase1.SHA1_LEN @@ -348,8 +311,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, fi_a2: int = rem_idx[i_a] proc_addr8: uint64 = uint64(file_processed) + fi_a2 * 4 proc_ptr8: t.CPtr = (int*)(proc_addr8) - if proc_ptr8 is None or proc_ptr8[0] != 0: - continue + if proc_ptr8 is None or proc_ptr8[0] != 0: continue target_sha1_2: str = file_sha1s_buf + fi_a2 * Phase1.SHA1_LEN for ri in range(result.Count): ea_r2: uint64 = uint64(result.Entries) + ri * entry_size @@ -358,8 +320,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, if string.strcmp(ent_r2.Sha1, target_sha1_2) == 0: out_idx_addr2: uint64 = uint64(out_order) + out_idx * 4 out_int_ptr2: t.CPtr = (int*)(out_idx_addr2) - if out_int_ptr2 is not None: - out_int_ptr2[0] = ri + if out_int_ptr2 is not None: out_int_ptr2[0] = ri out_idx += 1 break proc_ptr8[0] = 1 @@ -368,8 +329,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, # 写入输出数量 out_count_ptr: t.CPtr = (int*)(out_count) - if out_count_ptr is not None: - out_count_ptr[0] = out_idx + if out_count_ptr is not None: out_count_ptr[0] = out_idx # 释放扁平数组 mb.free(file_sha1s_buf) diff --git a/App/lib/Phase/Phase2/__init__.vp b/App/lib/Phase/Phase2/__init__.vp index afd634d..53a705e 100644 --- a/App/lib/Phase/Phase2/__init__.vp +++ b/App/lib/Phase/Phase2/__init__.vp @@ -56,15 +56,12 @@ def _ScanDirForPyFiles(mb: memhub.MemBuddy*, entry_size: sizet, file_count: int, max_files: int) -> int: """递归扫描目录,收集 .vp/.py 文件到 entries,返回新的 file_count""" - if dir_path is None or entries is None: - return file_count - if file_count >= max_files: - return file_count + if dir_path is None or entries is None: return file_count + if file_count >= max_files: return file_count dir_len: sizet = string.strlen(dir_path) pattern: bytes = stdlib.malloc(dir_len + 16) - if pattern is None: - return file_count + if pattern is None: return file_count viperlib.snprintf(pattern, dir_len + 16, "%s/*", dir_path) find_data_size: sizet = w32.win32file.WIN32_FIND_DATAA.__sizeof__() @@ -83,37 +80,30 @@ def _ScanDirForPyFiles(mb: memhub.MemBuddy*, while True: fname: str = find_data.cFileName if fname is None: - if w32.win32file.FindNextFileA(handle, find_data) == 0: - break + if w32.win32file.FindNextFileA(handle, find_data) == 0: break continue fname_len: sizet = string.strlen(fname) if fname_len <= 0: - if w32.win32file.FindNextFileA(handle, find_data) == 0: - break + if w32.win32file.FindNextFileA(handle, find_data) == 0: break continue # 跳过 . 和 .. is_dot: int = 0 - if fname_len == 1 and fname[0] == '.': - is_dot = 1 - elif fname_len == 2 and fname[0] == '.' and fname[1] == '.': - is_dot = 1 + if fname_len == 1 and fname[0] == '.': is_dot = 1 + elif fname_len == 2 and fname[0] == '.' and fname[1] == '.': is_dot = 1 if is_dot != 0: - if w32.win32file.FindNextFileA(handle, find_data) == 0: - break + if w32.win32file.FindNextFileA(handle, find_data) == 0: break continue # 检查是否是目录 attrs: ULONG = find_data.dwFileAttributes is_dir: int = 0 - if (attrs & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: - is_dir = 1 + if (attrs & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: is_dir = 1 if is_dir != 0: # 递归扫描子目录 sub_dir: bytes = Utils.JoinPath(dir_path, fname) if sub_dir is not None: file_count = _ScanDirForPyFiles(mb, sub_dir, entries, entry_size, file_count, max_files) stdlib.free(sub_dir) - if w32.win32file.FindNextFileA(handle, find_data) == 0: - break + if w32.win32file.FindNextFileA(handle, find_data) == 0: break continue # 检查是否是 .vp 源文件(Viper 源仅 .vp,不再识别 .py) if fname_len > 3 and Utils.is_vp_at(fname, 0, fname_len) != 0 and file_count < max_files: @@ -121,8 +111,7 @@ def _ScanDirForPyFiles(mb: memhub.MemBuddy*, if full_path is not None: sbuf: bytes = Utils.read_file_to_buf(full_path, SRC_BUF_SIZE) if sbuf is None: - if w32.win32file.FindNextFileA(handle, find_data) == 0: - break + if w32.win32file.FindNextFileA(handle, find_data) == 0: break continue # 统一用 IncludesScanner.compute_file_sha1(CRLF→LF 归一化),与 StubMerger 对同一批 App 源文件的口径一致; # 用原始字节口径会导致 stub/define 符号前缀不一致 → 链接 undefined reference。 @@ -139,8 +128,7 @@ def _ScanDirForPyFiles(mb: memhub.MemBuddy*, stdlib.free(sbuf) # full_path 不释放:ent.Path 引用它 - if w32.win32file.FindNextFileA(handle, find_data) == 0: - break + if w32.win32file.FindNextFileA(handle, find_data) == 0: break w32.win32file.FindClose(handle) stdlib.free(pattern) @@ -161,15 +149,12 @@ def _ScanDirForAsmFiles(mb: memhub.MemBuddy*, entry_size: sizet, file_count: int, max_files: int) -> int: """递归扫描目录,收集 .s 汇编文件到 entries,返回新的 file_count""" - if dir_path is None or entries is None: - return file_count - if file_count >= max_files: - return file_count + if dir_path is None or entries is None: return file_count + if file_count >= max_files: return file_count dir_len: sizet = string.strlen(dir_path) pattern: bytes = stdlib.malloc(dir_len + 16) - if pattern is None: - return file_count + if pattern is None: return file_count viperlib.snprintf(pattern, dir_len + 16, "%s/*", dir_path) find_data_size: sizet = w32.win32file.WIN32_FIND_DATAA.__sizeof__() @@ -188,41 +173,33 @@ def _ScanDirForAsmFiles(mb: memhub.MemBuddy*, while True: fname: str = find_data.cFileName if fname is None: - if w32.win32file.FindNextFileA(handle, find_data) == 0: - break + if w32.win32file.FindNextFileA(handle, find_data) == 0: break continue fname_len: sizet = string.strlen(fname) if fname_len <= 0: - if w32.win32file.FindNextFileA(handle, find_data) == 0: - break + if w32.win32file.FindNextFileA(handle, find_data) == 0: break continue # 跳过 . 和 .. is_dot: int = 0 - if fname_len == 1 and fname[0] == '.': - is_dot = 1 - elif fname_len == 2 and fname[0] == '.' and fname[1] == '.': - is_dot = 1 + if fname_len == 1 and fname[0] == '.': is_dot = 1 + elif fname_len == 2 and fname[0] == '.' and fname[1] == '.': is_dot = 1 if is_dot != 0: - if w32.win32file.FindNextFileA(handle, find_data) == 0: - break + if w32.win32file.FindNextFileA(handle, find_data) == 0: break continue # 检查是否是目录 attrs: ULONG = find_data.dwFileAttributes is_dir: int = 0 - if (attrs & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: - is_dir = 1 + if (attrs & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: is_dir = 1 if is_dir != 0: sub_dir: bytes = Utils.JoinPath(dir_path, fname) if sub_dir is not None: file_count = _ScanDirForAsmFiles(mb, sub_dir, entries, entry_size, file_count, max_files) stdlib.free(sub_dir) - if w32.win32file.FindNextFileA(handle, find_data) == 0: - break + if w32.win32file.FindNextFileA(handle, find_data) == 0: break continue # 检查是否以 .s 后缀结尾(汇编源文件) is_asm: int = 0 - if fname_len > 2 and fname[fname_len - 2] == '.' and fname[fname_len - 1] == 's': - is_asm = 1 + if fname_len > 2 and fname[fname_len - 2] == '.' and fname[fname_len - 1] == 's': is_asm = 1 if is_asm != 0 and file_count < max_files: full_path: bytes = Utils.JoinPath(dir_path, fname) if full_path is not None: @@ -239,8 +216,7 @@ def _ScanDirForAsmFiles(mb: memhub.MemBuddy*, VLogger.info(f"{fname} (asm sha1={sha1_val})", "project") # full_path 不释放:ent.Path 引用它 - if w32.win32file.FindNextFileA(handle, find_data) == 0: - break + if w32.win32file.FindNextFileA(handle, find_data) == 0: break w32.win32file.FindClose(handle) stdlib.free(pattern) @@ -260,18 +236,15 @@ def _PreRegisterAppGenericTemplates(mb: memhub.MemBuddy*, file_count: int, entry_size: sizet) -> int: """mark2 前预注册 App 源文件的泛型类模板,返回处理到的泛型类数量""" - if mb is None or entries is None or file_count <= 0: - return 0 + if mb is None or entries is None or file_count <= 0: return 0 handled: int = 0 for i in range(file_count): ea_pa: uint64 = uint64(entries) + i * entry_size ent_pa: SrcFileEntry* = (SrcFileEntry*)(ea_pa) - if ent_pa is None or ent_pa.Path is None or ent_pa.Sha1 is None: - continue + if ent_pa is None or ent_pa.Path is None or ent_pa.Sha1 is None: continue # 读取文件 f_pa: rawptr[fileio.File] = fileio.File(ent_pa.Path, fileio.MODE.R) - if f_pa.closed: - continue + if f_pa.closed: continue # read_all 的容量参数含终止符(最多读 cap-1 字节), 文件更长会被静默截断 if f_pa.size() >= SRC_BUF_SIZE: VLogger.error(f"源文件超过 {SRC_BUF_SIZE} 字节上限, 拒绝读取: {ent_pa.Path}", "PhaseA") @@ -286,12 +259,10 @@ def _PreRegisterAppGenericTemplates(mb: memhub.MemBuddy*, if bytes_read_pa <= 0: stdlib.free(src_buf_pa) continue - if bytes_read_pa < SRC_BUF_SIZE: - src_buf_pa[bytes_read_pa] = 0 + if bytes_read_pa < SRC_BUF_SIZE: src_buf_pa[bytes_read_pa] = 0 # 解析 AST(只解析,不完整翻译;用永久池使模板节点跨 mark2 reset 存活) perm_pa: memhub.MemBuddy* = CompilerFactory.factory.PermPool - if perm_pa is None: - perm_pa = mb + if perm_pa is None: perm_pa = mb lx_pa: ast.Lexer* = ast.new_lexer(perm_pa) if lx_pa is None: stdlib.free(src_buf_pa) @@ -308,32 +279,26 @@ def _PreRegisterAppGenericTemplates(mb: memhub.MemBuddy*, cn_pa: sizet = len(ch_pa) for ci_pa in range(cn_pa): child_pa: ast.AST* = ch_pa.get(ci_pa) - if child_pa is None: - continue + if child_pa is None: continue ck_pa: int = child_pa.kind() if ck_pa == ast.ASTKind.ClassDef: cd_pa: ast.ClassDef* = ast.ClassDef*(child_pa) - if cd_pa is None or cd_pa.name is None: - continue + if cd_pa is None or cd_pa.name is None: continue tp_pa: list[str]* = cd_pa.type_params - if tp_pa is None: - continue + if tp_pa is None: continue GenApi.set_current_file_type(ent_pa.Path) GenApi._register_generic_template(perm_pa, cd_pa, ent_pa.Sha1) handled += 1 elif ck_pa == ast.ASTKind.FunctionDef: fd_pa: ast.FunctionDef* = ast.FunctionDef*(child_pa) - if fd_pa is None or fd_pa.name is None: - continue + if fd_pa is None or fd_pa.name is None: continue tf_pa: list[str]* = fd_pa.type_params - if tf_pa is None: - continue + if tf_pa is None: continue GenApi.set_current_file_type(ent_pa.Path) 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"mark2 前预注册 {handled} 个 App 泛型模板(类+函数)", "PhaseA") return handled @@ -363,12 +328,9 @@ def _PhaseADiagInit(max_count: sizet) -> None: _pa_diag_sha1 = stdlib.malloc(max_count * 17) _pa_diag_deps = stdlib.malloc(max_count * PA_DEPS_MAX_STR) _pa_diag_miss = stdlib.malloc(max_count * PA_MISS_MAX_STR) - if _pa_diag_sha1 is not None: - string.memset(_pa_diag_sha1, 0, max_count * 17) - if _pa_diag_deps is not None: - string.memset(_pa_diag_deps, 0, max_count * PA_DEPS_MAX_STR) - if _pa_diag_miss is not None: - string.memset(_pa_diag_miss, 0, max_count * PA_MISS_MAX_STR) + if _pa_diag_sha1 is not None: string.memset(_pa_diag_sha1, 0, max_count * 17) + if _pa_diag_deps is not None: string.memset(_pa_diag_deps, 0, max_count * PA_DEPS_MAX_STR) + if _pa_diag_miss is not None: string.memset(_pa_diag_miss, 0, max_count * PA_MISS_MAX_STR) def _PhaseADiagFree() -> None: @@ -390,10 +352,8 @@ def _PhaseADiagFree() -> None: def _PhaseADiagRecord(sha1: str, deps: str, miss: str) -> None: """记录/更新单文件诊断:sha1 → 依赖串 + 缺失明细(None 表示不更新该字段)""" global _pa_diag_count - if _pa_diag_sha1 is None or _pa_diag_deps is None or sha1 is None: - return - if string.strlen(sha1) < 16: - return + if _pa_diag_sha1 is None or _pa_diag_deps is None or sha1 is None: return + if string.strlen(sha1) < 16: return for i in range(_pa_diag_count): es: bytes = _pa_diag_sha1 + sizet(i) * 17 if string.strcmp(es, sha1) == 0: @@ -402,14 +362,12 @@ def _PhaseADiagRecord(sha1: str, deps: str, miss: str) -> None: string.strncpy(maddr, miss, PA_MISS_MAX_STR - 1) maddr[PA_MISS_MAX_STR - 1] = 0 return - if _pa_diag_count >= _pa_diag_max: - return + if _pa_diag_count >= _pa_diag_max: return saddr: bytes = _pa_diag_sha1 + sizet(_pa_diag_count) * 17 string.strncpy(saddr, sha1, 16) saddr[16] = 0 daddr: bytes = _pa_diag_deps + sizet(_pa_diag_count) * PA_DEPS_MAX_STR - if deps is not None: - string.strncpy(daddr, deps, PA_DEPS_MAX_STR - 1) + if deps is not None: string.strncpy(daddr, deps, PA_DEPS_MAX_STR - 1) daddr[PA_DEPS_MAX_STR - 1] = 0 if miss is not None and _pa_diag_miss is not None: maddr2: bytes = _pa_diag_miss + sizet(_pa_diag_count) * PA_MISS_MAX_STR @@ -420,16 +378,14 @@ def _PhaseADiagRecord(sha1: str, deps: str, miss: str) -> None: def _PhaseADiagDepsLookup(sha1: str) -> str: """按 sha1 查持久化依赖串(stdlib.malloc 副本,调用者 free;未命中 None)""" - if _pa_diag_sha1 is None or _pa_diag_deps is None or sha1 is None: - return None + if _pa_diag_sha1 is None or _pa_diag_deps is None or sha1 is None: return None for i in range(_pa_diag_count): es: bytes = _pa_diag_sha1 + sizet(i) * 17 if string.strcmp(es, sha1) == 0: src: bytes = _pa_diag_deps + sizet(i) * PA_DEPS_MAX_STR ln: sizet = string.strlen(src) out: bytes = stdlib.malloc(ln + 1) - if out is None: - return None + if out is None: return None string.strcpy(out, src) return out return None @@ -437,18 +393,15 @@ def _PhaseADiagDepsLookup(sha1: str) -> str: def _PhaseADiagMissLookup(sha1: str) -> str: """按 sha1 查持久化缺失明细(stdlib.malloc 副本,调用者 free;未命中/空 None)""" - if _pa_diag_sha1 is None or _pa_diag_miss is None or sha1 is None: - return None + if _pa_diag_sha1 is None or _pa_diag_miss is None or sha1 is None: return None for i in range(_pa_diag_count): es: bytes = _pa_diag_sha1 + sizet(i) * 17 if string.strcmp(es, sha1) == 0: src: bytes = _pa_diag_miss + sizet(i) * PA_MISS_MAX_STR ln: sizet = string.strlen(src) - if ln == 0: - return None + if ln == 0: return None out: bytes = stdlib.malloc(ln + 1) - if out is None: - return None + if out is None: return None string.strcpy(out, src) return out return None @@ -456,11 +409,9 @@ def _PhaseADiagMissLookup(sha1: str) -> str: def _PhaseATextLLExists(temp_dir: str, td_len: sizet, sha1: str) -> int: """探测 {temp_dir}/{sha1前2位}/{sha1}.text.ll 是否存在,1=存在""" - if temp_dir is None or td_len == 0 or sha1 is None or string.strlen(sha1) < 2: - return 0 + if temp_dir is None or td_len == 0 or sha1 is None or string.strlen(sha1) < 2: return 0 tpath: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "text.ll") - if tpath is None: - return 0 + if tpath is None: return 0 tf: rawptr[fileio.File] = fileio.File(tpath, fileio.MODE.R) exists: int = 0 if not tf.closed: @@ -472,11 +423,9 @@ def _PhaseATextLLExists(temp_dir: str, td_len: sizet, sha1: str) -> int: def _PhaseAResolveDepSha1(mod_name: str) -> str: """依赖模块名 → SHA1(精确 → 后缀兜底),未命中 None""" - if mod_name is None: - return None + if mod_name is None: return None s1: str = StubMergerStore.LookupSha1ByModName(mod_name) - if s1 is not None: - return s1 + if s1 is not None: return s1 return StubMergerStore.LookupSha1ByModNameSuffix(mod_name) @@ -484,8 +433,7 @@ def _PhaseADumpNode(temp_dir: str, td_len: sizet, sha1: str, depth: int, prefix: bytes) -> None: """递归打印依赖子图;[MISS]=缺 text.ll(下钻整链),[OK]=就绪(仅探测 1 层)""" deps: bytes = None - if sha1 is not None: - deps = _PhaseADiagDepsLookup(sha1) + if sha1 is not None: deps = _PhaseADiagDepsLookup(sha1) if deps is None and sha1 is not None: # 回退:读取 {temp_dir}/{前缀}/{sha1}.deps.txt(Phase1 已为 includes 写盘) dpath: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "deps.txt") @@ -495,85 +443,64 @@ def _PhaseADumpNode(temp_dir: str, td_len: sizet, sha1: str, deps = stdlib.malloc(PA_DEPS_MAX_STR) if deps is not None: rl: int64 = df.read_all(deps, PA_DEPS_MAX_STR) - if rl < 0: - rl = 0 + if rl < 0: rl = 0 # read_all 的容量参数即缓冲区容量(含终止符):传真实容量 MAX 时最多读 MAX-1 字节,故 rl 恒 <= MAX-1,在界内直接写终止符即可。 deps[rl] = 0 df.close() stdlib.free(dpath) if deps is None or deps[0] == 0: - if deps is not None: - stdlib.free(deps) + if deps is not None: stdlib.free(deps) return dl: sizet = string.strlen(deps) token_count: int = 0 pos: sizet = 0 while pos < dl: - while pos < dl and deps[pos] == ' ': - pos += 1 - if pos >= dl: - break + while pos < dl and deps[pos] == ' ': pos += 1 + if pos >= dl: break token_count += 1 - while pos < dl and deps[pos] != ' ': - pos += 1 + while pos < dl and deps[pos] != ' ': pos += 1 pos = 0 idx: int = 0 while pos < dl: - while pos < dl and deps[pos] == ' ': - pos += 1 - if pos >= dl: - break + while pos < dl and deps[pos] == ' ': pos += 1 + if pos >= dl: break ts: sizet = pos - while pos < dl and deps[pos] != ' ': - pos += 1 + while pos < dl and deps[pos] != ' ': pos += 1 tl: sizet = pos - ts nm: bytes = stdlib.malloc(tl + 1) if nm is not None: string.strncpy(nm, deps + ts, tl) nm[tl] = 0 is_last: int = 0 - if idx + 1 >= token_count: - is_last = 1 + if idx + 1 >= token_count: is_last = 1 builtin: int = 0 - if string.strcmp(nm, "t") == 0 or string.strcmp(nm, "c") == 0: - builtin = 1 + if string.strcmp(nm, "t") == 0 or string.strcmp(nm, "c") == 0: builtin = 1 dep_sha1: str = _PhaseAResolveDepSha1(nm) txt_ok: int = 0 - if dep_sha1 is not None: - txt_ok = _PhaseATextLLExists(temp_dir, td_len, dep_sha1) + if dep_sha1 is not None: txt_ok = _PhaseATextLLExists(temp_dir, td_len, dep_sha1) # 分支字符内联(不返回字符串字面量:避免 TPV 对字面量返回的 # 栈临时指针悬垂 → printf %s 崩溃,图输出被吞) br_1: str = "|-- " br_2: str = "`-- " if builtin != 0: - if is_last != 0: - stdio.printf("%s%s%s (builtin)\n", prefix, br_2, nm) - else: - stdio.printf("%s%s%s (builtin)\n", prefix, br_1, nm) + if is_last != 0: stdio.printf("%s%s%s (builtin)\n", prefix, br_2, nm) + else: stdio.printf("%s%s%s (builtin)\n", prefix, br_1, nm) elif dep_sha1 is None: - if is_last != 0: - stdio.printf("%s%s%s (unresolved)\n", prefix, br_2, nm) - else: - stdio.printf("%s%s%s (unresolved)\n", prefix, br_1, nm) + if is_last != 0: stdio.printf("%s%s%s (unresolved)\n", prefix, br_2, nm) + else: stdio.printf("%s%s%s (unresolved)\n", prefix, br_1, nm) elif txt_ok != 0: - if is_last != 0: - stdio.printf("%s%s%s [OK]\n", prefix, br_2, nm) - else: - stdio.printf("%s%s%s [OK]\n", prefix, br_1, nm) + if is_last != 0: stdio.printf("%s%s%s [OK]\n", prefix, br_2, nm) + else: stdio.printf("%s%s%s [OK]\n", prefix, br_1, nm) else: - if is_last != 0: - stdio.printf("%s%s%s [MISS] text.ll=%s\n", prefix, br_2, nm, dep_sha1) - else: - stdio.printf("%s%s%s [MISS] text.ll=%s\n", prefix, br_1, nm, dep_sha1) + if is_last != 0: stdio.printf("%s%s%s [MISS] text.ll=%s\n", prefix, br_2, nm, dep_sha1) + else: stdio.printf("%s%s%s [MISS] text.ll=%s\n", prefix, br_1, nm, dep_sha1) # 下钻:MISS 全链(至 PA_GRAPH_DEPTH_MAX),OK 仅探测 1 层(PA_GRAPH_OK_PROBE) can_expand: int = 0 if dep_sha1 is not None and builtin == 0: if txt_ok == 0: - if depth + 1 < PA_GRAPH_DEPTH_MAX: - can_expand = 1 + if depth + 1 < PA_GRAPH_DEPTH_MAX: can_expand = 1 else: - if depth + 1 < PA_GRAPH_OK_PROBE: - can_expand = 1 + if depth + 1 < PA_GRAPH_OK_PROBE: can_expand = 1 if can_expand != 0: # +5:strcat 追加 "| "/" "(4 字符)+ NUL;strlen+4 会溢出 1 字节 # 破坏堆元数据 → 后续 malloc/free 崩溃,图打印中断且 stdout 缓冲丢失 @@ -581,10 +508,8 @@ def _PhaseADumpNode(temp_dir: str, td_len: sizet, sha1: str, new_prefix: bytes = stdlib.malloc(npl) if new_prefix is not None: string.strcpy(new_prefix, prefix) - if is_last != 0: - string.strcat(new_prefix, " ") - else: - string.strcat(new_prefix, "| ") + if is_last != 0: string.strcat(new_prefix, " ") + else: string.strcat(new_prefix, "| ") _PhaseADumpNode(temp_dir, td_len, dep_sha1, depth + 1, new_prefix) stdlib.free(new_prefix) stdlib.free(nm) @@ -604,8 +529,7 @@ def _PhaseADumpFailGraph(temp_dir: str, td_len: sizet, path: str, sha1: str) -> stdio.fflush(None) miss: bytes = _PhaseADiagMissLookup(sha1) if miss is not None: - if miss[0] != 0: - stdio.printf("[PhaseA-Fail] pending reason: %s\n", miss) + if miss[0] != 0: stdio.printf("[PhaseA-Fail] pending reason: %s\n", miss) stdlib.free(miss) stdio.fflush(None) stdio.printf("[PhaseA-Fail] dep graph ([MISS]=missing text.ll, [OK]=ready, depth<=%d):\n", @@ -643,8 +567,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, # === 1. 递归扫描 source_dir 下的 .vp/.py 文件(包括子目录)=== entry_size: sizet = SrcFileEntry.__sizeof__() entries: SrcFileEntry* = stdlib.malloc(MAX_SRC_FILES * entry_size) - if entries is None: - return 1 + if entries is None: return 1 string.memset(entries, 0, MAX_SRC_FILES * entry_size) file_count: int = _ScanDirForPyFiles(mb, source_dir, entries, entry_size, 0, MAX_SRC_FILES) @@ -657,8 +580,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, 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} 个(llvm-mc 汇编参与链接)", "project") if file_count == 0: stdlib.free(entries) @@ -690,16 +612,13 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, 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 分配失败,无法填充 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("依赖图扫描失败,无法填充 Sha1Store", "project") + elif rc_05 > 0: VLogger.info(f"Phase2 依赖图按需填充 Sha1Store: {rc_05} 个", "project") stdlib.free(rs_05) # 追加 App 源文件 SHA1 到 _sha1_map.txt(人类可读输出,程序内部不读取此文件) @@ -717,27 +636,23 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, for i in range(file_count): ea_am: uint64 = uint64(entries) + i * entry_size ent_am: SrcFileEntry* = (SrcFileEntry*)(ea_am) - if ent_am is None or ent_am.Path is None or ent_am.Sha1 is None: - continue + if ent_am is None or ent_am.Path is None or ent_am.Sha1 is None: continue # 计算相对路径(去除 source_dir 前缀,保留目录结构) p_str: str = ent_am.Path p_len: sizet = string.strlen(p_str) rel_path_am: str = p_str if p_len > src_dir_len_am + 1: - if string.strncmp(p_str, source_dir, src_dir_len_am) == 0: - rel_path_am = p_str + src_dir_len_am + 1 + if string.strncmp(p_str, source_dir, src_dir_len_am) == 0: rel_path_am = p_str + src_dir_len_am + 1 # 同步追加到内存存储器(供跨模块 CDefine 查找) # rel_path_am 格式如 "lib/core/StubMerger.vp",与 _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 失败: {rel_path_am}", "project") app_filled += 1 # 写入 _sha1_map.txt(人类可读输出) if not mf.closed and line_am is not None: viperlib.snprintf(line_am, 512, "%s:%s\n", ent_am.Sha1, rel_path_am) ll_am: sizet = string.strlen(line_am) mf.write(line_am, ll_am) - if line_am is not None: - stdlib.free(line_am) + 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") @@ -802,8 +717,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, vpi_failed_p2 += 1 VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | 文件读取失败或为空", "PhaseA") continue - if bytes_read_vp2 < SRC_BUF_SIZE: - src_buf_vp2[bytes_read_vp2] = 0 + 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) @@ -876,15 +790,13 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, # 返回类型默认推断成 i32,调用点报误导性的「找不到模块 SHA1」)。declare_only=1 时 import 的 SHA1 检查跳过,故预注册失败只可能是文件自身无法翻译。 # 必须跳过 App 文件:Sha1Store 里含 App 源文件 SHA1,但其预注册由 Phase A-pre 负责(App 是严格模式且此阶段依赖未就绪,在此预注册必然失败误报)。 inc_fail_flags: bytes = stdlib.malloc(store_count_inc_pre) - if inc_fail_flags is not None: - string.memset(inc_fail_flags, 1, store_count_inc_pre) + if inc_fail_flags is not None: string.memset(inc_fail_flags, 1, store_count_inc_pre) for pass_inc_i in range(PHASE_A_INC_MAX_PASSES): struct_count_before_inc: int = GenApi.get_struct_count() for si_inc in range(store_count_inc_pre): inc_sha1_pre: str = store_sha1_inc_pre + sizet(si_inc) * 17 inc_rel_pre: str = store_rel_inc_pre + sizet(si_inc) * StubMerger.MAX_REL_PATH_LEN - if inc_rel_pre is None or inc_rel_pre[0] == '\0': - continue + if inc_rel_pre is None or inc_rel_pre[0] == '\0': continue # 跳过 App 源文件(main.vp 等):由 Phase A-pre 预注册,不算失败 is_app_file_inc: int = 0 for i_app_inc in range(file_count): @@ -899,12 +811,10 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, rel_len_pre: sizet = string.strlen(inc_rel_pre) # 所属 includes 根目录(多目录逐条取自 IncDir 数组,空串回退 includes_dir) incdir_pre: str = store_incdir_inc_pre + sizet(si_inc) * StubMerger.MAX_INC_DIR_LEN - if incdir_pre is None or incdir_pre[0] == '\0': - incdir_pre = includes_dir + if incdir_pre is None or incdir_pre[0] == '\0': incdir_pre = includes_dir incdir_len_pre: sizet = string.strlen(incdir_pre) full_path_pre: bytes = stdlib.malloc(incdir_len_pre + rel_len_pre + 2) - if full_path_pre is None: - continue + if full_path_pre is None: continue viperlib.snprintf(full_path_pre, incdir_len_pre + rel_len_pre + 2, "%s/%s", incdir_pre, inc_rel_pre) pkg_inc_pre: str = GenApi.compute_package_from_relpath(mb, inc_rel_pre) @@ -915,8 +825,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, # 记录本文件依赖(供收敛失败依赖图诊断;stdlib 表跨 reset 存活) _PhaseADiagRecord(inc_sha1_pre, tr_inc_pre._imported_modules, None) # 预注册成功:清除失败标记 - if inc_fail_flags is not None: - inc_fail_flags[si_inc] = 0 + if inc_fail_flags is not None: inc_fail_flags[si_inc] = 0 # 依赖填充只在第一遍执行(PopulateIncludesDeps 内部有去重) # 注意:必须在 reset_to(mark2) 之前调用——内部深拷贝到 stdlib if pass_inc_i == 0 and tr_inc_pre._imported_modules is not None and StubMergerStore.PopulateIncludesDeps( @@ -927,8 +836,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, mb.reset_to(mark2) struct_count_after_inc: int = GenApi.get_struct_count() # 收敛检查:本遍没有新结构体注册 → 所有类已注册 - if struct_count_after_inc == struct_count_before_inc: - break + if struct_count_after_inc == struct_count_before_inc: break # 多遍后仍预注册失败的 includes → 报错终止(不允许降级) if inc_fail_flags is not None: for si_inc_f in range(store_count_inc_pre): @@ -949,8 +857,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, for i in range(file_count): ea_pre: uint64 = uint64(entries) + i * entry_size ent_pre: SrcFileEntry* = (SrcFileEntry*)(ea_pre) - if ent_pre is None or ent_pre.Path is None: - continue + if ent_pre is None or ent_pre.Path is None: continue pkg_pre: str = None if string.strlen(ent_pre.Path) > src_dir_len_pre + 1: rel_path_pre: str = ent_pre.Path + src_dir_len_pre + 1 @@ -961,14 +868,12 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, # 解析出的真定义前缀分裂 → 结构体布局不兼容,见 Translator 字段说明)。 tr_pre: rawptr[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"预注册失败: {ent_pre.Path}", "PhaseA") # OOM 清理:回收本 App 文件预注册翻译的瞬时数据 mb.reset_to(mark2) struct_count_after: int = GenApi.get_struct_count() # 收敛检查:本遍没有新结构体注册 → 所有类已注册 - if struct_count_after == struct_count_before: - break + if struct_count_after == struct_count_before: break VLogger.info("预注册完成", "PhaseA") # Phase A IR 缓冲:1MB 不够,ast/parser.vp 的 text.ll 超 1MB 被截断 → @@ -987,8 +892,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, # 声明已在 if 块外,此处仅赋值 app_deps_buf = stdlib.malloc(APP_DEPS_BUF_SIZE) app_deps_len = 0 - if app_deps_buf is not None: - app_deps_buf[0] = '\0' + if app_deps_buf is not None: app_deps_buf[0] = '\0' # Phase A 多遍重试:同项目多源文件时,main.vp 可能先于其 import 的 # mbuddytest.vp 翻译(文件系统顺序);翻译失败(语法/解析错误)的文件 @@ -1003,8 +907,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, for pass_a in range(PHASE_A_MAX_PASSES): completed_this_pass: int = 0 for i in range(file_count): - if done_flags[i] != 0: - continue + if done_flags[i] != 0: continue ea: uint64 = uint64(entries) + i * entry_size ent: SrcFileEntry* = (SrcFileEntry*)(ea) # 计时点 0:本文件处理开始(translate 段起点) @@ -1038,16 +941,12 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, im_pos_a: sizet = 0 while im_pos_a < im_len_a: im_start_a: sizet = im_pos_a - while im_pos_a < im_len_a and tr_a._imported_modules[im_pos_a] != ' ': - im_pos_a += 1 + while im_pos_a < im_len_a and tr_a._imported_modules[im_pos_a] != ' ': im_pos_a += 1 im_mod_len: sizet = im_pos_a - im_start_a - if im_pos_a < im_len_a: - im_pos_a += 1 - if im_mod_len == 0: - continue + if im_pos_a < im_len_a: im_pos_a += 1 + if im_mod_len == 0: continue im_mod_buf: bytes = stdlib.malloc(im_mod_len + 1) - if im_mod_buf is None: - continue + if im_mod_buf is None: continue string.strncpy(im_mod_buf, tr_a._imported_modules + im_start_a, im_mod_len) im_mod_buf[im_mod_len] = '\0' # 已在 app_deps 中则跳过(词边界精确匹配) @@ -1064,8 +963,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, 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 缓冲区分配失败", "PhaseA") tr_a.dump_ir(stub_buf_a, PHASE_A_IR_SIZE, mlirlite.OUTPUT_STUB) stub_len_a: sizet = string.strlen(stub_buf_a) @@ -1081,8 +979,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, # 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 缓冲区分配失败", "PhaseA") tr_a.dump_ir(text_buf_a, PHASE_A_IR_SIZE, mlirlite.OUTPUT_TEXT) text_len_a: sizet = string.strlen(text_buf_a) @@ -1101,8 +998,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, # save {sha1}.full.ll(在线 FULL 产物:模型在线时的自足单模块 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 缓冲区分配失败", "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") @@ -1147,8 +1043,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, if done_flags[i_ck] == 0: all_done = 0 break - if all_done != 0: - break + if all_done != 0: break if completed_this_pass == 0: # 无进展:剩余文件无法完成(真实编译错误),终止并列出未完成文件。每个失败文件附带依赖图诊断(_PhaseADumpFailGraph):pending 明细 + 依赖树。 # VLogger.error 内部 sys.exit(1),必须放在所有图形输出之后(否则进程在 ERROR 处即退出,图永远打不出)。 @@ -1158,8 +1053,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, ea_err: uint64 = uint64(entries) + i_err * entry_size ent_err: SrcFileEntry* = (SrcFileEntry*)(ea_err) if ent_err is not None and ent_err.Path is not None: - if ent_err.Sha1 is not None: - _PhaseADumpFailGraph(temp_dir, td_len_fail, ent_err.Path, ent_err.Sha1) + 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") @@ -1171,8 +1065,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, if do_phase2 == 0: VLogger.info("Phase A 完成(仅 stub 生成)", "project") - if app_deps_buf is not None: - stdlib.free(app_deps_buf) + if app_deps_buf is not None: stdlib.free(app_deps_buf) stdlib.free(entries) return 0 @@ -1186,15 +1079,13 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, reachable_count: int = 0 OBJ_PATHS_SIZE: sizet = 65536 obj_paths: bytes = stdlib.malloc(OBJ_PATHS_SIZE) - if obj_paths is None: - return 1 + if obj_paths is None: return 1 obj_paths[0] = '\0' obj_pos: sizet = 0 # main_obj_path: 存放定义了用户 main 的 .obj 路径(链接时放在最前面, # 避免 --allow-multiple-definition 选择了其他模块的 wrapper main) main_obj_path: bytes = stdlib.malloc(512) - if main_obj_path is None: - return 1 + if main_obj_path is None: return 1 main_obj_path[0] = '\0' compiled_count: int = 0 @@ -1212,8 +1103,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, for i in range(file_count): ea: uint64 = uint64(entries) + i * entry_size ent: SrcFileEntry* = (SrcFileEntry*)(ea) - if ent is None or ent.Path is None or ent.Sha1 is None: - continue + if ent is None or ent.Path is None or ent.Sha1 is None: continue # 单文件三步计时起点(GetTickCount64,ms) t_pb0: uint64 = w32.win32base.GetTickCount64() # 读在线 FULL 产物 {sha1}.full.ll → 完整 IR(取代 stub + 依赖 stub/text 合并) @@ -1258,10 +1148,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, # 构造 .obj 路径,检测是否是 main 模块(test_main.vp 或 main.vp,不再识别 .py) od_len: sizet = string.strlen(output_dir) is_main_mod: int = 0 - if string.strstr(ent.Path, "test_main.vp") is not None: - is_main_mod = 1 - elif string.strstr(ent.Path, "main.vp") is not None: - is_main_mod = 1 + if string.strstr(ent.Path, "test_main.vp") is not None: is_main_mod = 1 + elif string.strstr(ent.Path, "main.vp") is not None: is_main_mod = 1 # 切片路径: output_dir/{sha1前缀}/{sha1}.obj obj_path_sliced: str = StubMergerCollect._sliced_path(output_dir, od_len, ent.Sha1, "obj") @@ -1269,10 +1157,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, op_sliced_len: sizet = string.strlen(obj_path_sliced) if is_main_mod != 0: # main 模块: 复制到 main_obj_path(确保链接时 main 在最前) - if op_sliced_len < 512: - string.strcpy(main_obj_path, obj_path_sliced) - else: - VLogger.error("main_obj_path 缓冲区不足,终止编译", "PhaseB") + if op_sliced_len < 512: string.strcpy(main_obj_path, obj_path_sliced) + else: VLogger.error("main_obj_path 缓冲区不足,终止编译", "PhaseB") else: # 其他模块: 追加到 obj_paths if obj_pos + op_sliced_len + 2 < OBJ_PATHS_SIZE: @@ -1282,8 +1168,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, 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 路径缓冲区不足", "PhaseB") stdlib.free(obj_path_sliced) # 并行执行全部 llc(分批 LLC_MAX_THREADS 线程) @@ -1308,8 +1193,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, for ai_as in range(asm_file_count): ea_as: uint64 = uint64(asm_entries) + ai_as * entry_size ent_as: SrcFileEntry* = (SrcFileEntry*)(ea_as) - if ent_as is None or ent_as.Path is None or ent_as.Sha1 is None: - continue + 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: @@ -1418,8 +1302,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, if string.strcmp(ent_ap.Sha1, inc_sha1_mi) == 0: app_skip_mi = 1 break - if app_skip_mi != 0: - continue + if app_skip_mi != 0: continue # 检查 .obj 是否已存在于 includes.binary(切片子目录) ibd_len_mi: sizet = string.strlen(includes_binary_dir) check_pat_mi: str = StubMergerCollect._sliced_path(includes_binary_dir, ibd_len_mi, inc_sha1_mi, "obj") @@ -1432,8 +1315,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, w32.win32file.FindClose(check_h_mi) obj_exists_mi = 1 if obj_exists_mi != 0: - if check_pat_mi is not None: - stdlib.free(check_pat_mi) + if check_pat_mi is not None: stdlib.free(check_pat_mi) stdlib.free(check_fd_mi) continue @@ -1441,14 +1323,12 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, # 构造源文件路径: {所属 includes 根目录}/{rel_path}(多目录逐条取 IncDir,空串回退 includes_dir) rel_path_len_mi: sizet = string.strlen(inc_rel_mi) incdir_mi: str = store_incdir_arr_mi + sizet(ti) * StubMerger.MAX_INC_DIR_LEN - if incdir_mi is None or incdir_mi[0] == '\0': - incdir_mi = includes_dir + if incdir_mi is None or incdir_mi[0] == '\0': incdir_mi = includes_dir inc_dir_len_mi: sizet = string.strlen(incdir_mi) src_fp_mi: bytes = stdlib.malloc(inc_dir_len_mi + 1 + rel_path_len_mi + 1) if src_fp_mi is None: stdlib.free(check_pat_mi) - if check_fd_mi is not None: - stdlib.free(check_fd_mi) + if check_fd_mi is not None: stdlib.free(check_fd_mi) VLogger.error("includes 源路径分配失败,终止编译", "PhaseB+") viperlib.snprintf(src_fp_mi, inc_dir_len_mi + 1 + rel_path_len_mi + 1, "%s/%s", incdir_mi, inc_rel_mi) @@ -1461,16 +1341,14 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, # 只跳过声明文件(is_decl_mi == 1);meta 不存在时继续,让后续翻译逻辑处理 if is_decl_mi == 1: stdlib.free(check_pat_mi) - if check_fd_mi is not None: - stdlib.free(check_fd_mi) + if check_fd_mi is not None: stdlib.free(check_fd_mi) stdlib.free(src_fp_mi) continue # 尝试读在线 FULL 产物 {sha1}.full.ll(应已由 Phase1/PhaseA 生成) inc_combined_mi: bytes = stdlib.malloc(COMBINED_IR_SIZE) inc_combined_len_mi: sizet = 0 - if inc_combined_mi is not None: - inc_combined_len_mi = StubMergerBuild.LoadFullIR(temp_dir, inc_sha1_mi, inc_combined_mi, COMBINED_IR_SIZE) + if inc_combined_mi is not None: inc_combined_len_mi = StubMergerBuild.LoadFullIR(temp_dir, inc_sha1_mi, inc_combined_mi, COMBINED_IR_SIZE) # 如果 full.ll 不存在,翻译源文件并保存 stub/text/meta/full,然后重试 if inc_combined_len_mi == 0 and inc_combined_mi is not None: @@ -1515,8 +1393,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, StubMergerIR.WriteModuleMeta(tr_mi.Module, temp_dir, td_len_mi, inc_sha1_mi) # save {sha1}.full.ll(在线 FULL 产物) 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 缓冲区分配失败", "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") @@ -1566,11 +1443,9 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, 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+") - if inc_combined_mi is not None: - stdlib.free(inc_combined_mi) + 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) + if check_fd_mi is not None: stdlib.free(check_fd_mi) stdlib.free(src_fp_mi) continue @@ -1601,26 +1476,20 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, 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 路径缓冲区溢出,终止编译", "PhaseB+") stdlib.free(inc_obj_sliced) # 释放本次迭代的临时内存 - if check_pat_mi is not None: - stdlib.free(check_pat_mi) + if check_pat_mi is not None: stdlib.free(check_pat_mi) - if check_fd_mi is not None: - stdlib.free(check_fd_mi) + if check_fd_mi is not None: stdlib.free(check_fd_mi) stdlib.free(src_fp_mi) # 释放拓扑排序索引与局部映射副本 - if topo_idx is not None: - stdlib.free(topo_idx) - 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) + if topo_idx is not None: stdlib.free(topo_idx) + 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+") @@ -1635,8 +1504,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, od_len2: sizet = string.strlen(output_dir) lo_len: sizet = string.strlen(linker_output) exe_path: bytes = stdlib.malloc(od_len2 + lo_len + 2) - if exe_path is not None: - viperlib.snprintf(exe_path, od_len2 + lo_len + 2, "%s/%s", output_dir, linker_output) + 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") @@ -1674,8 +1542,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, ri_pc: int for ri_pc in range(reachable_count): rsha1_pc: str = reachable_set + sizet(ri_pc) * 17 - if rsha1_pc[0] == '\0': - continue + if rsha1_pc[0] == '\0': continue # 跳过 App 源文件:其 .obj 已入 final_obj_paths,若 includes_binary 残留同 sha1 的 .obj 被收集进来会与 output obj 同符号 → 链接 duplicate symbol。 app_skip_pc: int = 0 for ai_pc in range(file_count): @@ -1685,8 +1552,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, if string.strcmp(ent_pc.Sha1, rsha1_pc) == 0: app_skip_pc = 1 break - if app_skip_pc != 0: - continue + if app_skip_pc != 0: continue obj_path_pc: str = StubMergerCollect._sliced_path(includes_binary_dir, ibd_len_pc, rsha1_pc, "obj") if obj_path_pc is not None: # 检查 .obj 文件是否存在 @@ -1716,8 +1582,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, 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"可达模块 .obj 缺失: {obj_path_pc}", "PhaseC") stdlib.free(obj_path_pc) final_obj_paths[fop_pos] = '\0' @@ -1738,16 +1603,14 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, VLogger.success(f"输出: {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 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 模式:exe 尚未链接(命令在 bat 中),跳过 --run VLogger.info("phase2command 模式:跳过 --run(exe 尚未链接)", "phase2cmd") elif args.get_bool("run"): VLogger.info(f"执行: {exe_path}", "run") rp: rawptr[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"退出码: {rp.returncode}", "run") else: VLogger.error("链接失败", "PhaseC") stdlib.free(entries) diff --git a/App/lib/Projectrans/Config.vp b/App/lib/Projectrans/Config.vp index 3c35285..c6c0abb 100644 --- a/App/lib/Projectrans/Config.vp +++ b/App/lib/Projectrans/Config.vp @@ -97,10 +97,8 @@ def Load_project_config(path: str) -> int: SourceDir = sd_val.as_string() if sd_val is not None else None # build_dir: 统一构建目录(默认 ./.tpv_build),temp 和 output 作为其子目录 bd_val: JsonValue* = root["build_dir"] - if bd_val is not None and bd_val.is_string(): - BuildDir = bd_val.as_string() - else: - BuildDir = "./.tpv_build" + if bd_val is not None and bd_val.is_string(): BuildDir = bd_val.as_string() + else: BuildDir = "./.tpv_build" name_val: JsonValue* = root["name"] ProjectName = name_val.as_string() if name_val is not None else None ver_val: JsonValue* = root["version"] @@ -149,11 +147,9 @@ def Load_project_config(path: str) -> int: StrictMode = 1 if options is not None and options.is_object(): sl: JsonValue* = options["sha1_slice_level"] - if sl is not None and sl.is_int(): - Sha1SliceLevel = sl.as_int() + if sl is not None and sl.is_int(): Sha1SliceLevel = sl.as_int() sm: JsonValue* = options["strict_mode"] - if sm is not None and sm.is_bool(): - StrictMode = 1 if sm.as_bool() else 0 + if sm is not None and sm.is_bool(): StrictMode = 1 if sm.as_bool() else 0 # 读取 includes 数组(支持多目录:首元素存 IncludesDir,全部拼接存 IncludesDirs) includes_val: JsonValue* = root["includes"] @@ -165,12 +161,10 @@ def Load_project_config(path: str) -> int: inc_pos: sizet = 0 for inc_i in range(arr_len): inc_item: JsonValue* = includes_val.get_item(inc_i) - if inc_item is None or not inc_item.is_string(): - continue + if inc_item is None or not inc_item.is_string(): continue inc_str: str = inc_item.as_string() inc_slen: sizet = string.strlen(inc_str) - if inc_i == 0: - IncludesDir = inc_str + if inc_i == 0: IncludesDir = inc_str # 拼接进 IncludesDirs(空格分隔) if inc_pos + inc_slen + 1 < 2048: if inc_pos > 0: @@ -180,8 +174,7 @@ def Load_project_config(path: str) -> int: inc_pos += inc_slen inc_buf[inc_pos] = '\0' IncludesDirs = inc_buf - if IncludesDir is None: - IncludesDir = inc_buf + if IncludesDir is None: IncludesDir = inc_buf return 0 @@ -202,8 +195,7 @@ def _join_flags_array(flags_val: JsonValue*) -> str: if not flags_val.is_array(): return None arr_len: sizet = len(flags_val) - if arr_len == 0: - return None + if arr_len == 0: return None # 第一遍:计算总长度(所有 flag 长度 + 空格分隔符) total_len: sizet = 0 @@ -214,13 +206,11 @@ def _join_flags_array(flags_val: JsonValue*) -> str: if s is not None: total_len += string.strlen(s) + 1 # +1 for space - if total_len == 0: - return None + if total_len == 0: return None # 分配缓冲区(total_len 已含每个 flag 后的空格,最后一个是 '\0') buf: str = _mbuddy.alloc(total_len + 1) - if buf is None: - return None + if buf is None: return None # 第二遍:拼接(flag 之间用空格分隔) pos: sizet = 0 @@ -257,22 +247,18 @@ def _join_path(rel: str, project_dir: str) -> str: collect_obj_files 调 FindFirstFileA、命令串走 CreateProcessA), 故展开必须发生在**配置路径设置层**而不是逐个调用点。 """ - if rel is None: - return None + if rel is None: return None # 环境变量展开:仅在含 '%' 时生效(fileio.ExpandEnvironmentPath 自带 # "失败/无 '%' 返回 None" 契约),展开失败时保持原串不变 ep: str = fileio.ExpandEnvironmentPath(rel) - if ep is not None: - rel = ep + if ep is not None: rel = ep # 绝对路径(以 / 或 \ 开头)保持不变 - if rel[0] == '/' or rel[0] == '\\': - return rel + if rel[0] == '/' or rel[0] == '\\': return rel # 路径已含 project_dir 前缀时不再拼接,避免双份路径(./TransPyV/TransPyV/.tpv_build2);边界取到目录分隔符或串尾 if project_dir is not None: pdl: sizet = string.strlen(project_dir) if pdl > 0 and string.strncmp(rel, project_dir, pdl) == 0: - if rel[pdl] == '/' or rel[pdl] == '\\' or rel[pdl] == '\0': - return rel + if rel[pdl] == '/' or rel[pdl] == '\\' or rel[pdl] == '\0': return rel rel_len: sizet = string.strlen(rel) dir_len: sizet = string.strlen(project_dir) @@ -280,20 +266,17 @@ def _join_path(rel: str, project_dir: str) -> str: # 处理 ../ 或 ..\\ 前缀:拼接 project_dir/../... if rel_len >= 3 and rel[0] == '.' and rel[1] == '.': if rel[2] == '/' or rel[2] == '\\': - if dir_len == 0: - return rel + if dir_len == 0: return rel total_len: sizet = dir_len + 1 + rel_len + 1 buf: str = _mbuddy.alloc(total_len) - if buf is None: - return rel + if buf is None: return rel viperlib.snprintf(buf, total_len, "%s/%s", project_dir, rel) return _normalize_path(buf) # 处理 ./ 或 .\\ 前缀:拼接 project_dir + rel[2:] rel_off: sizet = 0 if rel_len >= 2 and rel[0] == '.': - if rel[1] == '/' or rel[1] == '\\': - rel_off = 2 + if rel[1] == '/' or rel[1] == '\\': rel_off = 2 else: return rel # 不是 ./ 开头,保持不变 else: @@ -319,57 +302,43 @@ def _normalize_path(path: str) -> str: 绝对路径(/ 或 \\ 开头,含盘符 C:)保持不变。 返回 _mbuddy 分配的字符串;失败时返回原路径。 """ - if path is None: - return None + if path is None: return None plen: sizet = string.strlen(path) - if plen == 0: - return path + if plen == 0: return path # 绝对路径(/ 或 \ 开头,或盘符如 C:)不规范化 - if path[0] == '/' or path[0] == '\\': - return path - if plen >= 2 and path[1] == ':': - return path + if path[0] == '/' or path[0] == '\\': return path + if plen >= 2 and path[1] == ':': return path # 输出缓冲(最坏情况 = 输入长度 + 可能的前缀 ./) out: str = _mbuddy.alloc(plen + 3) - if out is None: - return path + if out is None: return path seg_start: sizet = 0 out_len: sizet = 0 has_seg: int = 0 i: sizet = 0 while i <= plen: ch: char = '\0' - if i < plen: - ch = path[i] + if i < plen: ch = path[i] if ch == '/' or ch == '\\' or ch == '\0': seg_len: sizet = i - seg_start if seg_len > 0: # 单段 ".":跳过 - if seg_len == 1 and path[seg_start] == '.': - pass + if seg_len == 1 and path[seg_start] == '.': pass # 单段 "..":弹出上一段;前导 ".." 无段可弹时必须保留(对齐 Python os.path.normpath) elif seg_len == 2 and path[seg_start] == '.' and path[seg_start + 1] == '.': # 末段是否已经是前导 ".."(独立一段:要么是开头,要么前面是分隔符) last_is_dotdot: int = 0 if out_len >= 2 and out[out_len - 1] == '.' and out[out_len - 2] == '.': - if out_len == 2: - last_is_dotdot = 1 - elif out[out_len - 3] == '/' or out[out_len - 3] == '\\': - last_is_dotdot = 1 + if out_len == 2: last_is_dotdot = 1 + elif out[out_len - 3] == '/' or out[out_len - 3] == '\\': last_is_dotdot = 1 if out_len > 0 and last_is_dotdot == 0: # 回退到上一个分隔符 k: sizet = out_len - while k > 0 and out[k - 1] != '/' and out[k - 1] != '\\': - k -= 1 - if k > 0: - out_len = k - 1 - else: - out_len = 0 + while k > 0 and out[k - 1] != '/' and out[k - 1] != '\\': k -= 1 + if k > 0: out_len = k - 1 + else: out_len = 0 # 仍有剩余段时保持分隔符逻辑 - if out_len > 0: - has_seg = 1 - else: - has_seg = 0 + if out_len > 0: has_seg = 1 + else: has_seg = 0 else: # 没有普通段可弹:把 ".." 当普通段追加(前导 .. 累积保留) if has_seg > 0: @@ -423,10 +392,8 @@ def resolve_paths(project_dir: str) -> int: """ global SourceDir, BuildDir, TempDir, OutputDir, IncludesDir, IncludesDirs global ProjectDir, LinkerStaticLibs, LinkerDynamicLibs - if project_dir is None: - return 1 - if _mbuddy is None: - return 1 + if project_dir is None: return 1 + if _mbuddy is None: return 1 ProjectDir = project_dir @@ -458,13 +425,10 @@ def resolve_paths(project_dir: str) -> int: id_pos: sizet = 0 id_i: sizet = 0 while id_i < id_total: - while id_i < id_total and IncludesDirs[id_i] == ' ': - id_i += 1 - if id_i >= id_total: - break + while id_i < id_total and IncludesDirs[id_i] == ' ': id_i += 1 + if id_i >= id_total: break id_start: sizet = id_i - while id_i < id_total and IncludesDirs[id_i] != ' ': - id_i += 1 + while id_i < id_total and IncludesDirs[id_i] != ' ': id_i += 1 seg_len: sizet = id_i - id_start if seg_len > 0: seg_buf: str = _mbuddy.alloc(seg_len + 1) @@ -481,8 +445,7 @@ def resolve_paths(project_dir: str) -> int: id_pos += jl id_out[id_pos] = '\0' IncludesDirs = id_out - if IncludesDir is not None: - IncludesDir = _join_path(IncludesDir, project_dir) + if IncludesDir is not None: IncludesDir = _join_path(IncludesDir, project_dir) # linker.static_libs 显式静态链接文件路径基于 project_dir 逐段解析为绝对路径 if LinkerStaticLibs is not None: sl_total: sizet = string.strlen(LinkerStaticLibs) @@ -492,13 +455,10 @@ def resolve_paths(project_dir: str) -> int: sl_pos: sizet = 0 sl_i: sizet = 0 while sl_i < sl_total: - while sl_i < sl_total and LinkerStaticLibs[sl_i] == ' ': - sl_i += 1 - if sl_i >= sl_total: - break + while sl_i < sl_total and LinkerStaticLibs[sl_i] == ' ': sl_i += 1 + if sl_i >= sl_total: break sl_start: sizet = sl_i - while sl_i < sl_total and LinkerStaticLibs[sl_i] != ' ': - sl_i += 1 + while sl_i < sl_total and LinkerStaticLibs[sl_i] != ' ': sl_i += 1 seg_len: sizet = sl_i - sl_start if seg_len > 0: seg_buf: str = _mbuddy.alloc(seg_len + 1) @@ -525,13 +485,10 @@ def resolve_paths(project_dir: str) -> int: dl_pos: sizet = 0 dl_i: sizet = 0 while dl_i < dl_total: - while dl_i < dl_total and LinkerDynamicLibs[dl_i] == ' ': - dl_i += 1 - if dl_i >= dl_total: - break + while dl_i < dl_total and LinkerDynamicLibs[dl_i] == ' ': dl_i += 1 + if dl_i >= dl_total: break dl_start: sizet = dl_i - while dl_i < dl_total and LinkerDynamicLibs[dl_i] != ' ': - dl_i += 1 + while dl_i < dl_total and LinkerDynamicLibs[dl_i] != ' ': dl_i += 1 seg_len: sizet = dl_i - dl_start if seg_len > 0: seg_buf: str = _mbuddy.alloc(seg_len + 1) @@ -558,22 +515,16 @@ def _join_path_abs(rel: str, project_dir: str) -> str: 已为绝对路径(/ \\ 开头)或盘符形式(x:)时原样返回。 """ - if rel is None: - return None + if rel is None: return None rel_len: sizet = string.strlen(rel) - if rel_len == 0: - return rel - if rel[0] == '/' or rel[0] == '\\': - return rel - if rel_len >= 2 and rel[1] == ':': - return rel + if rel_len == 0: return rel + if rel[0] == '/' or rel[0] == '\\': return rel + if rel_len >= 2 and rel[1] == ':': return rel dir_len: sizet = string.strlen(project_dir) - if dir_len == 0: - return rel + if dir_len == 0: return rel total_len: sizet = dir_len + 1 + rel_len + 1 buf: str = _mbuddy.alloc(total_len) - if buf is None: - return rel + if buf is None: return rel viperlib.snprintf(buf, total_len, "%s/%s", project_dir, rel) return buf @@ -586,31 +537,24 @@ def _resolve_linker_t_paths(project_dir: str) -> None: project_dir 拼接(与 resolve_paths 对其他相对路径的处理保持一致)。 """ global LinkerFlags - if LinkerFlags is None or project_dir is None: - return + if LinkerFlags is None or project_dir is None: return fl_total: sizet = string.strlen(LinkerFlags) - if fl_total == 0: - return + if fl_total == 0: return out: str = _mbuddy.alloc(fl_total * 2 + 512) - if out is None: - return + if out is None: return out[0] = '\0' out_pos: sizet = 0 i: sizet = 0 prev_is_t: int = 0 # 前一 token 是否为 -T while i < fl_total: # 跳过前导空格 - while i < fl_total and LinkerFlags[i] == ' ': - i += 1 - if i >= fl_total: - break + while i < fl_total and LinkerFlags[i] == ' ': i += 1 + if i >= fl_total: break start: sizet = i - while i < fl_total and LinkerFlags[i] != ' ': - i += 1 + while i < fl_total and LinkerFlags[i] != ' ': i += 1 tok_len: sizet = i - start is_t_flag: int = 0 - if tok_len == 2 and LinkerFlags[start] == '-' and LinkerFlags[start + 1] == 'T': - is_t_flag = 1 + if tok_len == 2 and LinkerFlags[start] == '-' and LinkerFlags[start + 1] == 'T': is_t_flag = 1 # 输出分隔符(前一 token 之后) if out_pos > 0: out[out_pos] = ' ' @@ -651,15 +595,13 @@ def get_includes_binary_dir() -> str: 隔离 asan 插桩 obj,避免与非 asan obj 混链。 再追加单端 MLIR 后缀(如 .binary_asan_mlir):隔离旧 LLVM 后端留下的缓存 obj。 """ - if IncludesDir is None: - return None + if IncludesDir is None: return None inc_len: sizet = string.strlen(IncludesDir) suf_len: sizet = string.strlen(_inc_bin_suffix) be_suf: str = mlir_dir_suffix() be_suf_len: sizet = string.strlen(be_suf) buf: str = _mbuddy.alloc(inc_len + suf_len + be_suf_len + 1) - if buf is None: - return None + if buf is None: return None viperlib.snprintf(buf, inc_len + suf_len + be_suf_len + 1, "%s%s%s", IncludesDir, _inc_bin_suffix, be_suf) return buf @@ -691,35 +633,24 @@ def asan_runtime_declared() -> int: 判定方式:以上任一处出现 "asan" 即视为已声明。 """ if LinkerStaticLibs is not None: - if string.strstr(LinkerStaticLibs, "asan") is not None: - return 1 + if string.strstr(LinkerStaticLibs, "asan") is not None: return 1 if LinkerDynamicLibs is not None: - if string.strstr(LinkerDynamicLibs, "asan") is not None: - return 1 + if string.strstr(LinkerDynamicLibs, "asan") is not None: return 1 if LinkerFlags is not None: - if string.strstr(LinkerFlags, "asan") is not None: - return 1 + if string.strstr(LinkerFlags, "asan") is not None: return 1 return 0 def print_config(): """打印当前配置""" - if ProjectName is not None: - VLogger.info(f"project: {ProjectName} v{ProjectVersion if ProjectVersion is not None else "?"}", "config") - if SourceDir is not None: - VLogger.info(f"source_dir: {SourceDir}", "config") - if BuildDir is not None: - VLogger.info(f"build_dir: {BuildDir}", "config") - if TempDir is not None: - VLogger.info(f"temp_dir: {TempDir}", "config") - if OutputDir is not None: - VLogger.info(f"output_dir: {OutputDir}", "config") - if CompilerCmd is not None: - VLogger.info(f"compiler: {CompilerCmd}", "config") - if LinkerCmd is not None: - VLogger.info(f"linker: {LinkerCmd} -> {LinkerOutput if LinkerOutput is not None else "?"}", "config") - if IncludesDir is not None: - VLogger.info(f"includes: {IncludesDir}", "config") + if ProjectName is not None: VLogger.info(f"project: {ProjectName} v{ProjectVersion if ProjectVersion is not None else "?"}", "config") + if SourceDir is not None: VLogger.info(f"source_dir: {SourceDir}", "config") + if BuildDir is not None: VLogger.info(f"build_dir: {BuildDir}", "config") + if TempDir is not None: VLogger.info(f"temp_dir: {TempDir}", "config") + if OutputDir is not None: VLogger.info(f"output_dir: {OutputDir}", "config") + if CompilerCmd is not None: VLogger.info(f"compiler: {CompilerCmd}", "config") + if LinkerCmd is not None: VLogger.info(f"linker: {LinkerCmd} -> {LinkerOutput if LinkerOutput is not None else "?"}", "config") + if IncludesDir is not None: VLogger.info(f"includes: {IncludesDir}", "config") VLogger.info(f"sha1_slice_level: {Sha1SliceLevel}", "config") @@ -730,16 +661,13 @@ def print_config(): # ============================================================ def slice_subdir(sha1: str, level: int) -> str: """根据 SHA1 和切片层数返回子目录路径""" - if level <= 0 or sha1 is None: - return None - if _mbuddy is None: - return None + if level <= 0 or sha1 is None: return None + if _mbuddy is None: return None # 每层 2 字符 + 分隔符,最后无分隔符 + null # buf 大小: level * 2 + (level - 1) + 1 = level * 3 buf_len: sizet = sizet(level * 3) buf: str = _mbuddy.alloc(buf_len) - if buf is None: - return None + if buf is None: return None pos: int = 0 i: int = 0 while i < level: diff --git a/App/lib/Projectrans/Utils.vp b/App/lib/Projectrans/Utils.vp index 8929b5a..f91db8e 100644 --- a/App/lib/Projectrans/Utils.vp +++ b/App/lib/Projectrans/Utils.vp @@ -41,16 +41,12 @@ def bytes_to_hex(pool: memhub.MemBuddy*, use_malloc=1 时用 stdlib.malloc(调用方负责 free),否则 pool.alloc。 合并自 Utils.compute_sha1 / IncludesScanner.compute_file_sha1 的重复 hex 转换。 """ - if digest is None or nbytes <= 0: - return None + if digest is None or nbytes <= 0: return None hex_len: sizet = nbytes * 2 + 1 hex_buf: str = None - if use_malloc != 0: - hex_buf = stdlib.malloc(hex_len) - else: - hex_buf = pool.alloc(hex_len) - if hex_buf is None: - return None + if use_malloc != 0: hex_buf = stdlib.malloc(hex_len) + else: hex_buf = pool.alloc(hex_len) + if hex_buf is None: return None for i in range(nbytes): hi: int = (digest[i] >> 4) & 0xF lo: int = digest[i] & 0xF @@ -65,8 +61,7 @@ def bytes_to_hex(pool: memhub.MemBuddy*, # ============================================================ def compute_sha1(pool: memhub.MemBuddy*, content: str) -> str: """计算字符串的 SHA1,返回前 16 个十六进制字符(用于文件命名)""" - if content is None or pool is None: - return None + if content is None or pool is None: return None # 构造 sha1 对象(__init__ 会初始化 state/count/buf) # ctx 在栈上分配(alloca),函数内使用完即丢弃,无需堆分配 @@ -91,11 +86,9 @@ def is_vp_at(p: str, start: sizet, plen: sizet) -> int: 不再识别 .py(移除 vp -> py 后缀识别回退:Viper 源文件仅 .vp)。 """ - if p is None or plen <= 3: - return 0 + if p is None or plen <= 3: return 0 base: sizet = start + plen - 3 - if p[base] == '.' and p[base + 1] == 'v' and p[base + 2] == 'p': - return 1 + if p[base] == '.' and p[base + 1] == 'v' and p[base + 2] == 'p': return 1 return 0 @@ -104,8 +97,7 @@ def is_vp_at(p: str, start: sizet, plen: sizet) -> int: # ============================================================ def JoinPath(a: str, b: str) -> str: """拼接路径段为 "a/b"(stdlib.malloc 分配,调用方负责 free),失败返回 None""" - if a is None or b is None: - return None + if a is None or b is None: return None a_len: sizet = string.strlen(a) b_len: sizet = string.strlen(b) total_len: sizet = a_len + b_len + 2 @@ -136,8 +128,7 @@ def read_file_to_buf(path: str, buf_size: sizet) -> bytes: if br <= 0: stdlib.free(buf) return None - if br < buf_size: - buf[br] = 0 + if br < buf_size: buf[br] = 0 return buf @@ -151,8 +142,7 @@ def PathToModuleName(path: str, strip_includes_prefix: int) -> str: 特殊处理 __init__.vp:pkg/__init__.vp → pkg(而非 pkg.__init__)。 合并自 StubMerger._PathToModuleName / IncludesScanner 内联模块名计算。 """ - if path is None: - return None + if path is None: return None plen: sizet = string.strlen(path) # 跳过 includes/ 或 includes\ 前缀(Windows 反斜杠兼容) prefix_len: sizet = 9 @@ -163,10 +153,8 @@ def PathToModuleName(path: str, strip_includes_prefix: int) -> str: path_start = prefix_len plen = plen - prefix_len # 去掉 .vp 后缀(Viper 源文件仅 .vp,不再识别 .py) - if is_vp_at(path, path_start, plen) != 0: - plen -= 3 - if plen == 0: - return None + if is_vp_at(path, path_start, plen) != 0: plen -= 3 + if plen == 0: return None # 检查是否以 /__init__ 或 \__init__ 结尾(包的 __init__.vp) # 同时支持 / 和 \ 两种分隔符(TPC 写入的路径可能混合使用) if plen > 9: @@ -175,18 +163,14 @@ def PathToModuleName(path: str, strip_includes_prefix: int) -> str: if (sep_char == '/' or sep_char == '\\') and path[tail_off + 1] == '_' and path[tail_off + 2] == '_' and path[tail_off + 3] == 'i' and path[tail_off + 4] == 'n' and path[tail_off + 5] == 'i' and path[tail_off + 6] == 't' and path[tail_off + 7] == '_' and path[tail_off + 8] == '_': # 去掉 分隔符+__init__ 后缀,plen 就是包名部分长度 plen = tail_off - path_start - if plen == 0: - return None + if plen == 0: return None # 复制并替换 / 为 . result: str = stdlib.malloc(plen + 1) - if result is None: - return None + if result is None: return None for ri in range(plen): ch: char = path[path_start + ri] - if ch == '/' or ch == '\\': - result[ri] = '.' - else: - result[ri] = ch + if ch == '/' or ch == '\\': result[ri] = '.' + else: result[ri] = ch result[plen] = '\0' return result @@ -196,12 +180,10 @@ def PathToModuleName(path: str, strip_includes_prefix: int) -> str: # ============================================================ def CleanDir(dir_path: str) -> int: """递归删除目录中所有文件和子目录,保留 dir_path 本身,返回删除的文件数,-1 表示错误""" - if dir_path is None: - return -1 + if dir_path is None: return -1 dir_len: sizet = string.strlen(dir_path) pattern: bytes = stdlib.malloc(dir_len + 8) - if pattern is None: - return -1 + if pattern is None: return -1 viperlib.snprintf(pattern, dir_len + 8, "%s/*", dir_path) find_data: w32.win32file.WIN32_FIND_DATAA* = stdlib.malloc(w32.win32file.WIN32_FIND_DATAA.__sizeof__()) @@ -222,10 +204,8 @@ def CleanDir(dir_path: str) -> int: if fname is not None: # 跳过 . 和 .. if fname[0] == '.': - if fname[1] == '\0': - fname = None - elif fname[1] == '.' and fname[2] == '\0': - fname = None + if fname[1] == '\0': fname = None + elif fname[1] == '.' and fname[2] == '\0': fname = None if fname is not None: full_path: bytes = JoinPath(dir_path, fname) if full_path is not None: @@ -234,18 +214,15 @@ def CleanDir(dir_path: str) -> int: if is_dir != 0: # 递归清理子目录中的文件 sub_deleted: int = CleanDir(full_path) - if sub_deleted > 0: - deleted += sub_deleted + if sub_deleted > 0: deleted += sub_deleted # 删除空子目录(RemoveDirectoryA 要求目录为空) w32.win32file.RemoveDirectoryA(full_path) else: # 删除文件 - if w32.win32file.DeleteFileA(full_path) != 0: - deleted += 1 + if w32.win32file.DeleteFileA(full_path) != 0: deleted += 1 stdlib.free(full_path) - if w32.win32file.FindNextFileA(handle, find_data) == 0: - break + if w32.win32file.FindNextFileA(handle, find_data) == 0: break w32.win32file.FindClose(handle) stdlib.free(pattern) diff --git a/App/lib/Stub/StubGen/Converter.vp b/App/lib/Stub/StubGen/Converter.vp index 43562b4..0e5ccd4 100644 --- a/App/lib/Stub/StubGen/Converter.vp +++ b/App/lib/Stub/StubGen/Converter.vp @@ -26,20 +26,17 @@ def _eval_binop_valid(node: ast.AST*) -> int: k: int = node.kind() if k == ast.ASTKind.Constant: cn: ast.Constant* = ast.Constant*(node) - if cn.const_kind == ast.CONST_INT: - return 1 + if cn.const_kind == ast.CONST_INT: return 1 return 0 if k == ast.ASTKind.UnaryOp: uop: ast.UnaryOp* = ast.UnaryOp*(node) - if uop.operand is not None: - return _eval_binop_valid(uop.operand) + if uop.operand is not None: return _eval_binop_valid(uop.operand) return 0 if k == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(node) if bop.left is not None and bop.right is not None: if _eval_binop_valid(bop.left) != 0: - if _eval_binop_valid(bop.right) != 0: - return 1 + if _eval_binop_valid(bop.right) != 0: return 1 return 0 if k == ast.ASTKind.Name: # Name 引用:检查是否是已注册的 CDefine 常量 @@ -47,35 +44,28 @@ def _eval_binop_valid(node: ast.AST*) -> int: if nm.id is not None: # 从本地 CDefine 表查找 val: int = _lookup_cdefine_for_pyi(nm.id) - if _pyi_cdefine_found() != 0: - return 1 + if _pyi_cdefine_found() != 0: return 1 return 0 return 0 def _eval_binop_int(node: ast.AST*) -> int64: """递归计算 BinOp 节点的整数值(64 位,避免大整数 CDefine 截断)""" - if node is None: - return 0 + if node is None: return 0 k: int = node.kind() if k == ast.ASTKind.Constant: cn: ast.Constant* = ast.Constant*(node) - if cn.const_kind == ast.CONST_INT: - return cn.int_val + if cn.const_kind == ast.CONST_INT: return cn.int_val return 0 if k == ast.ASTKind.UnaryOp: uop: ast.UnaryOp* = ast.UnaryOp*(node) - if uop.op == ast.OpKind.USub and uop.operand is not None: - return -_eval_binop_int(uop.operand) - if uop.op == ast.OpKind.UAdd and uop.operand is not None: - return _eval_binop_int(uop.operand) - if uop.op == ast.OpKind.Invert and uop.operand is not None: - return ~_eval_binop_int(uop.operand) + if uop.op == ast.OpKind.USub and uop.operand is not None: return -_eval_binop_int(uop.operand) + if uop.op == ast.OpKind.UAdd and uop.operand is not None: return _eval_binop_int(uop.operand) + if uop.op == ast.OpKind.Invert and uop.operand is not None: return ~_eval_binop_int(uop.operand) return 0 if k == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(node) - if bop.left is None or bop.right is None: - return 0 + if bop.left is None or bop.right is None: return 0 lv: int64 = _eval_binop_int(bop.left) rv: int64 = _eval_binop_int(bop.right) if bop.op == ast.OpKind.BitOr: return lv | rv @@ -92,8 +82,7 @@ def _eval_binop_int(node: ast.AST*) -> int64: return 0 if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) - if nm.id is not None: - return _lookup_cdefine_for_pyi(nm.id) + if nm.id is not None: return _lookup_cdefine_for_pyi(nm.id) return 0 return 0 @@ -132,30 +121,23 @@ def _lookup_cdefine_for_pyi(name: str) -> int64: def _eval_cdefine_value_cache(node: ast.AST*) -> int64: """求值 CDefine 值(Constant/UnaryOp/BinOp/Call/Name),供 vpi 预处理注册缓存""" - if node is None: - return 0 + if node is None: return 0 k: int = node.kind() if k == ast.ASTKind.Constant: cn_c: ast.Constant* = ast.Constant*(node) - if cn_c.const_kind == ast.CONST_INT: - return cn_c.int_val - if cn_c.const_kind == ast.CONST_BOOL: - return cn_c.int_val + if cn_c.const_kind == ast.CONST_INT: return cn_c.int_val + if cn_c.const_kind == ast.CONST_BOOL: return cn_c.int_val # STR/FLOAT/NONE 不参与整数 BinOp 引用(注册 0 无害) return 0 - if k == ast.ASTKind.UnaryOp: - return _eval_binop_int(node) - if k == ast.ASTKind.BinOp: - return _eval_binop_int(node) + if k == ast.ASTKind.UnaryOp: return _eval_binop_int(node) + if k == ast.ASTKind.BinOp: return _eval_binop_int(node) if k == ast.ASTKind.Call: cl_c: ast.Call* = ast.Call*(node) - if cl_c.args is not None and len(cl_c.args) > 0: - return _eval_cdefine_value_cache(cl_c.args.get(0)) + if cl_c.args is not None and len(cl_c.args) > 0: return _eval_cdefine_value_cache(cl_c.args.get(0)) return 0 if k == ast.ASTKind.Name: nm_c: ast.Name* = ast.Name*(node) - if nm_c.id is not None: - return _lookup_cdefine_for_pyi(nm_c.id) + if nm_c.id is not None: return _lookup_cdefine_for_pyi(nm_c.id) return 0 return 0 @@ -174,16 +156,12 @@ def _pyi_cdefine_found() -> int: def _PyiEmit(buf: bytes, buf_size: sizet, pos: sizet, text: str) -> sizet: """追加 text 到 buf 的 pos 位置,返回新的 pos""" - if buf is None or text is None or pos >= buf_size: - return pos + if buf is None or text is None or pos >= buf_size: return pos tlen: sizet = string.strlen(text) - if tlen == 0: - return pos + if tlen == 0: return pos remain: sizet = buf_size - pos - if tlen >= remain: - tlen = remain - 1 - if tlen > 0: - string.memcpy(buf + pos, text, tlen) + if tlen >= remain: tlen = remain - 1 + if tlen > 0: string.memcpy(buf + pos, text, tlen) return pos + tlen @@ -248,16 +226,14 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, if depth > 64: VLogger.error("vpi 类型注解递归过深(AST 环或嵌套超过 64 层)", "StubGen") sys.exit(1) - if annot is None: - return _PyiEmit(buf, buf_size, pos, "int") + if annot is None: return _PyiEmit(buf, buf_size, pos, "int") k: int = annot.kind() # Name: 简单类型名 (如 int, str, MyClass) if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(annot) - if nm.id is not None: - return _PyiEmit(buf, buf_size, pos, nm.id) + if nm.id is not None: return _PyiEmit(buf, buf_size, pos, nm.id) return _PyiEmit(buf, buf_size, pos, "int") # Attribute: 属性引用 (如 int, memhub.MemBuddy) @@ -265,8 +241,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, at: ast.Attribute* = ast.Attribute*(annot) pos = _PyiTypeStr(buf, buf_size, pos, at.value, depth + 1) pos = _PyiEmit(buf, buf_size, pos, ".") - if at.attr is not None: - pos = _PyiEmit(buf, buf_size, pos, at.attr) + if at.attr is not None: pos = _PyiEmit(buf, buf_size, pos, at.attr) return pos # Subscript: 下标类型 (如 list[int], t.CArray[elem, count]) @@ -293,12 +268,9 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, # USub → "-";其余一元运算符两侧都不支持 → fail-fast(不静默写错符号)。 if k == ast.ASTKind.UnaryOp: uop_t: ast.UnaryOp* = ast.UnaryOp*(annot) - if uop_t.op == ast.OpKind.Not: - pos = _PyiEmit(buf, buf_size, pos, "not ") - 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, "-") + if uop_t.op == ast.OpKind.Not: pos = _PyiEmit(buf, buf_size, pos, "not ") + 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") return pos # 不可达(fatal_error 已退出) @@ -326,8 +298,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, else: pos = _PyiEmit(buf, buf_size, pos, " ? ") # TPC 按 ops 的下标取 comparators[i];此处加长度守卫, # 畸形 AST(ops/comparators 不等长)不越界。 - if cmps_ct is not None and oi_ct < len(cmps_ct): - pos = _PyiTypeStr(buf, buf_size, pos, cmps_ct.get(oi_ct), depth + 1) + if cmps_ct is not None and oi_ct < len(cmps_ct): pos = _PyiTypeStr(buf, buf_size, pos, cmps_ct.get(oi_ct), depth + 1) oi_ct += 1 return pos @@ -341,10 +312,8 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, vi_bt: sizet = 0 while vi_bt < vn_bt: if vi_bt > 0: - if bool_t.op == ast.OpKind.Or: - pos = _PyiEmit(buf, buf_size, pos, " or ") - else: - pos = _PyiEmit(buf, buf_size, pos, " and ") + if bool_t.op == ast.OpKind.Or: pos = _PyiEmit(buf, buf_size, pos, " or ") + else: pos = _PyiEmit(buf, buf_size, pos, " and ") pos = _PyiTypeStr(buf, buf_size, pos, vals_bt.get(vi_bt), depth + 1) vi_bt += 1 return pos @@ -354,12 +323,10 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, cn: ast.Constant* = ast.Constant*(annot) if cn.const_kind == ast.CONST_STR: pos = _PyiEmit(buf, buf_size, pos, "'") - if cn.str_val is not None: - pos = _PyiEmit(buf, buf_size, pos, cn.str_val) + if cn.str_val is not None: pos = _PyiEmit(buf, buf_size, pos, cn.str_val) pos = _PyiEmit(buf, buf_size, pos, "'") return pos - if cn.const_kind == ast.CONST_NONE: - return _PyiEmit(buf, buf_size, pos, "None") + if cn.const_kind == ast.CONST_NONE: return _PyiEmit(buf, buf_size, pos, "None") # 数字常量(t.CArray[uint32, 64] 的 count 等):输出数值本身, # 而不是回退 int——否则 vpi 生成 "t.CArray[..., int]" 在加载 # stub 时触发 TypeError(count 必须是整数常量、None、CDefine 常量名 @@ -385,8 +352,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, ln: sizet = len(lst_elts) li: sizet = 0 while li < ln: - if li > 0: - pos = _PyiEmit(buf, buf_size, pos, ", ") + if li > 0: pos = _PyiEmit(buf, buf_size, pos, ", ") le: ast.AST* = lst_elts.get(li) pos = _PyiTypeStr(buf, buf_size, pos, le, depth + 1) li += 1 @@ -401,8 +367,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, tn: sizet = len(tup_elts) ti: sizet = 0 while ti < tn: - if ti > 0: - pos = _PyiEmit(buf, buf_size, pos, ", ") + if ti > 0: pos = _PyiEmit(buf, buf_size, pos, ", ") el: ast.AST* = tup_elts.get(ti) pos = _PyiTypeStr(buf, buf_size, pos, el, depth + 1) ti += 1 @@ -418,8 +383,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, can: sizet = len(cl_args) cai: sizet = 0 while cai < can: - if cai > 0: - pos = _PyiEmit(buf, buf_size, pos, ", ") + if cai > 0: pos = _PyiEmit(buf, buf_size, pos, ", ") ca: ast.AST* = cl_args.get(cai) pos = _PyiTypeStr(buf, buf_size, pos, ca, depth + 1) cai += 1 @@ -448,8 +412,7 @@ def _PyiDefaultStr(buf: bytes, buf_size: sizet, pos: sizet, if depth > 64: VLogger.error("vpi 默认值表达式递归过深(AST 环或嵌套超过 64 层)", "StubGen") sys.exit(1) - if node is None: - return pos + if node is None: return pos k: int = node.kind() # Constant: 数字/字符串/bool/None 直接输出字面量 @@ -464,37 +427,28 @@ def _PyiDefaultStr(buf: bytes, buf_size: sizet, pos: sizet, return pos if cn.const_kind == ast.CONST_STR: pos = _PyiEmit(buf, buf_size, pos, "\"") - if cn.str_val is not None: - pos = _PyiEmit(buf, buf_size, pos, cn.str_val) + if cn.str_val is not None: pos = _PyiEmit(buf, buf_size, pos, cn.str_val) return _PyiEmit(buf, buf_size, pos, "\"") if cn.const_kind == ast.CONST_BOOL: - if cn.int_val != 0: - return _PyiEmit(buf, buf_size, pos, "True") + if cn.int_val != 0: return _PyiEmit(buf, buf_size, pos, "True") return _PyiEmit(buf, buf_size, pos, "False") - if cn.const_kind == ast.CONST_NONE: - return _PyiEmit(buf, buf_size, pos, "None") + if cn.const_kind == ast.CONST_NONE: return _PyiEmit(buf, buf_size, pos, "None") return pos # Name: CDefine 常量名(如 share: ULONG = SHARE_READ) if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) - if nm.id is not None: - return _PyiEmit(buf, buf_size, pos, nm.id) + if nm.id is not None: return _PyiEmit(buf, buf_size, pos, nm.id) return pos # UnaryOp: 一元运算(如 -1, ~0) if k == ast.ASTKind.UnaryOp: uop: ast.UnaryOp* = ast.UnaryOp*(node) - if uop.op == ast.OpKind.USub: - pos = _PyiEmit(buf, buf_size, pos, "-") - elif uop.op == ast.OpKind.UAdd: - pos = _PyiEmit(buf, buf_size, pos, "+") - elif uop.op == ast.OpKind.Invert: - pos = _PyiEmit(buf, buf_size, pos, "~") - else: - return pos - if uop.operand is not None: - return _PyiDefaultStr(buf, buf_size, pos, uop.operand, depth + 1) + if uop.op == ast.OpKind.USub: pos = _PyiEmit(buf, buf_size, pos, "-") + elif uop.op == ast.OpKind.UAdd: pos = _PyiEmit(buf, buf_size, pos, "+") + elif uop.op == ast.OpKind.Invert: pos = _PyiEmit(buf, buf_size, pos, "~") + else: return pos + if uop.operand is not None: return _PyiDefaultStr(buf, buf_size, pos, uop.operand, depth + 1) return pos # 其它(BinOp 等复杂表达式):不输出,保持无默认值(fail-fast 由调用侧兜底) @@ -511,25 +465,20 @@ def _PyiDefaultStr(buf: bytes, buf_size: sizet, pos: sizet, def _PyiRejectCReturnDecorator(node: ast.AST*, decorators: list[ast.AST*]*) -> int: """装饰器列表里出现 @c.CReturn 即 fatal_error(返回 0 = 无该装饰器)""" - if decorators is None: - return 0 + if decorators is None: return 0 dn: sizet = len(decorators) di: sizet = 0 while di < dn: dnode: ast.AST* = decorators.get(di) di += 1 - if dnode is None: - continue + if dnode is None: continue # 兼容 @c.CReturn(...)(Call(func=Attribute))与裸 @c.CReturn(Attribute)两形态 dattr: ast.Attribute* = None if dnode.kind() == ast.ASTKind.Call: dcall: ast.Call* = ast.Call*(dnode) - if dcall.func is not None and dcall.func.kind() == ast.ASTKind.Attribute: - dattr = ast.Attribute*(dcall.func) - elif dnode.kind() == ast.ASTKind.Attribute: - dattr = ast.Attribute*(dnode) - if dattr is None or dattr.attr is None: - continue + if dcall.func is not None and dcall.func.kind() == ast.ASTKind.Attribute: dattr = ast.Attribute*(dcall.func) + 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") return 1 @@ -561,8 +510,7 @@ def _PyiFunction(buf: bytes, buf_size: sizet, pos: sizet, pos = _PyiIndent(buf, buf_size, pos, indent_level) pos = _PyiEmit(buf, buf_size, pos, "def ") - if fn.name is not None: - pos = _PyiEmit(buf, buf_size, pos, fn.name) + if fn.name is not None: pos = _PyiEmit(buf, buf_size, pos, fn.name) pos = _PyiEmit(buf, buf_size, pos, "(") # 参数列表 @@ -580,16 +528,13 @@ def _PyiFunction(buf: bytes, buf_size: sizet, pos: sizet, # arg_defaults 必须内联声明:联合接收者的 .get 会被误分派,预声明 + 重赋值会解析成 list[int].get 返回 i32 截断指针而崩溃。 arg_defaults: list[ast.AST*]* = args.defaults dn: sizet = 0 - if arg_defaults is not None: - dn = len(arg_defaults) + if arg_defaults is not None: dn = len(arg_defaults) ai: sizet = 0 while ai < an: - if first == 0: - pos = _PyiEmit(buf, buf_size, pos, ", ") + if first == 0: pos = _PyiEmit(buf, buf_size, pos, ", ") first = 0 ag: ast.Arg* = ast.Arg*(args_args.get(ai)) - if ag.arg is not None: - pos = _PyiEmit(buf, buf_size, pos, ag.arg) + if ag.arg is not None: pos = _PyiEmit(buf, buf_size, pos, ag.arg) if ag.annotation is not None: pos = _PyiEmit(buf, buf_size, pos, ": ") pos = _PyiTypeStr(buf, buf_size, pos, ag.annotation) @@ -603,23 +548,19 @@ def _PyiFunction(buf: bytes, buf_size: sizet, pos: sizet, # *args if args.vararg is not None: - if first == 0: - pos = _PyiEmit(buf, buf_size, pos, ", ") + if first == 0: pos = _PyiEmit(buf, buf_size, pos, ", ") first = 0 pos = _PyiEmit(buf, buf_size, pos, "*") va: ast.Arg* = ast.Arg*(args.vararg) - if va.arg is not None: - pos = _PyiEmit(buf, buf_size, pos, va.arg) + if va.arg is not None: pos = _PyiEmit(buf, buf_size, pos, va.arg) # **kwargs if args.kwarg is not None: - if first == 0: - pos = _PyiEmit(buf, buf_size, pos, ", ") + if first == 0: pos = _PyiEmit(buf, buf_size, pos, ", ") first = 0 pos = _PyiEmit(buf, buf_size, pos, "**") kw: ast.Arg* = ast.Arg*(args.kwarg) - if kw.arg is not None: - pos = _PyiEmit(buf, buf_size, pos, kw.arg) + if kw.arg is not None: pos = _PyiEmit(buf, buf_size, pos, kw.arg) pos = _PyiEmit(buf, buf_size, pos, ")") @@ -662,8 +603,7 @@ def _PyiClass(buf: bytes, buf_size: sizet, pos: sizet, pos = _PyiIndent(buf, buf_size, pos, indent_level) pos = _PyiEmit(buf, buf_size, pos, "class ") - if cls.name is not None: - pos = _PyiEmit(buf, buf_size, pos, cls.name) + if cls.name is not None: pos = _PyiEmit(buf, buf_size, pos, cls.name) # PEP 695 类型参数 (class Foo[T]:) if cls.type_params is not None: @@ -682,11 +622,9 @@ def _PyiClass(buf: bytes, buf_size: sizet, pos: sizet, pos = _PyiEmit(buf, buf_size, pos, "[") tpi: sizet = 0 while tpi < tpn: - if tpi > 0: - pos = _PyiEmit(buf, buf_size, pos, ", ") + if tpi > 0: pos = _PyiEmit(buf, buf_size, pos, ", ") tpname: str = cls_type_params.get(tpi) - if tpname is not None: - pos = _PyiEmit(buf, buf_size, pos, tpname) + if tpname is not None: pos = _PyiEmit(buf, buf_size, pos, tpname) tpi += 1 pos = _PyiEmit(buf, buf_size, pos, "]") @@ -698,8 +636,7 @@ def _PyiClass(buf: bytes, buf_size: sizet, pos: sizet, pos = _PyiEmit(buf, buf_size, pos, "(") bi: sizet = 0 while bi < bn: - if bi > 0: - pos = _PyiEmit(buf, buf_size, pos, ", ") + if bi > 0: pos = _PyiEmit(buf, buf_size, pos, ", ") base: ast.AST* = cls_bases.get(bi) pos = _PyiTypeStr(buf, buf_size, pos, base) bi += 1 @@ -741,8 +678,7 @@ def _PyiClass(buf: bytes, buf_size: sizet, pos: sizet, ici += 1 continue pos = _PyiIndent(buf, buf_size, pos, indent_level + 1) - if iat.attr is not None: - pos = _PyiEmit(buf, buf_size, pos, iat.attr) + if iat.attr is not None: pos = _PyiEmit(buf, buf_size, pos, iat.attr) pos = _PyiEmit(buf, buf_size, pos, ": ") pos = _PyiTypeStr(buf, buf_size, pos, iaa.annotation) pos = _PyiEmit(buf, buf_size, pos, "\n") @@ -757,8 +693,7 @@ def _PyiClass(buf: bytes, buf_size: sizet, pos: sizet, if aa.target is not None and aa.target.kind() == ast.ASTKind.Name: tn: ast.Name* = ast.Name*(aa.target) pos = _PyiIndent(buf, buf_size, pos, indent_level + 1) - if tn.id is not None: - pos = _PyiEmit(buf, buf_size, pos, tn.id) + if tn.id is not None: pos = _PyiEmit(buf, buf_size, pos, tn.id) pos = _PyiEmit(buf, buf_size, pos, ": ") pos = _PyiTypeStr(buf, buf_size, pos, aa.annotation) pos = _PyiEmit(buf, buf_size, pos, "\n") @@ -789,8 +724,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf: bytes, buf_size: sizet) -> sizet: """从 AST 生成 .vpi 存根文件内容到 buf""" - if tree is None or buf is None or buf_size == 0: - return 0 + if tree is None or buf is None or buf_size == 0: return 0 # 错误归因:把"当前文件"指向正在生成 stub 的这份(rel_path 非 None 时)。 # 本函数内触发的 fatal_error(如 L227/L303/L430 的注解节点类型未知)应指向 @@ -801,8 +735,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, # 中途新增的分支;入口设一次覆盖全部(含后续所有 fatal_error / push_trace)。 # rel_path 为 None 时不改写 CurrentFile(保持上一次设置值):调用侧确实拿不到 # 路径时,宁可沿用"上一次设置的文件"也不要把归因抹成 None。 - if rel_path is not None: - GenApi.set_current_file_type(rel_path) + if rel_path is not None: GenApi.set_current_file_type(rel_path) pos: sizet = 0 @@ -822,8 +755,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, tgt_pc0: ast.Name* = ast.Name*(aa_pc0.target) if tgt_pc0.id is not None and aa_pc0.annotation.kind() == ast.ASTKind.Attribute: ann_pc0: ast.Attribute* = ast.Attribute*(aa_pc0.annotation) - if ann_pc0.attr is not None and string.strcmp(ann_pc0.attr, "CDefine") == 0: - _g_pyi_cdef_count += 1 + if ann_pc0.attr is not None and string.strcmp(ann_pc0.attr, "CDefine") == 0: _g_pyi_cdef_count += 1 if _g_pyi_cdef_count > 0: _g_pyi_cdef_names = (str*)(mb.alloc(sizet(_g_pyi_cdef_count) * 8)) _g_pyi_cdef_vals = (int64*)(mb.alloc(sizet(_g_pyi_cdef_count) * 8)) @@ -849,8 +781,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, pos = _PyiEmit(buf, buf_size, pos, "\"\"\"Auto-generated Python stub file\"\"\"\n\n") if tree.children is None: - if pos < buf_size: - buf[pos] = 0 + if pos < buf_size: buf[pos] = 0 return pos tree_children: list[ast.AST*]* = tree.children @@ -869,20 +800,14 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, for ai in range(an): al: ast.Alias* = ast.Alias*(imp_names.get(ai)) if al is not None and al.name is not None: - if string.strcmp(al.name, "t") == 0: - has_import_t = 1 - elif string.strcmp(al.name, "c") == 0: - has_import_c = 1 + if string.strcmp(al.name, "t") == 0: has_import_t = 1 + elif string.strcmp(al.name, "c") == 0: has_import_c = 1 # 补充缺失的 import t/c - if has_import_t == 0 and has_import_c == 0: - pos = _PyiEmit(buf, buf_size, pos, "import t, c\n\n") - elif has_import_t == 0: - pos = _PyiEmit(buf, buf_size, pos, "import t\n\n") - elif has_import_c == 0: - pos = _PyiEmit(buf, buf_size, pos, "import c\n\n") - else: - pos = _PyiEmit(buf, buf_size, pos, "\n") + if has_import_t == 0 and has_import_c == 0: pos = _PyiEmit(buf, buf_size, pos, "import t, c\n\n") + elif has_import_t == 0: pos = _PyiEmit(buf, buf_size, pos, "import t\n\n") + elif has_import_c == 0: pos = _PyiEmit(buf, buf_size, pos, "import c\n\n") + else: pos = _PyiEmit(buf, buf_size, pos, "\n") # 第二遍扫描:生成声明 for i in range(n): @@ -905,8 +830,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, an2: sizet = len(imp2_names) ai2: sizet = 0 while ai2 < an2: - if ai2 > 0: - pos = _PyiEmit(buf, buf_size, pos, ", ") + if ai2 > 0: pos = _PyiEmit(buf, buf_size, pos, ", ") al2: ast.Alias* = ast.Alias*(imp2_names.get(ai2)) # fail-fast:别名节点或其名字为空 ⇒ 绝不静默写出 "import , "。 # vpi 里 import 行的名字是**包重导出注册的唯一输入** @@ -942,8 +866,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, while lvl > 0: pos = _PyiEmit(buf, buf_size, pos, ".") lvl -= 1 - if ifr.module is not None: - pos = _PyiEmit(buf, buf_size, pos, ifr.module) + if ifr.module is not None: pos = _PyiEmit(buf, buf_size, pos, ifr.module) pos = _PyiEmit(buf, buf_size, pos, " import ") # fail-fast:同 Import 分支——`from X import *` 走的是 Alias("*"), # 列表为空或名字为空都说明 AST 坏;静默写出 `from X import ` 会让 @@ -958,8 +881,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, an3: sizet = len(ifr_names) ai3: sizet = 0 while ai3 < an3: - if ai3 > 0: - pos = _PyiEmit(buf, buf_size, pos, ", ") + if ai3 > 0: pos = _PyiEmit(buf, buf_size, pos, ", ") al3: ast.Alias* = ast.Alias*(ifr_names.get(ai3)) # fail-fast:同 Import 分支(两种成因分开报,一次定位)。 if al3 is None: @@ -987,8 +909,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, # 特化体按调用点单态化生成({模板SHA1}.f[args]),其签名由编译器 # 内存中的模板表 + 实参跨模块复现(见 ClassGenGeneric. # _ensure_generic_func_declare),不落 vpi。 - if fn.type_params is not None: - continue + if fn.type_params is not None: continue pos = _PyiFunction(buf, buf_size, pos, fn, 0, "") # 类定义 @@ -1014,8 +935,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, if ctd_at.attr is not None and string.strcmp(ctd_at.attr, "CTypedef") == 0: if ctd_at.value is not None and ctd_at.value.kind() == ast.ASTKind.Name: ctd_mod: ast.Name* = ast.Name*(ctd_at.value) - if ctd_mod.id is not None and string.strcmp(ctd_mod.id, "t") == 0: - is_ctypedef_ann = 1 + if ctd_mod.id is not None and string.strcmp(ctd_mod.id, "t") == 0: is_ctypedef_ann = 1 if is_ctypedef_ann != 0 and aa.value is not None: pos = _PyiEmit(buf, buf_size, pos, " = ") pos = _PyiTypeStr(buf, buf_size, pos, aa.value) @@ -1032,10 +952,8 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, viperlib.snprintf(fbuf_c, 64, " = %.17g", cv.float_val) pos = _PyiEmit(buf, buf_size, pos, fbuf_c) elif cv.const_kind == ast.CONST_BOOL: - if cv.int_val != 0: - pos = _PyiEmit(buf, buf_size, pos, " = True") - else: - pos = _PyiEmit(buf, buf_size, pos, " = False") + if cv.int_val != 0: pos = _PyiEmit(buf, buf_size, pos, " = True") + else: pos = _PyiEmit(buf, buf_size, pos, " = False") elif cv.const_kind == ast.CONST_STR: # 字符串 CDefine(pyzlib.ZLIB_VERSION = "1.3.2" 等)必须输出值,让 stub 自包含(读回端按目标名判定会回退源文件) sbuf_c: bytes = mb.alloc(string.strlen(cv.str_val) + 6) @@ -1043,8 +961,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, viperlib.snprintf(sbuf_c, string.strlen(cv.str_val) + 6, " = \"%s\"", cv.str_val) pos = _PyiEmit(buf, buf_size, pos, sbuf_c) - elif cv.const_kind == ast.CONST_NONE: - pos = _PyiEmit(buf, buf_size, pos, " = None") + elif cv.const_kind == ast.CONST_NONE: pos = _PyiEmit(buf, buf_size, pos, " = None") elif aa.value is not None and aa.value.kind() == ast.ASTKind.UnaryOp: # 处理负值常量(如 INVALID_HANDLE_VALUE = -1) # UnaryOp(USub, Constant(1)) → -1 @@ -1138,34 +1055,22 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, inferred: int = 0 if avk == ast.ASTKind.Constant: acv: ast.Constant* = ast.Constant*(aval) - if acv.const_kind == ast.CONST_INT: - inferred = 1 - elif acv.const_kind == ast.CONST_FLOAT: - inferred = 2 - elif acv.const_kind == ast.CONST_STR: - inferred = 3 - elif acv.const_kind == ast.CONST_BOOL: - inferred = 4 - elif acv.const_kind == ast.CONST_NONE: - inferred = 5 + if acv.const_kind == ast.CONST_INT: inferred = 1 + elif acv.const_kind == ast.CONST_FLOAT: inferred = 2 + elif acv.const_kind == ast.CONST_STR: inferred = 3 + elif acv.const_kind == ast.CONST_BOOL: inferred = 4 + elif acv.const_kind == ast.CONST_NONE: inferred = 5 if inferred > 0 and agn.id is not None: pos = _PyiEmit(buf, buf_size, pos, agn.id) pos = _PyiEmit(buf, buf_size, pos, ": ") - if inferred == 1: - pos = _PyiEmit(buf, buf_size, pos, "int") - elif inferred == 2: - pos = _PyiEmit(buf, buf_size, pos, "double") - elif inferred == 3: - pos = _PyiEmit(buf, buf_size, pos, "str") - elif inferred == 4: - pos = _PyiEmit(buf, buf_size, pos, "bool") - elif inferred == 5: - pos = _PyiEmit(buf, buf_size, pos, "None") + if inferred == 1: pos = _PyiEmit(buf, buf_size, pos, "int") + elif inferred == 2: pos = _PyiEmit(buf, buf_size, pos, "double") + elif inferred == 3: pos = _PyiEmit(buf, buf_size, pos, "str") + elif inferred == 4: pos = _PyiEmit(buf, buf_size, pos, "bool") + elif inferred == 5: pos = _PyiEmit(buf, buf_size, pos, "None") pos = _PyiEmit(buf, buf_size, pos, "\n") # NUL 终止 - if pos < buf_size: - buf[pos] = 0 - else: - buf[buf_size - 1] = 0 + if pos < buf_size: buf[pos] = 0 + else: buf[buf_size - 1] = 0 return pos diff --git a/App/lib/Stub/StubGen/VpiReader.vp b/App/lib/Stub/StubGen/VpiReader.vp index 435de78..1e68e7c 100644 --- a/App/lib/Stub/StubGen/VpiReader.vp +++ b/App/lib/Stub/StubGen/VpiReader.vp @@ -155,8 +155,7 @@ _g_vpi_param_idx_built: int = 0 def _vpi_idx_hash(key: bytes) -> uint64: """键串 → 64 位哈希(32 位 FNV-1a,逐字节到 NUL 结束;空键返回偏移基值)""" h: uint64 = uint64(VPI_IDX_FNV_OFFSET) - if key is None: - return h + if key is None: return h i: sizet = 0 while key[i] != '\0': h = (h ^ uint64(int(key[i]))) * uint64(VPI_IDX_FNV_PRIME) @@ -176,8 +175,7 @@ def _vpi_idx_find(keys: bytes, key_stride: int, idx_base: bytes, 命中判据是"当前键相等"(strcmp),不能只比哈希。 """ - if keys is None or idx_base is None or cap <= 0 or key is None: - return -1 + if keys is None or idx_base is None or cap <= 0 or key is None: return -1 h: uint64 = _vpi_idx_hash(key) mask: sizet = sizet(cap - 1) si: sizet = sizet(h) & mask @@ -185,12 +183,10 @@ def _vpi_idx_find(keys: bytes, key_stride: int, idx_base: bytes, while i < cap: slot: sizet* = _vpi_idx_slot(idx_base, si) sv: sizet = slot[0] - if sv == 0: - return -1 + if sv == 0: return -1 se: int = int(sv) - 1 ek: bytes = keys + se * key_stride - if string.strcmp(ek, key) == 0: - return se + if string.strcmp(ek, key) == 0: return se si = (si + 1) & mask i += 1 return -1 @@ -198,8 +194,7 @@ def _vpi_idx_find(keys: bytes, key_stride: int, idx_base: bytes, def _vpi_idx_insert(idx_base: bytes, cap: int, slot_index: int, key: bytes) -> int: """把 (key → slot_index) 记入索引(每次注册占一槽,不去重);0=成功 / 1=失败""" - if idx_base is None or cap <= 0 or key is None: - return 1 + if idx_base is None or cap <= 0 or key is None: return 1 h: uint64 = _vpi_idx_hash(key) mask: sizet = sizet(cap - 1) si: sizet = sizet(h) & mask @@ -227,10 +222,8 @@ def _vpi_rebuild_ret_idx(new_cap: int) -> int: _g_vpi_ret_idx_built = -1 return 1 new_idx: bytes = None - if _g_vpi_ret_idx is None: - new_idx = stdlib.malloc(new_cap * 8) - else: - new_idx = stdlib.realloc(_g_vpi_ret_idx, new_cap * 8) + if _g_vpi_ret_idx is None: new_idx = stdlib.malloc(new_cap * 8) + else: new_idx = stdlib.realloc(_g_vpi_ret_idx, new_cap * 8) if new_idx is None: _g_vpi_ret_idx = None _g_vpi_ret_idx_cap = 0 @@ -262,10 +255,8 @@ def _vpi_rebuild_param_idx(new_cap: int) -> int: _g_vpi_param_idx_built = -1 return 1 new_idx: bytes = None - if _g_vpi_param_idx is None: - new_idx = stdlib.malloc(new_cap * 8) - else: - new_idx = stdlib.realloc(_g_vpi_param_idx, new_cap * 8) + if _g_vpi_param_idx is None: new_idx = stdlib.malloc(new_cap * 8) + else: new_idx = stdlib.realloc(_g_vpi_param_idx, new_cap * 8) if new_idx is None: _g_vpi_param_idx = None _g_vpi_param_idx_cap = 0 @@ -301,13 +292,11 @@ def _cache_vpi_return_annots_text(vpi_buf: bytes, src_sha1: str) -> int: """从 vpi_buf 文本提取方法返回注解字符串(stdlib 持久)""" global _g_vpi_ret_keys, _g_vpi_ret_strs, _g_vpi_ret_count, _g_vpi_ret_cap global _g_vpi_ret_idx, _g_vpi_ret_idx_cap, _g_vpi_ret_idx_built - if vpi_buf is None or src_sha1 is None: - return 0 + if vpi_buf is None or src_sha1 is None: return 0 if _g_vpi_ret_keys is None: _g_vpi_ret_keys = stdlib.malloc(VPI_RET_MAX * VPI_KEY_LEN) _g_vpi_ret_strs = stdlib.malloc(VPI_RET_MAX * VPI_RET_LEN) - if _g_vpi_ret_keys is None or _g_vpi_ret_strs is None: - return 0 + if _g_vpi_ret_keys is None or _g_vpi_ret_strs is None: return 0 string.memset(_g_vpi_ret_keys, 0, VPI_RET_MAX * VPI_KEY_LEN) string.memset(_g_vpi_ret_strs, 0, VPI_RET_MAX * VPI_RET_LEN) _g_vpi_ret_cap = VPI_RET_MAX @@ -329,13 +318,11 @@ def _cache_vpi_return_annots_text(vpi_buf: bytes, src_sha1: str) -> int: while pos < buf_len: ls: sizet = pos le: sizet = pos - while le < buf_len and vpi_buf[le] != '\n': - le += 1 + while le < buf_len and vpi_buf[le] != '\n': le += 1 line_len: sizet = le - ls # 跳过前导空格,检查 class/def i: sizet = ls - while i < le and vpi_buf[i] == ' ': - i += 1 + while i < le and vpi_buf[i] == ' ': i += 1 if i < le: # class X: if line_len >= 6 and string.strncmp(vpi_buf + i, "class ", 6) == 0: @@ -343,11 +330,9 @@ def _cache_vpi_return_annots_text(vpi_buf: bytes, src_sha1: str) -> int: cend: sizet = cstart # 类名提取:到 ':' / ' ' / '(' 前停止(继承基类括号不入类名, # 如 "class MemBuddy(MemManager):" → "MemBuddy",与调用方短名一致) - while cend < le and vpi_buf[cend] != ':' and vpi_buf[cend] != ' ' and vpi_buf[cend] != '(': - cend += 1 + while cend < le and vpi_buf[cend] != ':' and vpi_buf[cend] != ' ' and vpi_buf[cend] != '(': cend += 1 if cend > cstart: - if cur_cls is not None: - stdlib.free(cur_cls) + if cur_cls is not None: stdlib.free(cur_cls) cur_cls = stdlib.malloc(cend - cstart + 1) if cur_cls is not None: string.strncpy(cur_cls, vpi_buf + cstart, cend - cstart) @@ -361,8 +346,7 @@ def _cache_vpi_return_annots_text(vpi_buf: bytes, src_sha1: str) -> int: cur_cls = None dstart: sizet = i + 4 dend: sizet = dstart - while dend < le and vpi_buf[dend] != '(': - dend += 1 + while dend < le and vpi_buf[dend] != '(': dend += 1 # 方法名 = [dstart, dend) # 找 "->" rpos: sizet = dstart @@ -381,11 +365,9 @@ def _cache_vpi_return_annots_text(vpi_buf: bytes, src_sha1: str) -> int: if arrow_pos < le: # 返回类型 = arrow_pos+2 跳过空格 到 ':' 前 rstart2: sizet = arrow_pos + 2 - while rstart2 < le and vpi_buf[rstart2] == ' ': - rstart2 += 1 + while rstart2 < le and vpi_buf[rstart2] == ' ': rstart2 += 1 rend2: sizet = rstart2 - while rend2 < le and vpi_buf[rend2] != ':': - rend2 += 1 + while rend2 < le and vpi_buf[rend2] != ':': rend2 += 1 if rend2 > rstart2: rtype_len = rend2 - rstart2 ret_src = vpi_buf + rstart2 @@ -397,8 +379,7 @@ def _cache_vpi_return_annots_text(vpi_buf: bytes, src_sha1: str) -> int: # 构造 key 和 ret_str,存入缓存 mname_len: sizet = dend - dstart cls_len2: sizet = 0 - if cur_cls is not None: - cls_len2 = string.strlen(cur_cls) + if cur_cls is not None: cls_len2 = string.strlen(cur_cls) key_len: sizet = sha1_len + 1 + cls_len2 + 1 + mname_len if key_len < VPI_KEY_LEN and rtype_len < VPI_RET_LEN: # 方法名复制到临时缓冲(vpi_buf+dstart 非 null 结尾,不能直接 snprintf) @@ -414,10 +395,8 @@ def _cache_vpi_return_annots_text(vpi_buf: bytes, src_sha1: str) -> int: if skip_def == 0: key_buf: bytes = stdlib.malloc(key_len + 1) if key_buf is not None: - if cur_cls is not None: - viperlib.snprintf(key_buf, key_len + 1, "%s.%s.%s", src_sha1, cur_cls, mname_buf) - else: - viperlib.snprintf(key_buf, key_len + 1, "%s.%s", src_sha1, mname_buf) + if cur_cls is not None: viperlib.snprintf(key_buf, key_len + 1, "%s.%s.%s", src_sha1, cur_cls, mname_buf) + else: viperlib.snprintf(key_buf, key_len + 1, "%s.%s", src_sha1, mname_buf) # 去重:同一 key 已存在则跳过(同文件可能被多次加载) dup_key: int = 0 dki: int @@ -438,8 +417,7 @@ def _cache_vpi_return_annots_text(vpi_buf: bytes, src_sha1: str) -> int: dup_key = 1 break grow_ok: int = 1 - if dup_key == 0 and _g_vpi_ret_count >= _g_vpi_ret_cap: - grow_ok = _grow_vpi_ret_cache() + if dup_key == 0 and _g_vpi_ret_count >= _g_vpi_ret_cap: grow_ok = _grow_vpi_ret_cache() if dup_key == 0 and grow_ok != 0: string.strcpy(_g_vpi_ret_keys + _g_vpi_ret_count * VPI_KEY_LEN, key_buf) string.strncpy(_g_vpi_ret_strs + _g_vpi_ret_count * VPI_RET_LEN, @@ -451,14 +429,12 @@ def _cache_vpi_return_annots_text(vpi_buf: bytes, src_sha1: str) -> int: if _g_vpi_ret_idx_built == _g_vpi_ret_count - 1 and _vpi_idx_insert(_g_vpi_ret_idx, _g_vpi_ret_idx_cap, _g_vpi_ret_count - 1, key_buf) == 0: _g_vpi_ret_idx_built = _g_vpi_ret_count - else: - _g_vpi_ret_idx_built = -1 + else: _g_vpi_ret_idx_built = -1 stdlib.free(key_buf) stdlib.free(mname_buf) pos = le + 1 line_no += 1 - if cur_cls is not None: - stdlib.free(cur_cls) + if cur_cls is not None: stdlib.free(cur_cls) return 1 @@ -473,13 +449,11 @@ def _cache_vpi_param_annots_text(vpi_buf: bytes, src_sha1: str) -> int: """从 vpi_buf 文本提取函数/方法参数注解字符串(stdlib 持久)""" global _g_vpi_param_keys, _g_vpi_param_strs, _g_vpi_param_count, _g_vpi_param_cap global _g_vpi_param_idx, _g_vpi_param_idx_cap, _g_vpi_param_idx_built - if vpi_buf is None or src_sha1 is None: - return 0 + if vpi_buf is None or src_sha1 is None: return 0 if _g_vpi_param_keys is None: _g_vpi_param_keys = stdlib.malloc(VPI_PARAM_MAX * VPI_PARAM_KEY_LEN) _g_vpi_param_strs = stdlib.malloc(VPI_PARAM_MAX * VPI_PARAM_LEN) - if _g_vpi_param_keys is None or _g_vpi_param_strs is None: - return 0 + if _g_vpi_param_keys is None or _g_vpi_param_strs is None: return 0 string.memset(_g_vpi_param_keys, 0, VPI_PARAM_MAX * VPI_PARAM_KEY_LEN) string.memset(_g_vpi_param_strs, 0, VPI_PARAM_MAX * VPI_PARAM_LEN) _g_vpi_param_cap = VPI_PARAM_MAX @@ -500,21 +474,17 @@ def _cache_vpi_param_annots_text(vpi_buf: bytes, src_sha1: str) -> int: while pos < buf_len: ls: sizet = pos le: sizet = pos - while le < buf_len and vpi_buf[le] != '\n': - le += 1 + while le < buf_len and vpi_buf[le] != '\n': le += 1 line_len: sizet = le - ls i: sizet = ls - while i < le and vpi_buf[i] == ' ': - i += 1 + while i < le and vpi_buf[i] == ' ': i += 1 if i < le: if line_len >= 6 and string.strncmp(vpi_buf + i, "class ", 6) == 0: cstart: sizet = i + 6 cend: sizet = cstart - while cend < le and vpi_buf[cend] != ':' and vpi_buf[cend] != ' ' and vpi_buf[cend] != '(': - cend += 1 + while cend < le and vpi_buf[cend] != ':' and vpi_buf[cend] != ' ' and vpi_buf[cend] != '(': cend += 1 if cend > cstart: - if cur_cls is not None: - stdlib.free(cur_cls) + if cur_cls is not None: stdlib.free(cur_cls) cur_cls = stdlib.malloc(cend - cstart + 1) if cur_cls is not None: string.strncpy(cur_cls, vpi_buf + cstart, cend - cstart) @@ -526,8 +496,7 @@ def _cache_vpi_param_annots_text(vpi_buf: bytes, src_sha1: str) -> int: cur_cls = None dstart: sizet = i + 4 dend: sizet = dstart - while dend < le and vpi_buf[dend] != '(': - dend += 1 + while dend < le and vpi_buf[dend] != '(': dend += 1 if dend >= le: pos = le + 1 continue @@ -537,8 +506,7 @@ def _cache_vpi_param_annots_text(vpi_buf: bytes, src_sha1: str) -> int: pend: sizet = dend while p < le: ch_p: char = vpi_buf[p] - if ch_p == '(' or ch_p == '[' or ch_p == '{': - pdepth += 1 + if ch_p == '(' or ch_p == '[' or ch_p == '{': pdepth += 1 elif ch_p == ')' or ch_p == ']' or ch_p == '}': pdepth -= 1 if pdepth < 0: @@ -555,41 +523,31 @@ def _cache_vpi_param_annots_text(vpi_buf: bytes, src_sha1: str) -> int: seg_written: int = 0 seg_cur: sizet = dend + 1 while seg_cur < pend: - while seg_cur < pend and (vpi_buf[seg_cur] == ' ' or vpi_buf[seg_cur] == ','): - seg_cur += 1 - if seg_cur >= pend: - break + while seg_cur < pend and (vpi_buf[seg_cur] == ' ' or vpi_buf[seg_cur] == ','): seg_cur += 1 + if seg_cur >= pend: break s_start: sizet = seg_cur sd: int = 0 while seg_cur < pend: ch_s: char = vpi_buf[seg_cur] - if ch_s == '(' or ch_s == '[' or ch_s == '{': - sd += 1 - elif ch_s == ')' or ch_s == ']' or ch_s == '}': - sd -= 1 - elif ch_s == ',' and sd == 0: - break + if ch_s == '(' or ch_s == '[' or ch_s == '{': sd += 1 + elif ch_s == ')' or ch_s == ']' or ch_s == '}': sd -= 1 + elif ch_s == ',' and sd == 0: break seg_cur += 1 s_end: sizet = seg_cur # 跳过 * / **(vararg/kwarg 不入 args 列表) st: sizet = s_start - while st < s_end and vpi_buf[st] == ' ': - st += 1 + while st < s_end and vpi_buf[st] == ' ': st += 1 if st < s_end and vpi_buf[st] == '*': - if seg_cur < pend and vpi_buf[seg_cur] == ',': - seg_cur += 1 + if seg_cur < pend and vpi_buf[seg_cur] == ',': seg_cur += 1 continue # 截断默认值(顶层 '=',如 ": str = None") e_pos: sizet = st ed: int = 0 while e_pos < s_end: ch_e: char = vpi_buf[e_pos] - if ch_e == '(' or ch_e == '[' or ch_e == '{': - ed += 1 - elif ch_e == ')' or ch_e == ']' or ch_e == '}': - ed -= 1 - elif ch_e == '=' and ed == 0: - break + if ch_e == '(' or ch_e == '[' or ch_e == '{': ed += 1 + elif ch_e == ')' or ch_e == ']' or ch_e == '}': ed -= 1 + elif ch_e == '=' and ed == 0: break e_pos += 1 s_end = e_pos # 提取注解:顶层 ':' 之后(无 ':' → 空串,如 self) @@ -598,20 +556,16 @@ def _cache_vpi_param_annots_text(vpi_buf: bytes, src_sha1: str) -> int: annot_start: sizet = s_end while c_pos < s_end: ch_c: char = vpi_buf[c_pos] - if ch_c == '(' or ch_c == '[' or ch_c == '{': - cd2 += 1 - elif ch_c == ')' or ch_c == ']' or ch_c == '}': - cd2 -= 1 + if ch_c == '(' or ch_c == '[' or ch_c == '{': cd2 += 1 + elif ch_c == ')' or ch_c == ']' or ch_c == '}': cd2 -= 1 elif ch_c == ':' and cd2 == 0: annot_start = c_pos + 1 break c_pos += 1 a_start: sizet = annot_start - while a_start < s_end and vpi_buf[a_start] == ' ': - a_start += 1 + while a_start < s_end and vpi_buf[a_start] == ' ': a_start += 1 a_end: sizet = s_end - while a_end > a_start and vpi_buf[a_end - 1] == ' ': - a_end -= 1 + while a_end > a_start and vpi_buf[a_end - 1] == ' ': a_end -= 1 if plist_pos + (a_end - a_start) + 1 < VPI_PARAM_LEN: if seg_written > 0: plist[plist_pos] = '@' @@ -622,14 +576,12 @@ def _cache_vpi_param_annots_text(vpi_buf: bytes, src_sha1: str) -> int: plist_pos += 1 plist[plist_pos] = '\0' seg_written += 1 - if seg_cur < pend and vpi_buf[seg_cur] == ',': - seg_cur += 1 + if seg_cur < pend and vpi_buf[seg_cur] == ',': seg_cur += 1 # 存入缓存(key = sha1.class.method / sha1.method,去重) if plist_pos > 0 and plist[0] != '\0': mname_len: sizet = dend - dstart cls_len2: sizet = 0 - if cur_cls is not None: - cls_len2 = string.strlen(cur_cls) + if cur_cls is not None: cls_len2 = string.strlen(cur_cls) key_len: sizet = sha1_len + 1 + cls_len2 + 1 + mname_len if key_len < VPI_PARAM_KEY_LEN: mname_buf: bytes = stdlib.malloc(mname_len + 1) @@ -638,10 +590,8 @@ def _cache_vpi_param_annots_text(vpi_buf: bytes, src_sha1: str) -> int: mname_buf[mname_len] = '\0' key_buf: bytes = stdlib.malloc(key_len + 1) if key_buf is not None: - if cur_cls is not None: - viperlib.snprintf(key_buf, key_len + 1, "%s.%s.%s", src_sha1, cur_cls, mname_buf) - else: - viperlib.snprintf(key_buf, key_len + 1, "%s.%s", src_sha1, mname_buf) + if cur_cls is not None: viperlib.snprintf(key_buf, key_len + 1, "%s.%s.%s", src_sha1, cur_cls, mname_buf) + else: viperlib.snprintf(key_buf, key_len + 1, "%s.%s", src_sha1, mname_buf) dup_key: int = 0 dki: int # 索引快速路径:索引可信(Built==Count)时一次探测判定 @@ -661,8 +611,7 @@ def _cache_vpi_param_annots_text(vpi_buf: bytes, src_sha1: str) -> int: dup_key = 1 break grow_ok: int = 1 - if dup_key == 0 and _g_vpi_param_count >= _g_vpi_param_cap: - grow_ok = _grow_vpi_param_cache() + if dup_key == 0 and _g_vpi_param_count >= _g_vpi_param_cap: grow_ok = _grow_vpi_param_cache() if dup_key == 0 and grow_ok != 0: string.strcpy(_g_vpi_param_keys + _g_vpi_param_count * VPI_PARAM_KEY_LEN, key_buf) string.strncpy(_g_vpi_param_strs + _g_vpi_param_count * VPI_PARAM_LEN, @@ -674,14 +623,12 @@ def _cache_vpi_param_annots_text(vpi_buf: bytes, src_sha1: str) -> int: if _g_vpi_param_idx_built == _g_vpi_param_count - 1 and _vpi_idx_insert(_g_vpi_param_idx, _g_vpi_param_idx_cap, _g_vpi_param_count - 1, key_buf) == 0: _g_vpi_param_idx_built = _g_vpi_param_count - else: - _g_vpi_param_idx_built = -1 + else: _g_vpi_param_idx_built = -1 stdlib.free(key_buf) stdlib.free(mname_buf) stdlib.free(plist) pos = le + 1 - if cur_cls is not None: - stdlib.free(cur_cls) + if cur_cls is not None: stdlib.free(cur_cls) return 1 @@ -691,17 +638,13 @@ def _cache_vpi_param_annots_text(vpi_buf: bytes, src_sha1: str) -> int: def _grow_vpi_param_cache() -> int: """扩容参数注解缓存(容量翻倍),返回 1=成功 / 0=失败""" global _g_vpi_param_keys, _g_vpi_param_strs, _g_vpi_param_cap - if _g_vpi_param_keys is None or _g_vpi_param_cap <= 0: - return 0 + if _g_vpi_param_keys is None or _g_vpi_param_cap <= 0: return 0 new_cap: int = _g_vpi_param_cap * 2 - if new_cap > 1048576: - return 0 + if new_cap > 1048576: return 0 new_keys: bytes = stdlib.realloc(_g_vpi_param_keys, new_cap * VPI_PARAM_KEY_LEN) - if new_keys is None: - return 0 + if new_keys is None: return 0 new_strs: bytes = stdlib.realloc(_g_vpi_param_strs, new_cap * VPI_PARAM_LEN) - if new_strs is None: - return 0 + if new_strs is None: return 0 _g_vpi_param_keys = new_keys _g_vpi_param_strs = new_strs _g_vpi_param_cap = new_cap @@ -715,23 +658,17 @@ def _grow_vpi_param_cache() -> int: # ============================================================ def _lookup_vpi_param_annots(src_sha1: str, cls_name: str, method_name: str) -> str: """查参数注解缓存;返回注解串('@' 分隔,含首参空串占位)或 None""" - if src_sha1 is None or method_name is None or _g_vpi_param_keys is None: - return None + if src_sha1 is None or method_name is None or _g_vpi_param_keys is None: return None sha1_len: sizet = string.strlen(src_sha1) mlen: sizet = string.strlen(method_name) clen: sizet = 0 - if cls_name is not None: - clen = string.strlen(cls_name) + if cls_name is not None: clen = string.strlen(cls_name) key_len: sizet = sha1_len + clen + mlen + 2 - if key_len >= VPI_PARAM_KEY_LEN: - return None + if key_len >= VPI_PARAM_KEY_LEN: return None key_buf: bytes = stdlib.malloc(key_len + 1) - if key_buf is None: - return None - if cls_name is not None: - viperlib.snprintf(key_buf, key_len + 1, "%s.%s.%s", src_sha1, cls_name, method_name) - else: - viperlib.snprintf(key_buf, key_len + 1, "%s.%s", src_sha1, method_name) + if key_buf is None: return None + if cls_name is not None: viperlib.snprintf(key_buf, key_len + 1, "%s.%s.%s", src_sha1, cls_name, method_name) + else: viperlib.snprintf(key_buf, key_len + 1, "%s.%s", src_sha1, method_name) r: str = None ki: int # 索引快速路径:索引可信(Built==Count)时一次探测返回命中槽下标(= 原线性 @@ -750,8 +687,7 @@ def _lookup_vpi_param_annots(src_sha1: str, cls_name: str, method_name: str) -> if ent_p[0] == key_first and string.strcmp(ent_p, key_buf) == 0: hit_p = ki break - if hit_p >= 0: - r = _g_vpi_param_strs + hit_p * VPI_PARAM_LEN + if hit_p >= 0: r = _g_vpi_param_strs + hit_p * VPI_PARAM_LEN stdlib.free(key_buf) return r @@ -771,21 +707,16 @@ def _resolve_vpi_param_annot_seg_template(pool: memhub.MemBuddy*, i32_ty: mlirlite.LLVMType*, i8_ptr_ty: mlirlite.LLVMType*) -> mlirlite.LLVMType*: """特化类 X[arg] 的参数注解段解析(模板 X[T] 注解 + T→arg 替换);未命中 None""" - if pool is None or src_sha1 is None or cls_name is None or method_name is None or _g_vpi_param_keys is None: - return None + if pool is None or src_sha1 is None or cls_name is None or method_name is None or _g_vpi_param_keys is None: return None lbkt_t: str = string.strchr(cls_name, 91) # '[' = 91 - if lbkt_t is None: - return None + if lbkt_t is None: return None rbkt_t: str = string.strrchr(cls_name, 93) # ']' = 93 - if rbkt_t is None or rbkt_t <= lbkt_t: - return None + if rbkt_t is None or rbkt_t <= lbkt_t: return None base_len_t: sizet = uint64(lbkt_t) - uint64(cls_name) arg_len_t: sizet = uint64(rbkt_t) - uint64(lbkt_t) - 1 - if base_len_t <= 0 or arg_len_t <= 0: - return None + if base_len_t <= 0 or arg_len_t <= 0: return None base_t: bytes = stdlib.malloc(base_len_t + 1) - if base_t is None: - return None + if base_t is None: return None arg_t: bytes = stdlib.malloc(arg_len_t + 1) if arg_t is None: stdlib.free(base_t) @@ -799,40 +730,29 @@ def _resolve_vpi_param_annot_seg_template(pool: memhub.MemBuddy*, ki_t: int for ki_t in range(_g_vpi_param_count): gk_t: bytes = _g_vpi_param_keys + ki_t * VPI_PARAM_KEY_LEN - if string.strncmp(gk_t, src_sha1, sha1_len_t) != 0 or gk_t[sha1_len_t] != '.': - continue - if string.strncmp(gk_t + sha1_len_t + 1, base_t, base_len_t) != 0: - continue - if gk_t[sha1_len_t + 1 + base_len_t] != 91: - continue + if string.strncmp(gk_t, src_sha1, sha1_len_t) != 0 or gk_t[sha1_len_t] != '.': continue + if string.strncmp(gk_t + sha1_len_t + 1, base_t, base_len_t) != 0: continue + if gk_t[sha1_len_t + 1 + base_len_t] != 91: continue gklb_t: str = string.strchr(gk_t + sha1_len_t + 1 + base_len_t, 93) - if gklb_t is None: - continue + if gklb_t is None: continue tplen_t: sizet = uint64(gklb_t) - uint64(gk_t + sha1_len_t + 1 + base_len_t) - 1 # 方法名须整体匹配(gklb_t 后即 ']' 与 '.';mangled 形态保证无同名歧义) - if tplen_t <= 0 or string.strcmp(gklb_t + 2, method_name) != 0: - continue + if tplen_t <= 0 or string.strcmp(gklb_t + 2, method_name) != 0: continue annots_t: str = _g_vpi_param_strs + ki_t * VPI_PARAM_LEN - if annots_t is None or annots_t[0] == '\0': - break + if annots_t is None or annots_t[0] == '\0': break # 段定位(与 _resolve_vpi_param_annot_seg 同口径:'@' 分隔,段 0 = self 空段) cur_t: sizet = 0 cur_seg_t: int = 0 while cur_seg_t < seg_idx and annots_t[cur_t] != '\0': - while annots_t[cur_t] != '\0' and annots_t[cur_t] != '@': - cur_t += 1 - if annots_t[cur_t] == '@': - cur_t += 1 + while annots_t[cur_t] != '\0' and annots_t[cur_t] != '@': cur_t += 1 + if annots_t[cur_t] == '@': cur_t += 1 cur_seg_t += 1 seg_start_t: sizet = cur_t seg_len_t: sizet = 0 - while annots_t[seg_start_t + seg_len_t] != '\0' and annots_t[seg_start_t + seg_len_t] != '@': - seg_len_t += 1 - if seg_len_t == 0: - break + while annots_t[seg_start_t + seg_len_t] != '\0' and annots_t[seg_start_t + seg_len_t] != '@': seg_len_t += 1 + if seg_len_t == 0: break seg_buf_t: bytes = stdlib.malloc(seg_len_t + 1) - if seg_buf_t is None: - break + if seg_buf_t is None: break string.strncpy(seg_buf_t, annots_t + seg_start_t, seg_len_t) seg_buf_t[seg_len_t] = '\0' # 类型形参 token(如 T)→ 特化实参(如 str / rawptr[AST] / AST*): @@ -846,8 +766,7 @@ def _resolve_vpi_param_annot_seg_template(pool: memhub.MemBuddy*, # _subst_template_arg 早退分支(tplen==0 或 tplen>alen)返回入参 # 本身 ⇒ subst_t 与 seg_buf_t 同指针时并非新分配,此处不得 free # (否则与末尾 free(seg_buf_t) 重复释放) - if uint64(subst_t) != uint64(seg_buf_t): - stdlib.free(seg_buf_t) + if uint64(subst_t) != uint64(seg_buf_t): stdlib.free(seg_buf_t) seg_buf_t = subst_t stdlib.free(tparam_t) ty_t = _resolve_vpi_ret_annot_str(pool, seg_buf_t, i32_ty, i8_ptr_ty) @@ -873,30 +792,24 @@ def _repair_declare_params_from_text(pool: memhub.MemBuddy*, i32_ty: mlirlite.LLVMType*, i8_ptr_ty: mlirlite.LLVMType*) -> int: """用 vpi 文本缓存的参数注解补全 declare 参数;返回补全后参数数""" - if func is None or src_sha1 is None or method_name is None: - return param_count + if func is None or src_sha1 is None or method_name is None: return param_count prm_annots: str = _lookup_vpi_param_annots(src_sha1, cls_name, method_name) - if prm_annots is None or prm_annots[0] == '\0': - return param_count + if prm_annots is None or prm_annots[0] == '\0': return param_count # 统计文本参数数('@' 分隔;段数 = 分隔符数 + 1,含首参) pa_count: int = 1 pi2: sizet = 0 while prm_annots[pi2] != '\0': - if prm_annots[pi2] == '@': - pa_count += 1 + if prm_annots[pi2] == '@': pa_count += 1 pi2 += 1 - if pa_count <= param_count: - return param_count + if pa_count <= param_count: return param_count # 补全缺失参数:段索引 >= param_count 的段即缺失参数位置 seg_idx: int = 0 seg_start2: sizet = 0 cur2: sizet = 0 while prm_annots[cur2] != '\0': - while prm_annots[cur2] != '\0' and prm_annots[cur2] != '@': - cur2 += 1 + while prm_annots[cur2] != '\0' and prm_annots[cur2] != '@': cur2 += 1 seg_len2: sizet = cur2 - seg_start2 - if prm_annots[cur2] == '@': - cur2 += 1 + if prm_annots[cur2] == '@': cur2 += 1 if seg_idx >= param_count: param_ty_r: mlirlite.LLVMType* = i8_ptr_ty if seg_len2 > 0: @@ -906,8 +819,7 @@ def _repair_declare_params_from_text(pool: memhub.MemBuddy*, seg_buf_r[seg_len2] = '\0' rt: mlirlite.LLVMType* = _resolve_vpi_ret_annot_str( pool, seg_buf_r, i32_ty, i8_ptr_ty) - if rt is not None: - param_ty_r = rt + if rt is not None: param_ty_r = rt stdlib.free(seg_buf_r) mlirlite.add_param(pool, func, param_ty_r, "arg") seg_start2 = cur2 @@ -930,28 +842,21 @@ def _resolve_vpi_param_annot_seg(pool: memhub.MemBuddy*, i32_ty: mlirlite.LLVMType*, i8_ptr_ty: mlirlite.LLVMType*) -> mlirlite.LLVMType*: """按段索引解析 vpi 参数注解段为 LLVMType,空段/失败返回 None""" - if pool is None or src_sha1 is None or method_name is None: - return None + if pool is None or src_sha1 is None or method_name is None: return None prm_annots_p: str = _lookup_vpi_param_annots(src_sha1, cls_name, method_name) - if prm_annots_p is None or prm_annots_p[0] == '\0': - return None + if prm_annots_p is None or prm_annots_p[0] == '\0': return None cur_p: sizet = 0 cur_seg_p: int = 0 while cur_seg_p < seg_idx and prm_annots_p[cur_p] != '\0': - while prm_annots_p[cur_p] != '\0' and prm_annots_p[cur_p] != '@': - cur_p += 1 - if prm_annots_p[cur_p] == '@': - cur_p += 1 + while prm_annots_p[cur_p] != '\0' and prm_annots_p[cur_p] != '@': cur_p += 1 + if prm_annots_p[cur_p] == '@': cur_p += 1 cur_seg_p += 1 seg_start_p: sizet = cur_p seg_len_p: sizet = 0 - while prm_annots_p[seg_start_p + seg_len_p] != '\0' and prm_annots_p[seg_start_p + seg_len_p] != '@': - seg_len_p += 1 - if seg_len_p == 0: - return None + while prm_annots_p[seg_start_p + seg_len_p] != '\0' and prm_annots_p[seg_start_p + seg_len_p] != '@': seg_len_p += 1 + if seg_len_p == 0: return None seg_buf_p: bytes = stdlib.malloc(seg_len_p + 1) - if seg_buf_p is None: - return None + if seg_buf_p is None: return None string.strncpy(seg_buf_p, prm_annots_p + seg_start_p, seg_len_p) seg_buf_p[seg_len_p] = '\0' seg_ty_p: mlirlite.LLVMType* = _resolve_vpi_ret_annot_str( @@ -969,17 +874,13 @@ def _resolve_vpi_param_annot_seg(pool: memhub.MemBuddy*, def _grow_vpi_ret_cache() -> int: """扩容返回注解缓存(容量翻倍),返回 1=成功 / 0=失败""" global _g_vpi_ret_keys, _g_vpi_ret_strs, _g_vpi_ret_cap - if _g_vpi_ret_keys is None or _g_vpi_ret_cap <= 0: - return 0 + if _g_vpi_ret_keys is None or _g_vpi_ret_cap <= 0: return 0 new_cap: int = _g_vpi_ret_cap * 2 - if new_cap > 1048576: - return 0 + if new_cap > 1048576: return 0 new_keys: bytes = stdlib.realloc(_g_vpi_ret_keys, new_cap * VPI_KEY_LEN) - if new_keys is None: - return 0 + if new_keys is None: return 0 new_strs: bytes = stdlib.realloc(_g_vpi_ret_strs, new_cap * VPI_RET_LEN) - if new_strs is None: - return 0 + if new_strs is None: return 0 _g_vpi_ret_keys = new_keys _g_vpi_ret_strs = new_strs _g_vpi_ret_cap = new_cap @@ -997,11 +898,9 @@ def _grow_vpi_ret_cache() -> int: # ============================================================ def _ensure_vpi_ret_annot_loaded(src_sha1: str, temp_dir: str) -> int: """按需加载模块 vpi stub 的返回注解缓存,返回 1=已就绪 / 0=失败""" - if src_sha1 is None or temp_dir is None: - return 0 + if src_sha1 is None or temp_dir is None: return 0 sha1_len: sizet = string.strlen(src_sha1) - if sha1_len < 2: - return 0 + if sha1_len < 2: return 0 # 该模块已有缓存条目 → 跳过(幂等) if _g_vpi_ret_keys is not None and _g_vpi_ret_count > 0: pre_i: int @@ -1011,14 +910,12 @@ def _ensure_vpi_ret_annot_loaded(src_sha1: str, temp_dir: str) -> int: s1: int = src_sha1[1] for pre_i in range(_g_vpi_ret_count): pre_key: bytes = _g_vpi_ret_keys + pre_i * VPI_KEY_LEN - if pre_key[0] == s0 and pre_key[1] == s1 and string.strncmp(pre_key, src_sha1, sha1_len) == 0 and pre_key[sha1_len] == '.': - return 1 + if pre_key[0] == s0 and pre_key[1] == s1 and string.strncmp(pre_key, src_sha1, sha1_len) == 0 and pre_key[sha1_len] == '.': return 1 # 构造路径 {temp_dir}/{sha1[0:2]}/{sha1}.vpi(逐字符拼接,避免 %c 格式化问题) td_len: sizet = string.strlen(temp_dir) path_len: sizet = td_len + sha1_len + 12 vpi_path: bytes = stdlib.malloc(path_len) - if vpi_path is None: - return 0 + if vpi_path is None: return 0 string.strcpy(vpi_path, temp_dir) vpi_path[td_len] = '/' vpi_path[td_len + 1] = src_sha1[0] @@ -1038,8 +935,7 @@ def _ensure_vpi_ret_annot_loaded(src_sha1: str, temp_dir: str) -> int: bytes_read: LONG = f.read_all(vpi_buf, VPI_READ_BUF_SIZE) f.close() if bytes_read > 0: - if bytes_read < VPI_READ_BUF_SIZE: - vpi_buf[bytes_read] = 0 + if bytes_read < VPI_READ_BUF_SIZE: vpi_buf[bytes_read] = 0 _cache_vpi_return_annots_text(vpi_buf, src_sha1) stdlib.free(vpi_buf) stdlib.free(vpi_path) @@ -1059,31 +955,24 @@ def _vpi_param_annot_seg_is(src_sha1: str, cls_name: str, method_name: str, 典型用途:判定定义侧形参注解是否为**裸** `str` / `bytes`(用于"str/bytes 不是通用指针通配"这条规则;`str*` 这类组合段不等值,不受影响)。 """ - if want is None or seg_idx < 0: - return 0 + if want is None or seg_idx < 0: return 0 prm: str = _lookup_vpi_param_annots(src_sha1, cls_name, method_name) - if prm is None or prm[0] == '\0': - return 0 + if prm is None or prm[0] == '\0': return 0 cur: sizet = 0 seg: int = 0 # 定位段起点:跳过 seg_idx 个 '@' 段 while seg < seg_idx: - while prm[cur] != '\0' and prm[cur] != '@': - cur += 1 - if prm[cur] == '\0': - return 0 + while prm[cur] != '\0' and prm[cur] != '@': cur += 1 + if prm[cur] == '\0': return 0 cur += 1 seg += 1 slen: sizet = 0 - while prm[cur + slen] != '\0' and prm[cur + slen] != '@': - slen += 1 + while prm[cur + slen] != '\0' and prm[cur + slen] != '@': slen += 1 wlen: sizet = string.strlen(want) - if slen != wlen: - return 0 + if slen != wlen: return 0 i: sizet for i in range(slen): - if prm[cur + i] != want[i]: - return 0 + if prm[cur + i] != want[i]: return 0 return 1 @@ -1096,11 +985,9 @@ def _vpi_param_annot_seg_is(src_sha1: str, cls_name: str, method_name: str, # ============================================================ def _ensure_vpi_param_annot_loaded(src_sha1: str, temp_dir: str) -> int: """按需加载模块 vpi stub 的参数注解缓存,返回 1=已就绪 / 0=失败""" - if src_sha1 is None or temp_dir is None: - return 0 + if src_sha1 is None or temp_dir is None: return 0 sha1_len: sizet = string.strlen(src_sha1) - if sha1_len < 2: - return 0 + if sha1_len < 2: return 0 # 该模块已有参数缓存条目 → 跳过(幂等) if _g_vpi_param_keys is not None and _g_vpi_param_count > 0: pre_i: int @@ -1110,14 +997,12 @@ def _ensure_vpi_param_annot_loaded(src_sha1: str, temp_dir: str) -> int: s1: int = src_sha1[1] for pre_i in range(_g_vpi_param_count): pre_key: bytes = _g_vpi_param_keys + pre_i * VPI_PARAM_KEY_LEN - if pre_key[0] == s0 and pre_key[1] == s1 and string.strncmp(pre_key, src_sha1, sha1_len) == 0 and pre_key[sha1_len] == '.': - return 1 + if pre_key[0] == s0 and pre_key[1] == s1 and string.strncmp(pre_key, src_sha1, sha1_len) == 0 and pre_key[sha1_len] == '.': return 1 # 构造路径 {temp_dir}/{sha1[0:2]}/{sha1}.vpi(逐字符拼接,避免 %c 格式化问题) td_len: sizet = string.strlen(temp_dir) path_len: sizet = td_len + sha1_len + 12 vpi_path: bytes = stdlib.malloc(path_len) - if vpi_path is None: - return 0 + if vpi_path is None: return 0 string.strcpy(vpi_path, temp_dir) vpi_path[td_len] = '/' vpi_path[td_len + 1] = src_sha1[0] @@ -1137,8 +1022,7 @@ def _ensure_vpi_param_annot_loaded(src_sha1: str, temp_dir: str) -> int: bytes_read: LONG = f.read_all(vpi_buf, VPI_READ_BUF_SIZE) f.close() if bytes_read > 0: - if bytes_read < VPI_READ_BUF_SIZE: - vpi_buf[bytes_read] = 0 + if bytes_read < VPI_READ_BUF_SIZE: vpi_buf[bytes_read] = 0 _cache_vpi_param_annots_text(vpi_buf, src_sha1) stdlib.free(vpi_buf) stdlib.free(vpi_path) @@ -1153,24 +1037,20 @@ def _ensure_vpi_param_annot_loaded(src_sha1: str, temp_dir: str) -> int: # ============================================================ def _subst_template_arg(annot: str, tparam: str, targ: str) -> str: """替换 annot 中独立的 tparam token 为 targ""" - if annot is None or tparam is None or targ is None: - return None + if annot is None or tparam is None or targ is None: return None alen: sizet = string.strlen(annot) tplen: sizet = string.strlen(tparam) tglen: sizet = string.strlen(targ) - if tplen == 0 or tplen > alen: - return annot + if tplen == 0 or tplen > alen: return annot # 容量 = alen + tglen*8 + 16 只覆盖 ≤8 次替换;替换次数无上限时 # opos 会越界写穿 stdlib 堆(哨兵盲区 → CRT 堆损坏后任意 malloc/free # 静默段错误、崩溃点漂移)。按最坏上界分配:每替换消耗 tplen 写 tglen, # 最坏全部被替换 → alen + (alen/tplen)*tglen + 1。 max_sub: sizet = alen / tplen - if max_sub == 0: - max_sub = 1 + if max_sub == 0: max_sub = 1 out_size: sizet = alen + max_sub * tglen + 1 out: bytes = stdlib.malloc(out_size) - if out is None: - return None + if out is None: return None opos: sizet = 0 p: sizet = 0 while p < alen: @@ -1183,16 +1063,12 @@ def _subst_template_arg(annot: str, tparam: str, targ: str) -> str: if string.strncmp(annot + p, tparam, tplen) == 0: prev_ch: int = 0 next_ch: int = 0 - if p > 0: - prev_ch = annot[p - 1] - if p + tplen < alen: - next_ch = annot[p + tplen] + if p > 0: prev_ch = annot[p - 1] + if p + tplen < alen: next_ch = annot[p + tplen] prev_ok: int = 1 - if (prev_ch >= 'a' and prev_ch <= 'z') or (prev_ch >= 'A' and prev_ch <= 'Z') or (prev_ch >= '0' and prev_ch <= '9') or prev_ch == '_': - prev_ok = 0 + if (prev_ch >= 'a' and prev_ch <= 'z') or (prev_ch >= 'A' and prev_ch <= 'Z') or (prev_ch >= '0' and prev_ch <= '9') or prev_ch == '_': prev_ok = 0 next_ok: int = 1 - if (next_ch >= 'a' and next_ch <= 'z') or (next_ch >= 'A' and next_ch <= 'Z') or (next_ch >= '0' and next_ch <= '9') or next_ch == '_': - next_ok = 0 + if (next_ch >= 'a' and next_ch <= 'z') or (next_ch >= 'A' and next_ch <= 'Z') or (next_ch >= '0' and next_ch <= '9') or next_ch == '_': next_ok = 0 if prev_ok != 0 and next_ok != 0: string.strncpy(out + opos, targ, tglen) opos += tglen @@ -1211,23 +1087,17 @@ def _subst_template_arg(annot: str, tparam: str, targ: str) -> str: # ============================================================ def _lookup_vpi_ret_annot(src_sha1: str, cls_name: str, method_name: str) -> str: """查找缓存的方法返回注解字符串,未找到返回 None""" - if _g_vpi_ret_keys is None or _g_vpi_ret_count == 0: - return None - if src_sha1 is None or method_name is None: - return None + if _g_vpi_ret_keys is None or _g_vpi_ret_count == 0: return None + if src_sha1 is None or method_name is None: return None sha1_len: sizet = string.strlen(src_sha1) cl_len: sizet = 0 - if cls_name is not None: - cl_len = string.strlen(cls_name) + if cls_name is not None: cl_len = string.strlen(cls_name) me_len: sizet = string.strlen(method_name) key_len: sizet = sha1_len + 1 + cl_len + 1 + me_len key_buf: bytes = stdlib.malloc(key_len + 1) - if key_buf is None: - return None - if cls_name is not None: - viperlib.snprintf(key_buf, key_len + 1, "%s.%s.%s", src_sha1, cls_name, method_name) - else: - viperlib.snprintf(key_buf, key_len + 1, "%s.%s", src_sha1, method_name) + if key_buf is None: return None + if cls_name is not None: viperlib.snprintf(key_buf, key_len + 1, "%s.%s.%s", src_sha1, cls_name, method_name) + else: viperlib.snprintf(key_buf, key_len + 1, "%s.%s", src_sha1, method_name) i: int # 索引快速路径:索引可信(Built==Count)时一次探测返回命中槽下标(= 原线性 # 扫描首个同名,首注册优先);未命中即"确无"精确键(键表只追加、键文本注册后 @@ -1302,8 +1172,7 @@ def _lookup_vpi_ret_annot(src_sha1: str, cls_name: str, method_name: str) -> str def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*, seg: str) -> mlirlite.LLVMType*: """解析单个类型段为 LLVMType,无法识别返回 None""" - if seg is None or pool is None: - return None + if seg is None or pool is None: return None # 【指针实参唯一规范形 `T*`(用户定口径,2026-09-30)】`rawptr[T]` ≡ # `t.CPtr[T]` ≡ `T*` ⇒ 一律折叠为 `T*`(见 TypeGenResolve # ._norm_type_arg_name 规则 1.0/1.5)。为什么必须在此补:_subst_template_arg @@ -1317,8 +1186,7 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*, # "{sha}.AST*" → "rawptr[{sha}.AST]";"i8**" → "rawptr[rawptr[i8]]"。 seg_len_ps: sizet = string.strlen(seg) star_end_ps: sizet = seg_len_ps - while star_end_ps > 0 and seg[star_end_ps - 1] == ' ': - star_end_ps -= 1 + while star_end_ps > 0 and seg[star_end_ps - 1] == ' ': star_end_ps -= 1 star_cnt_ps: sizet = 0 star_base_end_ps: sizet = star_end_ps while star_base_end_ps > 0 and seg[star_base_end_ps - 1] == '*': @@ -1328,8 +1196,7 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*, # 基数段长度 = star_base_end_ps;每层 "rawptr[" + "]" 共 8 字符 star_buf_len_ps: sizet = star_base_end_ps + 8 * star_cnt_ps + 1 star_buf_ps: bytes = stdlib.malloc(star_buf_len_ps) - if star_buf_ps is None: - return None + if star_buf_ps is None: return None star_buf_ps[0] = '\0' star_k_ps: sizet = 0 while star_k_ps < star_cnt_ps: @@ -1348,12 +1215,9 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*, i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty) # 内置别名 - if string.strcmp(seg, "str") == 0 or string.strcmp(seg, "bytes") == 0: - return i8_ptr_ty - if string.strcmp(seg, "int") == 0: - return mlirlite.Int32(pool) - if string.strcmp(seg, "bool") == 0: - return mlirlite.Int1(pool) + if string.strcmp(seg, "str") == 0 or string.strcmp(seg, "bytes") == 0: return i8_ptr_ty + if string.strcmp(seg, "int") == 0: return mlirlite.Int32(pool) + if string.strcmp(seg, "bool") == 0: return mlirlite.Int1(pool) # LLVM 类型串:vpi 缓存对无返回注解方法默认存 "i32" # (见 _cache_vpi_return_annots_text;push 等无注解方法返回 i32)。 # 之前缺分支导致解析返回 None → 泛型模板方法(Vector[int].push)调用 @@ -1371,8 +1235,7 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*, # `-> None` 的跨模块方法(如 AssignGenMixin._register_cdefine_from_value)vpi # 缓存命中也解析不出 void → 方法返回类型 fail-fast 误报(追加80e 断点 B)。 # None 与 void 同义,归一到 Void。 - if string.strcmp(seg, "None") == 0: - return mlirlite.Void(pool) + if string.strcmp(seg, "None") == 0: return mlirlite.Void(pool) # rawptr[T] 内建裸指针(等价 t.CPtr[T] → Ptr(T)):vpi 返回/参数注解按源码 # 原样保留 Subscript 形态(如 tokens.vp `new_token -> rawptr[Token]`)。 # 此前无此分支 → 整个注解解析返回 None → text.ll 尚未生成(合法时序:依赖 @@ -1389,14 +1252,12 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*, inner_buf_rp[inner_len_rp] = '\0' inner_ty_rp: mlirlite.LLVMType* = _resolve_single_vpi_type_str(pool, inner_buf_rp) stdlib.free(inner_buf_rp) - if inner_ty_rp is not None: - return mlirlite.Ptr(pool, inner_ty_rp) + if inner_ty_rp is not None: return mlirlite.Ptr(pool, inner_ty_rp) return None # t.CPtr[T] / c.CPtr[T] 下标指针(含嵌套,如 t.CPtr[t.CPtr] → Ptr(Ptr(i8))):与定义侧 TypeGenResolve 的 Subscript(CPtr) 分支同口径 Ptr(resolve(T))。 # vpi 注解文本按源码原样缓存;本函数若对该形态返回 None 会让该段被丢弃 → 联合坍缩到首段(i8),与定义侧指针层级不一致(跨模块 declare/define ABI 错位)。 cptr_sub_pfx: sizet = 0 - if string.strncmp(seg, "t.CPtr[", 7) == 0 or string.strncmp(seg, "c.CPtr[", 7) == 0: - cptr_sub_pfx = 7 + if string.strncmp(seg, "t.CPtr[", 7) == 0 or string.strncmp(seg, "c.CPtr[", 7) == 0: cptr_sub_pfx = 7 if cptr_sub_pfx > 0: seg_len_cp: sizet = string.strlen(seg) if seg_len_cp > cptr_sub_pfx + 1 and seg[seg_len_cp - 1] == ']': @@ -1408,8 +1269,7 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*, inner_ty_cp: mlirlite.LLVMType* = _resolve_single_vpi_type_str( pool, inner_buf_cp) stdlib.free(inner_buf_cp) - if inner_ty_cp is not None: - return mlirlite.Ptr(pool, inner_ty_cp) + if inner_ty_cp is not None: return mlirlite.Ptr(pool, inner_ty_cp) return None # t.XXX / c.XXX 内置类型映射 if string.strncmp(seg, "t.", 2) == 0 or string.strncmp(seg, "c.", 2) == 0: @@ -1419,42 +1279,35 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*, # 调用方解析必须同样归一 Void,否则 vpi 缓存 miss → 跨模块函数 # 返回类型无法精确获取 fail-fast 误报(VKernel mm.free -> t.CExport # "1fdad1c76fb116bc.free 返回类型无法精确获取" 根因)。 - if string.strcmp(attr_nm, "CExport") == 0: - return mlirlite.Void(pool) + if string.strcmp(attr_nm, "CExport") == 0: return mlirlite.Void(pool) # [阶段2] 统一口径:CTypedef 动态表优先(库 typedef 走正常库分析), # miss 回退 map_t_type(t/c 库内部特判)。 mapped_ty: mlirlite.LLVMType* = GenApi.resolve_typedef_or_map(pool, attr_nm, None, None) - if mapped_ty is not None: - return mapped_ty + if mapped_ty is not None: return mapped_ty return None # 模块限定类名 "memhub.MemBuddy" → 取最后一段查 struct last_dot: str = string.strrchr(seg, '.') if last_dot is not None: cls_nm2: str = last_dot + 1 mod_struct_ty: mlirlite.LLVMType* = GenApi.get_struct_type(cls_nm2) - if mod_struct_ty is not None: - return mod_struct_ty + if mod_struct_ty is not None: return mod_struct_ty # 枚举兜底:t.CEnum 注册在独立 EnumTable(EnumEntry),不进 StructTable, # get_struct_type 查不到。如 fat32.close -> types.FRESULT(FRESULT 是枚举), # struct 落空必须回退枚举表取 BaseTy(通常 i32)。否则 vpi 返回注解解析 # 失败 → 跨模块函数返回类型无法精确获取 → text.ll 缺失(依赖环)时 # 永久 pending(VKernel fat32→sched→process→fat32 Phase A 死锁根因)。 mod_enum_ty: mlirlite.LLVMType* = GenApi.get_enum_base_type(cls_nm2) - if mod_enum_ty is not None: - return mod_enum_ty + if mod_enum_ty is not None: return mod_enum_ty return None # 裸类名 → 全局 struct 注册表 bare_struct_ty: mlirlite.LLVMType* = GenApi.get_struct_type(seg) - if bare_struct_ty is not None: - return bare_struct_ty + if bare_struct_ty is not None: return bare_struct_ty # 裸枚举名 → EnumTable 兜底(同上:枚举不在 StructTable) bare_enum_ty: mlirlite.LLVMType* = GenApi.get_enum_base_type(seg) - if bare_enum_ty is not None: - return bare_enum_ty + if bare_enum_ty is not None: return bare_enum_ty # 裸 typedef 名(如 VOIDPTR):CTypedef 动态表优先,miss 回退 map_t_type mapped_bare: mlirlite.LLVMType* = GenApi.resolve_typedef_or_map(pool, seg, None, None) - if mapped_bare is not None: - return mapped_bare + if mapped_bare is not None: return mapped_bare return None @@ -1470,8 +1323,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, i32_ty: mlirlite.LLVMType*, i8_ptr_ty: mlirlite.LLVMType*) -> mlirlite.LLVMType*: """直接解析 vpi 返回注解字符串为 LLVMType(不构造 AST 节点)""" - if ret_annot is None or pool is None: - return None + if ret_annot is None or pool is None: return None # tuple[T1, T2, ...] → 匿名结构体 {T1, T2, ...}(多返回值打包, # 与 TypeGenMixin._resolve_generic_subscript_ty 的 tuple 分支一致)。 @@ -1479,10 +1331,8 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, # 返回类型退化 i8* → tuple 解包失效(hqx 段崩溃根因)。 if string.strncmp(ret_annot, "tuple[", 6) == 0: inner_len_t: sizet = 0 - while ret_annot[6 + inner_len_t] != ']' and ret_annot[6 + inner_len_t] != '\0': - inner_len_t += 1 - if ret_annot[6 + inner_len_t] != ']' or inner_len_t == 0: - return None + while ret_annot[6 + inner_len_t] != ']' and ret_annot[6 + inner_len_t] != '\0': inner_len_t += 1 + if ret_annot[6 + inner_len_t] != ']' or inner_len_t == 0: return None # tuple 返回类型的字段链表是 mlirlite.ParamNode(new_param_node / paramnode_set_next / # Struct 形参均为 rawptr[ParamNode])——原先误注解为 Function*。 tup_head_t: mlirlite.ParamNode* = None @@ -1491,36 +1341,27 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, p_t: sizet = 0 while p_t < inner_len_t: # 跳过前导空格/逗号 - while p_t < inner_len_t and (ret_annot[6 + p_t] == ' ' or ret_annot[6 + p_t] == ','): - p_t += 1 + while p_t < inner_len_t and (ret_annot[6 + p_t] == ' ' or ret_annot[6 + p_t] == ','): p_t += 1 seg_s_t: sizet = p_t - while p_t < inner_len_t and ret_annot[6 + p_t] != ',': - p_t += 1 + while p_t < inner_len_t and ret_annot[6 + p_t] != ',': p_t += 1 seg_e_t: sizet = p_t - while seg_e_t > seg_s_t and ret_annot[6 + seg_e_t - 1] == ' ': - seg_e_t -= 1 + while seg_e_t > seg_s_t and ret_annot[6 + seg_e_t - 1] == ' ': seg_e_t -= 1 if seg_e_t > seg_s_t: seg_len_t: sizet = seg_e_t - seg_s_t seg_buf_t: bytes = stdlib.malloc(seg_len_t + 1) - if seg_buf_t is None: - return None + if seg_buf_t is None: return None string.strncpy(seg_buf_t, ret_annot + 6 + seg_s_t, seg_len_t) seg_buf_t[seg_len_t] = '\0' seg_ty_t: mlirlite.LLVMType* = _resolve_single_vpi_type_str(pool, seg_buf_t) stdlib.free(seg_buf_t) - if seg_ty_t is None: - return None + if seg_ty_t is None: return None tup_node_t: mlirlite.ParamNode* = mlirlite.new_param_node(pool, seg_ty_t) - if tup_node_t is None: - return None - if tup_head_t is None: - tup_head_t = tup_node_t - else: - mlirlite.paramnode_set_next(tup_tail_t, tup_node_t) + if tup_node_t is None: return None + if tup_head_t is None: tup_head_t = tup_node_t + else: mlirlite.paramnode_set_next(tup_tail_t, tup_node_t) tup_tail_t = tup_node_t tup_count_t += 1 - if tup_head_t is None: - return None + if tup_head_t is None: return None return mlirlite.Struct(pool, tup_head_t, tup_count_t, None) # 纯 marker 注解(`t.State` / `t.CExtern` / `t.CExport` 单独出现,可带 t./c. @@ -1534,14 +1375,11 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, # 类型,其段循环会以 first_ty 返回真实类型,不得在此误判。 marker_len: sizet = string.strlen(ret_annot) mk_s: sizet = 0 - while mk_s < marker_len and ret_annot[mk_s] == ' ': - mk_s += 1 + while mk_s < marker_len and ret_annot[mk_s] == ' ': mk_s += 1 mk_e: sizet = marker_len - while mk_e > mk_s and ret_annot[mk_e - 1] == ' ': - mk_e -= 1 + while mk_e > mk_s and ret_annot[mk_e - 1] == ' ': mk_e -= 1 mk_off_m: sizet = 0 - if mk_e - mk_s >= 2 and (ret_annot[mk_s] == 't' or ret_annot[mk_s] == 'c') and ret_annot[mk_s + 1] == '.': - mk_off_m = 2 + if mk_e - mk_s >= 2 and (ret_annot[mk_s] == 't' or ret_annot[mk_s] == 'c') and ret_annot[mk_s + 1] == '.': mk_off_m = 2 mk_nlen: sizet = mk_e - mk_s - mk_off_m if (mk_nlen == 5 and string.strncmp(ret_annot + mk_s + mk_off_m, "State", 5) == 0) or (mk_nlen == 7 and string.strncmp(ret_annot + mk_s + mk_off_m, "CExtern", 7) == 0) or (mk_nlen == 7 and string.strncmp(ret_annot + mk_s + mk_off_m, "CExport", 7) == 0): return mlirlite.Void(pool) @@ -1569,8 +1407,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, pos: sizet = 0 while pos <= buf_len: # 跳过前导空格 - while pos < buf_len and ret_annot[pos] == ' ': - pos += 1 + while pos < buf_len and ret_annot[pos] == ' ': pos += 1 seg_start: sizet = pos # 只在**顶层**切 `|`:`[...]` 内的 `|` 属于泛型实参内部的联合注解,裸切会把首段 # 截成 `list[ast.AST`(来自 `list[ast.AST*] | t.CPtr`),该段再经 @@ -1580,24 +1417,19 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, depth_ra: int = 0 while pos < buf_len: ch_ra: char = ret_annot[pos] - if ch_ra == '[': - depth_ra += 1 + if ch_ra == '[': depth_ra += 1 elif ch_ra == ']': - if depth_ra > 0: - depth_ra -= 1 + if depth_ra > 0: depth_ra -= 1 elif ch_ra == '|': - if depth_ra == 0: - break + if depth_ra == 0: break pos += 1 seg_end: sizet = pos # trim 尾随空格 - while seg_end > seg_start and ret_annot[seg_end - 1] == ' ': - seg_end -= 1 + while seg_end > seg_start and ret_annot[seg_end - 1] == ' ': seg_end -= 1 if seg_end > seg_start: seg_len2: sizet = seg_end - seg_start seg_buf: bytes = stdlib.malloc(seg_len2 + 1) - if seg_buf is None: - break + if seg_buf is None: break string.strncpy(seg_buf, ret_annot + seg_start, seg_len2) seg_buf[seg_len2] = '\0' # CPtr 下标段(t.CPtr[T]/c.CPtr[T],含嵌套如 t.CPtr[t.CPtr]): @@ -1628,8 +1460,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, if lvl_cs > cptr_sub_lvl: cptr_sub_lvl = lvl_cs cptr_sub_ty = seg_ty_cs - elif string.strcmp(seg_buf, "t.CPtr") == 0 or string.strcmp(seg_buf, "CPtr") == 0: - has_cptr = 1 + elif string.strcmp(seg_buf, "t.CPtr") == 0 or string.strcmp(seg_buf, "CPtr") == 0: has_cptr = 1 elif string.strcmp(seg_buf, "void") == 0 or string.strcmp(seg_buf, "CVoid") == 0 or string.strcmp(seg_buf, "void") == 0: # 裸名 void 是 t.CVoid 的别名(用户 2026-10-01):必须与 CVoid 同处理, # 否则会走 else 分支取到 first_td=1 → Ptr(Void) 这种非法类型 @@ -1643,8 +1474,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, # 对**裸名** pointee 仅在它解析为已注册结构体、泛型参数名或白名单 # 裸标量时才保留 pointee,否则联合坍缩为 i8*;stub 侧此前无条件 # Ptr(first_ty) → `uint64*` 两侧不一致(定义 i8* vs declare i64*)。 - if string.strchr(seg_buf, 46) is not None: - first_qual = 1 + if string.strchr(seg_buf, 46) is not None: first_qual = 1 if string.strcmp(seg_buf, "int") == 0 or string.strcmp(seg_buf, "char") == 0 or string.strcmp(seg_buf, "str") == 0 or string.strcmp(seg_buf, "bytes") == 0 or string.strcmp(seg_buf, "bool") == 0 or string.strcmp(seg_buf, "float") == 0 or string.strcmp(seg_buf, "double") == 0: first_wl = 1 # 裸名 typedef 别名保真(N13,与定义侧同源):sizet/uint64/INT/u32 等别名若被判「非 struct 且不在白名单」会被坍缩成 i8*, @@ -1652,14 +1482,12 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, # 仅对**非指针**解析结果置位(指针别名 BYTEPTR/HANDLE/VOIDPTR 不置位 → 仍坍缩 i8*,与定义侧守卫对称)。 if first_qual == 0 and first_wl == 0: if first_ty.kind() != mlirlite.LLVMType.Ptr: - if GenApi.resolve_typedef_or_map(pool, seg_buf, None, None) is not None: - first_td = 1 + if GenApi.resolve_typedef_or_map(pool, seg_buf, None, None) is not None: first_td = 1 stdlib.free(seg_buf) pos += 1 # 跳过 '|' if has_cptr != 0: - if has_cvoid != 0: - return i8_ptr_ty + if has_cvoid != 0: return i8_ptr_ty if first_ty is not None: # 解析结果本身即 void(如 `typedef 不透明结构体 = void` 的名字经 typedef 兜底 # 解析出 void)⇒ 与 t.CPtr 合并即 void* = i8*,与 has_cvoid 分支同结论 @@ -1673,10 +1501,8 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, # 其余(解析失败、裸枚举名、指针别名)→ 联合坍缩为 i8*,与定义侧 resolve_annotation_type 对称(两侧同型即收敛)。 # 指针别名(first_td 不置位,如 VOIDPTR = CVoid* → i8*):`| t.CPtr` # **恒追加恰好 1 层** → i8**(不吸收);指针型 T 同理(见下)。 - if first_qual != 0 or first_wl != 0 or first_td != 0: - return mlirlite.Ptr(pool, first_ty) - if first_ty.kind() == mlirlite.LLVMType.Struct: - return mlirlite.Ptr(pool, first_ty) + if first_qual != 0 or first_wl != 0 or first_td != 0: return mlirlite.Ptr(pool, first_ty) + if first_ty.kind() == mlirlite.LLVMType.Struct: return mlirlite.Ptr(pool, first_ty) if first_ty.kind() == mlirlite.LLVMType.Ptr: # `| t.CPtr` **恒追加恰好 1 层**(与定义侧 TypeGenResolve 的 BinOp 分支同口径): # 这里原先还做"pointee 命中 find_struct_by_type(类引用语义)就吸收 1 层", @@ -1690,8 +1516,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, # CPtr 下标段联合合并(与定义侧同口径):有另一侧基类型 first_ty → 结果 = Ptr^N(first_ty)(N=cptr_sub_lvl);仅 CPtr 下标段自身 → 该段解析类型本身。 # 下标段无 struct 吸收,不与上方 has_cptr 分支的吸收判据混用;has_cptr 在上一分支已全部返回,二者不叠加。 if cptr_sub_lvl > 0: - if first_ty is None: - return cptr_sub_ty + if first_ty is None: return cptr_sub_ty res_ty_cs: mlirlite.LLVMType* = first_ty wrap_i_cs: int = 0 while wrap_i_cs < cptr_sub_lvl: @@ -1703,8 +1528,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, # 此前缺此分支 → first_ty=None → 返回 None → 跨模块函数返回类型 # fail-fast(CPythonTest Py_Initialize() -> t\.CVoid | t.State 根因)。 return mlirlite.Void(pool) - if first_ty is not None: - return first_ty + if first_ty is not None: return first_ty return None @@ -1736,8 +1560,7 @@ SHA1_HEX_LEN: sizet = 16 # ============================================================ def _extract_sha1_from_path(vpi_path: str) -> str: """从 .vpi 文件路径提取 SHA1(文件名前16字符,malloc 分配)""" - if vpi_path is None: - return None + if vpi_path is None: return None # 查找最后一个路径分隔符 / 或 \ total_len: sizet = string.strlen(vpi_path) if total_len < SHA1_HEX_LEN + 4: # 至少需要 "xxxx.vpi" 的长度 @@ -1750,12 +1573,10 @@ def _extract_sha1_from_path(vpi_path: str) -> str: if ch == '/' or ch == '\\': sep_pos += 1 break - if sep_pos + SHA1_HEX_LEN > total_len: - return None + if sep_pos + SHA1_HEX_LEN > total_len: return None # 分配缓冲区并复制 SHA1(16 字符 + null 终止符) sha1_buf: str = stdlib.malloc(SHA1_HEX_LEN + 1) - if sha1_buf is None: - return None + if sha1_buf is None: return None string.strncpy(sha1_buf, vpi_path + sep_pos, SHA1_HEX_LEN) sha1_buf[SHA1_HEX_LEN] = '\0' return sha1_buf @@ -1806,22 +1627,18 @@ def ResetVpiTypedefVisited() -> None: def _vpi_typedef_visited_check(sha1: str) -> int: """检查 sha1 是否已递归注册过(1=已处理,0=未处理;纯查询不标记)""" global _g_vpi_typedef_visited, _g_vpi_typedef_visited_count - if sha1 is None: - return 1 - if _g_vpi_typedef_visited is None: - return 0 + if sha1 is None: return 1 + if _g_vpi_typedef_visited is None: return 0 vi: int for vi in range(_g_vpi_typedef_visited_count): - if string.strcmp(_g_vpi_typedef_visited + vi * 17, sha1) == 0: - return 1 + if string.strcmp(_g_vpi_typedef_visited + vi * 17, sha1) == 0: return 1 return 0 def _vpi_typedef_visited_mark(sha1: str) -> None: """标记 sha1 为已递归注册(成功后调用,防环)""" global _g_vpi_typedef_visited, _g_vpi_typedef_visited_count, _g_vpi_typedef_visited_cap - if sha1 is None: - return + if sha1 is None: return if _g_vpi_typedef_visited is None: _g_vpi_typedef_visited = stdlib.malloc(_TYPEDEF_VISIT_MAX * 17) if _g_vpi_typedef_visited is None: @@ -1860,44 +1677,33 @@ def _vpi_register_typedef_closure(pool: memhub.MemBuddy*, 传递依赖的函数表膨胀)。vpi 文件缺失(Phase A 早期 stub 未生成)时 静默跳过,Phase 2 stub 就绪后自然命中。 """ - if pool is None or import_mods is None or temp_dir is None: - return 0 - if depth > 8: - return 0 + if pool is None or import_mods is None or temp_dir is None: return 0 + if depth > 8: return 0 td_len: sizet = string.strlen(temp_dir) total_len: sizet = string.strlen(import_mods) pos: sizet = 0 while pos < total_len: - while pos < total_len and import_mods[pos] == ' ': - pos += 1 - if pos >= total_len: - break + while pos < total_len and import_mods[pos] == ' ': pos += 1 + if pos >= total_len: break m_start: sizet = pos - while pos < total_len and import_mods[pos] != ' ': - pos += 1 + while pos < total_len and import_mods[pos] != ' ': pos += 1 m_len: sizet = pos - m_start - if m_len == 0: - continue + if m_len == 0: continue # t/c 内建库不编译,无 vpi stub - if m_len == 1 and (import_mods[m_start] == 't' or import_mods[m_start] == 'c'): - continue + if m_len == 1 and (import_mods[m_start] == 't' or import_mods[m_start] == 'c'): continue mod_buf: bytes = stdlib.malloc(m_len + 1) - if mod_buf is None: - continue + if mod_buf is None: continue string.strncpy(mod_buf, import_mods + m_start, m_len) mod_buf[m_len] = '\0' sha1_r: str = StubMergerStore.LookupSha1ByModName(mod_buf) stdlib.free(mod_buf) - if sha1_r is None: - continue - if _vpi_typedef_visited_check(sha1_r) != 0: - continue + if sha1_r is None: continue + if _vpi_typedef_visited_check(sha1_r) != 0: continue # 构造 {temp_dir}/{sha1[0:2]}/{sha1}.vpi(手写拼接,与 # _ensure_vpi_ret_annot_loaded 一致,避免引入 StubMergerCollect 环依赖) path_len_r: sizet = td_len + 16 + 12 vpi_path_r: bytes = stdlib.malloc(path_len_r) - if vpi_path_r is None: - continue + if vpi_path_r is None: continue string.strcpy(vpi_path_r, temp_dir) vpi_path_r[td_len] = '/' vpi_path_r[td_len + 1] = sha1_r[0] @@ -1920,8 +1726,7 @@ def _vpi_register_typedef_closure(pool: memhub.MemBuddy*, # 成功读到 vpi 才标记已处理(文件缺失/读取失败不标记, # 后续 pass 的 stub 注入可重试) _vpi_typedef_visited_mark(sha1_r) - if bytes_read_r < VPI_READ_BUF_SIZE: - vpi_buf_r[bytes_read_r] = 0 + if bytes_read_r < VPI_READ_BUF_SIZE: vpi_buf_r[bytes_read_r] = 0 lx_r: ast.Lexer* = ast.new_lexer(pool) if lx_r is not None: ast._lexer_init(lx_r, vpi_buf_r, pool) @@ -1937,8 +1742,7 @@ def _vpi_register_typedef_closure(pool: memhub.MemBuddy*, ci_c: sizet for ci_c in range(cn_r): child_c: ast.AST* = ch_r.get(ci_c) - if child_c is None: - continue + if child_c is None: continue kk_c: int = child_c.kind() if kk_c == ast.ASTKind.Import: imp_c: ast.Import* = ast.Import*(child_c) @@ -1946,12 +1750,10 @@ def _vpi_register_typedef_closure(pool: memhub.MemBuddy*, in_nc: sizet = len(imp_c.names) for ii_c in range(in_nc): al_c: ast.Alias* = ast.Alias*(imp_c.names.get(ii_c)) - if al_c is not None and al_c.name is not None: - sub_need += string.strlen(al_c.name) + 1 + if al_c is not None and al_c.name is not None: sub_need += string.strlen(al_c.name) + 1 elif kk_c == ast.ASTKind.ImportFrom: ifr_c: ast.ImportFrom* = ast.ImportFrom*(child_c) - if ifr_c.module is not None: - sub_need += string.strlen(ifr_c.module) + 1 + if ifr_c.module is not None: sub_need += string.strlen(ifr_c.module) + 1 sub_imports: bytes = stdlib.malloc(sub_need) if sub_imports is not None: sub_imports[0] = '\0' @@ -1959,8 +1761,7 @@ def _vpi_register_typedef_closure(pool: memhub.MemBuddy*, ci_r: sizet for ci_r in range(cn_r): child_r: ast.AST* = ch_r.get(ci_r) - if child_r is None: - continue + if child_r is None: continue kk_r: int = child_r.kind() if kk_r == ast.ASTKind.Import: imp_r: ast.Import* = ast.Import*(child_r) @@ -1991,31 +1792,23 @@ def _vpi_register_typedef_closure(pool: memhub.MemBuddy*, ci2_r: sizet for ci2_r in range(cn_r): child2_r: ast.AST* = ch_r.get(ci2_r) - if child2_r is None: - continue - if child2_r.kind() != ast.ASTKind.AnnAssign: - continue + if child2_r is None: continue + if child2_r.kind() != ast.ASTKind.AnnAssign: continue aa_r: ast.AnnAssign* = ast.AnnAssign*(child2_r) - if aa_r.annotation is None or aa_r.target is None or aa_r.value is None: - continue - if GenApi._is_ctypedef_annotation(aa_r.annotation) != 0: - _register_ctypedef_from_annassign(pool, aa_r) + if aa_r.annotation is None or aa_r.target is None or aa_r.value is None: continue + if GenApi._is_ctypedef_annotation(aa_r.annotation) != 0: _register_ctypedef_from_annassign(pool, aa_r) elif GenApi.is_cdefine_annotation(aa_r.annotation) != 0: - if aa_r.target.kind() != ast.ASTKind.Name: - continue + if aa_r.target.kind() != ast.ASTKind.Name: continue cdef_t: ast.Name* = ast.Name*(aa_r.target) - if cdef_t.id is None: - continue + if cdef_t.id is None: continue if aa_r.value.kind() == ast.ASTKind.Constant: cn_v: ast.Constant* = ast.Constant*(aa_r.value) - if cn_v.const_kind == ast.CONST_FLOAT: - GenApi.register_cdefine_double(pool, cdef_t.id, cn_v.float_val) + if cn_v.const_kind == ast.CONST_FLOAT: GenApi.register_cdefine_double(pool, cdef_t.id, cn_v.float_val) elif cn_v.const_kind == ast.CONST_INT: cdef_val: int64 = GenApi.extract_cdefine_int_value(aa_r.value) GenApi.register_cdefine_constant(pool, cdef_t.id, cdef_val) # 递归处理子模块 imports(防环由 visited 标记保证) - if sub_imports[0] != '\0': - _vpi_register_typedef_closure(pool, sub_imports, temp_dir, depth + 1) + if sub_imports[0] != '\0': _vpi_register_typedef_closure(pool, sub_imports, temp_dir, depth + 1) stdlib.free(sub_imports) stdlib.free(vpi_buf_r) stdlib.free(vpi_path_r) @@ -2042,8 +1835,7 @@ def ParseVpiIntoModule(pool: memhub.MemBuddy*, 注解解析失败时 fatal_error 应指向 stub 及其行号(真实出错位置), 而非当前编译模块(错误归因修复)。 """ - if pool is None or mod is None or vpi_path is None or trans is None: - return 0 + if pool is None or mod is None or vpi_path is None or trans is None: return 0 saved_cur: str = GenApi.get_current_file() GenApi.set_current_file_type(vpi_path) ret: int = _ParseVpiIntoModuleImpl(pool, mod, vpi_path, trans) @@ -2056,13 +1848,11 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, vpi_path: str, trans: HT.Translator*) -> int: """解析 .vpi 文件,将函数声明注入到当前模块(ParseVpiIntoModule 实际实现)""" - if pool is None or mod is None or vpi_path is None or trans is None: - return 0 + if pool is None or mod is None or vpi_path is None or trans is None: return 0 # 1. 读取 .vpi 文件 f: rawptr[fileio.File] = fileio.File(vpi_path, fileio.MODE.R) - if f.closed: - return 0 + if f.closed: return 0 vpi_buf: bytes = stdlib.malloc(VPI_READ_BUF_SIZE) if vpi_buf is None: f.close() @@ -2072,8 +1862,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, if bytes_read <= 0: stdlib.free(vpi_buf) return 0 - if bytes_read < VPI_READ_BUF_SIZE: - vpi_buf[bytes_read] = 0 + if bytes_read < VPI_READ_BUF_SIZE: vpi_buf[bytes_read] = 0 # 2. 解析为 AST lx: ast.Lexer* = ast.new_lexer(pool) @@ -2104,8 +1893,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, # 3. 遍历 AST 顶层节点 ch: list[ast.AST*]* = tree.children if ch is None: - if src_sha1 is not None: - stdlib.free(src_sha1) + if src_sha1 is not None: stdlib.free(src_sha1) return 1 n: sizet = len(ch) @@ -2121,8 +1909,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, stub_ctx: StubMergerStore.ImportCtx* = StubMergerStore.AllocImportCtx(pool, None, None) for si in range(n): schild: ast.AST* = ch.get(si) - if schild is None: - continue + if schild is None: continue sk: int = schild.kind() if sk == ast.ASTKind.Import: simp: ast.Import* = ast.Import*(schild) @@ -2130,8 +1917,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, sn_n: sizet = len(simp.names) for sni in range(sn_n): sal: ast.Alias* = ast.Alias*(simp.names.get(sni)) - if sal is not None and sal.name is not None: - StubMergerStore.NotePlainImport(pool, stub_ctx, sal.name, sal.asname) + if sal is not None and sal.name is not None: StubMergerStore.NotePlainImport(pool, stub_ctx, sal.name, sal.asname) elif sk == ast.ASTKind.ImportFrom: sifr: ast.ImportFrom* = ast.ImportFrom*(schild) sifr_mod: str = sifr.module @@ -2166,8 +1952,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, # 故必须用本 stub 自己的模块名确认,不确认就让位给 rel_path。 _conf_rt: int = 0 if _my_mod_rt is not None and string.strlen(_my_mod_rt) == _pfx_len_rt: - if string.strncmp(_my_mod_rt, _sub_mod_rt, _pfx_len_rt) == 0: - _conf_rt = 1 + if string.strncmp(_my_mod_rt, _sub_mod_rt, _pfx_len_rt) == 0: _conf_rt = 1 if _conf_rt != 0: pkg_prefix_rt = pool.alloc(_pfx_len_rt + 1) if pkg_prefix_rt is not None: @@ -2215,8 +2000,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, # 前缀分裂(现场 ClassGenGeneric.vp:92 的 CastError)。 # 仅当模块名证据不足时才回退旧 rel_path 判定(行为不变)。 is_pkg_init_rt: int = 0 - if pkg_prefix_rt is not None: - is_pkg_init_rt = 1 + if pkg_prefix_rt is not None: is_pkg_init_rt = 1 if is_pkg_init_rt == 0: rel_path_rt: str = StubMergerStore.LookupSha1RelPath(src_sha1) if rel_path_rt is not None: @@ -2225,8 +2009,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, # 长 15,该后缀从索引 4 起(11 字符),len-9=6 指向 "init__.vp" # → 判定恒 false → 包重导出永不触发(ast.Attribute 未注册根因之一)。 # 改用 strstr 判定 rel_path 包含 "__init__.vp"(仅包 __init__ 文件命中)。 - if string.strstr(rel_path_rt, "__init__.vp") is not None: - is_pkg_init_rt = 1 + if string.strstr(rel_path_rt, "__init__.vp") is not None: is_pkg_init_rt = 1 # 解析被 from-import 的模块 sha1:相对导入按 parser 表示判定—— # 前导点存于 level(from .exprs import → level=1, module="exprs", # 见 includes/ast/stmts.vp ImportFrom.level / parser.vp _parse_from_import), @@ -2240,10 +2023,8 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, # 后缀匹配只作旧行为兜底:后缀命中可能落到别的同后缀模块, # 而下面的按需注入会按该 sha1 拉 vpi,注入错模块代价大。 sub_sha1_rt = StubMergerStore.LookupSha1ByModName(sifr_mod_q) - if sub_sha1_rt is None: - sub_sha1_rt = StubMergerStore.LookupSha1ByModNameSuffix(sifr_mod) - else: - sub_sha1_rt = StubMergerStore.LookupSha1ByModName(sifr_mod) + if sub_sha1_rt is None: sub_sha1_rt = StubMergerStore.LookupSha1ByModNameSuffix(sifr_mod) + else: sub_sha1_rt = StubMergerStore.LookupSha1ByModName(sifr_mod) # [D26 fail-fast] 包 __init__ 的 from-import 解析不出子模块 sha1 时 # **不再静默跳过**:跳过会让该子模块的类一个都注册不上 → 包 stub 里 # 引用这些类的注解在后续解析时落空 → 报错点远离真因(实测:报错指向 @@ -2291,10 +2072,8 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, stub_from_imports = stub_ctx.FromImports imported_modules: str = trans._imported_modules from_imports: str = trans._from_imports - if stub_imported_modules is not None: - imported_modules = stub_imported_modules - if stub_from_imports is not None: - from_imports = stub_from_imports + if stub_imported_modules is not None: imported_modules = stub_imported_modules + if stub_from_imports is not None: from_imports = stub_from_imports # 把源模块自己加入 stub 注解上下文:stub 注解(如 __sha512 的 transform # 参数 t.CArray[uint8, SHA512_BLOCK_LEN])引用源模块自身的 CDefine, # 但 stub 的 import 只含被 import 的模块(t/c/string),不含自己。 @@ -2305,18 +2084,15 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, stub_rel_src: str = StubMergerStore.LookupSha1RelPath(src_sha1) if stub_rel_src is not None: sr_len_src: sizet = string.strlen(stub_rel_src) - if sr_len_src > 3 and string.strncmp(stub_rel_src + sr_len_src - 3, ".vp", 3) == 0: - sr_len_src -= 3 + if sr_len_src > 3 and string.strncmp(stub_rel_src + sr_len_src - 3, ".vp", 3) == 0: sr_len_src -= 3 if sr_len_src > 0: src_mod_buf: str = stdlib.malloc(sr_len_src + 1) if src_mod_buf is not None: sri_src: sizet for sri_src in range(sr_len_src): ch_src: char = stub_rel_src[sri_src] - if ch_src == '/' or ch_src == '\\': - src_mod_buf[sri_src] = '.' - else: - src_mod_buf[sri_src] = ch_src + if ch_src == '/' or ch_src == '\\': src_mod_buf[sri_src] = '.' + else: src_mod_buf[sri_src] = ch_src src_mod_buf[sr_len_src] = '\0' imported_modules = StubMergerStore.AppendImportedModule( pool, imported_modules, src_mod_buf) @@ -2326,8 +2102,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, # UINT)的 typedef 定义在 stdint.vp,但 CTypedef 表每文件隔离——当前 # 模块未直接 import stdint 时表里没有 UINT → 参数类型退化为 i8_ptr_ty # → 调用侧整数实参误报 CastError(testcheck.SetConsoleOutputCP 根因)。 - if imported_modules is not None: - _vpi_register_typedef_closure(pool, imported_modules, GenApi.get_temp_dir(), 0) + if imported_modules is not None: _vpi_register_typedef_closure(pool, imported_modules, GenApi.get_temp_dir(), 0) i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) @@ -2355,19 +2130,15 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, i0: sizet for i0 in range(n): child0: ast.AST* = ch.get(i0) - if child0 is None: - continue - if child0.kind() != ast.ASTKind.ClassDef: - continue + if child0 is None: continue + if child0.kind() != ast.ASTKind.ClassDef: continue class_cd0: ast.ClassDef* = ast.ClassDef*(child0) - if class_cd0 is None or class_cd0.name is None: - continue + if class_cd0 is None or class_cd0.name is None: continue cls_name_v0: str = class_cd0.name # 泛型类(class X[T])跳过:stub 模板签名含类级类型参数 T,注入时 # T 无法确定;特化方法 define 已在 Phase1 生成,无需 stub 模板 declare。 tp_stub0: list[str]* = class_cd0.type_params - if tp_stub0 is not None and len(tp_stub0) > 0: - continue + if tp_stub0 is not None and len(tp_stub0) > 0: continue _inject_class_struct_declare(pool, mod, class_cd0, cls_name_v0, trans, src_sha1, imported_modules, from_imports) @@ -2382,8 +2153,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, # 结构体因字段引用尚未注册的 GenTypes 类而本遍未登记)。 # 全量翻译(_declare_only==0,_pre_allow_dep_inject==0)不跳过,仍 fail-fast。 pre_skip_fn_declares: int = 0 - if trans is not None and trans._pre_allow_dep_inject != 0: - pre_skip_fn_declares = 1 + if trans is not None and trans._pre_allow_dep_inject != 0: pre_skip_fn_declares = 1 # ============================================================ # 第一遍 B:**全部类注册完成之后**再处理方法 declare——方法形参/返回值可能引用本文件更靠后定义的类(类间前向引用), @@ -2391,31 +2161,23 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, # ============================================================ for i1 in range(n): child1: ast.AST* = ch.get(i1) - if child1 is None: - continue - if child1.kind() != ast.ASTKind.ClassDef: - continue + if child1 is None: continue + if child1.kind() != ast.ASTKind.ClassDef: continue class_cd1: ast.ClassDef* = ast.ClassDef*(child1) - if class_cd1 is None or class_cd1.name is None: - continue + if class_cd1 is None or class_cd1.name is None: continue cls_name_v1: str = class_cd1.name # 泛型类跳过(与第一遍 A 同判据) tp_stub1: list[str]* = class_cd1.type_params - if tp_stub1 is not None and len(tp_stub1) > 0: - continue + if tp_stub1 is not None and len(tp_stub1) > 0: continue cls_children1: list[ast.AST*]* = class_cd1.children - if cls_children1 is None: - continue + if cls_children1 is None: continue cn21: sizet = len(cls_children1) for ci21 in range(cn21): m_child1: ast.AST* = cls_children1.get(ci21) - if m_child1 is None: - continue - if m_child1.kind() != ast.ASTKind.FunctionDef: - continue + if m_child1 is None: continue + if m_child1.kind() != ast.ASTKind.FunctionDef: continue m_fd1: ast.FunctionDef* = ast.FunctionDef*(m_child1) - if m_fd1 is None or m_fd1.name is None: - continue + if m_fd1 is None or m_fd1.name is None: continue # App 预注册跳过方法 declare(原因见上方 pre_skip_fn_declares 注释)。 if pre_skip_fn_declares == 0: _inject_method_declare(pool, mod, m_fd1, cls_name_v1, trans, @@ -2425,21 +2187,18 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, i: sizet for i in range(n): child: ast.AST* = ch.get(i) - if child is None: - continue + if child is None: continue kd: int = child.kind() # FunctionDef → 提取函数名、参数、返回类型 → 注入 declare if kd == ast.ASTKind.FunctionDef: fd: ast.FunctionDef* = ast.FunctionDef*(child) - if fd is None or fd.name is None: - continue + if fd is None or fd.name is None: continue # App 预注册跳过函数 declare(原因见上方 pre_skip_fn_declares 注释): # 其形参/返回注解可能引用本遍尚未注册的类,resolve 落空会 fail-fast # 打断多遍收敛(现场 Translator.vpi 的 InjectTracebackInstallCtor # 形参 rawptr[Translator])。 - if pre_skip_fn_declares != 0: - continue + if pre_skip_fn_declares != 0: continue _inject_function_declare(pool, mod, fd, trans, src_sha1, imported_modules, from_imports, i32_ty, i8_ptr_ty, @@ -2450,16 +2209,14 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, # 普通模块级全局变量(如 tokens._op_head)→ external global declare if kd == ast.ASTKind.AnnAssign: aa: ast.AnnAssign* = ast.AnnAssign*(child) - if aa is None: - continue + if aa is None: continue if aa.target is not None and aa.target.kind() == ast.ASTKind.Name: dbg_tn: ast.Name* = ast.Name*(aa.target) if dbg_tn.id is not None and dbg_tn.id[0] != '\0': # 存疑 if string.strcmp(dbg_tn.id, "irq_handler_t") == 0 or string.strcmp(dbg_tn.id, "gdt") == 0 or string.strcmp(dbg_tn.id, "KBD_BUF_SIZE") == 0: dbg_ct: int = GenApi._is_ctypedef_annotation(aa.annotation) dbg_cd: int = GenApi.is_cdefine_annotation(aa.annotation) - if GenApi._is_ctypedef_annotation(aa.annotation) != 0: - _register_ctypedef_from_annassign(pool, aa) + if GenApi._is_ctypedef_annotation(aa.annotation) != 0: _register_ctypedef_from_annassign(pool, aa) elif GenApi.is_cdefine_annotation(aa.annotation) != 0: # vpi 里 CDefine 定义(如 keyboard.vp 的 KBD_BUF_SIZE: t.CDefine = 1024) # 注册到当前文件 CDefine 表,供同 vpi 后续 t.CArray count 引用解析 @@ -2474,8 +2231,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, cdef_float_val: double = 0.0 if aa.value.kind() == ast.ASTKind.Constant: cn_v: ast.Constant* = ast.Constant*(aa.value) - if cn_v.const_kind == ast.CONST_STR: - cdef_is_str = 1 + if cn_v.const_kind == ast.CONST_STR: cdef_is_str = 1 elif cn_v.const_kind == ast.CONST_FLOAT: cdef_is_float = 1 cdef_float_val = cn_v.float_val @@ -2500,8 +2256,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, # (import 不需要处理) # 释放 SHA1 缓冲区(_extract_sha1_from_path 用 stdlib.malloc 分配) - if src_sha1 is not None: - stdlib.free(src_sha1) + if src_sha1 is not None: stdlib.free(src_sha1) # vpi_buf 延迟到全部 tree 处理完成后释放(见解析处注释) stdlib.free(vpi_buf) return 1 @@ -2542,40 +2297,30 @@ def _ensure_dep_vpi_injected(pool: memhub.MemBuddy*, trans: HT.Translator*) -> int: """按需注入 dep_sha1 对应的 .vpi 到当前模块(防重入),1=就绪 / 0=失败""" global _vpi_inj_sha1s, _vpi_inj_count, _vpi_inj_depth - if pool is None or mod is None or dep_sha1 is None or trans is None: - return 0 - if dep_sha1[0] == '\0': - return 0 + if pool is None or mod is None or dep_sha1 is None or trans is None: return 0 + if dep_sha1[0] == '\0': return 0 if _vpi_inj_sha1s is None: _vpi_inj_sha1s = stdlib.malloc(VPI_INJ_MAX * 17) - if _vpi_inj_sha1s is None: - return 0 + if _vpi_inj_sha1s is None: return 0 string.memset(_vpi_inj_sha1s, 0, VPI_INJ_MAX * 17) _vpi_inj_count = 0 # 已注入过 / 正在注入(环)→ 视为就绪,直接短路 ii: int for ii in range(_vpi_inj_count): - if string.strcmp(_vpi_inj_sha1s + sizet(ii) * 17, dep_sha1) == 0: - return 1 - if _vpi_inj_count >= VPI_INJ_MAX or _vpi_inj_depth >= 32: - return 0 + if string.strcmp(_vpi_inj_sha1s + sizet(ii) * 17, dep_sha1) == 0: return 1 + if _vpi_inj_count >= VPI_INJ_MAX or _vpi_inj_depth >= 32: return 0 temp_dir: str = GenApi.get_temp_dir() - if temp_dir is None: - return 0 + if temp_dir is None: return 0 td_len_i: sizet = string.strlen(temp_dir) sh_len_i: sizet = string.strlen(dep_sha1) sub_i: str = Config.slice_subdir(dep_sha1, Config.Sha1SliceLevel) sub_len_i: sizet = 0 - if sub_i is not None: - sub_len_i = string.strlen(sub_i) + if sub_i is not None: sub_len_i = string.strlen(sub_i) path_len_i: sizet = td_len_i + sub_len_i + sh_len_i + 8 path_i: bytes = stdlib.malloc(path_len_i) - if path_i is None: - return 0 - if sub_len_i > 0: - viperlib.snprintf(path_i, path_len_i, "%s/%s/%s.vpi", temp_dir, sub_i, dep_sha1) - else: - viperlib.snprintf(path_i, path_len_i, "%s/%s.vpi", temp_dir, dep_sha1) + if path_i is None: return 0 + if sub_len_i > 0: viperlib.snprintf(path_i, path_len_i, "%s/%s/%s.vpi", temp_dir, sub_i, dep_sha1) + else: viperlib.snprintf(path_i, path_len_i, "%s/%s.vpi", temp_dir, dep_sha1) vf_i: rawptr[fileio.File] = fileio.File(path_i, fileio.MODE.R) if vf_i.closed: stdlib.free(path_i) @@ -2619,28 +2364,21 @@ def _inject_reexport_class_declare(pool: memhub.MemBuddy*, pkg_sha1: str, trans: HT.Translator*) -> int: """把包子模块重导出的类以包 sha1 注册别名 entry(方案A:ast.Attribute 归属 ast 包)""" - if pool is None or mod is None or src_name is None or local_name is None: - return 0 - if sub_sha1 is None or sub_sha1[0] == '\0' or pkg_sha1 is None or pkg_sha1[0] == '\0': - return 0 - if src_name[0] == '\0' or local_name[0] == '\0': - return 0 + if pool is None or mod is None or src_name is None or local_name is None: return 0 + if sub_sha1 is None or sub_sha1[0] == '\0' or pkg_sha1 is None or pkg_sha1[0] == '\0': return 0 + if src_name[0] == '\0' or local_name[0] == '\0': return 0 # 幂等:包 sha1 下 local_name 已注册则跳过(重复 import 不重复注册) - if GenApi.find_struct_by_module(local_name, pkg_sha1) is not None: - return 1 + if GenApi.find_struct_by_module(local_name, pkg_sha1) is not None: return 1 # 找子模块源 entry(仅类有 entry;函数/常量查不到自然跳过) src_entry: GenTypes.StructEntry* = GenApi.find_struct_by_module(src_name, sub_sha1) if src_entry is None or src_entry.Ty is None: # 源模块 stub 尚未注入(包 __init__ 与子模块互相等待,见 # _ensure_dep_vpi_injected 顶部说明):按需注入 sub_sha1 的 vpi 后 # 重试一次。失败照原逻辑跳过(不把可恢复问题升级为 fatal)。 - if _ensure_dep_vpi_injected(pool, mod, sub_sha1, trans) != 0: - src_entry = GenApi.find_struct_by_module(src_name, sub_sha1) - if src_entry is None or src_entry.Ty is None: - return 0 + if _ensure_dep_vpi_injected(pool, mod, sub_sha1, trans) != 0: src_entry = GenApi.find_struct_by_module(src_name, sub_sha1) + if src_entry is None or src_entry.Ty is None: return 0 # 注册别名 entry(绕过 register_struct 的 Ty 去重) - if GenApi.register_struct_alias(pool, local_name, pkg_sha1, src_entry) is None: - return 0 + if GenApi.register_struct_alias(pool, local_name, pkg_sha1, src_entry) is None: return 0 GenApi.add_visible_struct(pool, local_name) return 1 @@ -2654,49 +2392,38 @@ def _inject_reexport_class_declare(pool: memhub.MemBuddy*, # ============================================================ def _vpi_tattr_name(node: ast.AST*, attr_name: str) -> int: """从 t.attr. / t.attr.(args) 提取最外层属性名并比较""" - if node is None: - return 0 + if node is None: return 0 if node.kind() == ast.ASTKind.Call: cl2: ast.Call* = ast.Call*(node) - if cl2.func is None: - return 0 + if cl2.func is None: return 0 return _vpi_tattr_name(cl2.func, attr_name) if node.kind() == ast.ASTKind.Attribute: at2: ast.Attribute* = ast.Attribute*(node) - if at2.attr is None: - return 0 + if at2.attr is None: return 0 return 1 if string.strcmp(at2.attr, attr_name) == 0 else 0 return 0 def _vpi_class_has_packed(decorator_list: list[ast.AST*]*) -> int: """检查 vpi ClassDef 装饰器列表是否含 t.attr.packed""" - if decorator_list is None: - return 0 + if decorator_list is None: return 0 dn: sizet = len(decorator_list) - if dn == 0: - return 0 + if dn == 0: return 0 for di in range(dn): deco: ast.AST* = decorator_list.get(di) - if deco is None: - continue + if deco is None: continue if deco.kind() == ast.ASTKind.Call: cl: ast.Call* = ast.Call*(deco) - if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute: - continue + if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute: continue at0: ast.Attribute* = ast.Attribute*(cl.func) - if at0.attr is None or string.strcmp(at0.attr, "Attribute") != 0: - continue - if cl.args is None: - continue + if at0.attr is None or string.strcmp(at0.attr, "Attribute") != 0: continue + if cl.args is None: continue an: sizet = len(cl.args) for ai in range(an): ag: ast.AST* = cl.args.get(ai) - if ag is not None and _vpi_tattr_name(ag, "packed") != 0: - return 1 + if ag is not None and _vpi_tattr_name(ag, "packed") != 0: return 1 else: - if _vpi_tattr_name(deco, "packed") != 0: - return 1 + if _vpi_tattr_name(deco, "packed") != 0: return 1 return 0 @@ -2708,25 +2435,21 @@ def _vpi_class_is_renum(class_cd: ast.ClassDef*) -> int: _translate_renum_def 在正式翻译时按变体计算;vpi 侧按普通 struct 注册 会得到错误布局(变体字段都在嵌套类里,直接 AnnAssign 扫描得到 0 字段)。 """ - if class_cd is None or class_cd.bases is None: - return 0 + if class_cd is None or class_cd.bases is None: return 0 bases: list[ast.AST*]* = class_cd.bases bn: sizet = len(bases) for bi in range(bn): base_node: ast.AST* = bases.get(bi) - if base_node is None: - continue + if base_node is None: continue bk: int = base_node.kind() # Attribute(t.REnum) 形式 if bk == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(base_node) - if at.attr is not None and string.strcmp(at.attr, "REnum") == 0: - return 1 + if at.attr is not None and string.strcmp(at.attr, "REnum") == 0: return 1 # Name(REnum) 形式(from t import REnum) elif bk == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(base_node) - if nm.id is not None and string.strcmp(nm.id, "REnum") == 0: - return 1 + if nm.id is not None and string.strcmp(nm.id, "REnum") == 0: return 1 return 0 @@ -2754,8 +2477,7 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*, `{prefix}_{cls_name}`(多层嵌套自然递归为 A_B_C)——与定义端 ClassGenDef._translate_nested_classdefs 的命名口径逐字一致。 """ - if pool is None or mod is None or class_cd is None or cls_name is None: - return 0 + if pool is None or mod is None or class_cd is None or cls_name is None: return 0 # 扁平名(嵌套类):`{外类}_{内类}`。父类未注册时也照常登记(本函数自带 # "字段解析失败即不注册"的既有口径,交给多遍收敛)。 real_name: str = cls_name @@ -2777,10 +2499,8 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*, se: rawptr[ReplStubClass] = _repl_stub_find( _repl_stub_key(pool, src_sha1, real_name)) if se is not None and se.State != _REPL_SS_EMPTY: - if se.State == _REPL_SS_PENDING: - _repl_stub_try(se, mod) - if se.State == _REPL_SS_OK: - GenApi.add_visible_struct(pool, real_name) + if se.State == _REPL_SS_PENDING: _repl_stub_try(se, mod) + if se.State == _REPL_SS_OK: GenApi.add_visible_struct(pool, real_name) return 1 # 1. 已注册检查(含源模块编译时注册的 entry):仅标记可见,避免重复注册。 # 例外:**前向声明占位**(IsForwardDecl != 0)不早退——必须走下方注册路径, @@ -2791,8 +2511,7 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*, if src_sha1 is not None and src_sha1[0] != '\0': existing_c = GenApi.find_struct_by_module(real_name, src_sha1) if existing_c is not None and existing_c.Ty is not None: - if existing_c.IsForwardDecl != 0: - fill_fwd_c = 1 + if existing_c.IsForwardDecl != 0: fill_fwd_c = 1 else: GenApi.add_visible_struct(pool, real_name) return 1 @@ -2801,8 +2520,7 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*, # 会得到错误布局(变体字段都在嵌套类里,直接 AnnAssign 扫描得 0 字段)。 # 留给源模块正式翻译注册。LLVMType 本就因 field_count==0 早退,此守卫把 # 该行为显式化,避免将来 REnum 带直接字段时被误注册为普通 struct。 - if _vpi_class_is_renum(class_cd) != 0: - return 0 + if _vpi_class_is_renum(class_cd) != 0: return 0 # 规则 5.5 的证据前置(**必须早于**下方字段注解解析): # 本函数在**注入期**解析字段注解(GenApi.resolve_annotation_type → # _norm_type_arg_name),此刻被注入的类尚未 register_struct,且注入期**没有 @@ -2832,8 +2550,7 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*, # 2. 收集字段类型(AnnAssign 子节点,仿 ClassGenDef.translate_class_def) field_names_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX) field_types_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX) - if field_names_buf is None or field_types_buf is None: - return 0 + if field_names_buf is None or field_types_buf is None: return 0 string.memset(field_names_buf, 0, 8 * GenTypes.FIELD_MAX) string.memset(field_types_buf, 0, 8 * GenTypes.FIELD_MAX) field_count: int = 0 @@ -2842,18 +2559,13 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*, cn_c: sizet = len(cls_children_c) for ci_c in range(cn_c): m_child_c: ast.AST* = cls_children_c.get(ci_c) - if m_child_c is None: - continue - if m_child_c.kind() != ast.ASTKind.AnnAssign: - continue + if m_child_c is None: continue + if m_child_c.kind() != ast.ASTKind.AnnAssign: continue m_aa_c: ast.AnnAssign* = ast.AnnAssign*(m_child_c) - if m_aa_c is None or m_aa_c.target is None: - continue - if m_aa_c.target.kind() != ast.ASTKind.Name: - continue + if m_aa_c is None or m_aa_c.target is None: continue + if m_aa_c.target.kind() != ast.ASTKind.Name: continue m_tgt_c: ast.Name* = ast.Name*(m_aa_c.target) - if m_tgt_c.id is None: - continue + if m_tgt_c.id is None: continue field_ty_c: mlirlite.LLVMType* = GenApi.resolve_annotation_type( pool, m_aa_c.annotation, imported_modules, from_imports, trans, 0) if field_ty_c is None: @@ -2865,22 +2577,18 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*, field_count += 1 # 3. vpi 存根不含类字段(只序列化 class 名 + def 签名)→ field_count 恒为 0;注册空类会让源模块编译时 find_struct_by_module 命中空类 # → "结构体已注册但字段数为0" InternalCompilerError。故改为不注册:依赖模块已编译时命中真实类(上方已处理),未编译时由 _deps_pending 多遍收敛。 - if field_count == 0: - return 0 + if field_count == 0: return 0 # 4. 构建 ParamNode 链表 first_node_c: rawptr[mlirlite.ParamNode] = None prev_node_c: rawptr[mlirlite.ParamNode] = None for fi_c in range(field_count): fty_c: mlirlite.LLVMType* = (mlirlite.LLVMType*)(field_types_buf[fi_c]) pnode_c: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__()) - if pnode_c is None: - continue + if pnode_c is None: continue string.memset(pnode_c, 0, mlirlite.ParamNode.__sizeof__()) pnode_c.Ty = fty_c - if first_node_c is None: - first_node_c = pnode_c - if prev_node_c is not None: - prev_node_c.Next = pnode_c + if first_node_c is None: first_node_c = pnode_c + if prev_node_c is not None: prev_node_c.Next = pnode_c prev_node_c = pnode_c # 4. 命名结构体类型名 "sha1.ClassName"(与定义侧 ClassGenDef 一致)。 # 嵌套类用扁平名 real_name(`外类_内类`),与定义端 @@ -2901,15 +2609,13 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*, type_name_c = name_buf_c struct_ty_c: mlirlite.LLVMType* = mlirlite.Struct( pool, first_node_c, field_count, type_name_c) - if struct_ty_c is None: - return 0 + if struct_ty_c is None: return 0 # 5. StdlibAlloc(Phase B)时深拷贝到 perm_pool,跨文件 reset 存活 # (对齐 ClassGenDef.translate_class_def L489-494) if GenApi.get_stdlib_alloc() != 0: st_copy_c: mlirlite.LLVMType* = mlirlite.DeepCopyType( CompilerFactory.factory.PermPool, struct_ty_c) - if st_copy_c is not None: - struct_ty_c = st_copy_c + if st_copy_c is not None: struct_ty_c = st_copy_c # 5.5 前向声明占位命中 ⇒ **占位 Ty 原地写入**(与 ClassGenDef.translate_class_def # 的 fill_fwd 段逐句同款):给已存在的类型对象 `*existing.Ty` 赋入刚构建的 # 字段体,并让 struct_ty_c 指向**同一个 Ty**。 @@ -2931,19 +2637,16 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*, # B5:vpi 保留 @c.Attribute(t.attr.packed) 装饰器,stub 注入的跨模块 # struct 必须同样 packed(<{...}>),否则引用模块 GEP 按非 packed 布局 # 算偏移,与定义侧 packed 布局错位(gdt/elf/fat32 二进制格式字段错读)。 - if _vpi_class_has_packed(class_cd.decorator_list) != 0: - mlirlite.module_set_named_type_packed(mod, pool, struct_ty_c, 1) + if _vpi_class_has_packed(class_cd.decorator_list) != 0: mlirlite.module_set_named_type_packed(mod, pool, struct_ty_c, 1) # 注册名用扁平名 real_name:跨模块引用 `外类.内类` 时 TypeGenResolve 查的是 # 扁平名条目(与定义端 StructGen 的登记名同源)。 entry_c: GenTypes.StructEntry* = GenApi.register_struct( pool, real_name, struct_ty_c, src_sha1) - if entry_c is None: - return 0 + if entry_c is None: return 0 # B5:vpi 注入注册的 entry 同步 IsPacked——后续跨模块 stub 注入 # (ensure_struct_def_in_module)按 entry.IsPacked 判定 packed,否则读 0 # → 注入的跨模块 struct 非 packed(GEP 布局错位)。 - if _vpi_class_has_packed(class_cd.decorator_list) != 0: - entry_c.IsPacked = 1 + if _vpi_class_has_packed(class_cd.decorator_list) != 0: entry_c.IsPacked = 1 # vpi 注入类时同步注册字段到 StructEntry 字段表(名字+类型):仅设 Ty 而字段表空(FieldCount=0)会让 lookup_field/lookup_field_by_class 按名查字段失败 # → 属性访问走 _deps_pending → includes 无重译 → 失败版本落盘恒 0(如 File.size 的 li.QuadPart 恒 0 → read_all=0)。 # add_field 内部按 StdlibAlloc 复制字段名到 perm_pool,跨 reset 存活。 @@ -2980,21 +2683,16 @@ def _inject_nested_class_declares(pool: memhub.MemBuddy*, imported_modules: str, from_imports: str) -> None: """递归登记 class_cd 的所有嵌套 ClassDef 为扁平名类型(前缀 = prefix_name)""" - if pool is None or mod is None or class_cd is None or prefix_name is None: - return + if pool is None or mod is None or class_cd is None or prefix_name is None: return children: list[ast.AST*]* = class_cd.children - if children is None: - return + if children is None: return cn: sizet = len(children) for ci in range(cn): child_ast: ast.AST* = children.get(ci) - if child_ast is None: - continue - if child_ast.kind() != ast.ASTKind.ClassDef: - continue + if child_ast is None: continue + if child_ast.kind() != ast.ASTKind.ClassDef: continue child_cd: ast.ClassDef* = ast.ClassDef*(child_ast) - if child_cd is None or child_cd.name is None or child_cd.name[0] == '\0': - continue + if child_cd is None or child_cd.name is None or child_cd.name[0] == '\0': continue _inject_class_struct_declare(pool, mod, child_cd, child_cd.name, trans, src_sha1, imported_modules, from_imports, prefix_name) @@ -3021,11 +2719,9 @@ def _ensure_full_value_types(mod: mlirlite.LLVMModule*, # vpi 全局变量(@_per_cpu = global %per_cpu_data)/值返回类型注入完整 # 定义时若只 add 不 set_packed → 引用模块节点 IsPacked=0 → 输出 {…} # 非 packed(GEP 与定义侧 packed 布局错位,stub packed 失效根因)。 - if full_se_h.IsPacked != 0: - mlirlite.module_set_named_type_packed(mod, pool, full_se_h.Ty, 1) + if full_se_h.IsPacked != 0: mlirlite.module_set_named_type_packed(mod, pool, full_se_h.Ty, 1) case mlirlite.LLVMType.Array(aelem_h, _): - if aelem_h is not None: - _ensure_full_value_types(mod, pool, aelem_h) + if aelem_h is not None: _ensure_full_value_types(mod, pool, aelem_h) case _: pass @@ -3049,15 +2745,13 @@ def _AggregateParamTy(mod: mlirlite.LLVMModule*, ty: mlirlite.LLVMType*, is_c_abi: int) -> mlirlite.LLVMType*: """裸结构体形参类型(C ABI 按值 / 内部 Ptr(struct),见上方注释)""" - if mod is None or pool is None or ty is None: - return ty + if mod is None or pool is None or ty is None: return ty if is_c_abi != 0: # 真 opaque 哨兵:fcount < 0(includes/mlirlite/__module.vp L491) is_opaque_ap: int = 0 match ty: case mlirlite.LLVMType.Struct(_, fcount_ap, _): - if fcount_ap < 0: - is_opaque_ap = 1 + if fcount_ap < 0: is_opaque_ap = 1 case _: pass if is_opaque_ap == 0 and GenApi.find_struct_by_type(ty) is not None: @@ -3085,17 +2779,13 @@ def _inject_global_variable_declare(pool: memhub.MemBuddy*, i8_ptr_ty: mlirlite.LLVMType*, src_sha1: str) -> None: """从 vpi AnnAssign 创建模块级全局变量 external declare(mangled 名 @.)""" - if pool is None or mod is None or aa is None or trans is None: - return + if pool is None or mod is None or aa is None or trans is None: return tgt_v: ast.AST* = aa.target - if tgt_v is None or tgt_v.kind() != ast.ASTKind.Name: - return + if tgt_v is None or tgt_v.kind() != ast.ASTKind.Name: return nm_v: ast.Name* = ast.Name*(tgt_v) - if nm_v is None or nm_v.id is None: - return + if nm_v is None or nm_v.id is None: return gname_v: str = nm_v.id - if gname_v[0] == '\0': - return + if gname_v[0] == '\0': return # 自注入守卫(仅全量翻译阶段 _declare_only == 0):本模块自己定义的模块级全局, # 其定义由 TranslatorGenMixin.handle_module_level_var 发射(@<本模块sha1>. = global …)。 # 把本模块自己的 vpi 经依赖链反向注入(循环 import:os/__init__ 导入 os._win32/os._posix, @@ -3104,8 +2794,7 @@ def _inject_global_variable_declare(pool: memhub.MemBuddy*, # redefinition of global '@.'。与 _inject_function_declare / # _inject_method_declare 的自注入守卫同因同构(那两处已修,全局此处此前遗漏)。 if trans is not None and trans._declare_only == 0 and trans.ModuleSha1 is not None and src_sha1 is not None: - if string.strcmp(src_sha1, trans.ModuleSha1) == 0: - return + if string.strcmp(src_sha1, trans.ModuleSha1) == 0: return # mangled 名:带源模块 SHA1 前缀(对齐定义端 5f7a873 的 @. # 与查找端 from-import 精确查找三方一致;裸短名会退化为未定义)。 # 注:a42923c 曾把此处写成未定义变量 gv_name_m(笔误,mangle 未实现), @@ -3116,18 +2805,15 @@ def _inject_global_variable_declare(pool: memhub.MemBuddy*, # (gdt.vp gdt/gp、idt.vp idt、sched.vp _sched_ptr/_switch_*_rsp、 # coroutine.vp _coro_*、process.vp _saved_cr3 等 CExport 全局根因)。 is_gv_cexport: int = 0 - if aa.annotation is not None: - is_gv_cexport = GenApi.has_decorator_marker(aa.annotation, "CExport") + if aa.annotation is not None: is_gv_cexport = GenApi.has_decorator_marker(aa.annotation, "CExport") if src_sha1 is not None and src_sha1[0] != '\0' and is_gv_cexport == 0: ml_v: sizet = string.strlen(src_sha1) + 1 + string.strlen(gname_v) + 1 gv_name_m = pool.alloc(ml_v) - if gv_name_m is not None: - viperlib.snprintf(gv_name_m, ml_v, "%s.%s", src_sha1, gname_v) + if gv_name_m is not None: viperlib.snprintf(gv_name_m, ml_v, "%s.%s", src_sha1, gname_v) # 去重:遍历模块全局变量链表(mangled 名匹配) cur_v: mlirlite.GlobalVariable* = mod.GlobalHead while cur_v is not None: - if cur_v.Name is not None and string.strcmp(cur_v.Name, gv_name_m) == 0: - return + if cur_v.Name is not None and string.strcmp(cur_v.Name, gv_name_m) == 0: return cur_v = cur_v.Next # 解析注解类型(裸类 → Ptr(struct),CArray → 元素指针) resolved_v: mlirlite.LLVMType* = None @@ -3142,18 +2828,15 @@ def _inject_global_variable_declare(pool: memhub.MemBuddy*, # 对象类(@t.Object/@t.CVTable:对象即指针,HasNew/HasVTable/IsOOP)→ Ptr(struct),与定义端 handle_module_level_var 一致; # 纯 t.CStruct 值类(如 pci_device)保持值实例——一律转 Ptr 会把实例前 8 字节当指针解引用(#GP),一律保持值则 @t.Object 类模块级变量按指针访问读错 vtable(#PF)。 gv_entry_v: GenTypes.StructEntry* = GenApi.find_struct_by_type(resolved_v) - if gv_entry_v is not None and (gv_entry_v.HasNew != 0 or gv_entry_v.HasVTable != 0 or gv_entry_v.IsOOP != 0): - gv_ty_v = mlirlite.Ptr(pool, resolved_v) - else: - gv_ty_v = resolved_v + if gv_entry_v is not None and (gv_entry_v.HasNew != 0 or gv_entry_v.HasVTable != 0 or gv_entry_v.IsOOP != 0): gv_ty_v = mlirlite.Ptr(pool, resolved_v) + else: gv_ty_v = resolved_v case mlirlite.LLVMType.Array(aelem_v, acount_v): # 定长数组(CArray[T, N]):保留完整数组类型 [N x T],与定义端 # handle_module_level_var 生成的 global [N x T] 一致——此前一律 # 衰减为元素指针 i32*,链接后引用端 load 把数组前 8 字节当指针 # 读 → 垃圾地址 → zdeflate_len_to_symbol 读 NULL/垃圾崩溃 # (zdeflate_len_base 跨模块数组根因)。 - if acount_v > 0: - gv_ty_v = resolved_v + if acount_v > 0: gv_ty_v = resolved_v else: # 不定长数组(CArray[T, None]):元素指针(C 数组衰减) gv_ty_v = mlirlite.Ptr(pool, aelem_v) @@ -3168,8 +2851,7 @@ def _inject_global_variable_declare(pool: memhub.MemBuddy*, _ensure_full_value_types(mod, pool, gv_ty_v) mlirlite.module_ensure_opaque_for_type(mod, pool, gv_ty_v) gv_v: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, gv_name_m, gv_ty_v) - if gv_v is None: - return + if gv_v is None: return mlirlite.module_add_global(mod, gv_v) gv_v.Linkage = "external" @@ -3193,8 +2875,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*, funcs_ptr: GenTypes.FuncEntry*, max_funcs: int) -> None: """为 FunctionDef 创建 declare 声明并注入到模块""" - if fd.name is None: - return + if fd.name is None: return # 自注入守卫(仅全量翻译阶段 _declare_only == 0):本模块自己定义的顶层函数, # 其 define 由 FuncGenDef.forward_declare_functions + translate_function_def @@ -3204,8 +2885,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*, # ParseState.__init__ 取 i32(vpi 无返回注解 → i32 默认),而定义端是 void # → llc: value doesn't match function result type 'i32'。 if trans is not None and trans._declare_only == 0 and trans.ModuleSha1 is not None: - if string.strcmp(src_sha1, trans.ModuleSha1) == 0: - return + if string.strcmp(src_sha1, trans.ModuleSha1) == 0: return # 检测 CExtern/State/CExport 标记(从返回类型注解) has_extern: int = 0 @@ -3220,8 +2900,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*, # 本树内)保持 Ptr(struct)。与定义侧 FuncGenDef is_extern_decl 同源, # 保证注入侧 declare 与定义侧 define 同口径(三处必须同步)。 agg_is_c_abi: int = 0 - if has_extern != 0 or has_state != 0: - agg_is_c_abi = 1 + if has_extern != 0 or has_state != 0: agg_is_c_abi = 1 # 计算 mangled name # CExport/CExtern/State/main 函数用裸名,其他函数用源模块 SHA1 前缀 @@ -3229,8 +2908,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*, if has_extern != 0 or has_state != 0 or has_export != 0 or string.strcmp(fd.name, "main") == 0: mangled_name: str = fd.name use_bare_name = 1 - else: - mangled_name = GenApi._mangle_name_with_sha1(src_sha1, fd.name) + else: mangled_name = GenApi._mangle_name_with_sha1(src_sha1, fd.name) # 本文件自己的裸名声明优先:extern/state/export 声明的符号**不带 SHA1 前缀** # (与 FuncGenDef.vp:172-173 同口径),若本文件自己也声明了同名符号,先注入的 @@ -3242,18 +2920,15 @@ def _inject_function_declare(pool: memhub.MemBuddy*, # socket.vp:236 `connect(self.fd, c.Addr(addr), 16)` 报 # 「指针隐式转指针已禁止:SocketAddr* → WSASocketAddr*」。 # 判据只用**裸名**:带 SHA1 前缀的依赖函数名与本文件同名声明不会相互顶替。 - if use_bare_name != 0 and GenApi.is_file_func(fd.name) != 0: - return + if use_bare_name != 0 and GenApi.is_file_func(fd.name) != 0: return # 去重:如果函数已存在则跳过 existing: mlirlite.Function* = GenApi.find_func_in_module(mod, mangled_name) - if existing is not None: - return + if existing is not None: return # 也检查裸名(非裸名模式时,CExport 函数可能已通过其他途径注册) if use_bare_name == 0: existing_bare: mlirlite.Function* = GenApi.find_func_in_module(mod, fd.name) - if existing_bare is not None: - return + if existing_bare is not None: return # 推断返回类型 # 优先用缓存的返回注解字符串(tree 解析后立即提取,节点未损坏) @@ -3261,8 +2936,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*, # __init__/vtable 未执行问题,节点 kind() 异常导致 resolve 得垃圾类型) ret_ty: mlirlite.LLVMType* = None ret_annot_fd: str = _lookup_vpi_ret_annot(src_sha1, None, fd.name) - if ret_annot_fd is not None: - ret_ty = _resolve_vpi_ret_annot_str(pool, ret_annot_fd, i32_ty, i8_ptr_ty) + if ret_annot_fd is not None: ret_ty = _resolve_vpi_ret_annot_str(pool, ret_annot_fd, i32_ty, i8_ptr_ty) if ret_ty is None and fd.returns is not None: ret_ty = GenApi.resolve_annotation_type( pool, fd.returns, imported_modules, from_imports, trans) @@ -3275,16 +2949,14 @@ def _inject_function_declare(pool: memhub.MemBuddy*, # 仅纯标记注解(t.State/t.CExtern/t.CExport 单独出现)才返回 Void。 is_pure_marker_rt: int = 0 rk2_rt: int = fd.returns.kind() - if rk2_rt == ast.ASTKind.Name or rk2_rt == ast.ASTKind.Constant: - is_pure_marker_rt = 1 + if rk2_rt == ast.ASTKind.Name or rk2_rt == ast.ASTKind.Constant: is_pure_marker_rt = 1 elif rk2_rt == ast.ASTKind.Attribute: pm_at: ast.Attribute* = ast.Attribute*(fd.returns) if pm_at.attr is not None and (string.strcmp(pm_at.attr, "State") == 0 or string.strcmp(pm_at.attr, "CExtern") == 0 or string.strcmp(pm_at.attr, "CExport") == 0): is_pure_marker_rt = 1 - if is_pure_marker_rt != 0: - ret_ty = mlirlite.Void(pool) + if is_pure_marker_rt != 0: ret_ty = mlirlite.Void(pool) elif has_state != 0 or has_extern != 0 or has_export != 0: # 含真实类型但解析失败:回退外部函数返回类型白名单 # (FindFirstFileA/GetStdHandle → i8* HANDLE 等),避免默认 i32 @@ -3297,8 +2969,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*, fd.returns, f"extern 声明 '{fd.name}' 返回类型注解解析失败", "NameError") # 默认返回 i32 - if ret_ty is None: - ret_ty = i32_ty + if ret_ty is None: ret_ty = i32_ty # 值 struct 返回类型(如 gfx.vp Mat4_Identity -> Mat4)需要完整定义: # declare %Mat4 opaque → llc "use of undefined type"。注册完整定义。 @@ -3308,8 +2979,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*, # 创建 declare func: mlirlite.Function* = mlirlite.create_declare( pool, mod, mangled_name, ret_ty) - if func is None: - return + if func is None: return # 提取参数并添加到 declare param_count: int = 0 @@ -3333,11 +3003,9 @@ def _inject_function_declare(pool: memhub.MemBuddy*, pi: sizet for pi in range(param_count): ag: ast.Arg* = ast.Arg*(args_list.get(pi)) - if ag is None: - continue + if ag is None: continue pname: str = ag.arg - if pname is None: - pname = "arg" + if pname is None: pname = "arg" # 解析参数类型 param_ty: mlirlite.LLVMType* = i8_ptr_ty # 优先用 vpi 文本注解缓存解析参数类型(与返回类型同源——vpi @@ -3386,8 +3054,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*, # *args 变长参数:标记 IsVarArg=1,使调用侧走 C ABI 参数提升 # (i8/i16 → i32,float → double),避免 %d/%x 等格式因参数按 i64 # 传递而读错(第二个 %x 读到第一个 i64 槽的高 4 字节)。 - if args_node.vararg is not None: - func.IsVarArg = 1 + if args_node.vararg is not None: func.IsVarArg = 1 # 默认参数:vpi 签名含 '= '(Converter 已输出),提取 defaults # 列表注册默认参数表——跨模块缺参调用(如 resolve_annotation_type 的 # depth=0)才能按表填充,否则被调函数读到栈垃圾(假报递归过深/崩溃)。 @@ -3405,8 +3072,7 @@ def _inject_function_declare(pool: memhub.MemBuddy*, fd.name, fd_default_count) fd_defaults = None fd_default_count = 0 - else: - fd_defaults = fd_dlist + else: fd_defaults = fd_dlist # 注册到函数表(用裸名 fd.name,不是 mangled_name) if funcs_ptr is not None: @@ -3439,10 +3105,8 @@ def _inject_method_declare(pool: memhub.MemBuddy*, funcs_ptr: GenTypes.FuncEntry*, max_funcs: int) -> None: """为 ClassDef 内方法创建 declare 声明并注入到模块""" - if m_fd is None or m_fd.name is None or cls_name is None: - return - if src_sha1 is None: - return + if m_fd is None or m_fd.name is None or cls_name is None: return + if src_sha1 is None: return # 自注入守卫(仅全量翻译阶段 _declare_only == 0):本模块自己定义的类,其方法 # define 由 ClassGenVTable._translate_oop_methods 发射;把本模块自己的 vpi 经 @@ -3451,27 +3115,23 @@ def _inject_method_declare(pool: memhub.MemBuddy*, # ParseState.__init__ 注入成 i32(vpi 无返回注解 → i32 默认)而定义端是 void # → llc: value doesn't match function result type 'i32'。 if trans is not None and trans._declare_only == 0 and trans.ModuleSha1 is not None: - if string.strcmp(src_sha1, trans.ModuleSha1) == 0: - return + if string.strcmp(src_sha1, trans.ModuleSha1) == 0: return # 构造方法查找名: ClassName.method lookup_name_len: sizet = string.strlen(cls_name) + 1 + string.strlen(m_fd.name) + 1 lookup_name: str = pool.alloc(lookup_name_len) - if lookup_name is None: - return + if lookup_name is None: return viperlib.snprintf(lookup_name, lookup_name_len, "%s.%s", cls_name, m_fd.name) # mangled name: {src_sha1}.{ClassName}.{method} mangled_len: sizet = string.strlen(src_sha1) + 1 + lookup_name_len mangled_name: str = pool.alloc(mangled_len) - if mangled_name is None: - return + if mangled_name is None: return viperlib.snprintf(mangled_name, mangled_len, "%s.%s", src_sha1, lookup_name) # 去重:如果方法已存在则跳过 existing: mlirlite.Function* = GenApi.find_func_in_module(mod, mangled_name) - if existing is not None: - return + if existing is not None: return # 推断返回类型 # 优先用缓存的返回注解字符串(tree 解析后立即提取,节点未损坏), @@ -3479,16 +3139,14 @@ def _inject_method_declare(pool: memhub.MemBuddy*, # 直接解析 m_fd.returns 可能因 vpi tree 深层节点被覆盖而得到垃圾类型。 ret_ty: mlirlite.LLVMType* = None ret_annot: str = _lookup_vpi_ret_annot(src_sha1, cls_name, m_fd.name) - if ret_annot is not None: - ret_ty = _resolve_vpi_ret_annot_str(pool, ret_annot, i32_ty, i8_ptr_ty) + if ret_annot is not None: ret_ty = _resolve_vpi_ret_annot_str(pool, ret_annot, i32_ty, i8_ptr_ty) if ret_ty is None and m_fd.returns is not None: ret_ty = GenApi.resolve_annotation_type( pool, m_fd.returns, imported_modules, from_imports, trans) # __new__ 无返回注解时推断为类指针(__new__ 返回 self 指针,默认 i32 会截断指针) if ret_ty is None and string.strcmp(m_fd.name, "__new__") == 0: cls_ty: mlirlite.LLVMType* = GenApi.get_struct_type(cls_name) - if cls_ty is not None: - ret_ty = mlirlite.Ptr(pool, cls_ty) + if cls_ty is not None: ret_ty = mlirlite.Ptr(pool, cls_ty) # [S4 fail-fast] 有返回注解却解析不出类型 → 不再静默退 i32; # __new__ 无注解、普通方法无注解均走下方 i32 合法默认。 if ret_ty is None and m_fd.returns is not None: @@ -3500,16 +3158,13 @@ def _inject_method_declare(pool: memhub.MemBuddy*, # ClassGenVTable._translate_method 对 __init__ 恒 Void)。若按"普通方法无注解" # 退成下方 i32 默认,就会出现 declare i32 / define void 的返回类型分裂: # 同模块内 llc 报 value doesn't match function result type,跨模块是静默 ABI 不一致。 - if ret_ty is None and string.strcmp(m_fd.name, "__init__") == 0: - ret_ty = mlirlite.Void(pool) - if ret_ty is None: - ret_ty = i32_ty + if ret_ty is None and string.strcmp(m_fd.name, "__init__") == 0: ret_ty = mlirlite.Void(pool) + if ret_ty is None: ret_ty = i32_ty # 创建 declare func: mlirlite.Function* = mlirlite.create_declare( pool, mod, mangled_name, ret_ty) - if func is None: - return + if func is None: return # 提取参数并添加到 declare param_count: int = 0 @@ -3531,11 +3186,9 @@ def _inject_method_declare(pool: memhub.MemBuddy*, pi: sizet for pi in range(param_count): ag: ast.Arg* = ast.Arg*(args_list.get(pi)) - if ag is None: - continue + if ag is None: continue pname: str = ag.arg - if pname is None: - pname = "arg" + if pname is None: pname = "arg" # self/cls 参数(首参):跨模块声明用类指针(%"sha1.Class"*)而非 # 默认 i8* —— 与定义侧 _translate_method 的 self 参数 Ptr(StructTy) # 签名一致,消除跨模块声明/定义歧义。调用侧按形参 coerce 自动 @@ -3603,8 +3256,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*, i1_ty_si: mlirlite.LLVMType* = mlirlite.Int1(pool) if i1_ty_si is not None: i1_ptr_ty_si: mlirlite.LLVMType* = mlirlite.Ptr(pool, i1_ty_si) - if i1_ptr_ty_si is not None: - mlirlite.add_param(pool, func, i1_ptr_ty_si, "__stop_iter_flag__") + if i1_ptr_ty_si is not None: mlirlite.add_param(pool, func, i1_ptr_ty_si, "__stop_iter_flag__") # 默认参数:vpi 签名含 '= '(Converter 已输出),提取 defaults # 列表注册默认参数表——跨模块缺参调用(如 resolve_annotation_type 的 # depth=0)才能按表填充,否则被调函数读到栈垃圾(假报递归过深/崩溃)。 @@ -3621,8 +3273,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*, cls_name, m_fd.name, md_default_count) md_defaults = None md_default_count = 0 - else: - md_defaults = md_dlist + else: md_defaults = md_dlist # 注册到函数表(用裸名 ClassName.method,与调用方 lookup_name 一致) # ParamCount 不含 self(方法首参 self/cls 不计入,与 _translate_method 的 @@ -3631,8 +3282,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*, if funcs_ptr is not None: cur_count: int = trans._func_count param_count_no_self: int = param_count - if param_count_no_self > 0: - param_count_no_self -= 1 + if param_count_no_self > 0: param_count_no_self -= 1 if GenApi.add_func_to_table(funcs_ptr, cur_count, lookup_name, func, max_funcs, md_defaults, md_default_count, param_count_no_self, None, src_sha1) == 0: trans._func_count = cur_count + 1 @@ -3652,20 +3302,15 @@ def _inject_method_declare(pool: memhub.MemBuddy*, def _register_ctypedef_from_annassign(pool: memhub.MemBuddy*, aa: ast.AnnAssign*) -> None: """从 AnnAssign 节点提取并注册 CTypedef""" - if aa is None or pool is None: - return + if aa is None or pool is None: return # 提取目标名称(必须是 Name 节点) - if aa.target is None or aa.target.kind() != ast.ASTKind.Name: - return + if aa.target is None or aa.target.kind() != ast.ASTKind.Name: return tgt: ast.Name* = ast.Name*(aa.target) - if tgt.id is None: - return + if tgt.id is None: return # 提取类型表达式字符串(从 value AST 节点) - if aa.value is None: - return + if aa.value is None: return type_str: str = GenApi._get_type_name_from_annotation(pool, aa.value) - if type_str is None: - return + if type_str is None: return # 注册 CTypedef GenApi.register_ctypedef(pool, tgt.id, type_str) @@ -3737,58 +3382,46 @@ ReplStubTmpArity: int = 0 def _repl_stub_dupstr(pool: memhub.MemBuddy*, src: str) -> str: """把字符串深拷贝到指定池""" - if src is None or pool is None: - return None + if src is None or pool is None: return None ln: sizet = string.strlen(src) dst: str = pool.alloc(ln + 1) - if dst is None: - return None + if dst is None: return None string.strcpy(dst, src) return dst def _repl_stub_key(pool: memhub.MemBuddy*, sha1: str, cls: str) -> str: """拼接 .<类名>:与定义侧 ClassGenDef 的命名结构体名逐字一致""" - if pool is None or sha1 is None or cls is None: - return None - if sha1[0] == '\0' or cls[0] == '\0': - return None + if pool is None or sha1 is None or cls is None: return None + if sha1[0] == '\0' or cls[0] == '\0': return None ln: sizet = string.strlen(sha1) + 1 + string.strlen(cls) + 1 buf: str = pool.alloc(ln) - if buf is None: - return None + if buf is None: return None viperlib.snprintf(buf, ln, "%s.%s", sha1, cls) return buf def _repl_stub_path(sha1: str, ext: str) -> str: """REPL 临时目录下的切片路径 //.(stdlib 分配)""" - if ReplStubTempDir is None or sha1 is None: - return None + if ReplStubTempDir is None or sha1 is None: return None td_len: sizet = string.strlen(ReplStubTempDir) sh_len: sizet = string.strlen(sha1) sub: str = Config.slice_subdir(sha1, Config.Sha1SliceLevel) sub_len: sizet = 0 - if sub is not None: - sub_len = string.strlen(sub) + if sub is not None: sub_len = string.strlen(sub) cap: sizet = td_len + sub_len + sh_len + 8 buf: str = stdlib.malloc(cap) - if buf is None: - return None - if sub_len > 0: - viperlib.snprintf(buf, cap, "%s/%s/%s.%s", ReplStubTempDir, sub, sha1, ext) - else: - viperlib.snprintf(buf, cap, "%s/%s.%s", ReplStubTempDir, sha1, ext) + if buf is None: return None + if sub_len > 0: viperlib.snprintf(buf, cap, "%s/%s/%s.%s", ReplStubTempDir, sub, sha1, ext) + else: viperlib.snprintf(buf, cap, "%s/%s.%s", ReplStubTempDir, sha1, ext) return buf def _repl_stub_readtext(path: str) -> str: """读入存根文本(stdlib.malloc,调用方 free);不存在/超限返回 None""" - if path is None: - return None + if path is None: return None f: rawptr[fileio.File] = fileio.File(path, fileio.MODE.R) - if f is None or f.closed: - return None + if f is None or f.closed: return None sz: sizet = f.size() if sz <= 0 or sz >= _REPL_STUB_TXT_CAP: f.close() @@ -3802,16 +3435,14 @@ def _repl_stub_readtext(path: str) -> str: if rd <= 0: stdlib.free(buf) return None - if rd < LONG(sz + 1): - buf[rd] = 0 + if rd < LONG(sz + 1): buf[rd] = 0 return buf # 从 txt[start, end) 解析十进制整数(跳过前导空格;无数字返回 0) def _meta_atoi(txt: str, start: sizet, end: sizet) -> int: i: sizet = start - while i < end and (txt[i] == ' ' or txt[i] == '\t'): - i += 1 + while i < end and (txt[i] == ' ' or txt[i] == '\t'): i += 1 neg: int = 0 if i < end and txt[i] == '-': neg = 1 @@ -3820,8 +3451,7 @@ def _meta_atoi(txt: str, start: sizet, end: sizet) -> int: while i < end and txt[i] >= '0' and txt[i] <= '9': v = v * 10 + (int(txt[i]) - 48) i += 1 - if neg != 0: - return -v + if neg != 0: return -v return v @@ -3836,29 +3466,22 @@ def _repl_meta_scan_layout(txt: str, key: str) -> None: ReplStubTmpCount = -1 ReplStubTmpPacked = 0 ReplStubTmpArity = 0 - if txt is None or key is None: - return + if txt is None or key is None: return n: sizet = string.strlen(txt) key_len: sizet = string.strlen(key) - if key_len == 0: - return + if key_len == 0: return i: sizet = 0 while i < n: ls: sizet = i - while i < n and txt[i] != '\n': - i += 1 + while i < n and txt[i] != '\n': i += 1 le: sizet = i - if i < n: - i += 1 - if le > ls and txt[le - 1] == '\r': - le -= 1 + if i < n: i += 1 + if le > ls and txt[le - 1] == '\r': le -= 1 if ls + 7 <= le and string.strncmp(txt + ls, "STRUCT ", 7) == 0: ns: sizet = ls + 7 ne: sizet = ns + key_len - if ne > le or string.strncmp(txt + ns, key, key_len) != 0: - continue - if ne >= le or txt[ne] != ' ': - continue + if ne > le or string.strncmp(txt + ns, key, key_len) != 0: continue + if ne >= le or txt[ne] != ' ': continue # OPAQUE if ne + 7 <= le and string.strncmp(txt + ne + 1, "OPAQUE", 6) == 0: ReplStubTmpCount = -2 @@ -3867,20 +3490,15 @@ def _repl_meta_scan_layout(txt: str, key: str) -> None: if ne + 8 <= le and string.strncmp(txt + ne + 1, "FIELDS ", 7) == 0: ReplStubTmpCount = _meta_atoi(txt, ne + 8, le) ps: sizet = ne + 8 - while ps < le and txt[ps] >= '0' and txt[ps] <= '9': - ps += 1 - if ps + 8 <= le and string.strncmp(txt + ps + 1, "PACKED ", 7) == 0: - ReplStubTmpPacked = _meta_atoi(txt, ps + 8, le) + while ps < le and txt[ps] >= '0' and txt[ps] <= '9': ps += 1 + if ps + 8 <= le and string.strncmp(txt + ps + 1, "PACKED ", 7) == 0: ReplStubTmpPacked = _meta_atoi(txt, ps + 8, le) continue if ls + 7 <= le and string.strncmp(txt + ls, "VTABLE ", 7) == 0: vs: sizet = ls + 7 ve: sizet = vs + key_len - if ve > le or string.strncmp(txt + vs, key, key_len) != 0: - continue - if ve >= le or txt[ve] != ' ': - continue - if ve + 7 <= le and string.strncmp(txt + ve + 1, "SLOTS ", 6) == 0: - ReplStubTmpArity = _meta_atoi(txt, ve + 7, le) + if ve > le or string.strncmp(txt + vs, key, key_len) != 0: continue + if ve >= le or txt[ve] != ' ': continue + if ve + 7 <= le and string.strncmp(txt + ve + 1, "SLOTS ", 6) == 0: ReplStubTmpArity = _meta_atoi(txt, ve + 7, le) continue return @@ -3892,15 +3510,12 @@ def ReplStubLayoutBegin(temp_dir: str) -> int: global ReplStubWarnLeft global ReplStubRefusedNoStub, ReplStubRefusedNoClass, ReplStubRefusedOpaque, ReplStubRefusedParent pool: memhub.MemBuddy* = CompilerFactory.factory.PermPool - if pool is None or temp_dir is None: - return 1 + if pool is None or temp_dir is None: return 1 ReplStubPool = pool ReplStubTempDir = _repl_stub_dupstr(pool, temp_dir) - if ReplStubTempDir is None: - return 1 + if ReplStubTempDir is None: return 1 ReplStubTable = pool.alloc(8 * _REPL_STUB_CLS_MAX) - if ReplStubTable is None: - return 1 + if ReplStubTable is None: return 1 string.memset(ReplStubTable, 0, 8 * _REPL_STUB_CLS_MAX) ReplStubCount = 0 ReplStubOk = 0 @@ -3918,67 +3533,52 @@ def ReplStubLayoutBegin(temp_dir: str) -> int: def _repl_stub_at(i: int) -> rawptr[ReplStubClass]: """类表第 i 项(无则 None)""" - if ReplStubTable is None or i < 0 or i >= ReplStubCount: - return None + if ReplStubTable is None or i < 0 or i >= ReplStubCount: return None addr: sizet = ReplStubTable[i] - if addr == 0: - return None + if addr == 0: return None return rawptr[ReplStubClass](uint64(addr)) def _repl_stub_find(key: str) -> rawptr[ReplStubClass]: """按 ".<类名>" 查类表条目(无则 None)""" - if key is None: - return None + if key is None: return None i: int for i in range(ReplStubCount): e: rawptr[ReplStubClass] = _repl_stub_at(i) - if e is None or e.Key is None: - continue - if string.strcmp(e.Key, key) == 0: - return e + if e is None or e.Key is None: continue + if string.strcmp(e.Key, key) == 0: return e return None def _repl_stub_find_base(e: rawptr[ReplStubClass], bi: int) -> rawptr[ReplStubClass]: """父类表条目:先同模块 SHA1 精确匹配,再按裸类名首个匹配(镜像 StructGen.find_struct_by_module → find_struct 的父类回退口径)""" - if e is None or e.Bases is None or bi < 0 or bi >= e.BaseCount: - return None + if e is None or e.Bases is None or bi < 0 or bi >= e.BaseCount: return None pname: str = rawptr(e.Bases[bi]) - if pname is None: - return None + if pname is None: return None i: int for i in range(ReplStubCount): pe: rawptr[ReplStubClass] = _repl_stub_at(i) - if pe is None or pe.ClassName is None: - continue - if string.strcmp(pe.ClassName, pname) != 0: - continue + if pe is None or pe.ClassName is None: continue + if string.strcmp(pe.ClassName, pname) != 0: continue if e.Sha1 is not None and pe.Sha1 is not None: - if string.strcmp(pe.Sha1, e.Sha1) == 0: - return pe + if string.strcmp(pe.Sha1, e.Sha1) == 0: return pe for i in range(ReplStubCount): pe2: rawptr[ReplStubClass] = _repl_stub_at(i) - if pe2 is None or pe2.ClassName is None: - continue - if string.strcmp(pe2.ClassName, pname) == 0: - return pe2 + if pe2 is None or pe2.ClassName is None: continue + if string.strcmp(pe2.ClassName, pname) == 0: return pe2 return None def _repl_stub_has_name(arr: sizet*, cnt: int, name: str) -> int: """名单里是否已有该名(先声明优先去重)""" - if arr is None or name is None: - return 0 + if arr is None or name is None: return 0 i: int for i in range(cnt): addr: sizet = arr[i] - if addr == 0: - continue + if addr == 0: continue ex: str = rawptr(addr) - if ex is not None and string.strcmp(ex, name) == 0: - return 1 + if ex is not None and string.strcmp(ex, name) == 0: return 1 return 0 @@ -3987,50 +3587,39 @@ def _repl_stub_deco_flags(deco_list: list[ast.AST*]*) -> int: 与 ClassGenBase._has_decorator 同判据(Attribute(t.NoVTable) 与 Name(NoVTable) 两种写法)。 """ - if deco_list is None: - return 0 + if deco_list is None: return 0 flags: int = 0 dn: sizet = len(deco_list) di: sizet for di in range(dn): deco: ast.AST* = deco_list.get(di) - if deco is None: - continue + if deco is None: continue nm: str = None k: int = deco.kind() if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(deco) if at.attr is not None and at.value is not None and at.value.kind() == ast.ASTKind.Name: vn: ast.Name* = ast.Name*(at.value) - if vn.id is not None and string.strcmp(vn.id, "t") == 0: - nm = at.attr + if vn.id is not None and string.strcmp(vn.id, "t") == 0: nm = at.attr elif k == ast.ASTKind.Name: nn: ast.Name* = ast.Name*(deco) nm = nn.id - if nm is None: - continue - if string.strcmp(nm, "NoVTable") == 0: - flags = flags | 1 - elif string.strcmp(nm, "CVTable") == 0: - flags = flags | 2 + if nm is None: continue + if string.strcmp(nm, "NoVTable") == 0: flags = flags | 1 + elif string.strcmp(nm, "CVTable") == 0: flags = flags | 2 return flags def _repl_stub_is_virtual(e: rawptr[ReplStubClass], mi: int, first: rawptr[ReplStubClass]) -> int: """本类第 mi 个方法是否进虚表(转写 ClassGenBase._should_method_be_virtual)""" - if e is None or e.MethodFlags is None or mi < 0 or mi >= e.MethodCount: - return 0 + if e is None or e.MethodFlags is None or mi < 0 or mi >= e.MethodCount: return 0 mf: int = int(e.MethodFlags[mi]) - if (mf & 1) != 0: - return 0 - if (mf & 2) != 0: - return 1 - if (e.Flags & _REPL_SF_CVTABLE) != 0: - return 1 + if (mf & 1) != 0: return 0 + if (mf & 2) != 0: return 1 + if (e.Flags & _REPL_SF_CVTABLE) != 0: return 1 if first is not None: - if first.IsNoVTable != 0: - return 0 + if first.IsNoVTable != 0: return 0 return first.HasVt return 0 @@ -4039,8 +3628,7 @@ def _repl_stub_warn_refuse(e: rawptr[ReplStubClass], why: str, a: int, b: int) - """**判据拒绝**告警(两侧都是真数字时才用它):存根字段数 a 与展平+虚表推断 b 不符""" global ReplStubWarnLeft, ReplStubRefused ReplStubRefused += 1 - if ReplStubWarnLeft <= 0: - return + if ReplStubWarnLeft <= 0: return ReplStubWarnLeft -= 1 stdio.printf("includes 类布局: %s.%s 布局不可信 ⇒ 明确拒绝(原因=判据拒绝:%s;" "存根字段数=%d ≠ 展平字段数+虚表位=%d)。该类字段访问被明确拒绝" @@ -4059,16 +3647,11 @@ def _repl_stub_warn_nodata(e: rawptr[ReplStubClass], cause: int) -> None: global ReplStubRefusedNoStub, ReplStubRefusedNoClass global ReplStubRefusedOpaque, ReplStubRefusedParent ReplStubRefused += 1 - if cause == _REPL_SU_NOSTUB: - ReplStubRefusedNoStub += 1 - elif cause == _REPL_SU_NOCLASS: - ReplStubRefusedNoClass += 1 - elif cause == _REPL_SU_OPAQUE: - ReplStubRefusedOpaque += 1 - else: - ReplStubRefusedParent += 1 - if ReplStubWarnLeft <= 0: - return + if cause == _REPL_SU_NOSTUB: ReplStubRefusedNoStub += 1 + elif cause == _REPL_SU_NOCLASS: ReplStubRefusedNoClass += 1 + elif cause == _REPL_SU_OPAQUE: ReplStubRefusedOpaque += 1 + else: ReplStubRefusedParent += 1 + if ReplStubWarnLeft <= 0: return ReplStubWarnLeft -= 1 if cause == _REPL_SU_NOSTUB: # 数据缺失:连模块布局元数据都没有(LayoutCount = -1 只是"没读到"的哨兵) @@ -4098,8 +3681,7 @@ def _repl_stub_warn_parent(e: rawptr[ReplStubClass], detail: str, pname: str) -> global ReplStubWarnLeft, ReplStubRefused, ReplStubRefusedParent ReplStubRefused += 1 ReplStubRefusedParent += 1 - if ReplStubWarnLeft <= 0: - return + if ReplStubWarnLeft <= 0: return ReplStubWarnLeft -= 1 stdio.printf("includes 类布局: %s.%s 布局不可用 ⇒ 明确拒绝(原因=『上游无数据』:%s," "父类=%s;父类字段与虚表位无法展平 ⇒ 本类未做字段数比较)。该类字段访问" @@ -4109,14 +3691,10 @@ def _repl_stub_warn_parent(e: rawptr[ReplStubClass], detail: str, pname: str) -> def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int: """按存根校验并登记完整布局:1=已登记 / 0=父类未就绪(推迟)/ -1=拒绝""" global ReplStubOk, ReplStubVtOk, ReplStubWarnLeft - if e is None: - return -1 - if e.State == _REPL_SS_OK: - return 1 - if e.State == _REPL_SS_REFUSED: - return -1 - if e.State != _REPL_SS_PENDING: - return -1 + if e is None: return -1 + if e.State == _REPL_SS_OK: return 1 + if e.State == _REPL_SS_REFUSED: return -1 + if e.State != _REPL_SS_PENDING: return -1 pool: memhub.MemBuddy* = ReplStubPool if pool is None: e.State = _REPL_SS_REFUSED @@ -4125,10 +3703,8 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int: bi: int for bi in range(e.BaseCount): pe: rawptr[ReplStubClass] = _repl_stub_find_base(e, bi) - if pe is None: - return 0 - if pe.State == _REPL_SS_PENDING: - return 0 + if pe is None: return 0 + 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) @@ -4142,46 +3718,34 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int: pe.ClassName) return -1 first: rawptr[ReplStubClass] = None - if e.BaseCount > 0: - first = _repl_stub_find_base(e, 0) + if e.BaseCount > 0: first = _repl_stub_find_base(e, 0) # ② HasVTable(转写 ClassGenBase._detect_vtable_status) hv: int = 0 - if (e.Flags & _REPL_SF_CVTABLE) != 0: - hv = 1 - elif (e.Flags & _REPL_SF_NOVTABLE) != 0: - hv = 1 if (e.Flags & _REPL_SF_ANYFUNC) != 0 else 0 + if (e.Flags & _REPL_SF_CVTABLE) != 0: hv = 1 + elif (e.Flags & _REPL_SF_NOVTABLE) != 0: hv = 1 if (e.Flags & _REPL_SF_ANYFUNC) != 0 else 0 elif first is not None: - if first.IsNoVTable != 0: - hv = 1 if (e.Flags & _REPL_SF_ANYFUNC) != 0 else 0 - else: - hv = first.HasVt - else: - hv = 1 if (e.Flags & _REPL_SF_ANYFUNC) != 0 else 0 + if first.IsNoVTable != 0: hv = 1 if (e.Flags & _REPL_SF_ANYFUNC) != 0 else 0 + else: hv = first.HasVt + else: hv = 1 if (e.Flags & _REPL_SF_ANYFUNC) != 0 else 0 # ③ 字段展平(父类字段在前 + 本类字段,短名去重先声明优先) cn: int = 0 for bi in range(e.BaseCount): pe: rawptr[ReplStubClass] = _repl_stub_find_base(e, bi) fi: int for fi in range(pe.Count): - if cn >= _REPL_STUB_FIELD_MAX: - break + if cn >= _REPL_STUB_FIELD_MAX: break nm: str = rawptr(pe.Names[fi]) - if nm is None: - continue - if _repl_stub_has_name(e.Names, cn, nm) != 0: - continue + if nm is None: continue + if _repl_stub_has_name(e.Names, cn, nm) != 0: continue e.Names[cn] = pe.Names[fi] e.Types[cn] = pe.Types[fi] cn += 1 oi: int for oi in range(e.OwnCount): - if cn >= _REPL_STUB_FIELD_MAX: - break + if cn >= _REPL_STUB_FIELD_MAX: break nm2: str = rawptr(e.OwnNames[oi]) - if nm2 is None: - continue - if _repl_stub_has_name(e.Names, cn, nm2) != 0: - continue + if nm2 is None: continue + if _repl_stub_has_name(e.Names, cn, nm2) != 0: continue e.Names[cn] = e.OwnNames[oi] e.Types[cn] = e.OwnTypes[oi] cn += 1 @@ -4200,39 +3764,28 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int: pe: rawptr[ReplStubClass] = _repl_stub_find_base(e, bi) vi: int for vi in range(pe.VtCount): - if vn >= _REPL_STUB_VT_MAX: - break + if vn >= _REPL_STUB_VT_MAX: break mn: str = rawptr(pe.VtNames[vi]) - if mn is None: - continue - if _repl_stub_has_name(e.VtNames, vn, mn) != 0: - continue + if mn is None: continue + if _repl_stub_has_name(e.VtNames, vn, mn) != 0: continue e.VtNames[vn] = pe.VtNames[vi] vn += 1 mi: int for mi in range(e.MethodCount): - if vn >= _REPL_STUB_VT_MAX: - break + if vn >= _REPL_STUB_VT_MAX: break mn2: str = rawptr(e.MethodNames[mi]) - if mn2 is None: - continue - if string.strcmp(mn2, "__init__") == 0: - continue - if string.strcmp(mn2, "__before_init__") == 0: - continue - if string.strcmp(mn2, "__new__") == 0: - continue - if _repl_stub_has_name(e.VtNames, vn, mn2) != 0: - continue - if _repl_stub_is_virtual(e, mi, first) == 0: - continue + if mn2 is None: continue + if string.strcmp(mn2, "__init__") == 0: continue + if string.strcmp(mn2, "__before_init__") == 0: continue + if string.strcmp(mn2, "__new__") == 0: continue + if _repl_stub_has_name(e.VtNames, vn, mn2) != 0: continue + if _repl_stub_is_virtual(e, mi, first) == 0: continue e.VtNames[vn] = e.MethodNames[mi] vn += 1 e.VtCount = vn e.VtTrust = 0 if hv == 1 and vn > 0: - if vn == e.VtArity: - e.VtTrust = 1 + if vn == e.VtArity: e.VtTrust = 1 elif ReplStubWarnLeft > 0: ReplStubWarnLeft -= 1 stdio.printf("includes 类布局: %s.%s 的虚表槽数与存根不符(%d vs %d)" @@ -4241,14 +3794,12 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int: # ⑥ 建 LLVM 结构体(命名 "%.<类名>",与定义侧同口径) total: int = cn + hv i8_ptr: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) - if i8_ptr is None: - return 0 + if i8_ptr is None: return 0 first_node: rawptr[mlirlite.ParamNode] = None prev_node: rawptr[mlirlite.ParamNode] = None if hv == 1: nd0: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__()) - if nd0 is None: - return 0 + if nd0 is None: return 0 string.memset(nd0, 0, mlirlite.ParamNode.__sizeof__()) nd0.Ty = i8_ptr first_node = nd0 @@ -4256,33 +3807,26 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int: fi2: int for fi2 in range(cn): fty: mlirlite.LLVMType* = (mlirlite.LLVMType*)(e.Types[fi2]) - if fty is None: - continue + if fty is None: continue nd: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__()) - if nd is None: - continue + if nd is None: continue string.memset(nd, 0, mlirlite.ParamNode.__sizeof__()) nd.Ty = fty - if first_node is None: - first_node = nd - if prev_node is not None: - prev_node.Next = nd + if first_node is None: first_node = nd + if prev_node is not None: prev_node.Next = nd prev_node = nd struct_ty: mlirlite.LLVMType* = mlirlite.Struct(pool, first_node, total, e.Key) - if struct_ty is None: - return 0 + if struct_ty is None: return 0 # ⑦ 登记(StdlibAlloc=1 期间的注册走 PermPool,跨片段存活) entry: GenTypes.StructEntry* = GenApi.register_struct( pool, e.ClassName, struct_ty, e.Sha1) if entry is None: e.State = _REPL_SS_REFUSED return -1 - if mod is not None: - mlirlite.module_add_named_type(mod, pool, struct_ty) + if mod is not None: mlirlite.module_add_named_type(mod, pool, struct_ty) if (e.Flags & _REPL_SF_PACKED) != 0: entry.IsPacked = 1 - if mod is not None: - mlirlite.module_set_named_type_packed(mod, pool, struct_ty, 1) + if mod is not None: mlirlite.module_set_named_type_packed(mod, pool, struct_ty, 1) if hv == 1: entry.HasVTable = 1 GenApi.add_field(pool, entry, "__vtable__", i8_ptr) @@ -4290,11 +3834,9 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int: for fi3 in range(cn): fname: str = rawptr(e.Names[fi3]) fty3: mlirlite.LLVMType* = (mlirlite.LLVMType*)(e.Types[fi3]) - if fname is None or fty3 is None: - continue + if fname is None or fty3 is None: continue GenApi.add_field(pool, entry, fname, fty3) - if e.IsNoVTable != 0: - entry.IsNoVTable = 1 + if e.IsNoVTable != 0: entry.IsNoVTable = 1 entry.IsOOP = e.IsOOP entry.HasInit = e.HasInit entry.HasNew = e.HasNew @@ -4307,8 +3849,7 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int: for bi3 in range(e.BaseCount): bnm: str = rawptr(e.Bases[bi3]) bdup: str = _repl_stub_dupstr(pool, bnm) - if bdup is not None: - arr[bi3] = sizet(bdup) + if bdup is not None: arr[bi3] = sizet(bdup) entry.ParentNames = arr entry.ParentCount = e.BaseCount pn: str = rawptr(e.Bases[0]) @@ -4337,18 +3878,13 @@ def _repl_stub_add_class(pool: memhub.MemBuddy*, 『数据缺失』拒绝,与"meta 在但无此类"的『判据拒绝』在文案/计数上分开)。 """ global ReplStubCount - if pool is None or cd is None or cd.name is None or ReplStubTable is None: - return 0 - if cd.name[0] == '\0' or ReplStubCount >= _REPL_STUB_CLS_MAX: - return 0 + if pool is None or cd is None or cd.name is None or ReplStubTable is None: return 0 + if cd.name[0] == '\0' or ReplStubCount >= _REPL_STUB_CLS_MAX: return 0 key: str = _repl_stub_key(pool, sha1, cd.name) - if key is None: - return 0 - if _repl_stub_find(key) is not None: - return 0 + if key is None: return 0 + if _repl_stub_find(key) is not None: return 0 e: rawptr[ReplStubClass] = pool.alloc(ReplStubClass.__sizeof__()) - if e is None: - return 0 + if e is None: return 0 string.memset(e, 0, ReplStubClass.__sizeof__()) e.Key = key e.ClassName = _repl_stub_dupstr(pool, cd.name) @@ -4361,8 +3897,7 @@ def _repl_stub_add_class(pool: memhub.MemBuddy*, e.Names = pool.alloc(8 * _REPL_STUB_FIELD_MAX) e.Types = pool.alloc(8 * _REPL_STUB_FIELD_MAX) e.VtNames = pool.alloc(8 * _REPL_STUB_VT_MAX) - if e.OwnNames is None or e.OwnTypes is None or e.MethodNames is None or e.MethodFlags is None or e.Bases is None or e.Names is None or e.Types is None or e.VtNames is None: - return 0 + if e.OwnNames is None or e.OwnTypes is None or e.MethodNames is None or e.MethodFlags is None or e.Bases is None or e.Names is None or e.Types is None or e.VtNames is None: return 0 string.memset(e.OwnNames, 0, 8 * _REPL_STUB_FIELD_MAX) string.memset(e.OwnTypes, 0, 8 * _REPL_STUB_FIELD_MAX) string.memset(e.MethodNames, 0, 8 * _REPL_STUB_FIELD_MAX) @@ -4373,13 +3908,11 @@ def _repl_stub_add_class(pool: memhub.MemBuddy*, string.memset(e.VtNames, 0, 8 * _REPL_STUB_VT_MAX) # 类装饰器 cf: int = _repl_stub_deco_flags(cd.decorator_list) - if (cf & 2) != 0: - e.Flags = e.Flags | _REPL_SF_CVTABLE + if (cf & 2) != 0: e.Flags = e.Flags | _REPL_SF_CVTABLE if (cf & 1) != 0: e.Flags = e.Flags | _REPL_SF_NOVTABLE e.IsNoVTable = 1 - if _vpi_class_has_packed(cd.decorator_list) != 0: - e.Flags = e.Flags | _REPL_SF_PACKED + if _vpi_class_has_packed(cd.decorator_list) != 0: e.Flags = e.Flags | _REPL_SF_PACKED # 真实父类(复用 ClassGenBase._collect_parents:别名解析 + marker 剔除) pb: sizet* = pool.alloc(8 * GenTypes.PARENT_MAX) bcnt: int = 0 @@ -4388,14 +3921,12 @@ def _repl_stub_add_class(pool: memhub.MemBuddy*, bcnt = GenApi._g_gen.ClassGenBase._collect_parents( pool, cd, pb, GenTypes.PARENT_MAX, trans) if bcnt > 0: - if bcnt > _REPL_STUB_FIELD_MAX: - bcnt = _REPL_STUB_FIELD_MAX + if bcnt > _REPL_STUB_FIELD_MAX: bcnt = _REPL_STUB_FIELD_MAX bi: int for bi in range(bcnt): bnm: str = rawptr(pb[bi]) bdup: str = _repl_stub_dupstr(pool, bnm) - if bdup is not None: - e.Bases[bi] = sizet(bdup) + if bdup is not None: e.Bases[bi] = sizet(bdup) e.BaseCount = bcnt # 类体扫描:字段(AnnAssign)+ 方法(FunctionDef) children: list[ast.AST*]* = cd.children @@ -4405,20 +3936,15 @@ def _repl_stub_add_class(pool: memhub.MemBuddy*, ci: sizet for ci in range(cn): ch2: ast.AST* = children.get(ci) - if ch2 is None: - continue + if ch2 is None: continue k2: int = ch2.kind() if k2 == ast.ASTKind.AnnAssign: - if e.OwnCount >= _REPL_STUB_FIELD_MAX: - continue + if e.OwnCount >= _REPL_STUB_FIELD_MAX: continue aa2: ast.AnnAssign* = ast.AnnAssign*(ch2) - if aa2 is None or aa2.target is None or aa2.annotation is None: - continue - if aa2.target.kind() != ast.ASTKind.Name: - continue + if aa2 is None or aa2.target is None or aa2.annotation is None: continue + if aa2.target.kind() != ast.ASTKind.Name: continue tg: ast.Name* = ast.Name*(aa2.target) - if tg.id is None or tg.id[0] == '\0': - continue + if tg.id is None or tg.id[0] == '\0': continue fty2: mlirlite.LLVMType* = GenApi.resolve_annotation_type( pool, aa2.annotation, imported_modules, from_imports, trans, 0) if fty2 is None: @@ -4434,15 +3960,11 @@ def _repl_stub_add_class(pool: memhub.MemBuddy*, continue if k2 == ast.ASTKind.FunctionDef: fd2: ast.FunctionDef* = ast.FunctionDef*(ch2) - if fd2 is None or fd2.name is None or fd2.name[0] == '\0': - continue + if fd2 is None or fd2.name is None or fd2.name[0] == '\0': continue mf2: int = _repl_stub_deco_flags(fd2.decorator_list) - if (mf2 & 2) != 0: - e.Flags = e.Flags | _REPL_SF_ANYFUNC - if string.strcmp(fd2.name, "__init__") == 0: - e.HasInit = 1 - elif string.strcmp(fd2.name, "__new__") == 0: - e.HasNew = 1 + if (mf2 & 2) != 0: e.Flags = e.Flags | _REPL_SF_ANYFUNC + if string.strcmp(fd2.name, "__init__") == 0: e.HasInit = 1 + elif string.strcmp(fd2.name, "__new__") == 0: e.HasNew = 1 e.IsOOP = 1 if e.MethodCount < _REPL_STUB_FIELD_MAX: e.MethodNames[e.MethodCount] = sizet(_repl_stub_dupstr(pool, fd2.name)) @@ -4455,8 +3977,7 @@ def _repl_stub_add_class(pool: memhub.MemBuddy*, _repl_meta_scan_layout(txt, key) e.LayoutCount = ReplStubTmpCount e.VtArity = ReplStubTmpArity - if ReplStubTmpPacked != 0: - e.Flags = e.Flags | _REPL_SF_PACKED + if ReplStubTmpPacked != 0: e.Flags = e.Flags | _REPL_SF_PACKED # 状态判定 if own_fail != 0: # 字段类型解析失败:交既有 vpi 注入口径(其整类跳过),本表只做展平来源 @@ -4466,8 +3987,7 @@ def _repl_stub_add_class(pool: memhub.MemBuddy*, e.Count = e.OwnCount e.Names = e.OwnNames e.Types = e.OwnTypes - elif e.LayoutCount >= 0: - e.State = _REPL_SS_PENDING + elif e.LayoutCount >= 0: e.State = _REPL_SS_PENDING elif e.BaseCount == 0 and (e.Flags & (_REPL_SF_CVTABLE | _REPL_SF_ANYFUNC)) == 0: # 无父类、无虚表 ⇒ 本类自有字段即完整布局(与既有口径等价) e.State = _REPL_SS_EMPTY @@ -4481,16 +4001,12 @@ def _repl_stub_add_class(pool: memhub.MemBuddy*, # ③ 其余:meta 在但没有该类的 `STRUCT … FIELDS n` 记录(判据拒绝;若该类确实 # 定义于此模块则说明 meta 陈旧/不完整) e.State = _REPL_SS_REFUSED - if have_stub == 0: - _repl_stub_warn_nodata(e, _REPL_SU_NOSTUB) - elif e.LayoutCount == _REPL_STUB_NOCOUNT_OPAQUE: - _repl_stub_warn_nodata(e, _REPL_SU_OPAQUE) - else: - _repl_stub_warn_nodata(e, _REPL_SU_NOCLASS) + if have_stub == 0: _repl_stub_warn_nodata(e, _REPL_SU_NOSTUB) + elif e.LayoutCount == _REPL_STUB_NOCOUNT_OPAQUE: _repl_stub_warn_nodata(e, _REPL_SU_OPAQUE) + else: _repl_stub_warn_nodata(e, _REPL_SU_NOCLASS) ReplStubTable[ReplStubCount] = sizet(e) ReplStubCount += 1 - if e.State == _REPL_SS_PENDING: - _repl_stub_try(e, mod) + if e.State == _REPL_SS_PENDING: _repl_stub_try(e, mod) return 1 @@ -4504,10 +4020,8 @@ def _repl_stub_collect_module(pool: memhub.MemBuddy*, from_imports: str) -> int: """(REPL)为当前模块的类收集布局要素 + 尝试登记;返回处理的类数""" global ReplStubNoStub, ReplStubWarnLeft - if ReplStubLayoutMode == 0 or pool is None or ch is None: - return 0 - if src_sha1 is None or src_sha1[0] == '\0' or ReplStubTable is None: - return 0 + if ReplStubLayoutMode == 0 or pool is None or ch is None: return 0 + if src_sha1 is None or src_sha1[0] == '\0' or ReplStubTable is None: return 0 # 布局元数据({sha1}.meta;缺失:带父类/虚表的类将因"数据缺失"被明确拒绝,逐个可见) txt: str = None sp: str = _repl_stub_path(src_sha1, "meta") @@ -4515,8 +4029,7 @@ def _repl_stub_collect_module(pool: memhub.MemBuddy*, txt = _repl_stub_readtext(sp) stdlib.free(sp) have_stub: int = 0 - if txt is not None: - have_stub = 1 + if txt is not None: have_stub = 1 else: ReplStubNoStub += 1 if ReplStubWarnLeft > 0: @@ -4530,13 +4043,10 @@ def _repl_stub_collect_module(pool: memhub.MemBuddy*, i: sizet for i in range(n): child: ast.AST* = ch.get(i) - if child is None: - continue - if child.kind() != ast.ASTKind.ClassDef: - continue + if child is None: continue + if child.kind() != ast.ASTKind.ClassDef: continue cd: ast.ClassDef* = ast.ClassDef*(child) - if cd is None or cd.name is None: - continue + if cd is None or cd.name is None: continue # 泛型模板类:与 _inject_class_struct_declare / 第一遍 A 同口径跳过(模板签名 # 含类级类型参数 T,注入时 T 无法确定)。但**归属模块必须登记**:REPL 会话不 # 注册 includes 泛型模板,故注解里的泛型下标(list[rawptr[AST]] 等)要靠 @@ -4546,49 +4056,40 @@ def _repl_stub_collect_module(pool: memhub.MemBuddy*, StubMergerStore.RegisterGenericOwner(cd.name, src_sha1) continue # REnum 类:布局 {i32 tag, payload} 由 ClassGenEnum 计算,既有路径整体跳过 - if _vpi_class_is_renum(cd) != 0: - continue + if _vpi_class_is_renum(cd) != 0: continue if _repl_stub_add_class(pool, mod, cd, src_sha1, txt, have_stub, trans, imported_modules, from_imports) != 0: cnt += 1 - if txt is not None: - stdlib.free(txt) + if txt is not None: stdlib.free(txt) return cnt def ReplStubLayoutFinish() -> int: """收尾:收敛登记剩余类 + 打印汇总;返回已登记完整布局的类数""" global ReplStubRefused, ReplStubWarnLeft - if ReplStubLayoutMode == 0: - return 0 + if ReplStubLayoutMode == 0: return 0 rounds: int for rounds in range(_REPL_STUB_FINISH_PASSES): prog: int = 0 i: int for i in range(ReplStubCount): e: rawptr[ReplStubClass] = _repl_stub_at(i) - if e is None or e.State != _REPL_SS_PENDING: - continue - if _repl_stub_try(e, None) != 0: - prog += 1 - if prog == 0: - break + if e is None or e.State != _REPL_SS_PENDING: continue + if _repl_stub_try(e, None) != 0: prog += 1 + if prog == 0: break # 仍未就绪 ⇒ 父类始终未注册(缺存根/被拒):明确拒绝(本类无法展平 ⇒ 不比较) i2: int for i2 in range(ReplStubCount): e2: rawptr[ReplStubClass] = _repl_stub_at(i2) - if e2 is None or e2.State != _REPL_SS_PENDING: - continue + if e2 is None or e2.State != _REPL_SS_PENDING: continue e2.State = _REPL_SS_REFUSED # 找出仍未就绪的父类名(自证"上游是谁") pbad: str = "(未定位)" bi2: int for bi2 in range(e2.BaseCount): peb: rawptr[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 + 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 个)/ " diff --git a/App/lib/Stub/StubMerger/StubMergerBuild.vp b/App/lib/Stub/StubMerger/StubMergerBuild.vp index 0c1e377..d9991f8 100644 --- a/App/lib/Stub/StubMerger/StubMergerBuild.vp +++ b/App/lib/Stub/StubMerger/StubMergerBuild.vp @@ -35,16 +35,13 @@ import lib.Stub.StubMerger as StubMerger # ============================================================ def _IsAppModule(mod_name: str) -> int: """mod_name 是否为 App 源文件(store 命中且 incdir 为空)""" - if mod_name is None: - return 0 - if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None: - return 0 + if mod_name is None: return 0 + if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None: return 0 for i in range(StubMerger._sha1_store_count): midx: sizet = sizet(i) * 64 if string.strcmp(StubMerger._sha1_store_mod + midx, mod_name) == 0: iidx: sizet = sizet(i) * StubMerger.MAX_INC_DIR_LEN - if StubMerger._sha1_store_incdir[iidx] == '\0': - return 1 + if StubMerger._sha1_store_incdir[iidx] == '\0': return 1 return 0 return 0 # ============================================================ @@ -58,32 +55,25 @@ def _IsAppModule(mod_name: str) -> int: # ============================================================ def _AppendDepsToWorklist(worklist: bytes, wl_len: sizet, deps_str: str, processed: str) -> int: - if worklist is None or deps_str is None: - return -1 + if worklist is None or deps_str is None: return -1 cur_len: sizet = wl_len dl: sizet = string.strlen(deps_str) dpos: sizet = 0 while dpos < dl: dstart: sizet = dpos - while dpos < dl and deps_str[dpos] != ' ': - dpos += 1 + while dpos < dl and deps_str[dpos] != ' ': dpos += 1 dlen: sizet = dpos - dstart - if dpos < dl: - dpos += 1 - if dlen == 0: - continue + if dpos < dl: dpos += 1 + if dlen == 0: continue dmod: bytes = stdlib.malloc(dlen + 1) - if dmod is None: - continue + if dmod is None: continue string.strncpy(dmod, deps_str + dstart, dlen) dmod[dlen] = '\0' in_wl: int = 0 if cur_len > 0: - if GenApi.is_module_imported(worklist, dmod) != 0: - in_wl = 1 + if GenApi.is_module_imported(worklist, dmod) != 0: in_wl = 1 if in_wl == 0 and processed is not None: - if GenApi.is_module_imported(processed, dmod) != 0: - in_wl = 1 + if GenApi.is_module_imported(processed, dmod) != 0: in_wl = 1 if in_wl == 0: if cur_len + dlen + 2 < StubMerger.REACH_WORKLIST_BUF: if cur_len > 0 and worklist[cur_len - 1] != ' ': @@ -119,8 +109,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, app_deps: str = None, includes_dirs: str = None) -> int: """构建可达 SHA1 集合(依赖图按需扫描,App 优先)""" - if source_dir is None or temp_dir is None or reachable_set is None: - return -1 + 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") return -1 @@ -129,8 +118,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, # 工作列表(空格分隔的模块名) worklist: bytes = stdlib.malloc(StubMerger.REACH_WORKLIST_BUF) - if worklist is None: - return -1 + if worklist is None: return -1 worklist[0] = '\0' wl_len: sizet = 0 @@ -142,8 +130,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, es_r: sizet = IncludesScanner.FileEntry.__sizeof__() for e_i_r in range(scan_res_r.Count): e_r: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](uint64(scan_res_r.Entries) + uint64(e_i_r) * es_r) - if e_r is None or e_r.Path is None: - continue + if e_r is None or e_r.Path is None: continue # 文件级 mark:parse 完立即回收 AST(App 全量 parse 驻留会 OOM) app_mark: sizet = mb.mark() sbuf: bytes = Utils.read_file_to_buf(e_r.Path, SRC_BUF_SIZE_R) @@ -186,21 +173,16 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, im_pos_a: sizet = 0 while im_pos_a < im_len_a: im_start_a: sizet = im_pos_a - while im_pos_a < im_len_a and tr._imported_modules[im_pos_a] != ' ': - im_pos_a += 1 + while im_pos_a < im_len_a and tr._imported_modules[im_pos_a] != ' ': im_pos_a += 1 im_mod_len: sizet = im_pos_a - im_start_a - if im_pos_a < im_len_a: - im_pos_a += 1 - if im_mod_len == 0: - continue + if im_pos_a < im_len_a: im_pos_a += 1 + if im_mod_len == 0: continue im_buf_a: bytes = stdlib.malloc(im_mod_len + 1) - if im_buf_a is None: - continue + if im_buf_a is None: continue string.strncpy(im_buf_a, tr._imported_modules + im_start_a, im_mod_len) im_buf_a[im_mod_len] = '\0' in_wl_a: int = 0 - if wl_len > 0 and GenApi.is_module_imported(worklist, im_buf_a) != 0: - in_wl_a = 1 + if wl_len > 0 and GenApi.is_module_imported(worklist, im_buf_a) != 0: in_wl_a = 1 if in_wl_a == 0: if wl_len + im_mod_len + 2 < StubMerger.REACH_WORKLIST_BUF: if wl_len > 0: @@ -213,10 +195,8 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, worklist[wl_len] = '\0' stdlib.free(im_buf_a) # 释放 Translator 资源 - if tr._global_names is not None: - stdlib.free(tr._global_names) - if tr._nonlocal_names is not None: - stdlib.free(tr._nonlocal_names) + if tr._global_names is not None: stdlib.free(tr._global_names) + if tr._nonlocal_names is not None: stdlib.free(tr._nonlocal_names) stdlib.free(sbuf) mb.reset_to(app_mark) else: @@ -263,12 +243,9 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, tb_inc_slot[0] = 0 tb_found = IncludesScanner.ResolveModuleToPath( includes_dirs, "traceback", tb_abs, tb_rel, tb_inc) - if tb_abs is not None: - stdlib.free(tb_abs) - if tb_rel is not None: - stdlib.free(tb_rel) - if tb_inc is not None: - stdlib.free(tb_inc) + if tb_abs is not None: stdlib.free(tb_abs) + if tb_rel is not None: stdlib.free(tb_rel) + 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") @@ -299,19 +276,15 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, pos: sizet = wl_pos_slot[0] # 提取一个模块名(到空格或末尾) name_start: sizet = pos - while pos < wl_len and worklist[pos] != ' ': - pos += 1 + while pos < wl_len and worklist[pos] != ' ': pos += 1 name_len: sizet = pos - name_start - if pos < wl_len: - pos += 1 + if pos < wl_len: pos += 1 wl_pos_slot[0] = pos - if name_len == 0: - continue + if name_len == 0: continue # 复制模块名 mod_buf: bytes = stdlib.malloc(name_len + 1) - if mod_buf is None: - continue + if mod_buf is None: continue string.strncpy(mod_buf, worklist + name_start, name_len) mod_buf[name_len] = '\0' @@ -354,12 +327,9 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, out_rel: t.CPtr = stdlib.malloc(8) out_inc: t.CPtr = stdlib.malloc(8) if out_abs is None or out_rel is None or out_inc is None: - if out_abs is not None: - stdlib.free(out_abs) - if out_rel is not None: - stdlib.free(out_rel) - if out_inc is not None: - stdlib.free(out_inc) + if out_abs is not None: stdlib.free(out_abs) + if out_rel is not None: stdlib.free(out_rel) + if out_inc is not None: stdlib.free(out_inc) stdlib.free(mod_buf) continue # 输出槽防御性初始化(成功路径必全写;未找到/未命中时仅 free 槽本身) @@ -501,10 +471,8 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, stdlib.free(out_rel) stdlib.free(out_inc) stdlib.free(sbuf_r) - if tr_r2._global_names is not None: - stdlib.free(tr_r2._global_names) - if tr_r2._nonlocal_names is not None: - stdlib.free(tr_r2._nonlocal_names) + if tr_r2._global_names is not None: stdlib.free(tr_r2._global_names) + if tr_r2._nonlocal_names is not None: stdlib.free(tr_r2._nonlocal_names) stdlib.free(mod_buf) stdlib.free(worklist) stdlib.free(processed) @@ -525,8 +493,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, df_w: rawptr[fileio.File] = fileio.File(deps_path_w, fileio.MODE.W) if not df_w.closed: dl_w: sizet = string.strlen(deps_r2) - if dl_w > 0: - df_w.write(deps_r2, dl_w) + if dl_w > 0: df_w.write(deps_r2, dl_w) df_w.close() stdlib.free(deps_path_w) # 追加依赖到 worklist(去重防溢出) @@ -546,14 +513,11 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_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"无依赖: {rel_path}", "Reachable") # 释放 Translator 的 C malloc 资源 + 回收本文件 AST - if tr_r2._global_names is not None: - stdlib.free(tr_r2._global_names) - if tr_r2._nonlocal_names is not None: - stdlib.free(tr_r2._nonlocal_names) + if tr_r2._global_names is not None: stdlib.free(tr_r2._global_names) + if tr_r2._nonlocal_names is not None: stdlib.free(tr_r2._nonlocal_names) stdlib.free(sbuf_r) mb.reset_to(scan_mark_r) @@ -581,25 +545,21 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, def LoadFullIR(temp_dir: str, sha1: str, out_buf: bytes, out_size: sizet) -> sizet: """读取 {sha1}.full.ll 到 out_buf;返回长度(0=失败)""" - if temp_dir is None or sha1 is None or out_buf is None or out_size == 0: - return 0 + if temp_dir is None or sha1 is None or out_buf is None or out_size == 0: return 0 td_len: sizet = string.strlen(temp_dir) p: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "full.ll") - if p is None: - return 0 + if p is None: return 0 f: rawptr[fileio.File] = fileio.File(p, fileio.MODE.R) stdlib.free(p) out_buf[0] = '\0' - if f.closed: - return 0 + if f.closed: return 0 if f.size() >= out_size: f.close() VLogger.error("full.ll 超过 IR 缓冲上限", "StubMerger") return 0 rd: int64 = f.read_all(out_buf, out_size) f.close() - if rd <= 0: - return 0 + if rd <= 0: return 0 out_buf[rd] = '\0' return sizet(rd) @@ -620,10 +580,8 @@ def LoadDepVpiIntoModule(pool: memhub.MemBuddy*, temp_dir: str, trans: rawptr[HandlesTranslator.Translator]) -> int: """加载依赖模块的 .vpi 文件,将函数声明注入到当前模块""" - if pool is None or mod is None or temp_dir is None or trans is None: - return 0 - if imported_modules is None: - return 0 + if pool is None or mod is None or temp_dir is None or trans is None: return 0 + if imported_modules is None: return 0 # 每个模块的 stub 注入前重置 typedef 递归注册的防环标记: # CTypedef 表每文件隔离(translate 前 clear),visited 若跨模块残留会 @@ -642,22 +600,17 @@ def LoadDepVpiIntoModule(pool: memhub.MemBuddy*, ci: sizet = 0 while ci < total_len: # 跳过前导空格 - while ci < total_len and imported_modules[ci] == ' ': - ci += 1 - if ci >= total_len: - break + while ci < total_len and imported_modules[ci] == ' ': ci += 1 + if ci >= total_len: break # 提取模块名(到下一个空格或字符串末尾) word_start: sizet = ci - while ci < total_len and imported_modules[ci] != ' ': - ci += 1 + while ci < total_len and imported_modules[ci] != ' ': ci += 1 word_len: sizet = ci - word_start - if word_len == 0: - continue + if word_len == 0: continue # 复制模块名到临时缓冲区并 null 终止 mod_nm_buf: str = stdlib.malloc(word_len + 1) - if mod_nm_buf is None: - continue + if mod_nm_buf is None: continue string.strncpy(mod_nm_buf, imported_modules + word_start, word_len) mod_nm_buf[word_len] = '\0' @@ -667,8 +620,7 @@ def LoadDepVpiIntoModule(pool: memhub.MemBuddy*, # 改名别名(import X as Y,如 HT→lib.core.Handles.HandlesTranslator): # 精确/包名回退均失败时从 from_imports 查别名映射再查 SHA1, # 否则该类模块的 vpi/stub 不注入 → 跨模块符号解析失败 - if sha1_val is None and from_imports is not None: - sha1_val = StubMergerStore.LookupSha1ByAlias(from_imports, mod_nm_buf) + if sha1_val is None and from_imports is not None: sha1_val = StubMergerStore.LookupSha1ByAlias(from_imports, mod_nm_buf) # 如果精确查找失败,尝试包名回退(如 "ast" → "ast.__init__") # LookupSha1ByModName 内部已处理包名回退,此处无需重复 @@ -684,8 +636,7 @@ def LoadDepVpiIntoModule(pool: memhub.MemBuddy*, # 调用 VpiReader 解析 .vpi 并注入 declare # (错误上下文帧由调用方 HandlesTranslator 维护) ret: int = VpiReader.ParseVpiIntoModule(pool, mod, vpi_path, trans) - if ret == 1: - success_count += 1 + if ret == 1: success_count += 1 stdlib.free(vpi_path) # sha1_val 指向内部存储,无需 free diff --git a/App/lib/Stub/StubMerger/StubMergerCollect.vp b/App/lib/Stub/StubMerger/StubMergerCollect.vp index 611762a..c57eeb3 100644 --- a/App/lib/Stub/StubMerger/StubMergerCollect.vp +++ b/App/lib/Stub/StubMerger/StubMergerCollect.vp @@ -44,8 +44,7 @@ def _sliced_path(temp_dir: str, td_len: sizet, sha1: str, ext: str) -> str: level>0 时自动调用 ensure_dir 创建子目录。 """ - if temp_dir is None or sha1 is None or ext is None: - return None + if temp_dir is None or sha1 is None or ext is None: return None sha1_len: sizet = string.strlen(sha1) ext_len: sizet = string.strlen(ext) @@ -71,13 +70,11 @@ def _sliced_path(temp_dir: str, td_len: sizet, sha1: str, ext: str) -> str: if sub_len > 0: path_len = td_len + sub_len + sha1_len + ext_len + 4 path = stdlib.malloc(path_len) - if path is not None: - viperlib.snprintf(path, path_len, "%s/%s/%s.%s", temp_dir, subdir_buf, sha1, ext) + if path is not None: viperlib.snprintf(path, path_len, "%s/%s/%s.%s", temp_dir, subdir_buf, sha1, ext) else: path_len = td_len + sha1_len + ext_len + 3 path = stdlib.malloc(path_len) - if path is not None: - viperlib.snprintf(path, path_len, "%s/%s.%s", temp_dir, sha1, ext) + if path is not None: viperlib.snprintf(path, path_len, "%s/%s.%s", temp_dir, sha1, ext) return path @@ -96,14 +93,11 @@ def _load_includes_sha1_set(pool: memhub.MemBuddy*, 数据来源是 PopulateSha1MapStore 填充的全局存储器。 sha1_set 大小为 MAX_INCLUDES_SHA1 * 17(每个 SHA1 16字符+null) 返回找到的 includes SHA1 数量,-1 表示错误""" - if sha1_set is None: - return -1 - if StubMerger._sha1_store_arr is None: - return -1 + if sha1_set is None: return -1 + if StubMerger._sha1_store_arr is None: return -1 count: int = 0 for i in range(StubMerger._sha1_store_count): - if count >= StubMerger.MAX_INCLUDES_SHA1: - break + if count >= StubMerger.MAX_INCLUDES_SHA1: break idx: sizet = sizet(i) * 17 string.strcpy(sha1_set + sizet(count) * 17, StubMerger._sha1_store_arr + idx) count += 1 @@ -113,11 +107,9 @@ def _load_includes_sha1_set(pool: memhub.MemBuddy*, # ============================================================ def _is_in_sha1_set(sha1: str, sha1_set: str, set_count: int) -> int: """检查 sha1 是否在集合中""" - if sha1 is None or sha1_set is None: - return 0 + if sha1 is None or sha1_set is None: return 0 for i in range(set_count): - if string.strcmp(sha1_set + i * 17, sha1) == 0: - return 1 + if string.strcmp(sha1_set + i * 17, sha1) == 0: return 1 return 0 # ============================================================ # WriteIncludesSha1Map - 将 includes 扫描结果写入 _sha1_map.txt(仅人类可读的调试输出,程序内部不读取, @@ -134,20 +126,17 @@ def WriteIncludesSha1Map(mb: memhub.MemBuddy*, temp_dir: str, 若 filter_set 不为 None 且 filter_count > 0,只写入 filter_set 中的条目。 """ - if temp_dir is None or scan_result is None: - return 1 + if temp_dir is None or scan_result is None: return 1 # 构造路径 temp_dir/_sha1_map.txt dir_len: sizet = string.strlen(temp_dir) map_path: bytes = stdlib.malloc(dir_len + 32) - if map_path is None: - return 1 + if map_path is None: return 1 viperlib.snprintf(map_path, dir_len + 32, "%s/_sha1_map.txt", temp_dir) # 打开文件写入(CREATE_ALWAYS) f: rawptr[fileio.File] = fileio.File(map_path, fileio.MODE.W) - if f.closed: - return 1 + if f.closed: return 1 # 写入每个 include 条目: {sha1}:includes/{rel_path}\n entry_size_w: sizet = IncludesScanner.FileEntry.__sizeof__() @@ -160,12 +149,10 @@ def WriteIncludesSha1Map(mb: memhub.MemBuddy*, temp_dir: str, for i in range(scan_result.Count): ea_w: uint64 = uint64(scan_result.Entries) + i * entry_size_w ent_w: rawptr[IncludesScanner.FileEntry] = (rawptr[IncludesScanner.FileEntry])(ea_w) - if ent_w is None or ent_w.Sha1 is None or ent_w.RelPath is None: - continue + if ent_w is None or ent_w.Sha1 is None or ent_w.RelPath is None: continue # 若提供过滤集合,只写入集合中的条目 if filter_set is not None and filter_count > 0: - if _is_in_sha1_set(ent_w.Sha1, filter_set, filter_count) == 0: - continue + if _is_in_sha1_set(ent_w.Sha1, filter_set, filter_count) == 0: continue viperlib.snprintf(line_buf, 512, "%s:includes/%s\n", ent_w.Sha1, ent_w.RelPath) line_len_w: sizet = string.strlen(line_buf) f.write(line_buf, line_len_w) diff --git a/App/lib/Stub/StubMerger/StubMergerIR.vp b/App/lib/Stub/StubMerger/StubMergerIR.vp index 400e7b0..cf2bac4 100644 --- a/App/lib/Stub/StubMerger/StubMergerIR.vp +++ b/App/lib/Stub/StubMerger/StubMergerIR.vp @@ -76,8 +76,7 @@ def WriteModuleMeta(mod: mlirlite.LLVMModule*, temp_dir: str, VLogger.error("meta 写出:行缓冲分配失败", "Meta") break mark: str = "DECL" - if mlirlite.function_is_declared(cur) == 0: - mark = "DEF" + if mlirlite.function_is_declared(cur) == 0: mark = "DEF" viperlib.snprintf(line, nlen + 16, "FUNC %s %s\n", nm, mark) mf.write(line, string.strlen(line)) stdlib.free(line) @@ -98,10 +97,8 @@ def WriteModuleMeta(mod: mlirlite.LLVMModule*, temp_dir: str, VLogger.error("meta 写出:行缓冲分配失败", "Meta") break fc: int = mlirlite.get_struct_fcount(nt.Ty) - if fc < 0: - viperlib.snprintf(lb, tl + 48, "STRUCT %s OPAQUE\n", tn) - else: - viperlib.snprintf(lb, tl + 48, "STRUCT %s FIELDS %d PACKED %d\n", tn, fc, nt.IsPacked) + if fc < 0: viperlib.snprintf(lb, tl + 48, "STRUCT %s OPAQUE\n", tn) + else: viperlib.snprintf(lb, tl + 48, "STRUCT %s FIELDS %d PACKED %d\n", tn, fc, nt.IsPacked) mf.write(lb, string.strlen(lb)) stdlib.free(lb) nt = nt.Next @@ -123,11 +120,9 @@ def WriteModuleMeta(mod: mlirlite.LLVMModule*, temp_dir: str, string.strncpy(base, gn, base_len) base[base_len] = '\0' ar: int = mlirlite.get_struct_fcount(gv.Ty) - if ar < 0: - ar = 0 + 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 写出:行缓冲分配失败", "Meta") else: viperlib.snprintf(lb2, base_len + 40, "VTABLE %s SLOTS %d\n", base, ar) mf.write(lb2, string.strlen(lb2)) @@ -146,41 +141,32 @@ def WriteModuleMeta(mod: mlirlite.LLVMModule*, temp_dir: str, # ============================================================ def _MetaHasDef(temp_dir: str, td_len: sizet, sha1: str) -> int: """读 {sha1}.meta:含 "FUNC ... DEF" 行返回 1,无则 0,文件不可读 -1""" - if temp_dir is None or sha1 is None: - return -1 + if temp_dir is None or sha1 is None: return -1 mpath: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "meta") - if mpath is None: - return -1 + if mpath is None: return -1 mf: fileio.File = fileio.File(mpath, fileio.MODE.R) stdlib.free(mpath) - if mf.closed: - return -1 + if mf.closed: return -1 mbuf: bytes = stdlib.malloc(StubMerger.STUB_READ_BUF_SIZE) mbr: int64 = 0 - if mbuf is not None: - mbr = mf.read_all(mbuf, StubMerger.STUB_READ_BUF_SIZE) + if mbuf is not None: mbr = mf.read_all(mbuf, StubMerger.STUB_READ_BUF_SIZE) mf.close() - if mbuf is None: - return -1 + if mbuf is None: return -1 if mbr <= 0: # 空 meta:无 DEF,纯声明 stdlib.free(mbuf) return 0 - if mbr < StubMerger.STUB_READ_BUF_SIZE: - mbuf[mbr] = '\0' + if mbr < StubMerger.STUB_READ_BUF_SIZE: mbuf[mbr] = '\0' # 逐行扫描:行尾 " DEF" 即为实现文件 mpos: sizet = 0 while mpos < mbr: mls: sizet = mpos while mpos < mbr: - if mbuf[mpos] == '\n': - break + if mbuf[mpos] == '\n': break mpos += 1 mll: sizet = mpos - mls - if mpos < mbr: - mpos += 1 - if mll > 0 and mbuf[mls + mll - 1] == '\r': - mll -= 1 + if mpos < mbr: mpos += 1 + if mll > 0 and mbuf[mls + mll - 1] == '\r': mll -= 1 if mll >= 10 and string.strncmp(mbuf + mls, "FUNC ", 5) == 0: if mbuf[mls + mll - 4] == ' ' and string.strncmp(mbuf + mls + mll - 3, "DEF", 3) == 0: stdlib.free(mbuf) @@ -199,10 +185,8 @@ def _MetaHasDef(temp_dir: str, td_len: sizet, sha1: str) -> int: def IsDeclOnlyModule(temp_dir: str, td_len: sizet, sha1: str) -> int: """判断模块是否为纯声明文件(meta 无 FUNC ... DEF 行)""" h: int = _MetaHasDef(temp_dir, td_len, sha1) - if h < 0: - return -1 - if h == 1: - return 0 + if h < 0: return -1 + if h == 1: return 0 return 1 # ============================================================ # _is_submodule_of_imported - 检查模块名是否是已导入包的子模块 @@ -212,15 +196,12 @@ def IsDeclOnlyModule(temp_dir: str, td_len: sizet, sha1: str) -> int: # ============================================================ def _is_submodule_of_imported(deps_buf: str, mod_name: str) -> int: """检查 mod_name 是否是 deps_buf 中已导入包的子模块""" - if deps_buf is None or mod_name is None: - return 0 + if deps_buf is None or mod_name is None: return 0 # 查找第一个 '.',提取顶层包名 dot_pos: str = string.strchr(mod_name, 46) # '.' = 46 - if dot_pos is None: - return 0 + if dot_pos is None: return 0 pkg_len: sizet = sizet(uint64(dot_pos) - uint64(mod_name)) - if pkg_len == 0 or pkg_len >= 256: - return 0 + if pkg_len == 0 or pkg_len >= 256: return 0 # 构造顶层包名(截断到 '.' 之前) # 直接在 mod_name 上临时截断检查,避免分配 saved_ch: char = mod_name[pkg_len] @@ -243,14 +224,11 @@ def _BuildIncludesSha1Map(temp_dir: str, td_len: sizet, temp_dir/td_len 参数保留以兼容现有调用者,但不再使用。 数据来源是 PopulateSha1MapStore 填充的全局存储器。 """ - if sha1_list is None or mod_list is None: - return 0 - if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None: - return 0 + if sha1_list is None or mod_list is None: return 0 + if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None: return 0 count: int = 0 for i in range(StubMerger._sha1_store_count): - if count >= StubMerger.MAX_INCLUDES: - break + if count >= StubMerger.MAX_INCLUDES: break idx: sizet = sizet(i) * 17 idx2: sizet = sizet(i) * 64 string.strcpy(sha1_list + sizet(count) * 17, StubMerger._sha1_store_arr + idx) @@ -270,10 +248,8 @@ def _FindSha1ByModName(sha1_arr: str, mod_arr: str, 精确匹配失败时,尝试 "{mod_name}.__init__" 回退, 支持 import ast(包)→ ast.__init__ 的 SHA1 查找。 """ - if sha1_arr is None or mod_arr is None or mod_name is None: - return None - if count <= 0: - return None + if sha1_arr is None or mod_arr is None or mod_name is None: return None + if count <= 0: return None # 第一遍:精确匹配 for i in range(count): idx: sizet = sizet(i) * 64 @@ -303,12 +279,10 @@ def _FindSha1ByModName(sha1_arr: str, mod_arr: str, # ============================================================ def _AddSha1ToSet(set_buf: str, count: int, sha1: str) -> int: """将 SHA1 加入集合,返回新 count""" - if set_buf is None or sha1 is None: - return count + if set_buf is None or sha1 is None: return count for i in range(count): idx: sizet = sizet(i) * 17 - if string.strcmp(set_buf + idx, sha1) == 0: - return count + if string.strcmp(set_buf + idx, sha1) == 0: return count if count < StubMerger.MAX_INCLUDES_SHA1: idx: sizet = sizet(count) * 17 string.strcpy(set_buf + idx, sha1) diff --git a/App/lib/Stub/StubMerger/StubMergerStore.vp b/App/lib/Stub/StubMerger/StubMergerStore.vp index bafe0cd..1d0bb1b 100644 --- a/App/lib/Stub/StubMerger/StubMergerStore.vp +++ b/App/lib/Stub/StubMerger/StubMergerStore.vp @@ -57,13 +57,11 @@ class ImportCtx: # ============================================================ def AppendImportedModule(pool: memhub.MemBuddy*, cur: str, name: str) -> str: """追加模块名到空格分隔列表(pool 分配),返回新列表""" - if name is None: - return cur + if name is None: return cur if cur is None: nlen: sizet = string.strlen(name) buf: str = pool.alloc(nlen + 1) - if buf is not None: - string.strcpy(buf, name) + if buf is not None: string.strcpy(buf, name) return buf old_len: sizet = string.strlen(cur) name_len: sizet = string.strlen(name) @@ -85,8 +83,7 @@ def AppendImportedModule(pool: memhub.MemBuddy*, cur: str, name: str) -> str: def AppendFromImport(pool: memhub.MemBuddy*, cur: str, local: str, mod: str, orig: str) -> str: """追加 from-import 映射(pool 分配),返回新列表""" - if local is None or mod is None: - return cur + if local is None or mod is None: return cur llen: sizet = string.strlen(local) mlen: sizet = string.strlen(mod) use_orig: int = 0 @@ -96,19 +93,16 @@ def AppendFromImport(pool: memhub.MemBuddy*, cur: str, olen = string.strlen(orig) # local ':' mod [':' orig] '\0' need: sizet = llen + 1 + mlen + 1 - if use_orig != 0: - need += 1 + olen + if use_orig != 0: need += 1 + olen entry: str = pool.alloc(need) - if entry is None: - return cur + if entry is None: return cur string.strcpy(entry, local) entry[llen] = ':' string.strcpy(entry + llen + 1, mod) if use_orig != 0: entry[llen + 1 + mlen] = ':' string.strcpy(entry + llen + 1 + mlen + 1, orig) - if cur is None: - return entry + if cur is None: return entry old_len: sizet = string.strlen(cur) entry_len: sizet = string.strlen(entry) buf: str = pool.alloc(old_len + 1 + entry_len + 1) @@ -126,8 +120,7 @@ def AllocImportCtx(pool: memhub.MemBuddy*, imported_modules: str, from_imports: str) -> ImportCtx*: """构造导入上下文容器(pool 分配);两串可为 None""" ctx: ImportCtx* = pool.alloc(ImportCtx.__sizeof__()) - if ctx is None: - return None + if ctx is None: return None ctx.ImportedModules = imported_modules ctx.FromImports = from_imports return ctx @@ -144,8 +137,7 @@ def AllocImportCtx(pool: memhub.MemBuddy*, def NotePlainImport(pool: memhub.MemBuddy*, ctx: ImportCtx*, name: str, asname: str) -> int: """记账单条 import(就地更新 ctx),返回 0""" - if ctx is None or name is None: - return 1 + if ctx is None or name is None: return 1 ctx.ImportedModules = AppendImportedModule(pool, ctx.ImportedModules, name) if asname is not None: ctx.ImportedModules = AppendImportedModule(pool, ctx.ImportedModules, asname) @@ -178,23 +170,17 @@ def PopulateSha1MapStore(scan_result: rawptr[IncludesScanner.ScanResult]) -> int 模块名通过 _PathToModuleName(includes/rel_path) 计算。 内存用 stdlib.malloc 分配(全局存储器,不随 mbuddy 释放)。 """ - if scan_result is None: - return -1 + if scan_result is None: return -1 # 释放旧存储器 - if StubMerger._sha1_store_arr is not None: - stdlib.free(StubMerger._sha1_store_arr) - if StubMerger._sha1_store_mod is not None: - stdlib.free(StubMerger._sha1_store_mod) - if StubMerger._sha1_store_rel is not None: - stdlib.free(StubMerger._sha1_store_rel) - if StubMerger._sha1_store_incdir is not None: - stdlib.free(StubMerger._sha1_store_incdir) + if StubMerger._sha1_store_arr is not None: stdlib.free(StubMerger._sha1_store_arr) + if StubMerger._sha1_store_mod is not None: stdlib.free(StubMerger._sha1_store_mod) + if StubMerger._sha1_store_rel is not None: stdlib.free(StubMerger._sha1_store_rel) + if StubMerger._sha1_store_incdir is not None: stdlib.free(StubMerger._sha1_store_incdir) StubMerger._sha1_store_arr = stdlib.malloc(StubMerger.MAX_INCLUDES * 17) StubMerger._sha1_store_mod = stdlib.malloc(StubMerger.MAX_INCLUDES * 64) StubMerger._sha1_store_rel = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_REL_PATH_LEN) StubMerger._sha1_store_incdir = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_INC_DIR_LEN) - if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None: - return -1 + if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None: return -1 string.memset(StubMerger._sha1_store_arr, 0, StubMerger.MAX_INCLUDES * 17) string.memset(StubMerger._sha1_store_mod, 0, StubMerger.MAX_INCLUDES * 64) string.memset(StubMerger._sha1_store_rel, 0, StubMerger.MAX_INCLUDES * StubMerger.MAX_REL_PATH_LEN) @@ -203,8 +189,7 @@ def PopulateSha1MapStore(scan_result: rawptr[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 存储超上限,终止", "StubMerger") ea: uint64 = uint64(scan_result.Entries) + i * entry_size_p ent: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](ea) if ent is None or ent.Sha1 is None or ent.RelPath is None: @@ -224,16 +209,14 @@ def PopulateSha1MapStore(scan_result: rawptr[IncludesScanner.ScanResult]) -> int string.strcpy(StubMerger._sha1_store_arr + idx, ent.Sha1) idx2: sizet = sizet(StubMerger._sha1_store_count) * 64 mn_len: sizet = string.strlen(mod_name) - if mn_len < 64: - string.strcpy(StubMerger._sha1_store_mod + idx2, mod_name) + if mn_len < 64: string.strcpy(StubMerger._sha1_store_mod + idx2, mod_name) else: string.strncpy(StubMerger._sha1_store_mod + idx2, mod_name, 63) StubMerger._sha1_store_mod[idx2 + 63] = '\0' stdlib.free(mod_name) # 保存 rel_path(供 Phase2 3.5 编译缺失 includes 使用) idx3: sizet = sizet(StubMerger._sha1_store_count) * StubMerger.MAX_REL_PATH_LEN - if rp_len < StubMerger.MAX_REL_PATH_LEN: - string.strcpy(StubMerger._sha1_store_rel + idx3, ent.RelPath) + if rp_len < StubMerger.MAX_REL_PATH_LEN: string.strcpy(StubMerger._sha1_store_rel + idx3, ent.RelPath) else: string.strncpy(StubMerger._sha1_store_rel + idx3, ent.RelPath, StubMerger.MAX_REL_PATH_LEN - 1) StubMerger._sha1_store_rel[idx3 + StubMerger.MAX_REL_PATH_LEN - 1] = '\0' @@ -241,14 +224,12 @@ def PopulateSha1MapStore(scan_result: rawptr[IncludesScanner.ScanResult]) -> int idx_inc: sizet = sizet(StubMerger._sha1_store_count) * StubMerger.MAX_INC_DIR_LEN if ent.IncDir is not None: icd_len: sizet = string.strlen(ent.IncDir) - if icd_len < StubMerger.MAX_INC_DIR_LEN: - string.strcpy(StubMerger._sha1_store_incdir + idx_inc, ent.IncDir) + if icd_len < StubMerger.MAX_INC_DIR_LEN: string.strcpy(StubMerger._sha1_store_incdir + idx_inc, ent.IncDir) else: 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 存储有 {p_bad} 个条目失败", "StubMerger") return StubMerger._sha1_store_count # ============================================================ # AppendToSha1MapStore - 追加 App 模块条目到全局 SHA1 映射存储器(Phase1 先用 PopulateSha1MapStore 填 includes, @@ -260,32 +241,27 @@ def PopulateSha1MapStore(scan_result: rawptr[IncludesScanner.ScanResult]) -> int # ============================================================ def AppendToSha1MapStore(sha1: str, rel_path: str) -> int: """追加条目到全局 SHA1 映射存储器(Phase2 用)""" - if sha1 is None or rel_path is None: - return 1 + if sha1 is None or rel_path is None: return 1 # 存储器未初始化:自动初始化(Phase2 可能先于 Phase1 调用) if StubMerger._sha1_store_arr is None: StubMerger._sha1_store_arr = stdlib.malloc(StubMerger.MAX_INCLUDES * 17) StubMerger._sha1_store_mod = stdlib.malloc(StubMerger.MAX_INCLUDES * 64) StubMerger._sha1_store_rel = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_REL_PATH_LEN) StubMerger._sha1_store_incdir = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_INC_DIR_LEN) - if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None: - return 1 + if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None: return 1 string.memset(StubMerger._sha1_store_arr, 0, StubMerger.MAX_INCLUDES * 17) string.memset(StubMerger._sha1_store_mod, 0, StubMerger.MAX_INCLUDES * 64) string.memset(StubMerger._sha1_store_rel, 0, StubMerger.MAX_INCLUDES * StubMerger.MAX_REL_PATH_LEN) string.memset(StubMerger._sha1_store_incdir, 0, StubMerger.MAX_INCLUDES * StubMerger.MAX_INC_DIR_LEN) StubMerger._sha1_store_count = 0 - if StubMerger._sha1_store_count >= StubMerger.MAX_INCLUDES: - return 1 + if StubMerger._sha1_store_count >= StubMerger.MAX_INCLUDES: return 1 # 模块名:rel_path "lib/core/StubMerger.vp" → "lib.core.StubMerger" full_path_buf: bytes = stdlib.malloc(string.strlen(rel_path) + 10) - if full_path_buf is None: - return 1 + if full_path_buf is None: return 1 viperlib.snprintf(full_path_buf, string.strlen(rel_path) + 10, "includes/%s", rel_path) mod_name: str = Utils.PathToModuleName(full_path_buf, 1) stdlib.free(full_path_buf) - if mod_name is None: - return 1 + if mod_name is None: return 1 # 去重:SHA1 与模块名都相同才跳过——同一 SHA1 可能先以全路径模块名注册(App 源文件在 includes 目录下), # App 追加的短模块名必须保留,否则 import 该模块的精确查找失败、后缀匹配会劫持到其它同名模块。 for i in range(StubMerger._sha1_store_count): @@ -301,8 +277,7 @@ def AppendToSha1MapStore(sha1: str, rel_path: str) -> int: # 写入模块名 idx_m: sizet = sizet(StubMerger._sha1_store_count) * 64 mn_len: sizet = string.strlen(mod_name) - if mn_len < 64: - string.strcpy(StubMerger._sha1_store_mod + idx_m, mod_name) + if mn_len < 64: string.strcpy(StubMerger._sha1_store_mod + idx_m, mod_name) else: string.strncpy(StubMerger._sha1_store_mod + idx_m, mod_name, 63) StubMerger._sha1_store_mod[idx_m + 63] = '\0' @@ -310,8 +285,7 @@ def AppendToSha1MapStore(sha1: str, rel_path: str) -> int: # 写入相对路径 idx_r: sizet = sizet(StubMerger._sha1_store_count) * StubMerger.MAX_REL_PATH_LEN rp_len: sizet = string.strlen(rel_path) - if rp_len < StubMerger.MAX_REL_PATH_LEN: - string.strcpy(StubMerger._sha1_store_rel + idx_r, rel_path) + if rp_len < StubMerger.MAX_REL_PATH_LEN: string.strcpy(StubMerger._sha1_store_rel + idx_r, rel_path) else: string.strncpy(StubMerger._sha1_store_rel + idx_r, rel_path, StubMerger.MAX_REL_PATH_LEN - 1) StubMerger._sha1_store_rel[idx_r + StubMerger.MAX_REL_PATH_LEN - 1] = '\0' @@ -330,46 +304,40 @@ def AppendToSha1MapStore(sha1: str, rel_path: str) -> int: # ============================================================ def AddIncludeToSha1MapStore(sha1: str, rel_path: str, inc_dir: str, mod_name: str) -> int: """单条登记 includes 条目到全局 SHA1 映射存储器(依赖图按需扫描用)""" - if sha1 is None or rel_path is None or mod_name is None: - return 1 + if sha1 is None or rel_path is None or mod_name is None: return 1 # 存储器未初始化:自动初始化 if StubMerger._sha1_store_arr is None: StubMerger._sha1_store_arr = stdlib.malloc(StubMerger.MAX_INCLUDES * 17) StubMerger._sha1_store_mod = stdlib.malloc(StubMerger.MAX_INCLUDES * 64) StubMerger._sha1_store_rel = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_REL_PATH_LEN) StubMerger._sha1_store_incdir = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_INC_DIR_LEN) - if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None: - return 1 + if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None: return 1 string.memset(StubMerger._sha1_store_arr, 0, StubMerger.MAX_INCLUDES * 17) string.memset(StubMerger._sha1_store_mod, 0, StubMerger.MAX_INCLUDES * 64) string.memset(StubMerger._sha1_store_rel, 0, StubMerger.MAX_INCLUDES * StubMerger.MAX_REL_PATH_LEN) string.memset(StubMerger._sha1_store_incdir, 0, StubMerger.MAX_INCLUDES * StubMerger.MAX_INC_DIR_LEN) StubMerger._sha1_store_count = 0 - if StubMerger._sha1_store_count >= StubMerger.MAX_INCLUDES: - return 1 + if StubMerger._sha1_store_count >= StubMerger.MAX_INCLUDES: return 1 # 去重:SHA1 与模块名都相同才跳过(对齐 AppendToSha1MapStore) for i in range(StubMerger._sha1_store_count): sidx_d: sizet = sizet(i) * 17 if string.strcmp(StubMerger._sha1_store_arr + sidx_d, sha1) == 0: midx_d: sizet = sizet(i) * 64 - if string.strcmp(StubMerger._sha1_store_mod + midx_d, mod_name) == 0: - return 0 + if string.strcmp(StubMerger._sha1_store_mod + midx_d, mod_name) == 0: return 0 # 写 SHA1 idx_a: sizet = sizet(StubMerger._sha1_store_count) * 17 string.strcpy(StubMerger._sha1_store_arr + idx_a, sha1) # 写模块名 idx_m: sizet = sizet(StubMerger._sha1_store_count) * 64 mn_len: sizet = string.strlen(mod_name) - if mn_len < 64: - string.strcpy(StubMerger._sha1_store_mod + idx_m, mod_name) + if mn_len < 64: string.strcpy(StubMerger._sha1_store_mod + idx_m, mod_name) else: string.strncpy(StubMerger._sha1_store_mod + idx_m, mod_name, 63) StubMerger._sha1_store_mod[idx_m + 63] = '\0' # 写相对路径 idx_r: sizet = sizet(StubMerger._sha1_store_count) * StubMerger.MAX_REL_PATH_LEN rp_len: sizet = string.strlen(rel_path) - if rp_len < StubMerger.MAX_REL_PATH_LEN: - string.strcpy(StubMerger._sha1_store_rel + idx_r, rel_path) + if rp_len < StubMerger.MAX_REL_PATH_LEN: string.strcpy(StubMerger._sha1_store_rel + idx_r, rel_path) else: string.strncpy(StubMerger._sha1_store_rel + idx_r, rel_path, StubMerger.MAX_REL_PATH_LEN - 1) StubMerger._sha1_store_rel[idx_r + StubMerger.MAX_REL_PATH_LEN - 1] = '\0' @@ -377,13 +345,11 @@ def AddIncludeToSha1MapStore(sha1: str, rel_path: str, inc_dir: str, mod_name: s idx_inc: sizet = sizet(StubMerger._sha1_store_count) * StubMerger.MAX_INC_DIR_LEN if inc_dir is not None: icd_len: sizet = string.strlen(inc_dir) - if icd_len < StubMerger.MAX_INC_DIR_LEN: - string.strcpy(StubMerger._sha1_store_incdir + idx_inc, inc_dir) + if icd_len < StubMerger.MAX_INC_DIR_LEN: string.strcpy(StubMerger._sha1_store_incdir + idx_inc, inc_dir) else: string.strncpy(StubMerger._sha1_store_incdir + idx_inc, inc_dir, StubMerger.MAX_INC_DIR_LEN - 1) StubMerger._sha1_store_incdir[idx_inc + StubMerger.MAX_INC_DIR_LEN - 1] = '\0' - else: - StubMerger._sha1_store_incdir[idx_inc] = '\0' + else: StubMerger._sha1_store_incdir[idx_inc] = '\0' StubMerger._sha1_store_count += 1 return 0 # ============================================================ @@ -446,26 +412,21 @@ def RegisterGenericOwner(cls_name: str, mod_sha1: str) -> int: 同名异 sha1(跨模块同名泛型类)保留首个,与泛型模板表按类名去重的口径一致。 """ global _generic_owner_names, _generic_owner_sha1s, _generic_owner_count - if cls_name is None or mod_sha1 is None: - return 0 - if cls_name[0] == '\0' or mod_sha1[0] == '\0': - return 0 + if cls_name is None or mod_sha1 is None: return 0 + if cls_name[0] == '\0' or mod_sha1[0] == '\0': return 0 if _generic_owner_names is None: _generic_owner_names = stdlib.malloc(GENERIC_OWNER_MAX * 64) _generic_owner_sha1s = stdlib.malloc(GENERIC_OWNER_MAX * 17) - if _generic_owner_names is None or _generic_owner_sha1s is None: - return 0 + if _generic_owner_names is None or _generic_owner_sha1s is None: return 0 string.memset(_generic_owner_names, 0, GENERIC_OWNER_MAX * 64) string.memset(_generic_owner_sha1s, 0, GENERIC_OWNER_MAX * 17) _generic_owner_count = 0 i_go: int for i_go in range(_generic_owner_count): if string.strcmp(_generic_owner_names + sizet(i_go) * 64, cls_name) == 0: - if string.strcmp(_generic_owner_sha1s + sizet(i_go) * 17, mod_sha1) == 0: - return 1 + if string.strcmp(_generic_owner_sha1s + sizet(i_go) * 17, mod_sha1) == 0: return 1 return 0 - if _generic_owner_count >= GENERIC_OWNER_MAX: - return 0 + if _generic_owner_count >= GENERIC_OWNER_MAX: return 0 string.strncpy(_generic_owner_names + sizet(_generic_owner_count) * 64, cls_name, 63) string.strncpy(_generic_owner_sha1s + sizet(_generic_owner_count) * 17, mod_sha1, 16) _generic_owner_count += 1 @@ -474,12 +435,10 @@ def RegisterGenericOwner(cls_name: str, mod_sha1: str) -> int: def LookupGenericOwnerSha1(cls_name: str) -> str: """按泛型类名取定义模块 SHA1(返回内部指针,无需释放;未登记 None)""" - if cls_name is None or _generic_owner_names is None: - return None + if cls_name is None or _generic_owner_names is None: return None i_lg: int for i_lg in range(_generic_owner_count): - if string.strcmp(_generic_owner_names + sizet(i_lg) * 64, cls_name) == 0: - return _generic_owner_sha1s + sizet(i_lg) * 17 + if string.strcmp(_generic_owner_names + sizet(i_lg) * 64, cls_name) == 0: return _generic_owner_sha1s + sizet(i_lg) * 17 return None # ============================================================ # LookupSha1ByModNameSuffix - 后缀匹配查找模块 SHA1(用于 from .X import Y:impf.module 是 ".X",而映射表键是 "pkg.X") @@ -489,22 +448,17 @@ def LookupGenericOwnerSha1(cls_name: str) -> str: # ============================================================ def LookupSha1ByModNameSuffix(mod_suffix: str) -> str: """后缀匹配查找模块 SHA1""" - if mod_suffix is None: - return None - if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None: - return None - if StubMerger._sha1_store_count <= 0: - return None + if mod_suffix is None: return None + if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None: return None + if StubMerger._sha1_store_count <= 0: return None suffix_len_sf: sizet = string.strlen(mod_suffix) - if suffix_len_sf == 0: - return None + if suffix_len_sf == 0: return None i_sf: int for i_sf in range(StubMerger._sha1_store_count): idx_sf: sizet = sizet(i_sf) * 64 mod_name_sf: str = StubMerger._sha1_store_mod + idx_sf mod_len_sf: sizet = string.strlen(mod_name_sf) - if mod_len_sf == 0: - continue + if mod_len_sf == 0: continue # 精确匹配 if mod_len_sf == suffix_len_sf: if string.strcmp(mod_name_sf, mod_suffix) == 0: @@ -534,23 +488,18 @@ def LookupSha1ByModNameSuffix(mod_suffix: str) -> str: # ============================================================ def LookupSha1ByAlias(from_imports: str, alias: str) -> str: """从 from_imports 别名映射解析模块 SHA1(改名别名 import X as Y 场景)""" - if from_imports is None or alias is None: - return None + if from_imports is None or alias is None: return None alias_len: sizet = string.strlen(alias) - if alias_len == 0: - return None + if alias_len == 0: return None total_len: sizet = string.strlen(from_imports) ci: sizet = 0 while ci < total_len: # 跳过前导空格 - while ci < total_len and from_imports[ci] == ' ': - ci += 1 - if ci >= total_len: - break + while ci < total_len and from_imports[ci] == ' ': ci += 1 + if ci >= total_len: break # 条目起点 ci,找 ':'(local_name 结束) colon: sizet = ci - while colon < total_len and from_imports[colon] != ':' and from_imports[colon] != ' ': - colon += 1 + while colon < total_len and from_imports[colon] != ':' and from_imports[colon] != ' ': colon += 1 local_len: sizet = colon - ci if colon < total_len and from_imports[colon] == ':' and local_len == alias_len: # 比较 local_name == alias @@ -565,8 +514,7 @@ def LookupSha1ByAlias(from_imports: str, alias: str) -> str: # 提取 module(colon+1 到下一个 ':' 或空格) m_start: sizet = colon + 1 m_end: sizet = m_start - while m_end < total_len and from_imports[m_end] != ':' and from_imports[m_end] != ' ': - m_end += 1 + while m_end < total_len and from_imports[m_end] != ':' and from_imports[m_end] != ' ': m_end += 1 if m_end > m_start: mbuf: str = stdlib.malloc(m_end - m_start + 1) if mbuf is not None: @@ -577,8 +525,7 @@ def LookupSha1ByAlias(from_imports: str, alias: str) -> str: return res return None # 跳到下一条目 - while ci < total_len and from_imports[ci] != ' ': - ci += 1 + while ci < total_len and from_imports[ci] != ' ': ci += 1 return None # ============================================================ # LookupModNameByAlias - 从 from_imports 别名映射解析模块真名 @@ -589,23 +536,18 @@ def LookupSha1ByAlias(from_imports: str, alias: str) -> str: # ============================================================ def LookupModNameByAlias(from_imports: str, alias: str) -> str: """从 from_imports 别名映射解析模块真名(import X as Y → Y:X)""" - if from_imports is None or alias is None: - return None + if from_imports is None or alias is None: return None alias_len: sizet = string.strlen(alias) - if alias_len == 0: - return None + if alias_len == 0: return None total_len: sizet = string.strlen(from_imports) ci: sizet = 0 while ci < total_len: # 跳过前导空格 - while ci < total_len and from_imports[ci] == ' ': - ci += 1 - if ci >= total_len: - break + while ci < total_len and from_imports[ci] == ' ': ci += 1 + if ci >= total_len: break # 条目起点 ci,找 ':'(local_name 结束) colon: sizet = ci - while colon < total_len and from_imports[colon] != ':' and from_imports[colon] != ' ': - colon += 1 + while colon < total_len and from_imports[colon] != ':' and from_imports[colon] != ' ': colon += 1 local_len: sizet = colon - ci if colon < total_len and from_imports[colon] == ':' and local_len == alias_len: # 比较 local_name == alias @@ -620,8 +562,7 @@ def LookupModNameByAlias(from_imports: str, alias: str) -> str: # 提取 module(colon+1 到下一个 ':' 或空格) m_start: sizet = colon + 1 m_end: sizet = m_start - while m_end < total_len and from_imports[m_end] != ':' and from_imports[m_end] != ' ': - m_end += 1 + while m_end < total_len and from_imports[m_end] != ':' and from_imports[m_end] != ' ': m_end += 1 if m_end > m_start: mbuf: str = stdlib.malloc(m_end - m_start + 1) if mbuf is not None: @@ -630,8 +571,7 @@ def LookupModNameByAlias(from_imports: str, alias: str) -> str: return mbuf return None # 跳到下一条目 - while ci < total_len and from_imports[ci] != ' ': - ci += 1 + while ci < total_len and from_imports[ci] != ' ': ci += 1 return None # ============================================================ # PopulateIncludesDeps - 将 includes 文件的依赖存入内存 @@ -642,24 +582,20 @@ def LookupModNameByAlias(from_imports: str, alias: str) -> str: # ============================================================ def PopulateIncludesDeps(sha1: str, deps_str: str) -> int: """将 includes 文件的依赖存入内存""" - if sha1 is None: - return 1 + if sha1 is None: return 1 # 延迟初始化 if StubMerger._includes_deps_sha1 is None: StubMerger._includes_deps_sha1 = stdlib.malloc(StubMerger.MAX_INCLUDES * 17) StubMerger._includes_deps_str = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_DEPS_STR_LEN) - if StubMerger._includes_deps_sha1 is None or StubMerger._includes_deps_str is None: - return 1 + if StubMerger._includes_deps_sha1 is None or StubMerger._includes_deps_str is None: return 1 string.memset(StubMerger._includes_deps_sha1, 0, StubMerger.MAX_INCLUDES * 17) string.memset(StubMerger._includes_deps_str, 0, StubMerger.MAX_INCLUDES * StubMerger.MAX_DEPS_STR_LEN) StubMerger._includes_deps_count = 0 - if StubMerger._includes_deps_count >= StubMerger.MAX_INCLUDES: - return 1 + if StubMerger._includes_deps_count >= StubMerger.MAX_INCLUDES: return 1 # 去重:若 SHA1 已存在则跳过 for i in range(StubMerger._includes_deps_count): sidx: sizet = sizet(i) * 17 - if string.strcmp(StubMerger._includes_deps_sha1 + sidx, sha1) == 0: - return 0 + if string.strcmp(StubMerger._includes_deps_sha1 + sidx, sha1) == 0: return 0 # 写入 SHA1 idx: sizet = sizet(StubMerger._includes_deps_count) * 17 string.strcpy(StubMerger._includes_deps_sha1 + idx, sha1) @@ -667,12 +603,9 @@ def PopulateIncludesDeps(sha1: str, deps_str: str) -> int: idx2: sizet = sizet(StubMerger._includes_deps_count) * StubMerger.MAX_DEPS_STR_LEN if deps_str is not None: dl: sizet = string.strlen(deps_str) - if dl < StubMerger.MAX_DEPS_STR_LEN: - string.strcpy(StubMerger._includes_deps_str + idx2, deps_str) - else: - string.strncpy(StubMerger._includes_deps_str + idx2, deps_str, StubMerger.MAX_DEPS_STR_LEN - 1) - else: - StubMerger._includes_deps_str[idx2] = '\0' + if dl < StubMerger.MAX_DEPS_STR_LEN: string.strcpy(StubMerger._includes_deps_str + idx2, deps_str) + else: string.strncpy(StubMerger._includes_deps_str + idx2, deps_str, StubMerger.MAX_DEPS_STR_LEN - 1) + else: StubMerger._includes_deps_str[idx2] = '\0' StubMerger._includes_deps_count = StubMerger._includes_deps_count + 1 return 0 # ============================================================ @@ -686,10 +619,8 @@ def PopulateIncludesDeps(sha1: str, deps_str: str) -> int: # ============================================================ def LookupIncludesDeps(sha1: str) -> str: """从内存查找 includes 文件的依赖""" - if sha1 is None or StubMerger._includes_deps_sha1 is None: - return None - if StubMerger._includes_deps_count <= 0: - return None + if sha1 is None or StubMerger._includes_deps_sha1 is None: return None + if StubMerger._includes_deps_count <= 0: return None for i in range(StubMerger._includes_deps_count): sidx: sizet = sizet(i) * 17 if string.strcmp(StubMerger._includes_deps_sha1 + sidx, sha1) == 0: @@ -721,19 +652,14 @@ def GetSha1StoreArr(out_sha1_arr: rawptr[t.CPtr], out_mod_arr: rawptr[t.CPtr], o out_sha1_arr/out_mod_arr/out_rel_arr 是调用者提供的 t.CPtr 槽的地址(t.CPtr*), 函数把存储器数组指针写入这些槽。返回条目数,-1 失败 """ - if out_sha1_arr is None or out_mod_arr is None or out_rel_arr is None: - return -1 - if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None: - return -1 + if out_sha1_arr is None or out_mod_arr is None or out_rel_arr is None: return -1 + if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None: return -1 sp: rawptr[t.CPtr] = out_sha1_arr - if sp is not None: - sp[0] = StubMerger._sha1_store_arr + if sp is not None: sp[0] = StubMerger._sha1_store_arr mp: rawptr[t.CPtr] = out_mod_arr - if mp is not None: - mp[0] = StubMerger._sha1_store_mod + if mp is not None: mp[0] = StubMerger._sha1_store_mod rp: rawptr[t.CPtr] = out_rel_arr - if rp is not None: - rp[0] = StubMerger._sha1_store_rel + if rp is not None: rp[0] = StubMerger._sha1_store_rel return StubMerger._sha1_store_count # ============================================================ @@ -745,10 +671,8 @@ def GetSha1StoreArr(out_sha1_arr: rawptr[t.CPtr], out_mod_arr: rawptr[t.CPtr], o # ============================================================ def LookupSha1RelPath(sha1: str) -> str: """通过 SHA1 查找相对路径,返回只读指针,None=未找到""" - if sha1 is None: - return None - if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_rel is None: - return None + if sha1 is None: return None + if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_rel is None: return None for i in range(StubMerger._sha1_store_count): sidx: sizet = sizet(i) * 17 if string.strcmp(StubMerger._sha1_store_arr + sidx, sha1) == 0: @@ -776,10 +700,8 @@ def LookupSha1RelPath(sha1: str) -> str: # ============================================================ def LookupModNameBySha1(sha1: str) -> str: """通过 SHA1 查找模块名,返回只读指针,None=未找到""" - if sha1 is None or sha1[0] == '\0': - return None - if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None: - return None + if sha1 is None or sha1[0] == '\0': return None + if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None: return None for i in range(StubMerger._sha1_store_count): sidx_mb: sizet = sizet(i) * 17 if string.strcmp(StubMerger._sha1_store_arr + sidx_mb, sha1) == 0: diff --git a/App/lib/Stub/StubMerger/StubMergerTopo.vp b/App/lib/Stub/StubMerger/StubMergerTopo.vp index 92fcb45..19f25fc 100644 --- a/App/lib/Stub/StubMerger/StubMergerTopo.vp +++ b/App/lib/Stub/StubMerger/StubMergerTopo.vp @@ -46,18 +46,14 @@ def BuildTopoSortedIndices(store_count: int, store_sha1_arr: bytes, reachable_count: int, sorted_idx: sizet*) -> int: """对可达 includes 逆拓扑排序(被依赖者先),store 索引写入 sorted_idx""" - if store_count <= 0 or store_sha1_arr is None or store_mod_arr is None or sorted_idx is None: - return 0 + if store_count <= 0 or store_sha1_arr is None or store_mod_arr is None or sorted_idx is None: return 0 indegree: sizet* = (sizet*)(stdlib.malloc(8 * (store_count + 1))) queue: sizet* = (sizet*)(stdlib.malloc(8 * (store_count + 1))) rel_idx: sizet* = (sizet*)(stdlib.malloc(8 * (store_count + 1))) if indegree is None or queue is None or rel_idx is None: - if indegree is not None: - stdlib.free(indegree) - if queue is not None: - stdlib.free(queue) - if rel_idx is not None: - stdlib.free(rel_idx) + if indegree is not None: stdlib.free(indegree) + if queue is not None: stdlib.free(queue) + if rel_idx is not None: stdlib.free(rel_idx) return 0 # 清零 indegree/queue/rel_idx(malloc 返回未初始化内存,Kahn 依赖入度初值 0) zi: int = 0 @@ -82,22 +78,17 @@ def BuildTopoSortedIndices(store_count: int, store_sha1_arr: bytes, for i_r in range(rel_count): si: int = rel_idx[i_r] deps_si: str = StubMergerStore.LookupIncludesDeps(store_sha1_arr + sizet(si) * 17) - if deps_si is None: - continue + if deps_si is None: continue dl_si: sizet = string.strlen(deps_si) dpos: sizet = 0 while dpos < dl_si: dstart: sizet = dpos - while dpos < dl_si and deps_si[dpos] != ' ': - dpos += 1 + while dpos < dl_si and deps_si[dpos] != ' ': dpos += 1 dlen: sizet = dpos - dstart - if dpos < dl_si: - dpos += 1 - if dlen == 0: - continue + if dpos < dl_si: dpos += 1 + if dlen == 0: continue dname_buf: bytes = stdlib.malloc(dlen + 1) - if dname_buf is None: - continue + if dname_buf is None: continue string.strncpy(dname_buf, deps_si + dstart, dlen) dname_buf[dlen] = '\0' dsha1: str = StubMergerIR._FindSha1ByModName(store_sha1_arr, store_mod_arr, store_count, dname_buf) @@ -127,25 +118,19 @@ def BuildTopoSortedIndices(store_count: int, store_sha1_arr: bytes, mod_m_len: sizet = string.strlen(mod_m) for i_r in range(rel_count): si3: int = rel_idx[i_r] - if indegree[si3] == 0: - continue + if indegree[si3] == 0: continue deps_si3: str = StubMergerStore.LookupIncludesDeps(store_sha1_arr + sizet(si3) * 17) - if deps_si3 is None: - continue + if deps_si3 is None: continue dl_si3: sizet = string.strlen(deps_si3) dpos3: sizet = 0 found_dep: int = 0 while dpos3 < dl_si3 and found_dep == 0: dstart3: sizet = dpos3 - while dpos3 < dl_si3 and deps_si3[dpos3] != ' ': - dpos3 += 1 + while dpos3 < dl_si3 and deps_si3[dpos3] != ' ': dpos3 += 1 dlen3: sizet = dpos3 - dstart3 - if dpos3 < dl_si3: - dpos3 += 1 - if dlen3 == 0: - continue - if dlen3 == mod_m_len and string.strncmp(deps_si3 + dstart3, mod_m, mod_m_len) == 0: - found_dep = 1 + if dpos3 < dl_si3: dpos3 += 1 + if dlen3 == 0: continue + if dlen3 == mod_m_len and string.strncmp(deps_si3 + dstart3, mod_m, mod_m_len) == 0: found_dep = 1 if found_dep == 1: # 中间 int 变量递减:绕过联合类型指针算术编译 bug indg3: int = indegree[si3] diff --git a/App/lib/core/Gen/AssignGenMixin.vp b/App/lib/core/Gen/AssignGenMixin.vp index c9c9271..d3ccecb 100644 --- a/App/lib/core/Gen/AssignGenMixin.vp +++ b/App/lib/core/Gen/AssignGenMixin.vp @@ -39,15 +39,12 @@ novirtual class AssignGenMixin: k: int = annot.kind() if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(annot) - if at.attr is not None and string.strcmp(at.attr, "CDefine") == 0: - return 1 + if at.attr is not None and string.strcmp(at.attr, "CDefine") == 0: return 1 return 0 if k == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(annot) - if self.is_cdefine_annotation(bop.left) != 0: - return 1 - if self.is_cdefine_annotation(bop.right) != 0: - return 1 + if self.is_cdefine_annotation(bop.left) != 0: return 1 + if self.is_cdefine_annotation(bop.right) != 0: return 1 return 0 # ============================================================ @@ -66,8 +63,7 @@ novirtual class AssignGenMixin: 64 位返回:大整数 CDefine(如 sys.maxsize=9223372036854775807) 必须全精度提取,否则 int(32 位) 截断成 -1(SysLibTest maxsize FAIL 根因)。 """ - if val_node is None: - return 0 + if val_node is None: return 0 k: int = val_node.kind() # Case 1: Constant(INT) — 如 0x0002 @@ -75,8 +71,7 @@ novirtual class AssignGenMixin: cn: ast.Constant* = ast.Constant*(val_node) # True/False 布尔常量 → 1/0(对齐 TPC:bool 在 CDefine 语境按整数处理, # 如 SHADOW_ENABLED: t.CDefine = False) - if cn.const_kind == ast.CONST_BOOL: - return 1 if cn.int_val != 0 else 0 + if cn.const_kind == ast.CONST_BOOL: return 1 if cn.int_val != 0 else 0 if cn.const_kind != ast.CONST_INT: # 非 INT 常量:直接报错终止(fail-fast) self.Gen.TypeGenErr.fatal_error(val_node, "CDefine 值提取失败:无法从表达式解析编译期常量", "TypeError") @@ -106,13 +101,10 @@ novirtual class AssignGenMixin: nm: ast.Name* = ast.Name*(val_node) if nm.id is not None: # True/False 布尔字面量 → 1/0(bool 在 CDefine 语境按整数处理) - if string.strcmp(nm.id, "True") == 0: - return 1 - if string.strcmp(nm.id, "False") == 0: - return 0 + if string.strcmp(nm.id, "True") == 0: return 1 + if string.strcmp(nm.id, "False") == 0: return 0 looked_up: int64 = self.Gen.TypeGenCDef.lookup_cdefine_constant(nm.id) - if self.Gen.TypeGenCDef.is_cdefine_found() != 0: - return looked_up + if self.Gen.TypeGenCDef.is_cdefine_found() != 0: return looked_up # 引用未注册:直接报错终止(fail-fast) self.Gen.TypeGenErr.fatal_error(val_node, "CDefine 值提取失败:无法从表达式解析编译期常量", "TypeError") @@ -176,39 +168,29 @@ novirtual class AssignGenMixin: -2^31 改用**算术表达式**(`-2147483647 - 1`),两者都不含危险字面量。 """ if value < 0: - if value >= -128: - return 8 - if value >= -32768: - return 16 + if value >= -128: return 8 + if value >= -32768: return 16 # -2^31:字面量 2147483648 同样落 i32,改用安全字面量的算术等价式 - if value >= -2147483647 - 1: - return 32 + if value >= -2147483647 - 1: return 32 return 64 - if value <= 255: - return 8 - if value <= 65535: - return 16 - if value <= 2147483647: - return 32 + if value <= 255: return 8 + if value <= 65535: return 16 + if value <= 2147483647: return 32 # 2^31 .. 2^32-1:uint32 回绕后仍等于原值 ⇒ 可容于无符号 32 位位模式 - if uint64(uint32(value)) == value: - return 32 + if uint64(uint32(value)) == value: return 32 return 64 def _is_cdefine_marker_node(self, node: ast.AST*) -> int: """节点是否为 t.CDefine 标记(Attribute.attr / Name.id == "CDefine")""" - if node is None: - return 0 + if node is None: return 0 k: int = node.kind() if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(node) - if at.attr is not None and string.strcmp(at.attr, "CDefine") == 0: - return 1 + if at.attr is not None and string.strcmp(at.attr, "CDefine") == 0: return 1 return 0 if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) - if nm.id is not None and string.strcmp(nm.id, "CDefine") == 0: - return 1 + if nm.id is not None and string.strcmp(nm.id, "CDefine") == 0: return 1 return 0 def _define_explicit_annot(self, annot: ast.AST*) -> ast.AST*: @@ -219,15 +201,11 @@ novirtual class AssignGenMixin: `t.CDefine | T`(既有手写惯用法,如 CODE_SEG: t.CDefine | uint16)⇒ 首个是 CDefine 标记 ⇒ 无显式类型 ⇒ **既有声明行为逐字不变**。 """ - if annot is None: - return None - if annot.kind() != ast.ASTKind.BinOp: - return None + if annot is None: return None + if annot.kind() != ast.ASTKind.BinOp: return None bop: ast.BinOp* = ast.BinOp*(annot) - if bop.left is None: - return None - if self._is_cdefine_marker_node(bop.left) != 0: - return None + if bop.left is None: return None + if self._is_cdefine_marker_node(bop.left) != 0: return None return bop.left def _annot_int_bits(self, pool: memhub.MemBuddy*, @@ -239,8 +217,7 @@ novirtual class AssignGenMixin: `int` / `bool` 两个"注解直通名"补在此表(TPC: int → int 32 位、 bool → 8 位,与 include/builtins 口径一致)。 """ - if annot is None: - return 0 + if annot is None: return 0 k: int = annot.kind() nm: str = None if k == ast.ASTKind.Attribute: @@ -249,33 +226,22 @@ novirtual class AssignGenMixin: elif k == ast.ASTKind.Name: n2: ast.Name* = ast.Name*(annot) nm = n2.id - if nm is None: - return 0 - if string.strcmp(nm, "int") == 0: - return 32 - if string.strcmp(nm, "bool") == 0: - return 8 + if nm is None: return 0 + if string.strcmp(nm, "int") == 0: return 32 + if string.strcmp(nm, "bool") == 0: return 8 # stdint.vp / builtins 的定长小写别名(非 t 模块名,map_t_type 不认): # 与 TPC EnumMemberAnnotationIntWidth 走 builtins typedef 表的同口径。 - if string.strcmp(nm, "int8") == 0 or string.strcmp(nm, "uint8") == 0: - return 8 - if string.strcmp(nm, "int16") == 0 or string.strcmp(nm, "uint16") == 0: - return 16 - if string.strcmp(nm, "int32") == 0 or string.strcmp(nm, "uint32") == 0: - return 32 - if string.strcmp(nm, "int64") == 0 or string.strcmp(nm, "uint64") == 0: - return 64 - if string.strcmp(nm, "sizet") == 0 or string.strcmp(nm, "size_t") == 0: - return 64 + if string.strcmp(nm, "int8") == 0 or string.strcmp(nm, "uint8") == 0: return 8 + if string.strcmp(nm, "int16") == 0 or string.strcmp(nm, "uint16") == 0: return 16 + if string.strcmp(nm, "int32") == 0 or string.strcmp(nm, "uint32") == 0: return 32 + if string.strcmp(nm, "int64") == 0 or string.strcmp(nm, "uint64") == 0: return 64 + if string.strcmp(nm, "sizet") == 0 or string.strcmp(nm, "size_t") == 0: return 64 ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.map_t_type(pool, nm) - if ty is None: - return 0 + if ty is None: return 0 match ty: case mlirlite.LLVMType.Int(bits): - if bits == 1: - return 8 - if bits == 8 or bits == 16 or bits == 32 or bits == 64: - return bits + if bits == 1: return 8 + if bits == 8 or bits == 16 or bits == 32 or bits == 64: return bits return 0 case _: return 0 @@ -295,14 +261,11 @@ novirtual class AssignGenMixin: 是 int64,超出 int64 的字面量已在词法层回绕(lexer.vp `string.atoll`) ⇒ 只有源文本可靠。读取失败 / 未命中 → None。 """ - if name is None: - return None + if name is None: return None fp: str = self.Gen.TypeGenResolve.get_current_file() - if fp is None: - return None + if fp is None: return None f: rawptr[fileio.File] = fileio.File(fp, fileio.MODE.R) - if f.closed: - return None + if f.closed: return None BUF_SZ: sizet = 1048576 buf: bytes = stdlib.malloc(BUF_SZ) if buf is None: @@ -313,55 +276,40 @@ novirtual class AssignGenMixin: if nrd <= 0: stdlib.free(buf) return None - if nrd < BUF_SZ: - buf[nrd] = 0 + if nrd < BUF_SZ: buf[nrd] = 0 name_len: sizet = string.strlen(name) total_len: sizet = string.strlen(buf) pos: sizet = 0 result: str = None while pos < total_len: line_start: sizet = pos - while pos < total_len and buf[pos] != '\n': - pos += 1 + while pos < total_len and buf[pos] != '\n': pos += 1 line_len: sizet = pos - line_start - if pos < total_len: - pos += 1 - if line_len < name_len + 1: - continue + if pos < total_len: pos += 1 + if line_len < name_len + 1: continue ok: int = 1 ki: sizet for ki in range(name_len): if buf[line_start + ki] != name[ki]: ok = 0 break - if ok == 0: - continue + if ok == 0: continue sep: sizet = line_start + name_len - while sep < line_start + line_len and buf[sep] == ' ': - sep += 1 - if sep >= line_start + line_len: - continue - if buf[sep] != ':' and buf[sep] != '=': - continue + while sep < line_start + line_len and buf[sep] == ' ': sep += 1 + if sep >= line_start + line_len: continue + if buf[sep] != ':' and buf[sep] != '=': continue eq: sizet = line_start - while eq < line_start + line_len and buf[eq] != '=': - eq += 1 - if eq >= line_start + line_len: - continue + while eq < line_start + line_len and buf[eq] != '=': eq += 1 + if eq >= line_start + line_len: continue eq += 1 - while eq < line_start + line_len and buf[eq] == ' ': - eq += 1 + while eq < line_start + line_len and buf[eq] == ' ': eq += 1 vstart: sizet = eq - while eq < line_start + line_len and buf[eq] != ' ' and buf[eq] != '\t' and buf[eq] != '#' and buf[eq] != '\r': - eq += 1 - if eq == vstart: - continue + while eq < line_start + line_len and buf[eq] != ' ' and buf[eq] != '\t' and buf[eq] != '#' and buf[eq] != '\r': eq += 1 + if eq == vstart: continue txt: str = stdlib.malloc(eq - vstart + 1) - if txt is None: - continue + if txt is None: continue vi: sizet - for vi in range(eq - vstart): - txt[vi] = buf[vstart + vi] + for vi in range(eq - vstart): txt[vi] = buf[vstart + vi] txt[eq - vstart] = 0 result = txt break @@ -377,20 +325,16 @@ novirtual class AssignGenMixin: 十六进制(0x/0X):去 '_' 与前导零后 > 16 位 ⇒ 超出。 其余(表达式 / 浮点 / 字符串)⇒ 0(不进入本判据,由注册处的 AST 求值判据负责)。 """ - if text is None: - return 0 + if text is None: return 0 tl: sizet = string.strlen(text) - if tl == 0: - return 0 + if tl == 0: return 0 neg: int = 0 i: sizet = 0 if text[0] == '-': neg = 1 i = 1 - elif text[0] == '+': - i = 1 - if i >= tl: - return 0 + elif text[0] == '+': i = 1 + if i >= tl: return 0 if i + 1 < tl and text[i] == '0' and (text[i + 1] == 'x' or text[i + 1] == 'X'): # 十六进制:去 '_' 与前导零后的有效位数(>16 位 ⇒ 超出 64 位) sig: sizet = 0 @@ -399,56 +343,44 @@ novirtual class AssignGenMixin: while j2 < tl: c2: char = text[j2] j2 += 1 - if c2 == '_': - continue + if c2 == '_': continue if not ((c2 >= '0' and c2 <= '9') or (c2 >= 'a' and c2 <= 'f') or (c2 >= 'A' and c2 <= 'F')): return 0 - if leading != 0 and c2 == '0': - continue + if leading != 0 and c2 == '0': continue leading = 0 sig += 1 - if sig > 16: - return 1 + if sig > 16: return 1 return 0 # 十进制:定位首个非零有效位 s: sizet = i - while s < tl and (text[s] == '0' or text[s] == '_'): - s += 1 + while s < tl and (text[s] == '0' or text[s] == '_'): s += 1 digits2: int = 0 j3: sizet = s while j3 < tl: c3: char = text[j3] j3 += 1 - if c3 == '_': - continue - if c3 < '0' or c3 > '9': - return 0 + if c3 == '_': continue + if c3 < '0' or c3 > '9': return 0 digits2 += 1 - if digits2 == 0: - return 0 + if digits2 == 0: return 0 max_text: str = "18446744073709551615" mlen: sizet = 20 if neg != 0: max_text = "9223372036854775808" mlen = 19 - if digits2 > mlen: - return 1 - if digits2 < mlen: - return 0 + if digits2 > mlen: return 1 + if digits2 < mlen: return 0 # 等长(len(max_text) 位):逐位字典序比较(同位数时字典序 = 数值序) d: sizet = 0 k2: sizet = s while k2 < tl and d < mlen: c4: char = text[k2] k2 += 1 - if c4 == '_': - continue + if c4 == '_': continue mc: char = max_text[d] - if c4 > mc: - return 1 - if c4 < mc: - return 0 + if c4 > mc: return 1 + if c4 < mc: return 0 d += 1 return 0 @@ -478,8 +410,7 @@ novirtual class AssignGenMixin: f"修法: 把值改到 64 位范围内,或为该数字引入更大的整数类型(扩容)。", "TypeError") return - if bits == 0: - return + if bits == 0: return # 32 位档的上下界用**安全字面量**构造(同一字面量纪律,见 define_min_width): # 2147483648 / 4294967295 落在 [0x80000000, 0xFFFFFFFF],被 TPC 编译时会被压成 # i32 并在提升/赋值时按有符号解释,存在与现场同族的隐患;改用 2^31-1 的 @@ -493,8 +424,7 @@ novirtual class AssignGenMixin: elif bits == 16: lo = -32768 hi = 65535 - elif bits == 64: - return + elif bits == 64: return if value < lo or value > hi: self.Gen.TypeGenErr.fatal_error(node, f"[TPV] define 常量数值不可存储: 常量 '{name}' 的初始值 {value} 不可存储。" @@ -520,25 +450,18 @@ novirtual class AssignGenMixin: 判定:`w >= W_min` ⇒ 通过(消费端按 T 物化/升宽,即"上下文更宽 ⇒ 用使用处宽度");`w < W_min` ⇒ 报错终止(替换静默截断)。 """ - if value_node is None or target_annot is None: - return - if value_node.kind() != ast.ASTKind.Name: - return + if value_node is None or target_annot is None: return + if value_node.kind() != ast.ASTKind.Name: return rn: ast.Name* = ast.Name*(value_node) - if rn.id is None: - return + if rn.id is None: return if trans is not None: - if self.Gen.VarGen.lookup_var(trans.SymTab, rn.id) is not None: - return + if self.Gen.VarGen.lookup_var(trans.SymTab, rn.id) is not None: return cdef_val: int64 = self.Gen.TypeGenCDef.lookup_cdefine_constant(rn.id) - if self.Gen.TypeGenCDef.is_cdefine_found() == 0: - return + if self.Gen.TypeGenCDef.is_cdefine_found() == 0: return bits: int = self._annot_int_bits(pool, target_annot) - if bits == 0: - return + if bits == 0: return wmin: int = self.define_min_width(cdef_val) - if bits >= wmin: - return + if bits >= wmin: return self.Gen.TypeGenErr.fatal_error(value_node, f"[TPV] define 常量使用处宽度不足: 常量 '{rn.id}' 的实际值 {cdef_val} " f"需要至少 {wmin} 位(最小可容纳宽度 W_min)," @@ -562,8 +485,7 @@ novirtual class AssignGenMixin: name: str, val_node: ast.AST*, annot: ast.AST* = None) -> None: """注册 CDefine 常量(浮点字面量 → register_cdefine_double,否则整数)""" - if pool is None or name is None: - return + if pool is None or name is None: return # Call 包装的常量:如 PI: t.CDefine = float(3.14159...) / # t.CFloat64T(2.5) / t.CDouble(1.0)。取第一个参数作为真实值节点, # 再按 Constant 分支处理(浮点 → register_cdefine_double)。 @@ -573,8 +495,7 @@ novirtual class AssignGenMixin: cl_args_cd: list[ast.AST*]* = cl_cd.args if len(cl_args_cd) > 0: first_arg_cd: ast.AST* = cl_args_cd.get(0) - if first_arg_cd is not None and first_arg_cd.kind() == ast.ASTKind.Constant: - val_node = first_arg_cd + if first_arg_cd is not None and first_arg_cd.kind() == ast.ASTKind.Constant: val_node = first_arg_cd # 负浮点字面量(`define NAME: double = -1e308`):RHS 是 # UnaryOp(USub, Constant(CONST_FLOAT)),不是裸 Constant ⇒ 否则会落到下方的 # 整数提取,报"无法从表达式解析编译期常量"。此处只剥掉一层一元负号,把内层 @@ -586,8 +507,7 @@ novirtual class AssignGenMixin: uu_cd: ast.UnaryOp* = ast.UnaryOp*(val_node) if uu_cd is not None and uu_cd.op == ast.OpKind.USub and uu_cd.operand is not None and uu_cd.operand.kind() == ast.ASTKind.Constant: ic_cd: ast.Constant* = ast.Constant*(uu_cd.operand) - if ic_cd is not None and ic_cd.const_kind == ast.CONST_FLOAT: - val_node = uu_cd.operand + if ic_cd is not None and ic_cd.const_kind == ast.CONST_FLOAT: val_node = uu_cd.operand if val_node is not None and val_node.kind() == ast.ASTKind.Constant: cn_fp: ast.Constant* = ast.Constant*(val_node) if cn_fp.const_kind == ast.CONST_STR: @@ -600,8 +520,7 @@ novirtual class AssignGenMixin: # 源文件文本不受影响;用输出参数绕开跨模块 double 返回值传递 bug) use_val: double = cn_fp.float_val rec_d: double = 0.0 - if self._recover_cdefine_float(name, t.CPtr(&rec_d)) != 0: - use_val = rec_d + if self._recover_cdefine_float(name, t.CPtr(&rec_d)) != 0: use_val = rec_d else: # 源文件恢复失败:直接报错终止(fail-fast),避免注册被 pool 覆写的错误浮点值 self.Gen.TypeGenErr.fatal_error(val_node, "CDefine 浮点值源文件恢复失败", "InternalCompilerError") @@ -637,11 +556,9 @@ novirtual class AssignGenMixin: """ self.RecoverFound = 0 fp: str = self.Gen.TypeGenResolve.get_current_file() - if fp is None or name is None or out is None: - return 0 + if fp is None or name is None or out is None: return 0 f: rawptr[fileio.File] = fileio.File(fp, fileio.MODE.R) - if f.closed: - return 0 + if f.closed: return 0 BUF_SZ: sizet = 1048576 buf: bytes = stdlib.malloc(BUF_SZ) if buf is None: @@ -652,19 +569,16 @@ novirtual class AssignGenMixin: if nrd <= 0: stdlib.free(buf) return 0 - if nrd < BUF_SZ: - buf[nrd] = 0 + if nrd < BUF_SZ: buf[nrd] = 0 name_len: sizet = string.strlen(name) total_len: sizet = string.strlen(buf) pos: sizet = 0 while pos < total_len: line_start: sizet = pos - while pos < total_len and buf[pos] != '\n': - pos += 1 + while pos < total_len and buf[pos] != '\n': pos += 1 line_len: sizet = pos - line_start - if pos < total_len: - pos += 1 + if pos < total_len: pos += 1 # `define NAME: T = V`(宏常量关键字形式):名字前有 "define " 前缀, # 且行内没有 t.CDefine 文本(CDefine 标记来自关键字本身,见 @@ -675,8 +589,7 @@ novirtual class AssignGenMixin: if line_len >= 8: if buf[ns] == 'd' and buf[ns + 1] == 'e' and buf[ns + 2] == 'f' and buf[ns + 3] == 'i' and buf[ns + 4] == 'n' and buf[ns + 5] == 'e': nb: sizet = ns + 6 - while nb < line_start + line_len and (buf[nb] == ' ' or buf[nb] == '\t'): - nb += 1 + while nb < line_start + line_len and (buf[nb] == ' ' or buf[nb] == '\t'): nb += 1 # 后随空白才算关键字(避免匹配到 defineX 之类的标识符) if nb > ns + 6: is_define_line = 1 @@ -684,23 +597,18 @@ novirtual class AssignGenMixin: # 匹配行首(或 define 之后)的 "name",其后(跳过空格)必须是 ':' 或 '=' # (AnnAssign:`NAME: t.CDouble = 1.0`;无注解赋值:`NAME = 1.0`; # 宏常量:`define NAME: double = 3.14`) - if ns + name_len + 1 > line_start + line_len: - continue + if ns + name_len + 1 > line_start + line_len: continue match_ok: int = 1 ki: sizet for ki in range(name_len): if buf[ns + ki] != name[ki]: match_ok = 0 break - if match_ok == 0: - continue + if match_ok == 0: continue sep: sizet = ns + name_len - while sep < line_start + line_len and buf[sep] == ' ': - sep += 1 - if sep >= line_start + line_len: - continue - if buf[sep] != ':' and buf[sep] != '=': - continue + while sep < line_start + line_len and buf[sep] == ' ': sep += 1 + if sep >= line_start + line_len: continue + if buf[sep] != ':' and buf[sep] != '=': continue # CDefine 路径要求行内出现 "t.CDefine",或本行是 `define` 关键字形式 # (宏常量 `define NAME: T = V` 行内无 t.CDefine 文本);普通浮点全局 @@ -715,18 +623,14 @@ novirtual class AssignGenMixin: has_cd = 1 break ci += 1 - if has_cd == 0: - continue + if has_cd == 0: continue # 找 '=' eq: sizet = line_start - while eq < line_start + line_len and buf[eq] != '=': - eq += 1 - if eq >= line_start + line_len: - continue + while eq < line_start + line_len and buf[eq] != '=': eq += 1 + if eq >= line_start + line_len: continue eq += 1 - while eq < line_start + line_len and buf[eq] == ' ': - eq += 1 + while eq < line_start + line_len and buf[eq] == ' ': eq += 1 # Call 包装的浮点常量(t.CDouble(1.0) / float(3.14...)):跳过 "float(" 等 # 前缀,从括号内首个数字/符号/'.' 起取值(否则 atof 只认数字恒得 0.0)。 # 裸字面量(3.14 / -1.5)首字符已是数字/符号/'.',不受影响。 @@ -741,18 +645,15 @@ novirtual class AssignGenMixin: break pfx_rf += 1 val_start: sizet = eq - while eq < line_start + line_len and buf[eq] != ' ' and buf[eq] != '\t' and buf[eq] != '#' and buf[eq] != '\r' and buf[eq] != '\n': - eq += 1 - if eq == val_start: - continue + while eq < line_start + line_len and buf[eq] != ' ' and buf[eq] != '\t' and buf[eq] != '#' and buf[eq] != '\r' and buf[eq] != '\n': eq += 1 + if eq == val_start: continue val_txt: str = stdlib.malloc(eq - val_start + 1) if val_txt is None: stdlib.free(buf) return 0 vi: sizet - for vi in range(eq - val_start): - val_txt[vi] = buf[val_start + vi] + for vi in range(eq - val_start): val_txt[vi] = buf[val_start + vi] val_txt[eq - val_start] = 0 stdlib.free(buf) # 用 atof_out(输出参数)绕开跨模块 double 返回值传递 bug @@ -775,25 +676,20 @@ novirtual class AssignGenMixin: # ============================================================ def _annotation_contains_name(self, annot: ast.AST*, name: str) -> int: """递归检查注解中是否包含指定名称,返回 1=包含 / 0=不包含""" - if annot is None or name is None: - return 0 + if annot is None or name is None: return 0 k: int = annot.kind() if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(annot) - if at.attr is not None and string.strcmp(at.attr, name) == 0: - return 1 + if at.attr is not None and string.strcmp(at.attr, name) == 0: return 1 return 0 if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(annot) - if nm.id is not None and string.strcmp(nm.id, name) == 0: - return 1 + if nm.id is not None and string.strcmp(nm.id, name) == 0: return 1 return 0 if k == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(annot) - if self._annotation_contains_name(bop.left, name) != 0: - return 1 - if self._annotation_contains_name(bop.right, name) != 0: - return 1 + if self._annotation_contains_name(bop.left, name) != 0: return 1 + if self._annotation_contains_name(bop.right, name) != 0: return 1 return 0 # ============================================================ @@ -810,18 +706,13 @@ novirtual class AssignGenMixin: # ============================================================ def _is_ptr_element_annotation(self, annot: ast.AST*) -> int: """检查注解是否为 bytes* 或 str* 形式""" - if annot is None: - return 0 + if annot is None: return 0 k: int = annot.kind() - if k != ast.ASTKind.BinOp: - return 0 + if k != ast.ASTKind.BinOp: return 0 bop: ast.BinOp* = ast.BinOp*(annot) - if bop.op != ast.OpKind.BitOr: - return 0 - if self._annotation_contains_name(annot, "str") != 0: - return 1 - if self._annotation_contains_name(annot, "bytes") != 0: - return 1 + if bop.op != ast.OpKind.BitOr: return 0 + if self._annotation_contains_name(annot, "str") != 0: return 1 + if self._annotation_contains_name(annot, "bytes") != 0: return 1 # 泛型类型参数/嵌套联合 | t.CPtr(如 _list.vp 的 elem_ptr: T*): # 先经泛型上下文解析 T 的具体类型——纯标量(int/float 等 sizeof≠8)时 # 元素按标量自身大小(list[int] elem_size=4 匹配 i32),不能按 8 字节 @@ -842,16 +733,14 @@ novirtual class AssignGenMixin: gp_resolved: str = self.Gen.TypeGenBase.resolve_generic_type_name(gp_nm) if gp_resolved is not None and string.strcmp(gp_resolved, gp_nm) != 0: # 泛型参数解析为纯标量 → 元素按标量自身大小(非 8 字节指针槽) - if self._is_scalar_ty_name(gp_resolved) != 0: - return 0 + if self._is_scalar_ty_name(gp_resolved) != 0: return 0 return 1 # 64 位标量数值类型 | CPtr(如 CUInt64T* / CSizeT*): # 联合解析后同样退化为指针表示,元素为 8 字节(i64 或指针)。 # 下标必须按 8 字节步长读写——否则 GEP 步长 1 + trunc i8 截断, # 指针存进数组只剩低 1 字节(BuddyTest OOM/fill 的 ptrs 数组全错位: # store i8 trunc i64、读回 inttoptr i8 丢高 56 位,free 全部无效)。 - if self._is_64bit_scalar_ty(bop.left) != 0 or self._is_64bit_scalar_ty(bop.right) != 0: - return 1 + if self._is_64bit_scalar_ty(bop.left) != 0 or self._is_64bit_scalar_ty(bop.right) != 0: return 1 return 0 def _stg_ty_equal(self, pool: memhub.MemBuddy*, @@ -868,19 +757,15 @@ novirtual class AssignGenMixin: (VKernel devfs devfs_init 双 storage + 栈临时 self 根因)。改为 TypePrint 内容比较(命名结构体比名字、匿名结构体比字段布局)。 """ - if ta is None or tb is None: - return 0 + if ta is None or tb is None: return 0 # 快路径:同一实例直接相等 - if uint64(ta) == uint64(tb): - return 1 + if uint64(ta) == uint64(tb): return 1 buf_a: str = pool.alloc(512) buf_b: str = pool.alloc(512) - if buf_a is None or buf_b is None: - return 0 + if buf_a is None or buf_b is None: return 0 mlirlite.TypePrint(buf_a, 512, ta, pool) mlirlite.TypePrint(buf_b, 512, tb, pool) - if buf_a[0] == 0 or buf_b[0] == 0: - return 0 + if buf_a[0] == 0 or buf_b[0] == 0: return 0 return 1 if string.strcmp(buf_a, buf_b) == 0 else 0 def _is_addrlike_call(self, node: ast.AST*) -> int: @@ -891,19 +776,14 @@ novirtual class AssignGenMixin: X = &Y 应直接 store &Y 到 @X(X 与 Y 指向同一对象),若误绑定则 @X 自指 X.stg 并值复制 Y 的当前值(devfs DevFSObject 脱钩根因)。 """ - if node is None or node.kind() != ast.ASTKind.Call: - return 0 + if node is None or node.kind() != ast.ASTKind.Call: return 0 cl: ast.Call* = ast.Call*(node) - if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute: - return 0 + if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute: return 0 at: ast.Attribute* = ast.Attribute*(cl.func) - if at.value is None or at.value.kind() != ast.ASTKind.Name: - return 0 + if at.value is None or at.value.kind() != ast.ASTKind.Name: return 0 vn: ast.Name* = ast.Name*(at.value) - if vn.id is None or string.strcmp(vn.id, "c") != 0: - return 0 - if at.attr is None: - return 0 + if vn.id is None or string.strcmp(vn.id, "c") != 0: return 0 + if at.attr is None: return 0 if string.strcmp(at.attr, "Addr") == 0: return 1 if string.strcmp(at.attr, "Deref") == 0: return 1 if string.strcmp(at.attr, "Cast") == 0: return 1 @@ -912,8 +792,7 @@ novirtual class AssignGenMixin: def _is_64bit_scalar_ty(self, node: ast.AST*) -> int: """判断类型节点是否为 64 位标量数值类型(CUInt64T/CInt64T/CSizeT),元素 8 字节""" - if node is None: - return 0 + if node is None: return 0 ty_nm: str = None nk: int = node.kind() if nk == ast.ASTKind.Name: @@ -922,14 +801,10 @@ novirtual class AssignGenMixin: elif nk == ast.ASTKind.Attribute: at64: ast.Attribute* = ast.Attribute*(node) ty_nm = at64.attr - if ty_nm is None: - return 0 - if string.strcmp(ty_nm, "CUInt64T") == 0: - return 1 - if string.strcmp(ty_nm, "CInt64T") == 0: - return 1 - if string.strcmp(ty_nm, "CSizeT") == 0: - return 1 + if ty_nm is None: return 0 + if string.strcmp(ty_nm, "CUInt64T") == 0: return 1 + if string.strcmp(ty_nm, "CInt64T") == 0: return 1 + if string.strcmp(ty_nm, "CSizeT") == 0: return 1 return 0 def _is_scalar_ty_name(self, ty_name: str) -> int: @@ -946,27 +821,18 @@ novirtual class AssignGenMixin: 走通用路径生成 Value* → list[str].get 声明 i8* 与 ret Value* 不匹配 (8fbba llc 报错根因)。改白名单:已知标量才 1,未知类名按 8 字节指针槽。 """ - if ty_name is None: - return 0 + if ty_name is None: return 0 # 前缀归一化:剥离 "t."/"c." 内建命名空间前缀,使 "int" 与裸名 "CInt" 判定 # 一致(泛型实参经 _norm_type_arg_name 规则 3 会保留 "t.")。不剥离则 # 误判为非标量 → 8 字节指针槽 → GEP 元素类型退化为指针(整数存指针报 CastError)。 - if ty_name[0] == 't' and ty_name[1] == '.': - ty_name += 2 - elif ty_name[0] == 'c' and ty_name[1] == '.': - ty_name += 2 - if string.strchr(ty_name, '|') is not None: - return 0 - if string.strchr(ty_name, '*') is not None: - return 0 - if string.strcmp(ty_name, "str") == 0: - return 0 - if string.strcmp(ty_name, "bytes") == 0: - return 0 - if string.strcmp(ty_name, "CPtr") == 0: - return 0 - if string.strstr(ty_name, "Ptr") is not None: - return 0 + if ty_name[0] == 't' and ty_name[1] == '.': ty_name += 2 + elif ty_name[0] == 'c' and ty_name[1] == '.': ty_name += 2 + if string.strchr(ty_name, '|') is not None: return 0 + if string.strchr(ty_name, '*') is not None: return 0 + if string.strcmp(ty_name, "str") == 0: return 0 + if string.strcmp(ty_name, "bytes") == 0: return 0 + if string.strcmp(ty_name, "CPtr") == 0: return 0 + if string.strstr(ty_name, "Ptr") is not None: return 0 # === 白名单:已知纯标量(基础名 + stdint 大写别名) === if string.strcmp(ty_name, "int") == 0: return 1 if string.strcmp(ty_name, "char") == 0: return 1 @@ -1040,19 +906,15 @@ novirtual class AssignGenMixin: def _is_generic_tp_or_nested(self, node: ast.AST*) -> int: """判断注解节点是否为泛型类型参数名(单字母大写,如 T)或嵌套联合(BinOp)""" - if node is None: - return 0 + if node is None: return 0 nk: int = node.kind() - if nk == ast.ASTKind.BinOp: - return 1 + if nk == ast.ASTKind.BinOp: return 1 if nk == ast.ASTKind.Name: nm_tp: ast.Name* = ast.Name*(node) - if nm_tp.id is None: - return 0 + if nm_tp.id is None: return 0 tp_len: sizet = string.strlen(nm_tp.id) if tp_len == 1: - if nm_tp.id[0] >= 65 and nm_tp.id[0] <= 90: - return 1 + if nm_tp.id[0] >= 65 and nm_tp.id[0] <= 90: return 1 return 0 # ============================================================ @@ -1084,15 +946,12 @@ novirtual class AssignGenMixin: owner_ctx: 站点描述(如 "类 X 字段 y"),仅用于空元素 fail-fast 报文, 便于从报错直接定位到"哪个类/哪个字段的第几个元素"。 """ - if builder is None or array_alloca is None or list_node is None: - return 1 + if builder is None or array_alloca is None or list_node is None: return 1 # 获取数组类型(Pointee of [N x elem_ty]*) arr_ty: mlirlite.LLVMType* = None - if array_alloca.Ty is not None: - arr_ty = array_alloca.Ty.Pointee - if arr_ty is None: - return 1 + if array_alloca.Ty is not None: arr_ty = array_alloca.Ty.Pointee + if arr_ty is None: return 1 # 匹配数组类型获取元素类型与声明长度 elem_ty: mlirlite.LLVMType* = None @@ -1101,13 +960,11 @@ novirtual class AssignGenMixin: case mlirlite.LLVMType.Array(et, cnt): elem_ty = et arr_count = cnt - if elem_ty is None: - return 1 + if elem_ty is None: return 1 # 获取列表元素 lst: ast.List* = ast.List*(list_node) - if lst is None or lst.elts is None: - return 1 + if lst is None or lst.elts is None: return 1 elts: list[ast.AST*]* = lst.elts elts_count: sizet = len(elts) @@ -1129,8 +986,7 @@ novirtual class AssignGenMixin: while bi_s < 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) - if bp_s is None: - break + if bp_s is None: break bvv: mlirlite.Value* = mlirlite.const_int32(pool, sv_s[bi_s]) bsv: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, bvv, elem_ty, e0_s) mlirlite.build_store(builder, bsv, bp_s) @@ -1179,8 +1035,7 @@ novirtual class AssignGenMixin: # 本函数 1185 行(`elem_ptr.Ty.Pointee`)已按此约定改为 `!= 0`。 if elem_node is None: ctx_dbg: str = "" - if owner_ctx is not None: - ctx_dbg = owner_ctx + if owner_ctx is not None: ctx_dbg = owner_ctx src_line: int = 0 src_col: int = 0 if list_node is not None: @@ -1206,8 +1061,7 @@ novirtual class AssignGenMixin: elem_vptr: uint64 = *((uint64*)(elem_node)) if elem_vptr == 0: ctx_vt: str = "" - if owner_ctx is not None: - ctx_vt = owner_ctx + if owner_ctx is not None: ctx_vt = owner_ctx vt_line: int = 0 vt_col: int = 0 if list_node is not None: @@ -1224,16 +1078,14 @@ novirtual class AssignGenMixin: 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) - if elem_ptr is None: - continue + if elem_ptr is None: continue # 内层嵌套数组:元素类型是数组且元素节点是列表字面量 → 递归数组初始化 # (逐元素 GEP + store)。list 字面量赋给 t.CArray 属数组语义,不特化 # list 泛型(否则 _list 未注册时报特化失败);只有显式 list[T] 注解才引入 _list。 inner_arr: int = 0 if self.Gen.ExprGenBase.is_array_type(elem_ty) != 0: # 嵌套元素判空:同上硬约定,用 `is not None`(不用整型字面量 0 比较)。 - if elem_node is not None and elem_node.kind() == ast.ASTKind.List: - inner_arr = 1 + if elem_node is not None and elem_node.kind() == ast.ASTKind.List: inner_arr = 1 if inner_arr != 0: self._init_global_array_from_list(builder, pool, mod, elem_ptr, elem_node, trans, owner_ctx) continue @@ -1245,8 +1097,7 @@ novirtual class AssignGenMixin: # 判据硬约定:`Pointee` 静态类型是 i64(REnum 载荷槽,非指针)⇒ 必须 `!= 0`; # 写成 `is not None` 会被折成常量 true(IR 见上方 1146-1156 注释)。 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) + 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) mlirlite.build_store(builder, store_val, elem_ptr) return 0 @@ -1268,8 +1119,7 @@ novirtual class AssignGenMixin: """应用增强赋值的二元运算(浮点 + 指针算术 + 整数运算)""" # `**=` 幂运算:基础类型 → llvm.pow(与 BinOp 共用 ExprGenOps.emit_pow) if op == ast.OpKind.Pow: - if trans is None: - return None + if trans is None: return None return self.Gen.ExprGenOps.emit_pow(pool, builder, trans.Module, lhs, rhs, node, trans) lhs_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(lhs.Ty) rhs_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(rhs.Ty) @@ -1281,11 +1131,9 @@ novirtual class AssignGenMixin: if lhs_fbits != 0 or rhs_fbits != 0: # 确定目标浮点类型(使用较大的位宽) target_fbits: int = lhs_fbits - if rhs_fbits > target_fbits: - target_fbits = rhs_fbits + if rhs_fbits > target_fbits: target_fbits = rhs_fbits target_float_ty: mlirlite.LLVMType* = mlirlite.Double(pool) - if target_fbits == 32: - target_float_ty = mlirlite.Float(pool) + if target_fbits == 32: target_float_ty = mlirlite.Float(pool) # 将两个操作数转换为目标浮点类型(int→float via si2fp, float→float via fpext/fptrunc) lhs = self.Gen.ExprGenBase.coerce_to_type(builder, lhs, target_float_ty, node) rhs = self.Gen.ExprGenBase.coerce_to_type(builder, rhs, target_float_ty, node) @@ -1299,8 +1147,7 @@ novirtual class AssignGenMixin: # 指针算术: ptr += int / ptr -= int → getelementptr(按元素大小缩放) # 对齐 TPC HandlesAugAssign.py L140-149 / L170-180 if lhs_bits == 0 and rhs_bits != 0: - if op == ast.OpKind.Add or op == ast.OpKind.Sub: - return self.Gen.ExprGenBase.translate_ptr_arith(pool, builder, lhs, rhs, op) + if op == ast.OpKind.Add or op == ast.OpKind.Sub: return self.Gen.ExprGenBase.translate_ptr_arith(pool, builder, lhs, rhs, op) return None # 双指针算术 fail-fast:判据/报文唯一实现见 ExprGenOps.fail_if_double_ptr_binop @@ -1311,16 +1158,13 @@ novirtual class AssignGenMixin: self.Gen.ExprGenOps.fail_if_double_ptr_binop(pool, op, lhs, rhs, node, 1) # 整数运算:类型提升 - if lhs_bits > rhs_bits and rhs_bits > 0: - rhs = self.Gen.ExprGenBase.coerce_to_type(builder, rhs, lhs.Ty, node, trans) - elif rhs_bits > lhs_bits and lhs_bits > 0: - lhs = self.Gen.ExprGenBase.coerce_to_type(builder, lhs, rhs.Ty, node, trans) + if lhs_bits > rhs_bits and rhs_bits > 0: rhs = self.Gen.ExprGenBase.coerce_to_type(builder, rhs, lhs.Ty, node, trans) + elif rhs_bits > lhs_bits and lhs_bits > 0: lhs = self.Gen.ExprGenBase.coerce_to_type(builder, lhs, rhs.Ty, node, trans) # 无符号操作数(如 u_num_l: uint64 的 //= / %=)→ udiv/urem,有符号走 sdiv/srem。 aug_unsigned: int = 0 if lhs_node is not None: - if self.Gen.ExprGenOps._node_type_unsigned(pool, lhs_node, trans) != 0: - aug_unsigned = 1 + if self.Gen.ExprGenOps._node_type_unsigned(pool, lhs_node, trans) != 0: aug_unsigned = 1 if op == ast.OpKind.Add: return mlirlite.build_add(builder, lhs, rhs) elif op == ast.OpKind.Sub: return mlirlite.build_sub(builder, lhs, rhs) @@ -1341,11 +1185,9 @@ novirtual class AssignGenMixin: elif op == ast.OpKind.RShift: # 无符号 >> → lshr(逻辑右移),有符号 >> → ashr(算术右移) # 对齐 TPC ExprGen.emit_binary_op:i8/i16 默认无符号;其余查操作数无符号性 - if lhs_bits == 8 or lhs_bits == 16: - return mlirlite.build_lshr(builder, lhs, rhs) + if lhs_bits == 8 or lhs_bits == 16: return mlirlite.build_lshr(builder, lhs, rhs) if lhs_node is not None and trans is not None: - if self.Gen.ExprGenOps._node_type_unsigned(pool, lhs_node, trans) != 0: - return mlirlite.build_lshr(builder, lhs, rhs) + if self.Gen.ExprGenOps._node_type_unsigned(pool, lhs_node, trans) != 0: return mlirlite.build_lshr(builder, lhs, rhs) return mlirlite.build_ashr(builder, lhs, rhs) return None @@ -1377,8 +1219,7 @@ novirtual class AssignGenMixin: GenApi.escape_fstring_copy 显式拷到 stdlib 堆(f-string 本身是栈临时值)。 """ decl: str = "(注解含 t.CConst,声明处来源名未记录)" - if src_name is not None: - decl = f"t.CConst | {src_name}" + 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"增量赋值与元素赋值,且不会降级为警告)") def const_assign_fail(self, node: ast.AST*, kind: str, @@ -1390,16 +1231,13 @@ novirtual class AssignGenMixin: def translate_augassign(self, trans: HT.Translator*, node: ast.AST*) -> int: """翻译增强赋值语句 (x += 1, y -= 2, etc.)""" - if node is None: - return 0 + if node is None: return 0 aug: rawptr[ast.AugAssign] = rawptr[ast.AugAssign](node) - if aug is None: - return 0 + if aug is None: return 0 target: ast.AST* = aug.target - if target is None: - return 0 + if target is None: return 0 tk: int = target.kind() @@ -1425,8 +1263,7 @@ novirtual class AssignGenMixin: # 2. 确定字段类型并加载当前值 target_ty: mlirlite.LLVMType* = None - if field_ptr.Ty is not None and field_ptr.Ty.Pointee != 0: - target_ty = field_ptr.Ty.Pointee + 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: 字段类型信息缺失,禁止兜底 i32 self.Gen.TypeGenErr.fatal_error(target, "字段类型信息缺失", "TypeError") @@ -1436,8 +1273,7 @@ novirtual class AssignGenMixin: # 字段 += 的 load/store 亦带 volatile(两来源取或)。 at_aug: ast.Attribute* = ast.Attribute*(target) if at_aug is not None: - if self.Gen.ExprGenAttr.base_pointee_is_volatile(pool, trans, at_aug.value) != 0: - vol_fa = 1 + if self.Gen.ExprGenAttr.base_pointee_is_volatile(pool, trans, at_aug.value) != 0: vol_fa = 1 cur_val: mlirlite.Value* = mlirlite.build_load(builder, target_ty, field_ptr, vol_fa) if cur_val is None: # fail-fast: 属性当前值加载失败 @@ -1496,8 +1332,7 @@ novirtual class AssignGenMixin: # 2. 确定元素类型并加载当前值 target_ty: mlirlite.LLVMType* = None - if elem_ptr.Ty is not None and elem_ptr.Ty.Pointee != 0: - target_ty = elem_ptr.Ty.Pointee + 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: 元素类型信息缺失,禁止兜底 i32 self.Gen.TypeGenErr.fatal_error(target, "元素类型信息缺失", "TypeError") @@ -1505,8 +1340,7 @@ novirtual class AssignGenMixin: # load/store 均带 volatile。仅基址可解析到 VarEntry/FieldEntry 时为 1。 vol_sa: int = 0 sub_aug: ast.Subscript* = ast.Subscript*(target) - if sub_aug is not None: - vol_sa = self.Gen.ExprGenAttr.base_pointee_is_volatile(pool, trans, sub_aug.value) + if sub_aug is not None: vol_sa = self.Gen.ExprGenAttr.base_pointee_is_volatile(pool, trans, sub_aug.value) cur_val: mlirlite.Value* = mlirlite.build_load(builder, target_ty, elem_ptr, vol_sa) if cur_val is None: # fail-fast: 元素当前值加载失败 @@ -1538,8 +1372,7 @@ novirtual class AssignGenMixin: # 操作数求值取指针 → load 当前值 → 二元运算 → store 回同址。 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, "增量赋值目标单目运算缺少操作数", "TypeError") if uo_ag.op != ast.OpKind.Deref: self.Gen.TypeGenErr.fatal_error(target, "增量赋值目标只支持单目 '*' 解引用(&x / -x / ~x 不是合法左值)", "SyntaxError") @@ -1555,17 +1388,13 @@ novirtual class AssignGenMixin: self.Gen.TypeGenErr.fatal_error(target, "解引用增量赋值的目标类型缺失(pointee 为空)", "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, "无法加载解引用当前值", "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 翻译失败", "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"解引用二元运算失败 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, "类型对齐失败", "TypeError") mlirlite.build_store(builder, res_ag, ptr_ag, 0) return 0 @@ -1574,8 +1403,7 @@ novirtual class AssignGenMixin: self.Gen.TypeGenErr.fatal_error(target, "AugAssign 目标类型不支持,仅支持 Name/Attribute/Subscript/*解引用", "TypeError") nm: ast.Name* = ast.Name*(target) - if nm is None or nm.id is None: - return 0 + if nm is None or nm.id is None: return 0 # const 变量:+= 立即 fail-fast(与 TPC HandlesAugAssign 同判据/同报文) ve_aug: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id) @@ -1589,8 +1417,7 @@ novirtual class AssignGenMixin: # 作用域用 repl_in_frag_entry_scope(M3):被提升的会话函数体内 `x += 1` # 按普通局部变量路径处理(不写会话槽)。 if trans.ReplCtx is not None and self.Gen.VarGen.repl_in_frag_entry_scope(trans) != 0: - if self.Gen.VarGen.repl_try_augassign(trans, nm.id, aug.op, aug.value, node) != 0: - return 0 + if self.Gen.VarGen.repl_try_augassign(trans, nm.id, aug.op, aug.value, node) != 0: return 0 pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder @@ -1598,10 +1425,8 @@ novirtual class AssignGenMixin: # 1. 确定变量作用域类型: 0=local, 1=global, 2=nonlocal scope_type: int = 0 - if GenApi.is_global_name(trans, nm.id) != 0: - scope_type = 1 - elif GenApi.is_nonlocal_name(trans, nm.id) != 0: - scope_type = 2 + if GenApi.is_global_name(trans, nm.id) != 0: scope_type = 1 + elif GenApi.is_nonlocal_name(trans, nm.id) != 0: scope_type = 2 # t.CVolatile 变量:+= 的 load 与 store 均带 volatile 限定符 vol_aa: int = self.Gen.VarGen.var_is_volatile(self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id)) @@ -1623,8 +1448,7 @@ novirtual class AssignGenMixin: elif scope_type == 2: # nonlocal 变量(通过闭包 env) cur_val = self.Gen.StmtGenDecl.load_nonlocal_var(trans, nm.id) - if cur_val is not None: - target_ty = cur_val.Ty + if cur_val is not None: target_ty = cur_val.Ty else: # 普通局部变量 target_alloca = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id) @@ -1655,8 +1479,7 @@ novirtual class AssignGenMixin: # 指针存储槽(Ptr(Ptr(Struct))):load 出对象指针作为 self if target_alloca.Ty is not None and target_alloca.Ty.Pointee != 0 and self.Gen.ExprGenBase.is_ptr_type(target_alloca.Ty.Pointee) != 0: load_self_aug: mlirlite.Value* = mlirlite.build_load(builder, target_alloca.Ty.Pointee, target_alloca) - if load_self_aug is not None: - ovl_self_aug = load_self_aug + if load_self_aug is not None: ovl_self_aug = load_self_aug # 仅当目标是结构体(类实例)时才尝试增量 dunder,避免无谓的实参池分配 if self.Gen.StructGen.get_struct_type_from_value(ovl_self_aug) is not None: aug_extra: sizet* = pool.alloc(8) @@ -1665,8 +1488,7 @@ novirtual class AssignGenMixin: aug_ovl: mlirlite.Value* = self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, ovl_self_aug, aug_dup, trans, aug_extra, 1) if aug_ovl is None: aug_fb: str = self._op_to_dunder(aug.op) - if aug_fb is not None: - aug_ovl = self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, ovl_self_aug, aug_fb, trans, aug_extra, 1) + if aug_fb is not None: aug_ovl = self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, ovl_self_aug, aug_fb, trans, aug_extra, 1) if aug_ovl is not None: aug_res: mlirlite.Value* = aug_ovl if target_ty is not None and aug_res.Ty is not None and self.Gen.ExprGenBase._same_agg_ty(pool, aug_res.Ty, target_ty) == 0: @@ -1675,8 +1497,7 @@ novirtual class AssignGenMixin: aug_res = mlirlite.build_load(builder, aug_res.Ty.Pointee, aug_res) else: coerced_aug: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, aug_res, target_ty, node, trans) - if coerced_aug is not None: - aug_res = coerced_aug + 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:重载返回值与目标变量类型不匹配,禁止静默写坏内存 self.Gen.TypeGenErr.fatal_error(node, "增量赋值运算符重载返回值类型与目标变量不匹配", "TypeError") @@ -1699,17 +1520,14 @@ novirtual class AssignGenMixin: if scope_type == 1: # global 变量 - if target_alloca is not None: - mlirlite.build_store(builder, result, target_alloca, vol_aa) + if target_alloca is not None: mlirlite.build_store(builder, result, target_alloca, vol_aa) elif scope_type == 2: # nonlocal 变量 nl_ptr: mlirlite.Value* = self.Gen.StmtGenDecl.get_nonlocal_var_ptr(trans, nm.id) - if nl_ptr is not None: - mlirlite.build_store(builder, result, nl_ptr) + if nl_ptr is not None: mlirlite.build_store(builder, result, nl_ptr) else: # 普通局部变量 - if target_alloca is not None: - mlirlite.build_store(builder, result, target_alloca, vol_aa) + if target_alloca is not None: mlirlite.build_store(builder, result, target_alloca, vol_aa) return 0 @@ -1739,40 +1557,30 @@ novirtual class AssignGenMixin: 1. 模块限定 t.CArray[...](Attribute value) 2. 裸名 CArray[...](from t import * 后使用) # 存疑 """ - if annot is None or annot.kind() != ast.ASTKind.Subscript: - return 0 + if annot is None or annot.kind() != ast.ASTKind.Subscript: return 0 sub: ast.Subscript* = ast.Subscript*(annot) - if sub.value is None or sub.slice is None: - return 0 + if sub.value is None or sub.slice is None: return 0 if sub.value.kind() == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(sub.value) - if at.attr is None or string.strcmp(at.attr, "CArray") != 0: - return 0 - if at.value is None or at.value.kind() != ast.ASTKind.Name: - return 0 + if at.attr is None or string.strcmp(at.attr, "CArray") != 0: return 0 + if at.value is None or at.value.kind() != ast.ASTKind.Name: return 0 mv: ast.Name* = ast.Name*(at.value) - if mv.id is None or string.strcmp(mv.id, "t") != 0: - return 0 + if mv.id is None or string.strcmp(mv.id, "t") != 0: return 0 elif sub.value.kind() == ast.ASTKind.Name: # 裸名 CArray(from t import *)/ 内建 rawarray / 内建 array(软关键字): # 三者均与 t.CArray 等价 bn: ast.Name* = ast.Name*(sub.value) - if bn.id is None or (string.strcmp(bn.id, "CArray") != 0 and string.strcmp(bn.id, "rawarray") != 0 and string.strcmp(bn.id, "array") != 0): - return 0 - else: - return 0 + if bn.id is None or (string.strcmp(bn.id, "CArray") != 0 and string.strcmp(bn.id, "rawarray") != 0 and string.strcmp(bn.id, "array") != 0): return 0 + else: return 0 # 单参形式:slice 非 Tuple(如 t.CArray[u64] / CArray[str]) - if sub.slice.kind() != ast.ASTKind.Tuple: - return 1 + if sub.slice.kind() != ast.ASTKind.Tuple: return 1 # 双参形式:count=None(t.CArray[u64, None])→ 等价单参 tup: ast.Tuple* = ast.Tuple*(sub.slice) - if tup.elts is None or len(tup.elts) < 2: - return 0 + if tup.elts is None or len(tup.elts) < 2: return 0 cnt_node: ast.AST* = tup.elts.get(1) if cnt_node is not None and cnt_node.kind() == ast.ASTKind.Constant: cn0: ast.Constant* = ast.Constant*(cnt_node) - if cn0.const_kind == ast.CONST_NONE: - return 1 + if cn0.const_kind == ast.CONST_NONE: return 1 return 0 # _infer_static_array_ty_from_literal - 单参 CArray + 列表字面量 → [len x elem_ty] @@ -1789,8 +1597,7 @@ novirtual class AssignGenMixin: elem_ty_arr: mlirlite.LLVMType* = resolved_ty.Pointee lst_arr: ast.List* = ast.List*(value) cnt_arr: int = 0 - if lst_arr.elts is not None: - cnt_arr = len(lst_arr.elts) + if lst_arr.elts is not None: cnt_arr = len(lst_arr.elts) # 特例:单个字符串字面量(如 hex_digits: t.CArray[char, None] = ["0123.."]) # 语义是"以字符串内容初始化字符数组",长度应取 strlen+1(含结尾 NUL), # 而不是列表元素个数 1——否则 alloca [1 x i8] 且只写首字节 → 下标 0..15 越界读。 @@ -1800,10 +1607,8 @@ novirtual class AssignGenMixin: c0_arr: ast.Constant* = ast.Constant*(e0_arr) if c0_arr.const_kind == ast.CONST_STR: sv0_arr: str = ast.constant_get_str_val(c0_arr) - if sv0_arr is not None and self.Gen.ExprGenBase.get_llvm_type_bits(elem_ty_arr) == 8: - return mlirlite.Array(pool, elem_ty_arr, int(string.strlen(sv0_arr)) + 1) - if elem_ty_arr is not None and cnt_arr > 0: - return mlirlite.Array(pool, elem_ty_arr, cnt_arr) + if sv0_arr is not None and self.Gen.ExprGenBase.get_llvm_type_bits(elem_ty_arr) == 8: return mlirlite.Array(pool, elem_ty_arr, int(string.strlen(sv0_arr)) + 1) + if elem_ty_arr is not None and cnt_arr > 0: return mlirlite.Array(pool, elem_ty_arr, cnt_arr) return resolved_ty # ============================================================ @@ -1822,22 +1627,16 @@ novirtual class AssignGenMixin: (stdlib.malloc + viperlib.snprintf)保证跨帧存活。 """ ann_txt_x: str = None - if annot is not None: - ann_txt_x = self.Gen.TypeGenResolve._get_type_name_from_annotation(pool, annot) - if ann_txt_x is None: - ann_txt_x = "?" + if annot is not None: ann_txt_x = self.Gen.TypeGenResolve._get_type_name_from_annotation(pool, annot) + if ann_txt_x is None: ann_txt_x = "?" btd_nm_x: str = self.Gen.TypeGenCType.LastBuiltinsTypedefName btd_rs_x: str = self.Gen.TypeGenCType.LastBuiltinsTypedefResult 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 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) return msg_buf # ============================================================ @@ -1849,22 +1648,17 @@ novirtual class AssignGenMixin: def translate_annassign_prescan(self, trans: HT.Translator*, node: ast.AST*) -> int: """预扫描 AnnAssign,提前创建 alloca 到 entry block 顶部""" - if node is None: - return 0 + if node is None: return 0 k: int = node.kind() - if k != ast.ASTKind.AnnAssign: - return 0 + if k != ast.ASTKind.AnnAssign: return 0 aa: ast.AnnAssign* = ast.AnnAssign*(node) - if aa is None or aa.target is None: - return 0 + if aa is None or aa.target is None: return 0 target: ast.AST* = aa.target - if target.kind() != ast.ASTKind.Name: - return 0 + if target.kind() != ast.ASTKind.Name: return 0 nm: ast.Name* = ast.Name*(target) - if nm.id is None: - return 0 + if nm.id is None: return 0 # CDefine 注解: 不创建 alloca,但注册常量到全局表 # 供后续 t.CArray[elem_ty, NAME] 编译期解析使用 @@ -1877,34 +1671,28 @@ novirtual class AssignGenMixin: # CTypedef 注解: 类型别名(ScanCTypedefDeclarations 已注册到 CTypedef 表), # 不创建全局/局部存储——否则 stdint.vp 的 float64_t: t.CTypedef = t.CFloat64T # 等生成 @float64_t 符号,链接 duplicate symbol warning - if self.is_ctypedef_annotation(aa.annotation) != 0: - return 0 + if self.is_ctypedef_annotation(aa.annotation) != 0: return 0 # REPL 模式(M2/M3):片段**入口**函数本体内的 AnnAssign 一律走会话槽(见 # translate_annassign 的会话分支),此处不得预建局部 alloca——否则局部名 # 会遮蔽同名会话变量(此后读 `x` 命中空局部槽,槽值丢失)。 # 被提升的会话函数体内不走该分支(那里按普通局部声明预建 alloca)。 # CDefine/CTypedef 两个分支在本次返回之前,其行为不变。 - if trans.ReplCtx is not None and self.Gen.VarGen.repl_in_frag_entry_scope(trans) != 0: - return 0 + if trans.ReplCtx is not None and self.Gen.VarGen.repl_in_frag_entry_scope(trans) != 0: return 0 # global/nonlocal 变量不需要局部 alloca - if GenApi.is_global_name(trans, nm.id) != 0: - return 0 - if GenApi.is_nonlocal_name(trans, nm.id) != 0: - return 0 + if GenApi.is_global_name(trans, nm.id) != 0: return 0 + if GenApi.is_nonlocal_name(trans, nm.id) != 0: return 0 # 模块级全局变量已由 handle_module_level_var 注册到模块作用域。 # Python 语义:仅模块级代码(Current == Root)时跳过局部 alloca; # 函数内无 global 声明时应创建局部变量(不遮蔽全局)。 if self.Gen.VarGen.is_module_scope(trans.SymTab) != 0: - if self.Gen.VarGen.lookup_module_var(trans.SymTab, nm.id) is not None: - return 0 + if self.Gen.VarGen.lookup_module_var(trans.SymTab, nm.id) is not None: return 0 # 检查是否已存在 existing: mlirlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, nm.id) - if existing is not None: - return 0 + if existing is not None: return 0 pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder @@ -1947,27 +1735,22 @@ novirtual class AssignGenMixin: # 模板未注册时属性访问会报"类未注册"。 if annot is not None: cls_nm_ps: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(annot, trans._imported_modules, pool, trans._from_imports) - if cls_nm_ps is not None: - self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, nm.id, cls_nm_ps) + if cls_nm_ps is not None: self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, nm.id, cls_nm_ps) # 检查是否为 bytes* 或 str*(i8** 语义,8 字节步长) - if self._is_ptr_element_annotation(annot) != 0: - self.Gen.VarGen.set_var_ptr_element(trans.SymTab, nm.id) + if self._is_ptr_element_annotation(annot) != 0: self.Gen.VarGen.set_var_ptr_element(trans.SymTab, nm.id) # const 对象(注解含 t.CConst 且声明类型非指针):整个作用域内 # 禁止对该变量名赋值/增量赋值/元素赋值。判据与 TPC 的 # BaseGen._IsConstObject 逐条一致(见 Debugger/type-descriptors.md)。 - if self.Gen.TypeGenErr.is_const_object_marker(annot, var_ty) != 0: - self.Gen.VarGen.set_var_const(trans.SymTab, nm.id) + if self.Gen.TypeGenErr.is_const_object_marker(annot, var_ty) != 0: self.Gen.VarGen.set_var_const(trans.SymTab, nm.id) # t.CVolatile:声明期即标记该变量的 load/store 带 volatile。 # 覆盖「无初值声明」`x: t.CVolatile | T`(有初值路径 # translate_annassign 亦会登记,幂等)。动机:volatile 禁优化器 # 把忙等循环的重复 load 提升/消除,不能依赖优化器保序。 - if self.Gen.TypeGenErr.has_decorator_marker(annot, "CVolatile", 0) != 0: - self.Gen.VarGen.set_var_volatile(trans.SymTab, nm.id) + if self.Gen.TypeGenErr.has_decorator_marker(annot, "CVolatile", 0) != 0: self.Gen.VarGen.set_var_volatile(trans.SymTab, nm.id) # rawptr[t.CVolatile | T](volatile 指针指向物,等价 C 的 # volatile T*):解引用(p[i]/p.field/c.Deref(p))的 load/store # 带 volatile。声明期登记,覆盖「无初值声明」。 - if self.Gen.TypeGenErr.has_pointee_volatile_marker(annot) != 0: - self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, nm.id) + if self.Gen.TypeGenErr.has_pointee_volatile_marker(annot) != 0: self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, nm.id) return 0 return 0 @@ -1983,33 +1766,24 @@ novirtual class AssignGenMixin: pool: memhub.MemBuddy*, annot: ast.AST*) -> int: """泛型注解预特化(见上方注释),返回 1=已尝试 / 0=不适用""" - if annot is None or trans is None: - return 0 + if annot is None or trans is None: return 0 # 取注解中的泛型 Subscript 一侧:Subscript 本身,或 A* 的 Subscript 分支 spec_annot: ast.Subscript* = None - if annot.kind() == ast.ASTKind.Subscript: - spec_annot = ast.Subscript*(annot) + if annot.kind() == ast.ASTKind.Subscript: spec_annot = ast.Subscript*(annot) elif annot.kind() == ast.ASTKind.BinOp: bop_ps: ast.BinOp* = ast.BinOp*(annot) if bop_ps.op == ast.OpKind.BitOr: - if bop_ps.left is not None and bop_ps.left.kind() == ast.ASTKind.Subscript: - spec_annot = ast.Subscript*(bop_ps.left) - elif bop_ps.right is not None and bop_ps.right.kind() == ast.ASTKind.Subscript: - spec_annot = ast.Subscript*(bop_ps.right) - if spec_annot is None: - return 0 + if bop_ps.left is not None and bop_ps.left.kind() == ast.ASTKind.Subscript: spec_annot = ast.Subscript*(bop_ps.left) + elif bop_ps.right is not None and bop_ps.right.kind() == ast.ASTKind.Subscript: spec_annot = ast.Subscript*(bop_ps.right) + if spec_annot is None: return 0 sv_ps: ast.AST* = spec_annot.value - if sv_ps is None or sv_ps.kind() != ast.ASTKind.Name: - return 0 + if sv_ps is None or sv_ps.kind() != ast.ASTKind.Name: return 0 sub_nm: ast.Name* = ast.Name*(sv_ps) - if sub_nm.id is None: - return 0 + if sub_nm.id is None: return 0 template_cd: ast.ClassDef* = self.Gen.ClassGenGeneric._find_generic_template(sub_nm.id) - if template_cd is None: - return 0 + if template_cd is None: return 0 type_args_ps: list[str]* = self.Gen.CallGenCtor._extract_type_args_from_slice(pool, spec_annot.slice, trans._from_imports) - if type_args_ps is None or len(type_args_ps) == 0: - return 0 + if type_args_ps is None or len(type_args_ps) == 0: return 0 self.Gen.ClassGenGeneric._specialize_generic_class(trans, sub_nm.id, type_args_ps) return 1 @@ -2039,32 +1813,23 @@ novirtual class AssignGenMixin: 返回 0=未退化(继续);退化则 fatal_error 终止(不返回)。 """ - if aa is None or annot is None or var_ty is None: - return 0 + if aa is None or annot is None or var_ty is None: return 0 # 取注解里的泛型 Subscript 一侧:Subscript 本身,或 A* 的 Subscript 分支 ann_sub: ast.Subscript* = None - if annot.kind() == ast.ASTKind.Subscript: - ann_sub = ast.Subscript*(annot) + if annot.kind() == ast.ASTKind.Subscript: ann_sub = ast.Subscript*(annot) elif annot.kind() == ast.ASTKind.BinOp: bop_ff: ast.BinOp* = ast.BinOp*(annot) if bop_ff.op == ast.OpKind.BitOr: - if bop_ff.left is not None and bop_ff.left.kind() == ast.ASTKind.Subscript: - ann_sub = ast.Subscript*(bop_ff.left) - elif bop_ff.right is not None and bop_ff.right.kind() == ast.ASTKind.Subscript: - ann_sub = ast.Subscript*(bop_ff.right) - if ann_sub is None or ann_sub.value is None or ann_sub.value.kind() != ast.ASTKind.Name: - return 0 + if bop_ff.left is not None and bop_ff.left.kind() == ast.ASTKind.Subscript: ann_sub = ast.Subscript*(bop_ff.left) + elif bop_ff.right is not None and bop_ff.right.kind() == ast.ASTKind.Subscript: ann_sub = ast.Subscript*(bop_ff.right) + if ann_sub is None or ann_sub.value is None or ann_sub.value.kind() != ast.ASTKind.Name: return 0 base_nm_ff: ast.Name* = ast.Name*(ann_sub.value) - if base_nm_ff.id is None: - return 0 + if base_nm_ff.id is None: return 0 # 仅当该基名确实是泛型模板(list/GSList/...)才判定为退化 - if self.Gen.ClassGenGeneric._find_generic_template(base_nm_ff.id) is None: - return 0 - if var_ty.Pointee == 0: - return 0 + if self.Gen.ClassGenGeneric._find_generic_template(base_nm_ff.id) is None: return 0 + if var_ty.Pointee == 0: return 0 vt_nm_ff: str = mlirlite.get_struct_name(var_ty.Pointee) - if vt_nm_ff is None: - return 0 + if vt_nm_ff is None: return 0 vt_pf_ff: int = GenApi.sha1_prefix_len(vt_nm_ff) 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: @@ -2081,16 +1846,13 @@ novirtual class AssignGenMixin: node: ast.AST*) -> int: """翻译 AnnAssign(target=Name, annotation=..., value=expr)""" aa: ast.AnnAssign* = ast.AnnAssign*(node) - if aa is None: - return 0 + if aa is None: return 0 target: ast.AST* = aa.target - if target is None or target.kind() != ast.ASTKind.Name: - return 0 + if target is None or target.kind() != ast.ASTKind.Name: return 0 nm: ast.Name* = ast.Name*(target) - if nm.id is None: - return 0 + if nm.id is None: return 0 # CDefine 注解: 编译期常量,不生成运行时代码 # 注册到全局 CDefine 表供 t.CArray[elem_ty, NAME] 解析 @@ -2109,8 +1871,7 @@ novirtual class AssignGenMixin: if self.is_ctypedef_annotation(aa.annotation) != 0: pool_ct: memhub.MemBuddy* = trans.Pool ctd_str: str = self.Gen.TypeGenResolve._get_type_name_from_annotation(pool_ct, aa.value) - if ctd_str is not None: - self.Gen.TypeGenCType.register_ctypedef(pool_ct, nm.id, ctd_str) + if ctd_str is not None: self.Gen.TypeGenCType.register_ctypedef(pool_ct, nm.id, ctd_str) return 0 # define / CDefine 常量的**使用处宽度**(`a: T = C` 场景):RHS 是已注册常量 @@ -2144,8 +1905,7 @@ novirtual class AssignGenMixin: # 不归本检查(模块级由 handle_module_level_var 登记,本就不构成"遮蔽")。 if nm.id is not None and trans is not None and self.Gen.VarGen.is_module_scope(trans.SymTab) == 0 and self.Gen.VarGen.lookup_module_var(trans.SymTab, nm.id) is not None: 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 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 之后" @@ -2171,8 +1931,7 @@ novirtual class AssignGenMixin: # 不复用预扫描 alloca 的路径(详见 _prespecialize_generic_annotation)。 self._prespecialize_generic_annotation(trans, pool, annot) resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, annot, trans._imported_modules, trans._from_imports, trans, 0) - if resolved is not None: - var_ty = resolved + if resolved is not None: var_ty = resolved else: # fast-fail: 注解类型解析失败,Python traceback 立即终止(不静默回退 i32) self.Gen.TypeGenErr.fatal_error(aa, @@ -2197,8 +1956,7 @@ novirtual class AssignGenMixin: # 返回值:0=成功/同名同类型幂等命中;非 0 已在 register_func_ptr_sig # 内部 fatal_error(表满/同名不同类型/表分配失败)终止编译。此处分支 # 仅为防御——报错通道异常时不带着未登记的签名继续翻译。 - if self.Gen.CallGenLeafKit.register_func_ptr_sig(pool, nm.id, callable_ret, aa) != 0: - return 0 + if self.Gen.CallGenLeafKit.register_func_ptr_sig(pool, nm.id, callable_ret, aa) != 0: return 0 # 值位置 volatile 调用前缀:`a: int = volatile f()` / `a: S = volatile S(...)` # ⇒ 结果槽按 volatile 存取(下述三条"条目已先存在"的分支——global / @@ -2208,8 +1966,7 @@ novirtual class AssignGenMixin: # volatile,且此后该变量的 load/store 亦带,避免这次调用/构造的往返访问 # 被优化器消除或提升。 if aa.value is not None and aa.value.kind() == ast.ASTKind.Call and (ast.Call*(aa.value)).IsVolatile != 0 and nm.id is not None: - if self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id) is not None: - self.Gen.VarGen.set_var_volatile(trans.SymTab, nm.id) + if self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id) is not None: self.Gen.VarGen.set_var_volatile(trans.SymTab, nm.id) # global 变量:写入模块作用域中的全局变量 if GenApi.is_global_name(trans, nm.id) != 0: @@ -2219,8 +1976,7 @@ novirtual class AssignGenMixin: # 使整数字面量按目标位宽直接物化(如 uint64 目标 → i64 const), # 与显式 u64(...) 强转一致,且省去后续 coerce 生成的 zext。 aa_glob_ty: mlirlite.LLVMType* = None - if mod_alloca.Ty is not None: - aa_glob_ty = mod_alloca.Ty.Pointee + if mod_alloca.Ty is not None: aa_glob_ty = mod_alloca.Ty.Pointee # 供裸名泛型构造从注解推断类型实参(消费者见 CallGenCtor.vp 的 # CurAssignNode 判定):与主分支(普通局部变量路径)同一口径—— # 必须在翻译 RHS 之前写入 CurAssignAnnot/CurAssignNode。四处 @@ -2250,16 +2006,14 @@ novirtual class AssignGenMixin: if rhs_inner_aa is not None and rhs_inner_aa.kind() == mlirlite.LLVMType.Struct and self._stg_ty_equal(pool, stg_ty_aa, rhs_inner_aa) != 0: mlirlite.build_store(builder, stg_ref_aa, mod_alloca) stg_obj_val_aa: mlirlite.Value* = mlirlite.build_load(builder, stg_ty_aa, rhs_val) - if stg_obj_val_aa is not None: - mlirlite.build_store(builder, stg_obj_val_aa, stg_ref_aa) + if stg_obj_val_aa is not None: mlirlite.build_store(builder, stg_obj_val_aa, stg_ref_aa) # 清除赋值上下文(防残留):与主分支清空时机同款—— # 提前 return 前必须清,否则泄漏到后续语句 trans.CurAssignAnnot = None trans.CurAssignNode = None return 0 target_ty: mlirlite.LLVMType* = None - if mod_alloca.Ty is not None: - target_ty = mod_alloca.Ty.Pointee + if mod_alloca.Ty is not None: target_ty = mod_alloca.Ty.Pointee if target_ty is not None: # 「str/bytes 不是通用指针通配」:目标注解为裸 str/bytes 而右值 # 是指向聚合类型(结构体/类/数组/函数)的指针 → fail-fast。 @@ -2285,8 +2039,7 @@ novirtual class AssignGenMixin: # 从 nl_ptr 的类型推断 nonlocal 变量实际类型, # 不再强制 i32(会截断指针/结构体/i64 导致闭包数据损坏) nl_target_ty: mlirlite.LLVMType* = None - if nl_ptr is not None and nl_ptr.Ty is not None: - nl_target_ty = nl_ptr.Ty.Pointee + if nl_ptr is not None and nl_ptr.Ty is not None: nl_target_ty = nl_ptr.Ty.Pointee # 供裸名泛型构造从注解推断类型实参:与主分支、上方 global 分支、 # 下方 mod_glob 分支同一口径——必须在翻译 RHS 之前写入 # CurAssignAnnot/CurAssignNode。四处(主分支 / global / mod_glob / @@ -2319,20 +2072,16 @@ novirtual class AssignGenMixin: # 模块级全局变量(由 handle_module_level_var 注册到模块作用域) # Python 语义:仅模块级代码(Current == Root)时修改全局变量; # 函数内无 global 声明时应创建局部变量(走后面的 get_or_create_sym 路径)。 - if self.Gen.VarGen.is_module_scope(trans.SymTab) != 0: - mod_glob: mlirlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm.id) - else: - mod_glob = None + if self.Gen.VarGen.is_module_scope(trans.SymTab) != 0: mod_glob: mlirlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm.id) + else: mod_glob = None if mod_glob is not None: if aa.value is not None: # 列表字面量 → 逐元素 GEP + store 初始化数组 - if aa.value.kind() == ast.ASTKind.List: - self._init_global_array_from_list(builder, pool, mod, mod_glob, aa.value, trans) + if aa.value.kind() == ast.ASTKind.List: self._init_global_array_from_list(builder, pool, mod, mod_glob, aa.value, trans) else: # P1-A:模块级全局目标类型作为 target_ty(同上方 global 分支) mg_val_ty: mlirlite.LLVMType* = None - if mod_glob.Ty is not None: - mg_val_ty = mod_glob.Ty.Pointee + if mod_glob.Ty is not None: mg_val_ty = mod_glob.Ty.Pointee # 供裸名泛型构造从注解推断类型实参:与主分支、上方 global 分支 # 同一口径——翻译 RHS 前写入 CurAssignAnnot/CurAssignNode。 # 模块级 `s: Stack[int] = Stack()` 走的就是本分支,四处(主分支 / @@ -2359,16 +2108,14 @@ novirtual class AssignGenMixin: if rhs_inner_mg is not None and rhs_inner_mg.kind() == mlirlite.LLVMType.Struct and self._stg_ty_equal(pool, stg_ty_mg, rhs_inner_mg) != 0: mlirlite.build_store(builder, stg_ref_mg, mod_glob) stg_obj_val_mg: mlirlite.Value* = mlirlite.build_load(builder, stg_ty_mg, rhs_val_mg) - if stg_obj_val_mg is not None: - mlirlite.build_store(builder, stg_obj_val_mg, stg_ref_mg) + if stg_obj_val_mg is not None: mlirlite.build_store(builder, stg_obj_val_mg, stg_ref_mg) # 清除赋值上下文(防残留):与主分支清空时机同款, # 提前 return 前必须清,否则泄漏到后续语句 trans.CurAssignAnnot = None trans.CurAssignNode = None return 0 target_ty_mg: mlirlite.LLVMType* = None - if mod_glob.Ty is not None: - target_ty_mg = mod_glob.Ty.Pointee + if mod_glob.Ty is not None: target_ty_mg = mod_glob.Ty.Pointee if target_ty_mg is not None: # 「str/bytes 不是通用指针通配」:同上(global 分支), # 目标注解为裸 str/bytes 而右值是指向聚合类型的指针 → fail-fast。 @@ -2435,8 +2182,7 @@ novirtual class AssignGenMixin: if annot is not None and annot.kind() == ast.ASTKind.Name: fd_annot: ast.Name* = ast.Name*(annot) if fd_annot is not None and fd_annot.id is not None: - if string.strcmp(fd_annot.id, "str") == 0: - fd_str_ty = self.Gen.StructGen.get_struct_type("_str") + if string.strcmp(fd_annot.id, "str") == 0: fd_str_ty = self.Gen.StructGen.get_struct_type("_str") if fd_str_ty is not None: # 确保 _str 完整类型定义在当前模块可用:跨模块结构体默认 opaque, # 直接 alloca opaque 类型 → llc "Cannot allocate unsized type" @@ -2444,8 +2190,7 @@ novirtual class AssignGenMixin: # 影子变量名必须用 pool 持久缓冲:f-string 生成栈缓冲,在 AnnAssign # 返回后被覆盖,符号表注册的名字内容损坏 → 后续 lookup 找不到。 fd_meta_name = pool.alloc(256) - if fd_meta_name is not None: - viperlib.snprintf(fd_meta_name, 256, "%s__meta__", nm.id) + if fd_meta_name is not None: viperlib.snprintf(fd_meta_name, 256, "%s__meta__", nm.id) 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: 影子存储创建失败,立即终止 @@ -2454,16 +2199,13 @@ novirtual class AssignGenMixin: # 传 pool:泛型 Subscript 返回 mangled name(对齐 L401 同根因修复) 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) - if cls_nm_hd is not None: - self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, nm.id, cls_nm_hd) + if cls_nm_hd is not None: self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, nm.id, cls_nm_hd) # 检查是否为 bytes* 或 str*(i8** 语义,8 字节步长) - if self._is_ptr_element_annotation(annot) != 0: - self.Gen.VarGen.set_var_ptr_element(trans.SymTab, nm.id) + if self._is_ptr_element_annotation(annot) != 0: self.Gen.VarGen.set_var_ptr_element(trans.SymTab, nm.id) new_vars: int = 0 existing: mlirlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, nm.id) - if existing is None: - new_vars = 1 + if existing is None: new_vars = 1 # 如果有初始值,store if aa.value is not None: @@ -2476,8 +2218,7 @@ novirtual class AssignGenMixin: if val_cl.func is not None and val_cl.func.kind() == ast.ASTKind.Name: val_nm: ast.Name* = ast.Name*(val_cl.func) if val_nm.id is not None: - if self.Gen.AsyncGen.is_async_func(trans, val_nm.id) != 0: - self.Gen.AsyncGen.register_coro_var(trans, nm.id, val_nm.id) + if self.Gen.AsyncGen.is_async_func(trans, val_nm.id) != 0: self.Gen.AsyncGen.register_coro_var(trans, nm.id, val_nm.id) # c.Addr(async_call):tt: Coroutine = c.Addr(task()) 就地解读 elif val_cl.func is not None and val_cl.func.kind() == ast.ASTKind.Attribute: val_at: ast.Attribute* = ast.Attribute*(val_cl.func) @@ -2488,19 +2229,16 @@ novirtual class AssignGenMixin: if icl2.func is not None and icl2.func.kind() == ast.ASTKind.Name: inm2: ast.Name* = ast.Name*(icl2.func) if inm2.id is not None: - if self.Gen.AsyncGen.is_async_func(trans, inm2.id) != 0: - self.Gen.AsyncGen.register_coro_var(trans, nm.id, inm2.id) + if self.Gen.AsyncGen.is_async_func(trans, inm2.id) != 0: self.Gen.AsyncGen.register_coro_var(trans, nm.id, inm2.id) # 局部数组:列表字面量 → 先整体置零,再逐元素 GEP + store 初始化。 # 不走 translate_list_literal(避免误触发 list[T] 泛型特化)。 local_arr_ty: mlirlite.LLVMType* = None if aa.value.kind() == ast.ASTKind.List and alloca.Ty is not None: pt_l: mlirlite.LLVMType* = alloca.Ty.Pointee - if self.Gen.ExprGenBase.is_array_type(pt_l) != 0: - local_arr_ty = pt_l + if self.Gen.ExprGenBase.is_array_type(pt_l) != 0: local_arr_ty = pt_l if local_arr_ty is not None: zero_arr: mlirlite.Value* = mlirlite.ConstZero(pool, local_arr_ty) - if zero_arr is not None: - mlirlite.build_store(builder, zero_arr, alloca) + if zero_arr is not None: mlirlite.build_store(builder, zero_arr, alloca) self._init_global_array_from_list(builder, pool, mod, alloca, aa.value, trans) else: # 供裸名泛型构造从注解推断类型实参(消费者见 CallGenCtor.vp 的 @@ -2513,8 +2251,7 @@ novirtual class AssignGenMixin: # P1-A:局部变量 alloca 的 pointee 类型作为 target_ty(同全局分支), # 使 `x: uint64 = 12345` 直接物化 i64 常量,与 `x: uint64 = u64(12345)` 一致。 lv_target_ty: mlirlite.LLVMType* = None - if alloca.Ty is not None: - lv_target_ty = alloca.Ty.Pointee + 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, "局部变量注解") if rhs_val is not None: # 注解退化修复(对齐 TPC 从构造结果推断类型):无实参泛型模板注解 @@ -2547,16 +2284,13 @@ novirtual class AssignGenMixin: if ag_side.kind() == ast.ASTKind.BinOp: ag_bop: ast.BinOp* = ast.BinOp*(ag_side) if ag_bop.op == ast.OpKind.BitOr: - if ag_bop.left is not None and ag_bop.left.kind() == ast.ASTKind.Subscript: - ag_side = ag_bop.left - elif ag_bop.right is not None and ag_bop.right.kind() == ast.ASTKind.Subscript: - ag_side = ag_bop.right + if ag_bop.left is not None and ag_bop.left.kind() == ast.ASTKind.Subscript: ag_side = ag_bop.left + elif ag_bop.right is not None and ag_bop.right.kind() == ast.ASTKind.Subscript: ag_side = ag_bop.right if ag_side.kind() == ast.ASTKind.Subscript: ag_sub: ast.Subscript* = ast.Subscript*(ag_side) if ag_sub.value is not None and ag_sub.value.kind() == ast.ASTKind.Name: ag_nm: ast.Name* = ast.Name*(ag_sub.value) - if ag_nm.id is not None: - ann_gen_base = ag_nm.id + if ag_nm.id is not None: ann_gen_base = ag_nm.id rb_is_bare_generic: int = 0 if alloca_pt is not None and uint64(alloca_pt) != uint64(precise_rhs_ty): rhs_pt_rb: mlirlite.LLVMType* = precise_rhs_ty.Pointee @@ -2567,14 +2301,12 @@ novirtual class AssignGenMixin: rb_short: str = rb_nm + rb_pf if rb_pf != 0 else rb_nm if string.strchr(rb_short, '[') is None: # ① 裸名命中泛型模板注册表(list/GSList/...) - if self.Gen.ClassGenGeneric._find_generic_template(rb_short) is not None: - rb_is_bare_generic = 1 + if self.Gen.ClassGenGeneric._find_generic_template(rb_short) is not None: rb_is_bare_generic = 1 # ② 与注解同基名:注解是 `Base[...]`(带类型实参, # 已比 RHS 的裸 Base 精确)⇒ 本次重建方向是**降级**, # 必须禁止。此判定不依赖泛型模板注册表(list/dict 等 # 内建容器未登记时①会漏判,②仍能命中)。 - elif ann_gen_base is not None and string.strcmp(rb_short, ann_gen_base) == 0: - rb_is_bare_generic = 1 + elif ann_gen_base is not None and string.strcmp(rb_short, ann_gen_base) == 0: rb_is_bare_generic = 1 # 禁止「上转被窄化」重建(方向判定其三):注解写明的被指类是 # RHS 被指类的**基类**时(如 `node: rawptr[AST] = Name(...)`, # AST 是 Name 的基类),注解就是合法的「基类指针」声明,RHS 只是 @@ -2591,8 +2323,7 @@ novirtual class AssignGenMixin: ann_pt_rb: mlirlite.LLVMType* = alloca_pt.Pointee rhs_pt_up: mlirlite.LLVMType* = precise_rhs_ty.Pointee if ann_pt_rb is not None and rhs_pt_up is not None and uint64(ann_pt_rb) != uint64(rhs_pt_up): - if self.Gen.ExprGenBase._is_inheritance_upcast(pool, rhs_pt_up, ann_pt_rb) != 0: - rb_is_upcast = 1 + if self.Gen.ExprGenBase._is_inheritance_upcast(pool, rhs_pt_up, ann_pt_rb) != 0: rb_is_upcast = 1 if alloca_pt is not None and uint64(alloca_pt) != uint64(precise_rhs_ty) and rb_is_bare_generic == 0 and rb_is_upcast == 0: new_alloca: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, precise_rhs_ty) if new_alloca is not None: @@ -2603,8 +2334,7 @@ novirtual class AssignGenMixin: # 类型转换:将 rhs_val 转换为 alloca 的 pointee 类型 # 修复:整数字面量是 i32,但变量可能是 i8/i16/i64,需 trunc/sext target_ty: mlirlite.LLVMType* = None - if alloca.Ty is not None: - target_ty = alloca.Ty.Pointee + if alloca.Ty is not None: target_ty = alloca.Ty.Pointee if target_ty is not None: # 「str/bytes 不是通用指针通配」:目标注解为裸 str/bytes 而右值 # 是指向聚合类型(结构体/类/数组/函数)的指针 → fail-fast。 @@ -2615,15 +2345,13 @@ novirtual class AssignGenMixin: if aa.annotation is not None and nm.id is not None: # const 对象局部变量:登记 VarEntry.IsConst(与 prescan 幂等)。 # 用 alloca 的值类型(target_ty)判指针性,判据同 TPC。 - if self.Gen.TypeGenErr.is_const_object_marker(aa.annotation, target_ty) != 0: - self.Gen.VarGen.set_var_const(trans.SymTab, nm.id) + if self.Gen.TypeGenErr.is_const_object_marker(aa.annotation, target_ty) != 0: self.Gen.VarGen.set_var_const(trans.SymTab, nm.id) if self.Gen.TypeGenErr.has_decorator_marker(aa.annotation, "CVolatile", 0) != 0: self.Gen.VarGen.set_var_volatile(trans.SymTab, nm.id) vol_laa = 1 # rawptr[t.CVolatile | T](volatile 指针指向物):登记 # PointeeVolatile;本 store 写的是指针变量自身,不影响。 - if self.Gen.TypeGenErr.has_pointee_volatile_marker(aa.annotation) != 0: - self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, nm.id) + if self.Gen.TypeGenErr.has_pointee_volatile_marker(aa.annotation) != 0: self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, nm.id) # 值位置 volatile 调用前缀:`a: int = volatile f()` / # `a: S = volatile S(...)`——LLVM 的 call 指令没有 volatile # 限定符,故语义落在内存存取上:结果槽按 volatile 存取 @@ -2639,8 +2367,7 @@ novirtual class AssignGenMixin: fd_data_fe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(fd_str_ty, "__data__") if fd_data_fe is not None: fd_data_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, fd_str_ty, fd_data_fe.Ty, fd_meta_alloca, fd_data_fe.Index) - if fd_data_ptr is not None: - mlirlite.build_store(builder, rhs_val, fd_data_ptr) + if fd_data_ptr is not None: mlirlite.build_store(builder, rhs_val, fd_data_ptr) # 清除赋值上下文(防残留):CurAssignAnnot/CurAssignNode 只在该 # AnnAssign 的 RHS 翻译期间有效,否则后续语句里裸名泛型构造的类型 # 实参推断会拿到残留注解。 @@ -2657,8 +2384,7 @@ novirtual class AssignGenMixin: fd_null: mlirlite.Value* = mlirlite.ConstNull(pool, fd_buddy_fe.Ty, "null") fd_buddy_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, fd_str_ty, fd_buddy_fe.Ty, fd_meta_alloca, fd_buddy_fe.Index) - if fd_buddy_ptr is not None and fd_null is not None: - mlirlite.build_store(builder, fd_null, fd_buddy_ptr) + if fd_buddy_ptr is not None and fd_null is not None: mlirlite.build_store(builder, fd_null, fd_buddy_ptr) # FakeDuck: with 上下文自动注入 requires 字段(如 __mbuddy__)。 # 跨 Mixin 经 self.Gen 调用 CallGenFd._inject_requires_fields。 self.Gen.CallGenFd._inject_requires_fields(trans, pool, builder, mod, fd_meta_alloca, "_str") @@ -2696,39 +2422,33 @@ novirtual class AssignGenMixin: # 无用 IR 再报错。 for ti_c in range(len(targets)): tgt_c: ast.AST* = targets.get(ti_c) - if tgt_c is None: - continue + if tgt_c is None: continue if tgt_c.kind() == ast.ASTKind.Name: nm_c: ast.Name* = ast.Name*(tgt_c) - if nm_c.id is None: - continue + 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)) elif tgt_c.kind() == ast.ASTKind.Attribute: at_c: ast.Attribute* = ast.Attribute*(tgt_c) - if at_c.attr is None: - continue + 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)) elif tgt_c.kind() == ast.ASTKind.Subscript: sub_c: ast.Subscript* = ast.Subscript*(tgt_c) - if sub_c.value is None: - continue + if sub_c.value is None: continue if sub_c.value.kind() == ast.ASTKind.Name: nm_c2: ast.Name* = ast.Name*(sub_c.value) - if nm_c2.id is None: - continue + 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)) 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 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)) @@ -2739,17 +2459,13 @@ novirtual class AssignGenMixin: # 缓冲同在当前函数。判据与拷贝出口见 GenApi.fail_if_fstring_escape 头注释。 for ti_f in range(len(targets)): tgt_f: ast.AST* = targets.get(ti_f) - if tgt_f is None: - continue + 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, "字段赋值") + elif tk_f == ast.ASTKind.Subscript: GenApi.fail_if_fstring_escape(asgn.value, "元素赋值") 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, "全局变量赋值") # 翻译 RHS 值 # 无注解赋值无目标类型可推断,清空 CurAssignAnnot/CurAssignNode @@ -2767,17 +2483,14 @@ novirtual class AssignGenMixin: asg_nm0: ast.Name* = ast.Name*(asg_t0) if asg_nm0.id is not None: asg_slot: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, asg_nm0.id) - if asg_slot is None: - asg_slot = self.Gen.VarGen.lookup_module_var(trans.SymTab, asg_nm0.id) - if asg_slot is not None and asg_slot.Ty is not None: - asg_target_ty = asg_slot.Ty.Pointee + if asg_slot is None: asg_slot = self.Gen.VarGen.lookup_module_var(trans.SymTab, asg_nm0.id) + if asg_slot is not None and asg_slot.Ty is not None: asg_target_ty = asg_slot.Ty.Pointee elif trans.ReplCtx is not None and self.Gen.VarGen.repl_in_frag_entry_scope(trans) != 0: # REPL 模式(M2/M3):已定型的会话变量也用槽类型做 target_ty # (与 P1-A 同口径;未定型则维持 None,由 RHS 类型定型)。 # 只在片段入口函数生效(被提升的会话函数体内同名赋值是局部变量) asg_re: rawptr[GenTypes.ReplVarEntry] = self.Gen.VarGen.repl_find_entry(trans.ReplCtx, asg_nm0.id) - if asg_re is not None and asg_re.Kind != GenTypes.REPL_KIND_UNTYPED: - asg_target_ty = self.Gen.VarGen.repl_slot_ty(pool, asg_re) + if asg_re is not None and asg_re.Kind != GenTypes.REPL_KIND_UNTYPED: asg_target_ty = self.Gen.VarGen.repl_slot_ty(pool, asg_re) rhs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, asgn.value, None, 0, trans, asg_target_ty) if rhs_val is None: # 归属:RHS 为 None 多数是分配失败(池耗尽)。“[MEM] alloc 失败”只给池基址, @@ -2785,10 +2498,8 @@ novirtual class AssignGenMixin: # 当前阶段/文件。故此处把两个池的用量与池标识一并打出来。 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("主池(Pool)") + if pp_diag is not None: pp_diag.dump_stats("常驻池(PermPool)") stdio.fflush(None) # 增强错误信息:包含文件名 + lineno + AST 节点详情,便于定位 if asgn.value is not None: @@ -2797,8 +2508,7 @@ novirtual class AssignGenMixin: val_line: int = asgn.value.lineno # 通过 sha1 查找文件名(人类可读) rel_path: str = None - if sha1 is not None: - rel_path = StubMergerStore.LookupSha1RelPath(sha1) + if sha1 is not None: rel_path = StubMergerStore.LookupSha1RelPath(sha1) # 根据 AST 节点类型提取详情 if val_kind == ast.ASTKind.Attribute: at_nv: ast.Attribute* = ast.Attribute*(asgn.value) @@ -2808,16 +2518,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"赋值右侧为 None: {rel_path}:{val_line} '{target_nm}.{attr_nm}' 属性访问失败", "ASGN") + else: VLogger.error(f"赋值右侧为 None: sha1={sha1}:{val_line} '{target_nm}.{attr_nm}' 属性访问失败", "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"赋值右侧为 None: {rel_path}:{val_line} 变量 '{nm_nv.id}' 未找到", "ASGN") + else: VLogger.error(f"赋值右侧为 None: sha1={sha1}:{val_line} 变量 '{nm_nv.id}' 未找到", "ASGN") elif val_kind == ast.ASTKind.Call: cl_nv: ast.Call* = ast.Call*(asgn.value) func_nm: str = "?" @@ -2825,25 +2531,19 @@ 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"赋值右侧为 None: {rel_path}:{val_line} 调用 '{func_nm}(...)' 返回 None", "ASGN") + else: VLogger.error(f"赋值右侧为 None: sha1={sha1}:{val_line} 调用 '{func_nm}(...)' 返回 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"赋值右侧为 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") return 0 new_vars: int = 0 tn: sizet = len(targets) for ti in range(tn): target: ast.AST* = targets.get(ti) - if target is None: - continue + if target is None: continue tk: int = target.kind() @@ -2857,8 +2557,7 @@ novirtual class AssignGenMixin: tgt_tup: ast.Tuple* = ast.Tuple*(target) tgt_elts: list[ast.AST*]* = tgt_tup.elts # 守卫:rhs 不是 struct(tuple 打包)时跳过本 target - if tgt_elts is None or rhs_val is None or rhs_val.Ty is None: - continue + if tgt_elts is None or rhs_val is None or rhs_val.Ty is None: continue match rhs_val.Ty: case mlirlite.LLVMType.Struct(_, _, _): tgt_n: sizet = len(tgt_elts) @@ -2870,31 +2569,24 @@ novirtual class AssignGenMixin: fti: sizet for fti in range(tgt_n): tgt_elt: ast.AST* = tgt_elts.get(fti) - if tgt_elt is None or fcur is None: - break + if tgt_elt is None or fcur is None: break fty: mlirlite.LLVMType* = mlirlite.paramnode_get_ty(fcur) fcur = mlirlite.paramnode_get_next(fcur) if fty is None: # fail-fast: 字段类型缺失,立即终止 self.Gen.TypeGenErr.fatal_error(target, "元组解包字段类型缺失", "TypeError") # 守卫:非 Name 元素无法解包,跳过 - if tgt_elt.kind() != ast.ASTKind.Name: - continue + if tgt_elt.kind() != ast.ASTKind.Name: continue tgt_nm2: ast.Name* = ast.Name*(tgt_elt) - if tgt_nm2.id is None: - continue + if tgt_nm2.id is None: continue fp2: mlirlite.Value* = mlirlite.build_gep_struct(builder, rhs_val.Ty, fty, tmp_s, fti) - if fp2 is None: - continue + if fp2 is None: continue fv2: mlirlite.Value* = mlirlite.build_load(builder, fty, fp2) tgt_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, tgt_nm2.id) - if tgt_alloca is None: - tgt_alloca = self.Gen.VarGen.get_or_create_sym(trans.SymTab, pool, builder, tgt_nm2.id, fty) - if tgt_alloca is None: - continue + if tgt_alloca is None: tgt_alloca = self.Gen.VarGen.get_or_create_sym(trans.SymTab, pool, builder, tgt_nm2.id, fty) + if tgt_alloca is None: continue sval: mlirlite.Value* = fv2 - if tgt_alloca.Ty is not None and tgt_alloca.Ty.Pointee != 0: - sval = self.Gen.ExprGenBase.coerce_to_type(builder, fv2, tgt_alloca.Ty.Pointee, node, trans) + if tgt_alloca.Ty is not None and tgt_alloca.Ty.Pointee != 0: sval = self.Gen.ExprGenBase.coerce_to_type(builder, fv2, tgt_alloca.Ty.Pointee, node, trans) mlirlite.build_store(builder, sval, tgt_alloca) case _: pass @@ -2924,14 +2616,12 @@ novirtual class AssignGenMixin: # (写 sizeof(T) 而非 8 字节指针)。数组槽(t.CArray[T,N])除外。 self._reject_whole_object_copy_into_ptr_slot(pool, trans, target, elem_ptr, rhs_val) # 守卫短路:elem 类型完整才做类型转换 - if elem_ptr.Ty is not None and elem_ptr.Ty.Pointee != 0: - store_val = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, elem_ptr.Ty.Pointee, node, trans) + if elem_ptr.Ty is not None and elem_ptr.Ty.Pointee != 0: store_val = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, elem_ptr.Ty.Pointee, node, trans) # rawptr[t.CVolatile|T] 基址(volatile 指针指向物):p[i] = v # 的 store 带 volatile。仅基址可解析到条目时为 1(否则文本不变)。 vol_sw: int = 0 sub_wr: ast.Subscript* = ast.Subscript*(target) - if sub_wr is not None: - vol_sw = self.Gen.ExprGenAttr.base_pointee_is_volatile(pool, trans, sub_wr.value) + if sub_wr is not None: vol_sw = self.Gen.ExprGenAttr.base_pointee_is_volatile(pool, trans, sub_wr.value) mlirlite.build_store(builder, store_val, elem_ptr, vol_sw) continue # get_subscript_ptr 返回 None: 尝试 __setitem__ 运算符重载 @@ -2973,8 +2663,7 @@ novirtual class AssignGenMixin: # load 解引用获取 Ptr(Struct) if cls_nm_attr is None and self.Gen.ExprGenBase.is_ptr_type(field_pointee_set) != 0 and field_pointee_set.Pointee != 0: cls_nm_attr = self.Gen.StructGen.get_class_name_by_type(pool, field_pointee_set.Pointee) - if cls_nm_attr is not None: - obj_val_attr = mlirlite.build_load(builder, field_pointee_set, field_ptr_set) + if cls_nm_attr is not None: obj_val_attr = mlirlite.build_load(builder, field_pointee_set, field_ptr_set) if cls_nm_attr is not None and obj_val_attr is not None: key_val_attr: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub_asgn.slice, None, 0, trans) if key_val_attr is not None: @@ -3018,12 +2707,10 @@ novirtual class AssignGenMixin: case _: elem_ptr_gen = mlirlite.build_gep(builder, elem_gen, obj_val_gen, key_val_gen) if elem_ptr_gen is not None and elem_ptr_gen.Ty is not None: - if elem_ptr_gen.Ty.Pointee != 0: - store_val_gen = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, elem_ptr_gen.Ty.Pointee, node) + if elem_ptr_gen.Ty.Pointee != 0: store_val_gen = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, elem_ptr_gen.Ty.Pointee, node) mlirlite.build_store(builder, store_val_gen, elem_ptr_gen) setitem_done = 1 - if setitem_done == 0: - self.Gen.TypeGenErr.fatal_error(target, "subscript ptr is None") + if setitem_done == 0: self.Gen.TypeGenErr.fatal_error(target, "subscript ptr is None") continue # UnaryOp 目标: *p = val —— 解引用写入(与读侧同一节点形态)。 @@ -3039,8 +2726,7 @@ novirtual class AssignGenMixin: # `&x`/`-x` 作目标不是合法左值,故除 Deref 外一律 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, "赋值目标单目运算缺少操作数", "TypeError") if uo_w.op != ast.OpKind.Deref: self.Gen.TypeGenErr.fatal_error(target, "赋值目标只支持单目 '*' 解引用(&x / -x / ~x 不是合法左值)", "SyntaxError") @@ -3065,8 +2751,7 @@ novirtual class AssignGenMixin: # property setter 拦截: obj.attr = v 且 attr 是 @x.setter 方法时, # 生成 call Class.attr$set(obj, v),跳过字段存储 # 注意参数顺序:_try_property_setter(pool, builder, mod, ...)。 - if self.Gen.CallGenProp._try_property_setter(pool, builder, mod, at_tg, rhs_val, trans) == 1: - continue + if self.Gen.CallGenProp._try_property_setter(pool, builder, mod, at_tg, rhs_val, trans) == 1: continue # FakeDuck: 影子结构体属性写入 (str 变量的 per-instance 字段) # a.__data__ = v → GEP {a}__meta__[field] 并 store # 对齐 TPC HandlesAssign.py L67-76:对象是 Name 变量且存在 @@ -3078,8 +2763,7 @@ novirtual class AssignGenMixin: if fd_obj_nm.id is not None: # pool 持久缓冲(f-string 栈缓冲在函数返回后失效) fd_meta_w: str = pool.alloc(256) - if fd_meta_w is not None: - viperlib.snprintf(fd_meta_w, 256, "%s__meta__", fd_obj_nm.id) + if fd_meta_w is not None: viperlib.snprintf(fd_meta_w, 256, "%s__meta__", fd_obj_nm.id) fd_meta_vw: mlirlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, fd_meta_w) if fd_meta_vw is not None: fd_sty_w: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type("_str") @@ -3096,22 +2780,19 @@ novirtual class AssignGenMixin: # vtable 方法不是数据字段(FieldEntry),get_attribute_ptr 查不到会 # fatal_error;此处对齐 TPC HandlesAssign.py L905-949 的写时复制, # 检测到 vtable 方法时直接生成槽位写入并跳过字段路径。 - if self.Gen.CallGenVt._write_vtable_attr(builder, pool, mod, target, rhs_val, trans) == 1: - continue + if self.Gen.CallGenVt._write_vtable_attr(builder, pool, mod, target, rhs_val, trans) == 1: continue field_ptr: mlirlite.Value* = self.Gen.ExprGenAttr.get_attribute_ptr(builder, pool, mod, target, trans) if field_ptr is not None: # 获取字段类型,对 rhs_val 进行类型转换(如 i32 → i64) store_val: mlirlite.Value* = rhs_val - if field_ptr.Ty is not None and field_ptr.Ty.Pointee != 0: - store_val = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, field_ptr.Ty.Pointee, node, trans) + if field_ptr.Ty is not None and field_ptr.Ty.Pointee != 0: store_val = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, field_ptr.Ty.Pointee, node, trans) # t.CVolatile 字段:store 带 volatile 限定符 vol_fw: int = self.Gen.ExprGenAttr.attr_field_is_volatile(pool, trans, target) # rawptr[t.CVolatile|T] 基址(volatile 指针指向物):p.field = v # 的 store 亦带 volatile(两来源取或)。 at_wr: ast.Attribute* = ast.Attribute*(target) if at_wr is not None: - if self.Gen.ExprGenAttr.base_pointee_is_volatile(pool, trans, at_wr.value) != 0: - vol_fw = 1 + if self.Gen.ExprGenAttr.base_pointee_is_volatile(pool, trans, at_wr.value) != 0: vol_fw = 1 mlirlite.build_store(builder, store_val, field_ptr, vol_fw) continue # 守卫:field_ptr 为 None → 构造详细错误信息 @@ -3129,16 +2810,14 @@ novirtual class AssignGenMixin: "attribute ptr is None: %s.%s", obj_name, attr_name) self.Gen.TypeGenErr.fatal_error(target, err_buf) - else: - self.Gen.TypeGenErr.fatal_error(target, "attribute ptr is None") + else: self.Gen.TypeGenErr.fatal_error(target, "attribute ptr is None") continue # Name 赋值: var = val if tk == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(target) # 守卫:target 名缺失时跳过 - if nm.id is None: - continue + if nm.id is None: continue # global 变量:写入模块作用域中的全局变量 if GenApi.is_global_name(trans, nm.id) != 0: mod_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm.id) @@ -3167,18 +2846,14 @@ novirtual class AssignGenMixin: mlirlite.build_store(builder, stg_ref_as, mod_alloca) # 2) 复制构造结果(临时对象)到 storage(函数内复制,alloca 仍有效) stg_obj_val_as: mlirlite.Value* = mlirlite.build_load(builder, stg_ty_as, rhs_val) - if stg_obj_val_as is not None: - mlirlite.build_store(builder, stg_obj_val_as, stg_ref_as) + if stg_obj_val_as is not None: mlirlite.build_store(builder, stg_obj_val_as, stg_ref_as) continue target_ty: mlirlite.LLVMType* = None - if mod_alloca.Ty is not None: - target_ty = mod_alloca.Ty.Pointee - if target_ty is not None: - rhs_val = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, target_ty, node, trans) + if mod_alloca.Ty is not None: target_ty = mod_alloca.Ty.Pointee + if target_ty is not None: rhs_val = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, target_ty, node, trans) # t.CVolatile 全局:store 带 volatile 限定符 vol_gas: int = 0 - if nm.id is not None: - vol_gas = self.Gen.VarGen.var_is_volatile(self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id)) + if nm.id is not None: vol_gas = self.Gen.VarGen.var_is_volatile(self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id)) mlirlite.build_store(builder, rhs_val, mod_alloca, vol_gas) continue @@ -3191,8 +2866,7 @@ novirtual class AssignGenMixin: # 从 nl_ptr 的类型推断 nonlocal 变量实际类型, # 不再强制 i32(会截断指针/结构体/i64 导致闭包数据损坏) nl_target_ty: mlirlite.LLVMType* = None - if nl_ptr.Ty is not None: - nl_target_ty = nl_ptr.Ty.Pointee + if nl_ptr.Ty is not None: nl_target_ty = nl_ptr.Ty.Pointee if nl_target_ty is None: # fail-fast: nl_ptr 类型信息丢失,无法安全 store self.Gen.TypeGenErr.fatal_error(target, f"nonlocal 变量 '{nm.id}' 类型信息丢失,无法写入", "TypeError") @@ -3216,8 +2890,7 @@ novirtual class AssignGenMixin: # (_mbuddy = mb 缺 global 声明即此类 bug:Int32 解引用 null 崩溃) 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"变量 '{nm.id}' 是模块级全局变量,函数内赋值需用 global 声明(否则创建局部变量遮蔽全局,导致全局保持 null 崩溃)", "SyntaxError") # 普通局部变量 alloca: mlirlite.Value* = self.Gen.VarGen.get_or_create_sym(trans.SymTab, pool, builder, nm.id, rhs_val.Ty) @@ -3226,12 +2899,10 @@ novirtual class AssignGenMixin: # (联合类型 X* 简化为 Ptr(i8),属性访问按需过滤需要 # AnnotClassName 才能定位结构体字段) cls_inf: str = self._infer_rhs_annot(pool, mod, asgn.value, trans, rhs_val) - if cls_inf is not None: - self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, nm.id, cls_inf) + if cls_inf is not None: self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, nm.id, cls_inf) # 按 alloca 类型对值进行转换(如 double → float) store_val: mlirlite.Value* = rhs_val - if alloca.Ty is not None and alloca.Ty.Pointee != 0: - store_val = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, alloca.Ty.Pointee, node, trans) + if alloca.Ty is not None and alloca.Ty.Pointee != 0: store_val = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, alloca.Ty.Pointee, node, trans) # t.CVolatile 局部变量:store 带 volatile 限定符 vol_las: int = self.Gen.VarGen.var_is_volatile(self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id)) mlirlite.build_store(builder, store_val, alloca, vol_las) @@ -3239,11 +2910,9 @@ novirtual class AssignGenMixin: # 调用分派(is_closure_name)才走闭包间接调用路径; # 否则 i8** alloca 被 _is_func_ptr_alloca 误判为 # 函数指针,无参 call 直接跳闭包数据崩溃 - if asgn.value is not None and asgn.value.kind() == ast.ASTKind.Lambda: - self.Gen.CallGenLeafKit.register_closure_name(nm.id) + if asgn.value is not None and asgn.value.kind() == ast.ASTKind.Lambda: self.Gen.CallGenLeafKit.register_closure_name(nm.id) existing: mlirlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, nm.id) - if existing is None: - new_vars += 1 + if existing is None: new_vars += 1 else: # fail-fast: 变量存储创建失败,立即终止 self.Gen.TypeGenErr.fatal_error(target, f"变量 '{nm.id}' 存储创建失败", "TypeError") @@ -3279,50 +2948,39 @@ novirtual class AssignGenMixin: elem_ptr: mlirlite.Value*, rhs_val: mlirlite.Value*) -> None: """rawptr[T] 下标赋值 + RHS 为指向 T 的指针 ⇒ fatal_error(整对象拷贝)""" - if elem_ptr is None or elem_ptr.Ty is None: - return - if rhs_val is None or rhs_val.Ty is None: - return + if elem_ptr is None or elem_ptr.Ty is None: return + if rhs_val is None or rhs_val.Ty is None: return elem_ty: mlirlite.LLVMType* = None match elem_ptr.Ty: case mlirlite.LLVMType.Ptr(pointee_wo): elem_ty = pointee_wo case _: return - if elem_ty is None: - return + if elem_ty is None: return # 元素必须是对象(结构体)。标量元素(rawptr[int])与指针元素 # (rawptr[rawptr[T]] / X*)在此返回。 - if elem_ty.kind() != mlirlite.LLVMType.Struct: - return + if elem_ty.kind() != mlirlite.LLVMType.Struct: return rhs_inner_wo: mlirlite.LLVMType* = None match rhs_val.Ty: case mlirlite.LLVMType.Ptr(pointee_rhs_wo): rhs_inner_wo = pointee_rhs_wo case _: return - if rhs_inner_wo is None: - return - if rhs_inner_wo.kind() != mlirlite.LLVMType.Struct: - return + if rhs_inner_wo is None: return + if rhs_inner_wo.kind() != mlirlite.LLVMType.Struct: return # 所指类型必须与元素类型一致(否则不是"隐式解引用得 T 再整对象存储") - if self._stg_ty_equal(pool, elem_ty, rhs_inner_wo) == 0: - return + if self._stg_ty_equal(pool, elem_ty, rhs_inner_wo) == 0: return # 数组槽(t.CArray[T,N])整对象赋值合法 → 不拦; # 仅基座确认为指针存储(kind==0)时才拦,-1(无法判定)不表态。 - if self.Gen.ExprGenName.subscript_base_store_kind(pool, trans, target) != 0: - return + 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 + if rhs_nm_wo is None: rhs_nm_wo = elem_nm_wo elem_sz_wo: int = self.Gen.ClassGenEnum._get_type_size(elem_ty) ptr_sz_wo: int = 8 over_wo: int = elem_sz_wo - ptr_sz_wo - if over_wo < 0: - over_wo = 0 + if over_wo < 0: over_wo = 0 col_s_wo: int = 0 col_e_wo: int = 0 if target is not None: @@ -3360,22 +3018,18 @@ novirtual class AssignGenMixin: trans: HT.Translator*, rhs_val: mlirlite.Value* = None) -> str: """从 RHS 表达式推断类名,无法推断返回 None""" - if node is None or trans is None: - return None + if node is None or trans is None: return None k: int = node.kind() # Call: 类实例化 / 方法调用 if k == ast.ASTKind.Call: cl: ast.Call* = ast.Call*(node) - if cl is None or cl.func is None: - return None + if cl is None or cl.func is None: return None if cl.func.kind() == ast.ASTKind.Name: # 类实例化:func 为已注册结构体名才采用 cand: str = (ast.Name*(cl.func)).id - if cand is None: - return None + if cand is None: return None se: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(cand) - if se is not None: - return cand + if se is not None: return cand return None if cl.func.kind() == ast.ASTKind.Attribute: # 方法调用 a.cross(b):从 vpi 返回注解缓存精确解析返回类名 @@ -3383,8 +3037,7 @@ novirtual class AssignGenMixin: # 启发式取 obj 类名会 GEP 错字段)。vpi 未命中时返回 None, # 由后续属性访问 fast-fail 暴露 vpi 缺失根因(不静默回退)。 ca: ast.Attribute* = ast.Attribute*(cl.func) - if ca is None or ca.attr is None or ca.value is None: - return None + if ca is None or ca.attr is None or ca.value is None: return None obj_cls: str = self._infer_rhs_annot(pool, mod, ca.value, trans) if obj_cls is None: # 模块级函数调用(requests.get):ca.value 是已导入模块名而非对象变量 @@ -3397,69 +3050,52 @@ novirtual class AssignGenMixin: mod_sha1_rhs: str = self.Gen.CallGenBase._lookup_module_sha1(mod_nm_rhs.id) if mod_sha1_rhs is not None: temp_dir_rhs: str = None - if self.Gen.CallGenBase.TempDir is not None: - temp_dir_rhs = self.Gen.CallGenBase.TempDir - if temp_dir_rhs is not None: - VpiReader._ensure_vpi_ret_annot_loaded(mod_sha1_rhs, temp_dir_rhs) + if self.Gen.CallGenBase.TempDir is not None: temp_dir_rhs = self.Gen.CallGenBase.TempDir + if temp_dir_rhs is not None: VpiReader._ensure_vpi_ret_annot_loaded(mod_sha1_rhs, temp_dir_rhs) annot_rhs: str = VpiReader._lookup_vpi_ret_annot(mod_sha1_rhs, None, ca.attr) if annot_rhs is not None: ret_cls_rhs: str = self._extract_annot_class_name(pool, annot_rhs) - if ret_cls_rhs is not None: - return ret_cls_rhs - return None - if self._cls_has_dunder(pool, mod, obj_cls, ca.attr) == 0: + if ret_cls_rhs is not None: return ret_cls_rhs return None + if self._cls_has_dunder(pool, mod, obj_cls, ca.attr) == 0: return None # 方法定义所在模块 SHA1(优先 struct entry,回退当前模块 sha1) cls_sha1: str = self.Gen.StructGen.get_struct_sha1(obj_cls) - if cls_sha1 is None and trans.ModuleSha1 is not None: - cls_sha1 = trans.ModuleSha1 + if cls_sha1 is None and trans.ModuleSha1 is not None: cls_sha1 = trans.ModuleSha1 ret_cls: str = None if cls_sha1 is not None: temp_dir: str = None - if self.Gen.CallGenBase.TempDir is not None: - temp_dir = self.Gen.CallGenBase.TempDir - if temp_dir is not None: - VpiReader._ensure_vpi_ret_annot_loaded(cls_sha1, temp_dir) + if self.Gen.CallGenBase.TempDir is not None: temp_dir = self.Gen.CallGenBase.TempDir + if temp_dir is not None: VpiReader._ensure_vpi_ret_annot_loaded(cls_sha1, temp_dir) annot_ret: str = VpiReader._lookup_vpi_ret_annot(cls_sha1, obj_cls, ca.attr) - if annot_ret is not None: - ret_cls = self._extract_annot_class_name(pool, annot_ret) + if annot_ret is not None: ret_cls = self._extract_annot_class_name(pool, annot_ret) return ret_cls return None # Name: 源变量注解 if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) - if nm is None or nm.id is None: - return None + if nm is None or nm.id is None: return None ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id) - if ve is None: - return None + if ve is None: return None return self.Gen.VarGen.var_annot_class_name(ve) # BinOp/UnaryOp: 运算符重载返回同类对象 if k == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(node) - if bop is None or bop.left is None: - return None + if bop is None or bop.left is None: return None dunder: str = self._op_to_dunder(bop.op) - if dunder is None: - return None + if dunder is None: return None lhs_cls: str = self._infer_rhs_annot(pool, mod, bop.left, trans) - if lhs_cls is None or self._cls_has_dunder(pool, mod, lhs_cls, dunder) == 0: - return None + if lhs_cls is None or self._cls_has_dunder(pool, mod, lhs_cls, dunder) == 0: return None return lhs_cls if k == ast.ASTKind.UnaryOp: uop: ast.UnaryOp* = ast.UnaryOp*(node) - if uop is None or uop.operand is None: - return None + if uop is None or uop.operand is None: return None dunder: str = self._op_to_dunder(uop.op) - if dunder is None: - return None + if dunder is None: return None opr_cls: str = self._infer_rhs_annot(pool, mod, uop.operand, trans) - if opr_cls is None or self._cls_has_dunder(pool, mod, opr_cls, dunder) == 0: - return None + if opr_cls is None or self._cls_has_dunder(pool, mod, opr_cls, dunder) == 0: return None return opr_cls # Attribute: 字段注解类名(属性链递归,如 p = r.origin) - if k == ast.ASTKind.Attribute: - return self.Gen.ExprGenAttr._resolve_attr_field_class(pool, trans, node) + if k == ast.ASTKind.Attribute: return self.Gen.ExprGenAttr._resolve_attr_field_class(pool, trans, node) return None # ============================================================ @@ -3473,14 +3109,11 @@ novirtual class AssignGenMixin: def _extract_annot_class_name(self, pool: memhub.MemBuddy*, annot: str) -> str: """从返回注解文本提取已注册结构体类名,无命中返回 None""" - if pool is None or annot is None: - return None + if pool is None or annot is None: return None alen: sizet = string.strlen(annot) - if alen == 0: - return None + if alen == 0: return None seg: str = pool.alloc(256) - if seg is None: - return None + if seg is None: return None start: sizet = 0 i: sizet for i in range(alen): @@ -3489,40 +3122,34 @@ novirtual class AssignGenMixin: # 段 [start, i):去除首尾空格与引号后查注册表 s: sizet = start e: sizet = i - while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'): - s += 1 + while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'): s += 1 # 段尾另需剥 '*':实参归一后段文本是 `{sha}.AST*`(旧形态 # `{sha}.AST*` 按 '|' 分段能落到 `{sha}.AST` 命中),与 # ExprGenName._list_elem_obj_ty_from_struct_name 的尾剔除同口径; # 不剥则 find_struct 落空 → 返回 None → 链式 .get(0).kind() 分派退化。 - while e > s and (annot[e - 1] == ' ' or annot[e - 1] == '\'' or annot[e - 1] == '"' or annot[e - 1] == '*'): - e -= 1 + while e > s and (annot[e - 1] == ' ' or annot[e - 1] == '\'' or annot[e - 1] == '"' or annot[e - 1] == '*'): e -= 1 seglen = e - s if seglen > 0 and seglen < 256: string.strncpy(seg, annot + s, seglen) seg[seglen] = '\0' se: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(seg) - if se is not None: - return seg + if se is not None: return seg start = i + 1 # 最后一段(无 '|' 后缀) s: sizet = start e: sizet = alen - while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'): - s += 1 + while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'): s += 1 # 段尾另需剥 '*':实参归一后段文本是 `{sha}.AST*`(旧形态 # `{sha}.AST*` 按 '|' 分段能落到 `{sha}.AST` 命中),与 # ExprGenName._list_elem_obj_ty_from_struct_name 的尾剔除同口径; # 不剥则 find_struct 落空 → 返回 None → 链式 .get(0).kind() 分派退化。 - while e > s and (annot[e - 1] == ' ' or annot[e - 1] == '\'' or annot[e - 1] == '"' or annot[e - 1] == '*'): - e -= 1 + while e > s and (annot[e - 1] == ' ' or annot[e - 1] == '\'' or annot[e - 1] == '"' or annot[e - 1] == '*'): e -= 1 seglen: sizet = e - s if seglen > 0 and seglen < 256: string.strncpy(seg, annot + s, seglen) seg[seglen] = '\0' se: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(seg) - if se is not None: - return seg + if se is not None: return seg return None # ============================================================ @@ -3581,14 +3208,11 @@ novirtual class AssignGenMixin: mod: mlirlite.LLVMModule*, class_name: str, dunder: str) -> int: """类及其 MRO 祖先链中是否存在 dunder 方法,存在返回 1""" - if class_name is None or dunder is None or mod is None: - return 0 + if class_name is None or dunder is None or mod is None: return 0 lookup_name: str = pool.alloc(128) - if lookup_name is None: - return 0 + if lookup_name is None: return 0 viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, dunder) - if self.Gen.CallGenBase.find_func_in_module(mod, lookup_name) is not None: - return 1 + if self.Gen.CallGenBase.find_func_in_module(mod, lookup_name) is not None: return 1 # 继承链祖先查找 mro_ptr: sizet* = self.Gen.StructGen.get_mro_chain(pool, class_name) mi: int = 1 @@ -3598,17 +3222,14 @@ novirtual class AssignGenMixin: anc_lookup: str = pool.alloc(128) if anc_lookup is not None: viperlib.snprintf(anc_lookup, 128, "%s.%s", anc, dunder) - if self.Gen.CallGenBase.find_func_in_module(mod, anc_lookup) is not None: - return 1 + if self.Gen.CallGenBase.find_func_in_module(mod, anc_lookup) is not None: return 1 mi += 1 # 跨模块:类有 SHA1(stub 中声明该方法)视为存在 - if self.Gen.StructGen.get_struct_sha1(class_name) is not None: - return 1 + if self.Gen.StructGen.get_struct_sha1(class_name) is not None: return 1 return 0 def InitAssignGen(self) -> int: """初始化 AssignGen 字段(构造时由 Generator 调用)""" - if self is None: - return 1 + if self is None: return 1 self.RecoverFound = 0 return 0 diff --git a/App/lib/core/Gen/AsyncGenMixin.vp b/App/lib/core/Gen/AsyncGenMixin.vp index bcff352..064b0bd 100644 --- a/App/lib/core/Gen/AsyncGenMixin.vp +++ b/App/lib/core/Gen/AsyncGenMixin.vp @@ -43,21 +43,17 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): 分配 state1..,switch case 预建(TPV build_switch 一次性生成,无法动态 add_case)。 """ fd: ast.FunctionDef* = ast.FunctionDef*(node) - if fd is None or fd.name is None or trans is None: - return 0 + if fd is None or fd.name is None or trans is None: return 0 name: str = fd.name pool: memhub.MemBuddy* = trans.Pool mod: mlirlite.LLVMModule* = trans.Module - if pool is None or mod is None: - return 0 + if pool is None or mod is None: return 0 # 防重复生成:create_ 已存在(模块多遍编译/重复定义) cname_buf: str = pool.alloc(64) - if cname_buf is not None: - viperlib.snprintf(cname_buf, 64, "create_%s", name) + if cname_buf is not None: viperlib.snprintf(cname_buf, 64, "create_%s", name) create_mangled: str = self.Gen.FuncGenBase._mangle_func_name(trans, cname_buf, 0) - if self.Gen.CallGenBase.find_func_in_module(mod, create_mangled) is not None: - return 0 + if self.Gen.CallGenBase.find_func_in_module(mod, create_mangled) is not None: return 0 # 注册 async 裸名(供 await 目标校验 / coro_run 反查) self._register_async_func(trans, name) @@ -85,12 +81,10 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): # 帧结构体 %Coro_ frame_ty: mlirlite.LLVMType* = self._build_frame_ty(pool, mod, trans, name, nparams, nlocals, nextra) - if frame_ty is None: - return 0 + if frame_ty is None: return 0 self._register_coro_frame(trans, name, frame_ty) # M3:wake 槽 index 注册(coro_run 轮询反查;wake 在额外槽相对 0) - if trans._coro_uses_sleep != 0: - self._register_coro_wake(trans, name, trans._coro_extra_base + 0) + if trans._coro_uses_sleep != 0: self._register_coro_wake(trans, name, trans._coro_extra_base + 0) # 进入函数作用域:resume 局部槽注册隔离,翻译完退出不污染模块作用域 self.Gen.VarGen.enter_scope(trans.SymTab, SCOPE_FUNCTION) @@ -109,20 +103,16 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): fd: ast.FunctionDef*) -> int: """收集 async 函数参数名到 trans._coro_params(char* 数组,8 字节/项)。 参数槽 index = 3 + i,create_ 按参数顺序收值入帧。""" - if fd is None or fd.args is None or trans is None: - return 0 - if trans._coro_params is None: - return 0 + if fd is None or fd.args is None or trans is None: return 0 + if trans._coro_params is None: return 0 ags: ast.Arguments* = ast.Arguments*(fd.args) cnt: int = 0 - if ags.args is None: - return 0 + if ags.args is None: return 0 bn: sizet = len(ags.args) i: sizet = 0 for i in range(bn): a0: ast.AST* = ags.args.get(i) - if a0 is None: - continue + if a0 is None: continue aname: str = None if a0.kind() == ast.ASTKind.Arg: ar: ast.Arg* = ast.Arg*(a0) @@ -130,10 +120,8 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): elif a0.kind() == ast.ASTKind.Name: anm: ast.Name* = ast.Name*(a0) aname = anm.id - if aname is None: - continue - if cnt >= HT.MAX_CORO_VARS: - break + if aname is None: continue + if cnt >= HT.MAX_CORO_VARS: break addr: uint64 = uint64(trans._coro_params) + cnt * 8 slot: str* = (str*)(addr) slot[0] = aname @@ -154,8 +142,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): def _pre_scan_awaits(self, trans: HT.Translator*, fd: ast.FunctionDef*) -> int: """DFS 预扫描协程体,填额外槽表并返回额外槽总数""" - if fd is None or fd.children is None or trans is None: - return 0 + if fd is None or fd.children is None or trans is None: return 0 trans._coro_extra_count = 0 trans._coro_hoist_count = 0 trans._coro_await_count = 0 @@ -169,23 +156,19 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): # ---------- 第一遍:coro_sleep 检测(wake 槽决定) ---------- def _scan_sleep_usage(self, trans: HT.Translator*, fd: ast.FunctionDef*): - if fd is None or fd.children is None or trans is None: - return + if fd is None or fd.children is None or trans is None: return self._scan_sleep_stmts(trans, fd.children) def _scan_sleep_stmts(self, trans: HT.Translator*, stmts: list[ast.AST*]*): - if stmts is None or trans._coro_uses_sleep != 0: - return + if stmts is None or trans._coro_uses_sleep != 0: return bn: sizet = len(stmts) i: sizet = 0 - for i in range(bn): - self._scan_sleep_stmt(trans, stmts.get(i)) + for i in range(bn): self._scan_sleep_stmt(trans, stmts.get(i)) def _scan_sleep_stmt(self, trans: HT.Translator*, stmt: ast.AST*): - if stmt is None or trans._coro_uses_sleep != 0: - return + if stmt is None or trans._coro_uses_sleep != 0: return sk: int = stmt.kind() if sk == ast.ASTKind.If: ifn: rawptr[ast.If] = rawptr[ast.If](stmt) @@ -213,8 +196,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): hh: sizet = 0 for hh in range(nh): h0: ast.AST* = trn.handlers.get(hh) - if h0 is not None: - self._scan_sleep_stmts(trans, h0.children) + if h0 is not None: self._scan_sleep_stmts(trans, h0.children) self._scan_sleep_stmts(trans, trn.orelse) self._scan_sleep_stmts(trans, trn.finalbody) return @@ -237,8 +219,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): def _scan_sleep_expr(self, trans: HT.Translator*, node: ast.AST*): - if node is None or trans._coro_uses_sleep != 0: - return + if node is None or trans._coro_uses_sleep != 0: return k: int = node.kind() if k == ast.ASTKind.Call: cl: ast.Call* = ast.Call*(node) @@ -257,8 +238,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if cl.args is not None: nb: sizet = len(cl.args) j: sizet = 0 - for j in range(nb): - self._scan_sleep_expr(trans, cl.args.get(j)) + for j in range(nb): self._scan_sleep_expr(trans, cl.args.get(j)) return if k == ast.ASTKind.BinOp: b: ast.BinOp* = ast.BinOp*(node) @@ -275,16 +255,14 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if cm.comparators is not None: nb2: sizet = len(cm.comparators) j2: sizet = 0 - for j2 in range(nb2): - self._scan_sleep_expr(trans, cm.comparators.get(j2)) + for j2 in range(nb2): self._scan_sleep_expr(trans, cm.comparators.get(j2)) return if k == ast.ASTKind.BoolOp: bo: rawptr[ast.BoolOp] = rawptr[ast.BoolOp](node) if bo.values is not None: nb3: sizet = len(bo.values) j3: sizet = 0 - for j3 in range(nb3): - self._scan_sleep_expr(trans, bo.values.get(j3)) + for j3 in range(nb3): self._scan_sleep_expr(trans, bo.values.get(j3)) return if k == ast.ASTKind.IfExp: ie: rawptr[ast.IfExp] = rawptr[ast.IfExp](node) @@ -309,29 +287,24 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): # ---------- 第二遍:填额外槽表 + 状态号计数 ---------- def _scan_stmts(self, trans: HT.Translator*, stmts: list[ast.AST*]*): - if stmts is None: - return + if stmts is None: return bn: sizet = len(stmts) i: sizet = 0 - for i in range(bn): - self._scan_stmt(trans, stmts.get(i)) + for i in range(bn): self._scan_stmt(trans, stmts.get(i)) def _scan_stmt(self, trans: HT.Translator*, stmt: ast.AST*): - if stmt is None: - return + if stmt is None: return sk: int = stmt.kind() if sk == ast.ASTKind.If: ifn: rawptr[ast.If] = rawptr[ast.If](stmt) - if ifn.test is not None: - self._scan_expr(trans, ifn.test) + if ifn.test is not None: self._scan_expr(trans, ifn.test) self._scan_stmts(trans, stmt.children) self._scan_stmts(trans, ifn.orelse) return if sk == ast.ASTKind.While: whn: rawptr[ast.While] = rawptr[ast.While](stmt) - if whn.test is not None: - self._scan_expr(trans, whn.test) + if whn.test is not None: self._scan_expr(trans, whn.test) self._scan_stmts(trans, stmt.children) self._scan_stmts(trans, whn.orelse) return @@ -346,8 +319,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): self.Gen.TypeGenErr.fatal_error(stmt, err_b2, "SyntaxError") return # 填 __f_idx_N / __f_len_N(i32) - if trans._coro_scan_for_count < HT.MAX_CORO_VARS: - trans._coro_for_slots[trans._coro_scan_for_count] = trans._coro_extra_count + if trans._coro_scan_for_count < HT.MAX_CORO_VARS: trans._coro_for_slots[trans._coro_scan_for_count] = trans._coro_extra_count trans._coro_extra_types[trans._coro_extra_count] = 1 trans._coro_extra_count = trans._coro_extra_count + 1 trans._coro_extra_types[trans._coro_extra_count] = 1 @@ -368,23 +340,19 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): hh2: sizet = 0 for hh2 in range(nh2): h2: ast.AST* = tr2.handlers.get(hh2) - if h2 is not None: - self._scan_stmts(trans, h2.children) + if h2 is not None: self._scan_stmts(trans, h2.children) self._scan_stmts(trans, tr2.orelse) self._scan_stmts(trans, tr2.finalbody) return if sk == ast.ASTKind.Raise: rz: rawptr[ast.Raise] = rawptr[ast.Raise](stmt) - if rz.exc is not None: - self._scan_expr(trans, rz.exc) + if rz.exc is not None: self._scan_expr(trans, rz.exc) return if sk == ast.ASTKind.Return: rv: rawptr[ast.Return] = rawptr[ast.Return](stmt) - if rv.value is not None: - self._scan_expr(trans, rv.value) - return - if sk == ast.ASTKind.Break or sk == ast.ASTKind.Continue: + if rv.value is not None: self._scan_expr(trans, rv.value) return + if sk == ast.ASTKind.Break or sk == ast.ASTKind.Continue: return # 顶层 await(AnnAssign/Assign/Expr value 直接 Await):计数不提升 if sk == ast.ASTKind.AnnAssign or sk == ast.ASTKind.Assign or sk == ast.ASTKind.Expr: if self._is_await_tail(stmt) != 0: @@ -396,31 +364,26 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): def _scan_stmt_exprs(self, trans: HT.Translator*, stmt: ast.AST*): """扫描语句的值表达式找嵌套 await""" - if stmt is None: - return + if stmt is None: return sk: int = stmt.kind() if sk == ast.ASTKind.AnnAssign: aa: ast.AnnAssign* = ast.AnnAssign*(stmt) - if aa.value is not None: - self._scan_expr(trans, aa.value) + if aa.value is not None: self._scan_expr(trans, aa.value) return if sk == ast.ASTKind.Assign: as_: ast.Assign* = ast.Assign*(stmt) - if as_.value is not None: - self._scan_expr(trans, as_.value) + if as_.value is not None: self._scan_expr(trans, as_.value) return if sk == ast.ASTKind.Expr: e: rawptr[ast.Expr] = rawptr[ast.Expr](stmt) - if e.value is not None: - self._scan_expr(trans, e.value) + if e.value is not None: self._scan_expr(trans, e.value) return # 其它语句类型:翻译端 fail-fast def _scan_expr(self, trans: HT.Translator*, node: ast.AST*): """DFS 扫描表达式找 Await:命中分配 __await_N 槽并计数状态号""" - if node is None: - return + if node is None: return k: int = node.kind() if k == ast.ASTKind.Await: # M3:await coro_sleep 用 wake 槽挂起,不占 __await_N 槽(仅计状态号) @@ -428,8 +391,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if self._expr_await_is_sleep(aw_s) != 0: trans._coro_await_count = trans._coro_await_count + 1 return - if trans._coro_hoist_count < HT.MAX_CORO_VARS: - trans._coro_await_slots[trans._coro_hoist_count] = trans._coro_extra_count + if trans._coro_hoist_count < HT.MAX_CORO_VARS: trans._coro_await_slots[trans._coro_hoist_count] = trans._coro_extra_count trans._coro_extra_types[trans._coro_extra_count] = 1 trans._coro_extra_count = trans._coro_extra_count + 1 trans._coro_hoist_count = trans._coro_hoist_count + 1 @@ -442,36 +404,30 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): return if k == ast.ASTKind.Call: cl: ast.Call* = ast.Call*(node) - if cl.func is not None: - self._scan_expr(trans, cl.func) + if cl.func is not None: self._scan_expr(trans, cl.func) if cl.args is not None: nb: sizet = len(cl.args) j: sizet = 0 - for j in range(nb): - self._scan_expr(trans, cl.args.get(j)) + for j in range(nb): self._scan_expr(trans, cl.args.get(j)) return if k == ast.ASTKind.UnaryOp: u: ast.UnaryOp* = ast.UnaryOp*(node) - if u.operand is not None: - self._scan_expr(trans, u.operand) + if u.operand is not None: self._scan_expr(trans, u.operand) return if k == ast.ASTKind.Compare: cm: rawptr[ast.Compare] = rawptr[ast.Compare](node) - if cm.left is not None: - self._scan_expr(trans, cm.left) + if cm.left is not None: self._scan_expr(trans, cm.left) if cm.comparators is not None: nb2: sizet = len(cm.comparators) j2: sizet = 0 - for j2 in range(nb2): - self._scan_expr(trans, cm.comparators.get(j2)) + for j2 in range(nb2): self._scan_expr(trans, cm.comparators.get(j2)) return if k == ast.ASTKind.BoolOp: bo: rawptr[ast.BoolOp] = rawptr[ast.BoolOp](node) if bo.values is not None: nb3: sizet = len(bo.values) j3: sizet = 0 - for j3 in range(nb3): - self._scan_expr(trans, bo.values.get(j3)) + for j3 in range(nb3): self._scan_expr(trans, bo.values.get(j3)) return if k == ast.ASTKind.IfExp: ie: rawptr[ast.IfExp] = rawptr[ast.IfExp](node) @@ -481,111 +437,85 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): return if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(node) - if at.value is not None: - self._scan_expr(trans, at.value) + if at.value is not None: self._scan_expr(trans, at.value) return if k == ast.ASTKind.Subscript: sb: ast.Subscript* = ast.Subscript*(node) - if sb.value is not None: - self._scan_expr(trans, sb.value) - if sb.slice is not None: - self._scan_expr(trans, sb.slice) + if sb.value is not None: self._scan_expr(trans, sb.value) + if sb.slice is not None: self._scan_expr(trans, sb.slice) return # Name / Constant 等叶子:无嵌套 await # ---------- For 判定辅助(M3) ---------- def _for_deep_await(self, stmt: ast.AST*) -> int: """For 语句树(含嵌套 If/While/For/Try/body/orelse)是否含 await""" - if stmt is None: - return 0 + if stmt is None: return 0 fn3: ast.For* = ast.For*(stmt) - if fn3.iter is not None and self._find_expr_await(fn3.iter) is not None: - return 1 + if fn3.iter is not None and self._find_expr_await(fn3.iter) is not None: return 1 if stmt.children is not None: bn4: sizet = len(stmt.children) i4: sizet = 0 for i4 in range(bn4): - if self._stmt_deep_await(stmt.children.get(i4)) != 0: - return 1 + if self._stmt_deep_await(stmt.children.get(i4)) != 0: return 1 if fn3.orelse is not None: bn5: sizet = len(fn3.orelse) i5: sizet = 0 for i5 in range(bn5): - if self._stmt_deep_await(fn3.orelse.get(i5)) != 0: - return 1 + if self._stmt_deep_await(fn3.orelse.get(i5)) != 0: return 1 return 0 def _stmt_deep_await(self, stmt: ast.AST*) -> int: """语句树(含嵌套 If/While/For/Try)是否含 await""" - if stmt is None: - return 0 + if stmt is None: return 0 sk2: int = stmt.kind() if sk2 == ast.ASTKind.If: ifn2: rawptr[ast.If] = rawptr[ast.If](stmt) - if ifn2.test is not None and self._find_expr_await(ifn2.test) is not None: - return 1 - if self._stmts_deep_await(stmt.children) != 0: - return 1 + if ifn2.test is not None and self._find_expr_await(ifn2.test) is not None: return 1 + if self._stmts_deep_await(stmt.children) != 0: return 1 return self._stmts_deep_await(ifn2.orelse) if sk2 == ast.ASTKind.While: whn2: rawptr[ast.While] = rawptr[ast.While](stmt) - if whn2.test is not None and self._find_expr_await(whn2.test) is not None: - return 1 - if self._stmts_deep_await(stmt.children) != 0: - return 1 + if whn2.test is not None and self._find_expr_await(whn2.test) is not None: return 1 + if self._stmts_deep_await(stmt.children) != 0: return 1 return self._stmts_deep_await(whn2.orelse) - if sk2 == ast.ASTKind.For: - return self._for_deep_await(stmt) + if sk2 == ast.ASTKind.For: return self._for_deep_await(stmt) if sk2 == ast.ASTKind.Try: tr3: ast.Try* = ast.Try*(stmt) - if self._stmts_deep_await(stmt.children) != 0: - return 1 + if self._stmts_deep_await(stmt.children) != 0: return 1 if tr3.handlers is not None: nh3: sizet = len(tr3.handlers) hh3: sizet = 0 for hh3 in range(nh3): h3: ast.AST* = tr3.handlers.get(hh3) - if h3 is not None and self._stmts_deep_await(h3.children) != 0: - return 1 - if self._stmts_deep_await(tr3.orelse) != 0: - return 1 + if h3 is not None and self._stmts_deep_await(h3.children) != 0: return 1 + if self._stmts_deep_await(tr3.orelse) != 0: return 1 return self._stmts_deep_await(tr3.finalbody) return self._stmt_has_await(stmt) def _stmts_deep_await(self, stmts: list[ast.AST*]*) -> int: - if stmts is None: - return 0 + if stmts is None: return 0 bn6: sizet = len(stmts) i6: sizet = 0 for i6 in range(bn6): - if self._stmt_deep_await(stmts.get(i6)) != 0: - return 1 + if self._stmt_deep_await(stmts.get(i6)) != 0: return 1 return 0 def _is_range_for(self, stmt: ast.AST*) -> int: """range-For:单 Name target + iter 是 range(x) 或 range(a, b),参数无 await""" - if stmt is None: - return 0 + if stmt is None: return 0 fn4: ast.For* = ast.For*(stmt) - if fn4.target is None or fn4.target.kind() != ast.ASTKind.Name: - return 0 - if fn4.iter is None or fn4.iter.kind() != ast.ASTKind.Call: - return 0 + if fn4.target is None or fn4.target.kind() != ast.ASTKind.Name: return 0 + if fn4.iter is None or fn4.iter.kind() != ast.ASTKind.Call: return 0 cl4: ast.Call* = ast.Call*(fn4.iter) - if cl4.func is None or cl4.func.kind() != ast.ASTKind.Name: - return 0 + if cl4.func is None or cl4.func.kind() != ast.ASTKind.Name: return 0 nm4: ast.Name* = ast.Name*(cl4.func) - if nm4.id is None or string.strcmp(nm4.id, "range") != 0: - return 0 - if cl4.args is None: - return 0 + if nm4.id is None or string.strcmp(nm4.id, "range") != 0: return 0 + if cl4.args is None: return 0 nb7: sizet = len(cl4.args) - if nb7 != 1 and nb7 != 2: - return 0 + if nb7 != 1 and nb7 != 2: return 0 j7: sizet = 0 for j7 in range(nb7): - if self._find_expr_await(cl4.args.get(j7)) is not None: - return 0 + if self._find_expr_await(cl4.args.get(j7)) is not None: return 0 return 1 # ============================================================ @@ -598,27 +528,22 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): - try 的 except as e 绑定名(M5/M6,跨 handler 需要帧槽) - 含 await 的 range-For 迭代目标(M3) 递归扫描(If/While/For/Try 嵌套)。""" - if fd is None or fd.children is None or trans is None: - return 0 - if trans._coro_locals is None: - return 0 + if fd is None or fd.children is None or trans is None: return 0 + if trans._coro_locals is None: return 0 trans._coro_local_count = 0 self._collect_locals_stmts(trans, fd.children) return trans._coro_local_count def _collect_locals_stmts(self, trans: HT.Translator*, stmts: list[ast.AST*]*): - if stmts is None: - return + if stmts is None: return bn: sizet = len(stmts) i: sizet = 0 - for i in range(bn): - self._collect_locals_stmt(trans, stmts.get(i)) + for i in range(bn): self._collect_locals_stmt(trans, stmts.get(i)) def _collect_locals_stmt(self, trans: HT.Translator*, stmt: ast.AST*): - if stmt is None: - return + if stmt is None: return sk: int = stmt.kind() if sk == ast.ASTKind.AnnAssign: aa: ast.AnnAssign* = ast.AnnAssign*(stmt) @@ -661,8 +586,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): hh: sizet = 0 for hh in range(nh): h0: ast.AST* = tr.handlers.get(hh) - if h0 is None: - continue + if h0 is None: continue hd: ast.ExceptHandler* = ast.ExceptHandler*(h0) self._add_local(trans, hd.name) self._collect_locals_stmts(trans, h0.children) @@ -672,11 +596,9 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): def _add_local(self, trans: HT.Translator*, name: str): - if name is None: - return + if name is None: return cnt: int = trans._coro_local_count - if cnt >= HT.MAX_CORO_VARS: - return + if cnt >= HT.MAX_CORO_VARS: return addr: uint64 = uint64(trans._coro_locals) + cnt * 8 slot: str* = (str*)(addr) slot[0] = name @@ -707,29 +629,22 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): fi: int = 0 for fi in range(total): fty: mlirlite.LLVMType* = i32_ty - if fi == 4: - fty = i8_ptr_ty + if fi == 4: fty = i8_ptr_ty elif fi >= trans._coro_extra_base: tidx: int = fi - trans._coro_extra_base if tidx < nextra and trans._coro_extra_types is not None: - if trans._coro_extra_types[tidx] == 2: - fty = i64_ty + if trans._coro_extra_types[tidx] == 2: fty = i64_ty pnode: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__()) - if pnode is None: - continue + if pnode is None: continue string.memset(pnode, 0, mlirlite.ParamNode.__sizeof__()) pnode.Ty = fty - if head is None: - head = pnode - if prev is not None: - prev.Next = pnode + if head is None: head = pnode + if prev is not None: prev.Next = pnode prev = pnode ty_name: str = pool.alloc(128) - if ty_name is not None: - viperlib.snprintf(ty_name, 128, "Coro_%s", name) + if ty_name is not None: viperlib.snprintf(ty_name, 128, "Coro_%s", name) frame_ty: mlirlite.LLVMType* = mlirlite.Struct(pool, head, total, ty_name) - if frame_ty is None: - return None + if frame_ty is None: return None mlirlite.module_add_named_type(mod, pool, frame_ty) self.Gen.StructGen.register_struct(pool, ty_name, frame_ty, trans.ModuleSha1) return frame_ty @@ -745,8 +660,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): nparams: int) -> int: """生成 create_(args...):M7 帧池弹帧(i64 池头 free-list)或 malloc, 5 头清零 + 参数存槽(帧槽 5+i)+ ret 帧指针""" - if frame_ty is None: - return 0 + if frame_ty is None: return 0 i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool) i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) @@ -755,48 +669,39 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): frame_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, frame_ty) cname_buf2: str = pool.alloc(64) - if cname_buf2 is not None: - viperlib.snprintf(cname_buf2, 64, "create_%s", name) + if cname_buf2 is not None: viperlib.snprintf(cname_buf2, 64, "create_%s", name) mangled: str = self.Gen.FuncGenBase._mangle_func_name(trans, cname_buf2, 0) - if self.Gen.CallGenBase.find_func_in_module(mod, mangled) is not None: - return 0 + if self.Gen.CallGenBase.find_func_in_module(mod, mangled) is not None: return 0 func: mlirlite.Function* = mlirlite.create_function(pool, mod, mangled, frame_ptr_ty) - if func is None: - return 0 + if func is None: return 0 # 参数(i32,帧槽 5+i)。TPV 无 Python % 格式化(% 是取模), # 参数名用 snprintf 生成("%%arg" → "%arg",与 resume "%frame" 命名一致)。 pi: int = 0 argn_buf: str = pool.alloc(16) for pi in range(nparams): - if argn_buf is not None: - viperlib.snprintf(argn_buf, 16, "%%arg%d", pi) + if argn_buf is not None: viperlib.snprintf(argn_buf, 16, "%%arg%d", pi) mlirlite.add_param(pool, func, i32_ty, argn_buf) # 注册到函数表(裸名 create_) funcs_ptr: GenTypes.FuncEntry* = trans._funcs cur_count: int = trans._func_count - if self.Gen.CallGenLeafKit.add_func_to_table(funcs_ptr, cur_count, cname_buf2, func, 1024, None, 0, 0, trans.Pool) == 0: - trans._func_count = cur_count + 1 + if self.Gen.CallGenLeafKit.add_func_to_table(funcs_ptr, cur_count, cname_buf2, func, 1024, None, 0, 0, trans.Pool) == 0: trans._func_count = cur_count + 1 entry: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "entry") - if entry is None: - return 0 + if entry is None: return 0 builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, func) - if builder is None: - return 0 + if builder is None: return 0 mlirlite.position_at_end(builder, entry) frame_size: int = self.Gen.ClassGenEnum._get_type_size(frame_ty) size_val: mlirlite.Value* = mlirlite.const_int64(pool, frame_size) - if size_val is None: - return 0 + if size_val is None: return 0 size_val.Next = None # M7 帧池:i64 池头(0 = 空);帧首 8 字节存 next(覆盖 state/done,弹池后统一清零) pool_gv: mlirlite.GlobalVariable* = self._get_coro_pool(pool, mod, trans, name) # GlobalVariable 非 Value 子类:构造 Value 视图(Ty=Ptr(i64), Name="@coro_pool_") pool_ref_name: str = pool.alloc(96) - if pool_ref_name is not None: - viperlib.snprintf(pool_ref_name, 96, "@coro_pool_%s", name) + if pool_ref_name is not None: viperlib.snprintf(pool_ref_name, 96, "@coro_pool_%s", name) pool_ref: mlirlite.Value* = mlirlite.SSAValue(pool, i64_ptr_ty, pool_ref_name) pool_head: mlirlite.Value* = mlirlite.build_load(builder, i64_ty, pool_ref) if pool_head is None: return 0 @@ -806,65 +711,53 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): hit_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "pool.hit") miss_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "pool.miss") join_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "pool.join") - if hit_bb is None or miss_bb is None or join_bb is None: - return 0 + if hit_bb is None or miss_bb is None or join_bb is None: return 0 mlirlite.build_cond_br(builder, empty_cond, miss_bb, hit_bb) # hit:弹池(帧首 8 字节是 next) mlirlite.position_at_end(builder, hit_bb) node_next_ptr: mlirlite.Value* = mlirlite.build_inttoptr(builder, pool_head, i64_ptr_ty) next_head: mlirlite.Value* = mlirlite.build_load(builder, i64_ty, node_next_ptr) - if next_head is None: - return 0 + if next_head is None: return 0 mlirlite.build_store(builder, next_head, pool_ref) hit_frame: mlirlite.Value* = mlirlite.build_inttoptr(builder, pool_head, frame_ptr_ty) - if hit_frame is None: - return 0 + if hit_frame is None: return 0 mlirlite.build_br(builder, join_bb) # miss:malloc + 帧首 8 字节置 0(弹池帧的 next 残留清零) mlirlite.position_at_end(builder, miss_bb) raw: mlirlite.Value* = mlirlite.build_call(builder, "malloc", size_val, 1, i8_ptr_ty, 0) - if raw is None: - return 0 + if raw is None: return 0 miss_frame: mlirlite.Value* = mlirlite.build_bitcast(builder, raw, frame_ptr_ty) - if miss_frame is None: - return 0 + if miss_frame is None: return 0 miss_head_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, miss_frame, i64_ptr_ty) - if miss_head_ptr is not None: - mlirlite.build_store(builder, zero64, miss_head_ptr) + if miss_head_ptr is not None: mlirlite.build_store(builder, zero64, miss_head_ptr) mlirlite.build_br(builder, join_bb) # join:phi 选帧 + 5 头清零(弹池复用帧必须重置 state/done/ret/exc/msg)+ 参数存槽 mlirlite.position_at_end(builder, join_bb) inc1: mlirlite.PhiIncoming* = mlirlite.new_phi_incoming(pool, hit_frame, hit_bb) inc2: mlirlite.PhiIncoming* = mlirlite.new_phi_incoming(pool, miss_frame, miss_bb) - if inc1 is None or inc2 is None: - return 0 + if inc1 is None or inc2 is None: return 0 inc1.Next = inc2 frame_ref: mlirlite.Value* = mlirlite.build_phi(builder, frame_ptr_ty, inc1, 2) - if frame_ref is None: - return 0 + if frame_ref is None: return 0 zero: mlirlite.Value* = mlirlite.const_int32(pool, 0) null_p: mlirlite.Value* = mlirlite.ConstNull(pool, i8_ptr_ty, "null") si: int = 0 for si in range(5): if si == 4: mslot: mlirlite.Value* = mlirlite.build_gep_struct(builder, frame_ty, i8_ptr_ty, frame_ref, 4) - if mslot is not None: - mlirlite.build_store(builder, null_p, mslot) + if mslot is not None: mlirlite.build_store(builder, null_p, mslot) else: slot: mlirlite.Value* = mlirlite.build_gep_struct(builder, frame_ty, i32_ty, frame_ref, si) - if slot is not None: - mlirlite.build_store(builder, zero, slot) + if slot is not None: mlirlite.build_store(builder, zero, slot) # 参数存帧槽(index 5+i) pj: int = 0 for pj in range(nparams): pslot: mlirlite.Value* = mlirlite.build_gep_struct(builder, frame_ty, i32_ty, frame_ref, 5 + pj) if pslot is not None: arnb: str = pool.alloc(16) - if arnb is not None: - viperlib.snprintf(arnb, 16, "%%arg%d", pj) + if arnb is not None: viperlib.snprintf(arnb, 16, "%%arg%d", pj) arg_ref: mlirlite.Value* = mlirlite.SSAValue(pool, i32_ty, arnb) - if arg_ref is not None: - mlirlite.build_store(builder, arg_ref, pslot) + if arg_ref is not None: mlirlite.build_store(builder, arg_ref, pslot) mlirlite.build_ret(builder, frame_ref) return 0 @@ -877,24 +770,20 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): name: str) -> mlirlite.GlobalVariable*: """取/建 coro_pool_ 全局(i64 池头)。池节点 next 存帧首 8 字节。""" pn_buf: str = pool.alloc(128) - if pn_buf is not None: - viperlib.snprintf(pn_buf, 128, "coro_pool_%s", name) + if pn_buf is not None: viperlib.snprintf(pn_buf, 128, "coro_pool_%s", name) # 幂等:create/destroy 都会调用,须先查模块全局链表(无 find_global API) g: mlirlite.GlobalVariable* = mod.GlobalHead while g is not None: - if g.Name is not None and string.strcmp(g.Name, pn_buf) == 0: - return g + if g.Name is not None and string.strcmp(g.Name, pn_buf) == 0: return g g = g.Next return mlirlite.create_global_int(pool, mod, pn_buf, 64, 0) def _register_coro_wake(self, trans: HT.Translator*, name: str, wake_idx: int): """记录 async 名的 wake 槽 index(_coro_wake_names/_coro_wake_idxs 平行表)""" - if trans is None or name is None or trans._coro_wake_names is None: - return + if trans is None or name is None or trans._coro_wake_names is None: return cnt: int = trans._coro_wake_count - if cnt >= HT.MAX_CORO_FUNCS: - return + if cnt >= HT.MAX_CORO_FUNCS: return addr: uint64 = uint64(trans._coro_wake_names) + cnt * 8 slot: str* = (str*)(addr) slot[0] = name @@ -904,14 +793,12 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): def _lookup_coro_wake(self, trans: HT.Translator*, name: str) -> int: """查 async 名的 wake 槽 index,无 wake 槽返回 -1""" - if trans is None or name is None or trans._coro_wake_names is None: - return -1 + if trans is None or name is None or trans._coro_wake_names is None: return -1 i: int = 0 for i in range(trans._coro_wake_count): addr: uint64 = uint64(trans._coro_wake_names) + i * 8 slot: str* = (str*)(addr) - if slot[0] is not None and string.strcmp(slot[0], name) == 0: - return trans._coro_wake_idxs[i] + if slot[0] is not None and string.strcmp(slot[0], name) == 0: return trans._coro_wake_idxs[i] return -1 # ============================================================ @@ -929,18 +816,15 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): entry 读 state → switch → state0 主入口递归翻译整个函数体; 每个 await(顶层或嵌套,DFS 序)分配 state{N} 恢复块(预建 case); exit 块 load done 返回(0=SUSPEND 1=DONE)。""" - if frame_ty is None: - return 0 + if frame_ty is None: return 0 i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) frame_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, frame_ty) rname_buf: str = pool.alloc(64) - if rname_buf is not None: - viperlib.snprintf(rname_buf, 64, "resume_%s", name) + if rname_buf is not None: viperlib.snprintf(rname_buf, 64, "resume_%s", name) mangled: str = self.Gen.FuncGenBase._mangle_func_name(trans, rname_buf, 0) func: mlirlite.Function* = mlirlite.create_function(pool, mod, mangled, i32_ty) - if func is None: - return 0 + if func is None: return 0 mlirlite.add_param(pool, func, frame_ptr_ty, "%frame") funcs_ptr: GenTypes.FuncEntry* = trans._funcs cur_count: int = trans._func_count @@ -949,16 +833,13 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): trans._func_count = cur_count + 1 entry: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "entry") - if entry is None: - return 0 + if entry is None: return 0 builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, func) - if builder is None: - return 0 + if builder is None: return 0 mlirlite.position_at_end(builder, entry) frame_arg: mlirlite.Value* = mlirlite.SSAValue(pool, frame_ptr_ty, "%frame") - if frame_arg is None: - return 0 + if frame_arg is None: return 0 # GEP 5 头槽(M4 exc / M7 msg) i8_ptr_ty_r: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) @@ -973,22 +854,18 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): pj: int = 0 for pj in range(nparams): pname: str = self._read_param_name(trans, pj) - if pname is None: - continue + if pname is None: continue pslot: mlirlite.Value* = mlirlite.build_gep_struct(builder, frame_ty, i32_ty, frame_arg, 5 + pj) - if pslot is not None: - self.Gen.VarGen.define_var(trans.SymTab, pname, pslot) + if pslot is not None: self.Gen.VarGen.define_var(trans.SymTab, pname, pslot) # 局部槽 GEP → 注册到符号表 li: int = 0 for li in range(nlocals): lname: str = self._read_local_name(trans, li) - if lname is None: - continue + if lname is None: continue slot: mlirlite.Value* = mlirlite.build_gep_struct(builder, frame_ty, i32_ty, frame_arg, trans._coro_local_base + li) - if slot is not None: - self.Gen.VarGen.define_var(trans.SymTab, lname, slot) + if slot is not None: self.Gen.VarGen.define_var(trans.SymTab, lname, slot) # M3-M7:额外槽注册(wake i64 / __f_idx/__f_len/__await i32)。 # 名字反查:wake=uses_sleep 且 ei==0;for=位置数组 _coro_for_slots; @@ -996,15 +873,12 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): ei: int = 0 for ei in range(nextra): ety: int = 1 - if trans._coro_extra_types is not None: - ety = trans._coro_extra_types[ei] + if trans._coro_extra_types is not None: ety = trans._coro_extra_types[ei] ety_llvm: mlirlite.LLVMType* = i32_ty - if ety == 2: - ety_llvm = i64_ty_r + if ety == 2: ety_llvm = i64_ty_r eslot: mlirlite.Value* = mlirlite.build_gep_struct(builder, frame_ty, ety_llvm, frame_arg, trans._coro_extra_base + ei) - if eslot is None: - continue + if eslot is None: continue # wake 槽:只存指针,不注册 SymTab(coro_run 轮询用) if trans._coro_uses_sleep != 0 and ei == 0: trans._coro_wake_ptr = eslot @@ -1024,10 +898,8 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): break if is_for != 0: if ename is not None: - if is_len != 0: - viperlib.snprintf(ename, 16, "__f_len_%d", kf) - else: - viperlib.snprintf(ename, 16, "__f_idx_%d", kf) + if is_len != 0: viperlib.snprintf(ename, 16, "__f_len_%d", kf) + else: viperlib.snprintf(ename, 16, "__f_idx_%d", kf) else: # __await_M:反查位置数组 found: int = 0 @@ -1036,18 +908,14 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if trans._coro_await_slots[km] == ei: found = 1 break - if found == 0: - continue - if ename is not None: - viperlib.snprintf(ename, 16, "__await_%d", km) - if ename is not None: - self.Gen.VarGen.define_var(trans.SymTab, ename, eslot) + if found == 0: continue + if ename is not None: viperlib.snprintf(ename, 16, "__await_%d", km) + if ename is not None: self.Gen.VarGen.define_var(trans.SymTab, ename, eslot) # state 值 + exit 块 state_val: mlirlite.Value* = mlirlite.build_load(builder, i32_ty, state_ptr) exit_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.exit") - if exit_bb is None: - return 0 + if exit_bb is None: return 0 # 保存 resume 上下文(await 挂起 / 恢复块共享) trans._coro_state_ptr = state_ptr @@ -1069,12 +937,10 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): trans._coro_continue_bb = None nseg: int = trans._coro_nseg - if nseg <= 0: - nseg = 1 + if nseg <= 0: nseg = 1 # 预建 state 块 + switch case(一次性生成,await 恢复块 position 填充) state_bbs: sizet* = pool.alloc(nseg * 8) - if state_bbs is None: - return 0 + if state_bbs is None: return 0 trans._coro_state_bbs = state_bbs sw_head: rawptr[mlirlite.SwitchCase] = None sw_tail: rawptr[mlirlite.SwitchCase] = None @@ -1082,11 +948,9 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): bb_name: str = pool.alloc(32) si: int = 0 for si in range(nseg): - if bb_name is not None: - viperlib.snprintf(bb_name, 32, "state%d", si) + if bb_name is not None: viperlib.snprintf(bb_name, 32, "state%d", si) sbb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_name) - if sbb is None: - continue + if sbb is None: continue state_bbs[si] = sizet(sbb) sc: rawptr[mlirlite.SwitchCase] = mlirlite.new_switch_case(pool, mlirlite.const_int32(pool, si), sbb) if sc is not None: @@ -1131,17 +995,14 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): mod: mlirlite.LLVMModule*, stmts: list[ast.AST*]*): """递归翻译协程体语句。builder 当前块 = 活跃执行块(state0 或某恢复块)。""" - if stmts is None: - return + if stmts is None: return bn: sizet = len(stmts) i: sizet = 0 for i in range(bn): stmt: ast.AST* = stmts.get(i) - if stmt is None: - continue + if stmt is None: continue # 当前块已终止(return/挂起后无后续)→ 停止本段 - if mlirlite.builder_cur_block_is_terminated(builder) != 0: - return + if mlirlite.builder_cur_block_is_terminated(builder) != 0: return sk: int = stmt.kind() if sk == ast.ASTKind.Return: self._emit_coro_return(builder, pool, mod, trans, stmt) @@ -1159,50 +1020,38 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): tr_: ast.Try* = ast.Try*(stmt) has_fin: int = 0 has_exc: int = 0 - if tr_.finalbody is not None and len(tr_.finalbody) > 0: - has_fin = 1 - if tr_.handlers is not None and len(tr_.handlers) > 0: - has_exc = 1 - if has_fin != 0 and has_exc == 0: - self._handle_coro_try_finally(trans, builder, pool, mod, stmt) - else: - self._handle_coro_try(trans, builder, pool, mod, stmt) + if tr_.finalbody is not None and len(tr_.finalbody) > 0: has_fin = 1 + if tr_.handlers is not None and len(tr_.handlers) > 0: has_exc = 1 + if has_fin != 0 and has_exc == 0: self._handle_coro_try_finally(trans, builder, pool, mod, stmt) + else: self._handle_coro_try(trans, builder, pool, mod, stmt) continue if sk == ast.ASTKind.For: - if self._for_deep_await(stmt) != 0: - self._handle_coro_for(trans, builder, pool, mod, stmt) + if self._for_deep_await(stmt) != 0: self._handle_coro_for(trans, builder, pool, mod, stmt) else: # 无 await:委托标准 For self.Gen.StmtGen.translate_stmt(trans, stmt) continue if sk == ast.ASTKind.Break: - if trans._coro_break_bb is not None: - mlirlite.build_br(builder, trans._coro_break_bb) + if trans._coro_break_bb is not None: mlirlite.build_br(builder, trans._coro_break_bb) continue if sk == ast.ASTKind.Continue: - if trans._coro_continue_bb is not None: - mlirlite.build_br(builder, trans._coro_continue_bb) - continue - if sk == ast.ASTKind.Pass: + if trans._coro_continue_bb is not None: mlirlite.build_br(builder, trans._coro_continue_bb) continue + if sk == ast.ASTKind.Pass: continue # 顶层 await:AnnAssign/Assign/Expr 的 value 直接是 Await → 挂起 if sk == ast.ASTKind.AnnAssign or sk == ast.ASTKind.Assign or sk == ast.ASTKind.Expr: if self._is_await_tail(stmt) != 0: target_name: str = self._get_assign_target_name(stmt) - if target_name is not None: - trans._coro_await_slot = self.Gen.VarGen.lookup_var(trans.SymTab, target_name) + if target_name is not None: trans._coro_await_slot = self.Gen.VarGen.lookup_var(trans.SymTab, target_name) else: # Expr(await ...):无目标槽(丢弃返回值),防残留旧槽 trans._coro_await_slot = None aw_node: rawptr[ast.Await] = self._get_await_value(stmt) call_name: str = None - if aw_node is not None: - call_name = self._extract_await_call_name(aw_node) - if call_name is not None and self.is_async_func(trans, call_name) != 0: - self._emit_await(builder, pool, mod, trans, aw_node, call_name) + if aw_node is not None: call_name = self._extract_await_call_name(aw_node) + if call_name is not None and self.is_async_func(trans, call_name) != 0: self._emit_await(builder, pool, mod, trans, aw_node, call_name) else: - if call_name is None: - call_name = "(unknown)" + 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) @@ -1224,8 +1073,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): mod: mlirlite.LLVMModule*, stmt: ast.AST*): ifn: rawptr[ast.If] = rawptr[ast.If](stmt) - if ifn is None or ifn.test is None: - return + if ifn is None or ifn.test is None: return if self._find_expr_await(ifn.test) is not None: err_b: str = pool.alloc(256) if err_b is not None: @@ -1233,33 +1081,27 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): 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) - if cond is None: - return + if cond is None: return cond1: mlirlite.Value* = self._normalize_cond(builder, pool, mod, cond, trans) func: mlirlite.Function* = trans._cur_func then_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.then") merge_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.end") has_else: int = 0 - if ifn.orelse is not None and len(ifn.orelse) > 0: - has_else = 1 + if ifn.orelse is not None and len(ifn.orelse) > 0: has_else = 1 else_bb: rawptr[mlirlite.BasicBlock] = None - if has_else != 0: - else_bb = mlirlite.create_block(pool, func, "coro.else") - if cond1 is None or then_bb is None or merge_bb is None: - return + if has_else != 0: else_bb = mlirlite.create_block(pool, func, "coro.else") + if cond1 is None or then_bb is None or merge_bb is None: return mlirlite.build_cond_br(builder, cond1, then_bb, else_bb if else_bb is not None else merge_bb) # then 分支 mlirlite.position_at_end(builder, then_bb) self._handle_segment(trans, builder, pool, mod, stmt.children) - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, merge_bb) + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, merge_bb) # else 分支 if else_bb is not None: mlirlite.position_at_end(builder, else_bb) self._handle_segment(trans, builder, pool, mod, ifn.orelse) - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, merge_bb) + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, merge_bb) mlirlite.position_at_end(builder, merge_bb) # ============================================================ @@ -1271,8 +1113,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): mod: mlirlite.LLVMModule*, stmt: ast.AST*): whn: rawptr[ast.While] = rawptr[ast.While](stmt) - if whn is None: - return + if whn is None: return 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: @@ -1283,8 +1124,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): cond_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.wcond") body_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.wbody") after_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.wend") - if cond_bb is None or body_bb is None or after_bb is None: - return + if cond_bb is None or body_bb is None or after_bb is None: return # break/continue 目标(M2 单层) prev_break: rawptr[mlirlite.BasicBlock] = trans._coro_break_bb prev_cont: rawptr[mlirlite.BasicBlock] = trans._coro_continue_bb @@ -1294,15 +1134,13 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): # 条件块 mlirlite.position_at_end(builder, cond_bb) cond: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, whn.test, None, 0, trans) - if cond is None: - cond = mlirlite.const_int32(pool, 0) + if cond is None: cond = mlirlite.const_int32(pool, 0) cond1: mlirlite.Value* = self._normalize_cond(builder, pool, mod, cond, trans) mlirlite.build_cond_br(builder, cond1, body_bb, after_bb) # 循环体 mlirlite.position_at_end(builder, body_bb) self._handle_segment(trans, builder, pool, mod, stmt.children) - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, cond_bb) + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, cond_bb) trans._coro_break_bb = prev_break trans._coro_continue_bb = prev_cont # 循环结束块 @@ -1320,14 +1158,11 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): guard: int = 0 while True: aw_node: rawptr[ast.Await] = self._extract_first_await(stmt) - if aw_node is None: - break - if guard >= HT.MAX_CORO_VARS: - break + if aw_node is None: break + if guard >= HT.MAX_CORO_VARS: break guard = guard + 1 temp_name: str = pool.alloc(32) - if temp_name is not None: - viperlib.snprintf(temp_name, 32, "__await_%d", trans._coro_hoist_count) + if temp_name is not None: viperlib.snprintf(temp_name, 32, "__await_%d", trans._coro_hoist_count) # 目标槽 = __await_N 帧额外槽(预扫描位置数组,wake/for 槽穿插在前) slot_idx: int = trans._coro_extra_base + trans._coro_await_slots[trans._coro_hoist_count] trans._coro_hoist_count = trans._coro_hoist_count + 1 @@ -1335,8 +1170,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): mlirlite.Int32(pool), trans._coro_frame, slot_idx) trans._coro_await_slot = slot call_name: str = self._extract_await_call_name(aw_node) - if call_name is None: - break + if call_name is None: break self._emit_await(builder, pool, mod, trans, aw_node, call_name) self._replace_await_with_name(pool, stmt, temp_name) # 提升完成 → 标准翻译(恢复块内继续执行剩余表达式) @@ -1347,14 +1181,12 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): # ============================================================ def _stmt_has_await(self, stmt: ast.AST*) -> int: aw: rawptr[ast.Await] = self._extract_first_await(stmt) - if aw is not None: - return 1 + if aw is not None: return 1 return 0 def _extract_first_await(self, stmt: ast.AST*) -> rawptr[ast.Await]: """取语句中第一个 Await 节点(DFS 字段序),未命中返回 None""" - if stmt is None: - return None + if stmt is None: return None sk: int = stmt.kind() if sk == ast.ASTKind.AnnAssign: aa: ast.AnnAssign* = ast.AnnAssign*(stmt) @@ -1372,30 +1204,25 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): def _find_expr_await(self, node: ast.AST*) -> rawptr[ast.Await]: """表达式树中 DFS 找第一个 Await""" - if node is None: - return None + if node is None: return None k: int = node.kind() - if k == ast.ASTKind.Await: - return rawptr[ast.Await](node) + if k == ast.ASTKind.Await: return rawptr[ast.Await](node) if k == ast.ASTKind.BinOp: b: ast.BinOp* = ast.BinOp*(node) r: rawptr[ast.Await] = self._find_expr_await(b.left) - if r is not None: - return r + if r is not None: return r return self._find_expr_await(b.right) if k == ast.ASTKind.Call: cl: ast.Call* = ast.Call*(node) if cl.func is not None: r2: rawptr[ast.Await] = self._find_expr_await(cl.func) - if r2 is not None: - return r2 + if r2 is not None: return r2 if cl.args is not None: nb: sizet = len(cl.args) j: sizet = 0 for j in range(nb): r3: rawptr[ast.Await] = self._find_expr_await(cl.args.get(j)) - if r3 is not None: - return r3 + if r3 is not None: return r3 return None if k == ast.ASTKind.UnaryOp: u: ast.UnaryOp* = ast.UnaryOp*(node) @@ -1403,15 +1230,13 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if k == ast.ASTKind.Compare: cm: rawptr[ast.Compare] = rawptr[ast.Compare](node) r4: rawptr[ast.Await] = self._find_expr_await(cm.left) - if r4 is not None: - return r4 + if r4 is not None: return r4 if cm.comparators is not None: nb2: sizet = len(cm.comparators) j2: sizet = 0 for j2 in range(nb2): r5: rawptr[ast.Await] = self._find_expr_await(cm.comparators.get(j2)) - if r5 is not None: - return r5 + if r5 is not None: return r5 return None if k == ast.ASTKind.BoolOp: bo: rawptr[ast.BoolOp] = rawptr[ast.BoolOp](node) @@ -1420,17 +1245,14 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): j3: sizet = 0 for j3 in range(nb3): r6: rawptr[ast.Await] = self._find_expr_await(bo.values.get(j3)) - if r6 is not None: - return r6 + if r6 is not None: return r6 return None if k == ast.ASTKind.IfExp: ie: rawptr[ast.IfExp] = rawptr[ast.IfExp](node) r7: rawptr[ast.Await] = self._find_expr_await(ie.test) - if r7 is not None: - return r7 + if r7 is not None: return r7 r8: rawptr[ast.Await] = self._find_expr_await(ie.body) - if r8 is not None: - return r8 + if r8 is not None: return r8 return self._find_expr_await(ie.orelse) if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(node) @@ -1438,8 +1260,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if k == ast.ASTKind.Subscript: sb: ast.Subscript* = ast.Subscript*(node) r9: rawptr[ast.Await] = self._find_expr_await(sb.value) - if r9 is not None: - return r9 + if r9 is not None: return r9 return self._find_expr_await(sb.slice) return None @@ -1447,28 +1268,23 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): stmt: ast.AST*, temp_name: str) -> int: """把语句树中第一个 Await 替换为 Name(temp_name)(DFS 字段序)""" - if stmt is None or temp_name is None: - return 0 + if stmt is None or temp_name is None: return 0 sk: int = stmt.kind() if sk == ast.ASTKind.AnnAssign: aa: ast.AnnAssign* = ast.AnnAssign*(stmt) - if aa.value is not None: - return self._replace_expr_await(pool, aa.value, temp_name) + if aa.value is not None: return self._replace_expr_await(pool, aa.value, temp_name) return 0 if sk == ast.ASTKind.Assign: as_: ast.Assign* = ast.Assign*(stmt) - if as_.value is not None: - return self._replace_expr_await(pool, as_.value, temp_name) + if as_.value is not None: return self._replace_expr_await(pool, as_.value, temp_name) return 0 if sk == ast.ASTKind.Expr: e: rawptr[ast.Expr] = rawptr[ast.Expr](stmt) - if e.value is not None: - return self._replace_expr_await(pool, e.value, temp_name) + if e.value is not None: return self._replace_expr_await(pool, e.value, temp_name) return 0 if sk == ast.ASTKind.Return: rv: rawptr[ast.Return] = rawptr[ast.Return](stmt) - if rv.value is not None: - return self._replace_expr_await(pool, rv.value, temp_name) + if rv.value is not None: return self._replace_expr_await(pool, rv.value, temp_name) return 0 return 0 @@ -1477,22 +1293,18 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): temp_name: str) -> int: """在表达式树中把第一个 Await 替换为 Name(temp_name, Load)。 node 本身是 Await 时返回 2(由父字段替换)。返回 1=已替换 0=无 2=node 即 Await。""" - if node is None: - return 0 + if node is None: return 0 k: int = node.kind() - if k == ast.ASTKind.Await: - return 2 + if k == ast.ASTKind.Await: return 2 if k == ast.ASTKind.BinOp: b: ast.BinOp* = ast.BinOp*(node) r: int = self._replace_expr_await(pool, b.left, temp_name) - if r == 1: - return 1 + if r == 1: return 1 if r == 2: b.left = ast.Name(pool, temp_name, 0) return 1 r2: int = self._replace_expr_await(pool, b.right, temp_name) - if r2 == 1: - return 1 + if r2 == 1: return 1 if r2 == 2: b.right = ast.Name(pool, temp_name, 0) return 1 @@ -1501,8 +1313,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): cl: ast.Call* = ast.Call*(node) if cl.func is not None: r3: int = self._replace_expr_await(pool, cl.func, temp_name) - if r3 == 1: - return 1 + if r3 == 1: return 1 if r3 == 2: cl.func = ast.Name(pool, temp_name, 0) return 1 @@ -1511,8 +1322,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): j: sizet = 0 for j in range(nb): r4: int = self._replace_expr_await(pool, cl.args.get(j), temp_name) - if r4 == 1: - return 1 + if r4 == 1: return 1 if r4 == 2: cl.args.set(j, ast.Name(pool, temp_name, 0)) return 1 @@ -1520,8 +1330,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if k == ast.ASTKind.UnaryOp: u: ast.UnaryOp* = ast.UnaryOp*(node) r5: int = self._replace_expr_await(pool, u.operand, temp_name) - if r5 == 1: - return 1 + if r5 == 1: return 1 if r5 == 2: u.operand = ast.Name(pool, temp_name, 0) return 1 @@ -1529,8 +1338,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if k == ast.ASTKind.Compare: cm: rawptr[ast.Compare] = rawptr[ast.Compare](node) r6: int = self._replace_expr_await(pool, cm.left, temp_name) - if r6 == 1: - return 1 + if r6 == 1: return 1 if r6 == 2: cm.left = ast.Name(pool, temp_name, 0) return 1 @@ -1539,8 +1347,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): j2: sizet = 0 for j2 in range(nb2): r7: int = self._replace_expr_await(pool, cm.comparators.get(j2), temp_name) - if r7 == 1: - return 1 + if r7 == 1: return 1 if r7 == 2: cm.comparators.set(j2, ast.Name(pool, temp_name, 0)) return 1 @@ -1552,8 +1359,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): j3: sizet = 0 for j3 in range(nb3): r8: int = self._replace_expr_await(pool, bo.values.get(j3), temp_name) - if r8 == 1: - return 1 + if r8 == 1: return 1 if r8 == 2: bo.values.set(j3, ast.Name(pool, temp_name, 0)) return 1 @@ -1561,20 +1367,17 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if k == ast.ASTKind.IfExp: ie: rawptr[ast.IfExp] = rawptr[ast.IfExp](node) r9: int = self._replace_expr_await(pool, ie.test, temp_name) - if r9 == 1: - return 1 + if r9 == 1: return 1 if r9 == 2: ie.test = ast.Name(pool, temp_name, 0) return 1 r10: int = self._replace_expr_await(pool, ie.body, temp_name) - if r10 == 1: - return 1 + if r10 == 1: return 1 if r10 == 2: ie.body = ast.Name(pool, temp_name, 0) return 1 r11: int = self._replace_expr_await(pool, ie.orelse, temp_name) - if r11 == 1: - return 1 + if r11 == 1: return 1 if r11 == 2: ie.orelse = ast.Name(pool, temp_name, 0) return 1 @@ -1582,8 +1385,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(node) r12: int = self._replace_expr_await(pool, at.value, temp_name) - if r12 == 1: - return 1 + if r12 == 1: return 1 if r12 == 2: at.value = ast.Name(pool, temp_name, 0) return 1 @@ -1591,14 +1393,12 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if k == ast.ASTKind.Subscript: sb: ast.Subscript* = ast.Subscript*(node) r13: int = self._replace_expr_await(pool, sb.value, temp_name) - if r13 == 1: - return 1 + if r13 == 1: return 1 if r13 == 2: sb.value = ast.Name(pool, temp_name, 0) return 1 r14: int = self._replace_expr_await(pool, sb.slice, temp_name) - if r14 == 1: - return 1 + if r14 == 1: return 1 if r14 == 2: sb.slice = ast.Name(pool, temp_name, 0) return 1 @@ -1621,8 +1421,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): # ============================================================ def _read_param_name(self, trans: HT.Translator*, idx: int) -> str: - if trans is None or trans._coro_params is None: - return None + if trans is None or trans._coro_params is None: return None addr: uint64 = uint64(trans._coro_params) + idx * 8 slot: str* = (str*)(addr) return slot[0] @@ -1632,10 +1431,8 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): # ============================================================ def _get_state_bb(self, trans: HT.Translator*, state_no: int) -> rawptr[mlirlite.BasicBlock]: - if trans is None or trans._coro_state_bbs is None: - return None - if state_no < 0 or state_no >= trans._coro_nseg: - return None + if trans is None or trans._coro_state_bbs is None: return None + if state_no < 0 or state_no >= trans._coro_nseg: return None # 注意:state_bbs 数组存的是块指针(sizet),必须下标取值, # 不能取元素地址(uint64(数组)+idx*8 是地址,会导致 position # 到非法块 → IR 指令链损坏 → RenumberSSA/FunctionPrint 崩溃)。 @@ -1645,11 +1442,9 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): """取当前 resume 的帧类型:从 _coro_frames 反查(当前 async 名未知时用帧指针类型不可行, 直接返回当前协程注册的帧类型——_handle_nested_await_stmt 需要帧类型做 GEP。""" # 简化:恢复块 GEP 需要帧类型;从 _coro_frame 的 Ty(Ptr(帧))取 Pointee - if trans is None or trans._coro_frame is None: - return None + if trans is None or trans._coro_frame is None: return None ft: mlirlite.LLVMType* = trans._coro_frame.Ty - if ft is None: - return None + if ft is None: return None match ft: case LLVMType.Ptr(): return ft.Pointee @@ -1668,28 +1463,22 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): 父挂起(state 分配 + br exit + position 恢复块);coro_run 轮询续跑。""" i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool) i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) - if node is None or trans is None or trans._coro_wake_ptr is None: - return mlirlite.const_int32(pool, 0) + if node is None or trans is None or trans._coro_wake_ptr is None: return mlirlite.const_int32(pool, 0) ms_val: mlirlite.Value* = mlirlite.const_int64(pool, 0) aw_s: rawptr[ast.Await] = rawptr[ast.Await](node) if aw_s.value is not None and aw_s.value.kind() == ast.ASTKind.Call: cl_s: ast.Call* = ast.Call*(aw_s.value) if cl_s.args is not None and len(cl_s.args) > 0: ms_v: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cl_s.args.get(0), None, 0, trans) - if ms_v is not None: - ms_val = ms_v + if ms_v is not None: ms_val = ms_v # GetTickCount64() + ms(i64) now_fn: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, "GetTickCount64") - if now_fn is None: - now_fn = mlirlite.create_declare(pool, mod, "GetTickCount64", i64_ty) - if now_fn is None: - return mlirlite.const_int32(pool, 0) + if now_fn is None: now_fn = mlirlite.create_declare(pool, mod, "GetTickCount64", i64_ty) + if now_fn is None: return mlirlite.const_int32(pool, 0) now_val: mlirlite.Value* = mlirlite.build_call(builder, "GetTickCount64", None, 0, i64_ty, 0) - if now_val is None: - return mlirlite.const_int32(pool, 0) + if now_val is None: return mlirlite.const_int32(pool, 0) wake_val: mlirlite.Value* = mlirlite.build_add(builder, now_val, ms_val) - if wake_val is None: - return mlirlite.const_int32(pool, 0) + if wake_val is None: return mlirlite.const_int32(pool, 0) mlirlite.build_store(builder, wake_val, trans._coro_wake_ptr) # 父挂起:新状态号 + br exit + position 恢复块 new_state_s: int = trans._coro_next_state @@ -1698,8 +1487,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): mlirlite.build_store(builder, st_v_s, trans._coro_state_ptr) mlirlite.build_br(builder, trans._coro_exit_bb) resume_bb_s: rawptr[mlirlite.BasicBlock] = self._get_state_bb(trans, new_state_s) - if resume_bb_s is not None: - mlirlite.position_at_end(builder, resume_bb_s) + if resume_bb_s is not None: mlirlite.position_at_end(builder, resume_bb_s) return mlirlite.const_int32(pool, 0) # ============================================================ @@ -1721,14 +1509,11 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): exc_code = mlirlite.const_int32(pool, code) # M7:异常消息(Exception("msg") 首参) msg_v: mlirlite.Value* = self._resolve_raise_msg(builder, pool, mod, trans, rz.exc) - if msg_v is not None and trans._coro_msg_ptr is not None: - mlirlite.build_store(builder, msg_v, trans._coro_msg_ptr) + if msg_v is not None and trans._coro_msg_ptr is not None: mlirlite.build_store(builder, msg_v, trans._coro_msg_ptr) else: v: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, rz.exc, None, 0, trans) - if v is not None: - exc_code = v - if trans._coro_exc_ptr is not None: - mlirlite.build_store(builder, exc_code, trans._coro_exc_ptr) + if v is not None: exc_code = v + if trans._coro_exc_ptr is not None: mlirlite.build_store(builder, exc_code, trans._coro_exc_ptr) # 跳 try except / 终止 if trans._coro_try_stack_count > 0: tbb_r: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](trans._coro_try_stack[trans._coro_try_stack_count - 1]) @@ -1741,8 +1526,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): def _resolve_raise_code(self, pool: memhub.MemBuddy*, exc_node: ast.AST*) -> int: """解析 raise 目标的异常码(内置/用户异常类名);非异常类返回 0""" - if exc_node is None: - return 0 + if exc_node is None: return 0 name: str = None if exc_node.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(exc_node) @@ -1755,8 +1539,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): elif exc_node.kind() == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(exc_node) name = at.attr - if name is None: - return 0 + if name is None: return 0 return self.Gen.ClassGenBase.lookup_exception_code(name) def _resolve_raise_msg(self, builder: mlirlite.IRBuilder*, @@ -1765,11 +1548,9 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): trans: HT.Translator*, exc_node: ast.AST*) -> mlirlite.Value*: """取异常消息表达式(Exception("msg") 首参),无则返回 None""" - if exc_node is None or exc_node.kind() != ast.ASTKind.Call: - return None + if exc_node is None or exc_node.kind() != ast.ASTKind.Call: return None cl: ast.Call* = ast.Call*(exc_node) - if cl.args is None or len(cl.args) < 1: - return None + if cl.args is None or len(cl.args) < 1: return None return self.Gen.ExprGen.translate_value(builder, pool, mod, cl.args.get(0), None, 0, trans) # ============================================================ @@ -1785,11 +1566,9 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): 全不匹配重新传播(done=1 + br exit)。""" i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) tr: ast.Try* = ast.Try*(stmt) - if tr is None: - return + if tr is None: return nhandlers: int = 0 - if tr.handlers is not None: - nhandlers = len(tr.handlers) + if tr.handlers is not None: nhandlers = len(tr.handlers) if nhandlers == 0: err_t: str = pool.alloc(256) if err_t is not None: @@ -1799,26 +1578,22 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): func: mlirlite.Function* = trans._cur_func except_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.try_except") merge_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.try_merge") - if except_bb is None or merge_bb is None: - return + if except_bb is None or merge_bb is None: return # try 栈 push if trans._coro_try_stack_count < HT.MAX_CORO_TRY: trans._coro_try_stack[trans._coro_try_stack_count] = sizet(except_bb) trans._coro_try_stack_count = trans._coro_try_stack_count + 1 # try body self._handle_segment(trans, builder, pool, mod, stmt.children) - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, merge_bb) - if trans._coro_try_stack_count > 0: - trans._coro_try_stack_count = trans._coro_try_stack_count - 1 + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, merge_bb) + if trans._coro_try_stack_count > 0: trans._coro_try_stack_count = trans._coro_try_stack_count - 1 # ---- 异常分发:exc 码依次匹配各 except ---- mlirlite.position_at_end(builder, except_bb) exc_val: mlirlite.Value* = mlirlite.build_load(builder, i32_ty, trans._coro_exc_ptr) # 预建 check/handler/unmatched 块 check_bbs: sizet* = pool.alloc((nhandlers + 1) * 8) handler_bbs: sizet* = pool.alloc(nhandlers * 8) - if check_bbs is None or handler_bbs is None: - return + if check_bbs is None or handler_bbs is None: return check_bbs[0] = sizet(except_bb) hi: int = 0 for hi in range(nhandlers): @@ -1828,8 +1603,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): # 的 name: str 参数收 i32 → int→ptr 禁令误报(CastError 根因)。 chk_name: str = pool.alloc(64) exc_name: str = pool.alloc(64) - if chk_name is None or exc_name is None: - return + if chk_name is None or exc_name is None: return viperlib.snprintf(chk_name, 64, "coro.exc_check_%d", hi) viperlib.snprintf(exc_name, 64, "coro.except_%d", hi) check_bbs[hi + 1] = sizet(mlirlite.create_block(pool, func, chk_name)) @@ -1845,36 +1619,26 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): ncodes: int = 0 if h_node is not None: hd: ast.ExceptHandler* = ast.ExceptHandler*(h_node) - if hd.type is None: - catch_all = 1 + if hd.type is None: catch_all = 1 else: ename: str = self._exception_type_name(pool, hd.type) - if ename is not None and string.strcmp(ename, "Exception") == 0: - catch_all = 1 - else: - ncodes = self.Gen.ClassGenBase.collect_descendant_codes(ename, codes_buf, 64) + if ename is not None and string.strcmp(ename, "Exception") == 0: catch_all = 1 + else: ncodes = self.Gen.ClassGenBase.collect_descendant_codes(ename, codes_buf, 64) next_check: rawptr[mlirlite.BasicBlock] = None - if hi + 1 < nhandlers: - next_check = rawptr[mlirlite.BasicBlock](check_bbs[hi + 1]) - else: - next_check = unmatched_bb + if hi + 1 < nhandlers: next_check = rawptr[mlirlite.BasicBlock](check_bbs[hi + 1]) + else: next_check = unmatched_bb handler_bb: rawptr[mlirlite.BasicBlock] = (rawptr[mlirlite.BasicBlock])(handler_bbs[hi]) - if catch_all != 0: - mlirlite.build_br(builder, handler_bb) + if catch_all != 0: mlirlite.build_br(builder, handler_bb) else: match_cond: mlirlite.Value* = None ci: int = 0 for ci in range(ncodes): eq_v: mlirlite.Value* = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, exc_val, mlirlite.const_int32(pool, codes_buf[ci])) - if match_cond is None: - match_cond = eq_v - else: - match_cond = mlirlite.build_or(builder, match_cond, eq_v) - if match_cond is None: - mlirlite.build_br(builder, next_check) - else: - mlirlite.build_cond_br(builder, match_cond, handler_bb, next_check) + if match_cond is None: match_cond = eq_v + else: match_cond = mlirlite.build_or(builder, match_cond, eq_v) + if match_cond is None: mlirlite.build_br(builder, next_check) + else: mlirlite.build_cond_br(builder, match_cond, handler_bb, next_check) # 未匹配:异常继续传播(重新终止协程) mlirlite.position_at_end(builder, unmatched_bb) done_u: mlirlite.Value* = mlirlite.const_int32(pool, 1) @@ -1897,15 +1661,13 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): z_clr: mlirlite.Value* = mlirlite.const_int32(pool, 0) mlirlite.build_store(builder, z_clr, trans._coro_exc_ptr) self._handle_segment(trans, builder, pool, mod, h_node2.children) - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, merge_bb) + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, merge_bb) mlirlite.position_at_end(builder, merge_bb) def _exception_type_name(self, pool: memhub.MemBuddy*, type_node: ast.AST*) -> str: """取 except 类型名(Name/Attribute),未命中返回 None""" - if type_node is None: - return None + if type_node is None: return None if type_node.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(type_node) return nm.id @@ -1926,8 +1688,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): 异常时 finally 后重新传播(done=1 + br exit);finally 内不支持 await。""" i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) tr: ast.Try* = ast.Try*(stmt) - if tr is None: - return + if tr is None: return 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: @@ -1938,25 +1699,21 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): fin_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.fin") fin_exc_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.fin_exc") merge_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.fin_merge") - if fin_bb is None or fin_exc_bb is None or merge_bb is None: - return + if fin_bb is None or fin_exc_bb is None or merge_bb is None: return # try 栈 push(异常跳 finally) if trans._coro_try_stack_count < HT.MAX_CORO_TRY: trans._coro_try_stack[trans._coro_try_stack_count] = sizet(fin_bb) trans._coro_try_stack_count = trans._coro_try_stack_count + 1 self._handle_segment(trans, builder, pool, mod, stmt.children) - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, fin_bb) - if trans._coro_try_stack_count > 0: - trans._coro_try_stack_count = trans._coro_try_stack_count - 1 + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, fin_bb) + if trans._coro_try_stack_count > 0: trans._coro_try_stack_count = trans._coro_try_stack_count - 1 # fin_bb:记录异常标志 + 执行 fbody mlirlite.position_at_end(builder, fin_bb) was_exc: mlirlite.Value* = mlirlite.build_icmp(builder, mlirlite.ICMP_NE, mlirlite.build_load(builder, i32_ty, trans._coro_exc_ptr), mlirlite.const_int32(pool, 0)) self._handle_segment(trans, builder, pool, mod, tr.finalbody) - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_cond_br(builder, was_exc, fin_exc_bb, merge_bb) + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_cond_br(builder, was_exc, fin_exc_bb, merge_bb) # fin_exc:finally 后异常继续传播 mlirlite.position_at_end(builder, fin_exc_bb) done_f: mlirlite.Value* = mlirlite.const_int32(pool, 1) @@ -1990,8 +1747,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): i32_ty, trans._coro_frame, idx_idx) len_slot: mlirlite.Value* = mlirlite.build_gep_struct(builder, self._lookup_coro_frame_by_trans(trans), i32_ty, trans._coro_frame, len_idx) - if idx_slot is None or len_slot is None: - return + if idx_slot is None or len_slot is None: return # start/end(range 1/2 参数) cl: ast.Call* = ast.Call*(fn.iter) start_val: mlirlite.Value* = None @@ -2003,10 +1759,8 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): else: start_val = self.Gen.ExprGen.translate_value(builder, pool, mod, cl.args.get(0), None, 0, trans) end_val = self.Gen.ExprGen.translate_value(builder, pool, mod, cl.args.get(1), None, 0, trans) - if start_val is None: - start_val = mlirlite.const_int32(pool, 0) - if end_val is None: - end_val = mlirlite.const_int32(pool, 0) + if start_val is None: start_val = mlirlite.const_int32(pool, 0) + if end_val is None: end_val = mlirlite.const_int32(pool, 0) mlirlite.build_store(builder, start_val, idx_slot) mlirlite.build_store(builder, end_val, len_slot) # 循环结构 @@ -2014,8 +1768,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): cond_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.fcond") body_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.fbody") after_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.fend") - if cond_bb is None or body_bb is None or after_bb is None: - return + if cond_bb is None or body_bb is None or after_bb is None: return prev_break: rawptr[mlirlite.BasicBlock] = trans._coro_break_bb prev_cont: rawptr[mlirlite.BasicBlock] = trans._coro_continue_bb trans._coro_break_bb = after_bb @@ -2057,28 +1810,22 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): """coro.coro_destroy(帧):帧回池(free-list,帧首 8 字节存 next)""" i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool) - if cl is None or trans is None or cl.args is None or len(cl.args) < 1: - return mlirlite.const_int32(pool, 0) + if cl is None or trans is None or cl.args is None or len(cl.args) < 1: return mlirlite.const_int32(pool, 0) async_name: str = self._var_to_async(trans, cl.args.get(0)) - if async_name is None: - return mlirlite.const_int32(pool, 0) + if async_name is None: return mlirlite.const_int32(pool, 0) frame_ty: mlirlite.LLVMType* = self._lookup_coro_frame(trans, async_name) - if frame_ty is None: - return mlirlite.const_int32(pool, 0) + if frame_ty is None: return mlirlite.const_int32(pool, 0) frame_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, frame_ty) frame_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cl.args.get(0), None, 0, trans) - if frame_val is None: - return mlirlite.const_int32(pool, 0) + if frame_val is None: return mlirlite.const_int32(pool, 0) frame_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, frame_val, frame_ptr_ty) - if frame_ptr is None: - return mlirlite.const_int32(pool, 0) + if frame_ptr is None: return mlirlite.const_int32(pool, 0) # 回池:帧首 8 字节存旧池头;池头 = 本帧(i64) pool_gv: mlirlite.GlobalVariable* = self._get_coro_pool(pool, mod, trans, async_name) # GlobalVariable 非 Value 子类:构造 Value 视图(Ty=Ptr(i64), Name="@coro_pool_") i64_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i64_ty) pool_ref_name: str = pool.alloc(96) - if pool_ref_name is not None: - viperlib.snprintf(pool_ref_name, 96, "@coro_pool_%s", async_name) + if pool_ref_name is not None: viperlib.snprintf(pool_ref_name, 96, "@coro_pool_%s", async_name) pool_ref: mlirlite.Value* = mlirlite.SSAValue(pool, i64_ptr_ty, pool_ref_name) pool_head: mlirlite.Value* = mlirlite.build_load(builder, i64_ty, pool_ref) node_next: mlirlite.Value* = mlirlite.build_bitcast(builder, frame_ptr, i64_ptr_ty) @@ -2094,21 +1841,16 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): trans: HT.Translator*) -> mlirlite.Value*: """coro.coro_exception(帧):返回帧 exc 槽(异常码,0=无异常)""" i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) - if cl is None or trans is None or cl.args is None or len(cl.args) < 1: - return mlirlite.const_int32(pool, 0) + if cl is None or trans is None or cl.args is None or len(cl.args) < 1: return mlirlite.const_int32(pool, 0) async_name: str = self._var_to_async(trans, cl.args.get(0)) - if async_name is None: - return mlirlite.const_int32(pool, 0) + if async_name is None: return mlirlite.const_int32(pool, 0) frame_ty: mlirlite.LLVMType* = self._lookup_coro_frame(trans, async_name) - if frame_ty is None: - return mlirlite.const_int32(pool, 0) + if frame_ty is None: return mlirlite.const_int32(pool, 0) frame_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, frame_ty) frame_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cl.args.get(0), None, 0, trans) - if frame_val is None: - return mlirlite.const_int32(pool, 0) + if frame_val is None: return mlirlite.const_int32(pool, 0) frame_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, frame_val, frame_ptr_ty) - if frame_ptr is None: - return mlirlite.const_int32(pool, 0) + if frame_ptr is None: return mlirlite.const_int32(pool, 0) exc_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, frame_ty, i32_ty, frame_ptr, 3) return mlirlite.build_load(builder, i32_ty, exc_ptr) @@ -2119,21 +1861,16 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): trans: HT.Translator*) -> mlirlite.Value*: """coro.coro_exception_msg(帧):返回帧 msg 槽(异常消息指针,null=无)""" i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) - if cl is None or trans is None or cl.args is None or len(cl.args) < 1: - return mlirlite.ConstNull(pool, i8_ptr_ty, "null") + if cl is None or trans is None or cl.args is None or len(cl.args) < 1: return mlirlite.ConstNull(pool, i8_ptr_ty, "null") async_name: str = self._var_to_async(trans, cl.args.get(0)) - if async_name is None: - return mlirlite.ConstNull(pool, i8_ptr_ty, "null") + if async_name is None: return mlirlite.ConstNull(pool, i8_ptr_ty, "null") frame_ty: mlirlite.LLVMType* = self._lookup_coro_frame(trans, async_name) - if frame_ty is None: - return mlirlite.ConstNull(pool, i8_ptr_ty, "null") + if frame_ty is None: return mlirlite.ConstNull(pool, i8_ptr_ty, "null") frame_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, frame_ty) frame_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cl.args.get(0), None, 0, trans) - if frame_val is None: - return mlirlite.ConstNull(pool, i8_ptr_ty, "null") + if frame_val is None: return mlirlite.ConstNull(pool, i8_ptr_ty, "null") frame_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, frame_val, frame_ptr_ty) - if frame_ptr is None: - return mlirlite.ConstNull(pool, i8_ptr_ty, "null") + if frame_ptr is None: return mlirlite.ConstNull(pool, i8_ptr_ty, "null") msg_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, frame_ty, i8_ptr_ty, frame_ptr, 4) return mlirlite.build_load(builder, i8_ptr_ty, msg_ptr) @@ -2144,36 +1881,28 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): trans: HT.Translator*) -> mlirlite.Value*: """coro.coro_gather(帧...):并发推进全部协程到完成,返回完成数(M4 纯 resume 循环)""" i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) - if cl is None or trans is None or cl.args is None: - return mlirlite.const_int32(pool, 0) + if cl is None or trans is None or cl.args is None: return mlirlite.const_int32(pool, 0) nb: sizet = len(cl.args) j: sizet = 0 for j in range(nb): arg0: ast.AST* = cl.args.get(j) async_name: str = self._var_to_async(trans, arg0) - if async_name is None: - continue + if async_name is None: continue frame_ty: mlirlite.LLVMType* = self._lookup_coro_frame(trans, async_name) - if frame_ty is None: - continue + if frame_ty is None: continue frame_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, frame_ty) frame_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg0, None, 0, trans) - if frame_val is None: - continue + if frame_val is None: continue frame_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, frame_val, frame_ptr_ty) - if frame_ptr is None: - continue + if frame_ptr is None: continue rn_buf: str = pool.alloc(64) - if rn_buf is not None: - viperlib.snprintf(rn_buf, 64, "resume_%s", async_name) + if rn_buf is not None: viperlib.snprintf(rn_buf, 64, "resume_%s", async_name) resume_mangled: str = self.Gen.FuncGenBase._mangle_func_name(trans, rn_buf, 0) - if self.Gen.CallGenBase.find_func_in_module(mod, resume_mangled) is None: - continue + if self.Gen.CallGenBase.find_func_in_module(mod, resume_mangled) is None: continue func: mlirlite.Function* = trans._cur_func loop_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "gather.loop") after_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "gather.after") - if loop_bb is None or after_bb is None: - continue + if loop_bb is None or after_bb is None: continue mlirlite.build_br(builder, loop_bb) mlirlite.position_at_end(builder, loop_bb) frame_ptr.Next = None @@ -2186,11 +1915,9 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): def _var_to_async(self, trans: HT.Translator*, arg0: ast.AST*) -> str: """变量节点 → async 函数名(_coro_var_async 反查),未命中返回 None""" - if trans is None or arg0 is None or arg0.kind() != ast.ASTKind.Name: - return None + if trans is None or arg0 is None or arg0.kind() != ast.ASTKind.Name: return None nm: ast.Name* = ast.Name*(arg0) - if nm.id is None: - return None + if nm.id is None: return None return self._lookup_coro_var(trans, nm.id) # ============================================================ @@ -2212,23 +1939,18 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): 返回子协程 ret 值(i32)。注意 node 是 Await,须先转 ast.Await 再取 value。""" i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) i8_ptr_ty_a: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) - if node is None or call_name is None or trans is None: - return mlirlite.const_int32(pool, 0) + if node is None or call_name is None or trans is None: return mlirlite.const_int32(pool, 0) # M3:await coro_sleep(ms) —— 挂起到 wake 时刻(帧 wake 槽) - if string.strcmp(call_name, "coro_sleep") == 0: - return self._emit_await_sleep(builder, pool, mod, trans, node) + if string.strcmp(call_name, "coro_sleep") == 0: return self._emit_await_sleep(builder, pool, mod, trans, node) child_frame_ty: mlirlite.LLVMType* = self._lookup_coro_frame(trans, call_name) - if child_frame_ty is None: - return mlirlite.const_int32(pool, 0) + if child_frame_ty is None: return mlirlite.const_int32(pool, 0) child_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, child_frame_ty) cc_buf: str = pool.alloc(64) - if cc_buf is not None: - viperlib.snprintf(cc_buf, 64, "create_%s", call_name) + if cc_buf is not None: viperlib.snprintf(cc_buf, 64, "create_%s", call_name) create_mangled: str = self.Gen.FuncGenBase._mangle_func_name(trans, cc_buf, 0) rc_buf: str = pool.alloc(64) - if rc_buf is not None: - viperlib.snprintf(rc_buf, 64, "resume_%s", call_name) + if rc_buf is not None: viperlib.snprintf(rc_buf, 64, "resume_%s", call_name) resume_mangled: str = self.Gen.FuncGenBase._mangle_func_name(trans, rc_buf, 0) if self.Gen.CallGenBase.find_func_in_module(mod, create_mangled) is None or self.Gen.CallGenBase.find_func_in_module(mod, resume_mangled) is None: # async 函数必须定义在前(前向引用未支持),静默返回 0 @@ -2246,8 +1968,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): j: sizet = 0 for j in range(nb): av: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cl_a.args.get(j), None, 0, trans) - if av is None: - av = mlirlite.const_int32(pool, 0) + if av is None: av = mlirlite.const_int32(pool, 0) av.Next = None if args_head is None: args_head = av @@ -2259,8 +1980,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): # 子协程 create(M2 带参数)+ resume child: mlirlite.Value* = mlirlite.build_call(builder, create_mangled, args_head, args_count, child_ptr_ty, 0) - if child is None: - return mlirlite.const_int32(pool, 0) + if child is None: return mlirlite.const_int32(pool, 0) child.Next = None mlirlite.build_call(builder, resume_mangled, child, 1, i32_ty, 0) # 子帧 ret 槽 GEP [0,2] load @@ -2272,14 +1992,12 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): zero32_x: mlirlite.Value* = mlirlite.const_int32(pool, 0) exc_ok_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, trans._cur_func, "coro.ok") exc_bad_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, trans._cur_func, "coro.exc") - if exc_ok_bb is None or exc_bad_bb is None: - return mlirlite.const_int32(pool, 0) + if exc_ok_bb is None or exc_bad_bb is None: return mlirlite.const_int32(pool, 0) exc_cond: mlirlite.Value* = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, child_exc, zero32_x) mlirlite.build_cond_br(builder, exc_cond, exc_ok_bb, exc_bad_bb) # exc 路径:父帧 exc/msg 槽 + 跳 try 或终止 mlirlite.position_at_end(builder, exc_bad_bb) - if trans._coro_exc_ptr is not None: - mlirlite.build_store(builder, child_exc, trans._coro_exc_ptr) + if trans._coro_exc_ptr is not None: mlirlite.build_store(builder, child_exc, trans._coro_exc_ptr) if trans._coro_msg_ptr is not None: child_msg_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, child_frame_ty, i8_ptr_ty_a, child, 4) child_msg: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty_a, child_msg_ptr) @@ -2294,8 +2012,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): # 正常路径:存父帧 await 槽(若非 None)+ 挂起 mlirlite.position_at_end(builder, exc_ok_bb) slot: mlirlite.Value* = trans._coro_await_slot - if slot is not None: - mlirlite.build_store(builder, child_ret, slot) + if slot is not None: mlirlite.build_store(builder, child_ret, slot) # 父挂起:新状态号(与预扫描 DFS 序一致) new_state: int = trans._coro_next_state trans._coro_next_state = new_state + 1 @@ -2304,8 +2021,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): mlirlite.build_br(builder, trans._coro_exit_bb) # 恢复块 state{new_state}:立即 position(预建 case 块,后续翻译在此继续) resume_bb: rawptr[mlirlite.BasicBlock] = self._get_state_bb(trans, new_state) - if resume_bb is not None: - mlirlite.position_at_end(builder, resume_bb) + if resume_bb is not None: mlirlite.position_at_end(builder, resume_bb) return child_ret # ============================================================ @@ -2323,47 +2039,35 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): M1 无 coro_sleep 轮询(无 wake 槽),纯忙等直到协程完成。 """ i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) - if cl is None or trans is None: - return mlirlite.const_int32(pool, 0) - if cl.args is None or len(cl.args) < 1: - return mlirlite.const_int32(pool, 0) + if cl is None or trans is None: return mlirlite.const_int32(pool, 0) + if cl.args is None or len(cl.args) < 1: return mlirlite.const_int32(pool, 0) arg0: ast.AST* = cl.args.get(0) - if arg0 is None or arg0.kind() != ast.ASTKind.Name: - return mlirlite.const_int32(pool, 0) + if arg0 is None or arg0.kind() != ast.ASTKind.Name: return mlirlite.const_int32(pool, 0) nm: ast.Name* = ast.Name*(arg0) - if nm.id is None: - return mlirlite.const_int32(pool, 0) + if nm.id is None: return mlirlite.const_int32(pool, 0) async_name: str = self._lookup_coro_var(trans, nm.id) - if async_name is None: - return mlirlite.const_int32(pool, 0) + if async_name is None: return mlirlite.const_int32(pool, 0) frame_ty: mlirlite.LLVMType* = self._lookup_coro_frame(trans, async_name) - if frame_ty is None: - return mlirlite.const_int32(pool, 0) + if frame_ty is None: return mlirlite.const_int32(pool, 0) frame_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, frame_ty) # 帧变量值(i8* / Ptr(帧))→ bitcast 到 Ptr(帧) frame_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg0, None, 0, trans) - if frame_val is None: - return mlirlite.const_int32(pool, 0) + if frame_val is None: return mlirlite.const_int32(pool, 0) frame_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, frame_val, frame_ptr_ty) - if frame_ptr is None: - return mlirlite.const_int32(pool, 0) + if frame_ptr is None: return mlirlite.const_int32(pool, 0) func: mlirlite.Function* = trans._cur_func - if func is None: - return mlirlite.const_int32(pool, 0) + if func is None: return mlirlite.const_int32(pool, 0) rn_buf: str = pool.alloc(64) - if rn_buf is not None: - viperlib.snprintf(rn_buf, 64, "resume_%s", async_name) + if rn_buf is not None: viperlib.snprintf(rn_buf, 64, "resume_%s", async_name) resume_mangled: str = self.Gen.FuncGenBase._mangle_func_name(trans, rn_buf, 0) - if self.Gen.CallGenBase.find_func_in_module(mod, resume_mangled) is None: - return mlirlite.const_int32(pool, 0) + if self.Gen.CallGenBase.find_func_in_module(mod, resume_mangled) is None: return mlirlite.const_int32(pool, 0) loop_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.loop") check_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.check") after_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.after") - if loop_bb is None or check_bb is None or after_bb is None: - return mlirlite.const_int32(pool, 0) + if loop_bb is None or check_bb is None or after_bb is None: return mlirlite.const_int32(pool, 0) mlirlite.build_br(builder, loop_bb) mlirlite.position_at_end(builder, loop_bb) frame_ptr.Next = None @@ -2374,8 +2078,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): # M3:SUSPEND → wake 轮询(GetTickCount64 >= wake 或 wake==0 继续,否则 Sleep(1)) mlirlite.position_at_end(builder, check_bb) wake_idx_r: int = self._lookup_coro_wake(trans, async_name) - if wake_idx_r < 0: - mlirlite.build_br(builder, loop_bb) + if wake_idx_r < 0: mlirlite.build_br(builder, loop_bb) else: i64_ty_r2: mlirlite.LLVMType* = mlirlite.Int64(pool) wake_ptr_r: mlirlite.Value* = mlirlite.build_gep_struct(builder, frame_ty, i64_ty_r2, frame_ptr, wake_idx_r) @@ -2406,34 +2109,28 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): def is_async_func(self, trans: HT.Translator*, name: str) -> int: """查询 name 是否已注册为 async 函数(_async_funcs 表),1=是 0=否""" - if trans is None or name is None or trans._async_funcs is None: - return 0 + if trans is None or name is None or trans._async_funcs is None: return 0 cnt: int = trans._async_func_count i: int = 0 for i in range(cnt): addr: uint64 = uint64(trans._async_funcs) + i * 8 slot: str* = (str*)(addr) - if slot[0] is not None and string.strcmp(slot[0], name) == 0: - return 1 + if slot[0] is not None and string.strcmp(slot[0], name) == 0: return 1 return 0 def register_coro_var(self, trans: HT.Translator*, var_name: str, func_name: str) -> int: """记录 变量名→async 函数名 映射(coro.coro_run 反查帧类型用)。 对齐 TPC HandlesAnnAssign.py L319-326。返回 0 成功。""" - if trans is None or var_name is None or func_name is None: - return 1 - if trans._coro_var_async is None: - return 1 + if trans is None or var_name is None or func_name is None: return 1 + if trans._coro_var_async is None: return 1 cnt: int = trans._coro_var_async_count i: int = 0 for i in range(cnt): addr: uint64 = uint64(trans._coro_var_async) + i * 16 pair: str* = (str*)(addr) - if pair[0] is not None and string.strcmp(pair[0], var_name) == 0: - return 0 - if cnt >= HT.MAX_CORO_VARS: - return 1 + if pair[0] is not None and string.strcmp(pair[0], var_name) == 0: return 0 + if cnt >= HT.MAX_CORO_VARS: return 1 pair2_addr: uint64 = uint64(trans._coro_var_async) + cnt * 16 pair2: str* = (str*)(pair2_addr) pair2[0] = var_name @@ -2444,17 +2141,14 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): def _register_async_func(self, trans: HT.Translator*, name: str) -> int: """注册 async 函数裸名到 _async_funcs 表""" - if trans is None or name is None or trans._async_funcs is None: - return 1 + if trans is None or name is None or trans._async_funcs is None: return 1 cnt: int = trans._async_func_count i: int = 0 for i in range(cnt): addr: uint64 = uint64(trans._async_funcs) + i * 8 slot: str* = (str*)(addr) - if slot[0] is not None and string.strcmp(slot[0], name) == 0: - return 0 - if cnt >= HT.MAX_CORO_FUNCS: - return 1 + if slot[0] is not None and string.strcmp(slot[0], name) == 0: return 0 + if cnt >= HT.MAX_CORO_FUNCS: return 1 addr2: uint64 = uint64(trans._async_funcs) + cnt * 8 slot2: str* = (str*)(addr2) slot2[0] = name @@ -2465,10 +2159,8 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): name: str, frame_ty: mlirlite.LLVMType*) -> int: """注册 async 名→帧类型 到 _coro_frames 表(16 字节/项 = char* + LLVMType*)""" - if trans is None or name is None or frame_ty is None: - return 1 - if trans._coro_frames is None: - return 1 + if trans is None or name is None or frame_ty is None: return 1 + if trans._coro_frames is None: return 1 cnt: int = trans._coro_frame_count i: int = 0 for i in range(cnt): @@ -2477,8 +2169,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if pair[0] is not None and string.strcmp(pair[0], name) == 0: pair[1] = str(frame_ty) return 0 - if cnt >= HT.MAX_CORO_FUNCS: - return 1 + if cnt >= HT.MAX_CORO_FUNCS: return 1 pair2_addr: uint64 = uint64(trans._coro_frames) + cnt * 16 pair2: str* = (str*)(pair2_addr) pair2[0] = name @@ -2489,8 +2180,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): def _lookup_coro_frame(self, trans: HT.Translator*, name: str) -> mlirlite.LLVMType*: """按 async 名查帧类型,未命中返回 None""" - if trans is None or name is None or trans._coro_frames is None: - return None + if trans is None or name is None or trans._coro_frames is None: return None cnt: int = trans._coro_frame_count i: int = 0 for i in range(cnt): @@ -2506,15 +2196,13 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): def _lookup_coro_var(self, trans: HT.Translator*, var_name: str) -> str: """按变量名反查 async 函数名(_coro_var_async 表),未命中返回 None""" - if trans is None or var_name is None or trans._coro_var_async is None: - return None + if trans is None or var_name is None or trans._coro_var_async is None: return None cnt: int = trans._coro_var_async_count i: int = 0 for i in range(cnt): addr: uint64 = uint64(trans._coro_var_async) + i * 16 pair: str* = (str*)(addr) - if pair[0] is not None and string.strcmp(pair[0], var_name) == 0: - return pair[1] + if pair[0] is not None and string.strcmp(pair[0], var_name) == 0: return pair[1] return None # ============================================================ @@ -2534,10 +2222,8 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): rv_node: rawptr[ast.Return] = rawptr[ast.Return](stmt) ret_val: mlirlite.Value* = None if rv_node is not None and rv_node.value is not None: - if rv_node.value.kind() != ast.ASTKind.Await: - ret_val = self.Gen.ExprGen.translate_value(builder, pool, mod, rv_node.value, None, 0, trans) - if ret_val is None: - ret_val = mlirlite.const_int32(pool, 0) + if rv_node.value.kind() != ast.ASTKind.Await: ret_val = self.Gen.ExprGen.translate_value(builder, pool, mod, rv_node.value, None, 0, trans) + if ret_val is None: ret_val = mlirlite.const_int32(pool, 0) mlirlite.build_store(builder, ret_val, trans._coro_ret_ptr) done_one: mlirlite.Value* = mlirlite.const_int32(pool, 1) mlirlite.build_store(builder, done_one, trans._coro_done_ptr) @@ -2545,47 +2231,37 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): def _expr_await_is_sleep(self, aw: rawptr[ast.Await]) -> int: """Await 目标是否为 coro_sleep(Name 或 coro.coro_sleep)""" - if aw is None or aw.value is None: - return 0 - if aw.value.kind() != ast.ASTKind.Call: - return 0 + if aw is None or aw.value is None: return 0 + if aw.value.kind() != ast.ASTKind.Call: return 0 cl: ast.Call* = ast.Call*(aw.value) - if cl.func is None: - return 0 + if cl.func is None: return 0 if cl.func.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(cl.func) - if nm.id is not None and string.strcmp(nm.id, "coro_sleep") == 0: - return 1 + if nm.id is not None and string.strcmp(nm.id, "coro_sleep") == 0: return 1 elif cl.func.kind() == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(cl.func) - if at.attr is not None and string.strcmp(at.attr, "coro_sleep") == 0: - return 1 + if at.attr is not None and string.strcmp(at.attr, "coro_sleep") == 0: return 1 return 0 def _is_await_tail(self, stmt: ast.AST*) -> int: """判断语句是否为段尾:AnnAssign/Assign/Expr 且 value 直接是 Await""" - if stmt is None: - return 0 + if stmt is None: return 0 sk: int = stmt.kind() if sk == ast.ASTKind.AnnAssign: aa: ast.AnnAssign* = ast.AnnAssign*(stmt) - if aa.value is not None and aa.value.kind() == ast.ASTKind.Await: - return 1 + if aa.value is not None and aa.value.kind() == ast.ASTKind.Await: return 1 elif sk == ast.ASTKind.Assign: as_: ast.Assign* = ast.Assign*(stmt) if as_.value is not None and as_.value.kind() == ast.ASTKind.Await: - if as_.targets is not None and len(as_.targets) == 1: - return 1 + if as_.targets is not None and len(as_.targets) == 1: return 1 elif sk == ast.ASTKind.Expr: e: rawptr[ast.Expr] = rawptr[ast.Expr](stmt) - if e.value is not None and e.value.kind() == ast.ASTKind.Await: - return 1 + if e.value is not None and e.value.kind() == ast.ASTKind.Await: return 1 return 0 def _get_assign_target_name(self, stmt: ast.AST*) -> str: """取 AnnAssign(target=Name)/Assign(单 target=Name) 的目标名,未命中返回 None""" - if stmt is None: - return None + if stmt is None: return None sk: int = stmt.kind() if sk == ast.ASTKind.AnnAssign: aa: ast.AnnAssign* = ast.AnnAssign*(stmt) @@ -2603,27 +2279,22 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): def _get_await_value(self, stmt: ast.AST*) -> rawptr[ast.Await]: """取段尾语句的 Await value 节点,未命中返回 None""" - if stmt is None: - return None + if stmt is None: return None sk: int = stmt.kind() if sk == ast.ASTKind.AnnAssign: aa: ast.AnnAssign* = ast.AnnAssign*(stmt) - if aa.value is not None and aa.value.kind() == ast.ASTKind.Await: - return rawptr[ast.Await](aa.value) + if aa.value is not None and aa.value.kind() == ast.ASTKind.Await: return rawptr[ast.Await](aa.value) elif sk == ast.ASTKind.Assign: as_: ast.Assign* = ast.Assign*(stmt) - if as_.value is not None and as_.value.kind() == ast.ASTKind.Await: - return rawptr[ast.Await](as_.value) + if as_.value is not None and as_.value.kind() == ast.ASTKind.Await: return rawptr[ast.Await](as_.value) elif sk == ast.ASTKind.Expr: ex: rawptr[ast.Expr] = rawptr[ast.Expr](stmt) - if ex.value is not None and ex.value.kind() == ast.ASTKind.Await: - return rawptr[ast.Await](ex.value) + if ex.value is not None and ex.value.kind() == ast.ASTKind.Await: return rawptr[ast.Await](ex.value) return None def _extract_await_call_name(self, aw_node: rawptr[ast.Await]) -> str: """从 Await(value=Call(func)) 提取 async 函数名或 coro_sleep,未命中返回 None""" - if aw_node is None or aw_node.value is None: - return None + if aw_node is None or aw_node.value is None: return None if aw_node.value.kind() == ast.ASTKind.Call: cl: ast.Call* = ast.Call*(aw_node.value) if cl.func is not None: @@ -2633,15 +2304,13 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if cl.func.kind() == ast.ASTKind.Attribute: # coro.coro_sleep(ms):M3 sleep 挂起 at: ast.Attribute* = ast.Attribute*(cl.func) - if at.attr is not None and string.strcmp(at.attr, "coro_sleep") == 0: - return "coro_sleep" + if at.attr is not None and string.strcmp(at.attr, "coro_sleep") == 0: return "coro_sleep" return None def _read_local_name(self, trans: HT.Translator*, idx: int) -> str: """读 trans._coro_locals 第 idx 个局部变量名,越界返回 None""" - if trans is None or trans._coro_locals is None: - return None + if trans is None or trans._coro_locals is None: return None addr: uint64 = uint64(trans._coro_locals) + idx * 8 slot: str* = (str*)(addr) return slot[0] diff --git a/App/lib/core/Gen/BaseGenMixin.vp b/App/lib/core/Gen/BaseGenMixin.vp index 8563768..c0bb429 100644 --- a/App/lib/core/Gen/BaseGenMixin.vp +++ b/App/lib/core/Gen/BaseGenMixin.vp @@ -32,8 +32,7 @@ novirtual class BaseGenMixin: def InitBaseGen(self, pool: memhub.MemBuddy*) -> int: """初始化生成器状态(默认值;子类构造时调用)""" - if self is None: - return 1 + if self is None: return 1 self.Pool = pool self.Module = None self.Builder = None diff --git a/App/lib/core/Gen/Call/CallGenBase.vp b/App/lib/core/Gen/Call/CallGenBase.vp index e8eb340..185500b 100644 --- a/App/lib/core/Gen/Call/CallGenBase.vp +++ b/App/lib/core/Gen/Call/CallGenBase.vp @@ -143,10 +143,8 @@ novirtual class CallGenBase: pkg_buf: str = pool.alloc(pkg_len + 1) if pkg_buf is None: return None for pi in range(pkg_len): - if rel[pi] == '/': - pkg_buf[pi] = '.' - else: - pkg_buf[pi] = rel[pi] + if rel[pi] == '/': pkg_buf[pi] = '.' + else: pkg_buf[pi] = rel[pi] pkg_buf[pkg_len] = '\0' return pkg_buf return None @@ -184,8 +182,7 @@ novirtual class CallGenBase: if nrd <= 0: stdlib.free(buf) return None - if nrd < READ_SZ: - buf[nrd] = 0 + if nrd < READ_SZ: buf[nrd] = 0 name_len: sizet = string.strlen(func_name) # 模块自含定义标志:vpi 中行首 "def {func_name}(" 命中且未被同名 # from-import 覆盖 → 该模块自身定义 func_name,不是 re-export 源。 @@ -194,17 +191,14 @@ novirtual class CallGenBase: pos: sizet = 0 while pos < total: ls: sizet = pos - while pos < total and buf[pos] != '\n': - pos += 1 + while pos < total and buf[pos] != '\n': pos += 1 ll: sizet = pos - ls - if pos < total: - pos += 1 + if pos < total: pos += 1 # 自含定义检测(须在 from-import 行匹配之前,对所有行生效):模块级 def 行首无缩进,类内方法 def 有缩进不会误命中 if ll > 4 and buf[ls] == 'd' and buf[ls + 1] == 'e' and buf[ls + 2] == 'f' and buf[ls + 3] == ' ': fstart_od: sizet = ls + 4 fend_od: sizet = fstart_od - while fend_od < ls + ll and buf[fend_od] != '(' and buf[fend_od] != ' ': - fend_od += 1 + while fend_od < ls + ll and buf[fend_od] != '(' and buf[fend_od] != ' ': fend_od += 1 fl2_od: sizet = fend_od - fstart_od if fl2_od == name_len: fd_eq_od: int = 1 @@ -214,22 +208,18 @@ novirtual class CallGenBase: fd_eq_od = 0 break fdi_od += 1 - if fd_eq_od != 0: - has_own_def = 1 + if fd_eq_od != 0: has_own_def = 1 continue # 行必须以 "from " 开头 - if ll < 6: - continue - if buf[ls] != 'f' or buf[ls + 1] != 'r' or buf[ls + 2] != 'o' or buf[ls + 3] != 'm' or buf[ls + 4] != ' ': - continue + if ll < 6: continue + if buf[ls] != 'f' or buf[ls + 1] != 'r' or buf[ls + 2] != 'o' or buf[ls + 3] != 'm' or buf[ls + 4] != ' ': continue # 找 " import " 分隔符 imp_pos: sizet = ls + 5 while imp_pos + 7 <= ls + ll: if buf[imp_pos] == ' ' and buf[imp_pos + 1] == 'i' and buf[imp_pos + 2] == 'm' and buf[imp_pos + 3] == 'p' and buf[imp_pos + 4] == 'o' and buf[imp_pos + 5] == 'r' and buf[imp_pos + 6] == 't' and buf[imp_pos + 7] == ' ': break imp_pos += 1 - if imp_pos + 7 > ls + ll: - continue + if imp_pos + 7 > ls + ll: continue mod_start: sizet = ls + 5 mod_end: sizet = imp_pos # 名称列表从 "import " 之后(逗号分隔,含 "A as B" 取原名 A) @@ -237,8 +227,7 @@ novirtual class CallGenBase: # star import 支持(from X import *):首个 star 行未必是定义模块,累积全部候选,扫描完由调用方按 vpi 返回注解逐个验证 if nm_start < ls + ll and buf[nm_start] == '*': star_dot: int = 0 - if buf[mod_start] == '.': - star_dot = 1 + if buf[mod_start] == '.': star_dot = 1 star_buf: str = pool.alloc(mod_end - mod_start + 1) if star_buf is not None: si2: sizet = 0 @@ -246,8 +235,7 @@ novirtual class CallGenBase: star_buf[si2] = buf[mod_start + si2] si2 += 1 star_buf[si2] = '\0' - while star_buf[0] == '.': - star_buf = star_buf + 1 + while star_buf[0] == '.': star_buf = star_buf + 1 if string.strlen(star_buf) > 0: if star_dot != 0: spkg: str = self._module_package_from_sha1(pool, mod_sha1) @@ -273,13 +261,10 @@ novirtual class CallGenBase: continue scan: sizet = nm_start while scan < ls + ll: - while scan < ls + ll and (buf[scan] == ' ' or buf[scan] == ','): - scan += 1 - if scan >= ls + ll: - break + while scan < ls + ll and (buf[scan] == ' ' or buf[scan] == ','): scan += 1 + if scan >= ls + ll: break n_end: sizet = scan - while n_end < ls + ll and buf[n_end] != ',' and buf[n_end] != ' ': - n_end += 1 + while n_end < ls + ll and buf[n_end] != ',' and buf[n_end] != ' ': n_end += 1 cand_start: sizet = scan cand_len: sizet = n_end - scan as_pos: sizet = scan @@ -298,8 +283,7 @@ novirtual class CallGenBase: if m_ok == 1: # 命中:解析模块名(前导点 → 相对导入,补包前缀) has_dot: int = 0 - if buf[mod_start] == '.': - has_dot = 1 + if buf[mod_start] == '.': has_dot = 1 mod_buf: str = pool.alloc(mod_end - mod_start + 1) if mod_buf is None: stdlib.free(buf) @@ -309,8 +293,7 @@ novirtual class CallGenBase: mod_buf[mi] = buf[mod_start + mi] mi += 1 mod_buf[mi] = '\0' - while mod_buf[0] == '.': - mod_buf = mod_buf + 1 + while mod_buf[0] == '.': mod_buf = mod_buf + 1 if string.strlen(mod_buf) == 0: stdlib.free(buf) return None @@ -333,8 +316,7 @@ novirtual class CallGenBase: # 全部行扫描完毕:仅有 star import 时返回累积候选(调用方逐个验证定义模块);模块自含 def {func_name} 时本模块即定义者,返回 None 保持归属 if star_cands is not None: stdlib.free(buf) - if has_own_def == 0: - return star_cands + if has_own_def == 0: return star_cands return None stdlib.free(buf) return None @@ -342,13 +324,11 @@ novirtual class CallGenBase: def register_cexport_func(self, sha1: str, func_name: str) -> int: """注册 CExport 函数到全局表(统一写入 Gen.CallGenBase 真源,跨子对象共享)""" - if self.Gen is None or sha1 is None or func_name is None: - return 0 + if self.Gen is None or sha1 is None or func_name is None: return 0 if self.Gen.CallGenBase.CexportSha1Arr is None: self.Gen.CallGenBase.CexportSha1Arr = CompilerFactory.factory.PermPool.alloc(_CEXPORT_MAX * 17) self.Gen.CallGenBase.CexportFuncArr = CompilerFactory.factory.PermPool.alloc(_CEXPORT_MAX * 64) - if self.Gen.CallGenBase.CexportSha1Arr is None or self.Gen.CallGenBase.CexportFuncArr is None: - return 0 + if self.Gen.CallGenBase.CexportSha1Arr is None or self.Gen.CallGenBase.CexportFuncArr is None: return 0 string.memset(self.Gen.CallGenBase.CexportSha1Arr, 0, _CEXPORT_MAX * 17) string.memset(self.Gen.CallGenBase.CexportFuncArr, 0, _CEXPORT_MAX * 64) if self.Gen.CallGenBase.CexportCount < _CEXPORT_MAX: @@ -378,8 +358,7 @@ novirtual class CallGenBase: idx: sizet = sizet(i) * 17 if string.strcmp(self.Gen.CallGenBase.CexportSha1Arr + idx, sha1) == 0: idx2: sizet = sizet(i) * 64 - if string.strcmp(self.Gen.CallGenBase.CexportFuncArr + idx2, func_name) == 0: - return 1 + if string.strcmp(self.Gen.CallGenBase.CexportFuncArr + idx2, func_name) == 0: return 1 return self._is_cexport_func_from_vpi(sha1, func_name) @@ -394,13 +373,11 @@ novirtual class CallGenBase: # ============================================================ def RegisterStaticSymbol(self, sha1: str, name: str) -> int: """登记 static 符号(定义模块 SHA1 + 符号名);1=已登记(含幂等重复)/ 0=失败""" - if self.Gen is None or sha1 is None or name is None: - return 0 + if self.Gen is None or sha1 is None or name is None: return 0 if self.Gen.CallGenBase.StaticSha1Arr is None: self.Gen.CallGenBase.StaticSha1Arr = CompilerFactory.factory.PermPool.alloc(_CEXPORT_MAX * 17) self.Gen.CallGenBase.StaticNameArr = CompilerFactory.factory.PermPool.alloc(_CEXPORT_MAX * 64) - if self.Gen.CallGenBase.StaticSha1Arr is None or self.Gen.CallGenBase.StaticNameArr is None: - return 0 + if self.Gen.CallGenBase.StaticSha1Arr is None or self.Gen.CallGenBase.StaticNameArr is None: return 0 string.memset(self.Gen.CallGenBase.StaticSha1Arr, 0, _CEXPORT_MAX * 17) string.memset(self.Gen.CallGenBase.StaticNameArr, 0, _CEXPORT_MAX * 64) # 幂等:同 (sha1, name) 重复登记(跨遍重译 / 同文件多次进入)直接命中返回 @@ -408,8 +385,7 @@ novirtual class CallGenBase: si: sizet = sizet(i) * 17 if string.strcmp(self.Gen.CallGenBase.StaticSha1Arr + si, sha1) == 0: sn: sizet = sizet(i) * 64 - if string.strcmp(self.Gen.CallGenBase.StaticNameArr + sn, name) == 0: - return 1 + if string.strcmp(self.Gen.CallGenBase.StaticNameArr + sn, name) == 0: return 1 if self.Gen.CallGenBase.StaticCount < _CEXPORT_MAX: idx: sizet = sizet(self.Gen.CallGenBase.StaticCount) * 17 # 槽位定长 17/64 字节,strcpy 无界会越界写相邻槽(stdlib 堆区) @@ -430,16 +406,13 @@ novirtual class CallGenBase: static 是"禁止跨模块"(跨模块**必须报错**);两者判据方向相反, 但同用 (sha1, 符号名) 精确配对,避免同名符号跨模块误判。 """ - if self.Gen is None or sha1 is None or name is None: - return 0 - if self.Gen.CallGenBase.StaticSha1Arr is None: - return 0 + if self.Gen is None or sha1 is None or name is None: return 0 + if self.Gen.CallGenBase.StaticSha1Arr is None: return 0 for i in range(self.Gen.CallGenBase.StaticCount): si: sizet = sizet(i) * 17 if string.strcmp(self.Gen.CallGenBase.StaticSha1Arr + si, sha1) == 0: sn: sizet = sizet(i) * 64 - if string.strcmp(self.Gen.CallGenBase.StaticNameArr + sn, name) == 0: - return 1 + if string.strcmp(self.Gen.CallGenBase.StaticNameArr + sn, name) == 0: return 1 return 0 @@ -448,16 +421,12 @@ novirtual class CallGenBase: 对齐 _is_state_func_from_vpi(State 标记)的 vpi 按需解析路径。 """ - if sha1 is None or func_name is None: - return 0 - if self.Gen is None or self.Gen.CallGenBase.TempDir is None or self.Gen.CallGenBase.TempDirLen <= 0: - return 0 + if sha1 is None or func_name is None: return 0 + if self.Gen is None or self.Gen.CallGenBase.TempDir is None or self.Gen.CallGenBase.TempDirLen <= 0: return 0 VpiReader._ensure_vpi_ret_annot_loaded(sha1, self.Gen.CallGenBase.TempDir) cexp_annot: str = VpiReader._lookup_vpi_ret_annot(sha1, None, func_name) - if cexp_annot is None: - return 0 - if string.strstr(cexp_annot, "CExport") is not None: - return 1 + if cexp_annot is None: return 0 + if string.strstr(cexp_annot, "CExport") is not None: return 1 return 0 @@ -470,10 +439,8 @@ novirtual class CallGenBase: → ld.lld undefined symbol(CPythonTest PyList_Size 根因)。CExport 走 is_cexport_func 注册表,State 函数未注册 → 按需解析 vpi 返回注解判断。 """ - if pool is None or sha1 is None or func_name is None: - return 0 - if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: - VpiReader._ensure_vpi_ret_annot_loaded(sha1, self.Gen.CallGenBase.TempDir) + if pool is None or sha1 is None or func_name is None: return 0 + if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: VpiReader._ensure_vpi_ret_annot_loaded(sha1, self.Gen.CallGenBase.TempDir) state_annot: str = VpiReader._lookup_vpi_ret_annot(sha1, None, func_name) if state_annot is None: return 0 # 返回注解含 "State"(如 "sizet | t.State")→ 外部 C 函数 @@ -498,21 +465,16 @@ novirtual class CallGenBase: """从原始模块名查找 SHA1,返回 None=未找到""" # 手动找到模块名结束位置(空格、null、或 ':' 别名分隔符),复制到新缓冲区 mod_len: sizet = 0 - while mod_name_raw[mod_len] != ' ' and mod_name_raw[mod_len] != '\0' and mod_name_raw[mod_len] != ':': - mod_len += 1 + while mod_name_raw[mod_len] != ' ' and mod_name_raw[mod_len] != '\0' and mod_name_raw[mod_len] != ':': mod_len += 1 mod_name_buf: str = pool.alloc(mod_len + 1) - if mod_name_buf is None: - return None - for mi in range(mod_len): - mod_name_buf[mi] = mod_name_raw[mi] + if mod_name_buf is None: return None + for mi in range(mod_len): mod_name_buf[mi] = mod_name_raw[mi] mod_name_buf[mod_len] = '\0' # 去掉相对导入的前导点 base_mod: str = mod_name_buf - while base_mod[0] == '.': - base_mod = base_mod + 1 + while base_mod[0] == '.': base_mod = base_mod + 1 sha1: str = self._lookup_module_sha1(base_mod) - if sha1 is None: - sha1 = self._lookup_module_sha1_suffix(base_mod) + if sha1 is None: sha1 = self._lookup_module_sha1_suffix(base_mod) return sha1 @@ -534,15 +496,11 @@ novirtual class CallGenBase: p_cur: mlirlite.Param* = mlirlite.function_get_param_head(f_ref) while p_cur is not None: p_ty: mlirlite.LLVMType* = mlirlite.param_get_ty(p_cur) - if p_ty is None: - return None + if p_ty is None: return None pn: mlirlite.ParamNode* = mlirlite.new_param_node(pool, p_ty) - if pn is None: - return None - if pn_head is None: - pn_head = pn - if pn_prev is not None: - mlirlite.paramnode_set_next(pn_prev, pn) + if pn is None: return None + if pn_head is None: pn_head = pn + if pn_prev is not None: mlirlite.paramnode_set_next(pn_prev, pn) pn_prev = pn p_cnt += 1 p_cur = mlirlite.param_get_next(p_cur) @@ -567,8 +525,7 @@ novirtual class CallGenBase: 使用 mlirlite.function_get_name/next 访问器绕过 stub 类型限制 (stub 类型字段不足且字段类型可能错误,直接字段访问会被静默跳过)。 """ - if mod is None or name is None: - return None + if mod is None or name is None: return None name_len: sizet = string.strlen(name) # 热点优化:原「趟 1 精确匹配+本模块同名、趟 2 declare/任意后缀」两趟完整链表扫描 # 合并为一趟——同一节点只取一次 function_get_name/NameLen/next(原两趟各取一次, @@ -583,8 +540,7 @@ novirtual class CallGenBase: cur_name: str = mlirlite.function_get_name(cur) if cur_name is not None: # 快速路径:strcmp 判等蕴含首字符相等,首字符不同者跳过 strcmp(mangled 名以 sha1 十六进制打头,裸名多为字母/下划线) - if cur_name[0] == name[0] and string.strcmp(cur_name, name) == 0: - return cur + if cur_name[0] == name[0] and string.strcmp(cur_name, name) == 0: return cur # 名字长度取 Function.NameLen(创建时一次算好),免去对热链每个节点重复 strlen cur_len: sizet = mlirlite.function_get_name_len(cur) # 本模块同名候选:仅接受恰为 "{owner_sha1}.{name}" 的形态(不匹配 "{sha1}.Class.method");declare 与 define 同名同符号,是否 IsDeclared==0 均可返回 @@ -597,8 +553,7 @@ novirtual class CallGenBase: if cur_name[suffix_start_o + i] != name[i]: match_o = 0 break - if match_o == 1: - mangle_hit = cur + if match_o == 1: mangle_hit = cur # 后缀匹配(.name):不跳过 declare(方法 stub 也是 declare,由调用处判断 IsDeclared 决定用裸名或 sha1 前缀名) if cur_len > name_len + 1: suffix_start: sizet = cur_len - name_len @@ -610,16 +565,12 @@ novirtual class CallGenBase: break if Matched == 1: # 首个任意后缀命中(原第三遍兜底) - if any_hit is None: - any_hit = cur + if any_hit is None: any_hit = cur # 首个 IsDeclared==0 命中(原第二遍优先) - if cur.IsDeclared == 0 and declare_hit is None: - declare_hit = cur + if cur.IsDeclared == 0 and declare_hit is None: declare_hit = cur cur = mlirlite.function_get_next(cur) - if mangle_hit is not None: - return mangle_hit - if declare_hit is not None: - return declare_hit + if mangle_hit is not None: return mangle_hit + if declare_hit is not None: return declare_hit return any_hit @@ -637,8 +588,7 @@ novirtual class CallGenBase: 参数,避免 llc 报 `argument invalid for parameter type` 之类的错误。 已存在的 define 不修改(其参数由定义决定)。 """ - if pool is None or mod is None or call_name is None: - return + if pool is None or mod is None or call_name is None: return # 链遍历哨兵(fail-fast):FuncHead/Params 的 Next 被越界写破坏成环时 # 无上限遍历会死循环(builtins.vp dump 卡死根因排查),超限即报错终止。 DECLARE_CHAIN_LIMIT: int = 100000 @@ -659,8 +609,7 @@ novirtual class CallGenBase: # 变长函数(*args,IsVarArg=1)不追加参数:多余实参由 # 变参机制(...)承接,追加有类型参数会导致调用侧把变参 # 强转为追加的类型(如 i8 → i64),%d/%x 等格式读错。 - if existing.IsVarArg == 1: - return + if existing.IsVarArg == 1: return # 遍历现有参数链表计数(避免依赖 GSList.Count 字段的类型推断) cur_count: int = 0 cur_p: mlirlite.Param* = mlirlite.function_get_param_head(existing) @@ -684,8 +633,7 @@ novirtual class CallGenBase: while pnode2 is not None and pi2 < param_count: if pnode2.Ty is not None: param2: mlirlite.Param* = mlirlite.new_param(pool, pnode2.Ty, None) - if param2 is not None: - mlirlite.function_add_param(existing, param2) + if param2 is not None: mlirlite.function_add_param(existing, param2) pnode2 = pnode2.Next pi2 += 1 return @@ -729,11 +677,9 @@ novirtual class CallGenBase: cls_buf_d[cls_len_d] = '\0' cls_d = cls_buf_d meth_d = dot2_d + 1 - else: - meth_d = rest_d + else: meth_d = rest_d prm_annots_d: str = None - if sha1_d is not None and meth_d is not None: - prm_annots_d = self._vpi_method_param_annot(pool, sha1_d, cls_d, meth_d) + if sha1_d is not None and meth_d is not None: prm_annots_d = self._vpi_method_param_annot(pool, sha1_d, cls_d, meth_d) i32_ty_d: mlirlite.LLVMType* = mlirlite.Int32(pool) i8_ptr_d: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) # 添加参数(declare 中参数名无意义,设为 None 只输出类型) @@ -748,8 +694,7 @@ novirtual class CallGenBase: case mlirlite.LLVMType.Int(bits_a): match seg_ty_d: case mlirlite.LLVMType.Int(bits_b): - if bits_b > bits_a: - param_ty_d = seg_ty_d + if bits_b > bits_a: param_ty_d = seg_ty_d case _: pass case mlirlite.LLVMType.Ptr(_): @@ -763,14 +708,11 @@ novirtual class CallGenBase: pass if param_ty_d is not None: param: mlirlite.Param* = mlirlite.new_param(pool, param_ty_d, None) - if param is not None: - mlirlite.function_add_param(func, param) + if param is not None: mlirlite.function_add_param(func, param) pnode = pnode.Next pi += 1 - if sha1_d is not None: - stdlib.free(sha1_d) - if cls_d is not None: - stdlib.free(cls_d) + if sha1_d is not None: stdlib.free(sha1_d) + if cls_d is not None: stdlib.free(cls_d) mlirlite.module_add_function(mod, func) # _lookup_method_ret_ty_via_vpi:按 模块SHA1 + 类名 + 方法名 查 vpi 返回注解缓存并解析为 LLVMType,未命中返回 None(不硬编码白名单,类型始终来自定义处) @@ -781,18 +723,15 @@ novirtual class CallGenBase: cls_name: str, method_name: str) -> mlirlite.LLVMType*: """从 vpi stub 返回注解缓存获取方法返回类型,未命中返回 None""" - if pool is None or cls_sha1 is None or method_name is None: - return None + if pool is None or cls_sha1 is None or method_name is None: return None # 函数内懒 import:VpiReader imports HandlesExprCall,顶层 import 会成环 i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) # 按需加载:缓存未命中时直接读 {temp_dir}/{sha1[0:2]}/{sha1}.vpi # 覆盖"模块自身翻译时 stub 尚未注入"(同模块方法调用,定义在后)的场景 - if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: - VpiReader._ensure_vpi_ret_annot_loaded(cls_sha1, self.Gen.CallGenBase.TempDir) + if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: VpiReader._ensure_vpi_ret_annot_loaded(cls_sha1, self.Gen.CallGenBase.TempDir) annot: str = VpiReader._lookup_vpi_ret_annot(cls_sha1, cls_name, method_name) - if annot is None: - return None + if annot is None: return None return VpiReader._resolve_vpi_ret_annot_str(pool, annot, i32_ty, i8_ptr_ty) # _vpi_method_param_annot:按需加载并查询 vpi 参数注解串('@' 分隔,含首参 self 空串占位),供调用方补全 declare/call 缺失参数;未命中返回 None @@ -801,19 +740,16 @@ novirtual class CallGenBase: cls_name: str, method_name: str) -> str: """按需加载并查询 vpi 参数注解串,未命中返回 None""" - if pool is None or cls_sha1 is None or cls_name is None or method_name is None: - return None + if pool is None or cls_sha1 is None or cls_name is None or method_name is None: return None # 按需加载:缓存未命中时直接读 {temp_dir}/{sha1[0:2]}/{sha1}.vpi - if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: - VpiReader._ensure_vpi_param_annot_loaded(cls_sha1, self.Gen.CallGenBase.TempDir) + if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: VpiReader._ensure_vpi_param_annot_loaded(cls_sha1, self.Gen.CallGenBase.TempDir) return VpiReader._lookup_vpi_param_annots(cls_sha1, cls_name, method_name) # _vpi_resolve_param_annot_ty:解析 vpi 参数注解段为 LLVMType,失败返回 None(调用方以 i8* 兜底) def _vpi_resolve_param_annot_ty(self, pool: memhub.MemBuddy*, seg: str) -> mlirlite.LLVMType*: """解析单个 vpi 参数注解段为 LLVMType,失败返回 None""" - if pool is None or seg is None: - return None + if pool is None or seg is None: return None i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) return VpiReader._resolve_vpi_ret_annot_str(pool, seg, i32_ty, i8_ptr_ty) @@ -825,15 +761,12 @@ novirtual class CallGenBase: class_name: str, method_name: str) -> mlirlite.LLVMType*: """编译器内置特殊方法的固定返回类型;非特殊返回 None""" - if pool is None or method_name is None: - return None - if string.strcmp(method_name, "__before_init__") == 0 or string.strcmp(method_name, "__init__") == 0: - return mlirlite.Void(pool) + if pool is None or method_name is None: return None + if string.strcmp(method_name, "__before_init__") == 0 or string.strcmp(method_name, "__init__") == 0: return mlirlite.Void(pool) if string.strcmp(method_name, "__new__") == 0: if class_name is not None: sp_struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(class_name) - if sp_struct_ty is not None: - return mlirlite.Ptr(pool, sp_struct_ty) + if sp_struct_ty is not None: return mlirlite.Ptr(pool, sp_struct_ty) return None return None @@ -858,10 +791,8 @@ novirtual class CallGenBase: """设置 temp 目录路径(统一写入 Gen.CallGenBase 真源,跨子对象共享)""" if self.Gen is None: return self.Gen.CallGenBase.TempDir = temp_dir - if temp_dir is not None: - self.Gen.CallGenBase.TempDirLen = string.strlen(temp_dir) - else: - self.Gen.CallGenBase.TempDirLen = 0 + if temp_dir is not None: self.Gen.CallGenBase.TempDirLen = string.strlen(temp_dir) + else: self.Gen.CallGenBase.TempDirLen = 0 # _ParseLLVMRetTyStr:把 LLVM IR 返回类型字符串(define 与 @ 之间)转为 LLVMType——void / iN / double / float,含 * 者返回通用 Ptr(Int8);无法解析返回 None @@ -871,28 +802,24 @@ novirtual class CallGenBase: start: sizet, end: sizet) -> mlirlite.LLVMType*: """将 LLVM IR 返回类型字符串转换为 mlirlite.LLVMType""" - if pool is None or buf is None or start >= end: - return None + if pool is None or buf is None or start >= end: return None # 去除前导空白 s: sizet = start while s < end: c: int = buf[s] - if c != ' ' and c != '\t': - break + if c != ' ' and c != '\t': break s += 1 # 去除尾部空白 e: sizet = end while e > s: c2: int = buf[e - 1] - if c2 != ' ' and c2 != '\t': - break + if c2 != ' ' and c2 != '\t': break e -= 1 ty_len: sizet = e - s - if ty_len == 0: - return None + if ty_len == 0: return None # struct 字面量 {T1, T2, ...}(tuple 打包返回类型)必须在 * 检查之前,否则内含 * 会被误判为 i8*(破坏 tuple 解包) if s < e and buf[s] == '{': @@ -905,32 +832,25 @@ novirtual class CallGenBase: tc_st: int = 0 ps_st: sizet = s + 1 while ps_st < e and buf[ps_st] != '}': - while ps_st < e and (buf[ps_st] == ' ' or buf[ps_st] == ','): - ps_st += 1 - if ps_st >= e or buf[ps_st] == '}': - break + while ps_st < e and (buf[ps_st] == ' ' or buf[ps_st] == ','): ps_st += 1 + if ps_st >= e or buf[ps_st] == '}': break es_st: sizet = ps_st - while ps_st < e and buf[ps_st] != ',' and buf[ps_st] != '}': - ps_st += 1 + while ps_st < e and buf[ps_st] != ',' and buf[ps_st] != '}': ps_st += 1 ee_st: sizet = ps_st if ee_st > es_st: et_st: mlirlite.LLVMType* = self._ParseLLVMRetTyStr(pool, buf, es_st, ee_st) if et_st is None: return None en_st: mlirlite.ParamNode* = mlirlite.new_param_node(pool, et_st) if en_st is None: return None - if th_st is None: - th_st = en_st - else: - mlirlite.paramnode_set_next(tt_st, en_st) + if th_st is None: th_st = en_st + else: mlirlite.paramnode_set_next(tt_st, en_st) tt_st = en_st tc_st += 1 - if th_st is None or tc_st == 0: - return None + if th_st is None or tc_st == 0: return None st_ty_st: mlirlite.LLVMType* = mlirlite.Struct(pool, th_st, tc_st, None) # 指针到 struct({i32, i8}*):返回 Ptr(Struct);纯 tuple 打包 # ({i8*, i16})无尾部 *,返回 Struct 本身。 - if ps_st < e and buf[ps_st] == '*': - return mlirlite.Ptr(pool, st_ty_st) + if ps_st < e and buf[ps_st] == '*': return mlirlite.Ptr(pool, st_ty_st) return st_ty_st # 命名类型(%"name" / %name)带指针:先解析到真实结构体/枚举类型再包 Ptr。 @@ -951,8 +871,7 @@ novirtual class CallGenBase: while nm_e > nm_s and buf[nm_e - 1] == '*': nm_star += 1 nm_e -= 1 - while nm_e > nm_s and (buf[nm_e - 1] == ' ' or buf[nm_e - 1] == '\t'): - nm_e -= 1 + while nm_e > nm_s and (buf[nm_e - 1] == ' ' or buf[nm_e - 1] == '\t'): nm_e -= 1 if nm_star > 0 and nm_e > nm_s: if buf[nm_s] == '"' and buf[nm_e - 1] == '"': nm_s += 1 @@ -964,8 +883,7 @@ novirtual class CallGenBase: string.strncpy(nm_buf, buf + nm_s, nm_len) nm_buf[nm_len] = '\0' nm_ty: mlirlite.LLVMType* = GenApi.get_struct_type(nm_buf) - if nm_ty is None: - nm_ty = GenApi.get_enum_base_type(nm_buf) + if nm_ty is None: nm_ty = GenApi.get_enum_base_type(nm_buf) stdlib.free(nm_buf) if nm_ty is not None: nm_wrap: mlirlite.LLVMType* = nm_ty @@ -979,21 +897,17 @@ novirtual class CallGenBase: # 包括 i8*, i32*, { i32, i8 }*,以及上面未登记命名的 %name* ci: sizet = s while ci < e: - if buf[ci] == '*': - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + if buf[ci] == '*': return mlirlite.Ptr(pool, mlirlite.Int8(pool)) ci += 1 # void - if ty_len == 4 and string.strncmp(buf + s, "void", 4) == 0: - return mlirlite.Void(pool) + if ty_len == 4 and string.strncmp(buf + s, "void", 4) == 0: return mlirlite.Void(pool) # double - if ty_len == 6 and string.strncmp(buf + s, "double", 6) == 0: - return mlirlite.Double(pool) + if ty_len == 6 and string.strncmp(buf + s, "double", 6) == 0: return mlirlite.Double(pool) # float - if ty_len == 5 and string.strncmp(buf + s, "float", 5) == 0: - return mlirlite.Float(pool) + if ty_len == 5 and string.strncmp(buf + s, "float", 5) == 0: return mlirlite.Float(pool) # iN (i8, i16, i32, i64) if ty_len >= 2 and buf[s] == 'i': @@ -1002,21 +916,16 @@ novirtual class CallGenBase: valid: int = 1 while di < e: d: int = buf[di] - if d >= '0' and d <= '9': - bits = bits * 10 + (d - '0') + if d >= '0' and d <= '9': bits = bits * 10 + (d - '0') else: valid = 0 break di += 1 if valid != 0 and bits > 0: - if bits == 8: - return mlirlite.Int8(pool) - if bits == 16: - return mlirlite.Int16(pool) - if bits == 32: - return mlirlite.Int32(pool) - if bits == 64: - return mlirlite.Int64(pool) + if bits == 8: return mlirlite.Int8(pool) + if bits == 16: return mlirlite.Int16(pool) + if bits == 32: return mlirlite.Int32(pool) + if bits == 64: return mlirlite.Int64(pool) # 无法解析 return None @@ -1039,20 +948,15 @@ novirtual class CallGenBase: 无法解析返回 None(与 _ParseLLVMRetTyStr 同约定:宁缺毋错,不静默降级)。 """ - if pool is None or buf is None or start >= end: - return None + if pool is None or buf is None or start >= end: return None s: sizet = start - while s < end and (buf[s] == ' ' or buf[s] == '\t'): - s += 1 + while s < end and (buf[s] == ' ' or buf[s] == '\t'): s += 1 e: sizet = end - while e > s and (buf[e - 1] == ' ' or buf[e - 1] == '\t' or buf[e - 1] == '{'): - e -= 1 - if s >= e: - return None + while e > s and (buf[e - 1] == ' ' or buf[e - 1] == '\t' or buf[e - 1] == '{'): e -= 1 + if s >= e: return None n: sizet = e - s # none → Void(MLIR 的 void 记法) - if n == 4 and string.strncmp(buf + s, "none", 4) == 0: - return mlirlite.Void(pool) + if n == 4 and string.strncmp(buf + s, "none", 4) == 0: return mlirlite.Void(pool) # 标量:iN / fN if buf[s] == 'i' or buf[s] == 'f': bits: int = 0 @@ -1060,8 +964,7 @@ novirtual class CallGenBase: ok: int = 1 while di < e: d: int = buf[di] - if d >= '0' and d <= '9': - bits = bits * 10 + (d - '0') + if d >= '0' and d <= '9': bits = bits * 10 + (d - '0') else: ok = 0 break @@ -1080,8 +983,7 @@ novirtual class CallGenBase: if bits == 128: return mlirlite.FP128(pool) return None # 不透明指针 → 通用 i8* - if n >= 9 and string.strncmp(buf + s, "!llvm.ptr", 9) == 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + if n >= 9 and string.strncmp(buf + s, "!llvm.ptr", 9) == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) # !llvm.array if n >= 12 and string.strncmp(buf + s, "!llvm.array<", 12) == 0: is_a: sizet = s + 12 @@ -1090,21 +992,17 @@ novirtual class CallGenBase: iia: sizet = is_a while iia < e: ca: int = buf[iia] - if ca == '<': - depth_a += 1 + if ca == '<': depth_a += 1 elif ca == '>': if depth_a == 0: iea = iia break depth_a -= 1 iia += 1 - if iea <= is_a: - return None + if iea <= is_a: return None xs: sizet = is_a - while xs < iea and buf[xs] != 'x': - xs += 1 - if xs >= iea: - return None + while xs < iea and buf[xs] != 'x': xs += 1 + if xs >= iea: return None cnt_a: int = 0 ok_a: int = 0 ci_a: sizet = is_a @@ -1114,11 +1012,9 @@ novirtual class CallGenBase: cnt_a = cnt_a * 10 + (da - '0') ok_a = 1 ci_a += 1 - if ok_a == 0 or cnt_a <= 0: - return None + if ok_a == 0 or cnt_a <= 0: return None et_a: mlirlite.LLVMType* = self._ParseMlirRetTyStr(pool, buf, xs + 1, iea) - if et_a is None: - return None + if et_a is None: return None return mlirlite.Array(pool, et_a, cnt_a) # !llvm.struct<...>(匿名体 / 具名内联体) if n >= 13 and string.strncmp(buf + s, "!llvm.struct<", 13) == 0: @@ -1128,41 +1024,32 @@ novirtual class CallGenBase: iis: sizet = is_s while iis < e: cs: int = buf[iis] - if cs == '<': - depth_s += 1 + if cs == '<': depth_s += 1 elif cs == '>': if depth_s == 0: ies = iis break depth_s -= 1 iis += 1 - if ies <= is_s: - return None + if ies <= is_s: return None a: sizet = is_s - while a < ies and (buf[a] == ' ' or buf[a] == '\t'): - a += 1 + while a < ies and (buf[a] == ' ' or buf[a] == '\t'): a += 1 b: sizet = ies - while b > a and (buf[b - 1] == ' ' or buf[b - 1] == '\t'): - b -= 1 + while b > a and (buf[b - 1] == ' ' or buf[b - 1] == '\t'): b -= 1 nm_buf: bytes = None if a < b and buf[a] == '"': ns: sizet = a + 1 ne: sizet = ns - while ne < b and buf[ne] != '"': - ne += 1 - if ne <= ns: - return None + while ne < b and buf[ne] != '"': ne += 1 + if ne <= ns: return None nm_buf = stdlib.malloc(ne - ns + 1) - if nm_buf is None: - return None + if nm_buf is None: return None string.strncpy(nm_buf, buf + ns, ne - ns) nm_buf[ne - ns] = '\0' a = ne + 1 - while a < b and (buf[a] == ' ' or buf[a] == ','): - a += 1 + while a < b and (buf[a] == ' ' or buf[a] == ','): a += 1 if a >= b or buf[a] != '(' or buf[b - 1] != ')': - if nm_buf is not None: - stdlib.free(nm_buf) + if nm_buf is not None: stdlib.free(nm_buf) return None # 字段表:按顶层逗号切分(括号/尖括号计入深度) head: mlirlite.ParamNode* = None @@ -1175,44 +1062,33 @@ novirtual class CallGenBase: done: int = 0 while done == 0: at_end: int = 0 - if cur_f >= fe_f: - at_end = 1 - elif buf[cur_f] == ',' and depth_f == 0: - at_end = 1 + if cur_f >= fe_f: at_end = 1 + elif buf[cur_f] == ',' and depth_f == 0: at_end = 1 if at_end != 0: gs: sizet = seg_s ge: sizet = cur_f - while gs < ge and (buf[gs] == ' ' or buf[gs] == '\t'): - gs += 1 - while ge > gs and (buf[ge - 1] == ' ' or buf[ge - 1] == '\t'): - ge -= 1 + while gs < ge and (buf[gs] == ' ' or buf[gs] == '\t'): gs += 1 + while ge > gs and (buf[ge - 1] == ' ' or buf[ge - 1] == '\t'): ge -= 1 if ge > gs: ft: mlirlite.LLVMType* = self._ParseMlirRetTyStr(pool, buf, gs, ge) if ft is None: - if nm_buf is not None: - stdlib.free(nm_buf) + if nm_buf is not None: stdlib.free(nm_buf) return None fn: mlirlite.ParamNode* = mlirlite.new_param_node(pool, ft) if fn is None: - if nm_buf is not None: - stdlib.free(nm_buf) + if nm_buf is not None: stdlib.free(nm_buf) return None - if head is None: - head = fn - else: - mlirlite.paramnode_set_next(tail, fn) + if head is None: head = fn + else: mlirlite.paramnode_set_next(tail, fn) tail = fn cnt_f += 1 seg_s = cur_f + 1 - if cur_f >= fe_f: - done = 1 + if cur_f >= fe_f: done = 1 else: c3: int = buf[cur_f] - if c3 == '(' or c3 == '<': - depth_f += 1 + if c3 == '(' or c3 == '<': depth_f += 1 elif c3 == ')' or c3 == '>': - if depth_f > 0: - depth_f -= 1 + if depth_f > 0: depth_f -= 1 cur_f += 1 # 具名:按登记表回查真实类型;未登记返回 None(不臆造类型对象) if nm_buf is not None: @@ -1226,32 +1102,25 @@ novirtual class CallGenBase: def _LookupCachedRetTyText(self, class_sha1: str, class_name: str, method_name: str, use_bare: int) -> str: """查返回类型文本缓存:命中返回文本,未命中返回 None""" - if self.Gen is None or class_sha1 is None or method_name is None: - return None + if self.Gen is None or class_sha1 is None or method_name is None: return None ht: hashtable.HashTable* = self.Gen.CallGenBase.MethodRetTyMap - if ht is None: - return None + if ht is None: return None sha1_len: sizet = string.strlen(class_sha1) cls_len: sizet = 0 - if class_name is not None: - cls_len = string.strlen(class_name) + if class_name is not None: cls_len = string.strlen(class_name) meth_len: sizet = string.strlen(method_name) # 长度公式与 _LookupMethodRetTyFromTextLL 构造 search_buf 时完全一致 key_len: sizet = sha1_len + meth_len + 2 - if use_bare == 0: - key_len = sha1_len + cls_len + meth_len + 4 + if use_bare == 0: key_len = sha1_len + cls_len + meth_len + 4 key_buf: bytes = stdlib.malloc(key_len) - if key_buf is None: - return None - if use_bare != 0: - viperlib.snprintf(key_buf, key_len, "%s.%s", class_sha1, method_name) + if key_buf is None: return None + if use_bare != 0: viperlib.snprintf(key_buf, key_len, "%s.%s", class_sha1, method_name) else: viperlib.snprintf(key_buf, key_len, "%s.%s.%s", class_sha1, class_name, method_name) v: t.CPtr = ht.__getitem__(key_buf) stdlib.free(key_buf) - if v is None: - return None + if v is None: return None return rawptr(v) # _CacheModuleRetTyTexts:单趟扫描某模块 text.ll——把全部 define 行的返回类型写入持久缓存(键/值深拷贝进 PermPool,同名只记首次,只登记 "{sha1}." 开头的本模块 mangled 名),并在同一趟里返回首个匹配 search_buf 的 define 的返回类型(未匹配返回 None);仅在成功读到 text.ll 后调用,负结果绝不缓存 @@ -1259,8 +1128,7 @@ novirtual class CallGenBase: text_len: sizet, pool: memhub.MemBuddy*, search_buf: str, search_str_len: sizet) -> mlirlite.LLVMType*: """单趟「登记 + 查找」text.ll 全部 define 行(建表/分配失败时只查找不登记)""" - if text_buf is None or text_len == 0: - return None + if text_buf is None or text_len == 0: return None # 合并原「先全量登记一遍、再二次扫描查找」的两趟全文件遍历(PROF:两次扫描合计约 14%)。 # 建表失败(PermPool 未就绪等)不影响查找:cache_on=0 时只走同趟查找。 cache_on: int = 0 @@ -1273,8 +1141,7 @@ novirtual class CallGenBase: ht = self.Gen.CallGenBase.MethodRetTyMap if ht is None: ht = hashtable.HashTable(perm) - if ht is not None: - self.Gen.CallGenBase.MethodRetTyMap = ht + if ht is not None: self.Gen.CallGenBase.MethodRetTyMap = ht if ht is not None: cache_on = 1 sha1_len = string.strlen(class_sha1) @@ -1284,8 +1151,7 @@ novirtual class CallGenBase: ls: sizet = pos le: sizet = pos while le < text_len: - if text_buf[le] == '\n': - break + if text_buf[le] == '\n': break le += 1 ll: sizet = le - ls # 函数定义行两种形态都要认: @@ -1295,8 +1161,7 @@ novirtual class CallGenBase: # 单端 MLIR 后 text.ll 里已无 define 行,只认 LLVM 形态会让回退恒 None # ⇒ 指针返回值退回默认 i32 被 inttoptr 截断。 fs: sizet = ls - while fs < ls + ll and (text_buf[fs] == ' ' or text_buf[fs] == '\t'): - fs += 1 + while fs < ls + ll and (text_buf[fs] == ' ' or text_buf[fs] == '\t'): fs += 1 is_mlir_line: int = 0 mlir_none: int = 0 matched: int = 0 @@ -1307,8 +1172,7 @@ novirtual class CallGenBase: matched = 1 at_pos = ls + 7 while at_pos < ls + ll: - if text_buf[at_pos] == '@': - break + if text_buf[at_pos] == '@': break at_pos += 1 ret_s = ls + 7 ret_e = at_pos @@ -1330,8 +1194,7 @@ novirtual class CallGenBase: ret_e = ls + ll else: ret_s = arrow + 3 - while ret_s < ls + ll and text_buf[ret_s] == ' ': - ret_s += 1 + while ret_s < ls + ll and text_buf[ret_s] == ' ': ret_s += 1 ret_e = ls + ll kk: sizet = ret_s while kk + 1 < ls + ll: @@ -1349,13 +1212,11 @@ novirtual class CallGenBase: name_end: sizet = name_start if quoted != 0: while name_end < ls + ll: - if text_buf[name_end] == '"': - break + if text_buf[name_end] == '"': break name_end += 1 else: while name_end < ls + ll: - if text_buf[name_end] == '(': - break + if text_buf[name_end] == '(': break name_end += 1 name_len: sizet = name_end - name_start # 只登记本模块 mangled 名 "{sha1}.{后缀}"(查询键恒为此前缀);表不可用时跳过登记 @@ -1374,10 +1235,8 @@ novirtual class CallGenBase: if is_mlir_line != 0: if mlir_none != 0: rt_len = 5 # '#' + "none" - else: - rt_len = 1 + (ret_e - ret_s) - else: - rt_len = at_pos - (ls + 7) + else: rt_len = 1 + (ret_e - ret_s) + else: rt_len = at_pos - (ls + 7) kcopy: str = perm.alloc(name_len + 1) tcopy: str = perm.alloc(rt_len + 1) if kcopy is not None and tcopy is not None: @@ -1385,12 +1244,9 @@ novirtual class CallGenBase: kcopy[name_len] = '\0' if is_mlir_line != 0: tcopy[0] = '#' - if mlir_none != 0: - string.strncpy(tcopy + 1, "none", 4) - else: - string.strncpy(tcopy + 1, text_buf + ret_s, ret_e - ret_s) - else: - string.strncpy(tcopy, text_buf + ls + 7, rt_len) + if mlir_none != 0: string.strncpy(tcopy + 1, "none", 4) + else: string.strncpy(tcopy + 1, text_buf + ret_s, ret_e - ret_s) + else: string.strncpy(tcopy, text_buf + ls + 7, rt_len) tcopy[rt_len] = '\0' ht.set_str(kcopy, tcopy) stdlib.free(key_buf) @@ -1399,16 +1255,12 @@ novirtual class CallGenBase: if result_ty is None and name_start + search_str_len <= ls + ll: if string.strncmp(text_buf + name_start, search_buf, search_str_len) == 0: end_ch: int = 0 - if name_start + search_str_len < ls + ll: - end_ch = text_buf[name_start + search_str_len] + if name_start + search_str_len < ls + ll: end_ch = text_buf[name_start + search_str_len] if end_ch == 34 or end_ch == 40 or end_ch == 0: if is_mlir_line != 0: - if mlir_none != 0: - result_ty = mlirlite.Void(pool) - else: - result_ty = self._ParseMlirRetTyStr(pool, text_buf, ret_s, ret_e) - else: - result_ty = self._ParseLLVMRetTyStr(pool, text_buf, ls + 7, at_pos) + if mlir_none != 0: result_ty = mlirlite.Void(pool) + else: result_ty = self._ParseMlirRetTyStr(pool, text_buf, ret_s, ret_e) + else: result_ty = self._ParseLLVMRetTyStr(pool, text_buf, ls + 7, at_pos) pos = le + 1 return result_ty @@ -1425,21 +1277,17 @@ novirtual class CallGenBase: use_bare: 1=按模块级函数查找(搜索 "{sha1}.{method_name}" define, 用于 new_lexer/tokenize 等模块函数;class_name 忽略)。 """ - if pool is None or class_sha1 is None or method_name is None: - return None - if self.Gen.CallGenBase.TempDir is None or self.Gen.CallGenBase.TempDirLen == 0: - return None + if pool is None or class_sha1 is None or method_name is None: return None + if self.Gen.CallGenBase.TempDir is None or self.Gen.CallGenBase.TempDirLen == 0: return None sha1_len: sizet = string.strlen(class_sha1) - if sha1_len < 2: - return None + if sha1_len < 2: return None # 缓存命中:O(1) 取回返回类型文本并用调用方 pool 重建类型直接返回;未命中走下方原实现 cached_text: str = self._LookupCachedRetTyText(class_sha1, class_name, method_name, use_bare) if cached_text is not None: # '#' 前缀 = MLIR 类型文本(_CacheModuleRetTyTexts 写入时打的形态标记) - if cached_text[0] == '#': - return self._ParseMlirRetTyStr(pool, cached_text, 1, string.strlen(cached_text)) + if cached_text[0] == '#': return self._ParseMlirRetTyStr(pool, cached_text, 1, string.strlen(cached_text)) return self._ParseLLVMRetTyStr(pool, cached_text, 0, string.strlen(cached_text)) # 构造 text.ll 路径 (level=1): {temp_dir}/{sha1[0:2]}/{sha1}.text.ll @@ -1485,12 +1333,10 @@ novirtual class CallGenBase: # 构造搜索模式: "{sha1}.{class_name}.{method_name}" 或 bare 模式 "{sha1}.{method_name}" cls_len: sizet = 0 - if class_name is not None: - cls_len = string.strlen(class_name) + if class_name is not None: cls_len = string.strlen(class_name) meth_len: sizet = string.strlen(method_name) search_len: sizet = sha1_len + meth_len + 2 - if use_bare == 0: - search_len = sha1_len + cls_len + meth_len + 4 + if use_bare == 0: search_len = sha1_len + cls_len + meth_len + 4 search_buf: bytes = stdlib.malloc(search_len) if search_buf is None: stdlib.free(read_buf) @@ -1518,19 +1364,15 @@ novirtual class CallGenBase: def _dep_text_ll_exists(self, pool: memhub.MemBuddy*, sha1: str) -> int: """探测 {temp_dir}/{sha1[0:2]}/{sha1}.text.ll 是否存在,1=存在""" - if self.Gen.CallGenBase.TempDir is None or self.Gen.CallGenBase.TempDirLen == 0 or sha1 is None: - return 0 + if self.Gen.CallGenBase.TempDir is None or self.Gen.CallGenBase.TempDirLen == 0 or sha1 is None: return 0 sha1_len: sizet = string.strlen(sha1) - if sha1_len < 2: - return 0 + if sha1_len < 2: return 0 path_len: sizet = self.Gen.CallGenBase.TempDirLen + sha1_len + 14 path_buf: bytes = stdlib.malloc(path_len) subdir_buf: bytes = stdlib.malloc(3) if path_buf is None or subdir_buf is None: - if path_buf is not None: - stdlib.free(path_buf) - if subdir_buf is not None: - stdlib.free(subdir_buf) + if path_buf is not None: stdlib.free(path_buf) + if subdir_buf is not None: stdlib.free(subdir_buf) return 0 subdir_buf[0] = sha1[0] subdir_buf[1] = sha1[1] @@ -1542,12 +1384,10 @@ novirtual class CallGenBase: attr: ULONG = win32file.GetFileAttributesA(path_buf) exists: int = 1 # INVALID_FILE_ATTRIBUTES = 不存在/不可访问 → 0。 - if attr == 0xFFFFFFFF: - exists = 0 + if attr == 0xFFFFFFFF: exists = 0 # 原实现以只读 CreateFileA 打开:目录会被拒绝(未带 FILE_FLAG_BACKUP_SEMANTICS) # → 0,故此处显式排除目录以保持「是可读常规文件」的等价判定。 - if (attr & win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: - exists = 0 + if (attr & win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: exists = 0 stdlib.free(path_buf) return exists diff --git a/App/lib/core/Gen/Call/CallGenCBuiltin.vp b/App/lib/core/Gen/Call/CallGenCBuiltin.vp index 16df26d..704bbdd 100644 --- a/App/lib/core/Gen/Call/CallGenCBuiltin.vp +++ b/App/lib/core/Gen/Call/CallGenCBuiltin.vp @@ -68,8 +68,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # (是否带注解赋值的 RHS)而变。 if self.Gen.ExprGenBase.is_ptr_type(ptr_val.Ty) != 0: pointee: mlirlite.LLVMType* = ptr_val.Ty.Pointee - if pointee is not None: - return mlirlite.build_load(builder, pointee, ptr_val, vol_deref) + if pointee is not None: return mlirlite.build_load(builder, pointee, ptr_val, vol_deref) # 非指针参数即类型推断退化:fail-fast,绝不按 i8 兜底读取(会读到垃圾宽度) self.Gen.TypeGenErr.fatal_error(cl, "c.Deref 参数不是指针类型(类型推断退化)", "TypeError") return None @@ -83,19 +82,16 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): """c.DerefAs(ptr, val) → store val to ptr(bitcast 后 store) 单参形式 c.DerefAs(ptr) → 读取 ptr 指向的值(等价 *ptr)。 """ - if cl is None: - return None + if cl is None: return None cargs: list[ast.AST*]* = cl.args - if cargs is None or len(cargs) < 1: - return None + if cargs is None or len(cargs) < 1: return None # 单参形式:deref 读(paging.vp save_pt_range L263 # saved = c.DerefAs(save_count)、restore_pt_range L277-278 # c.DerefAs(entry_ptr) 根因——此前 len<2 直接 return None → # 跌落跨模块函数调用生成 call @DerefAs → ld.lld undefined symbol: # DerefAs。读取宽度与 c.Deref 同口径(只认 pointee 类型), # 故直接复用 translate_c_deref。 - if len(cargs) < 2: - return self.translate_c_deref(pool, builder, mod, cl, trans) + if len(cargs) < 2: return self.translate_c_deref(pool, builder, mod, cl, trans) ptr_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), None, 0, trans) val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(1), None, 0, trans) @@ -119,15 +115,13 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # bitcast ptr 到结构体指针再 store struct_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, ptr_pointee) casted_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, ptr_val, struct_ptr_ty) - if casted_ptr is not None: - mlirlite.build_store(builder, loaded, casted_ptr) + if casted_ptr is not None: mlirlite.build_store(builder, loaded, casted_ptr) return val # bitcast ptr 到 val.Ty* 再 store val_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, val.Ty) casted_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, ptr_val, val_ptr_ty) - if casted_ptr is None: - return None + if casted_ptr is None: return None mlirlite.build_store(builder, val, casted_ptr) return val @@ -166,27 +160,19 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): store_val: mlirlite.Value* = b_val typed_elem: int = 0 elem_ty: mlirlite.LLVMType* = None - if ptr_val.Ty is not None: - elem_ty = ptr_val.Ty.Pointee + if ptr_val.Ty is not None: elem_ty = ptr_val.Ty.Pointee if elem_ty is not None: eb: int = self.Gen.ExprGenBase.get_llvm_type_bits(elem_ty) - if eb != 0 and eb != 8: - typed_elem = 1 - elif self.Gen.ExprGenBase.get_llvm_float_bits(elem_ty) != 0: - typed_elem = 1 - elif self.Gen.ExprGenBase.is_ptr_type(elem_ty) != 0: - typed_elem = 1 - elif self.Gen.ExprGenBase.is_array_type(elem_ty) != 0: - typed_elem = 1 - if typed_elem != 0: - store_val = self.Gen.ExprGenBase.coerce_to_type(builder, b_val, elem_ty, a_node) + if eb != 0 and eb != 8: typed_elem = 1 + elif self.Gen.ExprGenBase.get_llvm_float_bits(elem_ty) != 0: typed_elem = 1 + elif self.Gen.ExprGenBase.is_ptr_type(elem_ty) != 0: typed_elem = 1 + elif self.Gen.ExprGenBase.is_array_type(elem_ty) != 0: typed_elem = 1 + if typed_elem != 0: store_val = self.Gen.ExprGenBase.coerce_to_type(builder, b_val, elem_ty, a_node) else: val_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, b_val.Ty) casted_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, ptr_val, val_ptr_ty) - if casted_ptr is not None: - store_ptr = casted_ptr - if store_ptr is not None and store_val is not None: - mlirlite.build_store(builder, store_val, store_ptr) + if casted_ptr is not None: store_ptr = casted_ptr + if store_ptr is not None and store_val is not None: mlirlite.build_store(builder, store_val, store_ptr) return b_val # 其他 Call 形态不可作左值 return b_val @@ -199,32 +185,26 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): mod_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm_set.id) if mod_alloca is not None: tg_ty: mlirlite.LLVMType* = None - if mod_alloca.Ty is not None: - tg_ty = mod_alloca.Ty.Pointee + if mod_alloca.Ty is not None: tg_ty = mod_alloca.Ty.Pointee sv: mlirlite.Value* = b_val - if tg_ty is not None: - sv = self.Gen.ExprGenBase.coerce_to_type(builder, b_val, tg_ty, a_node) + if tg_ty is not None: sv = self.Gen.ExprGenBase.coerce_to_type(builder, b_val, tg_ty, a_node) mlirlite.build_store(builder, sv, mod_alloca) return b_val if GenApi.is_nonlocal_name(trans, nm_set.id) != 0: nl_ptr: mlirlite.Value* = self.Gen.StmtGenDecl.get_nonlocal_var_ptr(trans, nm_set.id) if nl_ptr is not None: nl_ty: mlirlite.LLVMType* = None - if nl_ptr.Ty is not None: - nl_ty = nl_ptr.Ty.Pointee + if nl_ptr.Ty is not None: nl_ty = nl_ptr.Ty.Pointee sv2: mlirlite.Value* = b_val - if nl_ty is not None: - sv2 = self.Gen.ExprGenBase.coerce_to_type(builder, b_val, nl_ty, a_node) + if nl_ty is not None: sv2 = self.Gen.ExprGenBase.coerce_to_type(builder, b_val, nl_ty, a_node) mlirlite.build_store(builder, sv2, nl_ptr) return b_val alloca: mlirlite.Value* = self.Gen.VarGen.get_or_create_sym(trans.SymTab, pool, builder, nm_set.id, b_val.Ty) if alloca is not None: ac_ty: mlirlite.LLVMType* = None - if alloca.Ty is not None: - ac_ty = alloca.Ty.Pointee + if alloca.Ty is not None: ac_ty = alloca.Ty.Pointee sv3: mlirlite.Value* = b_val - if ac_ty is not None: - sv3 = self.Gen.ExprGenBase.coerce_to_type(builder, b_val, ac_ty, a_node) + if ac_ty is not None: sv3 = self.Gen.ExprGenBase.coerce_to_type(builder, b_val, ac_ty, a_node) mlirlite.build_store(builder, sv3, alloca) return b_val return b_val @@ -234,11 +214,9 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): field_ptr: mlirlite.Value* = self.Gen.ExprGenAttr.get_attribute_ptr(builder, pool, mod, a_node, trans) if field_ptr is not None: fd_ty: mlirlite.LLVMType* = None - if field_ptr.Ty is not None: - fd_ty = field_ptr.Ty.Pointee + if field_ptr.Ty is not None: fd_ty = field_ptr.Ty.Pointee sv4: mlirlite.Value* = b_val - if fd_ty is not None: - sv4 = self.Gen.ExprGenBase.coerce_to_type(builder, b_val, fd_ty, a_node) + if fd_ty is not None: sv4 = self.Gen.ExprGenBase.coerce_to_type(builder, b_val, fd_ty, a_node) mlirlite.build_store(builder, sv4, field_ptr) return b_val @@ -251,21 +229,17 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): cl: ast.Call*, trans: HT.Translator* = None) -> mlirlite.Value*: """&var → 返回变量的 alloca 指针(不 load)""" - if cl is None: - return None + if cl is None: return None cargs: list[ast.AST*]* = cl.args - if cargs is None or len(cargs) < 1: - return None + if cargs is None or len(cargs) < 1: return None arg0: ast.AST* = cargs.get(0) - if arg0 is None: - return None + if arg0 is None: return None # Name 形式: c.Addr(var) → 返回变量的 alloca 指针(不 load) if arg0.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(arg0) - if nm.id is None: - return None + if nm.id is None: return None if trans is not None: # self/cls 对象引用:c.Addr(self) 返回对象指针本身(Ptr(Struct)), # 而非指针变量的地址(Ptr(Ptr(Struct)))。方法与 Attribute 分支 @@ -288,21 +262,18 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if trans is not None: if GenApi.is_nonlocal_name(trans, nm.id) != 0: nl_addr: mlirlite.Value* = self.Gen.StmtGenDecl.load_nonlocal_var(trans, nm.id) - if nl_addr is not None: - return nl_addr + if nl_addr is not None: return nl_addr return_var: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id) # REPL 模式(M2)会话变量取址:c.Addr(x) → ctx 内该槽的地址(地址同一性)。 # 位置在局部查找之后(片段自己声明的局部名优先,与读路径同序)、 # 模块全局/函数引用之前。守卫 trans.ReplCtx:非 REPL 恒 None ⇒ 不变。 if return_var is None and trans is not None and trans.ReplCtx is not None: sess_addr: mlirlite.Value* = self.Gen.VarGen.repl_try_addr(trans, nm.id, arg0) - if sess_addr is not None: - return sess_addr + if sess_addr is not None: return sess_addr if return_var is None and mod is not None: # 模块全局变量 c.Addr(模块全局) → 返回全局变量指针:必须经 make_global_ref 转成带引号的 Ptr(Ty) 引用(直接返回 GlobalVariable 节点时其 Ty 是 pointee、Name 无 @ 引号,参与 ptrtoint 会渲染成 "ptrtoint void to i64") gv_ref_nm: mlirlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(mod, nm.id) - if gv_ref_nm is not None and gv_ref_nm.Name is not None and gv_ref_nm.Ty is not None: - return_var = self.Gen.ExprGenAttr.make_global_ref(pool, gv_ref_nm.Name, gv_ref_nm.Ty) + if gv_ref_nm is not None and gv_ref_nm.Name is not None and gv_ref_nm.Ty is not None: return_var = self.Gen.ExprGenAttr.make_global_ref(pool, gv_ref_nm.Name, gv_ref_nm.Ty) # 模块函数地址:c.Addr(_on_int_complete) → 函数符号本身(@sha1.func)。 # 此前 Name 分支只查局部/模块全局变量,函数取地址失败 return None # → 跌落跨模块函数调用生成 call @Addr → ld.lld undefined symbol: @@ -323,10 +294,8 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): needs_q_ca: int = self.Gen.ClassGenVTable._vtable_name_needs_quote(f_addr_name) faddr_buf_ca: str = pool.alloc(fnlen_ca + 4) if faddr_buf_ca is not None and fn_ty_ca is not None: - if needs_q_ca != 0: - viperlib.snprintf(faddr_buf_ca, fnlen_ca + 4, "@\"%s\"", f_addr_name) - else: - viperlib.snprintf(faddr_buf_ca, fnlen_ca + 4, "@%s", f_addr_name) + if needs_q_ca != 0: viperlib.snprintf(faddr_buf_ca, fnlen_ca + 4, "@\"%s\"", f_addr_name) + else: viperlib.snprintf(faddr_buf_ca, fnlen_ca + 4, "@%s", f_addr_name) return_var = mlirlite.SSAValue(pool, mlirlite.Ptr(pool, fn_ty_ca), faddr_buf_ca) # 闭包变量:c.Addr(闭包名) → 返回闭包对象指针(load 一次)。 # 闭包 alloca 是 i8**(存 {fn_ptr, env_ptr} 结构地址);不 load 的话 @@ -365,11 +334,9 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # Attribute 形式: c.Addr(self.field) → 取字段地址(GEP 到字段,不 load) # 用于 atom.__atomic_test_and_set(c.Addr(self.lock_val), ...) 等锁操作 if arg0.kind() == ast.ASTKind.Attribute: - if trans is None: - return None + if trans is None: return None at_addr: ast.Attribute* = ast.Attribute*(arg0) - if at_addr is None or at_addr.attr is None or at_addr.value is None: - return None + if at_addr is None or at_addr.attr is None or at_addr.value is None: return None # 跨模块函数地址 c.Addr(serial.puts) → 函数符号本身(@sha1.puts):不可回退 ExprGenAttr 当全局变量处理,否则与 vpi 注入的 puts 函数 declare 同名冲突(llc "redefinition of function") if at_addr.value.kind() == ast.ASTKind.Name and trans is not None and trans._imported_modules is not None: mod_nm2: ast.Name* = ast.Name*(at_addr.value) @@ -388,16 +355,13 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): needs_q2: int = self.Gen.ClassGenVTable._vtable_name_needs_quote(fname2) faddr_buf2: str = pool.alloc(fnlen2 + 4) if faddr_buf2 is not None and fn_ty2 is not None: - if needs_q2 != 0: - viperlib.snprintf(faddr_buf2, fnlen2 + 4, "@\"%s\"", fname2) - else: - viperlib.snprintf(faddr_buf2, fnlen2 + 4, "@%s", fname2) + if needs_q2 != 0: viperlib.snprintf(faddr_buf2, fnlen2 + 4, "@\"%s\"", fname2) + else: viperlib.snprintf(faddr_buf2, fnlen2 + 4, "@%s", fname2) return mlirlite.SSAValue(pool, mlirlite.Ptr(pool, fn_ty2), faddr_buf2) else: # 模块限定全局 c.Addr(gdt.gp) → 全局符号本身(@gp):跨模块全局(含 CExport 裸名)已注入为 external global,经 make_global_ref 转成带引号的 Ptr(Ty) 引用(直接返回 GlobalVariable 节点会渲染 "ptrtoint void") g_ref2: mlirlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(mod, at_addr.attr) - if g_ref2 is not None and g_ref2.Name is not None and g_ref2.Ty is not None: - return self.Gen.ExprGenAttr.make_global_ref(pool, g_ref2.Name, g_ref2.Ty) + if g_ref2 is not None and g_ref2.Name is not None and g_ref2.Ty is not None: return self.Gen.ExprGenAttr.make_global_ref(pool, g_ref2.Name, g_ref2.Ty) # 解析 base(Name 变量 / Subscript 数组元素)→ 对象指针 obj_ptr: mlirlite.Value* = None struct_ty: mlirlite.LLVMType* = None @@ -408,15 +372,12 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # call @Addr(sched.vp L90/L182/L188/L196、coroutine.vp # L99/L106/L112/L120 根因)。 sub_base: ast.Subscript* = ast.Subscript*(at_addr.value) - if sub_base.value is None or sub_base.slice is None: - return None + if sub_base.value is None or sub_base.slice is None: return None bval: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub_base.value, None, 0, trans) bidx: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub_base.slice, None, 0, trans) - if bval is None or bidx is None or bval.Ty is None: - return None + if bval is None or bidx is None or bval.Ty is None: return None bpointee: mlirlite.LLVMType* = None - if self.Gen.ExprGenBase.is_ptr_type(bval.Ty) != 0: - bpointee = bval.Ty.Pointee + if self.Gen.ExprGenBase.is_ptr_type(bval.Ty) != 0: bpointee = bval.Ty.Pointee if bpointee is not None: match bpointee: case mlirlite.LLVMType.Array(bet, _): @@ -424,15 +385,12 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): struct_ty = bet case _: return None - else: - return None + else: return None elif at_addr.value.kind() == ast.ASTKind.Name: self_nm: ast.Name* = ast.Name*(at_addr.value) - if self_nm.id is None: - return None + if self_nm.id is None: return None self_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, self_nm.id) - if self_alloca is None or self_alloca.Ty is None: - return None + if self_alloca is None or self_alloca.Ty is None: return None # 从 self 类型提取结构体类型(Ptr(Struct) 或 Ptr(Ptr(Struct))) self_is_ptr_ptr: int = 0 match self_alloca.Ty: @@ -450,14 +408,11 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if self_is_ptr_ptr == 1: self_obj_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, struct_ty) obj_ptr = mlirlite.build_load(builder, self_obj_ty, self_alloca) - else: - return None - if obj_ptr is None or struct_ty is None: - return None + else: return None + if obj_ptr is None or struct_ty is None: return None # 查找字段 fe_addr: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(struct_ty, at_addr.attr) - if fe_addr is None: - return None + if fe_addr is None: return None # GEP 到字段地址 return mlirlite.build_gep_struct(builder, struct_ty, fe_addr.Ty, obj_ptr, fe_addr.Index) @@ -481,8 +436,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # 下标 zext 由 mlirlite.build_gep / build_gep_array 内部统一处理 # (唯一真源),此处不再自行 zext。 arr_pointee_ca: mlirlite.LLVMType* = None - if self.Gen.ExprGenBase.is_ptr_type(arr_val.Ty) != 0: - arr_pointee_ca = arr_val.Ty.Pointee + if self.Gen.ExprGenBase.is_ptr_type(arr_val.Ty) != 0: arr_pointee_ca = arr_val.Ty.Pointee if arr_pointee_ca is not None: match arr_pointee_ca: case mlirlite.LLVMType.Array(arr_et_ca, _): @@ -528,10 +482,8 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if dst_ptr is None or src_ptr is None: return None # 确定 pointee 类型(优先用 src 的 pointee,回退到 dst 的 pointee) pointee: mlirlite.LLVMType* = None - if src_ptr.Ty is not None: - pointee = src_ptr.Ty.Pointee - if pointee is None and dst_ptr.Ty is not None: - pointee = dst_ptr.Ty.Pointee + if src_ptr.Ty is not None: pointee = src_ptr.Ty.Pointee + if pointee is None and dst_ptr.Ty is not None: pointee = dst_ptr.Ty.Pointee if pointee is None: return None # bitcast src 到 pointee* 并 load target_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, pointee) @@ -549,13 +501,11 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): def _asm_append_cstr(self, dst: str, dst_size: sizet, src: str): """将 C 字符串 src 追加到 dst 末尾""" - if dst is None or src is None: - return + if dst is None or src is None: return dlen: sizet = string.strlen(dst) slen: sizet = string.strlen(src) remain: sizet = dst_size - dlen - if remain <= 0: - return + if remain <= 0: return i: sizet = 0 while i < slen and i + 1 < remain: dst[dlen + i] = src[i] @@ -575,14 +525,11 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): 的全局必须标记 t.CExport 使用裸名(@gdt),此处按词边界匹配(前后 非标识符字符,避免误伤寄存器名/局部标签/指令助记符)命中即报错。 """ - if asm_text is None or mod is None: - return asm_text + if asm_text is None or mod is None: return asm_text src_len: sizet = string.strlen(asm_text) - if src_len == 0: - return asm_text + if src_len == 0: return asm_text out: str = pool.alloc(asm_size * 2) - if out is None: - return asm_text + if out is None: return asm_text out[0] = '\0' out_pos: sizet = 0 i: sizet = 0 @@ -602,12 +549,10 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): next_ok: int = 1 if i > 0: prev_ch: char = asm_text[i - 1] - if (prev_ch >= 'a' and prev_ch <= 'z') or (prev_ch >= 'A' and prev_ch <= 'Z') or (prev_ch >= '0' and prev_ch <= '9') or prev_ch == '_': - prev_ok = 0 + if (prev_ch >= 'a' and prev_ch <= 'z') or (prev_ch >= 'A' and prev_ch <= 'Z') or (prev_ch >= '0' and prev_ch <= '9') or prev_ch == '_': prev_ok = 0 if i + bare_len < src_len: next_ch: char = asm_text[i + bare_len] - if (next_ch >= 'a' and next_ch <= 'z') or (next_ch >= 'A' and next_ch <= 'Z') or (next_ch >= '0' and next_ch <= '9') or next_ch == '_': - next_ok = 0 + if (next_ch >= 'a' and next_ch <= 'z') or (next_ch >= 'A' and next_ch <= 'Z') or (next_ch >= '0' and next_ch <= '9') or next_ch == '_': next_ok = 0 if prev_ok != 0 and next_ok != 0: # fail-fast:asm 模板引用的模块全局带 SHA1 混淆头 # 不可在 LLVM MC 内联汇编中使用(数字开头的符号名 @@ -628,12 +573,10 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): def _asm_escape_for_ir(self, pool: memhub.MemBuddy*, src: str) -> str: """转义汇编文本用于 LLVM IR 字符串字面量""" - if src is None: - return None + if src is None: return None slen: sizet = string.strlen(src) buf: str = pool.alloc(slen * 4 + 8) - if buf is None: - return None + if buf is None: return None pos: sizet = 0 for ch in src: if ch == '\n': @@ -666,8 +609,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): def _resolve_register(self, attr_name: str) -> str: """将 ASM_DESCR.XXX 的属性名映射到约束字符串值""" - if attr_name is None: - return "" + if attr_name is None: return "" # Clobber 破坏描述符 if string.strcmp(attr_name, "CLOBBER_MEMORY") == 0: return "memory" @@ -763,8 +705,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): def _resolve_asm_descr(self, pool: memhub.MemBuddy*, node: ast.AST*) -> str: """递归解析约束表达式,返回约束字符串""" - if node is None: - return "" + if node is None: return "" k: int = node.kind() @@ -777,11 +718,9 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): llen: sizet = string.strlen(left_str) rlen: sizet = string.strlen(right_str) buf: str = pool.alloc(llen + rlen + 1) - if buf is None: - return "" + if buf is None: return "" string.strcpy(buf, left_str) - for i in range(rlen): - buf[llen + i] = right_str[i] + for i in range(rlen): buf[llen + i] = right_str[i] buf[llen + rlen] = '\0' return buf return "" @@ -795,23 +734,19 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if inner.value is not None and inner.value.kind() == ast.ASTKind.Name: mod_nm: ast.Name* = ast.Name*(inner.value) if mod_nm.id is not None and string.strcmp(mod_nm.id, "t") == 0: - if inner.attr is not None and string.strcmp(inner.attr, "ASM_DESCR") == 0: - return self._resolve_register(at.attr) + if inner.attr is not None and string.strcmp(inner.attr, "ASM_DESCR") == 0: return self._resolve_register(at.attr) # t.XXX 简化形式 if at.value is not None and at.value.kind() == ast.ASTKind.Name: mod_nm2: ast.Name* = ast.Name*(at.value) - if mod_nm2.id is not None and string.strcmp(mod_nm2.id, "t") == 0: - return self._resolve_register(at.attr) + if mod_nm2.id is not None and string.strcmp(mod_nm2.id, "t") == 0: return self._resolve_register(at.attr) # 裸名 ASM_DESCR.XXX:省去 t. 前缀的等价写法 - if mod_nm2.id is not None and string.strcmp(mod_nm2.id, "ASM_DESCR") == 0: - return self._resolve_register(at.attr) + if mod_nm2.id is not None and string.strcmp(mod_nm2.id, "ASM_DESCR") == 0: return self._resolve_register(at.attr) return "" # Constant: 字符串常量 if k == ast.ASTKind.Constant: cn: ast.Constant* = ast.Constant*(node) - if cn.const_kind == ast.CONST_STR: - return cn.str_val + if cn.const_kind == ast.CONST_STR: return cn.str_val return "" return "" @@ -833,28 +768,20 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): - 内联汇编:asminp/asmout ↔ asminp/asmout("AsmInp"/"AsmOut") - LLVM IR:c.LInp/c.LOut ↔ irinp/irout("LInp"/"LOut") """ - if node is None or node.func is None: - return None + if node is None or node.func is None: return None if node.func.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node.func) if nm.id is not None: - if string.strcmp(nm.id, "asminp") == 0: - return "AsmInp" - if string.strcmp(nm.id, "asmout") == 0: - return "AsmOut" - if string.strcmp(nm.id, "irinp") == 0: - return "LInp" - if string.strcmp(nm.id, "irout") == 0: - return "LOut" - return None - if node.func.kind() != ast.ASTKind.Attribute: + if string.strcmp(nm.id, "asminp") == 0: return "AsmInp" + if string.strcmp(nm.id, "asmout") == 0: return "AsmOut" + if string.strcmp(nm.id, "irinp") == 0: return "LInp" + if string.strcmp(nm.id, "irout") == 0: return "LOut" return None + if node.func.kind() != ast.ASTKind.Attribute: return None at: ast.Attribute* = ast.Attribute*(node.func) - if at.value is None or at.value.kind() != ast.ASTKind.Name: - return None + if at.value is None or at.value.kind() != ast.ASTKind.Name: return None mod_nm: ast.Name* = ast.Name*(at.value) - if mod_nm.id is None or string.strcmp(mod_nm.id, "c") != 0: - return None + if mod_nm.id is None or string.strcmp(mod_nm.id, "c") != 0: return None return at.attr @@ -866,17 +793,13 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): 判定走唯一真源 GenApi.sha1_prefix_len(C10 收敛:不再接受大写 hex, 也不再扫描任意位置的 '.' 后回看 16 字节,避免 "a.b..." 形态误判)。 """ - if name is None: - return 0 + if name is None: return 0 n: str = name nlen: sizet = string.strlen(n) # 去掉 '@"..."' 包装(引用名) - if nlen >= 3 and n[0] == '@' and n[1] == '"' and n[nlen - 1] == '"': - n = n + 2 - elif nlen >= 1 and n[0] == '@': - n = n + 1 - if GenApi.sha1_prefix_len(n) != 0: - return 1 + if nlen >= 3 and n[0] == '@' and n[1] == '"' and n[nlen - 1] == '"': n = n + 2 + elif nlen >= 1 and n[0] == '@': n = n + 1 + if GenApi.sha1_prefix_len(n) != 0: return 1 return 0 @@ -892,19 +815,16 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): out=[AsmOut(v)])),同一 (Value, IsOutput) 只保留第一个, 避免约束数多于 asm 返回元素数(llc: output constraints mismatch)。 """ - if count >= ASM_MAX_OPERANDS: - return count + if count >= ASM_MAX_OPERANDS: return count # fail-fast:AsmInp/AsmOut 操作数不允许带 SHA1 混淆头的符号 # (模块级全局/函数)。LLVM MC 内联汇编无法解析数字开头的符号名, # 且裸机链接要求裸名 —— 必须将对应定义标记为 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__ 操作数(AsmInp/AsmOut)不允许带 SHA1 混淆头的符号 '{val.Name}',请将对应函数/全局定义标记为 t.CExport(裸名)", "TypeError") if val is not None: for ei in range(count): eop: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, ei) - if eop is not None and eop.Value == val and eop.IsOutput == is_output: - return count + if eop is not None and eop.Value == val and eop.IsOutput == is_output: return count op: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, count) op.Value = val # 缺省约束:AsmInp(reg) 只传 1 参无 descr → 约束空 → llc @@ -913,10 +833,8 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # 输入默认 "r"(通用寄存器)、输出默认 "=r"(寄存器输出), # 与 _resolve_register 的 REG_ANY/OUTPUT_REG 一致。 if constraint is None or string.strlen(constraint) == 0: - if is_output != 0: - constraint = "=r" - else: - constraint = "r" + if is_output != 0: constraint = "=r" + else: constraint = "r" op.Constraint = constraint op.IsOutput = is_output return count + 1 @@ -928,18 +846,15 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): cl: ast.Call*, trans: HT.Translator* = None) -> mlirlite.Value*: """翻译 __asm__ 内联汇编,返回结果 Value(无输出时返回 None)""" - if cl is None: - return None + if cl is None: return None cargs: list[ast.AST*]* = cl.args - if cargs is None or len(cargs) < 1: - return None + if cargs is None or len(cargs) < 1: return None # 分配操作数数组 operand_size: sizet = GenTypes.AsmOperand.__sizeof__() operands: rawptr[GenTypes.AsmOperand] = pool.alloc(operand_size * ASM_MAX_OPERANDS) - if operands is None: - return None + if operands is None: return None string.memset(operands, 0, operand_size * ASM_MAX_OPERANDS) # 分配 clobber 名数组(每槽 8 字节存字符串指针;容量=ASM_MAX_CLOBBERS, @@ -953,14 +868,12 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # 此前声明成 str*(=i8**) 与 alloc/memset 层数不符,隐式指针转换 # 禁止"层数不同",首行即报错。 clobbers: t.CPtr = pool.alloc(8 * ASM_MAX_CLOBBERS) - if clobbers is None: - return None + if clobbers is None: return None string.memset(clobbers, 0, 8 * ASM_MAX_CLOBBERS) # 分配 asm 文本缓冲区 asm_text: str = pool.alloc(ASM_TEXT_BUF_SIZE) - if asm_text is None: - return None + if asm_text is None: return None asm_text[0] = '\0' operand_count: int = 0 @@ -974,13 +887,11 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # 同样在收集时直接从 alloca 取 Pointee,绕开 AsmOperand 槽读不稳定。 out_ptys: sizet* = pool.alloc(8 * ASM_MAX_OPERANDS) out_pty_n: int = 0 - if out_ptys is not None: - string.memset(out_ptys, 0, 8 * ASM_MAX_OPERANDS) + if out_ptys is not None: string.memset(out_ptys, 0, 8 * ASM_MAX_OPERANDS) # 分配 fv 索引数组(记录每个 FormattedValue 对应的操作数原始索引) fv_orig_indices: int* = pool.alloc(4 * ASM_MAX_OPERANDS) - if fv_orig_indices is None: - return None + if fv_orig_indices is None: return None string.memset(fv_orig_indices, 0, 4 * ASM_MAX_OPERANDS) # ============================================================ @@ -998,47 +909,37 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): jvlen: sizet = len(jvalues) for vi in range(jvlen): part: ast.AST* = jvalues.get(vi) - if part is None: - continue + if part is None: continue pk: int = part.kind() if pk == ast.ASTKind.FormattedValue: fv: rawptr[ast.FormattedValue] = rawptr[ast.FormattedValue](part) fexpr: ast.AST* = fv.value - if fexpr is None or fexpr.kind() != ast.ASTKind.Call: - continue + if fexpr is None or fexpr.kind() != ast.ASTKind.Call: continue fcall: ast.Call* = ast.Call*(fexpr) attr_nm: str = self._asm_is_c_call(fcall) - if attr_nm is None: - continue + if attr_nm is None: continue is_out: int = 0 - if string.strcmp(attr_nm, "AsmOut") == 0: - is_out = 1 - elif string.strcmp(attr_nm, "AsmInp") == 0: - is_out = 0 - else: - continue + if string.strcmp(attr_nm, "AsmOut") == 0: is_out = 1 + elif string.strcmp(attr_nm, "AsmInp") == 0: is_out = 0 + else: continue fargs: list[ast.AST*]* = fcall.args - if fargs is None or len(fargs) < 1: - continue + if fargs is None or len(fargs) < 1: continue val_node: ast.AST* = fargs.get(0) cons_str: str = "" - if len(fargs) >= 2: - cons_str = self._resolve_asm_descr(pool, fargs.get(1)) + if len(fargs) >= 2: cons_str = self._resolve_asm_descr(pool, fargs.get(1)) if is_out != 0: # 输出:获取变量 alloca(Name 局部/全局 或 # Attribute 字段地址) - if val_node is None: - continue + if val_node is None: continue alloca: mlirlite.Value* = None if val_node.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(val_node) - if nm.id is None: - continue + if nm.id is None: continue alloca = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id) if alloca is None: # 模块级全局变量(process.vp _saved_cr3 来自 @@ -1051,8 +952,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # .Ty 读到 Name),必须按 c.Addr(模块全局) 分支的同一写法构造 # 带引号的 Ptr(Ty) 引用(见 L309 注释)。 gv_asm: mlirlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(mod, nm.id) - if gv_asm is not None and gv_asm.Name is not None and gv_asm.Ty is not None: - alloca = self.Gen.ExprGenAttr.make_global_ref(pool, gv_asm.Name, gv_asm.Ty) + if gv_asm is not None and gv_asm.Name is not None and gv_asm.Ty is not None: alloca = self.Gen.ExprGenAttr.make_global_ref(pool, gv_asm.Name, gv_asm.Ty) elif val_node.kind() == ast.ASTKind.Attribute: # AsmOut(p.pml4_root)(p 为 Process 指针): # GEP 到字段地址(对齐 translate_c_addr Attribute @@ -1080,23 +980,18 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): fe_a: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(struct_ty_a, at_a.attr) if fe_a is not None: obj_ptr_a: mlirlite.Value* = base_alloca_a - if self_is_ptr_ptr_a == 1: - obj_ptr_a = mlirlite.build_load(builder, mlirlite.Ptr(pool, struct_ty_a), base_alloca_a) - if obj_ptr_a is not None: - alloca = mlirlite.build_gep_struct(builder, struct_ty_a, fe_a.Ty, obj_ptr_a, fe_a.Index) - if alloca is None: - continue + if self_is_ptr_ptr_a == 1: obj_ptr_a = mlirlite.build_load(builder, mlirlite.Ptr(pool, struct_ty_a), base_alloca_a) + if obj_ptr_a is not None: alloca = mlirlite.build_gep_struct(builder, struct_ty_a, fe_a.Ty, obj_ptr_a, fe_a.Index) + if alloca is None: continue operand_count = self._asm_add_operand(operands, operand_count, alloca, cons_str, 1) - if out_ret_ty_first is None and alloca is not None and alloca.Ty is not None and alloca.Ty.Pointee != 0: - out_ret_ty_first = alloca.Ty.Pointee + if out_ret_ty_first is None and alloca is not None and alloca.Ty is not None and alloca.Ty.Pointee != 0: out_ret_ty_first = alloca.Ty.Pointee if out_ptys is not None and out_pty_n < ASM_MAX_OPERANDS and alloca is not None and alloca.Ty is not None and alloca.Ty.Pointee != 0: out_ptys[out_pty_n] = uint64(alloca.Ty.Pointee) out_pty_n += 1 else: # 输入:翻译值 ival: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, val_node, None, 0, trans) - if ival is None: - continue + if ival is None: continue operand_count = self._asm_add_operand(operands, operand_count, ival, cons_str, 0) # 记录 fv 的原始操作数索引 @@ -1112,8 +1007,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): kwlen: sizet = len(keywords) for ki in range(kwlen): kw: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(ki)) - if kw is None or kw.arg is None or kw.value is None: - continue + if kw is None or kw.arg is None or kw.value is None: continue kwk: int = kw.value.kind() if string.strcmp(kw.arg, "out") == 0: @@ -1133,16 +1027,14 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if oargs is None or len(oargs) < 1: continue oval_node: ast.AST* = oargs.get(0) ocons: str = "" - if len(oargs) >= 2: - ocons = self._resolve_asm_descr(pool, oargs.get(1)) + if len(oargs) >= 2: ocons = self._resolve_asm_descr(pool, oargs.get(1)) if oval_node is None or oval_node.kind() != ast.ASTKind.Name: continue onm: ast.Name* = ast.Name*(oval_node) if onm.id is None: continue oalloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, onm.id) if oalloca is None: continue operand_count = self._asm_add_operand(operands, operand_count, oalloca, ocons, 1) - if out_ret_ty_first is None and oalloca is not None and oalloca.Ty is not None and oalloca.Ty.Pointee != 0: - out_ret_ty_first = oalloca.Ty.Pointee + if out_ret_ty_first is None and oalloca is not None and oalloca.Ty is not None and oalloca.Ty.Pointee != 0: out_ret_ty_first = oalloca.Ty.Pointee if out_ptys is not None and out_pty_n < ASM_MAX_OPERANDS and oalloca is not None and oalloca.Ty is not None and oalloca.Ty.Pointee != 0: out_ptys[out_pty_n] = uint64(oalloca.Ty.Pointee) out_pty_n += 1 @@ -1164,8 +1056,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if iargs is None or len(iargs) < 1: continue ival_node: ast.AST* = iargs.get(0) icons: str = "" - if len(iargs) >= 2: - icons = self._resolve_asm_descr(pool, iargs.get(1)) + if len(iargs) >= 2: icons = self._resolve_asm_descr(pool, iargs.get(1)) ival2: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, ival_node, None, 0, trans) if ival2 is None: continue operand_count = self._asm_add_operand(operands, operand_count, ival2, icons, 0) @@ -1218,11 +1109,9 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): for oi2 in range(operand_count): op2: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, oi2) if op2.IsOutput != 0: - if first_output_idx < 0: - first_output_idx = oi2 + if first_output_idx < 0: first_output_idx = oi2 output_count += 1 - else: - input_count += 1 + else: input_count += 1 # 确定返回类型 # 多输出(如 vrandom rdrand*_step 的 val+ok 两个 AsmOut)返回 @@ -1241,27 +1130,20 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): out_seq: int = 0 for oi5 in range(operand_count): op5: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, oi5) - if op5 is None or op5.IsOutput == 0: - continue + if op5 is None or op5.IsOutput == 0: continue pty5: mlirlite.LLVMType* = None # 优先收集时按序缓存的直接类型,再回退从槽读回 - if out_ptys is not None and out_seq < out_pty_n: - pty5 = mlirlite.LLVMType*(out_ptys[out_seq]) - elif op5.Value is not None and op5.Value.Ty is not None and op5.Value.Ty.Pointee != 0: - pty5 = op5.Value.Ty.Pointee + if out_ptys is not None and out_seq < out_pty_n: pty5 = mlirlite.LLVMType*(out_ptys[out_seq]) + elif op5.Value is not None and op5.Value.Ty is not None and op5.Value.Ty.Pointee != 0: pty5 = op5.Value.Ty.Pointee out_seq += 1 - if pty5 is None: - continue + if pty5 is None: continue pn5: mlirlite.ParamNode* = mlirlite.new_param_node(pool, pty5) if pn5 is not None: - if out_pn_head is None: - out_pn_head = pn5 - else: - out_pn_last.Next = pn5 + if out_pn_head is None: out_pn_head = pn5 + else: out_pn_last.Next = pn5 out_pn_last = pn5 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) + 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") ret_ty = mlirlite.Int32(pool) @@ -1269,20 +1151,16 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): out_op: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, first_output_idx) out_pt: mlirlite.LLVMType* = None # 优先用收集时缓存的元素类型(对齐 python 参考),再回退从槽读回 - if out_ret_ty_first is not None: - out_pt = out_ret_ty_first - 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 + if out_ret_ty_first is not None: out_pt = out_ret_ty_first + 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") ret_ty = mlirlite.Int32(pool) # 判断 void — 直接基于 output_count 判断,避免 match 类型匹配问题 is_void: int = 1 - if output_count > 0: - is_void = 0 + if output_count > 0: is_void = 0 # [FIX] 有输出但 ret 仍是 Void:选择阶段(L1394 读 first_output_idx) # 偶发读不到输出操作数 Value/类型(静默留 Void → 发射带名 void asm → @@ -1299,8 +1177,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__ 输出操作数类型缺失(变量 alloca 类型退化)", "TypeError") ret_ty = ret_re case _: pass @@ -1313,8 +1190,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # ============================================================ new_order: int* = pool.alloc(4 * (operand_count + 1)) orig_to_new: int* = pool.alloc(4 * (operand_count + 1)) - if new_order is None or orig_to_new is None: - return None + if new_order is None or orig_to_new is None: return None new_idx: int = 0 # 先放输出 @@ -1330,8 +1206,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): new_order[new_idx] = oi4 new_idx += 1 # 建立映射 orig -> new - for ni2 in range(operand_count): - orig_to_new[new_order[ni2]] = ni2 + for ni2 in range(operand_count): orig_to_new[new_order[ni2]] = ni2 # ============================================================ # 4.6 生成汇编文本(第二遍遍历 f-string,用重排后的索引生成占位符) @@ -1347,13 +1222,11 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): fv_fi: int = 0 for vi2 in range(jvlen2): part2: ast.AST* = jvalues2.get(vi2) - if part2 is None: - continue + if part2 is None: continue pk2: int = part2.kind() if pk2 == ast.ASTKind.Constant: cn3: ast.Constant* = ast.Constant*(part2) - if cn3.const_kind == ast.CONST_STR and cn3.str_val is not None: - self._asm_append_cstr(asm_text, ASM_TEXT_BUF_SIZE, cn3.str_val) + if cn3.const_kind == ast.CONST_STR and cn3.str_val is not None: self._asm_append_cstr(asm_text, ASM_TEXT_BUF_SIZE, cn3.str_val) elif pk2 == ast.ASTKind.FormattedValue: if fv_fi < fv_count: orig_idx2: int = fv_orig_indices[fv_fi] @@ -1365,15 +1238,13 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): fv_fi += 1 elif tk2 == ast.ASTKind.Constant: cn4: ast.Constant* = ast.Constant*(tmpl_node) - if cn4.const_kind == ast.CONST_STR and cn4.str_val is not None: - self._asm_append_cstr(asm_text, ASM_TEXT_BUF_SIZE, cn4.str_val) + if cn4.const_kind == ast.CONST_STR and cn4.str_val is not None: self._asm_append_cstr(asm_text, ASM_TEXT_BUF_SIZE, cn4.str_val) # ============================================================ # 5. 构建约束字符串(按重排后的顺序:输出在前,输入在后) # ============================================================ const_buf: str = pool.alloc(ASM_CONST_BUF_SIZE) - if const_buf is None: - return None + if const_buf is None: return None const_buf[0] = '\0' first_const: int = 1 @@ -1381,29 +1252,23 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): orig_i: int = new_order[ci2] cop: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, orig_i) cons_val: str = cop.Constraint - if cons_val is None: - cons_val = "r" + if cons_val is None: cons_val = "r" - if first_const == 0: - self._asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, ",") + if first_const == 0: self._asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, ",") first_const = 0 if cop.IsOutput != 0: # 输出约束:确保以 = 开头 - if cons_val[0] != '=': - self._asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, "=") - self._asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, cons_val) - else: + if cons_val[0] != '=': self._asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, "=") self._asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, cons_val) + else: self._asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, cons_val) # 追加 clobber 约束 ~{name} for cidx in range(clobber_count): cl_addr2: uint64 = uint64(clobbers) + cidx * 8 cname: str = (str*)(cl_addr2)[0] - if cname is None or cname[0] == '\0': - continue - if first_const == 0: - self._asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, ",") + if cname is None or cname[0] == '\0': continue + if first_const == 0: self._asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, ",") first_const = 0 self._asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, "~{") self._asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, cname) @@ -1416,8 +1281,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # + 值名;固定 ASM_ARGS_BUF_SIZE(512) 只够一个短类型,须按操作数个数给足。 asm_arg_cap: sizet = sizet(operand_count + 1) * 544 + 64 args_buf: str = pool.alloc(asm_arg_cap) - if args_buf is None: - return None + if args_buf is None: return None args_buf[0] = '\0' first_arg: int = 1 @@ -1428,8 +1292,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): aval: mlirlite.Value* = aop.Value if aval is None or aval.Ty is None or aval.Name is None: continue - if first_arg == 0: - self._asm_append_cstr(args_buf, asm_arg_cap, ", ") + if first_arg == 0: self._asm_append_cstr(args_buf, asm_arg_cap, ", ") first_arg = 0 # 类型文本 @@ -1445,8 +1308,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # 7. 转义汇编文本 # 7.0 先做裸符号→混淆名替换(lea rax, [rip + gdt] → [rip + 054f5e56cbefcaa4.gdt]) mangled_asm: str = self._asm_mangle_global_symbols(pool, asm_text, ASM_TEXT_BUF_SIZE, mod) - if mangled_asm is None: - mangled_asm = asm_text + if mangled_asm is None: mangled_asm = asm_text escaped_asm: str = self._asm_escape_for_ir(pool, mangled_asm) if escaped_asm is None: return None @@ -1470,10 +1332,8 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # 行缓冲按实际内容长度分配(类型文本可达 512 字节,汇编文本/约束也可能很长) line_cap: sizet = 512 + string.strlen(escaped_asm) + string.strlen(args_buf) - if const_buf is not None: - line_cap += string.strlen(const_buf) - if ret_ty_buf is not None: - line_cap += string.strlen(ret_ty_buf) + if const_buf is not None: line_cap += string.strlen(const_buf) + if ret_ty_buf is not None: line_cap += string.strlen(ret_ty_buf) line: str = pool.alloc(line_cap) if line is None: return None @@ -1496,8 +1356,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): for oi_out in range(operand_count): orig_o: int = new_order[oi_out] oo: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, orig_o) - if oo is None or oo.IsOutput == 0: - continue + if oo is None or oo.IsOutput == 0: continue if output_count > 1: # 多输出:extractvalue 取第 out_emit_idx 个元素后 store if oo.Value is not None and oo.Value.Ty is not None and oo.Value.Ty.Pointee != 0: @@ -1515,8 +1374,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): ev_val: mlirlite.Value* = mlirlite.SSAValue(pool, oo.Value.Ty.Pointee, ev_name) mlirlite.build_store(builder, ev_val, oo.Value) else: - if oo.Value is not None: - mlirlite.build_store(builder, result_val, oo.Value) + if oo.Value is not None: mlirlite.build_store(builder, result_val, oo.Value) out_emit_idx += 1 return result_val @@ -1534,34 +1392,29 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): 嵌入当前基本块。c.LOut 变量由唯一 SSA 寄存器 %llvmirN 接收结果, 嵌入后自动追加 store 写回变量 alloca。返回 None(无返回值)。 """ - if cl is None or builder is None or pool is None or trans is None: - return None + 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 缺少模板参数", "TypeError") # LOut 写回记录(alloca 指针 + 寄存器名),最多 LLVMIR_MAX_OPS 个 out_alloca: sizet* = pool.alloc(8 * LLVMIR_MAX_OPS) out_regname: sizet* = pool.alloc(8 * LLVMIR_MAX_OPS) - if out_alloca is None or out_regname is None: - return None + if out_alloca is None or out_regname is None: return None string.memset(out_alloca, 0, 8 * LLVMIR_MAX_OPS) string.memset(out_regname, 0, 8 * LLVMIR_MAX_OPS) out_count: int = 0 # 模板文本缓冲区 text: str = pool.alloc(LLVMIR_TEMPLATE_BUF) - if text is None: - return None + if text is None: return None text[0] = '\0' # ============================================================ # 1. 解析 IR 模板(JoinedStr 或 Constant)— 替换 LInp/LOut/表达式为值文本 # ============================================================ first_arg: ast.AST* = cargs.get(0) - if first_arg is None: - return None + if first_arg is None: return None tk: int = first_arg.kind() @@ -1572,36 +1425,31 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): jvlen: sizet = len(jvalues) for vi in range(jvlen): part: ast.AST* = jvalues.get(vi) - if part is None: - continue + if part is None: continue pk: int = part.kind() if pk == ast.ASTKind.Constant: # 字符串字面量片段 cn: ast.Constant* = ast.Constant*(part) - if cn.str_val is not None: - self._asm_append_cstr(text, LLVMIR_TEMPLATE_BUF, cn.str_val) + if cn.str_val is not None: self._asm_append_cstr(text, LLVMIR_TEMPLATE_BUF, cn.str_val) elif pk == ast.ASTKind.FormattedValue: fv: rawptr[ast.FormattedValue] = rawptr[ast.FormattedValue](part) fexpr: ast.AST* = fv.value - if fexpr is None: - continue + if fexpr is None: continue # 检测 c.LInp / c.LOut if fexpr.kind() == ast.ASTKind.Call: fcall: ast.Call* = ast.Call*(fexpr) attr_nm: str = self._asm_is_c_call(fcall) if attr_nm is not None: fargs: list[ast.AST*]* = fcall.args - if fargs is None or len(fargs) < 1: - continue + if fargs is None or len(fargs) < 1: continue val_node: ast.AST* = fargs.get(0) if string.strcmp(attr_nm, "LInp") == 0: # 输入操作数:翻译值,替换为 LLVM 值引用文本(%x 或常量文本) inp_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, val_node, None, 0, trans) - if inp_val is not None and inp_val.Name is not None: - self._asm_append_cstr(text, LLVMIR_TEMPLATE_BUF, inp_val.Name) + if inp_val is not None and inp_val.Name is not None: self._asm_append_cstr(text, LLVMIR_TEMPLATE_BUF, inp_val.Name) elif string.strcmp(attr_nm, "LOut") == 0: # 输出操作数:为变量分配唯一 SSA 寄存器 %llvmirN, @@ -1610,8 +1458,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 变量 '{nm.id}' 未定义或输出数超过 {LLVMIR_MAX_OPS}", "TypeError") self.Gen.CallGenBase.LLVMIRRegSeq += 1 reg_buf: str = pool.alloc(32) if reg_buf is not None: @@ -1623,8 +1470,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): continue # 非 c.LInp/c.LOut 的 f-string 表达式:翻译值并嵌入值文本 ival: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fexpr, None, 0, trans) - if ival is not None and ival.Name is not None: - self._asm_append_cstr(text, LLVMIR_TEMPLATE_BUF, ival.Name) + if ival is not None and ival.Name is not None: self._asm_append_cstr(text, LLVMIR_TEMPLATE_BUF, ival.Name) elif tk == ast.ASTKind.Constant: cn2: ast.Constant* = ast.Constant*(first_arg) @@ -1643,11 +1489,9 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): for oi in range(out_count): oa: mlirlite.Value* = mlirlite.Value*(out_alloca[oi]) rn: str = str(out_regname[oi]) - if oa is None or oa.Ty is None or oa.Ty.Pointee == 0 or rn is None: - continue + if oa is None or oa.Ty is None or oa.Ty.Pointee == 0 or rn is None: continue reg_val: mlirlite.Value* = mlirlite.new_value(pool) - if reg_val is None: - continue + if reg_val is None: continue reg_val.Ty = oa.Ty.Pointee reg_val.Name = rn reg_val.IsConst = 0 diff --git a/App/lib/core/Gen/Call/CallGenCall.vp b/App/lib/core/Gen/Call/CallGenCall.vp index 55224a5..1f75b6c 100644 --- a/App/lib/core/Gen/Call/CallGenCall.vp +++ b/App/lib/core/Gen/Call/CallGenCall.vp @@ -58,8 +58,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): """ if pool is None or builder is None or class_name is None or method_name is None: return None if self_ptr is None or args_head is None: return None - if vtable_base is None: - vtable_base = self_ptr + if vtable_base is None: vtable_base = self_ptr # 1. 获取结构体类型(用 find_struct_by_type 规避跨模块同名 find_struct 找错) # 必须用 vtable_base(对象头)的类型而非 self_ptr:多继承 this 调整后 @@ -79,15 +78,13 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if vb_ty is not None: # vb_ty 是 struct_ty(LLVMType),需要找 StructEntry vc_entry = self.Gen.StructGen.find_struct_by_type(vb_ty) - if vc_entry is not None: - struct_ty = vc_entry.Ty + if vc_entry is not None: struct_ty = vc_entry.Ty if struct_ty is None and self_ptr is not None and self_ptr.Ty is not None: # fallback:vtable_base 无类型信息时退回 self_ptr(未调整场景两者一致) sp_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(self_ptr) if sp_ty is not None: vc_entry = self.Gen.StructGen.find_struct_by_type(sp_ty) - if vc_entry is not None: - struct_ty = vc_entry.Ty + if vc_entry is not None: struct_ty = vc_entry.Ty if struct_ty is None: struct_ty = self.Gen.StructGen.get_struct_type(class_name) if struct_ty is None: return None @@ -103,8 +100,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if mname is not None and string.strcmp(mname, method_name) == 0: method_index = mi break - else: - method_index = self.Gen.StructGen.get_vtable_method_index(class_name, method_name) + else: method_index = self.Gen.StructGen.get_vtable_method_index(class_name, method_name) if method_index < 0: return None # 3. 基础类型 @@ -126,10 +122,8 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # 6. 构造 vtable 类型 {i8*, i8*, ...} method_count: int = 0 - if vc_entry is not None: - method_count = vc_entry.VTableMethodCount - else: - method_count = self.Gen.StructGen.get_vtable_method_count(class_name) + if vc_entry is not None: method_count = vc_entry.VTableMethodCount + else: method_count = self.Gen.StructGen.get_vtable_method_count(class_name) if method_count <= 0: return None # 字段链表节点是 mlirlite.ParamNode(new_param_node 返回 rawptr[ParamNode], @@ -140,10 +134,8 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): for vi in range(method_count): pn: mlirlite.ParamNode* = mlirlite.new_param_node(pool, i8_ptr_ty) if pn is None: continue - if vt_first is None: - vt_first = pn - if vt_prev is not None: - mlirlite.paramnode_set_next(vt_prev, pn) + if vt_first is None: vt_first = pn + if vt_prev is not None: mlirlite.paramnode_set_next(vt_prev, pn) vt_prev = pn vtable_ty: mlirlite.LLVMType* = mlirlite.Struct(pool, vt_first, method_count, None) @@ -156,13 +148,11 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # 8. GEP 到方法槽位 func_slot: mlirlite.Value* = mlirlite.build_gep_struct(builder, vtable_ty, i8_ptr_ty, vtable_typed, method_index) - if func_slot is None: - return None + if func_slot is None: return None # 9. load 函数指针 (i8*) func_i8: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, func_slot) - if func_i8 is None: - return None + if func_i8 is None: return None # 10. 从 args_head 构造函数类型 RetTy(Param1, Param2, ...) # 直接遍历 Value 链表提取参数类型,避免跨模块访问 found_func(stub 字段偏移问题) @@ -173,28 +163,23 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): fp_count: int = 0 cur_val: mlirlite.Value* = args_head for vi in range(args_count): - if cur_val is None: - break + if cur_val is None: break cur_ty: mlirlite.LLVMType* = mlirlite.value_get_ty(cur_val) fpn: mlirlite.ParamNode* = mlirlite.new_param_node(pool, cur_ty) if fpn is not None: - if fp_first is None: - fp_first = fpn - if fp_prev is not None: - mlirlite.paramnode_set_next(fp_prev, fpn) + if fp_first is None: fp_first = fpn + if fp_prev is not None: mlirlite.paramnode_set_next(fp_prev, fpn) fp_prev = fpn cur_val = mlirlite.value_get_next(cur_val) fp_count += 1 func_ty: mlirlite.LLVMType* = mlirlite.Func(pool, ret_ty, fp_first, fp_count) - if func_ty is None: - return None + if func_ty is None: return None func_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, func_ty) # 11. bitcast i8* 到函数指针类型 func_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, func_i8, func_ptr_ty) - if func_ptr is None: - return None + if func_ptr is None: return None # 12. 间接调用 return mlirlite.build_call_indirect(builder, func_ptr, args_head, args_count, ret_ty) @@ -225,28 +210,22 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): 的 call 指令没有 volatile 限定符,故仅对构造三方法(__new__/ __before_init__/__init__)在调用后追加一次 volatile 内存屏障, 使被调函数内部对对象内存的写入不可被优化器消除/跨越。""" - if pool is None or builder is None or class_name is None or method_name is None: - return None - if self_ptr is None: - return None + if pool is None or builder is None or class_name is None or method_name is None: return None + if self_ptr is None: return None # 提前获取结构体 entry(用 find_struct_by_type 规避跨模块同名 find_struct 找错) # 用于 SHA1 查找和虚表分派 cmop_entry: GenTypes.StructEntry* = None cmop_struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(self_ptr) - if cmop_struct_ty is not None: - cmop_entry = self.Gen.StructGen.find_struct_by_type(cmop_struct_ty) - if cmop_entry is None: - cmop_entry = self.Gen.StructGen.find_struct(class_name) + if cmop_struct_ty is not None: cmop_entry = self.Gen.StructGen.find_struct_by_type(cmop_struct_ty) + if cmop_entry is None: cmop_entry = self.Gen.StructGen.find_struct(class_name) # fallback: 若 cmop_struct_ty 为 None 但 entry 存在,从 entry 获取类型 # 用于跨模块调用时 self_ptr 类型信息丢失的情况 - if cmop_struct_ty is None and cmop_entry is not None: - cmop_struct_ty = cmop_entry.Ty + if cmop_struct_ty is None and cmop_entry is not None: cmop_struct_ty = cmop_entry.Ty # 构造方法查找名: ClassName.method_name lookup_name: str = pool.alloc(128) - if lookup_name is None: - return None + if lookup_name is None: return None viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, method_name) # 查找函数(支持 SHA1 后缀匹配) @@ -256,16 +235,13 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): call_name: str = lookup_name if found_func is not None: found_name: str = mlirlite.function_get_name(found_func) - if found_name is not None: - call_name = found_name + if found_name is not None: call_name = found_name else: # found_func 为 None(stub 未注入):用类所属模块的 SHA1 构造调用名 # 优先从 entry 获取 SHA1(规避跨模块同名 find_struct 找错) cls_sha1: str = None - if cmop_entry is not None: - cls_sha1 = cmop_entry.ModuleSha1 - else: - cls_sha1 = self.Gen.StructGen.get_struct_sha1(class_name) + if cmop_entry is not None: cls_sha1 = cmop_entry.ModuleSha1 + else: cls_sha1 = self.Gen.StructGen.get_struct_sha1(class_name) if cls_sha1 is None and trans is not None: # fallback: 从 from_imports 查找类所属模块的 SHA1(含截断处理) cls_sha1 = self._lookup_mod_sha1(pool, trans._from_imports, class_name) @@ -292,8 +268,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): call_ret_ty: mlirlite.LLVMType* = void_ty if found_func is not None: frt: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(found_func) - if frt is not None: - call_ret_ty = frt + if frt is not None: call_ret_ty = frt elif string.strcmp(method_name, "__getitem__") == 0 or string.strcmp(method_name, "__new__") == 0: # fail-fast:__getitem__/__new__ 必返回指针,返回类型缺失意味着 # stub declare 损坏,静默推断会截断指针(32 位)崩溃,立即终止。 @@ -312,8 +287,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # 否则走 text.ll/vpi 解析失败 → fail-fast 误报 # (CPythonTest PyLongObj() 构造:类未定义 __init__/__before_init__ # 但实例化仍生成调用 → "PyLongObj.__before_init__ 返回类型无法确定"根因)。 - if string.strcmp(method_name, "__before_init__") == 0 or string.strcmp(method_name, "__init__") == 0: - call_ret_ty = void_ty + if string.strcmp(method_name, "__before_init__") == 0 or string.strcmp(method_name, "__init__") == 0: call_ret_ty = void_ty # __new__ 返回 Ptr(struct_ty)(构造函数返回自身指针,可推断)。 # __getitem__ 返回类型无法从 self 推断(可返回 i8* 如 HashTable.__getitem__ # -> t.CPtr,或 Ptr(JsonValue) 如 JsonValue.__getitem__)——推断 Ptr(cmop_struct_ty) @@ -321,8 +295,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # fail-fast:__getitem__ 无 stub declare 立即报错,暴露依赖模块 vpi 缺失或 # 拓扑顺序错误(依赖模块未先翻译生成 vpi/text.ll)。 elif string.strcmp(method_name, "__new__") == 0: - if cmop_struct_ty is not None: - call_ret_ty = mlirlite.Ptr(pool, cmop_struct_ty) + if cmop_struct_ty is not None: call_ret_ty = mlirlite.Ptr(pool, cmop_struct_ty) else: # [D6·截断纪律] 固定 256 → 精确长度(-2 = 一个 "%s") msg_fmt2: str = "方法 '%s' 的 self 结构体类型未知(字段类型退化,依赖模块未预注册?)" @@ -362,14 +335,10 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): local_fn_cm2: mlirlite.Function* = self.find_func_in_module(mod, local_lk_cm2) if local_fn_cm2 is not None: lrt_cm2: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(local_fn_cm2) - if lrt_cm2 is not None: - ret_cm = lrt_cm2 - if cls_sha1 is not None: - ret_cm = self._lookup_method_ret_ty_via_vpi(pool, cls_sha1, class_name, method_name) - if ret_cm is None and cls_sha1 is not None: - ret_cm = self._LookupMethodRetTyFromTextLL(pool, cls_sha1, class_name, method_name) - if ret_cm is not None: - call_ret_ty = ret_cm + if lrt_cm2 is not None: ret_cm = lrt_cm2 + if cls_sha1 is not None: ret_cm = self._lookup_method_ret_ty_via_vpi(pool, cls_sha1, class_name, method_name) + if ret_cm is None and cls_sha1 is not None: ret_cm = self._LookupMethodRetTyFromTextLL(pool, cls_sha1, class_name, method_name) + if ret_cm is not None: call_ret_ty = ret_cm else: # Phase A 依赖 text.ll 未生成(方法定义模块尚未翻译):保持默认 # 类型继续(本函数同样服务 Mixin 跨模块方法调用,如 BuildPipeline @@ -400,8 +369,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): nn_pn = mlirlite.param_get_next(nn_pn) # nn_pc == 1(只有注入的 self,如 `def __new__() -> 'Vec3' | CPtr`) # 同样要裁:extra_count 归 0,只传 self。 - if nn_pc >= 1 and extra_count > nn_pc - 1: - extra_count = nn_pc - 1 + if nn_pc >= 1 and extra_count > nn_pc - 1: extra_count = nn_pc - 1 # 构建参数链表: self_ptr → extra_args... mlirlite.value_set_next(self_ptr, None) @@ -411,8 +379,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if extra_args is not None and extra_count > 0: for ei in range(extra_count): arg_addr: sizet = extra_args[ei] - if arg_addr == 0: - continue + if arg_addr == 0: continue av: mlirlite.Value* = mlirlite.Value*(arg_addr) if av is not None: mlirlite.value_set_next(av, None) @@ -449,18 +416,15 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): vpi_pa: str = None if mdf_param_count == 0 and found_func is None: vpi_sha1_p: str = None - if cmop_entry is not None and cmop_entry.ModuleSha1 is not None: - vpi_sha1_p = cmop_entry.ModuleSha1 - else: - vpi_sha1_p = self.Gen.StructGen.get_struct_sha1(class_name) + if cmop_entry is not None and cmop_entry.ModuleSha1 is not None: vpi_sha1_p = cmop_entry.ModuleSha1 + else: vpi_sha1_p = self.Gen.StructGen.get_struct_sha1(class_name) if vpi_sha1_p is not None: vpi_pa = self.Gen.CallGenBase._vpi_method_param_annot(pool, vpi_sha1_p, class_name, method_name) if vpi_pa is not None and vpi_pa[0] != '\0': vpi_pc2: int = 1 vi2: sizet = 0 while vpi_pa[vi2] != '\0': - if vpi_pa[vi2] == '@': - vpi_pc2 += 1 + if vpi_pa[vi2] == '@': vpi_pc2 += 1 vi2 += 1 mdf_param_count = vpi_pc2 - 1 # 非 self 参数数 @@ -498,8 +462,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # 用 stdlib 常量快照重建(mdf_gd.Defaults 的 pool 内 AST 可能已被 reset 回收, # 直接回退读 AST 会 use-after-free——快照失败时 fail-fast 暴露,绝不读悬空 AST) 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_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: # 用 node(本函数报错行号节点,如构造实参/源码 Call)而非 cl—— # cl 在本函数未定义(无该参数),读取垃圾指针导致 fatal_error @@ -538,13 +501,11 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): seg_no_v: int = 0 seg_cur_v: sizet = 0 while seg_no_v < seg_idx_v and vpi_pa[seg_cur_v] != '\0': - if vpi_pa[seg_cur_v] == '@': - seg_no_v += 1 + if vpi_pa[seg_cur_v] == '@': seg_no_v += 1 seg_cur_v += 1 seg_start_v: sizet = seg_cur_v seg_len_v: sizet = 0 - while vpi_pa[seg_start_v + seg_len_v] != '\0' and vpi_pa[seg_start_v + seg_len_v] != '@': - seg_len_v += 1 + while vpi_pa[seg_start_v + seg_len_v] != '\0' and vpi_pa[seg_start_v + seg_len_v] != '@': seg_len_v += 1 if seg_no_v == seg_idx_v: pty_v: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) if seg_len_v > 0: @@ -553,8 +514,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): string.strncpy(seg_buf_v, vpi_pa + seg_start_v, seg_len_v) seg_buf_v[seg_len_v] = '\0' rty_v: mlirlite.LLVMType* = self.Gen.CallGenBase._vpi_resolve_param_annot_ty(pool, seg_buf_v) - if rty_v is not None: - pty_v = rty_v + if rty_v is not None: pty_v = rty_v stdlib.free(seg_buf_v) zero_val_v: mlirlite.Value* = mlirlite.ConstZero(pool, pty_v) if zero_val_v is not None: @@ -600,14 +560,11 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): pty_pc: mlirlite.LLVMType* = mlirlite.param_get_ty(pc_param) if pty_pc is not None: c_pc: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, pc_node, pty_pc, None) - if c_pc is not None: - coerced_pc = c_pc + if c_pc is not None: coerced_pc = c_pc pc_param = mlirlite.param_get_next(pc_param) coerced_pc.Next = None - if prev_pc is None: - new_head_pc = coerced_pc - else: - prev_pc.Next = coerced_pc + if prev_pc is None: new_head_pc = coerced_pc + else: prev_pc.Next = coerced_pc prev_pc = coerced_pc pc_node = pc_next_save head = new_head_pc @@ -623,8 +580,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): cmop_methods_arr: sizet* = (sizet*)(cmop_entry.VTableMethods) for cmop_mi in range(cmop_entry.VTableMethodCount): cmop_mname_addr: sizet = cmop_methods_arr[cmop_mi] - if cmop_mname_addr == 0: - continue + if cmop_mname_addr == 0: continue cmop_mname: str = rawptr(cmop_mname_addr) if cmop_mname is not None and string.strcmp(cmop_mname, method_name) == 0: cmop_method_idx = cmop_mi @@ -640,12 +596,10 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): cd_i0: int = 0 match call_ret_ty: case mlirlite.LLVMType.Int(bits): - if bits == 0: - cd_i0 = 1 + if bits == 0: cd_i0 = 1 case _: pass - if cd_i0 != 0: - call_ret_ty = self._fail_method_ret_ty(method_name, node) + if cd_i0 != 0: call_ret_ty = self._fail_method_ret_ty(method_name, node) # 跨模块调用(found_func 为 None):创建 declare 声明,避免 llc 报 undefined value if found_func is None: # 先按定义侧形参 coerce 实参(宽度/指针口径对齐),再建 declare(先例 @@ -672,10 +626,8 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): cmop_i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) cmop_i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, cmop_i8_ty) cmop_bar_ptr: mlirlite.Value* = self_ptr - if uint64(self_ptr.Ty) != uint64(cmop_i8_ptr_ty): - cmop_bar_ptr = mlirlite.build_bitcast(builder, self_ptr, cmop_i8_ptr_ty) - if cmop_bar_ptr is not None: - mlirlite.build_load(builder, cmop_i8_ty, cmop_bar_ptr, 1) + if uint64(self_ptr.Ty) != uint64(cmop_i8_ptr_ty): cmop_bar_ptr = mlirlite.build_bitcast(builder, self_ptr, cmop_i8_ptr_ty) + if cmop_bar_ptr is not None: mlirlite.build_load(builder, cmop_i8_ty, cmop_bar_ptr, 1) return call_res_cmop # ============================================================ # _translate_method_call - 翻译方法调用 obj.method(args) @@ -695,10 +647,8 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): cl: ast.Call*, trans: HT.Translator*) -> mlirlite.Value*: """翻译方法调用,返回 call 结果 Value""" - if pool is None or builder is None or class_name is None or method_name is None: - return None - if obj_ptr is None or cl is None: - return None + if pool is None or builder is None or class_name is None or method_name is None: return None + if obj_ptr is None or cl is None: return None # [修复] list 泛型容器方法兜底拦截:接收者被分派为 list 特化类名(list[...] / {sha1}.list[...])且方法属 list 内置集合时,本调用不存在对应 C 函数,继续走 MRO/函数/text.ll/vpi 解析必然落空 → fatal;直接转交 _translate_list_builtin_call 内联翻译(GEP __data__/__count__/__elem_size__) # [D25 分派修复] class_name 可能因注解在 Handle 阶段退化而为空串,使 list 内建拦截(_is_list_builtin_method)与 D25 泛型基类 fail-fast 双双失效 ⇒ 误绑到无关特化。接收者的**实际 struct 名**比退化注解可靠,用它补全判定来源(提升到分支外声明,D25 fail-fast 同样使用) @@ -707,16 +657,14 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): lb_sty_s: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(obj_ptr) if lb_sty_s is not None: lb_nm_s: str = mlirlite.get_struct_name(lb_sty_s) - if lb_nm_s is not None: - lb_src = lb_nm_s + if lb_nm_s is not None: lb_src = lb_nm_s if method_name is not None and lb_src is not None: lb_cls: str = lb_src # 剥离跨模块特化名 sha1 前缀 "{16hex}."({sha}.list[...] 形态); # 前缀长度判定走唯一真源 GenApi.sha1_prefix_len(C10 收敛)。 lb_pfx_d: int = GenApi.sha1_prefix_len(lb_cls) if string.strncmp(lb_cls, "list", 4) != 0 and lb_pfx_d != 0: - if string.strncmp(lb_cls + lb_pfx_d, "list", 4) == 0: - lb_cls = lb_cls + lb_pfx_d + if string.strncmp(lb_cls + lb_pfx_d, "list", 4) == 0: lb_cls = lb_cls + lb_pfx_d # 触发判据同样以接收者实际类型为准(_is_list_builtin_receiver): # 真实 list 命中不变;非容器不命中;实际类型不可得回退 lb_cls。 if self.Gen.CallGenProp._is_list_builtin_receiver(pool, obj_ptr, lb_cls, method_name, cl) != 0: @@ -737,8 +685,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): if lb_obj is not None: lb_cargs: list[ast.AST*]* = cl.args lb_can: sizet = 0 - if lb_cargs is not None: - lb_can = len(lb_cargs) + if lb_cargs is not None: lb_can = len(lb_cargs) return self._translate_list_builtin_call(pool, builder, mod, cl, method_name, lb_obj, lb_cargs, lb_can, trans) # [D25 fail-fast] 泛型模板**基类**(剥 sha1 前缀后不含 '[',如裸 "list")上的 @@ -766,24 +713,20 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # 用于继承链遍历、SHA1 查找和虚表分派 mc_entry: GenTypes.StructEntry* = None mc_struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(obj_ptr) - if mc_struct_ty is not None: - mc_entry = self.Gen.StructGen.find_struct_by_type(mc_struct_ty) - if mc_entry is None: - mc_entry = self.Gen.StructGen.find_struct(class_name) + if mc_struct_ty is not None: mc_entry = self.Gen.StructGen.find_struct_by_type(mc_struct_ty) + if mc_entry is None: mc_entry = self.Gen.StructGen.find_struct(class_name) # [D25 分派根治] 泛型容器接收者以**实际结构体名**为准:obj_ptr 的 LLVM 结构体类型名是 IR 层真值,class_name 可能因同名变量重复声明而退化到无关特化。判定仅作用于泛型容器接收者(普通类名不含方括号,既有路径不受影响) # 共用口径收敛到 CallGenProp._resolve_generic_receiver_name(唯一实现):去 sha1 前缀 → 基名是已注册泛型模板且含 '[' ⇒ 覆盖 class_name;裸泛型基类 ⇒ fail-fast;非泛型模板 ⇒ None mc_act_d: str = self.Gen.CallGenProp._resolve_generic_receiver_name(pool, mc_struct_ty, method_name, cl) - if mc_act_d is not None: - class_name = mc_act_d + if mc_act_d is not None: class_name = mc_act_d # 构造方法查找名: ClassName.method_name # [D6·截断纪律] 缓冲按精确长度分配(class_name 现可能取实际特化名,长度不定): # 固定 128 会在嵌套泛型名(如 list[rawptr[sha.AST]])下静默截断 → 查错/漏查。 lk_cap: sizet = string.strlen(class_name) + string.strlen(method_name) + 2 lookup_name: str = pool.alloc(lk_cap) - if lookup_name is None: - return None + if lookup_name is None: return None viperlib.snprintf(lookup_name, lk_cap, "%s.%s", class_name, method_name) # 查找函数(支持 SHA1 后缀匹配) @@ -834,13 +777,10 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): sib_recv_local: int = 1 if trans is not None and trans.ModuleSha1 is not None: sib_recv_sha1: str = None - if mc_entry is not None and mc_entry.ModuleSha1 is not None: - sib_recv_sha1 = mc_entry.ModuleSha1 - else: - sib_recv_sha1 = self.Gen.StructGen.get_struct_sha1(class_name) + if mc_entry is not None and mc_entry.ModuleSha1 is not None: sib_recv_sha1 = mc_entry.ModuleSha1 + else: sib_recv_sha1 = self.Gen.StructGen.get_struct_sha1(class_name) if sib_recv_sha1 is not None: - if string.strcmp(sib_recv_sha1, trans.ModuleSha1) != 0: - sib_recv_local = 0 + if string.strcmp(sib_recv_sha1, trans.ModuleSha1) != 0: sib_recv_local = 0 if sib_recv_local != 0: if self._recv_is_mixin_base(class_name) != 0: sc_i: int = 0 @@ -868,16 +808,14 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): call_name: str = lookup_name if found_func is not None: found_name: str = mlirlite.function_get_name(found_func) - if found_name is not None: - call_name = found_name + if found_name is not None: call_name = found_name # 确定返回类型 i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) call_ret_ty: mlirlite.LLVMType* = i32_ty if found_func is not None: frt: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(found_func) - if frt is not None: - call_ret_ty = frt + if frt is not None: call_ret_ty = frt else: # found_func 为 None(stub 未注入):先处理编译器内置特殊方法 sp_ty2: mlirlite.LLVMType* = self._special_method_ret_ty(pool, class_name, method_name) @@ -890,10 +828,8 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # {sha1}.Buf.__before_init__。 sp_anc_name: str = class_name sp_anc_sha1: str = None - if mc_entry is not None: - sp_anc_sha1 = mc_entry.ModuleSha1 - else: - sp_anc_sha1 = self.Gen.StructGen.get_struct_sha1(class_name) + if mc_entry is not None: sp_anc_sha1 = mc_entry.ModuleSha1 + else: sp_anc_sha1 = self.Gen.StructGen.get_struct_sha1(class_name) if sp_anc_sha1 is None and mc_struct_ty is not None: match mc_struct_ty: case mlirlite.LLVMType.Struct(_fs_sp, _fc_sp, type_name_sp): @@ -921,18 +857,15 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # 默认 class_name 自身,MRO fallback 命中祖先类时更新 ret_anc_name: str = class_name ret_anc_sha1: str = None - if mc_entry is not None: - ret_anc_sha1 = mc_entry.ModuleSha1 - else: - ret_anc_sha1 = self.Gen.StructGen.get_struct_sha1(class_name) + if mc_entry is not None: ret_anc_sha1 = mc_entry.ModuleSha1 + else: ret_anc_sha1 = self.Gen.StructGen.get_struct_sha1(class_name) if ret_anc_sha1 is None: # 沿 MRO 找第一个有 SHA1 的类 mro_s0: sizet* = self.Gen.StructGen.get_mro_chain(pool, class_name) mi_s0: int = 1 while mro_s0 is not None and mro_s0[mi_s0] != 0 and ret_anc_sha1 is None: anc_s0: str = rawptr(mro_s0[mi_s0]) - if anc_s0 is not None: - ret_anc_sha1 = self.Gen.StructGen.get_struct_sha1(anc_s0) + if anc_s0 is not None: ret_anc_sha1 = self.Gen.StructGen.get_struct_sha1(anc_s0) mi_s0 += 1 # 泛型特化方法调用:特化函数可能尚未注册(如 ast.base 用 @@ -982,8 +915,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # 不再硬编码 17(旧判据 `base_len_g > 17` 与真源 `>= 17` # 只差"前缀之后为空串"这一退化形态,一并对齐)。 base_pfx_g: int = GenApi.sha1_prefix_len(base_buf_g) - if base_pfx_g != 0: - base_clean_g = base_buf_g + sizet(base_pfx_g) + if base_pfx_g != 0: base_clean_g = base_buf_g + sizet(base_pfx_g) spec_name_g: str = self.Gen.ClassGenGeneric._specialize_generic_class(trans, base_clean_g, ta_list_g) if spec_name_g is not None: # 特化后重新查找特化函数(特化名 = 调用点类名)。 @@ -1043,8 +975,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): ret_anc_name = anc_v2 ret_anc_sha1 = anc_sha1_v2 mi_v2 += 1 - if gen_done == 0 and vpi_ret_ty is not None: - call_ret_ty = vpi_ret_ty + if gen_done == 0 and vpi_ret_ty is not None: call_ret_ty = vpi_ret_ty elif gen_done == 0: # 回退:从 text.ll 的 define 行查找实际返回类型 # 避免指针返回值被默认 i32 导致 inttoptr 截断 @@ -1062,8 +993,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): ret_anc_name = anc_t2 ret_anc_sha1 = anc_sha1_t2 mi_t2 += 1 - if looked_up_ty is not None: - call_ret_ty = looked_up_ty + if looked_up_ty is not None: call_ret_ty = looked_up_ty else: # Phase A 依赖 text.ll 未生成(方法定义模块尚未翻译):保持默认 # 类型继续。BuildPipeline.vp L216 gen.extract_module_docstrings @@ -1100,8 +1030,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # 依赖未就绪:保持默认 i32(同上,build_call(Void) 返回 # None 会破坏表达式翻译) call_ret_ty = mlirlite.Int32(pool) - else: - call_ret_ty = self._fail_method_ret_ty(method_name, cl) + else: call_ret_ty = self._fail_method_ret_ty(method_name, cl) # found_func 未命中但返回类型已解析:用方法定义类构造跨模块调用名 # (Module.append → {AST_sha1}.AST.append,避免链接 undefined reference) @@ -1144,12 +1073,10 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # 翻译调用参数 cargs: list[ast.AST*]* = cl.args can: sizet = 0 - if cargs is not None: - can = len(cargs) + if cargs is not None: can = len(cargs) kw_calls: list[ast.AST*]* = cl.keywords kwc: sizet = 0 - if kw_calls is not None: - kwc = len(kw_calls) + if kw_calls is not None: kwc = len(kw_calls) # 多继承 this 调整(字节偏移法,与 TPC HandlesExprCall._adjust_this_for_inherited_method 一致):继承方法体按"定义类自身布局"读 self 字段,父类字段区在子类中字节偏移可能不同,故 delta = 字段在子类中字节偏移 − 字段在父类自身布局中字节偏移;delta==0(第一父类,字段区前缀对齐)无需调整,delta>0 时按字节 GEP 到父类字段区在子类中的等效基址再 bitcast 成父类指针 self_arg: mlirlite.Value* = obj_ptr @@ -1162,8 +1089,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): mro_fp_th: sizet* = self.Gen.StructGen.get_mro_chain(pool, class_name) if mro_fp_th is not None and mro_fp_th[1] != 0: first_parent_th: str = rawptr(mro_fp_th[1]) - if first_parent_th is not None and string.strcmp(first_parent_th, mc_anc) == 0: - is_first_parent_th = 1 + if first_parent_th is not None and string.strcmp(first_parent_th, mc_anc) == 0: is_first_parent_th = 1 anc_entry_th: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(mc_anc) # 无字段父类(FieldCount==0,如多继承中的纯方法类 Vec2Extra): # 继承方法体按"定义类字段"读 self,定义类无字段则方法体不读 @@ -1227,8 +1153,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): self.Gen.TypeGenErr.fatal_error(cl, f"this-adjust 兄弟 Mixin 定义类大小未知: 方法'{method_name}'定义类'{mc_anc}'的 struct 大小计算失败", "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") + elif is_first_parent_th == 0: self.Gen.TypeGenErr.fatal_error(cl, f"this-adjust 子类结构体未注册: 方法'{method_name}'定义类'{mc_anc}',接收类'{class_name}'的 struct 未找到", "InternalCompilerError") else: # 父类仅 __vtable__ 字段(无字段 CVTable 类):方法体不读 # 布局字段,无需调整(对齐 TPC:first_field_name None → ObjVal) @@ -1251,8 +1176,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): pty_self: mlirlite.LLVMType* = mlirlite.param_get_ty(pp_self) if pty_self is not None: cself_tm: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, self_arg, pty_self, None) - if cself_tm is not None: - self_arg = cself_tm + if cself_tm is not None: self_arg = cself_tm # 构建参数链表: self → arg1 → arg2 → ... mlirlite.value_set_next(self_arg, None) head: mlirlite.Value* = self_arg @@ -1269,16 +1193,14 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): pi_k: int = 0 while cur_param_k is not None: arg_node_k: ast.AST* = None - if pi_k < can: - arg_node_k = cargs.get(pi_k) + if pi_k < can: arg_node_k = cargs.get(pi_k) else: pname_k: str = mlirlite.param_get_name(cur_param_k) if pname_k is not None: ki_k: int for ki_k in range(kwc): kw_k: rawptr[ast.Keyword] = rawptr[ast.Keyword](kw_calls.get(ki_k)) - if kw_k is None or kw_k.arg is None or kw_k.value is None: - continue + if kw_k is None or kw_k.arg is None or kw_k.value is None: continue if self._kwarg_name_matches(kw_k.arg, pname_k) == 1: arg_node_k = kw_k.value break @@ -1298,12 +1220,10 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # 参数序列位置(避免后续实参左移错位)。此占位不是"表达式翻译 # 失败"的兜底(那条通路已在上方 fail-fast)。 pty_k: mlirlite.LLVMType* = mlirlite.param_get_ty(cur_param_k) - if pty_k is not None: - arg_val_k = mlirlite.ConstZero(pool, pty_k) + if pty_k is not None: arg_val_k = mlirlite.ConstZero(pool, pty_k) if arg_val_k is not None: pty_k2: mlirlite.LLVMType* = mlirlite.param_get_ty(cur_param_k) - if pty_k2 is not None: - arg_val_k = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val_k, pty_k2, arg_node_k) + if pty_k2 is not None: arg_val_k = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val_k, pty_k2, arg_node_k) mlirlite.value_set_next(arg_val_k, None) mlirlite.value_set_next(tail, arg_val_k) tail = arg_val_k @@ -1328,12 +1248,10 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): pp = mlirlite.function_get_param_head(found_func) pi: int = 0 while pp is not None and pi < ai + 1: - if pi == ai + 1: - break + if pi == ai + 1: break pp = mlirlite.param_get_next(pp) pi += 1 - if pp is not None: - pty = mlirlite.param_get_ty(pp) + if pp is not None: pty = mlirlite.param_get_ty(pp) arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg_node, None, 0, trans, pty) if arg_val is None: # (a) 实参表达式翻译失败(translate_value 返回 None)→ fail-fast。 @@ -1347,8 +1265,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # 修复: CDefine/i32 常量传给 i64 形参(如 MemBuddy.__init__ 的 size: sizet) # 未提升导致 call(i32) 与 define(i64) 不匹配,运行时读到垃圾高 32 位崩溃 if found_func is not None: - if pty is not None: - arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, pty, arg_node) + if pty is not None: arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, pty, arg_node) else: # found_func=None(跨模块 stub 未注入):数组实参按 C 语义 # 衰减为元素指针(对齐 TPC _decay_array_to_ptr)。否则 @@ -1360,8 +1277,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): match arr_pointee_ma: case mlirlite.LLVMType.Array(arr_et_ma, _): decayed_ma: mlirlite.Value* = mlirlite.build_gep_array(builder, arr_pointee_ma, arr_et_ma, arg_val, mlirlite.const_int32(pool, 0)) - if decayed_ma is not None: - arg_val = decayed_ma + if decayed_ma is not None: arg_val = decayed_ma case _: pass mlirlite.value_set_next(arg_val, None) @@ -1401,18 +1317,15 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): vpi_pa: str = None if mdf_param_count == 0 and found_func is None: vpi_sha1_p: str = None - if mc_entry is not None and mc_entry.ModuleSha1 is not None: - vpi_sha1_p = mc_entry.ModuleSha1 - else: - vpi_sha1_p = self.Gen.StructGen.get_struct_sha1(class_name) + if mc_entry is not None and mc_entry.ModuleSha1 is not None: vpi_sha1_p = mc_entry.ModuleSha1 + else: vpi_sha1_p = self.Gen.StructGen.get_struct_sha1(class_name) if vpi_sha1_p is not None: vpi_pa = self.Gen.CallGenBase._vpi_method_param_annot(pool, vpi_sha1_p, class_name, method_name) if vpi_pa is not None and vpi_pa[0] != '\0': vpi_pc2: int = 1 vi2: sizet = 0 while vpi_pa[vi2] != '\0': - if vpi_pa[vi2] == '@': - vpi_pc2 += 1 + if vpi_pa[vi2] == '@': vpi_pc2 += 1 vi2 += 1 mdf_param_count = vpi_pc2 - 1 # 非 self 参数数 @@ -1452,8 +1365,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # 用 stdlib 常量快照重建(mdf_gd.Defaults 的 pool 内 AST 可能已被 reset 回收, # 直接回退读 AST 会 use-after-free——快照失败时 fail-fast 暴露,绝不读悬空 AST) 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_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") continue @@ -1497,13 +1409,11 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): seg_no_v: int = 0 seg_cur_v: sizet = 0 while seg_no_v < seg_idx_v and vpi_pa[seg_cur_v] != '\0': - if vpi_pa[seg_cur_v] == '@': - seg_no_v += 1 + if vpi_pa[seg_cur_v] == '@': seg_no_v += 1 seg_cur_v += 1 seg_start_v: sizet = seg_cur_v seg_len_v: sizet = 0 - while vpi_pa[seg_start_v + seg_len_v] != '\0' and vpi_pa[seg_start_v + seg_len_v] != '@': - seg_len_v += 1 + while vpi_pa[seg_start_v + seg_len_v] != '\0' and vpi_pa[seg_start_v + seg_len_v] != '@': seg_len_v += 1 if seg_no_v == seg_idx_v: pty_v: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) if seg_len_v > 0: @@ -1512,8 +1422,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): string.strncpy(seg_buf_v, vpi_pa + seg_start_v, seg_len_v) seg_buf_v[seg_len_v] = '\0' rty_v: mlirlite.LLVMType* = self.Gen.CallGenBase._vpi_resolve_param_annot_ty(pool, seg_buf_v) - if rty_v is not None: - pty_v = rty_v + if rty_v is not None: pty_v = rty_v stdlib.free(seg_buf_v) zero_val_v: mlirlite.Value* = mlirlite.ConstZero(pool, pty_v) if zero_val_v is not None: @@ -1534,8 +1443,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): mc_methods_arr: sizet* = (sizet*)(mc_entry.VTableMethods) for mc_mi in range(mc_entry.VTableMethodCount): mc_mname_addr: sizet = mc_methods_arr[mc_mi] - if mc_mname_addr == 0: - continue + if mc_mname_addr == 0: continue mc_mname: str = rawptr(mc_mname_addr) if mc_mname is not None and string.strcmp(mc_mname, method_name) == 0: mc_method_idx = mc_mi @@ -1579,8 +1487,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): can: sizet, trans: HT.Translator*) -> mlirlite.Value*: """翻译 list 内置方法调用,返回 call 结果 Value(void 方法返回 None)""" - if pool is None or builder is None or lm_obj is None or lm_name is None: - return None + if pool is None or builder is None or lm_obj is None or lm_name is None: return None i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool) i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty) @@ -1588,13 +1495,10 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # 未知/指针元素→i8*),与 CallGenDispatch 尾部 list 分支一致 lm_esty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(lm_obj) lm_ename: str = None - if lm_esty is not None: - lm_ename = mlirlite.get_struct_name(lm_esty) + if lm_esty is not None: lm_ename = mlirlite.get_struct_name(lm_esty) lm_elem_ty: mlirlite.LLVMType* = None - if lm_ename is not None: - lm_elem_ty = self.Gen.ExprGenName._list_elem_type_from_name(pool, lm_ename) - if lm_elem_ty is None: - lm_elem_ty = i8_ptr_ty + if lm_ename is not None: lm_elem_ty = self.Gen.ExprGenName._list_elem_type_from_name(pool, lm_ename) + if lm_elem_ty is None: lm_elem_ty = i8_ptr_ty # get / __getitem__: 返回 index 处的元素 if string.strcmp(lm_name, "get") == 0 or string.strcmp(lm_name, "__getitem__") == 0: @@ -1616,8 +1520,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): g_addr: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, g_data, g_offset) if g_addr is not None: g_ep: mlirlite.Value* = mlirlite.build_bitcast(builder, g_addr, mlirlite.Ptr(pool, lm_elem_ty)) - if g_ep is not None: - return mlirlite.build_load(builder, lm_elem_ty, g_ep) + if g_ep is not None: return mlirlite.build_load(builder, lm_elem_ty, g_ep) # set / __setitem__: 设置 index 处的元素 elif string.strcmp(lm_name, "set") == 0 or string.strcmp(lm_name, "__setitem__") == 0: @@ -1661,8 +1564,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): p_addr: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, p_data, p_offset) if p_addr is not None: p_ep: mlirlite.Value* = mlirlite.build_bitcast(builder, p_addr, mlirlite.Ptr(pool, lm_elem_ty)) - if p_ep is not None: - return mlirlite.build_load(builder, lm_elem_ty, p_ep) + if p_ep is not None: return mlirlite.build_load(builder, lm_elem_ty, p_ep) # clear: count = 0 elif string.strcmp(lm_name, "clear") == 0: @@ -1682,8 +1584,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): elif string.strcmp(lm_name, "__len__") == 0: l_idx1: mlirlite.Value* = mlirlite.const_int64(pool, 1) l_cpp: mlirlite.Value* = mlirlite.build_gep(builder, i64_ty, lm_obj, l_idx1) - if l_cpp is not None: - return mlirlite.build_load(builder, i64_ty, l_cpp) + if l_cpp is not None: return mlirlite.build_load(builder, i64_ty, l_cpp) # append: 直接调用 list.append(self, item) # append 需要容量检查和内存重分配,逻辑复杂,直接调用 _list.py 中的实现 @@ -1701,10 +1602,8 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # 从类型解析特化类名拼接调用名,否则 ld.lld undefined symbol ap_spec_nm: str = None ap_struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(lm_obj) - if ap_struct_ty is not None: - ap_spec_nm = self.Gen.StructGen.get_class_name_by_type(pool, ap_struct_ty) - if ap_spec_nm is None: - ap_spec_nm = "list" + if ap_struct_ty is not None: ap_spec_nm = self.Gen.StructGen.get_class_name_by_type(pool, ap_struct_ty) + if ap_spec_nm is None: ap_spec_nm = "list" # 触发泛型特化翻译(幂等,MethodsEmitted 防重入) if trans is not None and ap_spec_nm is not None: lbkt_ap: str = string.strchr(ap_spec_nm, '[') @@ -1776,18 +1675,15 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): method_name: str, trans: HT.Translator*) -> mlirlite.Value*: """super().method(args) → 父类方法静态调用,返回 call 结果 Value""" - if pool is None or builder is None or cl is None or method_name is None: - return None - if trans is None: - return None + if pool is None or builder is None or cl is None or method_name is None: return None + if trans is None: return None # 1. 当前方法所属类:从 self 变量的注解类名获取(_translate_method # 注册 self 时 set_var_annot_class_name(SymTab, "self", class_name))。 # 不用 Mixin 字段:TPV Mixin 字段按声明类独立布局(Generator 多继承 # 去重只保留首个声明),ClassGenMixin 写的 CurClassName 与 CallGenMixin # 读的位置偏移不一致 → 运行时读到空 → super() 误报"只能在类方法内使用"。 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_entry = self.Gen.VarGen.lookup_var_entry(trans.SymTab, "cls") if self_entry is None: self.Gen.TypeGenErr.fatal_error(cl, "super(): 当前作用域无 self 变量(静态方法内不可用)", "TypeError") return None @@ -1832,8 +1728,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): self_ptr = mlirlite.build_load(builder, self_entry.Alloca.Ty, self_entry.Alloca) case _: self_ptr = self_entry.Alloca - if self_ptr is None: - return None + if self_ptr is None: return None # 3. this_adjust(字节偏移法:父类字段区在子类中的偏移差) self_arg: mlirlite.Value* = self_ptr if string.strcmp(anc, cur_class) != 0: @@ -1872,36 +1767,30 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): self_arg = mlirlite.build_bitcast(builder, adj_sp, anc_ptr_sp) # 4. 查找父类方法函数 + 构造调用名(SHA1 mangled) anc_lookup: str = pool.alloc(160) - if anc_lookup is None: - return None + if anc_lookup is None: return None viperlib.snprintf(anc_lookup, 160, "%s.%s", anc, method_name) found_func: mlirlite.Function* = self.find_func_in_module(mod, anc_lookup) call_name: str = anc_lookup anc_sha1_sp: str = self.Gen.StructGen.get_struct_sha1(anc) - if anc_sha1_sp is None: - anc_sha1_sp = trans.ModuleSha1 + if anc_sha1_sp is None: anc_sha1_sp = trans.ModuleSha1 if found_func is not None: fname_sp: str = mlirlite.function_get_name(found_func) - if fname_sp is not None: - call_name = fname_sp + if fname_sp is not None: call_name = fname_sp else: if anc_sha1_sp is not None: mangled_sp: str = self.Gen.FuncGenBase._mangle_name_with_sha1(anc_sha1_sp, anc_lookup) - if mangled_sp is not None: - call_name = mangled_sp + if mangled_sp is not None: call_name = mangled_sp # 5. 翻译参数 + 按形参 coerce(self 是形参 0,第 ai 个实参对应形参 ai+1) cargs_sp: list[ast.AST*]* = cl.args can_sp: sizet = 0 - if cargs_sp is not None: - can_sp = len(cargs_sp) + if cargs_sp is not None: can_sp = len(cargs_sp) mlirlite.value_set_next(self_arg, None) head: mlirlite.Value* = self_arg tail: mlirlite.Value* = self_arg arg_count_sp: int = 1 for ai_sp in range(can_sp): arg_node_sp: ast.AST* = cargs_sp.get(ai_sp) - if arg_node_sp is None: - continue + if arg_node_sp is None: continue # 先取形参类型(char 字面量 → str 形参需物化字符串,见 translate_constant) pp_sp: mlirlite.Param* = None pty_sp: mlirlite.LLVMType* = None @@ -1909,17 +1798,13 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): pp_sp = mlirlite.function_get_param_head(found_func) pi_sp: int = 0 while pp_sp is not None and pi_sp < ai_sp + 1: - if pi_sp == ai_sp + 1: - break + if pi_sp == ai_sp + 1: break pp_sp = mlirlite.param_get_next(pp_sp) pi_sp += 1 - if pp_sp is not None: - pty_sp = mlirlite.param_get_ty(pp_sp) + if pp_sp is not None: pty_sp = mlirlite.param_get_ty(pp_sp) arg_val_sp: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg_node_sp, None, 0, trans, pty_sp) - if arg_val_sp is None: - continue - if pty_sp is not None: - arg_val_sp = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val_sp, pty_sp, arg_node_sp) + if arg_val_sp is None: continue + if pty_sp is not None: arg_val_sp = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val_sp, pty_sp, arg_node_sp) else: # found_func=None:数组实参按 C 语义衰减为元素指针 # (与 _translate_method_call 一致,避免 declare 类型不匹配) @@ -1929,8 +1814,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): match arr_pointee_sp: case mlirlite.LLVMType.Array(arr_et_sp, _): decayed_sp: mlirlite.Value* = mlirlite.build_gep_array(builder, arr_pointee_sp, arr_et_sp, arg_val_sp, mlirlite.const_int32(pool, 0)) - if decayed_sp is not None: - arg_val_sp = decayed_sp + if decayed_sp is not None: arg_val_sp = decayed_sp case _: pass mlirlite.value_set_next(arg_val_sp, None) @@ -1941,30 +1825,23 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): ret_ty_sp: mlirlite.LLVMType* = mlirlite.Int32(pool) if found_func is not None: frt_sp: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(found_func) - if frt_sp is not None: - ret_ty_sp = frt_sp + if frt_sp is not None: ret_ty_sp = frt_sp else: sp_ty_sp: mlirlite.LLVMType* = self._special_method_ret_ty(pool, anc, method_name) - if sp_ty_sp is not None: - ret_ty_sp = sp_ty_sp + if sp_ty_sp is not None: ret_ty_sp = sp_ty_sp else: vpi_ret_sp: mlirlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, anc_sha1_sp, anc, method_name) - if vpi_ret_sp is not None: - ret_ty_sp = vpi_ret_sp + if vpi_ret_sp is not None: ret_ty_sp = vpi_ret_sp else: looked_sp: mlirlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, anc_sha1_sp, anc, method_name) - if looked_sp is not None: - ret_ty_sp = looked_sp + if looked_sp is not None: ret_ty_sp = looked_sp else: # Phase A 依赖未就绪(anc_sha1_sp None / 定义模块 text.ll 未生成): # 保持默认 i32(build_call(Void) 返回 None 会破坏表达式翻译)。 - if anc_sha1_sp is None or self._dep_text_ll_exists(pool, anc_sha1_sp) == 0: - ret_ty_sp = mlirlite.Int32(pool) - else: - self._fail_method_ret_ty(method_name, cl) + if anc_sha1_sp is None or self._dep_text_ll_exists(pool, anc_sha1_sp) == 0: ret_ty_sp = mlirlite.Int32(pool) + else: self._fail_method_ret_ty(method_name, cl) # 7. 跨模块:创建 declare;生成 call - if found_func is None: - self._ensure_method_declare(pool, mod, call_name, ret_ty_sp, head, arg_count_sp) + if found_func is None: self._ensure_method_declare(pool, mod, call_name, ret_ty_sp, head, arg_count_sp) is_variadic_sp: int = self.Gen.CallGenVa._check_and_promote_variadic_call(pool, builder, mod, call_name, head, arg_count_sp, cargs_sp, 1, trans) return mlirlite.build_call(builder, call_name, head, arg_count_sp, ret_ty_sp, is_variadic_sp) # ============================================================ @@ -1976,10 +1853,8 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # ============================================================ def _recv_is_mixin_base(self, class_name: str) -> int: """接收类是否为某个已注册类的直接父类(1=是 / 0=否)""" - if class_name is None: - return 0 - if self.Gen is None: - return 0 + if class_name is None: return 0 + if self.Gen is None: return 0 j: int = 0 n: int = self.Gen.StructGen.get_struct_count() while j < n: @@ -1990,8 +1865,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): while pj < pc: pn: str = self.Gen.StructGen.get_parent_name_at(e.Name, pj) if pn is not None: - if string.strcmp(pn, class_name) == 0: - return 1 + if string.strcmp(pn, class_name) == 0: return 1 pj += 1 j += 1 return 0 @@ -2006,10 +1880,8 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): def _mixin_sibling_same_composite(self, pool: memhub.MemBuddy*, class_name: str, cand_name: str) -> int: """两类是否同处某个已注册组合类的 MRO(1=是 / 0=否)""" - if class_name is None or cand_name is None or pool is None: - return 0 - if self.Gen is None: - return 0 + if class_name is None or cand_name is None or pool is None: return 0 + if self.Gen is None: return 0 j: int = 0 n: int = self.Gen.StructGen.get_struct_count() while j < n: @@ -2023,12 +1895,9 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): while mro[mi] != 0: nm: str = rawptr(mro[mi]) if nm is not None: - if string.strcmp(nm, class_name) == 0: - has_self = 1 - elif string.strcmp(nm, cand_name) == 0: - has_cand = 1 - if has_self != 0 and has_cand != 0: - return 1 + if string.strcmp(nm, class_name) == 0: has_self = 1 + elif string.strcmp(nm, cand_name) == 0: has_cand = 1 + if has_self != 0 and has_cand != 0: return 1 mi += 1 j += 1 return 0 @@ -2044,8 +1913,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): entry: GenTypes.StructEntry*, field_index: int) -> int: """计算字段在结构体中的字节偏移(含对齐 padding),无法计算返回 0""" - if pool is None or entry is None or entry.Ty is None or field_index < 0: - return 0 + if pool is None or entry is None or entry.Ty is None or field_index < 0: return 0 match entry.Ty: case mlirlite.LLVMType.Struct(fields, fcount, name): offset_fb: int = 0 @@ -2061,8 +1929,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): falign_fb: int = self.Gen.ClassGenEnum._get_type_align(fty_fb) if is_packed_fb == 0 and falign_fb > 1: rem_fb: int = offset_fb % falign_fb - if rem_fb != 0: - offset_fb += falign_fb - rem_fb + if rem_fb != 0: offset_fb += falign_fb - rem_fb offset_fb += fsize_fb cur_fb = cur_fb.Next i_fb += 1 @@ -2072,8 +1939,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): falign2_fb: int = self.Gen.ClassGenEnum._get_type_align(fty2_fb) if is_packed_fb == 0 and falign2_fb > 1: rem2_fb: int = offset_fb % falign2_fb - if rem2_fb != 0: - offset_fb += falign2_fb - rem2_fb + if rem2_fb != 0: offset_fb += falign2_fb - rem2_fb return offset_fb case _: return 0 @@ -2086,15 +1952,11 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): def _kwarg_name_matches(self, kw_arg: str, param_name: str) -> int: """检查关键字参数名 kw_arg 是否匹配参数名 param_name(跳过 % 前缀)""" - if kw_arg is None or param_name is None: - return 0 + if kw_arg is None or param_name is None: return 0 start: sizet = 0 - if param_name[0] == '%': - start = 1 + if param_name[0] == '%': start = 1 for i, ch in enumerate(kw_arg): c: char = param_name[start + i] - if c == '\0' or c != ch: - return 0 - if param_name[start + i + 1] != '\0': - return 0 + if c == '\0' or c != ch: return 0 + if param_name[start + i + 1] != '\0': return 0 return 1 \ No newline at end of file diff --git a/App/lib/core/Gen/Call/CallGenCtor.vp b/App/lib/core/Gen/Call/CallGenCtor.vp index 76c78e4..26c71e8 100644 --- a/App/lib/core/Gen/Call/CallGenCtor.vp +++ b/App/lib/core/Gen/Call/CallGenCtor.vp @@ -61,14 +61,12 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): field_ptr_arr2: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, fe.Ty, tmp, fe.Index) if field_ptr_arr2 is not None: zero_arr2: mlirlite.Value* = mlirlite.ConstZero(pool, fe.Ty) - if zero_arr2 is not None: - mlirlite.build_store(builder, zero_arr2, field_ptr_arr2, is_volatile) + if zero_arr2 is not None: mlirlite.build_store(builder, zero_arr2, field_ptr_arr2, is_volatile) # owner_ctx 只服务空元素 fail-fast 报文(类名 + 字段名 + 下标) sd_ctx: str = pool.alloc(192) if sd_ctx is not None: fname_sd: str = fe.Name - if fname_sd is None: - fname_sd = "?" + if fname_sd is None: fname_sd = "?" viperlib.snprintf(sd_ctx, 192, "类 %s 字段 %s(结构体构造默认值):", class_name, fname_sd) self.Gen.AssignGen._init_global_array_from_list(builder, pool, mod, field_ptr_arr2, fe.DefaultVal, trans, sd_ctx) continue @@ -121,19 +119,16 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间) self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, struct_ty) tmp: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, struct_ty) - if tmp is None: - return mlirlite.ConstZero(pool, struct_ty) + if tmp is None: return mlirlite.ConstZero(pool, struct_ty) # 诊断节点:取第一个构造实参(有行号),供 _call_method_on_ptr 的 # fatal_error 显示构造调用行号(本函数无 cl 参数,实参节点最接近调用点) diag_node_ct: ast.AST* = None - if cargs is not None and len(cargs) > 0: - diag_node_ct = cargs.get(0) + if cargs is not None and len(cargs) > 0: diag_node_ct = cargs.get(0) # 检查是否为 OOP 结构体(用类型指针定位 entry,规避跨模块同名 find_struct 找错) ctor_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_type(struct_ty) is_oop: int = 0 - if ctor_entry is not None: - is_oop = ctor_entry.IsOOP + if ctor_entry is not None: is_oop = ctor_entry.IsOOP # 跨模块 OOP 类推断:IsOOP 可能未设置(Phase1 缓存跳过 _translate_oop_methods) # 方案1: 检查当前模块是否有 ClassName.__init__ 的声明(stub 注入) @@ -165,18 +160,15 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # 如果有 __new__,调用 __new__(tmp, args...) 获取实际存储指针 # __new__ 签名与 __init__ 一样(self + args),返回 Ptr(struct_ty) has_new_flag: int = 0 - if ctor_entry is not None: - has_new_flag = ctor_entry.HasNew + if ctor_entry is not None: has_new_flag = ctor_entry.HasNew # 注意: __new__ 是可选的,不推断 HasNew(仅 __init__ 是 OOP 类标准方法) if has_new_flag != 0: new_arg_vals: sizet* = pool.alloc(8 * 32) - if new_arg_vals is not None: - string.memset(new_arg_vals, 0, 8 * 32) + if new_arg_vals is not None: string.memset(new_arg_vals, 0, 8 * 32) new_arg_count: int = 0 for nai in range(can): new_arg_node: ast.AST* = cargs.get(nai) - if new_arg_node is None: - continue + if new_arg_node is None: continue new_av: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, new_arg_node, None, 0, trans) if new_av is not None: if new_arg_count < 32: @@ -196,8 +188,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): nw_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, struct_ty) if uint64(new_ptr.Ty) != uint64(nw_ty): nw_bc: mlirlite.Value* = mlirlite.build_bitcast(builder, new_ptr, nw_ty) - if nw_bc is not None: - storage_ptr = nw_bc + if nw_bc is not None: storage_ptr = nw_bc # OOP 结构体:调用 __before_init__ 进行零值填充和默认值赋值 self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, class_name,"__before_init__", storage_ptr, None, 0, trans, diag_node_ct, is_volatile) @@ -206,18 +197,15 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # 注意: 仅依据 ctor_entry.HasInit 判断,不强制推断 # (JsonValue 等类有 __new__ 但无 __init__,强制推断会导致 undefined reference) has_init_flag: int = 0 - if ctor_entry is not None: - has_init_flag = ctor_entry.HasInit + if ctor_entry is not None: has_init_flag = ctor_entry.HasInit if has_init_flag != 0: # 翻译构造函数参数 arg_vals: sizet* = pool.alloc(8 * 32) - if arg_vals is not None: - string.memset(arg_vals, 0, 8 * 32) + if arg_vals is not None: string.memset(arg_vals, 0, 8 * 32) real_arg_count: int = 0 for ai in range(can): arg_node: ast.AST* = cargs.get(ai) - if arg_node is None: - continue + if arg_node is None: continue av: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg_node, None, 0, trans) if av is not None: if real_arg_count < 32: @@ -246,8 +234,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): fe = cand_fe break target_idx += 1 - else: - fe = self.Gen.StructGen.get_field_by_index(class_name, ai) + else: fe = self.Gen.StructGen.get_field_by_index(class_name, ai) if fe is None: # fast-fail: 字段索引越界(用户传了多余参数) VLogger.error(f"构造函数参数过多,字段索引越界: {class_name}", "HandlesExprCall") @@ -278,14 +265,11 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # 逐字段 store 参数值(覆盖默认值) for ai in range(can): arg: ast.AST* = cargs.get(ai) - if arg is None: - continue + if arg is None: continue # 先取字段(fe.Ty 用于 char 字面量 → str 字段的物化判定,见 translate_constant) fe: GenTypes.FieldEntry* = None - if ctor_entry is not None: - fe = self.Gen.StructGen._get_field_entry(ctor_entry, ai) - else: - fe = self.Gen.StructGen.get_field_by_index(class_name, ai) + if ctor_entry is not None: fe = self.Gen.StructGen._get_field_entry(ctor_entry, ai) + else: fe = self.Gen.StructGen.get_field_by_index(class_name, ai) if fe is None: # fast-fail: 字段索引越界(用户传了多余参数) VLogger.error(f"构造函数参数过多,字段索引越界: {class_name}", "HandlesExprCall") @@ -346,29 +330,24 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): can: 参数数量 is_volatile=1:`volatile C.V(...)` 构造——清零/tag/payload 写入带 volatile """ - if pool is None or builder is None or class_name is None: - return None + if pool is None or builder is None or class_name is None: return None # 查找 REnum 结构体类型(用 find_struct_by_module 规避跨模块同名) renum_entry: GenTypes.StructEntry* = None - if trans is not None: - renum_entry = self.Gen.StructGen.find_struct_by_module(class_name, trans.ModuleSha1) - if renum_entry is None: - renum_entry = self.Gen.StructGen.find_struct(class_name) + if trans is not None: renum_entry = self.Gen.StructGen.find_struct_by_module(class_name, trans.ModuleSha1) + if renum_entry is None: renum_entry = self.Gen.StructGen.find_struct(class_name) if renum_entry is None: VLogger.error(f"REnum construct: type {class_name} not registered", "RENUM") return None renum_ty: mlirlite.LLVMType* = renum_entry.Ty - if renum_ty is None: - return None + if renum_ty is None: return None # alloca REnum 类型 # 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间) self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, renum_ty) tmp: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, renum_ty) - if tmp is None: - return mlirlite.ConstZero(pool, renum_ty) + if tmp is None: return mlirlite.ConstZero(pool, renum_ty) # 清零(确保未赋值的 payload 位置为零) zero: mlirlite.Value* = mlirlite.ConstZero(pool, renum_ty) @@ -381,16 +360,13 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # 这种静默错配(此前常量硬编码 i32、GEP 用字段类型,两者口径不一致)。 tag_field: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(renum_entry, 0) tag_field_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) - if tag_field is not None and tag_field.Ty is not None: - tag_field_ty = tag_field.Ty + if tag_field is not None and tag_field.Ty is not None: tag_field_ty = tag_field.Ty tag_name_buf: str = pool.alloc(32) - if tag_name_buf is not None: - viperlib.snprintf(tag_name_buf, 32, "%d", tag_value) + if tag_name_buf is not None: viperlib.snprintf(tag_name_buf, 32, "%d", tag_value) tag_const: mlirlite.Value* = mlirlite.ConstInt(pool, tag_field_ty, tag_value, tag_name_buf if tag_name_buf is not None else "0") tag_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, renum_ty, tag_field_ty, tmp, 0) - if tag_ptr is not None: - mlirlite.build_store(builder, tag_const, tag_ptr, is_volatile) + if tag_ptr is not None: mlirlite.build_store(builder, tag_const, tag_ptr, is_volatile) # 写入 payload 字段(索引 1, 2, ... 对应 _p1, _p2, ...) # 参数按位置顺序填充 payload,跳过 __tag(索引 0) @@ -416,8 +392,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): and self.Gen.ExprGenBase.is_ptr_type(pfe.Ty) == 0 and self.Gen.ExprGenBase.get_llvm_type_bits(pfe.Ty) != 0): casted_arg: mlirlite.Value* = mlirlite.build_ptrtoint(builder, arg_val, pfe.Ty) - if casted_arg is None: - continue + if casted_arg is None: continue arg_val = casted_arg # 类型转换并 store(payload 位置可能是 i32 或 i64,按字段类型 coerce) arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, pfe.Ty, arg) @@ -456,20 +431,17 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间) self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, struct_ty) tmp: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, struct_ty) - if tmp is None: - return mlirlite.ConstZero(pool, struct_ty) + if tmp is None: return mlirlite.ConstZero(pool, struct_ty) # 诊断节点:取第一个构造实参(有行号),供 _call_method_on_ptr 的 # fatal_error 显示构造调用行号(本函数无 cl 参数,实参节点最接近调用点) diag_node_ct: ast.AST* = None - if cargs is not None and len(cargs) > 0: - diag_node_ct = cargs.get(0) + if cargs is not None and len(cargs) > 0: diag_node_ct = cargs.get(0) # OOP 结构体:调用 __before_init__ 进行零值填充和默认值赋值 # 用 find_struct_by_type 规避跨模块同名 find_struct 找错 kw_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_type(struct_ty) is_oop: int = 0 - if kw_entry is not None: - is_oop = kw_entry.IsOOP + if kw_entry is not None: is_oop = kw_entry.IsOOP # 跨模块 OOP 类推断:IsOOP 可能未设置(Phase1 缓存跳过 _translate_oop_methods) # 方案1: 检查当前模块是否有 ClassName.__init__ 的声明(stub 注入) @@ -515,8 +487,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # 跨模块 OOP 类: HasInit 可能未设置(_translate_oop_methods 未被调用) # 但 IsOOP=1 说明类有方法,推断 HasInit=1(__init__ 在目标模块中存在) # 注意: __new__ 是可选的,不推断 HasNew(仅 __init__ 是 OOP 类标准方法) - if is_oop != 0 and has_init_flag == 0: - has_init_flag = 1 + if is_oop != 0 and has_init_flag == 0: has_init_flag = 1 if is_oop != 0 and has_init_flag != 0: # 有 __init__:构建参数数组并调用 __init__ @@ -525,8 +496,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # 如果有 __new__,调用 __new__ 获取实际存储指针 if has_new_flag != 0: new_arg_vals: sizet* = pool.alloc(8 * 32) - if new_arg_vals is not None: - string.memset(new_arg_vals, 0, 8 * 32) + if new_arg_vals is not None: string.memset(new_arg_vals, 0, 8 * 32) new_arg_count: int = 0 for nai in range(can): new_arg_node: ast.AST* = cargs.get(nai) @@ -558,13 +528,11 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): nw_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, struct_ty) if uint64(new_ptr.Ty) != uint64(nw_ty): nw_bc: mlirlite.Value* = mlirlite.build_bitcast(builder, new_ptr, nw_ty) - if nw_bc is not None: - storage_ptr = nw_bc + if nw_bc is not None: storage_ptr = nw_bc # 构建 __init__ 参数数组:位置参数按顺序 + 关键字参数追加 init_arg_vals: sizet* = pool.alloc(8 * 32) - if init_arg_vals is not None: - string.memset(init_arg_vals, 0, 8 * 32) + if init_arg_vals is not None: string.memset(init_arg_vals, 0, 8 * 32) init_arg_count: int = 0 # 位置参数 for ai_init in range(can): @@ -598,10 +566,8 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if arg is None: continue # 先取字段(fe.Ty 用于 char 字面量 → str 字段的物化判定,见 translate_constant) fe: GenTypes.FieldEntry* = None - if kw_entry is not None: - fe = self.Gen.StructGen._get_field_entry(kw_entry, ai) - else: - fe = self.Gen.StructGen.get_field_by_index(class_name, ai) + if kw_entry is not None: fe = self.Gen.StructGen._get_field_entry(kw_entry, ai) + else: fe = self.Gen.StructGen.get_field_by_index(class_name, ai) if fe is None: # 位置参数越界(字段表无对应项):fail-fast,绝不静默跳过 self.Gen.TypeGenErr.fatal_error(arg, f"结构体 '{class_name}' 位置参数越界(无对应字段)", "TypeError") @@ -616,8 +582,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # 处理关键字参数(按字段名查找) # SHA1 从 kw_entry 获取(规避跨模块同名 find_struct 找错) kw_sha1: str = None - if kw_entry is not None: - kw_sha1 = kw_entry.ModuleSha1 + if kw_entry is not None: kw_sha1 = kw_entry.ModuleSha1 for ki in range(kw_count): kw: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(ki)) if kw is None or kw.arg is None or kw.value is None: continue @@ -665,8 +630,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): 源表达式无符号(t.CUIntXXT(x) 强转 / 无符号注解变量)→ zext 否则 → sext(有符号整数拓宽保持数值,如 i8 -50 → 0xFFFFFFCE) """ - if val is None or target_ty is None: - return None + if val is None or target_ty is None: return None val_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(val.Ty) target_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(target_ty) @@ -675,15 +639,13 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # 整数 → 整数: trunc/zext/sext if val_bits != 0 and target_bits != 0: - if val_bits == target_bits: - return val + if val_bits == target_bits: return val elif val_bits < target_bits: if val_bits == 1: # i1 是布尔值(来自 icmp/fcmp),无符号语义,必须 zext return mlirlite.build_zext(builder, val, target_ty) # 统一拓宽方向(与 coerce_to_type 的 _zext_or_sext_val 同源):i1/i8 → zext;源为无符号(t.CUIntXXT 强转 / 无符号注解变量)→ zext;否则 sext(默认有符号)。拓宽保持**源**的数值语义(有符号源拓宽即保号),与目标类型无关 - if self.Gen.ExprGenBase._zext_or_sext_val(pool, val, src_node, trans) != 0: - return mlirlite.build_zext(builder, val, target_ty) + if self.Gen.ExprGenBase._zext_or_sext_val(pool, val, src_node, trans) != 0: return mlirlite.build_zext(builder, val, target_ty) return mlirlite.build_sext(builder, val, target_ty) else: # 目标 i1(bool / t.CBool):显式强转 `t.CBool(x)` 与隐式落存储 @@ -696,29 +658,22 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): return mlirlite.build_trunc(builder, val, target_ty) # 整数 → 浮点: sitofp - if val_bits != 0 and target_fbits != 0: - return mlirlite.build_si2fp(builder, val, target_ty) + if val_bits != 0 and target_fbits != 0: return mlirlite.build_si2fp(builder, val, target_ty) # 浮点 → 整数: fptosi - if val_fbits != 0 and target_bits != 0: - return mlirlite.build_fp2si(builder, val, target_ty) + if val_fbits != 0 and target_bits != 0: return mlirlite.build_fp2si(builder, val, target_ty) # 浮点 → 浮点: fpext/fptrunc if val_fbits != 0 and target_fbits != 0: - if val_fbits == target_fbits: - return val - elif val_fbits < target_fbits: - return mlirlite.build_fpext(builder, val, target_ty) - else: - return mlirlite.build_fptrunc(builder, val, target_ty) + if val_fbits == target_fbits: return val + elif val_fbits < target_fbits: return mlirlite.build_fpext(builder, val, target_ty) + else: return mlirlite.build_fptrunc(builder, val, target_ty) # 指针 → 整数: ptrtoint - if val_bits == 0 and val_fbits == 0 and target_bits != 0: - return mlirlite.build_ptrtoint(builder, val, target_ty) + if val_bits == 0 and val_fbits == 0 and target_bits != 0: return mlirlite.build_ptrtoint(builder, val, target_ty) # 整数 → 指针: inttoptr(必须排除浮点 target,浮点 target_bits 也是 0) - if val_bits != 0 and target_bits == 0 and target_fbits == 0: - return mlirlite.build_inttoptr(builder, val, target_ty) + if val_bits != 0 and target_bits == 0 and target_fbits == 0: return mlirlite.build_inttoptr(builder, val, target_ty) # 指针 → 指针: bitcast return mlirlite.build_bitcast(builder, val, target_ty) @@ -748,8 +703,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): 规范化为 "{定义模块SHA1}.{Class}"(ast.AST/AST → f467978339422f32.AST), 与特化注册名一致,消除跨模块特化名分裂(list[AST].set undefined symbol)。 """ - if slice_node is None or pool is None: - return None + if slice_node is None or pool is None: return None # elem_size=8:str 是 i8* 指针(8 字节),若用 4 则双元素时 append 写 8 字节 # 但步长按 4 计算,第 2 个元素覆盖第 1 个元素高 4 字节 → get 读出垃圾指针崩溃 result: list[str]* = list[str](pool, 8) @@ -766,13 +720,11 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): elt: ast.AST* = elts.get(i) tn_raw = self.Gen.TypeGenResolve._get_type_name_from_annotation(pool, elt) tn = self.Gen.TypeGenResolve._norm_type_arg_name(pool, tn_raw, from_imports) - if tn is not None: - result.append(tn) + if tn is not None: result.append(tn) else: tn_raw = self.Gen.TypeGenResolve._get_type_name_from_annotation(pool, slice_node) tn = self.Gen.TypeGenResolve._norm_type_arg_name(pool, tn_raw, from_imports) - if tn is not None: - result.append(tn) + if tn is not None: result.append(tn) return result # 泛型类构造调用辅助 list[str](pool, 8):复用 translate_list_literal 的构造逻辑——alloca tmp → 翻译 cl.args 为参数指针数组 → __new__(tmp,*args) → __before_init__ → __init__ → 返回 storage_ptr。必须独立于 translate_call 普通函数路径:spec_name 是类名不是函数名,走裸名会被 _lookup_mod_sha1 的 star import 回退误导 @@ -800,20 +752,15 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): cls_nm: str, ptr_level: int, from_imports: str) -> str: """注解类名 → 与注解侧同票名的类型实参文本(按 PtrLevel 补 `*`,非类名原样)""" - if cls_nm is None: - return None + if cls_nm is None: return None res_pl: str = self.Gen.TypeGenResolve._norm_type_arg_name(pool, cls_nm, from_imports) - if res_pl is None: - res_pl = cls_nm - if ptr_level <= 0: - return res_pl + if res_pl is None: res_pl = cls_nm + if ptr_level <= 0: return res_pl # 非类名(无 SHA1 前缀,如 typedef "VOIDPTR" / 裸标记 "CPtr")不补指针层 - if self.Gen.TypeGenResolve._is_sha1_prefixed(res_pl) == 0: - return res_pl + if self.Gen.TypeGenResolve._is_sha1_prefixed(res_pl) == 0: return res_pl # 已带尾随 `*`(如泛型上下文 resolve_generic_type_name 已给指针层)不再叠加 res_len_pl: sizet = string.strlen(res_pl) - if res_len_pl > 0 and res_pl[res_len_pl - 1] == '*': - return res_pl + if res_len_pl > 0 and res_pl[res_len_pl - 1] == '*': return res_pl lvl_pl: int = ptr_level while lvl_pl > 0: res_pl = self.Gen.TypeGenResolve._ptr_star_text(pool, res_pl) @@ -863,16 +810,12 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # 唯一真源 spec_sign_of_annot(白名单 + CTypedef 链回退): # 决定 CUInt64T/CInt16T 这类无裸名别名位宽发 t.CUInt64T/t.CInt64T。 callee_txt_c: str = None - if fk_c == ast.ASTKind.Name: - callee_txt_c = ast.Name*(cl_f.func).id - else: - callee_txt_c = ast.Attribute*(cl_f.func).attr + if fk_c == ast.ASTKind.Name: callee_txt_c = ast.Name*(cl_f.func).id + else: callee_txt_c = ast.Attribute*(cl_f.func).attr sign_c: int = TSpec.TS_SIGN_UNKNOWN - if callee_txt_c is not None: - sign_c = self.Gen.TypeGenCType.spec_sign_of_annot(callee_txt_c, 0) + if callee_txt_c is not None: sign_c = self.Gen.TypeGenCType.spec_sign_of_annot(callee_txt_c, 0) ta_c: str = self.Gen.ClassGenGeneric.infer_scalar_type_arg_from_llvm_ty(pool, cty_c, sign_c) - if ta_c is not None: - return ta_c + if ta_c is not None: return ta_c # 类型转换调用(Call)但被调名无法解析为标量类型:明确的类型意图却无法 # 解析,fail-fast(返回 None ⇒ 调用方 fail-fast)。 self.Gen.TypeGenErr.fatal_error(arg_node, f"无法从实参推断泛型类 '{class_name}' 的类型实参,请显式标注如 {class_name}[类型](...)", "TypeError") @@ -892,8 +835,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # `x: AST*`)时补足 `*`,与注解侧归一形 `{sha}.AST*` 同票名。 cn_nm_i: str = self.Gen.VarGen.var_annot_class_name(ve_i) pl_nm_i: int = 0 - if ve_i.Spec is not None: - pl_nm_i = ve_i.Spec.PtrLevel + if ve_i.Spec is not None: pl_nm_i = ve_i.Spec.PtrLevel return self._ptr_layer_type_arg(pool, cn_nm_i, pl_nm_i, trans._from_imports) return None # 属性(Attribute)实参:取字段注解类名(ExprGenAttr 沿属性链递归解析, @@ -905,11 +847,9 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): cn_at_i: str = self.Gen.ExprGenAttr._resolve_attr_field_class(pool, trans, arg_node) pl_at_i: int = 0 fe_at_i: GenTypes.FieldEntry* = self.Gen.ExprGenAttr._resolve_attr_field_entry(pool, trans, arg_node) - if fe_at_i is not None and fe_at_i.Spec is not None: - pl_at_i = fe_at_i.Spec.PtrLevel + if fe_at_i is not None and fe_at_i.Spec is not None: pl_at_i = fe_at_i.Spec.PtrLevel fi_at_i: str = None - if trans is not None: - fi_at_i = trans._from_imports + if trans is not None: fi_at_i = trans._from_imports return self._ptr_layer_type_arg(pool, cn_at_i, pl_at_i, fi_at_i) return None @@ -921,18 +861,15 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): Subscript(如 list[T])不认:实参是容器而非 T 本身,不能作为 T 的 推断来源。 """ - if node is None or tp_name is None: - return 0 + if node is None or tp_name is None: return 0 k: int = node.kind() if k == ast.ASTKind.Name: nm_a: ast.Name* = ast.Name*(node) - if nm_a.id is not None and string.strcmp(nm_a.id, tp_name) == 0: - return 1 + if nm_a.id is not None and string.strcmp(nm_a.id, tp_name) == 0: return 1 return 0 if k == ast.ASTKind.BinOp: bop_a: ast.BinOp* = ast.BinOp*(node) - if self._annotation_refers_type_param(bop_a.left, tp_name) != 0: - return 1 + if self._annotation_refers_type_param(bop_a.left, tp_name) != 0: return 1 return self._annotation_refers_type_param(bop_a.right, tp_name) return 0 @@ -946,26 +883,20 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): _find_ctor_type_param_param_index(TYPE 形参 → 形参序号) _ctor_init_arg_slot_by_name(关键字实参名 → 非 self 形参序号) """ - if class_name is None: - return None + if class_name is None: return None template_cd: ast.ClassDef* = self.Gen.ClassGenGeneric._find_generic_template(class_name) - if template_cd is None or template_cd.children is None: - return None + if template_cd is None or template_cd.children is None: return None children: list[ast.AST*]* = template_cd.children cn: sizet = len(children) ci: sizet for ci in range(cn): child: ast.AST* = children.get(ci) - if child is None or child.kind() != ast.ASTKind.FunctionDef: - continue + if child is None or child.kind() != ast.ASTKind.FunctionDef: continue fd: ast.FunctionDef* = ast.FunctionDef*(child) - if fd.name is None or string.strcmp(fd.name, "__init__") != 0: - continue - if fd.args is None or fd.args.kind() != ast.ASTKind.Arguments: - return None + if fd.name is None or string.strcmp(fd.name, "__init__") != 0: continue + if fd.args is None or fd.args.kind() != ast.ASTKind.Arguments: return None fargs: ast.Arguments* = ast.Arguments*(fd.args) - if fargs.args is None: - return None + if fargs.args is None: return None return fargs.args return None @@ -978,22 +909,18 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): 的 T 在第 3 个位置实参,pool/capacity 是非 T 参数),须按签名对齐——位置实参对齐(_find_ctor_type_param_arg_index) 与关键字实参对齐(_find_ctor_type_param_kw_arg_index)共用本函数。 """ - if class_name is None or tp_name is None: - return -1 + if class_name is None or tp_name is None: return -1 plist: list[ast.AST*]* = self._get_ctor_init_params(class_name) - if plist is None: - return -1 + if plist is None: return -1 pn: sizet = len(plist) pi: sizet for pi in range(pn): if pi == 0: continue # self:位置实参下标 = 形参序号 - 1 pa: ast.AST* = plist.get(pi) - if pa is None or pa.kind() != ast.ASTKind.Arg: - continue + if pa is None or pa.kind() != ast.ASTKind.Arg: continue ag: ast.Arg* = ast.Arg*(pa) - if self._annotation_refers_type_param(ag.annotation, tp_name) != 0: - return int(pi) + if self._annotation_refers_type_param(ag.annotation, tp_name) != 0: return int(pi) return -1 def _find_ctor_type_param_arg_index(self, class_name: str, @@ -1007,8 +934,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): 遍历(形参序号定位)委托 _find_ctor_type_param_param_index。 """ pi_arg: int = self._find_ctor_type_param_param_index(class_name, tp_name) - if pi_arg < 0: - return -1 + if pi_arg < 0: return -1 return pi_arg - 1 def _ctor_init_arg_slot_by_name(self, class_name: str, @@ -1021,22 +947,18 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): 按名匹配先例:CallGenCall._translate_method_call 的关键字分支 (CallGenCall.vp:1409-1418 遍历函数形参名逐个匹配关键字名)。 """ - if class_name is None or kw_name is None: - return -1 + if class_name is None or kw_name is None: return -1 plist_sb: list[ast.AST*]* = self._get_ctor_init_params(class_name) - if plist_sb is None: - return -1 + if plist_sb is None: return -1 pn_sb: sizet = len(plist_sb) pi_sb: sizet for pi_sb in range(pn_sb): if pi_sb == 0: continue # self 不是实参槽位 pa_sb: ast.AST* = plist_sb.get(pi_sb) - if pa_sb is None or pa_sb.kind() != ast.ASTKind.Arg: - continue + if pa_sb is None or pa_sb.kind() != ast.ASTKind.Arg: continue ag_sb: ast.Arg* = ast.Arg*(pa_sb) - if ag_sb.arg is not None and string.strcmp(ag_sb.arg, kw_name) == 0: - return int(pi_sb) - 1 + if ag_sb.arg is not None and string.strcmp(ag_sb.arg, kw_name) == 0: return int(pi_sb) - 1 return -1 def _find_ctor_type_param_kw_arg_index(self, class_name: str, @@ -1056,29 +978,23 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): 重复关键字名:parser 不做重复检测(parser.vp:877-889 直接 append), 沿用仓库既有处理"按名取首个匹配"(CallGenCall.vp:1412-1418)。 """ - if class_name is None or tp_name is None or keywords is None: - return -1 + if class_name is None or tp_name is None or keywords is None: return -1 pi_kw: int = self._find_ctor_type_param_param_index(class_name, tp_name) if pi_kw < 1: return -1 # 未找到,或落在 self 位(0 不是实参) if pi_kw - 1 < pos_count: return -1 # 该形参位已被位置实参占用 plist_kw: list[ast.AST*]* = self._get_ctor_init_params(class_name) - if plist_kw is None: - return -1 + if plist_kw is None: return -1 pa_kw: ast.AST* = plist_kw.get(sizet(pi_kw)) - if pa_kw is None or pa_kw.kind() != ast.ASTKind.Arg: - return -1 + if pa_kw is None or pa_kw.kind() != ast.ASTKind.Arg: return -1 ag_kw: ast.Arg* = ast.Arg*(pa_kw) - if ag_kw.arg is None: - return -1 + if ag_kw.arg is None: return -1 ki_kw: sizet for ki_kw in range(kw_count): kw_tp: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(ki_kw)) - if kw_tp is None or kw_tp.arg is None or kw_tp.value is None: - continue - if string.strcmp(kw_tp.arg, ag_kw.arg) == 0: - return int(ki_kw) + if kw_tp is None or kw_tp.arg is None or kw_tp.value is None: continue + if string.strcmp(kw_tp.arg, ag_kw.arg) == 0: return int(ki_kw) return -1 def _infer_ctor_type_args_from_ctx(self, pool: memhub.MemBuddy*, @@ -1107,23 +1023,18 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if pool is None or trans is None or class_name is None or cl is None: return None if tp_count <= 0: return None ctx_annot: ast.AST* = None - if trans.CurAssignNode is not None and uint64(cl) == uint64(trans.CurAssignNode): - ctx_annot = trans.CurAssignAnnot - if ctx_annot is None and trans.CurRetNode is not None and uint64(cl) == uint64(trans.CurRetNode): - ctx_annot = trans.CurFuncRetAnnot + if trans.CurAssignNode is not None and uint64(cl) == uint64(trans.CurAssignNode): ctx_annot = trans.CurAssignAnnot + if ctx_annot is None and trans.CurRetNode is not None and uint64(cl) == uint64(trans.CurRetNode): ctx_annot = trans.CurFuncRetAnnot if ctx_annot is None: return None # 取注解里的泛型 Subscript 一侧(与 _prespecialize_generic_annotation 同构: # 支持 `X[T]` 与 `X[T]*` 两种形态) spec_annot: ast.Subscript* = None - if ctx_annot.kind() == ast.ASTKind.Subscript: - spec_annot = ast.Subscript*(ctx_annot) + if ctx_annot.kind() == ast.ASTKind.Subscript: spec_annot = ast.Subscript*(ctx_annot) elif ctx_annot.kind() == ast.ASTKind.BinOp: bop_ctx: ast.BinOp* = ast.BinOp*(ctx_annot) if bop_ctx.op == ast.OpKind.BitOr: - if bop_ctx.left is not None and bop_ctx.left.kind() == ast.ASTKind.Subscript: - spec_annot = ast.Subscript*(bop_ctx.left) - elif bop_ctx.right is not None and bop_ctx.right.kind() == ast.ASTKind.Subscript: - spec_annot = ast.Subscript*(bop_ctx.right) + if bop_ctx.left is not None and bop_ctx.left.kind() == ast.ASTKind.Subscript: spec_annot = ast.Subscript*(bop_ctx.left) + elif bop_ctx.right is not None and bop_ctx.right.kind() == ast.ASTKind.Subscript: spec_annot = ast.Subscript*(bop_ctx.right) if spec_annot is None: return None # 注解必须与本次构造是同一个泛型类(不同类 ⇒ 上下文与本次构造无关) sv_ctx: ast.AST* = spec_annot.value @@ -1164,16 +1075,13 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # 翻译实参为参数指针数组(extra_args[slot] = Value 指针):位置实参 → 槽 0..can-1;关键字实参 → 按 __init__ 形参名定位槽位(与 _find_ctor_type_param_kw_arg_index 共用同一套形参遍历)。位置实参优先,关键字不可按出现顺序追加——乱序会串位 cargs: list[ast.AST*]* = cl.args can: sizet = 0 - if cargs is not None: - can = len(cargs) + if cargs is not None: can = len(cargs) keywords: list[ast.AST*]* = cl.keywords kw_count: sizet = 0 - if keywords is not None: - kw_count = len(keywords) + if keywords is not None: kw_count = len(keywords) extra_args: sizet* = pool.alloc_tagged(8 * 32, memhub.DETSITE_CALLGENCTOR_1175) - if extra_args is None: - return None + if extra_args is None: return None string.memset(extra_args, 0, 8 * 32) # 槽占用标志(0=空 1=已填),用于关键字定位后的连续性校验。 # 尺寸口径 = extra_args 同源:槽位数固定 32(下标 0..31,由下方 @@ -1222,8 +1130,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if kw_val is None: continue extra_args[sizet(slot_kw)] = sizet(kw_val) arg_filled[sizet(slot_kw)] = 1 - if slot_kw > arg_max_filled: - arg_max_filled = slot_kw + if slot_kw > arg_max_filled: arg_max_filled = slot_kw # 槽位必须连续(0..arg_max_filled 全满):出现空洞说明某形参既未给位置 # 实参也未给关键字实参(Python 会报缺参)——禁止把空洞当 0 传(会让 # __init__ 收到错位实参),fail-fast 暴露。 @@ -1234,8 +1141,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): break ci_hole += 1 arg_count: int = 0 - if arg_max_filled >= 0: - arg_count = arg_max_filled + 1 + if arg_max_filled >= 0: arg_count = arg_max_filled + 1 # 值位置 volatile 前缀:`a: T = volatile list[int](mb)` —— 构造写入带 volatile gc_volatile: int = cl.IsVolatile @@ -1245,8 +1151,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # (与 _translate_struct_ctor 保持一致,避免为无 __new__ 的类生成过度声明) storage_ptr: mlirlite.Value* = tmp has_new_flag: int = 0 - if struct_entry is not None: - has_new_flag = struct_entry.HasNew + if struct_entry is not None: has_new_flag = struct_entry.HasNew if has_new_flag != 0: new_ptr: mlirlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__new__", tmp, extra_args, arg_count, trans, None, gc_volatile) if new_ptr is not None: @@ -1261,8 +1166,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): nw_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, struct_ty) if uint64(new_ptr.Ty) != uint64(nw_ty): nw_bc: mlirlite.Value* = mlirlite.build_bitcast(builder, new_ptr, nw_ty) - if nw_bc is not None: - storage_ptr = nw_bc + if nw_bc is not None: storage_ptr = nw_bc # call __before_init__(storage_ptr)(TransPyV 自动生成,零值填充) self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__before_init__", storage_ptr, None, 0, trans, None, gc_volatile) diff --git a/App/lib/core/Gen/Call/CallGenDispatch.vp b/App/lib/core/Gen/Call/CallGenDispatch.vp index 2fa75cc..3949c68 100644 --- a/App/lib/core/Gen/Call/CallGenDispatch.vp +++ b/App/lib/core/Gen/Call/CallGenDispatch.vp @@ -61,15 +61,13 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): sn: ast.Name* = ast.Name*(sub.value) tpl_name = sn.id explicit_slice = sub.slice - elif fk == ast.ASTKind.Name: - tpl_name = func_name + elif fk == ast.ASTKind.Name: tpl_name = func_name elif fk == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(cl.func) if at.attr is not None and at.value is not None and at.value.kind() == ast.ASTKind.Name: mn: ast.Name* = ast.Name*(at.value) if mn.id is not None and trans._imported_modules is not None: - if self.Gen.ImportsGen.is_module_imported_or_known(trans._imported_modules, mn.id) != 0: - tpl_mod_sha1 = self._lookup_module_sha1(mn.id) + if self.Gen.ImportsGen.is_module_imported_or_known(trans._imported_modules, mn.id) != 0: tpl_mod_sha1 = self._lookup_module_sha1(mn.id) # 仅当基座是**已导入模块**时才按模块限定泛型函数处理; # 否则 `obj.add(x)` 里 obj 不是模块,绝不能按裸名 local 键 # 命中同名模块级泛型函数 add 而劫持方法调用。 @@ -83,19 +81,16 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # 模块限定调用:只认该模块 SHA1 的键 if tpl_mod_sha1 is not None: cand_q: str = self._generic_func_key(pool, tpl_mod_sha1, tpl_name) - if self.Gen.ClassGenGeneric._find_generic_func_template(cand_q) is not None: - tpl_key = cand_q + if self.Gen.ClassGenGeneric._find_generic_func_template(cand_q) is not None: tpl_key = cand_q else: if trans.ModuleSha1 is not None: cand_l: str = self._generic_func_key(pool, trans.ModuleSha1, tpl_name) - if self.Gen.ClassGenGeneric._find_generic_func_template(cand_l) is not None: - tpl_key = cand_l + if self.Gen.ClassGenGeneric._find_generic_func_template(cand_l) is not None: tpl_key = cand_l if tpl_key is None and trans._from_imports is not None: imp_sha: str = self._lookup_mod_sha1(pool, trans._from_imports, tpl_name, 0) if imp_sha is not None: cand_f: str = self._generic_func_key(pool, imp_sha, tpl_name) - if self.Gen.ClassGenGeneric._find_generic_func_template(cand_f) is not None: - tpl_key = cand_f + if self.Gen.ClassGenGeneric._find_generic_func_template(cand_f) is not None: tpl_key = cand_f if tpl_key is None: return None template_fd: ast.FunctionDef* = self.Gen.ClassGenGeneric._find_generic_func_template(tpl_key) if template_fd is None: return None @@ -123,17 +118,14 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): tp_name: str = tp_names.get(tpi) ta: str = None slot: int = self.Gen.ClassGenGeneric._find_generic_func_param_slot(template_fd, tp_name) - if slot >= 0 and sizet(slot) < can: - ta = self.Gen.ClassGenGeneric._infer_generic_func_type_arg(pool, cargs.get(sizet(slot)), tpl_name, trans) + if slot >= 0 and sizet(slot) < can: ta = self.Gen.ClassGenGeneric._infer_generic_func_type_arg(pool, cargs.get(sizet(slot)), tpl_name, trans) if ta is None and slot >= 0: # 关键字实参:按模板形参名定位(位置优先,槽位已被位置实参占用则 -1) kwi: int = self._generic_func_kw_arg_index(template_fd, slot, cl.keywords, int(can)) if kwi >= 0: kwn: rawptr[ast.Keyword] = rawptr[ast.Keyword](cl.keywords.get(sizet(kwi))) - 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 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});" @@ -181,10 +173,8 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): ki: sizet for ki in range(kn): kw: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(ki)) - if kw is None or kw.arg is None: - continue - if string.strcmp(kw.arg, ag.arg) == 0: - return int(ki) + if kw is None or kw.arg is None: continue + if string.strcmp(kw.arg, ag.arg) == 0: return int(ki) return -1 def _emit_generic_func_call(self, pool: memhub.MemBuddy*, @@ -209,8 +199,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if kw is not None and len(kw) > 0: self.Gen.TypeGenErr.fatal_error(cl, "泛型函数调用暂不支持关键字实参,请改用位置实参", "TypeError") return None - if hit_box is not None: - hit_box[0] = 1 + if hit_box is not None: hit_box[0] = 1 param_count: int = 0 pp: mlirlite.Param* = mlirlite.function_get_param_head(func) while pp is not None: @@ -228,21 +217,16 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): while ai < can: arg: ast.AST* = cargs.get(ai) fpty: mlirlite.LLVMType* = None - if fp is not None: - fpty = mlirlite.param_get_ty(fp) + 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, "形参") if av is not None: - if fpty is not None: - av = self.Gen.ExprGenBase.coerce_to_type(builder, av, fpty, arg, trans) + if fpty is not None: av = self.Gen.ExprGenBase.coerce_to_type(builder, av, fpty, arg, trans) av.Next = None - if head is None: - head = av - else: - tail.Next = av + if head is None: head = av + else: tail.Next = av tail = av - if fp is not None: - fp = mlirlite.param_get_next(fp) + if fp is not None: fp = mlirlite.param_get_next(fp) ai += 1 # build_call 的第二参是**被调符号名字符串**(callee: str),不是 Function*—— # 传 Function* 会被当成字符串读到结构体首字段(Next 指针),发射出 @@ -279,8 +263,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if sup_cl.func is not None and sup_cl.func.kind() == ast.ASTKind.Name: sup_nm: ast.Name* = ast.Name*(sup_cl.func) if sup_nm.id is not None and string.strcmp(sup_nm.id, "super") == 0: - if hit_box is not None: - hit_box[0] = 1 + if hit_box is not None: hit_box[0] = 1 return self.Gen.CallGenCall._translate_super_call(pool, builder, mod, cl, func_name, trans) # ctraits 宏库编译期谓词:ctraits.isptr(x) 不生成运行时调用, @@ -298,8 +281,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): ct_nm0: ast.Name* = ast.Name*(ct_arg0) if ct_nm0.id is not None and trans is not None: ct_r: int = self.Gen.StmtGenCif._eval_ctraits_isptr(trans.SymTab, ct_nm0.id) - if ct_r > 0: - return mlirlite.const_int32(pool, 1) + if ct_r > 0: return mlirlite.const_int32(pool, 1) return mlirlite.const_int32(pool, 0) return None @@ -329,13 +311,11 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if bare_nm.id is not None and string.strcmp(bare_nm.id, "__asm__") == 0: # 无输出(void)时 translate_c_asm 返回 None:置命中标记, # 避免 translate_call 误判未命中继续走外部函数路径。 - if hit_box is not None: - hit_box[0] = 1 + if hit_box is not None: hit_box[0] = 1 return self.Gen.CallGenCBuiltin.translate_c_asm(pool, builder, mod, cl, trans) if bare_nm.id is not None and string.strcmp(bare_nm.id, "__llvmir__") == 0: # c.LLVMIR 总是无返回值(返回 None):置命中标记 - if hit_box is not None: - hit_box[0] = 1 + if hit_box is not None: hit_box[0] = 1 return self.Gen.CallGenCBuiltin.translate_c_llvmir(pool, builder, mod, cl, trans) if bare_nm.id is not None and (string.strcmp(bare_nm.id, "irinp") == 0 or string.strcmp(bare_nm.id, "irout") == 0): # irinp/irout 独立调用时返回 0(仅在 __llvmir__ 的 f-string 内有意义) @@ -348,31 +328,24 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if at_node.value is not None and at_node.value.kind() == ast.ASTKind.Name: mod_nm: ast.Name* = ast.Name*(at_node.value) is_coro_mod: int = 0 - if mod_nm.id is not None and string.strcmp(mod_nm.id, "coro") == 0: - is_coro_mod = 1 + if mod_nm.id is not None and string.strcmp(mod_nm.id, "coro") == 0: is_coro_mod = 1 if mod_nm.id is not None and (string.strcmp(mod_nm.id, "c") == 0 or is_coro_mod != 0): - if string.strcmp(func_name, "Deref") == 0: - return self.Gen.CallGenCBuiltin.translate_c_deref(pool, builder, mod, cl, trans) - elif string.strcmp(func_name, "DerefAs") == 0: - return self.Gen.CallGenCBuiltin.translate_c_derefas(pool, builder, mod, cl, trans) - elif string.strcmp(func_name, "Addr") == 0: - return self.Gen.CallGenCBuiltin.translate_c_addr(pool, builder, mod, cl, trans) + if string.strcmp(func_name, "Deref") == 0: return self.Gen.CallGenCBuiltin.translate_c_deref(pool, builder, mod, cl, trans) + elif string.strcmp(func_name, "DerefAs") == 0: return self.Gen.CallGenCBuiltin.translate_c_derefas(pool, builder, mod, cl, trans) + elif string.strcmp(func_name, "Addr") == 0: return self.Gen.CallGenCBuiltin.translate_c_addr(pool, builder, mod, cl, trans) elif string.strcmp(func_name, "Set") == 0: # c.Set(a, b) = a = b(赋值语义,非指针解引用)。 # 若当普通函数调用会生成 @Set 引用导致链接失败(undefined reference to `Set')。 return self.Gen.CallGenCBuiltin.translate_c_set(pool, builder, mod, cl, trans) - elif string.strcmp(func_name, "Load") == 0: - return self.Gen.CallGenCBuiltin.translate_c_load(pool, builder, mod, cl, trans) + elif string.strcmp(func_name, "Load") == 0: return self.Gen.CallGenCBuiltin.translate_c_load(pool, builder, mod, cl, trans) elif string.strcmp(func_name, "Asm") == 0: # c.Asm 无输出(void)时 translate_c_asm 返回 None: # 置命中标记,避免 translate_call 误判未命中继续走外部函数 - if hit_box is not None: - hit_box[0] = 1 + if hit_box is not None: hit_box[0] = 1 return self.Gen.CallGenCBuiltin.translate_c_asm(pool, builder, mod, cl, trans) elif string.strcmp(func_name, "LLVMIR") == 0: # c.LLVMIR 总是无返回值(返回 None):置命中标记 - if hit_box is not None: - hit_box[0] = 1 + if hit_box is not None: hit_box[0] = 1 return self.Gen.CallGenCBuiltin.translate_c_llvmir(pool, builder, mod, cl, trans) elif string.strcmp(func_name, "LInp") == 0 or string.strcmp(func_name, "LOut") == 0: # c.LInp/c.LOut 独立调用时返回 0(仅在 c.LLVMIR 的 f-string 内有意义) @@ -385,8 +358,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): cif_arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cif_args.get(0), funcs_ptr, func_count, trans) if cif_arg_val is not None: cif_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(cif_arg_val.Ty) - if cif_bits == 1: - return cif_arg_val + if cif_bits == 1: return cif_arg_val if self.Gen.ExprGenBase.is_ptr_type(cif_arg_val.Ty) != 0: cif_null: mlirlite.Value* = mlirlite.ConstNull(pool, cif_arg_val.Ty, "null") return mlirlite.build_icmp(builder, mlirlite.ICMP_NE, cif_arg_val, cif_null) @@ -467,8 +439,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # 对象定义了 __str__ → 调度 __str__(对齐 TPC HandlesExprBuiltin) if string.strcmp(cast_fn_name, "str") == 0: str_ov: mlirlite.Value* = self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, cast_arg, "__str__", trans) - if str_ov is not None: - return str_ov + if str_ov is not None: return str_ov i8_ptr_ty_builtin: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, cast_arg, i8_ptr_ty_builtin) return None @@ -491,20 +462,17 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # 整数: icmp ne x, 0 if arg_bits != 0: zero_int: mlirlite.Value* = mlirlite.const_int(pool, arg_bits, 0) - if zero_int is not None: - return mlirlite.build_icmp(builder, mlirlite.ICMP_NE, cast_arg_bool, zero_int) + if zero_int is not None: return mlirlite.build_icmp(builder, mlirlite.ICMP_NE, cast_arg_bool, zero_int) return None # 浮点: fcmp one x, 0.0 if arg_fbits != 0: zero_ty: mlirlite.LLVMType* = cast_arg_bool.Ty zero_flt: mlirlite.Value* = mlirlite.ConstFloat(pool, zero_ty, 0.0) - if zero_flt is not None: - return mlirlite.build_fcmp(builder, mlirlite.FCMP_ONE, cast_arg_bool, zero_flt) + if zero_flt is not None: return mlirlite.build_fcmp(builder, mlirlite.FCMP_ONE, cast_arg_bool, zero_flt) return None # 指针: icmp ne x, null ptr_null: mlirlite.Value* = mlirlite.ConstNull(pool, cast_arg_bool.Ty, "null") - if ptr_null is not None: - return mlirlite.build_icmp(builder, mlirlite.ICMP_NE, cast_arg_bool, ptr_null) + if ptr_null is not None: return mlirlite.build_icmp(builder, mlirlite.ICMP_NE, cast_arg_bool, ptr_null) return None return None return None @@ -558,13 +526,11 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if cty_at3.attr is not None and string.strcmp(cty_at3.attr, "CPtr") == 0: if cty_at3.value is not None and cty_at3.value.kind() == ast.ASTKind.Name: cty_nm3: ast.Name* = ast.Name*(cty_at3.value) - if cty_nm3.id is not None and string.strcmp(cty_nm3.id, "t") == 0: - cty_is_cptr = 1 + if cty_nm3.id is not None and string.strcmp(cty_nm3.id, "t") == 0: cty_is_cptr = 1 # 形式 2: 裸名 CPtr elif cty_arg3.kind() == ast.ASTKind.Name: cty_bn3: ast.Name* = ast.Name*(cty_arg3) - if cty_bn3.id is not None and string.strcmp(cty_bn3.id, "CPtr") == 0: - cty_is_cptr = 1 + if cty_bn3.id is not None and string.strcmp(cty_bn3.id, "CPtr") == 0: cty_is_cptr = 1 if cty_is_cptr != 0: # CVoid* → i8*(LLVM 中 void* 表示为 i8*) match ctype_target: @@ -576,8 +542,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): cty_arg0: ast.AST* = cargs.get(0) if cty_arg0 is not None: cty_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cty_arg0, funcs_ptr, func_count, trans) - if cty_val is not None: - return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, cty_val, ctype_target, cty_arg0, trans) + if cty_val is not None: return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, cty_val, ctype_target, cty_arg0, trans) # t.CType 语法已确认:即使类型解析失败也不跌落到跨模块 FATAL return None # CConst const 标记:CConst(val, t.CPtr) → Ptr(i8)(const void*)。 @@ -592,10 +557,8 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if can >= 2: cconst_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) cconst_arg: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans) - if cconst_arg is not None: - return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, cconst_arg, cconst_ptr_ty, cargs.get(0), trans) - elif can == 1: - return self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans) + if cconst_arg is not None: return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, cconst_arg, cconst_ptr_ty, cargs.get(0), trans) + elif can == 1: return self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans) return None target_ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.map_t_type(pool, func_name) if target_ty is not None: @@ -612,13 +575,11 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if tc_arg2_at.attr is not None and string.strcmp(tc_arg2_at.attr, "CPtr") == 0: if tc_arg2_at.value is not None and tc_arg2_at.value.kind() == ast.ASTKind.Name: tc_arg2_nm: ast.Name* = ast.Name*(tc_arg2_at.value) - if tc_arg2_nm.id is not None and string.strcmp(tc_arg2_nm.id, "t") == 0: - tc_arg2_is_cptr = 1 + if tc_arg2_nm.id is not None and string.strcmp(tc_arg2_nm.id, "t") == 0: tc_arg2_is_cptr = 1 # 形式 2: 裸名 CPtr(from t import CPtr 后直接使用,如 t.CXXX(x, CPtr)) elif tc_arg2_node.kind() == ast.ASTKind.Name: tc_arg2_bn: ast.Name* = ast.Name*(tc_arg2_node) - if tc_arg2_bn.id is not None and string.strcmp(tc_arg2_bn.id, "CPtr") == 0: - tc_arg2_is_cptr = 1 + if tc_arg2_bn.id is not None and string.strcmp(tc_arg2_bn.id, "CPtr") == 0: tc_arg2_is_cptr = 1 if tc_arg2_is_cptr != 0: # CVoid* → i8*(LLVM 中 void* 表示为 i8*) match target_ty: @@ -636,8 +597,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # `uint64(0xFFFFFFFFFFFFFFFF)`(词法回绕为 -1)被 # 物化成 i32 -1 再 zext → 0x00000000FFFFFFFF(N1)。 tc_arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, tc_arg_node, None, 0, trans, target_ty) - if tc_arg_val is not None: - return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, tc_arg_val, target_ty, tc_arg_node, trans) + if tc_arg_val is not None: return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, tc_arg_val, target_ty, tc_arg_node, trans) # t.XXX 类型转换已确认但不满足参数条件:返回 None,不跌落到跨模块 FATAL return None @@ -665,8 +625,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): mod_td_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, mod_td_ast, mod_imp_td, mod_fi_td, trans, 0) if mod_td_ty is not None and can == 1: mt_arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans, mod_td_ty) - if mt_arg_val is not None: - return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, mt_arg_val, mod_td_ty, cargs.get(0), trans) + if mt_arg_val is not None: return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, mt_arg_val, mod_td_ty, cargs.get(0), trans) # 裸名 typedef 调用: BYTEPTR(ptr1), HANDLE(val), CHARPTR(str) 等 # 用户通过 `from stdint import *` 导入 typedef 后,可直接用裸名做类型转换 @@ -680,10 +639,8 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): bare_ty: mlirlite.LLVMType* = None # 泛型上下文解析出的内建名(如 T→"double"/"float"):map_t_type 只认 t.CDouble, # 且 float 必须映射 t.CFloat(f32)而非 f64(与注解语义一致) - if string.strcmp(bare_fn_name, "double") == 0: - bare_ty = mlirlite.Double(pool) - elif string.strcmp(bare_fn_name, "float") == 0: - bare_ty = mlirlite.Float(pool) + if string.strcmp(bare_fn_name, "double") == 0: bare_ty = mlirlite.Double(pool) + elif string.strcmp(bare_fn_name, "float") == 0: bare_ty = mlirlite.Float(pool) else: # 统一口径:CTypedef 动态表优先(BYTEPTR 等库 typedef 强转), # miss 回退 map_t_type(t/c 核心原语强转,阶段2 收敛后 map_t_type @@ -720,13 +677,11 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if bare_arg2_at.attr is not None and string.strcmp(bare_arg2_at.attr, "CPtr") == 0: if bare_arg2_at.value is not None and bare_arg2_at.value.kind() == ast.ASTKind.Name: bare_arg2_nm: ast.Name* = ast.Name*(bare_arg2_at.value) - if bare_arg2_nm.id is not None and string.strcmp(bare_arg2_nm.id, "t") == 0: - bare_arg2_is_cptr = 1 + if bare_arg2_nm.id is not None and string.strcmp(bare_arg2_nm.id, "t") == 0: bare_arg2_is_cptr = 1 # 形式 2: 裸名 CPtr(from t import CPtr 后直接使用) elif bare_arg2_node.kind() == ast.ASTKind.Name: bare_arg2_bn: ast.Name* = ast.Name*(bare_arg2_node) - if bare_arg2_bn.id is not None and string.strcmp(bare_arg2_bn.id, "CPtr") == 0: - bare_arg2_is_cptr = 1 + if bare_arg2_bn.id is not None and string.strcmp(bare_arg2_bn.id, "CPtr") == 0: bare_arg2_is_cptr = 1 if bare_arg2_is_cptr != 0: # CVoid* → i8*(LLVM 中 void* 表示为 i8*) match bare_ty: @@ -738,16 +693,14 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): bare_arg_node: ast.AST* = cargs.get(0) if bare_arg_node is not None: bare_arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, bare_arg_node, None, 0, trans, bare_ty) - if bare_arg_val is not None: - return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, bare_arg_val, bare_ty, bare_arg_node, trans) + if bare_arg_val is not None: return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, bare_arg_val, bare_ty, bare_arg_node, trans) if bare_ty is not None and can == 1: bare_arg_node: ast.AST* = cargs.get(0) if bare_arg_node is not None: # 第 8 参 target_ty 下传:裸名 typedef 强转(如 uint64(x))的 # 目标位宽必须参与常量物化(N1)。 bare_arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, bare_arg_node, None, 0, trans, bare_ty) - if bare_arg_val is not None: - return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, bare_arg_val, bare_ty, bare_arg_node, trans) + if bare_arg_val is not None: return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, bare_arg_val, bare_ty, bare_arg_node, trans) return None @@ -820,8 +773,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): gpn: str = trans.GenericTypeParamNames.get(gp_i) if gpn is not None and string.strcmp(sz_orig, gpn) == 0: gta: str = trans.GenericTypeArgs.get(gp_i) - if gta is not None: - sz_cls_name = gta + if gta is not None: sz_cls_name = gta break sz_resolved_name = sz_cls_name # 指针包装类型检查必须在 dot-strip 之前:类型实参可能带 sha1 @@ -830,10 +782,8 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # 前缀/联合判断永远失配 → 落回把接收者 Name(T) 当实例翻译 → # NameError: 未定义名称 'T'(SlotsBugTest rawptr[list[rawptr[AST]]] 根因)。 # 联合类型(X*)与新一代指针包装 rawptr[X] 均按指针大小 8。 - if string.strstr(sz_cls_name, "|") is not None: - return mlirlite.const_int64(pool, 8) - if string.strncmp(sz_cls_name, "rawptr[", 7) == 0: - return mlirlite.const_int64(pool, 8) + if string.strstr(sz_cls_name, "|") is not None: return mlirlite.const_int64(pool, 8) + if string.strncmp(sz_cls_name, "rawptr[", 7) == 0: return mlirlite.const_int64(pool, 8) # 归一后的指针唯一规范形 `T*`(TypeGenResolve._norm_type_arg_name # 的指针书写归一:rawptr[T] ≡ t.CPtr[T] ≡ T* ≡ T*) # ⇒ **尾随** '*' 一律按指针大小 8(多级 `**` 同为 8)。 @@ -845,10 +795,8 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # NameError: 未定义名称 'T'(现场 Test/AstTest/App/main.vp:21 # 特化 list[ast.AST*] → includes/_list.vp:36)。 _sz_len_s: sizet = string.strlen(sz_cls_name) - while _sz_len_s > 0 and sz_cls_name[_sz_len_s - 1] == ' ': - _sz_len_s -= 1 - if _sz_len_s > 0 and sz_cls_name[_sz_len_s - 1] == '*': - return mlirlite.const_int64(pool, 8) + while _sz_len_s > 0 and sz_cls_name[_sz_len_s - 1] == ' ': _sz_len_s -= 1 + if _sz_len_s > 0 and sz_cls_name[_sz_len_s - 1] == '*': return mlirlite.const_int64(pool, 8) # 保存完整名(含模块前缀)供模块归属精确匹配:去前缀后 # get_struct_type 裸名全局匹配会误命中跨模块同名类 # (w32.win32base.SECURITY_ATTRIBUTES 根因)。 @@ -857,8 +805,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # 而非 Attribute(value=Name("t"), attr="CInt"),需要手动提取最后的类名分量 # "int" → "CInt", "w32.win32file.WIN32_FIND_DATAA" → "WIN32_FIND_DATAA" dot_pos: str = string.strrchr(sz_cls_name, '.') - if dot_pos is not None: - sz_cls_name = dot_pos + 1 + if dot_pos is not None: sz_cls_name = dot_pos + 1 # [阶段3] 统一尺寸口径:库 typedef(BYTE/DWORD 等)先经正常 # 库分析解析(resolve_typedef_or_map → 位宽/8),miss 才走 # 下方硬编码尺寸表(t/c 核心原语)。 @@ -870,8 +817,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): dyn_sz_c: int = self.Gen.TypeGenResolve.get_type_size_bytes(pool, sz_cls_name, trans._imported_modules if trans is not None else None, trans._from_imports if trans is not None else None) - if dyn_sz_c > 0: - return mlirlite.const_int64(pool, dyn_sz_c) + if dyn_sz_c > 0: return mlirlite.const_int64(pool, dyn_sz_c) # 内置类型 sizeof(int=4, str/bytes=8 指针, double=8 等) sz_builtin: int = -1 if string.strcmp(sz_cls_name, "int") == 0: sz_builtin = 4 @@ -918,10 +864,8 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): szf_sha1: str = self.Gen.StructGen._resolve_module_sha1(szf_mod, trans._from_imports if trans is not None else None) if szf_sha1 is not None: szf_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(sz_cls_name, szf_sha1) - if szf_entry is not None and szf_entry.Ty is not None: - sz_resolved_ty = szf_entry.Ty - if sz_resolved_ty is None: - sz_resolved_ty = self.Gen.StructGen.get_struct_type(sz_cls_name) + if szf_entry is not None and szf_entry.Ty is not None: sz_resolved_ty = szf_entry.Ty + if sz_resolved_ty is None: sz_resolved_ty = self.Gen.StructGen.get_struct_type(sz_cls_name) # 回退 1: 泛型类引用接收者 Stack[T].__sizeof__() — Subscript → 特化后计算大小 # (GenericTest2 Stack.type_size 依赖此路径) if sz_resolved_ty is None and trans is not None and sz_vk == ast.ASTKind.Subscript: @@ -971,13 +915,11 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): pass if sz_resolved_ty is not None: sz_val: int = self.Gen.ClassGenEnum._get_type_size(sz_resolved_ty) - if sz_val > 0: - return mlirlite.const_int64(pool, sz_val) + if sz_val > 0: return mlirlite.const_int64(pool, sz_val) # 类型已注册但大小为 0(opaque struct 或字段链表未填充):Python 风格报错终止 self.Gen.TypeGenErr.fatal_error(sz_at, f"类型 '{sz_resolved_name}' 已注册但大小为 0(字段链表未填充),无法计算大小", "TypeError") # 类型未注册:Python 风格报错终止,不静默返回 0(会导致 malloc(0)/alloc(0) 堆溢出) - if sz_resolved_name is None: - sz_resolved_name = "(unknown)" + if sz_resolved_name is None: sz_resolved_name = "(unknown)" self.Gen.TypeGenErr.fatal_error(sz_at, f"类型 '{sz_resolved_name}' 未在结构体表中注册,无法计算大小", "TypeError") # 检测 len(obj) — 返回 list 对象的 __count__ 字段(偏移 8,i64) @@ -1004,8 +946,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # 导致 GEP 索引为 0(访问 __data__)而非 1(访问 __count__) idx_one: mlirlite.Value* = mlirlite.const_int64(pool, 1) count_ptr: mlirlite.Value* = mlirlite.build_gep(builder, i64_ty_len, obj_val, idx_one) - if count_ptr is not None: - return mlirlite.build_load(builder, i64_ty_len, count_ptr) + if count_ptr is not None: return mlirlite.build_load(builder, i64_ty_len, count_ptr) # 检测 len() 内置函数调用 — 结构体对象走 __len__ 方法,字符串走 strlen # len(s) 对 str 类型调用 strlen,返回 i64 @@ -1040,8 +981,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): len_arr_n = len_arr_cnt case _: pass - if len_is_arr != 0: - return mlirlite.const_int64(pool, len_arr_n) + if len_is_arr != 0: return mlirlite.const_int64(pool, len_arr_n) # len(对象):有 __len__ 就调用,没有就编译期报错 # (用户要求 2026-08-15,不再静默 strlen 读对象首字段): # - list 泛型内置容器:__len__ 由 list 内置分支内联 @@ -1053,8 +993,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() 参数类型推断失败(结构体类名未知)", "TypeError") # list 内置 __len__:读 __count__(GEP 偏移 1,i64) # 判据优先取接收者实际类型(_is_list_builtin_receiver) # 目标类型已由 can==1(len 的实参存在)确定为表达式节点 @@ -1066,8 +1005,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): i64_ty_lb: mlirlite.LLVMType* = mlirlite.Int64(pool) idx_one_lb: mlirlite.Value* = mlirlite.const_int64(pool, 1) cnt_ptr_lb: mlirlite.Value* = mlirlite.build_gep(builder, i64_ty_lb, len_val, idx_one_lb) - if cnt_ptr_lb is not None: - return mlirlite.build_load(builder, i64_ty_lb, cnt_ptr_lb) + if cnt_ptr_lb is not None: return mlirlite.build_load(builder, i64_ty_lb, cnt_ptr_lb) len_lookup: str = pool.alloc(128) if len_lookup is not None: viperlib.snprintf(len_lookup, 128, "%s.__len__", len_cls_nm) @@ -1081,8 +1019,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): len_first_param2: mlirlite.Param* = mlirlite.function_get_param_head(len_fn2) if len_first_param2 is not None: len_self_ty2: mlirlite.LLVMType* = mlirlite.param_get_ty(len_first_param2) - if len_self_ty2 is not None and len_val.Ty is not None: - len_self_arg2 = mlirlite.build_bitcast(builder, len_val, len_self_ty2) + if len_self_ty2 is not None and len_val.Ty is not None: len_self_arg2 = mlirlite.build_bitcast(builder, len_val, len_self_ty2) len_self_arg2.Next = None return mlirlite.build_call(builder, len_fn_name2, len_self_arg2, 1, len_ret_ty2, 0) # len_fn2 未命中(跨模块方法):如 ndarray[t.CDouble].__len__ @@ -1102,8 +1039,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if len_mangled_x is not None: viperlib.snprintf(len_mangled_x, len_ml_x, "%s.%s.__len__", len_cls_sha1_x, len_cls_nm) len_ret_x: mlirlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, len_cls_sha1_x, len_cls_nm, "__len__") - if len_ret_x is None: - len_ret_x = self._LookupMethodRetTyFromTextLL(pool, len_cls_sha1_x, len_cls_nm, "__len__") + if len_ret_x is None: len_ret_x = self._LookupMethodRetTyFromTextLL(pool, len_cls_sha1_x, len_cls_nm, "__len__") if len_ret_x is not None: # self 参数按对象实际类型 Ptr(len_struct_ty)(与定义侧 # 同名类型链接匹配);len_val 已是 load 后的对象指针。 @@ -1124,8 +1060,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if len_pt_ty is not None: match len_pt_ty: case mlirlite.LLVMType.Int(len_pt_bits): - if len_pt_bits == 8: - len_is_str = 1 + if len_pt_bits == 8: len_is_str = 1 case _: pass case _: @@ -1137,13 +1072,11 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): i64_ty_ln: mlirlite.LLVMType* = mlirlite.Int64(pool) i8_ptr_ty_ln: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) strlen_fn = mlirlite.create_declare(pool, mod, "strlen", i64_ty_ln) - if strlen_fn is not None: - mlirlite.add_param(pool, strlen_fn, i8_ptr_ty_ln, "s") + if strlen_fn is not None: mlirlite.add_param(pool, strlen_fn, i8_ptr_ty_ln, "s") # 参数类型转换为 i8* i8_ptr_ty_ln2: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) len_coerced: mlirlite.Value* = len_val - if self.Gen.ExprGenBase.is_ptr_type(len_arg_ty) != 0: - len_coerced = mlirlite.build_bitcast(builder, len_val, i8_ptr_ty_ln2) + if self.Gen.ExprGenBase.is_ptr_type(len_arg_ty) != 0: len_coerced = mlirlite.build_bitcast(builder, len_val, i8_ptr_ty_ln2) # 构建单参数链表并调用 strlen len_coerced.Next = None i64_ty_ln2: mlirlite.LLVMType* = mlirlite.Int64(pool) @@ -1159,8 +1092,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if func_name is not None and string.strcmp(func_name, "isinstance") == 0: if can >= 2: is_res: mlirlite.Value* = self.Gen.CallGenLeafKit._translate_isinstance(pool, builder, mod, cargs.get(0), cargs.get(1), trans) - if is_res is not None: - return is_res + if is_res is not None: return is_res return None @@ -1232,19 +1164,14 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # 类型落空(实况:CallGenLib.vp:355 `vk_a: int = val.Ty.kind()` 报 # 「指针隐式转整数已禁止」)。 if rk_cls is not None: - if self.Gen.ClassGenEnum._is_renum_class_name(rk_cls) != 0 or self.Gen.ClassGenEnum._is_renum_by_entry(rk_cls) != 0: - rk_is_rn = 1 - else: - rk_cls = None + if self.Gen.ClassGenEnum._is_renum_class_name(rk_cls) != 0 or self.Gen.ClassGenEnum._is_renum_by_entry(rk_cls) != 0: rk_is_rn = 1 + else: rk_cls = None # ③:类名反查不到也不要紧——直接看 pointee 结构体带不带 __tag。 # 顺带把 __tag 的字段声明类型记为 kind() 返回类型真源(第 2 层)。 rk_tag_fe: GenTypes.FieldEntry* = None - if rk_pointee is not None: - rk_tag_fe = self.Gen.StructGen.lookup_field(rk_pointee, "__tag") - if rk_is_rn == 0 and rk_tag_fe is not None: - rk_is_rn = 1 - if rk_tag_fe is not None and rk_tag_fe.Ty is not None: - rk_tag_ty = rk_tag_fe.Ty + if rk_pointee is not None: rk_tag_fe = self.Gen.StructGen.lookup_field(rk_pointee, "__tag") + if rk_is_rn == 0 and rk_tag_fe is not None: rk_is_rn = 1 + if rk_tag_fe is not None and rk_tag_fe.Ty is not None: rk_tag_ty = rk_tag_fe.Ty # 注解兜底:联合简化/退化后运行时类型丢失(如 # resolved: mlirlite.LLVMType* 存 i8*,pointee 非 # 结构体),用变量注解类名识别 REnum 类(kind() 语义: @@ -1257,18 +1184,15 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if rk_annot_raw is not None: # 截断联合/泛型后缀(" | t.CPtr" / "[...]") rk_ae: sizet = 0 - while rk_annot_raw[rk_ae] != '\0' and rk_annot_raw[rk_ae] != ' ' and rk_annot_raw[rk_ae] != '|' and rk_annot_raw[rk_ae] != '[': - rk_ae += 1 + while rk_annot_raw[rk_ae] != '\0' and rk_annot_raw[rk_ae] != ' ' and rk_annot_raw[rk_ae] != '|' and rk_annot_raw[rk_ae] != '[': rk_ae += 1 rk_ab: str = pool.alloc(rk_ae + 1) if rk_ab is not None: string.strncpy(rk_ab, rk_annot_raw, rk_ae) rk_ab[rk_ae] = '\0' # 去模块前缀("mlirlite.LLVMType" → "LLVMType") rk_ad: str = string.strrchr(rk_ab, '.') - if rk_ad is not None and rk_ad[1] != '\0': - rk_cls = rk_ad + 1 - else: - rk_cls = rk_ab + if rk_ad is not None and rk_ad[1] != '\0': rk_cls = rk_ad + 1 + else: rk_cls = rk_ab # 判据同上(表 或 struct 带 __tag),不再只认变体表 if self.Gen.ClassGenEnum._is_renum_class_name(rk_cls) != 0 or self.Gen.ClassGenEnum._is_renum_by_entry(rk_cls) != 0: rk_is_rn = 1 @@ -1276,10 +1200,8 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): rk_st_b: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(rk_cls) if rk_st_b is not None: rk_fe_b: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(rk_st_b, "__tag") - if rk_fe_b is not None and rk_fe_b.Ty is not None: - rk_tag_ty = rk_fe_b.Ty - else: - rk_cls = None + if rk_fe_b is not None and rk_fe_b.Ty is not None: rk_tag_ty = rk_fe_b.Ty + else: rk_cls = None # 第 4 层兜底:接收者是 `X.field` 形状时,运行时类型可能整体退化 # (rk_ty 不是"指向 REnum 结构体"的指针 ⇒ 上面三条判据都拿不到 # struct,只能用**声明**信息判):X 的注解类名 → struct → 该字段的 @@ -1296,8 +1218,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): rk_bannot: str = self.Gen.VarGen.var_annot_class_name(rk_bve) if rk_bannot is not None: rk_blen: sizet = 0 - while rk_bannot[rk_blen] != '\0' and rk_bannot[rk_blen] != ' ' and rk_bannot[rk_blen] != '|' and rk_bannot[rk_blen] != '[': - rk_blen += 1 + while rk_bannot[rk_blen] != '\0' and rk_bannot[rk_blen] != ' ' and rk_bannot[rk_blen] != '|' and rk_bannot[rk_blen] != '[': rk_blen += 1 rk_bbuf: str = pool.alloc(rk_blen + 1) if rk_bbuf is not None: string.strncpy(rk_bbuf, rk_bannot, rk_blen) @@ -1305,8 +1226,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # 去模块前缀("mlirlite.Value" → "Value") rk_bdot: str = string.strrchr(rk_bbuf, '.') rk_bcls: str = rk_bbuf - if rk_bdot is not None and rk_bdot[1] != '\0': - rk_bcls = rk_bdot + 1 + if rk_bdot is not None and rk_bdot[1] != '\0': rk_bcls = rk_bdot + 1 rk_bst: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(rk_bcls) if rk_bst is not None: rk_bfe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(rk_bst, rk_bat.attr) @@ -1314,8 +1234,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): rk_fpt: mlirlite.LLVMType* = rk_bfe.Ty if self.Gen.ExprGenBase.is_ptr_type(rk_fpt) != 0: rk_fpt = rk_fpt.Pointee - if rk_fpt is not None and self.Gen.ExprGenBase.is_ptr_type(rk_fpt) != 0: - rk_fpt = rk_fpt.Pointee + if rk_fpt is not None and self.Gen.ExprGenBase.is_ptr_type(rk_fpt) != 0: rk_fpt = rk_fpt.Pointee if rk_fpt is not None: rk_fcls: str = self.Gen.StructGen.get_class_name_by_type(pool, rk_fpt) if rk_fcls is not None: @@ -1324,10 +1243,8 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): rk_cls = rk_fcls rk_ffe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(rk_fpt, "__tag") if rk_ffe is not None: - if rk_is_rn == 0: - rk_is_rn = 1 - if rk_ffe.Ty is not None: - rk_tag_ty = rk_ffe.Ty + if rk_is_rn == 0: rk_is_rn = 1 + if rk_ffe.Ty is not None: rk_tag_ty = rk_ffe.Ty if rk_is_rn != 0: rk_val: mlirlite.Value* = rk_obj if rk_load != 0: @@ -1343,8 +1260,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): self.Gen.TypeGenErr.fatal_error(cl, f"REnum.kind() 翻译失败:接收者已判定为 REnum(变体表/__tag 判据命中)," f"但接收者指针解一层 load 失败(rk_load={rk_load})", "TypeError") - if hit_box is not None: - hit_box[0] = 1 + if hit_box is not None: hit_box[0] = 1 # 第 2 层:按 __tag 的**字段声明类型**取址并 load,不再硬编码 i32。 # 宽度口径交给赋值侧的隐式转换规则(coerce_to_type):整型↔整型 # (低向高无损 / 高向低可安全降级)自动提升降级,规则不覆盖的组合 @@ -1371,11 +1287,9 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # REnum 变体构造优先于静态/类方法调用: if self.Gen.ClassGenEnum._is_renum_class_name(st_nm.id) != 0: rc_tag_sc: int = self.Gen.ClassGenEnum._lookup_renum_variant_in_class(st_nm.id, func_name) - if rc_tag_sc >= 0: - return self.Gen.CallGenCtor._translate_renum_construct(pool, builder, mod, st_nm.id, func_name, rc_tag_sc, cargs, can, trans, cl.IsVolatile) + if rc_tag_sc >= 0: return self.Gen.CallGenCtor._translate_renum_construct(pool, builder, mod, st_nm.id, func_name, rc_tag_sc, cargs, can, trans, cl.IsVolatile) st_res: mlirlite.Value* = self.Gen.CallGenProp._translate_static_class_call(pool, builder, mod, st_nm.id, func_name, cl, trans) - if st_res is not None: - return st_res + if st_res is not None: return st_res # 实例方法经类名调用 ClassName.method(obj, args) → obj.method(args)(Python 语义,首参是 self 对象);但 st_nm.id == func_name(类名==方法名,如 CompilerFactory.CompilerFactory(...))是构造调用而非实例方法调用——本分支会误把模块限定类构造当 ClassName.method(obj,args) 且首实参当 self 传,导致返回类型查 "X.X" 永远落空 fail-fast。故跳过本分支,落到 translate_call 尾部的 ctor 检测 if can >= 1 and cargs is not None and string.strcmp(st_nm.id, func_name) != 0: im_self: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), None, 0, trans) @@ -1387,11 +1301,9 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): ri_im: sizet for ri_im in range(can - 1): im_rv: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(ri_im + 1), None, 0, trans) - if im_rv is not None: - im_rem[ri_im] = sizet(im_rv) + if im_rv is not None: im_rem[ri_im] = sizet(im_rv) im_res: mlirlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, st_nm.id, func_name, im_self, im_rem, can - 1, trans) - if im_res is not None: - return im_res + if im_res is not None: return im_res elif st_at.value.kind() == ast.ASTKind.Attribute: # 模块限定静态调用: module.ClassName.static_method(args) # cl.func = Attribute(value=Attribute(value=Name(module), @@ -1405,8 +1317,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # ClassName 是已注册结构体类名时尝试静态/类方法 if self.Gen.StructGen.get_struct_type(st_at2.attr) is not None: st_res2: mlirlite.Value* = self.Gen.CallGenProp._translate_static_class_call(pool, builder, mod, st_at2.attr, func_name, cl, trans) - if st_res2 is not None: - return st_res2 + if st_res2 is not None: return st_res2 # [M4·REPL 专用分支] 会话变量接收者的方法调用:`obj.m(args)` 的 obj 是**会话 # 变量**时,其值在 ctx 槽里、不在 SymTab ⇒ 上面的 lookup_var 分支恒不命中 @@ -1427,20 +1338,17 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if rp_ent.TyTag == GenTypes.REPL_TY_STRUCT: # 结构体值内联在槽里:槽地址即对象地址(self) rp_val = self.Gen.VarGen.repl_try_addr(trans, rp_nm.id, cl) - else: - rp_val = self.Gen.VarGen.repl_try_read(trans, rp_nm.id, cl) + else: rp_val = self.Gen.VarGen.repl_try_read(trans, rp_nm.id, cl) rp_cls: str = None if rp_val is not None and rp_val.Ty is not None: rp_sty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(rp_val) - if rp_sty is not None: - rp_cls = self.Gen.StructGen.get_class_name_by_type(pool, rp_sty) + if rp_sty is not None: rp_cls = self.Gen.StructGen.get_class_name_by_type(pool, rp_sty) if rp_cls is not None: rp_obj: mlirlite.Value* = rp_val if self.Gen.ExprGenBase.is_ptr_type(rp_val.Ty) != 0 and rp_val.Ty.Pointee != 0 and self.Gen.ExprGenBase.is_ptr_type(rp_val.Ty.Pointee) != 0: rp_obj = mlirlite.build_load(builder, rp_val.Ty, rp_val) if rp_obj is not None: - if hit_box is not None: - hit_box[0] = 1 + if hit_box is not None: hit_box[0] = 1 return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, rp_cls, rp_at.attr, rp_obj, cl, trans) # 会话变量命中但接收者不是结构体类(如 int/str/其它指针): # 不拦截、不置 hit,交给下方既有分支(list 内置/FakeDuck 等) @@ -1461,8 +1369,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if self.Gen.ExprGenBase.is_ptr_type(recv_ty_c) != 0: recv_ty_c = recv_ty_c.Pointee # 堆对象(@t.Object)双指针 → 再解一层取 struct - if self.Gen.ExprGenBase.is_ptr_type(recv_ty_c) != 0: - recv_ty_c = recv_ty_c.Pointee + if self.Gen.ExprGenBase.is_ptr_type(recv_ty_c) != 0: recv_ty_c = recv_ty_c.Pointee recv_cls_c: str = self.Gen.StructGen.get_class_name_by_type(pool, recv_ty_c) if recv_cls_c is not None: if self.Gen.CallGenProp._is_list_builtin_receiver(pool, recv_val_c, recv_cls_c, method_at.attr, cl) == 0: @@ -1470,8 +1377,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if self.Gen.ExprGenBase.is_ptr_type(recv_val_c.Ty) != 0 and recv_val_c.Ty.Pointee != 0 and self.Gen.ExprGenBase.is_ptr_type(recv_val_c.Ty.Pointee) != 0: obj_ptr_c = mlirlite.build_load(builder, recv_val_c.Ty, recv_val_c) if obj_ptr_c is not None: - if hit_box is not None: - hit_box[0] = 1 + if hit_box is not None: hit_box[0] = 1 return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, recv_cls_c, method_at.attr, obj_ptr_c, cl, trans) if method_at.value.kind() == ast.ASTKind.Name and trans is not None: method_obj_nm: ast.Name* = ast.Name*(method_at.value) @@ -1487,15 +1393,13 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): nl_obj: mlirlite.Value* = self.Gen.StmtGenDecl.load_nonlocal_var(trans, method_obj_nm.id) if nl_obj is not None and nl_obj.Ty is not None: nl_deref: mlirlite.Value* = self.Gen.ExprGenBase._deref_if_ptr_ptr(builder, nl_obj) - if nl_deref is None: - nl_deref = nl_obj + if nl_deref is None: nl_deref = nl_obj nl_struct: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(nl_deref) if nl_struct is not None: nl_cls: str = self.Gen.StructGen.get_class_name_by_type(pool, nl_struct) if nl_cls is not None: if self.Gen.CallGenProp._is_list_builtin_receiver(pool, nl_deref, nl_cls, func_name, cl) == 0: - if hit_box is not None: - hit_box[0] = 1 + if hit_box is not None: hit_box[0] = 1 return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, nl_cls, func_name, nl_deref, cl, trans) # 非 local 对象但分派未成功:绝不回退 lookup_var # (其 Alloca 是父函数存储,跨函数引用 → SSA 错乱), @@ -1510,11 +1414,9 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): la_buf: str = self.Gen.VarGen.var_annot_class_name(var_entry) if la_buf is not None: la_tail: str = la_buf - if string.strncmp(la_buf, "rawptr[", 7) == 0: - la_tail = la_buf + 7 + if string.strncmp(la_buf, "rawptr[", 7) == 0: la_tail = la_buf + 7 if string.strncmp(la_tail, "list", 4) == 0: - if self.Gen.CallGenProp._is_list_builtin_receiver(pool, obj_var, la_tail, func_name, cl) != 0: - is_list_annot_builtin = 1 + if self.Gen.CallGenProp._is_list_builtin_receiver(pool, obj_var, la_tail, func_name, cl) != 0: is_list_annot_builtin = 1 match obj_var.Ty: case mlirlite.LLVMType.Ptr(obj_struct_ty): class_nm: str = self.Gen.StructGen.get_class_name_by_type(pool, obj_struct_ty) @@ -1529,8 +1431,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # 可能被类型名后缀匹配错解为内层元素类,非 'list' 前缀 # 拦截会漏放 → 走 method_call/MRO fatal。 if self.Gen.CallGenProp._is_list_builtin_receiver(pool, obj_var, class_nm, func_name, cl) == 0 and is_list_annot_builtin == 0: - if hit_box is not None: - hit_box[0] = 1 + if hit_box is not None: hit_box[0] = 1 return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, class_nm, func_name, obj_var, cl, trans) # 指针变量: alloca 类型是 Ptr(Ptr(Struct)) # load 获取实际指针 Ptr(Struct) 后再查找 @@ -1544,8 +1445,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if self.Gen.CallGenProp._is_list_builtin_receiver(pool, obj_var, inner_nm, func_name, cl) == 0 and is_list_annot_builtin == 0: obj_ptr: mlirlite.Value* = mlirlite.build_load(builder, obj_struct_ty, obj_var) if obj_ptr is not None: - if hit_box is not None: - hit_box[0] = 1 + if hit_box is not None: hit_box[0] = 1 return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, inner_nm, func_name,obj_ptr, cl, trans) # FakeDuck: str/bytes 变量(Ptr(i8),AnnotClassName 为空) # 方法调用 → 扩展类 _Type/_str(a.type_id() / a.upper())。 @@ -1555,8 +1455,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # 接收者非 str/bytes,此调用必须由尾部 list 内置分支翻译。 if is_list_annot_builtin == 0: fd_name_res: mlirlite.Value* = self.Gen.CallGenFd._translate_fakeduck_call(pool, builder, mod, None, func_name, cl, trans) - if fd_name_res is not None: - return fd_name_res + if fd_name_res is not None: return fd_name_res # AnnotClassName 回退:联合类型简化为 Ptr(i8) 时, # 通过原始类型注解的类名查找结构体(var_entry 已在上方 # list 注解识别处查得,同一变量表项)。 @@ -1590,8 +1489,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): i8_ptr_ty2: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) obj_ptr2: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty2, obj_var) if obj_ptr2 is not None: - if hit_box is not None: - hit_box[0] = 1 + if hit_box is not None: hit_box[0] = 1 return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, cls_nm2, func_name,obj_ptr2, cl, trans) else: # list 内置方法跳过(结构体未注册路径同样不能 @@ -1602,13 +1500,11 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # AnnotClassName=="str" 且对象是 char* 时触发, # self 用影子结构体 {a}__meta__(或临时影子)。 fd_res: mlirlite.Value* = self.Gen.CallGenFd._translate_fakeduck_call(pool, builder, mod, cls_nm2, func_name, cl, trans) - if fd_res is not None: - return fd_res + if fd_res is not None: return fd_res # 结构体未注册(跨模块依赖未翻译): # 用模块名查 SHA1 构造方法调用名 sha1_fc: str = None - if mod_nm2 is not None: - sha1_fc = self._lookup_module_sha1(mod_nm2) + if mod_nm2 is not None: sha1_fc = self._lookup_module_sha1(mod_nm2) if sha1_fc is not None: # 构造 "{sha1}.{cls_nm2}.{func_name}" 调用名 mlen3: sizet = string.strlen(sha1_fc) + string.strlen(cls_nm2) + string.strlen(func_name) + 3 @@ -1636,8 +1532,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if ret_ty3 is None: # 权威来源:vpi stub 返回注解缓存(方法定义处,不硬编码白名单) ret_ty3 = self._lookup_method_ret_ty_via_vpi(pool, sha1_fc, cls_nm2, func_name) - if ret_ty3 is None: - ret_ty3 = self._LookupMethodRetTyFromTextLL(pool, sha1_fc, cls_nm2, func_name) + if ret_ty3 is None: ret_ty3 = self._LookupMethodRetTyFromTextLL(pool, sha1_fc, cls_nm2, func_name) if ret_ty3 is None: # 本分支仅在"注解类结构体未注册"时到达(L6932 else): # 类未注册 → 无法沿 MRO 解析 Mixin 方法定义模块。 @@ -1668,8 +1563,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): i8_ptr_ty4: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) obj_ptr4: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty4, obj_var) if obj_ptr4 is not None: - if hit_box is not None: - hit_box[0] = 1 + if hit_box is not None: hit_box[0] = 1 return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, cls_nm2, func_name, obj_ptr4, cl, trans) # ============================================================ @@ -1693,16 +1587,13 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): is_mod_path_expr: int = 0 if evk == ast.ASTKind.Attribute: expr_root: ast.AST* = expr_method_at.value - while expr_root is not None and expr_root.kind() == ast.ASTKind.Attribute: - expr_root = ast.Attribute*(expr_root).value + while expr_root is not None and expr_root.kind() == ast.ASTKind.Attribute: expr_root = ast.Attribute*(expr_root).value if expr_root is not None and expr_root.kind() == ast.ASTKind.Name: expr_root_nm: str = ast.Name*(expr_root).id if expr_root_nm is not None: - if string.strcmp(expr_root_nm, "t") == 0 or string.strcmp(expr_root_nm, "c") == 0: - is_mod_path_expr = 1 + if string.strcmp(expr_root_nm, "t") == 0 or string.strcmp(expr_root_nm, "c") == 0: is_mod_path_expr = 1 elif trans._imported_modules is not None: - if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, expr_root_nm) != 0: - is_mod_path_expr = 1 + if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, expr_root_nm) != 0: is_mod_path_expr = 1 if evk != ast.ASTKind.Name and is_mod_path_expr == 0: # 翻译接收者表达式(求值结果应为 Ptr(Struct)) expr_obj: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, expr_method_at.value, funcs_ptr, func_count, trans) @@ -1712,14 +1603,12 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # (如 (a*2.0 - b) 中 __mul__ 返回 Vec3**),否则方法 # 调用被当裸函数 @dot 解析 → 链接 undefined symbol expr_struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(expr_obj) - if expr_struct_ty is not None: - expr_cls_nm = self.Gen.StructGen.get_class_name_by_type(pool, expr_struct_ty) + if expr_struct_ty is not None: expr_cls_nm = self.Gen.StructGen.get_class_name_by_type(pool, expr_struct_ty) # 回退:LLVM 类型为 Ptr(i8)(方法返回 X* 无类型信息)时, # 从接收者表达式结构推断类名(链式调用 c2.scale(2.0).move(...) # 的 scale 返回 Ptr(i8),经 infer_expr_class → vpi 返回注解) # 跨 Mixin 不能 self 调用 ExprGenMixin 方法,经全局单例 - if expr_cls_nm is None: - expr_cls_nm = self.Gen.ExprGenCls.infer_expr_class(pool, mod, expr_method_at.value, trans) + if expr_cls_nm is None: expr_cls_nm = self.Gen.ExprGenCls.infer_expr_class(pool, mod, expr_method_at.value, trans) if expr_cls_nm is not None: # 值类型接收者(内嵌 struct 字段,如 zdeflate s.writer 值字段): # 方法调用 self 必须传字段地址(GEP)而非 load 出的结构体值, @@ -1735,17 +1624,14 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): expr_is_ptr = 0 if expr_is_ptr == 0: expr_addr: mlirlite.Value* = self.Gen.ExprGenAttr.get_attribute_ptr(builder, pool, mod, expr_method_at.value, trans) - if expr_addr is not None: - expr_obj = expr_addr - if hit_box is not None: - hit_box[0] = 1 + if expr_addr is not None: expr_obj = expr_addr + if hit_box is not None: hit_box[0] = 1 return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, expr_cls_nm, func_name, expr_obj, cl, trans) # FakeDuck: 表达式接收者解析失败且对象是 char* 时 # (如 " ".isspace()),尝试扩展类 _Type/_str 方法 # (self 用临时影子,对齐 TPC L2858-2873) fd_expr_res: mlirlite.Value* = self.Gen.CallGenFd._translate_fakeduck_call(pool, builder, mod, None, func_name, cl, trans) - if fd_expr_res is not None: - return fd_expr_res + if fd_expr_res is not None: return fd_expr_res # ============================================================ # 检测 self.field.method() 调用 @@ -1784,10 +1670,8 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): field_annot: str = self.Gen.StructGen.get_field_annot_class_name(field_info) if field_annot is not None: dot_p: str = string.strrchr(field_annot, 46) - if dot_p is not None: - field_cls_nm = dot_p + 1 - else: - field_cls_nm = field_annot + if dot_p is not None: field_cls_nm = dot_p + 1 + else: field_cls_nm = field_annot if field_cls_nm is not None: # 值类型字段(内嵌 struct,如 zdeflate_stream.writer: zbit_writer) # 方法调用 self 必须传字段地址(GEP),而非 load 出的结构体值: @@ -1802,10 +1686,8 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): is_val_field = 1 if is_val_field != 0: field_addr: mlirlite.Value* = self.Gen.ExprGenAttr.get_attribute_ptr(builder, pool, mod, attr_method_at.value, trans) - if field_addr is not None: - field_obj = field_addr - if hit_box is not None: - hit_box[0] = 1 + if field_addr is not None: field_obj = field_addr + if hit_box is not None: hit_box[0] = 1 return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, field_cls_nm, func_name, field_obj, cl, trans) # ============================================================ @@ -1850,22 +1732,19 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # 偏移读写垃圾)。 lm_conf_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(lm_obj) lm_conf_nm: str = None - if lm_conf_ty is not None: - lm_conf_nm = mlirlite.get_struct_name(lm_conf_ty) + if lm_conf_ty is not None: lm_conf_nm = mlirlite.get_struct_name(lm_conf_ty) # [S4] 容器基名**精确**比较:此处读的是 LLVM 注册名,含模块 sha1 # 前缀(如 "e94ef9e139461915.list[ast.ASTptr]");SpecTypeNameBaseIs # 会去前缀、截断泛型实参后精确比 "list"(原 strstr 子串会误命中 # playlist 之类的类名)。 - if lm_conf_nm is not None and TSpec.SpecTypeNameBaseIs(lm_conf_nm, "list") == 0: - return None + if lm_conf_nm is not None and TSpec.SpecTypeNameBaseIs(lm_conf_nm, "list") == 0: return None # list 内置分支命中标记:void 方法(set/clear)成功处理后返回 # None,必须置位 hit_box 区分"已识别为 list 方法路径",否则 # translate_call 误判未命中继续走跨模块函数路径,把对象名当 # 模块名查 SHA1 → "跨模块调用 'nums.set' 找不到模块 SHA1" # (ListTest main.vp nums.set(1,99) 根因;对齐 _translate_method_call # 调用点的 hit_box 置位模式)。 - if hit_box is not None: - hit_box[0] = 1 + if hit_box is not None: hit_box[0] = 1 i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool) i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty) @@ -1878,13 +1757,10 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # _list_elem_type_from_name 修正,方法调用路径漏改。 lm_esty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(lm_obj) lm_ename: str = None - if lm_esty is not None: - lm_ename = mlirlite.get_struct_name(lm_esty) + if lm_esty is not None: lm_ename = mlirlite.get_struct_name(lm_esty) lm_elem_ty: mlirlite.LLVMType* = None - if lm_ename is not None: - lm_elem_ty = self.Gen.ExprGenName._list_elem_type_from_name(pool, lm_ename) - if lm_elem_ty is None: - lm_elem_ty = i8_ptr_ty + if lm_ename is not None: lm_elem_ty = self.Gen.ExprGenName._list_elem_type_from_name(pool, lm_ename) + if lm_elem_ty is None: lm_elem_ty = i8_ptr_ty # get / __getitem__: 返回 index 处的元素 if string.strcmp(lm_name, "get") == 0 or string.strcmp(lm_name, "__getitem__") == 0: @@ -1906,8 +1782,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): g_addr: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, g_data, g_offset) if g_addr is not None: g_ep: mlirlite.Value* = mlirlite.build_bitcast(builder, g_addr, mlirlite.Ptr(pool, lm_elem_ty)) - if g_ep is not None: - return mlirlite.build_load(builder, lm_elem_ty, g_ep) + if g_ep is not None: return mlirlite.build_load(builder, lm_elem_ty, g_ep) # set / __setitem__: 设置 index 处的元素 elif string.strcmp(lm_name, "set") == 0 or string.strcmp(lm_name, "__setitem__") == 0: @@ -1951,8 +1826,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): p_addr: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, p_data, p_offset) if p_addr is not None: p_ep: mlirlite.Value* = mlirlite.build_bitcast(builder, p_addr, mlirlite.Ptr(pool, lm_elem_ty)) - if p_ep is not None: - return mlirlite.build_load(builder, lm_elem_ty, p_ep) + if p_ep is not None: return mlirlite.build_load(builder, lm_elem_ty, p_ep) # clear: count = 0 elif string.strcmp(lm_name, "clear") == 0: @@ -1985,10 +1859,8 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # 否则 ld.lld undefined symbol(定义端是特化名)。 ap_spec_nm: str = None ap_struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(lm_obj) - if ap_struct_ty is not None: - ap_spec_nm = self.Gen.StructGen.get_class_name_by_type(pool, ap_struct_ty) - if ap_spec_nm is None: - ap_spec_nm = "list" + if ap_struct_ty is not None: ap_spec_nm = self.Gen.StructGen.get_class_name_by_type(pool, ap_struct_ty) + if ap_spec_nm is None: ap_spec_nm = "list" # 触发泛型特化翻译(幂等,MethodsEmitted 防重入): # list[AST*].append 的 define 方法体在特化类翻译时 # 生成。仅构造调用名不触发特化会导致定义缺失 diff --git a/App/lib/core/Gen/Call/CallGenFd.vp b/App/lib/core/Gen/Call/CallGenFd.vp index 71eb45d..e21d2b8 100644 --- a/App/lib/core/Gen/Call/CallGenFd.vp +++ b/App/lib/core/Gen/Call/CallGenFd.vp @@ -41,8 +41,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): if fd_key is not None: for fd_ci in range(2): fd_cn: str = "_Type" - if fd_ci == 1: - fd_cn = "_str" + if fd_ci == 1: fd_cn = "_str" viperlib.snprintf(fd_key, 160, "%s.%s", fd_cn, method_name) fd_func = self.find_func_in_module(mod, fd_key) if fd_func is not None: @@ -56,8 +55,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): # 无字段(_Type)时 self 用对象值 bitcast 到扩展类指针(对齐 TPC L2856-2876) fd_entry_fd: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_type(fd_sty) fd_has_fields: int = 0 - if fd_entry_fd is not None and fd_entry_fd.FieldCount > 0: - fd_has_fields = 1 + if fd_entry_fd is not None and fd_entry_fd.FieldCount > 0: fd_has_fields = 1 # self 参数:优先使用已有影子 {var}__meta__(fd2 创建,仅当扩展类有字段时) fd_self: mlirlite.Value* = None if fd_at.value.kind() == ast.ASTKind.Name: @@ -65,11 +63,9 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): if fd_onm.id is not None: # pool 持久缓冲(f-string 栈缓冲在函数返回后失效) fd_mn: str = pool.alloc(256) - if fd_mn is not None: - viperlib.snprintf(fd_mn, 256, "%s__meta__", fd_onm.id) + if fd_mn is not None: viperlib.snprintf(fd_mn, 256, "%s__meta__", fd_onm.id) fd_meta: mlirlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, fd_mn) - if fd_meta is not None and fd_has_fields != 0: - fd_self = fd_meta + if fd_meta is not None and fd_has_fields != 0: fd_self = fd_meta if fd_self is None: if fd_has_fields != 0: # 有字段扩展类且无影子(字符串字面量等):入口创建临时影子并初始化 @@ -82,14 +78,12 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): fd_dfe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(fd_sty, "__data__") if fd_dfe is not None and fd_dfe.Ty is not None: fd_dp: mlirlite.Value* = mlirlite.build_gep_struct(builder, fd_sty, fd_dfe.Ty, fd_self, fd_dfe.Index) - if fd_dp is not None: - mlirlite.build_store(builder, fd_obj_val, fd_dp) + if fd_dp is not None: mlirlite.build_store(builder, fd_obj_val, fd_dp) fd_bfe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(fd_sty, "__mbuddy__") if fd_bfe is not None and fd_bfe.Ty is not None: fd_bp: mlirlite.Value* = mlirlite.build_gep_struct(builder, fd_sty, fd_bfe.Ty, fd_self, fd_bfe.Index) fd_null: mlirlite.Value* = mlirlite.ConstNull(pool, fd_bfe.Ty, "null") - if fd_bp is not None and fd_null is not None: - mlirlite.build_store(builder, fd_null, fd_bp) + if fd_bp is not None and fd_null is not None: mlirlite.build_store(builder, fd_null, fd_bp) # FakeDuck: with 上下文自动注入 requires 字段(如 __mbuddy__) self._inject_requires_fields(trans, pool, builder, mod, fd_self, fd_cls) else: @@ -104,8 +98,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): fd_tail: mlirlite.Value* = fd_self fd_args: list[ast.AST*]* = cl.args fd_can: int = 0 - if fd_args is not None: - fd_can = len(fd_args) + if fd_args is not None: fd_can = len(fd_args) for fd_ai in range(fd_can): fd_arg: ast.AST* = fd_args.get(fd_ai) if fd_arg is not None: @@ -127,8 +120,7 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): fd_tail = fd_av # 返回类型与调用名(来自 find_func_in_module 命中的函数定义) fd_ret_ty: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(fd_func) - if fd_ret_ty is None: - fd_ret_ty = mlirlite.Int32(pool) + if fd_ret_ty is None: fd_ret_ty = mlirlite.Int32(pool) fd_fname: str = mlirlite.function_get_name(fd_func) if fd_fname is None: return None # 返回类型精确化:跨模块 declare 的 list[T] 特化返回类型可能被简化为 Ptr(i8),调用方变量 alloca 类型随之退化 → parts[0] 走字符下标路径而非 list 内联 __getitem__(printf %s 崩溃)。权威来源为定义模块 vpi(未命中回退 text.ll);仅当函数名确为 "{16hex}.{func}"(判定走唯一真源 GenApi.sha1_prefix_len)才提取模块 sha1 @@ -138,10 +130,8 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): string.strncpy(fd_sha1, fd_fname, 16) fd_sha1[16] = '\0' fd_exact: mlirlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, fd_sha1, fd_cls, method_name) - if fd_exact is None: - fd_exact = self._LookupMethodRetTyFromTextLL(pool, fd_sha1, fd_cls, method_name) - if fd_exact is not None: - fd_ret_ty = fd_exact + if fd_exact is None: fd_exact = self._LookupMethodRetTyFromTextLL(pool, fd_sha1, fd_cls, method_name) + if fd_exact is not None: fd_ret_ty = fd_exact fd_total: int = 1 + fd_can return mlirlite.build_call(builder, fd_fname, fd_head, fd_total, fd_ret_ty, 0) # ============================================================ @@ -163,10 +153,8 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): meta_ptr: mlirlite.Value*, class_name: str) -> int: """在 with 上下文注入 requires 字段,返回注入字段数""" - if trans is None or pool is None or builder is None or mod is None: - return 0 - if meta_ptr is None or class_name is None: - return 0 + if trans is None or pool is None or builder is None or mod is None: return 0 + if meta_ptr is None or class_name is None: return 0 # _withcontent._find_provider(跨模块):仅当本模块可见(_withcontent # 被 import,vpi stub declare 已注入)时才注入。对齐 TPC L4048-4050 # (Gen.functions.get('_find_provider') 不存在则跳过)——否则非 with @@ -293,6 +281,5 @@ novirtual class CallGenFd(CallGenBase.CallGenBase): ret_i32_q: mlirlite.LLVMType* = mlirlite.Int32(pool) if ret_i32_q is None: return 0 self._ensure_method_declare(pool, mod, fd_pon, ret_i32_q, None, 0) - for _pi in range(fd_pc): - mlirlite.build_call(builder, fd_pon, None, 0, ret_i32_q, 0) + for _pi in range(fd_pc): mlirlite.build_call(builder, fd_pon, None, 0, ret_i32_q, 0) return fd_pc \ No newline at end of file diff --git a/App/lib/core/Gen/Call/CallGenLeafKit.vp b/App/lib/core/Gen/Call/CallGenLeafKit.vp index b4a64c0..382a3b6 100644 --- a/App/lib/core/Gen/Call/CallGenLeafKit.vp +++ b/App/lib/core/Gen/Call/CallGenLeafKit.vp @@ -70,8 +70,7 @@ def _gfn_idx_slot(idx_base: sizet*, si: sizet) -> sizet*: def _gfn_idx_find(funcs: GenTypes.FuncEntry*, idx_base: sizet*, cap: int, name: str) -> int: """在全局函数表名索引中探测 name,返回命中槽下标(>=0);未命中/不可用返回 -1""" - if funcs is None or idx_base is None or cap <= 0 or name is None: - return -1 + if funcs is None or idx_base is None or cap <= 0 or name is None: return -1 h: uint64 = _gfn_hash(name) mask: sizet = sizet(cap - 1) si: sizet = sizet(h) & mask @@ -93,8 +92,7 @@ def _gfn_idx_find(funcs: GenTypes.FuncEntry*, def _gfn_idx_insert(idx_base: sizet*, cap: int, slot_index: int, name: str) -> int: """把 (name → slot_index) 记入索引;0=成功 / 1=失败""" - if idx_base is None or cap <= 0 or name is None: - return 1 + if idx_base is None or cap <= 0 or name is None: return 1 h: uint64 = _gfn_hash(name) mask: sizet = sizet(cap - 1) si: sizet = sizet(h) & mask @@ -124,13 +122,11 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): # ============================================================ def _func_has_eh_params(self, func: mlirlite.Function*) -> int: """返回 1=函数带 EH 输出参数 / 0=不带""" - if func is None: - return 0 + if func is None: return 0 cur_p: mlirlite.Param* = mlirlite.function_get_param_head(func) while cur_p is not None: pn: str = mlirlite.param_get_name(cur_p) - if pn is not None and string.strcmp(pn, "%__eh_msg_out__") == 0: - return 1 + if pn is not None and string.strcmp(pn, "%__eh_msg_out__") == 0: return 1 cur_p = mlirlite.param_get_next(cur_p) return 0 @@ -164,14 +160,12 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): ret_ty: mlirlite.LLVMType*, is_variadic: int) -> mlirlite.Value*: """带 try-except EH 检测的函数调用,返回 call 结果(检查后位于 ok 块)""" - if trans is None or self._func_has_eh_params(func) == 0: - return mlirlite.build_call(builder, call_name, head, count, ret_ty, is_variadic) + if trans is None or self._func_has_eh_params(func) == 0: return mlirlite.build_call(builder, call_name, head, count, ret_ty, is_variadic) # ---- 1. 确定输出指针 ---- i8_ty_g: mlirlite.LLVMType* = mlirlite.Int8(pool) i8_ptr_ty_g: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_g) i32_ty_g: mlirlite.LLVMType* = mlirlite.Int32(pool) - if i8_ty_g is None or i8_ptr_ty_g is None or i32_ty_g is None: - return mlirlite.build_call(builder, call_name, head, count, ret_ty, is_variadic) + if i8_ty_g is None or i8_ptr_ty_g is None or i32_ty_g is None: return mlirlite.build_call(builder, call_name, head, count, ret_ty, is_variadic) msg_ptr: mlirlite.Value* = None code_ptr: mlirlite.Value* = None if trans._eh_msg_ptr is not None and trans._eh_code_ptr is not None: @@ -186,19 +180,15 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): # ---- 2. 调用前清零 ---- null_msg_g: mlirlite.Value* = mlirlite.ConstNull(pool, i8_ptr_ty_g, "null") zero_code_g: mlirlite.Value* = mlirlite.const_int32(pool, 0) - if null_msg_g is not None: - mlirlite.build_store(builder, null_msg_g, msg_ptr) - if zero_code_g is not None: - mlirlite.build_store(builder, zero_code_g, code_ptr) + if null_msg_g is not None: mlirlite.build_store(builder, null_msg_g, msg_ptr) + if zero_code_g is not None: mlirlite.build_store(builder, zero_code_g, code_ptr) # ---- 3. 追加实参(链表末尾 + count+2)---- msg_ptr.Next = code_ptr code_ptr.Next = None - if head is None: - head = msg_ptr + if head is None: head = msg_ptr else: tail_g: mlirlite.Value* = head - while tail_g.Next is not None: - tail_g = tail_g.Next + while tail_g.Next is not None: tail_g = tail_g.Next tail_g.Next = msg_ptr count = count + 2 # ---- 4. 调用 + 检查 ---- @@ -236,16 +226,13 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): mlirlite.build_ret_void(builder) case mlirlite.LLVMType.Ptr(_pg): nv_g: mlirlite.Value* = mlirlite.ConstNull(pool, ret_ty_g2, "null") - if nv_g is not None: - mlirlite.build_ret(builder, nv_g) + if nv_g is not None: mlirlite.build_ret(builder, nv_g) case mlirlite.LLVMType.Float(_fg): zf_g: mlirlite.Value* = mlirlite.ConstFloat(pool, ret_ty_g2, 0.0) - if zf_g is not None: - mlirlite.build_ret(builder, zf_g) + if zf_g is not None: mlirlite.build_ret(builder, zf_g) case _: zv_g: mlirlite.Value* = mlirlite.ConstZero(pool, ret_ty_g2) - if zv_g is not None: - mlirlite.build_ret(builder, zv_g) + if zv_g is not None: mlirlite.build_ret(builder, zv_g) # ok 块:继续 mlirlite.position_at_end(builder, ok_bb_g) return result @@ -284,8 +271,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): match inner_ty: case mlirlite.LLVMType.Ptr(_): loaded: mlirlite.Value* = mlirlite.build_load(builder, inner_ty, obj_val) - if loaded is not None: - obj_ptr = loaded + if loaded is not None: obj_ptr = loaded case _: pass obj_is_ptr: int = self.Gen.ExprGenBase.is_ptr_type(obj_ptr.Ty) @@ -308,16 +294,13 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): # NoVTable / 未知类 → 编译时静态判断(obj 静态类型 MRO) st: int = self._isinstance_compile_time(pool, obj_ptr, cn) c1: mlirlite.Value* = mlirlite.const_int(pool, 1, 1 if st > 0 else 0) - if res is None: - res = c1 - else: - res = mlirlite.build_or(builder, res, c1) + if res is None: res = c1 + else: res = mlirlite.build_or(builder, res, c1) elif obj_is_ptr != 0: # CVTable → 运行时 vtable 比较(读对象头部 vtable 指针) if vtable_ready == 0: vtable_slot: mlirlite.Value* = mlirlite.build_bitcast(builder, obj_ptr, i8_ptr_ptr_ty) - if vtable_slot is not None: - vtable_ptr = mlirlite.build_load(builder, i8_ptr_ty, vtable_slot) + if vtable_slot is not None: vtable_ptr = mlirlite.build_load(builder, i8_ptr_ty, vtable_slot) vtable_ready = 1 if vtable_ptr is not None: subs: sizet* = self._collect_subclass_vtable_classes(pool, cn) @@ -330,10 +313,8 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): if sub_i8 is not None: cmp: mlirlite.Value* = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, vtable_ptr, sub_i8) if cmp is not None: - if res is None: - res = cmp - else: - res = mlirlite.build_or(builder, res, cmp) + if res is None: res = cmp + else: res = mlirlite.build_or(builder, res, cmp) k += 1 ci += 1 if res is None: @@ -346,35 +327,29 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): node: ast.AST*) -> sizet*: """从 isinstance 第二参数提取类名数组(Name→id / Attribute→attr / Tuple→遍历)""" arr: sizet* = pool.alloc(8 * 16) - if arr is None: - return None + if arr is None: return None # 全数组清零:pool 分配内存非零时,未初始化槽位会被 while cls_names[ci]!=0 # 误当类名指针解引用 → 段错误 string.memset(arr, 0, 8 * 16) arr[0] = 0 - if node is None: - return arr + if node is None: return arr count: int = 0 k: int = node.kind() if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) - if nm.id is not None: - arr[0] = sizet(nm.id) + if nm.id is not None: arr[0] = sizet(nm.id) elif k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(node) - if at.attr is not None: - arr[0] = sizet(at.attr) + if at.attr is not None: arr[0] = sizet(at.attr) elif k == ast.ASTKind.Tuple: tp: ast.Tuple* = ast.Tuple*(node) elts: list[ast.AST*]* = tp.elts if elts is not None: n: sizet = len(elts) for i in range(n): - if count >= 15: - break + if count >= 15: break elt: ast.AST* = elts.get(i) - if elt is None: - continue + if elt is None: continue ek: int = elt.kind() if ek == ast.ASTKind.Name: enm: ast.Name* = ast.Name*(elt) @@ -393,13 +368,11 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): def _collect_subclass_vtable_classes(self, pool: memhub.MemBuddy*, class_name: str) -> sizet*: """反向 BFS 收集目标类及全部子类(含自身,仅 HasVTable==1),返回 0 结尾数组""" - if class_name is None: - return None + if class_name is None: return None names: sizet* = pool.alloc(8 * (CallGenBase.ISINSTANCE_CLASS_MAX + 1)) queue: sizet* = pool.alloc(8 * CallGenBase.ISINSTANCE_CLASS_MAX) visited: sizet* = pool.alloc(8 * CallGenBase.ISINSTANCE_CLASS_MAX) - if names is None or queue is None or visited is None: - return None + if names is None or queue is None or visited is None: return None string.memset(names, 0, 8 * (CallGenBase.ISINSTANCE_CLASS_MAX + 1)) string.memset(queue, 0, 8 * CallGenBase.ISINSTANCE_CLASS_MAX) string.memset(visited, 0, 8 * CallGenBase.ISINSTANCE_CLASS_MAX) @@ -411,8 +384,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): qcount -= 1 cur_addr: sizet = queue[qcount] cur: str = rawptr(cur_addr) - if cur is None: - continue + if cur is None: continue dup: int = 0 for vi in range(vcount): va: sizet = visited[vi] @@ -421,8 +393,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): if vn is not None and string.strcmp(vn, cur) == 0: dup = 1 break - if dup != 0: - continue + if dup != 0: continue if vcount < CallGenBase.ISINSTANCE_CLASS_MAX: visited[vcount] = sizet(cur) vcount += 1 @@ -438,8 +409,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): scnt: int = self.Gen.StructGen.get_struct_count() for i in range(scnt): e2: GenTypes.StructEntry* = self.Gen.StructGen._get_struct_entry(i) - if e2 is None or e2.Name is None: - continue + if e2 is None or e2.Name is None: continue if e2.ParentCount > 0 and e2.ParentNames is not None: parr: sizet* = (sizet*)(e2.ParentNames) for j in range(e2.ParentCount): @@ -461,26 +431,21 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): class_name: str, trans: HT.Translator* = None) -> mlirlite.Value*: """构造类 vtable 地址引用(i8*):本模块已定义直接引用,跨模块声明 external""" - if class_name is None: - return None + if class_name is None: return None i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty) buf: str = pool.alloc(256) - if buf is None: - return None + if buf is None: return None viperlib.snprintf(buf, 256, "%s.vtable", class_name) vn: str = rawptr(buf) sha1: str = self.Gen.StructGen.get_struct_sha1(class_name) if sha1 is None: - if trans is None: - return None + if trans is None: return None sha1 = trans.ModuleSha1 - if sha1 is None: - return None + if sha1 is None: return None mangled: str = self.Gen.FuncGenBase._mangle_name_with_sha1(sha1, vn) ref_name: str = pool.alloc(256) - if ref_name is None: - return None + if ref_name is None: return None # vtable 名含 sha1 点号前缀,一律 @"..." 引号形式 viperlib.snprintf(ref_name, 256, "@\"%s\"", mangled) gv: mlirlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(mod, mangled) @@ -491,13 +456,11 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): else: # 跨模块:声明 @mangled = external global i8*,引用类型 i8** gv2: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, mangled, i8_ptr_ty) - if gv2 is None: - return None + if gv2 is None: return None mlirlite.module_add_global(mod, gv2) ref_ty = mlirlite.Ptr(pool, i8_ptr_ty) ref: mlirlite.Value* = mlirlite.SSAValue(pool, ref_ty, ref_name) - if ref is None: - return None + if ref is None: return None return mlirlite.build_bitcast(builder, ref, i8_ptr_ty) @@ -505,21 +468,18 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): obj_ptr: mlirlite.Value*, class_name: str) -> int: """编译时静态判断:obj 静态类型 == class_name 或 class_name 在其 MRO 中""" - if obj_ptr is None or obj_ptr.Ty is None or class_name is None: - return 0 + if obj_ptr is None or obj_ptr.Ty is None or class_name is None: return 0 match obj_ptr.Ty: case mlirlite.LLVMType.Ptr(obj_struct_ty): sname: str = self.Gen.StructGen.get_class_name_by_type(pool, obj_struct_ty) if sname is not None: - if string.strcmp(sname, class_name) == 0: - return 1 + if string.strcmp(sname, class_name) == 0: return 1 mro: sizet* = self.Gen.StructGen.get_mro_chain(pool, sname) if mro is not None: k: int = 0 while mro[k] != 0: mn: str = rawptr(mro[k]) - if mn is not None and string.strcmp(mn, class_name) == 0: - return 1 + if mn is not None and string.strcmp(mn, class_name) == 0: return 1 k += 1 case _: pass @@ -541,8 +501,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): can: sizet, trans: HT.Translator* = None) -> mlirlite.Value*: """通过闭包指针间接调用(支持带参 lambda:i32(i8*, args...))""" - if builder is None or closure_alloca is None: - return None + if builder is None or closure_alloca is None: return None i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty) @@ -550,25 +509,20 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): # 1. 加载闭包指针 (i8*) closure_ptr: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, closure_alloca) - if closure_ptr is None: - return None + if closure_ptr is None: return None # 2. 加载 fn_ptr (offset 0): bitcast to i8**, load i8* fn_ptr_addr: mlirlite.Value* = mlirlite.build_bitcast(builder, closure_ptr, mlirlite.Ptr(pool, i8_ptr_ty)) - if fn_ptr_addr is None: - return None + if fn_ptr_addr is None: return None fn_raw: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, fn_ptr_addr) - if fn_raw is None: - return None + if fn_raw is None: return None # 3. 加载 env_ptr (offset 8): GEP i8, closure, 8; load i8* eight_val: mlirlite.Value* = mlirlite.const_int32(pool, 8) env_addr: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, closure_ptr, eight_val) - if env_addr is None: - return None + if env_addr is None: return None env_ptr: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, env_addr) - if env_ptr is None: - return None + if env_ptr is None: return None # 4. 构建参数:env 头 + 实参尾(带参 lambda 时翻译实参) total_args: int = 1 @@ -583,23 +537,20 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans) if arg_val is None or arg_val.Ty is None: continue arg_val.Next = None - if arg_tail is not None: - arg_tail.Next = arg_val + if arg_tail is not None: arg_tail.Next = arg_val arg_tail = arg_val pn_new: mlirlite.ParamNode* = mlirlite.new_param_node(pool, arg_val.Ty) if pn_new is not None: pn_tail.Next = pn_new pn_tail = pn_new total_args += 1 - if total_args == 1: - env_ptr.Next = None + if total_args == 1: env_ptr.Next = None # 5. bitcast fn_raw 到函数指针类型 i32(i8*, [args...])* func_ty: mlirlite.LLVMType* = mlirlite.Func(pool, i32_ty, param_node, total_args) func_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, func_ty) fn_typed: mlirlite.Value* = mlirlite.build_bitcast(builder, fn_raw, func_ptr_ty) - if fn_typed is None: - return None + if fn_typed is None: return None # 6. 间接调用: call i32 %fn_typed(env, args...) return mlirlite.build_call_indirect(builder, fn_typed, arg_head, total_args, i32_ty) @@ -607,16 +558,12 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): def _is_func_ptr_alloca(self, alloca: mlirlite.Value*) -> int: """判断 alloca 是否为函数指针变量(类型 Ptr(Ptr(i8))),1=是 / 0=否""" - if alloca is None or alloca.Ty is None: - return 0 - if self.Gen.ExprGenBase.is_ptr_type(alloca.Ty) == 0: - return 0 + if alloca is None or alloca.Ty is None: return 0 + if self.Gen.ExprGenBase.is_ptr_type(alloca.Ty) == 0: return 0 pointee: mlirlite.LLVMType* = alloca.Ty.Pointee - if pointee is None or self.Gen.ExprGenBase.is_ptr_type(pointee) == 0: - return 0 + if pointee is None or self.Gen.ExprGenBase.is_ptr_type(pointee) == 0: return 0 inner: mlirlite.LLVMType* = pointee.Pointee - if inner is None or self.Gen.ExprGenBase.is_ptr_type(inner) != 0: - return 0 + if inner is None or self.Gen.ExprGenBase.is_ptr_type(inner) != 0: return 0 return 1 @@ -642,23 +589,19 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): def is_closure_name(self, name: str) -> int: """检查 name 是否已注册为闭包变量名,1=是 / 0=否""" - if name is None or self.ClosureNames is None: - return 0 + if name is None or self.ClosureNames is None: return 0 i: sizet for i in range(self.ClosureCount): - if string.strcmp(self.ClosureNames + i * 64, name) == 0: - return 1 + if string.strcmp(self.ClosureNames + i * 64, name) == 0: return 1 return 0 def _ensure_funcptr_sigs(self) -> int: """确保函数指针签名表已分配(stdlib.malloc,懒初始化)""" - if self.FuncptrNames is not None: - return 1 + if self.FuncptrNames is not None: return 1 self.FuncptrNames = CompilerFactory.factory.PermPool.alloc(64 * CallGenBase.MAX_FUNC_PTR_SIGS) self.FuncptrRets = CompilerFactory.factory.PermPool.alloc(8 * CallGenBase.MAX_FUNC_PTR_SIGS) - if self.FuncptrNames is None or self.FuncptrRets is None: - return 0 + if self.FuncptrNames is None or self.FuncptrRets is None: return 0 string.memset(self.FuncptrNames, 0, 64 * CallGenBase.MAX_FUNC_PTR_SIGS) return 1 @@ -681,8 +624,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): typed_buf: str = pool.alloc(512) if typed_buf is not None: mlirlite.TypePrint(typed_buf, 512, ret_ty, pool) - if typed_buf[0] != '\0': - ret_str = typed_buf + if typed_buf[0] != '\0': ret_str = typed_buf msg_buf: str = pool.alloc(1024) if msg_buf is not None: viperlib.snprintf( @@ -711,8 +653,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): 也不能静默覆盖(先翻译模块的调用点已按旧值生成)——两者都是无声误编译; * 满表 → 报错(原实现静默丢弃)。 """ - if name is None or ret_ty is None: - return 1 + 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 内存不足)") @@ -723,8 +664,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): idx_hit: sizet = sizet(i) * 64 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 + 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, "该名字已按另一种返回类型登记过") return 1 if self.FuncptrCount >= CallGenBase.MAX_FUNC_PTR_SIGS: @@ -736,22 +676,18 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): # ret_ty 是调用方 pool 分配的裸 LLVMType,1a 每文件 reset 后悬空; # 深拷贝到 perm_pool(lookup_func_ptr_ret 跨文件读取) ret_copy_fp: mlirlite.LLVMType* = mlirlite.DeepCopyType(CompilerFactory.factory.PermPool, ret_ty) - if ret_copy_fp is not None: - self.FuncptrRets[self.FuncptrCount] = uint64(ret_copy_fp) - else: - self.FuncptrRets[self.FuncptrCount] = uint64(ret_ty) + if ret_copy_fp is not None: self.FuncptrRets[self.FuncptrCount] = uint64(ret_copy_fp) + else: self.FuncptrRets[self.FuncptrCount] = uint64(ret_ty) self.FuncptrCount += 1 return 0 def lookup_func_ptr_ret(self, name: str) -> mlirlite.LLVMType*: """查函数指针变量的返回类型,None=未注册(调用时默认 i32)""" - if name is None or self.FuncptrNames is None: - return None + if name is None or self.FuncptrNames is None: return None for i in range(self.FuncptrCount): idx: sizet = sizet(i) * 64 - if string.strcmp(self.FuncptrNames + idx, name) == 0: - return (mlirlite.LLVMType*)(self.FuncptrRets[i]) + if string.strcmp(self.FuncptrNames + idx, name) == 0: return (mlirlite.LLVMType*)(self.FuncptrRets[i]) return None @@ -764,8 +700,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): can: sizet, trans: HT.Translator*) -> mlirlite.Value*: """函数指针变量间接调用,返回结果 Value""" - if builder is None or fp_alloca is None: - return None + if builder is None or fp_alloca is None: return None i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty) i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) @@ -785,10 +720,8 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans) if arg_val is not None: arg_val.Next = None - if head is None: - head = arg_val - else: - tail.Next = arg_val + if head is None: head = arg_val + else: tail.Next = arg_val tail = arg_val arg_count += 1 @@ -801,27 +734,22 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): fp_prev: mlirlite.ParamNode* = None cur_v: mlirlite.Value* = head for pi in range(arg_count): - if cur_v is None: - break + if cur_v is None: break cur_ty: mlirlite.LLVMType* = mlirlite.value_get_ty(cur_v) pn2: mlirlite.ParamNode* = mlirlite.new_param_node(pool, cur_ty) if pn2 is not None: - if fp_first is None: - fp_first = pn2 - if fp_prev is not None: - mlirlite.paramnode_set_next(fp_prev, pn2) + if fp_first is None: fp_first = pn2 + if fp_prev is not None: mlirlite.paramnode_set_next(fp_prev, pn2) fp_prev = pn2 cur_v = mlirlite.value_get_next(cur_v) func_ty: mlirlite.LLVMType* = mlirlite.Func(pool, ret_ty, fp_first, arg_count) - if func_ty is None: - return None + if func_ty is None: return None func_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, func_ty) # 4. bitcast i8* → 函数指针类型,间接调用 fn_typed: mlirlite.Value* = mlirlite.build_bitcast(builder, fn_i8, func_ptr_ty) - if fn_typed is None: - return None + if fn_typed is None: return None return mlirlite.build_call_indirect(builder, fn_typed, head, arg_count, ret_ty) @@ -843,8 +771,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): arg0_kind: int = arg0.kind() if arg0_kind == ast.ASTKind.Constant: cn: ast.Constant* = ast.Constant*(arg0) - if cn.const_kind == ast.CONST_STR: - fmt_str = cn.str_val + if cn.const_kind == ast.CONST_STR: fmt_str = cn.str_val if fmt_str is None: return @@ -862,8 +789,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): if arg_val is not None: # C ABI integer promotion: i8/i16 → i32(printf 变参函数要求) arg_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(arg_val.Ty) - if arg_bits != 0 and arg_bits < 32: - arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, i32_ty, arg) + if arg_bits != 0 and arg_bits < 32: arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, i32_ty, arg) # C ABI float promotion: float → double(printf 变参函数要求) arg_fbits: int = self.Gen.ExprGenBase.get_llvm_float_bits(arg_val.Ty) if arg_fbits != 0 and arg_fbits < 64: @@ -886,13 +812,11 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): trans: HT.Translator* = None) -> None: """翻译 print 调用(类型感知格式化 + 默认换行)""" cargs: list[ast.AST*]* = cl.args - if cargs is None: - return + if cargs is None: return FMT_BUF_SIZE: sizet = 256 fmt_buf: bytes = stdlib.malloc(FMT_BUF_SIZE) - if fmt_buf is None: - return + if fmt_buf is None: return fmt_buf[0] = '\0' i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) @@ -917,8 +841,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): # 对象定义了 __str__ → 用其返回的字符串(i8*)按 %s 打印(对齐 TPC) str_ov_pr: mlirlite.Value* = self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, arg_val, "__str__", trans) - if str_ov_pr is not None: - arg_val = str_ov_pr + if str_ov_pr is not None: arg_val = str_ov_pr # 数组名(如 print(l),l: t.CArray[char, N]): # translate_value 会 load 出数组值([N x T]),print 无法格式化; @@ -957,8 +880,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): elif self.Gen.ExprGenBase.is_ptr_type(arg_val.Ty) != 0: # i8*(str/bytes)→ %s;其他指针 → 0x%llx pointee: mlirlite.LLVMType* = arg_val.Ty.Pointee - if pointee is not None and self.Gen.ExprGenBase.get_llvm_type_bits(pointee) == 8: - token = "%s" + if pointee is not None and self.Gen.ExprGenBase.get_llvm_type_bits(pointee) == 8: token = "%s" else: token = "0x%llx" arg_val = mlirlite.build_ptrtoint(builder, arg_val, i64_ty) @@ -972,35 +894,28 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): elif arg_bits == 16: token = "%d" arg_val = mlirlite.build_sext(builder, arg_val, i32_ty) - elif arg_bits == 32: - token = "%d" - else: - token = "%lld" + elif arg_bits == 32: token = "%d" + else: token = "%lld" elif arg_fbits != 0: token = "%f" - if arg_fbits < 64: - arg_val = mlirlite.build_fpext(builder, arg_val, dbl_ty) + if arg_fbits < 64: arg_val = mlirlite.build_fpext(builder, arg_val, dbl_ty) else: # 结构体值/数组/函数等 → "(unknown)",不传参 token = "(unknown)" chain_arg = 0 # 追加格式 token - if string.strlen(fmt_buf) < FMT_BUF_SIZE - 16: - viperlib.snprintf(fmt_buf + string.strlen(fmt_buf), 16, "%s", token) + if string.strlen(fmt_buf) < FMT_BUF_SIZE - 16: viperlib.snprintf(fmt_buf + string.strlen(fmt_buf), 16, "%s", token) # 链接参数 if chain_arg != 0: arg_val.Next = None - if arg_tail is None: - arg_head = arg_val - else: - arg_tail.Next = arg_val + if arg_tail is None: arg_head = arg_val + else: arg_tail.Next = arg_val arg_tail = arg_val arg_count += 1 # 追加默认换行(Python print 默认 end="\n") - if string.strlen(fmt_buf) < FMT_BUF_SIZE - 2: - viperlib.snprintf(fmt_buf + string.strlen(fmt_buf), 2, "\n") + if string.strlen(fmt_buf) < FMT_BUF_SIZE - 2: viperlib.snprintf(fmt_buf + string.strlen(fmt_buf), 2, "\n") fmt_ptr: mlirlite.Value* = self.Gen.ExprGenConst.create_global_string(builder, pool, mod, fmt_buf, trans) stdlib.free(fmt_buf) @@ -1014,8 +929,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): """分配并清零函数表数组""" size: sizet = max_count * GenTypes.FuncEntry.__sizeof__() funcs_ptr: GenTypes.FuncEntry* = pool.alloc(size) - if funcs_ptr is not None: - string.memset(funcs_ptr, 0, size) + if funcs_ptr is not None: string.memset(funcs_ptr, 0, size) return funcs_ptr @@ -1032,8 +946,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): "{owner_sha1}.{name}",按其 16 位前缀优先返回;无本模块条目 (纯 from-import/外部 stub)时回落首个同名条目(旧语义)。 """ - if name is None or funcs is None: - return None + if name is None or funcs is None: return None entry_size: sizet = GenTypes.FuncEntry.__sizeof__() # 全局函数表 + 无 owner(find_func_global / _register_global_func 去重路径): # owner 分支不激活 ⇒ 等价于"首个同名条目的 Func"(含 Func 为 None → None), @@ -1041,15 +954,13 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): # 线性扫描(owner 优先需按同组顺序遍历,索引不适用)。 gfuncs_match: int = 0 if owner_sha1 is None and self.GlobalFuncs is not None: - if uint64(funcs) == uint64(self.GlobalFuncs) and func_count == self.GlobalFuncCount: - gfuncs_match = 1 + if uint64(funcs) == uint64(self.GlobalFuncs) and func_count == self.GlobalFuncCount: gfuncs_match = 1 if gfuncs_match != 0 and self.GlobalFuncNameIdxBuilt == self.GlobalFuncCount and self.GlobalFuncNameIdx is not None and self.GlobalFuncNameIdxCap > 0: fi_t: int = _gfn_idx_find(self.GlobalFuncs, self.GlobalFuncNameIdx, self.GlobalFuncNameIdxCap, name) if fi_t >= 0: fe_t: GenTypes.FuncEntry* = GenTypes.FuncEntry*((uint64(self.GlobalFuncs) + fi_t * entry_size)) - if fe_t is not None: - return fe_t.Func + if fe_t is not None: return fe_t.Func # 索引可信(Built==GlobalFuncCount | 查询名非空)⇒ 未命中即"确无同名条目": # 全局表只经 _register_global_func 追加(每次追加即同步索引,失败则置 # Built=-1),名注册后不再改写 ⇒ owner_sha1 为 None 时原线性扫描等价于 @@ -1064,15 +975,12 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): # 快速路径:同名要求首字符相等(strcmp 判等蕴含首字符相等), # 首字符不同者直接跳过 strcmp,避免全表每槽一次函数调用。 if entry.Name[0] == name[0] and string.strcmp(entry.Name, name) == 0: - if fallback_entry is None: - fallback_entry = entry + if fallback_entry is None: fallback_entry = entry if entry.Func is not None and owner_sha1 is not None: fn_nm_o: str = mlirlite.function_get_name(entry.Func) if fn_nm_o is not None: - if string.strncmp(fn_nm_o, owner_sha1, 16) == 0 and fn_nm_o[16] == '.': - return entry.Func - if fallback_entry is not None: - return fallback_entry.Func + if string.strncmp(fn_nm_o, owner_sha1, 16) == 0 and fn_nm_o[16] == '.': return entry.Func + if fallback_entry is not None: return fallback_entry.Func return None @@ -1094,10 +1002,8 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): param_count: 形参数量(不含 self,len(args.args)) pool: 内存池(保留兼容参数;Spec 由 arena/PermPool 分配) """ - if name is None or func is None or funcs is None: - return 1 - if func_count >= max_count: - return 1 + if name is None or func is None or funcs is None: return 1 + if func_count >= max_count: return 1 entry_size: sizet = GenTypes.FuncEntry.__sizeof__() entry_addr: uint64 = uint64(funcs) + func_count * entry_size entry: GenTypes.FuncEntry* = GenTypes.FuncEntry*(entry_addr) @@ -1111,19 +1017,16 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): # 同时注册到全局函数表(供跨模块 vtable 初始化查找) self._register_global_func(name, func, pool) # 同时注册到全局默认参数表(供跨模块调用时填充默认值) - if default_count > 0: - self._register_global_defaults(name, defaults, default_count, param_count, def_sha1) + if default_count > 0: self._register_global_defaults(name, defaults, default_count, param_count, def_sha1) return 0 def _init_global_func_table(self) -> int: """初始化全局函数表(用 stdlib.malloc 分配,生命周期=整个程序)""" - if self.GlobalFuncs is not None: - return 1 + if self.GlobalFuncs is not None: return 1 size: sizet = CallGenBase.GLOBAL_FUNC_MAX * GenTypes.FuncEntry.__sizeof__() self.GlobalFuncs = CompilerFactory.factory.PermPool.alloc(size) - if self.GlobalFuncs is None: - return 0 + if self.GlobalFuncs is None: return 0 string.memset(self.GlobalFuncs, 0, size) self.GlobalFuncCount = 0 # 名索引(PermPool,与表同生命周期)。分配失败 → 保持不可信(Built=-1), @@ -1148,15 +1051,11 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): 直接操作全局表,不调用 add_func_to_table,避免递归。 """ - if name is None or func is None: - return 1 - if self._init_global_func_table() == 0: - return 1 + if name is None or func is None: return 1 + if self._init_global_func_table() == 0: return 1 # 已存在则跳过(避免重复) - if self.find_func_in_table(self.GlobalFuncs, self.GlobalFuncCount, name) is not None: - return 0 - if self.GlobalFuncCount >= CallGenBase.GLOBAL_FUNC_MAX: - return 1 + if self.find_func_in_table(self.GlobalFuncs, self.GlobalFuncCount, name) is not None: return 0 + if self.GlobalFuncCount >= CallGenBase.GLOBAL_FUNC_MAX: return 1 # 直接写入全局表(不调用 add_func_to_table,避免递归) entry_size: sizet = GenTypes.FuncEntry.__sizeof__() entry_addr: uint64 = uint64(self.GlobalFuncs) + self.GlobalFuncCount * entry_size @@ -1165,8 +1064,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): # reset_to(mark1) 回收导致悬空(vtable 生成 find_func_global 后 strcmp 崩溃) name_len: sizet = string.strlen(name) name_copy: str = CompilerFactory.factory.PermPool.alloc(name_len + 1) - if name_copy is None: - return 1 + if name_copy is None: return 1 string.strcpy(name_copy, name) entry.Name = name_copy entry.Func = func @@ -1180,8 +1078,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): if self.GlobalFuncNameIdxBuilt == self.GlobalFuncCount - 1 and _gfn_idx_insert(self.GlobalFuncNameIdx, self.GlobalFuncNameIdxCap, self.GlobalFuncCount - 1, name_copy) == 0: self.GlobalFuncNameIdxBuilt = self.GlobalFuncCount - else: - self.GlobalFuncNameIdxBuilt = -1 + else: self.GlobalFuncNameIdxBuilt = -1 return 0 @@ -1193,11 +1090,9 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): 用 NewTypeFunc 构造整签名 Spec(PermPool 驻留,跨 1b reset 安全), 供 vtable 生成在 func 被 1b reset 后经 SpecToLLVMText 派生类型文本。 """ - if name is None or func is None: - return 1 + if name is None or func is None: return 1 entry: GenTypes.FuncEntry* = self.find_func_entry_global(name) - if entry is None: - return 1 + if entry is None: return 1 entry.Spec = self._build_func_spec(func) return 0 @@ -1260,8 +1155,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): if entry.Name is not None: # 快速路径:同名要求首字符相等(strcmp 判等蕴含首字符相等), # 首字符不同者直接跳过 strcmp。 - if entry.Name[0] == name[0] and string.strcmp(entry.Name, name) == 0: - return entry + if entry.Name[0] == name[0] and string.strcmp(entry.Name, name) == 0: return entry return None @@ -1300,8 +1194,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): # 路径显式传入被依赖模块自身 sha1;非注入路径(本模块真实定义)取 # CurrentModuleSha1(此时它就是定义模块)。 cur_sha: str = def_sha1 - if cur_sha is None and self.Gen is not None and self.Gen.TypeGenBase is not None: - cur_sha = self.Gen.TypeGenBase.CurrentModuleSha1 + if cur_sha is None and self.Gen is not None and self.Gen.TypeGenBase is not None: cur_sha = self.Gen.TypeGenBase.CurrentModuleSha1 # 同模块同名已存在则跳过 if self.find_func_defaults(name, cur_sha) is not None: return 0 if self.GlobalDefaultsCount >= CallGenBase.GLOBAL_DEFAULTS_MAX: return 1 @@ -1400,21 +1293,16 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): module_sha1 非 None 时要求条目定义模块完全一致(限定名匹配,消除跨模块同名串味); 为 None 时退化为按名匹配(兼容旧调用点)。 """ - if name is None or self.GlobalDefaults is None: - return None + if name is None or self.GlobalDefaults is None: return None entry_size: sizet = GenTypes.FuncDefaultsEntry.__sizeof__() for i in range(self.GlobalDefaultsCount): entry_addr: uint64 = uint64(self.GlobalDefaults) + i * entry_size entry: GenTypes.FuncDefaultsEntry* = GenTypes.FuncDefaultsEntry*(entry_addr) - if entry.Name is None: - continue - if string.strcmp(entry.Name, name) != 0: - continue + if entry.Name is None: continue + if string.strcmp(entry.Name, name) != 0: continue if module_sha1 is not None: - if entry.ModuleSha1 is None: - continue - if string.strcmp(entry.ModuleSha1, module_sha1) != 0: - continue + if entry.ModuleSha1 is None: continue + if string.strcmp(entry.ModuleSha1, module_sha1) != 0: continue return entry return None @@ -1426,19 +1314,15 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): trans: HT.Translator*, builder: mlirlite.IRBuilder*) -> mlirlite.Value*: """从快照重建第 di 个默认值常量 IR""" - if gd_entry is None or gd_entry.ConstKinds is None or gd_entry.ConstInts is None: - return None - if di < 0 or di >= gd_entry.DefaultCount: - return None + if gd_entry is None or gd_entry.ConstKinds is None or gd_entry.ConstInts is None: return None + if di < 0 or di >= gd_entry.DefaultCount: return None kind: int = gd_entry.ConstKinds[di] ival: int64 = gd_entry.ConstInts[di] if kind == ast.CONST_INT: - if ival > 2147483647 or ival < -2147483648: - return mlirlite.const_int64(pool, ival) + if ival > 2147483647 or ival < -2147483648: return mlirlite.const_int64(pool, ival) return mlirlite.const_int32(pool, ival) elif kind == ast.CONST_BOOL: - if ival != 0: - return mlirlite.const_int32(pool, 1) + if ival != 0: return mlirlite.const_int32(pool, 1) return mlirlite.const_int32(pool, 0) elif kind == ast.CONST_NONE: i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) @@ -1456,16 +1340,14 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): func_count: int, name: str) -> GenTypes.FuncEntry*: """在函数表中按名称查找,返回完整 FuncEntry 或 None""" - if name is None or funcs is None: - return None + if name is None or funcs is None: return None entry_size: sizet = GenTypes.FuncEntry.__sizeof__() for i in range(func_count): entry_addr: uint64 = uint64(funcs) + i * entry_size entry: GenTypes.FuncEntry* = GenTypes.FuncEntry*(entry_addr) if entry.Name is not None: # 快速路径:strcmp 判等蕴含首字符相等,首字符不同者跳过 strcmp - if entry.Name[0] == name[0] and string.strcmp(entry.Name, name) == 0: - return entry + if entry.Name[0] == name[0] and string.strcmp(entry.Name, name) == 0: return entry return None def find_func_entry_in_table_owned(self, funcs: GenTypes.FuncEntry*, @@ -1482,25 +1364,20 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): 模块;owner_sha1 为 None(模块名不可解)时退化为裸名首命中(旧语义, 避免丢失合法的默认参数填充)。 """ - if name is None or funcs is None: - return None + if name is None or funcs is None: return None entry_size: sizet = GenTypes.FuncEntry.__sizeof__() for i in range(func_count): entry_addr: uint64 = uint64(funcs) + i * entry_size entry: GenTypes.FuncEntry* = GenTypes.FuncEntry*(entry_addr) - if entry is None or entry.Name is None: - continue + if entry is None or entry.Name is None: continue # 快速路径:strcmp 判等要求首字符相等,首字符不同者跳过 strcmp # (热点:本函数对函数表逐条按裸名 + 定义模块 SHA1 比对)。 - if entry.Name[0] != name[0] or string.strcmp(entry.Name, name) != 0: - continue - if owner_sha1 is None: - return entry + if entry.Name[0] != name[0] or string.strcmp(entry.Name, name) != 0: continue + if owner_sha1 is None: return entry if entry.Func is not None: fn_nm_o: str = mlirlite.function_get_name(entry.Func) if fn_nm_o is not None: - if string.strncmp(fn_nm_o, owner_sha1, 16) == 0 and fn_nm_o[16] == '.': - return entry + if string.strncmp(fn_nm_o, owner_sha1, 16) == 0 and fn_nm_o[16] == '.': return entry return None diff --git a/App/lib/core/Gen/Call/CallGenLib.vp b/App/lib/core/Gen/Call/CallGenLib.vp index a2ddee7..c95c79d 100644 --- a/App/lib/core/Gen/Call/CallGenLib.vp +++ b/App/lib/core/Gen/Call/CallGenLib.vp @@ -78,21 +78,16 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): elif string.strcmp(name, "labs") == 0: ret_ty = i64_ty params = 1 - else: - return None + else: return None # 创建 declare fn: mlirlite.Function* = mlirlite.create_declare(pool, mod, name, ret_ty) - if fn is None: - return None + if fn is None: return None # 添加参数 if params == 1: - if string.strcmp(name, "abs") == 0: - mlirlite.add_param(pool, fn, i32_ty, "n") - elif string.strcmp(name, "labs") == 0: - mlirlite.add_param(pool, fn, i64_ty, "n") - else: - mlirlite.add_param(pool, fn, i8_ptr_ty, "s") + if string.strcmp(name, "abs") == 0: mlirlite.add_param(pool, fn, i32_ty, "n") + elif string.strcmp(name, "labs") == 0: mlirlite.add_param(pool, fn, i64_ty, "n") + else: mlirlite.add_param(pool, fn, i8_ptr_ty, "s") elif params == 2: mlirlite.add_param(pool, fn, i8_ptr_ty, "dst") mlirlite.add_param(pool, fn, i8_ptr_ty, "src") @@ -122,11 +117,9 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): 实参提升到 i64,declare 与 call 均按 i64 生成 → 与定义一致。 未命中白名单原样返回 head。 """ - if pool is None or builder is None or call_name is None or head is None: - return head + if pool is None or builder is None or call_name is None or head is None: return head # 仅裸名(无 '.' 分隔 → 无 sha1 前缀);带前缀走 vpi 定义侧解析 - if string.strchr(call_name, 46) is not None: - return head + if string.strchr(call_name, 46) is not None: return head # 白名单:size_t(i64) 长度参数所在下标(与 _ensure_c_lib_declare 一致;vsnprintf 第二参即 sizet 长度) size_idx: int = -1 if string.strcmp(call_name, "memset") == 0: size_idx = 2 @@ -137,22 +130,19 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): elif string.strcmp(call_name, "strncpy") == 0: size_idx = 2 elif string.strcmp(call_name, "strncat") == 0: size_idx = 2 elif string.strcmp(call_name, "vsnprintf") == 0: size_idx = 1 - if size_idx < 0 or count <= size_idx: - return head + if size_idx < 0 or count <= size_idx: return head # 定位长度参数(index size_idx) cur: mlirlite.Value* = head idx: int = 0 while cur is not None and idx < size_idx: cur = cur.Next idx += 1 - if cur is None or cur.Ty is None: - return head + if cur is None or cur.Ty is None: return head i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool) promoted: mlirlite.Value* = None match cur.Ty: case mlirlite.LLVMType.Int(bits): - if bits >= 64: - return head + if bits >= 64: return head if cur.IsConst != 0: # 常量:直接 i64 常量(位模式保留,无符号长度语义) promoted = mlirlite.const_int(pool, 64, cur.IntVal) @@ -161,8 +151,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): promoted = mlirlite.build_zext(builder, cur, i64_ty) case _: return head - if promoted is None: - return head + if promoted is None: return head # 重建实参链表:index size_idx 替换为提升后的值 new_head: mlirlite.Value* = None new_tail: mlirlite.Value* = None @@ -170,12 +159,9 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): i2: int = 0 while cur2 is not None: node_v: mlirlite.Value* = cur2 - if i2 == size_idx: - node_v = promoted - if new_head is None: - new_head = node_v - else: - new_tail.Next = node_v + if i2 == size_idx: node_v = promoted + if new_head is None: new_head = node_v + else: new_tail.Next = node_v new_tail = node_v cur2 = cur2.Next i2 += 1 @@ -197,10 +183,8 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): (SSA)整型扩宽时的**源符号性**判定(与 ExprGenBase._zext_or_sext_val 同源);缺省时该判定退化为有符号(sext),与 coerce_to_type 默认一致。 """ - if pool is None or builder is None or call_name is None or head is None: - return head - if self._is_sha1_mangled_call(call_name) == 0: - return head + if pool is None or builder is None or call_name is None or head is None: return head + if self._is_sha1_mangled_call(call_name) == 0: return head # 拆 {sha1}.{rest}:rest 含 '.' 则为 {cls}.{method},否则为 {func} rest: str = call_name + 17 cls_nm: str = None @@ -209,39 +193,32 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): dot_r: str = string.strrchr(rest, 46) if dot_r is not None: cls_len: sizet = uint64(dot_r) - uint64(rest) - if cls_len <= 0: - return head + if cls_len <= 0: return head cls_buf: bytes = stdlib.malloc(cls_len + 1) - if cls_buf is None: - return head + if cls_buf is None: return head string.strncpy(cls_buf, rest, cls_len) cls_buf[cls_len] = '\0' cls_nm = cls_buf meth_nm = dot_r + 1 if meth_nm is None or meth_nm[0] == '\0': - if cls_nm is not None: - stdlib.free(cls_nm) + if cls_nm is not None: stdlib.free(cls_nm) return head sha1_buf: bytes = stdlib.malloc(17) if sha1_buf is None: - if cls_nm is not None: - stdlib.free(cls_nm) + if cls_nm is not None: stdlib.free(cls_nm) return head string.strncpy(sha1_buf, call_name, 16) sha1_buf[16] = '\0' # 直接 ensure 加载 + 直查缓存(不用 _vpi_method_param_annot:其 cls_name is None 时恒返回 None,模块级函数永不生效) - if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: - VpiReader._ensure_vpi_param_annot_loaded(sha1_buf, self.Gen.CallGenBase.TempDir) + if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: VpiReader._ensure_vpi_param_annot_loaded(sha1_buf, self.Gen.CallGenBase.TempDir) prm_annots: str = VpiReader._lookup_vpi_param_annots(sha1_buf, cls_nm, meth_nm) # 泛型特化类({sha}.list[str].__new__):定义侧注解写在模板类上,精确键必遗漏 ⇒ tpl_src=1 时退查模板注解并替换类型形参(VpiReader._resolve_vpi_param_annot_seg_template) tpl_src: int = 0 if prm_annots is None: - if cls_nm is not None and string.strchr(cls_nm, 91) is not None: - tpl_src = 1 + if cls_nm is not None and string.strchr(cls_nm, 91) is not None: tpl_src = 1 else: stdlib.free(sha1_buf) - if cls_nm is not None: - stdlib.free(cls_nm) + if cls_nm is not None: stdlib.free(cls_nm) return head i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) @@ -252,16 +229,13 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): while cur is not None and idx < count: node_v: mlirlite.Value* = cur tgt_ty: mlirlite.LLVMType* = None - if tpl_src != 0: - tgt_ty = VpiReader._resolve_vpi_param_annot_seg_template(pool, sha1_buf, cls_nm, meth_nm, idx, i32_ty, i8_ptr_ty) - else: - tgt_ty = VpiReader._resolve_vpi_param_annot_seg(pool, sha1_buf, cls_nm, meth_nm, idx, i32_ty, i8_ptr_ty) + if tpl_src != 0: tgt_ty = VpiReader._resolve_vpi_param_annot_seg_template(pool, sha1_buf, cls_nm, meth_nm, idx, i32_ty, i8_ptr_ty) + else: tgt_ty = VpiReader._resolve_vpi_param_annot_seg(pool, sha1_buf, cls_nm, meth_nm, idx, i32_ty, i8_ptr_ty) if tgt_ty is not None and cur.Ty is not None: # 实参 AST(源符号性判定用):链下标 idx 减 self 偏移即 AST 下标 arg_idx: int = idx - self_off arg_node: ast.AST* = None - if cargs is not None and arg_idx >= 0 and arg_idx < len(cargs): - arg_node = cargs.get(arg_idx) + if cargs is not None and arg_idx >= 0 and arg_idx < len(cargs): arg_node = cargs.get(arg_idx) # 「str / bytes 不是通用指针通配」:`void*` / `t.CPtr` / `rawptr` 允许 # 隐式转为任意指针类型,但 `str` / `bytes` 不允许——即便它们在 LLVM # 层同为 i8*。跨模块实参在这条路径上原本只做 bitcast、完全不过指针 @@ -276,16 +250,13 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): if VpiReader._vpi_param_annot_seg_is(sha1_buf, cls_nm, meth_nm, idx, "str") != 0 or VpiReader._vpi_param_annot_seg_is(sha1_buf, cls_nm, meth_nm, idx, "bytes") != 0: self.Gen.ExprGenBase.fail_if_str_annot_agg_ptr(cur, 1, arg_node) node_v = self._coerce_arg_value_to_ty(pool, builder, cur, tgt_ty, arg_node, trans, tpl_src) - if new_head is None: - new_head = node_v - else: - new_tail.Next = node_v + if new_head is None: new_head = node_v + else: new_tail.Next = node_v new_tail = node_v cur = cur.Next idx += 1 stdlib.free(sha1_buf) - if cls_nm is not None: - stdlib.free(cls_nm) + if cls_nm is not None: stdlib.free(cls_nm) return new_head # _coerce_arg_value_to_ty:单个实参 Value 转换到目标形参类型——整型同宽原样、窄化 trunc/按宽度重建常量、扩宽按源符号性 zext/sext;同层指针类型不一致则 bitcast 到目标类型;其余原样返回(不可转换亦不改型) @@ -304,14 +275,12 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): 类型形参替换,见 VpiReader._resolve_vpi_param_annot_seg_template)⇒ 指针口径亦可对齐定义侧(同为具体结构体指针但基类型不同时 bitcast)。 """ - if pool is None or builder is None or val is None or tgt_ty is None or val.Ty is None: - return val + if pool is None or builder is None or val is None or tgt_ty is None or val.Ty is None: return val match val.Ty: case mlirlite.LLVMType.Int(bits_a): match tgt_ty: case mlirlite.LLVMType.Int(bits_b): - if bits_b == bits_a: - return val + if bits_b == bits_a: return val if bits_b < bits_a: if val.IsConst != 0: nv_c: mlirlite.Value* = mlirlite.const_int(pool, bits_b, val.IntVal) @@ -322,8 +291,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): # 扩宽(实参窄于形参):编译期常量按十进制值重建,各自保持原类型数值,无需 AST 判符号性 if val.IsConst != 0: nv_w: mlirlite.Value* = mlirlite.const_int(pool, bits_b, val.IntVal) - if nv_w is not None: - return nv_w + if nv_w is not None: return nv_w return val # 非常量(SSA)扩宽:扩宽方向由源符号性决定(i1/i8、无符号源 → zext,否则 sext),使 declare/call/define 三者同宽 if bits_b > bits_a: @@ -382,8 +350,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): =0(Phase A 中间遍,_deps_pending 下遍重译可收敛)→ 返回默认 i32 占位,不输出 WARN(下遍依赖就绪后走 text.ll/vpi 精确解析)。 """ - if pool is None or func_name is None: - return mlirlite.Int32(pool) + if pool is None or func_name is None: return mlirlite.Int32(pool) # 提取裸函数名:去掉 SHA1 前缀(如 "240a9a4157959a9f.parse" → "parse") # SHA1 前缀是 16 位十六进制 + '.',检查是否有 '.' 分隔 @@ -396,28 +363,18 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) # 返回 i8* 的函数(指针返回值,截断会导致错误) - if string.strcmp(bare_name, "strchr") == 0 or string.strcmp(func_name, "strchr") == 0: - return i8_ptr_ty - if string.strcmp(bare_name, "strrchr") == 0 or string.strcmp(func_name, "strrchr") == 0: - return i8_ptr_ty - if string.strcmp(bare_name, "strstr") == 0 or string.strcmp(func_name, "strstr") == 0: - return i8_ptr_ty - if string.strcmp(bare_name, "strcpy") == 0 or string.strcmp(func_name, "strcpy") == 0: - return i8_ptr_ty - if string.strcmp(bare_name, "strncpy") == 0 or string.strcmp(func_name, "strncpy") == 0: - return i8_ptr_ty - if string.strcmp(bare_name, "memset") == 0 or string.strcmp(func_name, "memset") == 0: - return i8_ptr_ty - if string.strcmp(bare_name, "memset32") == 0 or string.strcmp(func_name, "memset32") == 0: - return i8_ptr_ty - if string.strcmp(bare_name, "memcpy") == 0 or string.strcmp(func_name, "memcpy") == 0: - return i8_ptr_ty - if string.strcmp(bare_name, "memmove") == 0 or string.strcmp(func_name, "memmove") == 0: - return i8_ptr_ty + if string.strcmp(bare_name, "strchr") == 0 or string.strcmp(func_name, "strchr") == 0: return i8_ptr_ty + if string.strcmp(bare_name, "strrchr") == 0 or string.strcmp(func_name, "strrchr") == 0: return i8_ptr_ty + if string.strcmp(bare_name, "strstr") == 0 or string.strcmp(func_name, "strstr") == 0: return i8_ptr_ty + if string.strcmp(bare_name, "strcpy") == 0 or string.strcmp(func_name, "strcpy") == 0: return i8_ptr_ty + if string.strcmp(bare_name, "strncpy") == 0 or string.strcmp(func_name, "strncpy") == 0: return i8_ptr_ty + if string.strcmp(bare_name, "memset") == 0 or string.strcmp(func_name, "memset") == 0: return i8_ptr_ty + if string.strcmp(bare_name, "memset32") == 0 or string.strcmp(func_name, "memset32") == 0: return i8_ptr_ty + if string.strcmp(bare_name, "memcpy") == 0 or string.strcmp(func_name, "memcpy") == 0: return i8_ptr_ty + if string.strcmp(bare_name, "memmove") == 0 or string.strcmp(func_name, "memmove") == 0: return i8_ptr_ty # JSON 解析函数返回 JsonValue*(指针) # from json.__parser import parse as json_parse → 别名 json_parse 也需覆盖 - if string.strcmp(bare_name, "parse") == 0 or string.strcmp(func_name, "parse") == 0 or string.strcmp(func_name, "json_parse") == 0: - return i8_ptr_ty + if string.strcmp(bare_name, "parse") == 0 or string.strcmp(func_name, "parse") == 0 or string.strcmp(func_name, "json_parse") == 0: return i8_ptr_ty # MemBuddy 方法(当类型信息丢失时可能走外部函数路径) # 存疑 # malloc:裸名 CExport 跨模块调用(uhci/desktop 等 mm.malloc → @malloc) @@ -425,107 +382,66 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): # 此白名单。缺失导致返回类型被推断为 i32 → call i32 @malloc 截断 64 位 # 指针 → mm.malloc 实际返回非空但调用方判 None(uhci frame list / # desktop bg_row_buf 根因)。calloc/realloc/alloc 均已登记,malloc 遗漏。 - if string.strcmp(bare_name, "malloc") == 0 or string.strcmp(func_name, "malloc") == 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) - if string.strcmp(func_name, "alloc") == 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) - if string.strcmp(func_name, "calloc") == 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) - if string.strcmp(func_name, "realloc") == 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) - if string.strcmp(func_name, "alloc_buf") == 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + if string.strcmp(bare_name, "malloc") == 0 or string.strcmp(func_name, "malloc") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + if string.strcmp(func_name, "alloc") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + if string.strcmp(func_name, "calloc") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + if string.strcmp(func_name, "realloc") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + if string.strcmp(func_name, "alloc_buf") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) # VLogger 模块函数(跨模块调用时 stub 未注入,返回指针被截断为 i32 导致崩溃) - if string.strcmp(func_name, "get_logger") == 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) - if string.strcmp(func_name, "fmt_buf") == 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + if string.strcmp(func_name, "get_logger") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + if string.strcmp(func_name, "fmt_buf") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) # Config 模块函数(跨模块调用时 stub 未注入,返回 i8* 被 inttoptr i32 截断导致路径损坏) - if string.strcmp(func_name, "get_includes_binary_dir") == 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + if string.strcmp(func_name, "get_includes_binary_dir") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) # HandlesType 模块函数(返回 ast.AST* 联合类型,跨模块推断为 i32 导致指针截断) - if string.strcmp(bare_name, "_parse_type_string") == 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + if string.strcmp(bare_name, "_parse_type_string") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) # 返回 i64 的函数 - if string.strcmp(func_name, "strlen") == 0: - return mlirlite.Int64(pool) - if string.strcmp(func_name, "atoll") == 0: - return mlirlite.Int64(pool) + if string.strcmp(func_name, "strlen") == 0: return mlirlite.Int64(pool) + if string.strcmp(func_name, "atoll") == 0: return mlirlite.Int64(pool) # mlirlite 函数名长度访问器返回 sizet(i64):默认 i32 与 declare 的 i64 签名不一致,须登记 - if string.strcmp(bare_name, "function_get_name_len") == 0 or string.strcmp(func_name, "function_get_name_len") == 0: - return mlirlite.Int64(pool) + if string.strcmp(bare_name, "function_get_name_len") == 0 or string.strcmp(func_name, "function_get_name_len") == 0: return mlirlite.Int64(pool) # 返回 double 的函数 - if string.strcmp(func_name, "atof") == 0: - return mlirlite.Double(pool) + if string.strcmp(func_name, "atof") == 0: return mlirlite.Double(pool) # 返回 i8 的函数 - if string.strcmp(func_name, "samestr") == 0: - return mlirlite.Int8(pool) + if string.strcmp(func_name, "samestr") == 0: return mlirlite.Int8(pool) # Win32 API 返回指针(VOIDPTR/HANDLE)的函数 # stubs 翻译时未注入,需推断返回 i8* 避免指针被截断为 i32 导致解引用崩溃 i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) - if string.strcmp(func_name, "VirtualAlloc") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "HeapAlloc") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "HeapReAlloc") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "HeapCreate") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "GetProcessHeap") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "GlobalAlloc") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "GlobalFree") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "GlobalLock") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "LocalAlloc") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "LocalFree") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "GetProcAddress") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "GetModuleHandleA") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "GetModuleHandleW") == 0: - return i8_ptr_ty + if string.strcmp(func_name, "VirtualAlloc") == 0: return i8_ptr_ty + if string.strcmp(func_name, "HeapAlloc") == 0: return i8_ptr_ty + if string.strcmp(func_name, "HeapReAlloc") == 0: return i8_ptr_ty + if string.strcmp(func_name, "HeapCreate") == 0: return i8_ptr_ty + if string.strcmp(func_name, "GetProcessHeap") == 0: return i8_ptr_ty + if string.strcmp(func_name, "GlobalAlloc") == 0: return i8_ptr_ty + if string.strcmp(func_name, "GlobalFree") == 0: return i8_ptr_ty + if string.strcmp(func_name, "GlobalLock") == 0: return i8_ptr_ty + if string.strcmp(func_name, "LocalAlloc") == 0: return i8_ptr_ty + if string.strcmp(func_name, "LocalFree") == 0: return i8_ptr_ty + if string.strcmp(func_name, "GetProcAddress") == 0: return i8_ptr_ty + if string.strcmp(func_name, "GetModuleHandleA") == 0: return i8_ptr_ty + if string.strcmp(func_name, "GetModuleHandleW") == 0: return i8_ptr_ty # GetCommandLineA/W 返回 LPSTR(i8*):缺则 64 位指针被截成 i32,解引用读到无效地址 - if string.strcmp(func_name, "GetCommandLineA") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "GetCommandLineW") == 0: - return i8_ptr_ty + if string.strcmp(func_name, "GetCommandLineA") == 0: return i8_ptr_ty + if string.strcmp(func_name, "GetCommandLineW") == 0: return i8_ptr_ty # gethostbyname 返回 hostent*(i8*) - if string.strcmp(func_name, "gethostbyname") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "LoadLibraryA") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "LoadLibraryW") == 0: - return i8_ptr_ty + if string.strcmp(func_name, "gethostbyname") == 0: return i8_ptr_ty + if string.strcmp(func_name, "LoadLibraryA") == 0: return i8_ptr_ty + if string.strcmp(func_name, "LoadLibraryW") == 0: return i8_ptr_ty # Win32 Handle 返回函数(HANDLE = void* = i8*) - if string.strcmp(func_name, "GetStdHandle") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "CreateFileA") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "CreateFileW") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "FindFirstFileA") == 0: - return i8_ptr_ty - if string.strcmp(func_name, "FindFirstFileW") == 0: - return i8_ptr_ty + if string.strcmp(func_name, "GetStdHandle") == 0: return i8_ptr_ty + if string.strcmp(func_name, "CreateFileA") == 0: return i8_ptr_ty + if string.strcmp(func_name, "CreateFileW") == 0: return i8_ptr_ty + if string.strcmp(func_name, "FindFirstFileA") == 0: return i8_ptr_ty + if string.strcmp(func_name, "FindFirstFileW") == 0: return i8_ptr_ty # Win32 API 返回 i64 (SIZE_T) 的函数 - if string.strcmp(func_name, "VirtualQuery") == 0: - return mlirlite.Int64(pool) - if string.strcmp(func_name, "HeapSize") == 0: - return mlirlite.Int64(pool) - if string.strcmp(func_name, "HeapCompact") == 0: - return mlirlite.Int64(pool) - if string.strcmp(func_name, "GlobalSize") == 0: - return mlirlite.Int64(pool) + if string.strcmp(func_name, "VirtualQuery") == 0: return mlirlite.Int64(pool) + if string.strcmp(func_name, "HeapSize") == 0: return mlirlite.Int64(pool) + if string.strcmp(func_name, "HeapCompact") == 0: return mlirlite.Int64(pool) + if string.strcmp(func_name, "GlobalSize") == 0: return mlirlite.Int64(pool) # mlirlite build_* 返回类型推断:多数返回 Value*,少数终止指令返回 void(stubs 未注入时防指针截断) if string.strncmp(func_name, "build_", 6) == 0: @@ -540,8 +456,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): return mlirlite.Ptr(pool, mlirlite.Int8(pool)) # 默认 i32 占位:fatal_if_unknown=1 → fail-fast 报错;=0(Phase A 中间遍)保持占位,不输出 WARN - 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"外部函数返回类型未登记且无法收敛推断(默认 i32 会截断指针/i64,需提供 stub 声明或加入白名单): {func_name}", "TypeError") return mlirlite.Int32(pool) def _get_external_func_param_ty(self, pool: memhub.MemBuddy*, func_name: str, @@ -558,8 +473,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): 与 declare(i32) 不匹配(mlir-opt: "llvm.call op operand type mismatch", 现场 FuncTest VirtualAlloc)。故仅在拿不到定义侧注解时才用。 """ - if pool is None or func_name is None: - return None + if pool is None or func_name is None: return None i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool) @@ -581,19 +495,15 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): api_count: sizet = len(win32_apis) for ai in range(api_count): api_name: str = win32_apis.get(ai) - if string.strcmp(api_name, func_name) == 0: - return i64_ty + if string.strcmp(api_name, func_name) == 0: return i64_ty # 内存分配函数:size 参数声明为 i64(size_t),裸名回退时不提升则 call 与 define 宽度不匹配;calloc/realloc 的 size 在 idx 1 if string.strcmp(func_name, "malloc") == 0 or string.strcmp(func_name, "alloc") == 0 or string.strcmp(func_name, "alloc_buf") == 0: - if param_idx == 0: - return i64_ty + if param_idx == 0: return i64_ty if string.strcmp(func_name, "calloc") == 0: - if param_idx == 0 or param_idx == 1: - return i64_ty + if param_idx == 0 or param_idx == 1: return i64_ty if string.strcmp(func_name, "realloc") == 0: - if param_idx == 1: - return i64_ty + if param_idx == 1: return i64_ty return None def _is_sha1_mangled_call(self, call_name: str) -> int: @@ -603,10 +513,8 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): 不参与精确返回类型解析(走 _infer_external_func_ret_ty 白名单)。 判定走唯一真源 GenApi.sha1_prefix_len(C10 收敛:不再接受大写 hex)。 """ - if call_name is None: - return 0 - if GenApi.sha1_prefix_len(call_name) != 0: - return 1 + if call_name is None: return 0 + if GenApi.sha1_prefix_len(call_name) != 0: return 1 return 0 def _emit_llvm_memcpy_intrinsic(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, @@ -619,10 +527,8 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): 直接接收三个 Value 参数,避免通过 Next 链表遍历(共享 alloca 对象的 Next 字段可能被其他操作污染,导致链表断裂)。 """ - if pool is None or builder is None or mod is None: - return None - if dst_val is None or src_val is None or num_val is None: - return None + if pool is None or builder is None or mod is None: return None + if dst_val is None or src_val is None or num_val is None: return None # 在函数顶部声明 void_ty,避免后续遮蔽 void_ty: mlirlite.LLVMType* = mlirlite.Void(pool) @@ -648,32 +554,27 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): # dst → i8* dst_coerced: mlirlite.Value* = dst_val dst_ty: mlirlite.LLVMType* = mlirlite.value_get_ty(dst_val) - if self.Gen.ExprGenBase.is_ptr_type(dst_ty) != 0: - dst_coerced = mlirlite.build_bitcast(builder, dst_val, i8_ptr_ty) + if self.Gen.ExprGenBase.is_ptr_type(dst_ty) != 0: dst_coerced = mlirlite.build_bitcast(builder, dst_val, i8_ptr_ty) else: dst_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(dst_ty) if dst_bits != 0: - if dst_bits < 64: - dst_coerced = mlirlite.build_zext(builder, dst_val, i64_ty) + if dst_bits < 64: dst_coerced = mlirlite.build_zext(builder, dst_val, i64_ty) dst_coerced = mlirlite.build_inttoptr(builder, dst_coerced, i8_ptr_ty) # src → i8* src_coerced: mlirlite.Value* = src_val src_ty: mlirlite.LLVMType* = mlirlite.value_get_ty(src_val) - if self.Gen.ExprGenBase.is_ptr_type(src_ty) != 0: - src_coerced = mlirlite.build_bitcast(builder, src_val, i8_ptr_ty) + if self.Gen.ExprGenBase.is_ptr_type(src_ty) != 0: src_coerced = mlirlite.build_bitcast(builder, src_val, i8_ptr_ty) else: src_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(src_ty) if src_bits != 0: - if src_bits < 64: - src_coerced = mlirlite.build_zext(builder, src_val, i64_ty) + if src_bits < 64: src_coerced = mlirlite.build_zext(builder, src_val, i64_ty) src_coerced = mlirlite.build_inttoptr(builder, src_coerced, i8_ptr_ty) # num → i64 num_coerced: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, num_val, i64_ty) - if dst_coerced is None or src_coerced is None or num_coerced is None: - return None + if dst_coerced is None or src_coerced is None or num_coerced is None: return None # 添加 i1 false 参数(isvolatile)— llvm.memcpy 需要 4 个参数 false_val: mlirlite.Value* = mlirlite.ConstInt(pool, mlirlite.Int1(pool), 0, "false") @@ -685,8 +586,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): if false_val is not None: mlirlite.value_set_next(num_coerced, false_val) mlirlite.value_set_next(false_val, None) - else: - mlirlite.value_set_next(num_coerced, None) + else: mlirlite.value_set_next(num_coerced, None) # 使用 build_call 发射 call 指令(内部用 includes Value 类型访问字段,索引正确) # _ll_name_needs_quote 已对 llvm. 前缀豁免引号 @@ -738,18 +638,15 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): string.strncpy(kw_sha_buf, kw_found_name, 16) kw_sha_buf[16] = '\0' kw_callee_sha = kw_sha_buf - if kw_callee_sha is None and self.Gen.TypeGenBase is not None: - kw_callee_sha = self.Gen.TypeGenBase.CurrentModuleSha1 + if kw_callee_sha is None and self.Gen.TypeGenBase is not None: kw_callee_sha = self.Gen.TypeGenBase.CurrentModuleSha1 kw_gd: GenTypes.FuncDefaultsEntry* = None - if kw_callee_sha is not None: - kw_gd = self.Gen.CallGenLeafKit.find_func_defaults(func_name, kw_callee_sha) + if kw_callee_sha is not None: kw_gd = self.Gen.CallGenLeafKit.find_func_defaults(func_name, kw_callee_sha) kw_default_count: int = 0 kw_default_off: int = 0 if kw_gd is not None: kw_default_count = kw_gd.DefaultCount kw_default_off = kw_gd.ParamCount - kw_gd.DefaultCount - if kw_default_off < 0: - kw_default_off = 0 + if kw_default_off < 0: kw_default_off = 0 # 遍历函数参数链表(使用访问器获取 Head) param_idx: sizet = 0 @@ -786,8 +683,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): pool, mod, kw_gd, kw_di, trans, builder) if arg_val is None: kw_node: ast.AST* = None - if keywords is not None and kw_count > 0: - kw_node = keywords.get(0) + if keywords is not None and kw_count > 0: kw_node = keywords.get(0) self.Gen.TypeGenErr.fatal_error( kw_node, f"调用 '{func_name}' 的某个形参既未按位置/关键字传入," @@ -796,21 +692,15 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): if arg_val is not None: # 类型转换(按参数类型,使用访问器) - if param_ty is not None: - arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, param_ty) + if param_ty is not None: arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, param_ty) arg_val.Next = None - if head is None: - head = arg_val - else: - tail.Next = arg_val + if head is None: head = arg_val + else: tail.Next = arg_val tail = arg_val # memcpy 专用: 保存前三个参数的独立引用 - if actual_count == 0: - mc_dst1 = arg_val - elif actual_count == 1: - mc_src1 = arg_val - elif actual_count == 2: - mc_num1 = arg_val + if actual_count == 0: mc_dst1 = arg_val + elif actual_count == 1: mc_src1 = arg_val + elif actual_count == 2: mc_num1 = arg_val actual_count += 1 param_idx += 1 @@ -819,8 +709,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): # declare 与 define 统一用 found_func.Name:普通函数带 SHA1 前缀,t.CExtern/t.State/t.CExport 用裸名(用裸名会造成 call 与 define 符号名不一致) call_name: str = func_name found_name: str = mlirlite.function_get_name(found_func) - if found_name is not None: - call_name = found_name + if found_name is not None: call_name = found_name # 返回类型(使用访问器) call_ret_ty: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(found_func) @@ -830,6 +719,5 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): call_ret_ty = self._infer_external_func_ret_ty(pool, func_name, None, 0) # memcpy → @llvm.memcpy 内联函数(避免 monomorphization 跨模块 @memcpy 声明缺失) - if string.strcmp(func_name, "memcpy") == 0 and actual_count >= 3: - return self._emit_llvm_memcpy_intrinsic(pool, builder, mod, mc_dst1, mc_src1, mc_num1) + if string.strcmp(func_name, "memcpy") == 0 and actual_count >= 3: return self._emit_llvm_memcpy_intrinsic(pool, builder, mod, mc_dst1, mc_src1, mc_num1) return mlirlite.build_call(builder, call_name, head, actual_count, call_ret_ty, 0) \ No newline at end of file diff --git a/App/lib/core/Gen/Call/CallGenMixin.vp b/App/lib/core/Gen/Call/CallGenMixin.vp index aa88ade..44c11b3 100644 --- a/App/lib/core/Gen/Call/CallGenMixin.vp +++ b/App/lib/core/Gen/Call/CallGenMixin.vp @@ -53,35 +53,24 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): def _CheckStaticCallCrossModule(self, pool: memhub.MemBuddy*, trans: HT.Translator*, cl: ast.Call*) -> int: - if cl is None or cl.func is None or trans is None: - return 0 - if cl.func.kind() != ast.ASTKind.Attribute: - return 0 - if trans.ModuleSha1 is None or trans._imported_modules is None: - return 0 + if cl is None or cl.func is None or trans is None: return 0 + if cl.func.kind() != ast.ASTKind.Attribute: return 0 + if trans.ModuleSha1 is None or trans._imported_modules is None: return 0 # 快速短路:项目内无 static 符号时零开销(不查 sha1、不扫表) - if self.Gen.CallGenBase.StaticCount <= 0: - return 0 + if self.Gen.CallGenBase.StaticCount <= 0: return 0 sc_at: ast.Attribute* = ast.Attribute*(cl.func) - if sc_at.value is None or sc_at.attr is None: - return 0 + if sc_at.value is None or sc_at.attr is None: return 0 sc_mod: str = None if sc_at.value.kind() == ast.ASTKind.Name: sc_nm: ast.Name* = ast.Name*(sc_at.value) sc_mod = sc_nm.id - elif sc_at.value.kind() == ast.ASTKind.Attribute: - sc_mod = self.Gen.ExprGenAttr._attr_module_path_str(pool, sc_at.value) - if sc_mod is None: - return 0 - if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, sc_mod) == 0: - return 0 + elif sc_at.value.kind() == ast.ASTKind.Attribute: sc_mod = self.Gen.ExprGenAttr._attr_module_path_str(pool, sc_at.value) + if sc_mod is None: return 0 + if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, sc_mod) == 0: return 0 sc_sha1: str = self.Gen.StructGen._resolve_module_sha1(sc_mod, trans._from_imports) - 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 + 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") @@ -110,38 +99,32 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): cargs: list[ast.AST*]* = cl.args can: sizet = 0 - if cargs is not None: - can = len(cargs) + if cargs is not None: can = len(cargs) # ---- 泛型函数调用(PEP 695 def f[T])优先拦截 ---- # 泛型函数模板在定义处不发射普通函数(见 FuncGenDef 守护),必须在此 # 之前完成类型实参推断 + 单态化。命中即返回(含 void 返回:hit_box=1 # 区分"已处理无返回值"与"未命中")。未命中返回 None 继续既有分派。 h0_hit: t.CPtr = stdlib.malloc(4) - if h0_hit is not None: - h0_hit[0] = 0 + if h0_hit is not None: h0_hit[0] = 0 _tc_h0_generic_func_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h0_generic_func(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h0_hit) h0_hit_val: int = 0 if h0_hit is not None: h0_hit_val = h0_hit[0] stdlib.free(h0_hit) - if _tc_h0_generic_func_res is not None: - return _tc_h0_generic_func_res - if h0_hit_val != 0: - return None + if _tc_h0_generic_func_res is not None: return _tc_h0_generic_func_res + if h0_hit_val != 0: return None # super()/ctraits 检测:void 方法(如 __init__)命中后 build_call 返回 # None 属预期(void call 无 SSA 值),必须用 hit_box 区分"命中已处理" # 与"未命中",否则 None 被误判继续主路径 → 内层 Call(super) 当裸名 # 调用报"super 未定义且未导入"(SuperTest 根因)。 h1_hit: t.CPtr = stdlib.malloc(4) - if h1_hit is not None: - h1_hit[0] = 0 + if h1_hit is not None: h1_hit[0] = 0 _tc_h1_super_ctraits_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h1_super_ctraits(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h1_hit) h1_hit_val: int = 0 if h1_hit is not None: h1_hit_val = h1_hit[0] stdlib.free(h1_hit) - if _tc_h1_super_ctraits_res is not None: - return _tc_h1_super_ctraits_res + if _tc_h1_super_ctraits_res is not None: return _tc_h1_super_ctraits_res if h1_hit_val != 0: # 命中 super()/ctraits 但无返回值(void 方法/宏调用):视为已处理 return None @@ -175,8 +158,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 泛型函数按普通函数编译,类型参数 [T] 仅在函数定义处消费)。 # 检查当前模块是否已定义同名函数(def double[T] 编译后即普通函数 # double),若是则丢弃 [int] 显式类型参数,退回普通函数调用。 - if self.find_func_in_module(mod, gen_class_name) is not None: - func_name = gen_class_name + if self.find_func_in_module(mod, gen_class_name) is not None: func_name = gen_class_name else: # 内建指针/类型下标 cast:(rawptr[list[int]])(lst)、 # (t.CPtr[T])(x)、(t.CArray[i8, N])(x) —— rawptr/CPtr/ @@ -204,8 +186,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): binop_args: list[ast.AST*]* = cl.args if binop_args is not None and len(binop_args) == 1: binop_arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, binop_args.get(0), funcs_ptr, func_count, trans) - if binop_arg_val is not None: - return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, binop_arg_val, binop_ty) + if binop_arg_val is not None: return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, binop_arg_val, binop_ty) return None # c.Asm/c.LLVMIR 等特殊调用:void(无输出)时 translate_c_asm/llvmir @@ -213,30 +194,25 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 否则会误判未命中继续走外部函数路径(外部函数返回类型未登记 Asm + # t.ASM_DESCR 被当 CDefine 常量赋值) h2_hit: t.CPtr = stdlib.malloc(4) - if h2_hit is not None: - h2_hit[0] = 0 + if h2_hit is not None: h2_hit[0] = 0 _tc_h2_c_special_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h2_c_special(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h2_hit) h2_hit_val: int = 0 if h2_hit is not None: h2_hit_val = h2_hit[0] stdlib.free(h2_hit) - if _tc_h2_c_special_res is not None: - return _tc_h2_c_special_res + if _tc_h2_c_special_res is not None: return _tc_h2_c_special_res if h2_hit_val != 0: # 命中 c.Asm/c.LLVMIR 但无返回值(void):视为已处理 return None _tc_h3_stdarg_cast_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h3_stdarg_cast(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can) - if _tc_h3_stdarg_cast_res is not None: - return _tc_h3_stdarg_cast_res + if _tc_h3_stdarg_cast_res is not None: return _tc_h3_stdarg_cast_res _tc_h4_type_casts_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h4_type_casts(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can) - if _tc_h4_type_casts_res is not None: - return _tc_h4_type_casts_res + if _tc_h4_type_casts_res is not None: return _tc_h4_type_casts_res _tc_h5_sizeof_len_isinst_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h5_sizeof_len_isinst(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can) - if _tc_h5_sizeof_len_isinst_res is not None: - return _tc_h5_sizeof_len_isinst_res + if _tc_h5_sizeof_len_isinst_res is not None: return _tc_h5_sizeof_len_isinst_res # c.Asm/c.LLVMIR 等方法调用分派:方法调用识别成功但返回 None # (如编译器生成方法 __before_init__/__init__ 恒返回 void,_translate_ @@ -245,15 +221,13 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 未命中继续走跨模块函数路径,把对象名当模块名查 SHA1 → # "跨模块调用 'buf.__before_init__' 找不到模块 SHA1"(memhub.alloc_buf 根因)。 h6_hit: t.CPtr = stdlib.malloc(4) - if h6_hit is not None: - h6_hit[0] = 0 + if h6_hit is not None: h6_hit[0] = 0 _tc_h6_method_dispatch_res: mlirlite.Value* = self.Gen.CallGenDispatch._tc_h6_method_dispatch(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h6_hit) h6_hit_val: int = 0 if h6_hit is not None: h6_hit_val = h6_hit[0] stdlib.free(h6_hit) - if _tc_h6_method_dispatch_res is not None: - return _tc_h6_method_dispatch_res + if _tc_h6_method_dispatch_res is not None: return _tc_h6_method_dispatch_res if h6_hit_val != 0: # 命中方法调用路径但无返回值(编译器生成方法等 void 语义):视为已处理 return None @@ -261,8 +235,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 获取关键字参数 keywords: list[ast.AST*]* = cl.keywords kw_count: sizet = 0 - if keywords is not None: - kw_count = len(keywords) + if keywords is not None: kw_count = len(keywords) # 检查是否是结构体构造函数: Point() / Point(10, 20) / Point(x=10, y=20) # 命名空间隔离:严格模式下检查结构体可见性 @@ -282,10 +255,8 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): mod_path0: str = None if at_qc0.value is not None and at_qc0.value.kind() == ast.ASTKind.Name: mod_nm0: ast.Name* = ast.Name*(at_qc0.value) - if mod_nm0.id is not None: - mod_path0 = mod_nm0.id - elif at_qc0.value is not None and at_qc0.value.kind() == ast.ASTKind.Attribute: - mod_path0 = self.Gen.ExprGenAttr._attr_module_path_str(pool, at_qc0.value) + if mod_nm0.id is not None: mod_path0 = mod_nm0.id + elif at_qc0.value is not None and at_qc0.value.kind() == ast.ASTKind.Attribute: mod_path0 = self.Gen.ExprGenAttr._attr_module_path_str(pool, at_qc0.value) if mod_path0 is not None: if self.Gen.ImportsGen.is_module_imported_or_known(trans._imported_modules, mod_path0) != 0: mod_sha1_0: str = self._lookup_module_sha1(mod_path0) @@ -294,17 +265,13 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): mod_qual_done = 1 vis: int = self.Gen.StructGen.is_struct_visible(func_name) if mod_qual_done == 0 and vis != 0: - if trans is not None: - gen_ctor_entry = self.Gen.StructGen.find_struct_by_module(func_name, trans.ModuleSha1) - if gen_ctor_entry is None: - gen_ctor_entry = self.Gen.StructGen.find_struct(func_name) + if trans is not None: gen_ctor_entry = self.Gen.StructGen.find_struct_by_module(func_name, trans.ModuleSha1) + if gen_ctor_entry is None: gen_ctor_entry = self.Gen.StructGen.find_struct(func_name) # 前向声明占位(裸泛型模板注解 `Class` 无实参时由 TypeGenResolve 登记) # 不是真实结构体定义:不作为裸名构造的 struct_ty,交由下方泛型推断按实参 # 特化(与模块限定分支同口径)。 - if gen_ctor_entry is not None and gen_ctor_entry.IsForwardDecl != 0 and self.Gen.ClassGenGeneric._find_generic_template(func_name) is not None: - gen_ctor_entry = None - if gen_ctor_entry is not None: - struct_ty = gen_ctor_entry.Ty + if gen_ctor_entry is not None and gen_ctor_entry.IsForwardDecl != 0 and self.Gen.ClassGenGeneric._find_generic_template(func_name) is not None: gen_ctor_entry = None + if gen_ctor_entry is not None: struct_ty = gen_ctor_entry.Ty elif trans is not None and cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: at_qc: ast.Attribute* = ast.Attribute*(cl.func) if at_qc.value is not None and at_qc.value.kind() == ast.ASTKind.Name: @@ -318,14 +285,10 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 0ae 先注册 → ctor 生成 @0ae.Scene3D.__before_init__ → 链接 # undefined symbol,Scene3D 根因)。 mod_sha1_qc2: str = None - if mod_nm_qc.id is not None: - mod_sha1_qc2 = self._lookup_module_sha1(mod_nm_qc.id) - if mod_sha1_qc2 is not None: - gen_ctor_entry = self.Gen.StructGen.find_struct_by_module(func_name, mod_sha1_qc2) - if gen_ctor_entry is None: - gen_ctor_entry = self.Gen.StructGen.find_struct(func_name) - if gen_ctor_entry is not None: - struct_ty = gen_ctor_entry.Ty + if mod_nm_qc.id is not None: mod_sha1_qc2 = self._lookup_module_sha1(mod_nm_qc.id) + if mod_sha1_qc2 is not None: gen_ctor_entry = self.Gen.StructGen.find_struct_by_module(func_name, mod_sha1_qc2) + if gen_ctor_entry is None: gen_ctor_entry = self.Gen.StructGen.find_struct(func_name) + if gen_ctor_entry is not None: struct_ty = gen_ctor_entry.Ty elif at_qc.value is not None and at_qc.value.kind() == ast.ASTKind.Attribute: # 多层模块路径类构造: w32.fileio.File(...)(value 是嵌套 Attribute)。 # 仅两层(fileio.File)支持时,三层会被跳过 → 退化走跨模块普通函数 @@ -340,12 +303,9 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): imp_ok_qc: int = self.Gen.ImportsGen.is_module_imported(trans._imported_modules, mod_path_qc) if imp_ok_qc != 0: mod_sha1_qc: str = self._lookup_module_sha1(mod_path_qc) - if mod_sha1_qc is not None: - gen_ctor_entry = self.Gen.StructGen.find_struct_by_module(func_name, mod_sha1_qc) - if gen_ctor_entry is None: - gen_ctor_entry = self.Gen.StructGen.find_struct(func_name) - if gen_ctor_entry is not None: - struct_ty = gen_ctor_entry.Ty + if mod_sha1_qc is not None: gen_ctor_entry = self.Gen.StructGen.find_struct_by_module(func_name, mod_sha1_qc) + if gen_ctor_entry is None: gen_ctor_entry = self.Gen.StructGen.find_struct(func_name) + if gen_ctor_entry is not None: struct_ty = gen_ctor_entry.Ty # 别名导入的类构造: from X import Class as Alias → Alias(args) # 可见性列表按别名注册(HandleImportFromNames 用 local_name=asname),但结构体 # 按原名注册(如 Keyword as KwNode → 可见 "KwNode"、注册名 "Keyword")。 @@ -359,17 +319,14 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if ctor_orig is not None: # 复制到独立 null 终止缓冲区(from_imports 内部缓冲未终止) co_len: sizet = 0 - while ctor_orig[co_len] != ' ' and ctor_orig[co_len] != '\0': - co_len += 1 + while ctor_orig[co_len] != ' ' and ctor_orig[co_len] != '\0': co_len += 1 co_buf: str = pool.alloc(co_len + 1) if co_buf is not None: - for co_i in range(co_len): - co_buf[co_i] = ctor_orig[co_i] + for co_i in range(co_len): co_buf[co_i] = ctor_orig[co_i] co_buf[co_len] = '\0' # 原名结构体查找(可见性已由别名保证,原名无需再查) gen_ctor_entry = self.Gen.StructGen.find_struct_by_module(co_buf, ctor_sha1) - if gen_ctor_entry is None: - gen_ctor_entry = self.Gen.StructGen.find_struct(co_buf) + if gen_ctor_entry is None: gen_ctor_entry = self.Gen.StructGen.find_struct(co_buf) if gen_ctor_entry is not None: struct_ty = gen_ctor_entry.Ty func_name = co_buf @@ -378,19 +335,15 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # OOP 结构体:即使无参数也调用 __before_init__ # 用 gen_ctor_entry 规避跨模块同名 find_struct 找错 ctor_is_oop: int = 0 - if gen_ctor_entry is not None: - ctor_is_oop = gen_ctor_entry.IsOOP - if ctor_is_oop != 0: - return self.Gen.CallGenCtor._translate_struct_ctor(pool, builder, mod, struct_ty, func_name, cargs, sizet(0), trans, cl.IsVolatile) + if gen_ctor_entry is not None: ctor_is_oop = gen_ctor_entry.IsOOP + if ctor_is_oop != 0: return self.Gen.CallGenCtor._translate_struct_ctor(pool, builder, mod, struct_ty, func_name, cargs, sizet(0), trans, cl.IsVolatile) # @t.NoVTable 类(无方法、类语义/指针对象):无参构造也应分配内存 # 返回指针。否则按值结构体返回 ConstZero(struct_ty),LHS 联合注解 # (如 Plain*)存 0 指针 → p.v 解引用 NULL 段错误 # (TpvIsinstanceTest Plain 场景崩溃根因)。 ctor_is_novt: int = 0 - if gen_ctor_entry is not None: - ctor_is_novt = gen_ctor_entry.IsNoVTable - if ctor_is_novt != 0: - return self.Gen.CallGenCtor._translate_struct_ctor(pool, builder, mod, struct_ty, func_name, cargs, sizet(0), trans, cl.IsVolatile) + if gen_ctor_entry is not None: ctor_is_novt = gen_ctor_entry.IsNoVTable + if ctor_is_novt != 0: return self.Gen.CallGenCtor._translate_struct_ctor(pool, builder, mod, struct_ty, func_name, cargs, sizet(0), trans, cl.IsVolatile) # 普通结构体:检查是否有默认值(用 entry 直接访问) gen_has_defaults: int = 0 if gen_ctor_entry is not None: @@ -399,8 +352,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if gdf is not None and gdf.DefaultVal is not None: gen_has_defaults = 1 break - else: - gen_has_defaults = self.Gen.StructGen.struct_has_defaults(func_name) + else: gen_has_defaults = self.Gen.StructGen.struct_has_defaults(func_name) if gen_has_defaults == 1: # 有默认值:走构造函数路径应用默认值 return self.Gen.CallGenCtor._translate_struct_ctor(pool, builder, mod, struct_ty, func_name, cargs, sizet(0), trans, cl.IsVolatile) @@ -426,19 +378,16 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # D25 接收者 fail-fast(VectorGenericTest 根因)。 gen_ctor_is_fwd_generic: int = 0 if gen_ctor_entry is not None and gen_ctor_entry.IsForwardDecl != 0: - if self.Gen.ClassGenGeneric._find_generic_template(func_name) is not None: - gen_ctor_is_fwd_generic = 1 + if self.Gen.ClassGenGeneric._find_generic_template(func_name) is not None: gen_ctor_is_fwd_generic = 1 if struct_ty is None and (gen_ctor_entry is None or gen_ctor_is_fwd_generic != 0) and trans is not None: is_gen_bare: int = 0 - if cl.func is not None and cl.func.kind() == ast.ASTKind.Name: - is_gen_bare = 1 + if cl.func is not None and cl.func.kind() == ast.ASTKind.Name: is_gen_bare = 1 elif cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: at_gb: ast.Attribute* = ast.Attribute*(cl.func) if at_gb.value is not None and at_gb.value.kind() == ast.ASTKind.Name: am_gb: ast.Name* = ast.Name*(at_gb.value) if am_gb.id is not None: - if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, am_gb.id) != 0: - is_gen_bare = 1 + if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, am_gb.id) != 0: is_gen_bare = 1 if is_gen_bare != 0: template_cd_bare: ast.ClassDef* = self.Gen.ClassGenGeneric._find_generic_template(func_name) if template_cd_bare is not None and template_cd_bare.type_params is not None: @@ -452,8 +401,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): tpi_bare: sizet = 0 for tpi_bare in range(tp_count_bare): aip_bare: int = self.Gen.CallGenCtor._find_ctor_type_param_arg_index(func_name, tp_bare.get(tpi_bare)) - if aip_bare < 0: - aip_bare = int(tpi_bare) + if aip_bare < 0: aip_bare = int(tpi_bare) ais_bare: sizet = sizet(aip_bare) # [D25 fail-fast] 禁止静默默认 "int":此前 ta_bare 初值为 # "int",在「hint 为空且位置实参也不足」时会凭空特化成 @@ -462,8 +410,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 与 _infer_generic_ctor_type_arg 的注释「绝不默认 int」对齐, # 改为 fail-fast 并指明显式标注写法。 ta_bare: str = None - if ais_bare < can: - ta_bare = self.Gen.CallGenCtor._infer_generic_ctor_type_arg(pool, cargs.get(ais_bare), func_name, trans) + if ais_bare < can: ta_bare = self.Gen.CallGenCtor._infer_generic_ctor_type_arg(pool, cargs.get(ais_bare), func_name, trans) if ta_bare is None: # [C②] 仅关键字实参(Box(v=42)):按 __init__ 形参名 # 把该类型形参对应的关键字实参找出来再推断(关键字乱序 @@ -471,8 +418,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): kwi_bare: int = self.Gen.CallGenCtor._find_ctor_type_param_kw_arg_index(func_name, tp_bare.get(tpi_bare), keywords, kw_count, int(can)) if kwi_bare >= 0: kwn_bare: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(sizet(kwi_bare))) - if kwn_bare is not None and kwn_bare.value is not None: - ta_bare = self.Gen.CallGenCtor._infer_generic_ctor_type_arg(pool, kwn_bare.value, func_name, trans) + if kwn_bare is not None and kwn_bare.value is not None: ta_bare = self.Gen.CallGenCtor._infer_generic_ctor_type_arg(pool, kwn_bare.value, func_name, trans) if ta_bare is None and ctx_args_bare is not None: # [C①] 注解已显式给出类型实参(如 # s: Stack[int] = Stack())⇒ 用它特化,而非 fail-fast @@ -486,8 +432,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): "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) + 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) # REnum 变体构造检测: ClassName.VariantName(args...) # 如 LLVMType.Int(1) → 构造 LLVMType 的 Int 变体 @@ -516,8 +461,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): f"({self.Gen.ClassGenEnum.RenumTableDump()});" f"变体表未注册或变体名不匹配", "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) + 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: # 模块限定 REnum 变体构造: mod.Class.Variant(args...) # 如 mlirlite.LLVMType.Struct(...) → 构造 mlirlite 模块 LLVMType 的 Struct 变体。 @@ -539,15 +483,13 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): string.memcpy(rc_mq_mod, rc_mq_path, rc_mq_len) rc_mq_mod[rc_mq_len] = '\0' rc_mq_imp: int = 1 - if trans is not None and trans._imported_modules is not None: - rc_mq_imp = self.Gen.ImportsGen.is_module_imported(trans._imported_modules, rc_mq_mod) + if trans is not None and trans._imported_modules is not None: rc_mq_imp = self.Gen.ImportsGen.is_module_imported(trans._imported_modules, rc_mq_mod) if rc_mq_imp != 0: rc_mq_cls: str = rc_mq_dot + 1 # 检查类名是否是已注册的 REnum 类 if self.Gen.ClassGenEnum._is_renum_class_name(rc_mq_cls) != 0: rc_mq_tag: int = self.Gen.ClassGenEnum._lookup_renum_variant_in_class(rc_mq_cls, func_name) - if rc_mq_tag >= 0: - return self.Gen.CallGenCtor._translate_renum_construct(pool, builder, mod, rc_mq_cls, func_name, rc_mq_tag, cargs, can, trans, cl.IsVolatile) + if rc_mq_tag >= 0: return self.Gen.CallGenCtor._translate_renum_construct(pool, builder, mod, rc_mq_cls, func_name, rc_mq_tag, cargs, can, trans, cl.IsVolatile) # async 裸名调用(TPV-M1/M2):普通函数调用 async 函数(如 task(5, 6))→ # 生成 create_(args...) 调用(返回 Ptr(帧),bitcast 成 i8* 供变量存储)。 @@ -558,8 +500,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if func_name is not None and trans is not None: if self.Gen.AsyncGen.is_async_func(trans, func_name) != 0: can_buf: str = pool.alloc(64) - if can_buf is not None: - viperlib.snprintf(can_buf, 64, "create_%s", func_name) + if can_buf is not None: viperlib.snprintf(can_buf, 64, "create_%s", func_name) create_an: str = self.Gen.FuncGenBase._mangle_func_name(trans, can_buf, 0) create_fn_an: mlirlite.Function* = self.find_func_in_module(mod, create_an) if create_fn_an is not None: @@ -576,8 +517,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): j_an: sizet = 0 for j_an in range(nb_an): av_an: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cl.args.get(j_an), None, 0, trans) - if av_an is None: - av_an = mlirlite.const_int32(pool, 0) + if av_an is None: av_an = mlirlite.const_int32(pool, 0) av_an.Next = None if arg_head_an is None: arg_head_an = av_an @@ -587,8 +527,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): arg_tail_an = av_an arg_cnt_an = arg_cnt_an + 1 child_an: mlirlite.Value* = mlirlite.build_call(builder, create_an, arg_head_an, arg_cnt_an, ret_ptr_ty_an, 0) - if child_an is not None: - return mlirlite.build_bitcast(builder, child_an, i8_ptr_ty_an) + if child_an is not None: return mlirlite.build_bitcast(builder, child_an, i8_ptr_ty_an) return mlirlite.const_int32(pool, 0) # 查找函数:优先从函数表按裸名精确匹配(同模块函数), @@ -613,8 +552,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # (对齐 TPC DecoratorPass.run 的 _redirect_calls;wrapper 在函数 # 翻译末尾生成,同 pass 内 main 调用点晚于被装饰函数定义,可达) decor_wrap_nm: str = self.Gen.ClassGenBase.lookup_decor_wrapper(func_name) - if decor_wrap_nm is not None: - found_func = self.find_func_in_module(mod, decor_wrap_nm) + if decor_wrap_nm is not None: found_func = self.find_func_in_module(mod, decor_wrap_nm) else: # 本模块已定义函数名的裸名调用:先按裸名在模块函数表(FuncEntry 数组,forward_declare_functions 已把所有模块级函数以 Name=裸名、Func=其 declare/define 登记进 trans._funcs)精确命中,再回落 find_func_in_module 的 LLVM 模块链表扫描。函数表才是同模块函数名的权威注册表(链表扫描漏掉本模块定义时会误走 C 库自动 declare / from_imports 回退)。模块表只含模块级函数(无方法),CExport 条目 Func 名即裸名,复用不改变既有符号语义 mod_fn_tb: mlirlite.Function* = None @@ -627,19 +565,16 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 使表查找优先返回 mangled 名为 "{ModuleSha1}.{name}" 的本模块 # 条目(forward_declare 已把本模块全部模块级函数登记进表)。 tbl_owner_sha1: str = None - if trans is not None: - tbl_owner_sha1 = trans.ModuleSha1 + if trans is not None: tbl_owner_sha1 = trans.ModuleSha1 mod_fn_tb = self.Gen.CallGenLeafKit.find_func_in_table(actual_funcs, actual_func_count, func_name, tbl_owner_sha1) - if mod_fn_tb is not None: - found_func = mod_fn_tb + if mod_fn_tb is not None: found_func = mod_fn_tb else: # 表内无同名条目(如本模块函数未登记/表被清空)时回退扫 # FuncHead。同样传 owner_sha1:本模块同名前向 declare 尚未 # 激活(IsDeclared==1)时 pass2 会跳过、pass3 会按链表顺序 # 误绑排在前面的跨模块 stub declare,前缀优先扫描兜住该时序。 ff_owner_sha1: str = None - if trans is not None: - ff_owner_sha1 = trans.ModuleSha1 + if trans is not None: ff_owner_sha1 = trans.ModuleSha1 found_func = self.find_func_in_module(mod, func_name, ff_owner_sha1) # 治本修复(对齐 Attribute 路径 L6579-6613):后缀匹配误命中类方法 # (SHA1.Class.method,第 2 段是已注册结构体类)必须拒绝——否则方法体内 @@ -653,8 +588,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): bn_dots: int = 0 bni2: sizet = 0 while bn_name[bni2] != '\0': - if bn_name[bni2] == '.': - bn_dots += 1 + if bn_name[bni2] == '.': bn_dots += 1 bni2 += 1 if bn_dots >= 2: # 提取第 2 段(SHA1.Class.method → Class;SHA1.submod.func → submod) @@ -662,11 +596,9 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if bn_seg2 is not None: bn_seg2[0] = '\0' bsi2: sizet = 0 - while bn_name[bsi2] != '\0' and bsi2 < 17: - bsi2 += 1 + while bn_name[bsi2] != '\0' and bsi2 < 17: bsi2 += 1 bse2: sizet = bsi2 - while bn_name[bse2] != '\0' and bn_name[bse2] != '.': - bse2 += 1 + while bn_name[bse2] != '\0' and bn_name[bse2] != '.': bse2 += 1 bsl2: sizet = bse2 - bsi2 if bsl2 > 0 and bsl2 < 63: string.strncpy(bn_seg2, bn_name + bsi2, bsl2) @@ -676,14 +608,11 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 既非已注册类又非已导入模块 → 一定是方法(对齐下方 # Attribute 分支 L660 修复,防裸名误绑未注册类方法)。 bn_seg2_cls: int = 0 - if self.Gen.StructGen.get_struct_type(bn_seg2) is not None: - bn_seg2_cls = 1 + if self.Gen.StructGen.get_struct_type(bn_seg2) is not None: bn_seg2_cls = 1 bn_seg2_mod: int = 0 if trans is not None and trans._imported_modules is not None: - if self.Gen.ImportsGen.is_module_imported_or_known(trans._imported_modules, bn_seg2) != 0: - bn_seg2_mod = 1 - if bn_seg2_cls != 0 or bn_seg2_mod == 0: - found_func = None + if self.Gen.ImportsGen.is_module_imported_or_known(trans._imported_modules, bn_seg2) != 0: bn_seg2_mod = 1 + if bn_seg2_cls != 0 or bn_seg2_mod == 0: found_func = None else: # 模块限定/属性调用:精确匹配优先,后缀匹配仅接受模块函数。 # 后缀匹配命中的"方法"(SHA1.Class.method,Class 是已注册类)必须拒绝—— @@ -710,10 +639,8 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): xm_mod_path: str = None if xm_at.value.kind() == ast.ASTKind.Name: xm_nm: ast.Name* = ast.Name*(xm_at.value) - if xm_nm.id is not None: - xm_mod_path = xm_nm.id - elif xm_at.value.kind() == ast.ASTKind.Attribute: - xm_mod_path = self.Gen.ExprGenAttr._attr_module_path_str(pool, xm_at.value) + if xm_nm.id is not None: xm_mod_path = xm_nm.id + elif xm_at.value.kind() == ast.ASTKind.Attribute: xm_mod_path = self.Gen.ExprGenAttr._attr_module_path_str(pool, xm_at.value) if xm_mod_path is not None: if self.Gen.ImportsGen.is_module_imported_or_known(trans._imported_modules, xm_mod_path) != 0: mod_sha1_chk: str = self._lookup_module_sha1(xm_mod_path) @@ -729,15 +656,13 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if mod_sha1_chk is not None: ff_nm2: str = mlirlite.function_get_name(found_func) if ff_nm2 is not None: - if string.strncmp(ff_nm2, mod_sha1_chk, 16) != 0: - found_func = None + if string.strncmp(ff_nm2, mod_sha1_chk, 16) != 0: found_func = None ff_name: str = mlirlite.function_get_name(found_func) if ff_name is not None: ff_dots: int = 0 ffi2: sizet = 0 while ff_name[ffi2] != '\0': - if ff_name[ffi2] == '.': - ff_dots += 1 + if ff_name[ffi2] == '.': ff_dots += 1 ffi2 += 1 if ff_dots >= 2: # 提取第 2 段(SHA1.Class.method → Class;SHA1.submod.func → submod) @@ -745,12 +670,10 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if seg2 is not None: seg2[0] = '\0' si: sizet = 0 - while ff_name[si] != '\0' and si < 17: - si += 1 + while ff_name[si] != '\0' and si < 17: si += 1 seg_start: sizet = si seg_end: sizet = si - while ff_name[seg_end] != '\0' and ff_name[seg_end] != '.': - seg_end += 1 + while ff_name[seg_end] != '\0' and ff_name[seg_end] != '.': seg_end += 1 seg_len: sizet = seg_end - seg_start if seg_len > 0 and seg_len < 63: string.strncpy(seg2, ff_name + seg_start, seg_len) @@ -764,14 +687,11 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 匹配误绑到 Logger.info → self 错位 NULL + 参数补零 → # 日志退化为 `├ INFO: ENUM`(二代自举日志退化根因)。 is_seg2_cls: int = 0 - if self.Gen.StructGen.get_struct_type(seg2) is not None: - is_seg2_cls = 1 + if self.Gen.StructGen.get_struct_type(seg2) is not None: is_seg2_cls = 1 is_seg2_mod: int = 0 if trans is not None and trans._imported_modules is not None: - if self.Gen.ImportsGen.is_module_imported_or_known(trans._imported_modules, seg2) != 0: - is_seg2_mod = 1 - if is_seg2_cls != 0 or is_seg2_mod == 0: - found_func = None + if self.Gen.ImportsGen.is_module_imported_or_known(trans._imported_modules, seg2) != 0: is_seg2_mod = 1 + if is_seg2_cls != 0 or is_seg2_mod == 0: found_func = None # ---- abs(obj):对象定义了 __abs__ 时优先调度(对齐 TPC _HandleAbsLlvm)---- # 仅当实参是类实例(注解类名可解析)且该类(含 MRO 祖先)定义了 __abs__ 时 # 命中;否则保持既有内建/整数/浮点 abs 路径不变。 @@ -783,8 +703,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): abs_sc: str = self.Gen.ExprGenOps._resolve_dunder_by_class(pool, mod, abs_cls, "__abs__", trans) if abs_sc is not None: abs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, abs_arg, None, 0, trans) - if abs_val is not None: - return self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, abs_sc, "__abs__", abs_val, None, 0, trans) + if abs_val is not None: return self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, abs_sc, "__abs__", abs_val, None, 0, trans) # C 库函数裸名调用支持:若模块中找不到且是已知 C 库函数,自动创建 declare # 对应 TPC 的 _C_LIB_FUNCS 机制,支持 memset/memmove/memcmp/strcmp 等裸名调用 if found_func is None and cl.func is not None and cl.func.kind() == ast.ASTKind.Name: @@ -822,8 +741,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): bi_decl: mlirlite.Function* = mlirlite.create_declare(pool, mod, bi_sym, bi_ret) if bi_decl is not None: mlirlite.add_param(pool, bi_decl, bi_p1, "v") - if bi_p2 is not None: - mlirlite.add_param(pool, bi_decl, bi_p2, "w") + if bi_p2 is not None: mlirlite.add_param(pool, bi_decl, bi_p2, "w") found_func = bi_decl # 使用访问器绕过 stub 类型限制 found_ret_ty: mlirlite.LLVMType* = None @@ -831,8 +749,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if found_func is not None: found_ret_ty = mlirlite.function_get_ret_ty(found_func) found_params = mlirlite.function_get_params(found_func) - if found_ret_ty is not None: - call_ret_ty: mlirlite.LLVMType* = found_ret_ty + if found_ret_ty is not None: call_ret_ty: mlirlite.LLVMType* = found_ret_ty else: # found_func=None(跨模块 stub 未注入):先从 vpi stub 返回注解 # 缓存精确获取返回类型(含 tuple[T1,T2] → 匿名结构体,如 @@ -864,8 +781,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if at_ret.value is not None and at_ret.value.kind() == ast.ASTKind.Name: mod_ret_nm: ast.Name* = ast.Name*(at_ret.value) mod_path_ret = mod_ret_nm.id - elif at_ret.value is not None and at_ret.value.kind() == ast.ASTKind.Attribute: - mod_path_ret = self.Gen.ExprGenAttr._attr_module_path_str(pool, at_ret.value) + elif at_ret.value is not None and at_ret.value.kind() == ast.ASTKind.Attribute: mod_path_ret = self.Gen.ExprGenAttr._attr_module_path_str(pool, at_ret.value) if mod_path_ret is not None: # import X as Y 别名(如 import lib.core.Gen.GenApi as GenApi): # 精确模块名查找(LookupSha1ByModName)查不到别名 → None → 误走 @@ -874,8 +790,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 同 CreatePipe 模式)。改经 _resolve_module_sha1(别名还原 # LookupModNameByAlias → 精确/后缀)解析。 fi_from_rt: str = None - if trans is not None: - fi_from_rt = trans._from_imports + if trans is not None: fi_from_rt = trans._from_imports mod_ret_sha1 = self.Gen.StructGen._resolve_module_sha1(mod_path_ret, fi_from_rt) if mod_ret_sha1 is not None: # 函数内懒 import:VpiReader imports HandlesExprCall, @@ -888,19 +803,15 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 经 reexport 定位定义模块(star import 多候选 # 逐个查返回注解)再查 vpi。 rr_src: str = self.Gen.ImportsGen.lookup_reexport(mod_ret_sha1, func_name) - if rr_src is None: - rr_src = self._lookup_reexport_from_vpi(pool, mod_ret_sha1, func_name) + if rr_src is None: rr_src = self._lookup_reexport_from_vpi(pool, mod_ret_sha1, func_name) if rr_src is not None: rr_total: sizet = string.strlen(rr_src) rr_i: sizet = 0 while rr_i < rr_total and ret_annot_fc is None: - while rr_i < rr_total and rr_src[rr_i] == ' ': - rr_i += 1 - if rr_i >= rr_total: - break + while rr_i < rr_total and rr_src[rr_i] == ' ': rr_i += 1 + if rr_i >= rr_total: break rr_start: sizet = rr_i - while rr_i < rr_total and rr_src[rr_i] != ' ': - rr_i += 1 + while rr_i < rr_total and rr_src[rr_i] != ' ': rr_i += 1 rr_len: sizet = rr_i - rr_start rr_buf: str = pool.alloc(rr_len + 1) if rr_buf is not None: @@ -910,10 +821,8 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if rr_sha1 is not None: VpiReader._ensure_vpi_ret_annot_loaded(rr_sha1, self.Gen.CallGenBase.TempDir) ret_annot_fc = VpiReader._lookup_vpi_ret_annot(rr_sha1, None, func_name) - if ret_annot_fc is not None: - vpi_ret_ty = VpiReader._resolve_vpi_ret_annot_str(pool, ret_annot_fc, mlirlite.Int32(pool), mlirlite.Ptr(pool, mlirlite.Int8(pool))) - if vpi_ret_ty is not None: - call_ret_ty = vpi_ret_ty + if ret_annot_fc is not None: vpi_ret_ty = VpiReader._resolve_vpi_ret_annot_str(pool, ret_annot_fc, mlirlite.Int32(pool), mlirlite.Ptr(pool, mlirlite.Int8(pool))) + if vpi_ret_ty is not None: call_ret_ty = vpi_ret_ty elif mod_ret_sha1 is not None: # 跨模块裸名 CExport 函数(如 mm.malloc → @malloc):found_func=None # 时从依赖模块精确解析返回类型(对齐 mangled 路径),避免静默默认 @@ -921,10 +830,8 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 0xbb69000 → null)。权威来源:vpi 注解缓存;未命中回退 text.ll。 cross_ret: mlirlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, mod_ret_sha1, None, func_name) if cross_ret is None: - if trans is not None and trans._declare_only == 0: - cross_ret = self._LookupMethodRetTyFromTextLL(pool, mod_ret_sha1, None, func_name, 1) - if cross_ret is not None: - call_ret_ty = cross_ret + if trans is not None and trans._declare_only == 0: cross_ret = self._LookupMethodRetTyFromTextLL(pool, mod_ret_sha1, None, func_name, 1) + if cross_ret is not None: call_ret_ty = cross_ret else: # 依赖模块 text.ll 未生成(Phase A 中间遍)→ fatal_if_unknown=0, # 本遍仅临时占位。 @@ -932,14 +839,11 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): else: # 裸名调用(cl.func 是 Name,mod_ret_sha1=None)两类来源:from-import 的函数(后续解析模块归属构造 mangled call_name 并经 text.ll/vpi 精确解析返回类型,可收敛)→ fatal_if_unknown=0 仅临时占位,不 fail-fast;纯外部 C 函数(无登记、无模块归属,白名单未命中)→ fail-fast(fatal_if_unknown=1)。闭包变量与持有函数指针/闭包的局部变量同样按可解析占位——返回类型由 translate_closure_call/lookup_var 路径固定处理,不依赖外部返回类型推断,否则被 fail-fast 误杀 bare_resolvable: int = 0 - if self.Gen.CallGenLeafKit.is_closure_name(func_name) != 0: - bare_resolvable = 1 + if self.Gen.CallGenLeafKit.is_closure_name(func_name) != 0: bare_resolvable = 1 if trans is not None and trans.SymTab is not None: - if self.Gen.VarGen.lookup_var(trans.SymTab, func_name) is not None: - bare_resolvable = 1 + if self.Gen.VarGen.lookup_var(trans.SymTab, func_name) is not None: bare_resolvable = 1 if trans is not None and trans._from_imports is not None: - if self._lookup_mod_sha1(pool, trans._from_imports, func_name, 0) is not None: - bare_resolvable = 1 + if self._lookup_mod_sha1(pool, trans._from_imports, func_name, 0) is not None: bare_resolvable = 1 # M3 会话函数(跨片段):名字命中会话函数表 ⇒ 同样按"可解析"占位, # 不 fail-fast。返回类型由下方 found_func==None 分支的 # repl_try_session_func_call 按表内签名(宿主从定义片段 IR 解析)构造, @@ -970,8 +874,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if tmp_alloca_nl is not None: mlirlite.build_store(builder, fp_alloca, tmp_alloca_nl) fp_alloca = tmp_alloca_nl - else: - fp_alloca = self.Gen.VarGen.lookup_var(trans.SymTab, func_name) + else: fp_alloca = self.Gen.VarGen.lookup_var(trans.SymTab, func_name) if fp_alloca is not None: # ---- 可调用对象 __call__:变量是类实例且类内定义了 __call__ ---- # obj(args) → obj.__call__(args)。仅当变量非闭包、非函数指针且其值 @@ -979,17 +882,14 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # (get_struct_type_from_value 返回 None)保持既有闭包/函数指针路径。 if trans is not None and self.Gen.CallGenLeafKit.is_closure_name(func_name) == 0 and self.Gen.CallGenLeafKit._is_func_ptr_alloca(fp_alloca) == 0: c_obj: mlirlite.Value* = self.Gen.ExprGenBase._deref_if_ptr_ptr(builder, fp_alloca) - if c_obj is None: - c_obj = fp_alloca + if c_obj is None: c_obj = fp_alloca c_struct: mlirlite.LLVMType* = None - if c_obj is not None: - c_struct = self.Gen.StructGen.get_struct_type_from_value(c_obj) + if c_obj is not None: c_struct = self.Gen.StructGen.get_struct_type_from_value(c_obj) if c_struct is not None: c_cls: str = self.Gen.StructGen.get_class_name_by_type(pool, c_struct) if c_cls is not None: c_call_cls: str = self.Gen.ExprGenOps._resolve_dunder_by_class(pool, mod, c_cls, "__call__", trans) - if c_call_cls is not None: - return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, c_call_cls, "__call__", c_obj, cl, trans) + if c_call_cls is not None: return self.Gen.CallGenCall._translate_method_call(pool, builder, mod, c_call_cls, "__call__", c_obj, cl, trans) # 闭包变量(嵌套函数提升,已注册到闭包名集合):提取 fn_ptr/env_ptr 间接调用 if self.Gen.CallGenLeafKit.is_closure_name(func_name) != 0: return self.Gen.CallGenLeafKit.translate_closure_call(pool, builder, mod, fp_alloca, @@ -1013,8 +913,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 原 strstr 子串匹配会误命中含 "CPtr" 的类名(如 CPtrHolder)。 # 已知局限(与改造前一致,非回归):`Foo*` 的 # SourceName 只留 "Foo"(取非 CPtr 侧类名)⇒ 此处判为非标记。 - if TSpec.SpecTypeNameBaseIs(fp_annot, "CPtr") != 0: - is_cptr_annot_fp = 1 + if TSpec.SpecTypeNameBaseIs(fp_annot, "CPtr") != 0: is_cptr_annot_fp = 1 if is_cptr_annot_fp == 0: return self.Gen.CallGenLeafKit._translate_func_ptr_call(pool, builder, mod, fp_alloca, func_name, cargs, can, trans) @@ -1082,8 +981,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): while fp is not None and fpi < ai: fp = mlirlite.param_get_next(fp) fpi += 1 - if fp is not None: - fpty = mlirlite.param_get_ty(fp) + 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, "形参") if arg_val is not None: # 参数类型提升:当 found_func 为 None(stub 未注入)时, @@ -1098,8 +996,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): match arr_pointee_fc: case mlirlite.LLVMType.Array(arr_et_fc, _): decayed_fc: mlirlite.Value* = mlirlite.build_gep_array(builder, arr_pointee_fc, arr_et_fc, arg_val, mlirlite.const_int32(pool, 0)) - if decayed_fc is not None: - arg_val = decayed_fc + if decayed_fc is not None: arg_val = decayed_fc case _: pass # 已知变参 C 库函数(snprintf/sprintf/vsprintf)固定参数 @@ -1108,8 +1005,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 则 call(i32 1024) 与 declare(i64 size) 不匹配,且 Win64 # 变参槽高 4 字节残留栈垃圾(clean 日志 0x7ff700000052 根因)。 kvc_ty: mlirlite.LLVMType* = self.Gen.CallGenVa._get_known_vararg_cfunc_param_ty(pool, func_name, ai) - if kvc_ty is not None: - arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, kvc_ty, arg) + if kvc_ty is not None: arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, kvc_ty, arg) # ① 模块限定调用的**定义侧 vpi 形参注解优先**(真实类型)。 # 白名单 _get_external_func_param_ty 把 Win32 API 的**所有** # 非指针参数一律当 i64(其注释基于"DWORD/ULONG 在 stubs 里 @@ -1125,30 +1021,24 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if at_pt.value is not None and at_pt.value.kind() == ast.ASTKind.Name: nm_pt: ast.Name* = ast.Name*(at_pt.value) mpath_pt = nm_pt.id - elif at_pt.value is not None and at_pt.value.kind() == ast.ASTKind.Attribute: - mpath_pt = self.Gen.ExprGenAttr._attr_module_path_str(pool, at_pt.value) + elif at_pt.value is not None and at_pt.value.kind() == ast.ASTKind.Attribute: mpath_pt = self.Gen.ExprGenAttr._attr_module_path_str(pool, at_pt.value) if mpath_pt is not None: fi_pt: str = None - if trans is not None: - fi_pt = trans._from_imports + if trans is not None: fi_pt = trans._from_imports sha_pt: str = self.Gen.StructGen._resolve_module_sha1(mpath_pt, fi_pt) if sha_pt is not None: - if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: - VpiReader._ensure_vpi_param_annot_loaded(sha_pt, self.Gen.CallGenBase.TempDir) + if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: VpiReader._ensure_vpi_param_annot_loaded(sha_pt, self.Gen.CallGenBase.TempDir) ext_param_ty = VpiReader._resolve_vpi_param_annot_seg( pool, sha_pt, None, func_name, ai, mlirlite.Int32(pool), mlirlite.Ptr(pool, mlirlite.Int8(pool))) # ② 白名单仅作**兜底**(定义侧注解不可得时) - if ext_param_ty is None: - ext_param_ty = self.Gen.CallGenLib._get_external_func_param_ty(pool, func_name, ai) + if ext_param_ty is None: ext_param_ty = self.Gen.CallGenLib._get_external_func_param_ty(pool, func_name, ai) if ext_param_ty is not None: val_bits_ap: int = self.Gen.ExprGenBase.get_llvm_type_bits(arg_val.Ty) tgt_bits_ap: int = self.Gen.ExprGenBase.get_llvm_type_bits(ext_param_ty) if val_bits_ap != 0 and tgt_bits_ap != 0 and val_bits_ap != tgt_bits_ap: - if val_bits_ap == 1 and val_bits_ap < tgt_bits_ap: - arg_val = mlirlite.build_zext(builder, arg_val, ext_param_ty) - else: - arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, ext_param_ty, arg) + if val_bits_ap == 1 and val_bits_ap < tgt_bits_ap: arg_val = mlirlite.build_zext(builder, arg_val, ext_param_ty) + else: arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, ext_param_ty, arg) elif found_func is not None: # found_func 存在:按形参类型 coerce(如 stdlib.malloc(size: sizet)) # 修复: CDefine/i32 常量传给 i64 形参未提升,导致 call(i32) 与 define(i64) 不匹配 @@ -1163,8 +1053,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if same_mod_vpi != 0: if VpiReader._vpi_param_annot_seg_is(trans.ModuleSha1, None, func_name, ai, "str") != 0 or VpiReader._vpi_param_annot_seg_is(trans.ModuleSha1, None, func_name, ai, "bytes") != 0: sm_is_str = 1 - if sm_is_str != 0: - self.Gen.ExprGenBase.fail_if_str_annot_agg_ptr(arg_val, 1, arg) + if sm_is_str != 0: self.Gen.ExprGenBase.fail_if_str_annot_agg_ptr(arg_val, 1, arg) arg_val = self.Gen.ExprGenBase.coerce_to_type(builder, arg_val, fpty, arg, trans) elif found_func.IsVarArg == 1: # Win64 变参 8 字节槽位:<64 位整数按 i64 传(sext 符号扩展), @@ -1175,23 +1064,16 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): ab_va: int = self.Gen.ExprGenBase.get_llvm_type_bits(arg_val.Ty) af_va: int = self.Gen.ExprGenBase.get_llvm_float_bits(arg_val.Ty) i64_va: mlirlite.LLVMType* = mlirlite.Int64(pool) - if ab_va != 0 and ab_va < 64: - arg_val = mlirlite.build_sext(builder, arg_val, i64_va) - elif af_va == 32: - arg_val = mlirlite.build_fpext(builder, arg_val, mlirlite.Double(pool)) + if ab_va != 0 and ab_va < 64: arg_val = mlirlite.build_sext(builder, arg_val, i64_va) + elif af_va == 32: arg_val = mlirlite.build_fpext(builder, arg_val, mlirlite.Double(pool)) arg_val.Next = None - if head is None: - head = arg_val - else: - tail.Next = arg_val + if head is None: head = arg_val + else: tail.Next = arg_val tail = arg_val # memcpy 专用: 保存前三个参数的独立引用 - if ai == 0: - mc_dst2 = arg_val - elif ai == 1: - mc_src2 = arg_val - elif ai == 2: - mc_num2 = arg_val + if ai == 0: mc_dst2 = arg_val + elif ai == 1: mc_src2 = arg_val + elif ai == 2: mc_num2 = arg_val # 默认参数填充:当实参数量 < 形参数量时,用默认值填充缺失参数 # defaults 数组右对齐到 args:defaults[0] 对应 args[offset],offset = param_count - default_count @@ -1209,10 +1091,8 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): dfx_at: ast.Attribute* = ast.Attribute*(cl.func) if dfx_at.value is not None and dfx_at.value.kind() == ast.ASTKind.Name: dfx_mn: ast.Name* = ast.Name*(dfx_at.value) - if dfx_mn.id is not None: - dfx_callee_sha = self._lookup_module_sha1(dfx_mn.id) - if dfx_callee_sha is None and self.Gen.TypeGenBase is not None: - dfx_callee_sha = self.Gen.TypeGenBase.CurrentModuleSha1 + if dfx_mn.id is not None: dfx_callee_sha = self._lookup_module_sha1(dfx_mn.id) + if dfx_callee_sha is None and self.Gen.TypeGenBase is not None: dfx_callee_sha = self.Gen.TypeGenBase.CurrentModuleSha1 # 从当前模块函数表查找 FuncEntry —— 必须按**定义模块 SHA1 限定**: # 表内含 LoadDepVpiIntoModule 以裸名注入的依赖 stub(槽位在前), # 裸名首命中会让 usb 的 `uhci.init(io_base)`(1 形参)拿到 mm.init 的 @@ -1244,12 +1124,10 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # **定义模块 SHA1** 复查默认参数表(SHA1 已校验,不会跨模块串味)。 if gd_entry is None and dfx_callee_sha is not None: rr_src_dx: str = self.Gen.ImportsGen.lookup_reexport(dfx_callee_sha, func_name) - if rr_src_dx is None: - rr_src_dx = self._lookup_reexport_from_vpi(pool, dfx_callee_sha, func_name) + if rr_src_dx is None: rr_src_dx = self._lookup_reexport_from_vpi(pool, dfx_callee_sha, func_name) if rr_src_dx is not None: rr_sha_dx: str = self._lookup_module_sha1(rr_src_dx) - if rr_sha_dx is not None: - gd_entry = self.Gen.CallGenLeafKit.find_func_defaults(func_name, rr_sha_dx) + if rr_sha_dx is not None: gd_entry = self.Gen.CallGenLeafKit.find_func_defaults(func_name, rr_sha_dx) # 覆盖条件含 df_default_count<=0:调用方函数表可能命中一条同名条目但 # Defaults 为空/默认值为 0 条(VpiReader 注入的 declare 条目), # 此时必须用全局默认参数表的真实条目覆盖,否则缺参填充整体不触发。 @@ -1283,19 +1161,15 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if df_param_idx >= can: # 优先用 stdlib 常量快照重建(gd_entry.Defaults 的 pool 内 AST 可能已被 reset 回收) df_arg_val: mlirlite.Value* = None - if gd_entry is not None: - df_arg_val = self.Gen.CallGenLeafKit._build_const_from_snapshot(pool, mod, gd_entry, df_di, trans, builder) + if gd_entry is not None: df_arg_val = self.Gen.CallGenLeafKit._build_const_from_snapshot(pool, mod, gd_entry, df_di, trans, builder) if df_arg_val is None and df_defaults is not None: df_defaults_list: list[ast.AST*]* = (list[ast.AST*] | t.CPtr)(uint64(df_defaults)) df_default_node: ast.AST* = df_defaults_list.get(df_di) - if df_default_node is not None: - df_arg_val = self.Gen.ExprGen.translate_value(builder, pool, mod, df_default_node, None, 0, trans) + if df_default_node is not None: df_arg_val = self.Gen.ExprGen.translate_value(builder, pool, mod, df_default_node, None, 0, trans) if df_arg_val is not None: df_arg_val.Next = None - if head is None: - head = df_arg_val - else: - tail.Next = df_arg_val + if head is None: head = df_arg_val + else: tail.Next = df_arg_val tail = df_arg_val # 追加的默认实参必须计入实参数:下方 # _coerce_args_to_def_params/_ensure_method_declare 等 @@ -1313,8 +1187,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): and string.strcmp(fp_nm_z, "%__eh_code_out__") != 0): fc_cnt += 1 fc_p = mlirlite.param_get_next(fc_p) - if fc_cnt == 0: - fc_cnt = df_param_count if df_param_count > 0 else 0 + if fc_cnt == 0: fc_cnt = df_param_count if df_param_count > 0 else 0 if can < fc_cnt: fp_z: mlirlite.Param* = mlirlite.function_get_param_head(found_func) fpi_z: int = 0 @@ -1326,10 +1199,8 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): zero_val_z: mlirlite.Value* = mlirlite.ConstZero(pool, zero_ty_z) if zero_val_z is not None: zero_val_z.Next = None - if head is None: - head = zero_val_z - else: - tail.Next = zero_val_z + if head is None: head = zero_val_z + else: tail.Next = zero_val_z tail = zero_val_z can += 1 # 零值兜底实参同样计入实参数(同默认实参) fp_z = mlirlite.param_get_next(fp_z) @@ -1365,8 +1236,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): if cx_sha1_buf is not None: string.memcpy(cx_sha1_buf, found_name, 16) cx_sha1_buf[16] = '\0' - if self.Gen.CallGenBase.is_cexport_func(cx_sha1_buf, func_name) != 0: - call_name = func_name + if self.Gen.CallGenBase.is_cexport_func(cx_sha1_buf, func_name) != 0: call_name = func_name else: # 跨模块函数调用:found_func 为 None 时,检查是否是模块限定调用 # 如 string.strchr(...) → @{sha1_of_string}.strchr @@ -1383,10 +1253,8 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): xmod_path: str = None if xmod_at.value.kind() == ast.ASTKind.Name: xmod_nm: ast.Name* = ast.Name*(xmod_at.value) - if xmod_nm.id is not None: - xmod_path = xmod_nm.id - else: - xmod_path = self.Gen.ExprGenAttr._attr_module_path_str(pool, xmod_at.value) + if xmod_nm.id is not None: xmod_path = xmod_nm.id + else: xmod_path = self.Gen.ExprGenAttr._attr_module_path_str(pool, xmod_at.value) if xmod_path is not None: mod_sha1: str = self._lookup_module_sha1(xmod_path) if mod_sha1 is not None: @@ -1421,13 +1289,10 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): cs_total: sizet = string.strlen(reexport_src) cs_i: sizet = 0 while cs_i < cs_total: - while cs_i < cs_total and reexport_src[cs_i] == ' ': - cs_i += 1 - if cs_i >= cs_total: - break + while cs_i < cs_total and reexport_src[cs_i] == ' ': cs_i += 1 + if cs_i >= cs_total: break cs_start: sizet = cs_i - while cs_i < cs_total and reexport_src[cs_i] != ' ': - cs_i += 1 + while cs_i < cs_total and reexport_src[cs_i] != ' ': cs_i += 1 cs_seg: sizet = cs_i - cs_start cs_buf: str = pool.alloc(cs_seg + 1) if cs_buf is not None: @@ -1457,19 +1322,16 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): orig_has_def: int = 0 if self.Gen.CallGenBase.TempDir is not None and self.Gen.CallGenBase.TempDirLen > 0: VpiReader._ensure_vpi_ret_annot_loaded(mod_sha1, self.Gen.CallGenBase.TempDir) - if VpiReader._lookup_vpi_ret_annot(mod_sha1, None, func_name) is not None: - orig_has_def = 1 + if VpiReader._lookup_vpi_ret_annot(mod_sha1, None, func_name) is not None: orig_has_def = 1 if orig_has_def == 0: # 原模块未定义:回退首个候选(旧行为,普通跨模块 # 函数带 sha1 前缀,如 ast._lexer_init 定义在 ast.lexer) reexport_sha1: str = self._lookup_module_sha1(reexport_src) - if reexport_sha1 is not None: - mod_sha1 = reexport_sha1 + if reexport_sha1 is not None: mod_sha1 = reexport_sha1 # CExport 函数定义用裸名(@strlen),跨模块调用需用裸名而非 @{sha1}.func if rs_found != 0: pass # 已验证 reexport 定义模块并置裸名 - elif self.Gen.CallGenBase.is_cexport_func(mod_sha1, func_name) != 0: - call_name = func_name + elif self.Gen.CallGenBase.is_cexport_func(mod_sha1, func_name) != 0: call_name = func_name elif self._is_state_func_from_vpi(pool, mod_sha1, func_name) != 0: # t.State 标记的外部 C 函数(如 CPython PyList_Size): # 定义端用裸名 @PyList_Size(链接外部库),跨模块调用 @@ -1483,26 +1345,22 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): call_name = mangled else: # t 和 c 是内部库,豁免 SHA1 查找:使用裸名调用 - if string.strcmp(xmod_path, "t") == 0 or string.strcmp(xmod_path, "c") == 0: - call_name = func_name + if string.strcmp(xmod_path, "t") == 0 or string.strcmp(xmod_path, "c") == 0: call_name = func_name else: # Bug 修复: 先检查是否是已导入的模块名(如 BuildPipeline.run_pipeline) # 如果是已导入模块但 SHA1 未注册,说明该模块未被编译(如 Phase2 未扫描到), # 应该立即报错,而不是错误地走 from_imports 查找(会被 star import 回退误导) is_imported_mod: int = 0 - if trans is not None and trans._imported_modules is not None: - is_imported_mod = self.Gen.ImportsGen.is_module_imported(trans._imported_modules, xmod_path) + if trans is not None and trans._imported_modules is not None: is_imported_mod = self.Gen.ImportsGen.is_module_imported(trans._imported_modules, xmod_path) if is_imported_mod != 0: # 别名导入(import X as Y):Y 在 _imported_modules 中, # 但 _lookup_module_sha1("Y") 精确匹配失败(mod_arr 只存文件名)。 # 先尝试 from_imports 查找别名→完整模块名→后缀匹配 SHA1。 # allow_star_fallback=0 避免被 star import 回退误导。 alias_sha1: str = None - if trans is not None and trans._from_imports is not None: - alias_sha1 = self._lookup_mod_sha1(pool, trans._from_imports, xmod_path, 0) + if trans is not None and trans._from_imports is not None: alias_sha1 = self._lookup_mod_sha1(pool, trans._from_imports, xmod_path, 0) if alias_sha1 is not None: - if self.Gen.CallGenBase.is_cexport_func(alias_sha1, func_name) != 0: - call_name = func_name + if self.Gen.CallGenBase.is_cexport_func(alias_sha1, func_name) != 0: call_name = func_name elif self._is_state_func_from_vpi(pool, alias_sha1, func_name) != 0: # t.State 外部 C 函数:裸名(同主路径 L7918) call_name = func_name @@ -1525,12 +1383,10 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 但 Ptr 是 __types 模块的模块级函数 # 禁用 star import 回退:xmod_path 是明确名称,不应回退到 star import 模块 from_sha1: str = None - if trans is not None and trans._from_imports is not None: - from_sha1 = self._lookup_mod_sha1(pool, trans._from_imports, xmod_path, 0) + if trans is not None and trans._from_imports is not None: from_sha1 = self._lookup_mod_sha1(pool, trans._from_imports, xmod_path, 0) if from_sha1 is not None: # CExport 函数定义用裸名,跨模块调用需用裸名 - if self.Gen.CallGenBase.is_cexport_func(from_sha1, func_name) != 0: - call_name = func_name + if self.Gen.CallGenBase.is_cexport_func(from_sha1, func_name) != 0: call_name = func_name else: fmangled_len: sizet = string.strlen(from_sha1) + string.strlen(func_name) + 2 fmangled: str = pool.alloc(fmangled_len) @@ -1562,12 +1418,10 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # bare_orig 指向 from_imports 内部缓冲区,未 null 终止 # 需复制到独立缓冲区(截断于空格或 null) bo_len: sizet = 0 - while bare_orig[bo_len] != ' ' and bare_orig[bo_len] != '\0': - bo_len += 1 + while bare_orig[bo_len] != ' ' and bare_orig[bo_len] != '\0': bo_len += 1 bo_buf: str = pool.alloc(bo_len + 1) if bo_buf is not None: - for bo_i in range(bo_len): - bo_buf[bo_i] = bare_orig[bo_i] + for bo_i in range(bo_len): bo_buf[bo_i] = bare_orig[bo_i] bo_buf[bo_len] = '\0' bare_func_name = bo_buf # 记录原始函数名,供后续重新推断返回类型 @@ -1587,10 +1441,8 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): reexport_src2 = self._lookup_reexport_from_vpi(pool, bare_sha1, bare_func_name) if reexport_src2 is not None: reexport_sha1_2: str = self._lookup_module_sha1(reexport_src2) - if reexport_sha1_2 is not None: - bare_sha1 = reexport_sha1_2 - if self.Gen.CallGenBase.is_cexport_func(bare_sha1, bare_func_name) != 0: - call_name = bare_func_name + if reexport_sha1_2 is not None: bare_sha1 = reexport_sha1_2 + if self.Gen.CallGenBase.is_cexport_func(bare_sha1, bare_func_name) != 0: call_name = bare_func_name else: bare_mangled_len: sizet = string.strlen(bare_sha1) + string.strlen(bare_func_name) + 2 bare_mangled: str = pool.alloc(bare_mangled_len) @@ -1612,8 +1464,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 直接调用 # memcpy → @llvm.memcpy 内联函数(避免 monomorphization 跨模块 @memcpy 声明缺失) - 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) + 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) # 别名导入重新推断返回类型: # from X import parse as json_parse → func_name="json_parse" 时 _infer_external_func_ret_ty 返回默认 i32 # 用 orig_func_name="parse" 重新推断,能正确匹配返回 i8*(JsonValue*) @@ -1623,8 +1474,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 若 call_name 是 mangled,L1272 起的 text.ll/vpi 精确解析会覆盖并 fail-fast; # 未命中时保持白名单/默认 i32 由后续路径兜底。 re_inferred_ty: mlirlite.LLVMType* = self.Gen.CallGenLib._infer_external_func_ret_ty(pool, orig_func_name, node, 0) - if re_inferred_ty is not None: - call_ret_ty = re_inferred_ty + if re_inferred_ty is not None: call_ret_ty = re_inferred_ty # ============================================================ # 跨模块 Viper 函数返回类型精确解析(对齐方法路径,fail-fast) # 根因:_infer_external_func_ret_ty 白名单未覆盖返回指针的模块函数 @@ -1655,26 +1505,21 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # 根因)。未命中(特化尚未声明)保持默认推断。 is_local_mod: int = 0 if trans is not None and trans.ModuleSha1 is not None: - if string.strncmp(cf_sha1, trans.ModuleSha1, 16) == 0: - is_local_mod = 1 + if string.strncmp(cf_sha1, trans.ModuleSha1, 16) == 0: is_local_mod = 1 if is_local_mod != 0: local_fn: mlirlite.Function* = self.find_func_in_module(mod, call_name) - if local_fn is not None and local_fn.RetTy is not None: - call_ret_ty = local_fn.RetTy + if local_fn is not None and local_fn.RetTy is not None: call_ret_ty = local_fn.RetTy else: cf_vpi: mlirlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, cf_sha1, None, cf_bare) - if cf_vpi is not None: - call_ret_ty = cf_vpi + if cf_vpi is not None: call_ret_ty = cf_vpi else: cf_ret: mlirlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, cf_sha1, None, cf_bare, 1) - if cf_ret is not None: - call_ret_ty = cf_ret + if cf_ret is not None: call_ret_ty = cf_ret else: # 依赖模块 text.ll 不存在(模块尚未翻译)→ Phase A 按文件 # 顺序翻译,main.vp 先于其 import 的 mbuddytest.vp(同项目 # 多源文件):本遍保持默认类型,不 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"跨模块函数返回类型无法精确获取(vpi/text.ll 均未命中),默认 i32 会截断指针: {call_name}", "TypeError") stdlib.free(cf_sha1) stdlib.free(cf_bare) # 裸名 C 库函数(string.memset → @memset):实参按标准签名提升 diff --git a/App/lib/core/Gen/Call/CallGenProp.vp b/App/lib/core/Gen/Call/CallGenProp.vp index 2795d47..79fcae2 100644 --- a/App/lib/core/Gen/Call/CallGenProp.vp +++ b/App/lib/core/Gen/Call/CallGenProp.vp @@ -60,8 +60,7 @@ novirtual class CallGenProp(CallGenBase.CallGenBase): call_name: str = lookup_name if found_func is not None: found_name: str = mlirlite.function_get_name(found_func) - if found_name is not None: - call_name = found_name + if found_name is not None: call_name = found_name else: # 未找到:用类所属模块的 SHA1 构造调用名 cls_sha1_pc: str = self.Gen.StructGen.get_struct_sha1(class_name) @@ -77,38 +76,31 @@ novirtual class CallGenProp(CallGenBase.CallGenBase): call_ret_ty: mlirlite.LLVMType* = i32_ty if found_func is not None: frt: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(found_func) - if frt is not None: - call_ret_ty = frt + if frt is not None: call_ret_ty = frt else: sp_ty1: mlirlite.LLVMType* = self._special_method_ret_ty(pool, class_name, method_name) - if sp_ty1 is not None: - call_ret_ty = sp_ty1 + if sp_ty1 is not None: call_ret_ty = sp_ty1 else: cls_sha1_rt: str = self.Gen.StructGen.get_struct_sha1(class_name) # 权威来源:vpi stub 返回注解缓存(方法定义处,不硬编码白名单) vpi_ret_ty: mlirlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, cls_sha1_rt, class_name, method_name) - if vpi_ret_ty is not None: - call_ret_ty = vpi_ret_ty + if vpi_ret_ty is not None: call_ret_ty = vpi_ret_ty else: # 回退:依赖模块 text.ll 的 define 行解析(vpi 未覆盖的历史形态) looked_up_ty: mlirlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, cls_sha1_rt, class_name, method_name) - if looked_up_ty is not None: - call_ret_ty = looked_up_ty + if looked_up_ty is not None: call_ret_ty = looked_up_ty else: # Phase A 依赖未就绪(cls_sha1_rt None / 定义模块 text.ll 未生成): # 保持默认 i32(build_call(Void) 返回 None 会破坏表达式翻译)。 - if cls_sha1_rt is None or self._dep_text_ll_exists(pool, cls_sha1_rt) == 0: - call_ret_ty = mlirlite.Int32(pool) - else: - call_ret_ty = self._fail_method_ret_ty(method_name) + if cls_sha1_rt is None or self._dep_text_ll_exists(pool, cls_sha1_rt) == 0: call_ret_ty = mlirlite.Int32(pool) + else: call_ret_ty = self._fail_method_ret_ty(method_name) # 参数类型对齐:按目标函数声明的参数类型转换实参(与 _translate_method_call # 一致)。例如 from_long(10) 的 i32 字面量 → i64 形参(v: t.CLong), # 不转换则 call(i32) 与 declare(i64) 不匹配,llc 报参数类型错误。 # 目标函数优先用已找到的 found_func,否则按 mangled 调用名查模块 declare。 tgt_func_pc: mlirlite.Function* = found_func - if tgt_func_pc is None: - tgt_func_pc = self.find_func_in_module(mod, call_name) + if tgt_func_pc is None: tgt_func_pc = self.find_func_in_module(mod, call_name) if tgt_func_pc is not None: prev_pc: mlirlite.Value* = None cur_arg_pc: mlirlite.Value* = call_head @@ -120,10 +112,8 @@ novirtual class CallGenProp(CallGenBase.CallGenBase): if coerced_pc is not None and coerced_pc != cur_arg_pc: # 保持链表完整性:新 Value 继承原节点的 Next,前驱指向新节点 mlirlite.value_set_next(coerced_pc, cur_arg_pc.Next) - if prev_pc is None: - call_head = coerced_pc - else: - mlirlite.value_set_next(prev_pc, coerced_pc) + if prev_pc is None: call_head = coerced_pc + else: mlirlite.value_set_next(prev_pc, coerced_pc) cur_arg_pc = coerced_pc prev_pc = cur_arg_pc cur_arg_pc = cur_arg_pc.Next @@ -145,8 +135,7 @@ novirtual class CallGenProp(CallGenBase.CallGenBase): trans: HT.Translator*, obj_node: ast.AST*) -> str: """解析对象表达式的类名(短名),失败返回 None""" - if pool is None or trans is None or obj_node is None: - return None + if pool is None or trans is None or obj_node is None: return None if obj_node.kind() == ast.ASTKind.Name: obj_nm: ast.Name* = ast.Name*(obj_node) if obj_nm.id is not None: @@ -164,15 +153,11 @@ novirtual class CallGenProp(CallGenBase.CallGenBase): ai_av: sizet = 0 while ai_av < n_av: ch_av: int = annot_val[ai_av] - if ch_av == '[': - depth_av += 1 - elif ch_av == ']': - depth_av -= 1 - elif ch_av == '.' and depth_av == 0: - last_dot_av = ai_av + if ch_av == '[': depth_av += 1 + elif ch_av == ']': depth_av -= 1 + elif ch_av == '.' and depth_av == 0: last_dot_av = ai_av ai_av += 1 - if last_dot_av < n_av: - return annot_val + last_dot_av + 1 + if last_dot_av < n_av: return annot_val + last_dot_av + 1 return annot_val return None # ============================================================ @@ -194,16 +179,12 @@ novirtual class CallGenProp(CallGenBase.CallGenBase): fallback_class_name: 对象表达式非 Name 时从 LLVM 类型解析出的类名兜底。 """ - if at_node is None or at_node.attr is None or obj_ptr is None or trans is None: - return None + if at_node is None or at_node.attr is None or obj_ptr is None or trans is None: return None class_name: str = self._resolve_obj_class_name(pool, trans, at_node.value) - if class_name is None: - class_name = fallback_class_name - if class_name is None: - return None + if class_name is None: class_name = fallback_class_name + if class_name is None: return None meta: int = self.Gen.ClassGenBase.lookup_method_meta(class_name, at_node.attr) - if meta & GenTypes.META_PROP_GETTER == 0: - return None + if meta & GenTypes.META_PROP_GETTER == 0: return None # 单参数调用: obj → getter mlirlite.value_set_next(obj_ptr, None) return self._translate_property_call(pool, builder, mod, class_name, at_node.attr, obj_ptr, 1, trans) @@ -315,8 +296,7 @@ novirtual class CallGenProp(CallGenBase.CallGenBase): # 翻译调用参数 cargs: list[ast.AST*]* = cl.args can: sizet = 0 - if cargs is not None: - can = len(cargs) + if cargs is not None: can = len(cargs) tail: mlirlite.Value* = head for ai in range(can): arg_node: ast.AST* = cargs.get(ai) @@ -379,8 +359,7 @@ novirtual class CallGenProp(CallGenBase.CallGenBase): # ============================================================ def _strip_module_sha1_prefix(self, name: str) -> str: """去除 "{16hex}." 前缀(无前缀则原样返回;返回原串内部子串)""" - if name is None: - return None + if name is None: return None pfx: int = GenApi.sha1_prefix_len(name) return name + pfx if pfx != 0 else name @@ -390,30 +369,22 @@ novirtual class CallGenProp(CallGenBase.CallGenBase): method_name: str, cl: ast.Call*) -> str: """返回实际泛型特化名(去 sha1)或 None;裸泛型基类 fail-fast""" - if struct_ty is None: - return None + if struct_ty is None: return None ty_nm: str = mlirlite.get_struct_name(struct_ty) - if ty_nm is None or ty_nm[0] == '\0': - return None + if ty_nm is None or ty_nm[0] == '\0': return None short_nm: str = self._strip_module_sha1_prefix(ty_nm) lb: str = string.strchr(short_nm, '[') bare_len: sizet = 0 - if lb is not None: - bare_len = sizet(uint64(lb) - uint64(short_nm)) - else: - bare_len = string.strlen(short_nm) - if bare_len == 0: - return None + if lb is not None: bare_len = sizet(uint64(lb) - uint64(short_nm)) + else: bare_len = string.strlen(short_nm) + if bare_len == 0: return None base_nm: str = pool.alloc(bare_len + 1) - if base_nm is None: - return None + if base_nm is None: return None string.strncpy(base_nm, short_nm, bare_len) base_nm[bare_len] = '\0' # 基名非已注册泛型模板(普通类接收者)⇒ 非泛型,交由调用方原口径处理 - if self.Gen.ClassGenGeneric._find_generic_template(base_nm) is None: - return None - if lb is not None: - return short_nm + if self.Gen.ClassGenGeneric._find_generic_template(base_nm) is None: return None + if lb is not None: return short_nm # 裸泛型基类(无类型实参):接收者元素类型未知 → fail-fast(D25 口径) self.Gen.TypeGenErr.fatal_error( cl, @@ -437,8 +408,7 @@ novirtual class CallGenProp(CallGenBase.CallGenBase): if ty_nm is not None and ty_nm[0] != '\0': # 泛型模板接收者:裸基类 fail-fast;含实参用实际特化名 act_nm: str = self._resolve_generic_receiver_name(pool, sty, method_name, cl) - if act_nm is not None: - return self._is_list_builtin_method(act_nm, method_name) + if act_nm is not None: return self._is_list_builtin_method(act_nm, method_name) # 非泛型模板接收者:用去 sha1 后的实际短名判定(不复用退化注解名) return self._is_list_builtin_method(self._strip_module_sha1_prefix(ty_nm), method_name) # 实际类型不可得 → 回退注解名/注册名判定(信息缺失下的既有行为) diff --git a/App/lib/core/Gen/Call/CallGenVa.vp b/App/lib/core/Gen/Call/CallGenVa.vp index 0970b6b..5a1d904 100644 --- a/App/lib/core/Gen/Call/CallGenVa.vp +++ b/App/lib/core/Gen/Call/CallGenVa.vp @@ -41,8 +41,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase): nm: ast.Name* = ast.Name*(arg_node) if nm.id is not None: alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id) - if alloca is not None: - return alloca + if alloca is not None: return alloca # 回退:translate_value(可能返回 load 后的值,仅适用于已是指针的情况) return self.Gen.ExprGen.translate_value(builder, pool, mod, arg_node, funcs_ptr, func_count, trans) def _resolve_va_arg_type(self, pool: memhub.MemBuddy*, @@ -58,12 +57,10 @@ novirtual class CallGenVa(CallGenBase.CallGenBase): str / bytes → i8* 无类型参数时默认 i32(vsnprintf 中 va_arg(ap) 常用于读取 i32) """ - if type_node is None: - return mlirlite.Int32(pool) + if type_node is None: return mlirlite.Int32(pool) # 使用 HandlesType.resolve_annotation_type 解析类型表达式 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 + if resolved is not None: return resolved # 类型节点存在但解析失败:fail-fast,绝不回退 i32(会按错宽度读变参槽位) self.Gen.TypeGenErr.fatal_error(type_node, "va_arg 类型解析失败", "TypeError") return mlirlite.Int32(pool) @@ -80,16 +77,14 @@ novirtual class CallGenVa(CallGenBase.CallGenBase): 生成 LLVM va_arg 指令,从 va_list 读取下一个变长参数。 """ - if can == 0 or cargs is None: - return mlirlite.const_int32(pool, 0) + if can == 0 or cargs is None: return mlirlite.const_int32(pool, 0) # 第一个参数:va_list(求值为 i8* 地址值,对齐 TPC _HandleVaArgLlvm) # 当前函数 *args:translate_value 经 vararg 名映射直接返回 va_list 缓冲区地址; # 转发场景(sprintf → vsnprintf 的 ap 参数):translate_value load 参数得到地址值。 ap_node: ast.AST* = cargs.get(0) ap_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, ap_node, None, 0, trans) - if ap_val is None: - return mlirlite.const_int32(pool, 0) + if ap_val is None: return mlirlite.const_int32(pool, 0) ap_ptr: mlirlite.Value* = ap_val # 第二个参数:目标类型(可选,默认 i32) @@ -107,8 +102,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase): if abits_va != 0 and abits_va < 64: read_ty = mlirlite.Int64(pool) va_raw: mlirlite.Value* = mlirlite.build_va_arg(builder, ap_ptr, read_ty) - if va_raw is None: - return mlirlite.const_int32(pool, 0) + if va_raw is None: return mlirlite.const_int32(pool, 0) # 8 字节槽 → 目标宽度(低 bits 位);调用方 int64(...) 会再 sext/zext return mlirlite.build_trunc(builder, va_raw, arg_ty) @@ -128,8 +122,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase): 使用当前函数的隐式 va_list(trans._va_list_ptr), 简化 *args 函数体内的 va_arg 调用。 """ - if trans._va_list_ptr is None: - return mlirlite.const_int32(pool, 0) + if trans._va_list_ptr is None: return mlirlite.const_int32(pool, 0) # 第一个参数:目标类型(可选,默认 i32) arg_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) @@ -144,8 +137,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase): if abits_arg != 0 and abits_arg < 64: read_ty = mlirlite.Int64(pool) arg_raw: mlirlite.Value* = mlirlite.build_va_arg(builder, trans._va_list_ptr, read_ty) - if arg_raw is None: - return mlirlite.const_int32(pool, 0) + if arg_raw is None: return mlirlite.const_int32(pool, 0) return mlirlite.build_trunc(builder, arg_raw, arg_ty) # 生成 va_arg 指令(使用 trans._va_list_ptr 作为 va_list 地址) @@ -162,21 +154,18 @@ novirtual class CallGenVa(CallGenBase.CallGenBase): 初始化 va_list。第二个参数 last_arg 在 LLVM intrinsic 中不使用(C 宏兼容)。 """ - if can == 0 or cargs is None: - return mlirlite.const_int32(pool, 0) + if can == 0 or cargs is None: return mlirlite.const_int32(pool, 0) # 第一个参数:va_list 指针(获取 alloca,不 load) ap_node: ast.AST* = cargs.get(0) ap_ptr: mlirlite.Value* = self._va_arg_get_alloca_ptr(pool, builder, mod, ap_node, funcs_ptr, func_count, trans) - if ap_ptr is None: - return mlirlite.const_int32(pool, 0) + if ap_ptr is None: return mlirlite.const_int32(pool, 0) # bitcast 到 i8*(@llvm.va_start 接受 i8*) i8_ty_vs: mlirlite.LLVMType* = mlirlite.Int8(pool) i8_ptr_ty_vs: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_vs) ap_i8: mlirlite.Value* = mlirlite.build_bitcast(builder, ap_ptr, i8_ptr_ty_vs) - if ap_i8 is None: - return mlirlite.const_int32(pool, 0) + if ap_i8 is None: return mlirlite.const_int32(pool, 0) void_ty_vs: mlirlite.LLVMType* = mlirlite.Void(pool) mlirlite.build_call(builder, "llvm.va_start", ap_i8, 1, void_ty_vs, 0) @@ -193,29 +182,25 @@ novirtual class CallGenVa(CallGenBase.CallGenBase): 清理 va_list。在大多数平台上是 no-op,但调用它是良好的 C ABI 习惯。 """ - if can == 0 or cargs is None: - return mlirlite.const_int32(pool, 0) + if can == 0 or cargs is None: return mlirlite.const_int32(pool, 0) # 第一个参数:va_list 指针(获取 alloca,不 load) ap_node: ast.AST* = cargs.get(0) ap_ptr: mlirlite.Value* = self._va_arg_get_alloca_ptr(pool, builder, mod, ap_node, funcs_ptr, func_count, trans) - if ap_ptr is None: - return mlirlite.const_int32(pool, 0) + if ap_ptr is None: return mlirlite.const_int32(pool, 0) # bitcast 到 i8*(@llvm.va_end 接受 i8*) i8_ty_ve: mlirlite.LLVMType* = mlirlite.Int8(pool) i8_ptr_ty_ve: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_ve) ap_i8: mlirlite.Value* = mlirlite.build_bitcast(builder, ap_ptr, i8_ptr_ty_ve) - if ap_i8 is None: - return mlirlite.const_int32(pool, 0) + if ap_i8 is None: return mlirlite.const_int32(pool, 0) void_ty_ve: mlirlite.LLVMType* = mlirlite.Void(pool) mlirlite.build_call(builder, "llvm.va_end", ap_i8, 1, void_ty_ve, 0) return mlirlite.const_int32(pool, 0) def _get_func_fixed_param_count(self, func: mlirlite.Function*) -> int: """获取函数的固定参数数量(遍历 Params 链表)""" - if func is None: - return 0 + if func is None: return 0 count: int = 0 param: mlirlite.Param* = mlirlite.function_get_param_head(func) while param is not None: @@ -230,14 +215,10 @@ novirtual class CallGenVa(CallGenBase.CallGenBase): 无法从函数对象获取 IsVarArg/固定参数个数。这些 t.CExport 变参函数 (viperlib 定义)签名固定,按表回退(对齐 TPC _C_LIB_FUNCS 机制)。 """ - if name is None: - return -1 - if string.strcmp(name, "snprintf") == 0: - return 3 - if string.strcmp(name, "sprintf") == 0: - return 2 - if string.strcmp(name, "vsprintf") == 0: - return 2 + if name is None: return -1 + if string.strcmp(name, "snprintf") == 0: return 3 + if string.strcmp(name, "sprintf") == 0: return 2 + if string.strcmp(name, "vsprintf") == 0: return 2 return -1 def _get_known_vararg_cfunc_param_ty(self, pool: memhub.MemBuddy*, @@ -247,23 +228,17 @@ novirtual class CallGenVa(CallGenBase.CallGenBase): 固定参数类型是 C ABI 硬约束(snprintf 的 size 为 i64),stub 未注入 时按表 coerce,避免 call(i32 1024) 与 declare(i64 size) 不匹配。 """ - if pool is None or name is None or idx < 0: - return None + if pool is None or name is None or idx < 0: return None i8_ptr_kv: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) i64_kv: mlirlite.LLVMType* = mlirlite.Int64(pool) if string.strcmp(name, "snprintf") == 0: - if idx == 0: - return i8_ptr_kv - if idx == 1: - return i64_kv - if idx == 2: - return i8_ptr_kv + if idx == 0: return i8_ptr_kv + if idx == 1: return i64_kv + if idx == 2: return i8_ptr_kv return None if string.strcmp(name, "sprintf") == 0 or string.strcmp(name, "vsprintf") == 0: - if idx == 0: - return i8_ptr_kv - if idx == 1: - return i8_ptr_kv + if idx == 0: return i8_ptr_kv + if idx == 1: return i8_ptr_kv return None return None def _check_and_promote_variadic_call(self, pool: memhub.MemBuddy*, @@ -284,22 +259,18 @@ novirtual class CallGenVa(CallGenBase.CallGenBase): self_offset: Value 链中 self 占用的偏移(方法调用=1,普通函数=0) trans: 供 _node_type_unsigned 查询变量注解 """ - if mod is None or call_name is None or head is None: - return 0 + if mod is None or call_name is None or head is None: return 0 # 查找函数对象 func: mlirlite.Function* = self.find_func_in_module(mod, call_name) fixed_count: int = -1 - if func is not None and func.IsVarArg == 1: - fixed_count = self._get_func_fixed_param_count(func) + if func is not None and func.IsVarArg == 1: fixed_count = self._get_func_fixed_param_count(func) else: # 两种情况回退已知变参 C 库函数签名表(snprintf 等):func 为 None(跨模块 stub 未注入,翻译时 found_func 恒 None);func 存在但 IsVarArg=0(该 declare 由 _ensure_method_declare 按实参类型临时创建,无 ... 标记,不代表真实签名)。否则 i32 变参不提升,Win64 8 字节槽只写 4 字节 → va_arg(i64) 高 4 字节读残留栈垃圾 fixed_count = self._get_known_vararg_cfunc_fixed_count(call_name) - if fixed_count < 0: - return 0 + if fixed_count < 0: return 0 # 无变长参数(实参数量 <= 固定参数数量),仍需 is_variadic=1 - if can <= fixed_count: - return 1 + if can <= fixed_count: return 1 # 遍历到第 fixed_count 个节点(固定参数的最后一个) cur: mlirlite.Value* = head @@ -330,32 +301,26 @@ novirtual class CallGenVa(CallGenBase.CallGenBase): if ast_idx_va >= 0 and ast_idx_va < len(arg_nodes): an_va: ast.AST* = arg_nodes.get(ast_idx_va) if an_va is not None: - if self.Gen.ExprGenOps._node_type_unsigned(pool, an_va, trans) != 0: - is_u_va = 1 - if is_u_va != 0: - promoted = mlirlite.build_zext(builder, cur, i32_ty_promote) + if self.Gen.ExprGenOps._node_type_unsigned(pool, an_va, trans) != 0: is_u_va = 1 + if is_u_va != 0: promoted = mlirlite.build_zext(builder, cur, i32_ty_promote) else: # is_u_va 判断失败(arg_nodes/trans 缺失或变量注解查不到)时, # i8 按系统编程惯例默认 zext(对齐 should_zext_widen 的 # "i8 → zext(系统编程中 i8 几乎总是无符号字节)"策略), # 否则 printf("%02x", buf[i]) 中 uint8 字节被 sext 成 # 0xFFFFFFF3,哈希摘要输出 ffffffXX 垃圾。 - if self.Gen.ExprGenBase.get_llvm_type_bits(cur.Ty) == 8: - promoted = mlirlite.build_zext(builder, cur, i32_ty_promote) - else: - promoted = self.Gen.ExprGenBase.coerce_to_type(builder, cur, i32_ty_promote, None) + if self.Gen.ExprGenBase.get_llvm_type_bits(cur.Ty) == 8: promoted = mlirlite.build_zext(builder, cur, i32_ty_promote) + else: promoted = self.Gen.ExprGenBase.coerce_to_type(builder, cur, i32_ty_promote, None) if promoted is not None: promoted.Next = next_node - if prev is not None: - prev.Next = promoted + if prev is not None: prev.Next = promoted # C ABI float promotion: float → double arg_fbits: int = self.Gen.ExprGenBase.get_llvm_float_bits(promoted.Ty) if arg_fbits != 0 and arg_fbits < 64: promoted = self.Gen.ExprGenBase.coerce_to_type(builder, promoted, double_ty_promote, None) if promoted is not None: promoted.Next = next_node - if prev is not None: - prev.Next = promoted + if prev is not None: prev.Next = promoted # Win64 变参槽位 8 字节:i8/i16/i32 → i64 # TPV va_arg 读取端统一按 i64 读(_translate_va_arg_sugar), # 调用方必须写满 8 字节槽,否则高 4 字节残留旧栈数据,%d 读到 @@ -371,16 +336,12 @@ novirtual class CallGenVa(CallGenBase.CallGenBase): if ast_idx_va2 >= 0 and ast_idx_va2 < len(arg_nodes): an_va2: ast.AST* = arg_nodes.get(ast_idx_va2) if an_va2 is not None: - if self.Gen.ExprGenOps._node_type_unsigned(pool, an_va2, trans) != 0: - is_u_va2 = 1 - if is_u_va2 != 0: - promoted_va2 = mlirlite.build_zext(builder, promoted, i64_ty_promote) - else: - promoted_va2 = mlirlite.build_sext(builder, promoted, i64_ty_promote) + if self.Gen.ExprGenOps._node_type_unsigned(pool, an_va2, trans) != 0: is_u_va2 = 1 + if is_u_va2 != 0: promoted_va2 = mlirlite.build_zext(builder, promoted, i64_ty_promote) + else: promoted_va2 = mlirlite.build_sext(builder, promoted, i64_ty_promote) if promoted_va2 is not None: promoted_va2.Next = next_node - if prev is not None: - prev.Next = promoted_va2 + if prev is not None: prev.Next = promoted_va2 promoted = promoted_va2 prev = promoted cur = next_node diff --git a/App/lib/core/Gen/Call/CallGenVt.vp b/App/lib/core/Gen/Call/CallGenVt.vp index 364129c..643f0f7 100644 --- a/App/lib/core/Gen/Call/CallGenVt.vp +++ b/App/lib/core/Gen/Call/CallGenVt.vp @@ -48,14 +48,11 @@ novirtual class CallGenVt(CallGenBase.CallGenBase): for vi in range(method_count): pn: mlirlite.ParamNode* = mlirlite.new_param_node(pool, i8_ptr_ty) if pn is None: continue - if vt_first is None: - vt_first = pn - if vt_prev is not None: - mlirlite.paramnode_set_next(vt_prev, pn) + if vt_first is None: vt_first = pn + if vt_prev is not None: mlirlite.paramnode_set_next(vt_prev, pn) vt_prev = pn vtable_ty: mlirlite.LLVMType* = mlirlite.Struct(pool, vt_first, method_count, None) - if vtable_ty is None: - return 0 + if vtable_ty is None: return 0 # 对象 vtable 槽位(对象头 → i8**,vtable 指针总是第一个字段) vtable_slot: mlirlite.Value* = mlirlite.build_bitcast(builder, obj_ptr, i8_ptr_ptr_ty) if vtable_slot is None: return 0 @@ -95,10 +92,8 @@ novirtual class CallGenVt(CallGenBase.CallGenBase): # (devfs vtable.copy 根因;全局定义 @name 是 new_global_variable # 输出时加的,引用侧不自动加) vcopy_ref_nm: str = pool.alloc(272) - if vcopy_ref_nm is None: - vcopy_ref_nm = vcopy_buf - else: - viperlib.snprintf(vcopy_ref_nm, 272, "@%s", vcopy_buf) + if vcopy_ref_nm is None: vcopy_ref_nm = vcopy_buf + else: viperlib.snprintf(vcopy_ref_nm, 272, "@%s", vcopy_buf) vcopy_ref: mlirlite.Value* = mlirlite.SSAValue(pool, mlirlite.Ptr(pool, vtable_ty), vcopy_ref_nm) if vcopy_ref is not None: vcopy_i8: mlirlite.Value* = mlirlite.build_bitcast(builder, vcopy_ref, i8_ptr_ty) @@ -110,8 +105,7 @@ novirtual class CallGenVt(CallGenBase.CallGenBase): if vtsz_buf is not None: viperlib.snprintf(vtsz_buf, 32, "%lld", method_count * 8) vt_size: mlirlite.Value* = mlirlite.ConstInt(pool, mlirlite.Int64(pool), method_count * 8, vtsz_buf) - if vt_size is not None: - self.Gen.CallGenLib._emit_llvm_memcpy_intrinsic(pool, builder, mod, vcopy_i8, class_vt, vt_size) + if vt_size is not None: self.Gen.CallGenLib._emit_llvm_memcpy_intrinsic(pool, builder, mod, vcopy_i8, class_vt, vt_size) mlirlite.build_store(builder, vcopy_i8, vtable_slot) mlirlite.build_br(builder, vt_skip_bb) # skip 块:reload vtable → GEP 槽位 → store 函数指针(i8*) @@ -123,8 +117,7 @@ novirtual class CallGenVt(CallGenBase.CallGenBase): vt_slotp: mlirlite.Value* = mlirlite.build_gep_struct(builder, vtable_ty, i8_ptr_ty, vt_typed, method_index) if vt_slotp is None: return 0 fptr_i8: mlirlite.Value* = mlirlite.build_bitcast(builder, func_val, i8_ptr_ty) - if fptr_i8 is not None: - mlirlite.build_store(builder, fptr_i8, vt_slotp) + if fptr_i8 is not None: mlirlite.build_store(builder, fptr_i8, vt_slotp) return 1 def _write_vtable_attr(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, @@ -143,24 +136,20 @@ novirtual class CallGenVt(CallGenBase.CallGenBase): nm_v: ast.Name* = ast.Name*(at.value) if nm_v.id is not None: ve_v: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm_v.id) - if ve_v is not None: - class_nm_v = self.Gen.VarGen.var_annot_class_name(ve_v) + if ve_v is not None: class_nm_v = self.Gen.VarGen.var_annot_class_name(ve_v) elif at.value.kind() == ast.ASTKind.Attribute: # 跨 Mixin:_resolve_attr_field_class 定义在 ExprGenAttr,经 self.Gen 调用 class_nm_v = self.Gen.ExprGenAttr._resolve_attr_field_class(pool, trans, at.value) if class_nm_v is None: return 0 fd_dot_v: str = string.strrchr(class_nm_v, '.') - if fd_dot_v is not None: - class_nm_v = fd_dot_v + 1 + if fd_dot_v is not None: class_nm_v = fd_dot_v + 1 if self.Gen.StructGen.get_struct_type(class_nm_v) is None: return 0 vm_idx_v: int = self.Gen.StructGen.get_vtable_method_index(class_nm_v, at.attr) if vm_idx_v < 0: return 0 # 解析 obj_ptr(对齐 get_attribute_ptr 前半段:Name 直接查 alloca) obj_ptr_v: mlirlite.Value* = None - if at.value.kind() == ast.ASTKind.Name: - obj_ptr_v = self.Gen.VarGen.lookup_var(trans.SymTab, (ast.Name*(at.value)).id) - else: - obj_ptr_v = self.Gen.ExprGen.translate_value(builder, pool, mod, at.value, None, 0, trans) + if at.value.kind() == ast.ASTKind.Name: obj_ptr_v = self.Gen.VarGen.lookup_var(trans.SymTab, (ast.Name*(at.value)).id) + else: obj_ptr_v = self.Gen.ExprGen.translate_value(builder, pool, mod, at.value, None, 0, trans) if obj_ptr_v is None or obj_ptr_v.Ty is None: return 0 # X* 变量(Ptr(Ptr))load 解引用取对象指针 match obj_ptr_v.Ty: @@ -172,6 +161,5 @@ novirtual class CallGenVt(CallGenBase.CallGenBase): pass case _: pass - if obj_ptr_v is None: - return 0 + if obj_ptr_v is None: return 0 return self._write_vtable_slot(pool, builder, mod, obj_ptr_v, class_nm_v, vm_idx_v, rhs_val, trans) \ No newline at end of file diff --git a/App/lib/core/Gen/Class/ClassGenBase.vp b/App/lib/core/Gen/Class/ClassGenBase.vp index 6b6a76f..0516950 100644 --- a/App/lib/core/Gen/Class/ClassGenBase.vp +++ b/App/lib/core/Gen/Class/ClassGenBase.vp @@ -159,172 +159,133 @@ novirtual class ClassGenBase: def _is_cenum_base(self, base_node: ast.AST*, trans: HT.Translator* = None) -> int: """检查 base 节点是否为 t.CEnum,返回 1=是 / 0=否""" - if base_node is None: - return 0 + if base_node is None: return 0 k: int = base_node.kind() # Name('CEnum') 形式(from t import CEnum) if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(base_node) - if nm.id is None: - return 0 - if string.strcmp(nm.id, "CEnum") == 0: - return 1 + if nm.id is None: return 0 + if string.strcmp(nm.id, "CEnum") == 0: return 1 # 别名形式: from t import CEnum as en; class Color(en) # 解析别名原始名(en → CEnum)再比较 if trans is not None and trans._from_imports is not None: alias_orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, nm.id) if alias_orig is not None: og_len_ce: sizet = 0 - while alias_orig[og_len_ce] != ' ' and alias_orig[og_len_ce] != '\0': - og_len_ce += 1 - if og_len_ce == 5 and string.strncmp(alias_orig, "CEnum", 5) == 0: - return 1 + while alias_orig[og_len_ce] != ' ' and alias_orig[og_len_ce] != '\0': og_len_ce += 1 + if og_len_ce == 5 and string.strncmp(alias_orig, "CEnum", 5) == 0: return 1 return 0 # Attribute(t.CEnum) 形式 if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(base_node) - if at.attr is not None and string.strcmp(at.attr, "CEnum") == 0: - return 1 + if at.attr is not None and string.strcmp(at.attr, "CEnum") == 0: return 1 return 0 return 0 def _is_enum_class(self, cd: ast.ClassDef*, trans: HT.Translator* = None) -> int: """检查 ClassDef 是否为 CEnum:继承自 t.CEnum 或 @t.CEnum 装饰器形式""" - if cd is None: - return 0 + if cd is None: return 0 # 装饰器形式: @t.CEnum class Color:(无基类,等价 class Color(t.CEnum):) if cd.decorator_list is not None: - if self._has_decorator(cd.decorator_list, "CEnum") == 1: - return 1 - if cd.bases is None: - return 0 + if self._has_decorator(cd.decorator_list, "CEnum") == 1: return 1 + if cd.bases is None: return 0 bases: list[ast.AST*]* = cd.bases bn: sizet = len(bases) - if bn == 0: - return 0 + if bn == 0: return 0 for bi in range(bn): base_node: ast.AST* = bases.get(bi) - if base_node is None: - continue - if self._is_cenum_base(base_node, trans) == 1: - return 1 + if base_node is None: continue + if self._is_cenum_base(base_node, trans) == 1: return 1 return 0 def _is_cunion_base(self, base_node: ast.AST*, trans: HT.Translator* = None) -> int: """检查 base 节点是否为 t.CUnion,返回 1=是 / 0=否""" - if base_node is None: - return 0 + if base_node is None: return 0 k: int = base_node.kind() # Name('CUnion') 形式(from t import CUnion) if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(base_node) - if nm.id is None: - return 0 - if string.strcmp(nm.id, "CUnion") == 0: - return 1 + if nm.id is None: return 0 + if string.strcmp(nm.id, "CUnion") == 0: return 1 # 别名形式: from t import CUnion as un; class Data(un) if trans is not None and trans._from_imports is not None: alias_orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, nm.id) if alias_orig is not None: og_len_cu: sizet = 0 - while alias_orig[og_len_cu] != ' ' and alias_orig[og_len_cu] != '\0': - og_len_cu += 1 - if og_len_cu == 6 and string.strncmp(alias_orig, "CUnion", 6) == 0: - return 1 + while alias_orig[og_len_cu] != ' ' and alias_orig[og_len_cu] != '\0': og_len_cu += 1 + if og_len_cu == 6 and string.strncmp(alias_orig, "CUnion", 6) == 0: return 1 return 0 # Attribute(t.CUnion) 形式 if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(base_node) - if at.attr is not None and string.strcmp(at.attr, "CUnion") == 0: - return 1 + if at.attr is not None and string.strcmp(at.attr, "CUnion") == 0: return 1 return 0 return 0 def _is_union_class(self, cd: ast.ClassDef*, trans: HT.Translator* = None) -> int: """检查 ClassDef 是否为 CUnion:继承自 t.CUnion 或 @t.CUnion 装饰器形式""" - if cd is None: - return 0 + if cd is None: return 0 # 装饰器形式: @t.CUnion class Data: if cd.decorator_list is not None: - if self._has_decorator(cd.decorator_list, "CUnion") == 1: - return 1 - if cd.bases is None: - return 0 + if self._has_decorator(cd.decorator_list, "CUnion") == 1: return 1 + if cd.bases is None: return 0 bases: list[ast.AST*]* = cd.bases bn: sizet = len(bases) - if bn == 0: - return 0 + if bn == 0: return 0 for bi in range(bn): base_node: ast.AST* = bases.get(bi) - if base_node is None: - continue - if self._is_cunion_base(base_node, trans) == 1: - return 1 + if base_node is None: continue + if self._is_cunion_base(base_node, trans) == 1: return 1 return 0 def _is_crenum_base(self, base_node: ast.AST*, trans: HT.Translator* = None) -> int: """检查 base 节点是否为 t.REnum,返回 1=是 / 0=否""" - if base_node is None: - return 0 + if base_node is None: return 0 k: int = base_node.kind() # Name('REnum') 形式(from t import REnum) if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(base_node) - if nm.id is None: - return 0 - if string.strcmp(nm.id, "REnum") == 0: - return 1 + if nm.id is None: return 0 + if string.strcmp(nm.id, "REnum") == 0: return 1 # 别名形式: from t import REnum as ren; class Opt(ren) if trans is not None and trans._from_imports is not None: alias_orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, nm.id) if alias_orig is not None: og_len_cr: sizet = 0 - while alias_orig[og_len_cr] != ' ' and alias_orig[og_len_cr] != '\0': - og_len_cr += 1 - if og_len_cr == 5 and string.strncmp(alias_orig, "REnum", 5) == 0: - return 1 + while alias_orig[og_len_cr] != ' ' and alias_orig[og_len_cr] != '\0': og_len_cr += 1 + if og_len_cr == 5 and string.strncmp(alias_orig, "REnum", 5) == 0: return 1 return 0 # Attribute(t.REnum) 形式 if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(base_node) - if at.attr is not None and string.strcmp(at.attr, "REnum") == 0: - return 1 + if at.attr is not None and string.strcmp(at.attr, "REnum") == 0: return 1 return 0 return 0 def _is_renum_class(self, cd: ast.ClassDef*, trans: HT.Translator* = None) -> int: """检查 ClassDef 是否为 REnum:继承自 t.REnum 或 @t.REnum 装饰器形式""" - if cd is None: - return 0 + if cd is None: return 0 # 装饰器形式: @t.REnum class X: if cd.decorator_list is not None: - if self._has_decorator(cd.decorator_list, "REnum") == 1: - return 1 - if cd.bases is None: - return 0 + if self._has_decorator(cd.decorator_list, "REnum") == 1: return 1 + if cd.bases is None: return 0 bases: list[ast.AST*]* = cd.bases bn: sizet = len(bases) - if bn == 0: - return 0 + if bn == 0: return 0 for bi in range(bn): base_node: ast.AST* = bases.get(bi) - if base_node is None: - continue - if self._is_crenum_base(base_node, trans) == 1: - return 1 + if base_node is None: continue + if self._is_crenum_base(base_node, trans) == 1: return 1 return 0 def _has_decorator(self, decorator_list: list[ast.AST*]*, deco_name: str) -> int: """检查 decorator_list 中是否有指定装饰器名""" - if decorator_list is None: - return 0 + if decorator_list is None: return 0 dn: sizet = len(decorator_list) - if dn == 0: - return 0 + if dn == 0: return 0 for di in range(dn): deco: ast.AST* = decorator_list.get(di) - if deco is None: - continue + if deco is None: continue k: int = deco.kind() # @t.NoVTable 形式(Attribute) if k == ast.ASTKind.Attribute: @@ -333,31 +294,26 @@ novirtual class ClassGenBase: # 检查 value 是 Name('t') if at.value is not None and at.value.kind() == ast.ASTKind.Name: vn: ast.Name* = ast.Name*(at.value) - if vn.id is not None and string.strcmp(vn.id, "t") == 0: - return 1 + if vn.id is not None and string.strcmp(vn.id, "t") == 0: return 1 return 0 # @NoVTable 形式(Name,from t import NoVTable) if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(deco) - if nm.id is not None and string.strcmp(nm.id, deco_name) == 0: - return 1 + if nm.id is not None and string.strcmp(nm.id, deco_name) == 0: return 1 return 0 def _tattr_name(self, node: ast.AST*, attr_name: str) -> int: """从 t.attr. / t.attr.(args) 节点提取最外层属性名并比较。 Call(t.attr.aligned(16))→ 递归取 func;Attribute(t.attr.packed)→ 取 attr。 """ - if node is None: - return 0 + if node is None: return 0 if node.kind() == ast.ASTKind.Call: cl2: ast.Call* = ast.Call*(node) - if cl2.func is None: - return 0 + if cl2.func is None: return 0 return self._tattr_name(cl2.func, attr_name) if node.kind() == ast.ASTKind.Attribute: at2: ast.Attribute* = ast.Attribute*(node) - if at2.attr is None: - return 0 + if at2.attr is None: return 0 return 1 if string.strcmp(at2.attr, attr_name) == 0 else 0 return 0 def _class_has_tattr(self, decorator_list: list[ast.AST*]*, @@ -366,157 +322,119 @@ novirtual class ClassGenBase: 覆盖 packed/aligned/naked/section 等所有 t.attr 属性(B5)。 """ - if decorator_list is None: - return 0 + if decorator_list is None: return 0 dn: sizet = len(decorator_list) - if dn == 0: - return 0 + if dn == 0: return 0 for di in range(dn): deco: ast.AST* = decorator_list.get(di) - if deco is None: - continue + if deco is None: continue k: int = deco.kind() if k == ast.ASTKind.Call: cl: ast.Call* = ast.Call*(deco) # @c.Attribute(t.attr.xxx) 形式:func 是 Attribute(c, "Attribute") - if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute: - continue + if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute: continue at0: ast.Attribute* = ast.Attribute*(cl.func) - if at0.attr is None or string.strcmp(at0.attr, "Attribute") != 0: - continue - if cl.args is None: - continue + if at0.attr is None or string.strcmp(at0.attr, "Attribute") != 0: continue + if cl.args is None: continue an: sizet = len(cl.args) for ai in range(an): ag: ast.AST* = cl.args.get(ai) - if ag is not None and self._tattr_name(ag, attr_name) != 0: - return 1 + if ag is not None and self._tattr_name(ag, attr_name) != 0: return 1 else: # @t.attr.xxx 直接形式 - if self._tattr_name(deco, attr_name) != 0: - return 1 + if self._tattr_name(deco, attr_name) != 0: return 1 return 0 def _tattr_aligned_int(self, node: ast.AST*) -> int: """t.attr.aligned(N) → N(整数参数),非 aligned 或无参返回 0""" - if node is None: - return 0 + if node is None: return 0 if node.kind() == ast.ASTKind.Call: cl2: ast.Call* = ast.Call*(node) - if cl2.func is None or cl2.func.kind() != ast.ASTKind.Attribute: - return 0 + if cl2.func is None or cl2.func.kind() != ast.ASTKind.Attribute: return 0 at2: ast.Attribute* = ast.Attribute*(cl2.func) - if at2.attr is None or string.strcmp(at2.attr, "aligned") != 0: - return 0 - if cl2.args is None or len(cl2.args) == 0: - return 0 + if at2.attr is None or string.strcmp(at2.attr, "aligned") != 0: return 0 + if cl2.args is None or len(cl2.args) == 0: return 0 a0: ast.AST* = cl2.args.get(0) - if a0 is None or a0.kind() != ast.ASTKind.Constant: - return 0 + if a0 is None or a0.kind() != ast.ASTKind.Constant: return 0 cn: ast.Constant* = ast.Constant*(a0) - if cn.const_kind != ast.CONST_INT: - return 0 + if cn.const_kind != ast.CONST_INT: return 0 return int(cn.int_val) return 0 def _class_aligned_value(self, decorator_list: list[ast.AST*]*) -> int: """取 @c.Attribute(t.attr.aligned(N)) 的对齐字节数,无 aligned 返回 0""" - if decorator_list is None: - return 0 + if decorator_list is None: return 0 dn: sizet = len(decorator_list) - if dn == 0: - return 0 + if dn == 0: return 0 for di in range(dn): deco: ast.AST* = decorator_list.get(di) - if deco is None: - continue + if deco is None: continue if deco.kind() == ast.ASTKind.Call: cl: ast.Call* = ast.Call*(deco) - if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute: - continue + if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute: continue at0: ast.Attribute* = ast.Attribute*(cl.func) - if at0.attr is None or string.strcmp(at0.attr, "Attribute") != 0: - continue - if cl.args is None: - continue + if at0.attr is None or string.strcmp(at0.attr, "Attribute") != 0: continue + if cl.args is None: continue an: sizet = len(cl.args) for ai in range(an): ag: ast.AST* = cl.args.get(ai) if ag is not None: av: int = self._tattr_aligned_int(ag) - if av > 0: - return av + if av > 0: return av else: av2: int = self._tattr_aligned_int(deco) - if av2 > 0: - return av2 + if av2 > 0: return av2 return 0 def _extract_func_meta(self, decorator_list: list[ast.AST*]*) -> int: """从装饰器列表提取元数据位掩码,返回 0=无装饰器元数据""" meta: int = 0 - if decorator_list is None: - return meta + if decorator_list is None: return meta dn: sizet = len(decorator_list) - if dn == 0: - return meta + if dn == 0: return meta for di in range(dn): deco: ast.AST* = decorator_list.get(di) - if deco is None: - continue + if deco is None: continue k: int = deco.kind() if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(deco) if nm.id is not None: - if string.strcmp(nm.id, "staticmethod") == 0: - meta |= GenTypes.META_STATIC - elif string.strcmp(nm.id, "property") == 0: - meta |= GenTypes.META_PROP_GETTER - elif string.strcmp(nm.id, "classmethod") == 0: - meta |= GenTypes.META_CLASS - elif string.strcmp(nm.id, "TLS") == 0: - meta |= META_TLS + if string.strcmp(nm.id, "staticmethod") == 0: meta |= GenTypes.META_STATIC + elif string.strcmp(nm.id, "property") == 0: meta |= GenTypes.META_PROP_GETTER + elif string.strcmp(nm.id, "classmethod") == 0: meta |= GenTypes.META_CLASS + elif string.strcmp(nm.id, "TLS") == 0: meta |= META_TLS elif k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(deco) if at.attr is not None and at.value is not None: if at.value.kind() == ast.ASTKind.Name: vn: ast.Name* = ast.Name*(at.value) is_prop_name: int = 0 - if vn.id is not None and string.strcmp(vn.id, "property") == 0: - is_prop_name = 1 + if vn.id is not None and string.strcmp(vn.id, "property") == 0: is_prop_name = 1 # @t.TLS 一次性初始化标记(对齐 TPC HandlesFunctions.py # L1223-1231:value 必须为 Name('t');@TLS 裸名走上面 Name 分支) - if vn.id is not None and string.strcmp(vn.id, "t") == 0 and string.strcmp(at.attr, "TLS") == 0: - meta |= META_TLS + if vn.id is not None and string.strcmp(vn.id, "t") == 0 and string.strcmp(at.attr, "TLS") == 0: meta |= META_TLS # @property.setter 或 @x.setter/getter/deleter 都识别 if is_prop_name != 0 or string.strcmp(at.attr, "setter") == 0 or string.strcmp(at.attr, "getter") == 0 or string.strcmp(at.attr, "deleter") == 0: - if string.strcmp(at.attr, "setter") == 0: - meta |= GenTypes.META_PROP_SETTER - elif string.strcmp(at.attr, "getter") == 0: - meta |= GenTypes.META_PROP_GETTER - elif string.strcmp(at.attr, "deleter") == 0: - meta |= GenTypes.META_PROP_DELETER + if string.strcmp(at.attr, "setter") == 0: meta |= GenTypes.META_PROP_SETTER + elif string.strcmp(at.attr, "getter") == 0: meta |= GenTypes.META_PROP_GETTER + elif string.strcmp(at.attr, "deleter") == 0: meta |= GenTypes.META_PROP_DELETER return meta def register_class_meta(self, pool: memhub.MemBuddy*, kind: int, cls: str, field: str) -> int: """注册类编译期元数据字段(__provides__/__requires__/__require_must__,幂等)""" - if pool is None or cls is None or field is None: - return -1 + if pool is None or cls is None or field is None: return -1 if self.ClassMetaKinds is None: self.ClassMetaKinds = CompilerFactory.factory.PermPool.alloc(CLASS_META_MAX * 4) self.ClassMetaClss = CompilerFactory.factory.PermPool.alloc(CLASS_META_MAX * 64) self.ClassMetaFields = CompilerFactory.factory.PermPool.alloc(CLASS_META_MAX * 64) - if self.ClassMetaKinds is None or self.ClassMetaClss is None or self.ClassMetaFields is None: - return -1 + if self.ClassMetaKinds is None or self.ClassMetaClss is None or self.ClassMetaFields is None: return -1 string.memset(self.ClassMetaKinds, 0, CLASS_META_MAX * 4) string.memset(self.ClassMetaClss, 0, CLASS_META_MAX * 64) string.memset(self.ClassMetaFields, 0, CLASS_META_MAX * 64) self.ClassMetaCount = 0 - if self.ClassMetaCount >= CLASS_META_MAX: - return -1 + if self.ClassMetaCount >= CLASS_META_MAX: return -1 # 幂等:同 (kind, cls, field) 跳过 for i in range(self.ClassMetaCount): if self.ClassMetaKinds[i] == kind: if string.strcmp(self.ClassMetaClss + i * 64, cls) == 0: - if string.strcmp(self.ClassMetaFields + i * 64, field) == 0: - return 0 + if string.strcmp(self.ClassMetaFields + i * 64, field) == 0: return 0 idx_cm: sizet = sizet(self.ClassMetaCount) * 64 self.ClassMetaKinds[self.ClassMetaCount] = kind string.strncpy(self.ClassMetaClss + idx_cm, cls, 63) @@ -527,24 +445,20 @@ novirtual class ClassGenBase: return 0 def class_meta_count(self, kind: int, cls: str) -> int: """返回某类某元数据类型的字段数""" - if self.ClassMetaKinds is None or cls is None: - return 0 + if self.ClassMetaKinds is None or cls is None: return 0 n_cm: int = 0 for i in range(self.ClassMetaCount): if self.ClassMetaKinds[i] == kind: - if string.strcmp(self.ClassMetaClss + i * 64, cls) == 0: - n_cm += 1 + if string.strcmp(self.ClassMetaClss + i * 64, cls) == 0: n_cm += 1 return n_cm def class_meta_field_at(self, kind: int, cls: str, idx: int) -> str: """返回某类某元数据类型的第 idx 个字段名""" - if self.ClassMetaKinds is None or cls is None: - return None + if self.ClassMetaKinds is None or cls is None: return None n_cm2: int = 0 for i in range(self.ClassMetaCount): if self.ClassMetaKinds[i] == kind: if string.strcmp(self.ClassMetaClss + i * 64, cls) == 0: - if n_cm2 == idx: - return self.ClassMetaFields + i * 64 + if n_cm2 == idx: return self.ClassMetaFields + i * 64 n_cm2 += 1 return None def register_decorator(self, pool: memhub.MemBuddy*, @@ -555,24 +469,20 @@ novirtual class ClassGenBase: 对齐 TPC HandlesFunctions.py L1621-1631 的 _decorated_funcs 注册。 arg0 为装饰器首个常量参数(@repeat(3) 的 3),无参数为 0。 """ - if pool is None or func_name is None or wrapper_name is None: - return -1 + if pool is None or func_name is None or wrapper_name is None: return -1 if self.DecoratorFuncNames is None: self.DecoratorFuncNames = CompilerFactory.factory.PermPool.alloc(DECOR_FUNC_MAX * DECOR_NAME_LEN) self.DecoratorWrapNames = CompilerFactory.factory.PermPool.alloc(DECOR_FUNC_MAX * DECOR_NAME_LEN) self.DecoratorArgs = CompilerFactory.factory.PermPool.alloc(DECOR_FUNC_MAX * 8) - if self.DecoratorFuncNames is None or self.DecoratorWrapNames is None or self.DecoratorArgs is None: - return -1 + if self.DecoratorFuncNames is None or self.DecoratorWrapNames is None or self.DecoratorArgs is None: return -1 string.memset(self.DecoratorFuncNames, 0, DECOR_FUNC_MAX * DECOR_NAME_LEN) string.memset(self.DecoratorWrapNames, 0, DECOR_FUNC_MAX * DECOR_NAME_LEN) string.memset(self.DecoratorArgs, 0, DECOR_FUNC_MAX * 8) self.DecoratorFuncCount = 0 - if self.DecoratorFuncCount >= DECOR_FUNC_MAX: - return -1 + if self.DecoratorFuncCount >= DECOR_FUNC_MAX: return -1 # 幂等:同名函数已注册则跳过(多遍扫描) for i in range(self.DecoratorFuncCount): - if string.strcmp(self.DecoratorFuncNames + i * DECOR_NAME_LEN, func_name) == 0: - return 0 + if string.strcmp(self.DecoratorFuncNames + i * DECOR_NAME_LEN, func_name) == 0: return 0 idx_dc: sizet = sizet(self.DecoratorFuncCount) * DECOR_NAME_LEN string.strncpy(self.DecoratorFuncNames + idx_dc, func_name, DECOR_NAME_LEN - 1) self.DecoratorFuncNames[idx_dc + DECOR_NAME_LEN - 1] = '\0' @@ -583,35 +493,28 @@ novirtual class ClassGenBase: return 0 def lookup_decor_wrapper(self, func_name: str) -> str: """按原函数名查 wrapper 名,未注册返回 None""" - if self.DecoratorFuncNames is None or func_name is None: - return None + if self.DecoratorFuncNames is None or func_name is None: return None for i in range(self.DecoratorFuncCount): - if string.strcmp(self.DecoratorFuncNames + i * DECOR_NAME_LEN, func_name) == 0: - return self.DecoratorWrapNames + i * DECOR_NAME_LEN + if string.strcmp(self.DecoratorFuncNames + i * DECOR_NAME_LEN, func_name) == 0: return self.DecoratorWrapNames + i * DECOR_NAME_LEN return None def lookup_decor_arg0(self, func_name: str) -> int64: """按原函数名查装饰器首个常量参数(无参数为 0)""" - if self.DecoratorFuncNames is None or func_name is None: - return 0 + if self.DecoratorFuncNames is None or func_name is None: return 0 for i in range(self.DecoratorFuncCount): - if string.strcmp(self.DecoratorFuncNames + i * DECOR_NAME_LEN, func_name) == 0: - return self.DecoratorArgs[i] + if string.strcmp(self.DecoratorFuncNames + i * DECOR_NAME_LEN, func_name) == 0: return self.DecoratorArgs[i] return 0 # ============================================================ # 异常类注册表(try-except,对齐 TPC HandlesClassDef.py L47-61) # ============================================================ def _ensure_exception_tables(self) -> int: """懒初始化异常表(perm_pool),返回 0 成功""" - if self.ExceptionNames is not None: - return 0 + if self.ExceptionNames is not None: return 0 pp_e: memhub.MemBuddy* = CompilerFactory.factory.PermPool - if pp_e is None: - return -1 + if pp_e is None: return -1 self.ExceptionNames = pp_e.alloc(EXCEPTION_MAX * EXCEPTION_NAME_LEN) self.ExceptionParents = pp_e.alloc(EXCEPTION_MAX * EXCEPTION_NAME_LEN) self.ExceptionCodes = pp_e.alloc(EXCEPTION_MAX * 4) - if self.ExceptionNames is None or self.ExceptionParents is None or self.ExceptionCodes is None: - return -1 + if self.ExceptionNames is None or self.ExceptionParents is None or self.ExceptionCodes is None: return -1 string.memset(self.ExceptionNames, 0, EXCEPTION_MAX * EXCEPTION_NAME_LEN) string.memset(self.ExceptionParents, 0, EXCEPTION_MAX * EXCEPTION_NAME_LEN) string.memset(self.ExceptionCodes, 0, EXCEPTION_MAX * 4) @@ -620,16 +523,12 @@ novirtual class ClassGenBase: return 0 def register_exception(self, class_name: str, parent_name: str) -> int: """注册用户异常类并分配编码(幂等:同名跳过)。返回编码或 -1""" - if class_name is None: - return -1 - if self._ensure_exception_tables() != 0: - return -1 + if class_name is None: return -1 + if self._ensure_exception_tables() != 0: return -1 # 幂等:已注册则返回既有编码(多遍扫描) for i in range(self.ExceptionCount): - if string.strcmp(self.ExceptionNames + i * EXCEPTION_NAME_LEN, class_name) == 0: - return self.ExceptionCodes[i] - if self.ExceptionCount >= EXCEPTION_MAX: - return -1 + if string.strcmp(self.ExceptionNames + i * EXCEPTION_NAME_LEN, class_name) == 0: return self.ExceptionCodes[i] + if self.ExceptionCount >= EXCEPTION_MAX: return -1 idx_e: sizet = sizet(self.ExceptionCount) * EXCEPTION_NAME_LEN string.strncpy(self.ExceptionNames + idx_e, class_name, EXCEPTION_NAME_LEN - 1) self.ExceptionNames[idx_e + EXCEPTION_NAME_LEN - 1] = '\0' @@ -643,8 +542,7 @@ novirtual class ClassGenBase: return code_e def _builtin_exception_code(self, name: str) -> int: """内置异常编码(对齐 TPC HandlesBase.py EXCEPTION_CODE_MAP),非内置返回 0""" - if name is None: - return 0 + if name is None: return 0 if string.strcmp(name, "ValueError") == 0: return 1 if string.strcmp(name, "TypeError") == 0: return 2 if string.strcmp(name, "RuntimeError") == 0: return 3 @@ -658,55 +556,43 @@ novirtual class ClassGenBase: return 0 def lookup_exception_code(self, name: str) -> int: """查异常编码:内置表优先,其次用户异常表,都未命中返回 0""" - if name is None: - return 0 + if name is None: return 0 bi: int = self._builtin_exception_code(name) - if bi != 0: - return bi - if self.ExceptionNames is None: - return 0 + if bi != 0: return bi + if self.ExceptionNames is None: return 0 for i in range(self.ExceptionCount): - if string.strcmp(self.ExceptionNames + i * EXCEPTION_NAME_LEN, name) == 0: - return self.ExceptionCodes[i] + if string.strcmp(self.ExceptionNames + i * EXCEPTION_NAME_LEN, name) == 0: return self.ExceptionCodes[i] return 0 def lookup_exception_parent(self, name: str) -> str: """查用户异常类的父类名,非用户异常返回 None""" - if name is None or self.ExceptionNames is None: - return None + if name is None or self.ExceptionNames is None: return None for i in range(self.ExceptionCount): if string.strcmp(self.ExceptionNames + i * EXCEPTION_NAME_LEN, name) == 0: p_e: str = self.ExceptionParents + i * EXCEPTION_NAME_LEN - if p_e is not None and p_e[0] != '\0': - return p_e + if p_e is not None and p_e[0] != '\0': return p_e return None return None def is_exception_name(self, name: str) -> int: """name 是否是内置或用户异常类名(1=是 / 0=否)""" - if name is None: - return 0 - if self._builtin_exception_code(name) != 0: - return 1 - if self.ExceptionNames is None: - return 0 + if name is None: return 0 + if self._builtin_exception_code(name) != 0: return 1 + if self.ExceptionNames is None: return 0 for i in range(self.ExceptionCount): - if string.strcmp(self.ExceptionNames + i * EXCEPTION_NAME_LEN, name) == 0: - return 1 + if string.strcmp(self.ExceptionNames + i * EXCEPTION_NAME_LEN, name) == 0: return 1 return 0 def collect_descendant_codes(self, name: str, out_codes: int*, max_codes: int) -> int: """把 name 及其所有子孙异常类的编码收集到 out_codes,返回数量 (对齐 TPC HandlesTry.py _get_all_match_codes/_collect_descendant_codes: 编译期静态展开继承树,except X 匹配 X 及全部子孙)。""" - if name is None or out_codes is None: - return 0 + if name is None or out_codes is None: return 0 self._exception_codes_tmp_count = 0 self._collect_desc_codes_rec(name, out_codes, max_codes, 0) return self._exception_codes_tmp_count def _collect_desc_codes_rec(self, name: str, out_codes: int*, max_codes: int, depth: int) -> None: """递归收集 name 编码 + 全部子孙编码(BFS 语义对齐 TPC)""" - if depth > 32: - return + if depth > 32: return code_e: int = self.lookup_exception_code(name) if code_e != 0 and self._exception_codes_tmp_count < max_codes: # 去重(继承环防护) @@ -719,106 +605,82 @@ novirtual class ClassGenBase: out_codes[self._exception_codes_tmp_count] = code_e self._exception_codes_tmp_count += 1 # 遍历全部用户异常,找以 name 为父类的子类递归收集 - if self.ExceptionNames is None: - return + if self.ExceptionNames is None: return for i in range(self.ExceptionCount): cname_e: str = self.ExceptionNames + i * EXCEPTION_NAME_LEN pname_e: str = self.ExceptionParents + i * EXCEPTION_NAME_LEN if pname_e is not None and pname_e[0] != '\0': - if string.strcmp(pname_e, name) == 0: - self._collect_desc_codes_rec(cname_e, out_codes, max_codes, depth + 1) + if string.strcmp(pname_e, name) == 0: self._collect_desc_codes_rec(cname_e, out_codes, max_codes, depth + 1) def _is_exception_class_def(self, cd: ast.ClassDef*) -> int: """类定义是否是异常类:基类是 Exception 或已注册异常类(1=是)""" - if cd is None or cd.bases is None: - return 0 + if cd is None or cd.bases is None: return 0 bases_e: list[ast.AST*]* = cd.bases bn_e: sizet = len(bases_e) for bi_e in range(bn_e): base_e: ast.AST* = bases_e.get(bi_e) - if base_e is None: - continue + if base_e is None: continue base_name_e: str = None - if base_e.kind() == ast.ASTKind.Name: - base_name_e = (ast.Name*(base_e)).id + if base_e.kind() == ast.ASTKind.Name: base_name_e = (ast.Name*(base_e)).id elif base_e.kind() == ast.ASTKind.Attribute: base_at_e: ast.Attribute* = ast.Attribute*(base_e) - if base_at_e.attr is not None: - base_name_e = base_at_e.attr - if base_name_e is None: - continue - if string.strcmp(base_name_e, "Exception") == 0: - return 1 - if self.is_exception_name(base_name_e) != 0: - return 1 + if base_at_e.attr is not None: base_name_e = base_at_e.attr + if base_name_e is None: continue + if string.strcmp(base_name_e, "Exception") == 0: return 1 + if self.is_exception_name(base_name_e) != 0: return 1 return 0 def _get_exception_parent_name(self, cd: ast.ClassDef*) -> str: """返回异常类定义的真实父类名(第一个非 Exception 的已注册异常类),无则 None""" - if cd is None or cd.bases is None: - return None + if cd is None or cd.bases is None: return None bases_e2: list[ast.AST*]* = cd.bases bn_e2: sizet = len(bases_e2) for bi_e2 in range(bn_e2): base_e2: ast.AST* = bases_e2.get(bi_e2) - if base_e2 is None: - continue + if base_e2 is None: continue base_name_e2: str = None - if base_e2.kind() == ast.ASTKind.Name: - base_name_e2 = (ast.Name*(base_e2)).id + if base_e2.kind() == ast.ASTKind.Name: base_name_e2 = (ast.Name*(base_e2)).id elif base_e2.kind() == ast.ASTKind.Attribute: base_at_e2: ast.Attribute* = ast.Attribute*(base_e2) - if base_at_e2.attr is not None: - base_name_e2 = base_at_e2.attr - if base_name_e2 is None: - continue - if string.strcmp(base_name_e2, "Exception") != 0 and self.is_exception_name(base_name_e2) != 0: - return base_name_e2 + if base_at_e2.attr is not None: base_name_e2 = base_at_e2.attr + if base_name_e2 is None: continue + if string.strcmp(base_name_e2, "Exception") != 0 and self.is_exception_name(base_name_e2) != 0: return base_name_e2 return None def _register_exception_class_def(self, trans: HT.Translator*, cd: ast.ClassDef*) -> int: """注册异常类(分配编码 + 记录父类),不生成 struct,返回 0""" - if cd is None or cd.name is None: - return 0 + if cd is None or cd.name is None: return 0 parent_e: str = self._get_exception_parent_name(cd) self.register_exception(cd.name, parent_e) return 0 def _register_class_meta_list(self, pool: memhub.MemBuddy*, kind: int, cls: str, value_node: ast.AST*) -> None: """解析类体 __provides__/__requires__ 的 list[str] 字面量并注册""" - if value_node is None or cls is None: - return - if value_node.kind() != ast.ASTKind.List: - return + if value_node is None or cls is None: return + if value_node.kind() != ast.ASTKind.List: return lst_rcm: ast.List* = ast.List*(value_node) - if lst_rcm.elts is None: - return + if lst_rcm.elts is None: return elts_rcm: list[ast.AST*]* = lst_rcm.elts en_rcm: sizet = len(elts_rcm) for ei_rcm in range(en_rcm): el_rcm: ast.AST* = elts_rcm.get(ei_rcm) - if el_rcm is None or el_rcm.kind() != ast.ASTKind.Constant: - continue + if el_rcm is None or el_rcm.kind() != ast.ASTKind.Constant: continue ec_rcm: ast.Constant* = ast.Constant*(el_rcm) - if ec_rcm.str_val is not None: - self.register_class_meta(pool, kind, cls, ec_rcm.str_val) + if ec_rcm.str_val is not None: self.register_class_meta(pool, kind, cls, ec_rcm.str_val) def register_method_meta(self, class_name: str, method_name: str, meta: int) -> None: """注册方法元数据(幂等)""" - if class_name is None or method_name is None or meta == 0: - return + if class_name is None or method_name is None or meta == 0: return # 懒初始化 if self.MethodMetaKeys is None: self.MethodMetaKeys = CompilerFactory.factory.PermPool.alloc(META_MAX * META_KEY_LEN) self.MethodMetaFlags = CompilerFactory.factory.PermPool.alloc(META_MAX * 4) - if self.MethodMetaKeys is None or self.MethodMetaFlags is None: - return + if self.MethodMetaKeys is None or self.MethodMetaFlags is None: return string.memset(self.MethodMetaKeys, 0, META_MAX * META_KEY_LEN) string.memset(self.MethodMetaFlags, 0, META_MAX * 4) # 构造 key "ClassName.method" cl_len: sizet = string.strlen(class_name) mn_len: sizet = string.strlen(method_name) key_buf: bytes = stdlib.malloc(cl_len + mn_len + 2) - if key_buf is None: - return + if key_buf is None: return viperlib.snprintf(key_buf, cl_len + mn_len + 2, "%s.%s", class_name, method_name) # 去重更新 i: int @@ -843,15 +705,12 @@ novirtual class ClassGenBase: stdlib.free(key_buf) def lookup_method_meta(self, class_name: str, method_name: str) -> int: """查找方法元数据位掩码,返回 0=未注册或非装饰器方法""" - if class_name is None or method_name is None: - return 0 - if self.MethodMetaKeys is None or self.MethodMetaCount <= 0: - return 0 + if class_name is None or method_name is None: return 0 + if self.MethodMetaKeys is None or self.MethodMetaCount <= 0: return 0 cl_len: sizet = string.strlen(class_name) mn_len: sizet = string.strlen(method_name) key_buf: bytes = stdlib.malloc(cl_len + mn_len + 2) - if key_buf is None: - return 0 + if key_buf is None: return 0 viperlib.snprintf(key_buf, cl_len + mn_len + 2, "%s.%s", class_name, method_name) found: int = 0 i: int @@ -874,26 +733,16 @@ novirtual class ClassGenBase: 'i32' but expected 'ptr'"。 与 TPC(_resolve_base_kind 对 t.Struct 返回 None → 无父类)保持一致。 """ - if base_name is None: - return 0 - if string.strcmp(base_name, "Object") == 0: - return 1 - if string.strcmp(base_name, "CVTable") == 0: - return 1 - if string.strcmp(base_name, "Exception") == 0: - return 1 - if string.strcmp(base_name, "CEnum") == 0: - return 1 - if string.strcmp(base_name, "Enum") == 0: - return 1 - if string.strcmp(base_name, "CStruct") == 0: - return 1 - if string.strcmp(base_name, "Struct") == 0: - return 1 - if string.strcmp(base_name, "CUnion") == 0: - return 1 - if string.strcmp(base_name, "REnum") == 0: - return 1 + if base_name is None: return 0 + if string.strcmp(base_name, "Object") == 0: return 1 + if string.strcmp(base_name, "CVTable") == 0: return 1 + if string.strcmp(base_name, "Exception") == 0: return 1 + if string.strcmp(base_name, "CEnum") == 0: return 1 + if string.strcmp(base_name, "Enum") == 0: return 1 + if string.strcmp(base_name, "CStruct") == 0: return 1 + if string.strcmp(base_name, "Struct") == 0: return 1 + if string.strcmp(base_name, "CUnion") == 0: return 1 + if string.strcmp(base_name, "REnum") == 0: return 1 return 0 def _get_base_name(self, base_node: ast.AST*, pool: memhub.MemBuddy* = None, @@ -909,8 +758,7 @@ novirtual class ClassGenBase: 产出 ⇒ 这里同样归一,否则父类 `GSListNode[Value]` 与注册的 `GSListNode[{sha1}.Value]` 不同名 ⇒ 父类查找落空/继承链断裂。 """ - if base_node is None: - return None + if base_node is None: return None k: int = base_node.kind() # Name(id) 形式 if k == ast.ASTKind.Name: @@ -923,12 +771,10 @@ novirtual class ClassGenBase: # Subscript(value, slice) 形式 — 如 GSListNode[Value] if k == ast.ASTKind.Subscript: sub: ast.Subscript* = ast.Subscript*(base_node) - if sub is None or sub.value is None or sub.slice is None: - return None + if sub is None or sub.value is None or sub.slice is None: return None # 提取基类名(如 "GSListNode") base_nm: str = self._get_base_name(sub.value, pool, from_imports) - if base_nm is None: - return None + if base_nm is None: return None # 提取类型实参名(如 "Value"),并与唯一生成器同口径归一 slice_k: int = sub.slice.kind() arg_nm: str = None @@ -936,14 +782,11 @@ novirtual class ClassGenBase: sl_nm: ast.Name* = ast.Name*(sub.slice) arg_nm = sl_nm.id # 如果无法提取类型实参,返回基类名(降级) - if arg_nm is None: - return base_nm + if arg_nm is None: return base_nm # 无 pool 时返回基类名(降级,无法拼接特化名) - if pool is None: - return base_nm + if pool is None: return base_nm arg_norm: str = self.Gen.TypeGenResolve._norm_type_arg_name(pool, arg_nm, from_imports) - if arg_norm is not None: - arg_nm = arg_norm + if arg_norm is not None: arg_nm = arg_norm # 拼接特化名 "GSListNode[Value]" base_len: sizet = string.strlen(base_nm) arg_len: sizet = string.strlen(arg_nm) @@ -961,29 +804,23 @@ novirtual class ClassGenBase: def _get_parent_class(self, cd: ast.ClassDef*, trans: HT.Translator* = None) -> str: """获取 ClassDef 的真实父类名,返回 None=无真实父类""" - if cd is None or cd.bases is None: - return None + if cd is None or cd.bases is None: return None pool: memhub.MemBuddy* = None - if trans is not None: - pool = trans.Pool + if trans is not None: pool = trans.Pool bases: list[ast.AST*]* = cd.bases bn: sizet = len(bases) - if bn == 0: - return None + if bn == 0: return None for bi in range(bn): base_node: ast.AST* = bases.get(bi) - if base_node is None: - continue + if base_node is None: continue _fi_pc: str = None - if trans is not None: - _fi_pc = trans._from_imports + if trans is not None: _fi_pc = trans._from_imports bname: str = self._get_base_name(base_node, pool, _fi_pc) if bname is not None: # 基类别名解析(from t import CStruct as cs → cs 实际是 CStruct)。 # 不解析会把别名当真实父类 → find_struct("cs") 失败 → 类 defer 永不注册。 bname = self._resolve_base_alias(bname, trans) - if self._is_marker_base(bname) == 0: - return bname + if self._is_marker_base(bname) == 0: return bname return None def _resolve_base_alias(self, base_name: str, trans: HT.Translator* = None) -> str: @@ -993,8 +830,7 @@ novirtual class ClassGenBase: PhaseA 预注册把整类 defer(永不注册)→ 变量注解 X 解析失败 (EdgeCaseTest Test12 class CsPoint(cs): 根因)。 """ - if base_name is None or trans is None or trans._from_imports is None: - return base_name + if base_name is None or trans is None or trans._from_imports is None: return base_name orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, base_name) if orig is not None: # lookup_from_import_original 返回 from_imports 内部指针且未 NUL 结尾 @@ -1003,8 +839,7 @@ novirtual class ClassGenBase: # strcmp 对整串比较失败 → 别名基类(CStruct as cs)被当真实父类 → # find_struct 失败 → 整类 defer 永不注册 → 变量注解解析失败。 og_len: sizet = 0 - while orig[og_len] != ' ' and orig[og_len] != '\0': - og_len += 1 + while orig[og_len] != ' ' and orig[og_len] != '\0': og_len += 1 if og_len > 0: og_buf: str = CompilerFactory.factory.PermPool.alloc(og_len + 1) if og_buf is not None: @@ -1018,20 +853,16 @@ novirtual class ClassGenBase: max_parents: int, trans: HT.Translator* = None) -> int: """收集所有非 marker 父类名到 parents_buf,返回数量""" - if pool is None or cd is None or cd.bases is None or parents_buf is None: - return 0 + if pool is None or cd is None or cd.bases is None or parents_buf is None: return 0 bases: list[ast.AST*]* = cd.bases bn: sizet = len(bases) count: int = 0 for bi in range(bn): - if count >= max_parents: - break + if count >= max_parents: break base_node: ast.AST* = bases.get(bi) - if base_node is None: - continue + if base_node is None: continue _fi_cp: str = None - if trans is not None: - _fi_cp = trans._from_imports + if trans is not None: _fi_cp = trans._from_imports bname: str = self._get_base_name(base_node, pool, _fi_cp) if bname is not None: # 基类别名解析(同 _get_parent_class,见 _resolve_base_alias) @@ -1043,113 +874,87 @@ novirtual class ClassGenBase: def _field_name_exists(self, names_buf: sizet*, count: int, name: str) -> int: """检查字段名是否已在 names_buf 中(先声明父类优先,重复跳过)""" - if names_buf is None or name is None: - return 0 + if names_buf is None or name is None: return 0 for fi in range(count): addr: sizet = names_buf[fi] if addr != 0: existing: str = rawptr(addr) - if existing is not None and string.strcmp(existing, name) == 0: - return 1 + if existing is not None and string.strcmp(existing, name) == 0: return 1 return 0 def _class_body_has_field(self, cd: ast.ClassDef*) -> int: """检查类体是否声明了字段(AnnAssign),0=纯方法/无字段类""" - if cd is None or cd.children is None: - return 0 + if cd is None or cd.children is None: return 0 cn: sizet = len(cd.children) for ci in range(cn): stmt: ast.AST* = cd.children.get(ci) - if stmt is None: - continue - if stmt.kind() == ast.ASTKind.AnnAssign: - return 1 + if stmt is None: continue + if stmt.kind() == ast.ASTKind.AnnAssign: return 1 return 0 def _trigger_base_specialization(self, trans: HT.Translator*, cd: ast.ClassDef*): """触发 base 中 Subscript 的泛型特化(如 GSListNode[Value])""" - if trans is None or cd is None or cd.bases is None: - return + if trans is None or cd is None or cd.bases is None: return pool: memhub.MemBuddy* = trans.Pool bases: list[ast.AST*]* = cd.bases bn: sizet = len(bases) - if bn == 0: - return + if bn == 0: return for bi in range(bn): base_node: ast.AST* = bases.get(bi) - if base_node is None: - continue + if base_node is None: continue bk: int = base_node.kind() - if bk != ast.ASTKind.Subscript: - continue + if bk != ast.ASTKind.Subscript: continue sub: ast.Subscript* = ast.Subscript*(base_node) - if sub is None or sub.value is None or sub.slice is None: - continue + if sub is None or sub.value is None or sub.slice is None: continue # 提取泛型类名(如 "GSListNode") gen_class_name: str = self._get_base_name(sub.value, pool) - if gen_class_name is None: - continue + if gen_class_name is None: continue # 跳过标记基类 - if self._is_marker_base(gen_class_name) == 1: - continue + if self._is_marker_base(gen_class_name) == 1: continue # 提取类型实参名(如 "Value") slice_k: int = sub.slice.kind() arg_nm: str = None if slice_k == ast.ASTKind.Name: sl_nm: ast.Name* = ast.Name*(sub.slice) arg_nm = sl_nm.id - if arg_nm is None: - continue + if arg_nm is None: continue # 构建 type_args 列表(elem_size=8:str 是指针,1 会导致双元素重叠损坏) type_args: list[str]* = list[str](pool, 8) - if type_args is None: - continue + if type_args is None: continue type_args.append(arg_nm) # 触发特化(_specialize_generic_class 有缓存,重复调用安全) self.Gen.ClassGenGeneric._specialize_generic_class(trans, gen_class_name, type_args) def _has_any_func_cvtable(self, cd: ast.ClassDef*) -> int: """检查类中是否有任何函数标记了 @t.CVTable,返回 1=有 / 0=无""" - if cd is None or cd.children is None: - return 0 + if cd is None or cd.children is None: return 0 children: list[ast.AST*]* = cd.children cn: sizet = len(children) for ci in range(cn): stmt: ast.AST* = children.get(ci) - if stmt is None: - continue - if stmt.kind() != ast.ASTKind.FunctionDef: - continue + if stmt is None: continue + if stmt.kind() != ast.ASTKind.FunctionDef: continue fd: ast.FunctionDef* = ast.FunctionDef*(stmt) - if fd is None or fd.name is None: - continue + if fd is None or fd.name is None: continue # 跳过构造函数 - if string.strcmp(fd.name, "__init__") == 0: - continue - if string.strcmp(fd.name, "__before_init__") == 0: - continue - if string.strcmp(fd.name, "__new__") == 0: - continue + if string.strcmp(fd.name, "__init__") == 0: continue + if string.strcmp(fd.name, "__before_init__") == 0: continue + if string.strcmp(fd.name, "__new__") == 0: continue if fd.decorator_list is not None: - if self._has_decorator(fd.decorator_list, "CVTable") == 1: - return 1 + if self._has_decorator(fd.decorator_list, "CVTable") == 1: return 1 return 0 def _should_method_be_virtual(self, cd: ast.ClassDef*, fd: ast.FunctionDef*, trans: HT.Translator* = None) -> int: """判断方法是否应该进入虚表,返回 1=包含 / 0=排除""" - if fd is None: - return 0 + if fd is None: return 0 # 1. 检查函数级 @t.NoVTable(最高优先级,排除) if fd.decorator_list is not None: - if self._has_decorator(fd.decorator_list, "NoVTable") == 1: - return 0 + if self._has_decorator(fd.decorator_list, "NoVTable") == 1: return 0 # 2. 检查函数级 @t.CVTable(明确包含) - if self._has_decorator(fd.decorator_list, "CVTable") == 1: - return 1 + if self._has_decorator(fd.decorator_list, "CVTable") == 1: return 1 # 3. 检查类级别 @t.CVTable if cd is not None and cd.decorator_list is not None: - if self._has_decorator(cd.decorator_list, "CVTable") == 1: - return 1 + if self._has_decorator(cd.decorator_list, "CVTable") == 1: return 1 # 4. 检查继承关系 parent_name: str = self._get_parent_class(cd, trans) @@ -1163,17 +968,14 @@ novirtual class ClassGenBase: # 与字段展平(1.5 节)的回退保持一致,否则父类 NoVTable 被误判为有虚表 → 子类插 vptr # 导致子类布局比父类多一个指针,父类方法按无 vptr 布局操作错位 p_entry = self.Gen.StructGen.find_struct(parent_name) - if p_entry is not None: - is_nvt = p_entry.IsNoVTable - else: - is_nvt = self.Gen.StructGen.is_novtable_by_name(parent_name) + if p_entry is not None: is_nvt = p_entry.IsNoVTable + else: is_nvt = self.Gen.StructGen.is_novtable_by_name(parent_name) if is_nvt != 1: # 继承链统一虚表:父类有虚表 → 方法进虚表;父类无虚表 → 静态方法。 # 与 _detect_vtable_status 规则一致,避免父类无 vptr 布局/子类有 vptr 的错位。 if p_entry is None: return 1 # 父类信息未知,保守进虚表 - if p_entry.HasVTable == 1: - return 1 + if p_entry.HasVTable == 1: return 1 return 0 # 5. 默认排除 @@ -1186,11 +988,9 @@ novirtual class ClassGenBase: # 检查类装饰器 if cd.decorator_list is not None: # @t.CVTable 优先级最高,直接启用 - if self._has_decorator(cd.decorator_list, "CVTable") == 1: - return 1 + if self._has_decorator(cd.decorator_list, "CVTable") == 1: return 1 # @t.NoVTable:类级别禁用,但检查函数级 @t.CVTable - if self._has_decorator(cd.decorator_list, "NoVTable") == 1: - return self._has_any_func_cvtable(cd) + if self._has_decorator(cd.decorator_list, "NoVTable") == 1: return self._has_any_func_cvtable(cd) # 检查是否有真实父类(继承自动启用 CVTable) parent_name: str = self._get_parent_class(cd, trans) @@ -1202,10 +1002,8 @@ novirtual class ClassGenBase: if p_entry is None: # 跨模块父类回退全局查找(同 _detect_vtable_status 的回退) p_entry = self.Gen.StructGen.find_struct(parent_name) - if p_entry is not None: - is_nvt = p_entry.IsNoVTable - else: - is_nvt = self.Gen.StructGen.is_novtable_by_name(parent_name) + if p_entry is not None: is_nvt = p_entry.IsNoVTable + else: is_nvt = self.Gen.StructGen.is_novtable_by_name(parent_name) if is_nvt == 1: # 父类是 NoVTable,检查函数级 @t.CVTable return self._has_any_func_cvtable(cd) @@ -1220,8 +1018,7 @@ novirtual class ClassGenBase: return self._has_any_func_cvtable(cd) def InitClassGen(self) -> int: """初始化 ClassGen 族字段(构造时由 Generator 调用)""" - if self is None: - return 1 + if self is None: return 1 self.MethodMetaKeys = None self.MethodMetaFlags = None self.MethodMetaCount = 0 diff --git a/App/lib/core/Gen/Class/ClassGenDef.vp b/App/lib/core/Gen/Class/ClassGenDef.vp index b7a228a..baf79d8 100644 --- a/App/lib/core/Gen/Class/ClassGenDef.vp +++ b/App/lib/core/Gen/Class/ClassGenDef.vp @@ -63,12 +63,10 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): return self.Gen.ClassGenEnum._translate_enum_def(trans, cd) # 联合体类:交给联合体处理 - if self.Gen.ClassGenBase._is_union_class(cd, trans) == 1: - return self.Gen.ClassGenEnum._translate_union_def(trans, cd) + if self.Gen.ClassGenBase._is_union_class(cd, trans) == 1: return self.Gen.ClassGenEnum._translate_union_def(trans, cd) # REnum 类:交给 REnum 处理({i32 tag, max_payload} 布局) - if self.Gen.ClassGenBase._is_renum_class(cd, trans) == 1: - return self.Gen.ClassGenEnum._translate_renum_def(trans, cd) + if self.Gen.ClassGenBase._is_renum_class(cd, trans) == 1: return self.Gen.ClassGenEnum._translate_renum_def(trans, cd) # 泛型类:存储为模板,不发射 IR(等实例化时特化) # 用局部变量接收 cd.type_params,触发类型推断 @@ -80,8 +78,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): # 异常类(try-except):注册编码+继承树,不生成 struct # (对齐 TPC HandlesClassDef.py L509-511:_is_exception_class → # _RegisterExceptionClass → return,异常类不编译为结构体) - if self.Gen.ClassGenBase._is_exception_class_def(cd) == 1: - return self.Gen.ClassGenBase._register_exception_class_def(trans, cd) + if self.Gen.ClassGenBase._is_exception_class_def(cd) == 1: return self.Gen.ClassGenBase._register_exception_class_def(trans, cd) # 嵌套类 / 嵌套 struct:类体里再写 class / struct 此前被**静默丢弃** # (字段循环只认 AnnAssign、_translate_oop_methods 只认 FunctionDef), @@ -105,12 +102,10 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): # 在填充后自动指向完整定义(对齐 TPC 的 opaque 占位 + set_body 填充)。 fill_fwd: int = 0 if existing is not None: - if existing.IsForwardDecl != 0: - fill_fwd = 1 + if existing.IsForwardDecl != 0: fill_fwd = 1 elif existing.FieldCount == 0 and trans._declare_only == 0: if self.Gen.ClassGenBase._class_body_has_field(cd) != 0: - if existing.Name is not None: - existing.Name[0] = '\0' + if existing.Name is not None: existing.Name[0] = '\0' existing.Ty = None existing.FieldCount = 0 needs_rereg = 1 @@ -128,8 +123,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): # 读悬空挂起(G3 LinkedNode.prepend 挂起根因)。DeepCopyType # 递归深拷贝字段链表/子类型/Name 到 stdlib(深度上限+链守卫)。 ty_deep: mlirlite.LLVMType* = mlirlite.DeepCopyType(CompilerFactory.factory.PermPool, existing.Ty) - if ty_deep is not None: - existing.Ty = ty_deep + if ty_deep is not None: existing.Ty = ty_deep old_name: str = mlirlite.get_struct_name(existing.Ty) if old_name is not None: on_len: sizet = string.strlen(old_name) @@ -165,14 +159,11 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): # 早退分支(不经过下方全新定义路径的字段扫描循环)。 self.Gen.StructGen._ensure_field_types_in_module(pool, trans.Module, existing.Ty) align_ex: int = self.Gen.ClassGenBase._class_aligned_value(cd.decorator_list) - if align_ex > 0 and existing.Align == 0: - existing.Align = align_ex + if align_ex > 0 and existing.Align == 0: existing.Align = align_ex # Phase A-pre(declare_only=1)多遍扫描时,类已注册但不应翻译方法体 # Phase B(declare_only=0)时全量翻译方法体 - if trans._declare_only == 1: - self.Gen.ClassGenVTable._translate_oop_methods(trans, cd, existing.Ty, class_name, 1) - else: - self.Gen.ClassGenVTable._translate_oop_methods(trans, cd, existing.Ty, class_name) + if trans._declare_only == 1: self.Gen.ClassGenVTable._translate_oop_methods(trans, cd, existing.Ty, class_name, 1) + else: self.Gen.ClassGenVTable._translate_oop_methods(trans, cd, existing.Ty, class_name) # SHA1 已在 register_struct 时设置,无需再补 return 0 @@ -191,12 +182,10 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): # 多继承:收集所有真实父类名(跳过 marker base),供字段展平/vtable/MRO 使用 parents_buf: sizet* = pool.alloc(8 * GenTypes.PARENT_MAX) parents_count: int = 0 - if parents_buf is not None: - parents_count = self.Gen.ClassGenBase._collect_parents(pool, cd, parents_buf, GenTypes.PARENT_MAX, trans) + if parents_buf is not None: parents_count = self.Gen.ClassGenBase._collect_parents(pool, cd, parents_buf, GenTypes.PARENT_MAX, trans) is_novtable_deco: int = 0 if cd.decorator_list is not None: - if self.Gen.ClassGenBase._has_decorator(cd.decorator_list, "NoVTable") == 1: - is_novtable_deco = 1 + if self.Gen.ClassGenBase._has_decorator(cd.decorator_list, "NoVTable") == 1: is_novtable_deco = 1 # ============================================================ # PhaseA 预注册延迟检查:父类未注册时延迟注册当前类 @@ -213,10 +202,8 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): # ============================================================ if trans._declare_only == 1 and parent_name is not None: parent_check: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(parent_name, trans.ModuleSha1) - if parent_check is None: - parent_check = self.Gen.StructGen.find_struct(parent_name) - if parent_check is None: - return 0 + if parent_check is None: parent_check = self.Gen.StructGen.find_struct(parent_name) + if parent_check is None: return 0 # ============================================================ # 1. 遍历 class body,收集字段信息 @@ -235,12 +222,9 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): # 字段 const 对象标记缓冲(1=字段注解含 t.CConst 且字段类型非指针); # 与 field_volatile_buf 并行,取值 0/1。 field_const_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX) - if field_names_buf is None or field_types_buf is None or field_defaults_buf is None: - return 0 - if field_annot_buf is None or field_volatile_buf is None: - return 0 - if field_pointee_volatile_buf is None or field_const_buf is None: - return 0 + if field_names_buf is None or field_types_buf is None or field_defaults_buf is None: return 0 + if field_annot_buf is None or field_volatile_buf is None: return 0 + if field_pointee_volatile_buf is None or field_const_buf is None: return 0 string.memset(field_names_buf, 0, 8 * GenTypes.FIELD_MAX) string.memset(field_types_buf, 0, 8 * GenTypes.FIELD_MAX) string.memset(field_defaults_buf, 0, 8 * GenTypes.FIELD_MAX) @@ -296,15 +280,12 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): pfa: str = self.Gen.StructGen.get_field_annot_class_name(pfe) field_names_buf[field_count] = sizet(pfn) field_types_buf[field_count] = sizet(pft) - if pfd is not None: - field_defaults_buf[field_count] = sizet(pfd) - else: - field_defaults_buf[field_count] = 0 + if pfd is not None: field_defaults_buf[field_count] = sizet(pfd) + else: field_defaults_buf[field_count] = 0 if pfa is not None: stored_val: sizet = sizet(pfa) field_annot_buf[field_count] = stored_val - else: - field_annot_buf[field_count] = 0 + else: field_annot_buf[field_count] = 0 # 继承父类字段的 volatile 标记(字段展平后语义不变) field_volatile_buf[field_count] = sizet(pfe.IsVolatile) # 继承父类字段的「所指物 volatile」标记(展平后语义不变) @@ -314,8 +295,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): field_count += 1 children: list[ast.AST*]* = cd.children - if children is None: - return 0 + if children is None: return 0 cn: sizet = len(children) for ci in range(cn): @@ -339,8 +319,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): # CDefine 表解析为常量值;类体开头的常量(MRO_MAX 等)由早期预注册 # 路径注册,但方法之后的 AnnAssign 不经过那些路径 → 此处统一兜底注册。 if self.Gen.AssignGen.is_cdefine_annotation(aa.annotation) != 0: - if aa.value is not None: - self.Gen.AssignGen._register_cdefine_from_value(pool, tgt.id, aa.value, aa.annotation) + if aa.value is not None: self.Gen.AssignGen._register_cdefine_from_value(pool, tgt.id, aa.value, aa.annotation) # CDefine 字段类型固定 i32,直接收集后跳过通用注解解析: # resolve_annotation_type 不识别 "CDefine"(map_t_type/CTypedef # 表均无此名),类体尾部常量(ISINSTANCE_CLASS_MAX 是首个触发 @@ -351,10 +330,8 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): if cdef_ty_l is not None: field_names_buf[field_count] = sizet(tgt.id) field_types_buf[field_count] = sizet(cdef_ty_l) - if aa.value is not None: - field_defaults_buf[field_count] = sizet(aa.value) - else: - field_defaults_buf[field_count] = 0 + if aa.value is not None: field_defaults_buf[field_count] = sizet(aa.value) + else: field_defaults_buf[field_count] = 0 field_count += 1 continue @@ -378,15 +355,13 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): # `typedef 不透明结构体 = void`);`void*` 已在上游归并为 i8*,不会命中。 # 放任会按 LLVM void 建字段槽 ⇒ 结构体布局非法(拖到 llc 才暴露), # 故此处编译期 fail-fast。 - 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"字段 '{tgt.id}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError") # 单参 t.CArray[elem] + 列表字面量 → 静态数组 [N x elem] # (与局部 AnnAssign 路径一致,对齐 TPC ParseListAnnotation 语义): # 否则字段保持 Ptr(elem)(如 t.CArray[str] → i8**), # for x in self.field 会误走指针迭代(元素非整数 → null 终止符 # 检查失败报错)。推断为静态数组后走数组迭代(按长度 N)。 - if field_ty is not None: - field_ty = self.Gen.AssignGen._infer_static_array_ty_from_literal(pool, aa.annotation, aa.value, field_ty) + if field_ty is not None: field_ty = self.Gen.AssignGen._infer_static_array_ty_from_literal(pool, aa.annotation, aa.value, field_ty) if field_ty is None: # BUG 5 方案1修改点1:消除 i32 静默回退 # Phase A-pre(declare_only=1):依赖的类可能尚未注册,延迟到下一遍 @@ -406,22 +381,19 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): if sub_g is not None and sub_g.value is not None: if sub_g.value.kind() == ast.ASTKind.Attribute: svg_at: ast.Attribute* = ast.Attribute*(sub_g.value) - if svg_at.attr is not None and string.strcmp(svg_at.attr, "CArray") == 0: - is_carray_sub_g = 1 + if svg_at.attr is not None and string.strcmp(svg_at.attr, "CArray") == 0: is_carray_sub_g = 1 elif sub_g.value.kind() == ast.ASTKind.Name: svg_nm: ast.Name* = ast.Name*(sub_g.value) if svg_nm.id is not None and (string.strcmp(svg_nm.id, "CArray") == 0 or string.strcmp(svg_nm.id, "rawarray") == 0 or string.strcmp(svg_nm.id, "array") == 0): is_carray_sub_g = 1 - if is_carray_sub_g == 0: - is_generic_sub = 1 + if is_carray_sub_g == 0: is_generic_sub = 1 if is_generic_sub != 0: # 泛型未特化:回退为 Ptr(i8),依赖 AnnotClassName 做后续类型恢复 field_ty = mlirlite.Ptr(pool, mlirlite.Int8(pool)) else: # Phase A-pre(declare_only=1):依赖的类可能尚未注册, # 静默 return 0 让多遍收敛机制生效(下一遍依赖类已注册即可成功) - if trans._declare_only == 1: - return 0 + if trans._declare_only == 1: return 0 # Phase A(declare_only=0,Phase2.vp L573 多遍):依赖模块按 # 文件序可能晚于本模块翻译(如 TypeGenMixin.vp G < HandlesType.vp # H,TraceFrames 注解的 HandlesType.TraceFrame 未注册)→ 不在本遍 @@ -436,10 +408,8 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): field_names_buf[field_count] = diag_name_val field_types_buf[field_count] = sizet(field_ty) # 存储默认值 AST 指针(None=无默认值) - if aa.value is not None: - field_defaults_buf[field_count] = sizet(aa.value) - else: - field_defaults_buf[field_count] = 0 + if aa.value is not None: field_defaults_buf[field_count] = sizet(aa.value) + else: field_defaults_buf[field_count] = 0 # 提取原始类型注解的类名(联合类型简化为 Ptr(i8) 时回退查找结构体) # BUG 1 方案3:传 pool 使泛型 Subscript 返回 mangled name(如 "list[ast.AST*]") if aa.annotation is not None: @@ -447,27 +417,20 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): if annot_cn is not None: diag_cn_val: sizet = sizet(annot_cn) field_annot_buf[field_count] = diag_cn_val - else: - field_annot_buf[field_count] = 0 + else: field_annot_buf[field_count] = 0 # t.CVolatile 存储类标记 → 该字段经对象访问的 load/store 带 # volatile(如 Spinlock.locked: t.CVolatile | t.CInt)。 - if self.Gen.TypeGenErr.has_decorator_marker(aa.annotation, "CVolatile", 0) != 0: - field_volatile_buf[field_count] = 1 - else: - field_volatile_buf[field_count] = 0 + if self.Gen.TypeGenErr.has_decorator_marker(aa.annotation, "CVolatile", 0) != 0: field_volatile_buf[field_count] = 1 + else: field_volatile_buf[field_count] = 0 # rawptr[t.CVolatile | T](volatile 指针指向物,等价 C 的 # volatile T*)→ 经该字段解引用(self.ptr[i]/self.ptr.field) # 的 load/store 带 volatile。 - if self.Gen.TypeGenErr.has_pointee_volatile_marker(aa.annotation) != 0: - field_pointee_volatile_buf[field_count] = 1 - else: - field_pointee_volatile_buf[field_count] = 0 + if self.Gen.TypeGenErr.has_pointee_volatile_marker(aa.annotation) != 0: field_pointee_volatile_buf[field_count] = 1 + else: field_pointee_volatile_buf[field_count] = 0 # const 对象字段(注解含 t.CConst 且字段类型非指针)→ 经对象给该 # 字段赋值 fail-fast。判据与 TPC 的 Gen.field_const_flags 一致。 - if self.Gen.TypeGenErr.is_const_object_marker(aa.annotation, field_ty) != 0: - field_const_buf[field_count] = 1 - else: - field_const_buf[field_count] = 0 + if self.Gen.TypeGenErr.is_const_object_marker(aa.annotation, field_ty) != 0: field_const_buf[field_count] = 1 + else: field_const_buf[field_count] = 0 else: field_annot_buf[field_count] = 0 field_volatile_buf[field_count] = 0 @@ -479,8 +442,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): # PhaseA 预注册时,父类可能尚未注册(字母序单遍扫描), # 导致子类无法继承父类字段 → field_count==0。 # 静默返回,Phase2.py 的多遍 PhaseA-pre 会在后续遍中重试。 - if trans._declare_only == 1 and parent_name is not None: - return 0 + if trans._declare_only == 1 and parent_name is not None: return 0 # 无字段类(接口/标记类):不能整体跳过——类可能只有方法 # (如多继承中的 ShapeM/Vec2Extra),需注册类并翻译方法。 # 空 struct 在 LLVM 中合法({});@t.CVTable 类由下方补 vtable 指针字段。 @@ -508,21 +470,17 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): for fi in range(field_count): fty_addr: sizet = field_types_buf[fi] - if fty_addr == 0: - continue + if fty_addr == 0: continue fty: mlirlite.LLVMType* = (mlirlite.LLVMType*)(fty_addr) # 创建 ParamNode pnode: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__()) - if pnode is None: - continue + if pnode is None: continue string.memset(pnode, 0, mlirlite.ParamNode.__sizeof__()) pnode.Ty = fty - if first_node is None: - first_node = pnode - if prev_node is not None: - prev_node.Next = pnode + if first_node is None: first_node = pnode + if prev_node is not None: prev_node.Next = pnode prev_node = pnode # 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName" @@ -584,15 +542,13 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): # (LLVM packed struct,无字段填充,GEP 按 packed 布局计算偏移)。 # idt/gdt/elf/fat32 等二进制格式结构体依赖它读写硬件/磁盘布局。 is_packed_cd: int = self.Gen.ClassGenBase._class_has_tattr(cd.decorator_list, "packed") - if is_packed_cd != 0: - mlirlite.module_set_named_type_packed(trans.Module, pool, struct_ty, 1) + if is_packed_cd != 0: mlirlite.module_set_named_type_packed(trans.Module, pool, struct_ty, 1) # 扫描字段类型:跨模块结构体引用在当前模块补声明 # 例如 list[int].__pool__ 引用 memhub.MemManager,需要在当前模块添加 %"sha1.MemManager" = type opaque for fi in range(field_count): fty_addr_op: sizet = field_types_buf[fi] - if fty_addr_op == 0: - continue + if fty_addr_op == 0: continue fty_op: mlirlite.LLVMType* = (mlirlite.LLVMType*)(fty_addr_op) if self.Gen.ExprGenBase.is_ptr_type(fty_op) != 0: # 指针字段:指向物只需 opaque 声明(GEP 不按字段下标解引用指向物本体) @@ -617,26 +573,21 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): # 前向声明占位:字段体已原位写入 existing.Ty,登记条目沿用 existing # (不新建条目/Ty,否则已发出的 Ptr(占位.Ty) 引用会指向旧空对象)。 entry = existing - else: - entry = self.Gen.StructGen.register_struct(pool, class_name, struct_ty, trans.ModuleSha1) + else: entry = self.Gen.StructGen.register_struct(pool, class_name, struct_ty, trans.ModuleSha1) if entry is None: VLogger.error(f"failed to register {class_name}", "CLASS") return 0 # B5:记录 packed 标记到 StructEntry(供 __sizeof__/字段布局等派生查询) - if is_packed_cd != 0: - entry.IsPacked = 1 + if is_packed_cd != 0: entry.IsPacked = 1 # B5:记录 aligned 对齐值(@c.Attribute(t.attr.aligned(N)),如 fpu_context 16 对齐), # 供全局变量/局部 alloca 生成时施加对齐。 align_cd: int = self.Gen.ClassGenBase._class_aligned_value(cd.decorator_list) - if align_cd > 0: - entry.Align = align_cd + if align_cd > 0: entry.Align = align_cd # 标记 VTable 状态(直接用 entry,规避跨模块同名 find_struct 找错) - if has_vtable == 1: - entry.HasVTable = 1 - if is_novtable_deco == 1: - entry.IsNoVTable = 1 + if has_vtable == 1: entry.HasVTable = 1 + if is_novtable_deco == 1: entry.IsNoVTable = 1 if parent_name is not None: # 1b 阶段父类名是 pool 字符串,reset 后悬空;_translate_oop_methods/ # _detect_vtable_status 会在后续文件 find_struct(ParentName) strcmp 解引用 @@ -647,11 +598,9 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): if pn_buf is not None: string.strcpy(pn_buf, parent_name) entry.ParentName = pn_buf - else: - entry.ParentName = parent_name + else: entry.ParentName = parent_name # 多继承:设置父类数组(供 MRO/字段/vtable 查询,stdlib 深拷贝跨文件存活) - if parents_count > 0 and parents_buf is not None: - self.Gen.StructGen.set_parent_names(pool, class_name, parents_buf, parents_count) + if parents_count > 0 and parents_buf is not None: self.Gen.StructGen.set_parent_names(pool, class_name, parents_buf, parents_count) # 添加字段信息 # 如果有虚表,先添加 __vtable__ 字段占位(索引 0),用户字段从索引 1 开始 @@ -661,41 +610,34 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): for fi in range(field_count): fname_addr: sizet = field_names_buf[fi] - if fname_addr == 0: - continue + if fname_addr == 0: continue fname: str = rawptr(fname_addr) fty_addr2: sizet = field_types_buf[fi] - if fty_addr2 == 0: - continue + if fty_addr2 == 0: continue fty2: mlirlite.LLVMType* = (mlirlite.LLVMType*)(fty_addr2) # 恢复默认值 AST 指针 fdef_addr: sizet = field_defaults_buf[fi] fdef: ast.AST* = None - if fdef_addr != 0: - fdef = (ast.AST*)(fdef_addr) + if fdef_addr != 0: fdef = (ast.AST*)(fdef_addr) # 恢复注解类名指针 fannot_addr: sizet = field_annot_buf[fi] fannot: str = None - if fannot_addr != 0: - fannot = str(fannot_addr) + if fannot_addr != 0: fannot = str(fannot_addr) if fname is not None and fty2 is not None: fidx_add: int = self.Gen.StructGen.add_field(pool, entry, fname, fty2, fdef, fannot) # t.CVolatile 字段标记(field_volatile_buf[fi] 与 add_field 顺序一一对应) if fidx_add >= 0 and field_volatile_buf[fi] != 0: fe_vol: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(entry, fidx_add) - if fe_vol is not None: - fe_vol.IsVolatile = 1 + if fe_vol is not None: fe_vol.IsVolatile = 1 # rawptr[t.CVolatile | T] 字段标记(field_pointee_volatile_buf[fi] 与 # add_field 顺序一一对应):经该字段解引用时 load/store 带 volatile。 if fidx_add >= 0 and field_pointee_volatile_buf[fi] != 0: fe_pv: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(entry, fidx_add) - if fe_pv is not None: - fe_pv.PointeeVolatile = 1 + if fe_pv is not None: fe_pv.PointeeVolatile = 1 # const 对象字段标记(field_const_buf[fi] 与 add_field 顺序一一对应) if fidx_add >= 0 and field_const_buf[fi] != 0: fe_c: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(entry, fidx_add) - if fe_c is not None: - fe_c.IsConst = 1 + if fe_c is not None: fe_c.IsConst = 1 # Phase 1a 声明模式:只注册 struct + 设置 OOP 标志,不翻译方法体 if trans._declare_only == 1: @@ -731,36 +673,28 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): def _translate_nested_classdefs(self, trans: HT.Translator*, cd: ast.ClassDef*) -> None: """把本类体内的嵌套 ClassDef 逐个按 `{外类}_{内类}` 递归翻译""" - if trans is None or cd is None or cd.name is None: - return + if trans is None or cd is None or cd.name is None: return children: list[ast.AST*]* = cd.children - if children is None: - return + if children is None: return cn: sizet = len(children) ci: sizet = 0 while ci < cn: child_ast: ast.AST* = children.get(ci) ci += 1 - if child_ast is None: - continue - if child_ast.kind() != ast.ASTKind.ClassDef: - continue + if child_ast is None: continue + if child_ast.kind() != ast.ASTKind.ClassDef: continue child: ast.ClassDef* = ast.ClassDef*(child_ast) - if child is None or child.name is None: - continue + if child is None or child.name is None: continue # 扁平名 `{外类}_{内类}`(优先 PermPool:名字要跨 Phase 存活; # PermPool 缺失时退回本遍池,行为与旧路径一致) flat_pool: memhub.MemBuddy* = CompilerFactory.factory.PermPool - if flat_pool is None: - flat_pool = trans.Pool - if flat_pool is None: - continue + if flat_pool is None: flat_pool = trans.Pool + if flat_pool is None: continue outer_len: sizet = string.strlen(cd.name) inner_len: sizet = string.strlen(child.name) flat_len: sizet = outer_len + 1 + inner_len flat_buf: str = flat_pool.alloc(flat_len + 1) - if flat_buf is None: - continue + if flat_buf is None: continue viperlib.snprintf(flat_buf, flat_len + 1, "%s_%s", cd.name, child.name) # 改写子节点名 → 递归(内部一律以扁平名注册/发射) old_name: str = child.name diff --git a/App/lib/core/Gen/Class/ClassGenEnum.vp b/App/lib/core/Gen/Class/ClassGenEnum.vp index de0cd6b..0a024b6 100644 --- a/App/lib/core/Gen/Class/ClassGenEnum.vp +++ b/App/lib/core/Gen/Class/ClassGenEnum.vp @@ -34,8 +34,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): imported_modules: str, from_imports: str) -> mlirlite.LLVMType*: """解析枚举成员的类型注解为 LLVM 整数类型""" - if ann_node is None: - return mlirlite.Int32(pool) + if ann_node is None: return mlirlite.Int32(pool) k: int = ann_node.kind() @@ -47,14 +46,12 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): self.Gen.TypeGenErr.fatal_error(ann_node, "枚举成员类型注解 Attribute 缺失成员名", "TypeError") return mlirlite.Int32(pool) # 不可达(fatal_error 已退出) # t.State → 默认 i32 - if string.strcmp(at.attr, "State") == 0: - return mlirlite.Int32(pool) + if string.strcmp(at.attr, "State") == 0: return mlirlite.Int32(pool) # [枚举侧 bool 口径] `t.CBool` 与裸名 `bool` 同宽(8 位),否则同一 # 枚举成员两种写法会分裂出 i1 / i8 两种宽度。全局 `t.CBool` = i1 # (map_t_type L1447-1449)保持不变,仅在**枚举成员注解**这一处按 # 8 位物化(枚举存储须可按字节寻址;TPC 侧 t.CBool.Size = 8 同口径)。 - if string.strcmp(at.attr, "CBool") == 0: - return mlirlite.Int8(pool) + if string.strcmp(at.attr, "CBool") == 0: return mlirlite.Int8(pool) # 其他 t.CXxx 类型:统一口径(CTypedef 动态表优先,miss 回退 map_t_type) ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_typedef_or_map(pool, at.attr, imported_modules, from_imports) if ty is not None: return ty @@ -69,17 +66,14 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # [S4 fail-fast] Name 缺失标识符(AST 损坏),不再静默回退 i32 self.Gen.TypeGenErr.fatal_error(ann_node, "枚举成员类型注解 Name 缺失标识符", "TypeError") return mlirlite.Int32(pool) # 不可达(fatal_error 已退出) - if string.strcmp(nm.id, "State") == 0: - return mlirlite.Int32(pool) + if string.strcmp(nm.id, "State") == 0: return mlirlite.Int32(pool) # 内建裸名整数类型(与 resolve_annotation_type 的 Name 分支同口径, # TypeGenResolve.vp L2189-2203):枚举成员是整数常量,`int` / `char` / # `bool` 裸名直通。其余裸名(含 str/bytes 指针形态与未知名)仍走 # typedef / builtins 表,miss 即下方 fail-fast(不静默当 int); # 指针与非整数成员的统一拦截见 _translate_enum_def。 - if string.strcmp(nm.id, "int") == 0: - return mlirlite.Int32(pool) - if string.strcmp(nm.id, "char") == 0: - return mlirlite.Int8(pool) + if string.strcmp(nm.id, "int") == 0: return mlirlite.Int32(pool) + if string.strcmp(nm.id, "char") == 0: return mlirlite.Int8(pool) if string.strcmp(nm.id, "bool") == 0: # [枚举侧 bool 口径] 枚举存储必须是可按字节寻址的整数类型, # i1 不能作为独立枚举宽度 ⇒ 枚举成员注解的 bool 一律 8 位。 @@ -88,8 +82,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # 两侧一致:TPC 侧枚举成员 bool 经 t.CBool.Size 亦为 8。 return mlirlite.Int8(pool) ty2: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_typedef_or_map(pool, nm.id, imported_modules, from_imports) - if ty2 is not None: - return ty2 + if ty2 is not None: return ty2 # [S4 fail-fast] 有注解但解析失败 → 不再静默回退 i32 self.Gen.TypeGenErr.fatal_error(ann_node, f"枚举成员类型注解解析失败: {nm.id}", "NameError") return mlirlite.Int32(pool) # 不可达(fatal_error 已退出) @@ -101,15 +94,12 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): left_ty: mlirlite.LLVMType* = self._resolve_enum_member_type(pool, bop.left, imported_modules, from_imports) # 跳过 t.State(i32 默认),优先返回具体类型 left_bits: int = self.Gen.TypeGenErr.get_llvm_type_bits(left_ty) - if left_bits != 0 and not self._is_state_annotation(bop.left): - return left_ty + if left_bits != 0 and not self._is_state_annotation(bop.left): return left_ty right_ty: mlirlite.LLVMType* = self._resolve_enum_member_type(pool, bop.right, imported_modules, from_imports) - if right_ty is not None and not self._is_state_annotation(bop.right): - return right_ty + if right_ty is not None and not self._is_state_annotation(bop.right): return right_ty # 两边都是 State 或无法确定,返回较宽的 right_bits: int = self.Gen.TypeGenErr.get_llvm_type_bits(right_ty) - if left_bits >= right_bits: - return left_ty + if left_bits >= right_bits: return left_ty return right_ty # fail-fast:BinOp 但非 BitOr(未知联合运算),不再静默回退 i32 self.Gen.TypeGenErr.fatal_error(ann_node, f"枚举成员类型注解解析失败: {self.Gen.TypeGenResolve.annotation_to_str(ann_node)}", "TypeError") @@ -120,18 +110,15 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): return mlirlite.Int32(pool) # 不可达(fatal_error 已退出) def _is_state_annotation(self, node: ast.AST*) -> int: """检查注解节点是否为 t.State,返回 1=是 / 0=否""" - if node is None: - return 0 + if node is None: return 0 k: int = node.kind() if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(node) - if at.attr is not None and string.strcmp(at.attr, "State") == 0: - return 1 + if at.attr is not None and string.strcmp(at.attr, "State") == 0: return 1 return 0 if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) - if nm.id is not None and string.strcmp(nm.id, "State") == 0: - return 1 + if nm.id is not None and string.strcmp(nm.id, "State") == 0: return 1 return 0 return 0 def _enum_annotation_name_is_ptr(self, node: ast.AST*) -> int: @@ -142,45 +129,31 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): (map_t_type L1421-1424 均为 i8*)、rawptr(内建指针,_lookup_builtins_typedef L921-923 恒返回 t.CPtr)、str / bytes(resolve_annotation_type L2190-2200 → i8*)。 """ - if node is None: - return 0 + if node is None: return 0 k: int = node.kind() if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(node) if at.attr is not None: - if string.strcmp(at.attr, "CPtr") == 0: - return 1 - if string.strcmp(at.attr, "CNeedPtr") == 0: - return 1 - if string.strcmp(at.attr, "CAutoPtr") == 0: - return 1 - if string.strcmp(at.attr, "rawptr") == 0: - return 1 - if string.strcmp(at.attr, "str") == 0: - return 1 - if string.strcmp(at.attr, "bytes") == 0: - return 1 + if string.strcmp(at.attr, "CPtr") == 0: return 1 + if string.strcmp(at.attr, "CNeedPtr") == 0: return 1 + if string.strcmp(at.attr, "CAutoPtr") == 0: return 1 + if string.strcmp(at.attr, "rawptr") == 0: return 1 + if string.strcmp(at.attr, "str") == 0: return 1 + if string.strcmp(at.attr, "bytes") == 0: return 1 return 0 if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) if nm.id is not None: - if string.strcmp(nm.id, "CPtr") == 0: - return 1 - if string.strcmp(nm.id, "CNeedPtr") == 0: - return 1 - if string.strcmp(nm.id, "CAutoPtr") == 0: - return 1 - if string.strcmp(nm.id, "rawptr") == 0: - return 1 - if string.strcmp(nm.id, "str") == 0: - return 1 - if string.strcmp(nm.id, "bytes") == 0: - return 1 + if string.strcmp(nm.id, "CPtr") == 0: return 1 + if string.strcmp(nm.id, "CNeedPtr") == 0: return 1 + if string.strcmp(nm.id, "CAutoPtr") == 0: return 1 + if string.strcmp(nm.id, "rawptr") == 0: return 1 + if string.strcmp(nm.id, "str") == 0: return 1 + if string.strcmp(nm.id, "bytes") == 0: return 1 return 0 if k == ast.ASTKind.Subscript: sub: ast.Subscript* = ast.Subscript*(node) - if sub.value is not None: - return self._enum_annotation_name_is_ptr(sub.value) + if sub.value is not None: return self._enum_annotation_name_is_ptr(sub.value) return 0 return 0 def _enum_member_annotation_is_ptr(self, ann_node: ast.AST*) -> int: @@ -190,25 +163,20 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): BinOp 分支会"优先返回具体整数类型"(源码 L94-105)——只看解析结果会把 含指针的联合静默当整数,故在解析前按注解树拦。 """ - if ann_node is None: - return 0 + if ann_node is None: return 0 if ann_node.kind() == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(ann_node) - if bop.op != ast.OpKind.BitOr: - return 0 - if self._enum_member_annotation_is_ptr(bop.left) == 1: - return 1 + if bop.op != ast.OpKind.BitOr: return 0 + if self._enum_member_annotation_is_ptr(bop.left) == 1: return 1 return self._enum_member_annotation_is_ptr(bop.right) return self._enum_annotation_name_is_ptr(ann_node) def _extract_int_value(self, node: ast.AST*) -> int64: """从 AST 节点提取整数值,失败返回 0""" - if node is None: - return 0 + if node is None: return 0 k: int = node.kind() if k == ast.ASTKind.Constant: cn: ast.Constant* = ast.Constant*(node) - if cn.const_kind == ast.CONST_INT: - return cn.int_val + if cn.const_kind == ast.CONST_INT: return cn.int_val return 0 if k == ast.ASTKind.UnaryOp: uo: ast.UnaryOp* = ast.UnaryOp*(node) @@ -231,11 +199,9 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # ======================================================== def _enum_elts_visible_names(self, elts: list[ast.AST*]*) -> int: """元素表里的"可见名"计数(Tuple/List 共用)。""" - if elts is None: - return 0 + if elts is None: return 0 n: int = 0 - for i in range(len(elts)): - n += self._enum_target_visible_names(elts.get(i)) + for i in range(len(elts)): n += self._enum_target_visible_names(elts.get(i)) return n def _enum_target_visible_names(self, node: ast.AST*) -> int: """成员名位置的"可见名"计数(Name / Tuple / List 逐项、Starred 解引用递归)。 @@ -243,11 +209,9 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): 与 TPC 侧 SymbolUtils._EnumMemberNameNodes 同口径:把"注册器不认的成员 写法"(逗号组 Tuple、元组目标、Starred)里的成员名照样数进来。 """ - if node is None: - return 0 + if node is None: return 0 k: int = node.kind() - if k == ast.ASTKind.Name: - return 1 + if k == ast.ASTKind.Name: return 1 if k == ast.ASTKind.Tuple: tup: ast.Tuple* = ast.Tuple*(node) return self._enum_elts_visible_names(tup.elts) @@ -264,19 +228,16 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): Assign 的每个 target / AnnAssign 的 target / Expr 语句的表达式; 不含成员名的语句(docstring / pass / 方法定义 / 嵌套类)计 0,不误报。 """ - if children is None: - return 0 + if children is None: return 0 n: int = 0 for ci in range(len(children)): stmt: ast.AST* = children.get(ci) - if stmt is None: - continue + if stmt is None: continue sk: int = stmt.kind() if sk == ast.ASTKind.Assign: ag: ast.Assign* = ast.Assign*(stmt) if ag.targets is not None: - for ti in range(len(ag.targets)): - n += self._enum_target_visible_names(ag.targets.get(ti)) + for ti in range(len(ag.targets)): n += self._enum_target_visible_names(ag.targets.get(ti)) elif sk == ast.ASTKind.AnnAssign: aa: ast.AnnAssign* = ast.AnnAssign*(stmt) n += self._enum_target_visible_names(aa.target) @@ -286,34 +247,28 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): return n def _enum_first_unregistered_node(self, children: list[ast.AST*]*) -> ast.AST*: """第一个"含可见成员名但注册器不认"的语句(供 fail-fast 定位真行号);无则 None。""" - if children is None: - return None + if children is None: return None for ci in range(len(children)): stmt: ast.AST* = children.get(ci) - if stmt is None: - continue + if stmt is None: continue sk: int = stmt.kind() if sk == ast.ASTKind.Expr: ex: rawptr[ast.Expr] = rawptr[ast.Expr](stmt) - if self._enum_target_visible_names(ex.value) > 0: - return stmt + if self._enum_target_visible_names(ex.value) > 0: return stmt elif sk == ast.ASTKind.AnnAssign: aa: ast.AnnAssign* = ast.AnnAssign*(stmt) - if aa.target is not None and aa.target.kind() != ast.ASTKind.Name and self._enum_target_visible_names(aa.target) > 0: - return stmt + if aa.target is not None and aa.target.kind() != ast.ASTKind.Name and self._enum_target_visible_names(aa.target) > 0: return stmt elif sk == ast.ASTKind.Assign: ag: ast.Assign* = ast.Assign*(stmt) if ag.targets is not None: for ti in range(len(ag.targets)): tgt: ast.AST* = ag.targets.get(ti) - if tgt is not None and tgt.kind() != ast.ASTKind.Name and self._enum_target_visible_names(tgt) > 0: - return stmt + if tgt is not None and tgt.kind() != ast.ASTKind.Name and self._enum_target_visible_names(tgt) > 0: return stmt return None def _translate_enum_def(self, trans: HT.Translator*, cd: ast.ClassDef*) -> int: """翻译枚举类定义,返回 0""" - if cd is None or cd.name is None or trans is None: - return 0 + if cd is None or cd.name is None or trans is None: return 0 pool: memhub.MemBuddy* = trans.Pool class_name: str = cd.name @@ -334,8 +289,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): member_names_buf: sizet* = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL) member_types_buf: sizet* = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL) member_values_buf: int64* = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL) - if member_names_buf is None or member_types_buf is None or member_values_buf is None: - return 0 + if member_names_buf is None or member_types_buf is None or member_values_buf is None: return 0 string.memset(member_names_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL) string.memset(member_types_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL) string.memset(member_values_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL) @@ -345,21 +299,17 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): for ci in range(cn): stmt: ast.AST* = children.get(ci) - if stmt is None: - continue + if stmt is None: continue sk: int = stmt.kind() if sk == ast.ASTKind.AnnAssign: aa: ast.AnnAssign* = ast.AnnAssign*(stmt) - if aa is None or aa.target is None: - continue + if aa is None or aa.target is None: continue # 获取成员名 - if aa.target.kind() != ast.ASTKind.Name: - continue + if aa.target.kind() != ast.ASTKind.Name: continue tgt: ast.Name* = ast.Name*(aa.target) - if tgt.id is None: - continue + if tgt.id is None: continue # [枚举规格 fail-fast] 成员不允许指针类型:t.CPtr / CNeedPtr / # CAutoPtr / rawptr[...] / str / bytes,以及**联合类型里夹带指针** @@ -387,8 +337,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): if aa.value is not None: cur_val = self._extract_int_value(aa.value) has_value = 1 - else: - cur_val = next_val + else: cur_val = next_val # 下一个自动值 next_val = cur_val + 1 @@ -407,32 +356,26 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # HandlesClassDef._RegisterEnumMembers 的逐 target 口径一致;此前 # 只取 targets[0] 会让后续 target 静默漏成员)。 ag: ast.Assign* = ast.Assign*(stmt) - if ag is None or ag.targets is None: - continue + if ag is None or ag.targets is None: continue tgts: list[ast.AST*]* = ag.targets tn: sizet = len(tgts) - if tn == 0: - continue + if tn == 0: continue # Assign 无类型注释,默认使用 i32 member_ty_a: mlirlite.LLVMType* = mlirlite.Int32(pool) # 解析成员值(同一语句的所有 target 共享该值,next_val 只推进一次) cur_val_a: int64 = 0 - if ag.value is not None: - cur_val_a = self._extract_int_value(ag.value) - else: - cur_val_a = next_val + if ag.value is not None: cur_val_a = self._extract_int_value(ag.value) + else: cur_val_a = next_val next_val = cur_val_a + 1 # 存储(逐 target;非 Name target 由注册处兜底判据拦住) for ti in range(tn): t0: ast.AST* = tgts.get(ti) - if t0 is None or t0.kind() != ast.ASTKind.Name: - continue + if t0 is None or t0.kind() != ast.ASTKind.Name: continue tgt_a: ast.Name* = ast.Name*(t0) - if tgt_a.id is None: - continue + if tgt_a.id is None: continue if member_count < ENUM_MEMBER_MAX_LOCAL: member_names_buf[member_count] = sizet(tgt_a.id) member_types_buf[member_count] = sizet(member_ty_a) @@ -451,8 +394,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): diff_count: int = visible_count - member_count bad: ast.AST* = self._enum_first_unregistered_node(children) bad_desc: str = "(无法定位到具体语句,请检查枚举体)" - if bad is not None: - bad_desc = bad.type_name() + 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} 个," @@ -476,8 +418,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): max_bits: int = 0 for mi in range(member_count): ty_addr: sizet = member_types_buf[mi] - if ty_addr == 0: - continue + if ty_addr == 0: continue mty: mlirlite.LLVMType* = (mlirlite.LLVMType*)(ty_addr) bits: int = self.Gen.TypeGenErr.get_llvm_type_bits(mty) if bits > max_bits: @@ -493,24 +434,20 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # 添加成员 for mi in range(member_count): fname_addr: sizet = member_names_buf[mi] - if fname_addr == 0: - continue + if fname_addr == 0: continue mname: str = rawptr(fname_addr) fty_addr2: sizet = member_types_buf[mi] - if fty_addr2 == 0: - continue + if fty_addr2 == 0: continue mty2: mlirlite.LLVMType* = (mlirlite.LLVMType*)(fty_addr2) mval: int64 = member_values_buf[mi] - if mname is not None and mty2 is not None: - self.Gen.StmtGenDecl.add_enum_member(pool, entry, mname, mval, mty2) + if mname is not None and mty2 is not None: self.Gen.StmtGenDecl.add_enum_member(pool, entry, mname, mval, mty2) VLogger.info(f"registered {class_name} with {member_count} members, base_bits={max_bits}", "ENUM") return 0 def _get_type_size(self, ty: mlirlite.LLVMType*) -> int: """计算 LLVM 类型的字节大小(含对齐 padding)""" - if ty is None: - return 0 + if ty is None: return 0 match ty: case mlirlite.LLVMType.Int(bits): return (bits + 7) // 8 @@ -540,49 +477,37 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # 对齐当前偏移到字段对齐边界(packed 不插填充) if is_packed == 0 and falign > 0: rem: int = total % falign - if rem != 0: - total += falign - rem + if rem != 0: total += falign - rem total += fsize - if is_packed == 0 and falign > max_align: - max_align = falign + if is_packed == 0 and falign > max_align: max_align = falign cur = cur.Next i += 1 # packed 无尾部对齐;非 packed 总大小对齐到最大字段对齐的倍数 - if is_packed != 0: - return total + if is_packed != 0: return total rem2: int = total % max_align - if rem2 != 0: - total += max_align - rem2 + if rem2 != 0: total += max_align - rem2 return total case _: return 8 def _get_type_align(self, ty: mlirlite.LLVMType*) -> int: """返回类型的自然对齐(字节)""" - if ty is None: - return 1 + if ty is None: return 1 match ty: case mlirlite.LLVMType.Int(bits): - if bits <= 8: - return 1 - elif bits <= 16: - return 2 - elif bits <= 32: - return 4 - else: - return 8 + if bits <= 8: return 1 + elif bits <= 16: return 2 + elif bits <= 32: return 4 + else: return 8 case mlirlite.LLVMType.Float(bits): - if bits <= 32: - return 4 - else: - return 8 + if bits <= 32: return 4 + else: return 8 case mlirlite.LLVMType.Ptr(pointee): return 8 case mlirlite.LLVMType.Array(elem_ty, count): return self._get_type_align(elem_ty) case mlirlite.LLVMType.Struct(fields, fcount, name): # packed 结构体整体按字节对齐(对齐 1,无填充) - if self.Gen.StructGen.struct_type_is_packed(ty) != 0: - return 1 + if self.Gen.StructGen.struct_type_is_packed(ty) != 0: return 1 # 结构体的对齐 = 最大字段对齐 max_align: int = 1 cur: rawptr[mlirlite.ParamNode] = fields @@ -591,8 +516,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): if cur.Ty is not None: fty: mlirlite.LLVMType* = (mlirlite.LLVMType*)(cur.Ty) fa: int = self._get_type_align(fty) - if fa > max_align: - max_align = fa + if fa > max_align: max_align = fa cur = cur.Next i += 1 return max_align @@ -613,8 +537,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): existing: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(class_name, trans.ModuleSha1) if existing is not None: # Phase B: 将已存在的命名结构体注册到当前模块 - if existing.Ty is not None: - mlirlite.module_add_named_type(trans.Module, pool, existing.Ty) + if existing.Ty is not None: mlirlite.module_add_named_type(trans.Module, pool, existing.Ty) # SHA1 已在 register_struct 时设置,无需再补 return 0 @@ -628,8 +551,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # 临时数组存储字段信息 field_names_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX) field_types_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX) - if field_names_buf is None or field_types_buf is None: - return 0 + if field_names_buf is None or field_types_buf is None: return 0 string.memset(field_names_buf, 0, 8 * GenTypes.FIELD_MAX) string.memset(field_types_buf, 0, 8 * GenTypes.FIELD_MAX) @@ -663,8 +585,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # 计算字段大小,更新 max_size fsize: int = self._get_type_size(field_ty) - if fsize > max_size: - max_size = fsize + if fsize > max_size: max_size = fsize # 存储到数组 if field_count < GenTypes.FIELD_MAX: @@ -676,8 +597,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): VLogger.warning(f"{class_name} has no fields", "UNION") return 0 - if max_size < 1: - max_size = 1 + if max_size < 1: max_size = 1 # 创建联合体的 LLVM 类型: Struct([Array(Int8, max_size)]) # 即 { [max_size x i8] } @@ -686,8 +606,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # 构建 ParamNode 链表(单字段:字节数组) pnode: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__()) - if pnode is None: - return 0 + if pnode is None: return 0 string.memset(pnode, 0, mlirlite.ParamNode.__sizeof__()) pnode.Ty = array_ty @@ -711,8 +630,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # (LoopTest _scan_type_for_cross_module_refs 0xFFFF 根因)。 if trans._declare_only == 0 or self.Gen.StructGen.get_stdlib_alloc() != 0: union_copy: mlirlite.LLVMType* = mlirlite.DeepCopyType(CompilerFactory.factory.PermPool, union_ty) - if union_copy is not None: - union_ty = union_copy + if union_copy is not None: union_ty = union_copy # 注册命名结构体到模块 mlirlite.module_add_named_type(trans.Module, pool, union_ty) @@ -732,44 +650,35 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # 添加字段信息(所有字段 Index=0,因为共享偏移 0) for fi in range(field_count): fname_addr: sizet = field_names_buf[fi] - if fname_addr == 0: - continue + if fname_addr == 0: continue fname: str = rawptr(fname_addr) fty_addr2: sizet = field_types_buf[fi] - if fty_addr2 == 0: - continue + if fty_addr2 == 0: continue fty2: mlirlite.LLVMType* = (mlirlite.LLVMType*)(fty_addr2) - if fname is not None and fty2 is not None: - self.Gen.StructGen.add_field(pool, entry, fname, fty2, None, None) + if fname is not None and fty2 is not None: self.Gen.StructGen.add_field(pool, entry, fname, fty2, None, None) VLogger.info(f"registered {class_name} with {field_count} fields, max_size={max_size}", "UNION") return 0 def _get_annotation_field_size(self, pool: memhub.MemBuddy*, annotation: ast.AST*) -> int: """计算注解类型的字节大小,用于 REnum 布局计算""" - if annotation is None: - return 8 + if annotation is None: return 8 k: int = annotation.kind() # 联合类型 A | B → 指针大小 8 - if k == ast.ASTKind.BinOp: - return 8 + if k == ast.ASTKind.BinOp: return 8 # Name(id) 或 Attribute(attr) → 解析类型名 type_name: str = None if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(annotation) - if nm is not None: - type_name = nm.id + if nm is not None: type_name = nm.id elif k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(annotation) - if at is not None: - type_name = at.attr - if type_name is None: - return 8 + if at is not None: type_name = at.attr + if type_name is None: return 8 # [阶段3] 统一尺寸口径:库 typedef(BYTE/DWORD 等)先经正常库分析解析, # miss 才走下方硬编码尺寸表(t/c 核心原语)。 dyn_sz: int = self.Gen.TypeGenResolve.get_type_size_bytes(pool, type_name, None, None) - if dyn_sz > 0: - return dyn_sz + if dyn_sz > 0: return dyn_sz # 内置类型 if string.strcmp(type_name, "int") == 0: return 4 if string.strcmp(type_name, "CInt") == 0: return 4 @@ -789,8 +698,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(type_name) if struct_ty is not None: sz: int = self._get_type_size(struct_ty) - if sz > 0: - return sz + if sz > 0: return sz # 未注册类型 → 默认指针大小 8(可能是自引用或前向引用) return 8 def _translate_renum_def(self, trans: HT.Translator*, @@ -813,14 +721,12 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # _register_renum_variants 永不再执行 ⇒ 变体表缺该类 ⇒ _is_renum_class_name # 恒 0 ⇒ match 走 _handle_simple_match(无变体绑定)⇒ case 绑定名未定义。 if self._is_renum_class_name(class_name) != 0: - if existing.Ty is not None: - mlirlite.module_add_named_type(trans.Module, pool, existing.Ty) + if existing.Ty is not None: mlirlite.module_add_named_type(trans.Module, pool, existing.Ty) return 0 # 变体表缺失:中和旧 entry(对齐 ClassGenDef needs_rereg 先例),使 # find_struct_by_module 不再命中(按 Name 精确匹配),走下方完整注册路径 # 以同时修正 struct 布局 + 变体表。 - if existing.Name is not None: - existing.Name[0] = '\0' + if existing.Name is not None: existing.Name[0] = '\0' existing.Ty = None existing.FieldCount = 0 @@ -837,8 +743,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # 变体最多 32 个,每个变体最多 16 个字段 # variant_field_sizes[i][j] = 变体 i 的第 j 个字段大小 variant_field_sizes: sizet* = pool.alloc(8 * 64 * 16) - if variant_field_sizes is None: - return 0 + if variant_field_sizes is None: return 0 string.memset(variant_field_sizes, 0, 8 * 64 * 16) variant_count: int = 0 @@ -846,8 +751,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): for ci in range(cn): stmt: ast.AST* = children.get(ci) - if stmt is None: - continue + if stmt is None: continue sk: int = stmt.kind() if sk == ast.ASTKind.ClassDef: @@ -861,16 +765,12 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): field_idx: int = 0 for vi in range(vcn): vstmt: ast.AST* = variant_children.get(vi) - if vstmt is None: - continue + if vstmt is None: continue vk: int = vstmt.kind() - if vk != ast.ASTKind.AnnAssign: - continue + if vk != ast.ASTKind.AnnAssign: continue vaa: ast.AnnAssign* = ast.AnnAssign*(vstmt) - if vaa is None or vaa.target is None or vaa.annotation is None: - continue - if vaa.target.kind() != ast.ASTKind.Name: - continue + if vaa is None or vaa.target is None or vaa.annotation is None: continue + if vaa.target.kind() != ast.ASTKind.Name: continue # 提取字段名 vnm: ast.Name* = ast.Name*(vaa.target) # 计算字段大小 @@ -887,12 +787,10 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # 后悬空,注册内部会 strcpy 到 perm_pool。 if vnm is not None and vnm.id is not None: mem_ty_l: mlirlite.LLVMType* = None - if trans is not None: - mem_ty_l = self.Gen.TypeGenResolve.resolve_annotation_type(pool, vaa.annotation, trans._imported_modules, trans._from_imports, trans, 0) + if trans is not None: mem_ty_l = self.Gen.TypeGenResolve.resolve_annotation_type(pool, vaa.annotation, trans._imported_modules, trans._from_imports, trans, 0) self._register_renum_field_alias(pool, class_name, vnm.id, field_idx + 1, mem_ty_l, variant_cd.name) field_idx += 1 - if field_idx > max_field_count: - max_field_count = field_idx + if field_idx > max_field_count: max_field_count = field_idx variant_count += 1 elif sk == ast.ASTKind.Assign: # Assign 形式的**无载荷变体**(如 `Empty = 1` / `None_ = 0`):与 TPC @@ -901,17 +799,13 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # `case Option.Empty():` 查表失配 tag=-1 → 硬校验 fail-fast。 # tag 值由 _register_renum_variants 按同一口径分配(显式值优先)。 ag_v: ast.Assign* = ast.Assign*(stmt) - if ag_v is None or ag_v.targets is None: - continue + if ag_v is None or ag_v.targets is None: continue tgts_v: list[ast.AST*]* = ag_v.targets - if len(tgts_v) == 0: - continue + if len(tgts_v) == 0: continue t0_v: ast.AST* = tgts_v.get(0) - if t0_v is None or t0_v.kind() != ast.ASTKind.Name: - continue + if t0_v is None or t0_v.kind() != ast.ASTKind.Name: continue tgt_v: ast.Name* = ast.Name*(t0_v) - if tgt_v.id is None: - continue + if tgt_v.id is None: continue variant_count += 1 if variant_count == 0: @@ -928,8 +822,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): total_positions = 2 # 至少 {i32, i32} position_max_sizes: sizet* = pool.alloc(8 * total_positions) - if position_max_sizes is None: - return 0 + if position_max_sizes is None: return 0 string.memset(position_max_sizes, 0, 8 * total_positions) # 位置 0 = tag = 4 字节 @@ -946,8 +839,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): continue # 超出每变体 16 字段槽位:未写入(memset 为 0),跳过 offset2: sizet = vi * 16 + field_pos fsize_val: sizet = variant_field_sizes[offset2] - if fsize_val > pos_max: - pos_max = fsize_val + if fsize_val > pos_max: pos_max = fsize_val position_max_sizes[pos] = sizet(pos_max) # 构建 ParamNode 链表 @@ -960,14 +852,11 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): for pos in range(total_positions): psize: int = position_max_sizes[pos] field_ty: mlirlite.LLVMType* = i32_ty - if psize > 4: - field_ty = i64_ty + if psize > 4: field_ty = i64_ty pnode: mlirlite.ParamNode* = mlirlite.new_param_node(pool, field_ty) - if pnode is None: - continue + if pnode is None: continue tail_node = mlirlite.param_list_append(first_node, tail_node, pnode) - if first_node is None: - first_node = tail_node + if first_node is None: first_node = tail_node if first_node is None: VLogger.error(f"failed to build field list for {class_name}", "RENUM") @@ -991,8 +880,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # StdlibAlloc=1(Phase2 mark2 后)也必须深拷贝:同 union 的悬空根因。 if trans._declare_only == 0 or self.Gen.StructGen.get_stdlib_alloc() != 0: renum_copy: mlirlite.LLVMType* = mlirlite.DeepCopyType(CompilerFactory.factory.PermPool, renum_ty) - if renum_copy is not None: - renum_ty = renum_copy + if renum_copy is not None: renum_ty = renum_copy # 注册命名结构体到模块 mlirlite.module_add_named_type(trans.Module, pool, renum_ty) @@ -1010,8 +898,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): for pos in range(1, total_positions): psize2: int = position_max_sizes[pos] payload_ty: mlirlite.LLVMType* = i32_ty - if psize2 > 4: - payload_ty = i64_ty + if psize2 > 4: payload_ty = i64_ty field_name_buf: str = pool.alloc(16) if field_name_buf is not None: viperlib.snprintf(field_name_buf, 16, "_p%d", pos) @@ -1050,34 +937,27 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): 不误伤)。非自引用字段(ParamNode/str/int 等)第一遍已解析成功,去重 命中类型槽非 0 → 直接跳过,行为不变。 """ - if trans is None or pool is None or class_name is None or cd is None: - return + if trans is None or pool is None or class_name is None or cd is None: return children: list[ast.AST*]* = cd.children - if children is None: - return + if children is None: return cn: sizet = len(children) for ci in range(cn): stmt: ast.AST* = children.get(ci) - if stmt is None or stmt.kind() != ast.ASTKind.ClassDef: - continue + if stmt is None or stmt.kind() != ast.ASTKind.ClassDef: continue variant_cd: ast.ClassDef* = ast.ClassDef*(stmt) - if variant_cd is None or variant_cd.name is None or variant_cd.children is None: - continue + if variant_cd is None or variant_cd.name is None or variant_cd.children is None: continue vchildren: list[ast.AST*]* = variant_cd.children vcn: sizet = len(vchildren) field_idx: int = 0 for vi in range(vcn): vstmt: ast.AST* = vchildren.get(vi) - if vstmt is None: - continue - if vstmt.kind() != ast.ASTKind.AnnAssign: - continue + if vstmt is None: continue + if vstmt.kind() != ast.ASTKind.AnnAssign: continue vaa: ast.AnnAssign* = ast.AnnAssign*(vstmt) if vaa is None or vaa.target is None or vaa.annotation is None: # 与第一遍同规则:无效 AnnAssign 不占用 payload 槽位 continue - if vaa.target.kind() != ast.ASTKind.Name: - continue + if vaa.target.kind() != ast.ASTKind.Name: continue vnm: ast.Name* = ast.Name*(vaa.target) if vnm.id is None: # 与第一遍同规则:有效 AnnAssign 仍占用 payload 槽位 @@ -1085,8 +965,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): continue mem_ty_l: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, vaa.annotation, trans._imported_modules, trans._from_imports, trans, 0) # 解析成功 → 触发别名表去重路径(类型槽为 0 时回填;非 0 跳过) - if mem_ty_l is not None: - self._register_renum_field_alias(pool, class_name, vnm.id, field_idx + 1, mem_ty_l, variant_cd.name) + if mem_ty_l is not None: self._register_renum_field_alias(pool, class_name, vnm.id, field_idx + 1, mem_ty_l, variant_cd.name) field_idx += 1 def _register_renum_variants(self, pool: memhub.MemBuddy*, class_name: str, @@ -1137,8 +1016,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # 检查是否已注册(避免重复注册) for i in range(self.RenumClassCount): existing: str = str(self.RenumClassNames[i]) - if existing is not None and string.strcmp(existing, class_name) == 0: - return + if existing is not None and string.strcmp(existing, class_name) == 0: return # 表已满 if self.RenumClassCount >= RENUM_CLASS_MAX: @@ -1171,22 +1049,16 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): max_explicit: int = -1 for ci in range(cn): stmt_p: ast.AST* = children.get(ci) - if stmt_p is None or stmt_p.kind() != ast.ASTKind.Assign: - continue + if stmt_p is None or stmt_p.kind() != ast.ASTKind.Assign: continue ag_p: ast.Assign* = ast.Assign*(stmt_p) - if ag_p is None or ag_p.targets is None or ag_p.value is None: - continue + if ag_p is None or ag_p.targets is None or ag_p.value is None: continue tgts_p: list[ast.AST*]* = ag_p.targets - if len(tgts_p) == 0: - continue + if len(tgts_p) == 0: continue t0_p: ast.AST* = tgts_p.get(0) - if t0_p is None or t0_p.kind() != ast.ASTKind.Name: - continue - if ag_p.value.kind() != ast.ASTKind.Constant: - continue + if t0_p is None or t0_p.kind() != ast.ASTKind.Name: continue + if ag_p.value.kind() != ast.ASTKind.Constant: continue ev_v: int = int(self._extract_int_value(ag_p.value)) - if ev_v > max_explicit: - max_explicit = ev_v + if ev_v > max_explicit: max_explicit = ev_v # 第二遍:按声明序写表。slot = 表中连续槽位序号(0..variant_count-1, # 查找侧 _lookup_renum_variant_in_class 按槽位顺序遍历),槽内存该变体的 @@ -1195,49 +1067,40 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): next_class_tag: int = max_explicit + 1 variant_index: int = 0 for ci in range(cn): - if slot >= variant_count: - break + if slot >= variant_count: break if slot >= RENUM_VARIANT_PER_CLASS: # 每类固定 32 槽:变体超过上限继续写会越界污染相邻类槽,fail-fast 报错 VLogger.error(f"REnum 变体数超过上限 {RENUM_VARIANT_PER_CLASS}: {class_name}", "RENUM") break stmt: ast.AST* = children.get(ci) - if stmt is None: - continue + if stmt is None: continue sk_rv: int = stmt.kind() vname_ptr: sizet = 0 tag_val: int = 0 if sk_rv == ast.ASTKind.ClassDef: vcd: ast.ClassDef* = ast.ClassDef*(stmt) - if vcd is None or vcd.name is None: - continue + if vcd is None or vcd.name is None: continue vname_ptr = sizet(vcd.name) tag_val = next_class_tag next_class_tag += 1 elif sk_rv == ast.ASTKind.Assign: # Assign 形式无载荷变体(与 _translate_renum_def 首遍同过滤口径) ag_rv: ast.Assign* = ast.Assign*(stmt) - if ag_rv is None or ag_rv.targets is None: - continue + if ag_rv is None or ag_rv.targets is None: continue tgts_rv: list[ast.AST*]* = ag_rv.targets - if len(tgts_rv) == 0: - continue + if len(tgts_rv) == 0: continue t0_rv: ast.AST* = tgts_rv.get(0) - if t0_rv is None or t0_rv.kind() != ast.ASTKind.Name: - continue + if t0_rv is None or t0_rv.kind() != ast.ASTKind.Name: continue tgt_rv: ast.Name* = ast.Name*(t0_rv) - if tgt_rv.id is None: - continue + if tgt_rv.id is None: continue vname_ptr = sizet(tgt_rv.id) - if ag_rv.value is not None and ag_rv.value.kind() == ast.ASTKind.Constant: - tag_val = int(self._extract_int_value(ag_rv.value)) + if ag_rv.value is not None and ag_rv.value.kind() == ast.ASTKind.Constant: tag_val = int(self._extract_int_value(ag_rv.value)) else: # 无显式值:用独立计数器(与类变体计数器分离,对齐 TPC # `variant_index`),避免与 next_class_tag 交叉撞号 tag_val = variant_index variant_index += 1 - else: - continue + else: continue name_offset: sizet = idx * RENUM_VARIANT_PER_CLASS + slot # 变体名同样 strcpy 到 perm_pool(1a 每文件 reset 后 AST 名悬空) vname_src: str = str(vname_ptr) @@ -1262,8 +1125,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): 返回: class_name (str),或 None """ - if variant_name is None or self.RenumClassNames is None: - return None + if variant_name is None or self.RenumClassNames is None: return None for i in range(self.RenumClassCount): vcount: int = self.RenumClassVariantCounts[i] @@ -1280,8 +1142,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): 用于区分「类根本没注册」与「类在但变体名没注册」两类失败。 """ buf: str = CompilerFactory.factory.PermPool.alloc(256) - if buf is None: - return "-" + if buf is None: return "-" buf[0] = '\0' cls_first: str = "-" v_first: str = "-" @@ -1290,8 +1151,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): cls_first = str(self.RenumClassNames[0]) if self.RenumVariantNames is not None and self.RenumClassVariantCounts is not None: n_first_v = self.RenumClassVariantCounts[0] - if n_first_v > 0: - v_first = str(self.RenumVariantNames[0]) + if n_first_v > 0: v_first = str(self.RenumVariantNames[0]) viperlib.snprintf(buf, 256, "count=%d first=%s vcount=%d vfirst=%s", self.RenumClassCount, cls_first, n_first_v, v_first) return buf @@ -1305,38 +1165,30 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): `_handle_simple_match`(不绑定)→ case 绑定名 NameError (includes/mlirlite/__types.vp L407 `bits` 根因)。 """ - if class_name is None: - return 0 + if class_name is None: return 0 st: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(class_name) - if st is None: - return 0 - if self.Gen.StructGen.lookup_field(st, "__tag") is None: - return 0 + if st is None: return 0 + if self.Gen.StructGen.lookup_field(st, "__tag") is None: return 0 return 1 def _is_renum_class_name(self, class_name: str) -> int: """检查名称是否是已注册的 REnum 类名,返回 1=是 / 0=否""" - if class_name is None or self.RenumClassNames is None: - return 0 + if class_name is None or self.RenumClassNames is None: return 0 for i in range(self.RenumClassCount): existing: str = str(self.RenumClassNames[i]) - if existing is not None and string.strcmp(existing, class_name) == 0: - return 1 + if existing is not None and string.strcmp(existing, class_name) == 0: return 1 return 0 def _lookup_renum_variant_in_class(self, class_name: str, variant_name: str) -> int: """在指定 REnum 类中查找变体,返回 tag 值或 -1""" - if class_name is None or variant_name is None or self.RenumClassNames is None: - return -1 + if class_name is None or variant_name is None or self.RenumClassNames is None: return -1 for i in range(self.RenumClassCount): existing: str = str(self.RenumClassNames[i]) - if existing is None or string.strcmp(existing, class_name) != 0: - continue + if existing is None or string.strcmp(existing, class_name) != 0: continue vcount: int = self.RenumClassVariantCounts[i] for j in range(vcount): name_offset: sizet = i * RENUM_VARIANT_PER_CLASS + j vname: str = str(self.RenumVariantNames[name_offset]) - if vname is not None and string.strcmp(vname, variant_name) == 0: - return self.RenumVariantTags[name_offset] + if vname is not None and string.strcmp(vname, variant_name) == 0: return self.RenumVariantTags[name_offset] return -1 return -1 def _register_renum_field_alias(self, pool: memhub.MemBuddy*, @@ -1351,10 +1203,8 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): LLVMType* 在注册期解析失败时为 None,match 绑定回退槽位类型)。 variant_name: 所属变体名(可选;match 绑定按 (class, 变体, 位置) 定位成员) """ - if pool is None or class_name is None or field_name is None: - return - if payload_idx < 1: - return + if pool is None or class_name is None or field_name is None: return + if payload_idx < 1: return # 懒初始化表(perm_pool:1a 每文件 reset 后表本体不被回收) if self.RenumAliasClass is None: @@ -1404,8 +1254,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # 回填真实类型;非 0 槽保持原样(避免重复 DeepCopy 覆盖抖动)。 if self.RenumAliasTy[i] == 0 and field_ty is not None: ty_copy_rf2: mlirlite.LLVMType* = mlirlite.DeepCopyType(CompilerFactory.factory.PermPool, field_ty) - if ty_copy_rf2 is not None: - self.RenumAliasTy[i] = sizet(ty_copy_rf2) + if ty_copy_rf2 is not None: self.RenumAliasTy[i] = sizet(ty_copy_rf2) return idx: int = self.RenumAliasCount @@ -1413,16 +1262,14 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # class_name 字符串都可用 strcmp 命中,无需 _update_renum_alias_class_ptr) cls_len_rfa: sizet = string.strlen(class_name) cls_buf_rfa: str = CompilerFactory.factory.PermPool.alloc(cls_len_rfa + 1) - if cls_buf_rfa is None: - return + if cls_buf_rfa is None: return string.strcpy(cls_buf_rfa, class_name) self.RenumAliasClass[idx] = sizet(cls_buf_rfa) # field_name 存 AST 裸指针,1a 每文件 reset 后悬空;_lookup_renum_field_alias # 用 strcmp 内容比较 → strcpy 到 perm_pool 不影响查找。 fn_len_rfa: sizet = string.strlen(field_name) fn_buf_rfa: str = CompilerFactory.factory.PermPool.alloc(fn_len_rfa + 1) - if fn_buf_rfa is None: - return + if fn_buf_rfa is None: return string.strcpy(fn_buf_rfa, field_name) self.RenumAliasField[idx] = sizet(fn_buf_rfa) self.RenumAliasIndex[idx] = sizet(payload_idx) @@ -1431,8 +1278,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): self.RenumAliasTy[idx] = 0 if field_ty is not None: ty_copy_rfa: mlirlite.LLVMType* = mlirlite.DeepCopyType(CompilerFactory.factory.PermPool, field_ty) - if ty_copy_rfa is not None: - self.RenumAliasTy[idx] = sizet(ty_copy_rfa) + if ty_copy_rfa is not None: self.RenumAliasTy[idx] = sizet(ty_copy_rfa) # 变体名同样 strcpy 到 perm_pool(1a reset 后 variant_cd.name 悬空) self.RenumAliasVariant[idx] = 0 if variant_name is not None: @@ -1450,15 +1296,13 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): class_name/field_name 均用 strcmp 内容比较(去指针化:槽位存 perm_pool 字符串拷贝,任何来源的 class_name 字符串都可命中) """ - if class_name is None or field_name is None or self.RenumAliasClass is None: - return -1 + if class_name is None or field_name is None or self.RenumAliasClass is None: return -1 for i in range(self.RenumAliasCount): cls_existing_ptr: str = rawptr(self.RenumAliasClass[i]) if cls_existing_ptr is not None and string.strcmp(cls_existing_ptr, class_name) == 0: # field_name 用 strcmp 内容比较(指针不同但内容相同) fld_existing_ptr: str = rawptr(self.RenumAliasField[i]) - if fld_existing_ptr is not None and string.strcmp(fld_existing_ptr, field_name) == 0: - return self.RenumAliasIndex[i] + if fld_existing_ptr is not None and string.strcmp(fld_existing_ptr, field_name) == 0: return self.RenumAliasIndex[i] return -1 def _lookup_renum_field_alias_ty(self, class_name: str, field_name: str) -> mlirlite.LLVMType*: @@ -1467,15 +1311,13 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): 与 _lookup_renum_field_alias 同表同键(class/field 均 strcmp 内容比较)。 注册期未解析成功(自引用类型等)槽位为 0 → 返回 None,绑定回退槽位类型。 """ - if class_name is None or field_name is None or self.RenumAliasTy is None: - return None + if class_name is None or field_name is None or self.RenumAliasTy is None: return None for i in range(self.RenumAliasCount): cls_existing_ptr: str = rawptr(self.RenumAliasClass[i]) if cls_existing_ptr is not None and string.strcmp(cls_existing_ptr, class_name) == 0: fld_existing_ptr: str = rawptr(self.RenumAliasField[i]) if fld_existing_ptr is not None and string.strcmp(fld_existing_ptr, field_name) == 0: - if self.RenumAliasTy[i] == 0: - return None + if self.RenumAliasTy[i] == 0: return None return (mlirlite.LLVMType*)(self.RenumAliasTy[i]) return None def _lookup_renum_member_ty(self, class_name: str, @@ -1487,22 +1329,15 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): Struct.Fields=Ptr),必须带变体名定位。class/变体均 strcmp 内容比较。 返回类型或 None(未注册/未解析成功 → 绑定回退槽位类型)。 """ - if class_name is None or variant_name is None or self.RenumAliasVariant is None: - return None - if payload_idx < 1: - return None + if class_name is None or variant_name is None or self.RenumAliasVariant is None: return None + if payload_idx < 1: return None for i in range(self.RenumAliasCount): cls_existing_ptr: str = rawptr(self.RenumAliasClass[i]) - if cls_existing_ptr is None or string.strcmp(cls_existing_ptr, class_name) != 0: - continue - if self.RenumAliasVariant[i] == 0: - continue + if cls_existing_ptr is None or string.strcmp(cls_existing_ptr, class_name) != 0: continue + if self.RenumAliasVariant[i] == 0: continue vnt_ptr: str = rawptr(self.RenumAliasVariant[i]) - if vnt_ptr is None or string.strcmp(vnt_ptr, variant_name) != 0: - continue - if self.RenumAliasIndex[i] != payload_idx: - continue - if self.RenumAliasTy[i] == 0: - return None + if vnt_ptr is None or string.strcmp(vnt_ptr, variant_name) != 0: continue + if self.RenumAliasIndex[i] != payload_idx: continue + if self.RenumAliasTy[i] == 0: return None return (mlirlite.LLVMType*)(self.RenumAliasTy[i]) return None \ No newline at end of file diff --git a/App/lib/core/Gen/Class/ClassGenGeneric.vp b/App/lib/core/Gen/Class/ClassGenGeneric.vp index e8009aa..20c3fd1 100644 --- a/App/lib/core/Gen/Class/ClassGenGeneric.vp +++ b/App/lib/core/Gen/Class/ClassGenGeneric.vp @@ -89,8 +89,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): if cd is None or cd.name is None: return perm: memhub.MemBuddy* = CompilerFactory.factory.PermPool table_pool: memhub.MemBuddy* = perm - if table_pool is None: - table_pool = pool + if table_pool is None: table_pool = pool if self.GenericClassNames is None: self.GenericClassNames = list[str](table_pool, 8) self.GenericClassNodes = list[ast.ClassDef*](table_pool, 8) @@ -123,8 +122,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): back_buf: str = self._copy_type_params_stdlib(cd.type_params) if back_buf is not None: self.GenericClassTpParams[i] = sizet(back_buf) - if self.GenericClassNodes is not None: - self.GenericClassNodes.set(i, cd) + if self.GenericClassNodes is not None: self.GenericClassNodes.set(i, cd) return # type_params stdlib 深拷贝:模板节点的 type_params 是 pool 分配的 tp_names_buf: str = self._copy_type_params_stdlib(cd.type_params) @@ -133,8 +131,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): self.GenericClassSha1s.append(self._dup_perm_str(module_sha1)) # 同时保存模板来源文件路径(错误定位用,见字段注释) self.GenericClassFiles.append(self._dup_perm_str(self.Gen.TypeGenResolve.get_current_file())) - if tp_names_buf is not None and cn < GENERIC_TEMPLATE_MAX: - self.GenericClassTpParams[cn] = sizet(tp_names_buf) + if tp_names_buf is not None and cn < GENERIC_TEMPLATE_MAX: self.GenericClassTpParams[cn] = sizet(tp_names_buf) def _copy_type_params_stdlib(self, tp: list[str]*) -> str: """将模板 type_params 深拷贝为空格分隔、NUL 结尾的 stdlib 缓冲区 @@ -143,28 +140,22 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): 分配 list,跨 Phase 内容可能被复用污染,必须注册时拷贝到 stdlib。 返回缓冲区指针;tp 为 None(非泛型)或分配失败返回 None。 """ - if tp is None: - return None + if tp is None: return None tp_n: sizet = len(tp) - if tp_n == 0: - return None + if tp_n == 0: return None # 计算总长:各名字长度 + (n-1) 个空格 + NUL total: sizet = 1 ti: sizet for ti in range(tp_n): tp_name: str = tp.get(ti) - if tp_name is not None: - total += string.strlen(tp_name) + 1 + if tp_name is not None: total += string.strlen(tp_name) + 1 buf: str = CompilerFactory.factory.PermPool.alloc(total) - if buf is None: - return None + if buf is None: return None buf[0] = '\0' for ti in range(tp_n): tp_name = tp.get(ti) - if tp_name is None: - continue - if ti > 0 and buf[0] != '\0': - string.strcat(buf, " ") + if tp_name is None: continue + if ti > 0 and buf[0] != '\0': string.strcat(buf, " ") string.strcat(buf, tp_name) return buf @@ -198,8 +189,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): if fd is None or fd.name is None or module_sha1 is None: return perm: memhub.MemBuddy* = CompilerFactory.factory.PermPool table_pool: memhub.MemBuddy* = perm - if table_pool is None: - table_pool = pool + if table_pool is None: table_pool = pool if self.GenericFuncKeys is None: self.GenericFuncKeys = list[str](table_pool, 8) self.GenericFuncNodes = list[ast.FunctionDef*](table_pool, 8) @@ -226,49 +216,42 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): self.GenericFuncNodes.append(fd) self.GenericFuncSha1s.append(self._dup_perm_str(module_sha1)) self.GenericFuncFiles.append(self._dup_perm_str(self.Gen.TypeGenResolve.get_current_file())) - if tp_names_buf is not None and kn < GENERIC_TEMPLATE_MAX: - self.GenericFuncTpParams[kn] = sizet(tp_names_buf) + if tp_names_buf is not None and kn < GENERIC_TEMPLATE_MAX: self.GenericFuncTpParams[kn] = sizet(tp_names_buf) def _find_generic_func_template(self, key: str) -> ast.FunctionDef*: """按 "{sha1}.{fname}" 键查找泛型函数模板节点,未找到返回 None""" - if self.GenericFuncKeys is None or key is None: - return None + if self.GenericFuncKeys is None or key is None: return None keys_local: list[str]* = self.GenericFuncKeys nodes_local: list[ast.FunctionDef*]* = self.GenericFuncNodes kn: sizet = len(keys_local) i: sizet for i in range(kn): knm: str = keys_local.get(i) - if knm is not None and string.strcmp(knm, key) == 0: - return nodes_local.get(i) + if knm is not None and string.strcmp(knm, key) == 0: return nodes_local.get(i) return None def _find_generic_func_template_sha1(self, key: str) -> str: """按键查找泛型函数模板的来源模块 SHA1,未找到返回 None""" - if self.GenericFuncKeys is None or key is None: - return None + if self.GenericFuncKeys is None or key is None: return None keys_local: list[str]* = self.GenericFuncKeys sha1s_local: list[str]* = self.GenericFuncSha1s kn: sizet = len(keys_local) i: sizet for i in range(kn): knm: str = keys_local.get(i) - if knm is not None and string.strcmp(knm, key) == 0: - return sha1s_local.get(i) + if knm is not None and string.strcmp(knm, key) == 0: return sha1s_local.get(i) return None def _find_generic_func_template_file(self, key: str) -> str: """按键查找泛型函数模板来源文件路径(错误定位用),未找到返回 None""" - if self.GenericFuncKeys is None or key is None: - return None + if self.GenericFuncKeys is None or key is None: return None keys_local: list[str]* = self.GenericFuncKeys files_local: list[str]* = self.GenericFuncFiles kn: sizet = len(keys_local) i: sizet for i in range(kn): knm: str = keys_local.get(i) - if knm is not None and string.strcmp(knm, key) == 0: - return files_local.get(i) + if knm is not None and string.strcmp(knm, key) == 0: return files_local.get(i) return None def _find_generic_func_tp_params(self, pool: memhub.MemBuddy*, @@ -279,23 +262,19 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): pool 有效)。逐字节解析逻辑与 _find_generic_template_tp_params 一致: 空格分隔;elem_size 必须传 8(str 指针 8 字节)。 """ - if self.GenericFuncKeys is None or key is None or self.GenericFuncTpParams is None: - return None + if self.GenericFuncKeys is None or key is None or self.GenericFuncTpParams is None: return None keys_local: list[str]* = self.GenericFuncKeys kn: sizet = len(keys_local) i: sizet for i in range(kn): knm: str = keys_local.get(i) if knm is not None and string.strcmp(knm, key) == 0: - if i >= GENERIC_TEMPLATE_MAX: - return None + if i >= GENERIC_TEMPLATE_MAX: return None buf_addr: sizet = self.GenericFuncTpParams[i] - if buf_addr == 0: - return None + if buf_addr == 0: return None buf_tp: str = rawptr(buf_addr) tp_list: list[str]* = list[str](pool, 8) - if tp_list is None: - return None + if tp_list is None: return None seg_start: sizet = 0 pos: sizet = 0 blen: sizet = string.strlen(buf_tp) @@ -332,8 +311,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): pa: ast.AST* = alist.get(ai) if pa is None or pa.kind() != ast.ASTKind.Arg: continue ag: ast.Arg* = ast.Arg*(pa) - if self.Gen.CallGenCtor._annotation_refers_type_param(ag.annotation, tp_name) != 0: - return int(ai) + if self.Gen.CallGenCtor._annotation_refers_type_param(ag.annotation, tp_name) != 0: return int(ai) return -1 def _infer_generic_func_type_arg(self, pool: memhub.MemBuddy*, @@ -366,10 +344,8 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): if ve is not None: cn_nm: str = self.Gen.VarGen.var_annot_class_name(ve) pl: int = 0 - if ve.Spec is not None: - pl = ve.Spec.PtrLevel - if cn_nm is not None: - return self.Gen.CallGenCtor._ptr_layer_type_arg(pool, cn_nm, pl, trans._from_imports) + if ve.Spec is not None: pl = ve.Spec.PtrLevel + if cn_nm is not None: return self.Gen.CallGenCtor._ptr_layer_type_arg(pool, cn_nm, pl, trans._from_imports) # 内建标量(str/char/bytes/bool/float/double 被 # extract_class_name_from_annotation 跳过 ⇒ SourceName 为 None): # 从 Spec 的 LLVM 形态反推可解析的类型名(double/float/int/char/bool)。 @@ -379,16 +355,12 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): cn_at: str = self.Gen.ExprGenAttr._resolve_attr_field_class(pool, trans, arg_node) pl_at: int = 0 fe: GenTypes.FieldEntry* = self.Gen.ExprGenAttr._resolve_attr_field_entry(pool, trans, arg_node) - if fe is not None and fe.Spec is not None: - pl_at = fe.Spec.PtrLevel + if fe is not None and fe.Spec is not None: pl_at = fe.Spec.PtrLevel fi: str = None - if trans is not None: - fi = trans._from_imports - if cn_at is not None: - return self.Gen.CallGenCtor._ptr_layer_type_arg(pool, cn_at, pl_at, fi) + if trans is not None: fi = trans._from_imports + if cn_at is not None: return self.Gen.CallGenCtor._ptr_layer_type_arg(pool, cn_at, pl_at, fi) # 内建标量字段:同 Name 分支的 Spec 反推 - if fe is not None: - return self._infer_scalar_type_name_from_spec(pool, fe.Spec) + if fe is not None: return self._infer_scalar_type_name_from_spec(pool, fe.Spec) return None if k == ast.ASTKind.Call: cl_f: ast.Call* = ast.Call*(arg_node) @@ -414,13 +386,10 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): # CUInt64T/CInt16T 这类无裸名别名的位宽靠它决定发 # t.CUInt64T 还是 t.CInt64T。 callee_txt: str = None - if fk_f == ast.ASTKind.Name: - callee_txt = ast.Name*(cl_f.func).id - else: - callee_txt = ast.Attribute*(cl_f.func).attr + if fk_f == ast.ASTKind.Name: callee_txt = ast.Name*(cl_f.func).id + else: callee_txt = ast.Attribute*(cl_f.func).attr sign_f: int = TSpec.TS_SIGN_UNKNOWN - if callee_txt is not None: - sign_f = self.Gen.TypeGenCType.spec_sign_of_annot(callee_txt, 0) + if callee_txt is not None: sign_f = self.Gen.TypeGenCType.spec_sign_of_annot(callee_txt, 0) return self.infer_scalar_type_arg_from_llvm_ty(pool, cty_f, sign_f) return None return None @@ -476,8 +445,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): # 函数对任何内建标量都恒返回 None —— 泛型函数隐式推断里"实参是内建标量的 # 形参"(如 fxi 体内 fxi2(a, ...),a: double)永远推不出,报 # "无法从实参推断泛型函数 ... 禁止静默默认 int"。 - if TSpec.SpecToLLVMText(sp, buf, 32) != 0: - return None + if TSpec.SpecToLLVMText(sp, buf, 32) != 0: return None sign: int = sign_override if sign == SIGN_FROM_SPEC: # LLVM 层 SpecFromLLVMType 恒给 TS_SIGN_SIGNED(无法区分 iN/uN), @@ -524,11 +492,9 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): TypeGenCType.spec_sign_of_annot 判定后传入;未知传 TSpec.TS_SIGN_UNKNOWN (此时 i16/i64 这类无裸名别名的位宽推不出,本函数返回 None)。 """ - if pool is None or ty is None: - return None + if pool is None or ty is None: return None arena: TSpec.TypeSpecArena* = self.Gen.TypeGenBase.ensure_spec_arena() - if arena is None: - return None + if arena is None: return None return self._infer_scalar_type_name_from_spec(pool, TSpec.SpecFromLLVMType(arena, ty), sign) def _clone_funcdef_for_spec(self, pool: memhub.MemBuddy*, @@ -555,8 +521,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): bi: sizet for bi in range(bn): stmt: ast.AST* = body.get(bi) - if stmt is not None: - new_fd.append(stmt) + if stmt is not None: new_fd.append(stmt) return new_fd def _ensure_generic_func_declare(self, trans: HT.Translator*, @@ -596,13 +561,10 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): self.Gen.TypeGenBase.set_generic_context(tp_names, type_args) saved_cur: str = self.Gen.TypeGenResolve.get_current_file() tpl_file: str = self._find_generic_func_template_file(template_key) - if tpl_file is not None: - self.Gen.TypeGenResolve.set_current_file(tpl_file) + if tpl_file is not None: self.Gen.TypeGenResolve.set_current_file(tpl_file) ret_ty: mlirlite.LLVMType* = None - if spec_fd.returns is not None: - ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, spec_fd.returns, trans._imported_modules, trans._from_imports, trans, 0) - if ret_ty is None: - ret_ty = i32_ty + if spec_fd.returns is not None: ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, spec_fd.returns, trans._imported_modules, trans._from_imports, trans, 0) + if ret_ty is None: ret_ty = i32_ty func: mlirlite.Function* = mlirlite.create_declare(pool, mod, spec_name, ret_ty) if func is not None and spec_fd.args is not None and spec_fd.args.kind() == ast.ASTKind.Arguments: ags: ast.Arguments* = ast.Arguments*(spec_fd.args) @@ -627,11 +589,9 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): case _: param_ty = resolved pname: str = pool.alloc(32) - if pname is not None: - viperlib.snprintf(pname, 32, "%%%s", arg.arg) + if pname is not None: viperlib.snprintf(pname, 32, "%%%s", arg.arg) mlirlite.add_param(pool, func, param_ty, pname) - if tpl_file is not None: - self.Gen.TypeGenResolve.set_current_file(saved_cur) + if tpl_file is not None: self.Gen.TypeGenResolve.set_current_file(saved_cur) trans.ModuleSha1 = saved_ms trans._imported_modules = saved_imp trans.GenericTypeParamNames = saved_gtpn @@ -648,11 +608,9 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): (命中且本模块无该符号 → 补 declare);4. 克隆模板 + generic_context 翻译发射 define(translate_function_def),命名/签名与调用点一致。 """ - if trans is None or template_key is None or type_args is None: - return None + 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, "泛型函数特化递归过深(疑似泛型循环套用)", "InternalCompilerError") pool: memhub.MemBuddy* = trans.Pool template_fd: ast.FunctionDef* = self._find_generic_func_template(template_key) if template_fd is None: @@ -670,11 +628,9 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): ta_raw_g: str = type_args.get(ta_i_g) if ta_raw_g is not None: ta_rsv_g: str = self.Gen.TypeGenBase.resolve_generic_type_name(ta_raw_g) - if ta_rsv_g is not None and string.strcmp(ta_raw_g, ta_rsv_g) != 0: - type_args.set(ta_i_g, ta_rsv_g) + if ta_rsv_g is not None and string.strcmp(ta_raw_g, ta_rsv_g) != 0: type_args.set(ta_i_g, ta_rsv_g) tp_names: list[str]* = self._find_generic_func_tp_params(pool, template_key) - if tp_names is None: - tp_names = template_fd.type_params + if tp_names is None: tp_names = template_fd.type_params if tp_names is None: self.GenericSpecDepth -= 1 return None @@ -753,8 +709,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): self.Gen.TypeGenResolve.set_current_file(tpl_file) self.Gen.TypeGenBase.push_trace(tpl_file, template_fd.lineno) self.Gen.FuncGenDef.translate_function_def(trans, spec_fd) - if tpl_file is not None: - self.Gen.TypeGenBase.pop_trace() + if tpl_file is not None: self.Gen.TypeGenBase.pop_trace() self.Gen.TypeGenResolve.set_current_file(saved_cur) trans.ModuleSha1 = saved_ms trans._imported_modules = saved_imp @@ -773,19 +728,16 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): 从注册时深拷贝的 stdlib 缓冲区重建当前 pool 的 list[str] (特化期间 pool 有效,方法与体翻译共用)。与 GenericClassNames 同序。 """ - if self.GenericClassNames is None or class_name is None or self.GenericClassTpParams is None: - return None + if self.GenericClassNames is None or class_name is None or self.GenericClassTpParams is None: return None names_local: list[str]* = self.GenericClassNames cn: sizet = len(names_local) i: sizet for i in range(cn): nm: str = names_local.get(i) if nm is not None and string.strcmp(nm, class_name) == 0: - if i >= GENERIC_TEMPLATE_MAX: - return None + if i >= GENERIC_TEMPLATE_MAX: return None buf_addr: sizet = self.GenericClassTpParams[i] - if buf_addr == 0: - return None + if buf_addr == 0: return None buf_tp: str = rawptr(buf_addr) # 空格分隔 → list[str] # 注意:list[str](pool, 8) 第二个参数是 elem_size(指针 8 字节), @@ -793,8 +745,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): # (Pair[T1,T2] 的 seg1 写 data+4 覆盖 seg0 高 4 字节 → strcmp # 收到 0x15B78D5015B78CB0 混合垃圾崩溃,GenericTest 回归根因) tp_list: list[str]* = list[str](pool, 8) - if tp_list is None: - return None + if tp_list is None: return None seg_start: sizet = 0 pos: sizet = 0 blen: sizet = string.strlen(buf_tp) @@ -813,8 +764,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): return None def _find_generic_template(self, class_name: str) -> ast.ClassDef*: """查找泛型类模板,返回 ClassDef 节点或 None""" - if self.GenericClassNames is None or class_name is None: - return None + if self.GenericClassNames is None or class_name is None: return None # 用局部变量接收 list,触发类型推断(避免字段 __len__ 失败) names_local: list[str]* = self.GenericClassNames nodes_local: list[ast.ClassDef*] | t.CPtr = self.GenericClassNodes @@ -828,8 +778,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): return None def _find_generic_template_sha1(self, class_name: str) -> str: """查找泛型类模板的来源模块 SHA1,未找到返回 None""" - if self.GenericClassNames is None or class_name is None: - return None + if self.GenericClassNames is None or class_name is None: return None # 用局部变量接收 list,触发类型推断 names_local: list[str]* = self.GenericClassNames sha1s_local: list[str]* = self.GenericClassSha1s @@ -847,8 +796,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): 与 _find_generic_template_sha1 同表同序;供特化翻译模板方法体时 临时切换 CurrentFile(错误定位:模板 node.lineno 需配模板文件路径)。 """ - if self.GenericClassNames is None or class_name is None: - return None + if self.GenericClassNames is None or class_name is None: return None names_local: list[str]* = self.GenericClassNames files_local: list[str]* = self.GenericClassFiles cn: sizet = len(names_local) @@ -877,49 +825,39 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): 分配新缓冲区拼接,避免原地 strcat 导致缓冲区溢出 """ - if class_name is None or type_args is None or pool is None: - return class_name + if class_name is None or type_args is None or pool is None: return class_name n: sizet = len(type_args) - if n == 0: - return class_name + if n == 0: return class_name # 逐实参规范化(幂等):先归一成新列表,长度计算与拼接都用归一后的串 norm_args: list[str]* = list[str](pool, 8) - if norm_args is None: - return class_name + if norm_args is None: return class_name i: sizet for i in range(n): ta_raw: str = type_args.get(i) - if ta_raw is None: - continue + if ta_raw is None: continue ta_norm: str = self.Gen.TypeGenResolve._norm_type_arg_name(pool, ta_raw, from_imports) - if ta_norm is None: - ta_norm = ta_raw + if ta_norm is None: ta_norm = ta_raw norm_args.append(ta_norm) n = len(norm_args) - if n == 0: - return class_name + if n == 0: return class_name # 计算总长度: class_name + "[" + arg0 + "," + arg1 + ... + "]" + NUL total_len: sizet = string.strlen(class_name) + 2 # "[" 和 "]" for i in range(n): if i > 0: total_len += 1 # "," ta: str = norm_args.get(i) - if ta is not None: - total_len += string.strlen(ta) + if ta is not None: total_len += string.strlen(ta) total_len += 1 # NUL # 分配新缓冲区 mangled: str = pool.alloc(total_len) - if mangled is None: - return class_name + if mangled is None: return class_name mangled[0] = '\0' string.strcat(mangled, class_name) string.strcat(mangled, "[") for i in range(n): - if i > 0: - string.strcat(mangled, ",") + if i > 0: string.strcat(mangled, ",") ta: str = norm_args.get(i) - if ta is not None: - string.strcat(mangled, ta) + if ta is not None: string.strcat(mangled, ta) string.strcat(mangled, "]") return mangled def _clone_annotation(self, pool: memhub.MemBuddy*, @@ -931,8 +869,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): tp_names: 类型参数名列表 ['T'] type_args: 类型实参名列表 ['int'] """ - if node is None: - return None + if node is None: return None k: int = node.kind() # Name: 可能是类型参数 T @@ -982,8 +919,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): for ei in range(en): el: ast.AST* = tup_elts.get(ei) new_el: ast.AST* = self._clone_annotation(pool, el, tp_names, type_args) - if new_el is not None: - new_elts.append(new_el) + if new_el is not None: new_elts.append(new_el) return ast.Tuple(pool, new_elts, tup.ctx) # Constant: 默认值等 @@ -999,10 +935,8 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): tp_names: list[str]*, type_args: list[str]*) -> ast.AST*: """拷贝 Arguments 节点,替换 arg annotation 中的 T""" - if args is None: - return None - if args.kind() != ast.ASTKind.Arguments: - return args + if args is None: return None + if args.kind() != ast.ASTKind.Arguments: return args old_args: ast.Arguments* = ast.Arguments*(args) # 拷贝 args 列表,替换每个 Arg 的 annotation new_arg_list: list[ast.AST*]* = list[ast.AST*](pool, 8) @@ -1012,15 +946,13 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): ai: sizet for ai in range(an): arg_node: ast.AST* = old_arg_list.get(ai) - if arg_node is None: - continue + if arg_node is None: continue if arg_node.kind() == ast.ASTKind.Arg: ag: ast.Arg* = ast.Arg*(arg_node) new_anno: ast.AST* = self._clone_annotation(pool, ag.annotation, tp_names, type_args) new_arg: ast.Arg* = ast.Arg(pool, ag.arg, new_anno) new_arg_list.append(new_arg) - else: - new_arg_list.append(arg_node) + else: new_arg_list.append(arg_node) return ast.Arguments(pool, new_arg_list, old_args.vararg, old_args.kwarg, old_args.defaults, old_args.kw_defaults) def _clone_classdef_for_spec(self, pool: memhub.MemBuddy*, @@ -1045,8 +977,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): ci: sizet for ci in range(cn): child: ast.AST* = cd_children.get(ci) - if child is None: - continue + if child is None: continue ck: int = child.kind() if ck == ast.ASTKind.AnnAssign: @@ -1070,18 +1001,15 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): bci: sizet for bci in range(bcn): body_stmt: ast.AST* = fd_children.get(bci) - if body_stmt is not None: - new_fd.append(body_stmt) + if body_stmt is not None: new_fd.append(body_stmt) new_cd.append(new_fd) - else: - new_cd.append(child) + else: new_cd.append(child) return new_cd def _find_cached_spec(self, spec_key: str) -> str: """查找已缓存的特化名,未找到返回 None""" - if self.SpecKeys is None or spec_key is None: - return None + if self.SpecKeys is None or spec_key is None: return None i: int for i in range(self.SpecCount): key_addr: sizet = self.SpecKeys[i] @@ -1089,30 +1017,25 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): k: str = rawptr(key_addr) if k is not None and string.strcmp(k, spec_key) == 0: name_addr: sizet = self.SpecNames[i] - if name_addr != 0: - return rawptr(name_addr) + if name_addr != 0: return rawptr(name_addr) return None def _cache_spec(self, pool: memhub.MemBuddy*, spec_key: str, spec_name: str): """缓存特化结果(stdlib 深拷贝存储,跨文件安全)""" - if spec_key is None or spec_name is None: - return + if spec_key is None or spec_name is None: return if self.SpecKeys is None: self.SpecKeys = CompilerFactory.factory.PermPool.alloc(SPEC_CACHE_MAX * 8) self.SpecNames = CompilerFactory.factory.PermPool.alloc(SPEC_CACHE_MAX * 8) - if self.SpecKeys is None or self.SpecNames is None: - return + if self.SpecKeys is None or self.SpecNames is None: return string.memset(self.SpecKeys, 0, SPEC_CACHE_MAX * 8) string.memset(self.SpecNames, 0, SPEC_CACHE_MAX * 8) self.SpecCount = 0 - if self.SpecCount >= SPEC_CACHE_MAX: - return + if self.SpecCount >= SPEC_CACHE_MAX: return # 深拷贝字符串到 stdlib 区 key_len: sizet = string.strlen(spec_key) name_len: sizet = string.strlen(spec_name) key_copy: str = CompilerFactory.factory.PermPool.alloc(key_len + 1) name_copy: str = CompilerFactory.factory.PermPool.alloc(name_len + 1) - if key_copy is None or name_copy is None: - return + if key_copy is None or name_copy is None: return string.strcpy(key_copy, spec_key) string.strcpy(name_copy, spec_name) self.SpecKeys[self.SpecCount] = sizet(key_copy) @@ -1121,11 +1044,9 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): def _merge_template_imports(self, trans: HT.Translator*, template_sha1: str) -> None: """将模板模块的 imports 并入 trans._imported_modules(空格分隔)""" - if trans is None or template_sha1 is None: - return + if trans is None or template_sha1 is None: return tdeps: str = StubMergerStore.LookupIncludesDeps(template_sha1) - if tdeps is None or tdeps[0] == '\0': - return + if tdeps is None or tdeps[0] == '\0': return cur: str = trans._imported_modules if cur is None or cur[0] == '\0': trans._imported_modules = tdeps @@ -1133,8 +1054,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): cur_len: sizet = string.strlen(cur) td_len: sizet = string.strlen(tdeps) merged: str = trans.Pool.alloc(cur_len + td_len + 2) - if merged is None: - return + if merged is None: return string.strcpy(merged, cur) merged[cur_len] = ' ' string.strcpy(merged + cur_len + 1, tdeps) @@ -1148,17 +1068,13 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): 特化方法体 MethodsEmitted 残留 1 → 下遍不补译 → 链接 undefined symbol。 记录触发文件 sha1 后按此精确重置(见 StructGenMixin.reset_module_methods_emitted)。 """ - if spec_name is None or trigger_sha1 is None: - return 0 + if spec_name is None or trigger_sha1 is None: return 0 entry_rt: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(spec_name) - if entry_rt is None: - return 0 - if string.strcmp(entry_rt.Name, spec_name) != 0: - return 0 + if entry_rt is None: return 0 + if string.strcmp(entry_rt.Name, spec_name) != 0: return 0 ts_len_r: sizet = string.strlen(trigger_sha1) ts_buf_r: str = CompilerFactory.factory.PermPool.alloc(ts_len_r + 1) - if ts_buf_r is None: - return 0 + if ts_buf_r is None: return 0 string.strcpy(ts_buf_r, trigger_sha1) entry_rt.SpecTriggerSha1 = ts_buf_r return 1 @@ -1171,10 +1087,8 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): 查找 → 报 "NameError: 未定义名称 'T'",现象与真因(元数据缺失)严重脱节。 """ 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 + 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") @@ -1193,8 +1107,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): 6. 调用 translate_class_def 翻译特化类 7. 返回特化名 """ - if trans is None or class_name is None or type_args is None: - return None + if trans is None or class_name is None or type_args is None: return None # 泛型循环套用防护:递归深度 +1,超过上限立即报错终止(防 F-bounded # 等循环特化把编译变死循环)。所有返回路径都必须 -1(见各 return 前)。 self.GenericSpecDepth += 1 @@ -1219,8 +1132,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): ta_raw_g: str = type_args.get(ta_i_g) if ta_raw_g is not None: ta_rsv_g: str = self.Gen.TypeGenBase.resolve_generic_type_name(ta_raw_g) - if ta_rsv_g is not None and string.strcmp(ta_raw_g, ta_rsv_g) != 0: - type_args.set(ta_i_g, ta_rsv_g) + if ta_rsv_g is not None and string.strcmp(ta_raw_g, ta_rsv_g) != 0: type_args.set(ta_i_g, ta_rsv_g) pool: memhub.MemBuddy* = trans.Pool @@ -1232,8 +1144,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): # 2. 生成特化名(唯一生成器内部逐实参规范化:裸名/带前缀在此收敛为同一名) _from_imports: str = None - if trans is not None: - _from_imports = trans._from_imports + if trans is not None: _from_imports = trans._from_imports spec_name: str = self._mangle_generic_class_name(pool, class_name, type_args, _from_imports) if spec_name is None: self.GenericSpecDepth -= 1 @@ -1275,8 +1186,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): self.Gen.TypeGenResolve.set_current_file(tpl_file_pre) self.Gen.TypeGenBase.push_trace(tpl_file_pre, template_cd.lineno) self.Gen.ClassGenVTable._translate_oop_methods(trans, spec_cd_pre, pre_existing.Ty, spec_name, 0, 1) - if tpl_file_pre is not None: - self.Gen.TypeGenBase.pop_trace() + if tpl_file_pre is not None: self.Gen.TypeGenBase.pop_trace() self.Gen.TypeGenResolve.set_current_file(saved_cur_pre) trans.ModuleSha1 = saved_ms_pre trans._imported_modules = saved_imp_pre @@ -1293,8 +1203,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): if sk_i > 0: sk_total += 1 # "," sk_ta: str = type_args.get(sk_i) - if sk_ta is not None: - sk_total += string.strlen(sk_ta) + if sk_ta is not None: sk_total += string.strlen(sk_ta) sk_total += 1 # NUL spec_key: str = pool.alloc(sk_total) if spec_key is None: @@ -1304,11 +1213,9 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): string.strcat(spec_key, class_name) string.strcat(spec_key, "<") for sk_i in range(sk_n): - if sk_i > 0: - string.strcat(spec_key, ",") + if sk_i > 0: string.strcat(spec_key, ",") sk_ta: str = type_args.get(sk_i) - if sk_ta is not None: - string.strcat(spec_key, sk_ta) + if sk_ta is not None: string.strcat(spec_key, sk_ta) string.strcat(spec_key, ">") cached: str = self._find_cached_spec(spec_key) if cached is not None: @@ -1393,8 +1300,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): self.Gen.TypeGenResolve.set_current_file(tpl_file_full) self.Gen.TypeGenBase.push_trace(tpl_file_full, template_cd.lineno) self.Gen.ClassGenDef.translate_class_def(trans, spec_cd) - if tpl_file_full is not None: - self.Gen.TypeGenBase.pop_trace() + if tpl_file_full is not None: self.Gen.TypeGenBase.pop_trace() self.Gen.TypeGenResolve.set_current_file(saved_cur_full) # 恢复原始 ModuleSha1 / imports / **类定义窗口**(窗口不平移,见上方说明) trans.ModuleSha1 = saved_module_sha1 diff --git a/App/lib/core/Gen/Class/ClassGenVTable.vp b/App/lib/core/Gen/Class/ClassGenVTable.vp index 4b501f3..bee4cae 100644 --- a/App/lib/core/Gen/Class/ClassGenVTable.vp +++ b/App/lib/core/Gen/Class/ClassGenVTable.vp @@ -35,8 +35,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): def _vtable_strcat(self, dst: str, dst_size: sizet, src: str): """将 src 追加到 dst 末尾""" - if dst is None or src is None: - return + if dst is None or src is None: return dlen: sizet = string.strlen(dst) slen: sizet = string.strlen(src) remain: sizet = dst_size - dlen @@ -51,13 +50,10 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): # ============================================================ def _vtable_name_needs_quote(self, name: str) -> int: """检查 LLVM 标识符是否需要引号(以数字开头或含 '.')""" - if name is None: - return 0 - if '0' <= name[0] <= '9': - return 1 + if name is None: return 0 + if '0' <= name[0] <= '9': return 1 for i in name: - if i == '.': - return 1 + if i == '.': return 1 return 0 # ============================================================ # _collect_vtable_methods — 收集类的虚方法信息 @@ -75,15 +71,13 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): cd: ast.ClassDef*, class_name: str) -> int: """收集虚方法信息,设置 entry.VTableMethods/VTableMethodCount""" - if trans is None or cd is None or class_name is None: - return 0 + if trans is None or cd is None or class_name is None: return 0 pool: memhub.MemBuddy* = trans.Pool mod: mlirlite.LLVMModule* = trans.Module children: list[ast.AST*]* = cd.children - if children is None: - return 0 + if children is None: return 0 cn: sizet = len(children) # 1. 收集虚方法信息 @@ -93,8 +87,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): method_names_buf: sizet* = CompilerFactory.factory.PermPool.alloc(8 * VTBL_METHOD_MAX) # 记录每个方法的父类 SHA1(非 0=继承方法用父模块 SHA1 mangling,0=当前类方法) method_parent_sha1s: sizet* = CompilerFactory.factory.PermPool.alloc(8 * VTBL_METHOD_MAX) - if full_names_buf is None or method_names_buf is None or method_parent_sha1s is None: - return 0 + if full_names_buf is None or method_names_buf is None or method_parent_sha1s is None: return 0 string.memset(full_names_buf, 0, 8 * VTBL_METHOD_MAX) string.memset(method_names_buf, 0, 8 * VTBL_METHOD_MAX) string.memset(method_parent_sha1s, 0, 8 * VTBL_METHOD_MAX) @@ -114,45 +107,36 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): if parent_count > 0: for pi in range(parent_count): pname: str = self.Gen.StructGen.get_parent_name_at(class_name, pi) - if pname is None: - continue + if pname is None: continue # 查找父类 entry(优先同模块 SHA1 匹配) vt_parent_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(pname, trans.ModuleSha1) if vt_parent_entry is None: # 跨模块继承: 父类在不同模块定义(SHA1 不同),回退到按类名查找 vt_parent_entry = self.Gen.StructGen.find_struct(pname) parent_vt_count: int = 0 - if vt_parent_entry is not None: - parent_vt_count = vt_parent_entry.VTableMethodCount + if vt_parent_entry is not None: parent_vt_count = vt_parent_entry.VTableMethodCount if parent_vt_count > 0: for pvi in range(parent_vt_count): - if method_count >= VTBL_METHOD_MAX: - break + if method_count >= VTBL_METHOD_MAX: break pmethod_name: str = None - if vt_parent_entry is not None: - pmethod_name = self.Gen.StructGen.get_vtable_method_name(pname, pvi) - if pmethod_name is None: - continue + if vt_parent_entry is not None: pmethod_name = self.Gen.StructGen.get_vtable_method_name(pname, pvi) + if pmethod_name is None: continue # 多继承 vtable 去重:方法短名已存在跳过(先声明父类优先) - if self.Gen.ClassGenBase._field_name_exists(method_names_buf, method_count, pmethod_name) != 0: - continue + if self.Gen.ClassGenBase._field_name_exists(method_names_buf, method_count, pmethod_name) != 0: continue # 检查子类是否覆盖了该方法,以及是否标记 @t.NoVTable child_overrides: int = 0 child_nvt: int = 0 for ci2 in range(cn): stmt2: ast.AST* = children.get(ci2) - if stmt2 is None: - continue - if stmt2.kind() != ast.ASTKind.FunctionDef: - continue + if stmt2 is None: continue + if stmt2.kind() != ast.ASTKind.FunctionDef: continue fd2: ast.FunctionDef* = ast.FunctionDef*(stmt2) if fd2 is not None and fd2.name is not None: if string.strcmp(fd2.name, pmethod_name) == 0: child_overrides = 1 # 检查子类覆盖方法是否标记 @t.NoVTable if fd2.decorator_list is not None: - if self.Gen.ClassGenBase._has_decorator(fd2.decorator_list, "NoVTable") == 1: - child_nvt = 1 + if self.Gen.ClassGenBase._has_decorator(fd2.decorator_list, "NoVTable") == 1: child_nvt = 1 break # 构造 full_name # 子类覆盖且未标记 NoVTable → 用子类实现 @@ -163,8 +147,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): # 沿父类链向上用 find_func_global("类名.方法名") 探测实际定义类, # 避免生成 "Car.is_running" 这类找不到函数的 full_name → vtable 槽变 null。 def_class: str = class_name - if child_overrides == 1 and child_nvt == 0: - def_class = class_name + if child_overrides == 1 and child_nvt == 0: def_class = class_name else: def_class = pname # 多继承:沿 pname 的 MRO 祖先链探测实际定义类(跳过自身,先声明父类优先) @@ -197,36 +180,26 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): else: # 继承未覆盖: 用实际定义类的模块 SHA1(跨模块继承时 mangling 正确) def_entry2: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(def_class) - if def_entry2 is not None and def_entry2.ModuleSha1 is not None: - method_parent_sha1s[method_count] = sizet(def_entry2.ModuleSha1) - else: - method_parent_sha1s[method_count] = 0 + if def_entry2 is not None and def_entry2.ModuleSha1 is not None: method_parent_sha1s[method_count] = sizet(def_entry2.ModuleSha1) + else: method_parent_sha1s[method_count] = 0 method_count += 1 # 2. 收集当前类的虚方法(跳过已从父类继承的) for ci in range(cn): stmt: ast.AST* = children.get(ci) - if stmt is None: - continue - if stmt.kind() != ast.ASTKind.FunctionDef: - continue + if stmt is None: continue + if stmt.kind() != ast.ASTKind.FunctionDef: continue fd: ast.FunctionDef* = ast.FunctionDef*(stmt) - if fd is None or fd.name is None: - continue - if method_count >= VTBL_METHOD_MAX: - break + if fd is None or fd.name is None: continue + if method_count >= VTBL_METHOD_MAX: break mname: str = fd.name # 跳过构造函数和特殊方法(不应放入虚表) - if string.strcmp(mname, "__init__") == 0: - continue - if string.strcmp(mname, "__before_init__") == 0: - continue - if string.strcmp(mname, "__new__") == 0: - continue + if string.strcmp(mname, "__init__") == 0: continue + if string.strcmp(mname, "__before_init__") == 0: continue + if string.strcmp(mname, "__new__") == 0: continue # 函数级装饰器过滤:判断方法是否应该进入虚表 - if self.Gen.ClassGenBase._should_method_be_virtual(cd, fd, trans) == 0: - continue + if self.Gen.ClassGenBase._should_method_be_virtual(cd, fd, trans) == 0: continue # 检查是否已从父类继承(避免重复) already_in_vt: int = 0 for mi in range(method_count): @@ -236,8 +209,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): if exist_name is not None and string.strcmp(exist_name, mname) == 0: already_in_vt = 1 break - if already_in_vt == 1: - continue + if already_in_vt == 1: continue # 构造 full_name = "ClassName.method_name" # 内容必须落在 perm_pool:1a(mark_only=1)收集的 VTableMethods 被 # Phase 1b 依赖模块翻译跨文件读取,1a 每文件 reset 后 pool 裸字符串悬空 @@ -267,8 +239,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): vt_self_entry.VTableMethodCount = method_count vt_self_entry.VTableMethods = method_names_buf - if method_count == 0: - return 0 + if method_count == 0: return 0 return 1 # ============================================================ # _generate_vtable — 生成 VTable 全局变量 @@ -283,8 +254,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): cd: ast.ClassDef*, class_name: str) -> int: """生成 VTable 全局变量""" - if trans is None or cd is None or class_name is None: - return 0 + if trans is None or cd is None or class_name is None: return 0 pool: memhub.MemBuddy* = trans.Pool @@ -292,8 +262,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): # 收集虚方法信息(继承父类 + 自身,结果存 self.VtFullNames 等暂存区) # 同时设置 entry.VTableMethodCount/VTableMethods(虚分派查询用) - if self._collect_vtable_methods(trans, cd, class_name) == 0: - return 0 + if self._collect_vtable_methods(trans, cd, class_name) == 0: return 0 full_names_buf: sizet* = self.VtFullNames method_names_buf: sizet* = self.VtMethodNames method_parent_sha1s: sizet* = self.VtParentSha1s @@ -309,28 +278,23 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): tail_node: mlirlite.ParamNode* = None for i in range(method_count): pnode: mlirlite.ParamNode* = mlirlite.new_param_node(pool, i8_ptr_ty) - if pnode is None: - continue + if pnode is None: continue tail_node = mlirlite.param_list_append(first_node, tail_node, pnode) - if first_node is None: - first_node = tail_node + if first_node is None: first_node = tail_node vtable_ty: mlirlite.LLVMType* = mlirlite.Struct(pool, first_node, method_count, None) - if vtable_ty is None: - return 0 + if vtable_ty is None: return 0 # 3. 构造初始化字符串 # 大 vtable(如 MemBuddy 28+ 方法)每个方法 bitcast 约 100+ 字节, # 4096 可能写满导致截断/strlen 越界,用 16384 预留足够空间。 init_buf: str = pool.alloc(16384) - if init_buf is None: - return 0 + if init_buf is None: return 0 init_buf[0] = '\0' self._vtable_strcat(init_buf, 16384, "{ ") for i in range(method_count): - if i > 0: - self._vtable_strcat(init_buf, 16384, ", ") + if i > 0: self._vtable_strcat(init_buf, 16384, ", ") full_name_addr: sizet = full_names_buf[i] if full_name_addr == 0: @@ -372,23 +336,20 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): self._vtable_strcat(init_buf, 16384, "\"") self._vtable_strcat(init_buf, 16384, mangled_name) self._vtable_strcat(init_buf, 16384, "\"") - else: - self._vtable_strcat(init_buf, 16384, mangled_name) + else: self._vtable_strcat(init_buf, 16384, mangled_name) self._vtable_strcat(init_buf, 16384, " to i8*)") self._vtable_strcat(init_buf, 16384, " }") # 4. 构造 VTable 全局变量名 vtable_name_buf: str = pool.alloc(128) - if vtable_name_buf is None: - return 0 + if vtable_name_buf is None: return 0 viperlib.snprintf(vtable_name_buf, 128, "%s.vtable", class_name) vtable_mangled: str = self.Gen.FuncGenBase._mangle_name(trans, vtable_name_buf) # 5. 创建全局变量 gv: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, vtable_mangled, vtable_ty) - if gv is None: - return 0 + if gv is None: return 0 gv.Initializer = init_buf gv.IsConstant = 1 # 默认 linkage(external,2026-08-10):isinstance 内建函数需要跨模块 @@ -429,12 +390,10 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): 必须跳过下方 MethodsEmitted==1 的防重复检查强制发射,否则补译 被自身拦截 → 特化方法只有 call 无 define → 链接 undefined symbol。 """ - if trans is None or cd is None or struct_ty is None or class_name is None: - return 0 + if trans is None or cd is None or struct_ty is None or class_name is None: return 0 children: list[ast.AST*]* = cd.children - if children is None: - return 0 + if children is None: return 0 cn: sizet = len(children) has_method: int = 0 @@ -447,43 +406,35 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): # 第一遍:检测是否有方法,标记 OOP,并注册装饰器元数据 for ci in range(cn): stmt: ast.AST* = children.get(ci) - if stmt is None: - continue + if stmt is None: continue if stmt.kind() == ast.ASTKind.FunctionDef: has_method = 1 fd_check: ast.FunctionDef* = ast.FunctionDef*(stmt) if fd_check is not None and fd_check.name is not None: - if string.strcmp(fd_check.name, "__init__") == 0: - has_init = 1 - if string.strcmp(fd_check.name, "__new__") == 0: - has_new = 1 + if string.strcmp(fd_check.name, "__init__") == 0: has_init = 1 + if string.strcmp(fd_check.name, "__new__") == 0: has_new = 1 # 注册装饰器元数据(@property/@staticmethod/@classmethod/@x.setter 等)。 # 此处(含 mark_only=1 的 struct 预注册阶段)注册, # 确保其他模块在 App 文件翻译时能识别属性访问。 fd_meta: int = self.Gen.ClassGenBase._extract_func_meta(fd_check.decorator_list) - if fd_meta != 0: - self.Gen.ClassGenBase.register_method_meta(class_name, fd_check.name, fd_meta) + if fd_meta != 0: self.Gen.ClassGenBase.register_method_meta(class_name, fd_check.name, fd_meta) if has_method == 0: # 子类没有自己的方法,但可能继承了父类的虚方法 # 用 oop_entry 直接获取 ParentName,规避 find_struct 按名查找找错 parent_name: str = None - if oop_entry is not None: - parent_name = oop_entry.ParentName + if oop_entry is not None: parent_name = oop_entry.ParentName if parent_name is not None: parent_vt_count: int = self.Gen.StructGen.get_vtable_method_count(parent_name) if parent_vt_count > 0: has_method = 1 # 标记为有方法(继承的虚方法) - if has_method == 0: - return 0 + if has_method == 0: return 0 # 标记为 OOP 结构体 if oop_entry is not None: oop_entry.IsOOP = 1 - if has_init != 0: - oop_entry.HasInit = 1 - if has_new != 0: - oop_entry.HasNew = 1 + if has_init != 0: oop_entry.HasInit = 1 + if has_new != 0: oop_entry.HasNew = 1 # mark_only 模式:只设置标志,不翻译方法体 if mark_only != 0: @@ -493,10 +444,8 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): # None)→ __new__ 返回 null → 崩溃。短名顺序与 Phase 1b 全量收集一致 # (父类方法在前 + 本类方法);多遍重复收集用新缓冲区覆盖(幂等)。 mk_has_vt: int = 0 - if oop_entry is not None: - mk_has_vt = oop_entry.HasVTable - if mk_has_vt == 1: - self._collect_vtable_methods(trans, cd, class_name) + if oop_entry is not None: mk_has_vt = oop_entry.HasVTable + if mk_has_vt == 1: self._collect_vtable_methods(trans, cd, class_name) return 0 # 防重复生成:MethodsEmitted==1 说明方法体/__before_init__ 已生成过。 @@ -506,15 +455,13 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): # 已生成过则直接跳过(方法+__before_init__ 都产出过,跳过安全)。 # reemit=1(补译模式)时跳过本检查:补译分支为防重入已提前置 # MethodsEmitted=1,但方法体尚未发射,必须强制发射。 - if oop_entry is not None and oop_entry.MethodsEmitted == 1 and reemit == 0: - return 0 + if oop_entry is not None and oop_entry.MethodsEmitted == 1 and reemit == 0: return 0 # 防重入:方法体翻译前先标记 MethodsEmitted=1。 # 根因:若等全部方法译完再标记,翻译 __iter__(返回 list[T]*)时, # 返回类型注解会再次触发 _specialize_generic_class,此时 MethodsEmitted # 仍为 0,走补译分支把同一特化类方法全部重发 → invalid redefinition。 - if oop_entry is not None: - oop_entry.MethodsEmitted = 1 + if oop_entry is not None: oop_entry.MethodsEmitted = 1 # 第二遍:翻译每个方法 # 翻译方法体前先预注册 vtable 元数据(VTableMethods/VTableMethodCount)。 @@ -523,10 +470,8 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): # VTableMethods,虚分派失败,被静态绑定到本类实现(基类 alloc 返回 # None),导致 calloc 永远返回 NULL。 oop_has_vt_pre: int = 0 - if oop_entry is not None: - oop_has_vt_pre = oop_entry.HasVTable - if oop_has_vt_pre == 1: - self._collect_vtable_methods(trans, cd, class_name) + if oop_entry is not None: oop_has_vt_pre = oop_entry.HasVTable + if oop_has_vt_pre == 1: self._collect_vtable_methods(trans, cd, class_name) # 先声明后定义:翻译方法体之前,先为本类**全部方法**建立前向声明 # (declare + 参数 + 函数表登记),使方法查找(find_func_in_module)不再 @@ -537,30 +482,24 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): # FileW* → File* 报 CastError(旧 IR 靠 bitcast 静默掩盖)。 for ci_pd in range(cn): stmt_pd: ast.AST* = children.get(ci_pd) - if stmt_pd is None: - continue + if stmt_pd is None: continue if stmt_pd.kind() == ast.ASTKind.FunctionDef: fd_pd: ast.FunctionDef* = ast.FunctionDef*(stmt_pd) - if fd_pd is not None and fd_pd.name is not None: - self._translate_method(trans, fd_pd, struct_ty, class_name, 1) + if fd_pd is not None and fd_pd.name is not None: self._translate_method(trans, fd_pd, struct_ty, class_name, 1) for ci in range(cn): stmt: ast.AST* = children.get(ci) - if stmt is None: - continue + if stmt is None: continue if stmt.kind() == ast.ASTKind.FunctionDef: fd: ast.FunctionDef* = ast.FunctionDef*(stmt) - if fd is not None and fd.name is not None: - self._translate_method(trans, fd, struct_ty, class_name) + if fd is not None and fd.name is not None: self._translate_method(trans, fd, struct_ty, class_name) # 如果有虚表,先生成 VTable 全局变量(设置 VTableMethodCount) # 必须在 __before_init__ 之前,否则 __before_init__ 读不到 VTableMethodCount # 用 oop_entry 直接检查,规避跨模块同名 find_struct 找错 has_vt_flag: int = 0 - if oop_entry is not None: - has_vt_flag = oop_entry.HasVTable - if has_vt_flag == 1: - self._generate_vtable(trans, cd, class_name) + if oop_entry is not None: has_vt_flag = oop_entry.HasVTable + if has_vt_flag == 1: self._generate_vtable(trans, cd, class_name) # 生成 __before_init__ 函数(零值填充 + 默认值赋值 + vtable 指针设置) self._generate_before_init(trans, struct_ty, class_name) @@ -591,8 +530,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): 查不到 FileW.seek,会落到"同名方法扫描"并误绑 File.seek,再被指针 规则以 FileW* → File* 报 CastError。 """ - if trans is None or fd is None or struct_ty is None or class_name is None: - return 0 + if trans is None or fd is None or struct_ty is None or class_name is None: return 0 pool: memhub.MemBuddy* = trans.Pool @@ -615,34 +553,27 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): func_meta: int = self.Gen.ClassGenBase._extract_func_meta(fd.decorator_list) # property setter/deleter 函数名带 $set/$del 后缀,避免与 getter 冲突 method_name_buf: str = pool.alloc(128) - if method_name_buf is None: - return 0 + if method_name_buf is None: return 0 viperlib.snprintf(method_name_buf, 128, "%s", fd.name) if func_meta & GenTypes.META_PROP_SETTER != 0: # 128 字节缓冲:追加 "$set" 前检查剩余容量,防 strcat 无界写穿 mn_len2: sizet = string.strlen(method_name_buf) - if mn_len2 + 5 < 128: - string.strcat(method_name_buf, "$set") + if mn_len2 + 5 < 128: string.strcat(method_name_buf, "$set") elif func_meta & GenTypes.META_PROP_DELETER != 0: mn_len2: sizet = string.strlen(method_name_buf) - if mn_len2 + 5 < 128: - string.strcat(method_name_buf, "$del") + if mn_len2 + 5 < 128: string.strcat(method_name_buf, "$del") method_name = method_name_buf is_static_m: int = 0 is_class_m: int = 0 is_tls_m: int = 0 - if func_meta & GenTypes.META_STATIC != 0: - is_static_m = 1 - if func_meta & GenTypes.META_CLASS != 0: - is_class_m = 1 - if func_meta & META_TLS != 0: - is_tls_m = 1 + if func_meta & GenTypes.META_STATIC != 0: is_static_m = 1 + if func_meta & GenTypes.META_CLASS != 0: is_class_m = 1 + if func_meta & META_TLS != 0: is_tls_m = 1 # 构建方法全名: ClassName.method_name full_name_buf: str = pool.alloc(128) - if full_name_buf is None: - return 0 + if full_name_buf is None: return 0 viperlib.snprintf(full_name_buf, 128, "%s.%s", class_name, method_name) full_name: str = full_name_buf @@ -651,8 +582,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): # 推断返回类型 ret_ty: mlirlite.LLVMType* = None - if fd.returns is not None: - ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, imported_modules, from_imports, trans, 0) + if fd.returns is not None: ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, imported_modules, from_imports, trans, 0) if ret_ty is None and fd.returns is not None: # 存储类标记(t.State / t.CExport / t.CExtern)语义为 Void:这类注解 # 不携带真实返回类型(extern/export 语法写成 "<原类型> | t.<标记>", @@ -666,11 +596,9 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): return 0 if ret_ty is None: # __init__ 和 __before_init__ 返回 void - if string.strcmp(method_name, "__init__") == 0: - ret_ty = mlirlite.Void(pool) + if string.strcmp(method_name, "__init__") == 0: ret_ty = mlirlite.Void(pool) # __new__ 返回 Ptr(struct_ty)(结构体指针作为存储空间) - elif string.strcmp(method_name, "__new__") == 0: - ret_ty = mlirlite.Ptr(pool, struct_ty) + elif string.strcmp(method_name, "__new__") == 0: ret_ty = mlirlite.Ptr(pool, struct_ty) else: 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) @@ -690,13 +618,11 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): decl_reuse = 1 else: func = mlirlite.create_declare(pool, mod, mangled_name, ret_ty) - if func is None: - return 0 + if func is None: return 0 if sig_only != 0: # 前向声明模式:已声明过直接返回;否则下方登记完参数/函数表后返回。 - if decl_reuse != 0: - return 0 + if decl_reuse != 0: return 0 else: # 发射函数体前必须把 IsDeclared 清零,否则打印端按 IsDeclared 输出 # declare、函数体整体丢失(对齐 FuncGenDef.vp:544-545)。 @@ -720,10 +646,8 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): md_ags: ast.Arguments* = ast.Arguments*(md_args_node) if md_ags.args is not None: md_alist: list[ast.AST*]* = md_ags.args - if is_static_m != 0: - md_param_count = len(md_alist) - else: - md_param_count = len(md_alist) - 1 + if is_static_m != 0: md_param_count = len(md_alist) + else: md_param_count = len(md_alist) - 1 if md_ags.defaults is not None: md_dlist: list[ast.AST*]* = md_ags.defaults md_defaults = md_dlist @@ -744,11 +668,9 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): fd_ags: ast.Arguments* = ast.Arguments*(fd.args) if fd_ags.args is not None and len(fd_ags.args) > 0: fd_first_arg: ast.Arg* = ast.Arg*(fd_ags.args.get(0)) - if fd_first_arg is not None and fd_first_arg.arg is not None: - first_pname = fd_first_arg.arg + if fd_first_arg is not None and fd_first_arg.arg is not None: first_pname = fd_first_arg.arg first_pname_buf: str = pool.alloc(32) - if first_pname_buf is not None: - viperlib.snprintf(first_pname_buf, 32, "%%%s", first_pname) + if first_pname_buf is not None: viperlib.snprintf(first_pname_buf, 32, "%%%s", first_pname) mlirlite.add_param(pool, func, self_ptr_ty, first_pname_buf) # 添加其他参数(支持类型注解;@staticmethod 从索引 0 开始,其余跳过索引 0 的 self/cls) @@ -759,8 +681,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): alist: list[ast.AST*]* = ags.args an: sizet = len(alist) start_idx: int = 0 - if is_static_m == 0: - start_idx = 1 + if is_static_m == 0: start_idx = 1 for ai in range(start_idx, an): arg: ast.Arg* = ast.Arg*(alist.get(ai)) if arg is not None and arg.arg is not None: @@ -791,8 +712,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): case _: param_ty = resolved pname: str = pool.alloc(32) - if pname is not None: - viperlib.snprintf(pname, 32, "%%%s", arg.arg) + if pname is not None: viperlib.snprintf(pname, 32, "%%%s", arg.arg) mlirlite.add_param(pool, func, param_ty, pname) # OOP iter 协议:__next__ 方法注入隐藏参数 __stop_iter_flag__(i1*)。 @@ -802,25 +722,21 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): i1_ty_si: mlirlite.LLVMType* = mlirlite.Int1(pool) if i1_ty_si is not None: i1_ptr_ty_si: mlirlite.LLVMType* = mlirlite.Ptr(pool, i1_ty_si) - if i1_ptr_ty_si is not None: - mlirlite.add_param(pool, func, i1_ptr_ty_si, "%__stop_iter_flag__") + if i1_ptr_ty_si is not None: mlirlite.add_param(pool, func, i1_ptr_ty_si, "%__stop_iter_flag__") # 参数添加完成,补全全局函数表的 Spec(供 vtable 在 func 被 reset 后派生类型文本) self.Gen.CallGenLeafKit.update_global_func_spec(full_name, func) # 前向声明模式:签名与函数表登记已完成,不发射函数体 - if sig_only != 0: - return 0 + if sig_only != 0: return 0 # 创建 entry 块 entry_blk: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "entry") - if entry_blk is None: - return 0 + if entry_blk is None: return 0 # 创建方法专属 builder func_builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, func) - if func_builder is None: - return 0 + if func_builder is None: return 0 mlirlite.position_at_end(func_builder, entry_blk) # --traceback: attach a DISubprogram to this method define (same as the @@ -862,20 +778,16 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): mlirlite.build_ret_void(func_builder) case mlirlite.LLVMType.Int(_): tlm0: mlirlite.Value* = mlirlite.ConstInt(pool, ret_ty, 0, "0") - if tlm0 is not None: - mlirlite.build_ret(func_builder, tlm0) + if tlm0 is not None: mlirlite.build_ret(func_builder, tlm0) case mlirlite.LLVMType.Float(_): tlmf: mlirlite.Value* = mlirlite.ConstFloat(pool, ret_ty, 0.0) - if tlmf is not None: - mlirlite.build_ret(func_builder, tlmf) + if tlmf is not None: mlirlite.build_ret(func_builder, tlmf) case _: tlmn: mlirlite.Value* = mlirlite.ConstNull(pool, ret_ty, "null") - if tlmn is not None: - mlirlite.build_ret(func_builder, tlmn) + if tlmn is not None: mlirlite.build_ret(func_builder, tlmn) mlirlite.position_at_end(func_builder, tls_m_cont) tlmo: mlirlite.Value* = mlirlite.ConstInt(pool, i1_ty_m, 1, "1") - if tlmo is not None: - mlirlite.build_store(func_builder, tlmo, tls_m_ref) + if tlmo is not None: mlirlite.build_store(func_builder, tlmo, tls_m_ref) # 进入函数作用域 self.Gen.VarGen.enter_scope(trans.SymTab, SCOPE_FUNCTION) @@ -912,8 +824,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): alist2: list[ast.AST*]* = ags2.args an2: sizet = len(alist2) start_idx2: int = 0 - if is_static_m == 0: - start_idx2 = 1 + if is_static_m == 0: start_idx2 = 1 for ai2 in range(start_idx2, an2): arg2: ast.Arg* = ast.Arg*(alist2.get(ai2)) if arg2 is not None and arg2.arg is not None: @@ -945,11 +856,9 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): # 传 pool:泛型 Subscript 返回 mangled name(对齐 HandlesAnnAssign 修复) if arg2.annotation is not None: cls_nm_oc: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(arg2.annotation, imported_modules, pool, trans._from_imports) - if cls_nm_oc is not None: - self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, arg2.arg, cls_nm_oc) + if cls_nm_oc is not None: self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, arg2.arg, cls_nm_oc) pname2: str = pool.alloc(32) - if pname2 is not None: - viperlib.snprintf(pname2, 32, "%%%s", arg2.arg) + if pname2 is not None: viperlib.snprintf(pname2, 32, "%%%s", arg2.arg) param_val: mlirlite.Value* = mlirlite.SSAValue(pool, param_ty2, pname2) mlirlite.build_store(func_builder, param_val, alloca) @@ -965,8 +874,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): if flag_ref_sf is not None: trans._stop_iter_flag_ptr = flag_ref_sf zero_i1_sf: mlirlite.Value* = mlirlite.ConstInt(pool, i1_ty_sf, 0, "0") - if zero_i1_sf is not None: - mlirlite.build_store(func_builder, zero_i1_sf, flag_ref_sf) + if zero_i1_sf is not None: mlirlite.build_store(func_builder, zero_i1_sf, flag_ref_sf) # 保存模块级作用域状态 old_func: mlirlite.Function* = trans._cur_func @@ -990,20 +898,17 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): bn: sizet = len(body) for bi in range(bn): stmt: ast.AST* = body.get(bi) - if stmt is not None: - self.Gen.StmtGenDecl.pre_scan_scope_decls(trans, stmt) + if stmt is not None: self.Gen.StmtGenDecl.pre_scan_scope_decls(trans, stmt) for bi in range(bn): stmt: ast.AST* = body.get(bi) - if stmt is not None: - self.Gen.StmtGenDecl.pre_scan_allocas(trans, stmt) + if stmt is not None: self.Gen.StmtGenDecl.pre_scan_allocas(trans, stmt) # 翻译方法体 if body is not None: bn2: sizet = len(body) for bi2 in range(bn2): stmt2: ast.AST* = body.get(bi2) - if stmt2 is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt2) + if stmt2 is not None: self.Gen.StmtGen.translate_stmt(trans, stmt2) # 方法末尾收尾与模块级函数(FuncGenMixin.translate_function_def)同语义—— # 编译器不替代码发明返回值,三种合法收尾: @@ -1021,8 +926,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): bn3 = len(body) if bn3 > 0: last_stmt_m: ast.AST* = body.get(bn3 - 1) - if last_stmt_m is not None and last_stmt_m.kind() == ast.ASTKind.Return: - last_is_return = 1 + if last_stmt_m is not None and last_stmt_m.kind() == ast.ASTKind.Return: last_is_return = 1 if last_is_return == 0: if mlirlite.builder_cur_block_is_terminated(func_builder) == 0: last_is_ctrl: int = 0 @@ -1048,14 +952,11 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): # TypeGenResolve._is_cvoid_marker(TypeGenResolve.vp:1484) # ③ -> None(CONST_NONE):解析即 Void(TypeGenResolve.vp:1996-1999) if _is_void == 0 and fd.returns is not None: - if self.Gen.TypeGenResolve._is_cvoid_marker(fd.returns, imported_modules) != 0: - _is_void = 1 + if self.Gen.TypeGenResolve._is_cvoid_marker(fd.returns, imported_modules) != 0: _is_void = 1 elif fd.returns.kind() == ast.ASTKind.Constant: ret_none_cn_m: ast.Constant* = (ast.Constant*)(fd.returns) - if ret_none_cn_m.const_kind == ast.CONST_NONE: - _is_void = 1 - if _is_void != 0: - mlirlite.build_ret_void(func_builder) + if ret_none_cn_m.const_kind == ast.CONST_NONE: _is_void = 1 + if _is_void != 0: mlirlite.build_ret_void(func_builder) elif last_is_ctrl != 0 and trans._ctrl_merge_reachable == 0: # 非 void 方法末句是控制流且 merge 块**结构性**不可达(全分支 return,无 br # 到 merge)→ LLVM 语义 unreachable。merge 可达时须正常收尾(下方 @@ -1067,27 +968,22 @@ 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") + 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: # fail-fast:有 -> 注解但流程真实掉出末尾(traceback 风格) if ret_ty is not None: rt_name_m: str = pool.alloc(512) if rt_name_m is not None: mlirlite.TypePrint(rt_name_m, 512, ret_ty, pool) - if rt_name_m[0] == '\0': - rt_name_m = "?" + 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) 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") + else: self.Gen.TypeGenErr.fatal_error(fd, "方法流程掉出末尾但未显式 return", "TypeError") # 恢复模块级作用域 self.Gen.VarGen.exit_scope(trans.SymTab) @@ -1098,8 +994,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): trans._closure_env_count = old_env_count trans._stop_iter_flag_ptr = old_stop_iter_flag - if dbg_pushed != 0: - DebugInfoGen.PopFunction(func_builder) + if dbg_pushed != 0: DebugInfoGen.PopFunction(func_builder) return 0 # ============================================================ @@ -1116,8 +1011,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): struct_ty: mlirlite.LLVMType*, class_name: str) -> int: """生成 __before_init__ 函数,返回 0""" - if trans is None or struct_ty is None or class_name is None: - return 0 + if trans is None or struct_ty is None or class_name is None: return 0 pool: memhub.MemBuddy* = trans.Pool @@ -1159,8 +1053,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): # 注册到函数表 max_funcs: int = 1024 rc_add: int = self.Gen.CallGenLeafKit.add_func_to_table(funcs_ptr, func_count, full_name, func, max_funcs, None, 0, 0, pool) - if rc_add == 0: - trans._func_count = func_count + 1 + if rc_add == 0: trans._func_count = func_count + 1 if bi_decl_reuse != 0: # 复用前向声明:self 参数已由 _ensure_method_declare 添加(无名), @@ -1196,19 +1089,16 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): struct_fcount_zi: int = mlirlite.get_struct_fcount(struct_ty) if struct_fcount_zi > 0: zero: mlirlite.Value* = mlirlite.ConstZero(pool, struct_ty) - if zero is not None: - mlirlite.build_store(func_builder, zero, self_val) + if zero is not None: mlirlite.build_store(func_builder, zero, self_val) # 1.5 如果有虚表,store vtable 全局地址到 __vtable__ 字段(索引 0) # 用 find_struct_by_type 定位 entry,规避跨模块同名 find_struct 找错 bi_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_type(struct_ty) bi_has_vt: int = 0 - if bi_entry is not None: - bi_has_vt = bi_entry.HasVTable + if bi_entry is not None: bi_has_vt = bi_entry.HasVTable if bi_has_vt == 1: vt_method_count: int = 0 - if bi_entry is not None: - vt_method_count = bi_entry.VTableMethodCount + if bi_entry is not None: vt_method_count = bi_entry.VTableMethodCount if vt_method_count > 0: # 构造 vtable 类型 { i8*, i8*, ..., i8* } vt_i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) @@ -1218,12 +1108,9 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): vt_prev_node: mlirlite.ParamNode* = None for vti in range(vt_method_count): vtnode: mlirlite.ParamNode* = mlirlite.new_param_node(pool, vt_i8_ptr_ty) - if vtnode is None: - continue - if vt_first_node is None: - vt_first_node = vtnode - if vt_prev_node is not None: - mlirlite.paramnode_set_next(vt_prev_node, vtnode) + if vtnode is None: continue + if vt_first_node is None: vt_first_node = vtnode + if vt_prev_node is not None: mlirlite.paramnode_set_next(vt_prev_node, vtnode) vt_prev_node = vtnode vt_ty: mlirlite.LLVMType* = mlirlite.Struct(pool, vt_first_node, vt_method_count, None) @@ -1248,23 +1135,19 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): vt_ref_name: str = pool.alloc(256) if vt_ref_name is not None: vt_ref_name[0] = '\0' - if self._vtable_name_needs_quote(vt_mangled) != 0: - viperlib.snprintf(vt_ref_name, 256, "@\"%s\"", vt_mangled) - else: - viperlib.snprintf(vt_ref_name, 256, "@%s", vt_mangled) + if self._vtable_name_needs_quote(vt_mangled) != 0: viperlib.snprintf(vt_ref_name, 256, "@\"%s\"", vt_mangled) + else: viperlib.snprintf(vt_ref_name, 256, "@%s", vt_mangled) mlirlite.value_set_name(vt_ref, vt_ref_name) # bitcast 到 i8* vt_as_i8: mlirlite.Value* = mlirlite.build_bitcast(func_builder, vt_ref, vt_i8_ptr_ty) - if vt_as_i8 is not None: - mlirlite.build_store(func_builder, vt_as_i8, vt_slot) + if vt_as_i8 is not None: mlirlite.build_store(func_builder, vt_as_i8, vt_slot) # 2. 逐字段 store 默认值(用 bi_entry 直接访问,规避跨模块同名 find_struct 找错) if bi_entry is not None: for fi in range(bi_entry.FieldCount): fe: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(bi_entry, fi) - if fe is None or fe.DefaultVal is None: - continue + if fe is None or fe.DefaultVal is None: continue # 静态数组字段 + 列表字面量默认值 → 整体置零 + 逐元素 GEP+store # (与局部 AnnAssign 数组初始化一致;translate_value 会把列表字面量 # 误译成动态 list 对象指针,coerce 到 [N x elem] 会失败)。 @@ -1274,8 +1157,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): field_ptr_arr: mlirlite.Value* = mlirlite.build_gep_struct(func_builder, struct_ty, fe.Ty, self_val, fe.Index) if field_ptr_arr is not None: zero_arr_f: mlirlite.Value* = mlirlite.ConstZero(pool, fe.Ty) - if zero_arr_f is not None: - mlirlite.build_store(func_builder, zero_arr_f, field_ptr_arr) + if zero_arr_f is not None: mlirlite.build_store(func_builder, zero_arr_f, field_ptr_arr) # Mixin 静态绑定:self._xxx 只沿本类查找,跨 Mixin 方法 # (AssignGenMixin._init_global_array_from_list)会生成不存在 # 符号 → 必须走 HandlesAnnAssign 模块级委托(延迟 import Gen)。 diff --git a/App/lib/core/Gen/DebugInfoGen.vp b/App/lib/core/Gen/DebugInfoGen.vp index 5d33906..34fa2f3 100644 --- a/App/lib/core/Gen/DebugInfoGen.vp +++ b/App/lib/core/Gen/DebugInfoGen.vp @@ -69,10 +69,8 @@ _g_loc_used: bytes = None def SetEnabled(flag: bool) -> int: """Enable/disable DI emission (mirrors BuildPipeline._traceback_mode).""" global _g_enabled - if flag: - _g_enabled = 1 - else: - _g_enabled = 0 + if flag: _g_enabled = 1 + else: _g_enabled = 0 # 把同一开关转达给 mlirlite 的调试调用点记录(--traceback 时我们自产 # .vpcall 旁文件,供 WriteStackMap 结合 objdump 还原调用点行号)。 mlirlite.DebugSetEnabled(flag) @@ -88,8 +86,7 @@ def IsEnabled() -> int: # ============================================================ def _EnsureStorage() -> int: global _g_stk_sp, _g_stk_ref, _g_stk_bld, _g_loc_key, _g_loc_ref, _g_loc_used - if _g_stk_sp is not None: - return 0 + if _g_stk_sp is not None: return 0 sbuf1: bytes = stdlib.malloc(DBG_STACK_MAX * 8) sbuf2: bytes = stdlib.malloc(DBG_STACK_MAX * 8) sbuf3: bytes = stdlib.malloc(DBG_STACK_MAX * 8) @@ -117,8 +114,7 @@ def _EnsureStorage() -> int: def _RefOf(pool: memhub.MemBuddy*, node_id: int) -> str: """Allocate a persistent "!N" reference string for a DI node id.""" buf: str = pool.alloc(24) - if buf is None: - return None + if buf is None: return None viperlib.snprintf(buf, 24, "!%d", node_id) return buf @@ -130,10 +126,8 @@ def BeginModule(mod: mlirlite.LLVMModule*, file_path: str) -> int: """Reset per-module DI state. Call once at the start of each module.""" global _g_mod, _g_file_path, _g_abs_file_path, _g_finalized, _g_file_id, _g_null_id global _g_subtype_id, _g_cu_id, _g_cur_sp, _g_cur_entry_ref, _g_cur_builder, _g_depth - if _g_enabled == 0: - return 0 - if _EnsureStorage() != 0: - return 1 + if _g_enabled == 0: return 0 + if _EnsureStorage() != 0: return 1 _g_mod = mod _g_file_path = file_path _g_abs_file_path = None @@ -149,8 +143,7 @@ def BeginModule(mod: mlirlite.LLVMModule*, file_path: str) -> int: _g_cur_entry_ref = None _g_cur_builder = None _g_depth = 0 - if _g_loc_used is not None: - string.memset(_g_loc_used, 0, DBG_LOC_SLOTS) + if _g_loc_used is not None: string.memset(_g_loc_used, 0, DBG_LOC_SLOTS) return 0 @@ -160,11 +153,9 @@ def BeginModule(mod: mlirlite.LLVMModule*, file_path: str) -> int: # ============================================================ def _EnsureModuleNodes(pool: memhub.MemBuddy*) -> int: global _g_file_id, _g_null_id, _g_subtype_id, _g_cu_id, _g_abs_file_path - if _g_cu_id >= 0: - return 0 + if _g_cu_id >= 0: return 0 mod: mlirlite.LLVMModule* = _g_mod - if mod is None: - return 1 + if mod is None: return 1 # DIFile: **绝对**路径(正斜杠),filename 保留整条路径。 # 为什么必须绝对:本工程给 CurrentFile 的是**项目相对**路径(如 # "./Test/LLvmLiteTest/App/main.vp"),LLVM 会把该目录写成 CU 的 DW_AT_comp_dir, @@ -176,16 +167,14 @@ def _EnsureModuleNodes(pool: memhub.MemBuddy*) -> int: # 还是把它拆成 dir+basename(dir_index 指向同一个绝对目录 ⇒ 拼回绝对路径), # 结果都是绝对路径 —— 故本改动不需要动写入端。 src: str = _g_file_path - if src is None: - src = "" + if src is None: src = "" slen: sizet = string.strlen(src) cap_n: sizet = slen + 4112 nbuf: str = pool.alloc(cap_n) if nbuf is None: VLogger.error("--traceback: DIFile 路径缓冲分配失败,终止编译", "DWARF") return 1 - if slen > 0: - string.strncpy(nbuf, src, slen) + if slen > 0: string.strncpy(nbuf, src, slen) nbuf[slen] = '\0' if slen > 0 and nbuf[0] != '/' and not (slen >= 2 and nbuf[1] == ':'): # 相对路径 → 前置当前工作目录。用 w32file 低层调用(同 Repl.vp), @@ -202,8 +191,7 @@ def _EnsureModuleNodes(pool: memhub.MemBuddy*) -> int: flen: sizet = string.strlen(nbuf) ni: sizet = 0 for ni in range(flen): - if nbuf[ni] == '\\': - nbuf[ni] = '/' + if nbuf[ni] == '\\': nbuf[ni] = '/' # 保存绝对路径供 mlirlite 调试调用点记录复用(.vpcall 旁文件里的文件路径口径 # 必须与 DIFile 一致:绝对 + 正斜杠,运行期才能按路径重读源码行)。 _g_abs_file_path = nbuf @@ -273,26 +261,20 @@ def _LocRefAt(slot: int) -> str: # _EnsureLocation - DILocation ref for (sp, line, col), created + cached once # ============================================================ def _EnsureLocation(pool: memhub.MemBuddy*, sp: int, line: int, col: int) -> str: - if line <= 0: - return _g_cur_entry_ref + if line <= 0: return _g_cur_entry_ref c: int = col - if c <= 0: - c = 1 - if _g_loc_used is None or _g_mod is None: - return None + if c <= 0: c = 1 + if _g_loc_used is None or _g_mod is None: return None h: uint64 = (uint64(sp) * 1000003 + uint64(line) * 31 + uint64(c)) & uint64(DBG_LOC_SLOTS - 1) pi: int = 0 while pi < DBG_LOC_PROBE: slot: int = int((h + uint64(pi)) & uint64(DBG_LOC_SLOTS - 1)) - if _g_loc_used[slot] == 0: - break + if _g_loc_used[slot] == 0: break kbase: int = slot * DBG_LOC_KEY_STRIDE - if int(_g_loc_key[kbase]) == sp and int(_g_loc_key[kbase + 1]) == line and int(_g_loc_key[kbase + 2]) == c: - return _LocRefAt(slot) + if int(_g_loc_key[kbase]) == sp and int(_g_loc_key[kbase + 1]) == line and int(_g_loc_key[kbase + 2]) == c: return _LocRefAt(slot) pi += 1 lbuf: str = pool.alloc(96) - if lbuf is None: - return None + if lbuf is None: return None 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: @@ -326,25 +308,20 @@ def PushFunction(pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, ", !dbg !N" until the next SetStatement. """ global _g_cur_sp, _g_cur_entry_ref, _g_cur_builder, _g_depth - 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_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") return 0 - if _EnsureModuleNodes(pool) != 0: - return 0 + if _EnsureModuleNodes(pool) != 0: return 0 name: str = mlirlite.function_get_name(func) if name is None: VLogger.error("--traceback: 函数名为空,无法发射 DISubprogram,终止编译", "DWARF") return 0 dline: int = line - if dline <= 0: - dline = 1 + if dline <= 0: dline = 1 dcol: int = col - if dcol <= 0: - dcol = 1 + if dcol <= 0: dcol = 1 ssize: sizet = string.strlen(name) + 320 spbuf: str = pool.alloc(ssize) if spbuf is None: @@ -388,18 +365,15 @@ def PushFunction(pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, # ============================================================ def PopFunction(builder: mlirlite.IRBuilder*) -> int: global _g_cur_sp, _g_cur_entry_ref, _g_cur_builder, _g_depth - if _g_enabled == 0: - return 0 - if _g_depth <= 0: - return 0 + if _g_enabled == 0: return 0 + if _g_depth <= 0: return 0 _g_depth -= 1 _g_cur_sp = int(_g_stk_sp[_g_depth]) - 1 rslot: str* = (str*)(uint64(_g_stk_ref) + sizet(_g_depth) * 8) _g_cur_entry_ref = rslot[0] bslot: str* = (str*)(uint64(_g_stk_bld) + sizet(_g_depth) * 8) _g_cur_builder = (mlirlite.IRBuilder*)(bslot[0]) - if builder is not None: - mlirlite.builder_clear_debug_location(builder) + if builder is not None: mlirlite.builder_clear_debug_location(builder) # 离开本 define:恢复 mlirlite 记录的外层函数上下文(嵌套 define 用)。 mlirlite.DebugClearFunc() return 0 @@ -415,15 +389,12 @@ def SetStatement(pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, No-op outside a DI-attached define (module-level code / synthetic defines), so instructions outside a function body never reference a function's scope. """ - if _g_enabled == 0 or pool is None or builder is None: - return 0 + if _g_enabled == 0 or pool is None or builder is None: return 0 # 记录当前语句行:随后本语句内 build_call 产生的 C 记录以它作为调用点行。 mlirlite.DebugNoteLine(line) - if _g_cur_sp < 0: - return 0 + if _g_cur_sp < 0: return 0 ref: str = _EnsureLocation(pool, _g_cur_sp, line, col) - if ref is None: - return 0 + if ref is None: return 0 mlirlite.builder_set_debug_location(builder, ref) return 1 @@ -432,16 +403,13 @@ def SetStatement(pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, # _ModuleHasDefine - does the module emit any define (IsDeclared == 0)? # ============================================================ def _ModuleHasDefine(mod: mlirlite.LLVMModule*) -> int: - if mod is None: - return 0 + if mod is None: return 0 cur: mlirlite.Function* = mod.FuncHead steps: int = 0 while cur is not None: steps += 1 - if steps > 100000: - break - if mlirlite.function_is_declared(cur) == 0: - return 1 + if steps > 100000: break + if mlirlite.function_is_declared(cur) == 0: return 1 cur = mlirlite.function_get_next(cur) return 0 @@ -452,20 +420,15 @@ def _ModuleHasDefine(mod: mlirlite.LLVMModule*) -> int: def Finalize(pool: memhub.MemBuddy*) -> int: """Module-level DI tail; idempotent per module, no-op when no SP was emitted.""" global _g_finalized - if _g_enabled == 0: - return 0 - if _g_finalized != 0: - return 0 + if _g_enabled == 0: return 0 + if _g_finalized != 0: return 0 mod: mlirlite.LLVMModule* = _g_mod - if mod is None or pool is None: - return 0 + if mod is None or pool is None: return 0 _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 _g_cu_id < 0: - return 0 + if mod.DIMetaCount == 0 and _ModuleHasDefine(mod) != 0: VLogger.warning("--traceback: 本模块发射了 define 但 IR 未携带 DWARF (!llvm.dbg.cu)——该模块帧在 Ctrl+C 栈里将只显示地址", "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") diff --git a/App/lib/core/Gen/Expr/ExprGenAttr.vp b/App/lib/core/Gen/Expr/ExprGenAttr.vp index e063db8..6075c56 100644 --- a/App/lib/core/Gen/Expr/ExprGenAttr.vp +++ b/App/lib/core/Gen/Expr/ExprGenAttr.vp @@ -32,15 +32,13 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): def find_global_in_module(self, mod: mlirlite.LLVMModule*, name: str) -> mlirlite.GlobalVariable*: """在模块全局变量链表中按名称查找全局变量""" - if mod is None or name is None: - return None + if mod is None or name is None: return None name_len: sizet = string.strlen(name) cur: mlirlite.GlobalVariable* = mod.GlobalHead # 第一遍: 精确匹配 while cur is not None: if cur.Name is not None: - if string.strcmp(cur.Name, name) == 0: - return cur + if string.strcmp(cur.Name, name) == 0: return cur cur = cur.Next # 第二遍: 后缀匹配 (.name) cur = mod.GlobalHead @@ -55,8 +53,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if cur.Name[suffix_start + i] != name[i]: Matched = 0 break - if Matched == 1: - return cur + if Matched == 1: return cur cur = cur.Next return None # ============================================================ @@ -69,20 +66,16 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): name: str, ty: mlirlite.LLVMType*) -> mlirlite.Value*: """创建全局变量引用 (类型为 ty*,名称为 @name)""" - if name is None or ty is None: - return None + if name is None or ty is None: return None ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, ty) ref_name: str = pool.alloc(96) - if ref_name is None: - return None + if ref_name is None: return None # LLVM 无引号标识符不能以数字开头:带 SHA1 前缀的全局名("sha1.name") # 必命中 needs_quote(数字开头 + '.'),引用必须加引号 @\"sha1.name\", # 否则 llc "expected instruction opcode"。对齐函数引用路径 # (ExprGenName L252-255 的 needs_quote 判断)。 - if self.Gen.ClassGenVTable._vtable_name_needs_quote(name) != 0: - viperlib.snprintf(ref_name, 96, "@\"%s\"", name) - else: - viperlib.snprintf(ref_name, 96, "@%s", name) + if self.Gen.ClassGenVTable._vtable_name_needs_quote(name) != 0: viperlib.snprintf(ref_name, 96, "@\"%s\"", name) + else: viperlib.snprintf(ref_name, 96, "@%s", name) return mlirlite.SSAValue(pool, ptr_ty, ref_name) # ============================================================ # _resolve_module_attribute_global - 解析模块属性访问的全局变量引用 @@ -101,8 +94,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): 这些类型对象在运行时作为全局变量 @CPtr/@CInt 等被引用, 但 t.py 不被编译,需要在使用处生成带 null 初值的定义。 """ - if name is None: - return 0 + if name is None: return 0 # t.py 中的类型对象名(PascalCase,首字母大写) if string.strcmp(name, "CPtr") == 0: return 1 if string.strcmp(name, "CInt") == 0: return 1 @@ -147,8 +139,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): """把模块引用 AST 转成模块路径字符串(递归拼接 Attribute 链): Name('sys') → "sys";Attribute(Attribute(Name('os'),'_win32')) → "os._win32"。 非模块引用形态(Call/Subscript 等)返回 None。""" - if node is None: - return None + if node is None: return None k: int = node.kind() if k == ast.ASTKind.Name: nm_m: ast.Name* = ast.Name*(node) @@ -183,38 +174,29 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): def _CheckStaticCrossModule(self, pool: memhub.MemBuddy*, trans: HT.Translator*, at: ast.Attribute*) -> int: - if at is None or at.value is None or trans is None: - return 0 - if trans.ModuleSha1 is None or trans._imported_modules is None: - return 0 + if at is None or at.value is None or trans is None: return 0 + if trans.ModuleSha1 is None or trans._imported_modules is None: return 0 # 快速短路:项目内无 static 符号时零开销(不查 sha1、不扫表) - if self.Gen.CallGenBase.StaticCount <= 0: - return 0 + if self.Gen.CallGenBase.StaticCount <= 0: return 0 cs_path: str = self._attr_module_path_str(pool, at.value) - if cs_path is None: - return 0 + if cs_path is None: return 0 # import 别名还原(import X as Y → 查表得原始模块名,否则 sha1 查不到) if trans._from_imports is not None: cs_orig: str = self.Gen.ImportsGen.lookup_from_import(trans._from_imports, cs_path, 0) if cs_orig is not None: cs_len: sizet = 0 - while cs_orig[cs_len] != ' ' and cs_orig[cs_len] != '\0' and cs_orig[cs_len] != ':': - cs_len += 1 + while cs_orig[cs_len] != ' ' and cs_orig[cs_len] != '\0' and cs_orig[cs_len] != ':': cs_len += 1 if cs_len > 0: cs_buf: str = pool.alloc(cs_len + 1) if cs_buf is not None: string.strncpy(cs_buf, cs_orig, cs_len) cs_buf[cs_len] = '\0' cs_path = cs_buf - if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, cs_path) == 0: - return 0 + if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, cs_path) == 0: return 0 cs_sha1: str = self._lookup_module_sha1(cs_path) - 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 + 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") @@ -225,10 +207,8 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): at: ast.Attribute*, ty_hint: mlirlite.LLVMType*) -> mlirlite.Value*: """解析模块属性访问,返回全局变量引用 (用于跨模块 global 访问)""" - if at is None or at.value is None or at.attr is None: - return None - if trans is None or trans._imported_modules is None: - return None + if at is None or at.value is None or at.attr is None: return None + if trans is None or trans._imported_modules is None: return None # 提取模块路径名:Name → "sys";嵌套 Attribute → "os._win32" # (此前只支持 Name 模块;SysLibTest main.vp L32 `os._win32._mbuddy = v` # 的 at.value 是 Attribute → 被跳过 → "属性写入失败" 根因) @@ -244,8 +224,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): orig_mw: str = self.Gen.ImportsGen.lookup_from_import(trans._from_imports, mod_path_w, 0) if orig_mw is not None: oml_a: sizet = 0 - while orig_mw[oml_a] != ' ' and orig_mw[oml_a] != '\0' and orig_mw[oml_a] != ':': - oml_a += 1 + while orig_mw[oml_a] != ' ' and orig_mw[oml_a] != '\0' and orig_mw[oml_a] != ':': oml_a += 1 if oml_a > 0: om_buf_a: str = pool.alloc(oml_a + 1) if om_buf_a is not None: @@ -253,8 +232,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): om_buf_a[oml_a] = '\0' mod_path_w = om_buf_a # 检查是否是已导入模块 - if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, mod_path_w) == 0: - return None + if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, mod_path_w) == 0: return None # 注:static 符号的跨模块拦截统一在 translate_attribute 入口的 # _CheckStaticCrossModule 内完成(本函数的两个调用点都在其后),此处不再重复。 # 在当前模块查找全局变量:优先按"目标模块 SHA1 前缀 + 属性名"精确匹配, @@ -267,8 +245,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): # (@"ef5b0ba0dc895058._sched_ptr")→ 与定义端裸名不匹配 → ld.lld # undefined symbol: ef5b0ba0dc895058._sched_ptr(idt.vp L134 # sched._sched_ptr 根因)。 - if gv is None: - gv = self.find_global_in_module(mod, at.attr) + if gv is None: gv = self.find_global_in_module(mod, at.attr) if gv is not None and gv.Ty is not None: # 用 gv.Name(完整名,带 SHA1 前缀时与定义端一致)构造引用, # 避免裸名 @_mbuddy 在多模块各自带前缀定义下 undefined symbol @@ -276,8 +253,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): # 未找到: 创建 external global 声明并添加到模块 # 否则只生成 @_argc 引用而无声明,LLVM 报 "use of undefined value '@_argc'" use_ty: mlirlite.LLVMType* = ty_hint - if use_ty is None: - use_ty = mlirlite.Int8(pool) + if use_ty is None: use_ty = mlirlite.Int8(pool) # 确保 use_ty 中的跨模块结构体类型有 opaque 声明 mlirlite.module_ensure_opaque_for_type(mod, pool, use_ty) # 特殊处理: t.py 中的类型对象(CPtr/CInt/CDouble 等) @@ -285,17 +261,14 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): # 创建带 null 初值的 linkonce_odr 全局变量定义,避免链接时 undefined reference。 # LLVM 22+ 不允许 external linkage 全局变量带初值,使用 linkonce_odr 替代。 is_t_type_obj: int = 0 - if string.strcmp(mod_path_w, "t") == 0: - is_t_type_obj = self._is_t_type_object_name(at.attr) + if string.strcmp(mod_path_w, "t") == 0: is_t_type_obj = self._is_t_type_object_name(at.attr) # 类名不是模块级全局变量:Module.ClassName(如 mlirlite.LLVMType,定义在 .__types.vp,包 __init__.vp 仅再导出)此前被制造成 @"sha1.LLVMType" = external global i8* 并 load,而全仓无该全局定义(唯一引用点是变体构造时被丢弃的 callee 求值),ASan 插桩下 ld.lld undefined symbol。已注册类/结构体/REnum 一律交给类/REnum 路径,不在此制造全局 - if is_t_type_obj == 0 and self.Gen.StructGen.find_struct(at.attr) is not None: - return None + if is_t_type_obj == 0 and self.Gen.StructGen.find_struct(at.attr) is not None: return None # 兜底声明名:t 类型对象(t.py 不编译、无 sha1)保持裸名 linkonce_odr; # 其他模块属性带目标模块 SHA1 前缀(对齐定义端 mangling,跨模块同名 # 全局独立命名,消除 duplicate symbol / 串扰) gv_name_ba: str = at.attr - if is_t_type_obj == 0: - gv_name_ba = self.Gen.FuncGenBase._mangle_name_with_sha1(self._lookup_module_sha1(mod_path_w), at.attr) + if is_t_type_obj == 0: gv_name_ba = self.Gen.FuncGenBase._mangle_name_with_sha1(self._lookup_module_sha1(mod_path_w), at.attr) ext_gv: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, gv_name_ba, use_ty) if ext_gv is not None: if is_t_type_obj != 0: @@ -310,8 +283,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): null_init[3] = 'l' null_init[4] = '\0' ext_gv.Initializer = null_init - else: - ext_gv.Initializer = None + else: ext_gv.Initializer = None else: # 普通模块属性: external 声明(由其他模块提供定义) ext_gv.Linkage = "external" @@ -352,24 +324,17 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): at_value: ast.AST*, trans: HT.Translator* = None) -> mlirlite.Value*: """检测 at.value 是否为 *ptr 调用,返回 ptr 指针(不做 load)""" - if at_value is None or at_value.kind() != ast.ASTKind.Call: - return None + if at_value is None or at_value.kind() != ast.ASTKind.Call: return None cl_cd: ast.Call* = ast.Call*(at_value) - if cl_cd.func is None or cl_cd.func.kind() != ast.ASTKind.Attribute: - return None + if cl_cd.func is None or cl_cd.func.kind() != ast.ASTKind.Attribute: return None f_cd: ast.Attribute* = ast.Attribute*(cl_cd.func) - if f_cd.attr is None or string.strcmp(f_cd.attr, "Deref") != 0: - return None - if f_cd.value is None or f_cd.value.kind() != ast.ASTKind.Name: - return None + if f_cd.attr is None or string.strcmp(f_cd.attr, "Deref") != 0: return None + if f_cd.value is None or f_cd.value.kind() != ast.ASTKind.Name: return None nm_cd: ast.Name* = ast.Name*(f_cd.value) - if nm_cd.id is None or string.strcmp(nm_cd.id, "c") != 0: - return None - if cl_cd.args is None or len(cl_cd.args) < 1: - return None + if nm_cd.id is None or string.strcmp(nm_cd.id, "c") != 0: return None + if cl_cd.args is None or len(cl_cd.args) < 1: return None inner_cd: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cl_cd.args.get(0), None, 0, trans) - if inner_cd is not None and self.is_ptr_type(inner_cd.Ty) != 0: - return inner_cd + if inner_cd is not None and self.is_ptr_type(inner_cd.Ty) != 0: return inner_cd return None def translate_attribute(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, @@ -377,8 +342,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): node: ast.AST*, trans: HT.Translator* = None) -> mlirlite.Value*: """翻译属性访问,返回加载的字段值""" - if node is None or builder is None: - return None + if node is None or builder is None: return None at: ast.Attribute* = ast.Attribute*(node) if at is None or at.value is None or at.attr is None: # fast-fail: AST 节点字段缺失属解析器 bug,应报告具体缺失字段 @@ -386,10 +350,8 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if diag_buf_an is not None: missing_an: str = "?" if at is not None: - if at.value is None: - missing_an = "value" - elif at.attr is None: - missing_an = "attr" + 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, @@ -412,26 +374,20 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if string.strcmp(at.attr, "__doc__") == 0: doc_mod_buf: bytes = pool.alloc(64) doc_sym_buf: bytes = pool.alloc(256) - if doc_mod_buf is None or doc_sym_buf is None: - return None + if doc_mod_buf is None or doc_sym_buf is None: return None doc_mod_buf[0] = '\0' doc_sym_buf[0] = '\0' if at.value is not None and at.value.kind() == ast.ASTKind.Name: nm_doc: ast.Name* = ast.Name*(at.value) - if nm_doc.id is not None: - self.Gen.ExprGenCls._resolve_doc_symbol_name(trans, nm_doc.id, doc_mod_buf, doc_sym_buf) - elif at.value is not None and at.value.kind() == ast.ASTKind.Attribute: - self.Gen.ExprGenCls._resolve_doc_symbol_attr(trans, ast.Attribute*(at.value), doc_mod_buf, doc_sym_buf) + if nm_doc.id is not None: self.Gen.ExprGenCls._resolve_doc_symbol_name(trans, nm_doc.id, doc_mod_buf, doc_sym_buf) + elif at.value is not None and at.value.kind() == ast.ASTKind.Attribute: self.Gen.ExprGenCls._resolve_doc_symbol_attr(trans, ast.Attribute*(at.value), doc_mod_buf, doc_sym_buf) doc_val: str = None - if doc_mod_buf[0] != '\0' and doc_sym_buf[0] != '\0': - doc_val = self.Gen.ExprGenCls.lookup_docstring(doc_mod_buf, doc_sym_buf) + if doc_mod_buf[0] != '\0' and doc_sym_buf[0] != '\0': doc_val = self.Gen.ExprGenCls.lookup_docstring(doc_mod_buf, doc_sym_buf) if doc_val is None: i8_ty_doc: mlirlite.LLVMType* = mlirlite.Int8(pool) - if i8_ty_doc is None: - return None + if i8_ty_doc is None: return None i8_ptr_ty_doc: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_doc) - if i8_ptr_ty_doc is None: - return None + if i8_ptr_ty_doc is None: return None return mlirlite.ConstNull(pool, i8_ptr_ty_doc, "null") return self.Gen.ExprGenConst.create_global_string(builder, pool, mod, doc_val, trans) @@ -447,8 +403,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if base_ty is not None: # 生成数字字符串作为常量名(LLVM IR 要求常量输出数字值) name_buf: str = pool.alloc(32) - if name_buf is not None: - viperlib.snprintf(name_buf, 32, "%lld", member.Value) + if name_buf is not None: viperlib.snprintf(name_buf, 32, "%lld", member.Value) return mlirlite.ConstInt(pool, base_ty, member.Value, name_buf) return mlirlite.const_int32(pool, member.Value) # fast-fail: 枚举成员未找到 @@ -470,15 +425,13 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): base_ty_e: mlirlite.LLVMType* = self.Gen.StmtGenDecl.get_enum_base_type(inner_at_e.attr) if base_ty_e is not None: name_buf_e: str = pool.alloc(32) - if name_buf_e is not None: - viperlib.snprintf(name_buf_e, 32, "%lld", member_e.Value) + if name_buf_e is not None: viperlib.snprintf(name_buf_e, 32, "%lld", member_e.Value) return mlirlite.ConstInt(pool, base_ty_e, member_e.Value, name_buf_e) return mlirlite.const_int32(pool, member_e.Value) # fast-fail: 嵌套枚举成员未找到 dbg_ee: rawptr[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 + 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") return None @@ -490,12 +443,10 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): renum_cls_rv: str = None if at.value.kind() == ast.ASTKind.Name: rn_nm_rv: ast.Name* = ast.Name*(at.value) - if rn_nm_rv.id is not None: - renum_cls_rv = rn_nm_rv.id + if rn_nm_rv.id is not None: renum_cls_rv = rn_nm_rv.id elif at.value.kind() == ast.ASTKind.Attribute: rn_at_rv: ast.Attribute* = ast.Attribute*(at.value) - if rn_at_rv.attr is not None: - renum_cls_rv = rn_at_rv.attr + if rn_at_rv.attr is not None: renum_cls_rv = rn_at_rv.attr if renum_cls_rv is not None and self.Gen.ClassGenEnum._is_renum_class_name(renum_cls_rv) != 0: rv_tag: int = self.Gen.ClassGenEnum._lookup_renum_variant_in_class(renum_cls_rv, at.attr) if rv_tag >= 0: @@ -514,8 +465,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if fd_nm.id is not None: # pool 持久缓冲(f-string 栈缓冲在函数返回后失效) fd_meta_buf: str = pool.alloc(256) - if fd_meta_buf is not None: - viperlib.snprintf(fd_meta_buf, 256, "%s__meta__", fd_nm.id) + if fd_meta_buf is not None: viperlib.snprintf(fd_meta_buf, 256, "%s__meta__", fd_nm.id) fd_meta_v: mlirlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, fd_meta_buf) if fd_meta_v is not None: fd_sty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type("_str") @@ -523,8 +473,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): fd_fe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(fd_sty, at.attr) if fd_fe is not None and fd_fe.Ty is not None: fd_fp: mlirlite.Value* = mlirlite.build_gep_struct(builder, fd_sty, fd_fe.Ty, fd_meta_v, fd_fe.Index) - if fd_fp is not None: - return mlirlite.build_load(builder, fd_fe.Ty, fd_fp) + if fd_fp is not None: return mlirlite.build_load(builder, fd_fe.Ty, fd_fp) # 模块属性访问 (读路径): sys._mbuddy → 加载全局变量 @_mbuddy # 当 obj 是已导入模块名且不是普通变量时,查找/创建全局变量引用并加载 @@ -548,12 +497,10 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if resolved_mod is not None: # 复制模块名到新缓冲区(截断于空格、null、或 ':') rm_len: sizet = 0 - while resolved_mod[rm_len] != ' ' and resolved_mod[rm_len] != '\0' and resolved_mod[rm_len] != ':': - rm_len += 1 + while resolved_mod[rm_len] != ' ' and resolved_mod[rm_len] != '\0' and resolved_mod[rm_len] != ':': rm_len += 1 rm_buf: str = pool.alloc(rm_len + 1) if rm_buf is not None: - for rm_i in range(rm_len): - rm_buf[rm_i] = resolved_mod[rm_i] + for rm_i in range(rm_len): rm_buf[rm_i] = resolved_mod[rm_i] rm_buf[rm_len] = '\0' real_mod_name = rm_buf # 即使 _from_imports 为 None(如纯 `import ast` 无 from-import), @@ -571,12 +518,10 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): # 字符串全局常量(test_pyzlib.vp L49 ver = pyzlib.ZLIB_VERSION) if self.Gen.TypeGenCDef.is_cdefine_str() != 0: cdef_str_v: str = self.Gen.TypeGenCDef.lookup_cdefine_string(at.attr) - if cdef_str_v is not None: - return self.Gen.ExprGenConst.create_global_string(builder, pool, mod, cdef_str_v, trans) + if cdef_str_v is not None: return self.Gen.ExprGenConst.create_global_string(builder, pool, mod, cdef_str_v, trans) # 跨模块浮点 CDefine(如 vipermath.U_M_PI)→ 浮点常量 dchk_ma: double = self.Gen.TypeGenCDef.lookup_cdefine_double(at.attr) - if self.Gen.TypeGenCDef.is_cdefine_double() != 0: - return mlirlite.ConstFloat(pool, mlirlite.Double(pool), dchk_ma) + if self.Gen.TypeGenCDef.is_cdefine_double() != 0: return mlirlite.ConstFloat(pool, mlirlite.Double(pool), dchk_ma) return self.Gen.ExprGenCdef._const_int_for_cdefine(pool, cdef_ma_val) # 检查 nm_ma.id.at.attr 是否是已导入子模块 (如 w32.win32file) # 如果是子模块,不应创建全局变量,让嵌套属性访问路径处理 @@ -586,20 +531,17 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): submod_buf: str = pool.alloc(submod_len) if submod_buf is not None: viperlib.snprintf(submod_buf, submod_len, "%s.%s", nm_ma.id, at.attr) - if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, submod_buf) == 1: - is_submod = 1 + if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, submod_buf) == 1: is_submod = 1 # also check from_imports: at.attr 别名对应真实模块 w32.win32file if is_submod == 0 and trans._from_imports is not None: fi_mod_raw: str = self.Gen.ImportsGen.lookup_from_import(trans._from_imports, at.attr, 0) if fi_mod_raw is not None: # 复制模块名到新缓冲区(截断于空格、null、或 ':') fm_len: sizet = 0 - while fi_mod_raw[fm_len] != ' ' and fi_mod_raw[fm_len] != '\0' and fi_mod_raw[fm_len] != ':': - fm_len += 1 + while fi_mod_raw[fm_len] != ' ' and fi_mod_raw[fm_len] != '\0' and fi_mod_raw[fm_len] != ':': fm_len += 1 fi_mod: str = pool.alloc(fm_len + 1) if fi_mod is not None: - for fm_i in range(fm_len): - fi_mod[fm_i] = fi_mod_raw[fm_i] + for fm_i in range(fm_len): fi_mod[fm_i] = fi_mod_raw[fm_i] fi_mod[fm_len] = '\0' # 检查 fi_mod 是否以 "nm_ma.id." 开头 (如 w32.win32file 以 w32. 开头) prefix_len: sizet = string.strlen(nm_ma.id) @@ -610,15 +552,13 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if fi_mod[pi] != nm_ma.id[pi]: match_prefix = 0 break - if match_prefix == 1 and fi_mod[prefix_len] == '.': - is_submod = 1 + if match_prefix == 1 and fi_mod[prefix_len] == '.': is_submod = 1 if is_submod != 0: return None # 是子模块,交给嵌套属性访问路径 # 特殊处理: t.ASM_DESCR 不是 CDefine,是内联汇编约束命名空间 # t.ASM_DESCR.XXX 由 HandlesExprCall 的 _asm_resolve_constraint 处理 # 此处返回 None,让上层嵌套属性访问路径处理 - if string.strcmp(nm_ma.id, "t") == 0 and string.strcmp(at.attr, "ASM_DESCR") == 0: - return None + if string.strcmp(nm_ma.id, "t") == 0 and string.strcmp(at.attr, "ASM_DESCR") == 0: return None # ALL_CAPS 模块属性但非 CDefine:先检查模块是否定义了同名全局 # 变量(如 Phase1.PYI_BUF_SIZE: sizet = 262144 是 i64 全局、 # 非宏,语义同 C 的 extern size_t PYI_BUF_SIZE)→ 按跨模块全局 @@ -673,8 +613,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): gv_nested: mlirlite.GlobalVariable* = self.find_global_in_module(mod, gv_nested_q) # CExport 全局(定义端裸名 @idt)mangled 名查不到时回退 # 裸名精确查找(对齐读路径 _resolve_module_attribute_global) - if gv_nested is None: - gv_nested = self.find_global_in_module(mod, at.attr) + if gv_nested is None: gv_nested = self.find_global_in_module(mod, at.attr) if gv_nested is not None and gv_nested.Ty is not None: gv_ref_nested: mlirlite.Value* = self.make_global_ref(pool, gv_nested.Name, gv_nested.Ty) if gv_ref_nested is not None and gv_ref_nested.Ty is not None: @@ -702,8 +641,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if self.Gen.TypeGenCDef.is_cdefine_found() != 0: # 跨模块浮点 CDefine → 浮点常量 dchk_nst: double = self.Gen.TypeGenCDef.lookup_cdefine_double(at.attr) - if self.Gen.TypeGenCDef.is_cdefine_double() != 0: - return mlirlite.ConstFloat(pool, mlirlite.Double(pool), dchk_nst) + if self.Gen.TypeGenCDef.is_cdefine_double() != 0: return mlirlite.ConstFloat(pool, mlirlite.Double(pool), dchk_nst) return self.Gen.ExprGenCdef._const_int_for_cdefine(pool, cdef_val_nested) # CDefine 未找到: fail-fast 终止编译(不再创建未定义的全局变量引用) # 之前此处创建 @INVALID_HANDLE_VALUE 等前向引用,但全局未定义, @@ -735,37 +673,29 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): obj_ptr = mlirlite.build_bitcast(builder, raw_nl_a, mlirlite.Ptr(pool, nl_ty_a)) case _: nl_val_ptr_a: mlirlite.Value* = mlirlite.build_bitcast(builder, raw_nl_a, mlirlite.Ptr(pool, nl_ty_a)) - if nl_val_ptr_a is not None: - obj_ptr = mlirlite.build_load(builder, nl_ty_a, nl_val_ptr_a) - else: - obj_ptr = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id) + if nl_val_ptr_a is not None: obj_ptr = mlirlite.build_load(builder, nl_ty_a, nl_val_ptr_a) + else: obj_ptr = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id) # 非 Name 路径:翻译对象值(会 load) if obj_ptr is None: # c.Deref(ptr).attr: 属性访问 base 取指针本身而非 load 后的结构体值 # (如 c.Deref(p).a 语义是 (*p).a,直接对 p 做 GEP) cd_base_rd: mlirlite.Value* = self._get_cderef_attr_base(builder, pool, mod, at.value, trans) - if cd_base_rd is not None: - obj_ptr = cd_base_rd + if cd_base_rd is not None: obj_ptr = cd_base_rd elif at.value.kind() == ast.ASTKind.Subscript: # 下标基座属性访问(如 pts[0].x):list[T]/OOP __getitem__ 类走 # translate_value(返回元素值/地址);普通结构体指针数组走 # get_subscript_ptr(GEP 元素地址,避免结构体值 base=非指针 报错) - if self._sub_base_uses_getitem(pool, mod, trans, at.value) != 0: - obj_ptr = self.Gen.ExprGen.translate_value(builder, pool, mod, at.value, None, 0, trans) - else: - obj_ptr = self.Gen.ExprGenName.get_subscript_ptr(builder, pool, mod, at.value, trans) + if self._sub_base_uses_getitem(pool, mod, trans, at.value) != 0: obj_ptr = self.Gen.ExprGen.translate_value(builder, pool, mod, at.value, None, 0, trans) + else: obj_ptr = self.Gen.ExprGenName.get_subscript_ptr(builder, pool, mod, at.value, trans) elif at.value.kind() == ast.ASTKind.Attribute: # 嵌套属性基座(如 r.origin.x):取内层字段地址(get_attribute_ptr 递归, # 地址语义),指针字段(X*)由 _deref_if_ptr_ptr load 解引用 obj_ptr = self.get_attribute_ptr(builder, pool, mod, at.value, trans) - if obj_ptr is None: - obj_ptr = self.Gen.ExprGen.translate_value(builder, pool, mod, at.value, None, 0, trans) - else: - obj_ptr = self.Gen.ExprGen.translate_value(builder, pool, mod, at.value, None, 0, trans) + if obj_ptr is None: obj_ptr = self.Gen.ExprGen.translate_value(builder, pool, mod, at.value, None, 0, trans) + else: obj_ptr = self.Gen.ExprGen.translate_value(builder, pool, mod, at.value, None, 0, trans) - if obj_ptr is None or obj_ptr.Ty is None: - return None + if obj_ptr is None or obj_ptr.Ty is None: return None # 如果 obj_ptr 是 Ptr(Ptr(Struct))(X* 变量的 alloca), # load 解引用获取 Ptr(Struct) @@ -803,16 +733,14 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): decl_ptr_rn: mlirlite.LLVMType* = mlirlite.Ptr(pool, decl_ty_rn) if decl_ptr_rn is not None: cast_ptr_rn: mlirlite.Value* = mlirlite.build_bitcast(builder, alias_ptr, decl_ptr_rn) - if cast_ptr_rn is not None: - return mlirlite.build_load(builder, decl_ty_rn, cast_ptr_rn) + if cast_ptr_rn is not None: return mlirlite.build_load(builder, decl_ty_rn, cast_ptr_rn) return mlirlite.build_load(builder, alias_fe.Ty, alias_ptr, vol_ba_rd) # property getter 回退: obj.attr 是 @property/@x.getter 方法时生成调用 # (字段未找到时先尝试,避免报误导性的"字段未找到"错误) if field_info is None and at.value is not None and trans is not None: prop_cls_fb: str = self.Gen.StructGen.get_class_name_by_type(pool, struct_ty) prop_val: mlirlite.Value* = self.Gen.CallGenProp._try_property_getter_attr(pool, builder, mod, at, obj_ptr, trans, prop_cls_fb) - if prop_val is not None: - return prop_val + if prop_val is not None: return prop_val # 按需过滤: struct_ty 为 i8(简化联合类型)时,通过 AnnotClassName 按类名查找 # 传递 SHA1 以区分跨模块同名类 # base 注解类名提取:Name → 变量注解类名;Attribute → 属性链递归字段注解类名 @@ -822,8 +750,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): nm_fb: ast.Name* = ast.Name*(at.value) if nm_fb.id is not None: var_entry: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm_fb.id) - if var_entry is not None: - base_class = self.Gen.VarGen.var_annot_class_name(var_entry) + if var_entry is not None: base_class = self.Gen.VarGen.var_annot_class_name(var_entry) elif at.value.kind() == ast.ASTKind.Attribute: # allow_module_global=1:基座可为「模块名.全局变量」(通用形态 # Mod.g,如 GenApi._g_gen)——缺此则 Mod.g.Field[.Field] 的 @@ -848,8 +775,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): rn_se: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(base_class) if rn_se is not None: rn_fe: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(rn_se, rn_alias) - if rn_fe is not None and rn_fe.Ty is not None: - field_info = rn_fe + if rn_fe is not None and rn_fe.Ty is not None: field_info = rn_fe # 按需过滤成功:bitcast obj_ptr 到 AnnotClassName 对应的结构体类型 # 原始 struct_ty 可能是 i8(X* 简化为 Ptr(i8)), # 需用实际结构体类型做 GEP,否则 GEP i8 失败 @@ -871,14 +797,12 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): field_vol_rd: int = self.Gen.StructGen.field_is_volatile(field_info) # 合并"字段所指物 volatile"(基址是 rawptr[t.CVolatile|T] 时, # 经其访问的字段 load 亦须 volatile;两者取或) - if vol_ba_rd != 0: - field_vol_rd = 1 + if vol_ba_rd != 0: field_vol_rd = 1 # 联合体:bitcast obj_ptr 到 field_ty* 后 load if self.Gen.StructGen.is_union_by_type(struct_ty) == 1: field_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, field_ty) casted: mlirlite.Value* = mlirlite.build_bitcast(builder, obj_ptr, field_ptr_ty) - if casted is not None: - return mlirlite.build_load(builder, field_ty, casted, field_vol_rd) + if casted is not None: return mlirlite.build_load(builder, field_ty, casted, field_vol_rd) return None # 普通结构体:GEP + load field_idx: int = field_info.Index @@ -895,12 +819,10 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): decl_ptr_rd: mlirlite.LLVMType* = mlirlite.Ptr(pool, decl_ty_rd) if decl_ptr_rd is not None: cast_ptr_rd: mlirlite.Value* = mlirlite.build_bitcast(builder, field_ptr, decl_ptr_rd) - if cast_ptr_rd is not None: - return mlirlite.build_load(builder, decl_ty_rd, cast_ptr_rd, field_vol_rd) + if cast_ptr_rd is not None: return mlirlite.build_load(builder, decl_ty_rd, cast_ptr_rd, field_vol_rd) # 数组类型字段不能 load 为 SSA value,直接返回字段指针 # 用于后续下标访问: self.state[0] → GEP state 字段 → GEP 数组元素 - if self.is_array_type(field_ty) != 0: - return field_ptr + if self.is_array_type(field_ty) != 0: return field_ptr loaded_val: mlirlite.Value* = mlirlite.build_load(builder, field_ty, field_ptr, field_vol_rd) # 联合类型字段(如 Token*)被编译为 i8*, # 若 AnnotClassName 指示了具体结构体类型,bitcast 为正确的结构体指针。 @@ -933,14 +855,11 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): diag_var_nm = dnm.id if dnm.id is not None: dve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, dnm.id) - if dve is not None: - diag_annot = self.Gen.VarGen.var_annot_class_name(dve) + if dve is not None: diag_annot = self.Gen.VarGen.var_annot_class_name(dve) diag_var_txt: str = "?" - if diag_var_nm is not None: - diag_var_txt = diag_var_nm + if diag_var_nm is not None: diag_var_txt = diag_var_nm diag_annot_txt: str = "None" - if diag_annot is not None: - diag_annot_txt = diag_annot + if diag_annot is not None: diag_annot_txt = diag_annot # 接收者链路径(Name/Attribute 链逐段拼接,如 # "GenApi._g_gen.TypeGenCDef"):`var=?` 说明接收者不是本模块 # 变量,此处补出完整拼写形态,供直接定位是模块限定全局链 @@ -948,25 +867,20 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): diag_base_txt: str = "?" if at.value is not None: dbg_bp: str = self._attr_module_path_str(pool, at.value) - if dbg_bp is not None: - diag_base_txt = dbg_bp + if dbg_bp is not None: diag_base_txt = dbg_bp sha1_attr: str = "?" - if trans.ModuleSha1 is not None: - sha1_attr = trans.ModuleSha1 + 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") return None case _: # fast-fail: 对非指针类型做属性访问(如 i32.x), # Python traceback 立即终止,不静默返回 None(否则下游 "store to None" 崩溃,丢失错误现场) attr_nm_ap: str = "?" - if at is not None and at.attr is not None: - attr_nm_ap = at.attr + if at is not None and at.attr is not None: attr_nm_ap = at.attr sha1_ap: str = "?" - if trans is not None and trans.ModuleSha1 is not None: - sha1_ap = trans.ModuleSha1 + 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 + 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") # fatal_error 后补显式 return 样板:match 末 arm 块必须 terminated, # 否则掉出末尾被函数收尾 fail-fast 误判(块设计约定) @@ -994,14 +908,11 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): 0=严格按变量注解/字段注解解析——其余调用方(虚拟分派/注解推断/volatile 判定等)口径逐字不变。 """ - if attr_node is None or trans is None: - return None + if attr_node is None or trans is None: return None k: int = attr_node.kind() - if k != ast.ASTKind.Attribute: - return None + if k != ast.ASTKind.Attribute: return None at: ast.Attribute* = ast.Attribute*(attr_node) - if at is None or at.attr is None or at.value is None: - return None + if at is None or at.attr is None or at.value is None: return None # 递归解析基座的注解类名(Name → 变量注解;Attribute → 字段注解) parent_class: str = None if at.value.kind() == ast.ASTKind.Name: @@ -1016,8 +927,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): return self._resolve_module_global_class_name(pool, trans, nm.id, at.attr) return None parent_class = self.Gen.VarGen.var_annot_class_name(var_entry) - elif at.value.kind() == ast.ASTKind.Attribute: - parent_class = self._resolve_attr_field_class(pool, trans, at.value, allow_module_global) + elif at.value.kind() == ast.ASTKind.Attribute: parent_class = self._resolve_attr_field_class(pool, trans, at.value, allow_module_global) elif at.value.kind() == ast.ASTKind.Call: # 指针强转基座(`(T*(x)).f.g` 的递归父节点):从强转注解提取类名, # 详见 _base_class_from_cast_base 头注释 @@ -1059,23 +969,17 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): trans: HT.Translator*, node: ast.AST*) -> str: """`T*(x)` 强转基座的裸类名;非该形态返回 None""" - if node is None or trans is None: - return None - if node.kind() != ast.ASTKind.Call: - return None + if node is None or trans is None: return None + if node.kind() != ast.ASTKind.Call: return None cl_cb: ast.Call* = ast.Call*(node) - if cl_cb.func is None or cl_cb.func.kind() != ast.ASTKind.BinOp: - return None + if cl_cb.func is None or cl_cb.func.kind() != ast.ASTKind.BinOp: return None bo_cb: ast.BinOp* = ast.BinOp*(cl_cb.func) - if bo_cb.op != ast.OpKind.BitOr: - return None + if bo_cb.op != ast.OpKind.BitOr: return None # 联合一侧是 t.CPtr 标记(`T*` / `T**` 展开的嵌套联合)时取另一侧; # 否则(手写 `X | Y`)取左侧——与 parser 的 _make_ptr_type 产物一致。 tgt_cb: ast.AST* = bo_cb.left - if self.Gen.TypeGenResolve._is_cptr_marker(bo_cb.left, trans._imported_modules) != 0: - tgt_cb = bo_cb.right - if tgt_cb is None: - return None + if self.Gen.TypeGenResolve._is_cptr_marker(bo_cb.left, trans._imported_modules) != 0: tgt_cb = bo_cb.right + if tgt_cb is None: return None k_cb: int = tgt_cb.kind() if k_cb == ast.ASTKind.Attribute: at_cb: ast.Attribute* = ast.Attribute*(tgt_cb) @@ -1103,31 +1007,26 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): mod_name: str, global_name: str) -> str: """解析模块限定全局 Mod.g 的元素类型类名;非该形态返回 None""" - if pool is None or trans is None or mod_name is None or global_name is None: - return None + if pool is None or trans is None or mod_name is None or global_name is None: return None mod: mlirlite.LLVMModule* = trans.Module - if mod is None or trans._imported_modules is None: - return None + if mod is None or trans._imported_modules is None: return None # 模块路径:import 别名还原(对齐 _resolve_module_attribute_global 的同款截断) mod_path: str = mod_name if trans._from_imports is not None: orig_mw: str = self.Gen.ImportsGen.lookup_from_import(trans._from_imports, mod_name, 0) if orig_mw is not None: oml_mg: sizet = 0 - while orig_mw[oml_mg] != ' ' and orig_mw[oml_mg] != '\0' and orig_mw[oml_mg] != ':': - oml_mg += 1 + while orig_mw[oml_mg] != ' ' and orig_mw[oml_mg] != '\0' and orig_mw[oml_mg] != ':': oml_mg += 1 if oml_mg > 0: om_buf_mg: str = pool.alloc(oml_mg + 1) if om_buf_mg is not None: string.strncpy(om_buf_mg, orig_mw, oml_mg) om_buf_mg[oml_mg] = '\0' mod_path = om_buf_mg - if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, mod_path) == 0: - return None + if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, mod_path) == 0: return None # 全局定位:SHA1 前缀名(对齐定义端 mangling)→ 裸名回退(CExport 全局) gv: mlirlite.GlobalVariable* = self.find_global_in_module(mod, self.Gen.FuncGenBase._mangle_name_with_sha1(self._lookup_module_sha1(mod_path), global_name)) - if gv is None: - gv = self.find_global_in_module(mod, global_name) + if gv is None: gv = self.find_global_in_module(mod, global_name) if gv is None or gv.Ty is None: return None if self.is_ptr_type(gv.Ty) == 0: return None # 全局变量类型是「元素类型的指针」(@"._g_gen" : %Generator*)⇒ 类名 @@ -1151,13 +1050,10 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): 再按名查字段取 FieldEntry.IsVolatile。查不到(vtable 方法、影子字段、 依赖未就绪等)返回 0,不影响既有行为(写路径退回非 volatile store)。 """ - if attr_node is None or trans is None: - return 0 - if attr_node.kind() != ast.ASTKind.Attribute: - return 0 + if attr_node is None or trans is None: return 0 + if attr_node.kind() != ast.ASTKind.Attribute: return 0 at: ast.Attribute* = ast.Attribute*(attr_node) - if at is None or at.attr is None or at.value is None: - return 0 + if at is None or at.attr is None or at.value is None: return 0 parent_class: str = None if at.value.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(at.value) @@ -1165,8 +1061,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id) if ve is None: return 0 parent_class = self.Gen.VarGen.var_annot_class_name(ve) - elif at.value.kind() == ast.ASTKind.Attribute: - parent_class = self._resolve_attr_field_class(pool, trans, at.value) + elif at.value.kind() == ast.ASTKind.Attribute: parent_class = self._resolve_attr_field_class(pool, trans, at.value) if parent_class is None: return 0 fe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field_by_class(parent_class, at.attr, trans.ModuleSha1, at, trans._from_imports) return self.Gen.StructGen.field_is_volatile(fe) @@ -1208,8 +1103,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): fi: int = 0 while fi < st.FieldCount: fe_u: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(st, fi) - if fe_u is not None and fe_u.Name is not None and string.strcmp(fe_u.Name, at.attr) == 0: - return fe_u + if fe_u is not None and fe_u.Name is not None and string.strcmp(fe_u.Name, at.attr) == 0: return fe_u fi += 1 return None @@ -1254,15 +1148,13 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): 基址是函数返回/下标/调用/更复杂表达式时返回 0(明确不支持)。 消费点:p[i] / p.field / *p 的 load/store 据此加 LLVM volatile。 """ - if base_node is None or trans is None: - return 0 + if base_node is None or trans is None: return 0 if base_node.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(base_node) if nm.id is None: return 0 ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id) return self.Gen.VarGen.var_pointee_is_volatile(ve) - if base_node.kind() == ast.ASTKind.Attribute: - return self.attr_field_pointee_is_volatile(pool, trans, base_node) + if base_node.kind() == ast.ASTKind.Attribute: return self.attr_field_pointee_is_volatile(pool, trans, base_node) return 0 def get_attribute_ptr(self, builder: mlirlite.IRBuilder*, @@ -1271,11 +1163,9 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): node: ast.AST*, trans: HT.Translator* = None) -> mlirlite.Value*: """获取属性访问的字段指针(用于赋值 lhs)""" - if node is None or builder is None: - return None + if node is None or builder is None: return None at: ast.Attribute* = ast.Attribute*(node) - if at is None or at.value is None or at.attr is None: - return None + if at is None or at.value is None or at.attr is None: return None # 对于 Name 类型的 obj,直接查找 alloca(不 load 结构体); # nonlocal 变量(提升函数内)从 env 读共享堆值,避免 lookup_var @@ -1299,10 +1189,8 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): obj_ptr = mlirlite.build_bitcast(builder, raw_nl_a, mlirlite.Ptr(pool, nl_ty_a)) case _: nl_val_ptr_a: mlirlite.Value* = mlirlite.build_bitcast(builder, raw_nl_a, mlirlite.Ptr(pool, nl_ty_a)) - if nl_val_ptr_a is not None: - obj_ptr = mlirlite.build_load(builder, nl_ty_a, nl_val_ptr_a) - else: - obj_ptr = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id) + if nl_val_ptr_a is not None: obj_ptr = mlirlite.build_load(builder, nl_ty_a, nl_val_ptr_a) + else: obj_ptr = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id) # 模块属性访问 (写路径): sys._mbuddy = mb / os._win32._mbuddy = v # → store 到模块全局变量。当 obj 是已导入模块名(Name 或嵌套 Attribute @@ -1326,35 +1214,28 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): # 使用 i8* 作为类型提示 (模块级变量通常存储指针) i8_ptr_w: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) wma_ref: mlirlite.Value* = self._resolve_module_attribute_global(pool, mod, trans, at, i8_ptr_w) - if wma_ref is not None: - return wma_ref + if wma_ref is not None: return wma_ref # 非 Name 路径:翻译对象值(会 load) if obj_ptr is None: # c.Deref(ptr).attr: 属性写入 base 取指针本身而非 load 后的结构体值 # (如 c.Deref(p).a = val 语义是 (*p).a = val,直接对 p 做 GEP) cd_base_wr: mlirlite.Value* = self._get_cderef_attr_base(builder, pool, mod, at.value, trans) - if cd_base_wr is not None: - obj_ptr = cd_base_wr + if cd_base_wr is not None: obj_ptr = cd_base_wr elif at.value.kind() == ast.ASTKind.Subscript: # 下标基座属性写入(如 pts[0].x = val):list[T]/OOP __getitem__ 类走 # translate_value(返回元素值/地址);普通结构体指针数组走 # get_subscript_ptr(GEP 元素地址,避免结构体值 base=非指针 报错) - if self._sub_base_uses_getitem(pool, mod, trans, at.value) != 0: - obj_ptr = self.Gen.ExprGen.translate_value(builder, pool, mod, at.value, None, 0, trans) - else: - obj_ptr = self.Gen.ExprGenName.get_subscript_ptr(builder, pool, mod, at.value, trans) + if self._sub_base_uses_getitem(pool, mod, trans, at.value) != 0: obj_ptr = self.Gen.ExprGen.translate_value(builder, pool, mod, at.value, None, 0, trans) + else: obj_ptr = self.Gen.ExprGenName.get_subscript_ptr(builder, pool, mod, at.value, trans) elif at.value.kind() == ast.ASTKind.Attribute: # 嵌套属性基座写入(如 r.origin.x = val):取内层字段地址 # (get_attribute_ptr 递归,地址语义),指针字段由 _deref_if_ptr_ptr 解引用 obj_ptr = self.get_attribute_ptr(builder, pool, mod, at.value, trans) - if obj_ptr is None: - obj_ptr = self.Gen.ExprGen.translate_value(builder, pool, mod, at.value, None, 0, trans) - else: - obj_ptr = self.Gen.ExprGen.translate_value(builder, pool, mod, at.value, None, 0, trans) + if obj_ptr is None: obj_ptr = self.Gen.ExprGen.translate_value(builder, pool, mod, at.value, None, 0, trans) + else: obj_ptr = self.Gen.ExprGen.translate_value(builder, pool, mod, at.value, None, 0, trans) - if obj_ptr is None or obj_ptr.Ty is None: - return None + if obj_ptr is None or obj_ptr.Ty is None: return None # 如果 obj_ptr 是 Ptr(Ptr(Struct))(X* 变量的 alloca), # load 解引用获取 Ptr(Struct) @@ -1376,8 +1257,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): nm_fb: ast.Name* = ast.Name*(at.value) if nm_fb.id is not None: var_entry: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm_fb.id) - if var_entry is not None: - base_class = self.Gen.VarGen.var_annot_class_name(var_entry) + if var_entry is not None: base_class = self.Gen.VarGen.var_annot_class_name(var_entry) elif at.value.kind() == ast.ASTKind.Attribute: # allow_module_global=1:同 translate_attribute(基座可为 # 「模块名.全局变量」,如 GenApi._g_gen.TypeGenCDef) @@ -1403,8 +1283,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): rn_se_g: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(base_class) if rn_se_g is not None: rn_fe_g: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(rn_se_g, rn_alias_g) - if rn_fe_g is not None and rn_fe_g.Ty is not None: - field_info = rn_fe_g + if rn_fe_g is not None and rn_fe_g.Ty is not None: field_info = rn_fe_g # 按需过滤成功:bitcast obj_ptr 到 AnnotClassName 对应的结构体类型 # 原始 struct_ty 可能是 i8(X* 简化为 Ptr(i8)), # 需用实际结构体类型做 GEP,否则 GEP i8 失败 @@ -1437,38 +1316,30 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): diag_var_nm_g = dnm_g.id if dnm_g.id is not None: dve_g: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, dnm_g.id) - if dve_g is not None: - diag_annot_g = self.Gen.VarGen.var_annot_class_name(dve_g) + if dve_g is not None: diag_annot_g = self.Gen.VarGen.var_annot_class_name(dve_g) diag_var_txt_g: str = "?" - if diag_var_nm_g is not None: - diag_var_txt_g = diag_var_nm_g + if diag_var_nm_g is not None: diag_var_txt_g = diag_var_nm_g diag_annot_txt_g: str = "None" - if diag_annot_g is not None: - diag_annot_txt_g = diag_annot_g + if diag_annot_g is not None: diag_annot_txt_g = diag_annot_g # 接收者链路径(同 translate_attribute 的读取侧补全):`var=?` # 说明接收者不是本模块变量,补出完整拼写形态(Mod.g.F[.F])。 diag_base_txt_g: str = "?" if at.value is not None: dbg_bp_g: str = self._attr_module_path_str(pool, at.value) - if dbg_bp_g is not None: - diag_base_txt_g = dbg_bp_g + 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 + 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") return None case _: # fast-fail: 对非指针类型做属性写入(如 i32.x = ...), # Python traceback 立即终止,不静默返回 None(否则下游 "store to None" 崩溃) attr_nm_gp: str = "?" - if at is not None and at.attr is not None: - attr_nm_gp = at.attr + if at is not None and at.attr is not None: attr_nm_gp = at.attr sha1_gp: str = "?" - if trans is not None and trans.ModuleSha1 is not None: - sha1_gp = trans.ModuleSha1 + 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 + 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") # fatal_error 后补显式 return 样板:match 末 arm 块必须 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 e74893c..3d65789 100644 --- a/App/lib/core/Gen/Expr/ExprGenBase.vp +++ b/App/lib/core/Gen/Expr/ExprGenBase.vp @@ -85,8 +85,7 @@ novirtual class ExprGenBase: pos += 1 for i in range(slen): ch: char = src[i] - if ch == '\0': - break + if ch == '\0': break if ch == '\"' or ch == '\\' or ch < 0x20: buf[pos] = '\\' pos += 1 @@ -207,17 +206,14 @@ novirtual class ExprGenBase: def _get_custom_struct_cls_nm(self, pool: memhub.MemBuddy*, ty: mlirlite.LLVMType*) -> str: """检查 ty 或 ty 的 pointee 是否是已注册的自定义结构体,返回类名或 None""" - if ty is None: - return None + if ty is None: return None # 直接检查 ty 是否是注册的结构体 cls_nm_direct: str = self.Gen.StructGen.get_class_name_by_type(pool, ty) - if cls_nm_direct is not None: - return cls_nm_direct + if cls_nm_direct is not None: return cls_nm_direct # 如果 ty 是 Ptr,检查 pointee if self.is_ptr_type(ty) != 0: pointee_cs: mlirlite.LLVMType* = ty.Pointee - if pointee_cs is not None: - return self.Gen.StructGen.get_class_name_by_type(pool, pointee_cs) + if pointee_cs is not None: return self.Gen.StructGen.get_class_name_by_type(pool, pointee_cs) return None # ============================================================ # _is_list_subscript_base - 判断下标基座是否为 list[T] 变量 @@ -249,8 +245,7 @@ novirtual class ExprGenBase: lsn_ls = lsn3 case _: pass - if lsn_ls is not None and string.strstr(lsn_ls, "list[") is not None: - return 1 + if lsn_ls is not None and string.strstr(lsn_ls, "list[") is not None: return 1 case _: pass return 0 @@ -273,8 +268,7 @@ novirtual class ExprGenBase: if pointee is None: return None if self.is_ptr_type(pointee) != 0: inner: mlirlite.LLVMType* = pointee.Pointee - if inner is not None: - return self.Gen.StructGen.get_class_name_by_type(pool, inner) + if inner is not None: return self.Gen.StructGen.get_class_name_by_type(pool, inner) return self.Gen.StructGen.get_class_name_by_type(pool, pointee) # ============================================================ # _sub_base_uses_getitem - 下标基座是否应走 __getitem__ 语义 @@ -328,22 +322,15 @@ novirtual class ExprGenBase: # ============================================================ def _value_node_of(self, node: ast.AST*) -> ast.AST*: """语句节点 → 其值子表达式节点;非语句/无值则原样返回""" - if node is None: - return node + if node is None: return node k: int = node.kind() v: ast.AST* = None - if k == ast.ASTKind.Assign: - v = (ast.Assign*(node)).value - elif k == ast.ASTKind.AnnAssign: - v = (ast.AnnAssign*(node)).value - elif k == ast.ASTKind.AugAssign: - v = (ast.AugAssign*(node)).value - elif k == ast.ASTKind.Expr: - v = (ast.Expr*(node)).value - elif k == ast.ASTKind.Return: - v = (ast.Return*(node)).value - if v is None: - return node + if k == ast.ASTKind.Assign: v = (ast.Assign*(node)).value + elif k == ast.ASTKind.AnnAssign: v = (ast.AnnAssign*(node)).value + elif k == ast.ASTKind.AugAssign: v = (ast.AugAssign*(node)).value + elif k == ast.ASTKind.Expr: v = (ast.Expr*(node)).value + elif k == ast.ASTKind.Return: v = (ast.Return*(node)).value + if v is None: return node return v # ============================================================ # IsNoneValue - 判据:源值是否为 None(空值常量),返回 1=是 / 0=否 @@ -375,11 +362,9 @@ novirtual class ExprGenBase: # 判据①:AST 是 None 字面量 if node is not None and node.kind() == ast.ASTKind.Constant: cn_nv: ast.Constant* = ast.Constant*(node) - if cn_nv is not None and cn_nv.const_kind == ast.CONST_NONE: - return 1 + if cn_nv is not None and cn_nv.const_kind == ast.CONST_NONE: return 1 # 判据②:已生成好的 null 常量(指针类型 + 编译期零) - if val is not None and val.IsConst == 1 and val.IntVal == 0 and self.is_ptr_type(val.Ty) != 0: - return 1 + if val is not None and val.IsConst == 1 and val.IntVal == 0 and self.is_ptr_type(val.Ty) != 0: return 1 return 0 # ============================================================ # _NoneValueAsTarget - 把 None(空值)物化为目标类型的空值/零值 @@ -395,15 +380,12 @@ novirtual class ExprGenBase: def _NoneValueAsTarget(self, builder: mlirlite.IRBuilder*, target_ty: mlirlite.LLVMType*) -> mlirlite.Value*: """把 None 转换为目标类型的空值/零值""" - if target_ty is None: - return None + if target_ty is None: return None pool: memhub.MemBuddy* = builder.Pool t_bits: int = self.get_llvm_type_bits(target_ty) - if t_bits != 0: - return mlirlite.ConstInt(pool, target_ty, 0, "0") + if t_bits != 0: return mlirlite.ConstInt(pool, target_ty, 0, "0") t_fbits: int = self.get_llvm_float_bits(target_ty) - if t_fbits != 0: - return mlirlite.ConstFloat(pool, target_ty, 0.0) + if t_fbits != 0: return mlirlite.ConstFloat(pool, target_ty, 0.0) return mlirlite.ConstZero(pool, target_ty) # ============================================================ # _is_universal_ptr_ty - 判据:类型是否为「通用指针」(t.CPtr / i8* = void*) @@ -417,15 +399,11 @@ novirtual class ExprGenBase: # ============================================================ def _is_universal_ptr_ty(self, ty: mlirlite.LLVMType*) -> int: """ty 是否为通用指针(i8*/t.CPtr),1=是 / 0=否""" - if ty is None or self.is_ptr_type(ty) == 0: - return 0 - if self.get_ptr_level(ty) != 1: - return 0 + if ty is None or self.is_ptr_type(ty) == 0: return 0 + if self.get_ptr_level(ty) != 1: return 0 pointee: mlirlite.LLVMType* = ty.Pointee - if pointee is None: - return 1 - if self.get_llvm_type_bits(pointee) == 8: - return 1 + if pointee is None: return 1 + if self.get_llvm_type_bits(pointee) == 8: return 1 return 0 # ============================================================ # 「str / bytes 不是通用指针通配」——规则与统一 fail-fast @@ -441,18 +419,14 @@ novirtual class ExprGenBase: # ============================================================ def _annot_name_is_bare_str(self, txt: str) -> int: """注解**文本**是否为裸 str / bytes;1=是 / 0=否""" - if txt is None or txt[0] == 0: - return 0 - if string.strcmp(txt, "str") == 0 or string.strcmp(txt, "bytes") == 0: - return 1 + if txt is None or txt[0] == 0: return 0 + if string.strcmp(txt, "str") == 0 or string.strcmp(txt, "bytes") == 0: return 1 return 0 def _annot_is_bare_str(self, annot: ast.AST*) -> int: """注解 AST 是否为裸 str / bytes(Name 形态);1=是 / 0=否""" - if annot is None or annot.kind() != ast.ASTKind.Name: - return 0 + if annot is None or annot.kind() != ast.ASTKind.Name: return 0 nm: ast.Name* = ast.Name*(annot) - if nm is None or nm.id is None: - return 0 + if nm is None or nm.id is None: return 0 return self._annot_name_is_bare_str(nm.id) def _str_rejects_ptr_kind(self, val: mlirlite.Value*) -> int: """val 是否为「str/bytes 不应接受」的聚合指针(1/2/3=是,0=否) @@ -463,23 +437,17 @@ novirtual class ExprGenBase: `name: str = find_data.cFileName`,WIN32_FIND_DATAA.cFileName 是 [260 x i8])。 多级指针/基本类型指针一律 0(不在本规则范围内)。 """ - if val is None or val.Ty is None: - return 0 - if self.is_ptr_type(val.Ty) == 0: - return 0 + if val is None or val.Ty is None: return 0 + if self.is_ptr_type(val.Ty) == 0: return 0 pointee: mlirlite.LLVMType* = val.Ty.Pointee - if pointee is None: - return 0 + if pointee is None: return 0 pk: int = pointee.kind() - if pk == mlirlite.LLVMType.Struct: - return 1 - if pk == mlirlite.LLVMType.Func: - return 3 + if pk == mlirlite.LLVMType.Struct: return 1 + if pk == mlirlite.LLVMType.Func: return 3 if pk == mlirlite.LLVMType.Array: match pointee: case mlirlite.LLVMType.Array(elem, _): - if self.get_llvm_type_bits(elem) == 8: - return 0 + if self.get_llvm_type_bits(elem) == 8: return 0 case _: pass return 2 @@ -493,10 +461,8 @@ novirtual class ExprGenBase: 字符数组衰减豁免)。显式转换(如 t.CPtr(p))的产物 pointee 是 i8, 不触发本检查,故显式转换不受影响。 """ - 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 + 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 不是通用指针通配)。若确需传递指针," @@ -520,12 +486,9 @@ novirtual class ExprGenBase: # ============================================================ def _is_basic_scalar_ty(self, ty: mlirlite.LLVMType*) -> int: """ty 是否为基本类型(整数/浮点),1=是 / 0=否""" - if ty is None: - return 0 - if self.get_llvm_type_bits(ty) != 0: - return 1 - if self.get_llvm_float_bits(ty) != 0: - return 1 + if ty is None: return 0 + if self.get_llvm_type_bits(ty) != 0: return 1 + if self.get_llvm_float_bits(ty) != 0: return 1 return 0 # ============================================================ # _scalar_convert_reason - 基本标量 T → U 是否无损(沿用 coerce_to_type 既有规则) @@ -542,19 +505,15 @@ novirtual class ExprGenBase: s_flt: int = self.get_llvm_float_bits(src_pt) d_flt: int = self.get_llvm_float_bits(dst_pt) # 整数 ↔ 整数:高→低安全降级、低→高无损,均允许 - if s_int != 0 and d_int != 0: - return PC_OK + if s_int != 0 and d_int != 0: return PC_OK # 浮点 ↔ 浮点:允许 - if s_flt != 0 and d_flt != 0: - return PC_OK + if s_flt != 0 and d_flt != 0: return PC_OK # 整数 → 浮点:浮点位宽 ≥ 整数位宽才无损 if s_int != 0 and d_flt != 0: - if d_flt >= s_int: - return PC_OK + if d_flt >= s_int: return PC_OK return PC_LOSSY # 浮点 → 整数:有损,禁止 - if s_flt != 0 and d_int != 0: - return PC_LOSSY + if s_flt != 0 and d_int != 0: return PC_LOSSY return PC_OK # ============================================================ # _class_name_of_ptr_pointee - 指针被指类型 → 已注册类名 @@ -566,8 +525,7 @@ novirtual class ExprGenBase: def _class_name_of_ptr_pointee(self, pool: memhub.MemBuddy*, pt: mlirlite.LLVMType*) -> str: """指针被指类型映射到已注册类名;失败返回 None""" - if pt is None: - return None + if pt is None: return None return self.Gen.StructGen.get_class_name_by_type(pool, pt) # ============================================================ # _is_inheritance_upcast - 继承上转判据(Derived* → Base*,含多级) @@ -583,22 +541,17 @@ novirtual class ExprGenBase: dst_pt: mlirlite.LLVMType*) -> int: """派生类指针 → 基类指针(含多级):1=允许上转 / 0=否""" src_name: str = self._class_name_of_ptr_pointee(pool, src_pt) - if src_name is None: - return 0 + if src_name is None: return 0 dst_name: str = self._class_name_of_ptr_pointee(pool, dst_pt) - if dst_name is None: - return 0 - if string.strcmp(src_name, dst_name) == 0: - return 0 + if dst_name is None: return 0 + if string.strcmp(src_name, dst_name) == 0: return 0 chain: sizet* = self.Gen.StructGen.get_mro_chain(pool, src_name) - if chain is None: - return 0 + if chain is None: return 0 # chain[0] = 自身;父类/祖先在后,遇 0 终止。只查「自身之后」的祖先。 i: int = 1 while chain[i] != 0: anc: str = rawptr(chain[i]) - if anc is not None and string.strcmp(anc, dst_name) == 0: - return 1 + if anc is not None and string.strcmp(anc, dst_name) == 0: return 1 i += 1 return 0 # ============================================================ @@ -616,18 +569,15 @@ novirtual class ExprGenBase: src_pt: mlirlite.LLVMType*, dst_pt: mlirlite.LLVMType*) -> int: """源被指类型是定长数组且目标被指类型是其元素类型:1=是 / 0=否""" - if src_pt is None or dst_pt is None: - return 0 - if self.is_array_type(src_pt) == 0: - return 0 + if src_pt is None or dst_pt is None: return 0 + if self.is_array_type(src_pt) == 0: return 0 elem: mlirlite.LLVMType* = None match src_pt: case mlirlite.LLVMType.Array(et, _): elem = et case _: return 0 - if elem is None: - return 0 + if elem is None: return 0 return self.Gen.AssignGen._stg_ty_equal(pool, elem, dst_pt) # ============================================================ # _pointee_convert_reason - 被指类型 src_pt → dst_pt(T*→U* 的 T→U 关系)判定码 @@ -646,26 +596,22 @@ novirtual class ExprGenBase: src_pt: mlirlite.LLVMType*, dst_pt: mlirlite.LLVMType*) -> int: """被指类型 src_pt → dst_pt 的判定码(PC_OK/PC_NONBASIC/PC_LOSSY/PC_DEPTH)""" - if src_pt is None or dst_pt is None: - return PC_OK + if src_pt is None or dst_pt is None: return PC_OK s_is_ptr: int = self.is_ptr_type(src_pt) d_is_ptr: int = self.is_ptr_type(dst_pt) if s_is_ptr != 0 or d_is_ptr != 0: # 一侧是指针、另一侧不是(如被指类型 Foo vs Foo*)→ 非基本类型值/指针互换,禁止 - if s_is_ptr == 0 or d_is_ptr == 0: - return PC_NONBASIC + if s_is_ptr == 0 or d_is_ptr == 0: return PC_NONBASIC # 两侧都是指针:递归 return self._ptr_cast_reason(pool, src_pt, dst_pt) # 一侧是非基本类型(结构体/类/联合/数组/函数)→ 一般禁止 if self._is_basic_scalar_ty(src_pt) == 0 or self._is_basic_scalar_ty(dst_pt) == 0: # 豁免一:Derived* → Base* 继承上转(含多级)允许(C++/GCC 同口径) - if self._is_inheritance_upcast(pool, src_pt, dst_pt) != 0: - return PC_OK + if self._is_inheritance_upcast(pool, src_pt, dst_pt) != 0: return PC_OK # 豁免二:数组退让(单向)——源被指类型是定长数组 Array(T, N)、目标被指 # 类型恰为其元素类型 T ⇒ 允许(数组指针 → 元素指针)。多维按最外层退让 # 一层;反向 T → Array(T, N) 与其它非基本类型规则不变,仍禁止。 - if self._is_array_decay(pool, src_pt, dst_pt) != 0: - return PC_OK + if self._is_array_decay(pool, src_pt, dst_pt) != 0: return PC_OK return PC_NONBASIC return self._scalar_convert_reason(src_pt, dst_pt) # ============================================================ @@ -682,21 +628,16 @@ novirtual class ExprGenBase: src_ty: mlirlite.LLVMType*, dst_ty: mlirlite.LLVMType*) -> int: """指针 → 指针对隐式转换的判定码(PC_OK 表示允许)""" - if src_ty is None or dst_ty is None: - return PC_OK + if src_ty is None or dst_ty is None: return PC_OK slev: int = self.get_ptr_level(src_ty) dlev: int = self.get_ptr_level(dst_ty) - if slev == 0 or dlev == 0: - return PC_OK + if slev == 0 or dlev == 0: return PC_OK # 层数不同 → 禁止(无论被指类型) - if slev != dlev: - return PC_DEPTH + if slev != dlev: return PC_DEPTH # 规则 4:完全相同类型(层数 + 逐级被指类型都相同)不算转换 - if self.Gen.AssignGen._stg_ty_equal(pool, src_ty, dst_ty) != 0: - return PC_OK + if self.Gen.AssignGen._stg_ty_equal(pool, src_ty, dst_ty) != 0: return PC_OK # 规则 1:通用指针是通配(i8* ↔ 任何 T*) - if self._is_universal_ptr_ty(src_ty) != 0 or self._is_universal_ptr_ty(dst_ty) != 0: - return PC_OK + if self._is_universal_ptr_ty(src_ty) != 0 or self._is_universal_ptr_ty(dst_ty) != 0: return PC_OK # 规则 2/3:逐级比较被指类型 return self._pointee_convert_reason(pool, src_ty.Pointee, dst_ty.Pointee) # ============================================================ @@ -705,14 +646,11 @@ novirtual class ExprGenBase: def _type_text(self, pool: memhub.MemBuddy*, ty: mlirlite.LLVMType*) -> str: """LLVM 类型文本(TypePrint);失败返回 "?" """ - if ty is None: - return "?" + if ty is None: return "?" buf: str = pool.alloc(512) - if buf is None: - return "?" + if buf is None: return "?" mlirlite.TypePrint(buf, 512, ty, pool) - if buf[0] == 0: - return "?" + if buf[0] == 0: return "?" return buf # ============================================================ # _ptr_cast_reason_text - 把指针间隐式转换的禁止原因写成可读文本 @@ -725,12 +663,9 @@ novirtual class ExprGenBase: dst_ty: mlirlite.LLVMType*) -> str: """指针间隐式转换禁止原因的可读文本(含源/目标类型)""" 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 = "被指类型之间的转换有损(整数→浮点位宽不足 / 浮点→整数)" + 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 = "被指类型之间的转换有损(整数→浮点位宽不足 / 浮点→整数)" 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}") @@ -748,11 +683,9 @@ novirtual class ExprGenBase: def _ctor_call_agg_ty(self, node: ast.AST*) -> mlirlite.LLVMType*: """node(或其值子节点)是构造调用 → 返回其构造的聚合类型;否则 None""" n: ast.AST* = self._value_node_of(node) - if n is None or n.kind() != ast.ASTKind.Call: - return None + if n is None or n.kind() != ast.ASTKind.Call: return None cl: ast.Call* = ast.Call*(n) - if cl.func is None: - return None + if cl.func is None: return None callee: str = None if cl.func.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(cl.func) @@ -760,11 +693,9 @@ novirtual class ExprGenBase: elif cl.func.kind() == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(cl.func) callee = at.attr - if callee is None: - return None + if callee is None: return None ent: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(callee) - if ent is not None and ent.Ty is not None: - return ent.Ty + if ent is not None and ent.Ty is not None: return ent.Ty # REnum 变体构造 `EnumType.Variant(...)`:被调方是「基础枚举.变体」,变体名不是 # 结构体名(find_struct 必 miss);但构造结果物化的就是**基础枚举**的整对象 # (boxed 指针指向该枚举结构体)⇒ 返回该 REnum 的聚合类型,使「构造物化」豁免 @@ -778,14 +709,11 @@ novirtual class ExprGenBase: qual: ast.AST* = (ast.Attribute*(cl.func)).value base_nm: str = None if qual is not None: - if qual.kind() == ast.ASTKind.Attribute: - base_nm = (ast.Attribute*(qual)).attr - elif qual.kind() == ast.ASTKind.Name: - base_nm = (ast.Name*(qual)).id + if qual.kind() == ast.ASTKind.Attribute: base_nm = (ast.Attribute*(qual)).attr + elif qual.kind() == ast.ASTKind.Name: base_nm = (ast.Name*(qual)).id if base_nm is not None and self.Gen.ClassGenEnum._is_renum_class_name(base_nm) != 0: rn_ent: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(base_nm) - if rn_ent is not None and rn_ent.Ty is not None: - return rn_ent.Ty + if rn_ent is not None and rn_ent.Ty is not None: return rn_ent.Ty return None # ============================================================ # _same_agg_ty - 两个聚合类型是否为「同一非基本类型」(构造物化豁免的类型匹配) @@ -793,8 +721,7 @@ novirtual class ExprGenBase: def _same_agg_ty(self, pool: memhub.MemBuddy*, a: mlirlite.LLVMType*, b: mlirlite.LLVMType*) -> int: """a、b 是否为同一聚合类型,1=是 / 0=否""" - if a is None or b is None: - return 0 + if a is None or b is None: return 0 return self.Gen.AssignGen._stg_ty_equal(pool, a, b) # ============================================================ # 类型强制转换:整数 sext/trunc,浮点 fpext/fptrunc,int↔float si2fp/fp2si @@ -823,8 +750,7 @@ novirtual class ExprGenBase: # 真实用例:`p.fd_used[fd] = None`(fd_used 为整数数组字段)曾被 # 「指针隐式转整数已禁止」拦成 CastError。 if self.IsNoneValue(val, node) != 0: - if self.is_ptr_type(target_ty) != 0: - return mlirlite.build_bitcast(builder, val, target_ty) + if self.is_ptr_type(target_ty) != 0: return mlirlite.build_bitcast(builder, val, target_ty) return self._NoneValueAsTarget(builder, target_ty) # void 类型的值**不允许被当作值使用**(用户 2026-10-01:void 只能用于 `void*` # 与 `typedef 不透明结构体 = void`)。任何把 void 值 coerce 到非 void 目标 @@ -840,8 +766,7 @@ novirtual class ExprGenBase: # 函数 Value 的 Ty 是 Func,既不是整数也不是指针,需在整数/浮点转换之前处理 match val.Ty: case mlirlite.LLVMType.Func(_, _, _): - if self.is_ptr_type(target_ty) != 0: - return mlirlite.build_bitcast(builder, val, target_ty) + if self.is_ptr_type(target_ty) != 0: return mlirlite.build_bitcast(builder, val, target_ty) return val case _: pass @@ -861,8 +786,7 @@ novirtual class ExprGenBase: # NULL 是 t.CDefine = 0(如 self.handle = NULL / CreateThread(NULL,...)), # 属标准 C 空指针用法,须放行而非报 CastError。先拓宽到 i64 # (inttoptr 要求同宽,对齐 MatchGenMixin 模式),再 inttoptr 成空指针。 - if val.IsConst == 1 and val.IntVal == 0: - return mlirlite.build_inttoptr(builder, mlirlite.const_int64(builder.Pool, 0), target_ty) + 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))才能把整数赋给指针类型" self.Gen.TypeGenErr.fatal_error(self._value_node_of(node), m_i2p, "CastError") @@ -877,8 +801,7 @@ novirtual class ExprGenBase: m_p2i, "CastError") return val if val_bits != 0 and target_bits != 0: - if val_bits == target_bits: - return val + if val_bits == target_bits: return val # 目标 i1(bool / t.CBool):**真值归一化** `x != 0 → 1/0`(C 6.3.1.2 的 # _Bool 转换语义),不是 trunc(取最低位)。判据与 `bool(x)` # (CallGenDispatch.vp:255-281)、条件归一化(AsyncGenMixin.vp:1611 @@ -899,8 +822,7 @@ novirtual class ExprGenBase: # trans 必须下传:_node_type_unsigned 对 Name/Subscript 形态需经 # trans.SymTab 查变量注解(uint16/sec:uint32 等)才能判定无符号, # 否则返回未知 → 退回 sext(无符号扩展缺陷根因)。 - if self._zext_or_sext_val(builder.Pool, val, node, trans) != 0: - return mlirlite.build_zext(builder, val, target_ty) + if self._zext_or_sext_val(builder.Pool, val, node, trans) != 0: return mlirlite.build_zext(builder, val, target_ty) return mlirlite.build_sext(builder, val, target_ty) # 窄化截断诊断(_Type.md 问题 8):宽→窄 trunc 静默丢位。 # 编译期已知常量且正溢出目标位宽无符号范围 → fail-fast(确定性数据 @@ -922,17 +844,13 @@ novirtual class ExprGenBase: "unsupported type conversion: float <-> ptr", "CastError") return val if val_fbits != 0 and target_fbits != 0: - if val_fbits == target_fbits: - return val - if val_fbits < target_fbits: - return mlirlite.build_fpext(builder, val, target_ty) + if val_fbits == target_fbits: return val + if val_fbits < target_fbits: return mlirlite.build_fpext(builder, val, target_ty) return mlirlite.build_fptrunc(builder, val, target_ty) # int → float - if val_bits != 0 and target_fbits != 0: - return mlirlite.build_si2fp(builder, val, target_ty) + if val_bits != 0 and target_fbits != 0: return mlirlite.build_si2fp(builder, val, target_ty) # float → int - if val_fbits != 0 and target_bits != 0: - return mlirlite.build_fp2si(builder, val, target_ty) + if val_fbits != 0 and target_bits != 0: return mlirlite.build_fp2si(builder, val, target_ty) # 聚合值 → 指针:落栈 materialize 临时对象后传其地址。FuncGenDef 已确认「裸类/数组形参一律 lowering 为 Ptr(struct/array)」——TPV 内部函数/方法不存在"按值传结构体"的形参(唯一例外:C ABI 外部声明的裸结构体形参按值,见 VpiReader._AggregateParamTy「三处必须同步」)。故调用点的 rvalue 聚合(函数调用返回值、下标元素 load 等)必须落栈取址,否则实参类型与指针形参失配。alloca 走入口块(支配性安全),生命周期覆盖整个调用,pointee 与聚合类型一致时直接用 alloca 地址 if self.is_ptr_type(val.Ty) == 0 and self.is_ptr_type(target_ty) != 0: vk_agg: int = val.Ty.kind() @@ -952,13 +870,11 @@ novirtual class ExprGenBase: mlirlite.build_store(builder, val, tmp_agg) match target_ty: case mlirlite.LLVMType.Ptr(pointee_agg): - if self.Gen.AssignGen._stg_ty_equal(builder.Pool, pointee_agg, val.Ty) != 0: - return tmp_agg + if self.Gen.AssignGen._stg_ty_equal(builder.Pool, pointee_agg, val.Ty) != 0: return tmp_agg case _: pass bc_agg: mlirlite.Value* = mlirlite.build_bitcast(builder, tmp_agg, target_ty) - if bc_agg is not None: - return bc_agg + if bc_agg is not None: return bc_agg return tmp_agg # Pointer -> non-pointer value: aggregate targets keep the implicit load **only** # for 「构造物化」(a constructor returning Ptr(Struct) held in a Struct-typed @@ -1048,8 +964,7 @@ novirtual class ExprGenBase: inner_ty = inner case _: return None - if inner_ty is None: - return None + if inner_ty is None: return None decayed: mlirlite.Value* = mlirlite.build_gep_array(builder, elem_ty, inner_ty, ptr_val, mlirlite.const_int64(pool, 0)) if decayed is None: return None return mlirlite.build_gep(builder, inner_ty, decayed, idx) diff --git a/App/lib/core/Gen/Expr/ExprGenCdef.vp b/App/lib/core/Gen/Expr/ExprGenCdef.vp index b0c82d3..43c835e 100644 --- a/App/lib/core/Gen/Expr/ExprGenCdef.vp +++ b/App/lib/core/Gen/Expr/ExprGenCdef.vp @@ -43,14 +43,12 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): if string.strcmp(cur_sha1, sha1) == 0: idx_s = i break - if idx_s < 0: - return None + if idx_s < 0: return None # 获取相对路径(MAX_REL_PATH_LEN=256,避免跨模块 CDefine 解析问题) MAX_RPL: sizet = 256 ridx: sizet = sizet(idx_s) * MAX_RPL rel_path: str = rel_arr_ptr + ridx - if rel_path[0] == '\0': - return None + if rel_path[0] == '\0': return None # 选择基础目录(优先级):1) 条目存储的 includes 根目录 IncDir(绝对路径,支持多 includes 目录,避免"首 includes 目录"启发式对非首目录文件失效);2) rel_path 前缀启发式——以 "lib/" 开头 → App 源文件(SourceDir);"includes/" 开头 → includes 文件(去掉前缀);其他无前缀路径先试 SourceDir,不存在再试 IncludesDir base_dir: str = None rel_used: str = rel_path @@ -58,8 +56,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): if inc_arr_ptr is not None: iidx: sizet = sizet(idx_s) * StubMerger.MAX_INC_DIR_LEN inc_dir: str = inc_arr_ptr + iidx - if inc_dir[0] != '\0': - base_dir = inc_dir + if inc_dir[0] != '\0': base_dir = inc_dir if base_dir is None and string.strlen(rel_path) >= 4: if (rel_path[0] == 'l' and rel_path[1] == 'i' and rel_path[2] == 'b' and rel_path[3] == '/'): @@ -72,15 +69,13 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): rel_path[8] == '/'): rel_used = rel_path + 9 base_dir = Config.IncludesDir - if base_dir is None: - base_dir = Config.SourceDir if Config.SourceDir is not None else Config.IncludesDir + if base_dir is None: base_dir = Config.SourceDir if Config.SourceDir is not None else Config.IncludesDir # 构建完整路径: {base_dir}/{rel_used} base_len: sizet = string.strlen(base_dir) rel_len: sizet = string.strlen(rel_used) path_len: sizet = base_len + rel_len + 2 buf: str = stdlib.malloc(path_len) - if buf is None: - return None + if buf is None: return None viperlib.snprintf(buf, path_len, "%s/%s", base_dir, rel_used) # 存在性检查:SourceDir 下不存在且 IncludesDir 不同 → 重试 IncludesDir pf_chk: rawptr[fileio.File] = fileio.File(buf, fileio.MODE.R) @@ -91,8 +86,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): base_len2: sizet = string.strlen(Config.IncludesDir) path_len2: sizet = base_len2 + rel_len + 2 buf = stdlib.malloc(path_len2) - if buf is None: - return None + if buf is None: return None viperlib.snprintf(buf, path_len2, "%s/%s", Config.IncludesDir, rel_used) pf_chk2: rawptr[fileio.File] = fileio.File(buf, fileio.MODE.R) if pf_chk2.closed: @@ -103,8 +97,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): else: stdlib.free(buf) return None - else: - pf_chk.close() + else: pf_chk.close() return buf # ============================================================ # _lookup_cross_module_cdefine - 跨模块查找 CDefine 常量 @@ -152,10 +145,8 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): # 入口处清零标志,确保所有早退路径(return -1)都返回"未找到"状态 # 避免递归调用时前一次成功的标志残留导致误判 self.Gen.TypeGenCDef.set_cdefine_found(0) - if name is None: - return -1 - if from_imports is None: - from_imports = "" + if name is None: return -1 + if from_imports is None: from_imports = "" # 1. 从 from_imports 查找名称对应的模块名 # 先尝试精确匹配(allow_star_fallback=0),避免 CDefine 常量被 star import 误导 @@ -173,17 +164,14 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): base_mod: str = None if mod_name_raw is not None: mbl: sizet = 0 - while mod_name_raw[mbl] != ' ' and mod_name_raw[mbl] != '\0' and mod_name_raw[mbl] != ':': - mbl += 1 + while mod_name_raw[mbl] != ' ' and mod_name_raw[mbl] != '\0' and mod_name_raw[mbl] != ':': mbl += 1 mb_buf: str = pool.alloc(mbl + 1) if mb_buf is not None: mi2: sizet - for mi2 in range(mbl): - mb_buf[mi2] = mod_name_raw[mi2] + for mi2 in range(mbl): mb_buf[mi2] = mod_name_raw[mi2] mb_buf[mbl] = '\0' base_mod = mb_buf - while base_mod is not None and base_mod[0] == '.': - base_mod = base_mod + 1 + while base_mod is not None and base_mod[0] == '.': base_mod = base_mod + 1 # 跨模块 CDefine 查找缓存(perm_pool 永久,跨文件复用): # 首次查找成功后结果缓存,后续文件(含 reset_to(mark2)/模块切换)直接命中, @@ -200,8 +188,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): viperlib.snprintf(xkey_buf, xk_len, "%s@%s", name, base_mod) xval: str = self.Gen.TypeGenCDef.lookup_xmod_cdefine(xkey_buf) if self.Gen.TypeGenCDef.is_cdefine_found() != 0: - if self.Gen.TypeGenCDef.is_cdefine_str() != 0: - self.Gen.TypeGenCDef.register_cdefine_string(pool, name, xval) + if self.Gen.TypeGenCDef.is_cdefine_str() != 0: self.Gen.TypeGenCDef.register_cdefine_string(pool, name, xval) elif self.Gen.TypeGenCDef.is_cdefine_double() != 0: xd_v: double = string.atof(xval) self.Gen.TypeGenCDef.register_cdefine_double(pool, name, xd_v) @@ -216,8 +203,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): if mod_name_raw is None: # from_imports 完全没有匹配(精确和 star 都失败) # 直接进入 imported_modules 遍历(步骤 9.6) - if imported_modules is None: - return -1 + if imported_modules is None: return -1 # 跳过 from_imports 模块读取,直接走步骤 9.6 的 imported_modules 遍历 # 设置 result_found=0 跳过步骤 3-9,直接到 9.6 self.Gen.TypeGenCDef.set_cdefine_found(0) @@ -225,13 +211,10 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): im_len: sizet = string.strlen(imported_modules) im_ci: sizet = 0 while im_ci < im_len: - while im_ci < im_len and imported_modules[im_ci] == ' ': - im_ci += 1 - if im_ci >= im_len: - break + while im_ci < im_len and imported_modules[im_ci] == ' ': im_ci += 1 + if im_ci >= im_len: break im_start: sizet = im_ci - while im_ci < im_len and imported_modules[im_ci] != ' ': - im_ci += 1 + while im_ci < im_len and imported_modules[im_ci] != ' ': im_ci += 1 im_end: sizet = im_ci im_nlen: sizet = im_end - im_start if im_nlen > 0 and im_nlen < 256: @@ -252,25 +235,21 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): mk2 += 1 sub_fi[2 + im_nlen] = '\0' sub_val: int64 = self._lookup_cross_module_cdefine(pool, name, sub_fi, None, depth + 1, node) - if self.Gen.TypeGenCDef.is_cdefine_found() != 0: - return sub_val + if self.Gen.TypeGenCDef.is_cdefine_found() != 0: return sub_val return -1 # 2. 截断模块名 → 去前导点 → 精确+后缀查找 SHA1(复用 HandlesExprCall 公共逻辑) sha1: str = self.Gen.CallGenBase._lookup_sha1_from_modname_raw(pool, mod_name_raw) - if sha1 is None: - return -1 + if sha1 is None: return -1 # 5. 获取 temp_dir temp_dir: str = self.Gen.TypeGenBase.get_temp_dir() - if temp_dir is None: - return -1 + if temp_dir is None: return -1 # 6. 构建 vpi 文件路径 td_len: sizet = string.strlen(temp_dir) pyi_path: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "vpi") - if pyi_path is None: - return -1 + if pyi_path is None: return -1 # 7. 读取 vpi 文件;若不存在或内容过短(空 stub)则回退读取源 .vp/.py 文件 PYI_READ_BUF_SIZE: sizet = 65536 @@ -288,11 +267,9 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): bytes_read = pf.read_all(pyi_buf, PYI_READ_BUF_SIZE) pf.close() # vpi 内容过短(< 10 字节)视为空 stub,回退 .py - if bytes_read < 10: - need_py_fallback = 1 + if bytes_read < 10: need_py_fallback = 1 else: - if bytes_read < PYI_READ_BUF_SIZE: - pyi_buf[bytes_read] = 0 + if bytes_read < PYI_READ_BUF_SIZE: pyi_buf[bytes_read] = 0 # vpi(存根签名文件)中的 CDefine 声明可能只带名字不带值 # (Converter 旧版只对 CONST_INT/BOOL 等输出 "= value",CONST_FLOAT # 等不输出 → numpy 的 pi/e 在 stub 中无值),真正的值在源 @@ -326,19 +303,16 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): cd_sig = 1 # 定位该行行首,检查是否以 "name:" 开头(目标名带值) cs_line_start: sizet = cs_i - while cs_line_start > 0 and pyi_buf[cs_line_start - 1] != '\n': - cs_line_start -= 1 + while cs_line_start > 0 and pyi_buf[cs_line_start - 1] != '\n': cs_line_start -= 1 if cs_i - cs_line_start >= cs_name_len + 1: nm_ok: int = 1 for ki2 in range(cs_name_len): if pyi_buf[cs_line_start + ki2] != name[ki2]: nm_ok = 0 break - if nm_ok == 1 and pyi_buf[cs_line_start + cs_name_len] == ':': - name_has_val = 1 + if nm_ok == 1 and pyi_buf[cs_line_start + cs_name_len] == ':': name_has_val = 1 cs_i += 1 - if cd_sig == 0 or name_has_val == 0: - need_py_fallback = 1 + if cd_sig == 0 or name_has_val == 0: need_py_fallback = 1 stdlib.free(pyi_path) if need_py_fallback != 0: @@ -366,8 +340,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): if bytes_read <= 0: stdlib.free(pyi_buf) return -1 - if bytes_read < PYI_READ_BUF_SIZE: - pyi_buf[bytes_read] = 0 + if bytes_read < PYI_READ_BUF_SIZE: pyi_buf[bytes_read] = 0 # 8. 在 pyi_buf 中查找 "name: t.CDefine = value" 行 # 格式: NAME: t.CDefine = value @@ -382,24 +355,20 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): # 找到行首 line_start: sizet = pos # 找到行尾 - while pos < total_len and pyi_buf[pos] != '\n': - pos += 1 + while pos < total_len and pyi_buf[pos] != '\n': pos += 1 line_len: sizet = pos - line_start if pos < total_len: pos += 1 # 跳过 '\n' # 检查行是否以 "name:" 开头 - if line_len < name_len + 1: - continue + if line_len < name_len + 1: continue match_ok: int = 1 for ki in range(name_len): if pyi_buf[line_start + ki] != name[ki]: match_ok = 0 break - if match_ok == 0: - continue - if pyi_buf[line_start + name_len] != ':': - continue + if match_ok == 0: continue + if pyi_buf[line_start + name_len] != ':': continue # 检查行是否包含 "t.CDefine" # 在行中查找 "t.CDefine" @@ -414,20 +383,16 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): has_cdefine = 1 break ci += 1 - if has_cdefine == 0: - continue + if has_cdefine == 0: continue # 找到 "=" 后面的值 eq_pos: sizet = line_start + name_len + 1 - while eq_pos < line_start + line_len and pyi_buf[eq_pos] != '=': - eq_pos += 1 - if eq_pos >= line_start + line_len: - continue + while eq_pos < line_start + line_len and pyi_buf[eq_pos] != '=': eq_pos += 1 + if eq_pos >= line_start + line_len: continue eq_pos += 1 # 跳过 '=' # 跳过空格 - while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ': - eq_pos += 1 + while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ': eq_pos += 1 # 检查是否是 t.CUnsignedLong(...) / t.CLong(...) / int(...) 等类型构造函数 # 格式: t.CUnsignedLong(-11) / t.CUnsignedLong(0xFFFFFFFF) @@ -437,22 +402,19 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): if pyi_buf[eq_pos] == 't' and pyi_buf[eq_pos + 1] == '.': # 找到 '(' 的位置 paren_pos: sizet = eq_pos + 2 - while paren_pos < line_start + line_len and pyi_buf[paren_pos] != '(': - paren_pos += 1 + while paren_pos < line_start + line_len and pyi_buf[paren_pos] != '(': paren_pos += 1 if paren_pos < line_start + line_len and pyi_buf[paren_pos] == '(': is_type_ctor = 1 eq_pos = paren_pos + 1 # 跳过 '(' # 跳过括号内可能的前导空格 - while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ': - eq_pos += 1 + while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ': eq_pos += 1 # 括号包裹标记:(1 << 23) / (512) / (A | B) is_paren_expr: int = 0 if eq_pos < line_start + line_len and pyi_buf[eq_pos] == '(': is_paren_expr = 1 eq_pos += 1 - while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ': - eq_pos += 1 + while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ': eq_pos += 1 # === 解析左操作数 token(数字 / hex / 负号 / 名称) === # 负号标记 @@ -490,8 +452,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): if (c_tk >= 'A' and c_tk <= 'Z') or (c_tk >= 'a' and c_tk <= 'z') or (c_tk >= '0' and c_tk <= '9') or c_tk == '_': val_str_len += 1 eq_pos += 1 - else: - break + else: break # 数字/hex 字符续读(字符串值已整体读取,跳过) while eq_pos < line_start + line_len and is_name_val == 0 and is_str_val == 0: ch: char = pyi_buf[eq_pos] @@ -501,8 +462,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): (ch >= 'A' and ch <= 'F')): val_str_len += 1 eq_pos += 1 - else: - break + else: break else: if ch >= '0' and ch <= '9': val_str_len += 1 @@ -512,18 +472,14 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): is_float_val = 1 val_str_len += 1 eq_pos += 1 - else: - break + else: break - if val_str_len == 0 and is_str_val == 0: - continue + if val_str_len == 0 and is_str_val == 0: continue # 复制左 token 到缓冲区 val_buf: str = pool.alloc(val_str_len + 1) - if val_buf is None: - continue - for vi in range(val_str_len): - val_buf[vi] = pyi_buf[val_str_start + vi] + if val_buf is None: continue + for vi in range(val_str_len): val_buf[vi] = pyi_buf[val_str_start + vi] val_buf[val_str_len] = '\0' # 左 token 求值 @@ -540,10 +496,8 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): res_is_str = 1 elif is_name_val != 0: # True/False 布尔字面量 → 1/0(对齐 TPC:bool 在 CDefine 语境按整数处理) - if string.strcmp(val_buf, "True") == 0: - lval = 1 - elif string.strcmp(val_buf, "False") == 0: - lval = 0 + if string.strcmp(val_buf, "True") == 0: lval = 1 + elif string.strcmp(val_buf, "False") == 0: lval = 0 else: # 名称引用:查当前 CDefine 表(如 FOREGROUND_COMBO = FOREGROUND_RED) lval = self.Gen.TypeGenCDef.lookup_cdefine_constant(val_buf) @@ -558,30 +512,23 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): for hi in range(val_str_len - 2): hc: char = hex_buf[hi] hd: int = 0 - if hc >= '0' and hc <= '9': - hd = hc - '0' - elif hc >= 'a' and hc <= 'f': - hd = hc - 'a' + 10 - elif hc >= 'A' and hc <= 'F': - hd = hc - 'A' + 10 - else: - break + if hc >= '0' and hc <= '9': hd = hc - '0' + elif hc >= 'a' and hc <= 'f': hd = hc - 'a' + 10 + elif hc >= 'A' and hc <= 'F': hd = hc - 'A' + 10 + else: break hex_result = hex_result * 16 + hd lval = hex_result elif is_float_val != 0: l_is_double = 1 ldbl = string.atof(val_buf) lval = string.atoll(val_buf) - else: - lval = string.atoll(val_buf) + else: lval = string.atoll(val_buf) if is_neg != 0: lval = -lval - if l_is_double != 0: - ldbl = -ldbl + if l_is_double != 0: ldbl = -ldbl # 跳过空格,检查是否有二元运算符 - while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ': - eq_pos += 1 + while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ': eq_pos += 1 # 解析运算符(<< >> | & ^ + - * /) cd_op: int = 0 @@ -617,8 +564,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): if cd_op != 0: # === 解析右操作数 token === - while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ': - eq_pos += 1 + while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ': eq_pos += 1 r_neg: int = 0 if eq_pos < line_start + line_len and pyi_buf[eq_pos] == '-': r_neg = 1 @@ -639,8 +585,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): if (c_r >= 'A' and c_r <= 'Z') or (c_r >= 'a' and c_r <= 'z') or (c_r >= '0' and c_r <= '9') or c_r == '_': r_len += 1 eq_pos += 1 - else: - break + else: break while eq_pos < line_start + line_len and r_name == 0: c_r2: char = pyi_buf[eq_pos] if r_hex == 1: @@ -649,30 +594,24 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): (c_r2 >= 'A' and c_r2 <= 'F')): r_len += 1 eq_pos += 1 - else: - break + else: break else: if c_r2 >= '0' and c_r2 <= '9': r_len += 1 eq_pos += 1 - else: - break + else: break if r_len == 0: # 运算符后无右操作数:无法求值,跳过该行 continue r_buf: str = pool.alloc(r_len + 1) - if r_buf is None: - continue - for r_i in range(r_len): - r_buf[r_i] = pyi_buf[r_start + r_i] + if r_buf is None: continue + for r_i in range(r_len): r_buf[r_i] = pyi_buf[r_start + r_i] r_buf[r_len] = '\0' rval: int64 = 0 if r_name != 0: # True/False 布尔字面量 → 1/0 - if string.strcmp(r_buf, "True") == 0: - rval = 1 - elif string.strcmp(r_buf, "False") == 0: - rval = 0 + if string.strcmp(r_buf, "True") == 0: rval = 1 + elif string.strcmp(r_buf, "False") == 0: rval = 0 else: rval = self.Gen.TypeGenCDef.lookup_cdefine_constant(r_buf) if self.Gen.TypeGenCDef.is_cdefine_found() == 0: @@ -684,50 +623,33 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): for rh_i in range(r_len - 2): rc: char = rh_buf[rh_i] rd: int = 0 - if rc >= '0' and rc <= '9': - rd = rc - '0' - elif rc >= 'a' and rc <= 'f': - rd = rc - 'a' + 10 - elif rc >= 'A' and rc <= 'F': - rd = rc - 'A' + 10 - else: - break + if rc >= '0' and rc <= '9': rd = rc - '0' + elif rc >= 'a' and rc <= 'f': rd = rc - 'a' + 10 + elif rc >= 'A' and rc <= 'F': rd = rc - 'A' + 10 + else: break rhex_v = rhex_v * 16 + rd rval = rhex_v - else: - rval = string.atoll(r_buf) - if r_neg != 0: - rval = -rval + else: rval = string.atoll(r_buf) + if r_neg != 0: rval = -rval # 计算二元表达式结果(对齐 TPC ConstEvaluator) - if cd_op == 1: - result_val = lval << rval - elif cd_op == 2: - result_val = lval >> rval - elif cd_op == 3: - result_val = lval | rval - elif cd_op == 4: - result_val = lval & rval - elif cd_op == 5: - result_val = lval ^ rval - elif cd_op == 6: - result_val = lval + rval - elif cd_op == 7: - result_val = lval - rval - elif cd_op == 8: - result_val = lval * rval + if cd_op == 1: result_val = lval << rval + elif cd_op == 2: result_val = lval >> rval + elif cd_op == 3: result_val = lval | rval + elif cd_op == 4: result_val = lval & rval + elif cd_op == 5: result_val = lval ^ rval + elif cd_op == 6: result_val = lval + rval + elif cd_op == 7: result_val = lval - rval + elif cd_op == 8: result_val = lval * rval else: - if rval == 0: - continue + if rval == 0: continue result_val = lval // rval result_found = 1 break else: # 单值(无运算符):括号内单值如 (512) / (-11) 也走这里 if is_paren_expr != 0: - while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ': - eq_pos += 1 - if eq_pos < line_start + line_len and pyi_buf[eq_pos] == ')': - eq_pos += 1 + while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ': eq_pos += 1 + if eq_pos < line_start + line_len and pyi_buf[eq_pos] == ')': eq_pos += 1 if is_float_val != 0: # 浮点 CDefine(如 U_M_PI = 3.14159...): # 值缓存为 double(register_cdefine_double),供调用处生成 @@ -754,17 +676,13 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): # 找到行首 rc_line_start: sizet = rc_pos # 找到行尾 - while rc_pos < total_len and pyi_buf[rc_pos] != '\n': - rc_pos += 1 + while rc_pos < total_len and pyi_buf[rc_pos] != '\n': rc_pos += 1 rc_line_len: sizet = rc_pos - rc_line_start - if rc_pos < total_len: - rc_pos += 1 + if rc_pos < total_len: rc_pos += 1 # 检查行是否以 "from " 开头(模块导入) - if rc_line_len < 12: - continue - if pyi_buf[rc_line_start] != 'f' or pyi_buf[rc_line_start+1] != 'r' or pyi_buf[rc_line_start+2] != 'o' or pyi_buf[rc_line_start+3] != 'm' or pyi_buf[rc_line_start+4] != ' ': - continue + if rc_line_len < 12: continue + if pyi_buf[rc_line_start] != 'f' or pyi_buf[rc_line_start+1] != 'r' or pyi_buf[rc_line_start+2] != 'o' or pyi_buf[rc_line_start+3] != 'm' or pyi_buf[rc_line_start+4] != ' ': continue # 提取模块路径 token(从 rc_line_start+5 到空格/tab 为止,跳过前导点) # 两种写法都要支持: @@ -780,11 +698,9 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): rc_is_rel = 1 rc_sub_start += 1 rc_sub_end: sizet = rc_sub_start - while rc_sub_end < rc_line_start + rc_line_len and pyi_buf[rc_sub_end] != ' ' and pyi_buf[rc_sub_end] != '\t': - rc_sub_end += 1 + while rc_sub_end < rc_line_start + rc_line_len and pyi_buf[rc_sub_end] != ' ' and pyi_buf[rc_sub_end] != '\t': rc_sub_end += 1 rc_sub_len: sizet = rc_sub_end - rc_sub_start - if rc_sub_len == 0: - continue + if rc_sub_len == 0: continue # 检查行是否包含 "import" rc_has_import: int = 0 @@ -794,8 +710,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): rc_has_import = 1 break rc_ipos += 1 - if rc_has_import == 0: - continue + if rc_has_import == 0: continue # 检查 NAME 是否在导入列表中,或导入是 * # 处理多行导入:from .X import (... NAME, ...) @@ -812,8 +727,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): if pyi_buf[rc_pp] == '(': rc_has_paren = 1 break - if pyi_buf[rc_pp] == '*': - rc_star = 1 + if pyi_buf[rc_pp] == '*': rc_star = 1 rc_pp += 1 if rc_has_paren != 0: # 多行导入:从 "(" 之后扫描到 ")" 为止 @@ -826,15 +740,13 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): rc_scan_end = rc_sp break rc_sp += 1 - if rc_paren_closed == 0: - rc_scan_end = total_len + if rc_paren_closed == 0: rc_scan_end = total_len # 在 rc_imp_start 到 rc_scan_end 范围内查找 NAME 和 * rc_cpos: sizet = rc_imp_start while rc_cpos < rc_scan_end: rc_ch: char = pyi_buf[rc_cpos] - if rc_ch == '*': - rc_star = 1 + if rc_ch == '*': rc_star = 1 # 检查 NAME 是否匹配(作为完整单词) if rc_cpos + name_len_rc <= rc_scan_end: rc_match: int = 1 @@ -846,35 +758,27 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): if rc_match == 1: # 检查前字符是否是非标识符字符 rc_before_ok: int = 0 - if rc_cpos == rc_imp_start: - rc_before_ok = 1 + if rc_cpos == rc_imp_start: rc_before_ok = 1 else: rc_before_ch: char = pyi_buf[rc_cpos - 1] - if rc_before_ch == ' ' or rc_before_ch == '\t' or rc_before_ch == '(' or rc_before_ch == ',' or rc_before_ch == '\n' or rc_before_ch == '\r': - rc_before_ok = 1 + if rc_before_ch == ' ' or rc_before_ch == '\t' or rc_before_ch == '(' or rc_before_ch == ',' or rc_before_ch == '\n' or rc_before_ch == '\r': rc_before_ok = 1 # 检查后字符是否是非标识符字符 rc_after_ok: int = 0 rc_after_pos: sizet = rc_cpos + name_len_rc - if rc_after_pos >= rc_scan_end: - rc_after_ok = 1 + if rc_after_pos >= rc_scan_end: rc_after_ok = 1 else: rc_after_ch: char = pyi_buf[rc_after_pos] - if rc_after_ch == ' ' or rc_after_ch == '\t' or rc_after_ch == ')' or rc_after_ch == ',' or rc_after_ch == '\r' or rc_after_ch == '\n': - rc_after_ok = 1 - if rc_before_ok == 1 and rc_after_ok == 1: - rc_name_match = 1 + if rc_after_ch == ' ' or rc_after_ch == '\t' or rc_after_ch == ')' or rc_after_ch == ',' or rc_after_ch == '\r' or rc_after_ch == '\n': rc_after_ok = 1 + if rc_before_ok == 1 and rc_after_ok == 1: rc_name_match = 1 rc_cpos += 1 - if rc_star == 0 and rc_name_match == 0: - continue + if rc_star == 0 and rc_name_match == 0: continue # 复制子模块名到新缓冲区(pyi_buf + rc_sub_start 不是 NUL 结尾) rc_sub_buf: str = pool.alloc(rc_sub_len + 1) - if rc_sub_buf is None: - continue + if rc_sub_buf is None: continue rc_si: sizet - for rc_si in range(rc_sub_len): - rc_sub_buf[rc_si] = pyi_buf[rc_sub_start + rc_si] + for rc_si in range(rc_sub_len): rc_sub_buf[rc_si] = pyi_buf[rc_sub_start + rc_si] rc_sub_buf[rc_sub_len] = '\0' # 构建完整模块名: @@ -890,17 +794,14 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): if rc_is_rel != 0: rc_base_mod: str = base_mod rc_pkg: str = self.Gen.CallGenBase._module_package_from_sha1(pool, sha1) - if rc_pkg is not None: - rc_base_mod = rc_pkg + if rc_pkg is not None: rc_base_mod = rc_pkg rc_full_len: sizet = string.strlen(rc_base_mod) + 1 + rc_sub_len + 1 rc_full_buf: str = pool.alloc(rc_full_len) - if rc_full_buf is None: - continue + if rc_full_buf is None: continue viperlib.snprintf(rc_full_buf, rc_full_len, "%s.%s", rc_base_mod, rc_sub_buf) rc_full_mod = rc_full_buf else: - if string.strcmp(rc_sub_buf, base_mod) == 0: - continue + if string.strcmp(rc_sub_buf, base_mod) == 0: continue rc_full_mod = rc_sub_buf # 防循环:若 base_mod 已以 "."+rc_sub_buf 结尾(如 ast.base 再拼 @@ -910,14 +811,12 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): rc_blen: sizet = string.strlen(base_mod) if rc_blen > rc_sub_len + 1: rc_tail: str = base_mod + (rc_blen - rc_sub_len) - if rc_tail[0] == '.' and string.strncmp(rc_tail + 1, rc_sub_buf, rc_sub_len) == 0: - continue + if rc_tail[0] == '.' and string.strncmp(rc_tail + 1, rc_sub_buf, rc_sub_len) == 0: continue # 构建临时 from_imports "name:full_mod" rc_fi_len: sizet = name_len_rc + 1 + string.strlen(rc_full_mod) + 1 rc_fi: str = pool.alloc(rc_fi_len) - if rc_fi is None: - continue + if rc_fi is None: continue viperlib.snprintf(rc_fi, rc_fi_len, "%s:%s", name, rc_full_mod) # 递归调用查找子模块 @@ -936,13 +835,10 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): im2_len: sizet = string.strlen(imported_modules) im2_ci: sizet = 0 while im2_ci < im2_len and result_found == 0: - while im2_ci < im2_len and imported_modules[im2_ci] == ' ': - im2_ci += 1 - if im2_ci >= im2_len: - break + while im2_ci < im2_len and imported_modules[im2_ci] == ' ': im2_ci += 1 + if im2_ci >= im2_len: break im2_start: sizet = im2_ci - while im2_ci < im2_len and imported_modules[im2_ci] != ' ': - im2_ci += 1 + while im2_ci < im2_len and imported_modules[im2_ci] != ' ': im2_ci += 1 im2_end: sizet = im2_ci im2_nlen: sizet = im2_end - im2_start if im2_nlen > 0 and im2_nlen < 256: @@ -1008,8 +904,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): stdio.snprintf(cbuf_d, 64, "%.17g", dval_cc) self.Gen.TypeGenCDef.register_xmod_cdefine(ckey2, cbuf_d, 1, 0) self.Gen.TypeGenCDef.set_cdefine_found(1) - else: - self.Gen.TypeGenCDef.set_cdefine_found(0) + else: self.Gen.TypeGenCDef.set_cdefine_found(0) return result_val # ============================================================ @@ -1026,16 +921,13 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): # ============================================================ def _is_cdefine_name_pattern(self, name: str) -> int: """检查名字是否符合 CDefine 命名约定(全大写+下划线+数字)""" - if name is None: - return 0 + if name is None: return 0 has_upper: int = 0 i: sizet = 0 while name[i] != '\0': c: char = name[i] - if c >= 'a' and c <= 'z': - return 0 - if c >= 'A' and c <= 'Z': - has_upper = 1 + if c >= 'a' and c <= 'z': return 0 + if c >= 'A' and c <= 'Z': has_upper = 1 i += 1 return has_upper # ============================================================ @@ -1084,8 +976,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): ⇒ MemBuddy canary 校验 rc=6 假阳性。下限判据与既有 ExprGenConst.vp:108 / CallGenLeafKit.vp:1477 的写法一致。 """ - if (value >= 0 and uint64(uint32(value)) != value) or value < -2147483648: - return mlirlite.const_int64(pool, value) + if (value >= 0 and uint64(uint32(value)) != value) or value < -2147483648: return mlirlite.const_int64(pool, value) return mlirlite.const_int32(pool, int(value)) # ============================================================ @@ -1101,16 +992,13 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): 与 _const_int_for_cdefine 既有的 i32 截断口径一致,避免生成非法 IR 文本。 """ if bits == 8: - if value > 127: - return value - 256 + if value > 127: return value - 256 return value if bits == 16: - if value > 32767: - return value - 65536 + if value > 32767: return value - 65536 return value if bits == 32: - if value > 2147483647: - return value - 4294967296 + if value > 2147483647: return value - 4294967296 return value return value @@ -1135,8 +1023,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): 本函数拦到时,硬编码标签会给出错误站点)。 """ bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(target_ty) - if bits != 8 and bits != 16 and bits != 32 and bits != 64: - return None + if bits != 8 and bits != 16 and bits != 32 and bits != 64: return None wmin: int = self.Gen.AssignGen.define_min_width(value) if bits < wmin: # "该使用处可表示的范围"与判据同一口径 = TPC `DefineWidthLoHi` diff --git a/App/lib/core/Gen/Expr/ExprGenCls.vp b/App/lib/core/Gen/Expr/ExprGenCls.vp index 16cc659..c487771 100644 --- a/App/lib/core/Gen/Expr/ExprGenCls.vp +++ b/App/lib/core/Gen/Expr/ExprGenCls.vp @@ -102,15 +102,13 @@ novirtual class ExprGenCls(ExprGenBase.ExprGenBase): if fd is not None and fd.name is not None: fd_body: list[ast.AST*]* = fd.children fdoc: str = self._extract_docstring_from_body(fd_body) - if fdoc is not None: - self.register_docstring(module_sha1, fd.name, fdoc) + if fdoc is not None: self.register_docstring(module_sha1, fd.name, fdoc) elif kd == ast.ASTKind.ClassDef: cd: ast.ClassDef* = ast.ClassDef*(child) if cd is None or cd.name is None: continue cd_body0: list[ast.AST*]* = cd.children cdoc: str = self._extract_docstring_from_body(cd_body0) - if cdoc is not None: - self.register_docstring(module_sha1, cd.name, cdoc) + if cdoc is not None: self.register_docstring(module_sha1, cd.name, cdoc) # 类方法 docstring(key="{ClassName}.{method}") cd_body: list[ast.AST*]* = cd.children if cd_body is not None: @@ -145,17 +143,14 @@ novirtual class ExprGenCls(ExprGenBase.ExprGenBase): # 2. 结构体类(entry.ModuleSha1 区分跨模块预注册的类) se: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(name_id) if se is not None: - if se.ModuleSha1 is not None: - string.strcpy(out_mod, se.ModuleSha1) - else: - string.strcpy(out_mod, trans.ModuleSha1) + if se.ModuleSha1 is not None: string.strcpy(out_mod, se.ModuleSha1) + else: string.strcpy(out_mod, trans.ModuleSha1) string.strcpy(out_sym, name_id) return 1 # 3. 模块名(模块本身,少见);用 StubMerger 模块级函数(避免 # 跨 Mixin self 调用生成不存在符号) mod_sha1: str = StubMergerStore.LookupSha1ByModName(name_id) - if mod_sha1 is None: - mod_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(name_id) + if mod_sha1 is None: mod_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(name_id) if mod_sha1 is not None: string.strcpy(out_mod, mod_sha1) string.strcpy(out_sym, name_id) @@ -200,10 +195,8 @@ novirtual class ExprGenCls(ExprGenBase.ExprGenBase): mod_sha1: str = None if self.Gen.VarGen.lookup_var(trans.SymTab, head_id) is None: mod_sha1 = StubMergerStore.LookupSha1ByModName(head_id) - if mod_sha1 is None: - mod_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(head_id) - if mod_sha1 is not None: - is_mod = 1 + if mod_sha1 is None: mod_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(head_id) + if mod_sha1 is not None: is_mod = 1 if is_mod != 0: # 模块限定:symbol = items 反转(不含 head_id) if n_items == 0: @@ -212,16 +205,14 @@ novirtual class ExprGenCls(ExprGenBase.ExprGenBase): stdlib.free(items) return 1 total: sizet = 0 - for j in range(n_items): - total += string.strlen(items + j * 128) + 1 + for j in range(n_items): total += string.strlen(items + j * 128) + 1 sym_buf: bytes = stdlib.malloc(total + 1) if sym_buf is None: stdlib.free(items) return 0 sym_buf[0] = '\0' for j in range(n_items): - if j > 0: - string.strcat(sym_buf, ".") + if j > 0: string.strcat(sym_buf, ".") string.strcat(sym_buf, items + (n_items - 1 - j) * 128) string.strcpy(out_mod, mod_sha1) string.strcpy(out_sym, sym_buf) @@ -230,8 +221,7 @@ novirtual class ExprGenCls(ExprGenBase.ExprGenBase): return 1 # 变量/类:symbol = head_id + '.' + items 反转 total2: sizet = string.strlen(head_id) - for j in range(n_items): - total2 += string.strlen(items + j * 128) + 1 + for j in range(n_items): total2 += string.strlen(items + j * 128) + 1 sym2: bytes = stdlib.malloc(total2 + 1) if sym2 is None: stdlib.free(items) @@ -242,10 +232,8 @@ novirtual class ExprGenCls(ExprGenBase.ExprGenBase): string.strcat(sym2, ".") string.strcat(sym2, items + (n_items - 1 - j) * 128) se2: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(head_id) - if se2 is not None and se2.ModuleSha1 is not None: - string.strcpy(out_mod, se2.ModuleSha1) - else: - string.strcpy(out_mod, trans.ModuleSha1) + if se2 is not None and se2.ModuleSha1 is not None: string.strcpy(out_mod, se2.ModuleSha1) + else: string.strcpy(out_mod, trans.ModuleSha1) string.strcpy(out_sym, sym2) stdlib.free(sym2) stdlib.free(items) @@ -295,33 +283,26 @@ novirtual class ExprGenCls(ExprGenBase.ExprGenBase): pool, trans._from_imports, mod_nm2) if mod_sha1_2 is not None: temp_dir2: str = None - if self.Gen.CallGenBase.TempDir is not None: - temp_dir2 = self.Gen.CallGenBase.TempDir - if temp_dir2 is not None: - VpiReader._ensure_vpi_ret_annot_loaded(mod_sha1_2, temp_dir2) + if self.Gen.CallGenBase.TempDir is not None: temp_dir2 = self.Gen.CallGenBase.TempDir + if temp_dir2 is not None: VpiReader._ensure_vpi_ret_annot_loaded(mod_sha1_2, temp_dir2) annot_ret2: str = VpiReader._lookup_vpi_ret_annot( mod_sha1_2, None, ca.attr) if annot_ret2 is not None: ret_cls2: str = self._extract_annot_class_name(pool, annot_ret2) - if ret_cls2 is not None: - return ret_cls2 + if ret_cls2 is not None: return ret_cls2 obj_cls: str = self.infer_expr_class(pool, mod, ca.value, trans) if obj_cls is None: return None if self._cls_has_dunder(pool, mod, obj_cls, ca.attr) == 0: return None cls_sha1: str = self.Gen.StructGen.get_struct_sha1(obj_cls) - if cls_sha1 is None and trans.ModuleSha1 is not None: - cls_sha1 = trans.ModuleSha1 + if cls_sha1 is None and trans.ModuleSha1 is not None: cls_sha1 = trans.ModuleSha1 ret_cls: str = None if cls_sha1 is not None: temp_dir: str = None # 跨子对象访问经 self.Gen 取 CallGenBase.TempDir(双向引用) - if self.Gen.CallGenBase.TempDir is not None: - temp_dir = self.Gen.CallGenBase.TempDir - if temp_dir is not None: - VpiReader._ensure_vpi_ret_annot_loaded(cls_sha1, temp_dir) + if self.Gen.CallGenBase.TempDir is not None: temp_dir = self.Gen.CallGenBase.TempDir + if temp_dir is not None: VpiReader._ensure_vpi_ret_annot_loaded(cls_sha1, temp_dir) annot_ret: str = VpiReader._lookup_vpi_ret_annot(cls_sha1, obj_cls, ca.attr) - if annot_ret is not None: - ret_cls = self._extract_annot_class_name(pool, annot_ret) + if annot_ret is not None: ret_cls = self._extract_annot_class_name(pool, annot_ret) return ret_cls return None # Name: 源变量注解 @@ -338,8 +319,7 @@ novirtual class ExprGenCls(ExprGenBase.ExprGenBase): # get_struct_sha1 查找都用裸类名(struct 注册名)。泛型名 # (list[str] 含 '[')不截断(方括号内可能有点号)。 acn_dot_n: str = string.strrchr(acn_n, 46) - if acn_dot_n is not None and string.strchr(acn_n, 91) is None: - acn_n = acn_dot_n + 1 + if acn_dot_n is not None and string.strchr(acn_n, 91) is None: acn_n = acn_dot_n + 1 return acn_n # BinOp/UnaryOp: 运算符重载返回同类对象 if k == ast.ASTKind.BinOp: @@ -359,8 +339,7 @@ novirtual class ExprGenCls(ExprGenBase.ExprGenBase): if opr_cls is None or self._cls_has_dunder(pool, mod, opr_cls, dunder) == 0: return None return opr_cls # Attribute: 字段注解类名(属性链递归,如 p = r.origin) - if k == ast.ASTKind.Attribute: - return self.Gen.ExprGenAttr._resolve_attr_field_class(pool, trans, node) + if k == ast.ASTKind.Attribute: return self.Gen.ExprGenAttr._resolve_attr_field_class(pool, trans, node) return None # ============================================================ # _cls_has_dunder - 检查类(含继承链)是否存在 dunder/方法 @@ -385,8 +364,7 @@ novirtual class ExprGenCls(ExprGenBase.ExprGenBase): anc_lookup: str = pool.alloc(128) if anc_lookup is not None: viperlib.snprintf(anc_lookup, 128, "%s.%s", anc, dunder) - if self.Gen.CallGenBase.find_func_in_module(mod, anc_lookup) is not None: - return 1 + if self.Gen.CallGenBase.find_func_in_module(mod, anc_lookup) is not None: return 1 mi += 1 # 跨模块:类有 SHA1(stub 中声明该方法)视为存在 if self.Gen.StructGen.get_struct_sha1(class_name) is not None: return 1 @@ -412,50 +390,42 @@ novirtual class ExprGenCls(ExprGenBase.ExprGenBase): if annot[i] == '|': s: sizet = start e: sizet = i - while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'): - s += 1 + while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'): s += 1 # 段尾另需剥 '*':实参归一后段文本是 `{sha}.AST*`(旧形态 # `{sha}.AST*` 按 '|' 分段能落到 `{sha}.AST` 命中),与 # ExprGenName._list_elem_obj_ty_from_struct_name 的尾剔除同口径; # 不剥则 find_struct 落空 → 返回 None → 链式 .get(0).kind() 分派退化。 - while e > s and (annot[e - 1] == ' ' or annot[e - 1] == '\'' or annot[e - 1] == '"' or annot[e - 1] == '*'): - e -= 1 + while e > s and (annot[e - 1] == ' ' or annot[e - 1] == '\'' or annot[e - 1] == '"' or annot[e - 1] == '*'): e -= 1 seglen: sizet = e - s if seglen > 0 and seglen < 256: string.strncpy(seg, annot + s, seglen) seg[seglen] = '\0' - if self.Gen.StructGen.find_struct(seg) is not None: - return seg + if self.Gen.StructGen.find_struct(seg) is not None: return seg # 模块前缀(memhub.MemBuddy → MemBuddy):find_struct 未命中 # 时去最后一个 '.' 前的模块名再试(vpi 返回注解常带模块限定) seg_dot2: str = string.strrchr(seg, 46) if seg_dot2 is not None and seg_dot2 != seg: seg_bare2: str = seg_dot2 + 1 - if self.Gen.StructGen.find_struct(seg_bare2) is not None: - return seg_bare2 + if self.Gen.StructGen.find_struct(seg_bare2) is not None: return seg_bare2 start = i + 1 # 最后一段(无 '|' 后缀) s: sizet = start e: sizet = alen - while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'): - s += 1 + while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'): s += 1 # 段尾另需剥 '*':实参归一后段文本是 `{sha}.AST*`(旧形态 # `{sha}.AST*` 按 '|' 分段能落到 `{sha}.AST` 命中),与 # ExprGenName._list_elem_obj_ty_from_struct_name 的尾剔除同口径; # 不剥则 find_struct 落空 → 返回 None → 链式 .get(0).kind() 分派退化。 - while e > s and (annot[e - 1] == ' ' or annot[e - 1] == '\'' or annot[e - 1] == '"' or annot[e - 1] == '*'): - e -= 1 + while e > s and (annot[e - 1] == ' ' or annot[e - 1] == '\'' or annot[e - 1] == '"' or annot[e - 1] == '*'): e -= 1 seglen: sizet = e - s if seglen > 0 and seglen < 256: string.strncpy(seg, annot + s, seglen) seg[seglen] = '\0' - if self.Gen.StructGen.find_struct(seg) is not None: - return seg + if self.Gen.StructGen.find_struct(seg) is not None: return seg # 模块前缀(memhub.MemBuddy → MemBuddy):find_struct 未命中时 # 去最后一个 '.' 前的模块名再试(vpi 返回注解常带模块限定) seg_dot3: str = string.strrchr(seg, 46) if seg_dot3 is not None and seg_dot3 != seg: seg_bare3: str = seg_dot3 + 1 - if self.Gen.StructGen.find_struct(seg_bare3) is not None: - return seg_bare3 + if self.Gen.StructGen.find_struct(seg_bare3) is not None: return seg_bare3 return None \ 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 2f8db29..5fe4913 100644 --- a/App/lib/core/Gen/Expr/ExprGenConst.vp +++ b/App/lib/core/Gen/Expr/ExprGenConst.vp @@ -43,16 +43,12 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): # 字符串名加 SHA1 前缀,和函数导出规则一致,避免跨模块重名 gv_name: str = pool.alloc(48) - if gv_name is None: - return None - if trans.ModuleSha1 is not None: - viperlib.snprintf(gv_name, 48, ".str.%s.%d", trans.ModuleSha1, str_idx) - else: - viperlib.snprintf(gv_name, 48, ".str.%d", str_idx) + if gv_name is None: return None + if trans.ModuleSha1 is not None: viperlib.snprintf(gv_name, 48, ".str.%s.%d", trans.ModuleSha1, str_idx) + else: viperlib.snprintf(gv_name, 48, ".str.%d", str_idx) gv: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, gv_name, arr_ty) - if gv is None: - return None + if gv is None: return None mlirlite.module_add_global(mod, gv) # 去掉 private 链接,和函数一致:stub 中 declare,text 中 define @@ -64,8 +60,7 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): arr_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, arr_ty) gv_ref_name: str = pool.alloc(64) - if gv_ref_name is None: - return None + if gv_ref_name is None: return None viperlib.snprintf(gv_ref_name, 64, "@%s", gv.Name) gv_ref: mlirlite.Value* = mlirlite.SSAValue(pool, arr_ptr_ty, gv_ref_name) @@ -84,8 +79,7 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): target_ty: mlirlite.LLVMType* = None) -> mlirlite.Value*: """翻译常量(int/str/bool)""" cn: ast.Constant* = ast.Constant*(node) - if cn is None: - return None + if cn is None: return None ck: int = cn.const_kind if cn.const_kind == ast.CONST_INT: # 位宽选择: @@ -96,10 +90,8 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): # const_int 按十进制值打印,故 i64 -1 即全 1,语义正确。 # 2) 否则维持旧规则:超出 i32 范围用 i64,其余 i32。 iv: int64 = cn.int_val - if target_ty is not None and self.is_ptr_type(target_ty) == 0 and self.get_llvm_type_bits(target_ty) > 32: - return mlirlite.const_int64(pool, iv) - if iv > 2147483647 or iv < -2147483648: - return mlirlite.const_int64(pool, iv) + if target_ty is not None and self.is_ptr_type(target_ty) == 0 and self.get_llvm_type_bits(target_ty) > 32: return mlirlite.const_int64(pool, iv) + if iv > 2147483647 or iv < -2147483648: return mlirlite.const_int64(pool, iv) return mlirlite.const_int32(pool, iv) elif cn.const_kind == ast.CONST_FLOAT: # 浮点常量默认创建为 double(64 位),赋值时由 coerce_to_type 自动 fptrunc @@ -109,8 +101,7 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): # 单引号单字符字面量(CONST_CHAR):默认按字符值(i32,coerce 截断为 i8);但当目标类型是指针(str/bytes/t.CPtr)时须物化为 1 字符字符串,否则 coerce inttoptr 把字符值当指针(如 '"'=0x22)→ 运行期 strlen 访问低地址崩溃。1a 阶段(declare_only=1)依赖函数 found_func=None,target_ty 未对齐即视为垃圾跳过,避免 is_ptr_type 解引用崩溃 if target_ty is not None and (uint64(target_ty) & 7) == 0 and self.is_ptr_type(target_ty) != 0: cbuf: bytes = stdlib.malloc(2) - if cbuf is None: - return mlirlite.const_int32(pool, 0) + if cbuf is None: return mlirlite.const_int32(pool, 0) cbuf[0] = char(cn.int_val) cbuf[1] = '\0' r_cs: mlirlite.Value* = self.create_global_string(builder, pool, mod, cbuf, trans) @@ -120,22 +111,18 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): return mlirlite.const_int32(pool, cv) elif cn.const_kind == ast.CONST_STR: sv: str = cn.str_val - if sv is None: - return None + if sv is None: return None r: mlirlite.Value* = self.create_global_string(builder, pool, mod, sv, trans) return r elif cn.const_kind == ast.CONST_BOOL: - if cn.int_val != 0: - return mlirlite.const_int32(pool, 1) + if cn.int_val != 0: return mlirlite.const_int32(pool, 1) return mlirlite.const_int32(pool, 0) elif cn.const_kind == ast.CONST_NONE: # None → i8* null(空指针常量),用于 `p is None` / `p is not None` 比较 i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) - if i8_ty is None: - return None + if i8_ty is None: return None i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty) - if i8_ptr_ty is None: - return None + if i8_ptr_ty is None: return None rv_none: mlirlite.Value* = mlirlite.ConstNull(pool, i8_ptr_ty, "null") return rv_none return None @@ -151,28 +138,20 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): fail-fast:值类型缺失/无法映射时返回 None(调用方携带节点报错终止), 绝不静默回退 "str"(掩盖上游 Value 类型缺失根因)。 """ - if value is None or value.Ty is None: - return None + if value is None or value.Ty is None: return None ty: mlirlite.LLVMType* = value.Ty bits: int = self.get_llvm_type_bits(ty) if bits != 0: - if bits == 32: - return "int" - if bits == 64: - return "CSizeT" - if bits == 8: - return "CInt8T" - if bits == 16: - return "CInt16T" + if bits == 32: return "int" + if bits == 64: return "CSizeT" + if bits == 8: return "CInt8T" + if bits == 16: return "CInt16T" return None - if self.is_ptr_type(ty) != 0: - return "str" + if self.is_ptr_type(ty) != 0: return "str" fbits: int = self.get_llvm_float_bits(ty) if fbits != 0: - if fbits == 64: - return "CDouble" - if fbits == 32: - return "CFloat" + if fbits == 64: return "CDouble" + if fbits == 32: return "CFloat" return None # ============================================================ # _find_pool_var — 查找上下文中的 pool 变量 @@ -188,20 +167,15 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): 此兜底仅用于函数内的动态 list 字面量(如 op=[...])。 @_mbuddy 由入口模块(如 Phase2.py)定义并初始化,其他模块以 external 引用。 """ - if trans is None: - return None + if trans is None: return None alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, "pool") - if alloca is not None: - return alloca + if alloca is not None: return alloca alloca = self.Gen.VarGen.lookup_var(trans.SymTab, "_mbuddy") - if alloca is not None: - return alloca + if alloca is not None: return alloca alloca = self.Gen.VarGen.lookup_var(trans.SymTab, "mbuddy") - if alloca is not None: - return alloca + if alloca is not None: return alloca alloca = self.Gen.VarGen.lookup_var(trans.SymTab, "mb") - if alloca is not None: - return alloca + if alloca is not None: return alloca # 兜底: 创建当前模块 mangled 的 @_mbuddy 定义(linkonce_odr + zeroinitializer) # 对齐模块级全局带 SHA1 前缀命名:裸名 @_mbuddy 依赖链接合并共享 # (--allow-multiple-definition),带前缀后每模块独立。linkonce_odr 允许 @@ -209,12 +183,10 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): # 运行时若该模块未在入口 main 赋值 _mbuddy(null pool 上动态建 list), # 由真实崩溃暴露(fail-fast 哲学,不掩盖上游未初始化)。 pool: memhub.MemBuddy* = trans.Pool - if pool is None or trans.Module is None or trans.SymTab is None: - return None + if pool is None or trans.Module is None or trans.SymTab is None: return None # 先检查是否已注册到模块作用域(避免重复创建全局变量) existing: mlirlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, "_mbuddy") - if existing is not None: - return existing + if existing is not None: return existing # 创建 i8* 类型(t.CPtr = i8*) i8_ty_fb: mlirlite.LLVMType* = mlirlite.Int8(pool) i8_ptr_ty_fb: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_fb) @@ -231,10 +203,8 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): ref_name_fb: str = pool.alloc(96) if ref_name_fb is not None: # mangled 名带 SHA1 前缀(数字开头),引用必须加引号(见 make_global_ref) - if self.Gen.ClassGenVTable._vtable_name_needs_quote(mb_name_fb) != 0: - viperlib.snprintf(ref_name_fb, 96, "@\"%s\"", mb_name_fb) - else: - viperlib.snprintf(ref_name_fb, 96, "@%s", mb_name_fb) + if self.Gen.ClassGenVTable._vtable_name_needs_quote(mb_name_fb) != 0: viperlib.snprintf(ref_name_fb, 96, "@\"%s\"", mb_name_fb) + else: viperlib.snprintf(ref_name_fb, 96, "@%s", mb_name_fb) gv_ref_fb: mlirlite.Value* = mlirlite.SSAValue(pool, i8_ptr_ptr_ty_fb, ref_name_fb) # 注册到模块作用域,避免重复创建 self.Gen.VarGen.define_module_var(trans.SymTab, "_mbuddy", gv_ref_fb) @@ -247,17 +217,14 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): elem_type_name: str, trans: HT.Translator*) -> mlirlite.Value*: """翻译 list 字面量 [a, b, c] → list[T](pool) + append 序列""" - if node is None or trans is None: - return None + if node is None or trans is None: return None list_node: ast.List* = ast.List*(node) - if list_node is None: - return None + if list_node is None: return None elts: list[ast.AST*]* = list_node.elts elts_count: sizet = 0 - if elts is not None: - elts_count = len(elts) + if elts is not None: elts_count = len(elts) # 推断元素类型 inferred_type_name: str = elem_type_name @@ -287,8 +254,7 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty) pool_val: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, pool_alloca) - if pool_val is None: - return None + if pool_val is None: return None # 特化 list[T] 类(elem_size=8:str 是指针,4 会导致双元素重叠损坏) type_args: list[str]* = list[str](pool, 8) @@ -304,15 +270,13 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): self.Gen.TypeGenErr.fatal_error(node, "list literal specialized class not registered") return None struct_ty: mlirlite.LLVMType* = struct_entry.Ty - if struct_ty is None: - return None + if struct_ty is None: return None # alloca 临时 list 空间 # 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间) self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, struct_ty) tmp: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, struct_ty) - if tmp is None: - return None + if tmp is None: return None # 存储指针:默认用 alloca,如果有 __new__ 则用 __new__ 返回的指针 # __new__ 是可选的,仅当泛型类模板定义了 __new__ 方法时才调用 @@ -320,17 +284,14 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): # 避免为无 __new__ 的类生成过度声明) storage_ptr: mlirlite.Value* = tmp has_new_flag: int = 0 - if struct_entry is not None: - has_new_flag = struct_entry.HasNew + if struct_entry is not None: has_new_flag = struct_entry.HasNew if has_new_flag != 0: new_args: sizet* = pool.alloc(8 * 32) - if new_args is None: - return None + if new_args is None: return None string.memset(new_args, 0, 8 * 32) new_args[0] = sizet(pool_val) new_ptr: mlirlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__new__", tmp, new_args, 1, trans) - if new_ptr is not None: - storage_ptr = new_ptr + if new_ptr is not None: storage_ptr = new_ptr # 调用 __before_init__(storage_ptr) self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__before_init__", storage_ptr, None, 0, trans) diff --git a/App/lib/core/Gen/Expr/ExprGenFstr.vp b/App/lib/core/Gen/Expr/ExprGenFstr.vp index 869af9c..266a4b0 100644 --- a/App/lib/core/Gen/Expr/ExprGenFstr.vp +++ b/App/lib/core/Gen/Expr/ExprGenFstr.vp @@ -74,29 +74,22 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): # 对象定义了 __str__ 且未指定格式 → 用其返回的字符串(对齐 TPC) if fv.format_spec is None: str_ov_fs: mlirlite.Value* = self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, val, "__str__", trans) - if str_ov_fs is not None: - val = str_ov_fs + if str_ov_fs is not None: val = str_ov_fs # 确定 C 格式说明符(format_spec 优先,否则按值类型推断) c_fmt: str = None - if fv.format_spec is not None: - c_fmt = self._fstr_parse_format_spec(pool, fv.format_spec, val, fv.value) - if c_fmt is None: - c_fmt = self._fstr_infer_c_fmt(pool, val, fv.value, trans) + if fv.format_spec is not None: c_fmt = self._fstr_parse_format_spec(pool, fv.format_spec, val, fv.value) + if c_fmt is None: c_fmt = self._fstr_infer_c_fmt(pool, val, fv.value, trans) if c_fmt is None: # fail-fast:f-string 格式无法推断(值类型缺失),立即终止编译 self.Gen.TypeGenErr.fatal_error(fv.value, "f-string 格式无法推断(值类型缺失)", "TypeError") # 追加格式说明符 - if string.strlen(fmt_buf) + string.strlen(c_fmt) < FSTR_BUF_SIZE - 1: - string.strcat(fmt_buf, c_fmt) + if string.strlen(fmt_buf) + string.strlen(c_fmt) < FSTR_BUF_SIZE - 1: string.strcat(fmt_buf, c_fmt) # 转换参数类型(i8/i16→i32、bool→i32、f32→f64) cast_val: mlirlite.Value* = self._fstr_cast_value(builder, pool, val, c_fmt, fv.value, trans) - if cast_val is None: - cast_val = val + if cast_val is None: cast_val = val cast_val.Next = None - if arg_head is None: - arg_head = cast_val - else: - arg_tail.Next = cast_val + if arg_head is None: arg_head = cast_val + else: arg_tail.Next = cast_val arg_tail = cast_val arg_count += 1 @@ -107,14 +100,11 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): node: ast.AST*, trans: HT.Translator* = None) -> mlirlite.Value*: """翻译裸 FormattedValue(f"{expr:spec}" 无字面量时解析器返回 FormattedValue 而非 JoinedStr)""" - if node is None or builder is None or trans is None: - return None + if node is None or builder is None or trans is None: return None fv: rawptr[ast.FormattedValue] = rawptr[ast.FormattedValue](node) - if fv is None or fv.value is None: - return None + if fv is None or fv.value is None: return None fmt_buf: str = pool.alloc(FSTR_BUF_SIZE) - if fmt_buf is None: - return None + if fmt_buf is None: return None fmt_buf[0] = '\0' arg_head: mlirlite.Value* = None arg_tail: mlirlite.Value* = None @@ -127,21 +117,16 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): # 对象定义了 __str__ 且未指定格式 → 用其返回的字符串(对齐 TPC) if fv.format_spec is None: str_ov_sf: mlirlite.Value* = self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, val, "__str__", trans) - if str_ov_sf is not None: - val = str_ov_sf + if str_ov_sf is not None: val = str_ov_sf c_fmt: str = None - if fv.format_spec is not None: - c_fmt = self._fstr_parse_format_spec(pool, fv.format_spec, val, fv.value) - if c_fmt is None: - c_fmt = self._fstr_infer_c_fmt(pool, val, fv.value, trans) + if fv.format_spec is not None: c_fmt = self._fstr_parse_format_spec(pool, fv.format_spec, val, fv.value) + if c_fmt is None: c_fmt = self._fstr_infer_c_fmt(pool, val, fv.value, trans) if c_fmt is None: # fail-fast:f-string 格式无法推断(值类型缺失),立即终止编译 self.Gen.TypeGenErr.fatal_error(fv.value, "f-string 格式无法推断(值类型缺失)", "TypeError") - if string.strlen(fmt_buf) + string.strlen(c_fmt) < FSTR_BUF_SIZE - 1: - string.strcat(fmt_buf, c_fmt) + 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 + if cast_val is None: cast_val = val cast_val.Next = None arg_head = cast_val arg_tail = cast_val @@ -205,8 +190,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): buf_ptr.Next = size_val size_val.Next = fmt_ptr fmt_ptr.Next = arg_head - if arg_tail is not None: - arg_tail.Next = None + if arg_tail is not None: arg_tail.Next = None mlirlite.build_call(builder, "snprintf", buf_ptr, 3 + arg_count, i32_ty, 1) return buf_ptr def _fstr_append_literal(self, fmt_buf: str, @@ -221,8 +205,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): while si < src_len and rem > 0: ch: char = lit[si] if ch == '%': - if rem < 2: - break + if rem < 2: break fmt_buf[cur_len] = '%' fmt_buf[cur_len + 1] = '%' cur_len += 2 @@ -235,23 +218,19 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): fmt_buf[cur_len] = '\0' def _fstr_append_raw(self, fmt_buf: str, s: str) -> None: """追加原始字符串(不做 % 转义)""" - if fmt_buf is None or s is None: - return + if fmt_buf is None or s is None: return cur_len: sizet = string.strlen(fmt_buf) src_len: sizet = string.strlen(s) - if cur_len + src_len < FSTR_BUF_SIZE: - string.strcpy(fmt_buf + cur_len, s) + if cur_len + src_len < FSTR_BUF_SIZE: string.strcpy(fmt_buf + cur_len, s) def _fstr_parse_format_spec(self, pool: memhub.MemBuddy*, spec_node: ast.AST*, val: mlirlite.Value*, arg_node: ast.AST*) -> str: """Python format_spec → C printf 格式串(pool 分配),无法解析返回 None""" - if spec_node is None or pool is None or val is None: - return None + if spec_node is None or pool is None or val is None: return None # 1. 提取 spec 字符串(JoinedStr 仅常量拼接) spec: str = pool.alloc(FSTR_SPEC_MAX) - if spec is None: - return None + if spec is None: return None spec[0] = '\0' sk: int = spec_node.kind() if sk == ast.ASTKind.JoinedStr: @@ -264,12 +243,10 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): if vpart.kind() != ast.ASTKind.Constant: return None vcn: ast.Constant* = ast.Constant*(vpart) if vcn.const_kind != ast.CONST_STR or vcn.str_val is None: return None - if string.strlen(spec) + string.strlen(vcn.str_val) < FSTR_SPEC_MAX - 1: - string.strcat(spec, vcn.str_val) + if string.strlen(spec) + string.strlen(vcn.str_val) < FSTR_SPEC_MAX - 1: string.strcat(spec, vcn.str_val) elif sk == ast.ASTKind.Constant: cn: ast.Constant* = ast.Constant*(spec_node) - if cn.const_kind != ast.CONST_STR or cn.str_val is None: - return None + if cn.const_kind != ast.CONST_STR or cn.str_val is None: return None string.strncpy(spec, cn.str_val, FSTR_SPEC_MAX - 1) else: return None slen: sizet = string.strlen(spec) @@ -297,10 +274,8 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): c_prec[0] = '\0' # sign if pos < slen and (spec[pos] == '+' or spec[pos] == '-' or spec[pos] == ' '): - if spec[pos] == '+': - string.strcat(c_flags, "+") - elif spec[pos] == ' ': - string.strcat(c_flags, " ") + if spec[pos] == '+': string.strcat(c_flags, "+") + elif spec[pos] == ' ': string.strcat(c_flags, " ") pos += 1 # alt '#' if pos < slen and spec[pos] == '#': @@ -311,8 +286,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): string.strcat(c_flags, "0") pos += 1 # 左对齐 '<'/'^' → '-'(与 0 同时存在时 C 语义 '-' 优先) - if align_char == '<' or align_char == '^': - string.strcat(c_flags, "-") + if align_char == '<' or align_char == '^': string.strcat(c_flags, "-") # width digits while pos < slen and spec[pos] >= '0' and spec[pos] <= '9': wl: sizet = string.strlen(c_width) @@ -321,8 +295,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): c_width[wl + 1] = '\0' pos += 1 # comma ',' → C printf 不支持千分位,忽略 - if pos < slen and spec[pos] == ',': - pos += 1 + if pos < slen and spec[pos] == ',': pos += 1 # .precision if pos < slen and spec[pos] == '.': string.strcat(c_prec, ".") @@ -367,34 +340,24 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): # 无 type:按值类型推断 fbits2: int = self.Gen.ExprGenBase.get_llvm_float_bits(val.Ty) if ibits != 0: - if ibits == 8: - string.strcat(out, "c") - elif ibits == 1: - string.strcat(out, "d") + if ibits == 8: string.strcat(out, "c") + elif ibits == 1: string.strcat(out, "d") else: string.strcat(out, len_mod) string.strcat(out, "d") - elif fbits2 != 0: - string.strcat(out, "f") - elif self.Gen.ExprGenBase.is_ptr_type(val.Ty) != 0: - string.strcat(out, "s") - else: - string.strcat(out, "d") - elif fmt_type == 'c': - string.strcat(out, "c") - elif fmt_type == 'f' or fmt_type == 'F': - string.strcat(out, "f") + elif fbits2 != 0: string.strcat(out, "f") + elif self.Gen.ExprGenBase.is_ptr_type(val.Ty) != 0: string.strcat(out, "s") + else: string.strcat(out, "d") + elif fmt_type == 'c': string.strcat(out, "c") + elif fmt_type == 'f' or fmt_type == 'F': string.strcat(out, "f") elif fmt_type == 'e' or fmt_type == 'E' or fmt_type == 'g' or fmt_type == 'G': tmp_ch: str = pool.alloc(2) - if tmp_ch is None: - return None + if tmp_ch is None: return None tmp_ch[0] = fmt_type tmp_ch[1] = '\0' string.strcat(out, tmp_ch) - elif fmt_type == 's': - string.strcat(out, "s") - elif fmt_type == '%': - string.strcat(out, "%") + elif fmt_type == 's': string.strcat(out, "s") + elif fmt_type == '%': string.strcat(out, "%") elif fmt_type == 'b': return None # 二进制不支持 elif fmt_type == 'd' or fmt_type == 'i': @@ -403,13 +366,11 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): elif fmt_type == 'x' or fmt_type == 'X' or fmt_type == 'o' or fmt_type == 'u': string.strcat(out, len_mod) tmp_ch2: str = pool.alloc(2) - if tmp_ch2 is None: - return None + if tmp_ch2 is None: return None tmp_ch2[0] = fmt_type tmp_ch2[1] = '\0' string.strcat(out, tmp_ch2) - else: - return None + else: return None return out def _fstr_infer_c_fmt(self, pool: memhub.MemBuddy*, val: mlirlite.Value*, @@ -426,20 +387,14 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): if ibits == 8: return "%c" # 字符 if ibits != 0: if self.Gen.ExprGenOps._node_type_unsigned(pool, arg_node, trans) != 0: - if ibits == 64: - string.strcpy(out, "%llu") - else: - string.strcpy(out, "%u") + if ibits == 64: string.strcpy(out, "%llu") + else: string.strcpy(out, "%u") else: - if ibits == 64: - string.strcpy(out, "%lld") - else: - string.strcpy(out, "%d") + if ibits == 64: string.strcpy(out, "%lld") + else: string.strcpy(out, "%d") return out - if fbits != 0: - return "%f" - if self.Gen.ExprGenBase.is_ptr_type(val.Ty) != 0: - return "%s" + if fbits != 0: return "%f" + if self.Gen.ExprGenBase.is_ptr_type(val.Ty) != 0: return "%s" # fail-fast:值类型缺失(非整数/浮点/指针),无法推断 C 格式,立即终止编译 self.Gen.TypeGenErr.fatal_error(arg_node, "f-string 格式无法推断(值类型缺失)", "TypeError") return None @@ -450,8 +405,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): arg_node: ast.AST*, trans: HT.Translator*) -> mlirlite.Value*: """按 C 格式转换值类型(i8/i16→i32、bool→i32、f32→f64)""" - if val is None or c_fmt is None: - return None + if val is None or c_fmt is None: return None # 找格式类型字符(最后一个字母,忽略 l/h 长度修饰) fmt_char: char = 0 flen: sizet = string.strlen(c_fmt) @@ -459,32 +413,26 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase): while fi > 0: fi -= 1 ch: char = c_fmt[fi] - if ch == '%': - break + if ch == '%': break if (ch >= 'a' and ch <= 'z') or (ch >= 'A' and ch <= 'Z'): if ch != 'l' and ch != 'h': fmt_char = ch break i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) - if fmt_char == 's': - return val + if fmt_char == 's': return val if fmt_char == 'c': ibits: int = self.Gen.ExprGenBase.get_llvm_type_bits(val.Ty) - if ibits != 0 and ibits < 32: - return mlirlite.build_zext(builder, val, i32_ty) + if ibits != 0 and ibits < 32: return mlirlite.build_zext(builder, val, i32_ty) return val if fmt_char == 'd' or fmt_char == 'i' or fmt_char == 'x' or fmt_char == 'X' or fmt_char == 'o' or fmt_char == 'u': ibits = self.Gen.ExprGenBase.get_llvm_type_bits(val.Ty) - if ibits == 1: - return mlirlite.build_zext(builder, val, i32_ty) + if ibits == 1: return mlirlite.build_zext(builder, val, i32_ty) if ibits == 8 or ibits == 16: - if self.Gen.ExprGenOps._node_type_unsigned(pool, arg_node, trans) != 0: - return mlirlite.build_zext(builder, val, i32_ty) + if self.Gen.ExprGenOps._node_type_unsigned(pool, arg_node, trans) != 0: return mlirlite.build_zext(builder, val, i32_ty) return mlirlite.build_sext(builder, val, i32_ty) return val if fmt_char == 'f' or fmt_char == 'e' or fmt_char == 'E' or fmt_char == 'g' or fmt_char == 'G': fbits: int = self.Gen.ExprGenBase.get_llvm_float_bits(val.Ty) - if fbits == 32: - return mlirlite.build_fpext(builder, val, mlirlite.Double(pool)) + if fbits == 32: return mlirlite.build_fpext(builder, val, mlirlite.Double(pool)) return val return val \ No newline at end of file diff --git a/App/lib/core/Gen/Expr/ExprGenMixin.vp b/App/lib/core/Gen/Expr/ExprGenMixin.vp index 163e67f..4cc7731 100644 --- a/App/lib/core/Gen/Expr/ExprGenMixin.vp +++ b/App/lib/core/Gen/Expr/ExprGenMixin.vp @@ -62,12 +62,10 @@ novirtual class ExprGenMixin(ExprGenBase.ExprGenBase): "形参" / "返回注解" …),只被 CDefine 使用处宽度不足报文读取;不参与判定。 """ 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, "表达式翻译嵌套过深(疑似 AST 自引用环或翻译 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 + if trans is not None: trans.TranslateDepth -= 1 return rv def _translate_value_impl(self, builder: mlirlite.IRBuilder*, @@ -80,8 +78,7 @@ novirtual class ExprGenMixin(ExprGenBase.ExprGenBase): target_ty: mlirlite.LLVMType* = None, use_ctx: str = None) -> mlirlite.Value*: """翻译值表达式为 LLVM Value""" - if node is None: - return None + if node is None: return None k: int = node.kind() if k == ast.ASTKind.Constant: rv: mlirlite.Value* = self.Gen.ExprGenConst.translate_constant(builder, pool, mod, node, trans, target_ty) @@ -111,8 +108,7 @@ novirtual class ExprGenMixin(ExprGenBase.ExprGenBase): if aw_cl.func is not None and aw_cl.func.kind() == ast.ASTKind.Name: aw_nm: ast.Name* = ast.Name*(aw_cl.func) if aw_nm.id is not None and trans is not None: - if self.Gen.AsyncGen.is_async_func(trans, aw_nm.id) != 0: - return self.Gen.AsyncGen._emit_await(builder, pool, mod, trans, aw, aw_nm.id) + if self.Gen.AsyncGen.is_async_func(trans, aw_nm.id) != 0: return self.Gen.AsyncGen._emit_await(builder, pool, mod, trans, aw, aw_nm.id) return None elif k == ast.ASTKind.Starred: # *x 在值上下文(如 printf("%d", *k) 实参):解析器把调用参数位的 diff --git a/App/lib/core/Gen/Expr/ExprGenName.vp b/App/lib/core/Gen/Expr/ExprGenName.vp index e7e25ff..cb2a0c5 100644 --- a/App/lib/core/Gen/Expr/ExprGenName.vp +++ b/App/lib/core/Gen/Expr/ExprGenName.vp @@ -33,8 +33,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): """ if raw is None: return None mbl_c: sizet = 0 - while raw[mbl_c] != ' ' and raw[mbl_c] != '\0' and raw[mbl_c] != ':': - mbl_c += 1 + while raw[mbl_c] != ' ' and raw[mbl_c] != '\0' and raw[mbl_c] != ':': mbl_c += 1 if mbl_c == 0: return None buf_c: str = pool.alloc(mbl_c + 1) if buf_c is None: return None @@ -75,11 +74,9 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # 字符串 CDefine(如 ZLIB_VERSION: t.CDefine = "1.3.2"): # 返回 global string(i8*),供 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) + 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") - if self.Gen.TypeGenCDef.is_cdefine_double() != 0: - return mlirlite.ConstFloat(pool, mlirlite.Double(pool), cdef_val_d) + if self.Gen.TypeGenCDef.is_cdefine_double() != 0: return mlirlite.ConstFloat(pool, mlirlite.Double(pool), cdef_val_d) # 整数 CDefine:重新查表取 64 位全精度值(double 往返会丢精度, # 9223372036854775807 → 9.223372036854776e18 舍入错位,生成错常量) cdef_val_c: int64 = self.Gen.TypeGenCDef.lookup_cdefine_constant(nm_id) @@ -87,8 +84,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # use_ctx 携带,仅供报文使用): # 更宽 ⇒ 就地升宽物化;更窄 ⇒ fail-fast;取不到 ⇒ 既有默认 32/64。 uw_val: mlirlite.Value* = self.Gen.ExprGenCdef.cdefine_use_width_value(pool, node, nm_id, cdef_val_c, target_ty, use_ctx) - if uw_val is not None: - return uw_val + if uw_val is not None: return uw_val return self.Gen.ExprGenCdef._const_int_for_cdefine(pool, cdef_val_c) # 本地表未找到:尝试跨模块 .vpi 查找(保证多模块查表存表一致) @@ -108,18 +104,15 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if self.Gen.TypeGenCDef.is_cdefine_found() != 0: 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) + 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") # 跨模块浮点 CDefine 已缓存为 double(is_cdefine_double), # 需返回浮点常量而非截断的整数 dchk_nm: double = self.Gen.TypeGenCDef.lookup_cdefine_double(nm_id) - if self.Gen.TypeGenCDef.is_cdefine_double() != 0: - return mlirlite.ConstFloat(pool, mlirlite.Double(pool), dchk_nm) + if self.Gen.TypeGenCDef.is_cdefine_double() != 0: return mlirlite.ConstFloat(pool, mlirlite.Double(pool), dchk_nm) # 使用处宽度同口径(跨模块 CDefine) uw_x: mlirlite.Value* = self.Gen.ExprGenCdef.cdefine_use_width_value(pool, node, nm_id, cdef_val, target_ty, use_ctx) - if uw_x is not None: - return uw_x + if uw_x is not None: return uw_x return self.Gen.ExprGenCdef._const_int_for_cdefine(pool, cdef_val) # CDefine 查找失败:from-import 的模块级全局变量(如 @@ -132,8 +125,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # 带源模块 SHA1 前缀精确查找,避免多模块同名全局后缀匹配串扰。 # fi_mod_raw 非 NUL 结尾,先截断再查 SHA1(否则整串查不到退化裸名) fi_mod_cut: str = self._cut_from_import_mod(pool, fi_mod_raw) - if fi_mod_cut is None: - fi_mod_cut = fi_mod_raw + if fi_mod_cut is None: fi_mod_cut = fi_mod_raw fi_gv_q: str = self.Gen.FuncGenBase._mangle_name_with_sha1(StubMergerStore.LookupSha1ByModName(fi_mod_cut), nm_id) fi_gv: mlirlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(trans.Module, fi_gv_q) if fi_gv is not None and fi_gv.Ty is not None: @@ -155,8 +147,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): mod_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm_id) if mod_alloca is not None: load_ty: mlirlite.LLVMType* = None - if mod_alloca.Ty is not None: - load_ty = mod_alloca.Ty.Pointee + if mod_alloca.Ty is not None: load_ty = mod_alloca.Ty.Pointee if load_ty is None: # fail-fast:global 变量存储类型缺失,立即终止编译(暴露上游根因) self.Gen.TypeGenErr.fatal_error(node, f"变量 '{nm_id}' 存储类型缺失", "TypeError") @@ -178,16 +169,14 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): return mlirlite.build_load(builder, load_ty, mod_alloca, vol_g) # nonlocal 变量:通过闭包 env 访问 - if GenApi.is_nonlocal_name(trans, nm_id) != 0: - return self.Gen.StmtGenDecl.load_nonlocal_var(trans, nm_id) + if GenApi.is_nonlocal_name(trans, nm_id) != 0: return self.Gen.StmtGenDecl.load_nonlocal_var(trans, nm_id) # *args va_list:变量名直接解析为指向 24 字节 va_list 缓冲区的 i8* 地址 # (对齐 TPC _direct_values[vararg_name] = va_list_ptr;不 load 缓冲区内容, # 转发时按值传该地址即可,如 sprintf → vsnprintf(..., args)) if trans is not None and trans._vararg_name is not None: if nm_id is not None and string.strcmp(nm_id, trans._vararg_name) == 0: - if trans._va_list_ptr is not None: - return trans._va_list_ptr + if trans._va_list_ptr is not None: return trans._va_list_ptr # 局部变量查找(必须先于模块别名检查) # 否则与模块同名的局部变量(如 `import t, c` 后的局部变量 c)会被误判为模块别名, @@ -195,8 +184,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm_id) if alloca is not None: load_ty: mlirlite.LLVMType* = None - if alloca.Ty is not None: - load_ty = alloca.Ty.Pointee + if alloca.Ty is not None: load_ty = alloca.Ty.Pointee if load_ty is None: # fail-fast:局部变量存储类型缺失,立即终止编译(暴露上游根因) self.Gen.TypeGenErr.fatal_error(node, f"变量 '{nm_id}' 存储类型缺失", "TypeError") @@ -245,15 +233,13 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # 非 REPL(trans.ReplCtx is None)时 repl_try_read 立即返回 None ⇒ 原路径逐字不变。 if trans is not None and trans.ReplCtx is not None: sess_val: mlirlite.Value* = self.Gen.VarGen.repl_try_read(trans, nm_id, node) - if sess_val is not None: - return sess_val + if sess_val is not None: return sess_val # 模块别名检查:SymTab 查找失败后才检查 # 如果 nm_id 是已导入模块名(如 win32file, fileio)且未被声明为局部变量, # 返回 None 让上层处理(用于属性访问 win32file.CreateFileA) if trans is not None and trans._imported_modules is not None: - if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, nm_id) != 0: - return None + if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, nm_id) != 0: return None # 模块级函数引用:函数名作为值传递(如 CreateThread(..., _thread_alloc_free, ...))。 # 之前缺失此查找导致函数名参数翻译返回 None 被跳过,后续参数整体前移 @@ -268,8 +254,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): fn_ref: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(trans.Module, nm_id) if fn_ref is not None: fn_name: str = mlirlite.function_get_name(fn_ref) - if fn_name is None: - return None + if fn_name is None: return None # 构造函数类型:ret_ty + 参数 ParamNode 链表 fn_ret_ty: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(fn_ref) if fn_ret_ty is None: @@ -283,29 +268,23 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): fn_pty: mlirlite.LLVMType* = mlirlite.param_get_ty(fn_pp) fn_pn: mlirlite.ParamNode* = mlirlite.new_param_node(pool, fn_pty) if fn_pn is not None: - if fn_first_node is None: - fn_first_node = fn_pn - if fn_prev_node is not None: - mlirlite.paramnode_set_next(fn_prev_node, fn_pn) + if fn_first_node is None: fn_first_node = fn_pn + if fn_prev_node is not None: mlirlite.paramnode_set_next(fn_prev_node, fn_pn) fn_prev_node = fn_pn fn_pcount += 1 fn_pp = mlirlite.param_get_next(fn_pp) fn_ty: mlirlite.LLVMType* = mlirlite.Func(pool, fn_ret_ty, fn_first_node, fn_pcount) - if fn_ty is None: - return None + if fn_ty is None: return None # 构造函数指针 Value(new_value 包装,避免触碰 Function.Next) fn_ref_v: mlirlite.Value* = mlirlite.new_value(pool) - if fn_ref_v is None: - return None + if fn_ref_v is None: return None mlirlite.value_set_ty(fn_ref_v, mlirlite.Ptr(pool, fn_ty)) mlirlite.value_set_isconst(fn_ref_v, 1) fn_ref_name: str = pool.alloc(256) if fn_ref_name is not None: fn_ref_name[0] = '\0' - if self.Gen.ClassGenVTable._vtable_name_needs_quote(fn_name) != 0: - viperlib.snprintf(fn_ref_name, 256, "@\"%s\"", fn_name) - else: - viperlib.snprintf(fn_ref_name, 256, "@%s", fn_name) + if self.Gen.ClassGenVTable._vtable_name_needs_quote(fn_name) != 0: viperlib.snprintf(fn_ref_name, 256, "@\"%s\"", fn_name) + else: viperlib.snprintf(fn_ref_name, 256, "@%s", fn_name) mlirlite.value_set_name(fn_ref_v, fn_ref_name) fn_i8ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) return mlirlite.build_bitcast(builder, fn_ref_v, fn_i8ptr_ty) @@ -326,18 +305,15 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if fi_mod is not None: # 排除已注册类名/枚举名:这些是类型,不作为全局变量值读取 fi_is_class: int = 0 - if self.Gen.StructGen.get_struct_type(nm_id) is not None: - fi_is_class = 1 + if self.Gen.StructGen.get_struct_type(nm_id) is not None: fi_is_class = 1 # 排除 ALL_CAPS CDefine(上方已处理本地+跨模块查找) - if self.Gen.ExprGenCdef._is_cdefine_name_pattern(nm_id) != 0: - fi_is_class = 1 + if self.Gen.ExprGenCdef._is_cdefine_name_pattern(nm_id) != 0: fi_is_class = 1 if fi_is_class == 0: fi_gname: str = nm_id fi_orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, nm_id) if fi_orig is not None: og_len_fi: sizet = 0 - while fi_orig[og_len_fi] != ' ' and fi_orig[og_len_fi] != '\0': - og_len_fi += 1 + while fi_orig[og_len_fi] != ' ' and fi_orig[og_len_fi] != '\0': og_len_fi += 1 if og_len_fi > 0: og_buf_fi: str = pool.alloc(og_len_fi + 1) if og_buf_fi is not None: @@ -350,13 +326,11 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # 带源模块 SHA1 前缀精确查找(避免多模块同名全局后缀匹配串扰); # fi_mod 非 NUL 结尾,先截断再查 SHA1(否则退化裸名 → undefined) fi_mod_cut2: str = self._cut_from_import_mod(pool, fi_mod) - if fi_mod_cut2 is None: - fi_mod_cut2 = fi_mod + if fi_mod_cut2 is None: fi_mod_cut2 = fi_mod gv_fi_q: str = self.Gen.FuncGenBase._mangle_name_with_sha1(StubMergerStore.LookupSha1ByModName(fi_mod_cut2), fi_gname) gv_fi: mlirlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(trans.Module, gv_fi_q) ref_fi: mlirlite.Value* = None - if gv_fi is not None and gv_fi.Ty is not None: - ref_fi = self.Gen.ExprGenAttr.make_global_ref(pool, gv_fi.Name, gv_fi.Ty) + if gv_fi is not None and gv_fi.Ty is not None: ref_fi = self.Gen.ExprGenAttr.make_global_ref(pool, gv_fi.Name, gv_fi.Ty) else: # 依赖模块 vpi/stub 未注入:Phase A 按文件序翻译时依赖模块 # (如 lexer 先于 ast.tokens)可能晚于本文件,其 .vpi 尚未生成 @@ -366,8 +340,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): return None if ref_fi is not None and ref_fi.Ty is not None: lty_fi: mlirlite.LLVMType* = ref_fi.Ty.Pointee - if lty_fi is not None: - return mlirlite.build_load(builder, lty_fi, ref_fi) + if lty_fi is not None: return mlirlite.build_load(builder, lty_fi, ref_fi) return ref_fi # 所有查找路径均失败 @@ -376,8 +349,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # 豁免:关键字/内建名(self/pool/true/false/None/match 上下文关键字、_、 # CIf 系等特殊名字)——这些名字不注册 SymTab 属正常,调用方有合法语义 # 处理路径(如 CIf 未定义名特判走 else),保持返回 None 不报错。 - if nm_id is None: - return None + if nm_id is None: return None if string.strcmp(nm_id, "self") == 0 or string.strcmp(nm_id, "pool") == 0 or string.strcmp(nm_id, "true") == 0 or string.strcmp(nm_id, "false") == 0 or string.strcmp(nm_id, "None") == 0 or string.strcmp(nm_id, "match") == 0 or string.strcmp(nm_id, "_") == 0 or string.strcmp(nm_id, "CIf") == 0 or string.strcmp(nm_id, "CIfdef") == 0 or string.strcmp(nm_id, "CIfndef") == 0: return None # 诊断:把当前泛型上下文一并报出 —— "未定义名称 'T'" 常与真因(泛型上下文 @@ -388,8 +360,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if trans is not None and trans.GenericTypeParamNames is not None: ctp_n: sizet = len(trans.GenericTypeParamNames) cta_n: sizet = 0 - if trans.GenericTypeArgs is not None: - cta_n = len(trans.GenericTypeArgs) + 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") return None @@ -406,31 +377,25 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): idx_val: mlirlite.Value*, node: ast.AST* = None) -> mlirlite.Value*: """内联生成 list __getitem__ 逻辑,返回元素地址 (i8*)""" - if builder is None or pool is None or lm_obj is None or idx_val is None: - return None + if builder is None or pool is None or lm_obj is None or idx_val is None: return None i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool) i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty) # 加载 __data__ (偏移 0, index 0) g_idx0: mlirlite.Value* = mlirlite.const_int64(pool, 0) g_dpp: mlirlite.Value* = mlirlite.build_gep(builder, i64_ty, lm_obj, g_idx0) - if g_dpp is None: - return None + if g_dpp is None: return None g_data: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, g_dpp) # 加载 __elem_size__ (偏移 32, index 4) g_idx4: mlirlite.Value* = mlirlite.const_int64(pool, 4) g_epp: mlirlite.Value* = mlirlite.build_gep(builder, i64_ty, lm_obj, g_idx4) - if g_epp is None: - return None + if g_epp is None: return None g_esize: mlirlite.Value* = mlirlite.build_load(builder, i64_ty, g_epp) - if g_data is None or g_esize is None: - return None + if g_data is None or g_esize is None: return None g_idx_i64: mlirlite.Value* = self.coerce_to_type(builder, idx_val, i64_ty, node) - if g_idx_i64 is None: - return None + if g_idx_i64 is None: return None g_offset: mlirlite.Value* = mlirlite.build_mul(builder, g_idx_i64, g_esize) - if g_offset is None: - return None + if g_offset is None: return None # 返回元素地址 (i8*),不 load return mlirlite.build_gep(builder, i8_ty, g_data, g_offset) # ============================================================ @@ -444,37 +409,23 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): def _list_elem_type_from_name(self, pool: memhub.MemBuddy*, struct_name: str) -> mlirlite.LLVMType*: """从 list 类型名提取元素 LLVM 类型""" - if pool is None or struct_name is None: - return None + if pool is None or struct_name is None: return None # 用 strstr 检查完整模式 - if string.strstr(struct_name, "list[int]") is not None: - return mlirlite.Int32(pool) - if string.strstr(struct_name, "list[CInt]") is not None: - return mlirlite.Int32(pool) - if string.strstr(struct_name, "list[CInt8T]") is not None: - return mlirlite.Int8(pool) - if string.strstr(struct_name, "list[CInt16T]") is not None: - return mlirlite.Int16(pool) - if string.strstr(struct_name, "list[CInt32T]") is not None: - return mlirlite.Int32(pool) - if string.strstr(struct_name, "list[CInt64T]") is not None: - return mlirlite.Int64(pool) - if string.strstr(struct_name, "list[CSizeT]") is not None: - return mlirlite.Int64(pool) - if string.strstr(struct_name, "list[CDouble]") is not None: - return mlirlite.Double(pool) - if string.strstr(struct_name, "list[CFloat]") is not None: - return mlirlite.Float(pool) - if string.strstr(struct_name, "list[CChar]") is not None: - return mlirlite.Int8(pool) + if string.strstr(struct_name, "list[int]") is not None: return mlirlite.Int32(pool) + if string.strstr(struct_name, "list[CInt]") is not None: return mlirlite.Int32(pool) + if string.strstr(struct_name, "list[CInt8T]") is not None: return mlirlite.Int8(pool) + if string.strstr(struct_name, "list[CInt16T]") is not None: return mlirlite.Int16(pool) + if string.strstr(struct_name, "list[CInt32T]") is not None: return mlirlite.Int32(pool) + if string.strstr(struct_name, "list[CInt64T]") is not None: return mlirlite.Int64(pool) + if string.strstr(struct_name, "list[CSizeT]") is not None: return mlirlite.Int64(pool) + if string.strstr(struct_name, "list[CDouble]") is not None: return mlirlite.Double(pool) + if string.strstr(struct_name, "list[CFloat]") is not None: return mlirlite.Float(pool) + if string.strstr(struct_name, "list[CChar]") is not None: return mlirlite.Int8(pool) # str/bytes/CPtr 等已知指针元素类型 → i8*(元素存储为 8 字节地址) i8_ty_d: mlirlite.LLVMType* = mlirlite.Int8(pool) - if string.strstr(struct_name, "list[str]") is not None: - return mlirlite.Ptr(pool, i8_ty_d) - if string.strstr(struct_name, "list[bytes]") is not None: - return mlirlite.Ptr(pool, i8_ty_d) - if string.strstr(struct_name, "list[CPtr]") is not None: - return mlirlite.Ptr(pool, i8_ty_d) + if string.strstr(struct_name, "list[str]") is not None: return mlirlite.Ptr(pool, i8_ty_d) + if string.strstr(struct_name, "list[bytes]") is not None: return mlirlite.Ptr(pool, i8_ty_d) + if string.strstr(struct_name, "list[CPtr]") is not None: return mlirlite.Ptr(pool, i8_ty_d) # 未知 list[T] 元素类型(自定义结构体元素,如 # list[rawptr[7565e081d88517ac.AST]] / list[sha1.Foo*]): # 元素槽存对象指针(8 字节)。从元素类型文本还原对象指针 LLVM 类型 @@ -484,8 +435,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # 类名,.kind() 被当未绑定外部函数(AstTest NewAstTest fatal: 'kind' # 根因:list 元素类名没有沿 get(0) 调用结果值类型传播到后续分派)。 elem_obj_ty_l: mlirlite.LLVMType* = self._list_elem_obj_ty_from_struct_name(pool, struct_name) - if elem_obj_ty_l is not None: - return elem_obj_ty_l + if elem_obj_ty_l is not None: return elem_obj_ty_l # 结构体未注册(依赖模块未就绪等):回退 Ptr(i8)(8 字节槽位宽一致, # load 值正确),由 AnnotClassName/方法分派回退机制保证语义。 # 禁止 fail-fast(误杀合法自定义类元素列表的访问)。 @@ -504,26 +454,20 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): def _list_elem_obj_ty_from_struct_name(self, pool: memhub.MemBuddy*, struct_name: str) -> mlirlite.LLVMType*: """从 list 特化类型名还原元素对象指针 LLVM 类型,失败返回 None""" - if pool is None or struct_name is None: - return None + if pool is None or struct_name is None: return None lb_e: str = string.strchr(struct_name, '[') - if lb_e is None: - return None + if lb_e is None: return None rb_e: str = string.strrchr(struct_name, ']') - if rb_e is None: - return None + if rb_e is None: return None elen_e: sizet = sizet(uint64(rb_e) - uint64(lb_e)) - 1 - if elen_e == 0 or elen_e > 512: - return None + if elen_e == 0 or elen_e > 512: return None elem_buf_e: str = pool.alloc(elen_e + 1) - if elem_buf_e is None: - return None + if elem_buf_e is None: return None string.strncpy(elem_buf_e, lb_e + 1, elen_e) elem_buf_e[elen_e] = '\0' # 剥 rawptr[...] 包装(元素声明为对象指针,如 rawptr[sha1.AST]) cur_e: str = elem_buf_e - if string.strncmp(cur_e, "rawptr[", 7) == 0: - cur_e = cur_e + 7 + if string.strncmp(cur_e, "rawptr[", 7) == 0: cur_e = cur_e + 7 # 按 '|' 联合分段(A|B),段内去首尾空白/尾部 ']'/引号;段文本直接 # 交给 find_struct(内置名 CPtr/str/int 等不注册 struct → 天然返回 # None 跳过;带 "sha1.Class" 前缀走模块归属精确匹配) @@ -532,10 +476,8 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): i_e: sizet = 0 while i_e <= total_e: hit_e: int = 0 - if i_e == total_e: - hit_e = 1 - elif cur_e[i_e] == '|': - hit_e = 1 + if i_e == total_e: hit_e = 1 + elif cur_e[i_e] == '|': hit_e = 1 if hit_e == 0: i_e += 1 continue @@ -545,10 +487,8 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # 见 TypeGenResolve._norm_type_arg_name 的指针书写归一),而 # find_struct 只认类名本身;不剥则对象元素还原失败、静默退回 Ptr(i8) # 丢元素类名(链式 .get(0).kind() 分派回退根因)。 - while b_e > a_e and (cur_e[b_e - 1] == ' ' or cur_e[b_e - 1] == ']' or cur_e[b_e - 1] == '\'' or cur_e[b_e - 1] == '"' or cur_e[b_e - 1] == '*'): - b_e -= 1 - while a_e < b_e and (cur_e[a_e] == ' ' or cur_e[a_e] == '\'' or cur_e[a_e] == '"'): - a_e += 1 + while b_e > a_e and (cur_e[b_e - 1] == ' ' or cur_e[b_e - 1] == ']' or cur_e[b_e - 1] == '\'' or cur_e[b_e - 1] == '"' or cur_e[b_e - 1] == '*'): b_e -= 1 + while a_e < b_e and (cur_e[a_e] == ' ' or cur_e[a_e] == '\'' or cur_e[a_e] == '"'): a_e += 1 if b_e > a_e: seg_len_e: sizet = b_e - a_e if seg_len_e < 256: @@ -557,10 +497,8 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): string.strncpy(seg_buf_e, cur_e + a_e, seg_len_e) seg_buf_e[seg_len_e] = '\0' s_entry_e: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(seg_buf_e) - if s_entry_e is not None and s_entry_e.Ty is not None: - return mlirlite.Ptr(pool, s_entry_e.Ty) - if i_e == total_e: - break + if s_entry_e is not None and s_entry_e.Ty is not None: return mlirlite.Ptr(pool, s_entry_e.Ty) + if i_e == total_e: break seg_s_e = i_e + 1 i_e += 1 return None @@ -576,52 +514,40 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): rhs_val: mlirlite.Value*, node: ast.AST* = None) -> int: """内联生成 list __setitem__ 逻辑,返回 0""" - if builder is None or pool is None or lm_obj is None or idx_val is None or rhs_val is None: - return 0 + if builder is None or pool is None or lm_obj is None or idx_val is None or rhs_val is None: return 0 i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool) i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty) # 加载 __data__ (偏移 0, index 0) s_idx0: mlirlite.Value* = mlirlite.const_int64(pool, 0) s_dpp: mlirlite.Value* = mlirlite.build_gep(builder, i64_ty, lm_obj, s_idx0) - if s_dpp is None: - return 0 + if s_dpp is None: return 0 s_data: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, s_dpp) # 加载 __elem_size__ (偏移 32, index 4) s_idx4: mlirlite.Value* = mlirlite.const_int64(pool, 4) s_epp: mlirlite.Value* = mlirlite.build_gep(builder, i64_ty, lm_obj, s_idx4) - if s_epp is None: - return 0 + if s_epp is None: return 0 s_esize: mlirlite.Value* = mlirlite.build_load(builder, i64_ty, s_epp) - if s_data is None or s_esize is None: - return 0 + if s_data is None or s_esize is None: return 0 s_idx_i64: mlirlite.Value* = self.coerce_to_type(builder, idx_val, i64_ty, node) - if s_idx_i64 is None: - return 0 + if s_idx_i64 is None: return 0 s_offset: mlirlite.Value* = mlirlite.build_mul(builder, s_idx_i64, s_esize) - if s_offset is None: - return 0 + if s_offset is None: return 0 s_addr: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, s_data, s_offset) - if s_addr is None: - return 0 + if s_addr is None: return 0 # 元素类型 T:从 list 特化类型名解析(list[int]→i32、list[str]→i8*)。 # 此前固定 i8*(8 字节)store(inttoptr 值)覆盖相邻元素——与 # CallGenMixin list 内置分支同根因(ListTest pop FAILED expect 30)。 s_sty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(lm_obj) s_name: str = None - if s_sty is not None: - s_name = mlirlite.get_struct_name(s_sty) + if s_sty is not None: s_name = mlirlite.get_struct_name(s_sty) s_elem_ty: mlirlite.LLVMType* = None - if s_name is not None: - s_elem_ty = self._list_elem_type_from_name(pool, s_name) - if s_elem_ty is None: - s_elem_ty = i8_ptr_ty + if s_name is not None: s_elem_ty = self._list_elem_type_from_name(pool, s_name) + if s_elem_ty is None: s_elem_ty = i8_ptr_ty s_val_ptr: mlirlite.Value* = self.coerce_to_type(builder, rhs_val, s_elem_ty, node) - if s_val_ptr is None: - return 0 + if s_val_ptr is None: return 0 s_ep: mlirlite.Value* = mlirlite.build_bitcast(builder, s_addr, mlirlite.Ptr(pool, s_elem_ty)) - if s_ep is not None: - mlirlite.build_store(builder, s_val_ptr, s_ep) + if s_ep is not None: mlirlite.build_store(builder, s_val_ptr, s_ep) return 0 # ============================================================ # is_list_subscript — 检查 Subscript 节点是否是 list[T] 类型 @@ -631,24 +557,17 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): def is_list_subscript(self, node: ast.AST*, trans: HT.Translator*) -> mlirlite.Value*: """检查 Subscript 节点是否是 list[T] 类型,返回 list 对象指针或 None""" - if node is None or trans is None: - return None + if node is None or trans is None: return None sub: ast.Subscript* = ast.Subscript*(node) - if sub is None or sub.value is None: - return None - if sub.value.kind() != ast.ASTKind.Name: - return None + if sub is None or sub.value is None: return None + if sub.value.kind() != ast.ASTKind.Name: return None nm: ast.Name* = ast.Name*(sub.value) - if nm is None or nm.id is None: - return None + if nm is None or nm.id is None: return None alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id) - if alloca is None or alloca.Ty is None: - return None - if self.is_ptr_type(alloca.Ty) == 0: - return None + if alloca is None or alloca.Ty is None: return None + if self.is_ptr_type(alloca.Ty) == 0: return None pointee: mlirlite.LLVMType* = alloca.Ty.Pointee - if pointee is None: - return None + if pointee is None: return None # 检查 pointee 是否是 Ptr(Struct) inner_ty: mlirlite.LLVMType* = None match pointee: @@ -656,8 +575,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): inner_ty = it case _: return None - if inner_ty is None: - return None + if inner_ty is None: return None # 检查 inner_ty 是否是 Struct 且名称包含 "list[" struct_name: str = None match inner_ty: @@ -665,10 +583,8 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): struct_name = sname case _: return None - if struct_name is None: - return None - if string.strstr(struct_name, "list[") is None: - return None + if struct_name is None: return None + if string.strstr(struct_name, "list[") is None: return None # 是 list 类型: load 出 list 对象指针 builder: mlirlite.IRBuilder* = trans._cur_builder return mlirlite.build_load(builder, pointee, alloca) @@ -679,19 +595,15 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): nm_id: str, idx_val: mlirlite.Value*) -> mlirlite.Value*: """nonlocal 数组/指针下标:从 env 读堆地址 → bitcast → GEP,返回元素指针""" - if trans is None or nm_id is None or idx_val is None: - return None + if trans is None or nm_id is None or idx_val is None: return None nl_ty: mlirlite.LLVMType* = GenApi.get_nonlocal_type(trans, nm_id) - if nl_ty is None: - return None + if nl_ty is None: return None raw_nl: mlirlite.Value* = self.Gen.StmtGenDecl._load_raw_var_ptr(trans, nm_id) - if raw_nl is None: - return None + if raw_nl is None: return None match nl_ty: case mlirlite.LLVMType.Array(elem_ty_nl, _cnt_nl): arr_ptr_nl: mlirlite.Value* = mlirlite.build_bitcast(builder, raw_nl, mlirlite.Ptr(pool, nl_ty)) - if arr_ptr_nl is None: - return None + if arr_ptr_nl is None: return None return mlirlite.build_gep_array(builder, nl_ty, elem_ty_nl, arr_ptr_nl, idx_val) case mlirlite.LLVMType.Ptr(inner_nl): arr_ptr_nl2: mlirlite.Value* = mlirlite.build_bitcast(builder, raw_nl, mlirlite.Ptr(pool, nl_ty)) @@ -715,11 +627,9 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): node: ast.AST*, trans: HT.Translator* = None) -> mlirlite.Value*: """翻译下标表达式,返回加载的元素值""" - if node is None or builder is None: - return None + if node is None or builder is None: return None sub: ast.Subscript* = ast.Subscript*(node) - if sub is None: - return None + if sub is None: return None # 切片形式 a[start:end](如 path[n:]):返回 i8* 基指针 + start 偏移。 # 此前 Slice AST 被当作单索引 translate_value → 无 Slice 分支返回 None → @@ -737,10 +647,8 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): start_w: mlirlite.Value* = start_v if start_v.Ty is not None: bt_sc: int = self.Gen.ExprGenBase.get_llvm_type_bits(start_v.Ty) - if bt_sc != 0 and bt_sc < 64: - start_w = mlirlite.build_sext(builder, start_v, i64_sc) - if start_w is None: - return None + if bt_sc != 0 and bt_sc < 64: start_w = mlirlite.build_sext(builder, start_v, i64_sc) + if start_w is None: return None i8_sc: mlirlite.LLVMType* = mlirlite.Int8(pool) return mlirlite.build_gep(builder, i8_sc, base_v, start_w) @@ -763,13 +671,11 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): match inner_elem_r: case mlirlite.LLVMType.Array(arr_ie_r, _): elem_ptr_r: mlirlite.Value* = mlirlite.build_gep_array(builder, inner_elem_r, arr_ie_r, inner_ptr_r, idx_val) - if elem_ptr_r is not None: - return mlirlite.build_load(builder, arr_ie_r, elem_ptr_r) + if elem_ptr_r is not None: return mlirlite.build_load(builder, arr_ie_r, elem_ptr_r) return None case _: elem_ptr_r2: mlirlite.Value* = mlirlite.build_gep(builder, inner_elem_r, inner_ptr_r, idx_val) - if elem_ptr_r2 is not None: - return mlirlite.build_load(builder, inner_elem_r, elem_ptr_r2) + if elem_ptr_r2 is not None: return mlirlite.build_load(builder, inner_elem_r, elem_ptr_r2) return None # 如果 value 是 Name,尝试从 alloca 类型推断 @@ -787,8 +693,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): nl_ptr_r: mlirlite.Value* = self._nonlocal_subscript_ptr(builder, pool, trans, nm.id, idx_val) if nl_ptr_r is not None and nl_ptr_r.Ty is not None: nl_elem_ty: mlirlite.LLVMType* = nl_ptr_r.Ty.Pointee - if nl_elem_ty is not None: - return mlirlite.build_load(builder, nl_elem_ty, nl_ptr_r) + if nl_elem_ty is not None: return mlirlite.build_load(builder, nl_elem_ty, nl_ptr_r) return None alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id) if alloca is not None and alloca.Ty is not None: @@ -801,8 +706,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): case mlirlite.LLVMType.Array(elem_ty, count): # 数组遍历: getelementptr [N x elem_ty], ... , i32 0, i32 %idx elem_ptr: mlirlite.Value* = mlirlite.build_gep_array(builder, pointee, elem_ty, alloca, idx_val) - if elem_ptr is not None: - return mlirlite.build_load(builder, elem_ty, elem_ptr) + if elem_ptr is not None: return mlirlite.build_load(builder, elem_ty, elem_ptr) return None case mlirlite.LLVMType.Struct(_fs_v, _fc_v, lsn_v): # list[T] 值变量(无注解赋值 rhs 返回 list 值, @@ -818,8 +722,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if elem_ty_v is not None: elem_ptr_ty_v: mlirlite.LLVMType* = mlirlite.Ptr(pool, elem_ty_v) casted_v: mlirlite.Value* = mlirlite.build_bitcast(builder, elem_addr_v, elem_ptr_ty_v) - if casted_v is not None: - return mlirlite.build_load(builder, elem_ty_v, casted_v) + if casted_v is not None: return mlirlite.build_load(builder, elem_ty_v, casted_v) return None case mlirlite.LLVMType.Ptr(inner_ty): # 检查 inner_ty 是否是 list[T] 类型(泛型类不注册 struct) @@ -842,8 +745,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if elem_ty_list is not None: elem_ptr_ty_list: mlirlite.LLVMType* = mlirlite.Ptr(pool, elem_ty_list) casted_addr_list: mlirlite.Value* = mlirlite.build_bitcast(builder, elem_addr_list, elem_ptr_ty_list) - if casted_addr_list is not None: - return mlirlite.build_load(builder, elem_ty_list, casted_addr_list) + if casted_addr_list is not None: return mlirlite.build_load(builder, elem_ty_list, casted_addr_list) return None # inner_ty 是 Ptr 说明 alloca.Ty 是三重指针 Ptr(Ptr(Ptr(...))), # 即 X* 当 X 本身是指针类型 (如 T=AST*, T*=AST**)。 @@ -875,8 +777,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if not (arg_vals_rd_p is None): arg_vals_rd_p[0] = sizet(idx_val) ret_rd_p: mlirlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, cls_nm_rd_ptr, "__getitem__", obj_ptr_rd, arg_vals_rd_p, 1, trans, sub) - if not (ret_rd_p is None): - return ret_rd_p + if not (ret_rd_p is None): return ret_rd_p # 无 __getitem__:结构体指针数组访问(GEP + load) ptr_val_rd_g: mlirlite.Value* = mlirlite.build_load(builder, pointee, alloca) if ptr_val_rd_g is not None: @@ -924,8 +825,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if bits_rd == 8: i8_ptr_rd: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) elem_ptr_rd: mlirlite.Value* = mlirlite.build_gep(builder, i8_ptr_rd, alloca, idx_val) - if elem_ptr_rd is not None: - return mlirlite.build_load(builder, i8_ptr_rd, elem_ptr_rd) + if elem_ptr_rd is not None: return mlirlite.build_load(builder, i8_ptr_rd, elem_ptr_rd) case _: pass # 自定义类(结构体类型): 仅当类定义了 __getitem__ @@ -943,8 +843,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if not (arg_vals_sub is None): arg_vals_sub[0] = sizet(idx_val) ret_sub: mlirlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, cls_nm_sub, "__getitem__", obj_val_sub, arg_vals_sub, 1, trans, sub) - if not (ret_sub is None): - return ret_sub + if not (ret_sub is None): return ret_sub # 无 __getitem__:结构体指针数组访问(GEP + load) ptr_val_sub_g: mlirlite.Value* = mlirlite.build_load(builder, pointee, alloca) if ptr_val_sub_g is not None: @@ -957,8 +856,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # 通用路径:翻译 value 获取指针 ptr_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub.value, None, 0, trans) - if ptr_val is None or ptr_val.Ty is None: - return None + if ptr_val is None or ptr_val.Ty is None: return None # 检查是否是指针类型 if self.is_ptr_type(ptr_val.Ty) != 0: @@ -972,8 +870,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): match elem_ty2: case mlirlite.LLVMType.Array(arr_elem_ty2, arr_count2): elem_ptr3: mlirlite.Value* = mlirlite.build_gep_array(builder, elem_ty2, arr_elem_ty2, ptr_val, idx_val) - if elem_ptr3 is not None: - return mlirlite.build_load(builder, arr_elem_ty2, elem_ptr3, vol_sub_gen) + if elem_ptr3 is not None: return mlirlite.build_load(builder, arr_elem_ty2, elem_ptr3, vol_sub_gen) return None case _: pass @@ -997,17 +894,14 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if not (arg_vals_rd_g is None): arg_vals_rd_g[0] = sizet(idx_val) ret_rd_g: mlirlite.Value* = self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, cls_nm_rd_gen, "__getitem__", ptr_val, arg_vals_rd_g, 1, trans, sub) - if not (ret_rd_g is None): - return ret_rd_g + if not (ret_rd_g is None): return ret_rd_g # 无 __getitem__:结构体指针数组访问(GEP + load) elem_ptr_gen: mlirlite.Value* = mlirlite.build_gep(builder, elem_ty2, ptr_val, idx_val) - if elem_ptr_gen is not None: - return mlirlite.build_load(builder, elem_ty2, elem_ptr_gen, vol_sub_gen) + if elem_ptr_gen is not None: return mlirlite.build_load(builder, elem_ty2, elem_ptr_gen, vol_sub_gen) return None # 指针类型: 单索引 GEP + load elem_ptr4: mlirlite.Value* = mlirlite.build_gep(builder, elem_ty2, ptr_val, idx_val) - if elem_ptr4 is not None: - return mlirlite.build_load(builder, elem_ty2, elem_ptr4, vol_sub_gen) + if elem_ptr4 is not None: return mlirlite.build_load(builder, elem_ty2, elem_ptr4, vol_sub_gen) return None # ============================================================ # 获取下标表达式的元素指针(不加载值,用于赋值) @@ -1050,8 +944,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): nm_bk: ast.Name* = ast.Name*(sub_bk.value) if nm_bk.id is None: return -1 alloca_bk: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm_bk.id) - if alloca_bk is None: - alloca_bk = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm_bk.id) + if alloca_bk is None: alloca_bk = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm_bk.id) if alloca_bk is None or alloca_bk.Ty is None: return -1 if self.is_ptr_type(alloca_bk.Ty) == 0: return -1 base_ty_bk = alloca_bk.Ty.Pointee @@ -1060,8 +953,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): fe_bk: GenTypes.FieldEntry* = self.Gen.ExprGenAttr._resolve_attr_field_entry(pool, trans, sub_bk.value) if fe_bk is None or fe_bk.Ty is None: return -1 base_ty_bk = fe_bk.Ty - else: - return -1 + else: return -1 if base_ty_bk is None: return -1 # 基座自身是数组值 → 数组存储 if self.is_array_type(base_ty_bk) != 0: return 1 @@ -1113,8 +1005,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if nm.id is not None and trans is not None: # nonlocal 数组/指针:从 env 读共享堆地址(提升函数内不能 # lookup_var 外层 alloca——SSA 编号跨函数错乱崩溃) - if GenApi.is_nonlocal_name(trans, nm.id) != 0: - return self._nonlocal_subscript_ptr(builder, pool, trans, nm.id, idx_val) + if GenApi.is_nonlocal_name(trans, nm.id) != 0: return self._nonlocal_subscript_ptr(builder, pool, trans, nm.id, idx_val) alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id) if alloca is not None and alloca.Ty is not None: if self.is_ptr_type(alloca.Ty) != 0: @@ -1131,8 +1022,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # 此时 [i]=val 应该是指针解引用赋值, 而非调用 __setitem__。 if self.is_ptr_type(inner_ty) != 0: ptr_val_gsp: mlirlite.Value* = mlirlite.build_load(builder, pointee, alloca) - if ptr_val_gsp is not None: - return mlirlite.build_gep(builder, inner_ty, ptr_val_gsp, idx_val) + if ptr_val_gsp is not None: return mlirlite.build_gep(builder, inner_ty, ptr_val_gsp, idx_val) return None # 自定义结构体 (如 HashTable*, JsonValue*): # 仅当类定义了 __setitem__(当前模块定义或跨模块 stub declare 注入) @@ -1143,8 +1033,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): si_lookup_gsp: str = pool.alloc(128) if si_lookup_gsp is not None: viperlib.snprintf(si_lookup_gsp, 128, "%s.__setitem__", cls_nm_ptr_chk) - if self.Gen.CallGenBase.find_func_in_module(mod, si_lookup_gsp) is not None: - return None + if self.Gen.CallGenBase.find_func_in_module(mod, si_lookup_gsp) is not None: return None # bytes* / str*: alloca 是 i8**, # 直接 GEP 按 i8* 步长(8 字节),不 load # 仅当 inner_ty 不是自定义结构体时才走指针遍历 @@ -1165,8 +1054,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # 否则元素类型为指针 → i64 存储触发整数隐式转指针 # fail-fast(把解引用写入误判为 int→ptr)。 pe_annot: str = self.Gen.VarGen.var_annot_class_name(ve_pe) - if pe_annot is not None and self._annot_is_64bit_scalar(pe_annot) != 0: - return mlirlite.build_gep(builder, mlirlite.Int64(pool), ptr_val_pe, idx_val) + if pe_annot is not None and self._annot_is_64bit_scalar(pe_annot) != 0: return mlirlite.build_gep(builder, mlirlite.Int64(pool), ptr_val_pe, idx_val) match pointee: case mlirlite.LLVMType.Int(bits_pe): if bits_pe == 8: @@ -1178,8 +1066,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): return None # 普通指针遍历: 先 load 指针值,再 GEP ptr_val: mlirlite.Value* = mlirlite.build_load(builder, pointee, alloca) - if ptr_val is None: - return None + if ptr_val is None: return None gep_r: mlirlite.Value* = mlirlite.build_gep(builder, inner_ty, ptr_val, idx_val) return gep_r case _: @@ -1212,8 +1099,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # 通用路径 ptr_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub.value, None, 0, trans) - if ptr_val is None or ptr_val.Ty is None: - return None + if ptr_val is None or ptr_val.Ty is None: return None if self.is_ptr_type(ptr_val.Ty) != 0: elem_ty2: mlirlite.LLVMType* = ptr_val.Ty.Pointee if elem_ty2 is not None: @@ -1231,8 +1117,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): si_lookup_gen: str = pool.alloc(128) if si_lookup_gen is not None: viperlib.snprintf(si_lookup_gen, 128, "%s.__setitem__", cls_nm_gen) - if self.Gen.CallGenBase.find_func_in_module(mod, si_lookup_gen) is not None: - return None + if self.Gen.CallGenBase.find_func_in_module(mod, si_lookup_gen) is not None: return None # 指针类型: 单索引 GEP (getelementptr ty, ptr, idx) return mlirlite.build_gep(builder, elem_ty2, ptr_val, idx_val) return None \ No newline at end of file diff --git a/App/lib/core/Gen/Expr/ExprGenOps.vp b/App/lib/core/Gen/Expr/ExprGenOps.vp index 8888ca4..b2fe439 100644 --- a/App/lib/core/Gen/Expr/ExprGenOps.vp +++ b/App/lib/core/Gen/Expr/ExprGenOps.vp @@ -49,8 +49,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): cnt: int = trans._label_counter trans._label_counter = cnt + 1 name_buf: str = pool.alloc(32) - if name_buf is None: - return None + if name_buf is None: return None viperlib.snprintf(name_buf, 32, "ifexp.then.%d", cnt) then_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf) viperlib.snprintf(name_buf, 32, "ifexp.else.%d", cnt) @@ -81,8 +80,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # str(i8*)、else '?' 恒 i32 → CastError)。非指针 then 分支不下传,既有 # 常量物化与位宽行为保持不变。 orelse_target_ty: mlirlite.LLVMType* = None - if self.is_ptr_type(body_val.Ty) != 0: - orelse_target_ty = body_val.Ty + if self.is_ptr_type(body_val.Ty) != 0: orelse_target_ty = body_val.Ty mlirlite.position_at_end(builder, else_bb) orelse_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, ie.orelse, None, 0, trans, orelse_target_ty) else_blk_for_phi: rawptr[mlirlite.BasicBlock] = trans._cur_builder.CurBlock @@ -136,8 +134,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): 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) - if inc1 is None or inc2 is None: - return None + if inc1 is None or inc2 is None: return None # 链表顺序: inc1 (head) -> inc2 (tail) # 之前错误写成 inc2.Next = inc1,导致 build_phi 从 inc1 遍历时 # inc1.Next 为 None,只输出一个 phi 条目,引发 LLVM 验证错误: @@ -172,33 +169,28 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): uint32 值比较,sext 会把 0xAABBCCDD 变成 0xFFFFFFFFAABBCCDD 导致恒不等) """ - if narrow_val is None or narrow_val.Ty is None: - return 0 + if narrow_val is None or narrow_val.Ty is None: return 0 narrow_bits: int = self.get_llvm_type_bits(narrow_val.Ty) - if narrow_bits == 1: - return 1 + if narrow_bits == 1: return 1 if narrow_bits == 8: # i8 默认按「无符号字节」处理(系统编程惯例,保持既有行为); # 但**源注解明确为有符号类型**时必须 sext 保号: # TypeCastTest 回归 —— `int32(v)`(v: int8 = -50)期望 -50, # 此前 b8470c1 把强转路径统一到本函数后撞上无条件 zext 而变成 206。 - if self._node_type_signed(pool, narrow_node, trans) != 0: - return 0 + if self._node_type_signed(pool, narrow_node, trans) != 0: return 0 return 1 # 宽侧常量启发式 if wide_val is not None and wide_val.IsConst == 1: wide_bits: int = self.get_llvm_type_bits(wide_val.Ty) if wide_bits > narrow_bits and narrow_bits < 64: signed_max: int64 = (int64(1) << (narrow_bits - 1)) - 1 - if wide_val.IntVal > signed_max: - return 1 + if wide_val.IntVal > signed_max: return 1 # 窄侧 AST 节点解析为无符号类型(如 t.CUIntXXT 字面量/强转) # trans 必须下沉:Name/Subscript 形态靠 trans.SymTab 查变量/数组元素 # 注解的无符号性,缺 trans 时恒返回 0 → 无符号值被误用 sext 扩展 # (ide.vp identify_data[60] / timer.vp sec 的 uint16/uint32→更宽 根因) if narrow_node is not None: - if self._node_type_unsigned(pool, narrow_node, trans) != 0: - return 1 + if self._node_type_unsigned(pool, narrow_node, trans) != 0: return 1 # 窄侧是高位比特置位的 CDefine 常量(0x80000000..0xFFFFFFFF)→ zext。 # CDefine 常量是编译期值而非变量,_node_type_unsigned 查不到类型注解; # 值落在有符号负数区表示无符号哨兵(如 INVALID_FILE_ATTRIBUTES = @@ -212,8 +204,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if cdef_nm_zw.id is not None: cdv_zw: int64 = self.Gen.TypeGenCDef.lookup_cdefine_constant(cdef_nm_zw.id) if self.Gen.TypeGenCDef.is_cdefine_found() != 0: - if cdv_zw > 0x7FFFFFFF: - return 1 + if cdv_zw > 0x7FFFFFFF: return 1 return 0 def _node_type_unsigned(self, pool: memhub.MemBuddy*, node: ast.AST*, @@ -225,8 +216,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): - 无符号类型名的 Name 引用(如 UInt32T 别名) - 变量名(trans 可用时):查询 SymTab 中变量的 AnnotClassName(如 v: uint32) """ - if node is None: - return 0 + if node is None: return 0 k: int = node.kind() if k == ast.ASTKind.Call: cl: ast.Call* = ast.Call*(node) @@ -235,38 +225,31 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if at.value is not None and at.value.kind() == ast.ASTKind.Name: mod_nm: ast.Name* = ast.Name*(at.value) if mod_nm.id is not None and string.strcmp(mod_nm.id, "t") == 0 and at.attr is not None: - if self._type_name_unsigned(at.attr) != 0: - return 1 + if self._type_name_unsigned(at.attr) != 0: return 1 return 0 if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) if nm.id is not None: # 1) 名字本身是无符号类型名(如 UInt32T 别名) - if self._type_name_unsigned(nm.id) != 0: - return 1 + if self._type_name_unsigned(nm.id) != 0: return 1 # 2) 变量注解类型为无符号类型(trans 可用时查 SymTab) if trans is not None: ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id) if ve is not None: # [S4 切读] Spec 明确无符号(TS_UINT)优先于字符串判定 - if self._entry_spec_unsigned(ve.Spec) != 0: - return 1 + if self._entry_spec_unsigned(ve.Spec) != 0: return 1 vcn_u: str = self.Gen.VarGen.var_annot_class_name(ve) if vcn_u is not None: - if self._type_name_unsigned(vcn_u) != 0: - return 1 + if self._type_name_unsigned(vcn_u) != 0: return 1 return 0 if k == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(node) - if self._node_type_unsigned(pool, bop.left, trans) != 0: - return 1 - if self._node_type_unsigned(pool, bop.right, trans) != 0: - return 1 + if self._node_type_unsigned(pool, bop.left, trans) != 0: return 1 + if self._node_type_unsigned(pool, bop.right, trans) != 0: return 1 return 0 if k == ast.ASTKind.UnaryOp: uop: ast.UnaryOp* = ast.UnaryOp*(node) - if self._node_type_unsigned(pool, uop.operand, trans) != 0: - return 1 + if self._node_type_unsigned(pool, uop.operand, trans) != 0: return 1 return 0 if k == ast.ASTKind.Subscript: # 数组/指针下标: md5_buf[i](t.CArray[uint8, N])或 buf[i] @@ -279,12 +262,10 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if ve_su is not None: # [S4 切读] Spec 明确无符号优先(数组元素为无符号的联合注解场景 # 时 Spec 仍是 Ptr/Array ⇒ 返回 0,自动回退字符串路径) - if self._entry_spec_unsigned(ve_su.Spec) != 0: - return 1 + if self._entry_spec_unsigned(ve_su.Spec) != 0: return 1 scn_u: str = self.Gen.VarGen.var_annot_class_name(ve_su) if scn_u is not None: - if self._annot_str_unsigned(scn_u) != 0: - return 1 + if self._annot_str_unsigned(scn_u) != 0: return 1 return 0 if k == ast.ASTKind.Attribute: # 结构体字段(如 viperio.Buf 的 self.capacity/length: sizet):经接收者变量的 AnnotClassName 取类名,再按类名+字段名查字段注解,判定无符号(CSizeT/uint*)。本函数在 translate_binop 对每个操作数调用,必须只读、失败返回 0——故不走 lookup_field_by_class(其模块限定名分支会 fatal_error),改用 find_struct + 自遍历字段(未命中一律返回 0) @@ -295,14 +276,12 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): vn_u: ast.Name* = ast.Name*(at_u.value) if vn_u.id is not None: ve_u: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, vn_u.id) - if ve_u is not None: - cls_nm_u = self.Gen.VarGen.var_annot_class_name(ve_u) + if ve_u is not None: cls_nm_u = self.Gen.VarGen.var_annot_class_name(ve_u) if cls_nm_u is not None: # 取裸类名(点前部分):只做裸名结构体查找,避免模块限定名解析 bare_u: str = cls_nm_u dot_u: str = self.Gen.StructGen._last_dot_outside_brackets(cls_nm_u) - if dot_u is not None: - bare_u = dot_u + 1 + if dot_u is not None: bare_u = dot_u + 1 if bare_u is not None: st_u: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(bare_u) if st_u is not None: @@ -311,12 +290,10 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): fe_u: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(st_u, fi_u) if fe_u is not None and fe_u.Name is not None and string.strcmp(fe_u.Name, at_u.attr) == 0: # [S4 切读] 字段 Spec 明确无符号优先 - if self._entry_spec_unsigned(fe_u.Spec) != 0: - return 1 + if self._entry_spec_unsigned(fe_u.Spec) != 0: return 1 fcn_u: str = self.Gen.StructGen.get_field_annot_class_name(fe_u) if fcn_u is not None: - if self._annot_str_unsigned(fcn_u) != 0: - return 1 + if self._annot_str_unsigned(fcn_u) != 0: return 1 break fi_u += 1 return 0 @@ -332,8 +309,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): 遍历形态对应,但只覆盖**注解直接可见**的节点形态(Call(t.X) / Name / Subscript);其余返回 0,即保持 i8 的既有默认行为(不扩大改动面)。 """ - if node is None: - return 0 + if node is None: return 0 k: int = node.kind() if k == ast.ASTKind.Call: cl: ast.Call* = ast.Call*(node) @@ -342,21 +318,18 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if at.value is not None and at.value.kind() == ast.ASTKind.Name: mod_nm: ast.Name* = ast.Name*(at.value) if mod_nm.id is not None and string.strcmp(mod_nm.id, "t") == 0 and at.attr is not None: - if self._spec_sign_from_annot(at.attr) == TSpec.TS_SIGN_SIGNED: - return 1 + if self._spec_sign_from_annot(at.attr) == TSpec.TS_SIGN_SIGNED: return 1 return 0 if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) if nm.id is not None: - if self._spec_sign_from_annot(nm.id) == TSpec.TS_SIGN_SIGNED: - return 1 + if self._spec_sign_from_annot(nm.id) == TSpec.TS_SIGN_SIGNED: return 1 if trans is not None: ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id) if ve is not None: ncn_s: str = self.Gen.VarGen.var_annot_class_name(ve) if ncn_s is not None: - if self._spec_sign_from_annot(ncn_s) == TSpec.TS_SIGN_SIGNED: - return 1 + if self._spec_sign_from_annot(ncn_s) == TSpec.TS_SIGN_SIGNED: return 1 return 0 if k == ast.ASTKind.Subscript: sub_s: ast.Subscript* = ast.Subscript*(node) @@ -367,8 +340,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if ve_s is not None: scn_s: str = self.Gen.VarGen.var_annot_class_name(ve_s) if scn_s is not None: - if self._spec_sign_from_annot(scn_s) == TSpec.TS_SIGN_SIGNED: - return 1 + if self._spec_sign_from_annot(scn_s) == TSpec.TS_SIGN_SIGNED: return 1 return 0 return 0 # ============================================================ @@ -404,10 +376,8 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # ============================================================ def _entry_spec_unsigned(self, sp: TSpec.TypeSpec*) -> int: """Spec 是否明确无符号整数(TS_UINT);其它一律 0(未表态/不适用)""" - if sp is None: - return 0 - if sp.Kind == TSpec.TS_UINT: - return 1 + if sp is None: return 0 + if sp.Kind == TSpec.TS_UINT: return 1 return 0 def _type_name_unsigned(self, type_name: str) -> int: """[S4] 类型名无符号判定:**真源唯一**(旧字符串兜底已删) @@ -415,8 +385,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): 真源 UNKNOWN = 不表态 ⇒ 返回 0(非无符号),保持编译器默认的 zext/sext 取向。 """ if type_name is not None: - if self._spec_sign_from_annot(type_name) == TSpec.TS_SIGN_UNSIGNED: - return 1 + if self._spec_sign_from_annot(type_name) == TSpec.TS_SIGN_UNSIGNED: return 1 return 0 def _annot_str_unsigned(self, annot: str) -> int: """[S4] 注解串无符号判定:**真源唯一**(旧子串扫描已删) @@ -427,8 +396,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): 且无子串假阳性。UNKNOWN = 不表态 ⇒ 返回 0。 """ if annot is not None: - if self._spec_sign_from_annot(annot) == TSpec.TS_SIGN_UNSIGNED: - return 1 + if self._spec_sign_from_annot(annot) == TSpec.TS_SIGN_UNSIGNED: return 1 return 0 def translate_compare(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, @@ -437,21 +405,17 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): trans: HT.Translator* = None) -> mlirlite.Value*: """翻译比较表达式,返回 i1 结果""" cmp: rawptr[ast.Compare] = rawptr[ast.Compare](node) - if cmp is None: - return None + if cmp is None: return None ops_list: list[int]* = (list[int]*)(cmp.ops) - if ops_list is None or len(ops_list) == 0: - return None + if ops_list is None or len(ops_list) == 0: return None op: int = ops_list.get(0) comparators: list[ast.AST*]* = cmp.comparators - if comparators is None or len(comparators) == 0: - return None + if comparators is None or len(comparators) == 0: return None rhs_node: ast.AST* = comparators.get(0) rhs: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, rhs_node, None, 0, trans) - if rhs is None: - return None + if rhs is None: return None # === None 比较优化: x == None / x != None 走身份比较(icmp eq/ne null)=== # 避免对结构体指针生成无效的 __eq__/__ne__ 调用(方法未定义但类有 SHA1 时 @@ -462,12 +426,10 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if op == ast.OpKind.Eq or op == ast.OpKind.Ne or op == ast.OpKind.Is or op == ast.OpKind.IsNot: if rhs_node is not None and rhs_node.kind() == ast.ASTKind.Constant: rhs_cn: ast.Constant* = ast.Constant*(rhs_node) - if rhs_cn is not None and rhs_cn.const_kind == ast.CONST_NONE: - cmp_with_none = 1 + if rhs_cn is not None and rhs_cn.const_kind == ast.CONST_NONE: cmp_with_none = 1 if cmp_with_none == 0 and lhs_node is not None and lhs_node.kind() == ast.ASTKind.Constant: lhs_cn: ast.Constant* = ast.Constant*(lhs_node) - if lhs_cn is not None and lhs_cn.const_kind == ast.CONST_NONE: - cmp_with_none = 1 + if lhs_cn is not None and lhs_cn.const_kind == ast.CONST_NONE: cmp_with_none = 1 # === 指针判空模式: ptr != 0 / ptr == 0 === # 跳过运算符重载走身份比较(icmp null)。跨模块类(如 cpython.PyObject) @@ -477,10 +439,8 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # `py_num != 0` 根因)。C 语义:指针与字面量 0 比较 = 判空。 cmp_zero: int = 0 if op == ast.OpKind.Eq or op == ast.OpKind.Ne: - if rhs_node is not None and self._is_zero_int_literal(rhs_node) != 0: - cmp_zero = 1 - if cmp_zero == 0 and lhs_node is not None and self._is_zero_int_literal(lhs_node) != 0: - cmp_zero = 1 + if rhs_node is not None and self._is_zero_int_literal(rhs_node) != 0: cmp_zero = 1 + if cmp_zero == 0 and lhs_node is not None and self._is_zero_int_literal(lhs_node) != 0: cmp_zero = 1 # === 比较运算符重载路径 1: lhs 是 Name 且对应结构体变量 === # 对于值类型变量(如 cnt: Counter),用 alloca 指针尝试重载 @@ -496,16 +456,13 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # (与 translate_binop 路径 1 一致,避免槽地址当对象地址) if lhs_alloca.Ty is not None and lhs_alloca.Ty.Pointee != 0 and self.Gen.ExprGenBase.is_ptr_type(lhs_alloca.Ty.Pointee) != 0: load_self1: mlirlite.Value* = mlirlite.build_load(builder, lhs_alloca.Ty.Pointee, lhs_alloca) - if load_self1 is not None: - ovl_self1 = load_self1 + if load_self1 is not None: ovl_self1 = load_self1 ovl_result: mlirlite.Value* = self.try_operator_overload(pool, builder, mod, ovl_self1, rhs, op, trans, 1) - if ovl_result is not None: - return ovl_result + if ovl_result is not None: return ovl_result # 正常翻译 lhs lhs: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cmp.left, None, 0, trans) - if lhs is None: - return None + if lhs is None: return None # === in / not in:容器右操作数调用 __contains__(对齐 TPC # HandlesExprOps.py L261-281)。x in y → y.__contains__(x); @@ -529,8 +486,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): cn_first: mlirlite.Param* = mlirlite.function_get_param_head(cn_fn) if cn_first is not None: cn_self_ty: mlirlite.LLVMType* = mlirlite.param_get_ty(cn_first) - if cn_self_ty is not None: - cn_self = mlirlite.build_bitcast(builder, rhs, cn_self_ty) + if cn_self_ty is not None: cn_self = mlirlite.build_bitcast(builder, rhs, cn_self_ty) if cn_self is not None: # 参数链表: self → key(独立 null 结尾) cn_self.Next = lhs @@ -543,22 +499,18 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): case mlirlite.LLVMType.Int(cn_bits): if cn_bits > 1: cn_zero: mlirlite.Value* = mlirlite.ConstInt(pool, cn_ret, 0, "0") - if cn_zero is not None: - cn_i1 = mlirlite.build_icmp(builder, mlirlite.ICMP_NE, cn_res, cn_zero) + if cn_zero is not None: cn_i1 = mlirlite.build_icmp(builder, mlirlite.ICMP_NE, cn_res, cn_zero) case _: pass if op == ast.OpKind.NotIn: i1_ty_ni: mlirlite.LLVMType* = mlirlite.Int1(pool) if i1_ty_ni is not None and cn_i1 is not None: one_i1_ni: mlirlite.Value* = mlirlite.ConstInt(pool, i1_ty_ni, 1, "1") - if one_i1_ni is not None: - cn_i1 = mlirlite.build_xor(builder, cn_i1, one_i1_ni) - if cn_i1 is not None: - return cn_i1 + if one_i1_ni is not None: cn_i1 = mlirlite.build_xor(builder, cn_i1, one_i1_ni) + if cn_i1 is not None: return cn_i1 # 容器无 __contains__:TPC 语义恒 False(i1 0) i1_ty_in: mlirlite.LLVMType* = mlirlite.Int1(pool) - if i1_ty_in is not None: - return mlirlite.ConstInt(pool, i1_ty_in, 0, "0") + if i1_ty_in is not None: return mlirlite.ConstInt(pool, i1_ty_in, 0, "0") return None # === 比较运算符重载路径 2: lhs 是 Ptr(Struct) === @@ -566,8 +518,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # None 比较跳过重载(走身份比较);指针判空(cmp_zero + 指针)同样跳过 if cmp_with_none == 0 and (cmp_zero == 0 or self.get_ptr_level(lhs.Ty) == 0): ovl_result2: mlirlite.Value* = self.try_operator_overload(pool, builder, mod, lhs, rhs, op, trans, 1) - if ovl_result2 is not None: - return ovl_result2 + if ovl_result2 is not None: return ovl_result2 # === 无符号比较(A5):操作数为无符号整数类型(CUInt64T/CUInt32T 等)时 # 用 ULT/ULE/UGT/UGE。此前固定有符号 predicate → uint64 地址比较在 @@ -576,25 +527,17 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # (Name→变量 AnnotClassName / Call→转换目标 / Attribute→类型名 / 递归)。 unsigned_l: int = 0 unsigned_r: int = 0 - if lhs_node is not None: - unsigned_l = self._node_type_unsigned(pool, lhs_node, trans) - if rhs_node is not None: - unsigned_r = self._node_type_unsigned(pool, rhs_node, trans) + if lhs_node is not None: unsigned_l = self._node_type_unsigned(pool, lhs_node, trans) + if rhs_node is not None: unsigned_r = self._node_type_unsigned(pool, rhs_node, trans) cmp_unsigned: int = 1 if (unsigned_l != 0 or unsigned_r != 0) else 0 predicate: int = mlirlite.ICMP_SLT - if op == ast.OpKind.Lt: - predicate = mlirlite.ICMP_ULT if cmp_unsigned != 0 else mlirlite.ICMP_SLT - elif op == ast.OpKind.Le: - predicate = mlirlite.ICMP_ULE if cmp_unsigned != 0 else mlirlite.ICMP_SLE - elif op == ast.OpKind.Gt: - predicate = mlirlite.ICMP_UGT if cmp_unsigned != 0 else mlirlite.ICMP_SGT - elif op == ast.OpKind.Ge: - predicate = mlirlite.ICMP_UGE if cmp_unsigned != 0 else mlirlite.ICMP_SGE - elif op == ast.OpKind.Eq: - predicate = mlirlite.ICMP_EQ - elif op == ast.OpKind.Ne: - predicate = mlirlite.ICMP_NE + if op == ast.OpKind.Lt: predicate = mlirlite.ICMP_ULT if cmp_unsigned != 0 else mlirlite.ICMP_SLT + elif op == ast.OpKind.Le: predicate = mlirlite.ICMP_ULE if cmp_unsigned != 0 else mlirlite.ICMP_SLE + elif op == ast.OpKind.Gt: predicate = mlirlite.ICMP_UGT if cmp_unsigned != 0 else mlirlite.ICMP_SGT + elif op == ast.OpKind.Ge: predicate = mlirlite.ICMP_UGE if cmp_unsigned != 0 else mlirlite.ICMP_SGE + elif op == ast.OpKind.Eq: predicate = mlirlite.ICMP_EQ + elif op == ast.OpKind.Ne: predicate = mlirlite.ICMP_NE elif op == ast.OpKind.Is: # `x is y` → 指针/值相等比较 predicate = mlirlite.ICMP_EQ @@ -612,23 +555,17 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # 不报类型不匹配(ClassArrayTest 的 if ptr != 0 等常见模式)。 zero_is_rhs: int = 0 zero_is_lhs: int = 0 - if rhs_ptr_level == 0 and self._is_zero_int_literal(rhs_node) != 0: - zero_is_rhs = 1 - if lhs_ptr_level == 0 and self._is_zero_int_literal(lhs_node) != 0: - zero_is_lhs = 1 + if rhs_ptr_level == 0 and self._is_zero_int_literal(rhs_node) != 0: zero_is_rhs = 1 + if lhs_ptr_level == 0 and self._is_zero_int_literal(lhs_node) != 0: zero_is_lhs = 1 if zero_is_rhs != 0 or zero_is_lhs != 0: - if zero_is_rhs != 0: - rhs = mlirlite.ConstNull(pool, lhs.Ty, "null") - else: - lhs = mlirlite.ConstNull(pool, rhs.Ty, "null") + if zero_is_rhs != 0: rhs = mlirlite.ConstNull(pool, lhs.Ty, "null") + else: lhs = mlirlite.ConstNull(pool, rhs.Ty, "null") else: # 指针 vs 非零整数(C 哨兵值模式,如 w32.win32base.INVALID_HANDLE_VALUE = -1): # 对齐 TPC HandlesExprOps.py L388-398 —— 指针 ptrtoint 成整数做地址值比较。 # (指针 vs 整数字面量 0 已在上方转 null 处理;此处处理非零整数哨兵) - if lhs_ptr_level != 0 and rhs_ptr_level == 0: - lhs = mlirlite.build_ptrtoint(builder, lhs, rhs.Ty) - elif rhs_ptr_level != 0 and lhs_ptr_level == 0: - rhs = mlirlite.build_ptrtoint(builder, rhs, lhs.Ty) + if lhs_ptr_level != 0 and rhs_ptr_level == 0: lhs = mlirlite.build_ptrtoint(builder, lhs, rhs.Ty) + elif rhs_ptr_level != 0 and lhs_ptr_level == 0: rhs = mlirlite.build_ptrtoint(builder, rhs, lhs.Ty) else: # 不同级指针(1 vs 2 等)→ 禁止(fast-fail) self.Gen.TypeGenErr.fatal_error(cmp, f"比较类型不匹配: 不同级指针比较 (lhs 层级={lhs_ptr_level}, rhs 层级={rhs_ptr_level})", "TypeError") @@ -641,8 +578,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): lhs_is_none_lit: int = 0 if lhs_node is not None and lhs_node.kind() == ast.ASTKind.Constant: lhs_none_cn: ast.Constant* = ast.Constant*(lhs_node) - if lhs_none_cn is not None and lhs_none_cn.const_kind == ast.CONST_NONE: - lhs_is_none_lit = 1 + if lhs_none_cn is not None and lhs_none_cn.const_kind == ast.CONST_NONE: lhs_is_none_lit = 1 lhs_ptr_level_none: int = self.get_ptr_level(lhs.Ty) rhs_ptr_level_none: int = self.get_ptr_level(rhs.Ty) if lhs_is_none_lit != 0: @@ -655,8 +591,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): case _: rhs_is_struct_none = 0 if rhs_is_struct_none != 0: - if op == ast.OpKind.Eq or op == ast.OpKind.Is: - return mlirlite.const_int(pool, 1, 0) + if op == ast.OpKind.Eq or op == ast.OpKind.Is: return mlirlite.const_int(pool, 1, 0) return mlirlite.const_int(pool, 1, 1) # 右值是数值 → 把 None 侧转为整数 0(保持 rhs 不变) lhs = mlirlite.const_int32(pool, 0) @@ -672,8 +607,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): lhs_is_struct_none = 0 if lhs_is_struct_none != 0: # 结构体值永远不等于 None:==/is 返回 false,!=/is not 返回 true - if op == ast.OpKind.Eq or op == ast.OpKind.Is: - return mlirlite.const_int(pool, 1, 0) + if op == ast.OpKind.Eq or op == ast.OpKind.Is: return mlirlite.const_int(pool, 1, 0) else: # Ne, IsNot return mlirlite.const_int(pool, 1, 1) # lhs 是数值, rhs 是 i8* null → 将 rhs 转为数值 0(保持 lhs 不变) @@ -686,15 +620,11 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): rhs_bits: int = self.get_llvm_type_bits(rhs.Ty) if lhs_bits != 0 and rhs_bits != 0 and lhs_bits != rhs_bits: if lhs_bits < rhs_bits: - if self.should_zext_widen(pool, lhs, rhs, cmp.left, trans) != 0: - lhs = mlirlite.build_zext(builder, lhs, rhs.Ty) - else: - lhs = mlirlite.build_sext(builder, lhs, rhs.Ty) + if self.should_zext_widen(pool, lhs, rhs, cmp.left, trans) != 0: lhs = mlirlite.build_zext(builder, lhs, rhs.Ty) + else: lhs = mlirlite.build_sext(builder, lhs, rhs.Ty) else: - if self.should_zext_widen(pool, rhs, lhs, rhs_node, trans) != 0: - rhs = mlirlite.build_zext(builder, rhs, lhs.Ty) - else: - rhs = mlirlite.build_sext(builder, rhs, lhs.Ty) + if self.should_zext_widen(pool, rhs, lhs, rhs_node, trans) != 0: rhs = mlirlite.build_zext(builder, rhs, lhs.Ty) + else: rhs = mlirlite.build_sext(builder, rhs, lhs.Ty) # 指针类型对齐:同层级但不同 pointee 类型的指针需要 bitcast 统一类型 # 例如 i8* vs Struct* → 将 rhs bitcast 为 lhs 的类型 @@ -708,8 +638,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if lhs_ty_buf is not None and rhs_ty_buf is not None: mlirlite.TypePrint(lhs_ty_buf, 512, lhs.Ty, pool) mlirlite.TypePrint(rhs_ty_buf, 512, rhs.Ty, pool) - if string.strcmp(lhs_ty_buf, rhs_ty_buf) != 0: - rhs = mlirlite.build_bitcast(builder, rhs, lhs.Ty) + if string.strcmp(lhs_ty_buf, rhs_ty_buf) != 0: rhs = mlirlite.build_bitcast(builder, rhs, lhs.Ty) # 浮点比较:任一操作数为浮点类型时使用 fcmp 而非 icmp lhs_fbits: int = self.get_llvm_float_bits(lhs.Ty) @@ -717,29 +646,20 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if lhs_fbits != 0 or rhs_fbits != 0: # 浮点类型对齐(fpext/fptrunc) if lhs_fbits != 0 and rhs_fbits != 0 and lhs_fbits != rhs_fbits: - if lhs_fbits < rhs_fbits: - lhs = mlirlite.build_fpext(builder, lhs, rhs.Ty) - else: - rhs = mlirlite.build_fptrunc(builder, rhs, lhs.Ty) + if lhs_fbits < rhs_fbits: lhs = mlirlite.build_fpext(builder, lhs, rhs.Ty) + else: rhs = mlirlite.build_fptrunc(builder, rhs, lhs.Ty) elif lhs_fbits != 0 and rhs_fbits == 0: # int → float rhs = mlirlite.build_si2fp(builder, rhs, lhs.Ty) - elif rhs_fbits != 0 and lhs_fbits == 0: - lhs = mlirlite.build_si2fp(builder, lhs, rhs.Ty) + elif rhs_fbits != 0 and lhs_fbits == 0: lhs = mlirlite.build_si2fp(builder, lhs, rhs.Ty) # 映射比较谓词到 fcmp fpredicate: int = mlirlite.FCMP_OEQ - if op == ast.OpKind.Eq or op == ast.OpKind.Is: - fpredicate = mlirlite.FCMP_OEQ - elif op == ast.OpKind.Ne or op == ast.OpKind.IsNot: - fpredicate = mlirlite.FCMP_ONE - elif op == ast.OpKind.Lt: - fpredicate = mlirlite.FCMP_OLT - elif op == ast.OpKind.Le: - fpredicate = mlirlite.FCMP_OLE - elif op == ast.OpKind.Gt: - fpredicate = mlirlite.FCMP_OGT - elif op == ast.OpKind.Ge: - fpredicate = mlirlite.FCMP_OGE + if op == ast.OpKind.Eq or op == ast.OpKind.Is: fpredicate = mlirlite.FCMP_OEQ + elif op == ast.OpKind.Ne or op == ast.OpKind.IsNot: fpredicate = mlirlite.FCMP_ONE + elif op == ast.OpKind.Lt: fpredicate = mlirlite.FCMP_OLT + elif op == ast.OpKind.Le: fpredicate = mlirlite.FCMP_OLE + elif op == ast.OpKind.Gt: fpredicate = mlirlite.FCMP_OGT + elif op == ast.OpKind.Ge: fpredicate = mlirlite.FCMP_OGE return mlirlite.build_fcmp(builder, fpredicate, lhs, rhs) return mlirlite.build_icmp(builder, predicate, lhs, rhs) @@ -768,13 +688,11 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # -x # 浮点类型用 fneg(直接生成 fneg 指令,避免 0.0 - x 的类型不匹配) operand_fbits: int = self.get_llvm_float_bits(operand.Ty) - if operand_fbits > 0: - return mlirlite.build_fneg(builder, operand) + if operand_fbits > 0: return mlirlite.build_fneg(builder, operand) # 整数类型:-x = 0 - x,根据位宽选择零值常量(避免 i32 与 i64 类型不匹配) operand_bits: int = self.get_llvm_type_bits(operand.Ty) zero: mlirlite.Value* = mlirlite.const_int32(pool, 0) - if operand_bits == 64: - zero = mlirlite.const_int64(pool, 0) + if operand_bits == 64: zero = mlirlite.const_int64(pool, 0) elif operand_bits > 0 and operand_bits != 32: # 其他位宽(i8/i16 等):用 i32 零值,operand 会被 coerce zero = mlirlite.const_int32(pool, 0) @@ -785,31 +703,27 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): elif uo.op == ast.OpKind.Not: # not x = (bool(x) == 0),返回 i1;优先调度 __bool__ not_cond: mlirlite.Value* = self.coerce_cond_to_bool(pool, builder, mod, operand, trans) - if not_cond is None: - return None + if not_cond is None: return None false_val: mlirlite.Value* = mlirlite.const_int(pool, 1, 0) return mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, not_cond, false_val) elif uo.op == ast.OpKind.Invert: # ~x = x ^ -1 operand_bits_inv: int = self.get_llvm_type_bits(operand.Ty) neg1: mlirlite.Value* = mlirlite.const_int32(pool, -1) - if operand_bits_inv == 64: - neg1 = mlirlite.const_int64(pool, -1) + if operand_bits_inv == 64: neg1 = mlirlite.const_int64(pool, -1) return mlirlite.build_xor(builder, operand, neg1) elif uo.op == ast.OpKind.Deref: # *p → load 按 pointee 类型读取(对齐 translate_c_deref) if self.Gen.ExprGenBase.is_ptr_type(operand.Ty) != 0: d_pointee: mlirlite.LLVMType* = operand.Ty.Pointee - if d_pointee is not None: - return mlirlite.build_load(builder, d_pointee, operand) + if d_pointee is not None: return mlirlite.build_load(builder, d_pointee, operand) # 非指针即类型推断退化:fail-fast,绝不按 i8 兜底读取 self.Gen.TypeGenErr.fatal_error(node, "单目 '*' 解引用的操作数必须是指针类型(类型推断退化)", "TypeError") return None elif uo.op == ast.OpKind.AddrOf: # &x → 左值地址(不 load):Name 变量 alloca / 模块全局 / 模块函数 / # Attribute 字段 GEP / Subscript 元素地址(对齐 translate_c_addr 语义) - if trans is None: - return None + if trans is None: return None if uo.operand.kind() == ast.ASTKind.Name: nm_ao: ast.Name* = ast.Name*(uo.operand) if nm_ao.id is not None: @@ -832,8 +746,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if v_ao is None and mod is not None: # 模块全局变量:经 make_global_ref 转成带引号的 Ptr(Ty) 引用 gv_ao: mlirlite.GlobalVariable* = self.Gen.ExprGenAttr.find_global_in_module(mod, nm_ao.id) - if gv_ao is not None and gv_ao.Name is not None and gv_ao.Ty is not None: - v_ao = self.Gen.ExprGenAttr.make_global_ref(pool, gv_ao.Name, gv_ao.Ty) + if gv_ao is not None and gv_ao.Name is not None and gv_ao.Ty is not None: v_ao = self.Gen.ExprGenAttr.make_global_ref(pool, gv_ao.Name, gv_ao.Ty) if v_ao is not None and v_ao.Ty is not None: # 对象指针变量(alloca 是 Ptr(Ptr(Struct)),存对象指针): # 变量语义即对象,返回对象指针(load 一次),对齐 translate_c_addr @@ -866,27 +779,22 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): needs_q_ao: int = self.Gen.ClassGenVTable._vtable_name_needs_quote(fname_ao) fbuf_ao: str = pool.alloc(fnlen_ao + 4) if fbuf_ao is not None and fn_ty_ao is not None: - if needs_q_ao != 0: - viperlib.snprintf(fbuf_ao, fnlen_ao + 4, "@\"%s\"", fname_ao) - else: - viperlib.snprintf(fbuf_ao, fnlen_ao + 4, "@%s", fname_ao) + if needs_q_ao != 0: viperlib.snprintf(fbuf_ao, fnlen_ao + 4, "@\"%s\"", fname_ao) + else: viperlib.snprintf(fbuf_ao, fnlen_ao + 4, "@%s", fname_ao) return mlirlite.SSAValue(pool, mlirlite.Ptr(pool, fn_ty_ao), fbuf_ao) elif uo.operand.kind() == ast.ASTKind.Attribute: # 字段地址(GEP,不 load) fptr_ao: mlirlite.Value* = self.Gen.ExprGenAttr.get_attribute_ptr(builder, pool, mod, uo.operand, trans) - if fptr_ao is not None: - return fptr_ao + if fptr_ao is not None: return fptr_ao elif uo.operand.kind() == ast.ASTKind.Subscript: # 元素地址(GEP,不 load) sptr_ao: mlirlite.Value* = self.Gen.ExprGenName.get_subscript_ptr(builder, pool, mod, uo.operand, trans) - if sptr_ao is not None: - return sptr_ao + if sptr_ao is not None: return sptr_ao elif uo.operand.kind() == ast.ASTKind.Call: # &() → rvalue 取址。复用上面已求值的 operand(绝不能二次求值: # 构造调用会再跑一遍 __before_init__/__init__)。判定见 _addrof_of_call。 ac_ao: mlirlite.Value* = self._addrof_of_call(builder, pool, operand) - if ac_ao is not None: - return ac_ao + if ac_ao is not None: return ac_ao self.Gen.TypeGenErr.fatal_error(node, "单目 '&' 取地址的操作数必须是左值(Name/Attribute/Subscript)或构造调用/函数调用结果", "TypeError") return None return operand @@ -906,8 +814,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): 承载——入口 alloca 同类型槽 → store → 返回槽地址(与 &expr 的 Call 形式同口径,见 CallGenCBuiltin.translate_c_addr)。 """ - if call_val is None or call_val.Ty is None: - return None + if call_val is None or call_val.Ty is None: return None if self.Gen.ExprGenBase.is_ptr_type(call_val.Ty) != 0 and call_val.Ty.Pointee is not None: pointee_is_struct: int = 0 match call_val.Ty.Pointee: @@ -915,11 +822,9 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): pointee_is_struct = 1 case _: pointee_is_struct = 0 - if pointee_is_struct != 0: - return call_val + if pointee_is_struct != 0: return call_val tmp_slot_ao: mlirlite.Value* = mlirlite.build_alloca_at_entry(builder, call_val.Ty) - if tmp_slot_ao is None: - return None + if tmp_slot_ao is None: return None mlirlite.build_store(builder, call_val, tmp_slot_ao) return tmp_slot_ao # ============================================================ @@ -940,31 +845,26 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): trans: HT.Translator* = None) -> mlirlite.Value*: """翻译布尔运算(and/or)的短路求值,返回 i1""" bo: rawptr[ast.BoolOp] = rawptr[ast.BoolOp](node) - if bo is None: - return None + if bo is None: return None op: int = bo.op values: list[ast.AST*]* = bo.values - if values is None: - return None + if values is None: return None count: sizet = len(values) - if count == 0: - return None + if count == 0: return None if count == 1: return self.Gen.ExprGen.translate_value(builder, pool, mod, values.get(0), funcs_ptr, func_count, trans) func: mlirlite.Function* = builder.Func - if func is None: - return None + if func is None: return None # 创建 merge BB(用 builder.Counter 生成唯一标签名,position_at_end 的 # move_to_end 保证 BB 文本顺序与控制流顺序一致,标签名用 counter 安全) cnt: int = builder.Counter builder.Counter = cnt + 1 name_buf: str = pool.alloc(32) - if name_buf is None: - return None + if name_buf is None: return None viperlib.snprintf(name_buf, 32, "bool.merge.%d", cnt) merge_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf) @@ -977,8 +877,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): for i in range(count - 1): val_node: ast.AST* = values.get(i) val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, val_node, funcs_ptr, func_count, trans) - if val is None: - return None + if val is None: return None # 转为 i1(已是 i1 直接使用;否则走 coerce_cond_to_bool:优先 __bool__) val_i1: mlirlite.Value* = self.coerce_cond_to_bool(pool, builder, mod, val, trans) @@ -990,10 +889,8 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): next_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf) # and: 短路假→merge,真→next;or: 短路真→merge,假→next - if op == ast.OpKind.And: - mlirlite.build_cond_br(builder, val_i1, next_bb, merge_bb) - else: - mlirlite.build_cond_br(builder, val_i1, merge_bb, next_bb) + if op == ast.OpKind.And: mlirlite.build_cond_br(builder, val_i1, next_bb, merge_bb) + else: mlirlite.build_cond_br(builder, val_i1, merge_bb, next_bb) # 添加 phi 入边:(val_i1, cond_br 所在 BB) cur_bb: rawptr[mlirlite.BasicBlock] = builder.CurBlock @@ -1011,18 +908,15 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # 最后一个值:求值后直接跳 merge last_node: ast.AST* = values.get(count - 1) last_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, last_node, funcs_ptr, func_count, trans) - if last_val is None: - return None + if last_val is None: return None last_i1: mlirlite.Value* = self.coerce_cond_to_bool(pool, builder, mod, last_val, trans) mlirlite.build_br(builder, merge_bb) cur_bb = builder.CurBlock inc = mlirlite.new_phi_incoming(pool, last_i1, cur_bb) - if phi_head is None: - phi_head = inc - else: - phi_tail.Next = inc + if phi_head is None: phi_head = inc + else: phi_tail.Next = inc phi_count += 1 # 定位到 merge,创建 phi 合并所有入边 @@ -1046,16 +940,14 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): node: ast.AST* = None, trans: HT.Translator* = None) -> mlirlite.Value*: """翻译 `**` 幂运算(基础类型走 llvm.pow)""" - if lhs is None or rhs is None: - return None + if lhs is None or rhs is None: return None lhs_fbits: int = self.get_llvm_float_bits(lhs.Ty) rhs_fbits: int = self.get_llvm_float_bits(rhs.Ty) f64_ty: mlirlite.LLVMType* = mlirlite.Double(pool) # 浮点路径:任一操作数为浮点 → 结果浮点 if lhs_fbits != 0 or rhs_fbits != 0: target_f: mlirlite.LLVMType* = f64_ty - if lhs_fbits == 32 and rhs_fbits == 32: - target_f = mlirlite.Float(pool) + if lhs_fbits == 32 and rhs_fbits == 32: target_f = mlirlite.Float(pool) lf: mlirlite.Value* = self.coerce_to_type(builder, lhs, target_f, node, trans) rf: mlirlite.Value* = self.coerce_to_type(builder, rhs, target_f, node, trans) return self._call_llvm_pow(pool, builder, mod, lf, rf) @@ -1063,12 +955,10 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): li: mlirlite.Value* = self.coerce_to_type(builder, lhs, f64_ty, node, trans) ri: mlirlite.Value* = self.coerce_to_type(builder, rhs, f64_ty, node, trans) res: mlirlite.Value* = self._call_llvm_pow(pool, builder, mod, li, ri) - if res is None: - return None + if res is None: return None # 指数为非负整数常量 → fptosi 回写为左操作数类型(Python int ** int = int) rhs_bits: int = self.get_llvm_type_bits(rhs.Ty) - if rhs_bits != 0 and rhs.IsConst == 1 and rhs.IntVal >= 0: - return self.coerce_to_type(builder, res, lhs.Ty, node, trans) + if rhs_bits != 0 and rhs.IsConst == 1 and rhs.IntVal >= 0: return self.coerce_to_type(builder, res, lhs.Ty, node, trans) return res def _call_llvm_pow(self, pool: memhub.MemBuddy*, @@ -1077,8 +967,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): lf: mlirlite.Value*, rf: mlirlite.Value*) -> mlirlite.Value*: """调用 llvm.pow.f64 内联函数;f32 结果再截断回 float""" - if lf is None or rf is None: - return None + if lf is None or rf is None: return None f64_ty: mlirlite.LLVMType* = mlirlite.Double(pool) pow_fn: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, "llvm.pow.f64") if pow_fn is None: @@ -1087,21 +976,16 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): mlirlite.add_param(pool, pow_fn, f64_ty, "x") mlirlite.add_param(pool, pow_fn, f64_ty, "y") lf_d: mlirlite.Value* = lf - if self.get_llvm_float_bits(lf.Ty) != 64: - lf_d = mlirlite.build_fpext(builder, lf, f64_ty) + if self.get_llvm_float_bits(lf.Ty) != 64: lf_d = mlirlite.build_fpext(builder, lf, f64_ty) rf_d: mlirlite.Value* = rf - if self.get_llvm_float_bits(rf.Ty) != 64: - rf_d = mlirlite.build_fpext(builder, rf, f64_ty) - if lf_d is None or rf_d is None: - return None + if self.get_llvm_float_bits(rf.Ty) != 64: rf_d = mlirlite.build_fpext(builder, rf, f64_ty) + if lf_d is None or rf_d is None: return None lf_d.Next = rf_d rf_d.Next = None res: mlirlite.Value* = mlirlite.build_call(builder, "llvm.pow.f64", lf_d, 2, f64_ty, 0) - if res is None: - return None + if res is None: return None # f32 目标:llvm.pow 恒为 f64,结果截断回 float - if self.get_llvm_float_bits(lf.Ty) == 32 and self.get_llvm_float_bits(rf.Ty) == 32: - res = mlirlite.build_fptrunc(builder, res, mlirlite.Float(pool)) + if self.get_llvm_float_bits(lf.Ty) == 32 and self.get_llvm_float_bits(rf.Ty) == 32: res = mlirlite.build_fptrunc(builder, res, mlirlite.Float(pool)) return res # ============================================================ @@ -1183,31 +1067,24 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): trans: HT.Translator*, is_compare: int) -> mlirlite.Value*: """尝试运算符重载:lhs 是结构体指针时调用 dunder 方法,否则返回 None""" - if lhs is None or rhs is None: - return None + if lhs is None or rhs is None: return None # 映射运算符到 dunder 方法名 dunder: str = None - if is_compare != 0: - dunder = self._cmpop_to_dunder(op) - else: - dunder = self._binop_to_dunder(op) - if dunder is None: - return None + if is_compare != 0: dunder = self._cmpop_to_dunder(op) + else: dunder = self._binop_to_dunder(op) + if dunder is None: return None # 检查 lhs 是否为结构体指针 struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(lhs) - if struct_ty is None: - return None + if struct_ty is None: return None # 获取类名 class_name: str = self.Gen.StructGen.get_class_name_by_type(pool, struct_ty) - if class_name is None: - return None + if class_name is None: return None # 在继承链中查找 dunder 方法 lookup_name: str = pool.alloc(128) - if lookup_name is None: - return None + if lookup_name is None: return None viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, dunder) found_func: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, lookup_name) @@ -1233,17 +1110,14 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # 优先用类型指针定位 entry 获取 SHA1(规避跨模块同名 find_struct 找错) cls_sha1: str = None op_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_type(struct_ty) - if op_entry is not None: - cls_sha1 = op_entry.ModuleSha1 - if cls_sha1 is None: - cls_sha1 = self.Gen.StructGen.get_struct_sha1(search_class) + if op_entry is not None: cls_sha1 = op_entry.ModuleSha1 + if cls_sha1 is None: cls_sha1 = self.Gen.StructGen.get_struct_sha1(search_class) if cls_sha1 is None: mro_p: sizet* = self.Gen.StructGen.get_mro_chain(pool, search_class) mj: int = 1 while mro_p is not None and mro_p[mj] != 0 and cls_sha1 is None: anc_p: str = rawptr(mro_p[mj]) - if anc_p is not None: - cls_sha1 = self.Gen.StructGen.get_struct_sha1(anc_p) + if anc_p is not None: cls_sha1 = self.Gen.StructGen.get_struct_sha1(anc_p) mj += 1 # 既无函数定义也无 SHA1 → 该类没有此 dunder 方法,返回 None 回退原生运算 @@ -1283,11 +1157,9 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): op: int, trans: HT.Translator*) -> mlirlite.Value*: """尝试一元运算符重载:operand 是结构体指针时调用 dunder 方法,否则返回 None""" - if operand is None: - return None + if operand is None: return None dunder: str = self._unaryop_to_dunder(op) - if dunder is None: - return None + if dunder is None: return None return self._try_named_dunder(pool, builder, mod, operand, dunder, trans) def _resolve_dunder_by_class(self, pool: memhub.MemBuddy*, @@ -1302,13 +1174,11 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): None。可选 struct_ty:提供时从其类型 entry 直接取 SHA1(跨模块类更可靠)。 跨模块类以依赖模块 vpi stub 为准,避免发出幽灵 call(链接 undefined)。 """ - if class_name is None or dunder is None: - return None + if class_name is None or dunder is None: return None # 在继承链中查找 dunder 方法 lookup_name: str = pool.alloc(128) - if lookup_name is None: - return None + if lookup_name is None: return None viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, dunder) found_func: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, lookup_name) @@ -1334,34 +1204,28 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): cls_sha1: str = None if struct_ty is not None: uop_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_type(struct_ty) - if uop_entry is not None: - cls_sha1 = uop_entry.ModuleSha1 - if cls_sha1 is None: - cls_sha1 = self.Gen.StructGen.get_struct_sha1(search_class) + if uop_entry is not None: cls_sha1 = uop_entry.ModuleSha1 + if cls_sha1 is None: cls_sha1 = self.Gen.StructGen.get_struct_sha1(search_class) if cls_sha1 is None: mro_p: sizet* = self.Gen.StructGen.get_mro_chain(pool, search_class) mj: int = 1 while mro_p is not None and mro_p[mj] != 0 and cls_sha1 is None: anc_p: str = rawptr(mro_p[mj]) - if anc_p is not None: - cls_sha1 = self.Gen.StructGen.get_struct_sha1(anc_p) + if anc_p is not None: cls_sha1 = self.Gen.StructGen.get_struct_sha1(anc_p) mj += 1 # 既无函数定义也无 SHA1 → 该类没有此 dunder 方法 - if found_func is None and cls_sha1 is None: - return None + if found_func is None and cls_sha1 is None: return None # 同模块类但模块内无此 dunder → 返回 None 回退原生运算,不发幽灵 call # (与 try_operator_overload 一致,防 IR 残留 call void @...__neg__) if found_func is None and trans is not None and trans.ModuleSha1 is not None: - if cls_sha1 is not None and string.strcmp(cls_sha1, trans.ModuleSha1) == 0: - return None + if cls_sha1 is not None and string.strcmp(cls_sha1, trans.ModuleSha1) == 0: return None # 跨模块类:stub 可能未注入,方法存在性以依赖模块 vpi stub 为准。 # vpi 未命中 → 回退(不发幽灵 call,避免链接 undefined) if cls_sha1 is not None: vpi_dup: mlirlite.LLVMType* = self.Gen.CallGenBase._lookup_method_ret_ty_via_vpi(pool, cls_sha1, search_class, dunder) - if vpi_dup is None: - return None + if vpi_dup is None: return None return search_class def _try_named_dunder(self, pool: memhub.MemBuddy*, @@ -1378,22 +1242,18 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): 对象 __call__ 共用此查找/发射逻辑。extra_args/extra_count:附加实参 (__call__ 传入调用实参;一元/__bool__ 为空)。找不到方法返回 None。 """ - if operand is None or dunder is None: - return None + if operand is None or dunder is None: return None # 检查 operand 是否为结构体指针 struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(operand) - if struct_ty is None: - return None + if struct_ty is None: return None # 获取类名 class_name: str = self.Gen.StructGen.get_class_name_by_type(pool, struct_ty) - if class_name is None: - return None + if class_name is None: return None search_class: str = self._resolve_dunder_by_class(pool, mod, class_name, dunder, trans, struct_ty) - if search_class is None: - return None + if search_class is None: return None # 调用方法:operand.__dunder__(extra_args…) return self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, search_class, dunder, operand, extra_args, extra_count, trans) @@ -1414,17 +1274,14 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): val: mlirlite.Value*, trans: HT.Translator*) -> mlirlite.Value*: """把条件值归一到 i1,优先调度 __bool__(类实例),否则与 0/null 比较""" - if val is None: - return None + if val is None: return None bits: int = self.get_llvm_type_bits(val.Ty) - if bits == 1: - return val + if bits == 1: return val # 类实例:优先调用 __bool__(指针指向结构体且类内定义了该方法) bres: mlirlite.Value* = self._try_named_dunder(pool, builder, mod, val, "__bool__", trans) if bres is not None: b_bits: int = self.get_llvm_type_bits(bres.Ty) - if b_bits == 1: - return bres + if b_bits == 1: return bres if self.is_ptr_type(bres.Ty) != 0: null_b: mlirlite.Value* = mlirlite.ConstNull(pool, bres.Ty, "null") return mlirlite.build_icmp(builder, mlirlite.ICMP_NE, bres, null_b) @@ -1460,10 +1317,8 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): node: ast.AST* = None, is_aug: int = 0) -> int: """双指针算术 fail-fast;命中即终止编译,未命中返回 0""" - if lhs is None or rhs is None: - return 0 - if self.is_ptr_type(lhs.Ty) == 0 or self.is_ptr_type(rhs.Ty) == 0: - return 0 + if lhs is None or rhs is None: return 0 + if self.is_ptr_type(lhs.Ty) == 0 or self.is_ptr_type(rhs.Ty) == 0: return 0 op_ch: str = None if op == ast.OpKind.Add: op_ch = "+" elif op == ast.OpKind.Sub: op_ch = "-" @@ -1477,8 +1332,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): elif op == ast.OpKind.BitXor: op_ch = "^" elif op == ast.OpKind.LShift: op_ch = "<<" elif op == ast.OpKind.RShift: op_ch = ">>" - else: - return 0 + else: return 0 op_lbl: str = op_ch aug_note: str = "" if is_aug != 0: @@ -1493,16 +1347,13 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if lty_buf is not None: mlirlite.TypePrint(lty_buf, 512, lhs.Ty, pool) lty_lbl = lty_buf - if string.strcmp(lty_buf, "i8*") == 0: - lty_lbl = "str(i8*)" + if string.strcmp(lty_buf, "i8*") == 0: lty_lbl = "str(i8*)" if rty_buf is not None: mlirlite.TypePrint(rty_buf, 512, rhs.Ty, pool) rty_lbl = rty_buf - if string.strcmp(rty_buf, "i8*") == 0: - rty_lbl = "str(i8*)" + 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 + if node is not None: col_s = node.col_offset + 1 self.Gen.TypeGenErr.fatal_error( node, f"[TPV] 双指针运算类型非法: op = '{op_lbl}'{aug_note}," @@ -1524,8 +1375,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): trans: HT.Translator* = None) -> mlirlite.Value*: """翻译二元运算(自动类型提升)""" binop: ast.BinOp* = ast.BinOp*(node) - if binop is None: - return None + if binop is None: return None lhs_node: ast.AST* = binop.left rhs_node: ast.AST* = binop.right @@ -1533,8 +1383,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # 先翻译 rhs(只翻译一次,避免副作用重复) rhs: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, rhs_node, None, 0, trans) - if rhs is None: - return None + if rhs is None: return None # === 运算符重载路径 1: lhs 是 Name 且对应结构体变量 === # 对于值类型变量(如 cnt: Counter),translate_value 会 load 返回 Struct 值, @@ -1552,21 +1401,17 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # 递归解指针后路径 1 能识别 alloca,需同步修正 self 语义) if lhs_alloca.Ty is not None and lhs_alloca.Ty.Pointee != 0 and self.Gen.ExprGenBase.is_ptr_type(lhs_alloca.Ty.Pointee) != 0: load_self1: mlirlite.Value* = mlirlite.build_load(builder, lhs_alloca.Ty.Pointee, lhs_alloca) - if load_self1 is not None: - ovl_self1 = load_self1 + if load_self1 is not None: ovl_self1 = load_self1 ovl_result: mlirlite.Value* = self.try_operator_overload(pool, builder, mod, ovl_self1, rhs, op, trans, 0) - if ovl_result is not None: - return ovl_result + if ovl_result is not None: return ovl_result # 正常翻译 lhs lhs: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, lhs_node, None, 0, trans) - if lhs is None: - return None + if lhs is None: return None # === 运算符重载路径 2: lhs 是 Ptr(Struct)(如 Counter* 变量 load 后)=== ovl_result2: mlirlite.Value* = self.try_operator_overload(pool, builder, mod, lhs, rhs, op, trans, 0) - if ovl_result2 is not None: - return ovl_result2 + if ovl_result2 is not None: return ovl_result2 # === 运算符重载路径 3: 反向运算符 —— lhs 无对应 dunder 时调度 rhs.__rX__(lhs) === # (Python 语义:a + b → 先 a.__add__(b),缺失再 b.__radd__(a)) @@ -1578,13 +1423,11 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if rev_extra is not None: rev_extra[0] = sizet(lhs) r_ovl: mlirlite.Value* = self._try_named_dunder(pool, builder, mod, rhs, r_dunder, trans, rev_extra, 1) - if r_ovl is not None: - return r_ovl + if r_ovl is not None: return r_ovl # `**` 幂运算:基础类型 → llvm.pow(整数结果按指数常量回写)。 # 必须在浮点/整数分流之前处理,且已在重载路径之后(自定义类型走 __pow__)。 - if op == ast.OpKind.Pow: - return self.emit_pow(pool, builder, mod, lhs, rhs, node, trans) + if op == ast.OpKind.Pow: return self.emit_pow(pool, builder, mod, lhs, rhs, node, trans) # 获取操作数类型信息 lhs_bits: int = self.get_llvm_type_bits(lhs.Ty) @@ -1597,36 +1440,27 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if lhs_fbits != 0 or rhs_fbits != 0: # 确定目标浮点类型(使用较大的位宽) target_fbits: int = lhs_fbits - if rhs_fbits > target_fbits: - target_fbits = rhs_fbits + if rhs_fbits > target_fbits: target_fbits = rhs_fbits target_float_ty: mlirlite.LLVMType* = mlirlite.Double(pool) - if target_fbits == 32: - target_float_ty = mlirlite.Float(pool) + if target_fbits == 32: target_float_ty = mlirlite.Float(pool) # 将两个操作数转换为目标浮点类型(int→float via si2fp, float→float via fpext/fptrunc) lhs = self.coerce_to_type(builder, lhs, target_float_ty, node) rhs = self.coerce_to_type(builder, rhs, target_float_ty, node) - if op == ast.OpKind.Add: - return mlirlite.build_fadd(builder, lhs, rhs) - if op == ast.OpKind.Sub: - return mlirlite.build_fsub(builder, lhs, rhs) - if op == ast.OpKind.Mult: - return mlirlite.build_fmul(builder, lhs, rhs) - if op == ast.OpKind.Div: - return mlirlite.build_fdiv(builder, lhs, rhs) - if op == ast.OpKind.Mod: - return mlirlite.build_frem(builder, lhs, rhs) + if op == ast.OpKind.Add: return mlirlite.build_fadd(builder, lhs, rhs) + if op == ast.OpKind.Sub: return mlirlite.build_fsub(builder, lhs, rhs) + if op == ast.OpKind.Mult: return mlirlite.build_fmul(builder, lhs, rhs) + if op == ast.OpKind.Div: return mlirlite.build_fdiv(builder, lhs, rhs) + if op == ast.OpKind.Mod: return mlirlite.build_frem(builder, lhs, rhs) return None # 指针算术: ptr + int / ptr - int / int + ptr → getelementptr(按元素大小缩放) # 对齐 TPC ExprGen.emit_binary_op L50-67;int - ptr 无 GEP 形式(C 语义非法) if (lhs_bits == 0 and rhs_bits != 0) or (lhs_bits != 0 and rhs_bits == 0): if op == ast.OpKind.Add: - if lhs_bits == 0: - return self.translate_ptr_arith(pool, builder, lhs, rhs, op) + if lhs_bits == 0: return self.translate_ptr_arith(pool, builder, lhs, rhs, op) # int + ptr(交换) return self.translate_ptr_arith(pool, builder, rhs, lhs, op) - if op == ast.OpKind.Sub and lhs_bits == 0: - return self.translate_ptr_arith(pool, builder, lhs, rhs, op) + if op == ast.OpKind.Sub and lhs_bits == 0: return self.translate_ptr_arith(pool, builder, lhs, rhs, op) # 双指针算术(含 AugAssign)fail-fast:判据/报文唯一实现见 # fail_if_double_ptr_binop(本文件;BinOp 与 AssignGenMixin._apply_aug_op 共用)。 @@ -1639,22 +1473,16 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # 统一在此求值一次并下沉 trans(Name/Subscript 靠 SymTab 注解判定)。 binop_unsigned: int = 0 if lhs_node is not None: - if self._node_type_unsigned(pool, lhs_node, trans) != 0: - binop_unsigned = 1 + if self._node_type_unsigned(pool, lhs_node, trans) != 0: binop_unsigned = 1 if binop_unsigned == 0 and rhs_node is not None: - if self._node_type_unsigned(pool, rhs_node, trans) != 0: - binop_unsigned = 1 + if self._node_type_unsigned(pool, rhs_node, trans) != 0: binop_unsigned = 1 if lhs_bits > rhs_bits: - if self.should_zext_widen(pool, rhs, lhs, rhs_node, trans) != 0: - rhs = mlirlite.build_zext(builder, rhs, lhs.Ty) - else: - rhs = self.coerce_to_type(builder, rhs, lhs.Ty, node, trans) + if self.should_zext_widen(pool, rhs, lhs, rhs_node, trans) != 0: rhs = mlirlite.build_zext(builder, rhs, lhs.Ty) + else: rhs = self.coerce_to_type(builder, rhs, lhs.Ty, node, trans) elif rhs_bits > lhs_bits: - if self.should_zext_widen(pool, lhs, rhs, lhs_node, trans) != 0: - lhs = mlirlite.build_zext(builder, lhs, rhs.Ty) - else: - lhs = self.coerce_to_type(builder, lhs, rhs.Ty, node, trans) + if self.should_zext_widen(pool, lhs, rhs, lhs_node, trans) != 0: lhs = mlirlite.build_zext(builder, lhs, rhs.Ty) + else: lhs = self.coerce_to_type(builder, lhs, rhs.Ty, node, trans) # 位运算类型安全检查:两边都是指针(lhs_bits==0 and rhs_bits==0)时, # 位运算(BitOr/BitAnd/BitXor/LShift/RShift)非法,LLVM 要求整数操作数。 @@ -1672,16 +1500,13 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): # 覆盖 sizet/uint64 及变量/数组元素的注解无符号性)。 # 此前一律 sdiv → 无符号值 ≥ 2^63 时结果错误(viperlib %lu/%lx、 # fat32_mkfs 扇区运算等根因)。 - if binop_unsigned != 0: - return mlirlite.build_udiv(builder, lhs, rhs) + if binop_unsigned != 0: return mlirlite.build_udiv(builder, lhs, rhs) return mlirlite.build_sdiv(builder, lhs, rhs) elif op == ast.OpKind.FloorDiv: - if binop_unsigned != 0: - return mlirlite.build_udiv(builder, lhs, rhs) + if binop_unsigned != 0: return mlirlite.build_udiv(builder, lhs, rhs) return mlirlite.build_sdiv(builder, lhs, rhs) elif op == ast.OpKind.Mod: - if binop_unsigned != 0: - return mlirlite.build_urem(builder, lhs, rhs) + if binop_unsigned != 0: return mlirlite.build_urem(builder, lhs, rhs) return mlirlite.build_srem(builder, lhs, rhs) elif op == ast.OpKind.BitAnd: return mlirlite.build_and(builder, lhs, rhs) elif op == ast.OpKind.BitOr: return mlirlite.build_or(builder, lhs, rhs) @@ -1690,9 +1515,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): elif op == ast.OpKind.RShift: # 无符号 >> → lshr(逻辑右移),有符号 >> → ashr(算术右移) # 对齐 TPC ExprGen.emit_binary_op:i8/i16 默认无符号;其余查操作数无符号性 - if lhs_bits == 8 or lhs_bits == 16: - return mlirlite.build_lshr(builder, lhs, rhs) - if self._node_type_unsigned(pool, lhs_node, trans) != 0: - return mlirlite.build_lshr(builder, lhs, rhs) + if lhs_bits == 8 or lhs_bits == 16: return mlirlite.build_lshr(builder, lhs, rhs) + if self._node_type_unsigned(pool, lhs_node, trans) != 0: return mlirlite.build_lshr(builder, lhs, rhs) return mlirlite.build_ashr(builder, lhs, rhs) return None \ No newline at end of file diff --git a/App/lib/core/Gen/Func/FuncGenBase.vp b/App/lib/core/Gen/Func/FuncGenBase.vp index 70bb1df..9a0f5e3 100644 --- a/App/lib/core/Gen/Func/FuncGenBase.vp +++ b/App/lib/core/Gen/Func/FuncGenBase.vp @@ -51,8 +51,7 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase): if dk == ast.ASTKind.Attribute: dan: str = self._get_attr_name_from_node(deco) if dan is not None and string.strcmp(dan, "section") != 0: - if self._append_llvm_attr(attrs_buf, dan) != 0: - found_any = 1 + if self._append_llvm_attr(attrs_buf, dan) != 0: found_any = 1 continue if dk != ast.ASTKind.Call: continue call_node: ast.Call* = ast.Call*(deco) @@ -89,8 +88,7 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase): if string.strcmp(attr_name, "section") == 0: continue # 映射到 LLVM 属性名并追加 ar: int = self._append_llvm_attr(attrs_buf, attr_name) - if ar != 0: - found_any = 1 + if ar != 0: found_any = 1 if found_any == 0: return None return attrs_buf @@ -186,8 +184,7 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase): return 0 # 支持的属性:如果缓冲区非空,先追加空格分隔 - if attrs_buf[0] != '\0': - self._append_str(attrs_buf, " ", 256) + if attrs_buf[0] != '\0': self._append_str(attrs_buf, " ", 256) self._append_str(attrs_buf, llvm_name, 256) return 1 def _append_str(self, buf: str, s: str, @@ -196,8 +193,7 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase): if buf is None or s is None: return # 防御:TPV 方法默认参数注册存在缺陷(缺参调用 max_len 落到 0), # 显式兜底为 256,避免有界写入检查误判丢弃全部属性文本。 - if max_len == 0: - max_len = 256 + if max_len == 0: max_len = 256 cur_len: sizet = string.strlen(buf) s_len: sizet = string.strlen(s) if cur_len + s_len + 1 > max_len: return # 无剩余容量:丢弃本次追加,避免越界写 存疑 @@ -270,8 +266,7 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase): # ============================================================ def _body_has_raise(self, fd: ast.FunctionDef*) -> int: """函数体顶层是否含 raise(非 StopIteration),1=是 / 0=否""" - if fd is None or fd.children is None: - return 0 + if fd is None or fd.children is None: return 0 body_f: list[ast.AST*]* = fd.children bn_f: sizet = len(body_f) for bi_f in range(bn_f): @@ -284,16 +279,13 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase): is_stop_f: int = 0 if ek_f == ast.ASTKind.Name: enm_f: ast.Name* = ast.Name*(rn_f.exc) - if enm_f.id is not None and string.strcmp(enm_f.id, "StopIteration") == 0: - is_stop_f = 1 + if enm_f.id is not None and string.strcmp(enm_f.id, "StopIteration") == 0: is_stop_f = 1 elif ek_f == ast.ASTKind.Call: ecl_f: ast.Call* = ast.Call*(rn_f.exc) if ecl_f.func is not None and ecl_f.func.kind() == ast.ASTKind.Name: ecn_f: ast.Name* = ast.Name*(ecl_f.func) - if ecn_f.id is not None and string.strcmp(ecn_f.id, "StopIteration") == 0: - is_stop_f = 1 - if is_stop_f == 0: - return 1 + if ecn_f.id is not None and string.strcmp(ecn_f.id, "StopIteration") == 0: is_stop_f = 1 + if is_stop_f == 0: return 1 return 0 # ============================================================ # RejectCReturnDecorator - @c.CReturn 装饰器已移除,遇到即编译期报错 @@ -316,10 +308,8 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase): rcr_attr: ast.Attribute* = None if rcr_deco.kind() == ast.ASTKind.Call: rcr_call: ast.Call* = ast.Call*(rcr_deco) - if rcr_call.func is not None and rcr_call.func.kind() == ast.ASTKind.Attribute: - rcr_attr = ast.Attribute*(rcr_call.func) - elif rcr_deco.kind() == ast.ASTKind.Attribute: - rcr_attr = ast.Attribute*(rcr_deco) + if rcr_call.func is not None and rcr_call.func.kind() == ast.ASTKind.Attribute: rcr_attr = ast.Attribute*(rcr_call.func) + 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") @@ -364,8 +354,7 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase): return None param_ty = resolved pname: str = pool.alloc(32) - if pname is not None: - viperlib.snprintf(pname, 32, "%%%s", arg.arg) + if pname is not None: viperlib.snprintf(pname, 32, "%%%s", arg.arg) mlirlite.add_param(pool, func, param_ty, pname) return func \ No newline at end of file diff --git a/App/lib/core/Gen/Func/FuncGenDef.vp b/App/lib/core/Gen/Func/FuncGenDef.vp index 4bda6ca..a78f117 100644 --- a/App/lib/core/Gen/Func/FuncGenDef.vp +++ b/App/lib/core/Gen/Func/FuncGenDef.vp @@ -111,14 +111,11 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): if ce_at.attr is not None and string.strcmp(ce_at.attr, "CExport") == 0: if ce_at.value is not None and ce_at.value.kind() == ast.ASTKind.Name: ce_nm: ast.Name* = ast.Name*(ce_at.value) - if ce_nm.id is not None and string.strcmp(ce_nm.id, "t") == 0: - ret_ty = mlirlite.Void(pool) + if ce_nm.id is not None and string.strcmp(ce_nm.id, "t") == 0: ret_ty = mlirlite.Void(pool) if ret_ty is None and fd.returns is not None: - if self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0) != 0: - ret_ty = mlirlite.Void(pool) + if self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0) != 0: ret_ty = mlirlite.Void(pool) # @c.CReturn 装饰器已移除:遇到即编译期报错(多返回值改用 -> tuple[...]) - if ret_ty is None: - self.Gen.FuncGenBase.RejectCReturnDecorator(fd, fd.decorator_list) + if ret_ty is None: self.Gen.FuncGenBase.RejectCReturnDecorator(fd, fd.decorator_list) if ret_ty is None and fd.returns is not None: # 有返回注解但解析失败:编译期报错,不静默回退 i32。 # (i32 回退曾导致掉尾检查强制 return i32 / 跨模块调用返回类型错位, @@ -126,8 +123,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): # 保留 i32 默认,不在此报错。 self.Gen.TypeGenErr.fatal_error(fd, "函数返回类型解析失败:注解不可解析", "TypeError") return 0 - if ret_ty is None: - ret_ty = i32_ty + if ret_ty is None: ret_ty = i32_ty # 检测 CExtern/State/CExport has_extern: int = 0 @@ -145,15 +141,11 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): # (Mixin 是 @t.NoVTable 静态绑定,跨 Mixin 方法经 MRO 调用会生成 # 不存在的 FuncGenMixin._has_decorator → 链接 undefined symbol) if fd.decorator_list is not None: - if has_extern == 0 and self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "CExtern") == 1: - has_extern = 1 - if has_state == 0 and self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "State") == 1: - has_state = 1 - if has_export == 0 and self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "CExport") == 1: - has_export = 1 + if has_extern == 0 and self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "CExtern") == 1: has_extern = 1 + if has_state == 0 and self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "State") == 1: has_state = 1 + if has_export == 0 and self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "CExport") == 1: has_export = 1 is_extern_decl: int = 0 - if has_extern != 0 or has_state != 0: - is_extern_decl = 1 + if has_extern != 0 or has_state != 0: is_extern_decl = 1 # static(禁止跨模块使用):注解形态(`def f() -> t.CVoid | t.CStatic:`) # 与装饰器形态(`@t.CStatic`;裸 `static def f(...)` 已由解析层归一为 @@ -163,23 +155,19 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): self._RegisterStaticFunc(trans, fd) # 计算 mangled name - if has_extern != 0 or has_state != 0 or has_export != 0 or string.strcmp(fd.name, "main") == 0: - mangled_name: str = fd.name - else: - mangled_name = self.Gen.FuncGenBase._mangle_func_name(trans, fd.name, 0) + if has_extern != 0 or has_state != 0 or has_export != 0 or string.strcmp(fd.name, "main") == 0: mangled_name: str = fd.name + else: mangled_name = self.Gen.FuncGenBase._mangle_func_name(trans, fd.name, 0) # 如果函数已存在(如重复定义),跳过 existing: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, mangled_name) if existing is not None: - if tp_names_fd is not None: - self.Gen.TypeGenBase.clear_generic_context() + if tp_names_fd is not None: self.Gen.TypeGenBase.clear_generic_context() continue # 创建 declare func: mlirlite.Function* = mlirlite.create_declare(pool, mod, mangled_name, ret_ty) if func is None: - if tp_names_fd is not None: - self.Gen.TypeGenBase.clear_generic_context() + if tp_names_fd is not None: self.Gen.TypeGenBase.clear_generic_context() continue # 提取默认参数信息 @@ -208,8 +196,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): trans._func_count = cur_count + 1 # 注册 CExport 函数到全局表 - if (has_export != 0 or has_state != 0) and trans.ModuleSha1 is not None: - self.Gen.CallGenBase.register_cexport_func(trans.ModuleSha1, fd.name) + if (has_export != 0 or has_state != 0) and trans.ModuleSha1 is not None: self.Gen.CallGenBase.register_cexport_func(trans.ModuleSha1, fd.name) # 添加参数 args_node: ast.Arguments* = fd.args @@ -259,27 +246,23 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): if is_extern_decl != 0 and self.Gen.StructGen.find_struct_by_type(resolved) is not None: self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, resolved) param_ty = resolved - else: - param_ty = mlirlite.Ptr(pool, resolved) + else: param_ty = mlirlite.Ptr(pool, resolved) case mlirlite.LLVMType.Array(aelem_ty, _): param_ty = mlirlite.Ptr(pool, aelem_ty) case _: param_ty = resolved pname: str = pool.alloc(32) - if pname is not None: - viperlib.snprintf(pname, 32, "%%%s", arg.arg) + if pname is not None: viperlib.snprintf(pname, 32, "%%%s", arg.arg) mlirlite.add_param(pool, func, param_ty, pname) # *args 变长参数:设置 IsVarArg=1,生成 ... 后缀 - if ags.vararg is not None: - func.IsVarArg = 1 + if ags.vararg is not None: func.IsVarArg = 1 # 参数添加完成,补全全局函数表的 Spec(供 vtable 在 func 被 reset 后派生类型文本) self.Gen.CallGenLeafKit.update_global_func_spec(fd.name, func) # 泛型函数上下文用完即清(防泄漏到后续函数的注解解析) - if tp_names_fd is not None: - self.Gen.TypeGenBase.clear_generic_context() + if tp_names_fd is not None: self.Gen.TypeGenBase.clear_generic_context() # 恢复原始声明模式 trans._declare_only = saved_declare_only @@ -294,8 +277,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): node: ast.AST*) -> int: """翻译函数定义,返回新增的变量数(通常为 0,函数定义不增加当前作用域变量)""" fd: ast.FunctionDef* = ast.FunctionDef*(node) - if fd is None or fd.name is None: - return 0 + if fd is None or fd.name is None: return 0 # PEP 695 泛型函数模板不直接发射(与 forward_declare_functions 同口径): # 调用点单态化时由 ClassGenGeneric._specialize_generic_function 克隆发射 @@ -308,8 +290,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): # 解析器把 async def 存为 FunctionDef 且 flags & 1)。 # → 走 AsyncGenMixin 状态机翻译(create_/resume_), # 早返回不进普通函数路径(普通路径生成 ret 型普通函数,无法挂起/恢复)。 - if fd.flags is not None and (fd.flags & 1) != 0: - return self.Gen.AsyncGen.translate_async_function(trans, node) + if fd.flags is not None and (fd.flags & 1) != 0: return self.Gen.AsyncGen.translate_async_function(trans, node) pool: memhub.MemBuddy* = trans.Pool mod: mlirlite.LLVMModule* = trans.Module @@ -333,18 +314,15 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): if ce_at2.attr is not None and string.strcmp(ce_at2.attr, "CExport") == 0: if ce_at2.value is not None and ce_at2.value.kind() == ast.ASTKind.Name: ce_nm2: ast.Name* = ast.Name*(ce_at2.value) - if ce_nm2.id is not None and string.strcmp(ce_nm2.id, "t") == 0: - ret_ty = mlirlite.Void(pool) + if ce_nm2.id is not None and string.strcmp(ce_nm2.id, "t") == 0: ret_ty = mlirlite.Void(pool) # 如果返回类型注解纯装饰器标记(如 t.State,无实际类型),使用 void # 注意:必须在 infer_return_type 之前检测,因为 infer_return_type 至少返回 i32 if ret_ty is None and fd.returns is not None: - if self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0) != 0: - ret_ty = mlirlite.Void(pool) + if self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0) != 0: ret_ty = mlirlite.Void(pool) # @c.CReturn 装饰器已移除:遇到即编译期报错(多返回值改用 -> tuple[...]) - if ret_ty is None: - self.Gen.FuncGenBase.RejectCReturnDecorator(fd, fd.decorator_list) + if ret_ty is None: self.Gen.FuncGenBase.RejectCReturnDecorator(fd, fd.decorator_list) # 如果仍然为 None,扫描 return 语句推断(至少返回 i32) if ret_ty is None: @@ -378,25 +356,19 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): has_state = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0) has_export = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExport", 0) # t.CExtern/t.State 忽略 body 体,仅声明(无论 body 是否为 pass) - if has_extern != 0 or has_state != 0: - is_extern_decl = 1 + if has_extern != 0 or has_state != 0: is_extern_decl = 1 # 装饰器形式存储类标记(@t.CExport/@t.CExtern/@t.State/@t.CStatic), # 对齐 TPC HandlesFunctions._extract_decorator_storage_flags(与 # forward_declare_functions 一致,保证 declare 与 define 同名同语义)。 # 用 HandlesClassDef._has_decorator 委托(Mixin 静态绑定不能 self. 跨类调) if fd.decorator_list is not None: - if has_extern == 0 and self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "CExtern") == 1: - has_extern = 1 - if has_state == 0 and self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "State") == 1: - has_state = 1 - if has_export == 0 and self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "CExport") == 1: - has_export = 1 - if (has_extern != 0 or has_state != 0) and is_extern_decl == 0: - is_extern_decl = 1 + if has_extern == 0 and self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "CExtern") == 1: has_extern = 1 + if has_state == 0 and self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "State") == 1: has_state = 1 + if has_export == 0 and self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "CExport") == 1: has_export = 1 + if (has_extern != 0 or has_state != 0) and is_extern_decl == 0: is_extern_decl = 1 # @t.TLS 一次性初始化标记(对齐 TPC HandlesFunctions.py L1223-1231) has_tls: int = 0 - if fd.decorator_list is not None: - has_tls = self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "TLS") + if fd.decorator_list is not None: has_tls = self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "TLS") # 自定义行为装饰器检测(@log/@skip/@repeat(3) 等):非 t 存储标记、 # 非内置(staticmethod/property/classmethod)的 Name/Name(args) 装饰器。 @@ -409,8 +381,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): ddn: sizet = len(fd.decorator_list) for ddi in range(ddn): deco: ast.AST* = fd.decorator_list.get(ddi) - if deco is None: - continue + if deco is None: continue dk: int = deco.kind() dname: str = None if dk == ast.ASTKind.Name: @@ -426,13 +397,10 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): da0: ast.AST* = dcl.args.get(0) if da0 is not None and da0.kind() == ast.ASTKind.Constant: dc0: ast.Constant* = ast.Constant*(da0) - if dc0.const_kind == ast.CONST_INT: - decor_arg0 = dc0.int_val - if dname is None: - continue + if dc0.const_kind == ast.CONST_INT: decor_arg0 = dc0.int_val + if dname is None: continue # 跳过内置装饰器 - if string.strcmp(dname, "staticmethod") == 0 or string.strcmp(dname, "property") == 0 or string.strcmp(dname, "classmethod") == 0: - continue + if string.strcmp(dname, "staticmethod") == 0 or string.strcmp(dname, "property") == 0 or string.strcmp(dname, "classmethod") == 0: continue # 跳过 t 模块存储类标记(@t.CExport/@t.CExtern/@t.State/@t.TLS/ # @t.CStatic/@t.CInline/@t.CVTable/@t.NoVTable/@t.Object/@t.CEnum # /@t.CUnion/@t.REnum/@t.CDefine 等裸名形式——Attribute 形式 @@ -446,15 +414,12 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): # SHA1 命名空间:t.CExtern/t.State/t.CExport 不加前缀,直接用裸名 # (裸名映射到 C 标准库符号,带 sha1 前缀会导致 undefined reference) # main 函数也不加前缀(程序入口点) - if has_extern != 0 or has_state != 0 or has_export != 0 or string.strcmp(fd.name, "main") == 0: - mangled_name: str = fd.name - else: - mangled_name: str = self.Gen.FuncGenBase._mangle_func_name(trans, fd.name, 0) + if has_extern != 0 or has_state != 0 or has_export != 0 or string.strcmp(fd.name, "main") == 0: mangled_name: str = fd.name + else: mangled_name: str = self.Gen.FuncGenBase._mangle_func_name(trans, fd.name, 0) # 注册 CExport 函数到全局表(供跨模块调用查表) # t.CExport 函数定义用裸名(@strlen),跨模块调用需查表确认用裸名而非 @{sha1}.func - if (has_export != 0 or has_state != 0) and trans.ModuleSha1 is not None: - self.Gen.CallGenBase.register_cexport_func(trans.ModuleSha1, fd.name) + if (has_export != 0 or has_state != 0) and trans.ModuleSha1 is not None: self.Gen.CallGenBase.register_cexport_func(trans.ModuleSha1, fd.name) if is_extern_decl != 0: # 外部声明函数:生成 declare(仅声明,不定义) @@ -467,8 +432,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): # 注册到函数表 max_funcs_extern: int = 256 - if self.Gen.CallGenLeafKit.add_func_to_table(funcs_ptr, func_count, fd.name, func, max_funcs_extern, None, 0, 0, pool) == 0: - trans._func_count = func_count + 1 + if self.Gen.CallGenLeafKit.add_func_to_table(funcs_ptr, func_count, fd.name, func, max_funcs_extern, None, 0, 0, pool) == 0: trans._func_count = func_count + 1 # 添加参数(支持类型注解) args_node_extern: ast.Arguments* = fd.args @@ -481,8 +445,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): arg_e: ast.Arg* = ast.Arg*(alist_e.get(ai_e)) if arg_e is not None and arg_e.arg is not None: # CVoid 表示空参:跳过,不添加到函数签名 - if arg_e.annotation is not None and self.Gen.TypeGenResolve._is_t_attr(arg_e.annotation, "CVoid", imported_modules) != 0: - continue + if arg_e.annotation is not None and self.Gen.TypeGenResolve._is_t_attr(arg_e.annotation, "CVoid", imported_modules) != 0: continue param_ty_e: mlirlite.LLVMType* = i32_ty if arg_e.annotation is not None: resolved_e: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg_e.annotation, imported_modules, from_imports, trans, 0) @@ -506,25 +469,21 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): 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) param_ty_e = resolved_e - else: - param_ty_e = mlirlite.Ptr(pool, resolved_e) + else: param_ty_e = mlirlite.Ptr(pool, resolved_e) case mlirlite.LLVMType.Array(aelem_ty_e, _): param_ty_e = mlirlite.Ptr(pool, aelem_ty_e) case _: param_ty_e = resolved_e pname_e: str = pool.alloc(32) - if pname_e is not None: - viperlib.snprintf(pname_e, 32, "%%%s", arg_e.arg) + if pname_e is not None: viperlib.snprintf(pname_e, 32, "%%%s", arg_e.arg) mlirlite.add_param(pool, func, param_ty_e, pname_e) # 提取 @c.Attribute 装饰器属性并设置到函数 func_attrs_e: str = self.Gen.FuncGenBase.extract_func_attrs(pool, fd.decorator_list, imported_modules) - if func_attrs_e is not None: - mlirlite.function_set_attrs(func, func_attrs_e) + if func_attrs_e is not None: mlirlite.function_set_attrs(func, func_attrs_e) # B5:section 字符串属性走属性组 #N func_section_e: str = self.Gen.FuncGenBase.extract_func_section(pool, fd.decorator_list, imported_modules) - if func_section_e is not None: - mlirlite.function_set_attr_group(func, func_section_e) + if func_section_e is not None: mlirlite.function_set_attr_group(func, func_section_e) # 参数添加完成,补全全局函数表的 Spec self.Gen.CallGenLeafKit.update_global_func_spec(fd.name, func) @@ -541,12 +500,10 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): func.IsDeclared = 0 # 装饰器属性设置(前向声明时未设置) func_attrs_reuse: str = self.Gen.FuncGenBase.extract_func_attrs(pool, fd.decorator_list, imported_modules) - if func_attrs_reuse is not None: - mlirlite.function_set_attrs(func, func_attrs_reuse) + if func_attrs_reuse is not None: mlirlite.function_set_attrs(func, func_attrs_reuse) # B5:section 字符串属性走属性组 #N func_section_reuse: str = self.Gen.FuncGenBase.extract_func_section(pool, fd.decorator_list, imported_modules) - if func_section_reuse is not None: - mlirlite.function_set_attr_group(func, func_section_reuse) + if func_section_reuse is not None: mlirlite.function_set_attr_group(func, func_section_reuse) else: # 创建新的 LLVM 函数(使用 SHA1 混淆名) func = mlirlite.create_function(pool, mod, mangled_name, ret_ty) @@ -556,12 +513,10 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): # 提取 @c.Attribute 装饰器属性并设置到函数 func_attrs: str = self.Gen.FuncGenBase.extract_func_attrs(pool, fd.decorator_list, imported_modules) - if func_attrs is not None: - mlirlite.function_set_attrs(func, func_attrs) + if func_attrs is not None: mlirlite.function_set_attrs(func, func_attrs) # B5:section 字符串属性走属性组 #N(LLVM 不接受内联 section="...") func_section: str = self.Gen.FuncGenBase.extract_func_section(pool, fd.decorator_list, imported_modules) - if func_section is not None: - mlirlite.function_set_attr_group(func, func_section) + if func_section is not None: mlirlite.function_set_attr_group(func, func_section) # 提取默认参数信息 tfd_defaults: t.CPtr = None @@ -594,8 +549,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): arg: ast.Arg* = ast.Arg*(alist.get(ai)) if arg is not None and arg.arg is not None: # CVoid 表示空参:跳过,不添加到函数签名 - if arg.annotation is not None and self.Gen.TypeGenResolve._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0: - continue + if arg.annotation is not None and self.Gen.TypeGenResolve._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0: continue param_ty: mlirlite.LLVMType* = i32_ty if arg.annotation is not None: resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, imported_modules, from_imports, trans, 0) @@ -620,13 +574,11 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): case _: param_ty = resolved pname: str = pool.alloc(32) - if pname is not None: - viperlib.snprintf(pname, 32, "%%%s", arg.arg) + if pname is not None: viperlib.snprintf(pname, 32, "%%%s", arg.arg) mlirlite.add_param(pool, func, param_ty, pname) # *args 变长参数:设置 IsVarArg=1,生成 ... 后缀 - if ags.vararg is not None: - func.IsVarArg = 1 + if ags.vararg is not None: func.IsVarArg = 1 # try-except:函数体含 raise → 追加 __eh_msg_out__(i8**)/ # __eh_code_out__(i32*)输出参数(对齐 TPC HandlesFunctions.py @@ -651,13 +603,11 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): # 创建 entry 块 entry_blk: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "entry") - if entry_blk is None: - return 0 + if entry_blk is None: return 0 # 创建函数专属 builder func_builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, func) - if func_builder is None: - return 0 + if func_builder is None: return 0 mlirlite.position_at_end(func_builder, entry_blk) # --traceback: attach a DISubprogram to this define and set every @@ -705,21 +655,17 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): mlirlite.build_ret_void(func_builder) case mlirlite.LLVMType.Int(_): tlz0: mlirlite.Value* = mlirlite.ConstInt(pool, ret_ty, 0, "0") - if tlz0 is not None: - mlirlite.build_ret(func_builder, tlz0) + if tlz0 is not None: mlirlite.build_ret(func_builder, tlz0) case mlirlite.LLVMType.Float(_): tlf0: mlirlite.Value* = mlirlite.ConstFloat(pool, ret_ty, 0.0) - if tlf0 is not None: - mlirlite.build_ret(func_builder, tlf0) + if tlf0 is not None: mlirlite.build_ret(func_builder, tlf0) case _: tln0: mlirlite.Value* = mlirlite.ConstNull(pool, ret_ty, "null") - if tln0 is not None: - mlirlite.build_ret(func_builder, tln0) + if tln0 is not None: mlirlite.build_ret(func_builder, tln0) # cont 块:置标志=1,继续函数体 mlirlite.position_at_end(func_builder, tls_cont_bb) tlone: mlirlite.Value* = mlirlite.ConstInt(pool, i1_ty_t, 1, "1") - if tlone is not None: - mlirlite.build_store(func_builder, tlone, tls_flag_ref) + if tlone is not None: mlirlite.build_store(func_builder, tlone, tls_flag_ref) # 进入函数作用域(嵌套符号表) self.Gen.VarGen.enter_scope(trans.SymTab, FuncGenMixin.SCOPE_FUNCTION) @@ -739,8 +685,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): if arg2 is not None and arg2.arg is not None: # CVoid 表示空参:跳过,不创建 alloca if arg2.annotation is not None: - if self.Gen.TypeGenResolve._is_t_attr(arg2.annotation, "CVoid", imported_modules) != 0: - continue + if self.Gen.TypeGenResolve._is_t_attr(arg2.annotation, "CVoid", imported_modules) != 0: continue param_ty2: mlirlite.LLVMType* = i32_ty if arg2.annotation is not None: resolved2: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg2.annotation, imported_modules, from_imports, trans, 0) @@ -769,10 +714,8 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): # 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体) # 传 pool:泛型 Subscript 返回 mangled name(对齐 HandlesAnnAssign 修复) cls_nm: str = None - if arg2.annotation is not None: - cls_nm = self.Gen.TypeGenResolve.extract_class_name_from_annotation(arg2.annotation, imported_modules, pool, trans._from_imports) - if cls_nm is not None: - self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, arg2.arg, cls_nm) + if arg2.annotation is not None: cls_nm = self.Gen.TypeGenResolve.extract_class_name_from_annotation(arg2.annotation, imported_modules, pool, trans._from_imports) + if cls_nm is not None: self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, arg2.arg, cls_nm) # t.CVolatile 形参:声明期标记,函数体内该参数名的 # load/store 带 volatile(volatile 参数对象的读改写不得 # 被优化器提升/合并,如自旋等待入参)。 @@ -781,17 +724,13 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): # 是否含 t.CConst,不看指针层数)——TPC 形参登记点 # HandlesFunctions 的 IsParam=True 用同一条件,两侧逐条 # 对齐(见 Debugger/type-descriptors.md 已知差异)。 - if self.Gen.TypeGenErr.has_decorator_marker(arg2.annotation, "CConst", 0) != 0: - self.Gen.VarGen.set_var_const(trans.SymTab, arg2.arg) - if self.Gen.TypeGenErr.has_decorator_marker(arg2.annotation, "CVolatile", 0) != 0: - self.Gen.VarGen.set_var_volatile(trans.SymTab, arg2.arg) + if self.Gen.TypeGenErr.has_decorator_marker(arg2.annotation, "CConst", 0) != 0: self.Gen.VarGen.set_var_const(trans.SymTab, arg2.arg) + if self.Gen.TypeGenErr.has_decorator_marker(arg2.annotation, "CVolatile", 0) != 0: self.Gen.VarGen.set_var_volatile(trans.SymTab, arg2.arg) # rawptr[t.CVolatile | T] 形参(volatile 指针指向物): # 函数体内该参数解引用(p[i]/p.field/c.Deref(p))带 volatile。 - if self.Gen.TypeGenErr.has_pointee_volatile_marker(arg2.annotation) != 0: - self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, arg2.arg) + if self.Gen.TypeGenErr.has_pointee_volatile_marker(arg2.annotation) != 0: self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, arg2.arg) pname2: str = pool.alloc(32) - if pname2 is not None: - viperlib.snprintf(pname2, 32, "%%%s", arg2.arg) + if pname2 is not None: viperlib.snprintf(pname2, 32, "%%%s", arg2.arg) param_val: mlirlite.Value* = mlirlite.SSAValue(pool, param_ty2, pname2) vol_p2: int = self.Gen.VarGen.var_is_volatile(self.Gen.VarGen.lookup_var_entry(trans.SymTab, arg2.arg)) mlirlite.build_store(func_builder, param_val, alloca, vol_p2) @@ -893,12 +832,10 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): bn: sizet = len(body) for bi in range(bn): stmt: ast.AST* = body.get(bi) - if stmt is not None: - self.Gen.StmtGenDecl.pre_scan_scope_decls(trans, stmt) + if stmt is not None: self.Gen.StmtGenDecl.pre_scan_scope_decls(trans, stmt) for bi in range(bn): stmt: ast.AST* = body.get(bi) - if stmt is not None: - self.Gen.StmtGenDecl.pre_scan_allocas(trans, stmt) + if stmt is not None: self.Gen.StmtGenDecl.pre_scan_allocas(trans, stmt) # 翻译函数体 if body is not None: @@ -921,8 +858,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): bn3 = len(body) if bn3 > 0: last_stmt: ast.AST* = body.get(bn3 - 1) - if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return: - last_is_return = 1 + if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return: last_is_return = 1 if last_is_return == 0: if mlirlite.builder_cur_block_is_terminated(func_builder) == 0: # 编译器不替代码发明返回值——函数流程真实掉出末尾而未显式 return 时 fail-fast @@ -942,8 +878,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): last_stmt3: ast.AST* = body.get(bn3 - 1) if last_stmt3 is not None: k3: int = last_stmt3.kind() - if k3 == ast.ASTKind.If or k3 == ast.ASTKind.While or k3 == ast.ASTKind.For or k3 == ast.ASTKind.Try or k3 == ast.ASTKind.With or k3 == ast.ASTKind.Match: - last_is_ctrl = 1 + if k3 == ast.ASTKind.If or k3 == ast.ASTKind.While or k3 == ast.ASTKind.For or k3 == ast.ASTKind.Try or k3 == ast.ASTKind.With or k3 == ast.ASTKind.Match: last_is_ctrl = 1 _is_void: int = 0 if ret_ty is not None: match ret_ty: @@ -961,14 +896,11 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): # ② 裸名 CVoid(from t import CVoid)③ -> None(CONST_NONE); # ①②统一经既有判据 TypeGenResolve._is_cvoid_marker 判定(不新增名字白名单)。 if _is_void == 0 and fd.returns is not None: - if self.Gen.TypeGenResolve._is_cvoid_marker(fd.returns, imported_modules) != 0: - _is_void = 1 + if self.Gen.TypeGenResolve._is_cvoid_marker(fd.returns, imported_modules) != 0: _is_void = 1 elif fd.returns.kind() == ast.ASTKind.Constant: ret_none_cn: ast.Constant* = (ast.Constant*)(fd.returns) - if ret_none_cn.const_kind == ast.CONST_NONE: - _is_void = 1 - if _is_void != 0: - mlirlite.build_ret_void(func_builder) + if ret_none_cn.const_kind == ast.CONST_NONE: _is_void = 1 + if _is_void != 0: mlirlite.build_ret_void(func_builder) elif last_is_ctrl != 0 and trans._ctrl_merge_reachable == 0: # 追加90:非 void 函数末句是控制流且 merge 块**结构性**不可达 # (全分支 return,无 br 到 merge)→ LLVM 语义 unreachable。 @@ -989,12 +921,9 @@ 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") + 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: # fail-fast:有 -> 注解但流程真实掉出末尾(定位到函数定义 # 节点,fatal_error 输出 traceback 风格错误) @@ -1004,15 +933,13 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): rt_name: str = pool.alloc(512) if rt_name is not None: mlirlite.TypePrint(rt_name, 512, ret_ty, pool) - if rt_name[0] == '\0': - rt_name = "?" + 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) 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") + else: self.Gen.TypeGenErr.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError") # 恢复模块级作用域(退出函数作用域) self.Gen.VarGen.exit_scope(trans.SymTab) @@ -1045,8 +972,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): self.Gen.ClassGenBase.register_decorator(pool, fd.name, wb_name, decor_arg0) self._gen_decor_wrapper(trans, pool, mod, func, fd.name, wb_name, decor_handler, decor_arg0) - if dbg_pushed != 0: - DebugInfoGen.PopFunction(func_builder) + if dbg_pushed != 0: DebugInfoGen.PopFunction(func_builder) return 0 @@ -1064,18 +990,13 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): def _RegisterStaticFunc(self, trans: HT.Translator*, fd: ast.FunctionDef*) -> int: """static 函数登记:returns 注解或 @t.CStatic 装饰器命中即登记;1=已登记 / 0=未命中""" - if trans is None or fd is None or fd.name is None: - return 0 - if trans.ModuleSha1 is None: - return 0 + if trans is None or fd is None or fd.name is None: return 0 + if trans.ModuleSha1 is None: return 0 has: int = 0 - if fd.returns is not None: - has = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CStatic", 0) + if fd.returns is not None: has = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CStatic", 0) if has == 0 and fd.decorator_list is not None: - if self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "CStatic") == 1: - has = 1 - if has == 0: - return 0 + if self.Gen.ClassGenBase._has_decorator(fd.decorator_list, "CStatic") == 1: has = 1 + if has == 0: return 0 return self.Gen.CallGenBase.RegisterStaticSymbol(trans.ModuleSha1, fd.name) # ============================================================ @@ -1103,16 +1024,12 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): handler_name: str, decor_arg0: int64) -> mlirlite.Function*: """生成装饰器 wrapper 函数,返回 wrapper 或 None""" - if trans is None or pool is None or mod is None or func is None: - return None - if func_name is None or wrapper_name is None or handler_name is None: - return None + if trans is None or pool is None or mod is None or func is None: return None + if func_name is None or wrapper_name is None or handler_name is None: return None ret_ty: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(func) - if ret_ty is None: - return None + if ret_ty is None: return None orig_call_name: str = mlirlite.function_get_name(func) - if orig_call_name is None: - return None + if orig_call_name is None: return None i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) @@ -1121,8 +1038,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): # ---- 收集原函数参数类型(按位置,最多 16 个)---- n_params: int = 0 param_tys: sizet* = pool.alloc(16 * 8) - if param_tys is None: - return None + if param_tys is None: return None string.memset(param_tys, 0, 16 * 8) pp: mlirlite.Param* = mlirlite.function_get_param_head(func) while pp is not None: @@ -1147,8 +1063,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): loop_h_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, wrapper, "loop.header") loop_b_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, wrapper, "loop.body") post_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, wrapper, "post") - if entry_bb is None or loop_h_bb is None or loop_b_bb is None or post_bb is None: - return None + if entry_bb is None or loop_h_bb is None or loop_b_bb is None or post_bb is None: return None # 递归保护标志(最外层):@__decor_rec_{wrapper} = global i8 0 rec_flag_ref: mlirlite.Value* = None @@ -1162,8 +1077,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): rec_flag_ref = mlirlite.SSAValue(pool, mlirlite.Ptr(pool, i8_ty), rec_ref_nm) wb: mlirlite.IRBuilder* = mlirlite.new_builder(pool, wrapper) - if wb is None: - return None + if wb is None: return None # 返回类型分类 ret_is_void: int = 0 @@ -1179,8 +1093,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): if rec_flag_ref is not None: rec_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, wrapper, "recursive_call") dec_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, wrapper, "decorated_entry") - if rec_bb is None or dec_bb is None: - return None + if rec_bb is None or dec_bb is None: return None rec_val: mlirlite.Value* = mlirlite.build_load(wb, i8_ty, rec_flag_ref) rec_zero: mlirlite.Value* = mlirlite.ConstInt(pool, i8_ty, 0, "0") rec_is: mlirlite.Value* = mlirlite.build_icmp(wb, mlirlite.ICMP_NE, rec_val, rec_zero) @@ -1191,34 +1104,28 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): ri: int = 0 for ri in range(n_params): an_r: str = pool.alloc(16) - if an_r is None: - continue + if an_r is None: continue viperlib.snprintf(an_r, 16, "%%a%d", ri) av_r: mlirlite.Value* = mlirlite.SSAValue(pool, (mlirlite.LLVMType*)(param_tys[ri]), an_r) if av_r is not None: mlirlite.value_set_next(av_r, None) - if rec_args is None: - rec_args = av_r + if rec_args is None: rec_args = av_r else: # 链尾追加 rt: mlirlite.Value* = rec_args - while rt.Next is not None: - rt = rt.Next + while rt.Next is not None: rt = rt.Next mlirlite.value_set_next(rt, av_r) if ret_is_void != 0: mlirlite.build_call(wb, orig_call_name, rec_args, n_params, ret_ty, 0) mlirlite.build_ret_void(wb) else: rc_res: mlirlite.Value* = mlirlite.build_call(wb, orig_call_name, rec_args, n_params, ret_ty, 0) - if rc_res is not None: - mlirlite.build_ret(wb, rc_res) - else: - mlirlite.build_ret_void(wb) + if rc_res is not None: mlirlite.build_ret(wb, rc_res) + else: mlirlite.build_ret_void(wb) # decorated_entry:置递归标志,继续装饰路径 mlirlite.position_at_end(wb, dec_bb) rec_one: mlirlite.Value* = mlirlite.ConstInt(pool, i8_ty, 1, "1") - if rec_one is not None: - mlirlite.build_store(wb, rec_one, rec_flag_ref) + if rec_one is not None: mlirlite.build_store(wb, rec_one, rec_flag_ref) loop_pred_bb = dec_bb # ---- 公共装饰路径(entry 或 decorated_entry)---- @@ -1250,11 +1157,9 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): if fld_nm is not None: viperlib.snprintf(fld_nm, 16, "%%a%d", fi2) fld_v: mlirlite.Value* = mlirlite.SSAValue(pool, fld_ty, fld_nm) - if fld_v is not None: - mlirlite.build_store(wb, fld_v, fld_ptr) + if fld_v is not None: mlirlite.build_store(wb, fld_v, fld_ptr) args_ptr = mlirlite.build_bitcast(wb, args_alloca, i8_ptr_ty) - else: - args_ptr = mlirlite.ConstNull(pool, i8_ptr_ty, "null") + else: args_ptr = mlirlite.ConstNull(pool, i8_ptr_ty, "null") # 3. 返回值存储(零初始化;跳过原函数时返回安全默认值) ret_alloca: mlirlite.Value* = None @@ -1268,13 +1173,11 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): ret_zero = mlirlite.ConstFloat(pool, ret_ty, 0.0) case _: ret_zero = mlirlite.ConstNull(pool, ret_ty, "null") - if ret_zero is not None and ret_alloca is not None: - mlirlite.build_store(wb, ret_zero, ret_alloca) + if ret_zero is not None and ret_alloca is not None: mlirlite.build_store(wb, ret_zero, ret_alloca) # 4. 函数名字符串常量 fn_str: mlirlite.Value* = self.Gen.ExprGenConst.create_global_string(wb, pool, mod, func_name, trans) - if fn_str is None: - fn_str = mlirlite.ConstNull(pool, i8_ptr_ty, "null") + if fn_str is None: fn_str = mlirlite.ConstNull(pool, i8_ptr_ty, "null") # 5. handler 声明(未翻译时 declare,固定签名 i32 (i8*,i8*,i32,i8*,i8*,i8*)) if self.Gen.CallGenBase.find_func_in_module(mod, handler_name) is None: @@ -1303,8 +1206,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): # 7. 计数器 alloca(TPV 用 alloca 计数器替代 phi) cnt_alloca: mlirlite.Value* = mlirlite.build_alloca(wb, i32_ty) cnt_zero: mlirlite.Value* = mlirlite.ConstInt(pool, i32_ty, 0, "0") - if cnt_alloca is not None and cnt_zero is not None: - mlirlite.build_store(wb, cnt_zero, cnt_alloca) + if cnt_alloca is not None and cnt_zero is not None: mlirlite.build_store(wb, cnt_zero, cnt_alloca) mlirlite.build_br(wb, loop_h_bb) # 8. loop.header:cur = load cnt; cur < n_calls → body / post @@ -1325,26 +1227,21 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): fld_vk: mlirlite.Value* = mlirlite.build_load(wb, fld_ty_k, fld_pk) if fld_vk is not None: mlirlite.value_set_next(fld_vk, None) - if call_args is None: - call_args = fld_vk + if call_args is None: call_args = fld_vk else: ct: mlirlite.Value* = call_args - while ct.Next is not None: - ct = ct.Next + while ct.Next is not None: ct = ct.Next mlirlite.value_set_next(ct, fld_vk) res_v: mlirlite.Value* = mlirlite.build_call(wb, orig_call_name, call_args, n_params, ret_ty, 0) - if ret_alloca is not None and res_v is not None: - mlirlite.build_store(wb, res_v, ret_alloca) + if ret_alloca is not None and res_v is not None: mlirlite.build_store(wb, res_v, ret_alloca) nxt_i: mlirlite.Value* = mlirlite.build_add(wb, cur_i, mlirlite.ConstInt(pool, i32_ty, 1, "1")) - if nxt_i is not None and cnt_alloca is not None: - mlirlite.build_store(wb, nxt_i, cnt_alloca) + if nxt_i is not None and cnt_alloca is not None: mlirlite.build_store(wb, nxt_i, cnt_alloca) mlirlite.build_br(wb, loop_h_bb) # 10. post:handler 后置 → 清递归标志 → 返回结果 mlirlite.position_at_end(wb, post_bb) ret_ptr: mlirlite.Value* = null_ret - if ret_alloca is not None: - ret_ptr = mlirlite.build_bitcast(wb, ret_alloca, i8_ptr_ty) + if ret_alloca is not None: ret_ptr = mlirlite.build_bitcast(wb, ret_alloca, i8_ptr_ty) ph1: mlirlite.Value* = mlirlite.ConstInt(pool, i32_ty, 1, "1") # 后置参数链:ctx_ptr → fn_str → 1 → args_ptr → ret_ptr → null if ctx_ptr is not None: mlirlite.value_set_next(ctx_ptr, fn_str) @@ -1355,15 +1252,11 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): mlirlite.build_call(wb, handler_name, ctx_ptr, 6, i32_ty, 0) if rec_flag_ref is not None: rec_zero2: mlirlite.Value* = mlirlite.ConstInt(pool, i8_ty, 0, "0") - if rec_zero2 is not None: - mlirlite.build_store(wb, rec_zero2, rec_flag_ref) - if ret_is_void != 0: - mlirlite.build_ret_void(wb) + if rec_zero2 is not None: mlirlite.build_store(wb, rec_zero2, rec_flag_ref) + if ret_is_void != 0: mlirlite.build_ret_void(wb) else: final_v: mlirlite.Value* = mlirlite.build_load(wb, ret_ty, ret_alloca) - if final_v is not None: - mlirlite.build_ret(wb, final_v) - else: - mlirlite.build_ret_void(wb) + if final_v is not None: mlirlite.build_ret(wb, final_v) + else: mlirlite.build_ret_void(wb) return wrapper \ No newline at end of file diff --git a/App/lib/core/Gen/Func/FuncGenMixin.vp b/App/lib/core/Gen/Func/FuncGenMixin.vp index 11c819b..8b078a9 100644 --- a/App/lib/core/Gen/Func/FuncGenMixin.vp +++ b/App/lib/core/Gen/Func/FuncGenMixin.vp @@ -54,8 +54,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): # 1. 构建提升后的函数名: __closure_{name}(加 SHA1 前缀避免跨模块冲突) promoted_name: str = pool.alloc(64) - if promoted_name is not None: - viperlib.snprintf(promoted_name, 64, "__closure_%s", func_name) + if promoted_name is not None: viperlib.snprintf(promoted_name, 64, "__closure_%s", func_name) mangled_promoted: str = self.Gen.FuncGenBase._mangle_name(trans, promoted_name) # 2. 创建提升后的函数: define i32 @__closure_{name}(i8* %env, args...) @@ -68,8 +67,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): imported_modules: str = trans._imported_modules from_imports: str = trans._from_imports param_tys: t.CPtr = pool.alloc(8 * 64) - if param_tys is not None: - string.memset(param_tys, 0, 8 * 64) + if param_tys is not None: string.memset(param_tys, 0, 8 * 64) param_count: int = 0 if fd.args is not None: ags_n: ast.Arguments* = ast.Arguments*(fd.args) @@ -132,43 +130,34 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): apn: sizet = len(alist_p) for api in range(apn): arg_p: ast.Arg* = ast.Arg*(alist_p.get(api)) - if arg_p is None or arg_p.arg is None: - continue + if arg_p is None or arg_p.arg is None: continue if arg_p.annotation is not None: - if self.Gen.TypeGenResolve._is_t_attr(arg_p.annotation, "CVoid", imported_modules) != 0: - continue - if idx_p >= param_count: - break + if self.Gen.TypeGenResolve._is_t_attr(arg_p.annotation, "CVoid", imported_modules) != 0: continue + if idx_p >= param_count: break pty2_n: mlirlite.LLVMType* = i32_ty if param_tys is not None: ty_addr_n: uint64 = uint64(param_tys) + idx_p * 8 ty_slot_n: str* = (str*)(ty_addr_n) pty2_n = (mlirlite.LLVMType*)(ty_slot_n[0]) - if pty2_n is None: - pty2_n = i32_ty + if pty2_n is None: pty2_n = i32_ty p_alloca: mlirlite.Value* = mlirlite.build_alloca(func_builder, pty2_n) if p_alloca is not None: self.Gen.VarGen.define_var(trans.SymTab, arg_p.arg, p_alloca) if arg_p.annotation is not None: cls_nm_p: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(arg_p.annotation, imported_modules, pool, trans._from_imports) - if cls_nm_p is not None: - self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, arg_p.arg, cls_nm_p) + if cls_nm_p is not None: self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, arg_p.arg, cls_nm_p) # const 形参:沿用 TPC 形参的历史判据(只看注解是否含 # t.CConst,不看指针层数),两侧逐条对齐(见 # Debugger/type-descriptors.md 已知差异)。 - if self.Gen.TypeGenErr.has_decorator_marker(arg_p.annotation, "CConst", 0) != 0: - self.Gen.VarGen.set_var_const(trans.SymTab, arg_p.arg) + if self.Gen.TypeGenErr.has_decorator_marker(arg_p.annotation, "CConst", 0) != 0: self.Gen.VarGen.set_var_const(trans.SymTab, arg_p.arg) # t.CVolatile 形参:声明期标记(与 FuncGenDef 主路径同款), # 函数体内该参数名的 load/store 带 volatile。 - if self.Gen.TypeGenErr.has_decorator_marker(arg_p.annotation, "CVolatile", 0) != 0: - self.Gen.VarGen.set_var_volatile(trans.SymTab, arg_p.arg) + if self.Gen.TypeGenErr.has_decorator_marker(arg_p.annotation, "CVolatile", 0) != 0: self.Gen.VarGen.set_var_volatile(trans.SymTab, arg_p.arg) # rawptr[t.CVolatile | T] 形参(volatile 指针指向物): # 函数体内该参数解引用带 volatile(与 FuncGenDef 主路径同款)。 - if self.Gen.TypeGenErr.has_pointee_volatile_marker(arg_p.annotation) != 0: - self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, arg_p.arg) + if self.Gen.TypeGenErr.has_pointee_volatile_marker(arg_p.annotation) != 0: self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, arg_p.arg) pname2_n: str = pool.alloc(32) - if pname2_n is not None: - viperlib.snprintf(pname2_n, 32, "%%%s", arg_p.arg) + if pname2_n is not None: viperlib.snprintf(pname2_n, 32, "%%%s", arg_p.arg) p_val: mlirlite.Value* = mlirlite.SSAValue(pool, pty2_n, pname2_n) vol_pn: int = self.Gen.VarGen.var_is_volatile(self.Gen.VarGen.lookup_var_entry(trans.SymTab, arg_p.arg)) mlirlite.build_store(func_builder, p_val, p_alloca, vol_pn) @@ -203,10 +192,8 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): # 嵌套函数独立 nonlocal 缓冲(避免覆盖父函数集合) trans._nonlocal_names = stdlib.malloc(HT.MAX_GLOBAL_NAMES * 8) trans._nonlocal_types = stdlib.malloc(HT.MAX_GLOBAL_NAMES * 8) - if trans._nonlocal_names is not None: - string.memset(trans._nonlocal_names, 0, HT.MAX_GLOBAL_NAMES * 8) - if trans._nonlocal_types is not None: - string.memset(trans._nonlocal_types, 0, HT.MAX_GLOBAL_NAMES * 8) + if trans._nonlocal_names is not None: string.memset(trans._nonlocal_names, 0, HT.MAX_GLOBAL_NAMES * 8) + if trans._nonlocal_types is not None: string.memset(trans._nonlocal_types, 0, HT.MAX_GLOBAL_NAMES * 8) # 8. 预扫描函数体: # a. 先预扫描 Global/Nonlocal 声明(Python 语义:对整个函数作用域生效) @@ -216,12 +203,10 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): bn: sizet = len(body) for bi in range(bn): stmt: ast.AST* = body.get(bi) - if stmt is not None: - self.Gen.StmtGenDecl.pre_scan_scope_decls(trans, stmt) + if stmt is not None: self.Gen.StmtGenDecl.pre_scan_scope_decls(trans, stmt) for bi in range(bn): stmt: ast.AST* = body.get(bi) - if stmt is not None: - self.Gen.StmtGenDecl.pre_scan_allocas(trans, stmt) + if stmt is not None: self.Gen.StmtGenDecl.pre_scan_allocas(trans, stmt) # 8c. 隐式捕获扫描:嵌套函数读取的外层函数局部变量注册为 nonlocal # (Python 语义,无需显式 nonlocal;否则 read 经 lookup_var @@ -232,16 +217,14 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): bnc: sizet = len(body) for bic in range(bnc): stmtc: ast.AST* = body.get(bic) - if stmtc is not None: - self._closure_scan_captures(trans, stmtc) + if stmtc is not None: self._closure_scan_captures(trans, stmtc) # 9. 翻译函数体(Nonlocal 语句会填充 _nonlocal_names) if body is not None: bn2: sizet = len(body) for bi2 in range(bn2): stmt2: ast.AST* = body.get(bi2) - if stmt2 is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt2) + if stmt2 is not None: self.Gen.StmtGen.translate_stmt(trans, stmt2) # 10. 隐式 ret last_is_return: int = 0 @@ -249,8 +232,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): bn3: sizet = len(body) if bn3 > 0: last_stmt: ast.AST* = body.get(bn3 - 1) - if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return: - last_is_return = 1 + if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return: last_is_return = 1 if last_is_return == 0: zero_val: mlirlite.Value* = mlirlite.const_int32(pool, 0) mlirlite.build_ret(func_builder, zero_val) @@ -265,8 +247,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): trans._break_bb = old_break_bb trans._continue_bb = old_continue_bb trans._in_switch_case = old_insw - if dbg_pushed_n != 0: - DebugInfoGen.PopFunction(func_builder) + if dbg_pushed_n != 0: DebugInfoGen.PopFunction(func_builder) # NOTE: _nonlocal_names 和 _nonlocal_name_count 仍为嵌套函数的值 # 13. 在父函数中创建闭包对象 @@ -308,8 +289,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): name_addr: uint64 = uint64(trans._nonlocal_names) + ni * 8 nl_slot: str* = (str*)(name_addr) nl_name: str = nl_slot[0] - if nl_name is None: - continue + if nl_name is None: continue heap_store: mlirlite.Value* = None # 1. 优先查全局堆地址映射(_prepare_chain_nonlocals 已为 # 链内 nonlocal 建堆并 store 到 @nlheap.*;不同层捕获 @@ -317,8 +297,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): gname_ck: str = self._nl_heap_global_name(pool, trans, nl_name) if gname_ck is not None and self._nl_heap_global_exists(mod, gname_ck) != 0: gv_ref0: mlirlite.Value* = self._nl_heap_global_ref(pool, trans, nl_name) - if gv_ref0 is not None: - heap_store = mlirlite.build_load(parent_builder, i8_ptr_ty, gv_ref0) + if gv_ref0 is not None: heap_store = mlirlite.build_load(parent_builder, i8_ptr_ty, gv_ref0) if heap_store is None: local_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_current(trans.SymTab, nl_name) if local_alloca is not None and local_alloca.Ty is not None: @@ -330,19 +309,16 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): # 不能固定 8 字节(越界写崩溃);指针/标量 ≥ 8 字节 st_size: int = self._type_byte_size(pool, nl_load_ty) st_size_val: mlirlite.Value* = mlirlite.const_int64(pool, st_size) - if st_size_val is not None: - st_size_val.Next = None + if st_size_val is not None: st_size_val.Next = None var_storage: mlirlite.Value* = mlirlite.build_call(parent_builder, "malloc", st_size_val, 1, i8_ptr_ty, 0) if var_storage is not None: # 拷贝当前值到堆存储 st_slot_nl: mlirlite.Value* = mlirlite.build_bitcast(parent_builder, var_storage, mlirlite.Ptr(pool, nl_load_ty)) - if st_slot_nl is not None and cur_val_nl is not None: - mlirlite.build_store(parent_builder, cur_val_nl, st_slot_nl) + if st_slot_nl is not None and cur_val_nl is not None: mlirlite.build_store(parent_builder, cur_val_nl, st_slot_nl) # 父函数 VarEntry.Alloca 重定向到堆(父函数读写走共享堆) ve_nl: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nl_name) heap_typed: mlirlite.Value* = mlirlite.build_bitcast(parent_builder, var_storage, mlirlite.Ptr(pool, nl_load_ty)) - if ve_nl is not None and heap_typed is not None: - ve_nl.Alloca = heap_typed + if ve_nl is not None and heap_typed is not None: ve_nl.Alloca = heap_typed # 记录到全局映射(后续层/父函数可见) gv_ref_new: mlirlite.Value* = None if gname_ck is not None and self._nl_heap_global_exists(mod, gname_ck) == 0: @@ -353,27 +329,23 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): gv_new.Initializer = "null" mlirlite.module_add_global(mod, gv_new) gv_ref_new = self._nl_heap_global_ref(pool, trans, nl_name) - if gv_ref_new is not None: - mlirlite.build_store(parent_builder, var_storage, gv_ref_new) + if gv_ref_new is not None: mlirlite.build_store(parent_builder, var_storage, gv_ref_new) heap_store = var_storage else: # 父函数中该变量是 nonlocal(多层嵌套):从父函数 env # 读堆地址(运行时链式共享同一堆),不新建 heap_store = self.Gen.StmtGenDecl._load_raw_var_ptr(trans, nl_name) - if heap_store is None: - continue + if heap_store is None: continue # env[ni] = 堆存储地址(共享) offset_val: mlirlite.Value* = mlirlite.const_int32(pool, ni * 8) slot: mlirlite.Value* = mlirlite.build_gep(parent_builder, i8_ty, env_ptr, offset_val) if slot is not None: slot_typed: mlirlite.Value* = mlirlite.build_bitcast(parent_builder, slot, i8_ptr_ptr_ty) - if slot_typed is not None: - mlirlite.build_store(parent_builder, heap_store, slot_typed) + if slot_typed is not None: mlirlite.build_store(parent_builder, heap_store, slot_typed) # 13b. 创建闭包结构: malloc(16) closure_size_val: mlirlite.Value* = mlirlite.const_int64(pool, 16) - if closure_size_val is not None: - closure_size_val.Next = None + if closure_size_val is not None: closure_size_val.Next = None closure_ptr: mlirlite.Value* = mlirlite.build_call(parent_builder, "malloc", closure_size_val, 1, i8_ptr_ty, 0) if closure_ptr is None: # malloc 失败,恢复状态 @@ -395,17 +367,14 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): fn_ptr_name: str = pool.alloc(64) if fn_ptr_name is not None: # SHA1 前缀名含 '.' 需要加引号(如 @"sha1.__closure_func") - if string.strchr(mangled_promoted, '.') is not None: - viperlib.snprintf(fn_ptr_name, 64, "@\"%s\"", mangled_promoted) - else: - viperlib.snprintf(fn_ptr_name, 64, "@%s", mangled_promoted) + if string.strchr(mangled_promoted, '.') is not None: viperlib.snprintf(fn_ptr_name, 64, "@\"%s\"", mangled_promoted) + else: viperlib.snprintf(fn_ptr_name, 64, "@%s", mangled_promoted) fn_ptr_val: mlirlite.Value* = mlirlite.SSAValue(pool, fn_func_ptr_ty, fn_ptr_name) # bitcast 函数指针到 i8*(闭包存储 i8* 类型) fn_as_i8ptr: mlirlite.Value* = mlirlite.build_bitcast(parent_builder, fn_ptr_val, i8_ptr_ty) fn_slot: mlirlite.Value* = mlirlite.build_bitcast(parent_builder, closure_ptr, mlirlite.Ptr(pool, i8_ptr_ty)) - if fn_slot is not None and fn_as_i8ptr is not None: - mlirlite.build_store(parent_builder, fn_as_i8ptr, fn_slot) + if fn_slot is not None and fn_as_i8ptr is not None: mlirlite.build_store(parent_builder, fn_as_i8ptr, fn_slot) # 13d. 存储 env_ptr 到 offset 8 eight_val: mlirlite.Value* = mlirlite.const_int32(pool, 8) @@ -413,8 +382,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): if env_slot_addr is not None: env_slot: mlirlite.Value* = mlirlite.build_bitcast(parent_builder, env_slot_addr, mlirlite.Ptr(pool, i8_ptr_ty)) if env_slot is not None: - if env_ptr is not None: - mlirlite.build_store(parent_builder, env_ptr, env_slot) + if env_ptr is not None: mlirlite.build_store(parent_builder, env_ptr, env_slot) else: # 无 nonlocal 变量,存储 null null_val: mlirlite.Value* = mlirlite.SSAValue(pool, i8_ptr_ty, "null") @@ -448,8 +416,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): def _closure_scan_captures(self, trans: HT.Translator*, node: ast.AST*) -> int: """递归扫描节点中的隐式捕获并注册为 nonlocal""" - if node is None or trans is None: - return 1 + if node is None or trans is None: return 1 k: int = node.kind() if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) @@ -472,71 +439,56 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): # ---- 语句 ---- if k == ast.ASTKind.Assign: asn: ast.Assign* = ast.Assign*(node) - if asn.value is not None: - self._closure_scan_captures(trans, asn.value) + if asn.value is not None: self._closure_scan_captures(trans, asn.value) return 1 if k == ast.ASTKind.AnnAssign: aan: ast.AnnAssign* = ast.AnnAssign*(node) - if aan.value is not None: - self._closure_scan_captures(trans, aan.value) + if aan.value is not None: self._closure_scan_captures(trans, aan.value) return 1 if k == ast.ASTKind.AugAssign: aun: rawptr[ast.AugAssign] = rawptr[ast.AugAssign](node) # 目标同时是读(先读旧值),参与捕获 - if aun.target is not None: - self._closure_scan_captures(trans, aun.target) - if aun.value is not None: - self._closure_scan_captures(trans, aun.value) + if aun.target is not None: self._closure_scan_captures(trans, aun.target) + if aun.value is not None: self._closure_scan_captures(trans, aun.value) return 1 if k == ast.ASTKind.If: ifn: rawptr[ast.If] = rawptr[ast.If](node) - if ifn.test is not None: - self._closure_scan_captures(trans, ifn.test) + if ifn.test is not None: self._closure_scan_captures(trans, ifn.test) if ifn.children is not None: bn_if: sizet = len(ifn.children) - for bi_if in range(bn_if): - self._closure_scan_captures(trans, ifn.children.get(bi_if)) + for bi_if in range(bn_if): self._closure_scan_captures(trans, ifn.children.get(bi_if)) if ifn.orelse is not None: bn_el: sizet = len(ifn.orelse) - for bi_el in range(bn_el): - self._closure_scan_captures(trans, ifn.orelse.get(bi_el)) + for bi_el in range(bn_el): self._closure_scan_captures(trans, ifn.orelse.get(bi_el)) return 1 if k == ast.ASTKind.For: for_n: ast.For* = ast.For*(node) # 循环目标是新局部变量,不参与捕获 - if for_n.iter is not None: - self._closure_scan_captures(trans, for_n.iter) + if for_n.iter is not None: self._closure_scan_captures(trans, for_n.iter) if for_n.children is not None: bn_f: sizet = len(for_n.children) - for bi_f in range(bn_f): - self._closure_scan_captures(trans, for_n.children.get(bi_f)) + for bi_f in range(bn_f): self._closure_scan_captures(trans, for_n.children.get(bi_f)) if for_n.orelse is not None: bn_fe: sizet = len(for_n.orelse) - for bi_fe in range(bn_fe): - self._closure_scan_captures(trans, for_n.orelse.get(bi_fe)) + for bi_fe in range(bn_fe): self._closure_scan_captures(trans, for_n.orelse.get(bi_fe)) return 1 if k == ast.ASTKind.While: wh_n: rawptr[ast.While] = rawptr[ast.While](node) - if wh_n.test is not None: - self._closure_scan_captures(trans, wh_n.test) + if wh_n.test is not None: self._closure_scan_captures(trans, wh_n.test) if wh_n.children is not None: bn_w: sizet = len(wh_n.children) - for bi_w in range(bn_w): - self._closure_scan_captures(trans, wh_n.children.get(bi_w)) + for bi_w in range(bn_w): self._closure_scan_captures(trans, wh_n.children.get(bi_w)) if wh_n.orelse is not None: bn_we: sizet = len(wh_n.orelse) - for bi_we in range(bn_we): - self._closure_scan_captures(trans, wh_n.orelse.get(bi_we)) + for bi_we in range(bn_we): self._closure_scan_captures(trans, wh_n.orelse.get(bi_we)) return 1 if k == ast.ASTKind.Return: rt_n: rawptr[ast.Return] = rawptr[ast.Return](node) - if rt_n.value is not None: - self._closure_scan_captures(trans, rt_n.value) + if rt_n.value is not None: self._closure_scan_captures(trans, rt_n.value) return 1 if k == ast.ASTKind.Expr: ex_n: rawptr[ast.Expr] = rawptr[ast.Expr](node) - if ex_n.value is not None: - self._closure_scan_captures(trans, ex_n.value) + if ex_n.value is not None: self._closure_scan_captures(trans, ex_n.value) return 1 if k == ast.ASTKind.With: wth: ast.With* = ast.With*(node) @@ -546,33 +498,26 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): wi_n: ast.AST* = wth.items.get(bi_wi) if wi_n is not None and wi_n.kind() == ast.ASTKind.WithItem: wi_c: rawptr[ast.WithItem] = rawptr[ast.WithItem](wi_n) - if wi_c.context_expr is not None: - self._closure_scan_captures(trans, wi_c.context_expr) + if wi_c.context_expr is not None: self._closure_scan_captures(trans, wi_c.context_expr) if wth.children is not None: bn_wb: sizet = len(wth.children) - for bi_wb in range(bn_wb): - self._closure_scan_captures(trans, wth.children.get(bi_wb)) + for bi_wb in range(bn_wb): self._closure_scan_captures(trans, wth.children.get(bi_wb)) return 1 if k == ast.ASTKind.Raise: rs_n: rawptr[ast.Raise] = rawptr[ast.Raise](node) - if rs_n.exc is not None: - self._closure_scan_captures(trans, rs_n.exc) - if rs_n.cause is not None: - self._closure_scan_captures(trans, rs_n.cause) + if rs_n.exc is not None: self._closure_scan_captures(trans, rs_n.exc) + if rs_n.cause is not None: self._closure_scan_captures(trans, rs_n.cause) return 1 if k == ast.ASTKind.Assert: as_n: rawptr[ast.Assert] = rawptr[ast.Assert](node) - if as_n.test is not None: - self._closure_scan_captures(trans, as_n.test) - if as_n.msg is not None: - self._closure_scan_captures(trans, as_n.msg) + if as_n.test is not None: self._closure_scan_captures(trans, as_n.test) + if as_n.msg is not None: self._closure_scan_captures(trans, as_n.msg) return 1 if k == ast.ASTKind.Try: tr_n: ast.Try* = ast.Try*(node) if tr_n.children is not None: bn_t: sizet = len(tr_n.children) - for bi_t in range(bn_t): - self._closure_scan_captures(trans, tr_n.children.get(bi_t)) + for bi_t in range(bn_t): self._closure_scan_captures(trans, tr_n.children.get(bi_t)) if tr_n.handlers is not None: bn_th: sizet = len(tr_n.handlers) for bi_th in range(bn_th): @@ -581,223 +526,176 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): eh_c: ast.ExceptHandler* = ast.ExceptHandler*(eh_n) if eh_c.children is not None: bn_ehb: sizet = len(eh_c.children) - for bi_ehb in range(bn_ehb): - self._closure_scan_captures(trans, eh_c.children.get(bi_ehb)) + for bi_ehb in range(bn_ehb): self._closure_scan_captures(trans, eh_c.children.get(bi_ehb)) if tr_n.orelse is not None: bn_to: sizet = len(tr_n.orelse) - for bi_to in range(bn_to): - self._closure_scan_captures(trans, tr_n.orelse.get(bi_to)) + for bi_to in range(bn_to): self._closure_scan_captures(trans, tr_n.orelse.get(bi_to)) if tr_n.finalbody is not None: bn_tf: sizet = len(tr_n.finalbody) - for bi_tf in range(bn_tf): - self._closure_scan_captures(trans, tr_n.finalbody.get(bi_tf)) + for bi_tf in range(bn_tf): self._closure_scan_captures(trans, tr_n.finalbody.get(bi_tf)) return 1 if k == ast.ASTKind.Match: mt_n: ast.Match* = ast.Match*(node) - if mt_n.subject is not None: - self._closure_scan_captures(trans, mt_n.subject) + if mt_n.subject is not None: self._closure_scan_captures(trans, mt_n.subject) if mt_n.cases is not None: bn_mc: sizet = len(mt_n.cases) for bi_mc in range(bn_mc): mc_n: ast.AST* = mt_n.cases.get(bi_mc) if mc_n is not None and mc_n.kind() == ast.ASTKind.MatchCase: mc_c: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](mc_n) - if mc_c.guard is not None: - self._closure_scan_captures(trans, mc_c.guard) + if mc_c.guard is not None: self._closure_scan_captures(trans, mc_c.guard) if mc_c.children is not None: bn_mcb: sizet = len(mc_c.children) - for bi_mcb in range(bn_mcb): - self._closure_scan_captures(trans, mc_c.children.get(bi_mcb)) + for bi_mcb in range(bn_mcb): self._closure_scan_captures(trans, mc_c.children.get(bi_mcb)) return 1 # ---- 表达式 ---- if k == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(node) - if bop.left is not None: - self._closure_scan_captures(trans, bop.left) - if bop.right is not None: - self._closure_scan_captures(trans, bop.right) + if bop.left is not None: self._closure_scan_captures(trans, bop.left) + if bop.right is not None: self._closure_scan_captures(trans, bop.right) return 1 if k == ast.ASTKind.UnaryOp: uop: ast.UnaryOp* = ast.UnaryOp*(node) - if uop.operand is not None: - self._closure_scan_captures(trans, uop.operand) + if uop.operand is not None: self._closure_scan_captures(trans, uop.operand) return 1 if k == ast.ASTKind.BoolOp: bop2: rawptr[ast.BoolOp] = rawptr[ast.BoolOp](node) if bop2.values is not None: bn_bo: sizet = len(bop2.values) - for bi_bo in range(bn_bo): - self._closure_scan_captures(trans, bop2.values.get(bi_bo)) + for bi_bo in range(bn_bo): self._closure_scan_captures(trans, bop2.values.get(bi_bo)) return 1 if k == ast.ASTKind.Compare: cmp: rawptr[ast.Compare] = rawptr[ast.Compare](node) - if cmp.left is not None: - self._closure_scan_captures(trans, cmp.left) + if cmp.left is not None: self._closure_scan_captures(trans, cmp.left) if cmp.comparators is not None: bn_cmp: sizet = len(cmp.comparators) - for bi_cmp in range(bn_cmp): - self._closure_scan_captures(trans, cmp.comparators.get(bi_cmp)) + for bi_cmp in range(bn_cmp): self._closure_scan_captures(trans, cmp.comparators.get(bi_cmp)) return 1 if k == ast.ASTKind.Call: cal: ast.Call* = ast.Call*(node) - if cal.func is not None: - self._closure_scan_captures(trans, cal.func) + if cal.func is not None: self._closure_scan_captures(trans, cal.func) if cal.args is not None: bn_ca: sizet = len(cal.args) - for bi_ca in range(bn_ca): - self._closure_scan_captures(trans, cal.args.get(bi_ca)) + for bi_ca in range(bn_ca): self._closure_scan_captures(trans, cal.args.get(bi_ca)) if cal.keywords is not None: bn_ck: sizet = len(cal.keywords) for bi_ck in range(bn_ck): kw_n: ast.AST* = cal.keywords.get(bi_ck) if kw_n is not None and kw_n.kind() == ast.ASTKind.Keyword: kw_c: rawptr[ast.Keyword] = rawptr[ast.Keyword](kw_n) - if kw_c.value is not None: - self._closure_scan_captures(trans, kw_c.value) + if kw_c.value is not None: self._closure_scan_captures(trans, kw_c.value) return 1 if k == ast.ASTKind.Subscript: sub: ast.Subscript* = ast.Subscript*(node) - if sub.value is not None: - self._closure_scan_captures(trans, sub.value) - if sub.slice is not None: - self._closure_scan_captures(trans, sub.slice) + if sub.value is not None: self._closure_scan_captures(trans, sub.value) + if sub.slice is not None: self._closure_scan_captures(trans, sub.slice) return 1 if k == ast.ASTKind.Attribute: at_n: ast.Attribute* = ast.Attribute*(node) - if at_n.value is not None: - self._closure_scan_captures(trans, at_n.value) + if at_n.value is not None: self._closure_scan_captures(trans, at_n.value) return 1 if k == ast.ASTKind.IfExp: ie: rawptr[ast.IfExp] = rawptr[ast.IfExp](node) - if ie.test is not None: - self._closure_scan_captures(trans, ie.test) - if ie.body is not None: - self._closure_scan_captures(trans, ie.body) - if ie.orelse is not None: - self._closure_scan_captures(trans, ie.orelse) + if ie.test is not None: self._closure_scan_captures(trans, ie.test) + if ie.body is not None: self._closure_scan_captures(trans, ie.body) + if ie.orelse is not None: self._closure_scan_captures(trans, ie.orelse) return 1 if k == ast.ASTKind.Dict: dc: rawptr[ast.Dict] = rawptr[ast.Dict](node) if dc.keys is not None: bn_dk: sizet = len(dc.keys) - for bi_dk in range(bn_dk): - self._closure_scan_captures(trans, dc.keys.get(bi_dk)) + for bi_dk in range(bn_dk): self._closure_scan_captures(trans, dc.keys.get(bi_dk)) if dc.values is not None: bn_dv: sizet = len(dc.values) - for bi_dv in range(bn_dv): - self._closure_scan_captures(trans, dc.values.get(bi_dv)) + for bi_dv in range(bn_dv): self._closure_scan_captures(trans, dc.values.get(bi_dv)) return 1 if k == ast.ASTKind.Set: st_n: rawptr[ast.Set] = rawptr[ast.Set](node) if st_n.elts is not None: bn_set: sizet = len(st_n.elts) - for bi_set in range(bn_set): - self._closure_scan_captures(trans, st_n.elts.get(bi_set)) + for bi_set in range(bn_set): self._closure_scan_captures(trans, st_n.elts.get(bi_set)) return 1 if k == ast.ASTKind.List: ls_n: ast.List* = ast.List*(node) if ls_n.elts is not None: bn_ls: sizet = len(ls_n.elts) - for bi_ls in range(bn_ls): - self._closure_scan_captures(trans, ls_n.elts.get(bi_ls)) + for bi_ls in range(bn_ls): self._closure_scan_captures(trans, ls_n.elts.get(bi_ls)) return 1 if k == ast.ASTKind.Tuple: tp_n: ast.Tuple* = ast.Tuple*(node) if tp_n.elts is not None: bn_tp: sizet = len(tp_n.elts) - for bi_tp in range(bn_tp): - self._closure_scan_captures(trans, tp_n.elts.get(bi_tp)) + for bi_tp in range(bn_tp): self._closure_scan_captures(trans, tp_n.elts.get(bi_tp)) return 1 if k == ast.ASTKind.Starred: sr_n: rawptr[ast.Starred] = rawptr[ast.Starred](node) - if sr_n.value is not None: - self._closure_scan_captures(trans, sr_n.value) + if sr_n.value is not None: self._closure_scan_captures(trans, sr_n.value) return 1 if k == ast.ASTKind.NamedExpr: ne_n: rawptr[ast.NamedExpr] = rawptr[ast.NamedExpr](node) - if ne_n.value is not None: - self._closure_scan_captures(trans, ne_n.value) + if ne_n.value is not None: self._closure_scan_captures(trans, ne_n.value) return 1 if k == ast.ASTKind.Slice: sl_n: rawptr[ast.Slice] = rawptr[ast.Slice](node) - if sl_n.lower is not None: - self._closure_scan_captures(trans, sl_n.lower) - if sl_n.upper is not None: - self._closure_scan_captures(trans, sl_n.upper) - if sl_n.step is not None: - self._closure_scan_captures(trans, sl_n.step) + if sl_n.lower is not None: self._closure_scan_captures(trans, sl_n.lower) + if sl_n.upper is not None: self._closure_scan_captures(trans, sl_n.upper) + if sl_n.step is not None: self._closure_scan_captures(trans, sl_n.step) return 1 if k == ast.ASTKind.JoinedStr: js_n: rawptr[ast.JoinedStr] = rawptr[ast.JoinedStr](node) if js_n.values is not None: bn_js: sizet = len(js_n.values) - for bi_js in range(bn_js): - self._closure_scan_captures(trans, js_n.values.get(bi_js)) + for bi_js in range(bn_js): self._closure_scan_captures(trans, js_n.values.get(bi_js)) return 1 if k == ast.ASTKind.FormattedValue: fv_n: rawptr[ast.FormattedValue] = rawptr[ast.FormattedValue](node) - if fv_n.value is not None: - self._closure_scan_captures(trans, fv_n.value) - if fv_n.format_spec is not None: - self._closure_scan_captures(trans, fv_n.format_spec) + if fv_n.value is not None: self._closure_scan_captures(trans, fv_n.value) + if fv_n.format_spec is not None: self._closure_scan_captures(trans, fv_n.format_spec) return 1 if k == ast.ASTKind.Await: aw_n: rawptr[ast.Await] = rawptr[ast.Await](node) - if aw_n.value is not None: - self._closure_scan_captures(trans, aw_n.value) + if aw_n.value is not None: self._closure_scan_captures(trans, aw_n.value) return 1 if k == ast.ASTKind.Yield: yd_n: rawptr[ast.Yield] = rawptr[ast.Yield](node) - if yd_n.value is not None: - self._closure_scan_captures(trans, yd_n.value) + if yd_n.value is not None: self._closure_scan_captures(trans, yd_n.value) return 1 if k == ast.ASTKind.YieldFrom: yf_n: rawptr[ast.YieldFrom] = rawptr[ast.YieldFrom](node) - if yf_n.value is not None: - self._closure_scan_captures(trans, yf_n.value) + if yf_n.value is not None: self._closure_scan_captures(trans, yf_n.value) return 1 is_comp: int = 0 - if k == ast.ASTKind.ListComp: - is_comp = 1 - elif k == ast.ASTKind.SetComp: - is_comp = 1 - elif k == ast.ASTKind.GeneratorExp: - is_comp = 1 + if k == ast.ASTKind.ListComp: is_comp = 1 + elif k == ast.ASTKind.SetComp: is_comp = 1 + elif k == ast.ASTKind.GeneratorExp: is_comp = 1 if is_comp != 0: lc_n: rawptr[ast.ListComp] = rawptr[ast.ListComp](node) - if lc_n.elt is not None: - self._closure_scan_captures(trans, lc_n.elt) + if lc_n.elt is not None: self._closure_scan_captures(trans, lc_n.elt) if lc_n.generators is not None: bn_gen: sizet = len(lc_n.generators) for bi_gen in range(bn_gen): cp_n: ast.AST* = lc_n.generators.get(bi_gen) if cp_n is not None and cp_n.kind() == ast.ASTKind.Comprehension: cp_c: rawptr[ast.Comprehension] = rawptr[ast.Comprehension](cp_n) - if cp_c.iter is not None: - self._closure_scan_captures(trans, cp_c.iter) + if cp_c.iter is not None: self._closure_scan_captures(trans, cp_c.iter) if cp_c.ifs is not None: bn_cpi: sizet = len(cp_c.ifs) - for bi_cpi in range(bn_cpi): - self._closure_scan_captures(trans, cp_c.ifs.get(bi_cpi)) + for bi_cpi in range(bn_cpi): self._closure_scan_captures(trans, cp_c.ifs.get(bi_cpi)) return 1 if k == ast.ASTKind.DictComp: dcn: rawptr[ast.DictComp] = rawptr[ast.DictComp](node) - if dcn.key is not None: - self._closure_scan_captures(trans, dcn.key) - if dcn.value is not None: - self._closure_scan_captures(trans, dcn.value) + if dcn.key is not None: self._closure_scan_captures(trans, dcn.key) + if dcn.value is not None: self._closure_scan_captures(trans, dcn.value) if dcn.generators is not None: bn_dgen: sizet = len(dcn.generators) for bi_dgen in range(bn_dgen): cp_dn: ast.AST* = dcn.generators.get(bi_dgen) if cp_dn is not None and cp_dn.kind() == ast.ASTKind.Comprehension: cp_dc: rawptr[ast.Comprehension] = rawptr[ast.Comprehension](cp_dn) - if cp_dc.iter is not None: - self._closure_scan_captures(trans, cp_dc.iter) + if cp_dc.iter is not None: self._closure_scan_captures(trans, cp_dc.iter) if cp_dc.ifs is not None: bn_dcpi: sizet = len(cp_dc.ifs) - for bi_dcpi in range(bn_dcpi): - self._closure_scan_captures(trans, cp_dc.ifs.get(bi_dcpi)) + for bi_dcpi in range(bn_dcpi): self._closure_scan_captures(trans, cp_dc.ifs.get(bi_dcpi)) return 1 return 1 @@ -842,12 +740,10 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): trans: HT.Translator*, name: str) -> str: """构造 nonlocal 堆地址全局映射变量名 nlheap_{sha1}.{name}""" - if pool is None or trans is None or name is None: - return None + if pool is None or trans is None or name is None: return None mangled: str = self.Gen.FuncGenBase._mangle_name(trans, name) buf: str = pool.alloc(160) - if buf is not None: - viperlib.snprintf(buf, 160, "nlheap_%s", mangled) + if buf is not None: viperlib.snprintf(buf, 160, "nlheap_%s", mangled) return buf # ============================================================ @@ -857,16 +753,13 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): trans: HT.Translator*, name: str) -> mlirlite.Value*: """获取 nonlocal 堆地址全局映射变量的引用(@"..." 引号包裹)""" - if pool is None or trans is None or name is None: - return None + if pool is None or trans is None or name is None: return None gname: str = self._nl_heap_global_name(pool, trans, name) - if gname is None: - return None + if gname is None: return None i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty) ref_buf: str = pool.alloc(176) - if ref_buf is None: - return None + if ref_buf is None: return None viperlib.snprintf(ref_buf, 176, "@\"%s\"", gname) return mlirlite.SSAValue(pool, mlirlite.Ptr(pool, i8_ptr_ty), ref_buf) @@ -876,12 +769,10 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): def _nl_heap_global_exists(self, mod: mlirlite.LLVMModule*, gname: str) -> int: """检查全局映射变量 gname 是否已在模块中,1=存在""" - if mod is None or gname is None: - return 0 + if mod is None or gname is None: return 0 gcur: mlirlite.GlobalVariable* = mod.GlobalHead while gcur is not None: - if gcur.Name is not None and string.strcmp(gcur.Name, gname) == 0: - return 1 + if gcur.Name is not None and string.strcmp(gcur.Name, gname) == 0: return 1 gcur = gcur.Next return 0 @@ -896,20 +787,16 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): names: t.CPtr, count: int) -> int: """递归收集 node(FunctionDef)链内所有 nonlocal 声明名(去重)""" - if node is None or names is None: - return count + if node is None or names is None: return count fd: ast.FunctionDef* = ast.FunctionDef*(node) - if fd is None or fd.children is None: - return count + if fd is None or fd.children is None: return count ch: list[ast.AST*]* = fd.children cn: sizet = len(ch) for ci in range(cn): st: ast.AST* = ch.get(ci) - if st is None: - continue + if st is None: continue k: int = st.kind() - if k == ast.ASTKind.FunctionDef: - count = self._collect_chain_nonlocals(trans, st, names, count) + if k == ast.ASTKind.FunctionDef: count = self._collect_chain_nonlocals(trans, st, names, count) elif k == ast.ASTKind.Nonlocal: nl_node: rawptr[ast.Nonlocal] = rawptr[ast.Nonlocal](st) if nl_node is not None and nl_node.names is not None: @@ -917,11 +804,9 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): nn: sizet = len(nl_list) for ni in range(nn): nm_node: ast.AST* = nl_list.get(ni) - if nm_node is None: - continue + if nm_node is None: continue nm_x: ast.Name* = ast.Name*(nm_node) - if nm_x is None or nm_x.id is None: - continue + if nm_x is None or nm_x.id is None: continue dup: int = 0 for di in range(count): if string.strcmp((str)(uint64(names) + di * 8), nm_x.id) == 0: @@ -957,8 +842,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): if trans._nl_chain_done != 0: return 1 if trans._nl_chain_names is None: trans._nl_chain_names = pool.alloc(8 * 64) - if trans._nl_chain_names is not None: - string.memset(trans._nl_chain_names, 0, 8 * 64) + if trans._nl_chain_names is not None: string.memset(trans._nl_chain_names, 0, 8 * 64) if trans._nl_chain_names is None: return 0 trans._nl_chain_count = self._collect_chain_nonlocals(trans, node, trans._nl_chain_names, 0) trans._nl_chain_done = 1 @@ -979,21 +863,17 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): # store 指令每次照发。 st_size: int = self._type_byte_size(pool, nl_ty) st_size_val: mlirlite.Value* = mlirlite.const_int64(pool, st_size) - if st_size_val is not None: - st_size_val.Next = None + if st_size_val is not None: st_size_val.Next = None var_storage: mlirlite.Value* = mlirlite.build_call(builder, "malloc", st_size_val, 1, i8_ptr_ty, 0) - if var_storage is None: - continue + if var_storage is None: continue cur_val: mlirlite.Value* = mlirlite.build_load(builder, nl_ty, local_alloca) st_slot: mlirlite.Value* = mlirlite.build_bitcast(builder, var_storage, mlirlite.Ptr(pool, nl_ty)) - if st_slot is not None and cur_val is not None: - mlirlite.build_store(builder, cur_val, st_slot) + if st_slot is not None and cur_val is not None: mlirlite.build_store(builder, cur_val, st_slot) # 重定向 VarEntry(父函数读写走共享堆) ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nl_name) if ve is not None: heap_typed: mlirlite.Value* = mlirlite.build_bitcast(builder, var_storage, mlirlite.Ptr(pool, nl_ty)) - if heap_typed is not None: - ve.Alloca = heap_typed + if heap_typed is not None: ve.Alloca = heap_typed # 创建/复用全局映射变量并 store 堆地址(跨函数可见) gv_found: mlirlite.GlobalVariable* = None gcur: mlirlite.GlobalVariable* = mod.GlobalHead @@ -1012,8 +892,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): mlirlite.module_add_global(mod, gv_found) if gv_found is not None: gv_ref: mlirlite.Value* = self._nl_heap_global_ref(pool, trans, nl_name) - if gv_ref is not None: - mlirlite.build_store(builder, var_storage, gv_ref) + if gv_ref is not None: mlirlite.build_store(builder, var_storage, gv_ref) return 1 # ============================================================ @@ -1033,11 +912,9 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): node: ast.AST*, trans: HT.Translator* = None) -> mlirlite.Value*: """翻译 lambda 表达式,返回闭包指针(i8*)""" - if node is None or trans is None or builder is None: - return None + if node is None or trans is None or builder is None: return None lam: rawptr[ast.Lambda] = rawptr[ast.Lambda](node) - if lam is None: - return None + if lam is None: return None i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) @@ -1051,19 +928,16 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): lambda_id: int = trans._lambda_count trans._lambda_count += 1 pname_buf: str = pool.alloc(64) - if pname_buf is None: - return None + if pname_buf is None: return None viperlib.snprintf(pname_buf, 64, "__lambda_%d", lambda_id) mangled_promoted: str = self.Gen.FuncGenBase._mangle_name(trans, pname_buf) # 2. 解析参数(名称 + 类型,类型默认 i32,有注解则解析) param_names: str = pool.alloc(32 * 64) # 64 参数 × 32 字节名 - if param_names is None: - return None + if param_names is None: return None string.memset(param_names, 0, 32 * 64) param_tys: t.CPtr = pool.alloc(8 * 64) # LLVMType 指针槽 - if param_tys is None: - return None + if param_tys is None: return None string.memset(param_tys, 0, 8 * 64) param_count: int = 0 if lam.args is not None: @@ -1072,11 +946,9 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): alist: list[ast.AST*]* = ags.args pn: sizet = len(alist) for pi in range(pn): - if param_count >= 64: - break + if param_count >= 64: break arg_n: ast.Arg* = ast.Arg*(alist.get(pi)) - if arg_n is None or arg_n.arg is None: - continue + if arg_n is None or arg_n.arg is None: continue string.strncpy(param_names + param_count * 32, arg_n.arg, 31) p_ty: mlirlite.LLVMType* = i32_ty if arg_n.annotation is not None: @@ -1099,16 +971,13 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): # 3. 收集捕获变量(body 中的外部 Name 引用) cap_names: str = pool.alloc(64 * 64) # 64 捕获 × 64 字节名 - if cap_names is None: - return None + if cap_names is None: return None string.memset(cap_names, 0, 64 * 64) cap_allocas: t.CPtr = pool.alloc(8 * 64) # 父函数 alloca 指针槽 - if cap_allocas is None: - return None + if cap_allocas is None: return None string.memset(cap_allocas, 0, 8 * 64) cap_tys: t.CPtr = pool.alloc(8 * 64) # 捕获变量类型槽 - if cap_tys is None: - return None + if cap_tys is None: return None string.memset(cap_tys, 0, 8 * 64) cap_count: int = self._lambda_scan_body(trans, lam.body, param_names, param_count, cap_names, cap_allocas, cap_tys, 0) @@ -1120,8 +989,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): ty_addr2: uint64 = uint64(param_tys) + pi2 * 8 ty_slot2: str* = str*(ty_addr2) p_ty2: mlirlite.LLVMType* = (mlirlite.LLVMType*)(ty_slot2[0]) - if p_ty2 is None: - p_ty2 = i32_ty + if p_ty2 is None: p_ty2 = i32_ty pname_l: str = pool.alloc(32) if pname_l is not None: viperlib.snprintf(pname_l, 32, "%%%s", param_names + pi2 * 32) @@ -1129,11 +997,9 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): # 5. entry 块 + builder entry_blk: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "entry") - if entry_blk is None: - return None + if entry_blk is None: return None func_builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, func) - if func_builder is None: - return None + if func_builder is None: return None mlirlite.position_at_end(func_builder, entry_blk) # --traceback: promoted lambda gets its own DISubprogram. @@ -1216,12 +1082,10 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): # 11. 翻译 body 表达式,coerce 到 i32 后 ret body_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(func_builder, pool, mod, lam.body, None, 0, trans) if body_val is not None and body_val.Ty is not None: - if self.Gen.ExprGenBase.get_llvm_type_bits(body_val.Ty) == 32 and self.Gen.ExprGenBase.is_ptr_type(body_val.Ty) == 0: - mlirlite.build_ret(func_builder, body_val) + if self.Gen.ExprGenBase.get_llvm_type_bits(body_val.Ty) == 32 and self.Gen.ExprGenBase.is_ptr_type(body_val.Ty) == 0: mlirlite.build_ret(func_builder, body_val) else: ret_val: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(func_builder, body_val, i32_ty, lam.body) - if ret_val is not None: - mlirlite.build_ret(func_builder, ret_val) + if ret_val is not None: mlirlite.build_ret(func_builder, ret_val) else: # fail-fast:lambda 体类型转换失败,不再静默 ret 0 self.Gen.TypeGenErr.fatal_error(lam.body, "lambda 体表达式翻译失败", "TypeError") @@ -1240,23 +1104,20 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): trans._global_name_count = old_global_count trans._nonlocal_name_count = old_nonlocal_count trans._closure_env_count = old_env_count - if dbg_pushed_l != 0: - DebugInfoGen.PopFunction(func_builder) + if dbg_pushed_l != 0: DebugInfoGen.PopFunction(func_builder) # 13. 在父函数中创建 env(每个捕获变量 8 字节堆存储,env[i] = 堆地址) env_ptr: mlirlite.Value* = None if cap_count > 0: env_size: int64 = cap_count * 8 env_size_val: mlirlite.Value* = mlirlite.const_int64(pool, env_size) - if env_size_val is not None: - env_size_val.Next = None + if env_size_val is not None: env_size_val.Next = None env_ptr = mlirlite.build_call(builder, "malloc", env_size_val, 1, i8_ptr_ty, 0) if env_ptr is not None: for ci3 in range(cap_count): # 与步骤 9 一致:str 指针偏移判空,避免整数转换 itoa 语义 cap_slot3: str = cap_names + ci3 * 64 - if cap_slot3[0] == '\0': - continue + if cap_slot3[0] == '\0': continue al_addr: uint64 = uint64(cap_allocas) + ci3 * 8 al_slot: str* = (str*)(al_addr) var_alloca2: mlirlite.Value* = (mlirlite.Value*)(al_slot[0]) @@ -1268,32 +1129,26 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): # 堆存储大小:位宽/8,至少 8 字节(容纳指针/标量) ty_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(cap_ty2) st_size: int = 8 - if ty_bits > 64: - st_size = ty_bits // 8 + if ty_bits > 64: st_size = ty_bits // 8 st_size_val: mlirlite.Value* = mlirlite.const_int64(pool, st_size) - if st_size_val is not None: - st_size_val.Next = None + if st_size_val is not None: st_size_val.Next = None var_storage: mlirlite.Value* = mlirlite.build_call(builder, "malloc", st_size_val, 1, i8_ptr_ty, 0) if var_storage is not None: cur_val: mlirlite.Value* = mlirlite.build_load(builder, cap_ty2, var_alloca2) if cur_val is not None: st_slot5: mlirlite.Value* = mlirlite.build_bitcast(builder, var_storage, mlirlite.Ptr(pool, cap_ty2)) - if st_slot5 is not None: - mlirlite.build_store(builder, cur_val, st_slot5) + if st_slot5 is not None: mlirlite.build_store(builder, cur_val, st_slot5) off_val2: mlirlite.Value* = mlirlite.const_int32(pool, ci3 * 8) slot2: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, env_ptr, off_val2) if slot2 is not None: slot_typed2: mlirlite.Value* = mlirlite.build_bitcast(builder, slot2, i8_ptr_ptr_ty) - if slot_typed2 is not None: - mlirlite.build_store(builder, var_storage, slot_typed2) + if slot_typed2 is not None: mlirlite.build_store(builder, var_storage, slot_typed2) # 14. 在父函数中创建闭包 malloc(16) closure_size_val: mlirlite.Value* = mlirlite.const_int64(pool, 16) - if closure_size_val is not None: - closure_size_val.Next = None + if closure_size_val is not None: closure_size_val.Next = None closure_ptr: mlirlite.Value* = mlirlite.build_call(builder, "malloc", closure_size_val, 1, i8_ptr_ty, 0) - if closure_ptr is None: - return None + if closure_ptr is None: return None # 15. [0] = fn_ptr(函数引用 bitcast 到 i8*) fn_param_node: mlirlite.ParamNode* = mlirlite.new_param_node(pool, i8_ptr_ty) @@ -1301,15 +1156,12 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): fn_func_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, fn_func_ty) fn_ptr_name: str = pool.alloc(64) if fn_ptr_name is not None: - if string.strchr(mangled_promoted, '.') is not None: - viperlib.snprintf(fn_ptr_name, 64, "@\"%s\"", mangled_promoted) - else: - viperlib.snprintf(fn_ptr_name, 64, "@%s", mangled_promoted) + if string.strchr(mangled_promoted, '.') is not None: viperlib.snprintf(fn_ptr_name, 64, "@\"%s\"", mangled_promoted) + else: viperlib.snprintf(fn_ptr_name, 64, "@%s", mangled_promoted) fn_ptr_val: mlirlite.Value* = mlirlite.SSAValue(pool, fn_func_ptr_ty, fn_ptr_name) fn_as_i8ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, fn_ptr_val, i8_ptr_ty) fn_slot: mlirlite.Value* = mlirlite.build_bitcast(builder, closure_ptr, mlirlite.Ptr(pool, i8_ptr_ty)) - if fn_slot is not None and fn_as_i8ptr is not None: - mlirlite.build_store(builder, fn_as_i8ptr, fn_slot) + if fn_slot is not None and fn_as_i8ptr is not None: mlirlite.build_store(builder, fn_as_i8ptr, fn_slot) # 16. [8] = env_ptr(无捕获存 null) eight_val: mlirlite.Value* = mlirlite.const_int32(pool, 8) @@ -1317,8 +1169,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): if env_slot_addr is not None: env_slot: mlirlite.Value* = mlirlite.build_bitcast(builder, env_slot_addr, mlirlite.Ptr(pool, i8_ptr_ty)) if env_slot is not None: - if env_ptr is not None: - mlirlite.build_store(builder, env_ptr, env_slot) + if env_ptr is not None: mlirlite.build_store(builder, env_ptr, env_slot) else: null_val: mlirlite.Value* = mlirlite.SSAValue(pool, i8_ptr_ty, "null") mlirlite.build_store(builder, null_val, env_slot) @@ -1342,35 +1193,27 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): cap_tys: t.CPtr, cap_count: int) -> int: """递归扫描 lambda body 中的 Name 引用,收集捕获变量""" - if node is None or trans is None: - return cap_count + if node is None or trans is None: return cap_count k: int = node.kind() if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) - if nm.id is None: - return cap_count + if nm.id is None: return cap_count # 排除 lambda 参数 for pi in range(param_count): - if string.strcmp(param_names + pi * 32, nm.id) == 0: - return cap_count + if string.strcmp(param_names + pi * 32, nm.id) == 0: return cap_count # 已捕获跳过 for ci in range(cap_count): - if string.strcmp(cap_names + ci * 64, nm.id) == 0: - return cap_count + if string.strcmp(cap_names + ci * 64, nm.id) == 0: return cap_count # 查当前作用域链 alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id) - if alloca is None or alloca.Ty is None: - return cap_count + if alloca is None or alloca.Ty is None: return cap_count pointee: mlirlite.LLVMType* = alloca.Ty.Pointee - if pointee is None: - return cap_count + if pointee is None: return cap_count # 跳过模块级全局(body 直接解析全局,无需 env 捕获) mod_gv: mlirlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm.id) if mod_gv is not None: - if uint64(mod_gv) == uint64(alloca): - return cap_count - if cap_count >= 64: - return cap_count + if uint64(mod_gv) == uint64(alloca): return cap_count + if cap_count >= 64: return cap_count string.strncpy(cap_names + cap_count * 64, nm.id, 63) al_slot: str* = (str*)(uint64(cap_allocas) + cap_count * 8) al_slot[0] = alloca diff --git a/App/lib/core/Gen/GenApi.vp b/App/lib/core/Gen/GenApi.vp index 722289a..e4a7694 100644 --- a/App/lib/core/Gen/GenApi.vp +++ b/App/lib/core/Gen/GenApi.vp @@ -25,15 +25,13 @@ _g_gen: Generator.Generator* = None # ---------------- set_temp_dir(委托 TypeGenBase.set_temp_dir) ---------------- def set_temp_dir(temp_dir: str) -> None: """委托到 gen.set_temp_dir(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.TypeGenBase.set_temp_dir(temp_dir) + if _g_gen is not None: _g_gen.TypeGenBase.set_temp_dir(temp_dir) # ---------------- set_current_file_imports(委托 ImportsGenMixin.set_current_file) ---------------- def set_current_file_imports(file_path: str) -> None: """委托到 gen.set_current_file(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.ImportsGen.set_current_file(file_path) + if _g_gen is not None: _g_gen.ImportsGen.set_current_file(file_path) # ---------------- set_current_file_type(委托 TypeGenResolve.set_current_file) ---------------- @@ -50,51 +48,44 @@ def set_current_file_type(file_path: str) -> None: _g_gen.TypeGenResolve.set_current_file(file_path) return gg: Generator.Generator* = Generator._g_gen - if gg is not None: - gg.TypeGenResolve.set_current_file(file_path) + if gg is not None: gg.TypeGenResolve.set_current_file(file_path) # ---------------- set_current_module_sha1(委托 TypeGenBase.set_current_module_sha1) ---------------- def set_current_module_sha1(sha1: str) -> None: """委托到 gen.set_current_module_sha1(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.TypeGenBase.set_current_module_sha1(sha1) + if _g_gen is not None: _g_gen.TypeGenBase.set_current_module_sha1(sha1) # ---------------- clear_trace(委托 TypeGenBase.clear_trace) ---------------- def clear_trace() -> None: """委托到 gen.clear_trace(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.TypeGenBase.clear_trace() + if _g_gen is not None: _g_gen.TypeGenBase.clear_trace() # ---------------- clear_cdefine_constants(委托 TypeGenCDef.clear_cdefine_constants) ---------------- def clear_cdefine_constants() -> None: """委托到 gen.clear_cdefine_constants(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.TypeGenCDef.clear_cdefine_constants() + if _g_gen is not None: _g_gen.TypeGenCDef.clear_cdefine_constants() # ---------------- clear_ctypedefs(委托 TypeGenCType.clear_ctypedefs) ---------------- def clear_ctypedefs() -> None: """委托到 gen.clear_ctypedefs(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.TypeGenCType.clear_ctypedefs() + if _g_gen is not None: _g_gen.TypeGenCType.clear_ctypedefs() # ---------------- RegisterCTypedefFromSource(委托 TypeGenCType.register_ctypedef_from_source) ---------------- def RegisterCTypedefFromSource(pool: memhub.MemBuddy*, src: str) -> int: """委托到 gen.register_ctypedef_from_source(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.TypeGenCType.register_ctypedef_from_source(pool, src) + if _g_gen is not None: _g_gen.TypeGenCType.register_ctypedef_from_source(pool, src) return 0 # ---------------- dump_parse_traceback(委托 TypeGenErr.dump_parse_traceback) ---------------- def dump_parse_traceback(file_path: str) -> None: """委托到 gen.dump_parse_traceback(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.TypeGenErr.dump_parse_traceback(file_path) + if _g_gen is not None: _g_gen.TypeGenErr.dump_parse_traceback(file_path) # ---------------- fatal_error(委托 TypeGenErr.fatal_error) ---------------- @@ -113,15 +104,13 @@ def fatal_error(node: ast.AST*, msg: str, _g_gen.TypeGenErr.fatal_error(node, msg, err_type) return gg: Generator.Generator* = Generator._g_gen - if gg is not None: - gg.TypeGenErr.fatal_error(node, msg, err_type) + if gg is not None: gg.TypeGenErr.fatal_error(node, msg, err_type) # ---------------- map_t_type(委托 TypeGenResolve.map_t_type) ---------------- def map_t_type(pool: memhub.MemBuddy*, type_name: str) -> mlirlite.LLVMType*: """委托到 gen.map_t_type(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.TypeGenResolve.map_t_type(pool, type_name) + if _g_gen is not None: _g_gen.TypeGenResolve.map_t_type(pool, type_name) return None @@ -132,8 +121,7 @@ def resolve_typedef_or_map(pool: memhub.MemBuddy*, from_imports: str, trans: HT.Translator* = None) -> mlirlite.LLVMType*: """委托到 gen.resolve_typedef_or_map(CTypedef 动态表优先,miss 回退 map_t_type)""" - if _g_gen is not None: - return _g_gen.TypeGenResolve.resolve_typedef_or_map(pool, name, imported_modules, from_imports, trans) + if _g_gen is not None: return _g_gen.TypeGenResolve.resolve_typedef_or_map(pool, name, imported_modules, from_imports, trans) return None @@ -148,32 +136,28 @@ def infer_external_func_ret_ty(pool: memhub.MemBuddy*, fatal_if_unknown=0:白名单未命中返回默认 i32(不 fail-fast,注入上下文 无法收敛判断交给调用侧)。 """ - if _g_gen is not None: - return _g_gen.CallGenLib._infer_external_func_ret_ty(pool, func_name, None, 0) + if _g_gen is not None: return _g_gen.CallGenLib._infer_external_func_ret_ty(pool, func_name, None, 0) return None # ---------------- get_current_file(委托 TypeGenResolve.get_current_file) ---------------- def get_current_file() -> str: """委托到 gen.get_current_file(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.TypeGenResolve.get_current_file() + if _g_gen is not None: return _g_gen.TypeGenResolve.get_current_file() return None # ---------------- _is_ctypedef_annotation(委托 TypeGenCType._is_ctypedef_annotation) ---------------- def _is_ctypedef_annotation(annotation: ast.AST*) -> int: """委托到 gen._is_ctypedef_annotation(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.TypeGenCType._is_ctypedef_annotation(annotation) + if _g_gen is not None: return _g_gen.TypeGenCType._is_ctypedef_annotation(annotation) return 0 # ---------------- resolve_annotation_type(委托 TypeGenResolve.resolve_annotation_type) ---------------- def resolve_annotation_type(pool: memhub.MemBuddy*, node: ast.AST*, imported_modules: str, from_imports: str, trans: HT.Translator* = None, depth: int = 0) -> mlirlite.LLVMType*: """委托到 gen.resolve_annotation_type(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.TypeGenResolve.resolve_annotation_type(pool, node, imported_modules, from_imports, trans, depth) + if _g_gen is not None: return _g_gen.TypeGenResolve.resolve_annotation_type(pool, node, imported_modules, from_imports, trans, depth) return None @@ -181,39 +165,34 @@ def resolve_annotation_type(pool: memhub.MemBuddy*, node: ast.AST*, imported_mod def has_decorator_marker(node: ast.AST*, marker_name: str, depth: int = 0) -> int: """委托到 gen.has_decorator_marker(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.TypeGenErr.has_decorator_marker(node, marker_name, depth) + if _g_gen is not None: return _g_gen.TypeGenErr.has_decorator_marker(node, marker_name, depth) return 0 # ---------------- _get_type_name_from_annotation(委托 TypeGenResolve._get_type_name_from_annotation) ---------------- def _get_type_name_from_annotation(pool: memhub.MemBuddy*, node: ast.AST*) -> str: """委托到 gen._get_type_name_from_annotation(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.TypeGenResolve._get_type_name_from_annotation(pool, node) + if _g_gen is not None: return _g_gen.TypeGenResolve._get_type_name_from_annotation(pool, node) return None # ---------------- register_ctypedef(委托 TypeGenCType.register_ctypedef) ---------------- def register_ctypedef(pool: memhub.MemBuddy*, name: str, type_str: str): """委托到 gen.register_ctypedef(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.TypeGenCType.register_ctypedef(pool, name, type_str) + if _g_gen is not None: _g_gen.TypeGenCType.register_ctypedef(pool, name, type_str) # ---------------- lookup_cdefine_constant(委托 TypeGenCDef.lookup_cdefine_constant) ---------------- def lookup_cdefine_constant(name: str) -> int64: """委托到 gen.lookup_cdefine_constant(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.TypeGenCDef.lookup_cdefine_constant(name) + if _g_gen is not None: return _g_gen.TypeGenCDef.lookup_cdefine_constant(name) return 0 # ---------------- is_cdefine_found(委托 TypeGenCDef.is_cdefine_found) ---------------- def is_cdefine_found() -> int: """委托到 gen.is_cdefine_found(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.TypeGenCDef.is_cdefine_found() + if _g_gen is not None: return _g_gen.TypeGenCDef.is_cdefine_found() return 0 @@ -221,91 +200,79 @@ def is_cdefine_found() -> int: def register_cdefine_constant(pool: memhub.MemBuddy*, name: str, value: int64): """委托到 gen.register_cdefine_constant(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.TypeGenCDef.register_cdefine_constant(pool, name, value) + if _g_gen is not None: _g_gen.TypeGenCDef.register_cdefine_constant(pool, name, value) # ---------------- register_cdefine_double(委托 TypeGenCDef.register_cdefine_double) ---------------- def register_cdefine_double(pool: memhub.MemBuddy*, name: str, value: double): """委托到 gen.register_cdefine_double(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.TypeGenCDef.register_cdefine_double(pool, name, value) + if _g_gen is not None: _g_gen.TypeGenCDef.register_cdefine_double(pool, name, value) # ---------------- is_cdefine_annotation(委托 AssignGenMixin.is_cdefine_annotation) ---------------- def is_cdefine_annotation(annot: ast.AST*) -> int: """委托到 gen.is_cdefine_annotation(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.AssignGen.is_cdefine_annotation(annot) + if _g_gen is not None: return _g_gen.AssignGen.is_cdefine_annotation(annot) return 0 # ---------------- extract_cdefine_int_value(委托 AssignGenMixin.extract_cdefine_int_value) ---------------- def extract_cdefine_int_value(val_node: ast.AST*) -> int64: """委托到 gen.extract_cdefine_int_value(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.AssignGen.extract_cdefine_int_value(val_node) + if _g_gen is not None: return _g_gen.AssignGen.extract_cdefine_int_value(val_node) return 0 # ---------------- push_trace(委托 TypeGenBase.push_trace) ---------------- def push_trace(file_name: str, lineno: int, col_start: int = 0, col_end: int = 0): """委托到 gen.push_trace(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.TypeGenBase.push_trace(file_name, lineno, col_start, col_end) + if _g_gen is not None: _g_gen.TypeGenBase.push_trace(file_name, lineno, col_start, col_end) # ---------------- pop_trace(委托 TypeGenBase.pop_trace) ---------------- def pop_trace(): """委托到 gen.pop_trace(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.TypeGenBase.pop_trace() + if _g_gen is not None: _g_gen.TypeGenBase.pop_trace() # ---------------- get_temp_dir(委托 TypeGenBase.get_temp_dir) ---------------- def get_temp_dir() -> str: """委托到 gen.get_temp_dir(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.TypeGenBase.get_temp_dir() + if _g_gen is not None: return _g_gen.TypeGenBase.get_temp_dir() return None # ---------------- reset_visible_structs(委托 StructGenMixin.reset_visible_structs) ---------------- def reset_visible_structs(pool: memhub.MemBuddy*, strict: int): """委托到 gen.reset_visible_structs(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.StructGen.reset_visible_structs(pool, strict) + if _g_gen is not None: _g_gen.StructGen.reset_visible_structs(pool, strict) # ---------------- set_stdlib_alloc(委托 StructGenMixin.set_stdlib_alloc) ---------------- def set_stdlib_alloc(flag: int): """委托到 gen.set_stdlib_alloc(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.StructGen.set_stdlib_alloc(flag) + if _g_gen is not None: _g_gen.StructGen.set_stdlib_alloc(flag) # ---------------- get_struct_count(委托 StructGenMixin.get_struct_count) ---------------- def get_struct_count() -> int: """委托到 gen.get_struct_count(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.StructGen.get_struct_count() + if _g_gen is not None: return _g_gen.StructGen.get_struct_count() return 0 # ---------------- reset_module_methods_emitted(委托 StructGenMixin.reset_module_methods_emitted) ---------------- def reset_module_methods_emitted(sha1: str) -> int: """委托到 gen.reset_module_methods_emitted(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.StructGen.reset_module_methods_emitted(sha1) + if _g_gen is not None: return _g_gen.StructGen.reset_module_methods_emitted(sha1) return 0 # ---------------- get_struct_type(委托 StructGenMixin.get_struct_type) ---------------- def get_struct_type(class_name: str) -> mlirlite.LLVMType*: """委托到 gen.get_struct_type(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.StructGen.get_struct_type(class_name) + if _g_gen is not None: return _g_gen.StructGen.get_struct_type(class_name) return None @@ -318,23 +285,20 @@ def get_enum_base_type(enum_name: str) -> mlirlite.LLVMType*: 落空必须回退枚举表取 BaseTy(通常 i32),否则跨模块函数返回类型 无法精确获取 → text.ll 缺失(依赖环)时永久 pending(Phase A 死锁根因)。 """ - if _g_gen is not None: - return _g_gen.StmtGenDecl.get_enum_base_type(enum_name) + if _g_gen is not None: return _g_gen.StmtGenDecl.get_enum_base_type(enum_name) return None # ---------------- add_visible_struct(委托 StructGenMixin.add_visible_struct) ---------------- def add_visible_struct(pool: memhub.MemBuddy*, name: str): """委托到 gen.add_visible_struct(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.StructGen.add_visible_struct(pool, name) + if _g_gen is not None: _g_gen.StructGen.add_visible_struct(pool, name) # ---------------- find_struct_by_module(委托 StructGenMixin.find_struct_by_module) ---------------- def find_struct_by_module(name: str, sha1: str) -> GenTypes.StructEntry*: """委托到 gen.find_struct_by_module(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.StructGen.find_struct_by_module(name, sha1) + if _g_gen is not None: return _g_gen.StructGen.find_struct_by_module(name, sha1) return None @@ -344,8 +308,7 @@ def mark_module_class(pool: memhub.MemBuddy*, sha1: str, name: str) -> None: 指向它。注入期(VpiReader)没有"类定义窗口",必须靠这一步让 `_norm_type_arg_name` 规则 5.5 的证据链能被查询(否则裸类名实参取不到定义模块 SHA1 ⇒ 特化名冻结成裸名版本,与该类自身翻译期的带前缀形式分裂)。""" - if _g_gen is not None: - _g_gen.StructGen.mark_module_class(pool, sha1, name) + if _g_gen is not None: _g_gen.StructGen.mark_module_class(pool, sha1, name) # ---------------- register_file_classes(委托 StructGenMixin.register_file_classes) ---------------- @@ -354,8 +317,7 @@ def register_file_classes(pool: memhub.MemBuddy*, sha1: str, tree: ast.AST*) -> 由 Translator.translate 的 prologue 调用(在翻译模块级变量/前向声明**之前**), 使"模块级语句早于类定义"这一窗口里裸类名也能判出归属。""" - if _g_gen is not None: - _g_gen.StructGen.register_file_classes(pool, sha1, tree) + if _g_gen is not None: _g_gen.StructGen.register_file_classes(pool, sha1, tree) # ---------------- register_file_funcs / is_file_func(委托 StructGenMixin) ---------------- @@ -365,22 +327,19 @@ def register_file_funcs(pool: memhub.MemBuddy*, tree: ast.AST*) -> None: 与 register_file_classes 同址调用(Translator 文件入口 prologue,早于依赖 vpi 注入):注入侧据此跳过"本文件已声明的裸名",避免依赖的 extern 声明顶掉本文件 自己的 extern 声明(现场 includes/socket.vp connect 被 w32.winsock2 顶掉)。""" - if _g_gen is not None: - _g_gen.StructGen.register_file_funcs(pool, tree) + if _g_gen is not None: _g_gen.StructGen.register_file_funcs(pool, tree) def is_file_func(name: str) -> int: """裸名是否为**本文件**顶层声明的函数(1=是 / 0=否)""" - if _g_gen is not None: - return _g_gen.StructGen.is_file_func(name) + if _g_gen is not None: return _g_gen.StructGen.is_file_func(name) return 0 # ---------------- find_struct_by_type(委托 StructGenMixin.find_struct_by_type) ---------------- def find_struct_by_type(struct_ty: mlirlite.LLVMType*) -> GenTypes.StructEntry*: """委托到 gen.find_struct_by_type(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.StructGen.find_struct_by_type(struct_ty) + if _g_gen is not None: return _g_gen.StructGen.find_struct_by_type(struct_ty) return None @@ -390,8 +349,7 @@ def register_struct(pool: memhub.MemBuddy*, struct_ty: mlirlite.LLVMType*, sha1: str = None) -> GenTypes.StructEntry*: """委托到 gen.register_struct(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.StructGen.register_struct(pool, name, struct_ty, sha1) + if _g_gen is not None: return _g_gen.StructGen.register_struct(pool, name, struct_ty, sha1) return None @@ -401,8 +359,7 @@ def add_field(pool: memhub.MemBuddy*, field_name: str, field_ty: mlirlite.LLVMType*) -> int: """委托到 gen.add_field(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.StructGen.add_field(pool, struct_entry, field_name, field_ty) + if _g_gen is not None: return _g_gen.StructGen.add_field(pool, struct_entry, field_name, field_ty) return -1 @@ -412,16 +369,14 @@ def register_struct_alias(pool: memhub.MemBuddy*, sha1: str, src_entry: GenTypes.StructEntry*) -> GenTypes.StructEntry*: """委托到 gen.StructGen.register_struct_alias(包重导出类别名注册,原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.StructGen.register_struct_alias(pool, name, sha1, src_entry) + if _g_gen is not None: return _g_gen.StructGen.register_struct_alias(pool, name, sha1, src_entry) return None # ---------------- get_stdlib_alloc(委托 StructGenMixin.get_stdlib_alloc) ---------------- def get_stdlib_alloc() -> int: """委托到 gen.get_stdlib_alloc(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.StructGen.get_stdlib_alloc() + if _g_gen is not None: return _g_gen.StructGen.get_stdlib_alloc() return 0 @@ -429,16 +384,14 @@ def get_stdlib_alloc() -> int: # ---------------- compute_package_from_relpath(委托 ImportsGenMixin.compute_package_from_relpath) ---------------- def compute_package_from_relpath(pool: memhub.MemBuddy*, rel_path: str) -> str: """委托到 gen.compute_package_from_relpath(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.ImportsGen.compute_package_from_relpath(pool, rel_path) + if _g_gen is not None: return _g_gen.ImportsGen.compute_package_from_relpath(pool, rel_path) return None # ---------------- is_module_imported(委托 ImportsGenMixin.is_module_imported) ---------------- def is_module_imported(imported_modules: str, name: str) -> int: """委托到 gen.is_module_imported(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.ImportsGen.is_module_imported(imported_modules, name) + if _g_gen is not None: return _g_gen.ImportsGen.is_module_imported(imported_modules, name) return 0 @@ -455,102 +408,86 @@ def is_module_imported(imported_modules: str, name: str) -> int: # ============================================================ def sha1_prefix_len(name: str) -> int: """名字若是 "{16位小写hex}." 形态返回 17(前缀字节数),否则返回 0""" - if name is None: - return 0 - if string.strlen(name) < 17: - return 0 - if name[16] != '.': - return 0 + if name is None: return 0 + if string.strlen(name) < 17: return 0 + if name[16] != '.': return 0 i: sizet for i in range(16): c: int = name[i] # 48-57 = '0'-'9',97-102 = 'a'-'f' - if not ((c >= 48 and c <= 57) or (c >= 97 and c <= 102)): - return 0 + if not ((c >= 48 and c <= 57) or (c >= 97 and c <= 102)): return 0 return 17 def is_sha1_hex16(seg: str) -> int: """seg 是否恰为 16 位小写 hex(SHA1 模块段),1=是 / 0=否""" - if seg is None: - return 0 - if string.strlen(seg) != 16: - return 0 + if seg is None: return 0 + if string.strlen(seg) != 16: return 0 i: sizet for i in range(16): c: int = seg[i] - if not ((c >= 48 and c <= 57) or (c >= 97 and c <= 102)): - return 0 + if not ((c >= 48 and c <= 57) or (c >= 97 and c <= 102)): return 0 return 1 # ---------------- add_imported_module(委托 ImportsGenMixin.add_imported_module) ---------------- def add_imported_module(pool: memhub.MemBuddy*, imported_modules: str, name: str) -> str: """委托到 gen.add_imported_module(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.ImportsGen.add_imported_module(pool, imported_modules, name) + if _g_gen is not None: return _g_gen.ImportsGen.add_imported_module(pool, imported_modules, name) return None # ---------------- translate_import(委托 ImportsGenMixin.translate_import) ---------------- def translate_import(trans: HT.Translator*, node: ast.AST*) -> int: """委托到 gen.translate_import(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.ImportsGen.translate_import(trans, node) + if _g_gen is not None: return _g_gen.ImportsGen.translate_import(trans, node) return 0 # ---------------- translate_import_from_module(委托 ImportsGenMixin.translate_import_from_module) ---------------- def translate_import_from_module(trans: HT.Translator*, node: ast.AST*) -> int: """委托到 gen.translate_import_from_module(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.ImportsGen.translate_import_from_module(trans, node) + if _g_gen is not None: return _g_gen.ImportsGen.translate_import_from_module(trans, node) return 0 # ---------------- translate_import_from_names(委托 ImportsGenMixin.translate_import_from_names) ---------------- def translate_import_from_names(trans: HT.Translator*, node: ast.AST*) -> int: """委托到 gen.translate_import_from_names(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.ImportsGen.translate_import_from_names(trans, node) + if _g_gen is not None: return _g_gen.ImportsGen.translate_import_from_names(trans, node) return 0 # ---------------- _get_parent_class(委托 ClassGenBase._get_parent_class) ---------------- def _get_parent_class(cd: ast.ClassDef*, trans: HT.Translator* = None) -> str: """委托到 gen._get_parent_class(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.ClassGenBase._get_parent_class(cd, trans) + if _g_gen is not None: return _g_gen.ClassGenBase._get_parent_class(cd, trans) return None # ---------------- _register_generic_template(委托 ClassGenGeneric._register_generic_template) ---------------- def _register_generic_template(pool: memhub.MemBuddy*, cd: ast.ClassDef*, module_sha1: str): """委托到 gen._register_generic_template(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.ClassGenGeneric._register_generic_template(pool, cd, module_sha1) + if _g_gen is not None: _g_gen.ClassGenGeneric._register_generic_template(pool, cd, module_sha1) # ---------------- _register_generic_func_template(委托 ClassGenGeneric._register_generic_func_template) ---------------- def _register_generic_func_template(pool: memhub.MemBuddy*, fd: ast.FunctionDef*, module_sha1: str): """委托到 gen.ClassGenGeneric._register_generic_func_template(扫描预注册用)""" - if _g_gen is not None: - _g_gen.ClassGenGeneric._register_generic_func_template(pool, fd, module_sha1) + if _g_gen is not None: _g_gen.ClassGenGeneric._register_generic_func_template(pool, fd, module_sha1) # ---------------- _mangle_name_with_sha1(委托 FuncGenBase._mangle_name_with_sha1) ---------------- def _mangle_name_with_sha1(sha1: str, name: str) -> str: """委托到 gen._mangle_name_with_sha1(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.FuncGenBase._mangle_name_with_sha1(sha1, name) + if _g_gen is not None: return _g_gen.FuncGenBase._mangle_name_with_sha1(sha1, name) return None # ---------------- forward_declare_functions(委托 FuncGenDef.forward_declare_functions) ---------------- def forward_declare_functions(trans: HT.Translator*, tree: ast.AST*) -> int: """委托到 gen.forward_declare_functions(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.FuncGenDef.forward_declare_functions(trans, tree) + if _g_gen is not None: return _g_gen.FuncGenDef.forward_declare_functions(trans, tree) return 0 @@ -575,12 +512,10 @@ def fail_if_fstring_escape(node: ast.AST*, where: str) -> int: where: 逃逸位置描述(如 "函数返回值" / "字段赋值" / "全局变量初始化")。 恒返回 0(命中即终止编译,不返回非 0 值)。 """ - if node is None: - return 0 + if node is None: return 0 hit: int = 0 k: int = node.kind() - if k == ast.ASTKind.JoinedStr or k == ast.ASTKind.FormattedValue: - hit = 1 + if k == ast.ASTKind.JoinedStr or k == ast.ASTKind.FormattedValue: hit = 1 elif k == ast.ASTKind.Tuple: tp: ast.Tuple* = ast.Tuple*(node) if tp.elts is not None: @@ -594,8 +529,7 @@ def fail_if_fstring_escape(node: ast.AST*, where: str) -> int: hit = 1 break i += 1 - if hit == 0: - return 0 + if hit == 0: return 0 if _g_gen is not None: _g_gen.TypeGenErr.fatal_error(node, f"f-string 结果不能用于{where}(逃逸):f-string 指向**当前函数的栈缓冲**," @@ -614,12 +548,10 @@ def escape_fstring_copy(src: str) -> str: 存全局 / 放进长期容器)必须显式拷贝。分配用 stdlib.malloc(CRT), 生命周期由调用方决定——编译器自身的报文构造只在错误路径使用,允许不回收。 """ - if src is None: - return None + if src is None: return None n: sizet = string.strlen(src) out: str = stdlib.malloc(n + 1) - if out is None: - return None + if out is None: return None string.strcpy(out, src) return out @@ -627,47 +559,41 @@ def escape_fstring_copy(src: str) -> str: # ---------------- create_wrapper_main(委托 TranslatorGenMixin.create_wrapper_main) ---------------- def create_wrapper_main(trans: HT.Translator*, tree: ast.AST*, i32_ty: mlirlite.LLVMType*) -> int: """委托到 gen.create_wrapper_main(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.TranslatorGen.create_wrapper_main(trans, tree, i32_ty) + if _g_gen is not None: return _g_gen.TranslatorGen.create_wrapper_main(trans, tree, i32_ty) return 0 # ---------------- handle_module_level_var(委托 TranslatorGenMixin.handle_module_level_var) ---------------- def handle_module_level_var(trans: HT.Translator*, node: ast.AST*) -> int: """委托到 gen.handle_module_level_var(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.TranslatorGen.handle_module_level_var(trans, node) + if _g_gen is not None: return _g_gen.TranslatorGen.handle_module_level_var(trans, node) return 0 # ---------------- translate_children(委托 TranslatorGenMixin.translate_children) ---------------- def translate_children(trans: HT.Translator*, tree: ast.AST*) -> int: """委托到 gen.translate_children(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.TranslatorGen.translate_children(trans, tree) + if _g_gen is not None: return _g_gen.TranslatorGen.translate_children(trans, tree) return 0 # ---------------- init_symbol_table(委托 VarGenMixin.init_symbol_table) ---------------- def init_symbol_table(pool: memhub.MemBuddy*) -> rawptr[GenTypes.SymbolTable]: """委托到 gen.init_symbol_table(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.VarGen.init_symbol_table(pool) + if _g_gen is not None: return _g_gen.VarGen.init_symbol_table(pool) return None # ---------------- SetTempDir(委托 CallGenBase.SetTempDir) ---------------- def SetTempDir(temp_dir: str): """委托到 gen.SetTempDir(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.CallGenBase.SetTempDir(temp_dir) + if _g_gen is not None: _g_gen.CallGenBase.SetTempDir(temp_dir) # ---------------- find_func_in_module(委托 CallGenBase.find_func_in_module) ---------------- def find_func_in_module(mod: mlirlite.LLVMModule*, name: str) -> mlirlite.Function*: """委托到 gen.find_func_in_module(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.CallGenBase.find_func_in_module(mod, name) + if _g_gen is not None: return _g_gen.CallGenBase.find_func_in_module(mod, name) return None @@ -677,53 +603,46 @@ def add_func_to_table(funcs: GenTypes.FuncEntry*, func_count: int, name: str, fu def_sha1:定义该函数的模块 SHA1(依赖注入路径必须传,避免默认值被挂到导入方名下) """ - if _g_gen is not None: - return _g_gen.CallGenLeafKit.add_func_to_table(funcs, func_count, name, func, max_count, defaults, default_count, param_count, pool, def_sha1) + if _g_gen is not None: return _g_gen.CallGenLeafKit.add_func_to_table(funcs, func_count, name, func, max_count, defaults, default_count, param_count, pool, def_sha1) return 0 # ---------------- init_func_table(委托 CallGenLeafKit.init_func_table) ---------------- def init_func_table(pool: memhub.MemBuddy*, max_count: int) -> GenTypes.FuncEntry*: """委托到 gen.init_func_table(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.CallGenLeafKit.init_func_table(pool, max_count) + if _g_gen is not None: return _g_gen.CallGenLeafKit.init_func_table(pool, max_count) return None # ---------------- translate_call(委托 CallGenMixin.translate_call) ---------------- def translate_call(pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, node: ast.AST*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator* = None) -> mlirlite.Value*: """委托到 gen.translate_call(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.CallGen.translate_call(pool, builder, mod, node, funcs_ptr, func_count, trans) + if _g_gen is not None: return _g_gen.CallGen.translate_call(pool, builder, mod, node, funcs_ptr, func_count, trans) return None # ---------------- translate_printf_call(委托 CallGenLeafKit.translate_printf_call) ---------------- def translate_printf_call(pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, trans: HT.Translator* = None): """委托到 gen.translate_printf_call(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.CallGenLeafKit.translate_printf_call(pool, builder, mod, cl, trans) + if _g_gen is not None: _g_gen.CallGenLeafKit.translate_printf_call(pool, builder, mod, cl, trans) # ---------------- translate_print_call(委托 CallGenLeafKit.translate_print_call) ---------------- def translate_print_call(pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, trans: HT.Translator* = None): """委托到 gen.translate_print_call(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.CallGenLeafKit.translate_print_call(pool, builder, mod, cl, trans) + if _g_gen is not None: _g_gen.CallGenLeafKit.translate_print_call(pool, builder, mod, cl, trans) # ---------------- add_global_name(委托 TranslatorGenMixin.add_global_name) ---------------- def add_global_name(trans: HT.Translator*, name: str): """委托到 gen.TranslatorGen.add_global_name(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.TranslatorGen.add_global_name(trans, name) + if _g_gen is not None: _g_gen.TranslatorGen.add_global_name(trans, name) # ---------------- is_global_name(委托 TranslatorGenMixin.is_global_name) ---------------- def is_global_name(trans: HT.Translator*, name: str) -> int: """委托到 gen.TranslatorGen.is_global_name(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.TranslatorGen.is_global_name(trans, name) + if _g_gen is not None: return _g_gen.TranslatorGen.is_global_name(trans, name) return 0 @@ -731,46 +650,40 @@ def is_global_name(trans: HT.Translator*, name: str) -> int: def add_nonlocal_name(trans: HT.Translator*, name: str, var_ty: mlirlite.LLVMType* = None): """委托到 gen.TranslatorGen.add_nonlocal_name(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.TranslatorGen.add_nonlocal_name(trans, name, var_ty) + if _g_gen is not None: _g_gen.TranslatorGen.add_nonlocal_name(trans, name, var_ty) # ---------------- get_nonlocal_type(委托 TranslatorGenMixin.get_nonlocal_type) ---------------- def get_nonlocal_type(trans: HT.Translator*, name: str) -> mlirlite.LLVMType*: """委托到 gen.TranslatorGen.get_nonlocal_type(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.TranslatorGen.get_nonlocal_type(trans, name) + if _g_gen is not None: return _g_gen.TranslatorGen.get_nonlocal_type(trans, name) return None # ---------------- is_nonlocal_name(委托 TranslatorGenMixin.is_nonlocal_name) ---------------- def is_nonlocal_name(trans: HT.Translator*, name: str) -> int: """委托到 gen.TranslatorGen.is_nonlocal_name(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.TranslatorGen.is_nonlocal_name(trans, name) + if _g_gen is not None: return _g_gen.TranslatorGen.is_nonlocal_name(trans, name) return 0 # ---------------- get_nonlocal_index(委托 TranslatorGenMixin.get_nonlocal_index) ---------------- def get_nonlocal_index(trans: HT.Translator*, name: str) -> int: """委托到 gen.TranslatorGen.get_nonlocal_index(原 Handles 壳)""" - if _g_gen is not None: - return _g_gen.TranslatorGen.get_nonlocal_index(trans, name) + if _g_gen is not None: return _g_gen.TranslatorGen.get_nonlocal_index(trans, name) return 0 # ---------------- clear_scope_names(委托 TranslatorGenMixin.clear_scope_names) ---------------- def clear_scope_names(trans: HT.Translator*): """委托到 gen.TranslatorGen.clear_scope_names(原 Handles 壳)""" - if _g_gen is not None: - _g_gen.TranslatorGen.clear_scope_names(trans) + if _g_gen is not None: _g_gen.TranslatorGen.clear_scope_names(trans) # ---------------- update_global_func_spec(委托 CallGenLeafKit.update_global_func_spec) ---------------- def update_global_func_spec(name: str, func: mlirlite.Function*) -> int: """委托到 gen.CallGenLeafKit.update_global_func_spec(原 ExprCallTable 壳)""" - if _g_gen is not None: - return _g_gen.CallGenLeafKit.update_global_func_spec(name, func) + if _g_gen is not None: return _g_gen.CallGenLeafKit.update_global_func_spec(name, func) return 0 diff --git a/App/lib/core/Gen/Generator.vp b/App/lib/core/Gen/Generator.vp index eba469d..12febe2 100644 --- a/App/lib/core/Gen/Generator.vp +++ b/App/lib/core/Gen/Generator.vp @@ -111,8 +111,7 @@ novirtual class Generator: TranslatorGen: rawptr[TranslatorGenMixin.TranslatorGenMixin] def __init__(self, pool: memhub.MemBuddy*): - if self is None: - return + if self is None: return # ---- alloc 46 个子对象 + 回指(永久池,fail-fast) ---- SubBaseGen: rawptr[BaseGenMixin.BaseGenMixin] = CompilerFactory.factory.PermPool.alloc(BaseGenMixin.BaseGenMixin.__sizeof__()) if SubBaseGen is None: diff --git a/App/lib/core/Gen/ImportsGenMixin.vp b/App/lib/core/Gen/ImportsGenMixin.vp index 9d27727..b6db411 100644 --- a/App/lib/core/Gen/ImportsGenMixin.vp +++ b/App/lib/core/Gen/ImportsGenMixin.vp @@ -71,11 +71,9 @@ novirtual class ImportsGenMixin: def _index_imported_module(self, old_ptr: str, new_ptr: str, name_ptr: str) -> None: """增量更新 imported_modules 索引(复用旧索引或新建,失败则解除绑定)""" - if new_ptr is None or name_ptr is None: - return + if new_ptr is None or name_ptr is None: return perm: memhub.MemBuddy* = CompilerFactory.factory.PermPool - if perm is None: - return + if perm is None: return idx: hashtable.HashTable* = None if old_ptr is None: # 新文件/新链首:建全新索引(旧索引随旧串一起废弃) @@ -93,8 +91,7 @@ novirtual class ImportsGenMixin: self.CurImportedModulesNames = None return # 同名已在(重复导入)则跳过;否则写入(key/value 均指向 new_ptr 内部) - if idx.__contains__(name_ptr) == 0: - idx.set_str(name_ptr, name_ptr) + if idx.__contains__(name_ptr) == 0: idx.set_str(name_ptr, name_ptr) self.CurImportedModulesPtr = new_ptr self.CurImportedModulesNames = idx @@ -107,11 +104,9 @@ novirtual class ImportsGenMixin: local_name: str, module_name: str, original_name: str) -> None: """增量更新 from_imports 索引(复用旧索引或新建,失败则解除绑定)""" - if new_ptr is None or local_name is None or module_name is None: - return + if new_ptr is None or local_name is None or module_name is None: return perm: memhub.MemBuddy* = CompilerFactory.factory.PermPool - if perm is None: - return + if perm is None: return idx_m: hashtable.HashTable* = None idx_o: hashtable.HashTable* = None if old_ptr is None: @@ -149,11 +144,9 @@ novirtual class ImportsGenMixin: # star import:模块名以最后一条为准(覆盖旧值,对齐 star_mod 语义) idx_m.set_str(key_ptr, mod_ptr) else: - if idx_m.__contains__(key_ptr) == 0: - idx_m.set_str(key_ptr, mod_ptr) + if idx_m.__contains__(key_ptr) == 0: idx_m.set_str(key_ptr, mod_ptr) if idx_o.__contains__(key_ptr) == 0: - if original_name is not None and string.strcmp(original_name, local_name) != 0 and string.strlen(original_name) > 0: - idx_o.set_str(key_ptr, mod_ptr + mod_len + 1) + if original_name is not None and string.strcmp(original_name, local_name) != 0 and string.strlen(original_name) > 0: idx_o.set_str(key_ptr, mod_ptr + mod_len + 1) else: # 首次出现即无别名(或别名为空)→ 该名查询返回 None(与逐字符扫描一致) idx_o.set_str(key_ptr, None) @@ -172,14 +165,11 @@ novirtual class ImportsGenMixin: 字符串记账走 StubMergerStore.AppendImportedModule(单一真源,与 vpi 注入期同源);本方法只额外维护查询索引。 """ - if name is None: - return imported_modules + if name is None: return imported_modules old_len: sizet = 0 - if imported_modules is not None: - old_len = string.strlen(imported_modules) + if imported_modules is not None: old_len = string.strlen(imported_modules) buf: str = StubMergerStore.AppendImportedModule(pool, imported_modules, name) - if buf is None: - return imported_modules + if buf is None: return imported_modules if imported_modules is None: # 索引:首个模块名(key 指向 buf 内部) self._index_imported_module(None, buf, buf) @@ -193,13 +183,11 @@ novirtual class ImportsGenMixin: # ============================================================ def is_module_imported(self, imported_modules: str, name: str) -> int: """检查模块是否已导入(词边界精确匹配,避免子串误匹配)""" - if name is None or imported_modules is None: - return 0 + if name is None or imported_modules is None: return 0 # [索引快路径] 传入串即当前索引绑定的串(trans 字段的常态)→ O(名字长) 哈希查; # 指针不匹配(stub 期 malloc 缓冲等)→ 回退下方逐字符扫描,语义不变。 if imported_modules == self.CurImportedModulesPtr and self.CurImportedModulesNames is not None: - if self.CurImportedModulesNames.__contains__(name) != 0: - return 1 + if self.CurImportedModulesNames.__contains__(name) != 0: return 1 # 索引未命中:绝不据此返回 0(索引不完整会误判"未导入"), # 落到下方原逐字符扫描按真实串内容判定(正确性优先 | 性能次之)。 name_len: sizet = string.strlen(name) @@ -207,13 +195,10 @@ novirtual class ImportsGenMixin: total_len: sizet = string.strlen(imported_modules) ci: sizet = 0 while ci < total_len: - while ci < total_len and cur[ci] == ' ': - ci += 1 - if ci >= total_len: - break + while ci < total_len and cur[ci] == ' ': ci += 1 + if ci >= total_len: break word_start: sizet = ci - while ci < total_len and cur[ci] != ' ': - ci += 1 + while ci < total_len and cur[ci] != ' ': ci += 1 word_len: sizet = ci - word_start if word_len == name_len: Matched: int = 1 @@ -221,8 +206,7 @@ novirtual class ImportsGenMixin: if cur[word_start + ei] != name[ei]: Matched = 0 break - if Matched == 1: - return 1 + if Matched == 1: return 1 return 0 # ============================================================ @@ -243,12 +227,9 @@ novirtual class ImportsGenMixin: (import intr → intr.gdt 可访问;`this.this()` 但 import this 被注释 → this 未导入 → 仍 fast-fail 报"模块未导入")。 """ - if self.is_module_imported(imported_modules, name) != 0: - return 1 - if name is None: - return 0 - if StubMergerStore.LookupSha1ByModName(name) is None: - return 0 + if self.is_module_imported(imported_modules, name) != 0: return 1 + if name is None: return 0 + if StubMergerStore.LookupSha1ByModName(name) is None: return 0 nl: sizet = string.strlen(name) dot_pos: sizet = 0 while dot_pos < nl: @@ -259,8 +240,7 @@ novirtual class ImportsGenMixin: pfx[dot_pos] = '\0' hit: int = self.is_module_imported(imported_modules, pfx) stdlib.free(pfx) - if hit != 0: - return 1 + if hit != 0: return 1 dot_pos += 1 return 0 @@ -282,19 +262,15 @@ novirtual class ImportsGenMixin: 字符串记账走 StubMergerStore.AppendFromImport(单一真源,与 vpi 注入期 同源;按精确长度分配,无旧的 256 缓冲静默截断);本方法只额外维护索引。 """ - if local_name is None or module_name is None: - return from_imports + if local_name is None or module_name is None: return from_imports old_len: sizet = 0 - if from_imports is not None: - old_len = string.strlen(from_imports) + if from_imports is not None: old_len = string.strlen(from_imports) buf: str = StubMergerStore.AppendFromImport( pool, from_imports, local_name, module_name, original_name) - if buf is None: - return from_imports + if buf is None: return from_imports # 索引:首条 entry_off=0;追加时 entry 从 buf[old_len+1] 开始 entry_off: sizet = 0 - if from_imports is not None: - entry_off = old_len + 1 + if from_imports is not None: entry_off = old_len + 1 self._index_from_import(from_imports, buf, entry_off, local_name, module_name, original_name) return buf @@ -308,15 +284,13 @@ novirtual class ImportsGenMixin: def lookup_from_import_original(self, from_imports: str, local_name: str) -> str: """查找 from-import 别名对应的原始函数名,返回 None=无别名或未找到""" - if local_name is None or from_imports is None: - return None + if local_name is None or from_imports is None: return None # [索引快路径] 传入串即当前索引绑定的串 → O(名字长) 哈希查;否则回退扫描。 # orig 表:名存在但存 None = 首次出现即无别名 → 返回 None(与扫描一致)。 if from_imports == self.CurFromImportsPtr and self.CurFromImportsOrigs is not None: if self.CurFromImportsOrigs.__contains__(local_name) != 0: v_o: t.CPtr = self.CurFromImportsOrigs.__getitem__(local_name) - if v_o is not None: - return rawptr(v_o) + if v_o is not None: return rawptr(v_o) # 索引未命中 | 值为 None(首个即无别名):绝不据此直接返回 None—— # 真实串可能仍含该名,落到下方原逐字符扫描按串内容判定(正确性优先)。 name_len: sizet = string.strlen(local_name) @@ -325,22 +299,17 @@ novirtual class ImportsGenMixin: total_len: sizet = string.strlen(from_imports) while ci < total_len: # 跳过前导空格 - while ci < total_len and cur[ci] == ' ': - ci += 1 - if ci >= total_len: - break + while ci < total_len and cur[ci] == ' ': ci += 1 + if ci >= total_len: break # 找到第一个 ':' 的位置 colon1: sizet = ci - while colon1 < total_len and cur[colon1] != ':' and cur[colon1] != ' ': - colon1 += 1 - if colon1 >= total_len or cur[colon1] != ':': - break + while colon1 < total_len and cur[colon1] != ':' and cur[colon1] != ' ': colon1 += 1 + if colon1 >= total_len or cur[colon1] != ':': break entry_name_len: sizet = colon1 - ci # 跳过 star import if entry_name_len == 1 and cur[ci] == '*': ci = colon1 - while ci < total_len and cur[ci] != ' ': - ci += 1 + while ci < total_len and cur[ci] != ' ': ci += 1 continue # 比较名称 if entry_name_len == name_len: @@ -355,14 +324,12 @@ novirtual class ImportsGenMixin: # 找到匹配,检查是否有第三个字段(原始名) pos: sizet = colon1 + 1 # 跳过模块名 - while pos < total_len and cur[pos] != ':' and cur[pos] != ' ' and cur[pos] != '\0': - pos += 1 + while pos < total_len and cur[pos] != ':' and cur[pos] != ' ' and cur[pos] != '\0': pos += 1 if pos < total_len and cur[pos] == ':': # 有第三个字段: original_name orig_start: sizet = pos + 1 orig_end: sizet = orig_start - while orig_end < total_len and cur[orig_end] != ' ' and cur[orig_end] != '\0': - orig_end += 1 + while orig_end < total_len and cur[orig_end] != ' ' and cur[orig_end] != '\0': orig_end += 1 orig_len: sizet = orig_end - orig_start if orig_len > 0: orig_buf: str = cur + orig_start @@ -372,8 +339,7 @@ novirtual class ImportsGenMixin: return None # 跳到下一个条目 ci = colon1 - while ci < total_len and cur[ci] != ' ': - ci += 1 + while ci < total_len and cur[ci] != ' ': ci += 1 return None # ============================================================ @@ -391,22 +357,18 @@ novirtual class ImportsGenMixin: 支持 star import: 如果 from_imports 中有 "*:module" 条目, 且未找到精确名称匹配,且 allow_star_fallback != 0,则返回 star import 的模块名。 """ - if name is None or from_imports is None: - return None + if name is None or from_imports is None: return None # [索引快路径] 传入串即当前索引绑定的串 → O(名字长) 哈希查;否则回退扫描。 # name 恰为 "*" 时与扫描一致:不做精确匹配,直接走 star 回退。 if from_imports == self.CurFromImportsPtr and self.CurFromImportsMods is not None: name_is_star: int = 0 - if string.strlen(name) == 1 and name[0] == '*': - name_is_star = 1 + if string.strlen(name) == 1 and name[0] == '*': name_is_star = 1 if name_is_star == 0: v_f: t.CPtr = self.CurFromImportsMods.__getitem__(name) - if v_f is not None: - return rawptr(v_f) + if v_f is not None: return rawptr(v_f) if allow_star_fallback != 0: sv_f: t.CPtr = self.CurFromImportsMods.__getitem__("*") - if sv_f is not None: - return rawptr(sv_f) + if sv_f is not None: return rawptr(sv_f) # 索引精确名 | star 均未命中:绝不据此直接返回 None(索引不完整会漏报 # "名已 import",_op_head NameError 即此类),落到下方原逐字符扫描按串内容判定。 name_len: sizet = string.strlen(name) @@ -416,23 +378,18 @@ novirtual class ImportsGenMixin: star_mod: str = None while ci < total_len: # 跳过前导空格 - while ci < total_len and cur[ci] == ' ': - ci += 1 - if ci >= total_len: - break + while ci < total_len and cur[ci] == ' ': ci += 1 + if ci >= total_len: break # 找到 ':' 的位置 colon_pos: sizet = ci - while colon_pos < total_len and cur[colon_pos] != ':' and cur[colon_pos] != ' ': - colon_pos += 1 - if colon_pos >= total_len or cur[colon_pos] != ':': - break + while colon_pos < total_len and cur[colon_pos] != ':' and cur[colon_pos] != ' ': colon_pos += 1 + if colon_pos >= total_len or cur[colon_pos] != ':': break entry_name_len: sizet = colon_pos - ci # 检测 star import ("*:module") if entry_name_len == 1 and cur[ci] == '*': mod_start: sizet = colon_pos + 1 mod_end: sizet = mod_start - while mod_end < total_len and cur[mod_end] != ' ' and cur[mod_end] != '\0' and cur[mod_end] != ':': - mod_end += 1 + while mod_end < total_len and cur[mod_end] != ' ' and cur[mod_end] != '\0' and cur[mod_end] != ':': mod_end += 1 star_mod = cur + mod_start # 比较名称 elif entry_name_len == name_len: @@ -447,16 +404,13 @@ novirtual class ImportsGenMixin: mod_start2: sizet = colon_pos + 1 mod_end2: sizet = mod_start2 # 模块名结束于: 空格、null、或第二个':'(别名格式的分隔符) - while mod_end2 < total_len and cur[mod_end2] != ' ' and cur[mod_end2] != '\0' and cur[mod_end2] != ':': - mod_end2 += 1 + while mod_end2 < total_len and cur[mod_end2] != ' ' and cur[mod_end2] != '\0' and cur[mod_end2] != ':': mod_end2 += 1 return cur + mod_start2 # 跳到下一个条目 ci = colon_pos - while ci < total_len and cur[ci] != ' ': - ci += 1 + while ci < total_len and cur[ci] != ' ': ci += 1 # 未找到精确匹配,仅在允许时回退到 star import - if allow_star_fallback == 0: - return None + if allow_star_fallback == 0: return None return star_mod # ============================================================ @@ -470,20 +424,17 @@ novirtual class ImportsGenMixin: # ============================================================ def register_reexport(self, mod_sha1: str, func_name: str, source_module: str) -> int: """注册 re-export 映射(幂等),返回 0 成功,-1 失败""" - if mod_sha1 is None or func_name is None or source_module is None: - return -1 + if mod_sha1 is None or func_name is None or source_module is None: return -1 # 懒初始化 if self.ReexportSha1s is None: self.ReexportSha1s = CompilerFactory.factory.PermPool.alloc(MAX_REEXPORT * 17) self.ReexportFuncs = CompilerFactory.factory.PermPool.alloc(MAX_REEXPORT * 64) self.ReexportSrcs = CompilerFactory.factory.PermPool.alloc(MAX_REEXPORT * 64) - if self.ReexportSha1s is None or self.ReexportFuncs is None or self.ReexportSrcs is None: - return -1 + if self.ReexportSha1s is None or self.ReexportFuncs is None or self.ReexportSrcs is None: return -1 string.memset(self.ReexportSha1s, 0, MAX_REEXPORT * 17) string.memset(self.ReexportFuncs, 0, MAX_REEXPORT * 64) string.memset(self.ReexportSrcs, 0, MAX_REEXPORT * 64) - if self.ReexportCount >= MAX_REEXPORT: - return -1 + if self.ReexportCount >= MAX_REEXPORT: return -1 # 幂等检查:查找是否已存在相同映射 for i in range(self.ReexportCount): sidx: sizet = sizet(i) * 17 @@ -514,16 +465,13 @@ novirtual class ImportsGenMixin: # ============================================================ def lookup_reexport(self, mod_sha1: str, func_name: str) -> str: """查找 re-export 映射,返回源模块名或 None""" - if mod_sha1 is None or func_name is None: - return None - if self.ReexportSha1s is None or self.ReexportCount <= 0: - return None + if mod_sha1 is None or func_name is None: return None + if self.ReexportSha1s is None or self.ReexportCount <= 0: return None for i in range(self.ReexportCount): sidx: sizet = sizet(i) * 17 fidx: sizet = sizet(i) * 64 if string.strcmp(self.ReexportSha1s + sidx, mod_sha1) == 0: - if string.strcmp(self.ReexportFuncs + fidx, func_name) == 0: - return self.ReexportSrcs + fidx + if string.strcmp(self.ReexportFuncs + fidx, func_name) == 0: return self.ReexportSrcs + fidx return None # ============================================================ @@ -551,8 +499,7 @@ novirtual class ImportsGenMixin: level: int, module: str) -> str: """解析相对导入为完整模块名""" - if level <= 0: - return module + if level <= 0: return module if current_package is None: # 无包上下文(includes 顶级文件 / App 顶层文件): # `from .X import Y` 的语义 = "同目录/根目录的 X 模块" @@ -622,8 +569,7 @@ novirtual class ImportsGenMixin: def compute_package_from_relpath(self, pool: memhub.MemBuddy*, rel_path: str) -> str: """从相对路径计算包名(目录部分,分隔符替换为 .)""" - if rel_path is None: - return None + if rel_path is None: return None rlen: sizet = string.strlen(rel_path) # 找最后一个 / 或 \ last_sep: sizet = 0 @@ -641,15 +587,12 @@ novirtual class ImportsGenMixin: # 复制目录部分,将 / 和 \ 替换为 . dir_len: sizet = last_sep buf: str = pool.alloc(dir_len + 1) - if buf is None: - return None + if buf is None: return None j: sizet = 0 while j < dir_len: ch2: char = rel_path[j] - if ch2 == '/' or ch2 == '\\': - buf[j] = '.' - else: - buf[j] = ch2 + if ch2 == '/' or ch2 == '\\': buf[j] = '.' + else: buf[j] = ch2 j += 1 buf[dir_len] = '\0' return buf @@ -686,11 +629,9 @@ novirtual class ImportsGenMixin: """以 Python 风格报错并退出(本地实现,避免循环依赖)""" stdio.printf("Traceback (most recent call last):\n") lineno: int = 0 - if node is not None: - lineno = node.lineno + if node is not None: lineno = node.lineno file_name: str = self.Gen.TypeGenResolve.get_current_file() - if file_name is None: - file_name = "" + if file_name is None: file_name = "" stdio.printf(' File "%s", line %d\n', file_name, lineno) # 显示行内内容(读源文件第 lineno 行的实际代码,便于快速定位) if lineno > 0 and file_name is not None: @@ -701,8 +642,7 @@ novirtual class ImportsGenMixin: cur_ln: int = 0 while cur_ln < lineno: r_err: LONG = f_err.readline(line_buf_err, 511) - if r_err <= 0: - break + if r_err <= 0: break cur_ln += 1 if cur_ln == lineno: ll_err: sizet = string.strlen(line_buf_err) @@ -726,11 +666,9 @@ novirtual class ImportsGenMixin: def _is_local_module_file(self, mod_name: str) -> int: """当前文件同目录存在 {mod_name}.vp/.py → 项目内兄弟模块""" cur: str = self.Gen.TypeGenResolve.get_current_file() - if cur is None or mod_name is None: - return 0 + if cur is None or mod_name is None: return 0 cur_len: sizet = string.strlen(cur) - if cur_len == 0: - return 0 + if cur_len == 0: return 0 sep_pos: sizet = cur_len while sep_pos > 0: sep_pos -= 1 @@ -741,8 +679,7 @@ novirtual class ImportsGenMixin: mod_len: sizet = string.strlen(mod_name) path_len: sizet = sep_pos + mod_len + 5 path_buf: bytes = stdlib.malloc(path_len + 1) - if path_buf is None: - return 0 + if path_buf is None: return 0 # .vp 文件(Viper 源仅 .vp,不再回退 .py) string.strncpy(path_buf, cur, sep_pos) path_buf[sep_pos] = '\0' @@ -770,31 +707,26 @@ novirtual class ImportsGenMixin: Returns: 1=检查通过;模块未注册时直接报错退出(不会返回 0) """ - if mod_name is None: - return 1 + if mod_name is None: return 1 # t/c 是内部库,不参与 includes 扫描,豁免检查 # ctraits 是纯编译期宏库(.vpi 后缀,IncludesScanner 不扫描 .vpi),豁免检查 # viperbuild 是编译器内建宏库(无磁盘模块、无 .vpi;配置由 Pass 0 的 # lib.core.builtin.ViperBuild 从依赖闭包提取),同样豁免检查 - if string.strcmp(mod_name, "t") == 0 or string.strcmp(mod_name, "c") == 0 or string.strcmp(mod_name, "ctraits") == 0: - return 1 - if string.strcmp(mod_name, "viperbuild") == 0: - return 1 + if string.strcmp(mod_name, "t") == 0 or string.strcmp(mod_name, "c") == 0 or string.strcmp(mod_name, "ctraits") == 0: return 1 + if string.strcmp(mod_name, "viperbuild") == 0: return 1 mod_sha1: str = StubMergerStore.LookupSha1ByModName(mod_name) if mod_sha1 is None: # App 兄弟模块豁免:当前文件同目录存在 {mod_name}.vp/.py # (如 Test/G4/App/caller1.vp import g4node——同项目源文件, # SHA1 在项目文件列表而非 includes 扫描存储器,不应报错) - if self._is_local_module_file(mod_name) != 0: - return 1 + 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) self._report_import_error(node, err_buf) - else: - self._report_import_error(node, "导入模块 SHA1 未注册(includes 扫描未找到该模块)") + else: self._report_import_error(node, "导入模块 SHA1 未注册(includes 扫描未找到该模块)") return 1 # ============================================================ @@ -816,25 +748,21 @@ novirtual class ImportsGenMixin: (与 vpi 注入期上下文同款,正确性不受影响)。 """ imp: ast.Import* = ast.Import*(node) - if imp is None: - return 0 + if imp is None: return 0 names: list[ast.AST*]* = imp.names - if names is None: - return 0 + if names is None: return 0 nn: sizet = len(names) pool_val: memhub.MemBuddy* = trans.Pool ctx: StubMergerStore.ImportCtx* = StubMergerStore.AllocImportCtx( pool_val, trans._imported_modules, trans._from_imports) - if ctx is None: - return 0 + if ctx is None: return 0 for ni in range(nn): alias: ast.Alias* = ast.Alias*(names.get(ni)) if alias is not None and alias.name is not None: # 导入时立即校验模块 SHA1 是否注册(fast-fail,仅全量翻译时检查) # declare_only=1/2 是 struct 预注册/import 扫描阶段:此时 SHA1 表 # 尚未包含后续才追加的模块(如 App 源文件),检查会造成误报。 - if trans._declare_only == 0: - self._check_import_sha1(node, alias.name) + if trans._declare_only == 0: self._check_import_sha1(node, alias.name) StubMergerStore.NotePlainImport(pool_val, ctx, alias.name, alias.asname) trans._imported_modules = ctx.ImportedModules trans._from_imports = ctx.FromImports @@ -852,8 +780,7 @@ novirtual class ImportsGenMixin: node: ast.AST*) -> int: """处理 from X import Y 的模块部分,更新 trans._imported_modules""" impf: ast.ImportFrom* = ast.ImportFrom*(node) - if impf is None: - return 0 + if impf is None: return 0 # 解析模块名:相对导入需补充包前缀 resolved: str = self._resolve_relative_module(trans.Pool, trans.CurrentPackage, impf.level, impf.module) @@ -864,8 +791,7 @@ novirtual class ImportsGenMixin: # 见 CallGenCall.vp L12 from . import CallGenBase),目录本身不是 # 模块文件、无 SHA1 → 跳过包级校验;真实目标子模块(pkg.Y)由 # 下方 L759-762 逐个校验(LookupSha1ByModName / 本地兄弟文件)。 - if trans._declare_only == 0 and impf.module is not None: - self._check_import_sha1(node, resolved) + if trans._declare_only == 0 and impf.module is not None: self._check_import_sha1(node, resolved) trans._imported_modules = self.add_imported_module(trans.Pool, trans._imported_modules, resolved) # from . import Y(impf.module is None):resolved 是包名(vpsdk), # 各 name 是包的子模块 vpsdk.Y。须把完整子模块名也加入 _imported_modules, @@ -892,8 +818,7 @@ novirtual class ImportsGenMixin: # translate_import_from_names 的 from-import / re-export 处理。 if (StubMergerStore.LookupSha1ByModName(jb_m) is not None or self._is_local_module_file(alias_m.name) != 0): - if trans._declare_only == 0: - self._check_import_sha1(node, jb_m) + if trans._declare_only == 0: self._check_import_sha1(node, jb_m) trans._imported_modules = self.add_imported_module(trans.Pool, trans._imported_modules, jb_m) return 0 @@ -916,20 +841,14 @@ novirtual class ImportsGenMixin: fi_target: str, orig_name: str, node: ast.AST*) -> int: - if trans is None or fi_target is None or orig_name is None: - return 0 - if trans.ModuleSha1 is None: - return 0 + if trans is None or fi_target is None or orig_name is None: return 0 + if trans.ModuleSha1 is None: return 0 # 快速短路:项目内无 static 符号时零开销(不查 sha1、不扫表) - if self.Gen.CallGenBase.StaticCount <= 0: - return 0 + if self.Gen.CallGenBase.StaticCount <= 0: return 0 sf_sha1: str = self.Gen.StructGen._resolve_module_sha1(fi_target, trans._from_imports) - 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 + 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") @@ -940,8 +859,7 @@ novirtual class ImportsGenMixin: node: ast.AST*) -> int: """处理 from X import Y 的名称部分,更新 trans._from_imports""" impf: ast.ImportFrom* = ast.ImportFrom*(node) - if impf is None: - return 0 + if impf is None: return 0 # 解析模块名:相对导入需补充包前缀 resolved: str = self._resolve_relative_module(trans.Pool, trans.CurrentPackage, impf.level, impf.module) @@ -983,14 +901,12 @@ novirtual class ImportsGenMixin: # 注册 re-export 映射:当前模块 re-export 了 local_name, # 源模块为 fi_target(from . import Y 时是子模块名 vpsdk.Y, # 非包名)。使跨模块调用 module.func() 能解析到正确 SHA1 - if trans.ModuleSha1 is not None: - self.register_reexport(trans.ModuleSha1, local_name, fi_target) + if trans.ModuleSha1 is not None: self.register_reexport(trans.ModuleSha1, local_name, fi_target) return 0 def InitImportsGen(self) -> int: """初始化 ImportsGen 字段(构造时由 Generator 调用)""" - if self is None: - return 1 + if self is None: return 1 self.ReexportSha1s = None self.ReexportFuncs = None self.ReexportSrcs = None diff --git a/App/lib/core/Gen/MatchGenMixin.vp b/App/lib/core/Gen/MatchGenMixin.vp index 0a0e27a..c7b96ae 100644 --- a/App/lib/core/Gen/MatchGenMixin.vp +++ b/App/lib/core/Gen/MatchGenMixin.vp @@ -39,20 +39,14 @@ novirtual class MatchGenMixin: def _case_tail_unreachable(self, trans: HT.Translator*, builder: mlirlite.IRBuilder*, body_list: list[ast.AST*]*) -> int: - if trans is None or builder is None: - return 0 - if mlirlite.builder_cur_block_is_terminated(builder) != 0: - return 0 - if body_list is None or len(body_list) == 0: - return 0 + if trans is None or builder is None: return 0 + if mlirlite.builder_cur_block_is_terminated(builder) != 0: return 0 + if body_list is None or len(body_list) == 0: return 0 lst: ast.AST* = body_list.get(len(body_list) - 1) - if lst is None: - return 0 + if lst is None: return 0 lk: int = lst.kind() - if lk != ast.ASTKind.If and lk != ast.ASTKind.While and lk != ast.ASTKind.For and lk != ast.ASTKind.Match: - return 0 - if trans._ctrl_merge_reachable != 0: - return 0 + if lk != ast.ASTKind.If and lk != ast.ASTKind.While and lk != ast.ASTKind.For and lk != ast.ASTKind.Match: return 0 + if trans._ctrl_merge_reachable != 0: return 0 mlirlite.build_unreachable(builder) return 1 @@ -64,23 +58,19 @@ novirtual class MatchGenMixin: node: ast.AST*) -> int: """match 语句翻译主入口(深度守卫包装器,原逻辑见 _translate_match_impl)""" 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 翻译嵌套过深(疑似 AST 自引用环或翻译 bug)", "RecursionError") trans.MatchTranslateDepth += 1 mret: int = self._translate_match_impl(trans, node) - if trans is not None: - trans.MatchTranslateDepth -= 1 + if trans is not None: trans.MatchTranslateDepth -= 1 return mret def _translate_match_impl(self, trans: HT.Translator*, node: ast.AST*) -> int: - if node is None: - return 0 + if node is None: return 0 pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder func: mlirlite.Function* = trans._cur_func - if builder is None or func is None: - return 0 + if builder is None or func is None: return 0 # match merge 可达性重置(分派前初始化为 0)。标志必须由各处理函数 # (_handle_renum_match/_handle_sequence_match/_handle_simple_match) @@ -114,8 +104,7 @@ novirtual class MatchGenMixin: if dpat.kind() == ast.ASTKind.MatchAs and rawptr[ast.MatchAs](dpat).pattern is None: # 只统计**无 guard** 的通配臂:带 guard 的 `case _ if ...` # 允许多个(各自 guard 区分),不当 default 计 - if rawptr[ast.MatchCase](dcase).guard is None: - default_cnt = default_cnt + 1 + if rawptr[ast.MatchCase](dcase).guard is None: default_cnt = default_cnt + 1 elif m_node.is_switch == 0: dcj: int = dci + 1 while dcj < ccn: @@ -134,14 +123,12 @@ novirtual class MatchGenMixin: # 1. 求值 subject subject_node: ast.AST* = m_node.subject - if subject_node is None: - return 0 + if subject_node is None: return 0 # 序列匹配(match (a, b): case (x, y): ...)走独立路径: # Tuple/List subject 无法用 translate_value 求值(会返回 None), # 提前分派到 _handle_sequence_match,避免 fail-fast 误报。 sk_seq: int = subject_node.kind() - if sk_seq == ast.ASTKind.Tuple or sk_seq == ast.ASTKind.List: - return self._handle_sequence_match(trans, m_node, subject_node) + if sk_seq == ast.ASTKind.Tuple or sk_seq == ast.ASTKind.List: return self._handle_sequence_match(trans, m_node, subject_node) 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: @@ -182,13 +169,11 @@ novirtual class MatchGenMixin: or self.Gen.ClassGenEnum._is_renum_by_entry(rnm) != 0): is_renum = 1 renum_name = rnm - if subject_ptr is None: - subject_ptr = subject_val + if subject_ptr is None: subject_ptr = subject_val ci = ci + 1 # 3. 分派 - if is_renum != 0 and subject_ptr is not None: - return self._handle_renum_match(trans, m_node, renum_name, subject_ptr) + if is_renum != 0 and subject_ptr is not None: return self._handle_renum_match(trans, m_node, renum_name, subject_ptr) return self._handle_simple_match(trans, m_node, subject_val) # ============================================================ @@ -200,12 +185,10 @@ novirtual class MatchGenMixin: # ============================================================ def _extract_renum_name_from_cls(self, pattern: ast.AST*) -> str: - if pattern is None: - return None + if pattern is None: return None mc: rawptr[ast.MatchClass] = rawptr[ast.MatchClass](pattern) cls_node: ast.AST* = mc.cls - if cls_node is None: - return None + if cls_node is None: return None # Attribute 形式 if cls_node.kind() == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(cls_node) @@ -227,12 +210,10 @@ novirtual class MatchGenMixin: # ============================================================ def _extract_variant_name_from_cls(self, pattern: ast.AST*) -> str: - if pattern is None: - return None + if pattern is None: return None mc: rawptr[ast.MatchClass] = rawptr[ast.MatchClass](pattern) cls_node: ast.AST* = mc.cls - if cls_node is None: - return None + if cls_node is None: return None if cls_node.kind() == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(cls_node) return at.attr @@ -248,8 +229,7 @@ novirtual class MatchGenMixin: # 模块级 _renum_class_* 已失效,统一委托到 gen._lookup_renum_variant。 # ============================================================ def _find_renum_class_for_variant(self, variant_name: str) -> str: - if variant_name is None: - return None + if variant_name is None: return None return self.Gen.ClassGenEnum._lookup_renum_variant(variant_name) # ============================================================ @@ -262,49 +242,39 @@ novirtual class MatchGenMixin: # ============================================================ def _value_label_same(self, a: ast.AST*, b: ast.AST*) -> int: """两个 `case` 值节点是否等价(常量值 / 名字 / 属性链)""" - if a is None or b is None: - return 0 + if a is None or b is None: return 0 ka: int = a.kind() - if ka != b.kind(): - return 0 + if ka != b.kind(): return 0 if ka == ast.ASTKind.Constant: ca: ast.Constant* = ast.Constant*(a) cb: ast.Constant* = ast.Constant*(b) - if ca.const_kind != cb.const_kind: - return 0 + if ca.const_kind != cb.const_kind: return 0 if ca.const_kind == ast.CONST_STR: - if ca.str_val is not None and cb.str_val is not None and string.strcmp(ca.str_val, cb.str_val) == 0: - return 1 + if ca.str_val is not None and cb.str_val is not None and string.strcmp(ca.str_val, cb.str_val) == 0: return 1 return 0 if ca.const_kind == ast.CONST_FLOAT: - if ca.float_val == cb.float_val: - return 1 + if ca.float_val == cb.float_val: return 1 return 0 # 整数 / 布尔 / 字符码 - if ca.int_val == cb.int_val: - return 1 + if ca.int_val == cb.int_val: return 1 return 0 if ka == ast.ASTKind.Name: na: ast.Name* = ast.Name*(a) nb: ast.Name* = ast.Name*(b) - if na.id is not None and nb.id is not None and string.strcmp(na.id, nb.id) == 0: - return 1 + if na.id is not None and nb.id is not None and string.strcmp(na.id, nb.id) == 0: return 1 return 0 if ka == ast.ASTKind.Attribute: aa: ast.Attribute* = ast.Attribute*(a) ab: ast.Attribute* = ast.Attribute*(b) - if aa.attr is None or ab.attr is None or string.strcmp(aa.attr, ab.attr) != 0: - return 0 + if aa.attr is None or ab.attr is None or string.strcmp(aa.attr, ab.attr) != 0: return 0 return self._value_label_same(aa.value, ab.value) return 0 def _case_label_same(self, a: ast.AST*, b: ast.AST*) -> int: """两个 case 模式是否有相同的 switch 标签""" - if a is None or b is None: - return 0 + if a is None or b is None: return 0 ka: int = a.kind() - if ka != b.kind(): - return 0 + if ka != b.kind(): return 0 if ka == ast.ASTKind.MatchValue: av: ast.AST* = rawptr[ast.MatchValue](a).value bv: ast.AST* = rawptr[ast.MatchValue](b).value @@ -314,20 +284,16 @@ novirtual class MatchGenMixin: if ka == ast.ASTKind.MatchClass: an: str = self._extract_variant_name_from_cls(a) bn: str = self._extract_variant_name_from_cls(b) - if an is None or bn is None: - return 0 - if string.strcmp(an, bn) == 0: - return 1 + if an is None or bn is None: return 0 + if string.strcmp(an, bn) == 0: return 1 return 0 if ka == ast.ASTKind.MatchOr: ap: list[ast.AST*]* = rawptr[ast.MatchOr](a).patterns bp: list[ast.AST*]* = rawptr[ast.MatchOr](b).patterns - if ap is None or bp is None or len(ap) != len(bp): - return 0 + if ap is None or bp is None or len(ap) != len(bp): return 0 oi: int = 0 while oi < len(ap): - if self._case_label_same(ap.get(oi), bp.get(oi)) == 0: - return 0 + if self._case_label_same(ap.get(oi), bp.get(oi)) == 0: return 0 oi = oi + 1 return 1 return 0 @@ -340,14 +306,12 @@ novirtual class MatchGenMixin: # 故此处无需再判上下文。 # ============================================================ def _has_no_break(self, body_list: list[ast.AST*]*) -> int: - if body_list is None: - return 0 + if body_list is None: return 0 n: sizet = len(body_list) i: int = 0 while i < n: stmt: ast.AST* = body_list.get(i) - if stmt is not None and stmt.kind() == ast.ASTKind.FallThrough: - return 1 + if stmt is not None and stmt.kind() == ast.ASTKind.FallThrough: return 1 i = i + 1 return 0 @@ -399,16 +363,14 @@ novirtual class MatchGenMixin: if subj_ty is not None and self.Gen.ExprGenBase.is_ptr_type(subj_ty) != 0 and subj_ty.Pointee != 0 and self.Gen.ExprGenBase.is_ptr_type(subj_ty.Pointee) != 0: # 情况1: T** → load 一次得 T* loaded_sub: mlirlite.Value* = mlirlite.build_load(builder, subj_ty.Pointee, subject_ptr) - if loaded_sub is not None: - subject_ptr = loaded_sub + if loaded_sub is not None: subject_ptr = loaded_sub # 情况2: 值型 subject(非指针)→ inttoptr 转回指针 # 值型 subject 来自 REnum payload 槽位 load(槽位类型 i64,存的是指针), # 所以直接 inttoptr 到 renum_sty* 即可,无需 alloca+store if subject_ptr.Ty is None or self.Gen.ExprGenBase.is_ptr_type(subject_ptr.Ty) == 0: renum_se: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(renum_name) renum_sty: mlirlite.LLVMType* = None - if renum_se is not None: - renum_sty = renum_se.Ty + if renum_se is not None: renum_sty = renum_se.Ty if renum_sty is None: # fail-fast: REnum 结构体未注册,无法构造 self.Gen.TypeGenErr.fatal_error(node, f"REnum 结构体 '{renum_name}' 未注册", "NameError") @@ -417,14 +379,11 @@ novirtual class MatchGenMixin: # 非 i64 整数值先扩展/截断到 i64(inttoptr 要求同宽) # 仅当 subj_ty 是已知整数类型时转换;类型未知时保持原值 if subj_ty is not None and self.Gen.ExprGenBase.get_llvm_type_bits(subj_ty) != 64 and self.Gen.ExprGenBase.is_ptr_type(subj_ty) == 0: - if self.Gen.ExprGenBase.get_llvm_type_bits(subj_ty) > 64: - int_val = mlirlite.build_trunc(builder, subject_ptr, i64_ty0) - else: - int_val = mlirlite.build_zext(builder, subject_ptr, i64_ty0) + if self.Gen.ExprGenBase.get_llvm_type_bits(subj_ty) > 64: int_val = mlirlite.build_trunc(builder, subject_ptr, i64_ty0) + else: int_val = mlirlite.build_zext(builder, subject_ptr, i64_ty0) renum_ptr_ty0: mlirlite.LLVMType* = mlirlite.Ptr(pool, renum_sty) subj_ptr0: mlirlite.Value* = mlirlite.build_inttoptr(builder, int_val, renum_ptr_ty0) - if subj_ptr0 is not None: - subject_ptr = subj_ptr0 + if subj_ptr0 is not None: subject_ptr = subj_ptr0 # 1. bitcast subject 到 __tag* 读 __tag # tag 的**类型**取 __tag 的字段声明类型(FieldEntry.Ty),与 kind() @@ -436,8 +395,7 @@ novirtual class MatchGenMixin: tag_se: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(renum_name) if tag_se is not None and tag_se.Ty is not None: tag_fe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field(tag_se.Ty, "__tag") - if tag_fe is not None and tag_fe.Ty is not None: - tag_ty = tag_fe.Ty + if tag_fe is not None and tag_fe.Ty is not None: tag_ty = tag_fe.Ty tag_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, tag_ty) tag_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, subject_ptr, tag_ptr_ty) if tag_ptr is None: @@ -507,8 +465,7 @@ novirtual class MatchGenMixin: # 同款「括号外取点」判定,泛型下标内的点不算)。 tag_cls_bare: str = renum_name rn_dot: str = self.Gen.StructGen._last_dot_outside_brackets(renum_name) - if rn_dot is not None and rn_dot[1] != '\0': - tag_cls_bare = rn_dot + 1 + if rn_dot is not None and rn_dot[1] != '\0': tag_cls_bare = rn_dot + 1 # 4. 第一遍:收集 case 信息 + 创建 BB + 构建链表 i: int = 0 @@ -539,12 +496,10 @@ novirtual class MatchGenMixin: # 失败再用注解书写形态重试(泛型特化 mangled 名确需带点)。 # 两者都失败 → tag=-1 → step 5 前的硬校验 fail-fast。 tag = self.Gen.ClassGenEnum._lookup_renum_variant_in_class(tag_cls_bare, vnm) - if tag < 0 and string.strcmp(tag_cls_bare, renum_name) != 0: - tag = self.Gen.ClassGenEnum._lookup_renum_variant_in_class(renum_name, vnm) + if tag < 0 and string.strcmp(tag_cls_bare, renum_name) != 0: tag = self.Gen.ClassGenEnum._lookup_renum_variant_in_class(renum_name, vnm) if tag >= 0: tag_buf: str = pool.alloc(32) - if tag_buf is not None: - viperlib.snprintf(tag_buf, 32, "%d", tag) + if tag_buf is not None: viperlib.snprintf(tag_buf, 32, "%d", tag) cv = mlirlite.ConstInt(pool, tag_ty, tag, tag_buf if tag_buf is not None else "0") elif pk == ast.ASTKind.MatchAs: @@ -568,12 +523,10 @@ novirtual class MatchGenMixin: # 创建 case BB if is_def == 0: - if collected >= MAX_MATCH_CASES: - break + if collected >= MAX_MATCH_CASES: break viperlib.snprintf(name_buf, 32, "match.case.%d.%d", cnt, i) bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf) - else: - bb = default_bb + else: bb = default_bb # 检测 NoBreak body_list: list[ast.AST*]* = mc.children @@ -593,8 +546,7 @@ novirtual class MatchGenMixin: # break,不参与校验)。 if is_def == 0 and pat is not None: pkm: int = pat.kind() - if pkm == ast.ASTKind.MatchClass or pkm == ast.ASTKind.MatchValue: - need_case = need_case + 1 + if pkm == ast.ASTKind.MatchClass or pkm == ast.ASTKind.MatchValue: need_case = need_case + 1 # 构建 SwitchCase 链表(非 default case 且有值) if is_def == 0 and cv is not None: @@ -661,8 +613,7 @@ novirtual class MatchGenMixin: # __types.LLVMType 的根因)。此处用结构体表 entry.Ty 的完整定义**同名替换** # opaque(module_add_named_type 原地替换,非追加,故不会 invalid redefinition); # 本地非跨模块类型(名不含 '.')会自动跳过。 - if renum_ty is not None: - self.Gen.StructGen.ensure_struct_def_in_module(pool, trans.Module, renum_ty) + if renum_ty is not None: self.Gen.StructGen.ensure_struct_def_in_module(pool, trans.Module, renum_ty) # 7. 第二遍:翻译每个 case body i = 0 @@ -700,8 +651,7 @@ novirtual class MatchGenMixin: # 变体字段绑定(MatchClass) if pat is not None and pat.kind() == ast.ASTKind.MatchClass: - if renum_entry is not None and renum_ty is not None: - self._bind_variant_fields(pat, renum_name, renum_entry, renum_ty, subject_ptr, trans, pool, builder) + if renum_entry is not None and renum_ty is not None: self._bind_variant_fields(pat, renum_name, renum_entry, renum_ty, subject_ptr, trans, pool, builder) elif (self.Gen.ClassGenEnum._is_renum_class_name(tag_cls_bare) != 0 or self.Gen.ClassGenEnum._is_renum_class_name(renum_name) != 0 or self.Gen.ClassGenEnum._is_renum_by_entry(tag_cls_bare) != 0 @@ -717,8 +667,7 @@ novirtual class MatchGenMixin: ent_nm = renum_entry.Name ent_fc = renum_entry.FieldCount ty_present: int = 0 - if renum_ty is not None: - ty_present = 1 + 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};" @@ -737,8 +686,7 @@ novirtual class MatchGenMixin: # `bl_data + bi*8` 裸地址:那会把数组槽地址当节点传入 # translate_stmt,虚调用跳进 vtable 表 → DEP 崩溃。 stmt: ast.AST* = body_list.get(bi) - if stmt is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt) + if stmt is not None: self.Gen.StmtGen.translate_stmt(trans, stmt) bi = bi + 1 # 退出 case 作用域,并恢复 break 目标 / match-case 标记 @@ -750,19 +698,15 @@ novirtual class MatchGenMixin: # c.NoBreak())则落到下一个 case 的 body(跳过其模式检查)。 # 末句控制流全 return(结构性不可达)时补 unreachable,不 br end_bb if mlirlite.builder_cur_block_is_terminated(builder) == 0 and self._case_tail_unreachable(trans, builder, body_list) == 0: - if nb == 0: - mlirlite.build_br(builder, end_bb) + if nb == 0: mlirlite.build_br(builder, end_bb) else: rmb_ft_nj: int = i + 1 - while rmb_ft_nj < collected and def_arr[rmb_ft_nj] != 0: - rmb_ft_nj = rmb_ft_nj + 1 + while rmb_ft_nj < collected and def_arr[rmb_ft_nj] != 0: rmb_ft_nj = rmb_ft_nj + 1 if rmb_ft_nj < collected: rmb_ft_bb: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](bb_arr[rmb_ft_nj]) mlirlite.build_br(builder, rmb_ft_bb) - elif has_default != 0: - mlirlite.build_br(builder, default_bb) - else: - mlirlite.build_br(builder, end_bb) + elif has_default != 0: mlirlite.build_br(builder, default_bb) + else: mlirlite.build_br(builder, end_bb) trans._ctrl_merge_reachable = 1 rm_merge_reach = 1 @@ -796,8 +740,7 @@ novirtual class MatchGenMixin: dj3: int = 0 while dj3 < dn3: stmt3: ast.AST* = dbody3.get(dj3) - if stmt3 is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt3) + if stmt3 is not None: self.Gen.StmtGen.translate_stmt(trans, stmt3) dj3 = dj3 + 1 self.Gen.VarGen.exit_scope(trans.SymTab) trans._break_bb = rmd_old_break @@ -828,17 +771,14 @@ novirtual class MatchGenMixin: trans: HT.Translator*, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*): - if pat is None or renum_entry is None or renum_ty is None: - return + if pat is None or renum_entry is None or renum_ty is None: return mc: rawptr[ast.MatchClass] = rawptr[ast.MatchClass](pat) pats: list[ast.AST*]* = mc.patterns - if pats is None: - return + if pats is None: return # bitcast subject_ptr 到 renum_ptr_ty(确保 GEP 类型匹配) renum_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, renum_ty) casted_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, subject_ptr, renum_ptr_ty) - if casted_ptr is None: - casted_ptr = subject_ptr + if casted_ptr is None: casted_ptr = subject_ptr pn: sizet = len(pats) for j in range(pn): sub_pat: ast.AST* = pats.get(j) @@ -855,8 +795,7 @@ novirtual class MatchGenMixin: # (注册时 _update_renum_alias_class_ptr 统一后的 perm_pool 指针); # renum_name(AnnotClassName 等)是不同指针,恒不匹配 → 误报 fail-fast。 alt_idx: int = self.Gen.ClassGenEnum._lookup_renum_field_alias(renum_entry.Name, bind_name) - if alt_idx >= 1: - payload_idx = alt_idx + if alt_idx >= 1: payload_idx = alt_idx else: # fail-fast: payload 越界且别名查找失败 # (node 在本函数不存在——参数是 pat/sub_pat,用 sub_pat @@ -866,8 +805,7 @@ novirtual class MatchGenMixin: # 获取字段类型 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 fe is not None: field_ty = fe.Ty if field_ty is None: # fail-fast: 变体字段类型缺失,禁止兜底 i8 self.Gen.TypeGenErr.fatal_error(sub_pat, f"REnum 变体字段类型缺失: {bind_name}", "TypeError") @@ -885,14 +823,12 @@ novirtual class MatchGenMixin: # 自引用类型注册期解析失败 → 查不到类型时回退槽位类型。 mem_ty_m: mlirlite.LLVMType* = None vnt_m: str = self._extract_variant_name_from_cls(pat) - if vnt_m is not None and renum_entry is not None and renum_entry.Name is not None: - mem_ty_m = self.Gen.ClassGenEnum._lookup_renum_member_ty(renum_entry.Name, vnt_m, payload_idx) + if vnt_m is not None and renum_entry is not None and renum_entry.Name is not None: mem_ty_m = self.Gen.ClassGenEnum._lookup_renum_member_ty(renum_entry.Name, vnt_m, payload_idx) if mem_ty_m is not None: mem_ptr_m: mlirlite.LLVMType* = mlirlite.Ptr(pool, mem_ty_m) if mem_ptr_m is not None: cast_m: mlirlite.Value* = mlirlite.build_bitcast(builder, elem_ptr, mem_ptr_m) - if cast_m is not None: - elem_ptr = cast_m + if cast_m is not None: elem_ptr = cast_m self.Gen.VarGen.define_var(trans.SymTab, bind_name, elem_ptr) # ============================================================ @@ -906,28 +842,21 @@ novirtual class MatchGenMixin: lhs: mlirlite.Value*, rhs: mlirlite.Value*) -> mlirlite.Value*: """对齐 lhs/rhs 后生成 icmp eq(指针统一 ptrtoint i64)""" - if lhs is None or rhs is None or builder is None: - return None + if lhs is None or rhs is None or builder is None: return None pool: memhub.MemBuddy* = trans.Pool if self.Gen.ExprGenBase.is_ptr_type(lhs.Ty) != 0 or self.Gen.ExprGenBase.is_ptr_type(rhs.Ty) != 0: i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool) - if self.Gen.ExprGenBase.is_ptr_type(lhs.Ty) != 0: - lhs = mlirlite.build_ptrtoint(builder, lhs, i64_ty) - if self.Gen.ExprGenBase.is_ptr_type(rhs.Ty) != 0: - rhs = mlirlite.build_ptrtoint(builder, rhs, i64_ty) + if self.Gen.ExprGenBase.is_ptr_type(lhs.Ty) != 0: lhs = mlirlite.build_ptrtoint(builder, lhs, i64_ty) + if self.Gen.ExprGenBase.is_ptr_type(rhs.Ty) != 0: rhs = mlirlite.build_ptrtoint(builder, rhs, i64_ty) lb: int = self.Gen.ExprGenBase.get_llvm_type_bits(lhs.Ty) rb: int = self.Gen.ExprGenBase.get_llvm_type_bits(rhs.Ty) if lb != rb and lb != 0 and rb != 0: if lb < rb: - if lb == 1: - lhs = mlirlite.build_zext(builder, lhs, rhs.Ty) - else: - lhs = mlirlite.build_sext(builder, lhs, rhs.Ty) + if lb == 1: lhs = mlirlite.build_zext(builder, lhs, rhs.Ty) + else: lhs = mlirlite.build_sext(builder, lhs, rhs.Ty) else: - if rb == 1: - rhs = mlirlite.build_zext(builder, rhs, lhs.Ty) - else: - rhs = mlirlite.build_sext(builder, rhs, lhs.Ty) + if rb == 1: rhs = mlirlite.build_zext(builder, rhs, lhs.Ty) + else: rhs = mlirlite.build_sext(builder, rhs, lhs.Ty) return mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, lhs, rhs) # ============================================================ @@ -951,8 +880,7 @@ novirtual class MatchGenMixin: pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder func: mlirlite.Function* = trans._cur_func - if builder is None or func is None: - return 0 + if builder is None or func is None: return 0 # 同主路径:局部记录本 sequence match 的 br end_bb,收尾覆盖 # _ctrl_merge_reachable,消除 case 体内嵌套控制流污染 sq_merge_reach: int = 0 @@ -961,20 +889,15 @@ novirtual class MatchGenMixin: elts: list[ast.AST*]* = None if subject_node.kind() == ast.ASTKind.Tuple: st: ast.Tuple* = ast.Tuple*(subject_node) - if st is not None: - elts = st.elts + if st is not None: elts = st.elts elif subject_node.kind() == ast.ASTKind.List: sl2: ast.List* = ast.List*(subject_node) - if sl2 is not None: - elts = sl2.elts - if elts is None: - return 0 + if sl2 is not None: elts = sl2.elts + if elts is None: return 0 ecount: sizet = len(elts) - if ecount == 0: - return 0 + if ecount == 0: return 0 subj_vals: sizet* = pool.alloc(8 * ecount) - if subj_vals is None: - return 0 + if subj_vals is None: return 0 for ei in range(ecount): # elts 预声明+重赋值会把 .get 误分派成 list[int].get(i32 截断); # 用内联别名接收者规避(对齐 Converter arg_defaults 内联模式) @@ -982,16 +905,14 @@ novirtual class MatchGenMixin: 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 序列元素 {ei} 翻译失败", "TypeError") subj_vals[ei] = sizet(sv) # 2. 创建 default/end BB cnt: int = trans._label_counter trans._label_counter = cnt + 1 name_buf: str = pool.alloc(32) - if name_buf is None: - return 0 + if name_buf is None: return 0 viperlib.snprintf(name_buf, 32, "match.seq.default.%d", cnt) default_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf) viperlib.snprintf(name_buf, 32, "match.seq.end.%d", cnt) @@ -999,16 +920,14 @@ novirtual class MatchGenMixin: # 3. 第一遍:收集 case 信息(check/body BB、default 标记、nobreak、guard) cases_list: list[ast.AST*]* = node.cases - if cases_list is None: - return 0 + if cases_list is None: return 0 case_count: sizet = len(cases_list) check_arr: sizet* = pool.alloc(8 * MAX_MATCH_CASES) body_arr: sizet* = pool.alloc(8 * MAX_MATCH_CASES) def_arr: int* = pool.alloc(4 * MAX_MATCH_CASES) nb_arr: int* = pool.alloc(4 * MAX_MATCH_CASES) guard_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 guard_arr is None: - return 0 + if check_arr is None or body_arr is None or def_arr is None or nb_arr is None or guard_arr is None: return 0 collected: int = 0 has_default: int = 0 # 穷尽臂(`case _`)节点:pass1 显式记录,default 块直接翻译 @@ -1053,16 +972,14 @@ novirtual class MatchGenMixin: check_arr[collected] = 0 body_arr[collected] = sizet(default_bb) else: - if collected >= MAX_MATCH_CASES: - break + if collected >= MAX_MATCH_CASES: break viperlib.snprintf(name_buf, 32, "match.seq.check.%d.%d", cnt, i) cbb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf) viperlib.snprintf(name_buf, 32, "match.seq.body.%d.%d", cnt, i) bbb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf) check_arr[collected] = sizet(cbb) body_arr[collected] = sizet(bbb) - if first_check < 0: - first_check = collected + if first_check < 0: first_check = collected body_list: list[ast.AST*]* = mc.children nb: int = self._has_no_break(body_list) def_arr[collected] = is_def @@ -1075,10 +992,8 @@ novirtual class MatchGenMixin: if first_check >= 0: head_bb: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](check_arr[first_check]) mlirlite.build_br(builder, head_bb) - elif has_default == 1: - mlirlite.build_br(builder, default_bb) - else: - mlirlite.build_br(builder, end_bb) + elif has_default == 1: mlirlite.build_br(builder, default_bb) + else: mlirlite.build_br(builder, end_bb) # 5. 发射 check 链 ci: int = 0 @@ -1096,11 +1011,9 @@ novirtual class MatchGenMixin: mc2: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](cnode) ms: rawptr[ast.MatchSequence] = (rawptr[ast.MatchSequence])(mc2.pattern) pats: list[ast.AST*]* = None - if ms is not None: - pats = ms.patterns + if ms is not None: pats = ms.patterns pcount: sizet = 0 - if pats is not None: - pcount = len(pats) + if pats is not None: pcount = len(pats) if pcount != ecount: # 元素数量不匹配 → 恒假(对齐 Python 语义) cond = mlirlite.const_int(pool, 1, 0) @@ -1110,22 +1023,17 @@ novirtual class MatchGenMixin: # 用内联别名接收者规避(对齐 Converter arg_defaults 内联模式) pats_inl: list[ast.AST*]* = pats pat1: ast.AST* = pats_inl.get(pi) - if pat1 is None: - continue + if pat1 is None: continue pk1: int = pat1.kind() if pk1 == ast.ASTKind.MatchValue: mv: rawptr[ast.MatchValue] = (rawptr[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"序列模式元素 {pi} 翻译失败", "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 cond is None: - cond = c1 - else: - cond = mlirlite.build_and(builder, cond, c1) + if c1 is None: self.Gen.TypeGenErr.fatal_error(pat1, "序列模式元素比较失败", "TypeError") + if cond is None: cond = c1 + else: cond = mlirlite.build_and(builder, cond, c1) elif pk1 == ast.ASTKind.MatchAs: ma2: rawptr[ast.MatchAs] = rawptr[ast.MatchAs](pat1) if ma2.pattern is None: @@ -1135,40 +1043,30 @@ novirtual class MatchGenMixin: self.Gen.TypeGenErr.fatal_error(pat1, "序列模式变量绑定暂不支持", "NotImplementedError") elif pk1 == ast.ASTKind.MatchStar: continue # 剩余元素通配:恒真 - else: - self.Gen.TypeGenErr.fatal_error(pat1, "序列模式不支持的 pattern 类型", "TypeError") + else: self.Gen.TypeGenErr.fatal_error(pat1, "序列模式不支持的 pattern 类型", "TypeError") # guard(若有):匹配成立且 guard 非零 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 翻译失败", "TypeError") gbits: int = self.Gen.ExprGenBase.get_llvm_type_bits(gv.Ty) - if gbits == 1: - g1: mlirlite.Value* = gv + if gbits == 1: g1: mlirlite.Value* = gv else: gzero: mlirlite.Value* = mlirlite.const_int(pool, gbits if gbits > 0 else 32, 0) g1 = mlirlite.build_icmp(builder, mlirlite.ICMP_NE, gv, gzero) - if cond is None: - cond = g1 - else: - cond = mlirlite.build_and(builder, cond, g1) - if cond is None: - cond = mlirlite.const_int(pool, 1, 1) + if cond is None: cond = g1 + else: cond = mlirlite.build_and(builder, cond, g1) + if cond is None: cond = mlirlite.const_int(pool, 1, 1) # 下一个 check(或 default/end) nxt: rawptr[mlirlite.BasicBlock] = None nj: int = ci + 1 - while nj < collected and def_arr[nj] == 1: - nj = nj + 1 - if nj < collected: - nxt = rawptr[mlirlite.BasicBlock](check_arr[nj]) - elif has_default == 1: - nxt = default_bb - else: - nxt = end_bb + while nj < collected and def_arr[nj] == 1: nj = nj + 1 + if nj < collected: nxt = rawptr[mlirlite.BasicBlock](check_arr[nj]) + elif has_default == 1: nxt = default_bb + else: nxt = end_bb mlirlite.build_cond_br(builder, cond, bbb2, nxt) ci = ci + 1 @@ -1194,28 +1092,23 @@ novirtual class MatchGenMixin: bi: int = 0 while bi < bc: stmt: ast.AST* = body_list2.get(bi) - if stmt is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt) + if stmt is not None: self.Gen.StmtGen.translate_stmt(trans, stmt) bi = bi + 1 self.Gen.VarGen.exit_scope(trans.SymTab) trans._break_bb = sqb_old_break trans._in_switch_case = sqb_old_inmc # 末句控制流全 return → 补 unreachable(不 br end,无 fallthrough) if mlirlite.builder_cur_block_is_terminated(builder) == 0 and self._case_tail_unreachable(trans, builder, body_list2) == 0: - if nb_arr[ci] == 0: - mlirlite.build_br(builder, end_bb) + if nb_arr[ci] == 0: mlirlite.build_br(builder, end_bb) else: # c.NoBreak:fallthrough 到下一个 case body(跳过模式检查) nj2: int = ci + 1 - while nj2 < collected and def_arr[nj2] == 1: - nj2 = nj2 + 1 + while nj2 < collected and def_arr[nj2] == 1: nj2 = nj2 + 1 if nj2 < collected: nbb: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](body_arr[nj2]) mlirlite.build_br(builder, nbb) - elif has_default == 1: - mlirlite.build_br(builder, default_bb) - else: - mlirlite.build_br(builder, end_bb) + elif has_default == 1: mlirlite.build_br(builder, default_bb) + else: mlirlite.build_br(builder, end_bb) trans._ctrl_merge_reachable = 1 sq_merge_reach = 1 ci = ci + 1 @@ -1243,8 +1136,7 @@ novirtual class MatchGenMixin: dj3: int = 0 while dj3 < dn3: stmt3: ast.AST* = dbody3.get(dj3) - if stmt3 is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt3) + if stmt3 is not None: self.Gen.StmtGen.translate_stmt(trans, stmt3) dj3 = dj3 + 1 self.Gen.VarGen.exit_scope(trans.SymTab) trans._break_bb = sqd_old_break @@ -1280,8 +1172,7 @@ novirtual class MatchGenMixin: subj_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(subject_val.Ty) subj_val: mlirlite.Value* = subject_val if subj_bits != 32: - if self.Gen.ExprGenBase.is_ptr_type(subject_val.Ty) != 0: - subj_val = mlirlite.build_ptrtoint(builder, subject_val, i32_ty) + if self.Gen.ExprGenBase.is_ptr_type(subject_val.Ty) != 0: subj_val = mlirlite.build_ptrtoint(builder, subject_val, i32_ty) elif subj_bits > 32: # trunc 到 i32 subj_val = mlirlite.build_trunc(builder, subject_val, i32_ty) @@ -1304,11 +1195,9 @@ novirtual class MatchGenMixin: while cg_i < cg_n: cg_case: ast.AST* = cases_g.get(cg_i) if cg_case is not None and cg_case.kind() == ast.ASTKind.MatchCase: - if rawptr[ast.MatchCase](cg_case).guard is not None: - has_guard = 1 + if rawptr[ast.MatchCase](cg_case).guard is not None: has_guard = 1 cg_i = cg_i + 1 - if has_guard != 0: - return self._handle_guarded_simple_match(trans, node, subj_val) + if has_guard != 0: return self._handle_guarded_simple_match(trans, node, subj_val) # 2. 创建 default/end BB cnt: int = trans._label_counter @@ -1402,12 +1291,10 @@ novirtual class MatchGenMixin: "InternalCompilerError") if is_def == 0: - if collected >= MAX_MATCH_CASES: - break + if collected >= MAX_MATCH_CASES: break viperlib.snprintf(name_buf, 32, "match.case.%d.%d", cnt, i) bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf) - else: - bb = default_bb + else: bb = default_bb body_list: list[ast.AST*]* = mc.children nb: int = self._has_no_break(body_list) @@ -1430,8 +1317,7 @@ novirtual class MatchGenMixin: # MatchSingleton 备选无法产出值,fail-fast 不得静默丢弃。 mo2: rawptr[ast.MatchOr] = (rawptr[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 模式无备选子模式", "TypeError") pats2_n: sizet = len(pats2) pats2_i: int = 0 while pats2_i < pats2_n: @@ -1445,8 +1331,7 @@ novirtual class MatchGenMixin: elif alt_pat.kind() == ast.ASTKind.MatchSingleton: # None -> 0(与单值/守卫路径同口径) 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, "switch OR 模式备选不是值模式", "TypeError") if alt_cv is not None: sc2: rawptr[mlirlite.SwitchCase] = mlirlite.new_switch_case(pool, alt_cv, bb) if sc2 is not None: @@ -1509,8 +1394,7 @@ novirtual class MatchGenMixin: bi: int = 0 while bi < bc: stmt: ast.AST* = body_list.get(bi) - if stmt is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt) + if stmt is not None: self.Gen.StmtGen.translate_stmt(trans, stmt) bi = bi + 1 self.Gen.VarGen.exit_scope(trans.SymTab) @@ -1521,19 +1405,15 @@ novirtual class MatchGenMixin: # c.NoBreak())则落到下一个 case 的 body(跳过其模式检查)。 # 末句控制流全 return → 补 unreachable(不 br end_bb) if mlirlite.builder_cur_block_is_terminated(builder) == 0 and self._case_tail_unreachable(trans, builder, body_list) == 0: - if nb == 0: - mlirlite.build_br(builder, end_bb) + if nb == 0: mlirlite.build_br(builder, end_bb) else: sm_ft_nj: int = i + 1 - while sm_ft_nj < collected and def_arr[sm_ft_nj] != 0: - sm_ft_nj = sm_ft_nj + 1 + while sm_ft_nj < collected and def_arr[sm_ft_nj] != 0: sm_ft_nj = sm_ft_nj + 1 if sm_ft_nj < collected: sm_ft_bb: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](bb_arr[sm_ft_nj]) mlirlite.build_br(builder, sm_ft_bb) - elif has_default != 0: - mlirlite.build_br(builder, default_bb) - else: - mlirlite.build_br(builder, end_bb) + elif has_default != 0: mlirlite.build_br(builder, default_bb) + else: mlirlite.build_br(builder, end_bb) trans._ctrl_merge_reachable = 1 sm_merge_reach = 1 @@ -1566,8 +1446,7 @@ novirtual class MatchGenMixin: dj3: int = 0 while dj3 < dn3: stmt3: ast.AST* = dbody3.get(dj3) - if stmt3 is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt3) + if stmt3 is not None: self.Gen.StmtGen.translate_stmt(trans, stmt3) dj3 = dj3 + 1 self.Gen.VarGen.exit_scope(trans.SymTab) trans._break_bb = smd_old_break @@ -1613,8 +1492,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, "标签缓冲区分配失败", "TypeError") viperlib.snprintf(name_buf, 32, "match.guard.default.%d", cnt) default_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf) viperlib.snprintf(name_buf, 32, "match.guard.end.%d", cnt) @@ -1622,8 +1500,7 @@ novirtual class MatchGenMixin: # 2. 收集 case 信息(check/body BB、default 标记、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 缺失", "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) @@ -1695,8 +1572,7 @@ novirtual class MatchGenMixin: bbb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf) check_arr[collected] = sizet(cbb) body_arr[collected] = sizet(bbb) - if first_check < 0: - first_check = collected + if first_check < 0: first_check = collected body_list: list[ast.AST*]* = mc.children nb: int = self._has_no_break(body_list) def_arr[collected] = is_def @@ -1711,10 +1587,8 @@ novirtual class MatchGenMixin: if first_check >= 0: head_bb: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](check_arr[first_check]) mlirlite.build_br(builder, head_bb) - elif has_default == 1: - mlirlite.build_br(builder, default_bb) - else: - mlirlite.build_br(builder, end_bb) + elif has_default == 1: mlirlite.build_br(builder, default_bb) + else: mlirlite.build_br(builder, end_bb) # 4. 发射 check 链(按书写顺序) ci: int = 0 @@ -1736,8 +1610,7 @@ novirtual class MatchGenMixin: # 值 → fail-fast,不静默丢弃)。 mo4: rawptr[ast.MatchOr] = (rawptr[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 模式无备选子模式", "TypeError") pats4_n: sizet = len(pats4) pats4_i: int = 0 while pats4_i < pats4_n: @@ -1751,24 +1624,18 @@ novirtual class MatchGenMixin: elif alt_pat2.kind() == ast.ASTKind.MatchSingleton: # None -> 0(与单值路径同口径) 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, "guard OR 模式备选不是值模式", "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 cond is None: - cond = cc - else: - cond = mlirlite.build_or(builder, cond, cc) + if cc is None: self.Gen.TypeGenErr.fatal_error(node, "match OR 备选值比较失败", "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, "guard OR 模式未能产出任何比较条件", "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 值比较失败", "TypeError") cond = c1 # guard(若有):匹配成立且 guard 非零(归一为 i1,写法同序列路径) g_addr: sizet = sizet(mc2.guard) @@ -1776,31 +1643,22 @@ novirtual class MatchGenMixin: 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 翻译失败", "TypeError") gbits: int = self.Gen.ExprGenBase.get_llvm_type_bits(gv.Ty) - if gbits == 1: - g1: mlirlite.Value* = gv + if gbits == 1: g1: mlirlite.Value* = gv else: gzero: mlirlite.Value* = mlirlite.const_int(pool, gbits if gbits > 0 else 32, 0) g1 = mlirlite.build_icmp(builder, mlirlite.ICMP_NE, gv, gzero) - if cond is None: - cond = g1 - else: - cond = mlirlite.build_and(builder, cond, g1) - if cond is None: - cond = mlirlite.const_int(pool, 1, 1) + if cond is None: cond = g1 + else: cond = mlirlite.build_and(builder, cond, g1) + if cond is None: cond = mlirlite.const_int(pool, 1, 1) # 下一个 check(跳过 default)→ 否则 default/end nxt: rawptr[mlirlite.BasicBlock] = None nj: int = ci + 1 - while nj < collected and def_arr[nj] == 1: - nj = nj + 1 - if nj < collected: - nxt = rawptr[mlirlite.BasicBlock](check_arr[nj]) - elif has_default == 1: - nxt = default_bb - else: - nxt = end_bb + while nj < collected and def_arr[nj] == 1: nj = nj + 1 + if nj < collected: nxt = rawptr[mlirlite.BasicBlock](check_arr[nj]) + elif has_default == 1: nxt = default_bb + else: nxt = end_bb mlirlite.build_cond_br(builder, cond, bbb2, nxt) ci = ci + 1 @@ -1825,8 +1683,7 @@ novirtual class MatchGenMixin: bi: int = 0 while bi < bc: stmt: ast.AST* = body_list2.get(bi) - if stmt is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt) + if stmt is not None: self.Gen.StmtGen.translate_stmt(trans, stmt) bi = bi + 1 self.Gen.VarGen.exit_scope(trans.SymTab) trans._break_bb = gmb_old_break @@ -1834,19 +1691,15 @@ novirtual class MatchGenMixin: # 若未终止:默认跳 end;含 fallthrough 则落到下一个非通配 body。 # 末句控制流全 return → 补 unreachable(不 br end_bb) if mlirlite.builder_cur_block_is_terminated(builder) == 0 and self._case_tail_unreachable(trans, builder, body_list2) == 0: - if nb_arr[ci] == 0: - mlirlite.build_br(builder, end_bb) + if nb_arr[ci] == 0: mlirlite.build_br(builder, end_bb) else: nj2: int = ci + 1 - while nj2 < collected and def_arr[nj2] == 1: - nj2 = nj2 + 1 + while nj2 < collected and def_arr[nj2] == 1: nj2 = nj2 + 1 if nj2 < collected: nbb: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](body_arr[nj2]) mlirlite.build_br(builder, nbb) - elif has_default == 1: - mlirlite.build_br(builder, default_bb) - else: - mlirlite.build_br(builder, end_bb) + elif has_default == 1: mlirlite.build_br(builder, default_bb) + else: mlirlite.build_br(builder, end_bb) trans._ctrl_merge_reachable = 1 gm_merge_reach = 1 ci = ci + 1 @@ -1874,8 +1727,7 @@ novirtual class MatchGenMixin: dj3: int = 0 while dj3 < dn3: stmt3: ast.AST* = dbody3.get(dj3) - if stmt3 is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt3) + if stmt3 is not None: self.Gen.StmtGen.translate_stmt(trans, stmt3) dj3 = dj3 + 1 self.Gen.VarGen.exit_scope(trans.SymTab) trans._break_bb = gmd_old_break diff --git a/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp b/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp index 44f20ef..6131671 100644 --- a/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp +++ b/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp @@ -48,8 +48,7 @@ novirtual class StmtGenCifMixin: def _is_cif_attr(self, attr: str) -> int: """检查方法名是否为 CIf 系(CIf/CIfdef/CIfndef)""" - if attr is None: - return 0 + if attr is None: return 0 if string.strcmp(attr, "CIf") == 0: return 1 if string.strcmp(attr, "CIfdef") == 0: return 1 if string.strcmp(attr, "CIfndef") == 0: return 1 @@ -57,25 +56,20 @@ novirtual class StmtGenCifMixin: def _is_cif_call(self, node: ast.AST*) -> int: """检查 test 是否为 c.CIf(...)/c.CIfdef(...)/c.CIfndef(...)(或裸 CIf 系)调用""" - if node is None or node.kind() != ast.ASTKind.Call: - return 0 + if node is None or node.kind() != ast.ASTKind.Call: return 0 cl: ast.Call* = ast.Call*(node) - if cl.func is None: - return 0 + if cl.func is None: return 0 fk: int = cl.func.kind() if fk == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(cl.func) - if at.attr is None: - return 0 + if at.attr is None: return 0 if at.value is not None and at.value.kind() == ast.ASTKind.Name: vn: ast.Name* = ast.Name*(at.value) - if vn.id is not None and string.strcmp(vn.id, "c") == 0: - return self._is_cif_attr(at.attr) + if vn.id is not None and string.strcmp(vn.id, "c") == 0: return self._is_cif_attr(at.attr) return 0 if fk == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(cl.func) - if nm.id is not None and self._is_cif_attr(nm.id) != 0: - return 1 + if nm.id is not None and self._is_cif_attr(nm.id) != 0: return 1 return 0 def _get_platform_macro_value(self, name: str) -> int: @@ -84,20 +78,16 @@ novirtual class StmtGenCifMixin: 命中置 self.CifEvalOk=1;未命中置 0 返回 0。 """ self.CifEvalOk = 0 - if name is None: - return 0 + if name is None: return 0 triple: str = Config.TargetTriple - if triple is None: - triple = "x86_64-pc-windows-gnu" + if triple is None: triple = "x86_64-pc-windows-gnu" is_win: int = 0 is_linux: int = 0 is_x64: int = 0 if string.strstr(triple, "windows") is not None or string.strstr(triple, "win32") is not None or string.strstr(triple, "mingw") is not None or string.strstr(triple, "msvc") is not None: is_win = 1 - if string.strstr(triple, "linux") is not None: - is_linux = 1 - if string.strstr(triple, "x86_64") is not None: - is_x64 = 1 + if string.strstr(triple, "linux") is not None: is_linux = 1 + if string.strstr(triple, "x86_64") is not None: is_x64 = 1 # 简化:本编译目标为 x86_64 Windows(_WIN64/WIN64 恒与 is_win 一致) if string.strcmp(name, "_WIN32") == 0: self.CifEvalOk = is_win; return 1 if is_win else 0 if string.strcmp(name, "WIN32") == 0: self.CifEvalOk = is_win; return 1 if is_win else 0 @@ -120,8 +110,7 @@ novirtual class StmtGenCifMixin: 命中置 self.CifEvalOk=1(值 0 也算命中,如 DISABLED=0);未命中置 0。 """ self.CifEvalOk = 0 - if name is None or trans is None: - return 0 + if name is None or trans is None: return 0 v: int = self.Gen.TypeGenCDef.lookup_cdefine_constant(name) if self.Gen.TypeGenCDef.is_cdefine_found() != 0: self.CifEvalOk = 1 @@ -131,8 +120,7 @@ novirtual class StmtGenCifMixin: self.CifEvalOk = 1 return v2 pv: int = self._get_platform_macro_value(name) - if self.CifEvalOk != 0: - return pv + if self.CifEvalOk != 0: return pv return 0 def _cif_attr_value(self, pool: memhub.MemBuddy*, @@ -143,13 +131,10 @@ novirtual class StmtGenCifMixin: 命中置 self.CifEvalOk=1;未命中置 0。 """ self.CifEvalOk = 0 - if at is None or at.attr is None or at.value is None or trans is None: - return 0 - if at.value.kind() != ast.ASTKind.Name: - return 0 + if at is None or at.attr is None or at.value is None or trans is None: return 0 + if at.value.kind() != ast.ASTKind.Name: return 0 vn: ast.Name* = ast.Name*(at.value) - if vn.id is None: - return 0 + if vn.id is None: return 0 v: int = self.Gen.TypeGenCDef.lookup_cdefine_constant(at.attr) if self.Gen.TypeGenCDef.is_cdefine_found() != 0: self.CifEvalOk = 1 @@ -160,18 +145,15 @@ novirtual class StmtGenCifMixin: resolved: str = self.Gen.ImportsGen.lookup_from_import(trans._from_imports, vn.id, 0) if resolved is not None: rm_len: sizet = 0 - while resolved[rm_len] != ' ' and resolved[rm_len] != '\0' and resolved[rm_len] != ':': - rm_len += 1 + while resolved[rm_len] != ' ' and resolved[rm_len] != '\0' and resolved[rm_len] != ':': rm_len += 1 rm_buf: str = pool.alloc(rm_len + 1) if rm_buf is not None: - for rm_i in range(rm_len): - rm_buf[rm_i] = resolved[rm_i] + for rm_i in range(rm_len): rm_buf[rm_i] = resolved[rm_i] rm_buf[rm_len] = '\0' real_mod = rm_buf fi_len: sizet = string.strlen(at.attr) + string.strlen(real_mod) + 2 fi: str = pool.alloc(fi_len) - if fi is None: - return 0 + if fi is None: return 0 viperlib.snprintf(fi, fi_len, "%s:%s", at.attr, real_mod) v2: int = self.Gen.ExprGenCdef._lookup_cross_module_cdefine(pool, at.attr, fi) if self.Gen.TypeGenCDef.is_cdefine_found() != 0: @@ -200,8 +182,7 @@ novirtual class StmtGenCifMixin: return cn.int_val self.CifEvalOk = 0 return 0 - if k == ast.ASTKind.Call: - return self._cif_eval_call(pool, trans, node) + if k == ast.ASTKind.Call: return self._cif_eval_call(pool, trans, node) if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) if nm.id is None: @@ -217,8 +198,7 @@ novirtual class StmtGenCifMixin: self.CifEvalOk = 0 return 0 ov: int = self._cif_eval_node(pool, trans, uop.operand) - if self.CifEvalOk == 0: - return 0 + if self.CifEvalOk == 0: return 0 if uop.op == ast.OpKind.Not: return 1 if ov == 0 else 0 if uop.op == ast.OpKind.USub: return -ov if uop.op == ast.OpKind.UAdd: return ov @@ -235,26 +215,21 @@ novirtual class StmtGenCifMixin: if bo.op == ast.OpKind.And: for bi in range(bn): rv: int = self._cif_eval_node(pool, trans, vals.get(bi)) - if self.CifEvalOk == 0: - return 0 - if rv == 0: - return 0 + if self.CifEvalOk == 0: return 0 + if rv == 0: return 0 return 1 if bo.op == ast.OpKind.Or: for bi in range(bn): rv: int = self._cif_eval_node(pool, trans, vals.get(bi)) - if self.CifEvalOk == 0: - return 0 - if rv != 0: - return 1 + if self.CifEvalOk == 0: return 0 + if rv != 0: return 1 return 0 self.CifEvalOk = 0 return 0 if k == ast.ASTKind.Compare: cmp: rawptr[ast.Compare] = rawptr[ast.Compare](node) lv: int = self._cif_eval_node(pool, trans, cmp.left) - if self.CifEvalOk == 0: - return 0 + if self.CifEvalOk == 0: return 0 ops_list: list[int]* = (list[int]*)(cmp.ops) comps: list[ast.AST*]* = cmp.comparators if ops_list is None or comps is None: @@ -264,8 +239,7 @@ novirtual class StmtGenCifMixin: ci: sizet for ci in range(cc): rv: int = self._cif_eval_node(pool, trans, comps.get(ci)) - if self.CifEvalOk == 0: - return 0 + if self.CifEvalOk == 0: return 0 op_id: int = ops_list.get(ci) ok_cmp: int = 0 if op_id == ast.OpKind.Eq: ok_cmp = 1 if lv == rv else 0 @@ -277,18 +251,15 @@ novirtual class StmtGenCifMixin: else: self.CifEvalOk = 0 return 0 - if ok_cmp == 0: - return 0 + if ok_cmp == 0: return 0 lv = rv return 1 if k == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(node) lv: int = self._cif_eval_node(pool, trans, bop.left) - if self.CifEvalOk == 0: - return 0 + if self.CifEvalOk == 0: return 0 rv: int = self._cif_eval_node(pool, trans, bop.right) - if self.CifEvalOk == 0: - return 0 + if self.CifEvalOk == 0: return 0 if bop.op == ast.OpKind.Add: return lv + rv if bop.op == ast.OpKind.Sub: return lv - rv if bop.op == ast.OpKind.Mult: return lv * rv @@ -326,14 +297,11 @@ novirtual class StmtGenCifMixin: (与 TPC ConstEvaluator._eval_compile_time_call 的 LLVM 类型判断一致)。 返回: 1=指针 0=非指针 -1=无法求值(变量不存在/无类型信息)。 """ - if name is None or symtab is None: - return -1 + if name is None or symtab is None: return -1 v: mlirlite.Value* = self.Gen.VarGen.lookup_var(symtab, name) - if v is None or v.Ty is None: - return -1 + if v is None or v.Ty is None: return -1 pointee: mlirlite.LLVMType* = v.Ty.Pointee - if pointee is not None and self.Gen.ExprGenBase.is_ptr_type(pointee) != 0: - return 1 + if pointee is not None and self.Gen.ExprGenBase.is_ptr_type(pointee) != 0: return 1 return 0 def _cif_eval_call(self, pool: memhub.MemBuddy*, @@ -344,24 +312,17 @@ novirtual class StmtGenCifMixin: 命中置 self.CifEvalOk=1 返回 1/0;未识别调用置 0 返回 0。 """ self.CifEvalOk = 0 - if node is None or trans is None: - return 0 + if node is None or trans is None: return 0 cl: ast.Call* = ast.Call*(node) - if cl is None or cl.func is None: - return 0 + if cl is None or cl.func is None: return 0 fk: int = cl.func.kind() - if fk != ast.ASTKind.Attribute: - return 0 + if fk != ast.ASTKind.Attribute: return 0 at: ast.Attribute* = ast.Attribute*(cl.func) - if at.value is None or at.attr is None: - return 0 - if at.value.kind() != ast.ASTKind.Name: - return 0 + if at.value is None or at.attr is None: return 0 + if at.value.kind() != ast.ASTKind.Name: return 0 vn: ast.Name* = ast.Name*(at.value) - if vn.id is None: - return 0 - if string.strcmp(vn.id, "ctraits") != 0 or string.strcmp(at.attr, "isptr") != 0: - return 0 + if vn.id is None: return 0 + if string.strcmp(vn.id, "ctraits") != 0 or string.strcmp(at.attr, "isptr") != 0: return 0 cargs: list[ast.AST*]* = cl.args if cargs is None or len(cargs) < 1: self.CifEvalOk = 0 @@ -391,8 +352,7 @@ novirtual class StmtGenCifMixin: """ self.CifEvalOk = 0 cl: ast.Call* = ast.Call*(test) - if cl is None or cl.func is None: - return 0 + if cl is None or cl.func is None: return 0 kind: str = None fk: int = cl.func.kind() if fk == ast.ASTKind.Attribute: @@ -401,23 +361,19 @@ novirtual class StmtGenCifMixin: elif fk == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(cl.func) kind = nm.id - if kind is None: - return 0 + if kind is None: return 0 cargs: list[ast.AST*]* = cl.args - if cargs is None or len(cargs) < 1: - return 0 + if cargs is None or len(cargs) < 1: return 0 arg0: ast.AST* = cargs.get(0) if string.strcmp(kind, "CIf") == 0: v: int = self._cif_eval_node(pool, trans, arg0) - if self.CifEvalOk == 0: - return 0 + if self.CifEvalOk == 0: return 0 return 1 if v != 0 else 0 # CIfdef / CIfndef: 判定宏名是否已定义 defined: int = 0 if arg0 is not None and arg0.kind() == ast.ASTKind.Name: nm0: ast.Name* = ast.Name*(arg0) - if nm0.id is None: - return 0 + if nm0.id is None: return 0 self._cif_name_value(pool, trans, nm0.id) defined = self.CifEvalOk elif arg0 is not None and arg0.kind() == ast.ASTKind.Constant: @@ -425,18 +381,15 @@ novirtual class StmtGenCifMixin: if cn0.const_kind == ast.CONST_STR and cn0.str_val is not None: self._cif_name_value(pool, trans, cn0.str_val) defined = self.CifEvalOk - else: - return 0 + else: return 0 elif arg0 is not None and arg0.kind() == ast.ASTKind.Attribute: at0: ast.Attribute* = ast.Attribute*(arg0) self._cif_attr_value(pool, trans, at0) defined = self.CifEvalOk - else: - return 0 + else: return 0 # 定义判定本身成功(未定义名特判:不报错,defined=0 走 else) self.CifEvalOk = 1 - if string.strcmp(kind, "CIfdef") == 0: - return 1 if defined != 0 else 0 + if string.strcmp(kind, "CIfdef") == 0: return 1 if defined != 0 else 0 # CIfndef return 0 if defined != 0 else 1 @@ -450,8 +403,7 @@ novirtual class StmtGenCifMixin: node: ast.AST*) -> int: """翻译 Return 语句""" rt: rawptr[ast.Return] = rawptr[ast.Return](node) - if rt is None: - return 0 + if rt is None: return 0 pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder @@ -469,8 +421,7 @@ novirtual class StmtGenCifMixin: rtp: ast.Tuple* = ast.Tuple*(rt.value) rtp_elts: list[ast.AST*]* = rtp.elts rt_n: sizet = 0 - if rtp_elts is not None: - rt_n = len(rtp_elts) + if rtp_elts is not None: rt_n = len(rtp_elts) if rt_n > 0 and rt_n <= 16: rt_vals: sizet* = pool.alloc(8 * 16) if rt_vals is not None: @@ -497,17 +448,13 @@ novirtual class StmtGenCifMixin: if rn is None: rt_val_ok = 0 break - if rt_head is None: - rt_head = rn - else: - mlirlite.paramnode_set_next(rt_tail, rn) + if rt_head is None: rt_head = rn + else: mlirlite.paramnode_set_next(rt_tail, rn) rt_tail = rn rt_struct_ty: mlirlite.LLVMType* = None - if rt_val_ok != 0 and rt_head is not None: - rt_struct_ty = mlirlite.Struct(pool, rt_head, rt_n, None) + if rt_val_ok != 0 and rt_head is not None: rt_struct_ty = mlirlite.Struct(pool, rt_head, rt_n, None) rt_tmp: mlirlite.Value* = None - if rt_struct_ty is not None: - rt_tmp = mlirlite.build_alloca(builder, rt_struct_ty) + if rt_struct_ty is not None: rt_tmp = mlirlite.build_alloca(builder, rt_struct_ty) if rt_tmp is not None: rvi3: sizet for rvi3 in range(rt_n): @@ -517,8 +464,7 @@ novirtual class StmtGenCifMixin: rt_val_ok = 0 break mlirlite.build_store(builder, rv3, rfp) - if rt_val_ok != 0: - val = mlirlite.build_load(builder, rt_struct_ty, rt_tmp) + if rt_val_ok != 0: val = mlirlite.build_load(builder, rt_struct_ty, rt_tmp) # return self: 返回 self 指针本身(Ptr(StructTy)),而非结构体值 # translate_value 会 load 得到结构体值,但 return self 需要指针 # 注意: lookup_var 返回的是存储 self 的 alloca (Ptr(Ptr(StructTy))) @@ -536,16 +482,14 @@ novirtual class StmtGenCifMixin: if self_pointee_ty is not None and self.Gen.ExprGenBase.is_ptr_type(self_pointee_ty) != 0: # Ptr(Ptr(StructTy)) → load 得到 Ptr(StructTy) val = mlirlite.build_load(builder, self_pointee_ty, self_ptr) - else: - val = self_ptr + else: val = self_ptr if val is None: # P1-A(上下文位宽传播):把当前函数的返回类型作为 target_ty 传入, # 使 `return 12345`(-> uint64)直接物化 i64 常量,与 `return u64(12345)` # 一致,并省去下方返回类型对齐生成的 zext。 ret_val_ty: mlirlite.LLVMType* = None cur_func_rv: mlirlite.Function* = trans._cur_func - if cur_func_rv is not None: - ret_val_ty = mlirlite.function_get_ret_ty(cur_func_rv) + if cur_func_rv is not None: ret_val_ty = mlirlite.function_get_ret_ty(cur_func_rv) # [C①] 返回注解上下文:记录本次 return 的直接值节点,供裸名泛型 # 构造(`-> Stack[int]` 里 `return Stack()`)用 CurFuncRetAnnot # 里的类型实参特化;仅该直接值生效(identity 判定在 CallGenCtor)。 @@ -600,8 +544,7 @@ novirtual class StmtGenCifMixin: # 也必须 inttoptr 转换,否则 llc 报 "value doesn't match function result type" cur_func_rt: mlirlite.Function* = trans._cur_func ret_ty_rt: mlirlite.LLVMType* = None - if cur_func_rt is not None and val is not None and val.Ty is not None: - ret_ty_rt = mlirlite.function_get_ret_ty(cur_func_rt) + if cur_func_rt is not None and val is not None and val.Ty is not None: ret_ty_rt = mlirlite.function_get_ret_ty(cur_func_rt) # void 函数 return :丢弃值 + ret void(Python 语义合法;此前 # 直接 build_ret(val) 生成 ret i32 与 define void 冲突 → llc "value # doesn't match function result type 'void'"——GenApi.add_global_name @@ -633,10 +576,8 @@ novirtual class StmtGenCifMixin: # 不写盘,下遍依赖就绪后多遍收敛精确解析(否则 fail-fast 硬 # 中断多遍收敛,memhub↔_list 环永不求解)。 fn_nm_ret: str = None - if cur_func_rt is not None: - fn_nm_ret = mlirlite.function_get_name(cur_func_rt) - if fn_nm_ret is not None and string.strstr(fn_nm_ret, "__new__") is not None and val_is_ptr == 0 and ret_is_ptr != 0: - val = mlirlite.build_inttoptr(builder, val, ret_ty_rt) + if cur_func_rt is not None: fn_nm_ret = mlirlite.function_get_name(cur_func_rt) + if fn_nm_ret is not None and string.strstr(fn_nm_ret, "__new__") is not None and val_is_ptr == 0 and ret_is_ptr != 0: val = mlirlite.build_inttoptr(builder, val, ret_ty_rt) else: # 传 trans:Phase A 依赖未就绪(_deps_pending)时,跨模块调用 # 返回类型退化为默认 i32,int→ptr 是退化指针重建而非隐式转换 @@ -656,11 +597,9 @@ novirtual class StmtGenCifMixin: match ret_ty_rt: case mlirlite.LLVMType.Ptr(r_inner): ret_pointee = r_inner - if val_pointee is not None and ret_pointee is not None and uint64(val_pointee) != uint64(ret_pointee): - val = self.Gen.ExprGenBase.coerce_to_type(builder, val, ret_ty_rt, node) + if val_pointee is not None and ret_pointee is not None and uint64(val_pointee) != uint64(ret_pointee): val = self.Gen.ExprGenBase.coerce_to_type(builder, val, ret_ty_rt, node) elif val_bits != 0 and ret_bits != 0 and val_bits != ret_bits: - if val_bits == 1 and val_bits < ret_bits: - val = mlirlite.build_zext(builder, val, ret_ty_rt) + if val_bits == 1 and val_bits < ret_bits: val = mlirlite.build_zext(builder, val, ret_ty_rt) else: # 传 trans:无符号源类型(uint16/uint32/CSizeT 等)扩展用 zext, # 缺 trans 时 _node_type_unsigned 查不到变量注解 → 误 sext @@ -694,15 +633,13 @@ novirtual class StmtGenCifMixin: def translate_if(self, trans: HT.Translator*, node: ast.AST*) -> int: """翻译 if/elif/else 语句""" - if node is None: - return 0 + if node is None: return 0 pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder func: mlirlite.Function* = trans._cur_func - if builder is None or func is None: - return 0 + if builder is None or func is None: return 0 if_node: rawptr[ast.If] = rawptr[ast.If](node) @@ -719,8 +656,7 @@ novirtual class StmtGenCifMixin: bi_cif: sizet for bi_cif in range(bc_cif): stmt_cif: ast.AST* = body_cif.get(bi_cif) - if stmt_cif is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt_cif) + if stmt_cif is not None: self.Gen.StmtGen.translate_stmt(trans, stmt_cif) else: orelse_cif: list[ast.AST*]* = if_node.orelse if orelse_cif is not None and len(orelse_cif) == 1: @@ -728,15 +664,13 @@ novirtual class StmtGenCifMixin: if sub_cif is not None and sub_cif.kind() == ast.ASTKind.If: # elif: 递归(子 If 的 test 仍会走 CIf 判定或运行时翻译) self.translate_if(trans, sub_cif) - elif sub_cif is not None: - self.Gen.StmtGen.translate_stmt(trans, sub_cif) + elif sub_cif is not None: self.Gen.StmtGen.translate_stmt(trans, sub_cif) elif orelse_cif is not None: oc_cif: sizet = len(orelse_cif) oi_cif: sizet for oi_cif in range(oc_cif): stmt_cif2: ast.AST* = orelse_cif.get(oi_cif) - if stmt_cif2 is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt_cif2) + if stmt_cif2 is not None: self.Gen.StmtGen.translate_stmt(trans, stmt_cif2) return 0 # 1. 求值条件表达式 @@ -764,8 +698,7 @@ novirtual class StmtGenCifMixin: has_else: int = 0 orelse_list: list[ast.AST*]* = if_node.orelse if orelse_list is not None: - if len(orelse_list) > 0: - has_else = 1 + if len(orelse_list) > 0: has_else = 1 else_bb: rawptr[mlirlite.BasicBlock] = None if has_else == 1: @@ -773,10 +706,8 @@ novirtual class StmtGenCifMixin: else_bb = mlirlite.create_block(pool, func, name_buf) # 4. 发射条件分支 - if has_else == 1: - mlirlite.build_cond_br(builder, cond_i1, then_bb, else_bb) - else: - mlirlite.build_cond_br(builder, cond_i1, then_bb, merge_bb) + if has_else == 1: mlirlite.build_cond_br(builder, cond_i1, then_bb, else_bb) + else: mlirlite.build_cond_br(builder, cond_i1, then_bb, merge_bb) # 5. 翻译 then body # 重置 merge 可达标志:分支内嵌套控制流会覆盖该标志,分支末尾判定依据 @@ -789,8 +720,7 @@ novirtual class StmtGenCifMixin: body_count: sizet = len(body) for bi in range(body_count): stmt: ast.AST* = body.get(bi) - if stmt is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt) + if stmt is not None: self.Gen.StmtGen.translate_stmt(trans, stmt) # then 块未终止则跳到 merge(记录 then 是否 br 到 merge) then_branches_merge: int = 0 @@ -815,8 +745,7 @@ novirtual class StmtGenCifMixin: else_count: sizet = len(orelse_list) for ei in range(else_count): stmt: ast.AST* = orelse_list.get(ei) - if stmt is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt) + if stmt is not None: self.Gen.StmtGen.translate_stmt(trans, stmt) if mlirlite.builder_cur_block_is_terminated(builder) == 0: if trans._ctrl_merge_reachable == 0: # 嵌套控制流全分支 return:补 unreachable,不 br merge(同 then 分支) @@ -829,8 +758,7 @@ novirtual class StmtGenCifMixin: # 有 else 时任一分支 br 到 merge 即可达;全分支 return(无 br)才结构性不可达。 # 经 HandlesBase 模块级全局传递(避免依赖 Translator 字段表)。 trans._ctrl_merge_reachable = 1 - if has_else == 1 and then_branches_merge == 0 and else_branches_merge == 0: - trans._ctrl_merge_reachable = 0 + if has_else == 1 and then_branches_merge == 0 and else_branches_merge == 0: trans._ctrl_merge_reachable = 0 # 8. 定位到 merge 块继续后续代码 mlirlite.position_at_end(builder, merge_bb) @@ -846,10 +774,8 @@ novirtual class StmtGenCifMixin: # ============================================================ def _LoopElseCount(self, orelse_list: list[ast.AST*]*) -> int: """orelse 非空返回 1(有 else 子句)""" - if orelse_list is None: - return 0 - if len(orelse_list) > 0: - return 1 + if orelse_list is None: return 0 + if len(orelse_list) > 0: return 1 return 0 def _MakeLoopElseBlock(self, pool: memhub.MemBuddy*, @@ -857,10 +783,8 @@ novirtual class StmtGenCifMixin: name_buf: str, kind: str, cnt: int, has_else: int) -> rawptr[mlirlite.BasicBlock]: """has_else=0 返回 None;否则 snprintf(name_buf,32,"%s.else.%d",kind,cnt) 并 create_block""" - if has_else == 0: - return None - if func is None: - return None + if has_else == 0: return None + if func is None: return None viperlib.snprintf(name_buf, 32, "%s.else.%d", kind, cnt) return mlirlite.create_block(pool, func, name_buf) @@ -872,11 +796,9 @@ novirtual class StmtGenCifMixin: 若当前块未终止则 build_br(end_bb) 并返回 1;否则返回 0。 else_bb 为空:直接返回 0(调用方自己 position_at_end(end_bb))。 翻译 orelse 前须置 trans._ctrl_merge_reachable = 1(对齐 translate_if 的做法)。""" - if else_bb is None: - return 0 + if else_bb is None: return 0 builder: mlirlite.IRBuilder* = trans._cur_builder - if builder is None: - return 0 + if builder is None: return 0 # 对齐 translate_if:翻译分支前重置 merge 可达标志,防上层残留值污染 trans._ctrl_merge_reachable = 1 mlirlite.position_at_end(builder, else_bb) @@ -884,8 +806,7 @@ novirtual class StmtGenCifMixin: n: sizet = len(orelse_list) for i in range(n): stmt: ast.AST* = orelse_list.get(i) - if stmt is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt) + if stmt is not None: self.Gen.StmtGen.translate_stmt(trans, stmt) if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, end_bb) return 1 @@ -908,15 +829,13 @@ novirtual class StmtGenCifMixin: def translate_while(self, trans: HT.Translator*, node: ast.AST*) -> int: """翻译 while 循环语句""" - if node is None: - return 0 + if node is None: return 0 pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder func: mlirlite.Function* = trans._cur_func - if builder is None or func is None: - return 0 + if builder is None or func is None: return 0 while_node: rawptr[ast.While] = rawptr[ast.While](node) @@ -967,15 +886,13 @@ novirtual class StmtGenCifMixin: body_count: sizet = len(body) for bi in range(body_count): stmt: ast.AST* = body.get(bi) - if stmt is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt) + if stmt is not None: self.Gen.StmtGen.translate_stmt(trans, stmt) # 恢复旧循环上下文 trans._break_bb = old_break trans._continue_bb = old_continue - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, cond_bb) + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, cond_bb) # 5. 循环 else 收尾(自然退出时先执行 orelse),再定位到 end 块 ret_while: int = self._EmitLoopElse(trans, while_node.orelse, else_bb_while, end_bb) @@ -990,8 +907,7 @@ novirtual class StmtGenCifMixin: # 修复 vrandom.gammavariate 的 while True 全 return 被误判"流程掉出末尾"。 # [else 子句] 有 else 时 else_bb 会 br 到 end_bb ⇒ merge 结构性可达, # 不能再置 0(否则 end 块被 unreachable 收尾,与 else 的 br 冲突)。 - if has_else_while == 0 and self._IsConstTrue(while_node.test) != 0 and self._StmtHasBreak(body) == 0: - trans._ctrl_merge_reachable = 0 + if has_else_while == 0 and self._IsConstTrue(while_node.test) != 0 and self._StmtHasBreak(body) == 0: trans._ctrl_merge_reachable = 0 return 0 # ============================================================ @@ -1003,52 +919,39 @@ novirtual class StmtGenCifMixin: # ============================================================ def _IsConstTrue(self, test: ast.AST*) -> int: """while 条件为常量真(1 / True)返回 1""" - if test is None: - return 0 + if test is None: return 0 if test.kind() == ast.ASTKind.Constant: cn: ast.Constant* = ast.Constant*(test) - if cn.const_kind == ast.CONST_INT and cn.int_val != 0: - return 1 - if cn.const_kind == ast.CONST_BOOL and cn.int_val != 0: - return 1 + if cn.const_kind == ast.CONST_INT and cn.int_val != 0: return 1 + if cn.const_kind == ast.CONST_BOOL and cn.int_val != 0: return 1 return 0 def _NodeHasBreak(self, node: ast.AST*) -> int: """递归扫描节点子树(跳过嵌套 While/For 子树),含 Break 返回 1""" - if node is None: - return 0 + if node is None: return 0 ch: list[ast.AST*]* = node.children if ch is not None: n: sizet = len(ch) for bi in range(n): c: ast.AST* = ch.get(bi) - if c is None: - continue + if c is None: continue k: int = c.kind() - if k == ast.ASTKind.Break: - return 1 - if k == ast.ASTKind.While or k == ast.ASTKind.For: - continue - if self._NodeHasBreak(c) != 0: - return 1 + if k == ast.ASTKind.Break: return 1 + if k == ast.ASTKind.While or k == ast.ASTKind.For: continue + if self._NodeHasBreak(c) != 0: return 1 return 0 def _StmtHasBreak(self, body: list[ast.AST*]*) -> int: """语句列表是否含本层 break(嵌套循环的 break 归内层)""" - if body is None: - return 0 + if body is None: return 0 n: sizet = len(body) for bi in range(n): s: ast.AST* = body.get(bi) - if s is None: - continue + if s is None: continue k: int = s.kind() - if k == ast.ASTKind.Break: - return 1 - if k == ast.ASTKind.While or k == ast.ASTKind.For: - continue - if self._NodeHasBreak(s) != 0: - return 1 + if k == ast.ASTKind.Break: return 1 + if k == ast.ASTKind.While or k == ast.ASTKind.For: continue + if self._NodeHasBreak(s) != 0: return 1 return 0 # ============================================================ @@ -1075,36 +978,30 @@ novirtual class StmtGenCifMixin: def translate_for(self, trans: HT.Translator*, node: ast.AST*) -> int: """翻译 for i in range(...) 循环语句""" - if node is None: - return 0 + if node is None: return 0 pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder func: mlirlite.Function* = trans._cur_func - if builder is None or func is None: - return 0 + if builder is None or func is None: return 0 for_node: ast.For* = ast.For*(node) # 1. 获取循环变量(Name 单变量 / Tuple 多变量) target: ast.AST* = for_node.target - if target is None: - return 0 + if target is None: return 0 tk: int = target.kind() - if tk != ast.ASTKind.Name and tk != ast.ASTKind.Tuple: - return 0 + if tk != ast.ASTKind.Name and tk != ast.ASTKind.Tuple: return 0 var_name: str = None if tk == ast.ASTKind.Name: target_nm: ast.Name* = ast.Name*(target) var_name = target_nm.id - if var_name is None: - return 0 + if var_name is None: return 0 # 2. 解析迭代器:支持 range() 和指针迭代 iter_node: ast.AST* = for_node.iter - if iter_node is None: - return 0 + if iter_node is None: return 0 # 检查是否是 range() 调用 is_range_iter: int = 0 @@ -1112,8 +1009,7 @@ novirtual class StmtGenCifMixin: call_pre: ast.Call* = ast.Call*(iter_node) fn_pre: str = self.Gen.ExprGenBase.get_func_name(call_pre.func) if fn_pre is not None: - if string.strcmp(fn_pre, "range") == 0: - is_range_iter = 1 + if string.strcmp(fn_pre, "range") == 0: is_range_iter = 1 elif string.strcmp(fn_pre, "enumerate") == 0 or string.strcmp(fn_pre, "zip") == 0: pass # 多变量迭代,在下方非 range 分支处理 else: @@ -1126,37 +1022,30 @@ novirtual class StmtGenCifMixin: # 非范围迭代:走指针/数组/列表字面量/容器/多变量迭代路径 if is_range_iter == 0: # 列表字面量:按元素顺序迭代(for x in [1, 2, 3]) - if iter_node.kind() == ast.ASTKind.List: - return self._handle_list_literal_iter(trans, for_node, var_name, iter_node) + if iter_node.kind() == ast.ASTKind.List: return self._handle_list_literal_iter(trans, for_node, var_name, iter_node) # enumerate(x):for i, v in enumerate(x)(多变量迭代) if iter_node.kind() == ast.ASTKind.Call: 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 迭代需要两个循环变量 (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 + 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 迭代变量必须是简单名称") 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 迭代需要两个循环变量 (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 + 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 迭代变量必须是简单名称") return self._handle_zip_iter(trans, for_node, t1_buf_iz, t2_buf_iz, call_mi) # list[T] 容器变量:按 __count__ 动态长度迭代 if iter_node.kind() == ast.ASTKind.Name and trans is not None: @@ -1171,14 +1060,12 @@ novirtual class StmtGenCifMixin: if TSpec.SpecTypeNameBaseIs(lst_annot, "dict") != 0: lst_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, iter_node, trans._funcs, trans._func_count, trans) - if lst_val is not None and lst_val.Ty is not None and self.Gen.ExprGenBase.is_ptr_type(lst_val.Ty) != 0: - return self._handle_dict_iter(trans, for_node, var_name, lst_val) + if lst_val is not None and lst_val.Ty is not None and self.Gen.ExprGenBase.is_ptr_type(lst_val.Ty) != 0: return self._handle_dict_iter(trans, for_node, var_name, lst_val) # [S4] 同上:原 strstr("list") 会误命中 playlist / GSList 等; # 非 list 基名的用户类改由下方 OOP __iter__/__next__ 路径处理(更正确)。 if TSpec.SpecTypeNameBaseIs(lst_annot, "list") != 0: lst_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, iter_node, trans._funcs, trans._func_count, trans) - if lst_val is not None and lst_val.Ty is not None and self.Gen.ExprGenBase.is_ptr_type(lst_val.Ty) != 0: - return self._handle_list_iter(trans, for_node, var_name, lst_val) + if lst_val is not None and lst_val.Ty is not None and self.Gen.ExprGenBase.is_ptr_type(lst_val.Ty) != 0: return self._handle_list_iter(trans, for_node, var_name, lst_val) # OOP iter 协议:迭代源是类对象且类有 __iter__/__next__ 方法 → # 走 __iter__/__next__ 调用迭代(对齐 TPC HandlesFor.py L142-166 # _HandleForIterLlvm)。dict/list 是内置泛型容器已在上方内联处理。 @@ -1198,15 +1085,13 @@ novirtual class StmtGenCifMixin: if on_lookup is not None: viperlib.snprintf(on_lookup, 128, "%s.__next__", ov_cn) on_fn: mlirlite.Function* = self.Gen.CallGenBase.find_func_in_module(trans.Module, on_lookup) - if on_fn is not None: - return self._handle_oop_iter(trans, for_node, var_name, ov_cn, ov_val) + if on_fn is not None: return self._handle_oop_iter(trans, for_node, var_name, ov_cn, ov_val) # 其它不支持的字面量:fast-fail 显式报错, # 避免 translate_value 触发 list[T] 特化崩溃或语义歧义。 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 迭代不支持该常量(仅支持字符串、数组、列表字面量、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 数组或列表字面量") return self._handle_ptr_iter(trans, for_node, var_name) @@ -1215,8 +1100,7 @@ novirtual class StmtGenCifMixin: # 3. 解析 range 参数: range(stop) / range(start, stop) / range(start, stop, step) args: list[ast.AST*]* = call.args - if args is None: - return 0 + if args is None: return 0 arg_count: sizet = len(args) i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) @@ -1260,12 +1144,10 @@ novirtual class StmtGenCifMixin: if uop_r.op == ast.OpKind.USub and uop_r.operand is not None: if uop_r.operand.kind() == ast.ASTKind.Constant: uoc_r: ast.Constant* = ast.Constant*(uop_r.operand) - if uoc_r.int_val > 0: - step_neg_const = 1 + if uoc_r.int_val > 0: step_neg_const = 1 elif skn == ast.ASTKind.Constant: skc_r: ast.Constant* = ast.Constant*(step_arg_node) - if skc_r.int_val < 0: - step_neg_const = 1 + if skc_r.int_val < 0: step_neg_const = 1 # 3.5 循环变量存储位宽随 range 参数类型(uint64→i64 / uint16→i16 / uint8→i8 / 其余→i32), # 不固定 i32:固定 i32 alloca 会截断 uint64 上界(range(heap_end, new_end, 4096) @@ -1274,22 +1156,16 @@ novirtual class StmtGenCifMixin: loop_store_ty: mlirlite.LLVMType* = i32_ty range_arg_bits: int = 0 if arg_count == 1: - if stop_val is not None and stop_val.Ty is not None: - range_arg_bits = self.Gen.ExprGenBase.get_llvm_type_bits(stop_val.Ty) + if stop_val is not None and stop_val.Ty is not None: range_arg_bits = self.Gen.ExprGenBase.get_llvm_type_bits(stop_val.Ty) else: start_bits_rt: int = 0 stop_bits_rt: int = 0 - if start_val is not None and start_val.Ty is not None: - start_bits_rt = self.Gen.ExprGenBase.get_llvm_type_bits(start_val.Ty) - if stop_val is not None and stop_val.Ty is not None: - stop_bits_rt = self.Gen.ExprGenBase.get_llvm_type_bits(stop_val.Ty) + if start_val is not None and start_val.Ty is not None: start_bits_rt = self.Gen.ExprGenBase.get_llvm_type_bits(start_val.Ty) + if stop_val is not None and stop_val.Ty is not None: stop_bits_rt = self.Gen.ExprGenBase.get_llvm_type_bits(stop_val.Ty) range_arg_bits = start_bits_rt if start_bits_rt > stop_bits_rt else stop_bits_rt - if range_arg_bits == 64: - loop_store_ty = mlirlite.Int64(pool) - elif range_arg_bits == 16: - loop_store_ty = mlirlite.Int16(pool) - elif range_arg_bits == 8: - loop_store_ty = mlirlite.Int8(pool) + if range_arg_bits == 64: loop_store_ty = mlirlite.Int64(pool) + elif range_arg_bits == 16: loop_store_ty = mlirlite.Int16(pool) + elif range_arg_bits == 8: loop_store_ty = mlirlite.Int8(pool) # 3.6 循环无符号性:循环变量注解或任一 range 边界为无符号整型 → # icmp ult/ugt 而非 slt/sgt(复用 ExprGenOps._node_type_unsigned: @@ -1298,8 +1174,7 @@ novirtual class StmtGenCifMixin: # fat32 的 i/s 已声明 uint32/uint8,靠循环变量注解判定。 loop_unsigned: int = 0 if tk == ast.ASTKind.Name: - if self.Gen.ExprGenOps._node_type_unsigned(pool, target, trans) != 0: - loop_unsigned = 1 + if self.Gen.ExprGenOps._node_type_unsigned(pool, target, trans) != 0: loop_unsigned = 1 if loop_unsigned == 0: args_u: sizet for args_u in range(arg_count): @@ -1328,14 +1203,11 @@ novirtual class StmtGenCifMixin: if stop_uop.op == ast.OpKind.USub and stop_uop.operand is not None: if stop_uop.operand.kind() == ast.ASTKind.Constant: stop_uc: ast.Constant* = ast.Constant*(stop_uop.operand) - if stop_uc.int_val > 0: - stop_neg_const = 1 + if stop_uc.int_val > 0: stop_neg_const = 1 elif stn_k == ast.ASTKind.Constant: stop_c: ast.Constant* = ast.Constant*(stop_arg_node) - if stop_c.int_val < 0: - stop_neg_const = 1 - if stop_neg_const != 0: - loop_unsigned = 0 + if stop_c.int_val < 0: stop_neg_const = 1 + if stop_neg_const != 0: loop_unsigned = 0 # 4. 创建/查找循环变量 alloca # 必须用 lookup_current(仅当前作用域):闭包内 lookup_var 会跨函数 @@ -1354,8 +1226,7 @@ novirtual class StmtGenCifMixin: # 位宽随 range 参数类型(loop_store_ty),不再固定 i32: # uint64 上界 → i64 alloca,避免 trunc i64→i32 丢失高位。 var_alloca = self.Gen.VarGen._alloca_at_entry(builder, loop_store_ty) - if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0: - new_vars = 1 + if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0: new_vars = 1 # 获取循环变量的实际元素类型(alloca 是指针类型,需解引用 Pointee) # 当循环变量已声明为 i64(如 sizet),使用 i64 而非硬编码 i32 @@ -1364,8 +1235,7 @@ novirtual class StmtGenCifMixin: if var_alloca is not None and var_alloca.Ty is not None: match var_alloca.Ty: case mlirlite.LLVMType.Ptr(pointee_ty): - if pointee_ty is not None: - loop_var_ty = pointee_ty + if pointee_ty is not None: loop_var_ty = pointee_ty loop_var_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(loop_var_ty) # 5. 存储初始值 (类型对齐: start_val 可能是 i32/i64,需对齐到 loop_var_ty) @@ -1373,10 +1243,8 @@ novirtual class StmtGenCifMixin: if start_val is not None and start_val.Ty is not None: start_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(start_val.Ty) if start_bits != 0 and start_bits != loop_var_bits: - if start_bits < loop_var_bits: - init_val = mlirlite.build_sext(builder, start_val, loop_var_ty) - else: - init_val = mlirlite.build_trunc(builder, start_val, loop_var_ty) + if start_bits < loop_var_bits: init_val = mlirlite.build_sext(builder, start_val, loop_var_ty) + else: init_val = mlirlite.build_trunc(builder, start_val, loop_var_ty) mlirlite.build_store(builder, init_val, var_alloca) # 6. 创建基本块: cond / body / incr / end(使用 trans._label_counter,不与 SSA 名共享) @@ -1413,8 +1281,7 @@ novirtual class StmtGenCifMixin: stop_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(stop_val.Ty) cur_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(cur_i.Ty) if stop_bits != 0 and cur_bits != 0 and stop_bits != cur_bits: - if cur_bits < stop_bits: - cmp_lhs = mlirlite.build_sext(builder, cur_i, stop_val.Ty) + if cur_bits < stop_bits: cmp_lhs = mlirlite.build_sext(builder, cur_i, stop_val.Ty) else: # 循环变量位宽 > stop 位宽(如 sizet 循环变量 + range(i32)):应把 cur_i 截断到 # stop_val 类型(低向高才 sext/zext,高向低用 trunc)。反过来把小的 stop_val @@ -1422,14 +1289,11 @@ novirtual class StmtGenCifMixin: cmp_lhs = mlirlite.build_trunc(builder, cur_i, stop_val.Ty) # 有符号基准谓词:step 为负时条件反转(i > stop,SGT);正/缺省 i < stop(SLT) range_cmp_op: int = mlirlite.ICMP_SLT - if step_neg_const != 0: - range_cmp_op = mlirlite.ICMP_SGT + if step_neg_const != 0: range_cmp_op = mlirlite.ICMP_SGT # 无符号循环:改用无符号谓词(正步长 ult / 负步长 ugt) if loop_unsigned != 0: - if step_neg_const != 0: - range_cmp_op = mlirlite.ICMP_UGT - else: - range_cmp_op = mlirlite.ICMP_ULT + if step_neg_const != 0: range_cmp_op = mlirlite.ICMP_UGT + else: range_cmp_op = mlirlite.ICMP_ULT cond_i1: mlirlite.Value* = mlirlite.build_icmp(builder, range_cmp_op, cmp_lhs, cmp_rhs) mlirlite.build_cond_br(builder, cond_i1, body_bb, else_bb_for if else_bb_for is not None else end_bb) @@ -1447,15 +1311,13 @@ novirtual class StmtGenCifMixin: body_count: sizet = len(body) for bi in range(body_count): stmt: ast.AST* = body.get(bi) - if stmt is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt) + if stmt is not None: self.Gen.StmtGen.translate_stmt(trans, stmt) # 恢复旧循环上下文 trans._break_bb = old_break trans._continue_bb = old_continue - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, incr_bb) + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, incr_bb) # 10. incr 块: i = i + step, 跳回 cond mlirlite.position_at_end(builder, incr_bb) @@ -1466,10 +1328,8 @@ novirtual class StmtGenCifMixin: step_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(step_val.Ty) cur2_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(cur_i2.Ty) if step_bits != 0 and cur2_bits != 0 and step_bits != cur2_bits: - if step_bits > cur2_bits: - incr_step = mlirlite.build_trunc(builder, step_val, loop_var_ty) - else: - incr_step = mlirlite.build_sext(builder, step_val, loop_var_ty) + if step_bits > cur2_bits: incr_step = mlirlite.build_trunc(builder, step_val, loop_var_ty) + else: incr_step = mlirlite.build_sext(builder, step_val, loop_var_ty) next_i: mlirlite.Value* = mlirlite.build_add(builder, cur_i2, incr_step) mlirlite.build_store(builder, next_i, var_alloca) mlirlite.build_br(builder, cond_bb) @@ -1491,22 +1351,17 @@ novirtual class StmtGenCifMixin: def _extract_tuple_names(self, tup: ast.Tuple*, out1: str, out2: str) -> int: """从 Tuple target 提取前两个 Name 变量名,写入 out1/out2,成功返回 1""" - if tup is None or tup.elts is None or out1 is None or out2 is None: - return 0 + if tup is None or tup.elts is None or out1 is None or out2 is None: return 0 elts: list[ast.AST*]* = tup.elts n: sizet = len(elts) - if n < 2: - return 0 + if n < 2: return 0 e0: ast.AST* = elts.get(0) e1: ast.AST* = elts.get(1) - if e0 is None or e1 is None: - return 0 - if e0.kind() != ast.ASTKind.Name or e1.kind() != ast.ASTKind.Name: - return 0 + if e0 is None or e1 is None: return 0 + if e0.kind() != ast.ASTKind.Name or e1.kind() != ast.ASTKind.Name: return 0 n0: ast.Name* = ast.Name*(e0) n1: ast.Name* = ast.Name*(e1) - if n0.id is None or n1.id is None: - return 0 + if n0.id is None or n1.id is None: return 0 string.strcpy(out1, n0.id) string.strcpy(out2, n1.id) return 1 @@ -1514,19 +1369,16 @@ novirtual class StmtGenCifMixin: def _seq_kind(self, trans: HT.Translator*, src: ast.AST*) -> int: """判断迭代源类型: SEQ_KIND_RANGE / STR / LIST,不支持返回 0""" - if src is None: - return 0 + if src is None: return 0 k: int = src.kind() if k == ast.ASTKind.Call: cl_s: ast.Call* = ast.Call*(src) fn_s: str = self.Gen.ExprGenBase.get_func_name(cl_s.func) - if fn_s is not None and string.strcmp(fn_s, "range") == 0: - return GenTypes.SEQ_KIND_RANGE + if fn_s is not None and string.strcmp(fn_s, "range") == 0: return GenTypes.SEQ_KIND_RANGE return 0 if k == ast.ASTKind.Constant: cn_s: ast.Constant* = ast.Constant*(src) - if cn_s is not None and cn_s.const_kind == ast.CONST_STR: - return GenTypes.SEQ_KIND_STR + if cn_s is not None and cn_s.const_kind == ast.CONST_STR: return GenTypes.SEQ_KIND_STR return 0 if k == ast.ASTKind.Name: nm_s: ast.Name* = ast.Name*(src) @@ -1535,8 +1387,7 @@ novirtual class StmtGenCifMixin: sq_annot: str = self.Gen.VarGen.var_annot_class_name(ve_s) if sq_annot is not None: # [S4] 容器基名精确比较(原 strstr("list") 子串匹配会误命中 playlist 等) - if TSpec.SpecTypeNameBaseIs(sq_annot, "list") != 0: - return GenTypes.SEQ_KIND_LIST + if TSpec.SpecTypeNameBaseIs(sq_annot, "list") != 0: return GenTypes.SEQ_KIND_LIST return GenTypes.SEQ_KIND_STR return 0 @@ -1562,8 +1413,7 @@ novirtual class StmtGenCifMixin: # ---- 源 1 准备 ---- 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, "序列迭代: 源 1 类型不支持") r1_start: mlirlite.Value* = None r1_stop: mlirlite.Value* = None r1_step: mlirlite.Value* = None @@ -1604,13 +1454,11 @@ novirtual class StmtGenCifMixin: 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, "序列迭代: 字符串源翻译失败") 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, "序列迭代: list 源不是指针类型") 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))) @@ -1627,8 +1475,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, "序列迭代: 源 2 类型不支持") if kind2 == GenTypes.SEQ_KIND_RANGE: elem2_ty = i32_ty r2_start = mlirlite.const_int64(pool, 0) @@ -1660,13 +1507,11 @@ novirtual class StmtGenCifMixin: 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, "序列迭代: 字符串源 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, "序列迭代: list 源 2 不是指针类型") 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))) @@ -1676,20 +1521,16 @@ novirtual class StmtGenCifMixin: t1_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, t1) new_vars: int = 0 if t1_alloca is None: - if n_srcs == 1: - t1_alloca = self.Gen.VarGen._alloca_at_entry(builder, i32_ty) - else: - t1_alloca = self.Gen.VarGen._alloca_at_entry(builder, elem1_ty) + if n_srcs == 1: t1_alloca = self.Gen.VarGen._alloca_at_entry(builder, i32_ty) + else: t1_alloca = self.Gen.VarGen._alloca_at_entry(builder, elem1_ty) if t1_alloca is not None: - if self.Gen.VarGen.define_var(trans.SymTab, t1, t1_alloca) == 0: - new_vars += 1 + if self.Gen.VarGen.define_var(trans.SymTab, t1, t1_alloca) == 0: new_vars += 1 # t2: 源 2 元素(enumerate 时 = 源 1 元素) t2_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, t2) if t2_alloca is None: t2_alloca = self.Gen.VarGen._alloca_at_entry(builder, elem2_ty) if t2_alloca is not None: - if self.Gen.VarGen.define_var(trans.SymTab, t2, t2_alloca) == 0: - new_vars += 1 + if self.Gen.VarGen.define_var(trans.SymTab, t2, t2_alloca) == 0: new_vars += 1 # 隐式 index 变量 (i64) idx_alloca: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, i64_ty) @@ -1722,27 +1563,23 @@ novirtual class StmtGenCifMixin: mlirlite.position_at_end(builder, cond_bb) cur_idx: mlirlite.Value* = mlirlite.build_load(builder, i64_ty, idx_alloca) done1: mlirlite.Value* = None - if kind1 == GenTypes.SEQ_KIND_RANGE: - done1 = mlirlite.build_icmp(builder, mlirlite.ICMP_SLT, cur_idx, r1_stop) + if kind1 == GenTypes.SEQ_KIND_RANGE: done1 = mlirlite.build_icmp(builder, mlirlite.ICMP_SLT, cur_idx, r1_stop) elif kind1 == GenTypes.SEQ_KIND_STR: ch_ptr1: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, s1_ptr, cur_idx) ch1: mlirlite.Value* = mlirlite.build_load(builder, i8_ty, ch_ptr1) zero1: mlirlite.Value* = mlirlite.const_int(pool, 8, 0) done1 = mlirlite.build_icmp(builder, mlirlite.ICMP_NE, ch1, zero1) - elif kind1 == GenTypes.SEQ_KIND_LIST: - done1 = mlirlite.build_icmp(builder, mlirlite.ICMP_SLT, cur_idx, l1_count) + elif kind1 == GenTypes.SEQ_KIND_LIST: done1 = mlirlite.build_icmp(builder, mlirlite.ICMP_SLT, cur_idx, l1_count) cont: mlirlite.Value* = done1 if n_srcs >= 2: done2: mlirlite.Value* = None - if kind2 == GenTypes.SEQ_KIND_RANGE: - done2 = mlirlite.build_icmp(builder, mlirlite.ICMP_SLT, cur_idx, r2_stop) + if kind2 == GenTypes.SEQ_KIND_RANGE: done2 = mlirlite.build_icmp(builder, mlirlite.ICMP_SLT, cur_idx, r2_stop) elif kind2 == GenTypes.SEQ_KIND_STR: ch_ptr2: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, s2_ptr, cur_idx) ch2: mlirlite.Value* = mlirlite.build_load(builder, i8_ty, ch_ptr2) zero2: mlirlite.Value* = mlirlite.const_int(pool, 8, 0) done2 = mlirlite.build_icmp(builder, mlirlite.ICMP_NE, ch2, zero2) - elif kind2 == GenTypes.SEQ_KIND_LIST: - done2 = mlirlite.build_icmp(builder, mlirlite.ICMP_SLT, cur_idx, l2_count) + elif kind2 == GenTypes.SEQ_KIND_LIST: done2 = mlirlite.build_icmp(builder, mlirlite.ICMP_SLT, cur_idx, l2_count) cont = mlirlite.build_and(builder, done1, done2) mlirlite.build_cond_br(builder, cont, body_bb, else_bb_seq if else_bb_seq is not None else end_bb) @@ -1803,14 +1640,12 @@ novirtual class StmtGenCifMixin: body_count: sizet = len(body) for bi in range(body_count): stmt: ast.AST* = body.get(bi) - if stmt is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt) + if stmt is not None: self.Gen.StmtGen.translate_stmt(trans, stmt) trans._break_bb = old_break trans._continue_bb = old_continue - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, incr_bb) + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, incr_bb) # incr 块: index++ mlirlite.position_at_end(builder, incr_bb) @@ -1860,35 +1695,30 @@ novirtual class StmtGenCifMixin: # 翻译迭代器表达式,获取指针值 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, "指针迭代: 无法翻译迭代器表达式") # 检查迭代器类型 if self.Gen.ExprGenBase.is_ptr_type(ptr_val.Ty) == 0: # 数组迭代:for k in arr(定长数组按长度迭代,元素可为任意类型) - if self.Gen.ExprGenBase.is_array_type(ptr_val.Ty) != 0: - return self._handle_array_iter(trans, for_node, var_name, ptr_val) + 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, "指针迭代: 迭代器不是指针类型") # 获取元素类型 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, "指针迭代: 无法获取元素类型") # 元素类型是数组(Ptr([N x T]),如 t.CArray 变量退化指针): # load 出数组值后走数组迭代(按长度,非 null 终止) if self.Gen.ExprGenBase.is_array_type(elem_ty) != 0: arr_v2: mlirlite.Value* = mlirlite.build_load(builder, elem_ty, ptr_val) - if arr_v2 is not None: - return self._handle_array_iter(trans, for_node, var_name, arr_v2) + if arr_v2 is not None: return self._handle_array_iter(trans, for_node, var_name, arr_v2) # 元素类型决定"空值"判定(用户语义:解引用后为空即终止): # 整数 → ==0;指针(如 i8** 遍历的元素 i8*)→ ==null;浮点 → ==0.0 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, "指针迭代: 元素类型不是整数/指针/浮点,无法检查空终止符") i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) @@ -1897,8 +1727,7 @@ novirtual class StmtGenCifMixin: new_vars: int = 0 if var_alloca is None: var_alloca = self.Gen.VarGen._alloca_at_entry(builder, elem_ty) - if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0: - new_vars = 1 + if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0: new_vars = 1 # 创建隐式 index 变量,初始为 0 idx_alloca: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, i32_ty) @@ -1936,17 +1765,14 @@ novirtual class StmtGenCifMixin: is_null: mlirlite.Value* = None if elem_is_ptr2 != 0: null_p: mlirlite.Value* = mlirlite.ConstNull(pool, elem_ty, "null") - if null_p is not None: - is_null = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, cur_elem, null_p) + if null_p is not None: is_null = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, cur_elem, null_p) elif elem_fbits2 != 0: zero_f2: mlirlite.Value* = mlirlite.ConstFloat(pool, elem_ty, 0.0) - if zero_f2 is not None: - is_null = mlirlite.build_fcmp(builder, mlirlite.FCMP_OEQ, cur_elem, zero_f2) + if zero_f2 is not None: is_null = mlirlite.build_fcmp(builder, mlirlite.FCMP_OEQ, cur_elem, zero_f2) else: null_val: mlirlite.Value* = mlirlite.const_int(pool, elem_bits, 0) is_null = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, cur_elem, null_val) - if is_null is None: - is_null = mlirlite.const_int(pool, 1, 0) + if is_null is None: is_null = mlirlite.const_int(pool, 1, 0) mlirlite.build_cond_br(builder, is_null, else_bb_ptr if else_bb_ptr is not None else end_bb, body_bb) # body 块: store elem to var, 翻译循环体 @@ -1964,15 +1790,13 @@ novirtual class StmtGenCifMixin: body_count: sizet = len(body) for bi in range(body_count): stmt: ast.AST* = body.get(bi) - if stmt is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt) + if stmt is not None: self.Gen.StmtGen.translate_stmt(trans, stmt) # 恢复旧循环上下文 trans._break_bb = old_break trans._continue_bb = old_continue - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, incr_bb) + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, incr_bb) # incr 块: index++, br cond mlirlite.position_at_end(builder, incr_bb) @@ -2031,15 +1855,13 @@ 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, "数组迭代: 无法解析数组类型") # 数组值 → 临时 alloca(数组值不是指针,需拷贝后 GEP 迭代) # 必须在 entry 块创建:非 entry alloca 会被 LLVM 当动态 alloca → 运行时 sub rsp 大数组, # 调用栈深时 rsp 骤降踩未映射页 → 概率性 #PF。 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, "数组迭代: 临时存储分配失败") mlirlite.build_store(builder, array_val, arr_tmp) i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) @@ -2049,8 +1871,7 @@ novirtual class StmtGenCifMixin: new_vars: int = 0 if var_alloca is None: var_alloca = self.Gen.VarGen._alloca_at_entry(builder, elem_ty) - if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0: - new_vars = 1 + if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0: new_vars = 1 # 隐式 index 变量,初始为 0 idx_alloca: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, i32_ty) @@ -2102,21 +1923,16 @@ novirtual class StmtGenCifMixin: is_empty_a: mlirlite.Value* = None if elem_ptr_a != 0: null_ap: mlirlite.Value* = mlirlite.ConstNull(pool, elem_ty, "null") - if null_ap is not None: - is_empty_a = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, cur_elem, null_ap) + if null_ap is not None: is_empty_a = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, cur_elem, null_ap) elif elem_fbits_a != 0: zero_af: mlirlite.Value* = mlirlite.ConstFloat(pool, elem_ty, 0.0) - if zero_af is not None: - is_empty_a = mlirlite.build_fcmp(builder, mlirlite.FCMP_OEQ, cur_elem, zero_af) + if zero_af is not None: is_empty_a = mlirlite.build_fcmp(builder, mlirlite.FCMP_OEQ, cur_elem, zero_af) else: zero_ai: mlirlite.Value* = mlirlite.const_int(pool, elem_bits_a, 0) is_empty_a = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, cur_elem, zero_ai) - if is_empty_a is not None: - mlirlite.build_cond_br(builder, is_empty_a, else_bb_arr if else_bb_arr is not None else end_bb, body_bb) - else: - mlirlite.build_br(builder, body_bb) - else: - mlirlite.build_br(builder, body_bb) + if is_empty_a is not None: mlirlite.build_cond_br(builder, is_empty_a, else_bb_arr if else_bb_arr is not None else end_bb, body_bb) + else: mlirlite.build_br(builder, body_bb) + else: mlirlite.build_br(builder, body_bb) # body 块: store elem to var → 循环体 mlirlite.position_at_end(builder, body_bb) @@ -2132,14 +1948,12 @@ novirtual class StmtGenCifMixin: body_count: sizet = len(body) for bi in range(body_count): stmt: ast.AST* = body.get(bi) - if stmt is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt) + if stmt is not None: self.Gen.StmtGen.translate_stmt(trans, stmt) trans._break_bb = old_break trans._continue_bb = old_continue - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, incr_bb) + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, incr_bb) # incr 块: index++ mlirlite.position_at_end(builder, incr_bb) @@ -2170,12 +1984,10 @@ 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, "列表字面量迭代: 空列表") 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, "列表字面量迭代: 空列表") # 翻译第一个元素,确定元素类型 first_el: ast.AST* = elts.get(0) @@ -2200,19 +2012,16 @@ novirtual class StmtGenCifMixin: "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, "列表字面量迭代: 无法确定元素类型") elem_ty: mlirlite.LLVMType* = first_val.Ty # 构建 [N x elem_ty] 数组值:临时 alloca 逐元素写入后 load # 同样必须在 entry 块创建,避免非 entry alloca 被降为动态 alloca(见 _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, "列表字面量迭代: 临时数组分配失败") 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) + if first_ptr is not None: mlirlite.build_store(builder, first_val, first_ptr) # 写其余元素(coerce 到 elem_ty) i: sizet = 1 while i < elts_count: @@ -2234,13 +2043,11 @@ novirtual class StmtGenCifMixin: if el_val is not None: el_val = self.Gen.ExprGenBase.coerce_to_type(builder, el_val, elem_ty, el_node) el_ptr: mlirlite.Value* = mlirlite.build_gep_array(builder, arr_ty, elem_ty, tmp_alloca, mlirlite.const_int32(pool, i)) - if el_ptr is not None: - mlirlite.build_store(builder, el_val, el_ptr) + if el_ptr is not None: mlirlite.build_store(builder, el_val, el_ptr) i += 1 # load 回数组值,复用数组迭代 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, "列表字面量迭代: 数组加载失败") return self._handle_array_iter(trans, for_node, var_name, arr_val) # ============================================================ @@ -2287,8 +2094,7 @@ novirtual class StmtGenCifMixin: # 读取 __count__ (偏移 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 迭代: 无法定位 __count__") count_val: mlirlite.Value* = mlirlite.build_load(builder, i64_ty, cnt_ptr) # 循环变量 alloca(元素类型 i8*,与 list.get 内联一致) @@ -2296,8 +2102,7 @@ novirtual class StmtGenCifMixin: new_vars: int = 0 if var_alloca is None: var_alloca = self.Gen.VarGen._alloca_at_entry(builder, i8_ptr_ty) - if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0: - new_vars = 1 + if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0: new_vars = 1 # 隐式 index 变量 (i64,与 __count__ 类型对齐) idx_alloca: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, i64_ty) @@ -2354,14 +2159,12 @@ novirtual class StmtGenCifMixin: body_count: sizet = len(body) for bi in range(body_count): stmt: ast.AST* = body.get(bi) - if stmt is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt) + if stmt is not None: self.Gen.StmtGen.translate_stmt(trans, stmt) trans._break_bb = old_break trans._continue_bb = old_continue - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, incr_bb) + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, incr_bb) # incr 块: index++ mlirlite.position_at_end(builder, incr_bb) @@ -2398,8 +2201,7 @@ novirtual class StmtGenCifMixin: # 读取 __count__(槽 2,字节偏移 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 迭代: 无法定位 __count__") count_val: mlirlite.Value* = mlirlite.build_load(builder, i64_ty, cnt_ptr) # 循环变量 alloca(元素类型 i8*,与 dict.__next__ 返回 str 一致) @@ -2407,8 +2209,7 @@ novirtual class StmtGenCifMixin: new_vars: int = 0 if var_alloca is None: var_alloca = self.Gen.VarGen._alloca_at_entry(builder, i8_ptr_ty) - if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0: - new_vars = 1 + if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0: new_vars = 1 # 隐式 index 变量 (i64,与 __count__ 类型对齐) idx_alloca: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, i64_ty) @@ -2464,14 +2265,12 @@ novirtual class StmtGenCifMixin: body_count: sizet = len(body) for bi in range(body_count): stmt: ast.AST* = body.get(bi) - if stmt is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt) + if stmt is not None: self.Gen.StmtGen.translate_stmt(trans, stmt) trans._break_bb = old_break trans._continue_bb = old_continue - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, incr_bb) + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, incr_bb) # incr 块: index++ mlirlite.position_at_end(builder, incr_bb) @@ -2524,51 +2323,39 @@ novirtual class StmtGenCifMixin: func: mlirlite.Function* = trans._cur_func 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 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 迭代: 迭代源对象不是指针类型") # 1. 查找 {Class}.__iter__ 并调用,得到迭代器 iter_lookup: str = pool.alloc(128) - if iter_lookup is None: - return 0 + 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 迭代: 类 '{class_name}' 没有 __iter__ 方法") 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 + if iter_ret_ty is None or iter_fn_name is None: return 0 # self 参数按 __iter__ 首参类型对齐(stub 声明 self 可能是 i8*) iter_self: mlirlite.Value* = obj_val iter_first: mlirlite.Param* = mlirlite.function_get_param_head(iter_fn) if iter_first is not None: iter_self_ty: mlirlite.LLVMType* = mlirlite.param_get_ty(iter_first) - if iter_self_ty is not None: - iter_self = mlirlite.build_bitcast(builder, obj_val, iter_self_ty) - if iter_self is None: - return 0 + if iter_self_ty is not None: iter_self = mlirlite.build_bitcast(builder, obj_val, iter_self_ty) + if iter_self is None: return 0 iter_self.Next = None iter_result: mlirlite.Value* = mlirlite.build_call(builder, iter_fn_name, iter_self, 1, iter_ret_ty, 0) - if iter_result is None: - return 0 + if iter_result is None: return 0 # 2. 查找 {Class}.__next__(带隐藏 __stop_iter_flag__ i1* 参数) next_lookup: str = pool.alloc(128) - if next_lookup is None: - return 0 + 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 迭代: 类 '{class_name}' 没有 __next__ 方法") 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 + if next_ret_ty is None or next_fn_name is None: return 0 # 3. 循环变量 alloca(元素类型 = __next__ 返回类型) var_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, var_name) @@ -2576,17 +2363,14 @@ novirtual class StmtGenCifMixin: if var_alloca is None: var_alloca = self.Gen.VarGen._alloca_at_entry(builder, next_ret_ty) if var_alloca is not None: - if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0: - new_vars = 1 + if self.Gen.VarGen.define_var(trans.SymTab, var_name, var_alloca) == 0: new_vars = 1 # 4. stop flag alloca(i1,初始 0) i1_ty: mlirlite.LLVMType* = mlirlite.Int1(pool) flag_alloca: mlirlite.Value* = mlirlite.build_alloca(builder, i1_ty) - if flag_alloca is None: - return 0 + if flag_alloca is None: return 0 flag_zero: mlirlite.Value* = mlirlite.ConstInt(pool, i1_ty, 0, "0") - if flag_zero is not None: - mlirlite.build_store(builder, flag_zero, flag_alloca) + if flag_zero is not None: mlirlite.build_store(builder, flag_zero, flag_alloca) # 5. 创建基本块: cond / body / step / end cnt: int = trans._label_counter @@ -2600,8 +2384,7 @@ novirtual class StmtGenCifMixin: step_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf) viperlib.snprintf(name_buf, 32, "oop.end.%d", cnt) end_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf) - if cond_bb is None or body_bb is None or step_bb is None or end_bb is None: - return 0 + if cond_bb is None or body_bb is None or step_bb is None or end_bb is None: return 0 # 循环 else:__next__ 返回 stop(迭代耗尽)边指向 else_bb(无 else 时仍指向 end_bb) has_else_oop: int = self._LoopElseCount(for_node.orelse) @@ -2611,38 +2394,30 @@ novirtual class StmtGenCifMixin: # 6. cond 块: 重置 flag → 调 __next__(iter, flag) → 检查 flag 判结束 mlirlite.position_at_end(builder, cond_bb) - if flag_zero is not None: - mlirlite.build_store(builder, flag_zero, flag_alloca) + if flag_zero is not None: mlirlite.build_store(builder, flag_zero, flag_alloca) # __next__ 参数 1:迭代器(按首参类型 bitcast) next_self: mlirlite.Value* = iter_result next_first: mlirlite.Param* = mlirlite.function_get_param_head(next_fn) if next_first is not None: next_self_ty: mlirlite.LLVMType* = mlirlite.param_get_ty(next_first) - if next_self_ty is not None and iter_result.Ty is not None: - next_self = mlirlite.build_bitcast(builder, iter_result, next_self_ty) - if next_self is None: - return 0 + if next_self_ty is not None and iter_result.Ty is not None: next_self = mlirlite.build_bitcast(builder, iter_result, next_self_ty) + if next_self is None: return 0 # 参数链表: arg1(iter).Next = arg2(flag);flag 独立 null 结尾防自链接 next_self.Next = flag_alloca flag_alloca.Next = None next_val: mlirlite.Value* = mlirlite.build_call(builder, next_fn_name, next_self, 2, next_ret_ty, 0) - if next_val is None: - return 0 + if next_val is None: return 0 stop_val: mlirlite.Value* = mlirlite.build_load(builder, i1_ty, flag_alloca) - if stop_val is None: - return 0 + if stop_val is None: return 0 flag_zero2: mlirlite.Value* = mlirlite.ConstInt(pool, i1_ty, 0, "0") continue_i1: mlirlite.Value* = None - if flag_zero2 is not None: - continue_i1 = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, stop_val, flag_zero2) - if continue_i1 is None: - return 0 + if flag_zero2 is not None: continue_i1 = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, stop_val, flag_zero2) + if continue_i1 is None: return 0 mlirlite.build_cond_br(builder, continue_i1, body_bb, else_bb_oop if else_bb_oop is not None else end_bb) # 7. body 块: store 元素 → 翻译循环体 → br step mlirlite.position_at_end(builder, body_bb) - if var_alloca is not None: - mlirlite.build_store(builder, next_val, var_alloca) + if var_alloca is not None: mlirlite.build_store(builder, next_val, var_alloca) old_break: rawptr[mlirlite.BasicBlock] = trans._break_bb old_continue: rawptr[mlirlite.BasicBlock] = trans._continue_bb trans._break_bb = end_bb @@ -2652,12 +2427,10 @@ novirtual class StmtGenCifMixin: body_count: sizet = len(body) for bi in range(body_count): stmt: ast.AST* = body.get(bi) - if stmt is not None: - self.Gen.StmtGen.translate_stmt(trans, stmt) + if stmt is not None: self.Gen.StmtGen.translate_stmt(trans, stmt) trans._break_bb = old_break trans._continue_bb = old_continue - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, step_bb) + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, step_bb) # 8. step 块 → cond;循环 else 收尾(迭代耗尽时先执行 orelse),再定位到 end 块 mlirlite.position_at_end(builder, step_bb) @@ -2673,11 +2446,9 @@ novirtual class StmtGenCifMixin: t1: str, t2: str, call: ast.Call*) -> int: """enumerate 迭代: for i, v in enumerate(x)""" - if call is None or call.args is None: - return 0 + 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 需要至少一个参数") return self._build_seq_loop(trans, for_node, t1, t2, cargs.get(0), None, 1) def _handle_zip_iter(self, trans: HT.Translator*, @@ -2689,15 +2460,13 @@ novirtual class StmtGenCifMixin: # fail-fast: zip 参数缺失 self.Gen.TypeGenErr.fatal_error(call, "zip 参数缺失", "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 需要至少两个参数") return self._build_seq_loop(trans, for_node, t1, t2, cargs.get(0), cargs.get(1), 2) def InitStmtGen(self) -> int: """初始化 StmtGen 族字段(构造时由 Generator 调用)""" - if self is None: - return 1 + if self is None: return 1 self.CifEvalOk = 0 self.EnumTable = None self.EnumCount = 0 diff --git a/App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp b/App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp index 98f8a21..fa5802d 100644 --- a/App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp +++ b/App/lib/core/Gen/Stmt/StmtGenDeclMixin.vp @@ -37,18 +37,15 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): node: ast.AST*) -> int: """翻译 global 语句:记录 global 变量名""" gn: rawptr[ast.Global] = rawptr[ast.Global](node) - if gn is None: - return 0 + if gn is None: return 0 names: list[ast.AST*]* = gn.names - if names is None: - return 0 + if names is None: return 0 n: sizet = len(names) for i in range(n): nm_node: ast.AST* = names.get(i) if nm_node is not None and nm_node.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(nm_node) - if nm.id is not None: - GenApi.add_global_name(trans, nm.id) + if nm.id is not None: GenApi.add_global_name(trans, nm.id) return 0 def translate_nonlocal(self, trans: HT.Translator*, @@ -58,11 +55,9 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): 类型信息通过查找父作用域的 alloca 获取(用于 env 指针数组方案的类型恢复)。 """ nl: rawptr[ast.Nonlocal] = rawptr[ast.Nonlocal](node) - if nl is None: - return 0 + if nl is None: return 0 names: list[ast.AST*]* = nl.names - if names is None: - return 0 + if names is None: return 0 n: sizet = len(names) for i in range(n): nm_node: ast.AST* = names.get(i) @@ -90,11 +85,9 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): node: ast.AST*) -> int: """翻译表达式语句(printf 调用等)""" ex: rawptr[ast.Expr] = rawptr[ast.Expr](node) - if ex is None: - return 0 + if ex is None: return 0 call_node: ast.AST* = ex.value - if call_node is None: - return 0 + if call_node is None: return 0 ck: int = call_node.kind() if ck != ast.ASTKind.Call: # REPL 模式(M2):片段函数本体内的裸表达式语句(如 1+2 / x / x + 1) @@ -102,14 +95,12 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): # (执行 + 丢弃返回值,同 print/printf 语义)。 # 守卫 trans.ReplCtx:非 REPL 恒 None ⇒ "表达式语句除调用外一律忽略" # 的原行为逐字不变。 - if trans is not None and trans.ReplCtx is not None and self.Gen.VarGen.repl_in_frag_scope(trans.SymTab) != 0: - self.Gen.VarGen.repl_expr_result(trans, call_node) + if trans is not None and trans.ReplCtx is not None and self.Gen.VarGen.repl_in_frag_scope(trans.SymTab) != 0: self.Gen.VarGen.repl_expr_result(trans, call_node) return 0 cl: ast.Call* = ast.Call*(call_node) func_node: ast.AST* = cl.func - if func_node is None: - return 0 + if func_node is None: return 0 func_name: str = self.Gen.ExprGenBase.get_func_name(func_node) if func_name is None: @@ -117,10 +108,8 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): self.Gen.TypeGenErr.fatal_error(call_node, "表达式语句的函数名解析失败", "SyntaxError") # printf / print 走特殊路径(print 是类型感知格式化,不映射到 printf) - if string.strcmp(func_name, "printf") == 0: - self.Gen.CallGenLeafKit.translate_printf_call(trans.Pool, trans._cur_builder, trans.Module, cl, trans) - elif string.strcmp(func_name, "print") == 0: - self.Gen.CallGenLeafKit.translate_print_call(trans.Pool, trans._cur_builder, trans.Module, cl, trans) + if string.strcmp(func_name, "printf") == 0: self.Gen.CallGenLeafKit.translate_printf_call(trans.Pool, trans._cur_builder, trans.Module, cl, trans) + elif string.strcmp(func_name, "print") == 0: self.Gen.CallGenLeafKit.translate_print_call(trans.Pool, trans._cur_builder, trans.Module, cl, trans) else: # 通用函数调用(返回值丢弃) # M3:裸名调用**会话函数**(跨片段)时额外把返回值写进 ctx 结果区回显 @@ -156,50 +145,41 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): 返回新增的变量数(调用方均忽略返回值)。 """ - if node is None: - return 0 + if node is None: return 0 k: int = node.kind() - if k == ast.ASTKind.AnnAssign: - return self.Gen.AssignGen.translate_annassign_prescan(trans, node) + if k == ast.ASTKind.AnnAssign: return self.Gen.AssignGen.translate_annassign_prescan(trans, node) if k == ast.ASTKind.If: ifn: rawptr[ast.If] = rawptr[ast.If](node) if ifn.children is not None: bn_pre_i: sizet = len(ifn.children) - for bi_pre_i in range(bn_pre_i): - self.pre_scan_allocas(trans, ifn.children.get(bi_pre_i)) + for bi_pre_i in range(bn_pre_i): self.pre_scan_allocas(trans, ifn.children.get(bi_pre_i)) if ifn.orelse is not None: bn_pre_e: sizet = len(ifn.orelse) - for bi_pre_e in range(bn_pre_e): - self.pre_scan_allocas(trans, ifn.orelse.get(bi_pre_e)) + for bi_pre_e in range(bn_pre_e): self.pre_scan_allocas(trans, ifn.orelse.get(bi_pre_e)) return 0 if k == ast.ASTKind.For: for_n: ast.For* = ast.For*(node) if for_n.children is not None: bn_pre_f: sizet = len(for_n.children) - for bi_pre_f in range(bn_pre_f): - self.pre_scan_allocas(trans, for_n.children.get(bi_pre_f)) + for bi_pre_f in range(bn_pre_f): self.pre_scan_allocas(trans, for_n.children.get(bi_pre_f)) if for_n.orelse is not None: bn_pre_fe: sizet = len(for_n.orelse) - for bi_pre_fe in range(bn_pre_fe): - self.pre_scan_allocas(trans, for_n.orelse.get(bi_pre_fe)) + for bi_pre_fe in range(bn_pre_fe): self.pre_scan_allocas(trans, for_n.orelse.get(bi_pre_fe)) return 0 if k == ast.ASTKind.While: wh_n: rawptr[ast.While] = rawptr[ast.While](node) if wh_n.children is not None: bn_pre_w: sizet = len(wh_n.children) - for bi_pre_w in range(bn_pre_w): - self.pre_scan_allocas(trans, wh_n.children.get(bi_pre_w)) + for bi_pre_w in range(bn_pre_w): self.pre_scan_allocas(trans, wh_n.children.get(bi_pre_w)) if wh_n.orelse is not None: bn_pre_we: sizet = len(wh_n.orelse) - for bi_pre_we in range(bn_pre_we): - self.pre_scan_allocas(trans, wh_n.orelse.get(bi_pre_we)) + for bi_pre_we in range(bn_pre_we): self.pre_scan_allocas(trans, wh_n.orelse.get(bi_pre_we)) return 0 if k == ast.ASTKind.Try: tr_n: ast.Try* = ast.Try*(node) if tr_n.children is not None: bn_pre_t: sizet = len(tr_n.children) - for bi_pre_t in range(bn_pre_t): - self.pre_scan_allocas(trans, tr_n.children.get(bi_pre_t)) + for bi_pre_t in range(bn_pre_t): self.pre_scan_allocas(trans, tr_n.children.get(bi_pre_t)) if tr_n.handlers is not None: bn_pre_th: sizet = len(tr_n.handlers) for bi_pre_th in range(bn_pre_th): @@ -208,23 +188,19 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): ehc_pre: ast.ExceptHandler* = ast.ExceptHandler*(eh_pre) if ehc_pre.children is not None: bn_pre_ehb: sizet = len(ehc_pre.children) - for bi_pre_ehb in range(bn_pre_ehb): - self.pre_scan_allocas(trans, ehc_pre.children.get(bi_pre_ehb)) + for bi_pre_ehb in range(bn_pre_ehb): self.pre_scan_allocas(trans, ehc_pre.children.get(bi_pre_ehb)) if tr_n.orelse is not None: bn_pre_to: sizet = len(tr_n.orelse) - for bi_pre_to in range(bn_pre_to): - self.pre_scan_allocas(trans, tr_n.orelse.get(bi_pre_to)) + for bi_pre_to in range(bn_pre_to): self.pre_scan_allocas(trans, tr_n.orelse.get(bi_pre_to)) if tr_n.finalbody is not None: bn_pre_tf: sizet = len(tr_n.finalbody) - for bi_pre_tf in range(bn_pre_tf): - self.pre_scan_allocas(trans, tr_n.finalbody.get(bi_pre_tf)) + for bi_pre_tf in range(bn_pre_tf): self.pre_scan_allocas(trans, tr_n.finalbody.get(bi_pre_tf)) return 0 if k == ast.ASTKind.With: wth: ast.With* = ast.With*(node) if wth.children is not None: bn_pre_wb: sizet = len(wth.children) - for bi_pre_wb in range(bn_pre_wb): - self.pre_scan_allocas(trans, wth.children.get(bi_pre_wb)) + for bi_pre_wb in range(bn_pre_wb): self.pre_scan_allocas(trans, wth.children.get(bi_pre_wb)) return 0 if k == ast.ASTKind.Match: mt_n: ast.Match* = ast.Match*(node) @@ -236,21 +212,17 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): mcc_pre: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](mc_pre) if mcc_pre.children is not None: bn_pre_mcb: sizet = len(mcc_pre.children) - for bi_pre_mcb in range(bn_pre_mcb): - self.pre_scan_allocas(trans, mcc_pre.children.get(bi_pre_mcb)) + for bi_pre_mcb in range(bn_pre_mcb): self.pre_scan_allocas(trans, mcc_pre.children.get(bi_pre_mcb)) return 0 return 0 def pre_scan_scope_decls(self, trans: HT.Translator*, node: ast.AST*) -> int: """预扫描 Global/Nonlocal 声明,提前注册作用域名称""" - if node is None: - return 0 + if node is None: return 0 k: int = node.kind() - if k == ast.ASTKind.Global: - return self.translate_global(trans, node) - if k == ast.ASTKind.Nonlocal: - return self.translate_nonlocal(trans, node) + if k == ast.ASTKind.Global: return self.translate_global(trans, node) + if k == ast.ASTKind.Nonlocal: return self.translate_nonlocal(trans, node) return 0 def translate_break(self, trans: HT.Translator*, node: ast.AST*) -> int: @@ -259,16 +231,14 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): func: mlirlite.Function* = trans._cur_func pool: memhub.MemBuddy* = trans.Pool - if builder is None or func is None: - return 0 + if builder is None or func is None: return 0 # 发射 br 到 break 目标(_break_bb 由循环 / switch / match 的 case 生成侧设置) if trans._break_bb is None: # fail-fast:没有循环 / switch / match 时 break 无处可跳,禁止静默无效果 self.Gen.TypeGenErr.fatal_error(node, "break 只能用在循环或 switch/match 的 case 体内(当前没有可跳出的目标)", "SyntaxError") - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, trans._break_bb) + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, trans._break_bb) # 创建死代码 BB,用于后续语句(break 后面的代码不可达) cnt: int = trans._label_counter @@ -287,8 +257,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): case 语句体**;写进 match 的 case 体(match 完全禁止 fallthrough)或 switch 之外一律 fail-fast,绝不静默无效果。 """ - if trans is None: - return 0 + if trans is None: return 0 if trans._in_switch_case == 0: self.Gen.TypeGenErr.fatal_error(node, "fallthrough 只能用在 switch 的 case 体内(match 完全禁止 fallthrough," @@ -301,16 +270,14 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): func: mlirlite.Function* = trans._cur_func pool: memhub.MemBuddy* = trans.Pool - if builder is None or func is None: - return 0 + if builder is None or func is None: return 0 # 发射 br 到 continue 目标 if trans._continue_bb is None: # fail-fast:循环之外的 continue 无处可跳,禁止静默无效果 self.Gen.TypeGenErr.fatal_error(node, "continue 只能用在循环体内(当前没有可继续的循环)", "SyntaxError") - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, trans._continue_bb) + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, trans._continue_bb) # 创建死代码 BB,用于后续语句 cnt: int = trans._label_counter @@ -323,8 +290,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): def get_stmt_kind_name(self, node: ast.AST*) -> str: """获取语句类型名""" - if node is None: - return None + if node is None: return None return node.type_name() # ============================================================ @@ -333,8 +299,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): def _is_void_type(self, ty: mlirlite.LLVMType*) -> int: """判断是否为 Void 类型,是则返回 1,否则 0""" - if ty is None: - return 0 + if ty is None: return 0 match ty: case mlirlite.LLVMType.Void(): return 1 @@ -344,16 +309,14 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): def get_env_ptr_var(self, trans: HT.Translator*) -> mlirlite.Value*: """获取或创建 _env_ptr 变量(存储闭包 env 指针)""" env_var: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, "_env_ptr") - if env_var is not None: - return env_var + if env_var is not None: return env_var # 创建 alloca 存储 env pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty) alloca: mlirlite.Value* = mlirlite.build_alloca(builder, i8_ptr_ty) - if alloca is None: - return None + if alloca is None: return None self.Gen.VarGen.define_var(trans.SymTab, "_env_ptr", alloca) return alloca @@ -364,8 +327,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): 返回 i8* 类型的 Value,调用方需 bitcast 为具体类型指针后 load/store。 """ idx: int = GenApi.get_nonlocal_index(trans, name) - if idx < 0: - return None + if idx < 0: return None pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder @@ -375,22 +337,18 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): # 1. 加载 env_ptr env_alloca: mlirlite.Value* = self.get_env_ptr_var(trans) - if env_alloca is None: - return None + if env_alloca is None: return None env_ptr: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty, env_alloca) - if env_ptr is None: - return None + if env_ptr is None: return None # 2. GEP to offset (idx * 8) — env 存储指针数组,每槽 8 字节 offset_val: mlirlite.Value* = mlirlite.const_int32(pool, idx * 8) addr: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, env_ptr, offset_val) - if addr is None: - return None + if addr is None: return None # 3. Bitcast to i8** and load the raw pointer ptr_addr: mlirlite.Value* = mlirlite.build_bitcast(builder, addr, i8_ptr_ptr_ty) - if ptr_addr is None: - return None + if ptr_addr is None: return None return mlirlite.build_load(builder, i8_ptr_ty, ptr_addr) def load_nonlocal_var(self, trans: HT.Translator*, @@ -400,8 +358,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): 通过 HT.get_nonlocal_type 获取变量类型,bitcast 原始指针后 load。 """ raw_ptr: mlirlite.Value* = self._load_raw_var_ptr(trans, name) - if raw_ptr is None: - return None + if raw_ptr is None: return None pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder @@ -415,8 +372,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): # bitcast raw i8* to var_ty* var_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, var_ty) var_ptr: mlirlite.Value* = mlirlite.build_bitcast(builder, raw_ptr, var_ptr_ty) - if var_ptr is None: - return None + if var_ptr is None: return None return mlirlite.build_load(builder, var_ty, var_ptr) def get_nonlocal_var_ptr(self, trans: HT.Translator*, @@ -426,8 +382,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): 返回的指针指向父函数的 alloca,store 操作对父函数可见。 """ raw_ptr: mlirlite.Value* = self._load_raw_var_ptr(trans, name) - if raw_ptr is None: - return None + if raw_ptr is None: return None pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder @@ -453,21 +408,18 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): 跨文件持久表,pool 分配会被 reset 回收导致 Phase B 读垃圾, enum_count 出现 512 等垃圾值 / entry.Name 解引用崩溃)。 """ - if self.EnumTable is not None: - return 1 + if self.EnumTable is not None: return 1 entry_size: sizet = GenTypes.EnumEntry.__sizeof__() self.EnumTable = CompilerFactory.factory.PermPool.alloc(entry_size * ENUM_MAX) - if self.EnumTable is None: - return 0 + if self.EnumTable is None: return 0 string.memset(self.EnumTable, 0, entry_size * ENUM_MAX) self.EnumCount = 0 return 1 def _get_enum_entry(self, i: int) -> rawptr[GenTypes.EnumEntry]: """获取第 i 个枚举条目""" - if self.EnumTable is None or i < 0 or i >= ENUM_MAX: - return None + if self.EnumTable is None or i < 0 or i >= ENUM_MAX: return None entry_size: sizet = GenTypes.EnumEntry.__sizeof__() addr: uint64 = uint64(self.EnumTable) + i * entry_size return rawptr[GenTypes.EnumEntry](addr) @@ -475,8 +427,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): def _get_enum_member(self, enum_entry: rawptr[GenTypes.EnumEntry], i: int) -> rawptr[GenTypes.EnumMember]: """获取枚举中第 i 个成员条目""" - if enum_entry is None or i < 0 or i >= ENUM_MEMBER_MAX: - return None + if enum_entry is None or i < 0 or i >= ENUM_MEMBER_MAX: return None member_size: sizet = GenTypes.EnumMember.__sizeof__() addr: uint64 = uint64(enum_entry.Members) + i * member_size return rawptr[GenTypes.EnumMember](addr) @@ -485,27 +436,23 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): name: str, base_ty: mlirlite.LLVMType*) -> rawptr[GenTypes.EnumEntry]: """注册枚举类型,返回 EnumEntry 指针""" - if self.init_enum_table(pool) == 0: - return None + if self.init_enum_table(pool) == 0: return None # 检查是否已注册 existing: rawptr[GenTypes.EnumEntry] = self.find_enum(name) - if existing is not None: - return existing + if existing is not None: return existing if self.EnumCount >= ENUM_MAX: VLogger.error(f"table full, cannot register {name}", "ENUM") return None entry: rawptr[GenTypes.EnumEntry] = self._get_enum_entry(self.EnumCount) - if entry is None: - return None + if entry is None: return None # 分配成员数组(永久池:跨 mark/reset 存活,对齐 EnumTable 永久池化) member_size: sizet = GenTypes.EnumMember.__sizeof__() entry.Members = CompilerFactory.factory.PermPool.alloc(member_size * ENUM_MEMBER_MAX) - if entry.Members is None: - return None + if entry.Members is None: return None string.memset(entry.Members, 0, member_size * ENUM_MEMBER_MAX) # 复制类名(永久池深拷贝) @@ -522,12 +469,9 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): # (NoVTable 按本 Mixin 字段布局编译),走模块级委托。 if self.Gen.StructGen.get_stdlib_alloc() != 0: base_ty_copy: mlirlite.LLVMType* = mlirlite.DeepCopyType(CompilerFactory.factory.PermPool, base_ty) - if base_ty_copy is not None: - entry.BaseTy = base_ty_copy - else: - entry.BaseTy = base_ty - else: - entry.BaseTy = base_ty + if base_ty_copy is not None: entry.BaseTy = base_ty_copy + else: entry.BaseTy = base_ty + else: entry.BaseTy = base_ty entry.MemberCount = 0 self.EnumCount += 1 @@ -539,16 +483,14 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): member_val: int64, member_ty: mlirlite.LLVMType*) -> int: """向枚举添加成员,返回成员索引(-1 失败)""" - if enum_entry is None or member_name is None or member_ty is None: - return -1 + if enum_entry is None or member_name is None or member_ty is None: return -1 # 去重:同名成员已存在则跳过(跨模块同名枚举合并注册 / 同模块 # 重复处理幂等——如 w32.fileio 与 fat32_types 都有 FRESULT) for ei_d in range(enum_entry.MemberCount): ex_d: rawptr[GenTypes.EnumMember] = self._get_enum_member(enum_entry, ei_d) if ex_d is not None and ex_d.Name is not None: - if string.strcmp(ex_d.Name, member_name) == 0: - return ei_d + if string.strcmp(ex_d.Name, member_name) == 0: return ei_d if enum_entry.MemberCount >= ENUM_MEMBER_MAX: VLogger.error(f"member table full for {enum_entry.Name}", "ENUM") @@ -556,8 +498,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): idx: int = enum_entry.MemberCount me: rawptr[GenTypes.EnumMember] = self._get_enum_member(enum_entry, idx) - if me is None: - return -1 + if me is None: return -1 # 复制成员名(永久池深拷贝:成员表跨 mark/reset 存活) name_len: sizet = string.strlen(member_name) @@ -574,41 +515,33 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): def find_enum(self, name: str) -> rawptr[GenTypes.EnumEntry]: """按枚举类名查找,返回 EnumEntry 或 None""" - if name is None or self.EnumTable is None: - return None + if name is None or self.EnumTable is None: return None for i in range(self.EnumCount): entry: rawptr[GenTypes.EnumEntry] = self._get_enum_entry(i) if entry is not None and entry.Name is not None: - if string.strcmp(entry.Name, name) == 0: - return entry + if string.strcmp(entry.Name, name) == 0: return entry return None def lookup_enum_member(self, enum_name: str, member_name: str) -> rawptr[GenTypes.EnumMember]: """按枚举类名和成员名查找,返回 EnumMember 或 None""" - if enum_name is None or member_name is None: - return None + if enum_name is None or member_name is None: return None entry: rawptr[GenTypes.EnumEntry] = self.find_enum(enum_name) - if entry is None: - return None + if entry is None: return None for mi in range(entry.MemberCount): me: rawptr[GenTypes.EnumMember] = self._get_enum_member(entry, mi) if me is not None and me.Name is not None: - if string.strcmp(me.Name, member_name) == 0: - return me + if string.strcmp(me.Name, member_name) == 0: return me return None def is_enum_class(self, name: str) -> int: """检查类名是否为已注册枚举,返回 1=是 / 0=否""" - if name is None: - return 0 - if self.find_enum(name) is not None: - return 1 + if name is None: return 0 + if self.find_enum(name) is not None: return 1 return 0 def get_enum_base_type(self, enum_name: str) -> mlirlite.LLVMType*: """按枚举类名获取基准类型""" entry: rawptr[GenTypes.EnumEntry] = self.find_enum(enum_name) - if entry is not None: - return entry.BaseTy + if entry is not None: return entry.BaseTy return None diff --git a/App/lib/core/Gen/Stmt/StmtGenMixin.vp b/App/lib/core/Gen/Stmt/StmtGenMixin.vp index 17df2fd..1949e68 100644 --- a/App/lib/core/Gen/Stmt/StmtGenMixin.vp +++ b/App/lib/core/Gen/Stmt/StmtGenMixin.vp @@ -39,69 +39,45 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): 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, "语句翻译嵌套过深(疑似 AST 自引用环或翻译 bug)", "RecursionError") trans.TranslateDepth += 1 mret: int = self._translate_stmt_impl(trans, node) - if trans is not None: - trans.TranslateDepth -= 1 + if trans is not None: trans.TranslateDepth -= 1 return mret def _translate_stmt_impl(self, trans: HT.Translator*, node: ast.AST*) -> int: """翻译单条语句,返回新增的变量数""" - if node is None: - return 0 + if node is None: return 0 k: int = node.kind() - if k == ast.ASTKind.Expr: - return self.translate_expr_stmt(trans, node) - elif k == ast.ASTKind.Assign: - return self.Gen.AssignGen.translate_assign(trans, node) - elif k == ast.ASTKind.AnnAssign: - return self.Gen.AssignGen.translate_annassign(trans, node) + if k == ast.ASTKind.Expr: return self.translate_expr_stmt(trans, node) + elif k == ast.ASTKind.Assign: return self.Gen.AssignGen.translate_assign(trans, node) + elif k == ast.ASTKind.AnnAssign: return self.Gen.AssignGen.translate_annassign(trans, node) elif k == ast.ASTKind.FunctionDef: # 嵌套函数定义:提升为顶层函数 + 创建闭包 return self.Gen.FuncGen.translate_nested_function_def(trans, node) - elif k == ast.ASTKind.Return: - return self.Gen.StmtGenCif.translate_return(trans, node) - elif k == ast.ASTKind.If: - return self.Gen.StmtGenCif.translate_if(trans, node) - elif k == ast.ASTKind.While: - return self.Gen.StmtGenCif.translate_while(trans, node) - elif k == ast.ASTKind.AugAssign: - return self.Gen.AssignGen.translate_augassign(trans, node) - elif k == ast.ASTKind.For: - return self.Gen.StmtGenCif.translate_for(trans, node) - elif k == ast.ASTKind.ClassDef: - return self.Gen.ClassGenDef.translate_class_def(trans, node) - elif k == ast.ASTKind.Import: - return self.Gen.ImportsGen.translate_import(trans, node) + elif k == ast.ASTKind.Return: return self.Gen.StmtGenCif.translate_return(trans, node) + elif k == ast.ASTKind.If: return self.Gen.StmtGenCif.translate_if(trans, node) + elif k == ast.ASTKind.While: return self.Gen.StmtGenCif.translate_while(trans, node) + elif k == ast.ASTKind.AugAssign: return self.Gen.AssignGen.translate_augassign(trans, node) + elif k == ast.ASTKind.For: return self.Gen.StmtGenCif.translate_for(trans, node) + elif k == ast.ASTKind.ClassDef: return self.Gen.ClassGenDef.translate_class_def(trans, node) + elif k == ast.ASTKind.Import: return self.Gen.ImportsGen.translate_import(trans, node) elif k == ast.ASTKind.ImportFrom: self.Gen.ImportsGen.translate_import_from_module(trans, node) return self.Gen.ImportsGen.translate_import_from_names(trans, node) - elif k == ast.ASTKind.Global: - return self.translate_global(trans, node) - elif k == ast.ASTKind.Nonlocal: - return self.translate_nonlocal(trans, node) - elif k == ast.ASTKind.Pass: - return 0 - elif k == ast.ASTKind.Break: - return self.translate_break(trans, node) - elif k == ast.ASTKind.Continue: - return self.translate_continue(trans, node) - elif k == ast.ASTKind.FallThrough: - return self.translate_fallthrough(trans, node) - elif k == ast.ASTKind.Match: - return self.Gen.MatchGen.translate_match(trans, node) - elif k == ast.ASTKind.Delete: - return self.translate_delete(trans, node) - elif k == ast.ASTKind.Raise: - return self.translate_raise(trans, node) - elif k == ast.ASTKind.Try: - return self.translate_try(trans, node) - elif k == ast.ASTKind.With: - return self.translate_with(trans, node) + elif k == ast.ASTKind.Global: return self.translate_global(trans, node) + elif k == ast.ASTKind.Nonlocal: return self.translate_nonlocal(trans, node) + elif k == ast.ASTKind.Pass: return 0 + elif k == ast.ASTKind.Break: return self.translate_break(trans, node) + elif k == ast.ASTKind.Continue: return self.translate_continue(trans, node) + elif k == ast.ASTKind.FallThrough: return self.translate_fallthrough(trans, node) + elif k == ast.ASTKind.Match: return self.Gen.MatchGen.translate_match(trans, node) + elif k == ast.ASTKind.Delete: return self.translate_delete(trans, node) + elif k == ast.ASTKind.Raise: return self.translate_raise(trans, node) + elif k == ast.ASTKind.Try: return self.translate_try(trans, node) + elif k == ast.ASTKind.With: return self.translate_with(trans, node) # 未知语句类型:直接报错终止(fail-fast),暴露上游解析问题 self.Gen.TypeGenErr.fatal_error(node, f"未知语句类型 kind={k}", "SyntaxError") return 0 @@ -109,21 +85,17 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): def translate_delete(self, trans: HT.Translator*, node: ast.AST*) -> int: """翻译 del 语句,返回 0""" - if trans is None or node is None: - return 0 + if trans is None or node is None: return 0 dnode: rawptr[ast.Delete] = rawptr[ast.Delete](node) - if dnode is None or dnode.targets is None: - return 0 + if dnode is None or dnode.targets is None: return 0 pool: memhub.MemBuddy* = trans.Pool mod: mlirlite.LLVMModule* = trans.Module builder: mlirlite.IRBuilder* = trans._cur_builder - if pool is None or mod is None or builder is None: - return 0 + if pool is None or mod is None or builder is None: return 0 tn: sizet = len(dnode.targets) for ti in range(tn): tgt: ast.AST* = dnode.targets.get(ti) - if tgt is None: - continue + if tgt is None: continue # del obj → __delete__(对齐 TPC HandlesDelete.py:Name 目标调用 __delete__, # 类未定义 __delete__ 时静默无操作) if tgt.kind() == ast.ASTKind.Name: @@ -132,8 +104,7 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): del_st_nm: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(del_obj) if del_st_nm is not None: del_cls_nm: str = self.Gen.StructGen.get_class_name_by_type(pool, del_st_nm) - if del_cls_nm is not None: - self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, del_obj, "__delete__", trans) + if del_cls_nm is not None: self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, del_obj, "__delete__", trans) # del obj.attr → property deleter;无 deleter 时回退对象 __del__(对齐 TPC) elif tgt.kind() == ast.ASTKind.Attribute: del_at: ast.Attribute* = ast.Attribute*(tgt) @@ -141,8 +112,7 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): del_prop: int = self.Gen.CallGenProp._try_property_deleter(pool, builder, mod, del_at, trans) if del_prop == 0: del_av: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, del_at, None, 0, trans) - if del_av is not None: - self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, del_av, "__del__", trans) + if del_av is not None: self.Gen.ExprGenOps._try_named_dunder(pool, builder, mod, del_av, "__del__", trans) # del obj[key] → __delitem__(obj, key)(对齐 TPC HandlesDelete.py)。 # 不能静默忽略 Subscript 目标——否则 del 不生效(len 不变)。 elif tgt.kind() == ast.ASTKind.Subscript: @@ -168,8 +138,7 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): dl_first: mlirlite.Param* = mlirlite.function_get_param_head(dl_fn) if dl_first is not None: dl_self_ty: mlirlite.LLVMType* = mlirlite.param_get_ty(dl_first) - if dl_self_ty is not None: - dl_self = mlirlite.build_bitcast(builder, dl_obj, dl_self_ty) + if dl_self_ty is not None: dl_self = mlirlite.build_bitcast(builder, dl_obj, dl_self_ty) if dl_self is not None: # 参数链表: self → key(独立 null 结尾) dl_self.Next = dl_idx @@ -195,42 +164,33 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): def translate_try(self, trans: HT.Translator*, node: ast.AST*) -> int: """翻译 try/except 语句,返回 0""" - if trans is None or node is None: - return 0 + if trans is None or node is None: return 0 tr: ast.Try* = ast.Try*(node) - if tr is None: - return 0 + if tr is None: return 0 pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder func: mlirlite.Function* = trans._cur_func - if pool is None or builder is None or func is None: - return 0 - if mlirlite.builder_cur_block_is_terminated(builder) != 0: - return 0 + if pool is None or builder is None or func is None: return 0 + if mlirlite.builder_cur_block_is_terminated(builder) != 0: return 0 # ---- 1. 异常编码/消息 alloca(当前 try 上下文)---- i32_ty_t: mlirlite.LLVMType* = mlirlite.Int32(pool) i8_ty_t: mlirlite.LLVMType* = mlirlite.Int8(pool) i8_ptr_ty_t: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty_t) - if i32_ty_t is None or i8_ptr_ty_t is None: - return 0 + if i32_ty_t is None or i8_ptr_ty_t is None: return 0 exception_code: mlirlite.Value* = mlirlite.build_alloca(builder, i32_ty_t) eh_message: mlirlite.Value* = mlirlite.build_alloca(builder, i8_ptr_ty_t) - if exception_code is None or eh_message is None: - return 0 + if exception_code is None or eh_message is None: return 0 init_code_t: mlirlite.Value* = mlirlite.const_int32(pool, 0) init_msg_t: mlirlite.Value* = mlirlite.ConstNull(pool, i8_ptr_ty_t, "null") - if init_code_t is not None: - mlirlite.build_store(builder, init_code_t, exception_code) - if init_msg_t is not None: - mlirlite.build_store(builder, init_msg_t, eh_message) + if init_code_t is not None: mlirlite.build_store(builder, init_code_t, exception_code) + if init_msg_t is not None: mlirlite.build_store(builder, init_msg_t, eh_message) # ---- 2. 块布局(块名唯一化,create_block 不自动编号)---- lc_t: int = trans._label_counter trans._label_counter = lc_t + 1 bb_buf_t: str = pool.alloc(64) - if bb_buf_t is None: - return 0 + if bb_buf_t is None: return 0 viperlib.snprintf(bb_buf_t, 64, "try.dispatch.%d", lc_t) dispatch_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_buf_t) viperlib.snprintf(bb_buf_t, 64, "try.after.%d", lc_t) @@ -239,22 +199,19 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): unhandled_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_buf_t) viperlib.snprintf(bb_buf_t, 64, "try.body.%d", lc_t) try_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_buf_t) - if dispatch_bb is None or after_bb is None or unhandled_bb is None or try_bb is None: - return 0 + if dispatch_bb is None or after_bb is None or unhandled_bb is None or try_bb is None: return 0 else_bb: rawptr[mlirlite.BasicBlock] = None if tr.orelse is not None and len(tr.orelse) > 0: viperlib.snprintf(bb_buf_t, 64, "try.else.%d", lc_t) else_bb = mlirlite.create_block(pool, func, bb_buf_t) n_handlers_t: sizet = 0 - if tr.handlers is not None: - n_handlers_t = len(tr.handlers) + if tr.handlers is not None: n_handlers_t = len(tr.handlers) # 注意:list[ptr](pool, N) 第二参数是 elem_size 不是容量! # 指针元素必须显式传 8(T.__sizeof__ 对联合类型不可靠), # 否则 append 按 N 字节步长错位存取 → 读出垃圾指针(崩溃)。 except_bbs: list[rawptr[mlirlite.BasicBlock]]* = list[rawptr[mlirlite.BasicBlock]](pool, 8) match_bbs: list[rawptr[mlirlite.BasicBlock]]* = list[rawptr[mlirlite.BasicBlock]](pool, 8) - if except_bbs is None or match_bbs is None: - return 0 + if except_bbs is None or match_bbs is None: return 0 for i_t in range(n_handlers_t): viperlib.snprintf(bb_buf_t, 64, "try.except.%d.%d", lc_t, i_t) eb_t: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_buf_t) @@ -278,16 +235,12 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): tb_n: sizet = len(tr.children) for tbi in range(tb_n): stmt_t: ast.AST* = tr.children.get(tbi) - if stmt_t is not None: - self.translate_stmt(trans, stmt_t) + if stmt_t is not None: self.translate_stmt(trans, stmt_t) # 正常走完 try 体:清异常码,进 else(若有)或 After if mlirlite.builder_cur_block_is_terminated(builder) == 0: - if init_code_t is not None: - mlirlite.build_store(builder, init_code_t, exception_code) - if else_bb is not None: - mlirlite.build_br(builder, else_bb) - else: - mlirlite.build_br(builder, after_bb) + if init_code_t is not None: mlirlite.build_store(builder, init_code_t, exception_code) + if else_bb is not None: mlirlite.build_br(builder, else_bb) + else: mlirlite.build_br(builder, after_bb) # ---- 5. DispatchBB:编码检查链 ---- mlirlite.position_at_end(builder, dispatch_bb) @@ -310,40 +263,32 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): # 展开匹配编码集(handler.type 自身 + 全部子孙异常类) hname_t: str = None htype_t: ast.AST* = hdr_t.type - if htype_t.kind() == ast.ASTKind.Name: - hname_t = (ast.Name*(htype_t)).id - elif htype_t.kind() == ast.ASTKind.Attribute: - hname_t = (ast.Attribute*(htype_t)).attr + if htype_t.kind() == ast.ASTKind.Name: hname_t = (ast.Name*(htype_t)).id + elif htype_t.kind() == ast.ASTKind.Attribute: hname_t = (ast.Attribute*(htype_t)).attr # 匹配编码缓冲:必须是 int*(i32 步长)——collect_descendant_codes 按 # out_codes[i](4 字节)写入;用 sizet*(8 字节)读会读出 64 位拼接垃圾 # (多码时 code[i+1]<<32|code[i];单码时高位恰为 0 掩盖)。 codes_buf_t: int* = pool.alloc(64 * 4) - if codes_buf_t is None: - return 0 + if codes_buf_t is None: return 0 n_codes_t: int = 0 - if hname_t is not None and self.Gen.ClassGenBase.is_exception_name(hname_t) != 0: - n_codes_t = self.Gen.ClassGenBase.collect_descendant_codes(hname_t, codes_buf_t, 64) + if hname_t is not None and self.Gen.ClassGenBase.is_exception_name(hname_t) != 0: n_codes_t = self.Gen.ClassGenBase.collect_descendant_codes(hname_t, codes_buf_t, 64) else: c0_t: int = 1 if hname_t is not None: c0_t = self.Gen.ClassGenBase.lookup_exception_code(hname_t) - if c0_t == 0: - c0_t = 1 + if c0_t == 0: c0_t = 1 codes_buf_t[0] = c0_t n_codes_t = 1 match_cond_t: mlirlite.Value* = None for ci_t in range(n_codes_t): code_val_t: mlirlite.Value* = mlirlite.const_int32(pool, codes_buf_t[ci_t]) is_match_t: mlirlite.Value* = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, eh_code_val, code_val_t) - if match_cond_t is None: - match_cond_t = is_match_t - elif is_match_t is not None: - match_cond_t = mlirlite.build_or(builder, match_cond_t, is_match_t) + if match_cond_t is None: match_cond_t = is_match_t + elif is_match_t is not None: match_cond_t = mlirlite.build_or(builder, match_cond_t, is_match_t) if i_t < n_handlers_t - 1: viperlib.snprintf(bb_buf_t, 64, "try.check.%d.%d", lc_t, i_t) next_check_t = mlirlite.create_block(pool, func, bb_buf_t) - else: - next_check_t = unhandled_bb + else: next_check_t = unhandled_bb mlirlite.build_cond_br(builder, match_cond_t, match_bb_t, next_check_t) # MatchBB:绑定 handler 变量(e = 消息指针),跳 ExceptBB mlirlite.position_at_end(builder, match_bb_t) @@ -353,16 +298,13 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): # 各自 store 消息,各 ExceptBB 读同一入口 alloca,避免 # 非支配 alloca 触发 "does not dominate all uses")。 h_ent_t: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, hdr_t.name) - if h_ent_t is not None and h_ent_t.Alloca is not None: - h_alloca_t: mlirlite.Value* = h_ent_t.Alloca + if h_ent_t is not None and h_ent_t.Alloca is not None: h_alloca_t: mlirlite.Value* = h_ent_t.Alloca else: h_alloca_t = self.Gen.VarGen._alloca_at_entry(builder, i8_ptr_ty_t) - if h_alloca_t is not None: - self.Gen.VarGen.define_var(trans.SymTab, hdr_t.name, h_alloca_t) + if h_alloca_t is not None: self.Gen.VarGen.define_var(trans.SymTab, hdr_t.name, h_alloca_t) if h_alloca_t is not None: h_msg_t: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty_t, eh_message) - if h_msg_t is not None: - mlirlite.build_store(builder, h_msg_t, h_alloca_t) + if h_msg_t is not None: mlirlite.build_store(builder, h_msg_t, h_alloca_t) except_bb_t: rawptr[mlirlite.BasicBlock] = except_bbs.get(i_t) mlirlite.build_br(builder, except_bb_t) @@ -371,14 +313,11 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): if trans._cur_func_has_eh != 0 and trans._eh_msg_out_param is not None and trans._eh_code_out_param is not None: un_msg_t: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty_t, eh_message) un_code_t: mlirlite.Value* = mlirlite.build_load(builder, i32_ty_t, exception_code) - if un_msg_t is not None: - mlirlite.build_store(builder, un_msg_t, trans._eh_msg_out_param) - if un_code_t is not None: - mlirlite.build_store(builder, un_code_t, trans._eh_code_out_param) + if un_msg_t is not None: mlirlite.build_store(builder, un_msg_t, trans._eh_msg_out_param) + if un_code_t is not None: mlirlite.build_store(builder, un_code_t, trans._eh_code_out_param) self._eh_ret_default(trans, pool, builder) else: - if init_code_t is not None: - mlirlite.build_store(builder, init_code_t, exception_code) + if init_code_t is not None: mlirlite.build_store(builder, init_code_t, exception_code) mlirlite.build_br(builder, after_bb) # ---- 7. Except 体 ---- @@ -390,10 +329,8 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): hn2_t: sizet = len(hdr2_t.children) for hi2 in range(hn2_t): stmt2_t: ast.AST* = hdr2_t.children.get(hi2) - if stmt2_t is not None: - self.translate_stmt(trans, stmt2_t) - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, after_bb) + if stmt2_t is not None: self.translate_stmt(trans, stmt2_t) + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, after_bb) # ---- 8. Else 体 ---- if else_bb is not None: @@ -402,10 +339,8 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): en_t: sizet = len(tr.orelse) for ei in range(en_t): stmt3_t: ast.AST* = tr.orelse.get(ei) - if stmt3_t is not None: - self.translate_stmt(trans, stmt3_t) - if mlirlite.builder_cur_block_is_terminated(builder) == 0: - mlirlite.build_br(builder, after_bb) + if stmt3_t is not None: self.translate_stmt(trans, stmt3_t) + if mlirlite.builder_cur_block_is_terminated(builder) == 0: mlirlite.build_br(builder, after_bb) # ---- 9. AfterBB + 恢复外层 try 上下文 ---- mlirlite.position_at_end(builder, after_bb) @@ -427,13 +362,11 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): __eh_code_out__/__eh_msg_out__,返回默认值(异常向调用方传播) 3. 两者皆无:仅返回默认值(v1 语义:异常被吞掉) """ - if trans is None or node is None: - return 0 + if trans is None or node is None: return 0 pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder mod: mlirlite.LLVMModule* = trans.Module - if pool is None or builder is None or mod is None: - return 0 + if pool is None or builder is None or mod is None: return 0 rn: rawptr[ast.Raise] = rawptr[ast.Raise](node) if rn is None or rn.exc is None: # bare raise(无 exc):v1 无活动异常可再抛,仅返回默认值 @@ -446,21 +379,18 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): is_stop_iter: int = 0 if ek == ast.ASTKind.Name: enm: ast.Name* = ast.Name*(rn.exc) - if enm.id is not None and string.strcmp(enm.id, "StopIteration") == 0: - is_stop_iter = 1 + if enm.id is not None and string.strcmp(enm.id, "StopIteration") == 0: is_stop_iter = 1 elif ek == ast.ASTKind.Call: ecl: ast.Call* = ast.Call*(rn.exc) if ecl.func is not None and ecl.func.kind() == ast.ASTKind.Name: ecn: ast.Name* = ast.Name*(ecl.func) - if ecn.id is not None and string.strcmp(ecn.id, "StopIteration") == 0: - is_stop_iter = 1 + if ecn.id is not None and string.strcmp(ecn.id, "StopIteration") == 0: is_stop_iter = 1 if is_stop_iter != 0: if trans._stop_iter_flag_ptr is not None: i1_ty_r: mlirlite.LLVMType* = mlirlite.Int1(pool) if i1_ty_r is not None: one_i1_r: mlirlite.Value* = mlirlite.ConstInt(pool, i1_ty_r, 1, "1") - if one_i1_r is not None: - mlirlite.build_store(builder, one_i1_r, trans._stop_iter_flag_ptr) + if one_i1_r is not None: mlirlite.build_store(builder, one_i1_r, trans._stop_iter_flag_ptr) self._eh_ret_default(trans, pool, builder) return 0 @@ -469,46 +399,36 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): exc_msg: mlirlite.Value* = None if ek == ast.ASTKind.Constant: cst_r: ast.Constant* = ast.Constant*(rn.exc) - if cst_r is not None and cst_r.const_kind == ast.CONST_INT: - exc_code = cst_r.int_val + if cst_r is not None and cst_r.const_kind == ast.CONST_INT: exc_code = cst_r.int_val elif ek == ast.ASTKind.Name: enm2: ast.Name* = ast.Name*(rn.exc) if enm2.id is not None: exc_code = self.Gen.ClassGenBase.lookup_exception_code(enm2.id) - if exc_code == 0: - exc_code = 1 + if exc_code == 0: exc_code = 1 elif ek == ast.ASTKind.Call: ecl2: ast.Call* = ast.Call*(rn.exc) if ecl2.func is not None and ecl2.func.kind() == ast.ASTKind.Name: ecn2: ast.Name* = ast.Name*(ecl2.func) if ecn2.id is not None: exc_code = self.Gen.ClassGenBase.lookup_exception_code(ecn2.id) - if exc_code == 0: - exc_code = 1 - if ecl2.args is not None and len(ecl2.args) > 0: - exc_msg = self.Gen.ExprGen.translate_value(builder, pool, mod, ecl2.args.get(0), None, 0, trans) + if exc_code == 0: exc_code = 1 + if ecl2.args is not None and len(ecl2.args) > 0: exc_msg = self.Gen.ExprGen.translate_value(builder, pool, mod, ecl2.args.get(0), None, 0, trans) # ---- 异常分发 ---- # 1. try 内:写入 try 的 eh_code/eh_message alloca,分支 DispatchBB if trans._eh_dispatch_bb is not None and trans._eh_code_ptr is not None: code_val_r: mlirlite.Value* = mlirlite.const_int32(pool, exc_code) - if code_val_r is not None: - mlirlite.build_store(builder, code_val_r, trans._eh_code_ptr) - if exc_msg is None: - exc_msg = mlirlite.ConstNull(pool, mlirlite.Ptr(pool, mlirlite.Int8(pool)), "null") - if exc_msg is not None and trans._eh_msg_ptr is not None: - mlirlite.build_store(builder, exc_msg, trans._eh_msg_ptr) + if code_val_r is not None: mlirlite.build_store(builder, code_val_r, trans._eh_code_ptr) + if exc_msg is None: exc_msg = mlirlite.ConstNull(pool, mlirlite.Ptr(pool, mlirlite.Int8(pool)), "null") + if exc_msg is not None and trans._eh_msg_ptr is not None: mlirlite.build_store(builder, exc_msg, trans._eh_msg_ptr) mlirlite.build_br(builder, trans._eh_dispatch_bb) return 0 # 2. 函数有 EH 输出参数:写入 out 参数(异常向调用方传播) if trans._cur_func_has_eh != 0 and trans._eh_msg_out_param is not None and trans._eh_code_out_param is not None: code_val_r2: mlirlite.Value* = mlirlite.const_int32(pool, exc_code) - if code_val_r2 is not None: - mlirlite.build_store(builder, code_val_r2, trans._eh_code_out_param) - if exc_msg is None: - exc_msg = mlirlite.ConstNull(pool, mlirlite.Ptr(pool, mlirlite.Int8(pool)), "null") - if exc_msg is not None: - mlirlite.build_store(builder, exc_msg, trans._eh_msg_out_param) + if code_val_r2 is not None: mlirlite.build_store(builder, code_val_r2, trans._eh_code_out_param) + if exc_msg is None: exc_msg = mlirlite.ConstNull(pool, mlirlite.Ptr(pool, mlirlite.Int8(pool)), "null") + if exc_msg is not None: mlirlite.build_store(builder, exc_msg, trans._eh_msg_out_param) self._eh_ret_default(trans, pool, builder) return 0 # 3. 无 try 无 EH 参数:仅返回默认值 @@ -526,31 +446,24 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*) -> int: """异常路径返回当前函数默认零值,返回 0""" - if trans is None or builder is None: - return 0 - if mlirlite.builder_cur_block_is_terminated(builder) != 0: - return 0 + if trans is None or builder is None: return 0 + if mlirlite.builder_cur_block_is_terminated(builder) != 0: return 0 cur_func: mlirlite.Function* = trans._cur_func - if cur_func is None: - return 0 + if cur_func is None: return 0 ret_ty: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(cur_func) - if ret_ty is None: - return 0 + if ret_ty is None: return 0 match ret_ty: case mlirlite.LLVMType.Void(): mlirlite.build_ret_void(builder) case mlirlite.LLVMType.Ptr(_pe): null_v: mlirlite.Value* = mlirlite.ConstNull(pool, ret_ty, "null") - if null_v is not None: - mlirlite.build_ret(builder, null_v) + if null_v is not None: mlirlite.build_ret(builder, null_v) case mlirlite.LLVMType.Float(_fb): zero_f: mlirlite.Value* = mlirlite.ConstFloat(pool, ret_ty, 0.0) - if zero_f is not None: - mlirlite.build_ret(builder, zero_f) + if zero_f is not None: mlirlite.build_ret(builder, zero_f) case _: zero_v: mlirlite.Value* = mlirlite.ConstZero(pool, ret_ty) - if zero_v is not None: - mlirlite.build_ret(builder, zero_v) + if zero_v is not None: mlirlite.build_ret(builder, zero_v) return 0 # ============================================================ @@ -572,19 +485,15 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): def translate_with(self, trans: HT.Translator*, node: ast.AST*) -> int: """翻译 with 语句,返回 0""" - if trans is None or node is None: - return 0 + if trans is None or node is None: return 0 wt: ast.With* = ast.With*(node) - if wt is None: - return 0 + if wt is None: return 0 pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder mod: mlirlite.LLVMModule* = trans.Module - if pool is None or builder is None or mod is None: - return 0 + if pool is None or builder is None or mod is None: return 0 items: list[ast.AST*]* = wt.items - if items is None: - return 0 + if items is None: return 0 n: sizet = len(items) # 保存外层 __with_ctx(嵌套 with 时退出后恢复) @@ -592,24 +501,19 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): # 记录每个 item 的类名(__exit__ 调用时设置 __with_ctx 类型用) ctx_class_buf: sizet* = pool.alloc(8 * n) - if ctx_class_buf is None: - return 0 + if ctx_class_buf is None: return 0 string.memset(ctx_class_buf, 0, 8 * n) # 1. 全部 item:构造 context 对象 + 调用 __enter__ + asname 绑定 for i in range(n): item_node: ast.AST* = items.get(i) - if item_node is None: - continue - if item_node.kind() != ast.ASTKind.WithItem: - continue + if item_node is None: continue + if item_node.kind() != ast.ASTKind.WithItem: continue item: rawptr[ast.WithItem] = rawptr[ast.WithItem](item_node) - if item is None or item.context_expr is None: - continue + if item is None or item.context_expr is None: continue # 翻译 context_expr(对象构造,如 MemPool(arena, 4096)) ctx_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, item.context_expr, trans._funcs, trans._func_count, trans) - if ctx_val is None: - continue + if ctx_val is None: continue # 提取类名(注解类名,Attribute 时带模块前缀,如 "memhub.MemPool"—— # 与 AnnAssign 的 extract_class_name_from_annotation 一致,跨模块 # 方法调用靠 AnnotClassName 回退按模块名查 SHA1) @@ -628,14 +532,11 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): if mbuf is not None: viperlib.snprintf(mbuf, ml2, "%s.%s", cmn.id, ca.attr) cls_name = mbuf - if cls_name is None: - cls_name = ca.attr - elif cfn.kind() == ast.ASTKind.Name: - cls_name = (ast.Name*(cfn)).id + if cls_name is None: cls_name = ca.attr + elif cfn.kind() == ast.ASTKind.Name: cls_name = (ast.Name*(cfn)).id # context 对象存入 __with_ctx(方法调用解析 self 用) ctx_alloca: mlirlite.Value* = mlirlite.build_alloca(builder, ctx_val.Ty) - if ctx_alloca is None: - continue + if ctx_alloca is None: continue mlirlite.build_store(builder, ctx_val, ctx_alloca) self.Gen.VarGen.define_var(trans.SymTab, "__with_ctx", ctx_alloca) if cls_name is not None: @@ -650,25 +551,21 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): asname: str = (ast.Name*(ov)).id if asname is not None: bind_val: mlirlite.Value* = enter_val - if bind_val is None: - bind_val = ctx_val + if bind_val is None: bind_val = ctx_val if bind_val is not None: asn_alloca: mlirlite.Value* = mlirlite.build_alloca(builder, bind_val.Ty) if asn_alloca is not None: mlirlite.build_store(builder, bind_val, asn_alloca) self.Gen.VarGen.define_var(trans.SymTab, asname, asn_alloca) - if cls_name is not None: - self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, asname, cls_name) + if cls_name is not None: self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, asname, cls_name) # FakeDuck: __provides__ 元数据 → 生成 _push_provider 调用 # (对齐 TPC HandlesWith.py L138-159;经 gen 单例委托 CallGenMixin。 # 类名去模块前缀后查 __provides__ 表,如 memhub.MemBuddy → MemBuddy) fd_cls_bare: str = cls_name if cls_name is not None: fd_dot: str = string.strrchr(cls_name, '.') - if fd_dot is not None: - fd_cls_bare = fd_dot + 1 - if fd_cls_bare is not None: - self.Gen.CallGenFd._emit_provider_push(trans, pool, builder, mod, fd_cls_bare, ctx_val) + if fd_dot is not None: fd_cls_bare = fd_dot + 1 + if fd_cls_bare is not None: self.Gen.CallGenFd._emit_provider_push(trans, pool, builder, mod, fd_cls_bare, ctx_val) # 2. 翻译 body body: list[ast.AST*]* = wt.children @@ -676,8 +573,7 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): bn: sizet = len(body) for bi in range(bn): st: ast.AST* = body.get(bi) - if st is not None: - self.translate_stmt(trans, st) + if st is not None: self.translate_stmt(trans, st) # 2.5 FakeDuck: __provides__ 元数据 → 生成 _pop_provider 调用 # (对齐 TPC HandlesWith.py L167-174;逆序弹栈,经 gen 单例委托) @@ -687,10 +583,8 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): fd_cls_bare_p: str = cls_pop if cls_pop is not None: fd_dot_p: str = string.strrchr(cls_pop, '.') - if fd_dot_p is not None: - fd_cls_bare_p = fd_dot_p + 1 - if fd_cls_bare_p is not None: - self.Gen.CallGenFd._emit_provider_pop(trans, pool, builder, mod, fd_cls_bare_p) + if fd_dot_p is not None: fd_cls_bare_p = fd_dot_p + 1 + if fd_cls_bare_p is not None: self.Gen.CallGenFd._emit_provider_pop(trans, pool, builder, mod, fd_cls_bare_p) # 3. 逆序调用 __exit__()(Python with 语义:后进先出) for i in range(n): @@ -701,8 +595,7 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): self._with_ctx_call(trans, pool, builder, mod, "__exit__") # 4. 恢复外层 __with_ctx - if old_ctx_alloca is not None: - self.Gen.VarGen.define_var(trans.SymTab, "__with_ctx", old_ctx_alloca) + if old_ctx_alloca is not None: self.Gen.VarGen.define_var(trans.SymTab, "__with_ctx", old_ctx_alloca) return 0 def _with_ctx_call(self, trans: HT.Translator*, diff --git a/App/lib/core/Gen/StructGenMixin.vp b/App/lib/core/Gen/StructGenMixin.vp index 33d9ffc..3e128a8 100644 --- a/App/lib/core/Gen/StructGenMixin.vp +++ b/App/lib/core/Gen/StructGenMixin.vp @@ -53,8 +53,7 @@ define FNV32_MASK = 4294967295 def _struct_name_hash(name: str) -> uint64: """名字 → 哈希(32 位 FNV-1a,逐字节到 NUL 结束;空名返回偏移基值)""" h: uint64 = uint64(FNV32_OFFSET) - if name is None: - return h + if name is None: return h i: int = 0 while name[i] != '\0': h = (h ^ uint64(int(name[i]))) * uint64(FNV32_PRIME) @@ -235,12 +234,10 @@ novirtual class StructGenMixin: def _module_class_key(self, pool: memhub.MemBuddy*, sha1: str, name: str) -> str: """拼 "{sha1}.{类名}" 查询/登记键(分配在给定 pool,调用方无需释放)。""" - if pool is None or sha1 is None or name is None: - return None + if pool is None or sha1 is None or name is None: return None k_len: sizet = string.strlen(sha1) + 1 + string.strlen(name) + 1 k_buf: str = pool.alloc(k_len) - if k_buf is None: - return None + if k_buf is None: return None k_buf[0] = '\0' string.strcat(k_buf, sha1) string.strcat(k_buf, ".") @@ -258,8 +255,7 @@ novirtual class StructGenMixin: `CurDefModuleSha1` 同步记录("正在定义类所属模块"的权威来源,任何翻译 路径上都是 trans.ModuleSha1)。 """ - if sha1 is None or name is None: - return + if sha1 is None or name is None: return self.CurDefModuleSha1 = sha1 # 类名同步记录(表无关的自引用判据;池/表缺失也必须记 —— 它只是当前 # 类定义入口手里的那个串,不经任何表查询,见 _norm_type_arg_name 规则 5.5)。 @@ -270,21 +266,16 @@ novirtual class StructGenMixin: # 已回收的键(ASan access-violation 现场)。 return k_buf: str = self._module_class_key(pool, sha1, name) - if k_buf is None: - return - if self.ModuleClasses.__contains__(k_buf) != 0: - return + if k_buf is None: return + if self.ModuleClasses.__contains__(k_buf) != 0: return self.ModuleClasses.set_int(k_buf, 1) def is_module_class(self, pool: memhub.MemBuddy*, sha1: str, name: str) -> int: """裸名 name 是否由模块 sha1 声明(1=是 / 0=否;与 struct 注册状态无关)。""" - if pool is None or sha1 is None or name is None: - return 0 - if self.ModuleClasses is None: - return 0 + if pool is None or sha1 is None or name is None: return 0 + if self.ModuleClasses is None: return 0 k_buf: str = self._module_class_key(pool, sha1, name) - if k_buf is None: - return 0 + if k_buf is None: return 0 return self.ModuleClasses.__contains__(k_buf) def register_file_classes(self, pool: memhub.MemBuddy*, sha1: str, tree: ast.AST*) -> None: @@ -302,42 +293,32 @@ novirtual class StructGenMixin: 判据是**正向事实**(该名字确由本文件声明),且与"窗口"无关 ⇒ 不依赖类定义顺序, 不需要在窗口里"猜"归属。表与键同池、每文件重建(见 reset_visible_structs)。 """ - if pool is None or sha1 is None or tree is None: - return + if pool is None or sha1 is None or tree is None: return self.FileModuleSha1 = sha1 ch: list[ast.AST*]* = tree.children - if ch is None: - return - if self.FileClassNames is None: - self.FileClassNames = hashtable.HashTable(pool) - if self.FileClassNames is None: - return + if ch is None: return + if self.FileClassNames is None: self.FileClassNames = hashtable.HashTable(pool) + if self.FileClassNames is None: return cn: sizet = len(ch) ci: sizet for ci in range(cn): child: ast.AST* = ch.get(ci) - if child is None: - continue - if child.kind() != ast.ASTKind.ClassDef: - continue + if child is None: continue + if child.kind() != ast.ASTKind.ClassDef: continue cd: ast.ClassDef* = ast.ClassDef*(child) - if cd is None or cd.name is None: - continue - if self.FileClassNames.__contains__(cd.name) != 0: - continue + if cd is None or cd.name is None: continue + if self.FileClassNames.__contains__(cd.name) != 0: continue # 键必须与表同池(AST 的 name 串零拷贝指向 src_buf,跨阶段可能失效): # 复制到 pool 后再登记,避免表 resize/查询时 strcmp 到悬空内存。 nm_len: sizet = string.strlen(cd.name) nm_buf: str = pool.alloc(nm_len + 1) - if nm_buf is None: - continue + if nm_buf is None: continue string.strcpy(nm_buf, cd.name) self.FileClassNames.set_int(nm_buf, 1) def is_file_class(self, pool: memhub.MemBuddy*, name: str) -> int: """裸名 name 是否为本文件顶层声明的类(1=是 / 0=否;与窗口、与注册状态无关)。""" - if name is None or self.FileClassNames is None: - return 0 + if name is None or self.FileClassNames is None: return 0 return self.FileClassNames.__contains__(name) def register_file_funcs(self, pool: memhub.MemBuddy*, tree: ast.AST*) -> None: @@ -359,41 +340,31 @@ novirtual class StructGenMixin: 注入侧据本表跳过"本文件已声明的裸名"(VpiReader._inject_function_declare), 使本文件自己的声明优先。表与键同池、每文件重建(与 FileClassNames 同规矩)。 """ - if pool is None or tree is None: - return + if pool is None or tree is None: return ch: list[ast.AST*]* = tree.children - if ch is None: - return - if self.FileFuncNames is None: - self.FileFuncNames = hashtable.HashTable(pool) - if self.FileFuncNames is None: - return + if ch is None: return + if self.FileFuncNames is None: self.FileFuncNames = hashtable.HashTable(pool) + if self.FileFuncNames is None: return cn: sizet = len(ch) ci: sizet for ci in range(cn): child: ast.AST* = ch.get(ci) - if child is None: - continue - if child.kind() != ast.ASTKind.FunctionDef: - continue + if child is None: continue + if child.kind() != ast.ASTKind.FunctionDef: continue fd: ast.FunctionDef* = ast.FunctionDef*(child) - if fd is None or fd.name is None: - continue - if self.FileFuncNames.__contains__(fd.name) != 0: - continue + if fd is None or fd.name is None: continue + if self.FileFuncNames.__contains__(fd.name) != 0: continue # 键必须与表同池(AST 的 name 串零拷贝指向 src_buf,跨阶段可能失效): # 复制到 pool 后再登记,避免表 resize/查询时 strcmp 到悬空内存。 nm_len: sizet = string.strlen(fd.name) nm_buf: str = pool.alloc(nm_len + 1) - if nm_buf is None: - continue + if nm_buf is None: continue string.strcpy(nm_buf, fd.name) self.FileFuncNames.set_int(nm_buf, 1) def is_file_func(self, name: str) -> int: """裸名 name 是否为本文件顶层声明的函数(1=是 / 0=否)""" - if name is None or self.FileFuncNames is None: - return 0 + if name is None or self.FileFuncNames is None: return 0 return self.FileFuncNames.__contains__(name) def get_file_module_sha1(self) -> str: @@ -440,8 +411,7 @@ novirtual class StructGenMixin: def _get_struct_entry(self, i: int) -> GenTypes.StructEntry*: """获取第 i 个结构体条目""" - if self.StructTable is None or i < 0 or i >= STRUCT_MAX: - return None + if self.StructTable is None or i < 0 or i >= STRUCT_MAX: return None entry_size: sizet = GenTypes.StructEntry.__sizeof__() addr: uint64 = uint64(self.StructTable) + i * entry_size return GenTypes.StructEntry*(addr) @@ -455,15 +425,13 @@ novirtual class StructGenMixin: def _struct_entry_name(self, i: int) -> str: """取第 i 个条目的 Name(供索引探测比较),越界/空返回 None""" e: GenTypes.StructEntry* = self._get_struct_entry(i) - if e is None: - return None + if e is None: return None return e.Name def _struct_entry_tyval(self, i: int) -> uint64: """取第 i 个条目的 Ty 指针值(Ty=None 返回 0)""" e: GenTypes.StructEntry* = self._get_struct_entry(i) - if e is None or e.Ty is None: - return 0 + if e is None or e.Ty is None: return 0 return uint64(e.Ty) def _struct_name_idx_insert(self, ei: int, name: str) -> int: @@ -474,8 +442,7 @@ novirtual class StructGenMixin: 则最早的重复项被中和(Name[0]=0)后,被丢弃的后续重复项将无法找回。 """ base: sizet* = self.StructNameIdx - if base is None or self.StructIdxCap <= 0: - return 1 + if base is None or self.StructIdxCap <= 0: return 1 h: uint64 = _struct_name_hash(name) mask: sizet = sizet(self.StructIdxCap - 1) idx: sizet = sizet(h) & mask @@ -496,8 +463,7 @@ novirtual class StructGenMixin: 顺序排列,查找首个"当前 Ty 相等"者 = 原扫描首个命中。 """ base: sizet* = self.StructTypeIdx - if base is None or self.StructIdxCap <= 0 or tyval == 0: - return 1 + if base is None or self.StructIdxCap <= 0 or tyval == 0: return 1 h: uint64 = _struct_ty_hash(tyval) mask: sizet = sizet(self.StructIdxCap - 1) idx: sizet = sizet(h) & mask @@ -517,12 +483,9 @@ novirtual class StructGenMixin: self.StructIdxBuilt = -1 return failed: int = 0 - if entry is not None and entry.Name is not None: - failed = failed + self._struct_name_idx_insert(ei, entry.Name) - if entry is not None and entry.Ty is not None: - failed = failed + self._struct_type_idx_insert(ei, uint64(entry.Ty)) - if failed != 0: - self.StructIdxBuilt = -1 + if entry is not None and entry.Name is not None: failed = failed + self._struct_name_idx_insert(ei, entry.Name) + if entry is not None and entry.Ty is not None: failed = failed + self._struct_type_idx_insert(ei, uint64(entry.Ty)) + if failed != 0: self.StructIdxBuilt = -1 else: # ei = StructCount-1,故同步后已建索引条目数 = StructCount self.StructIdxBuilt = self.StructCount @@ -534,13 +497,11 @@ novirtual class StructGenMixin: 探测链上同键条目按注册顺序排列,故首个"当前键相等"者即原扫描首个命中。 """ base: sizet* = self.StructNameIdx - if base is None or self.StructIdxCap <= 0 or self.StructIdxBuilt != self.StructCount: - return -1 + if base is None or self.StructIdxCap <= 0 or self.StructIdxBuilt != self.StructCount: return -1 # 空名("")特例:被中和的条目 Name 恰为 ""(Name[0]=0),原扫描会命中首个 # 空名条目;索引槽按"注册时的原名"哈希放置,无法保证给出首个空名条目 → # 空名一律回退原扫描,保证逐字节一致。 - if name is None or name[0] == '\0': - return -1 + if name is None or name[0] == '\0': return -1 h: uint64 = _struct_name_hash(name) mask: sizet = sizet(self.StructIdxCap - 1) idx: sizet = sizet(h) & mask @@ -569,8 +530,7 @@ novirtual class StructGenMixin: for i in range(self.StructIdxCap): slot: sizet* = (sizet*)(uint64(base) + uint64(idx * 8)) sv: sizet = slot[0] - if sv == 0: - return -1 + if sv == 0: return -1 se: int = int(sv) - 1 if self._struct_entry_tyval(se) == tyval: return se idx = (idx + 1) & mask @@ -599,8 +559,7 @@ novirtual class StructGenMixin: # 走 find_struct_by_type(其 Ty 索引判定已整体停用、恢复原线性扫描), # 去重语义 = 原去重扫描"首个 Ty 指针相等条目"(首注册优先),逐字节一致。 existing: GenTypes.StructEntry* = self.find_struct_by_type(struct_ty) - if existing is not None: - return existing + if existing is not None: return existing if self.StructCount >= STRUCT_MAX: VLogger.error(f"table full, cannot register {name}", "STRUCT") return None @@ -612,8 +571,7 @@ novirtual class StructGenMixin: perm_sg: memhub.MemBuddy* = CompilerFactory.factory.PermPool if perm_sg is None: perm_sg = pool entry.Fields = perm_sg.alloc(field_size * FIELD_MAX) - else: - entry.Fields = pool.alloc(field_size * FIELD_MAX) + else: entry.Fields = pool.alloc(field_size * FIELD_MAX) if entry.Fields is None: return None string.memset(entry.Fields, 0, field_size * FIELD_MAX) # 复制类名(1b/Phase2(StdlibAlloc=1)用永久池跨 reset 存活;1a 用主 pool, @@ -656,15 +614,11 @@ novirtual class StructGenMixin: # 返回占位/既有条目;参数非法或表满时返回 None。 # ============================================================ def ensure_forward_class(self, pool: memhub.MemBuddy*, sha1: str, class_name: str) -> GenTypes.StructEntry*: - if pool is None or sha1 is None or class_name is None: - return None - if sha1[0] == '\0' or class_name[0] == '\0': - return None + if pool is None or sha1 is None or class_name is None: return None + if sha1[0] == '\0' or class_name[0] == '\0': return None existing: GenTypes.StructEntry* = self.find_struct_by_module(class_name, sha1) - if existing is not None: - return existing - if self.init_struct_table(pool) == 0: - return None + if existing is not None: return existing + if self.init_struct_table(pool) == 0: return None if self.StructCount >= STRUCT_MAX: VLogger.error(f"table full, cannot forward-declare {class_name}", "STRUCT") return None @@ -675,22 +629,18 @@ novirtual class StructGenMixin: fwd_pool: memhub.MemBuddy* = pool if self.StdlibAlloc != 0: fwd_pool = CompilerFactory.factory.PermPool - if fwd_pool is None: - fwd_pool = pool + if fwd_pool is None: fwd_pool = pool sh_len: sizet = string.strlen(sha1) cn_len: sizet = string.strlen(class_name) name_buf: str = fwd_pool.alloc(sh_len + 1 + cn_len + 1) - if name_buf is None: - return None + if name_buf is None: return None string.strcpy(name_buf, sha1) name_buf[sh_len] = '.' string.strcpy(name_buf + sh_len + 1, class_name) fwd_ty: mlirlite.LLVMType* = mlirlite.Struct(fwd_pool, None, 0, name_buf) - if fwd_ty is None: - return None + if fwd_ty is None: return None entry: GenTypes.StructEntry* = self.register_struct(pool, class_name, fwd_ty, sha1) - if entry is None: - return None + if entry is None: return None entry.IsForwardDecl = 1 self.add_visible_struct(pool, class_name) return entry @@ -759,18 +709,15 @@ novirtual class StructGenMixin: def set_struct_sha1(self, pool: memhub.MemBuddy*, class_name: str, sha1: str) -> int: """设置结构体所属模块的 SHA1,返回 1=成功 / 0=失败""" - if class_name is None or sha1 is None: - return 0 + if class_name is None or sha1 is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(class_name) - if entry is None: - return 0 + if entry is None: return 0 # 复制 SHA1 字符串(StdlibAlloc=1 用永久池,跨 1a/1b 存活防 strcmp 悬空) sha1_len: sizet = string.strlen(sha1) sha1_pool: memhub.MemBuddy* = pool if self.StdlibAlloc != 0: sha1_pool = CompilerFactory.factory.PermPool - if sha1_pool is None: - sha1_pool = pool + if sha1_pool is None: sha1_pool = pool sha1_buf: str = sha1_pool.alloc(sha1_len + 1) if sha1_buf is None: return 0 string.strcpy(sha1_buf, sha1) @@ -779,11 +726,9 @@ novirtual class StructGenMixin: def get_struct_sha1(self, class_name: str) -> str: """获取结构体所属模块的 SHA1,返回 None=无 SHA1""" - if class_name is None or self.StructTable is None: - return None + if class_name is None or self.StructTable is None: return None entry: GenTypes.StructEntry* = self.find_struct(class_name) - if entry is None: - return None + if entry is None: return None return entry.ModuleSha1 def add_field(self, pool: memhub.MemBuddy*, @@ -843,12 +788,10 @@ novirtual class StructGenMixin: # 携带真实无符号性与注解书写形态名;LLVM 反推恒 TS_INT 且无名)。 # 类型信息缺失(Spec 为 None)时建 TS_UNKNOWN 承载注解名(不表态具体类型)。 if annot_class_name is not None: - if fe.Spec is None: - fe.Spec = TSpec.NewTypeSpec(arena_f, TSpec.TS_UNKNOWN, 0, TSpec.TS_SIGN_UNKNOWN) + if fe.Spec is None: fe.Spec = TSpec.NewTypeSpec(arena_f, TSpec.TS_UNKNOWN, 0, TSpec.TS_SIGN_UNKNOWN) if fe.Spec is not None: sign_f: int = self.Gen.TypeGenCType.spec_sign_of_annot(annot_class_name) - if sign_f != TSpec.TS_SIGN_UNKNOWN: - fe.Spec = TSpec.SpecWithSign(arena_f, fe.Spec, sign_f) + if sign_f != TSpec.TS_SIGN_UNKNOWN: fe.Spec = TSpec.SpecWithSign(arena_f, fe.Spec, sign_f) fe.Spec = TSpec.SpecWithSource(fe.Spec, annot_class_name) # const 标记显式置 0(不依赖条目内存的零初值约定):本字段由 ClassGenDef @@ -873,8 +816,7 @@ novirtual class StructGenMixin: if default_val.kind() != ast.ASTKind.Constant: return None src_c: ast.Constant* = ast.Constant*(default_val) dst_c: ast.Constant* = ast.Constant*(pool.alloc_tagged(ast.Constant.__sizeof__(), memhub.DETSITE_STRUCTGENMIXIN_641)) - if dst_c is None: - return None + if dst_c is None: return None string.memset(dst_c, 0, ast.Constant.__sizeof__()) # 拷贝 vtable 指针(AST 是 @t.CVTable,kind() 虚调用依赖首字段 vptr) # 【必须与 _deep_copy_list_ast 同款:c.Deref 读首字 + c.DerefAs 写首字】 @@ -1021,10 +963,8 @@ novirtual class StructGenMixin: real_rm: str = StubMergerStore.LookupModNameByAlias(from_imports, mod_name) if real_rm is not None: s_rm = StubMergerStore.LookupSha1ByModName(real_rm) - if s_rm is None: - s_rm = StubMergerStore.LookupSha1ByModNameSuffix(real_rm) - if s_rm is None: - s_rm = StubMergerStore.LookupSha1ByModNameSuffix(mod_name) + if s_rm is None: s_rm = StubMergerStore.LookupSha1ByModNameSuffix(real_rm) + if s_rm is None: s_rm = StubMergerStore.LookupSha1ByModNameSuffix(mod_name) return s_rm def find_struct_entry_with_ty(self, name: str, alt_name: str) -> GenTypes.StructEntry*: @@ -1039,18 +979,13 @@ novirtual class StructGenMixin: name / alt_name:主名与备选名(如模块限定名与裸类名),任一命中即可。 """ - if self.StructTable is None: - return None + if self.StructTable is None: return None for i in range(self.StructCount): entry: GenTypes.StructEntry* = self._get_struct_entry(i) - if entry is None or entry.Name is None or entry.Ty is None: - continue - if entry.Name[0] == '\0': - continue - if string.strcmp(entry.Name, name) == 0: - return entry - if alt_name is not None and string.strcmp(entry.Name, alt_name) == 0: - return entry + if entry is None or entry.Name is None or entry.Ty is None: continue + if entry.Name[0] == '\0': continue + if string.strcmp(entry.Name, name) == 0: return entry + if alt_name is not None and string.strcmp(entry.Name, alt_name) == 0: return entry return None def find_struct(self, name: str) -> GenTypes.StructEntry*: @@ -1062,8 +997,7 @@ novirtual class StructGenMixin: 跨库回退(防 sched.Thread 被 vthreading.Thread 顶掉的同类问题); 仅模块名无法解析时保留裸名回退(兼容旧行为)。 """ - if name is None or self.StructTable is None: - return None + if name is None or self.StructTable is None: return None # 第一遍:精确匹配 # StructCount 合理性守卫(内存损坏导致巨大值 → 索引循环假挂起) if self.StructCount < 0 or self.StructCount > 200000: @@ -1079,14 +1013,12 @@ novirtual class StructGenMixin: # 全部 strcmp)。索引不可信 / 无索引 / 空名查询时仍回退原线性扫描 # (正确性保证,非兜底);精确匹配确无时继续走模块限定名/裸名回退逻辑。 name_idx_trusted: int = 0 - if self.StructNameIdx is not None and self.StructIdxCap > 0 and self.StructIdxBuilt == self.StructCount: - name_idx_trusted = 1 + if self.StructNameIdx is not None and self.StructIdxCap > 0 and self.StructIdxBuilt == self.StructCount: name_idx_trusted = 1 if name_idx_trusted == 0 or name[0] == '\0': for i in range(self.StructCount): entry: GenTypes.StructEntry* = self._get_struct_entry(i) if entry is not None and entry.Name is not None: - if string.strcmp(entry.Name, name) == 0: - return entry + if string.strcmp(entry.Name, name) == 0: return entry # 模块限定名(module.Class):模块可解析时按模块归属精确匹配, # 防止裸名回退抓跨模块同名类。模块未命中时若裸名类唯一(无冲突) # 仍回退,避免误杀未登记模块的既有解析。 @@ -1132,8 +1064,7 @@ novirtual class StructGenMixin: same_cnt_f += 1 same_entry_f = e2 stdlib.free(mod_buf_f) - if same_cnt_f == 1: - return same_entry_f + if same_cnt_f == 1: return same_entry_f return None stdlib.free(mod_buf_f) # 第二遍:类名回退(处理模块限定名 "HT.Translator" → "Translator", @@ -1153,8 +1084,7 @@ novirtual class StructGenMixin: if string.strcmp(entry.Name, class_name) == 0: same_cnt_b += 1 same_entry_b = entry - if same_cnt_b == 1: - return same_entry_b + if same_cnt_b == 1: return same_entry_b return None def find_struct_by_module(self, name: str, sha1: str) -> GenTypes.StructEntry*: @@ -1163,8 +1093,7 @@ novirtual class StructGenMixin: SHA1 非 None 时:精确匹配 name+sha1,未找到返回 None(不回退,避免跨模块同名找错) SHA1 为 None 时:回退到 find_struct(name) 按类名查找第一个 """ - if name is None or self.StructTable is None: - return None + if name is None or self.StructTable is None: return None # StructCount 合理性守卫(内存损坏导致巨大值 → 索引循环假挂起) if self.StructCount < 0 or self.StructCount > 200000: VLogger.error(f"StructCount 异常: {self.StructCount} (find_struct_by_module)", "STRUCT") @@ -1175,8 +1104,7 @@ novirtual class StructGenMixin: # 未命中/索引不可信 ⇒ start=0,走原全表扫描(保证正确性)。 start: int = 0 fri: int = self._struct_name_idx_find(name) - if fri >= 0: - start = fri + if fri >= 0: start = fri for i in range(start, self.StructCount): entry: GenTypes.StructEntry* = self._get_struct_entry(i) if entry is not None and entry.Name is not None: @@ -1184,8 +1112,7 @@ novirtual class StructGenMixin: if entry.Name[0] == name[0] and string.strcmp(entry.Name, name) == 0: if entry.ModuleSha1 is not None: # 同上:sha1 判等蕴含首字符相等,先比首字符再 strcmp。 - if entry.ModuleSha1[0] == sha1[0] and string.strcmp(entry.ModuleSha1, sha1) == 0: - return entry + if entry.ModuleSha1[0] == sha1[0] and string.strcmp(entry.ModuleSha1, sha1) == 0: return entry # SHA1 查找失败:不回退到 find_struct(会返回跨模块同名错误 entry) # 返回 None 让调用方创建新类型,避免 Phase B 用错误类型短路 return None @@ -1205,8 +1132,7 @@ novirtual class StructGenMixin: AssignGenMixin text.ll 空 / HandlesTranslator 有模块函数缺类方法)。 按本文件 ModuleSha1 精确回滚,不影响其他已写盘文件的 MethodsEmitted。 """ - if sha1 is None or self.StructTable is None: - return 0 + 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") return 0 @@ -1237,8 +1163,7 @@ novirtual class StructGenMixin: 对悬空 entry.Ty(1b 泛型特化类注册后被 reset 回收的 pool 指针)解引用崩溃。 改用 uint64 纯指针值比较,不解引用任何内容。 """ - if struct_ty is None or self.StructTable is None: - return None + if struct_ty is None or self.StructTable is None: return None # StructCount 合理性守卫(内存损坏导致巨大值 → 索引循环假挂起) if self.StructCount < 0 or self.StructCount > 200000: VLogger.error(f"StructCount 异常: {self.StructCount} (find_struct_by_type)", "STRUCT") @@ -1252,8 +1177,7 @@ novirtual class StructGenMixin: for i in range(self.StructCount): entry: GenTypes.StructEntry* = self._get_struct_entry(i) if entry is not None and entry.Ty is not None: - if uint64(entry.Ty) == st_val: - return entry + if uint64(entry.Ty) == st_val: return entry return None def struct_type_is_packed(self, struct_ty: mlirlite.LLVMType*) -> int: @@ -1264,16 +1188,12 @@ novirtual class StructGenMixin: StructEntry.IsPacked(B5 在定义侧/stub 注入侧写入)。供 __sizeof__ 尺寸与字段偏移计算:packed 结构体无字段填充,大小=字段尺寸之和。 """ - if struct_ty is None: - return 0 + if struct_ty is None: return 0 sname: str = mlirlite.get_struct_name(struct_ty) - if sname is None: - return 0 + if sname is None: return 0 entry: GenTypes.StructEntry* = self.find_struct_by_type(struct_ty) - if entry is None: - entry = self.find_struct(sname) - if entry is None: - return 0 + if entry is None: entry = self.find_struct(sname) + if entry is None: return 0 return entry.IsPacked # ============================================================ @@ -1300,19 +1220,15 @@ novirtual class StructGenMixin: def verify_field_slot_consistency(self, struct_ty: mlirlite.LLVMType*, entry: GenTypes.StructEntry*) -> int: """字段表条数须等于结构体槽位数;每条目 Ty 须与其 Index 槽位同类""" - if struct_ty is None or entry is None: - return 0 - if entry.FieldCount <= 0: - return 0 + if struct_ty is None or entry is None: return 0 + if entry.FieldCount <= 0: return 0 # 联合体豁免:union 的字段表有 N 条(每个成员一条),但 LLVM 布局只有 **1 个 # 槽位**(成员全部偏移 0、按最大成员定宽),二者本就不相等;字段访问走的是 # bitcast 到字段类型后的 GEP(见 ExprGenAttr 的 union 分支),不依赖槽位下标, # 故本护栏不适用(误报实证:EdgeCaseTest 的 `class Data(t.CUnion)`,2 成员 → 1 槽)。 - if entry.IsUnion != 0 or self.is_union_by_type(struct_ty) != 0: - return 0 + if entry.IsUnion != 0 or self.is_union_by_type(struct_ty) != 0: return 0 fcount: int = mlirlite.get_struct_fcount(struct_ty) - if fcount <= 0: - return 0 + if fcount <= 0: return 0 if entry.FieldCount != fcount: self.Gen.TypeGenErr.fatal_error(None, f"结构体 '{entry.Name}' 的字段表条数({entry.FieldCount})与 LLVM 槽位数({fcount})不一致:" @@ -1352,8 +1268,7 @@ novirtual class StructGenMixin: 第一遍: 类型指针 is 身份比较(最高优先级,类型唯一确定 entry) 第二遍: 名称回退(is 未匹配时,按类名/strstr 匹配,字段未找到时 continue) """ - if struct_ty is None or field_name is None or self.StructTable is None: - return None + if struct_ty is None or field_name is None or self.StructTable is None: return None # ============================================================ # 两遍查找策略(跨模块同名类冲突的根本修复): @@ -1379,8 +1294,7 @@ novirtual class StructGenMixin: for fi in range(lk_entry.FieldCount): fe: GenTypes.FieldEntry* = self._get_field_entry(lk_entry, fi) if fe is not None and fe.Name is not None: - if string.strcmp(fe.Name, field_name) == 0: - return fe + if string.strcmp(fe.Name, field_name) == 0: return fe return None # 第二遍: 名称回退(is 未匹配到) @@ -1392,28 +1306,23 @@ novirtual class StructGenMixin: # → _thread_entry call 0)。strncmp 不分配临时缓冲。 # 前缀判定走唯一真源 GenApi.sha1_prefix_len。 ty_has_sha1_lf: int = 0 - if GenApi.sha1_prefix_len(ty_name) != 0: - ty_has_sha1_lf = 1 + if GenApi.sha1_prefix_len(ty_name) != 0: ty_has_sha1_lf = 1 for i in range(self.StructCount): entry: GenTypes.StructEntry* = self._get_struct_entry(i) if entry is not None and entry.Name is not None: # 类型名带 SHA1 前缀:必须与 entry.ModuleSha1 前 16 字符 # 精确一致,否则跳过(跨模块同名类命名空间隔离) if ty_has_sha1_lf != 0: - if entry.ModuleSha1 is None or string.strlen(entry.ModuleSha1) < 16 or string.strncmp(entry.ModuleSha1, ty_name, 16) != 0: - continue + if entry.ModuleSha1 is None or string.strlen(entry.ModuleSha1) < 16 or string.strncmp(entry.ModuleSha1, ty_name, 16) != 0: continue matched: int = 0 - if string.strcmp(entry.Name, ty_name) == 0: - matched = 1 - elif string.strstr(ty_name, entry.Name) is not None: - matched = 1 + if string.strcmp(entry.Name, ty_name) == 0: matched = 1 + elif string.strstr(ty_name, entry.Name) is not None: matched = 1 if matched != 0: # 查找字段 for fi in range(entry.FieldCount): fe: GenTypes.FieldEntry* = self._get_field_entry(entry, fi) if fe is not None and fe.Name is not None: - if string.strcmp(fe.Name, field_name) == 0: - return fe + if string.strcmp(fe.Name, field_name) == 0: return fe # 名称匹配但字段未找到,继续检查其他同名 entry(跨模块同名) continue # 所有条目都未匹配 @@ -1429,8 +1338,7 @@ novirtual class StructGenMixin: lookup_field_by_class FAIL 根因)。从末尾扫描并跟踪括号深度, 只认深度为 0 的 '.'。 """ - if s is None: - return None + if s is None: return None n: sizet = string.strlen(s) depth: int = 0 i: sizet = n @@ -1467,25 +1375,21 @@ novirtual class StructGenMixin: dot_pos_lfbc: str = self._last_dot_outside_brackets(class_name) if dot_pos_lfbc is not None: bare_name = dot_pos_lfbc + 1 - if bare_name is None or bare_name[0] == '\0': - bare_name = class_name + if bare_name is None or bare_name[0] == '\0': bare_name = class_name for i in range(self.StructCount): entry: GenTypes.StructEntry* = self._get_struct_entry(i) if entry is not None and entry.Name is not None: # 精确匹配或类名回退匹配 name_match: int = 0 - if string.strcmp(entry.Name, class_name) == 0: - name_match = 1 - elif bare_name is not class_name and string.strcmp(entry.Name, bare_name) == 0: - name_match = 1 + if string.strcmp(entry.Name, class_name) == 0: name_match = 1 + elif bare_name is not class_name and string.strcmp(entry.Name, bare_name) == 0: name_match = 1 if name_match != 0: if entry.ModuleSha1 is not None and string.strcmp(entry.ModuleSha1, sha1) == 0: sha1_matched = 1 # SHA1 + 类名匹配,查找字段 for fi in range(entry.FieldCount): fe: GenTypes.FieldEntry* = self._get_field_entry(entry, fi) - if fe is not None and fe.Name is not None and string.strcmp(fe.Name, field_name) == 0: - return fe + if fe is not None and fe.Name is not None and string.strcmp(fe.Name, field_name) == 0: return fe return None # 模块限定名(module.Class,module 非 t/c 内置):按模块归属解析,禁止裸名回退 @@ -1523,8 +1427,7 @@ novirtual class StructGenMixin: # SHA1 前缀自身即"已登记"证据(与既有解析同语义): # mod_sha1_q 别名 mod_buf_q(下方各返回路径统一 free 一次) mod_sha1_q = mod_buf_q - else: - mod_sha1_q = self._resolve_module_sha1(mod_buf_q, from_imports) + else: mod_sha1_q = self._resolve_module_sha1(mod_buf_q, from_imports) if mod_sha1_q is not None: mod_entry_q: GenTypes.StructEntry* = self.find_struct_by_module(bare_q, mod_sha1_q) if mod_entry_q is not None: @@ -1545,16 +1448,13 @@ novirtual class StructGenMixin: # 变体别名(REnum 字段是 _p1/_p2 槽位)。此前该回退只在裸名 # 路径,模块限定路径此处 fatal 先触发 → 永远走不到。 rn_cls_q: str = mod_entry_q.Name - if rn_cls_q is None: - rn_cls_q = bare_q + if rn_cls_q is None: rn_cls_q = bare_q rn_is_renum_q: int = self.Gen.ClassGenEnum._is_renum_class_name(bare_q) - if rn_is_renum_q == 0 and rn_cls_q is not None: - rn_is_renum_q = self.Gen.ClassGenEnum._is_renum_class_name(rn_cls_q) + if rn_is_renum_q == 0 and rn_cls_q is not None: rn_is_renum_q = self.Gen.ClassGenEnum._is_renum_class_name(rn_cls_q) rn_alias_q: int = -1 if rn_is_renum_q != 0: rn_alias_q = self.Gen.ClassGenEnum._lookup_renum_field_alias(rn_cls_q, field_name) - if rn_alias_q < 1 and bare_q is not rn_cls_q: - rn_alias_q = self.Gen.ClassGenEnum._lookup_renum_field_alias(bare_q, field_name) + if rn_alias_q < 1 and bare_q is not rn_cls_q: rn_alias_q = self.Gen.ClassGenEnum._lookup_renum_field_alias(bare_q, field_name) if rn_alias_q >= 1: rn_fe_q: GenTypes.FieldEntry* = self._get_field_entry(mod_entry_q, rn_alias_q) if rn_fe_q is not None and rn_fe_q.Ty is not None: @@ -1585,22 +1485,19 @@ novirtual class StructGenMixin: # FieldCount==0 的 stub 空类(vpi 注入不含字段 / 定义侧模块未编译注册)→ # 返回 None 让上层标记 _deps_pending 下遍重译(源模块编译后真实定义覆盖 # stub)。SECURITY_ATTRIBUTES FieldCount=0 根因(subprocess.vp sa.nLength)。 - if entry.FieldCount == 0 and sha1 is not None: - return None + if entry.FieldCount == 0 and sha1 is not None: return None # 先查找字段(诊断/error 之前返回,否则 error 立即退出导致查找永远失败) for fi in range(entry.FieldCount): fe: GenTypes.FieldEntry* = self._get_field_entry(entry, fi) if fe is not None and fe.Name is not None: - if string.strcmp(fe.Name, field_name) == 0: - return fe + if string.strcmp(fe.Name, field_name) == 0: return fe # REnum 变体字段别名回退:REnum 类(如 LLVMType)的变体内部字段(Ptr.Pointee # 等)不是普通字段,而是 _p1/_p2 槽位别名。若留给调用方回退,本函数字段未找到 # 时的 fatal 会先 sys.exit(1),调用方回退永远执行不到,故此处直接查变体别名。 # 注意:_lookup_renum_field_alias 用 class_name 指针值比较,必须传 entry.Name # (register_struct 复制 + _update_renum_alias_class_ptr 统一后的池指针)。 rn_cls_l: str = entry.Name - if rn_cls_l is None: - rn_cls_l = class_name + if rn_cls_l is None: rn_cls_l = class_name rn_is_renum_l: int = self.Gen.ClassGenEnum._is_renum_class_name(class_name) if rn_is_renum_l == 0 and rn_cls_l is not None: # 类名可能是模块限定名("mod.LLVMType"),REnum 表存裸名,双保险 @@ -1614,8 +1511,7 @@ novirtual class StructGenMixin: rn_alias_l = self.Gen.ClassGenEnum._lookup_renum_field_alias(class_name, field_name) if rn_alias_l >= 1: rn_fe_l: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(entry, rn_alias_l) - if rn_fe_l is not None and rn_fe_l.Ty is not None: - return rn_fe_l + if rn_fe_l is not None and rn_fe_l.Ty is not None: return rn_fe_l # 诊断:找到结构体但字段确实未找到 # 拼接注册字段列表(一行逗号分隔,供报错一眼定位) fb_flds_lst: str = stdlib.malloc(1024) @@ -1624,10 +1520,8 @@ novirtual class StructGenMixin: for fi in range(entry.FieldCount): fe: GenTypes.FieldEntry* = self._get_field_entry(entry, fi) if fe is not None and fe.Name is not None: - if string.strlen(fb_flds_lst) > 0 and string.strlen(fb_flds_lst) + 3 < 1024: - string.strcat(fb_flds_lst, ", ") - if string.strlen(fb_flds_lst) + string.strlen(fe.Name) < 1024: - string.strcat(fb_flds_lst, fe.Name) + if string.strlen(fb_flds_lst) > 0 and string.strlen(fb_flds_lst) + 3 < 1024: string.strcat(fb_flds_lst, ", ") + if string.strlen(fb_flds_lst) + string.strlen(fe.Name) < 1024: string.strcat(fb_flds_lst, fe.Name) err: str if rn_is_renum_l != 0: # 报错友好化:REnum 类直接说明是"变体字段别名查找失败",并附 @@ -1639,53 +1533,42 @@ novirtual class StructGenMixin: # 列表 + 期望 sha1(调用方)→ 一眼分辨"跨模块同名类误匹配" # vs "vpi stub 注入字段不全" vs "类定义与访问处不一致" sha1_txt: str = "?" - if entry.ModuleSha1 is not None: - sha1_txt = entry.ModuleSha1 + if entry.ModuleSha1 is not None: sha1_txt = entry.ModuleSha1 want_sha1_txt: str = "?" - if sha1 is not None: - want_sha1_txt = sha1 + if sha1 is not None: want_sha1_txt = sha1 fld_lst_txt: str = "(无)" - if fb_flds_lst is not None and string.strlen(fb_flds_lst) > 0: - fld_lst_txt = fb_flds_lst + 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 注入字段不全 / 类定义与访问处不一致" # 仿 Python traceback 格式输出(Traceback 帧 + 文件:行号 + 错误类型), # 立即终止编译(与 VLogger.error 同语义,格式对齐 fatal_error) self.Gen.TypeGenErr.fatal_error(node, err, "AttributeError") - if fb_flds_lst is not None: - stdlib.free(fb_flds_lst) + if fb_flds_lst is not None: stdlib.free(fb_flds_lst) # 诊断:找到结构体但字段未找到 return None def get_struct_type(self, class_name: str) -> mlirlite.LLVMType*: """按类名获取结构体的 LLVM 类型""" entry: GenTypes.StructEntry* = self.find_struct(class_name) - if entry is not None: - return entry.Ty + if entry is not None: return entry.Ty return None def get_field_by_index(self, class_name: str, idx: int) -> GenTypes.FieldEntry*: """按类名和字段索引获取字段信息""" - if class_name is None: - return None + if class_name is None: return None entry: GenTypes.StructEntry* = self.find_struct(class_name) - if entry is None: - return None - if idx < 0 or idx >= entry.FieldCount: - return None + if entry is None: return None + if idx < 0 or idx >= entry.FieldCount: return None return self._get_field_entry(entry, idx) def struct_has_defaults(self, class_name: str) -> int: """检查结构体是否有任何带默认值的字段,返回 1=有 / 0=无""" - if class_name is None: - return 0 + if class_name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(class_name) - if entry is None: - return 0 + if entry is None: return 0 for fi in range(entry.FieldCount): fe: GenTypes.FieldEntry* = self._get_field_entry(entry, fi) - if fe is not None and fe.DefaultVal is not None: - return 1 + if fe is not None and fe.DefaultVal is not None: return 1 return 0 def get_struct_type_from_value(self, val: mlirlite.Value*) -> mlirlite.LLVMType*: @@ -1696,8 +1579,7 @@ novirtual class StructGenMixin: 重载识别失败回退原生运算,对指针生成非法 sub 指令(llc: invalid operand type for instruction)。 """ - if val is None or val.Ty is None: - return None + if val is None or val.Ty is None: return None ty: mlirlite.LLVMType* = val.Ty while ty is not None: # 同类编译 bug(见 TypeGenResolve L1463 注释):case body 直接 @@ -1717,21 +1599,17 @@ novirtual class StructGenMixin: def mark_as_union(self, name: str) -> int: """标记已注册的结构体为联合体,返回 1=成功 / 0=失败""" - if name is None: - return 0 + if name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return 0 + if entry is None: return 0 entry.IsUnion = 1 return 1 def is_union_by_name(self, name: str) -> int: """按类名检查是否为联合体,返回 1=是 / 0=否""" - if name is None: - return 0 + if name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return 0 + if entry is None: return 0 return entry.IsUnion def is_union_by_type(self, struct_ty: mlirlite.LLVMType*) -> int: @@ -1739,92 +1617,73 @@ novirtual class StructGenMixin: 先尝试类型指针 == 比较,失败时回退到名称匹配 """ - if struct_ty is None or self.StructTable is None: - return 0 + if struct_ty is None or self.StructTable is None: return 0 ty_name: str = self._extract_struct_name(struct_ty) st_iu: uint64 = uint64(struct_ty) for i in range(self.StructCount): entry: GenTypes.StructEntry* = self._get_struct_entry(i) if entry is not None and entry.Ty is not None: matched: int = 0 - if uint64(entry.Ty) == st_iu: - matched = 1 + if uint64(entry.Ty) == st_iu: matched = 1 elif ty_name is not None and entry.Name is not None: - if string.strcmp(entry.Name, ty_name) == 0: - matched = 1 - elif string.strstr(ty_name, entry.Name) is not None: - matched = 1 - if matched != 0: - return entry.IsUnion + if string.strcmp(entry.Name, ty_name) == 0: matched = 1 + elif string.strstr(ty_name, entry.Name) is not None: matched = 1 + if matched != 0: return entry.IsUnion return 0 def mark_as_oop(self, name: str) -> int: """标记已注册的结构体为 OOP,返回 1=成功 / 0=失败""" - if name is None: - return 0 + if name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return 0 + if entry is None: return 0 entry.IsOOP = 1 return 1 def is_oop_by_name(self, name: str) -> int: """按类名检查是否为 OOP 结构体,返回 1=是 / 0=否""" - if name is None: - return 0 + if name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return 0 + if entry is None: return 0 return entry.IsOOP def mark_has_init(self, name: str) -> int: """标记结构体拥有 __init__ 方法,返回 1=成功 / 0=失败""" - if name is None: - return 0 + if name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return 0 + if entry is None: return 0 entry.HasInit = 1 return 1 def has_init_by_name(self, name: str) -> int: """按类名检查是否有 __init__ 方法,返回 1=有 / 0=无""" - if name is None: - return 0 + if name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return 0 + if entry is None: return 0 return entry.HasInit def mark_has_new(self, name: str) -> int: """标记结构体拥有 __new__ 方法,返回 1=成功 / 0=失败""" - if name is None: - return 0 + if name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return 0 + if entry is None: return 0 entry.HasNew = 1 return 1 def has_new_by_name(self, name: str) -> int: """按类名检查是否有 __new__ 方法,返回 1=有 / 0=无""" - if name is None: - return 0 + if name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return 0 + if entry is None: return 0 return entry.HasNew def get_class_name_by_type(self, pool: memhub.MemBuddy*, struct_ty: mlirlite.LLVMType*) -> str: """按类型指针查找类名,返回类名字符串或 None""" - if struct_ty is None or self.StructTable is None: - return None + if struct_ty is None or self.StructTable is None: return None # find_struct_by_type 的语义 = 原扫描"首个 Ty 指针相等条目"(首注册优先), # 返回其 Name;其 Ty 索引判定已整体停用、恢复原线性扫描 ⇒ 逐字节一致。 fast_cn: GenTypes.StructEntry* = self.find_struct_by_type(struct_ty) - if fast_cn is not None: - return fast_cn.Name + if fast_cn is not None: return fast_cn.Name # 回退: 类型指针比较失败时,遍历所有注册的结构体按名称匹配 # 提取 struct_ty 的 Name 字段(可能是 "SHA1.ClassName" 格式) ty_name: str = self._extract_struct_name(struct_ty) @@ -1838,11 +1697,9 @@ novirtual class StructGenMixin: full_nm: str = pool.alloc(128) if full_nm is not None: viperlib.snprintf(full_nm, 128, "%s.%s", entry2_sha1, entry2.Name) - if string.strcmp(full_nm, ty_name) == 0: - return entry2.Name + if string.strcmp(full_nm, ty_name) == 0: return entry2.Name # 也直接比较类名(struct_ty 的 Name 可能无 SHA1 前缀) - if string.strcmp(entry2.Name, ty_name) == 0: - return entry2.Name + if string.strcmp(entry2.Name, ty_name) == 0: return entry2.Name # 最后回退: 后缀匹配("SHA1.ClassName" 尾部)——比 strstr 子串 # 匹配安全:特化名 "SHA1.GSList[Param]" 会被基础名 "GSList" 错误 # 命中(子串),导致链式方法调用 class_name 解析错(如 @@ -1859,14 +1716,12 @@ novirtual class StructGenMixin: if ty_name[_tlen_cn - _nlen_cn + _ti_cn] != entry2.Name[_ti_cn]: _tail_ok_cn = 0 break - if _tail_ok_cn == 1: - return entry2.Name + if _tail_ok_cn == 1: return entry2.Name return None def _extract_struct_name(self, ty: mlirlite.LLVMType*) -> str: """从 LLVMType 提取 Struct 变体的 Name 字段,返回 None 非 Struct""" - if ty is None: - return None + if ty is None: return None match ty: case mlirlite.LLVMType.Struct(fields, fcount, name): return name @@ -1875,49 +1730,39 @@ novirtual class StructGenMixin: def mark_has_vtable(self, name: str) -> int: """标记结构体拥有虚表,返回 1=成功 / 0=失败""" - if name is None: - return 0 + if name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return 0 + if entry is None: return 0 entry.HasVTable = 1 return 1 def has_vtable_by_name(self, name: str) -> int: """按类名检查是否有虚表,返回 1=有 / 0=无""" - if name is None: - return 0 + if name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return 0 + if entry is None: return 0 return entry.HasVTable def mark_novtable(self, name: str) -> int: """标记结构体为 NoVTable,返回 1=成功 / 0=失败""" - if name is None: - return 0 + if name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return 0 + if entry is None: return 0 entry.IsNoVTable = 1 return 1 def is_novtable_by_name(self, name: str) -> int: """按类名检查是否为 NoVTable,返回 1=是 / 0=否""" - if name is None: - return 0 + if name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return 0 + if entry is None: return 0 return entry.IsNoVTable def set_parent_name(self, name: str, parent_name: str) -> int: """设置结构体的父类名,返回 1=成功 / 0=失败""" - if name is None: - return 0 + if name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return 0 + if entry is None: return 0 entry.ParentName = parent_name return 1 @@ -1925,25 +1770,20 @@ novirtual class StructGenMixin: name: str, names_ptr: sizet*, count: int) -> int: """设置结构体的父类名数组(永久池深拷贝,跨文件永久存活)""" - if name is None: - return 0 + if name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return 0 + if entry is None: return 0 if names_ptr is None or count <= 0: entry.ParentNames = None entry.ParentCount = 0 return 1 - if count > PARENT_MAX: - count = PARENT_MAX + if count > PARENT_MAX: count = PARENT_MAX pn_pool: memhub.MemBuddy* = pool if self.StdlibAlloc != 0: pn_pool = CompilerFactory.factory.PermPool - if pn_pool is None: - pn_pool = pool + if pn_pool is None: pn_pool = pool arr: sizet* = pn_pool.alloc(8 * count) - if arr is None: - return 0 + if arr is None: return 0 for i in range(count): addr: sizet = names_ptr[i] arr[i] = 0 @@ -1961,42 +1801,32 @@ novirtual class StructGenMixin: def get_parent_count(self, name: str) -> int: """获取父类数量(0=无父类,1=单继承,>1=多继承)""" - if name is None: - return 0 + if name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return 0 + if entry is None: return 0 return entry.ParentCount def get_parent_name_at(self, name: str, idx: int) -> str: """获取第 idx 个父类名,越界返回 None""" - if name is None or idx < 0: - return None + if name is None or idx < 0: return None entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None or entry.ParentNames is None: - return None - if idx >= entry.ParentCount: - return None + if entry is None or entry.ParentNames is None: return None + if idx >= entry.ParentCount: return None parr: sizet* = (sizet*)(entry.ParentNames) addr: sizet = parr[idx] - if addr == 0: - return None + if addr == 0: return None return rawptr(addr) def get_mro_chain(self, pool: memhub.MemBuddy*, name: str) -> sizet*: """MRO 线性化类名数组(深度优先 + 声明顺序 + 去重,含自身)""" - if pool is None or name is None: - return None + if pool is None or name is None: return None arr: sizet* = pool.alloc(8 * (MRO_MAX + 1)) - if arr is None: - return None + if arr is None: return None stack: sizet* = pool.alloc(8 * MRO_MAX) - if stack is None: - return None + if stack is None: return None visited: sizet* = pool.alloc(8 * MRO_MAX) - if visited is None: - return None + if visited is None: return None stack_count: int = 0 out_count: int = 0 visit_count: int = 0 @@ -2007,8 +1837,7 @@ novirtual class StructGenMixin: stack_count -= 1 cur_addr: sizet = stack[stack_count] cur: str = rawptr(cur_addr) - if cur is None: - continue + if cur is None: continue # 已访问检查(线性搜索) dup: int = 0 for vi in range(visit_count): @@ -2018,8 +1847,7 @@ novirtual class StructGenMixin: if vn is not None and string.strcmp(vn, cur) == 0: dup = 1 break - if dup != 0: - continue + if dup != 0: continue # 加入结果与已访问集合 if out_count < MRO_MAX: arr[out_count] = sizet(cur) @@ -2043,74 +1871,58 @@ novirtual class StructGenMixin: def get_parent_name(self, name: str) -> str: """获取结构体的父类名,返回 None=无父类""" - if name is None: - return None + if name is None: return None entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return None + if entry is None: return None return entry.ParentName def set_vtable_methods(self, name: str, methods: str, count: int) -> int: """设置虚表方法名数组,返回 1=成功 / 0=失败""" - if name is None: - return 0 + if name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return 0 + if entry is None: return 0 entry.VTableMethods = methods entry.VTableMethodCount = count return 1 def get_vtable_method_index(self, name: str, method_name: str) -> int: """获取方法在虚表中的索引,返回 -1=未找到""" - if name is None or method_name is None: - return -1 + if name is None or method_name is None: return -1 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None or entry.VTableMethods is None: - return -1 + if entry is None or entry.VTableMethods is None: return -1 # VTableMethods 字段声明为 char*,但实际存储的是 sizet 数组 # 必须转换为 sizet* 才能正确读取 8 字节指针值 methods_arr: sizet* = (sizet*)(entry.VTableMethods) for i in range(entry.VTableMethodCount): mname_addr: sizet = methods_arr[i] - if mname_addr == 0: - continue + if mname_addr == 0: continue mname: str = rawptr(mname_addr) - if mname is not None and string.strcmp(mname, method_name) == 0: - return i + if mname is not None and string.strcmp(mname, method_name) == 0: return i return -1 def get_vtable_method_count(self, name: str) -> int: """获取虚表方法数量""" - if name is None: - return 0 + if name is None: return 0 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return 0 + if entry is None: return 0 return entry.VTableMethodCount def get_vtable_method_name(self, name: str, idx: int) -> str: """获取虚表中第 idx 个方法名,返回 None=越界""" - if name is None or idx < 0: - return None + if name is None or idx < 0: return None entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None or entry.VTableMethods is None: - return None - if idx >= entry.VTableMethodCount: - return None + if entry is None or entry.VTableMethods is None: return None + if idx >= entry.VTableMethodCount: return None methods_arr: sizet* = (sizet*)(entry.VTableMethods) mname_addr: sizet = methods_arr[idx] - if mname_addr == 0: - return None + if mname_addr == 0: return None return rawptr(mname_addr) def get_field_count(self, name: str) -> int: """获取结构体字段数量,返回 -1=未找到""" - if name is None: - return -1 + if name is None: return -1 entry: GenTypes.StructEntry* = self.find_struct(name) - if entry is None: - return -1 + if entry is None: return -1 return entry.FieldCount def ensure_struct_def_in_module(self, pool: memhub.MemBuddy*, @@ -2122,23 +1934,20 @@ novirtual class StructGenMixin: 1. Struct 值类型:需要完整定义(供 alloca 分配空间) 2. Ptr(Struct) 指针类型:需要 pointee 至少有 opaque 声明 """ - if ty is None or mod is None or pool is None: - return + if ty is None or mod is None or pool is None: return # 指针类型:确保 pointee 至少有 opaque 声明 match ty: case mlirlite.LLVMType.Ptr(pointee): mlirlite.module_ensure_opaque_for_type(mod, pool, ty) # 如果 pointee 是 Struct,递归复制完整定义 # (GEP 访问字段需要 sized 类型,仅 opaque 会导致 llc 报错) - if pointee is not None: - self.ensure_struct_def_in_module(pool, mod, pointee) + if pointee is not None: self.ensure_struct_def_in_module(pool, mod, pointee) return case _: pass # 获取结构体名称(非 Struct 类型返回 None) sname: str = mlirlite.get_struct_name(ty) - if sname is None: - return + if sname is None: return # 检查是否为跨模块引用(名称包含 '.') if string.strchr(sname, 46) is None: return # 非跨模块引用,无需处理 @@ -2146,23 +1955,19 @@ novirtual class StructGenMixin: # 必须用 strchr 而非 strrchr:泛型特化名如 "list[ast.AST*]" # 内部含 '.'(ast.AST),strrchr 会错误地把类名解析为 "AST*]" dot_pos: str = string.strchr(sname, '.') - if dot_pos is None: - return + if dot_pos is None: return class_name: str = dot_pos + 1 - if class_name is None or class_name[0] == '\0': - return + if class_name is None or class_name[0] == '\0': return # 提取 SHA1(sname 到 dot_pos 之间,用 strlen 避免指针减法) total_len: sizet = string.strlen(sname) class_name_len: sizet = string.strlen(class_name) sha1_len: sizet = total_len - class_name_len - 1 sha1_buf: str = pool.alloc_tagged(32, memhub.DETSITE_STRUCTGENMIXIN_1804) - if sha1_buf is None: - return + if sha1_buf is None: return # 32 字节缓冲:strncpy 不截断,前缀超过 31 字符会越界写 + 手动 NUL 再越界 sha1_cp: sizet = sha1_len - if sha1_cp > 31: - sha1_cp = 31 + if sha1_cp > 31: sha1_cp = 31 string.strncpy(sha1_buf, sname, sha1_cp) sha1_buf[sha1_cp] = '\0' # 按类名 + SHA1 查找结构体定义 @@ -2170,17 +1975,14 @@ novirtual class StructGenMixin: if entry is None: # 回退到按类名查找(可能找到不同模块的同名类,但总比没有好) entry = self.find_struct(class_name) - if entry is None: - return - if entry.Ty is None: - return + if entry is None: return + if entry.Ty is None: return # 将完整定义添加到当前模块(会替换已存在的 opaque 声明) mlirlite.module_add_named_type(mod, pool, entry.Ty) # B5:跨模块注入的 packed 类必须同步 packed 标记(<{...}>),否则引用 # 模块按非 packed 布局 GEP,与定义侧 packed 布局错位(gdt/elf/fat32 # 二进制格式字段错读;合并 IR 中 idt_entry/gdt_entry 退化 {…} 根因)。 - if entry.IsPacked != 0: - mlirlite.module_set_named_type_packed(mod, pool, entry.Ty, 1) + if entry.IsPacked != 0: mlirlite.module_set_named_type_packed(mod, pool, entry.Ty, 1) # 递归扫描字段类型,确保值类型子结构体(如 WIN32_FIND_DATAA 中的 FILETIME) # 也有完整定义。指针类型字段只需 opaque 声明(已由 module_ensure_opaque_for_type 处理)。 self._ensure_field_types_in_module(pool, mod, entry.Ty) @@ -2189,8 +1991,7 @@ novirtual class StructGenMixin: mod: mlirlite.LLVMModule*, ty: mlirlite.LLVMType*): """递归扫描类型树,确保值类型子结构体有完整定义""" - if ty is None or mod is None or pool is None: - return + if ty is None or mod is None or pool is None: return # 嵌套 match 遍历类型树 match ty: case mlirlite.LLVMType.Struct(fields, fcount, sname): @@ -2217,8 +2018,7 @@ novirtual class StructGenMixin: case mlirlite.LLVMType.Ptr(pointee): # 指针类型:pointee 只需 opaque 声明,不需要完整定义 # 但如果 pointee 是 Struct,确保 opaque 声明存在 - if pointee is not None: - mlirlite.module_ensure_opaque_for_type(mod, pool, ty) + if pointee is not None: mlirlite.module_ensure_opaque_for_type(mod, pool, ty) case mlirlite.LLVMType.Array(elem_ty, acount): # 数组类型:元素如果是值类型结构体,需要完整定义(Array 元素只递归 # 字段不发射定义 → llc "use of undefined type named '...'")。 @@ -2234,20 +2034,17 @@ novirtual class StructGenMixin: def get_field_name_ptr(self, fe: GenTypes.FieldEntry*) -> str: """获取 FieldEntry 的字段名,返回 None=未设置""" - if fe is None: - return None + if fe is None: return None return fe.Name def get_field_type_ptr(self, fe: GenTypes.FieldEntry*) -> mlirlite.LLVMType*: """获取 FieldEntry 的字段类型,返回 None=未设置""" - if fe is None: - return None + if fe is None: return None return fe.Ty def get_field_default_ptr(self, fe: GenTypes.FieldEntry*) -> ast.AST*: """获取 FieldEntry 的默认值 AST 节点,返回 None=无默认值""" - if fe is None: - return None + if fe is None: return None return fe.DefaultVal def get_field_annot_class_name(self, fe: GenTypes.FieldEntry*) -> str: @@ -2256,8 +2053,7 @@ novirtual class StructGenMixin: [S4] 原 FieldEntry.AnnotClassName 字段已删除,注解名承载在 Spec.SourceName (由 add_field 经 SpecWithSource 写入)。 """ - if fe is None: - return None + if fe is None: return None return TSpec.SpecSourceName(fe.Spec) def field_is_volatile(self, fe: GenTypes.FieldEntry*) -> int: @@ -2266,8 +2062,7 @@ novirtual class StructGenMixin: 由 ClassGenDef 收集字段注解时检测 t.CVolatile 写入;消费点(成员读写的 load/store)据此加 LLVM volatile 限定符。 """ - if fe is None: - return 0 + if fe is None: return 0 return fe.IsVolatile def field_pointee_is_volatile(self, fe: GenTypes.FieldEntry*) -> int: @@ -2277,8 +2072,7 @@ novirtual class StructGenMixin: 写入;消费点(经该字段解引用 self.ptr[i] / self.ptr.field 的 load/store) 据此加 LLVM volatile 限定符。 """ - if fe is None: - return 0 + if fe is None: return 0 return fe.PointeeVolatile def field_is_const(self, fe: GenTypes.FieldEntry*) -> int: @@ -2287,6 +2081,5 @@ novirtual class StructGenMixin: 字段注解含 t.CConst 且字段类型非指针时由 ClassGenDef 写入;消费点 (obj.f = ... / self.f = ... 的字段赋值)据此 fail-fast。 """ - if fe is None: - return 0 + if fe is None: return 0 return fe.IsConst diff --git a/App/lib/core/Gen/Translator.vp b/App/lib/core/Gen/Translator.vp index 27c2d64..b4954c5 100644 --- a/App/lib/core/Gen/Translator.vp +++ b/App/lib/core/Gen/Translator.vp @@ -380,76 +380,60 @@ novirtual class Translator: def _init_state(self, pool: memhub.MemBuddy*): """初始化变量表、函数表和子 Handle""" self.Pool = pool - if self._funcs is None: - self._funcs = GenApi.init_func_table(pool, MAX_FUNCS) + if self._funcs is None: self._funcs = GenApi.init_func_table(pool, MAX_FUNCS) # 嵌套作用域符号表(新版) - if self.SymTab is None: - self.SymTab = GenApi.init_symbol_table(pool) + if self.SymTab is None: self.SymTab = GenApi.init_symbol_table(pool) # global/nonlocal 名称集合缓冲区(MAX_GLOBAL_NAMES 个 char* 指针 = 128*8 字节) if self._global_names is None: self._global_names = stdlib.malloc(MAX_GLOBAL_NAMES * 8) - if self._global_names is not None: - string.memset(self._global_names, 0, MAX_GLOBAL_NAMES * 8) + if self._global_names is not None: string.memset(self._global_names, 0, MAX_GLOBAL_NAMES * 8) self._global_name_count = 0 if self._nonlocal_names is None: self._nonlocal_names = stdlib.malloc(MAX_GLOBAL_NAMES * 8) - if self._nonlocal_names is not None: - string.memset(self._nonlocal_names, 0, MAX_GLOBAL_NAMES * 8) + if self._nonlocal_names is not None: string.memset(self._nonlocal_names, 0, MAX_GLOBAL_NAMES * 8) self._nonlocal_name_count = 0 # nonlocal 变量类型数组(LLVMType 指针数组,与 _nonlocal_names 一一对应) if self._nonlocal_types is None: self._nonlocal_types = stdlib.malloc(MAX_GLOBAL_NAMES * 8) - if self._nonlocal_types is not None: - string.memset(self._nonlocal_types, 0, MAX_GLOBAL_NAMES * 8) + if self._nonlocal_types is not None: string.memset(self._nonlocal_types, 0, MAX_GLOBAL_NAMES * 8) # 协程表(TPV-M1):async 函数名 / 变量→async 映射 / 局部名 / 帧类型 if self._async_funcs is None: self._async_funcs = stdlib.malloc(MAX_CORO_FUNCS * 8) - if self._async_funcs is not None: - string.memset(self._async_funcs, 0, MAX_CORO_FUNCS * 8) + if self._async_funcs is not None: string.memset(self._async_funcs, 0, MAX_CORO_FUNCS * 8) self._async_func_count = 0 if self._coro_var_async is None: self._coro_var_async = stdlib.malloc(MAX_CORO_VARS * 16) - if self._coro_var_async is not None: - string.memset(self._coro_var_async, 0, MAX_CORO_VARS * 16) + if self._coro_var_async is not None: string.memset(self._coro_var_async, 0, MAX_CORO_VARS * 16) self._coro_var_async_count = 0 if self._coro_locals is None: self._coro_locals = stdlib.malloc(MAX_CORO_VARS * 8) - if self._coro_locals is not None: - string.memset(self._coro_locals, 0, MAX_CORO_VARS * 8) + if self._coro_locals is not None: string.memset(self._coro_locals, 0, MAX_CORO_VARS * 8) if self._coro_params is None: self._coro_params = stdlib.malloc(MAX_CORO_VARS * 8) - if self._coro_params is not None: - string.memset(self._coro_params, 0, MAX_CORO_VARS * 8) + if self._coro_params is not None: string.memset(self._coro_params, 0, MAX_CORO_VARS * 8) if self._coro_try_stack is None: self._coro_try_stack = stdlib.malloc(MAX_CORO_TRY * 8) - if self._coro_try_stack is not None: - string.memset(self._coro_try_stack, 0, MAX_CORO_TRY * 8) + if self._coro_try_stack is not None: string.memset(self._coro_try_stack, 0, MAX_CORO_TRY * 8) if self._coro_extra_types is None: self._coro_extra_types = stdlib.malloc(MAX_CORO_VARS) - if self._coro_extra_types is not None: - string.memset(self._coro_extra_types, 0, MAX_CORO_VARS) + if self._coro_extra_types is not None: string.memset(self._coro_extra_types, 0, MAX_CORO_VARS) if self._coro_await_slots is None: self._coro_await_slots = stdlib.malloc(MAX_CORO_VARS * 4) - if self._coro_await_slots is not None: - string.memset(self._coro_await_slots, 0, MAX_CORO_VARS * 4) + if self._coro_await_slots is not None: string.memset(self._coro_await_slots, 0, MAX_CORO_VARS * 4) if self._coro_for_slots is None: self._coro_for_slots = stdlib.malloc(MAX_CORO_VARS * 4) - if self._coro_for_slots is not None: - string.memset(self._coro_for_slots, 0, MAX_CORO_VARS * 4) + if self._coro_for_slots is not None: string.memset(self._coro_for_slots, 0, MAX_CORO_VARS * 4) if self._coro_wake_names is None: self._coro_wake_names = stdlib.malloc(MAX_CORO_FUNCS * 8) - if self._coro_wake_names is not None: - string.memset(self._coro_wake_names, 0, MAX_CORO_FUNCS * 8) + if self._coro_wake_names is not None: string.memset(self._coro_wake_names, 0, MAX_CORO_FUNCS * 8) if self._coro_wake_idxs is None: self._coro_wake_idxs = stdlib.malloc(MAX_CORO_FUNCS * 4) - if self._coro_wake_idxs is not None: - string.memset(self._coro_wake_idxs, 0, MAX_CORO_FUNCS * 4) + if self._coro_wake_idxs is not None: string.memset(self._coro_wake_idxs, 0, MAX_CORO_FUNCS * 4) self._coro_local_count = 0 if self._coro_frames is None: self._coro_frames = stdlib.malloc(MAX_CORO_FUNCS * 16) - if self._coro_frames is not None: - string.memset(self._coro_frames, 0, MAX_CORO_FUNCS * 16) + if self._coro_frames is not None: string.memset(self._coro_frames, 0, MAX_CORO_FUNCS * 16) self._coro_frame_count = 0 # ============================================================ @@ -457,10 +441,8 @@ novirtual class Translator: # ============================================================ def translate(self, tree: ast.AST*) -> int: """将 AST 翻译为 LLVM IR""" - if tree is None: - return 1 - if _mbuddy is None: - return 1 + if tree is None: return 1 + if _mbuddy is None: return 1 pool: memhub.MemBuddy* = _mbuddy @@ -484,13 +466,11 @@ novirtual class Translator: # 设置目标(优先使用 project.vpj / viperbuild 中的配置) triple: str = Config.TargetTriple - if triple is None: - triple = "x86_64-pc-windows-msvc" + if triple is None: triple = "x86_64-pc-windows-msvc" mlirlite.module_set_target(mod, triple) # 数据布局:project.vpj / viperbuild 的 target.datalayout(None 时不输出该行)。 # 写入 .ll 模块头,使生成的 IR 自带 LLVM 布局信息,与目标 triple 配套。 - if Config.TargetDataLayout is not None: - mlirlite.module_set_datalayout(mod, Config.TargetDataLayout) + if Config.TargetDataLayout is not None: mlirlite.module_set_datalayout(mod, Config.TargetDataLayout) # 类型 i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) @@ -509,11 +489,9 @@ novirtual class Translator: # declare void @llvm.va_end(i8*) void_ty_decl: mlirlite.LLVMType* = mlirlite.Void(pool) va_start_func: mlirlite.Function* = mlirlite.create_declare(pool, mod, "llvm.va_start", void_ty_decl) - if va_start_func is not None: - mlirlite.add_param(pool, va_start_func, i8_ptr_ty, "ap") + if va_start_func is not None: mlirlite.add_param(pool, va_start_func, i8_ptr_ty, "ap") va_end_func: mlirlite.Function* = mlirlite.create_declare(pool, mod, "llvm.va_end", void_ty_decl) - if va_end_func is not None: - mlirlite.add_param(pool, va_end_func, i8_ptr_ty, "ap") + if va_end_func is not None: mlirlite.add_param(pool, va_end_func, i8_ptr_ty, "ap") # 声明 malloc(闭包分配用) malloc_func: mlirlite.Function* = mlirlite.create_declare(pool, mod, "malloc", i8_ptr_ty) @@ -615,8 +593,7 @@ novirtual class Translator: cn_count: sizet = len(ch) for ci in range(cn_count): child: ast.AST* = ch.get(ci) - if child is None: - continue + if child is None: continue kd: int = child.kind() if kd == ast.ASTKind.Import: cur_imp_lineno = child.lineno @@ -661,11 +638,9 @@ novirtual class Translator: if ch is not None: for ci in range(cn_count): child: ast.AST* = ch.get(ci) - if child is None: - continue + if child is None: continue kd_mv: int = child.kind() - if kd_mv == ast.ASTKind.AnnAssign or kd_mv == ast.ASTKind.Assign: - GenApi.handle_module_level_var(self, child) + if kd_mv == ast.ASTKind.AnnAssign or kd_mv == ast.ASTKind.Assign: GenApi.handle_module_level_var(self, child) # 创建前向声明 GenApi.forward_declare_functions(self, tree) added: int = GenApi.translate_children(self, tree) @@ -684,137 +659,102 @@ novirtual class Translator: # ============================================================ def _vb_in_proj_vars(self, name: str, proj_vars: list[str]*) -> int: """name 是否为已登记的 Project 宏变量;1=是""" - if name is None or proj_vars is None: - return 0 + if name is None or proj_vars is None: return 0 n: sizet = len(proj_vars) i: sizet = 0 while i < n: s: str = proj_vars.get(i) - if s is not None and string.strcmp(s, name) == 0: - return 1 + if s is not None and string.strcmp(s, name) == 0: return 1 i += 1 return 0 def _vb_is_project_ctor(self, value: ast.AST*, alias: str, ctor: str) -> int: """value 是否为 `vb.Project(...)` / `Project(...)`;1=是""" - if value is None or value.kind() != ast.ASTKind.Call: - return 0 + if value is None or value.kind() != ast.ASTKind.Call: return 0 cl: ast.Call* = ast.Call*(value) - if cl is None or cl.func is None: - return 0 + if cl is None or cl.func is None: return 0 fk: int = cl.func.kind() if fk == ast.ASTKind.Attribute: - if alias is None: - return 0 + if alias is None: 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: - return 0 + if at is None or at.attr is None or at.value is None: return 0 + if at.value.kind() != ast.ASTKind.Name: return 0 bn: ast.Name* = ast.Name*(at.value) - if bn is None or bn.id is None: - return 0 - if string.strcmp(bn.id, alias) != 0: - return 0 - if string.strcmp(at.attr, "Project") == 0: - return 1 + if bn is None or bn.id is None: return 0 + if string.strcmp(bn.id, alias) != 0: return 0 + if string.strcmp(at.attr, "Project") == 0: return 1 return 0 if fk == ast.ASTKind.Name: - if ctor is None: - return 0 + if ctor is None: return 0 nm: ast.Name* = ast.Name*(cl.func) - if nm is None or nm.id is None: - return 0 - if string.strcmp(nm.id, ctor) == 0: - return 1 + if nm is None or nm.id is None: return 0 + if string.strcmp(nm.id, ctor) == 0: return 1 return 0 def _vb_is_macro_assign(self, target: ast.AST*, value: ast.AST*, alias: str, ctor: str, proj_vars: list[str]*) -> int: """赋值是否为 viperbuild 宏语句(Project 绑定 / 字段赋值);1=是且已登记""" - if target is None or value is None: - return 0 + if target is None or value is None: return 0 tk: int = target.kind() if tk == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(target) - if nm is None or nm.id is None: - return 0 + if nm is None or nm.id is None: return 0 if self._vb_is_project_ctor(value, alias, ctor) != 0: proj_vars.append(nm.id) return 1 return 0 if tk == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(target) - if at is None or at.value is None: - return 0 - if at.value.kind() != ast.ASTKind.Name: - return 0 + if at is None or at.value is None: return 0 + if at.value.kind() != ast.ASTKind.Name: return 0 bn: ast.Name* = ast.Name*(at.value) - if bn is None or bn.id is None: - return 0 - if self._vb_in_proj_vars(bn.id, proj_vars) != 0: - return 1 + if bn is None or bn.id is None: return 0 + if self._vb_in_proj_vars(bn.id, proj_vars) != 0: return 1 return 0 def _vb_is_macro_call(self, value: ast.AST*, proj_vars: list[str]*) -> int: """表达式是否为 `proj.config(...)` / `proj.build(...)`;1=是""" - if value is None or value.kind() != ast.ASTKind.Call: - return 0 + if value is None or value.kind() != ast.ASTKind.Call: return 0 cl: ast.Call* = ast.Call*(value) - if cl is None or cl.func is None: - return 0 - if cl.func.kind() != ast.ASTKind.Attribute: - return 0 + if cl is None or cl.func is None: return 0 + if cl.func.kind() != ast.ASTKind.Attribute: 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: - return 0 + if at is None or at.attr is None or at.value is None: return 0 + if at.value.kind() != ast.ASTKind.Name: return 0 bn: ast.Name* = ast.Name*(at.value) - if bn is None or bn.id is None: - return 0 - if self._vb_in_proj_vars(bn.id, proj_vars) == 0: - return 0 - if string.strcmp(at.attr, "config") == 0: - return 1 - if string.strcmp(at.attr, "build") == 0: - return 1 + if bn is None or bn.id is None: return 0 + if self._vb_in_proj_vars(bn.id, proj_vars) == 0: return 0 + if string.strcmp(at.attr, "config") == 0: return 1 + if string.strcmp(at.attr, "build") == 0: return 1 return 0 def _vb_is_macro_stmt(self, child: ast.AST*, alias: str, ctor: str, proj_vars: list[str]*) -> int: """单条模块级语句是否为 viperbuild 宏语句;1=是(应擦除)""" - if child is None: - return 0 + if child is None: return 0 kd: int = child.kind() if kd == ast.ASTKind.Assign: a: ast.Assign* = ast.Assign*(child) - if a is None or a.targets is None or a.value is None: - return 0 - if len(a.targets) != 1: - return 0 + if a is None or a.targets is None or a.value is None: return 0 + if len(a.targets) != 1: return 0 return self._vb_is_macro_assign(a.targets.get(0), a.value, alias, ctor, proj_vars) if kd == ast.ASTKind.AnnAssign: an: ast.AnnAssign* = ast.AnnAssign*(child) - if an is None or an.target is None or an.value is None: - return 0 + if an is None or an.target is None or an.value is None: return 0 return self._vb_is_macro_assign(an.target, an.value, alias, ctor, proj_vars) if kd == ast.ASTKind.Expr: ex: ast.Expr* = ast.Expr*(child) - if ex is None or ex.value is None: - return 0 + if ex is None or ex.value is None: return 0 return self._vb_is_macro_call(ex.value, proj_vars) return 0 def _erase_viperbuild_macros(self, pool: memhub.MemBuddy*, tree: ast.AST*) -> int: """擦除模块级 viperbuild 宏语句(就地替换 tree.children);1=发生擦除""" - if tree is None or tree.children is None: - return 0 + if tree is None or tree.children is None: return 0 ch: list[ast.AST*]* = tree.children cn: sizet = len(ch) - if cn == 0: - return 0 + if cn == 0: return 0 # ① 找 viperbuild 的本地名 / Project 构造名 alias: str = None ctor: str = None @@ -831,10 +771,8 @@ novirtual class Translator: al: ast.Alias* = ast.Alias*(names.get(ni)) if al is not None and al.name is not None: if string.strcmp(al.name, "viperbuild") == 0: - if al.asname is not None: - alias = al.asname - else: - alias = "viperbuild" + if al.asname is not None: alias = al.asname + else: alias = "viperbuild" ni += 1 elif kd == ast.ASTKind.ImportFrom: ifr: ast.ImportFrom* = ast.ImportFrom*(child) @@ -845,31 +783,24 @@ novirtual class Translator: al: ast.Alias* = ast.Alias*(ifr.names.get(ni)) if al is not None and al.name is not None: if string.strcmp(al.name, "Project") == 0: - if al.asname is not None: - ctor = al.asname - else: - ctor = "Project" + if al.asname is not None: ctor = al.asname + else: ctor = "Project" ni += 1 ci += 1 - if alias is None and ctor is None: - return 0 + if alias is None and ctor is None: return 0 # ② 过滤:先登记 Project 宏变量,再摘掉相关语句 proj_vars: list[str]* = list[str](pool, 8) kept: list[ast.AST*]* = list[ast.AST*](pool, 8) - if proj_vars is None or kept is None: - return 0 + if proj_vars is None or kept is None: return 0 erased: int = 0 ci = 0 while ci < cn: child = ch.get(ci) if child is not None: - if self._vb_is_macro_stmt(child, alias, ctor, proj_vars) != 0: - erased = 1 - else: - kept.append(child) + if self._vb_is_macro_stmt(child, alias, ctor, proj_vars) != 0: erased = 1 + else: kept.append(child) ci += 1 - if erased != 0: - tree.children = kept + if erased != 0: tree.children = kept return erased # 容器模块自动可见性注入(对齐 TPC _inject_auto_imports) @@ -883,16 +814,13 @@ novirtual class Translator: def _inject_auto_container_visibility(self, pool: memhub.MemBuddy*, tree: ast.AST*): """检测 list/dict 容器使用,注入容器类可见性""" - if tree is None or tree.children is None: - return + if tree is None or tree.children is None: return # 用栈式缓冲区传递检测结果(跨函数参数用 4 字节 int 指针) need_list_box: t.CPtr = stdlib.malloc(4) need_dict_box: t.CPtr = stdlib.malloc(4) if need_list_box is None or need_dict_box is None: - if need_list_box is not None: - stdlib.free(need_list_box) - if need_dict_box is not None: - stdlib.free(need_dict_box) + if need_list_box is not None: stdlib.free(need_list_box) + if need_dict_box is not None: stdlib.free(need_dict_box) return need_list_box[0] = 0 need_dict_box[0] = 0 @@ -905,13 +833,11 @@ novirtual class Translator: # 对齐 Phase1Main._InjectedCreatesCycle,覆盖所有 translate 路径 # (Phase1 1b / Phase2 pre-inc / PhaseA)——否则 _list/_dict 显式 # import memhub 且 memhub 用容器泛型时成 2-环,Phase A 永不收敛。 - if self._ContainerInjectionCreatesCycle("_dict") == 0: - self._imported_modules = GenApi.add_imported_module(pool, self._imported_modules, "_dict") + if self._ContainerInjectionCreatesCycle("_dict") == 0: self._imported_modules = GenApi.add_imported_module(pool, self._imported_modules, "_dict") if need_list_box[0] != 0: GenApi.add_visible_struct(pool, "list") if self._imported_modules is None or GenApi.is_module_imported(self._imported_modules, "_list") == 0: - if self._ContainerInjectionCreatesCycle("_list") == 0: - self._imported_modules = GenApi.add_imported_module(pool, self._imported_modules, "_list") + if self._ContainerInjectionCreatesCycle("_list") == 0: self._imported_modules = GenApi.add_imported_module(pool, self._imported_modules, "_list") stdlib.free(need_list_box) stdlib.free(need_dict_box) @@ -927,33 +853,24 @@ novirtual class Translator: 去掉环边后,_list 已因当前模块被其依赖而处于闭包,list 类仍由 add_visible_struct 可见、泛型模板已由 Phase1 注册。 """ - if mod_name is None or self.ModuleSha1 is None: - return 0 + if mod_name is None or self.ModuleSha1 is None: return 0 inj_sha1: str = StubMergerStore.LookupSha1ByModName(mod_name) - if inj_sha1 is None: - return 0 + if inj_sha1 is None: return 0 inj_deps: str = StubMergerStore.LookupIncludesDeps(inj_sha1) - if inj_deps is None: - return 0 + if inj_deps is None: return 0 # 当前模块名 = RelPath 基名(最后 '/' 或 '\\' 之后)去扩展名 rel_path: str = StubMergerStore.LookupSha1RelPath(self.ModuleSha1) - if rel_path is None: - return 0 + if rel_path is None: return 0 base: str = string.strrchr(rel_path, '/') - if base is None: - base = string.strrchr(rel_path, '\\') - if base is not None: - base = base + 1 - else: - base = rel_path + if base is None: base = string.strrchr(rel_path, '\\') + if base is not None: base = base + 1 + else: base = rel_path dot: str = string.strchr(base, '.') nm_buf: bytes = stdlib.malloc(128) - if nm_buf is None: - return 0 + if nm_buf is None: return 0 if dot is not None: nm_len: sizet = sizet(uint64(dot) - uint64(base)) - if nm_len > 127: - nm_len = 127 + if nm_len > 127: nm_len = 127 string.strncpy(nm_buf, base, nm_len) nm_buf[nm_len] = '\0' else: @@ -965,11 +882,9 @@ novirtual class Translator: dp: sizet = 0 while dp < d_len: ts: sizet = dp - while dp < d_len and inj_deps[dp] != ' ': - dp += 1 + while dp < d_len and inj_deps[dp] != ' ': dp += 1 tl: sizet = dp - ts - if dp < d_len: - dp += 1 + if dp < d_len: dp += 1 if tl > 0 and tl == nm_len2 and string.strncmp(inj_deps + ts, nm_buf, tl) == 0: stdlib.free(nm_buf) return 1 @@ -980,25 +895,20 @@ novirtual class Translator: need_list_box: t.CPtr, need_dict_box: t.CPtr): """递归扫描 AST 语句结构,检测 list/dict 容器使用""" - if node is None: - return + if node is None: return k: int = node.kind() if k == ast.ASTKind.AnnAssign: aa_s: ast.AnnAssign* = ast.AnnAssign*(node) - if aa_s.annotation is not None: - self._check_container_type_node(aa_s.annotation, need_list_box, need_dict_box) + if aa_s.annotation is not None: self._check_container_type_node(aa_s.annotation, need_list_box, need_dict_box) elif k == ast.ASTKind.Call: cl_s: ast.Call* = ast.Call*(node) - if cl_s.func is not None: - self._check_container_type_node(cl_s.func, need_list_box, need_dict_box) + if cl_s.func is not None: self._check_container_type_node(cl_s.func, need_list_box, need_dict_box) elif k == ast.ASTKind.Subscript: sub_s: ast.Subscript* = ast.Subscript*(node) - if sub_s.value is not None: - self._check_container_type_node(sub_s.value, need_list_box, need_dict_box) + if sub_s.value is not None: self._check_container_type_node(sub_s.value, need_list_box, need_dict_box) elif k == ast.ASTKind.FunctionDef: fd_s: ast.FunctionDef* = ast.FunctionDef*(node) - if fd_s.returns is not None: - self._check_container_type_node(fd_s.returns, need_list_box, need_dict_box) + if fd_s.returns is not None: self._check_container_type_node(fd_s.returns, need_list_box, need_dict_box) if fd_s.args is not None: args_s: ast.Arguments* = ast.Arguments*(fd_s.args) if args_s.args is not None: @@ -1009,8 +919,7 @@ novirtual class Translator: arg_s: ast.AST* = args_list_s.get(ai_s) if arg_s is not None: ag_s: ast.Arg* = ast.Arg*(arg_s) - if ag_s.annotation is not None: - self._check_container_type_node(ag_s.annotation, need_list_box, need_dict_box) + if ag_s.annotation is not None: self._check_container_type_node(ag_s.annotation, need_list_box, need_dict_box) # `[...]`/`{}` 字面量不触发 _list/_dict 导入:字面量广泛用于编译期常量列表 # (c.Asm 的 op/inp/out CLOBBER 参数、数组数据初始化),并非 list 容器使用。 # list/dict 容器的真实使用由类型位置检测覆盖:`x: list` / `list[...]` 注解、 @@ -1021,30 +930,24 @@ novirtual class Translator: if node.children is not None: ch_s: list[ast.AST*]* = node.children n_s: sizet = len(ch_s) - for ci_s in range(n_s): - self._scan_container_usage(ch_s.get(ci_s), need_list_box, need_dict_box) + for ci_s in range(n_s): self._scan_container_usage(ch_s.get(ci_s), need_list_box, need_dict_box) def _check_container_type_node(self, node: ast.AST*, need_list_box: t.CPtr, need_dict_box: t.CPtr): """检测类型位置节点是否为 list/dict(支持 Name / Subscript / BinOp 递归)""" - if node is None: - return + if node is None: return k: int = node.kind() if k == ast.ASTKind.Name: nm_s: ast.Name* = ast.Name*(node) if nm_s.id is not None: - if string.strcmp(nm_s.id, "dict") == 0: - need_dict_box[0] = 1 - elif string.strcmp(nm_s.id, "list") == 0: - need_list_box[0] = 1 + if string.strcmp(nm_s.id, "dict") == 0: need_dict_box[0] = 1 + elif string.strcmp(nm_s.id, "list") == 0: need_list_box[0] = 1 elif k == ast.ASTKind.Subscript: sub_s: ast.Subscript* = ast.Subscript*(node) - if sub_s.value is not None: - self._check_container_type_node(sub_s.value, need_list_box, need_dict_box) + if sub_s.value is not None: self._check_container_type_node(sub_s.value, need_list_box, need_dict_box) # rawptr[list[int]] / list[AST] 等:slice 里可能含 list,需下钻 - if sub_s.slice is not None: - self._check_container_type_node(sub_s.slice, need_list_box, need_dict_box) + if sub_s.slice is not None: self._check_container_type_node(sub_s.slice, need_list_box, need_dict_box) elif k == ast.ASTKind.BinOp: bop_s: ast.BinOp* = ast.BinOp*(node) self._check_container_type_node(ast.binop_get_left(bop_s), need_list_box, need_dict_box) @@ -1061,16 +964,13 @@ novirtual class Translator: if ak == ast.ASTKind.Name: nm_c: ast.Name* = ast.Name*(ann) if nm_c.id is not None: - if string.strcmp(nm_c.id, "list") == 0: - return 1 - if string.strcmp(nm_c.id, "dict") == 0: - return 1 + if string.strcmp(nm_c.id, "list") == 0: return 1 + if string.strcmp(nm_c.id, "dict") == 0: return 1 return 0 elif ak == ast.ASTKind.Subscript: sub_c: ast.Subscript* = ast.Subscript*(ann) ann = sub_c.value - else: - return 0 + else: return 0 return 0 @@ -1082,10 +982,8 @@ novirtual class Translator: mode: 0=完整, 1=stub(仅声明), 2=text(仅代码) """ - if self.Module is None or buf is None: - return - if _mbuddy is None: - return + if self.Module is None or buf is None: return + if _mbuddy is None: return buf[0] = '\0' mlirlite.LLVMModulePrint(buf, size, self.Module, _mbuddy, mode) @@ -1109,16 +1007,13 @@ novirtual class Translator: # _tb_module_has_global_ctors - does the module already define @llvm.global_ctors def _tb_module_has_global_ctors(mod: mlirlite.LLVMModule*) -> int: - if mod is None: - return 0 + if mod is None: return 0 g: mlirlite.GlobalVariable* = mod.GlobalHead steps: sizet = 0 while g is not None: steps += 1 - if steps > 100000: - break - if g.Name is not None and string.strcmp(g.Name, "llvm.global_ctors") == 0: - return 1 + if steps > 100000: break + if g.Name is not None and string.strcmp(g.Name, "llvm.global_ctors") == 0: return 1 g = g.Next return 0 @@ -1127,21 +1022,17 @@ def _tb_module_has_global_ctors(mod: mlirlite.LLVMModule*) -> int: # # Accepts "<16hex>.Install" (the usual SHA1-mangled form) or the bare name. def _tb_find_install_function(mod: mlirlite.LLVMModule*) -> mlirlite.Function*: - if mod is None: - return None + if mod is None: return None cur: mlirlite.Function* = mod.FuncHead steps: sizet = 0 while cur is not None: steps += 1 - if steps > 100000: - return None + if steps > 100000: return None nm: str = mlirlite.function_get_name(cur) if nm is not None: - if string.strcmp(nm, "Install") == 0: - return cur + if string.strcmp(nm, "Install") == 0: return cur nl: sizet = mlirlite.function_get_name_len(cur) - if nl == 24 and string.strcmp(nm + 16, ".Install") == 0: - return cur + if nl == 24 and string.strcmp(nm + 16, ".Install") == 0: return cur cur = mlirlite.function_get_next(cur) return None @@ -1152,10 +1043,8 @@ def _tb_find_install_function(mod: mlirlite.LLVMModule*) -> mlirlite.Function*: # (external) linkage instead of TPC's 'internal'; only traceback.vp defines it, # so there is no symbol clash. def InjectTracebackInstallCtor(tr: rawptr[Translator]) -> int: - if tr is None or tr.Module is None: - return 0 - if tr._declare_only != 0: - return 0 + if tr is None or tr.Module is None: return 0 + if tr._declare_only != 0: return 0 pool: memhub.MemBuddy* = tr.Pool if pool is None: VLogger.error("--traceback: 内存池未初始化,无法注入 Install 构造器", "TRACEBACK") diff --git a/App/lib/core/Gen/TranslatorGenMixin.vp b/App/lib/core/Gen/TranslatorGenMixin.vp index 9f74c5d..7d587cf 100644 --- a/App/lib/core/Gen/TranslatorGenMixin.vp +++ b/App/lib/core/Gen/TranslatorGenMixin.vp @@ -51,8 +51,7 @@ novirtual class TranslatorGenMixin: has_export = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExport", 0) has_state = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0) - if has_export != 0 or has_state != 0: - self.Gen.CallGenBase.register_cexport_func(trans.ModuleSha1, fd.name) + if has_export != 0 or has_state != 0: self.Gen.CallGenBase.register_cexport_func(trans.ModuleSha1, fd.name) return 0 @@ -83,8 +82,7 @@ novirtual class TranslatorGenMixin: # _declare_only == 0 时,_translate_module_level 已预处理导入语句, # 此处跳过避免重复处理(from_imports 条目重复) if trans._declare_only == 0 and (kd == ast.ASTKind.Import or kd == ast.ASTKind.ImportFrom): continue - if kd == ast.ASTKind.Import: - self.Gen.ImportsGen.translate_import(trans, child) + if kd == ast.ASTKind.Import: self.Gen.ImportsGen.translate_import(trans, child) elif kd == ast.ASTKind.ImportFrom: self.Gen.ImportsGen.translate_import_from_module(trans, child) self.Gen.ImportsGen.translate_import_from_names(trans, child) @@ -94,8 +92,7 @@ novirtual class TranslatorGenMixin: # 必须在此跳过——否则 1a 的 _prescan_funcdef_signatures 会把未绑定 # 类型形参 T 当注解解析(落空/误导)。 fd_tc: ast.FunctionDef* = ast.FunctionDef*(child) - if fd_tc is not None and fd_tc.type_params is not None: - continue + if fd_tc is not None and fd_tc.type_params is not None: continue # Phase 1a 声明模式:只注册 CExport/State 函数到全局表(解决翻译顺序依赖) # Phase 1b 全量翻译:正常翻译函数体 if trans._declare_only == 0: @@ -112,8 +109,7 @@ novirtual class TranslatorGenMixin: elif kd == ast.ASTKind.ClassDef: # ClassDef 在模块级直接处理(不需要 builder) # _declare_only=2(import扫描模式)时跳过,只处理 import 依赖 - if trans._declare_only != 2: - self.Gen.ClassGenDef.translate_class_def(trans, child) + if trans._declare_only != 2: self.Gen.ClassGenDef.translate_class_def(trans, child) elif trans._declare_only == 0 and trans._cur_builder is not None: # 有 builder → 委托 HandlesBody 分派 added = self.Gen.StmtGen.translate_stmt(trans, child) @@ -142,22 +138,18 @@ novirtual class TranslatorGenMixin: # ============================================================ def _prescan_funcdef_signatures(self, trans: HT.Translator*, node: ast.AST*) -> None: """预解析模块级函数签名的返回/参数类型,触发泛型类特化""" - if trans is None or node is None: - return + if trans is None or node is None: return # 入口收基类 ast.AST*(模块级调度器只持有 ast.AST* 子节点,与同一处调用的 # translate_function_def / translate_class_def / _register_cexport_from_funcdef # 形参口径一致),在此显式窄化为 ast.FunctionDef*:基类指针传派生类形参属 # 向下转型,严格指针规则下禁止隐式转换。 fd: ast.FunctionDef* = ast.FunctionDef*(node) - if fd is None: - return + if fd is None: return pool: memhub.MemBuddy* = trans.Pool - if pool is None: - return + if pool is None: return imp: str = trans._imported_modules fi: str = trans._from_imports - if fd.returns is not None: - self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, imp, fi, trans, 0) + if fd.returns is not None: self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, imp, fi, trans, 0) if fd.args is not None: ags: ast.Arguments* = ast.Arguments*(fd.args) if ags.args is not None: @@ -166,8 +158,7 @@ novirtual class TranslatorGenMixin: ai: sizet for ai in range(an): ag: ast.Arg* = ast.Arg*(al.get(ai)) - if ag is not None and ag.annotation is not None: - self.Gen.TypeGenResolve.resolve_annotation_type(pool, ag.annotation, imp, fi, trans, 0) + if ag is not None and ag.annotation is not None: self.Gen.TypeGenResolve.resolve_annotation_type(pool, ag.annotation, imp, fi, trans, 0) # ============================================================ # _build_array_initializer_text - 从 AST List 生成 LLVM IR 数组初始化器 @@ -179,14 +170,12 @@ novirtual class TranslatorGenMixin: var_ty: mlirlite.LLVMType*, list_node: ast.List*) -> str: """从 AST List 节点生成 LLVM IR 数组初始化器文本,None 失败""" - if var_ty is None or list_node is None: - return None + if var_ty is None or list_node is None: return None # 重新进行类型转换,确保 TPV 编译器正确识别 ast.List 类型 # (避免 init_list_node 初始值为 None 时类型推断退化为 t.CPtr) ln: ast.List* = ast.List*(list_node) - if ln is None: - return None + if ln is None: return None # 从 var_ty 提取数组元素类型和数量 elem_ty: mlirlite.LLVMType* = None @@ -196,8 +185,7 @@ novirtual class TranslatorGenMixin: elem_ty = et arr_count = cnt - if elem_ty is None or arr_count <= 0: - return None + if elem_ty is None or arr_count <= 0: return None # 确定元素类型的 IR 表示 elem_ir_ty: str = "i8" @@ -205,21 +193,16 @@ novirtual class TranslatorGenMixin: match elem_ty: case mlirlite.LLVMType.Int(bits): is_int_elem = 1 - if bits == 8: - elem_ir_ty = "i8" - elif bits == 16: - elem_ir_ty = "i16" - elif bits == 32: - elem_ir_ty = "i32" - elif bits == 64: - elem_ir_ty = "i64" + if bits == 8: elem_ir_ty = "i8" + elif bits == 16: elem_ir_ty = "i16" + elif bits == 32: elem_ir_ty = "i32" + elif bits == 64: elem_ir_ty = "i64" case _: is_int_elem = 0 # 获取列表元素(通过 ln.elts 而非 list_node.elts,确保类型正确识别) elts: list[ast.AST*]* = ln.elts - if elts is None: - return None + if elts is None: return None elts_count: sizet = len(elts) # 元素数超过声明长度 → fail-fast(不按声明长度截断、静默丢弃多余元素)。 @@ -244,8 +227,7 @@ novirtual class TranslatorGenMixin: cnt_total_n: sizet = sizet(arr_count) buf_size_n: sizet = 128 + cnt_total_n * 768 buf_n: str = pool.alloc(buf_size_n) - if buf_n is None: - return None + if buf_n is None: return None written_n: int = viperlib.snprintf(buf_n, buf_size_n, "[") pos_n: sizet = sizet(written_n) # 子数组元素类型前缀(如 "[16 x i8]"):嵌套数组初始化器内层 @@ -253,8 +235,7 @@ novirtual class TranslatorGenMixin: # "expected number in address space";用户规范要求 # [[16 x i8][i8 0, ...], ...] 形式)。TypePrint 序列化 elem_ty。 elem_ty_str_n: str = pool.alloc(512) - if elem_ty_str_n is None: - return None + if elem_ty_str_n is None: return None mlirlite.TypePrint(elem_ty_str_n, 512, elem_ty, pool) i_n: sizet = 0 while i_n < cnt_total_n: @@ -263,14 +244,12 @@ novirtual class TranslatorGenMixin: en_n: ast.AST* = elts.get(i_n) if en_n is not None: ek_n: int = en_n.kind() - if ek_n == ast.ASTKind.List: - sub_n = self._build_array_initializer_text(pool, elem_ty, ast.List*(en_n)) + if ek_n == ast.ASTKind.List: sub_n = self._build_array_initializer_text(pool, elem_ty, ast.List*(en_n)) elif ek_n == ast.ASTKind.Set: # 花括号行字面量(如点阵字库 {0x00, ...}):Set.elts # 与 List 同构,包装为临时 List 递归生成子数组文本 se_n: rawptr[ast.Set] = rawptr[ast.Set](en_n) - if se_n is not None and se_n.elts is not None: - sub_n = self._build_array_initializer_text(pool, elem_ty, ast.List(pool, se_n.elts, ast.ASTCtx.Load)) + if se_n is not None and se_n.elts is not None: sub_n = self._build_array_initializer_text(pool, elem_ty, ast.List(pool, se_n.elts, ast.ASTCtx.Load)) if sub_n is None: # 元素缺失/无法展开:子数组整体零初始化 sub_n = "zeroinitializer" @@ -284,26 +263,20 @@ novirtual class TranslatorGenMixin: return buf_n for zi in range(elts_count): ze: ast.AST* = elts.get(zi) - if ze is None: - continue + if ze is None: continue zk: int = ze.kind() if zk == ast.ASTKind.Constant: zc: ast.Constant* = ast.Constant*(ze) - if zc is None: - continue + if zc is None: continue # None(CONST_NONE)视为零:函数指针数组 # irq_handlers: t.CArray[irq_handler_t, 16] = [None] 表示 # 全空(idt.vp L387)——CONST_NONE 不是 CONST_INT,此前 # 被拒 → "初始化器构建失败" fail-fast。None 归一零填充。 - if zc.const_kind == ast.CONST_NONE: - continue - if zc.const_kind != ast.CONST_INT or zc.int_val != 0: - return None + if zc.const_kind == ast.CONST_NONE: continue + if zc.const_kind != ast.CONST_INT or zc.int_val != 0: return None elif zk == ast.ASTKind.UnaryOp: - if self.Gen.AssignGen.extract_cdefine_int_value(ze) != 0: - return None - else: - return None + if self.Gen.AssignGen.extract_cdefine_int_value(ze) != 0: return None + else: return None return "zeroinitializer" # 计算缓冲区大小: 每个元素最多 "i32 -9223372036854775808, " 约 26 字符 @@ -311,8 +284,7 @@ novirtual class TranslatorGenMixin: cnt_total: sizet = sizet(arr_count) buf_size: sizet = 64 + cnt_total * 32 buf: str = pool.alloc(buf_size) - if buf is None: - return None + if buf is None: return None # 写入前缀: "["(类型前缀由 _print_global 输出,初始化器只需元素列表) written: int = viperlib.snprintf(buf, buf_size, "[") @@ -334,14 +306,12 @@ novirtual class TranslatorGenMixin: ec: ast.Constant* = ast.Constant*(elem_node) # CONST_CHAR 字符字面量(如 `_ps2_set1 = ['\x1b', '1', ...]`): # int_val 即字符码(不识别则字符元素全编成 0)。 - if ec is not None and (ec.const_kind == ast.CONST_INT or ec.const_kind == ast.CONST_CHAR): - elem_val = ec.int_val + if ec is not None and (ec.const_kind == ast.CONST_INT or ec.const_kind == ast.CONST_CHAR): elem_val = ec.int_val # CONST_STR 单字符(双引号如 "'" / '"'):parser 把双引号一律判为 # CONST_STR,strlen == 1 时取首字符码;多字符字符串无法表达为整型 # 元素 → 保持 0(由下方按声明长度补零)。 elif ec is not None and ec.const_kind == ast.CONST_STR: - if ec.str_val is not None and string.strlen(ec.str_val) == 1: - elem_val = int64(ec.str_val[0]) + if ec.str_val is not None and string.strlen(ec.str_val) == 1: elem_val = int64(ec.str_val[0]) elif ek == ast.ASTKind.UnaryOp: # 负数: UnaryOp(USub, Constant) elem_val = self.Gen.AssignGen.extract_cdefine_int_value(elem_node) @@ -364,21 +334,17 @@ novirtual class TranslatorGenMixin: var_ty: mlirlite.LLVMType*, str_val: str) -> str: """字符串字面量初始化数组全局,返回初始化器文本或 None""" - if var_ty is None or str_val is None: - return None + if var_ty is None or str_val is None: return None arr_count: int = 0 match var_ty: case mlirlite.LLVMType.Array(_, cnt): arr_count = cnt - if arr_count <= 0: - return None + if arr_count <= 0: return None slen: sizet = string.strlen(str_val) - if slen == 0: - return "zeroinitializer" + if slen == 0: return "zeroinitializer" buf_size: sizet = 64 + sizet(arr_count) * 16 buf: str = pool.alloc(buf_size) - if buf is None: - return None + if buf is None: return None written: int = viperlib.snprintf(buf, buf_size, "[") pos: sizet = sizet(written) i: sizet = 0 @@ -387,8 +353,7 @@ novirtual class TranslatorGenMixin: written = viperlib.snprintf(buf + pos, buf_size - pos, ", ") pos += sizet(written) bv: int64 = 0 - if i < slen: - bv = int64(str_val[i]) + if i < slen: bv = int64(str_val[i]) written = viperlib.snprintf(buf + pos, buf_size - pos, "i8 %lld", bv) pos += sizet(written) i += 1 @@ -407,25 +372,21 @@ novirtual class TranslatorGenMixin: var_name: str, str_val: str) -> str: """为字符串字面量创建内部常量全局并返回 GEP 初始化器文本,None 失败""" - if str_val is None or var_name is None: - return None + if str_val is None or var_name is None: return None # 构造内部字符串常量名称: .str.{var_name} str_name_buf: str = pool.alloc(64) - if str_name_buf is None: - return None + if str_name_buf is None: return None viperlib.snprintf(str_name_buf, 64, ".str.%s", var_name) # 调用 mlirlite.create_global_string 创建字符串常量全局 str_gv: mlirlite.GlobalVariable* = mlirlite.create_global_string(pool, mod, str_name_buf, str_val) - if str_gv is None: - return None + if str_gv is None: return None # 生成 GEP 初始化器文本 str_len: sizet = string.strlen(str_val) init_buf: str = pool.alloc(128) - if init_buf is None: - return None + if init_buf is None: return None viperlib.snprintf(init_buf, 128, "getelementptr inbounds ([%d x i8], [%d x i8]* @%s, i32 0, i32 0)", str_len + 1, str_len + 1, str_name_buf) @@ -440,11 +401,9 @@ novirtual class TranslatorGenMixin: "initializer with struct type has wrong # elements")。 Ptr→null、Int→0、Float→0.0、Array/Struct→zeroinitializer。 """ - if fty is None or ty_str is None: - return None + if fty is None or ty_str is None: return None buf: str = pool.alloc(160) - if buf is None: - return None + if buf is None: return None match fty: case mlirlite.LLVMType.Ptr(_): viperlib.snprintf(buf, 576, "%s null", ty_str) @@ -468,8 +427,7 @@ novirtual class TranslatorGenMixin: ty_str: str, dval: ast.AST*) -> str: """字段默认值 → "ty 值" 文本;不可折叠返回 None""" - if dval is None or fty is None or ty_str is None: - return None + if dval is None or fty is None or ty_str is None: return None is_int: int = 0 dv_int: int64 = 0 if dval.kind() == ast.ASTKind.Constant: @@ -482,8 +440,7 @@ novirtual class TranslatorGenMixin: # 负数/按位取反字面量(如 -1 / 0xFFFFFFFFFFFFFFFF) dv_int = self.Gen.AssignGen.extract_cdefine_int_value(dval) is_int = 1 - if is_int == 0: - return None + if is_int == 0: return None # 仅整型字段可写整数常量(浮点/指针/聚合交给零值兜底) match fty: case mlirlite.LLVMType.Int(_): @@ -491,8 +448,7 @@ novirtual class TranslatorGenMixin: case _: return None buf: str = pool.alloc(576) - if buf is None: - return None + if buf is None: return None viperlib.snprintf(buf, 576, "%s %lld", ty_str, dv_int) return buf @@ -505,17 +461,14 @@ novirtual class TranslatorGenMixin: se: GenTypes.StructEntry*, start_idx: int) -> str: """按字段默认值生成 "e0, e1, ..." 元素文本;无非零默认值返回 None""" - if se is None or se.Fields is None: - return None + if se is None or se.Fields is None: return None fc: int = se.FieldCount - if fc <= start_idx: - return None + if fc <= start_idx: return None # 每个字段元素 = 类型前缀(MLIR 形态可达 _TY_TEXT_CAP 字节)+ 值文本; # 160 是按旧的短类型估的,会截断。 buf_size: sizet = 256 + sizet(fc) * 576 buf: str = pool.alloc(buf_size) - if buf is None: - return None + if buf is None: return None pos: sizet = 0 first: int = 1 has_nonzero: int = 0 @@ -523,19 +476,16 @@ novirtual class TranslatorGenMixin: while i < fc: fe: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(se, i) i += 1 - if fe is None or fe.Ty is None: - continue + if fe is None or fe.Ty is None: continue ty_str: str = pool.alloc(512) - if ty_str is None: - continue + if ty_str is None: continue mlirlite.TypePrint(ty_str, 512, fe.Ty, pool) elem: str = self._default_val_const_text(pool, fe.Ty, ty_str, fe.DefaultVal) is_zero: int = 0 if elem is None: elem = self._stg_field_zero_text(pool, fe.Ty, ty_str) is_zero = 1 - if elem is None: - continue + if elem is None: continue written: int = 0 if first == 0: written = viperlib.snprintf(buf + pos, buf_size - pos, ", ") @@ -543,10 +493,8 @@ novirtual class TranslatorGenMixin: written = viperlib.snprintf(buf + pos, buf_size - pos, "%s", elem) pos += sizet(written) first = 0 - if is_zero == 0: - has_nonzero = 1 - if has_nonzero == 0: - return None + if is_zero == 0: has_nonzero = 1 + if has_nonzero == 0: return None return buf # _build_stg_struct_init_text - storage struct 完整常量初始化器(含字段默认值) @@ -558,12 +506,10 @@ novirtual class TranslatorGenMixin: start_idx: int) -> str: """按字段默认值生成完整 struct 初始化器;无非零默认值返回 None""" body: str = self._build_stg_struct_body_text(pool, se, start_idx) - if body is None: - return None + if body is None: return None body_len: sizet = sizet(string.strlen(body)) buf: str = pool.alloc(body_len + 8) - if buf is None: - return None + if buf is None: return None viperlib.snprintf(buf, body_len + 8, "{ %s }", body) return buf @@ -588,18 +534,15 @@ novirtual class TranslatorGenMixin: Attribute: t.attr.weak),未命中返回 None。属性名识别复用类侧 ClassGenBase._tattr_name(Call→func→attr / Attribute→attr)。 """ - if node is None: - return None + if node is None: return None if node.kind() == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(node) if bop.op == ast.OpKind.BitOr: hit_l: ast.AST* = self._scan_global_tattr(bop.left, want_name) - if hit_l is not None: - return hit_l + if hit_l is not None: return hit_l return self._scan_global_tattr(bop.right, want_name) return None - if self.Gen.ClassGenBase._tattr_name(node, want_name) != 0: - return node + if self.Gen.ClassGenBase._tattr_name(node, want_name) != 0: return node return None def _extract_global_attr_section(self, node: ast.AST*, var_name: str) -> str: @@ -610,8 +553,7 @@ novirtual class TranslatorGenMixin: 无意义/非法的 IR,静默忽略只会掩盖拼写错误。 """ hit: ast.AST* = self._scan_global_tattr(node, "section") - if hit is None: - return None + 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") @@ -625,8 +567,7 @@ novirtual class TranslatorGenMixin: → fail-fast(llc 亦拒绝 `align 0`,静默忽略会掩盖参数错误)。 """ hit: ast.AST* = self._scan_global_tattr(node, "aligned") - if hit is None: - return 0 + 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") @@ -634,8 +575,7 @@ novirtual class TranslatorGenMixin: return al_val def _extract_global_attr_weak(self, node: ast.AST*) -> int: """检测 `T | t.attr.weak` / `t.attr.weak()`(1=有,0=无)""" - if self._scan_global_tattr(node, "weak") is not None: - return 1 + if self._scan_global_tattr(node, "weak") is not None: return 1 return 0 # ============================================================ @@ -659,12 +599,9 @@ novirtual class TranslatorGenMixin: def _RegisterStaticModuleVar(self, trans: HT.Translator*, annot_node: ast.AST*, var_name: str) -> int: - if trans is None or annot_node is None or var_name is None: - return 0 - if trans.ModuleSha1 is None: - return 0 - if self.Gen.TypeGenErr.has_decorator_marker(annot_node, "CStatic", 0) == 0: - return 0 + if trans is None or annot_node is None or var_name is None: return 0 + if trans.ModuleSha1 is None: return 0 + if self.Gen.TypeGenErr.has_decorator_marker(annot_node, "CStatic", 0) == 0: return 0 self.Gen.CallGenBase.RegisterStaticSymbol(trans.ModuleSha1, var_name) return 0 @@ -694,14 +631,12 @@ novirtual class TranslatorGenMixin: # (每文件隔离),不注册则函数参数注解查表失败 → NameError。 if self.Gen.TypeGenCType._is_ctypedef_annotation(aa_cd.annotation) != 0: ctd_str: str = self.Gen.TypeGenResolve._get_type_name_from_annotation(pool, aa_cd.value) - if ctd_str is not None: - self.Gen.TypeGenCType.register_ctypedef(pool, nm_cd.id, ctd_str) + if ctd_str is not None: self.Gen.TypeGenCType.register_ctypedef(pool, nm_cd.id, ctd_str) return 0 # _declare_only=1(struct注册模式)时只处理 CDefine,不创建全局变量 # CDefine 已在上面处理并返回,到这里说明不是 CDefine,直接跳过 - if trans._declare_only == 1: - return 0 + if trans._declare_only == 1: return 0 var_name: str = None var_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) @@ -721,10 +656,8 @@ novirtual class TranslatorGenMixin: if k == ast.ASTKind.AnnAssign: aa: ast.AnnAssign* = ast.AnnAssign*(node) - if aa is None or aa.target is None: - return 0 - if aa.target.kind() != ast.ASTKind.Name: - return 0 + if aa is None or aa.target is None: return 0 + if aa.target.kind() != ast.ASTKind.Name: return 0 nm: ast.Name* = ast.Name*(aa.target) var_name = nm.id annot_node = aa.annotation @@ -754,8 +687,7 @@ novirtual class TranslatorGenMixin: if ml_callable_ret is not None: # 返回值:0=成功/同类型幂等命中;非 0 已在 register_func_ptr_sig # 内部 fatal_error 终止编译,此处分支仅防御(见 AssignGenMixin 同处)。 - if self.Gen.CallGenLeafKit.register_func_ptr_sig(pool, var_name, ml_callable_ret, aa) != 0: - return 0 + if self.Gen.CallGenLeafKit.register_func_ptr_sig(pool, var_name, ml_callable_ret, aa) != 0: return 0 # 解析类型 if aa.annotation is not None: resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, aa.annotation, trans._imported_modules, trans._from_imports, trans, 0) @@ -795,8 +727,7 @@ novirtual class TranslatorGenMixin: val_kind: int = aa.value.kind() if val_kind == ast.ASTKind.Constant: cn: ast.Constant* = ast.Constant*(aa.value) - if cn.const_kind == ast.CONST_NONE: - is_none_init = 1 + if cn.const_kind == ast.CONST_NONE: is_none_init = 1 elif cn.const_kind == ast.CONST_INT: init_val = cn.int_val init_kind = 1 @@ -818,22 +749,18 @@ novirtual class TranslatorGenMixin: init_kind = 2 elif k == ast.ASTKind.Assign: asgn: ast.Assign* = ast.Assign*(node) - if asgn is None or asgn.targets is None: - return 0 + if asgn is None or asgn.targets is None: return 0 targets: list[ast.AST*]* = asgn.targets - if len(targets) < 1: - return 0 + if len(targets) < 1: return 0 t0: ast.AST* = targets.get(0) - if t0 is None or t0.kind() != ast.ASTKind.Name: - return 0 + if t0 is None or t0.kind() != ast.ASTKind.Name: return 0 nm2: ast.Name* = ast.Name*(t0) var_name = nm2.id if asgn.value is not None: val_kind2: int = asgn.value.kind() if val_kind2 == ast.ASTKind.Constant: cn2: ast.Constant* = ast.Constant*(asgn.value) - if cn2.const_kind == ast.CONST_NONE: - is_none_init = 1 + if cn2.const_kind == ast.CONST_NONE: is_none_init = 1 elif cn2.const_kind == ast.CONST_INT: init_val = cn2.int_val init_kind = 1 @@ -860,15 +787,13 @@ novirtual class TranslatorGenMixin: # 真正的函数别名机制(可调用 + 可 re-export)属独立特性,待后续实现。 return 0 - if var_name is None: - return 0 + if var_name is None: return 0 # __all__ 是 Python 模块元数据(公开名列表),无运行时语义:StubGen 的 .vpi 不为其 # 生成 stub 声明,此处同样跳过全局创建——否则无注解 list-of-strings 全局类型推断 # 缺失(var_ty 默认 i32)→ _build_array_initializer_text 返回 None → 误报 # "初始化器构建失败"。与 CDefine/CTypedef 同类:编译期/元数据实体不落入 LLVM 全局。 - if string.strcmp(var_name, "__all__") == 0: - return 0 + if string.strcmp(var_name, "__all__") == 0: return 0 # 浮点字面量初始化(init_kind==4):数值一律从当前源文件按变量名重读, # 不用 AST 节点的 float_val —— 该字段可能被后续 pool 操作覆写,且跨模块 @@ -892,8 +817,7 @@ novirtual class TranslatorGenMixin: # 检查是否已注册 existing: mlirlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, var_name) - if existing is not None: - return 0 + if existing is not None: return 0 # 创建全局变量 @var_name # 先确保 var_ty 中的跨模块结构体类型在模块中有 opaque 声明 @@ -908,8 +832,7 @@ novirtual class TranslatorGenMixin: # VKernel gdt/gp/_switch_old_rsp/_coro_* 被 c.Asm 引用,带 SHA1 前缀 # 无法在 LLVM MC 中解析)。 is_global_cexport: int = 0 - if annot_node is not None: - is_global_cexport = self.Gen.TypeGenErr.has_decorator_marker(annot_node, "CExport", 0) + if annot_node is not None: is_global_cexport = self.Gen.TypeGenErr.has_decorator_marker(annot_node, "CExport", 0) # extern 全局(`extern NAME: T` → 注解含 t.State / t.CExtern):符号定义在 # 外部(C 库 / 汇编 / 其它翻译单元),本模块只生成外部声明 # `@裸名 = external global T`——external linkage、无初始值、无 storage。 @@ -918,8 +841,7 @@ novirtual class TranslatorGenMixin: is_global_extern: int = 0 if annot_node is not None: is_global_extern = self.Gen.TypeGenErr.has_decorator_marker(annot_node, "CExtern", 0) - if is_global_extern == 0: - is_global_extern = self.Gen.TypeGenErr.has_decorator_marker(annot_node, "State", 0) + if is_global_extern == 0: is_global_extern = self.Gen.TypeGenErr.has_decorator_marker(annot_node, "State", 0) # 全局变量侧 t.attr.* 属性(`T | t.attr.xxx` 注解联合形态): # section→gv.Section、aligned→gv.Align、weak→gv.Linkage(见下方应用点)。 # 仅在 AnnAssign(annot_node 非 None)时存在,与 t.CExport 同一条路。 @@ -931,16 +853,13 @@ novirtual class TranslatorGenMixin: gv_attr_align = self._extract_global_attr_aligned(annot_node, var_name) gv_attr_weak = self._extract_global_attr_weak(annot_node) mangled_name: str = var_name - if is_global_cexport == 0 and is_global_extern == 0: - mangled_name = self.Gen.FuncGenBase._mangle_name(trans, var_name) + if is_global_cexport == 0 and is_global_extern == 0: mangled_name = self.Gen.FuncGenBase._mangle_name(trans, var_name) gv: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, mangled_name, var_ty) - if gv is None: - return 0 + if gv is None: return 0 mlirlite.module_add_global(mod, gv) # 段名:直接写字段(_print_global 会补 `, section "xxx"` 的引号)。 - if gv_attr_section is not None: - mlirlite.global_set_section(gv, gv_attr_section) + if gv_attr_section is not None: mlirlite.global_set_section(gv, gv_attr_section) # B5:@c.Attribute(t.attr.aligned(N)) 类的全局实例施加对齐(如 fpu_context 16 对齐, # FXSAVE 区域要求 16 字节对齐,否则 fxsave/fxrstor #GP)。 @@ -953,22 +872,17 @@ novirtual class TranslatorGenMixin: case _: pass al_entry: GenTypes.StructEntry* = None - if al_ty is not None and al_ty.kind() == mlirlite.LLVMType.Struct: - al_entry = self.Gen.StructGen.find_struct_by_type(al_ty) - if gv_attr_align > 0: - gv.Align = gv_attr_align - elif al_entry is not None and al_entry.Align > 0: - gv.Align = al_entry.Align + if al_ty is not None and al_ty.kind() == mlirlite.LLVMType.Struct: al_entry = self.Gen.StructGen.find_struct_by_type(al_ty) + if gv_attr_align > 0: gv.Align = gv_attr_align + elif al_entry is not None and al_entry.Align > 0: gv.Align = al_entry.Align # 设置初始值(有初始值时清除 external linkage,因为 LLVM 22+ 不允许 external global 带初始值) # extern 全局例外:保持 external(仅外部声明,绝不写初始值 / storage)。 - if is_global_extern != 0: - gv.Linkage = "external" + if is_global_extern != 0: gv.Linkage = "external" else: gv.Linkage = None # t.attr.weak → weak linkage(须在 Linkage 清空之后设置)。 - if gv_attr_weak != 0: - mlirlite.global_set_linkage(gv, "weak") + if gv_attr_weak != 0: mlirlite.global_set_linkage(gv, "weak") if init_kind == 1: # 整数初始值 init_buf: str = pool.alloc(48) @@ -978,8 +892,7 @@ novirtual class TranslatorGenMixin: elif init_kind == 2: # 列表字面量 → 数组初始化器 [N x elem_ty] [elem_ty val0, ...] arr_init: str = self._build_array_initializer_text(pool, var_ty, init_list_node) - if arr_init is not None: - gv.Initializer = arr_init + if arr_init is not None: gv.Initializer = arr_init else: # 初始化器构建失败:直接报错终止(fail-fast),不再回退 zeroinitializer self.Gen.TypeGenErr.fatal_error(node, f"模块级变量 '{var_name}' 初始化器构建失败", "TypeError") @@ -995,27 +908,21 @@ novirtual class TranslatorGenMixin: pass 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") + if arr_str_init is not None: gv.Initializer = arr_str_init + else: self.Gen.TypeGenErr.fatal_error(node, f"模块级数组变量 '{var_name}' 字符串初始化器构建失败", "TypeError") else: # 指针类型(如 b64_tab: t.CArray[char, None] = "ABC..."): # 创建字符串常量全局 + GEP 引用 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") + if str_init is not None: gv.Initializer = str_init + else: self.Gen.TypeGenErr.fatal_error(node, f"模块级变量 '{var_name}' 初始化器构建失败", "TypeError") elif init_kind == 4: # 浮点初始值:LLVM IR 的浮点常量必须写成位模式文本(0x%016llx / 0x%08x)—— # 十进制文本经 llc 解析对部分值有 ±1 ulp 误差(见 mlirlite.ConstFloat 注释)。 # 浮点分支缺失时模块级 t.CDouble 全局会退化成 zeroinitializer(值全变 0)。 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") + 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: # 使用 zeroinitializer 而非 "0":指针类型必须用 null/zeroinitializer, # 整数/聚合类型也兼容 zeroinitializer,避免 "integer constant must have integer type" @@ -1023,8 +930,7 @@ novirtual class TranslatorGenMixin: # 此处不覆盖;但 = None 懒初始化全局(is_none_init)既无 storage 也无其他 # Initializer → 必须显式 zeroinitializer(LLVM 对指针类型输出为 null), # 否则 gv 无初始化器 → 全局声明残缺。 - if (resolved_stg_ty is None or is_none_init != 0) and is_global_extern == 0: - gv.Initializer = "zeroinitializer" + if (resolved_stg_ty is None or is_none_init != 0) and is_global_extern == 0: gv.Initializer = "zeroinitializer" # 对象类全局:创建静态 storage 全局(BSS)承载对象实例,@g 编译期引用它。 # 函数内 `g = T()` 构造时把对象复制到 storage(见 AssignGenMixin 全局分支), @@ -1049,10 +955,8 @@ novirtual class TranslatorGenMixin: # "@当前sha1.Class.vtable",而 vtable 实为定义模块的符号 → llc "use of # undefined value"。resolved_stg_entry.ModuleSha1 即定义模块,比裸名反查精确。 vt_sha1: str = None - if resolved_stg_entry.ModuleSha1 is not None: - vt_sha1 = resolved_stg_entry.ModuleSha1 - if vt_sha1 is None: - vt_sha1 = trans.ModuleSha1 + if resolved_stg_entry.ModuleSha1 is not None: vt_sha1 = resolved_stg_entry.ModuleSha1 + if vt_sha1 is None: vt_sha1 = trans.ModuleSha1 vt_mangled: str = self.Gen.FuncGenBase._mangle_name_with_sha1(vt_sha1, vt_name_buf) if vt_mangled is not None: # 跨模块 vtable 只被本初始化器文本引用 ⇒ 模块内无对应 GlobalVariable ⇒ @@ -1063,13 +967,11 @@ novirtual class TranslatorGenMixin: # LLVM 22 不透明指针 ⇒ 声明 pointee 用 i8* 即可(pointee 无语义)。 vt_cross: int = 0 if resolved_stg_entry.ModuleSha1 is not None and trans.ModuleSha1 is not None: - if string.strncmp(resolved_stg_entry.ModuleSha1, trans.ModuleSha1, 16) != 0: - vt_cross = 1 + if string.strncmp(resolved_stg_entry.ModuleSha1, trans.ModuleSha1, 16) != 0: vt_cross = 1 if vt_cross != 0 and self.Gen.ExprGenAttr.find_global_in_module(mod, vt_mangled) is None: vt_decl_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) vt_gv: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, vt_mangled, vt_decl_ty) - if vt_gv is not None: - mlirlite.module_add_global(mod, vt_gv) + if vt_gv is not None: mlirlite.module_add_global(mod, vt_gv) # 完整 struct 初始化器(LLVM 拒绝部分初始化): # 字段 0 = __vtable__(i8* @vtable),其余用户字段按类型零值。 init_full_len: sizet = 16384 @@ -1077,10 +979,8 @@ novirtual class TranslatorGenMixin: if init_full is not None: written_v: int = viperlib.snprintf(init_full, init_full_len, "{ ") pos_v: sizet = sizet(written_v) - if self.Gen.ClassGenVTable._vtable_name_needs_quote(vt_mangled) != 0: - written_v = viperlib.snprintf(init_full + pos_v, init_full_len - pos_v, "i8* @\"%s\"", vt_mangled) - else: - written_v = viperlib.snprintf(init_full + pos_v, init_full_len - pos_v, "i8* @%s", vt_mangled) + if self.Gen.ClassGenVTable._vtable_name_needs_quote(vt_mangled) != 0: written_v = viperlib.snprintf(init_full + pos_v, init_full_len - pos_v, "i8* @\"%s\"", vt_mangled) + else: written_v = viperlib.snprintf(init_full + pos_v, init_full_len - pos_v, "i8* @%s", vt_mangled) pos_v += sizet(written_v) # 字段 1..N 优先按字段默认值折叠(vtable 对象全局 # 如 `_mbuddy: MemBuddy` 的字段默认不再丢失); @@ -1094,15 +994,12 @@ novirtual class TranslatorGenMixin: fc_v: int = resolved_stg_entry.FieldCount for fi_v in range(1, fc_v): fe_v: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(resolved_stg_entry, fi_v) - if fe_v is None or fe_v.Ty is None: - continue + if fe_v is None or fe_v.Ty is None: continue ty_buf_v: str = pool.alloc(512) - if ty_buf_v is None: - continue + if ty_buf_v is None: continue mlirlite.TypePrint(ty_buf_v, 512, fe_v.Ty, pool) zero_v: str = self._stg_field_zero_text(pool, fe_v.Ty, ty_buf_v) - if zero_v is None: - continue + if zero_v is None: continue written_v = viperlib.snprintf(init_full + pos_v, init_full_len - pos_v, ", %s", zero_v) pos_v += sizet(written_v) viperlib.snprintf(init_full + pos_v, init_full_len - pos_v, " }") @@ -1112,8 +1009,7 @@ novirtual class TranslatorGenMixin: # 一律 zeroinitializer 会丢掉全部字段默认值(模块级 X: T = T() 的构造调用 # 不发射)。无任何非零默认值时返回 None → 保持 zeroinitializer(零开销)。 stg_default_text: str = self._build_stg_struct_init_text(pool, resolved_stg_entry, 0) - if stg_default_text is not None: - stg_init_text = stg_default_text + if stg_default_text is not None: stg_init_text = stg_default_text stg_name_len: sizet = sizet(string.strlen(mangled_name)) + 8 stg_name_buf: str = pool.alloc(stg_name_len) if stg_name_buf is not None: @@ -1124,16 +1020,13 @@ novirtual class TranslatorGenMixin: stg_gv.Linkage = None stg_gv.Initializer = stg_init_text # B5:storage(BSS 对象实例)同样施加 aligned 对齐 - if resolved_stg_entry is not None and resolved_stg_entry.Align > 0: - stg_gv.Align = resolved_stg_entry.Align + if resolved_stg_entry is not None and resolved_stg_entry.Align > 0: stg_gv.Align = resolved_stg_entry.Align # @g 初始值 = &@storage(对象引用指向 BSS 实例,非 NULL) stg_init_len: sizet = sizet(string.strlen(mangled_name)) + 8 stg_init_buf: str = pool.alloc(stg_init_len) if stg_init_buf is not None: - if self.Gen.ClassGenVTable._vtable_name_needs_quote(stg_name_buf) != 0: - viperlib.snprintf(stg_init_buf, stg_init_len, "@\"%s\"", stg_name_buf) - else: - viperlib.snprintf(stg_init_buf, stg_init_len, "@%s", stg_name_buf) + if self.Gen.ClassGenVTable._vtable_name_needs_quote(stg_name_buf) != 0: viperlib.snprintf(stg_init_buf, stg_init_len, "@\"%s\"", stg_name_buf) + else: viperlib.snprintf(stg_init_buf, stg_init_len, "@%s", stg_name_buf) gv.Initializer = stg_init_buf # 注册 storage 引用(key: var_name.__stg),供 AssignGenMixin # 全局赋值分支检测对象类全局并复制对象到 storage。 @@ -1150,10 +1043,8 @@ novirtual class TranslatorGenMixin: ref_name: str = pool.alloc(96) if ref_name is not None: # mangled 名带 SHA1 前缀(数字开头),引用必须加引号(对齐 make_global_ref) - if self.Gen.ClassGenVTable._vtable_name_needs_quote(mangled_name) != 0: - viperlib.snprintf(ref_name, 96, "@\"%s\"", mangled_name) - else: - viperlib.snprintf(ref_name, 96, "@%s", mangled_name) + if self.Gen.ClassGenVTable._vtable_name_needs_quote(mangled_name) != 0: viperlib.snprintf(ref_name, 96, "@\"%s\"", mangled_name) + else: viperlib.snprintf(ref_name, 96, "@%s", mangled_name) gv_ref: mlirlite.Value* = mlirlite.SSAValue(pool, var_ptr_ty, ref_name) # 注册到模块作用域 @@ -1165,23 +1056,19 @@ novirtual class TranslatorGenMixin: # const 对象全局:注解含 t.CConst 且类型非指针 ⇒ 登记 IsConst, # 之后对该全局名的赋值/增量赋值/元素赋值 fail-fast(判据同 TPC # 的 Gen.global_const_flags,见 Debugger/type-descriptors.md)。 - if self.Gen.TypeGenErr.is_const_object_marker(annot_node, var_ty) != 0: - self.Gen.VarGen.set_var_const(trans.SymTab, var_name) - if self.Gen.TypeGenErr.has_decorator_marker(annot_node, "CVolatile", 0) != 0: - self.Gen.VarGen.set_var_volatile(trans.SymTab, var_name) + if self.Gen.TypeGenErr.is_const_object_marker(annot_node, var_ty) != 0: self.Gen.VarGen.set_var_const(trans.SymTab, var_name) + if self.Gen.TypeGenErr.has_decorator_marker(annot_node, "CVolatile", 0) != 0: self.Gen.VarGen.set_var_volatile(trans.SymTab, var_name) # rawptr[t.CVolatile | T](volatile 指针指向物):解引用(p[i]/ # p.field/c.Deref(p))的 load/store 带 volatile。与上一分支互斥: # 前者是变量自身限定(BinOp 联合),后者是 rawptr 下标实参标记。 - if self.Gen.TypeGenErr.has_pointee_volatile_marker(annot_node) != 0: - self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, var_name) + if self.Gen.TypeGenErr.has_pointee_volatile_marker(annot_node) != 0: self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, var_name) # 设置 AnnotClassName(联合类型如 Logger* 简化为 Ptr(i8) 时, # 属性访问需要通过 AnnotClassName 回退到类名查找结构体) if k == ast.ASTKind.AnnAssign: aa_ml: ast.AnnAssign* = ast.AnnAssign*(node) if aa_ml is not None and aa_ml.annotation is not None: cls_nm_ml: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(aa_ml.annotation, trans._imported_modules, pool, trans._from_imports) - if cls_nm_ml is not None: - self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, var_name, cls_nm_ml) + if cls_nm_ml is not None: self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, var_name, cls_nm_ml) # 模块级 str* / bytes* 全局:标记 IsPtrElement # (i8** 语义,var[i] 按 8 字节指针步长),对齐 TPC 的 # global_var_ptr_element(_argv 等字符串指针数组)。否则 @@ -1247,16 +1134,14 @@ novirtual class TranslatorGenMixin: child: ast.AST* = ch.get(ci) if child is not None: kd: int = child.kind() - if kd == ast.ASTKind.AnnAssign or kd == ast.ASTKind.Assign: - self.handle_module_level_var(trans, child) + if kd == ast.ASTKind.AnnAssign or kd == ast.ASTKind.Assign: self.handle_module_level_var(trans, child) # 预扫描顶层语句:为函数内 AnnAssign 提前创建 alloca # (模块级变量已在上面注册到模块作用域,PreScan 的 lookup_current 会跳过它们) if ch is not None: for ci in range(cn_count): child: ast.AST* = ch.get(ci) - if child is not None: - self.Gen.StmtGenDecl.pre_scan_allocas(trans, child) + if child is not None: self.Gen.StmtGenDecl.pre_scan_allocas(trans, child) # 翻译子节点 added_total: int = self.translate_children(trans, tree) @@ -1272,23 +1157,18 @@ novirtual class TranslatorGenMixin: # ============================================================ def add_global_name(self, trans: HT.Translator*, name: str): """添加一个 global 变量名""" - if trans is None or name is None: - return - if trans._global_names is None: - return + if trans is None or name is None: return + if trans._global_names is None: return # 检查是否已存在 - if self.is_global_name(trans, name) != 0: - return + if self.is_global_name(trans, name) != 0: return if trans._global_name_count >= HT.MAX_GLOBAL_NAMES: pool_err: memhub.MemBuddy* = trans.Pool err_buf: str = None - if pool_err is not None: - err_buf = pool_err.alloc(256) + 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) VLogger.error(err_buf, "ScopeDecl") - else: - VLogger.error("global 变量数量超过上限,请减少 global 声明或增大 MAX_GLOBAL_NAMES", "ScopeDecl") + else: VLogger.error("global 变量数量超过上限,请减少 global 声明或增大 MAX_GLOBAL_NAMES", "ScopeDecl") return entry_addr: uint64 = uint64(trans._global_names) + trans._global_name_count * 8 slot_ptr: str* = (str*)(entry_addr) @@ -1297,15 +1177,13 @@ novirtual class TranslatorGenMixin: def is_global_name(self, trans: HT.Translator*, name: str) -> int: """检查 name 是否在当前函数的 global 集合中""" - if trans is None or name is None or trans._global_names is None: - return 0 + if trans is None or name is None or trans._global_names is None: return 0 for i in range(trans._global_name_count): entry_addr: uint64 = uint64(trans._global_names) + i * 8 slot_ptr: str* = (str*)(entry_addr) entry: str = slot_ptr[0] if entry is not None: - if string.strcmp(entry, name) == 0: - return 1 + if string.strcmp(entry, name) == 0: return 1 return 0 def add_nonlocal_name(self, trans: HT.Translator*, name: str, @@ -1317,10 +1195,8 @@ novirtual class TranslatorGenMixin: var_ty: 变量的 LLVM 类型(用于 env 指针数组方案的类型恢复, None 时回退为 i32) """ - if trans is None or name is None: - return - if trans._nonlocal_names is None: - return + if trans is None or name is None: return + if trans._nonlocal_names is None: return if self.is_nonlocal_name(trans, name) != 0: # 已存在:更新类型信息(可能在预扫描时类型未知,正式翻译时更新) # _nonlocal_types 每槽 8 字节,存 LLVMType* 指针。 @@ -1336,13 +1212,11 @@ novirtual class TranslatorGenMixin: if trans._nonlocal_name_count >= HT.MAX_GLOBAL_NAMES: pool_err_nl: memhub.MemBuddy* = trans.Pool err_buf_nl: str = None - if pool_err_nl is not None: - err_buf_nl = pool_err_nl.alloc(256) + 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) VLogger.error(err_buf_nl, "ScopeDecl") - else: - VLogger.error("nonlocal 变量数量超过上限,请减少 nonlocal 声明或增大 MAX_GLOBAL_NAMES", "ScopeDecl") + else: VLogger.error("nonlocal 变量数量超过上限,请减少 nonlocal 声明或增大 MAX_GLOBAL_NAMES", "ScopeDecl") return entry_addr: uint64 = uint64(trans._nonlocal_names) + trans._nonlocal_name_count * 8 slot_ptr: str* = (str*)(entry_addr) @@ -1366,45 +1240,38 @@ novirtual class TranslatorGenMixin: Returns: 找到的类型指针,找不到返回 None """ - if trans is None or name is None or trans._nonlocal_types is None: - return None + if trans is None or name is None or trans._nonlocal_types is None: return None idx: int = self.get_nonlocal_index(trans, name) - if idx < 0: - return None + if idx < 0: return None ty_addr: uint64 = uint64(trans._nonlocal_types) + idx * 8 ty_slot: str* = (str*)(ty_addr) return (mlirlite.LLVMType*)(ty_slot[0]) def is_nonlocal_name(self, trans: HT.Translator*, name: str) -> int: """检查 name 是否在当前函数的 nonlocal 集合中""" - if trans is None or name is None or trans._nonlocal_names is None: - return 0 + if trans is None or name is None or trans._nonlocal_names is None: return 0 for i in range(trans._nonlocal_name_count): entry_addr: uint64 = uint64(trans._nonlocal_names) + i * 8 slot_ptr: str* = (str*)(entry_addr) entry: str = slot_ptr[0] if entry is not None: - if string.strcmp(entry, name) == 0: - return 1 + if string.strcmp(entry, name) == 0: return 1 return 0 def get_nonlocal_index(self, trans: HT.Translator*, name: str) -> int: """获取 nonlocal 变量在 env 中的索引(0-based),找不到返回 -1""" - if trans is None or name is None or trans._nonlocal_names is None: - return -1 + if trans is None or name is None or trans._nonlocal_names is None: return -1 for i in range(trans._nonlocal_name_count): entry_addr: uint64 = uint64(trans._nonlocal_names) + i * 8 slot_ptr: str* = (str*)(entry_addr) entry: str = slot_ptr[0] if entry is not None: - if string.strcmp(entry, name) == 0: - return i + if string.strcmp(entry, name) == 0: return i return -1 def clear_scope_names(self, trans: HT.Translator*): """清空当前函数的 global/nonlocal 名称集合(进入新函数时调用)""" - if trans is None: - return + if trans is None: return trans._global_name_count = 0 trans._nonlocal_name_count = 0 trans._closure_env_count = 0 diff --git a/App/lib/core/Gen/Type/TypeGenBase.vp b/App/lib/core/Gen/Type/TypeGenBase.vp index 8ce06ce..69e9962 100644 --- a/App/lib/core/Gen/Type/TypeGenBase.vp +++ b/App/lib/core/Gen/Type/TypeGenBase.vp @@ -282,8 +282,7 @@ novirtual class TypeGenBase: 用于表达式中的 T 替换(如 T.__sizeof__() → int.__sizeof__()) """ - if name is None: - return name + if name is None: return name rv_d: str = name if self.GenericTpNames is not None and self.GenericTypeArgs is not None: rg_n: sizet = len(self.GenericTpNames) diff --git a/App/lib/core/Gen/Type/TypeGenCDef.vp b/App/lib/core/Gen/Type/TypeGenCDef.vp index 4ddde2a..568b228 100644 --- a/App/lib/core/Gen/Type/TypeGenCDef.vp +++ b/App/lib/core/Gen/Type/TypeGenCDef.vp @@ -41,8 +41,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): def _cdef_idx_hash(self, name: str) -> uint64: """名 → 64 位哈希(32 位 FNV-1a,逐字节到 NUL 结束)""" h: uint64 = uint64(CDEF_IDX_FNV_OFFSET) - if name is None: - return h + if name is None: return h i: sizet = 0 while name[i] != '\0': h = (h ^ uint64(int(name[i]))) * uint64(CDEF_IDX_FNV_PRIME) @@ -69,10 +68,8 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): def _cdef_idx_find(self, name: str) -> int: """在名索引中探测 name,返回命中槽下标(>=0);未命中/不可用返回 -1""" - if self.CDefineNameIdx is None or self.CDefineNameIdxCap <= 0 or name is None: - return -1 - if self.CDefineNameIdxBuilt != int(len(self.CDefineNames)): - return -1 + if self.CDefineNameIdx is None or self.CDefineNameIdxCap <= 0 or name is None: return -1 + if self.CDefineNameIdxBuilt != int(len(self.CDefineNames)): return -1 h: uint64 = self._cdef_idx_hash(name) mask: sizet = sizet(self.CDefineNameIdxCap - 1) si: sizet = sizet(h) & mask @@ -80,20 +77,17 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): while i < self.CDefineNameIdxCap: slot: sizet* = self._cdef_idx_slot(si) sv: sizet = slot[0] - if sv == 0: - return -1 + if sv == 0: return -1 se: int = int(sv) - 1 nm: str = self.CDefineNames.get(sizet(se)) - if nm is not None and string.strcmp(nm, name) == 0: - return se + if nm is not None and string.strcmp(nm, name) == 0: return se si = (si + 1) & mask i += 1 return -1 def _cdef_idx_insert(self, slot_index: int, name: str) -> int: """把 (name → slot_index) 记入索引;0=成功 / 1=失败""" - if self.CDefineNameIdx is None or self.CDefineNameIdxCap <= 0 or name is None: - return 1 + if self.CDefineNameIdx is None or self.CDefineNameIdxCap <= 0 or name is None: return 1 h: uint64 = self._cdef_idx_hash(name) mask: sizet = sizet(self.CDefineNameIdxCap - 1) si: sizet = sizet(h) & mask @@ -110,10 +104,8 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): def _cdef_idx_sync_append(self, name: str) -> None: """CDefineNames.append 后同步索引(槽下标 = len-1);不可信则保持不可信""" n: int = int(len(self.CDefineNames)) - if self.CDefineNameIdxBuilt == n - 1 and self._cdef_idx_insert(n - 1, name) == 0: - self.CDefineNameIdxBuilt = n - else: - self.CDefineNameIdxBuilt = -1 + if self.CDefineNameIdxBuilt == n - 1 and self._cdef_idx_insert(n - 1, name) == 0: self.CDefineNameIdxBuilt = n + else: self.CDefineNameIdxBuilt = -1 # ============================================================ # CDefine 表本体的池归一 @@ -132,8 +124,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): def _cdefine_table_pool(self, pool: memhub.MemBuddy*) -> memhub.MemBuddy*: """CDefine 表本体的池:恒取 PermPool(不可用则退回入参 pool)""" - if CompilerFactory.factory is not None and CompilerFactory.factory.PermPool is not None: - return CompilerFactory.factory.PermPool + if CompilerFactory.factory is not None and CompilerFactory.factory.PermPool is not None: return CompilerFactory.factory.PermPool return pool def register_cdefine_constant(self, pool: memhub.MemBuddy*, @@ -152,8 +143,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): 悬空名:之后 lookup 的 strcmp 若命中被回收/复用内存里恰好出现的同名文本, 就会返回别的条目的值(Phase1.SHA1_LEN=17 被读成 0 的根因)。 """ - if name is None: - return + if name is None: return if self.CDefineNames is None: tp: memhub.MemBuddy* = self._cdefine_table_pool(pool) tn: list[str]* = list[str](tp, 64) @@ -186,16 +176,12 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): if val_buf is not None: viperlib.snprintf(val_buf, 32, "%lld", value) self.CDefineValues.append(val_buf) - else: - self.CDefineValues.append("0") + else: self.CDefineValues.append("0") # fail-fast:CDefine 值缓冲区分配失败必须终止编译 # (与浮点/字符串分支口径一致,不再静默写 "0" 污染常量表) - if val_buf is None: - self.Gen.TypeGenErr.fatal_error(None, f"CDefine '{name}' 值缓冲区分配失败", "MemoryError") - if self.CDefineDoubleFlags is not None: - self.CDefineDoubleFlags.append(0) - if self.CDefineStrFlags is not None: - self.CDefineStrFlags.append(0) + if val_buf is None: self.Gen.TypeGenErr.fatal_error(None, f"CDefine '{name}' 值缓冲区分配失败", "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: """注册浮点 CDefine 编译期常量(如 U_M_PI: t.CDefine = 3.14159...) @@ -205,8 +191,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): 名称同样深拷贝到 pool(理由见 register_cdefine_constant:注入 .vpi 时 Name.id 指向的 vpi_buf 会被释放,只存指针会留下悬空名)。 """ - if name is None: - return + if name is None: return if self.CDefineNames is None: tp: memhub.MemBuddy* = self._cdefine_table_pool(pool) tn: list[str]* = list[str](tp, 64) @@ -239,12 +224,9 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): # 位模式 %a 正确),会导致 CDefine 表存错文本 → lookup 生成错 LLVM 常量。 stdio.snprintf(val_buf, 32, "%.17g", value) self.CDefineValues.append(val_buf) - else: - self.CDefineValues.append("0") - if self.CDefineDoubleFlags is not None: - self.CDefineDoubleFlags.append(1) - if self.CDefineStrFlags is not None: - self.CDefineStrFlags.append(0) + else: self.CDefineValues.append("0") + if self.CDefineDoubleFlags is not None: self.CDefineDoubleFlags.append(1) + if self.CDefineStrFlags is not None: self.CDefineStrFlags.append(0) # fail-fast:CDefine 值缓冲区分配失败必须终止编译, if val_buf is None: VLogger.error("CDefine 浮点值缓冲区分配失败", "CDEF-DBG") @@ -257,8 +239,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): 与浮点 CDefine 的恢复同理)。名称同样深拷贝(理由见 register_cdefine_constant:注入 .vpi 的 Name.id 指向会被释放的 vpi_buf)。 """ - if pool is None or name is None: - return + if pool is None or name is None: return if value is None: self.Gen.TypeGenErr.fatal_error(None, f"CDefine 字符串值缺失: {name}", "InternalCompilerError") return @@ -294,10 +275,8 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): return string.strcpy(vcopy, value) self.CDefineValues.append(vcopy) - if self.CDefineDoubleFlags is not None: - self.CDefineDoubleFlags.append(0) - if self.CDefineStrFlags is not None: - self.CDefineStrFlags.append(1) + if self.CDefineDoubleFlags is not None: self.CDefineDoubleFlags.append(0) + if self.CDefineStrFlags is not None: self.CDefineStrFlags.append(1) # 同步设置"最近注册/查表结果为字符串"标志(is_cdefine_str() 读取)。 # 跨模块字符串 CDefine 读回只调本函数 + 尾部 set_cdefine_found;不设标志会让 # 属性路径 is_cdefine_str()==0 → 退化为整数分支返回 0 → IR 生成 inttoptr i32 0 @@ -317,16 +296,14 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): is_double: 1=浮点值 is_str: 1=字符串值 """ - if name is None or value_str is None: - return + if name is None or value_str is None: return # 去重:同名已缓存则跳过(首次查找结果为准,CDefine 全局唯一约定) if self.XmodCdefNames is not None: x_n: sizet = len(self.XmodCdefNames) x_i: sizet for x_i in range(x_n): x_nm: str = self.XmodCdefNames.get(x_i) - if x_nm is not None and string.strcmp(x_nm, name) == 0: - return + if x_nm is not None and string.strcmp(x_nm, name) == 0: return perm: memhub.MemBuddy* = CompilerFactory.factory.PermPool if self.XmodCdefNames is None: self.XmodCdefNames = list[str](perm, 64) @@ -337,20 +314,16 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): # reset_to(mark2) 后悬空,append 只存指针 → 必须深拷贝跨 reset 存活 klen: sizet = string.strlen(name) kcopy: str = perm.alloc(klen + 1) - if kcopy is None: - return + if kcopy is None: return string.strcpy(kcopy, name) vlen: sizet = string.strlen(value_str) vcopy: str = perm.alloc(vlen + 1) - if vcopy is None: - return + if vcopy is None: return string.strcpy(vcopy, value_str) self.XmodCdefNames.append(kcopy) self.XmodCdefValues.append(vcopy) - if self.XmodCdefDoubleFlags is not None: - self.XmodCdefDoubleFlags.append(is_double) - if self.XmodCdefStrFlags is not None: - self.XmodCdefStrFlags.append(is_str) + if self.XmodCdefDoubleFlags is not None: self.XmodCdefDoubleFlags.append(is_double) + if self.XmodCdefStrFlags is not None: self.XmodCdefStrFlags.append(is_str) def lookup_xmod_cdefine(self, name: str) -> str: """查找跨模块 CDefine 缓存,命中设置 found/is_double/is_str 标志 @@ -360,8 +333,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): self.CDefineFound = 0 self.CDefineIsDouble = 0 self.CDefineIsStr = 0 - if name is None or self.XmodCdefNames is None: - return None + if name is None or self.XmodCdefNames is None: return None n: sizet = len(self.XmodCdefNames) i: sizet for i in range(n): @@ -370,10 +342,8 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): val_str: str = self.XmodCdefValues.get(i) if val_str is not None: self.CDefineFound = 1 - if self.XmodCdefStrFlags is not None and self.XmodCdefStrFlags.get(i) == 1: - self.CDefineIsStr = 1 - elif self.XmodCdefDoubleFlags is not None and self.XmodCdefDoubleFlags.get(i) == 1: - self.CDefineIsDouble = 1 + if self.XmodCdefStrFlags is not None and self.XmodCdefStrFlags.get(i) == 1: self.CDefineIsStr = 1 + elif self.XmodCdefDoubleFlags is not None and self.XmodCdefDoubleFlags.get(i) == 1: self.CDefineIsDouble = 1 return val_str return None def lookup_cdefine_constant(self, name: str) -> int64: @@ -388,8 +358,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): self.CDefineFound = 0 self.CDefineIsDouble = 0 self.CDefineIsStr = 0 - if self.CDefineNames is None: - return 0 + if self.CDefineNames is None: return 0 n: sizet = len(self.CDefineNames) i: sizet # 名索引快速路径:可信(Built==n | 查询名非空)时直接定位唯一候选下标 @@ -400,8 +369,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): cd_end: sizet = n if name is not None and self.CDefineNameIdxBuilt == int(n) and self.CDefineNameIdx is not None and self.CDefineNameIdxCap > 0: cd_hit: int = self._cdef_idx_find(name) - if cd_hit < 0: - return 0 + if cd_hit < 0: return 0 cd_start = sizet(cd_hit) cd_end = sizet(cd_hit + 1) for i in range(cd_start, cd_end): @@ -429,8 +397,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): self.CDefineFound = 0 self.CDefineIsDouble = 0 self.CDefineIsStr = 0 - if self.CDefineNames is None: - return 0.0 + if self.CDefineNames is None: return 0.0 n: sizet = len(self.CDefineNames) i: sizet # 名索引快速路径:可信(Built==n | 查询名非空)时直接定位唯一候选下标 @@ -441,8 +408,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): cd_end: sizet = n if name is not None and self.CDefineNameIdxBuilt == int(n) and self.CDefineNameIdx is not None and self.CDefineNameIdxCap > 0: cd_hit: int = self._cdef_idx_find(name) - if cd_hit < 0: - return 0.0 + if cd_hit < 0: return 0.0 cd_start = sizet(cd_hit) cd_end = sizet(cd_hit + 1) for i in range(cd_start, cd_end): @@ -471,8 +437,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): self.CDefineFound = 0 self.CDefineIsDouble = 0 self.CDefineIsStr = 0 - if self.CDefineNames is None: - return None + if self.CDefineNames is None: return None n: sizet = len(self.CDefineNames) i: sizet # 名索引快速路径:可信(Built==n | 查询名非空)时直接定位唯一候选下标 @@ -483,8 +448,7 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): cd_end: sizet = n if name is not None and self.CDefineNameIdxBuilt == int(n) and self.CDefineNameIdx is not None and self.CDefineNameIdxCap > 0: cd_hit: int = self._cdef_idx_find(name) - if cd_hit < 0: - return None + if cd_hit < 0: return None cd_start = sizet(cd_hit) cd_end = sizet(cd_hit + 1) for i in range(cd_start, cd_end): @@ -522,14 +486,10 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): - 空表与既有语义完全等价:lookup 命中空表即"未命中", register 首次 append 即写回第 0 槽。 """ - if self.CDefineNames is not None: - self.CDefineNames.clear() - if self.CDefineValues is not None: - self.CDefineValues.clear() - if self.CDefineDoubleFlags is not None: - self.CDefineDoubleFlags.clear() - if self.CDefineStrFlags is not None: - self.CDefineStrFlags.clear() + if self.CDefineNames is not None: self.CDefineNames.clear() + if self.CDefineValues is not None: self.CDefineValues.clear() + if self.CDefineDoubleFlags is not None: self.CDefineDoubleFlags.clear() + if self.CDefineStrFlags is not None: self.CDefineStrFlags.clear() # 名索引清槽(槽存 index+1,0=空槽)+ Built 归零(空表与索引同步; # 与"新建表后首次 register"的索引状态逐字一致) if self.CDefineNameIdx is not None and self.CDefineNameIdxCap > 0: diff --git a/App/lib/core/Gen/Type/TypeGenCType.vp b/App/lib/core/Gen/Type/TypeGenCType.vp index 5059760..bd011f8 100644 --- a/App/lib/core/Gen/Type/TypeGenCType.vp +++ b/App/lib/core/Gen/Type/TypeGenCType.vp @@ -84,10 +84,8 @@ class TypeGenCType(TypeGenBase.TypeGenBase): def _ctypedef_idx_find(self, name: str) -> int: """在名索引中探测 name,返回命中槽下标(>=0);未命中/不可用返回 -1""" - if self.CTypedefNameIdx is None or self.CTypedefNameIdxCap <= 0 or name is None: - return -1 - if self.CTypedefNameIdxBuilt != int(len(self.CTypedefNames)): - return -1 + if self.CTypedefNameIdx is None or self.CTypedefNameIdxCap <= 0 or name is None: return -1 + if self.CTypedefNameIdxBuilt != int(len(self.CTypedefNames)): return -1 h: uint64 = _ctypedef_idx_hash(name) mask: sizet = sizet(self.CTypedefNameIdxCap - 1) si: sizet = sizet(h) & mask @@ -95,20 +93,17 @@ class TypeGenCType(TypeGenBase.TypeGenBase): while i < self.CTypedefNameIdxCap: slot: sizet* = self._ctypedef_idx_slot(si) sv: sizet = slot[0] - if sv == 0: - return -1 + if sv == 0: return -1 se: int = int(sv) - 1 nm: str = self.CTypedefNames.get(sizet(se)) - if nm is not None and string.strcmp(nm, name) == 0: - return se + if nm is not None and string.strcmp(nm, name) == 0: return se si = (si + 1) & mask i += 1 return -1 def _ctypedef_idx_insert(self, slot_index: int, name: str) -> int: """把 (name → slot_index) 记入索引;0=成功 / 1=失败""" - if self.CTypedefNameIdx is None or self.CTypedefNameIdxCap <= 0 or name is None: - return 1 + if self.CTypedefNameIdx is None or self.CTypedefNameIdxCap <= 0 or name is None: return 1 h: uint64 = _ctypedef_idx_hash(name) mask: sizet = sizet(self.CTypedefNameIdxCap - 1) si: sizet = sizet(h) & mask @@ -125,10 +120,8 @@ class TypeGenCType(TypeGenBase.TypeGenBase): def _ctypedef_idx_sync_append(self, name: str) -> None: """CTypedefNames.append 后同步索引(槽下标 = len-1);不可信则保持不可信""" n: int = int(len(self.CTypedefNames)) - if self.CTypedefNameIdxBuilt == n - 1 and self._ctypedef_idx_insert(n - 1, name) == 0: - self.CTypedefNameIdxBuilt = n - else: - self.CTypedefNameIdxBuilt = -1 + if self.CTypedefNameIdxBuilt == n - 1 and self._ctypedef_idx_insert(n - 1, name) == 0: self.CTypedefNameIdxBuilt = n + else: self.CTypedefNameIdxBuilt = -1 # ============================================================ # CTypedef 表本体的池归一 @@ -147,8 +140,7 @@ class TypeGenCType(TypeGenBase.TypeGenBase): def _ctypedef_table_pool(self, pool: memhub.MemBuddy*) -> memhub.MemBuddy*: """CTypedef 表本体的池:恒取 PermPool(不可用则退回入参 pool)""" - if CompilerFactory.factory is not None and CompilerFactory.factory.PermPool is not None: - return CompilerFactory.factory.PermPool + if CompilerFactory.factory is not None and CompilerFactory.factory.PermPool is not None: return CompilerFactory.factory.PermPool return pool def register_ctypedef(self, pool: memhub.MemBuddy*, @@ -160,26 +152,22 @@ class TypeGenCType(TypeGenBase.TypeGenBase): name: CTypedef 名称(如 "HANDLE") type_str: 类型表达式字符串(如 "VOIDPTR" 或 "t.CPtr") """ - if name is None or type_str is None or pool is None: - return + if name is None or type_str is None or pool is None: return # rawptr 是编译器内置语法(TPC/TPV 双端),不可重定义: # 忽略任何对 rawptr 的 typedef 注册,防止覆盖内置裸指针语义 # (rawptr[T] 固定 = 指向原始类型 T 的裸指针)。 - if string.strcmp(name, "rawptr") == 0: - return + if string.strcmp(name, "rawptr") == 0: return # 复制 name/type_str 到 pool:调用方可能传入零拷贝 AST 字符串 # (如 .vpi 读取缓冲区),缓冲区随后被 free 会导致表项悬空、 # lookup_ctypedef strcmp 失配、typedef 退化为 i8*(testcheck # SetConsoleOutputCP 的 UINT 根因)。表须持有自己的字符串副本。 name_len: sizet = string.strlen(name) name_copy: str = pool.alloc(name_len + 1) - if name_copy is None: - return + if name_copy is None: return string.strcpy(name_copy, name) type_len: sizet = string.strlen(type_str) type_copy: str = pool.alloc(type_len + 1) - if type_copy is None: - return + if type_copy is None: return string.strcpy(type_copy, type_str) if self.CTypedefNames is None: tp: memhub.MemBuddy* = self._ctypedef_table_pool(pool) @@ -220,26 +208,20 @@ class TypeGenCType(TypeGenBase.TypeGenBase): heap-use-after-free)。诊断字段必须持有自己的副本。 text 为 None 时返回 None("未命中"标记)。 """ - if text is None: - return None + if text is None: return None # 诊断串按需 realloc 到精确长度:固定 TYPEDEF_DIAG_BUF(256) + strncpy(buf, text, 255) # 会静默截断超长诊断串 ⇒ 报错文本丢掉关键名字(归因信息失效)。 # 缓冲仍为自有字段(生命周期不变:仍在 reset/析构时统一 stdlib.free)。 need: sizet = string.strlen(text) + 1 if which == 0: - if self.LastBuiltinsTypedefNameBuf is None: - self.LastBuiltinsTypedefNameBuf = stdlib.malloc(need) - else: - self.LastBuiltinsTypedefNameBuf = stdlib.realloc(self.LastBuiltinsTypedefNameBuf, need) + if self.LastBuiltinsTypedefNameBuf is None: self.LastBuiltinsTypedefNameBuf = stdlib.malloc(need) + else: self.LastBuiltinsTypedefNameBuf = stdlib.realloc(self.LastBuiltinsTypedefNameBuf, need) buf: str = self.LastBuiltinsTypedefNameBuf else: - if self.LastBuiltinsTypedefResultBuf is None: - self.LastBuiltinsTypedefResultBuf = stdlib.malloc(need) - else: - self.LastBuiltinsTypedefResultBuf = stdlib.realloc(self.LastBuiltinsTypedefResultBuf, need) + if self.LastBuiltinsTypedefResultBuf is None: self.LastBuiltinsTypedefResultBuf = stdlib.malloc(need) + else: self.LastBuiltinsTypedefResultBuf = stdlib.realloc(self.LastBuiltinsTypedefResultBuf, need) buf = self.LastBuiltinsTypedefResultBuf - if buf is None: - return None + if buf is None: return None string.strcpy(buf, text) return buf @@ -250,10 +232,8 @@ class TypeGenCType(TypeGenBase.TypeGenBase): 调用方应在调用后检查 _g_ctypedef_found 标志区分"未找到"和"空字符串"。 """ self.CTypedefFound = 0 - if name is None: - return None - if self.CTypedefNames is None: - return None + if name is None: return None + if self.CTypedefNames is None: return None n: sizet = len(self.CTypedefNames) i: sizet # 名索引快速路径:可信(Built==n)时直接定位唯一候选槽下标。CTypedef 表 @@ -262,8 +242,7 @@ class TypeGenCType(TypeGenBase.TypeGenBase): # (= 原全表扫描结果);索引不可用/不可信 → 回退下方原全表扫描。 if self.CTypedefNameIdxBuilt == int(n) and self.CTypedefNameIdx is not None and self.CTypedefNameIdxCap > 0: ti: int = self._ctypedef_idx_find(name) - if ti < 0: - return None + if ti < 0: return None ts_hit: str = self.CTypedefTypeStrs.get(sizet(ti)) self.CTypedefFound = 1 return ts_hit @@ -284,21 +263,17 @@ class TypeGenCType(TypeGenBase.TypeGenBase): 未命中返回 None(CTypedefFound=0)。用于符号性独立真源的别名链展开。 """ self.CTypedefFound = 0 - if text is None or end <= start: - return None - if self.CTypedefNames is None: - return None + if text is None or end <= start: return None + if self.CTypedefNames is None: return None want: sizet = end - start n: sizet = len(self.CTypedefNames) i: sizet for i in range(n): nm: str = self.CTypedefNames.get(i) - if nm is None: - continue + if nm is None: continue # 快速路径:命中要求 nm[0]==text[start](逐字节比较的 k=0 项), # 首字节不同者无需 strlen 即可判定不命中(不影响任何原命中项)。 - if nm[0] != text[start] or string.strlen(nm) != want: - continue + if nm[0] != text[start] or string.strlen(nm) != want: continue hit: int = 1 k: sizet = 0 while k < want: @@ -319,8 +294,7 @@ class TypeGenCType(TypeGenBase.TypeGenBase): # uint32),且多层别名(WCHAR→WORD→uint16)漏判。 def spec_sign_of_annot(self, text: str, depth: int = 0) -> int: """按注解文本判定其整数值符号性(独立真源),未覆盖返回 TS_SIGN_UNKNOWN""" - if text is None or depth > 16: - return TSpec.TS_SIGN_UNKNOWN + if text is None or depth > 16: return TSpec.TS_SIGN_UNKNOWN return self._spec_sign_of_span(text, 0, string.strlen(text), depth) def _spec_sign_of_span(self, text: str, start: sizet, end: sizet, depth: int) -> int: @@ -330,20 +304,15 @@ class TypeGenCType(TypeGenBase.TypeGenBase): i: sizet = start while i <= end: is_split: int = 0 - if i == end: - is_split = 1 - elif text[i] == '|' and bracket_depth == 0: - is_split = 1 + if i == end: is_split = 1 + elif text[i] == '|' and bracket_depth == 0: is_split = 1 if is_split != 0: r: int = self._spec_sign_of_segment(text, seg_start, i, depth) - if r != TSpec.TS_SIGN_UNKNOWN: - return r + if r != TSpec.TS_SIGN_UNKNOWN: return r seg_start = i + 1 - elif text[i] == '[' or text[i] == '(': - bracket_depth += 1 + elif text[i] == '[' or text[i] == '(': bracket_depth += 1 elif text[i] == ']' or text[i] == ')': - if bracket_depth > 0: - bracket_depth -= 1 + if bracket_depth > 0: bracket_depth -= 1 i += 1 return TSpec.TS_SIGN_UNKNOWN def _spec_sign_of_segment(self, text: str, start: sizet, end: sizet, @@ -352,32 +321,25 @@ class TypeGenCType(TypeGenBase.TypeGenBase): s: sizet = start e: sizet = end while s < e: - if text[s] != ' ' and text[s] != '\t' and text[s] != '\n': - break + if text[s] != ' ' and text[s] != '\t' and text[s] != '\n': break s += 1 while e > s: - if text[e - 1] != ' ' and text[e - 1] != '\t' and text[e - 1] != '\n': - break + if text[e - 1] != ' ' and text[e - 1] != '\t' and text[e - 1] != '\n': break e -= 1 # 去外层成对括号(如 "(uint32)") while e > s + 1: - if text[s] != '(' or text[e - 1] != ')': - break + if text[s] != '(' or text[e - 1] != ')': break s += 1 e -= 1 while s < e: - if text[s] != ' ' and text[s] != '\t': - break + if text[s] != ' ' and text[s] != '\t': break s += 1 while e > s: - if text[e - 1] != ' ' and text[e - 1] != '\t': - break + if text[e - 1] != ' ' and text[e - 1] != '\t': break e -= 1 - if e <= s: - return TSpec.TS_SIGN_UNKNOWN + if e <= s: return TSpec.TS_SIGN_UNKNOWN # C 指针后缀 '*' → 指针,不表态(指针语义由 PtrLevel 表达) - if text[e - 1] == '*': - return TSpec.TS_SIGN_UNKNOWN + if text[e - 1] == '*': return TSpec.TS_SIGN_UNKNOWN # 泛型/数组/rawptr 下标:IDENT[INNER, ...] → 取 INNER(元素决定值符号性) bracket: sizet = 0 has_bracket: int = 0 @@ -393,36 +355,28 @@ class TypeGenCType(TypeGenBase.TypeGenBase): inner_e: sizet = inner_s d: int = 0 while inner_e < e: - if text[inner_e] == '[' or text[inner_e] == '(': - d += 1 + if text[inner_e] == '[' or text[inner_e] == '(': d += 1 elif text[inner_e] == ']': - if d == 0: - break + if d == 0: break d -= 1 elif text[inner_e] == ')': - if d > 0: - d -= 1 + if d > 0: d -= 1 elif text[inner_e] == ',': - if d == 0: - break + if d == 0: break inner_e += 1 return self._spec_sign_of_span(text, inner_s, inner_e, depth) # 去模块限定前缀:取最后一个 '.' 之后的名字 name_s: sizet = s w: sizet = s while w < e: - if text[w] == '.': - name_s = w + 1 + if text[w] == '.': name_s = w + 1 w += 1 exact: int = TSpec.SpecSignFromTypeNameSpan(text, name_s, e) - if exact != TSpec.TS_SIGN_UNKNOWN: - return exact + if exact != TSpec.TS_SIGN_UNKNOWN: return exact # 精确名未覆盖 → 沿 CTypedef 链展开(depth 限制防环) - if depth >= 16: - return TSpec.TS_SIGN_UNKNOWN + if depth >= 16: return TSpec.TS_SIGN_UNKNOWN ts: str = self.lookup_ctypedef_span(text, name_s, e) - if ts is None or self.CTypedefFound == 0: - return TSpec.TS_SIGN_UNKNOWN + if ts is None or self.CTypedefFound == 0: return TSpec.TS_SIGN_UNKNOWN return self._spec_sign_of_span(ts, 0, string.strlen(ts), depth + 1) def clear_ctypedefs(self) -> None: """清空 CTypedef 表(模块切换时调用) @@ -436,10 +390,8 @@ class TypeGenCType(TypeGenBase.TypeGenBase): - 空表与既有语义完全等价:lookup 命中空表即"未命中", register 首次 append 即写回第 0 槽。 """ - if self.CTypedefNames is not None: - self.CTypedefNames.clear() - if self.CTypedefTypeStrs is not None: - self.CTypedefTypeStrs.clear() + if self.CTypedefNames is not None: self.CTypedefNames.clear() + if self.CTypedefTypeStrs is not None: self.CTypedefTypeStrs.clear() # 名索引清槽(槽存 index+1,0=空槽)+ Built 归零(空表与索引同步; # 与"新建表后首次 register"的索引状态逐字一致) if self.CTypedefNameIdx is not None and self.CTypedefNameIdxCap > 0: @@ -451,8 +403,7 @@ class TypeGenCType(TypeGenBase.TypeGenBase): self.CTypedefNameIdxCap = 0 self.CTypedefNameIdxBuilt = -1 self.CTypedefResolveDepth = 0 - if self.CTypedefVisiting is not None: - self.CTypedefVisiting.clear() + if self.CTypedefVisiting is not None: self.CTypedefVisiting.clear() # builtins 源扫描标记随表清空复位:每文件最多读一次 includes/builtins.vp # (_lookup_builtins_typedef 的"最后匹配"兜底,见 TypeGenResolve) self.BuiltinsTypedefScanned = 0 @@ -460,14 +411,11 @@ class TypeGenCType(TypeGenBase.TypeGenBase): self.LastBuiltinsTypedefResult = None # 别名缓冲 / 诊断缓冲均为 stdlib.malloc 分配,跨 pool 生命周期; # 此处释放防泄漏(诊断缓冲按需再分配) - if self.LastBuiltinsTypedefNameBuf is not None: - stdlib.free(self.LastBuiltinsTypedefNameBuf) + if self.LastBuiltinsTypedefNameBuf is not None: stdlib.free(self.LastBuiltinsTypedefNameBuf) self.LastBuiltinsTypedefNameBuf = None - if self.LastBuiltinsTypedefResultBuf is not None: - stdlib.free(self.LastBuiltinsTypedefResultBuf) + if self.LastBuiltinsTypedefResultBuf is not None: stdlib.free(self.LastBuiltinsTypedefResultBuf) self.LastBuiltinsTypedefResultBuf = None - if self.ImportAliasBuf is not None: - stdlib.free(self.ImportAliasBuf) + if self.ImportAliasBuf is not None: stdlib.free(self.ImportAliasBuf) self.ImportAliasBuf = None def _ctypedef_push_visiting(self, pool: memhub.MemBuddy*, name: str) -> int: """将 CTypedef 名加入正在解析列表(循环检测) @@ -475,15 +423,13 @@ class TypeGenCType(TypeGenBase.TypeGenBase): Returns: 0=成功加入(无循环),1=检测到循环 """ - if name is None: - return 0 + if name is None: return 0 if self.CTypedefVisiting is None: # 与 CTypedef 表同池(PermPool):clear_ctypedefs 只清空、指针不丢, # 避免这张表也落在会被 reset_to 回收的调用方池上 vp: memhub.MemBuddy* = self._ctypedef_table_pool(pool) self.CTypedefVisiting = list[str](vp, 32) - if self.CTypedefVisiting is None: - return 0 + if self.CTypedefVisiting is None: return 0 vn: sizet = len(self.CTypedefVisiting) vi: sizet for vi in range(vn): @@ -494,11 +440,9 @@ class TypeGenCType(TypeGenBase.TypeGenBase): return 0 def _ctypedef_pop_visiting(self) -> None: """从正在解析列表弹出最后一个 CTypedef 名""" - if self.CTypedefVisiting is None: - return + if self.CTypedefVisiting is None: return vn: sizet = len(self.CTypedefVisiting) - if vn > 0: - self.CTypedefVisiting.pop() + if vn > 0: self.CTypedefVisiting.pop() def _is_ctypedef_annotation(self, annotation: ast.AST*) -> int: """检测类型注解是否为 t.CTypedef @@ -508,38 +452,29 @@ class TypeGenCType(TypeGenBase.TypeGenBase): Returns: 1=是 t.CTypedef,0=否 """ - if annotation is None: - return 0 + if annotation is None: return 0 k_v: int = annotation.kind() - if k_v != ast.ASTKind.Attribute: - return 0 + if k_v != ast.ASTKind.Attribute: return 0 at: ast.Attribute* = ast.Attribute*(annotation) # 字段访问改用 ast 模块访问器(直接访问 at.attr 可能按 stub 类型生成错误 GEP, # 读垃圾地址 → strcmp 崩溃)。 at_attr_v: str = ast.attribute_get_attr(at) - if at_attr_v is None: - return 0 + if at_attr_v is None: return 0 # 限长比较替代 strcmp:attr 是零拷贝引用 src_buf 的 token 字符串,可能无 NUL # 结尾("CTypedef" 后紧跟空格/其他字符),strcmp 会读穿到页边界 → 崩溃。 # strncmp 只读 8 字节,再校验第 9 字节为终止/分隔符(防 "CTypedefXXX" 误匹配)。 - if string.strncmp(at_attr_v, "CTypedef", 8) != 0: - return 0 + if string.strncmp(at_attr_v, "CTypedef", 8) != 0: return 0 sep_ch_d: char = at_attr_v[8] - if sep_ch_d != '\0' and sep_ch_d != ' ' and sep_ch_d != '\n' and sep_ch_d != '\r' and sep_ch_d != '\t' and sep_ch_d != '|': - return 0 + if sep_ch_d != '\0' and sep_ch_d != ' ' and sep_ch_d != '\n' and sep_ch_d != '\r' and sep_ch_d != '\t' and sep_ch_d != '|': return 0 at_val_v: ast.AST* = ast.attribute_get_value(at) - if at_val_v is None or at_val_v.kind() != ast.ASTKind.Name: - return 0 + if at_val_v is None or at_val_v.kind() != ast.ASTKind.Name: return 0 mod_nm: ast.Name* = ast.Name*(at_val_v) mod_id_v: str = ast.name_get_id(mod_nm) - if mod_id_v is None: - return 0 + if mod_id_v is None: return 0 # 同样限长比较("t" 无 NUL 结尾时 strcmp 读穿) - if string.strncmp(mod_id_v, "t", 1) != 0: - return 0 + if string.strncmp(mod_id_v, "t", 1) != 0: return 0 sep_ch_m: char = mod_id_v[1] - if sep_ch_m != '\0' and sep_ch_m != ' ' and sep_ch_m != '\n' and sep_ch_m != '\r' and sep_ch_m != '\t' and sep_ch_m != '|': - return 0 + if sep_ch_m != '\0' and sep_ch_m != ' ' and sep_ch_m != '\n' and sep_ch_m != '\r' and sep_ch_m != '\t' and sep_ch_m != '|': return 0 return 1 def ScanCTypedefDeclarations(self, pool: memhub.MemBuddy*, tree: ast.AST*) -> int: @@ -555,39 +490,29 @@ class TypeGenCType(TypeGenBase.TypeGenBase): Returns: 注册的 CTypedef 数量 """ - if pool is None or tree is None: - return 0 + if pool is None or tree is None: return 0 ch: list[ast.AST*]* = tree.children - if ch is None: - return 0 + if ch is None: return 0 n: sizet = len(ch) count: int = 0 i: sizet for i in range(n): child: ast.AST* = ch.get(i) - if child is None: - continue - if child.kind() != ast.ASTKind.AnnAssign: - continue + if child is None: continue + if child.kind() != ast.ASTKind.AnnAssign: continue aa: ast.AnnAssign* = ast.AnnAssign*(child) - if aa.annotation is None: - continue + if aa.annotation is None: continue # 检测注解是否为 t.CTypedef - if self._is_ctypedef_annotation(aa.annotation) == 0: - continue + if self._is_ctypedef_annotation(aa.annotation) == 0: continue # 提取目标名称(必须是 Name 节点) - if aa.target is None or aa.target.kind() != ast.ASTKind.Name: - continue + if aa.target is None or aa.target.kind() != ast.ASTKind.Name: continue tgt: ast.Name* = ast.Name*(aa.target) tgt_id_v: str = ast.name_get_id(tgt) - if tgt_id_v is None: - continue + if tgt_id_v is None: continue # 提取类型表达式字符串(从 value AST 节点) - if aa.value is None: - continue + if aa.value is None: continue type_str: str = self.Gen.TypeGenResolve._get_type_name_from_annotation(pool, aa.value) - if type_str is None: - continue + if type_str is None: continue # 注册 CTypedef self.register_ctypedef(pool, tgt_id_v, type_str) count += 1 @@ -601,8 +526,7 @@ class TypeGenCType(TypeGenBase.TypeGenBase): attr 会 0xC0000005。本函数在 src_buf 有效期内(Phase1 1b translate 前)用纯文本匹配注册,不依赖 AST 节点内容。 """ - if pool is None or src is None: - return 0 + if pool is None or src is None: return 0 # 文件边界防护:clear_ctypedefs 只在 translate 前调用(Phase1Main # L800),文件级 reset_to(mark1) 回收本文件翻译期 pool 分配后,上一 # 文件的 CTypedefNames 表指针悬空(非 None,list 本身也 pool 分配)。 @@ -649,8 +573,7 @@ class TypeGenCType(TypeGenBase.TypeGenBase): return 0 # 递归深度守卫:BinOp 左右子树成环时无限递归直至栈耗尽。 # fail-fast 终止(fatal_type_error → sys.exit(1)),不静默回落。 - if depth > 64: - self.Gen.TypeGenErr.fatal_type_error(node, "常量表达式递归过深(AST 环或嵌套超过 64 层)") + if depth > 64: self.Gen.TypeGenErr.fatal_type_error(node, "常量表达式递归过深(AST 环或嵌套超过 64 层)") k: int = node.kind() # Constant: 整数字面量 @@ -701,8 +624,7 @@ class TypeGenCType(TypeGenBase.TypeGenBase): if fi_buf is not None: fi_buf[0] = '*' fi_buf[1] = ':' - for mi in range(mod_len): - fi_buf[2 + mi] = at_mod.id[mi] + for mi in range(mod_len): fi_buf[2 + mi] = at_mod.id[mi] fi_buf[2 + mod_len] = '\0' av: int = self.Gen.ExprGenCdef._lookup_cross_module_cdefine(pool, at.attr, fi_buf, imported_modules) if self.Gen.TypeGenCDef.is_cdefine_found() != 0: @@ -716,12 +638,10 @@ class TypeGenCType(TypeGenBase.TypeGenBase): bop: ast.BinOp* = ast.BinOp*(node) # 递归计算左操作数 lv: int = self._eval_const_int_expr(bop.left, pool, from_imports, imported_modules, depth + 1) - if self.ConstEvalOk == 0: - return 0 + if self.ConstEvalOk == 0: return 0 # 递归计算右操作数 rv: int = self._eval_const_int_expr(bop.right, pool, from_imports, imported_modules, depth + 1) - if self.ConstEvalOk == 0: - return 0 + if self.ConstEvalOk == 0: return 0 # 根据运算符执行计算 if bop.op == ast.OpKind.Add: self.ConstEvalOk = 1 diff --git a/App/lib/core/Gen/Type/TypeGenErr.vp b/App/lib/core/Gen/Type/TypeGenErr.vp index ededfcc..87df1ef 100644 --- a/App/lib/core/Gen/Type/TypeGenErr.vp +++ b/App/lib/core/Gen/Type/TypeGenErr.vp @@ -55,8 +55,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): if buf[i] == '\n': if cur_line == lineno: line_len: sizet = i - line_start - if line_len > 0 and buf[line_start + line_len - 1] == '\r': - line_len -= 1 + if line_len > 0 and buf[line_start + line_len - 1] == '\r': line_len -= 1 line_buf: bytes = stdlib.malloc(line_len + 1) if line_buf is not None: string.strncpy(line_buf, buf + line_start, line_len) @@ -78,8 +77,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): err_col: int = ast.get_parse_err_col() err_msg: str = ast.get_parse_err_msg() stdio.printf("Traceback (most recent call last, compile-time error):\n") - if file_path is None or file_path[0] == 0: - file_path = "" + if file_path is None or file_path[0] == 0: file_path = "" if err_line > 0: stdio.printf(' File "%s", line %d\n', file_path, err_line) src: str = self._read_source_line(file_path, err_line) @@ -89,14 +87,11 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): # 前缀 4 空格 + err_col 个空格后落点恰好是该 token 首字符) if err_col > 0: stdio.printf(" ") - for _ in range(err_col): - stdio.printf(" ") + for _ in range(err_col): stdio.printf(" ") 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 = "语法错误" + else: stdio.printf(' File "%s"\n', file_path) + if err_msg is None or err_msg[0] == 0: err_msg = "语法错误" stdio.printf("SyntaxError: %s\n", err_msg) def fatal_error(self, node: ast.AST*, msg: str, err_type: str = "SyntaxError", @@ -116,15 +111,12 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): if src is not None: stdio.printf(" %s\n", src) stdlib.free(src) - else: - stdio.printf(' File "%s"\n', frame.file_name) + else: stdio.printf(' File "%s"\n', frame.file_name) # 输出当前帧(node 对应的位置) lineno: int = 0 - if node is not None: - lineno = node.lineno + if node is not None: lineno = node.lineno file_name: str = self.Gen.TypeGenResolve.get_current_file() - if file_name is None: - file_name = "" + if file_name is None: file_name = "" # 行号兜底:克隆/构造节点 lineno 可能为 0(如泛型特化 _clone_arguments 的 # ast.Arg 构造器硬编码 0,astaux.vp L139)。此时回退到 trace 栈最后一个 # 有效帧(文件+行号)作为出错位置,避免输出误导性的 "line 0"。 @@ -144,8 +136,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): line_ok: int = 1 if lineno > 0 and string.strcmp(file_name, "") != 0: src_line = self._read_source_line(file_name, lineno) - if src_line is None: - line_ok = 0 + if src_line is None: line_ok = 0 if line_ok == 0: stdio.printf(' File "%s", line %d (!! 无法读取该行源码:文件不存在或行号超出范围,错误可能来自被复用的 AST 树,请以错误消息为准)\n', file_name, lineno) @@ -158,15 +149,12 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): stdio.printf(" ") j: int for j in range(col_end): - if j >= col_start - 1 and j < col_end: - stdio.printf("^") - else: - stdio.printf(" ") + if j >= col_start - 1 and j < col_end: stdio.printf("^") + else: stdio.printf(" ") stdio.printf("\n") stdlib.free(src_line) # 输出错误类型 + 消息 - if err_type is None or err_type[0] == 0: - err_type = "SyntaxError" + if err_type is None or err_type[0] == 0: err_type = "SyntaxError" stdio.printf("%s: %s\n", err_type, msg) # 退出前强制刷出:stdout 重定向到文件时是全缓冲,直接终止进程会把整段 # traceback 丢掉(实测 2.log 只剩一行 VLogger 输出)。 @@ -186,34 +174,27 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): trans: HT.Translator*) -> mlirlite.LLVMType*: """提取函数指针注解(t.Callable[[A,B], R] / callable[[A,B], R])的返回类型 LLVMType;非 Callable 注解或无签名形态([]、[[]])返回 None""" - if annot is None or annot.kind() != ast.ASTKind.Subscript: - return None + if annot is None or annot.kind() != ast.ASTKind.Subscript: return None sub_cr: ast.Subscript* = ast.Subscript*(annot) # 构造子判据走 TypeGenResolve 单一真源(Attribute 形态 t.Callable 与 # 裸名形态 callable / Callable 等价) - if self.Gen.TypeGenResolve._IsCallableSubscriptValue(sub_cr.value) == 0: - return None + if self.Gen.TypeGenResolve._IsCallableSubscriptValue(sub_cr.value) == 0: return None # slice 必须是 Tuple(elts=[args_list, ret_node]) - if sub_cr.slice is None or sub_cr.slice.kind() != ast.ASTKind.Tuple: - return None + if sub_cr.slice is None or sub_cr.slice.kind() != ast.ASTKind.Tuple: return None tp_cr: ast.Tuple* = ast.Tuple*(sub_cr.slice) - if tp_cr.elts is None or len(tp_cr.elts) != 2: - return None + if tp_cr.elts is None or len(tp_cr.elts) != 2: return None ret_node_cr: ast.AST* = tp_cr.elts.get(1) - if ret_node_cr is None: - return None + if ret_node_cr is None: return None return self.Gen.TypeGenResolve.resolve_annotation_type(pool, ret_node_cr, imported_modules, from_imports, trans, 0) def has_decorator_marker(self, node: ast.AST*, marker_name: str, depth: int = 0) -> int: """检测类型注解中是否包含指定的装饰器标记""" - if node is None or marker_name is None: - return 0 + if node is None or marker_name is None: return 0 # 递归深度守卫:vpi stub 注入时对每个函数 returns 调用本函数, # vpi tree 深层节点可能被覆盖损坏成回指环(VpiReader L810-813), # BinOp 递归无守卫会无限递归直至栈耗尽。fail-fast 终止。 - if depth > 128: - self.fatal_type_error(node, "装饰器标记检测递归过深(AST 环或嵌套超过 128 层)") + if depth > 128: self.fatal_type_error(node, "装饰器标记检测递归过深(AST 环或嵌套超过 128 层)") k: int = node.kind() @@ -221,17 +202,14 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(node) if at.attr is not None: - if string.strcmp(at.attr, marker_name) == 0: - return 1 + if string.strcmp(at.attr, marker_name) == 0: return 1 return 0 # BinOp 节点: int | t.CExtern(递归检测左右子节点) if k == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(node) - if self.has_decorator_marker(bop.left, marker_name, depth + 1) != 0: - return 1 - if self.has_decorator_marker(bop.right, marker_name, depth + 1) != 0: - return 1 + if self.has_decorator_marker(bop.left, marker_name, depth + 1) != 0: return 1 + if self.has_decorator_marker(bop.right, marker_name, depth + 1) != 0: return 1 return 0 return 0 @@ -251,16 +229,12 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): 多级指针 rawptr[rawptr[t.CVolatile|T]] 的 slice 是 Subscript, has_decorator_marker 不递归 Subscript ⇒ 返回 0(明确不支持,见限制清单)。 """ - if node is None or node.kind() != ast.ASTKind.Subscript: - return 0 + if node is None or node.kind() != ast.ASTKind.Subscript: return 0 sub: ast.Subscript* = ast.Subscript*(node) - if sub.value is None or sub.value.kind() != ast.ASTKind.Name: - return 0 + if sub.value is None or sub.value.kind() != ast.ASTKind.Name: return 0 rp_nm: ast.Name* = ast.Name*(sub.value) - if rp_nm.id is None or string.strcmp(rp_nm.id, "rawptr") != 0: - return 0 - if sub.slice is None: - return 0 + if rp_nm.id is None or string.strcmp(rp_nm.id, "rawptr") != 0: return 0 + if sub.slice is None: return 0 return self.has_decorator_marker(sub.slice, "CVolatile", 0) def is_const_object_marker(self, node: ast.AST*, @@ -275,25 +249,19 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): 对指针类型(`p: t.CConst | T*`)限定只作用于 pointee ⇒ 指针变量自身 仍可重新赋值,不登记。 """ - if self.has_decorator_marker(node, "CConst", 0) == 0: - return 0 - if var_ty is None: - return 0 - if var_ty.kind() == mlirlite.LLVMType.Ptr: - return 0 + if self.has_decorator_marker(node, "CConst", 0) == 0: return 0 + if var_ty is None: return 0 + if var_ty.kind() == mlirlite.LLVMType.Ptr: return 0 return 1 def is_pass_body(self, body: list[ast.AST*]*) -> int: """检测函数体是否为 pass(空体或仅含 pass 语句)""" - if body is None: - return 1 + if body is None: return 1 bn: sizet = len(body) - if bn == 0: - return 1 + if bn == 0: return 1 if bn == 1: stmt: ast.AST* = body.get(0) - if stmt is not None and stmt.kind() == ast.ASTKind.Pass: - return 1 + if stmt is not None and stmt.kind() == ast.ASTKind.Pass: return 1 return 0 # 获取 LLVM 整数类型的位宽 # 实现已收拢到 TSpec.SpecTypeBits(该块在 TypeSpec 模块中的唯一实现),此处只做委托。 @@ -308,13 +276,11 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): param_types 格式: "name:bits,name:bits,..." """ - if node is None: - return mlirlite.Int32(pool) + if node is None: return mlirlite.Int32(pool) k: int = node.kind() - if k == ast.ASTKind.Constant: - return mlirlite.Int32(pool) + if k == ast.ASTKind.Constant: return mlirlite.Int32(pool) elif k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) @@ -335,16 +301,11 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): bits: int = 0 for bi in range(4): ch: char = bits_str[bi] - if ch >= '0' and ch <= '9': - bits = bits * 10 + (ch - '0') - else: - break - if bits == 64: - return mlirlite.Int64(pool) - elif bits == 16: - return mlirlite.Int16(pool) - elif bits == 8: - return mlirlite.Int8(pool) + if ch >= '0' and ch <= '9': bits = bits * 10 + (ch - '0') + else: break + if bits == 64: return mlirlite.Int64(pool) + elif bits == 16: return mlirlite.Int16(pool) + elif bits == 8: return mlirlite.Int8(pool) return mlirlite.Int32(pool) elif k == ast.ASTKind.BinOp: @@ -353,8 +314,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): rhs_ty: mlirlite.LLVMType* = self.infer_expr_type(pool, binop.right, param_types) lhs_bits: int = self.get_llvm_type_bits(lhs_ty) rhs_bits: int = self.get_llvm_type_bits(rhs_ty) - if lhs_bits >= rhs_bits: - return lhs_ty + if lhs_bits >= rhs_bits: return lhs_ty return rhs_ty return mlirlite.Int32(pool) @@ -362,8 +322,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): body: list[ast.AST*]*, param_types: str) -> mlirlite.LLVMType*: """扫描函数体中的 return 语句,推断返回类型""" - if body is None: - return mlirlite.Int32(pool) + if body is None: return mlirlite.Int32(pool) ret_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) bn: sizet = len(body) @@ -376,8 +335,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): if expr_ty is not None: cur_bits: int = self.get_llvm_type_bits(ret_ty) new_bits: int = self.get_llvm_type_bits(expr_ty) - if new_bits > cur_bits: - ret_ty = expr_ty + if new_bits > cur_bits: ret_ty = expr_ty return ret_ty def body_has_value_return(self, pool: memhub.MemBuddy*, body: list[ast.AST*]*) -> int: @@ -390,13 +348,11 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): 供无返回类型注解函数的 fail-fast 检查使用:返回具体值必须有显式 -> 注解,编译器不替用户推断返回类型(推断位宽会掩盖返回契约)。 """ - if body is None: - return 0 + if body is None: return 0 bn: sizet = len(body) for bi in range(bn): stmt: ast.AST* = body.get(bi) - if stmt is None: - continue + if stmt is None: continue k: int = stmt.kind() if k == ast.ASTKind.Return: rt: rawptr[ast.Return] = rawptr[ast.Return](stmt) @@ -404,16 +360,13 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): # return None(CONST_NONE)不算返回非 None 值 if rt.value.kind() == ast.ASTKind.Constant: cn: ast.Constant* = ast.Constant*(rt.value) - if cn.const_kind == ast.CONST_NONE: - continue + if cn.const_kind == ast.CONST_NONE: continue return 1 - elif k == ast.ASTKind.FunctionDef or k == ast.ASTKind.ClassDef: - continue + elif k == ast.ASTKind.FunctionDef or k == ast.ASTKind.ClassDef: continue elif k == ast.ASTKind.If or k == ast.ASTKind.While or k == ast.ASTKind.For or k == ast.ASTKind.Try or k == ast.ASTKind.With or k == ast.ASTKind.Match: sub: list[ast.AST*]* = stmt.children if sub is not None and len(sub) > 0: - if self.body_has_value_return(pool, sub) != 0: - return 1 + if self.body_has_value_return(pool, sub) != 0: return 1 return 0 def build_param_types_str(self, pool: memhub.MemBuddy*, args_node: ast.AST*) -> str: @@ -427,15 +380,12 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): 解析类型后逐条目就地格式化并立即拼接 —— 缓冲恒够,不存在截断; `_strappend` 一并删除(唯一调用点在本函数)。 """ - if args_node is None: - return None + if args_node is None: return None ags: ast.Arguments* = ast.Arguments*(args_node) - if ags.args is None: - return None + if ags.args is None: return None alist: list[ast.AST*]* = ags.args an: sizet = len(alist) - if an == 0: - return None + if an == 0: return None # 1) 上界估长(**只扫参数名**,不解析类型,也不暂存结果指针): # 每条 = name + ':' + 位宽(int32 十进制最长 11 字符含符号)+ ',';再加 NUL。 @@ -445,12 +395,10 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): pre_i: sizet for pre_i in range(an): pre_arg: ast.Arg* = ast.Arg*(alist.get(pre_i)) - if pre_arg is None or pre_arg.arg is None: - continue + if pre_arg is None or pre_arg.arg is None: continue bound += string.strlen(pre_arg.arg) + 1 + 12 + 1 buf: str = pool.alloc(bound) - if buf is None: - return None + if buf is None: return None buf[0] = '\0' # 2) 单遍:解析类型 → 就地格式化条目 → 立即拼接(缓冲为上界,不会截断) @@ -458,8 +406,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool) for ai in range(an): arg: ast.Arg* = ast.Arg*(alist.get(ai)) - if arg is None or arg.arg is None: - continue + if arg is None or arg.arg is None: continue param_ty: mlirlite.LLVMType* = i32_ty if arg.annotation is not None: # 统一口径:CTypedef 动态表优先,miss 回退 map_t_type @@ -468,23 +415,18 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): at: ast.Attribute* = ast.Attribute*(arg.annotation) if at.attr is not None: resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_typedef_or_map(pool, at.attr, None, None) - if resolved is not None: - param_ty = resolved + if resolved is not None: param_ty = resolved bits: int = self.get_llvm_type_bits(param_ty) - if bits == 0: - bits = 32 + if bits == 0: bits = 32 nlen: sizet = string.strlen(arg.arg) # 条目缓冲:name + ':' + 位宽(预留 16 字节,足够 %d 任意取值)+ NUL ent: str = pool.alloc(nlen + 1 + 16 + 1) - if ent is None: - continue + if ent is None: continue string.strcpy(ent, arg.arg) ent[nlen] = ':' viperlib.snprintf(ent + nlen + 1, 16, "%d", bits) - if cnt > 0: - string.strcat(buf, ",") + if cnt > 0: string.strcat(buf, ",") string.strcat(buf, ent) cnt += 1 - if cnt == 0: - return None + if cnt == 0: return None return buf \ No newline at end of file diff --git a/App/lib/core/Gen/Type/TypeGenResolve.vp b/App/lib/core/Gen/Type/TypeGenResolve.vp index 9154203..c883125 100644 --- a/App/lib/core/Gen/Type/TypeGenResolve.vp +++ b/App/lib/core/Gen/Type/TypeGenResolve.vp @@ -35,15 +35,13 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): def _get_type_name_from_annotation(self, pool: memhub.MemBuddy*, node: ast.AST*) -> str: """从类型注解节点提取类型名(支持 Name/Attribute/BinOp)""" - if node is None: - return None + if node is None: return None k: int = node.kind() # Constant: 字符串注解,直接返回字符串值 if k == ast.ASTKind.Constant: cn: ast.Constant* = ast.Constant*(node) cn_val_v: str = ast.constant_get_str_val(cn) - if cn.const_kind == ast.CONST_STR and cn_val_v is not None: - return cn_val_v + if cn.const_kind == ast.CONST_STR and cn_val_v is not None: return cn_val_v return None # Name: 直接返回 id(泛型特化上下文内先做 T 替换,避免 ndarray[T] 中 T 未解析 # 导致 _specialize_generic_class("ndarray", ["T"]) 二次递归崩溃) @@ -59,8 +57,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # Box[int](v) 泛型实参提取失败,与 Name 分支 L53-55 同源)。 if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(node) - if at.attr is None: - return None + if at.attr is None: return None if at.value is not None and at.value.kind() == ast.ASTKind.Name: mod_nm: ast.Name* = ast.Name*(at.value) if mod_nm.id is not None: @@ -82,11 +79,9 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if k == ast.ASTKind.Subscript: sub_s: ast.Subscript* = ast.Subscript*(node) val_s: str = self._get_type_name_from_annotation(pool, sub_s.value) - if val_s is None: - return None + if val_s is None: return None slice_s: str = self._subscript_slice_to_str(pool, sub_s.slice) - if slice_s is None: - return None + if slice_s is None: return None total_s: sizet = string.strlen(val_s) + 1 + string.strlen(slice_s) + 2 buf_s: str = pool.alloc(total_s) if buf_s is not None: @@ -117,12 +112,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): def _subscript_slice_to_str(self, pool: memhub.MemBuddy*, node: ast.AST*) -> str: """Subscript slice 节点转类型字符串(递归,支持 Name/Attribute/BinOp/Constant/List/Tuple/Subscript)""" - if node is None: - return None + if node is None: return None k2: int = node.kind() # Name / Attribute / BinOp / 嵌套 Subscript:复用类型名提取 - if k2 == ast.ASTKind.Name or k2 == ast.ASTKind.Attribute or k2 == ast.ASTKind.BinOp or k2 == ast.ASTKind.Subscript: - return self._get_type_name_from_annotation(pool, node) + if k2 == ast.ASTKind.Name or k2 == ast.ASTKind.Attribute or k2 == ast.ASTKind.BinOp or k2 == ast.ASTKind.Subscript: return self._get_type_name_from_annotation(pool, node) # Constant:数值/字符串字面量(t.CArray[elem, 104] 的 count 等) if k2 == ast.ASTKind.Constant: cn2: ast.Constant* = ast.Constant*(node) @@ -131,8 +124,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if buf2 is not None: viperlib.snprintf(buf2, 24, "%lld", int64(cn2.int_val)) return buf2 - if cn2.const_kind == ast.CONST_STR and cn2.str_val is not None: - return cn2.str_val + if cn2.const_kind == ast.CONST_STR and cn2.str_val is not None: return cn2.str_val return None # List:Callable 参数列表([[A], B]),元素递归,逗号连接 if k2 == ast.ASTKind.List: @@ -158,8 +150,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 所需长度,再按精确长度分配后拼接——**不存在长度上限**,故无需截断。 元素解析不出类型名时 **fail-fast**(不兜底):静默跳过同样拼出错误类型串。 """ - if elts is None or pool is None: - return None + if elts is None or pool is None: return None n3: sizet = len(elts) # 1) 量长(解析结果用完即弃):**不把元素指针暂存进数组再取回**—— # 该「sizet 数组往返再转回指针」的写法在自举出的二进制上会取回 -1 @@ -169,8 +160,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): cnt3: sizet = 0 for i3 in range(n3): e3: ast.AST* = elts.get(i3) - if e3 is None: - continue + if e3 is None: continue es3: str = self._subscript_slice_to_str(pool, e3) if es3 is None: # 类型名缺失 ⇒ 立即报错(静默丢弃会拼出错误类型串) @@ -182,20 +172,17 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): total3 += (cnt3 - 1) * 2 # 分隔符 ", " # 2) 按精确长度分配 + 二次解析直写(无上限,不会截断) buf4: str = pool.alloc(total3 + 1) - if buf4 is None: - return None + if buf4 is None: return None buf4[0] = '\0' string.strcat(buf4, open_ch) wrote3: sizet = 0 for i4 in range(n3): e4: ast.AST* = elts.get(i4) - if e4 is None: - continue + if e4 is None: continue es4: str = self._subscript_slice_to_str(pool, e4) if es4 is None: continue # 第一遍已校验过,此处不会发生 - if wrote3 > 0: - string.strcat(buf4, ", ") + if wrote3 > 0: string.strcat(buf4, ", ") string.strcat(buf4, es4) wrote3 += 1 string.strcat(buf4, close_ch) @@ -214,12 +201,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): def _concat_sha1_class(self, pool: memhub.MemBuddy*, sha1: str, cls_name: str) -> str: """拼接 "{sha1}.{cls_name}"(pool 分配),失败返回 None""" - if pool is None or sha1 is None or cls_name is None: - return None + if pool is None or sha1 is None or cls_name is None: return None total: sizet = string.strlen(sha1) + 1 + string.strlen(cls_name) + 1 buf: str = pool.alloc(total) - if buf is None: - return None + if buf is None: return None buf[0] = '\0' string.strcat(buf, sha1) string.strcat(buf, ".") @@ -251,8 +236,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): def _class_true_def_sha1(self, pool: memhub.MemBuddy*, cls_name: str, cand_sha1: str) -> str: """类名 cls_name 的真定义模块 SHA1;无证据时原样返回 cand_sha1""" - if pool is None or cls_name is None or cand_sha1 is None: - return cand_sha1 + if pool is None or cls_name is None or cand_sha1 is None: return cand_sha1 e: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(cls_name, cand_sha1) if e is None or e.Ty is None: # [重导出类归属校正] cand 模块下查不到该类:它可能由该模块 from-import @@ -265,37 +249,27 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # ⇒ fail-fast。查全局 re-export 映射(内存表,命中即返回),未命中 # 再按需解析该模块 .vpi 的 from-import,定位源模块后取其 SHA1。 rr_mod: str = self.Gen.ImportsGen.lookup_reexport(cand_sha1, cls_name) - if rr_mod is None: - rr_mod = self.Gen.CallGenBase._lookup_reexport_from_vpi(pool, cand_sha1, cls_name) - if rr_mod is None: - return cand_sha1 + if rr_mod is None: rr_mod = self.Gen.CallGenBase._lookup_reexport_from_vpi(pool, cand_sha1, cls_name) + if rr_mod is None: return cand_sha1 rr_sha: str = self.Gen.StructGen._resolve_module_sha1(rr_mod) - if rr_sha is None or rr_sha[0] == '\0' or string.strcmp(rr_sha, cand_sha1) == 0: - return cand_sha1 + if rr_sha is None or rr_sha[0] == '\0' or string.strcmp(rr_sha, cand_sha1) == 0: return cand_sha1 # 源模块自身可能是包 __init__(其重导出类已登记别名 entry,Ty 复用 # 真定义)⇒ 按同一 IR 名前缀口径继续校正,得到最终真定义模块。 e = self.Gen.StructGen.find_struct_by_module(cls_name, rr_sha) - if e is None or e.Ty is None: - return rr_sha + if e is None or e.Ty is None: return rr_sha nm: str = mlirlite.get_struct_name(e.Ty) - if nm is None: - return cand_sha1 + if nm is None: return cand_sha1 # GenApi.sha1_prefix_len 返回的是**含末尾 '.' 的前缀字节数 17**(见其文档), # 本函数只要 hex 段本身(16)—— 直接拷 17 再交 _concat_sha1_class 拼 '.' # 会得到双点 `d1ed020479454541..AST*`(现场 parser.vp:3355 的 CastError 根因)。 pf: int = GenApi.sha1_prefix_len(nm) - if pf <= 1 or pf >= 32: - return cand_sha1 + if pf <= 1 or pf >= 32: return cand_sha1 hexn: int = pf - if nm[sizet(hexn) - 1] == '.': - hexn -= 1 - if hexn <= 0: - return cand_sha1 - if string.strncmp(nm, cand_sha1, sizet(hexn)) == 0: - return cand_sha1 + if nm[sizet(hexn) - 1] == '.': hexn -= 1 + if hexn <= 0: return cand_sha1 + if string.strncmp(nm, cand_sha1, sizet(hexn)) == 0: return cand_sha1 b: str = pool.alloc(sizet(hexn) + 1) - if b is None: - return cand_sha1 + if b is None: return cand_sha1 string.strncpy(b, nm, sizet(hexn)) b[sizet(hexn)] = '\0' return b @@ -318,31 +292,24 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): inner_name: str, trans: HT.Translator*) -> mlirlite.LLVMType*: """`外类.内类` → 嵌套类 Ty;无证据返回 None""" - if pool is None or outer_name is None or inner_name is None: - return None + if pool is None or outer_name is None or inner_name is None: return None # ① base 必须是已知类(或正定义中的本类) outer_known: int = 0 - if self.Gen.StructGen.find_struct(outer_name) is not None: - outer_known = 1 + if self.Gen.StructGen.find_struct(outer_name) is not None: outer_known = 1 if outer_known == 0: cur_cls: str = self.Gen.StructGen.CurDefClassName - if cur_cls is not None and string.strcmp(cur_cls, outer_name) == 0: - outer_known = 1 - if outer_known == 0: - return None + if cur_cls is not None and string.strcmp(cur_cls, outer_name) == 0: outer_known = 1 + if outer_known == 0: return None # ② 扁平名 `外类_内类` flat_len: sizet = string.strlen(outer_name) + 1 + string.strlen(inner_name) flat_buf: str = pool.alloc(flat_len + 1) - if flat_buf is None: - return None + if flat_buf is None: return None viperlib.snprintf(flat_buf, flat_len + 1, "%s_%s", outer_name, inner_name) if trans is not None and trans.ModuleSha1 is not None: own_e: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(flat_buf, trans.ModuleSha1) - if own_e is not None and own_e.Ty is not None: - return own_e.Ty + if own_e is not None and own_e.Ty is not None: return own_e.Ty any_e: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(flat_buf) - if any_e is not None and any_e.Ty is not None: - return any_e.Ty + if any_e is not None and any_e.Ty is not None: return any_e.Ty return None def _repl_opaque_class_ty(self, pool: memhub.MemBuddy*, mod_sha1: str, @@ -367,16 +334,12 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 恒 None ⇒ 本函数不被调用,批处理逐字不变;模块名未登记时调用方不接受 本兜底(那是真实的"未编译/未扫描"错误,仍 fail-fast)。 """ - if pool is None or mod_sha1 is None or cls_name is None: - return None - if mod_sha1[0] == '\0' or cls_name[0] == '\0': - return None + if pool is None or mod_sha1 is None or cls_name is None: return None + if mod_sha1[0] == '\0' or cls_name[0] == '\0': return None full: str = self._concat_sha1_class(pool, mod_sha1, cls_name) - if full is None: - return None + if full is None: return None ex: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(full) - if ex is not None: - return ex + if ex is not None: return ex # fcount=-1 = opaque 哨兵(区别于空结构体 {}:后者 fcount==0 是"完整定义、 # 可 alloca");与 mlirlite 的跨模块 opaque 声明同一表示。 return mlirlite.Struct(pool, None, -1, full) @@ -400,12 +363,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 另兼容历史写法 `list[E, N]`(`list` 本体是 _list.vp 的泛型容器,第 2 实参不是类型名)。 其余泛型类(GSList[T]、Box[T]…)的实参全是类型名,不受此判据影响。 """ - if container is None or container[0] == '\0': - return 0 + if container is None or container[0] == '\0': return 0 _cname: str = container _c_dot: str = string.strrchr(container, '.') - if _c_dot is not None: - _cname = _c_dot + 1 + if _c_dot is not None: _cname = _c_dot + 1 if string.strcmp(_cname, "CArray") == 0: return 1 if string.strcmp(_cname, "list") == 0: return 1 return 0 @@ -439,20 +400,16 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): (:2156/:2167)与 CallGenCtor 的泛型实参提取(:768)里都是被**单独**归一的 —— 那些入口拿不到容器上下文,规则 1.5 的跳过对它们无效。 """ - if name is None or name[0] == '\0': - return 0 + if name is None or name[0] == '\0': return 0 if self.Gen.TypeGenCType is not None: _ts_nc: str = self.Gen.TypeGenCType.lookup_ctypedef(name) - if _ts_nc is not None and self.Gen.TypeGenCType.CTypedefFound != 0: - return 1 - if self._lookup_builtins_typedef(pool, name) is not None: - return 1 + if _ts_nc is not None and self.Gen.TypeGenCType.CTypedefFound != 0: return 1 + if self._lookup_builtins_typedef(pool, name) is not None: return 1 if self.Gen.TypeGenCDef is not None: # 返回值不用:只需它置起的 CDefineFound 标志(-1 也是合法常量值, # 判"命中"必须看标志,见 TypeGenCDef.lookup_cdefine_constant 的约定) self.Gen.TypeGenCDef.lookup_cdefine_constant(name) - if self.Gen.TypeGenCDef.is_cdefine_found() != 0: - return 1 + if self.Gen.TypeGenCDef.is_cdefine_found() != 0: return 1 if string.strcmp(name, "int") == 0: return 1 if string.strcmp(name, "char") == 0: return 1 if string.strcmp(name, "bool") == 0: return 1 @@ -462,8 +419,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if string.strcmp(name, "bytes") == 0: return 1 if string.strcmp(name, "void") == 0: return 1 if string.strlen(name) == 1: - if name[0] >= 'A' and name[0] <= 'Z': - return 1 + if name[0] >= 'A' and name[0] <= 'Z': return 1 return 0 # ============================================================ @@ -482,8 +438,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # ============================================================ def _is_ptr_marker_text(self, txt: str) -> int: """txt 是否为裸指针标记(只贡献一层指针),1=是 / 0=否""" - if txt is None: - return 0 + if txt is None: return 0 if string.strcmp(txt, "CPtr") == 0: return 1 if string.strcmp(txt, "t.CPtr") == 0: return 1 if string.strcmp(txt, "c.CPtr") == 0: return 1 @@ -507,10 +462,8 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # ============================================================ def _is_ptr_subscript_container_text(self, txt: str) -> int: """txt 是否为指针下标容器名(rawptr[T]/t.CPtr[T]/CPtr[T] 的容器位),1=是 / 0=否""" - if txt is None: - return 0 - if self._is_ptr_marker_text(txt) != 0: - return 1 + if txt is None: return 0 + if self._is_ptr_marker_text(txt) != 0: return 1 if string.strcmp(txt, "rawptr") == 0: return 1 if string.strcmp(txt, "t.rawptr") == 0: return 1 if string.strcmp(txt, "c.rawptr") == 0: return 1 @@ -525,12 +478,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # ============================================================ def _ptr_star_text(self, pool: memhub.MemBuddy*, base: str) -> str: """base + '*'(base 为 None 返回 None;分配失败返回 base)""" - if base is None: - return None + if base is None: return None _n_pst: sizet = string.strlen(base) _out_pst: str = pool.alloc(_n_pst + 2) - if _out_pst is None: - return base + if _out_pst is None: return base _out_pst[0] = '\0' string.strcat(_out_pst, base) string.strcat(_out_pst, "*") @@ -575,8 +526,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 返回 None 表示 type_name 为 None。 """ - if type_name is None: - return None + if type_name is None: return None # [FIX] 类型名指针越界(垃圾指针,ViperOS Mat4.m 嵌套泛型崩溃现场 # strlen 收到 0x12124AE128712850 > x64 用户空间上限 2^47;低 16 位 # 0x2850 残留 pool 偏移 → pool 越界写/寄存器破坏)。解引用前 fail-fast @@ -588,47 +538,38 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 空格开头的字符串作为类型名/查表 key 是脏数据(ViperOS Mat4.m 的 # t.CArray[t.CArray[float, 4], 4] 崩溃现场:_norm_type_arg_name 收到 # " 4")。跳过前导空格后再按规则规范化。 - while type_name[0] == ' ': - type_name += 1 - if type_name[0] == '\0': - return type_name + while type_name[0] == ' ': type_name += 1 + if type_name[0] == '\0': return type_name # ---- 1. 顶层联合 "A|B"('|' 仅在括号外才分割)---- # 括号感知:list[A|B] 的 '|' 在 '[' 内不是顶层联合,应留给第 1.5 步 # 泛型 slice 递归处理;list[A]* 的 '|' 在括号外才是联合分割。 seg_len: sizet = string.strlen(type_name) - if seg_len == 0: - return type_name + if seg_len == 0: return type_name pipe_idx: sizet = seg_len p_depth: int = 0 pi: sizet = 0 while pi < seg_len: ch_p: int = type_name[pi] - if ch_p == '[': - p_depth += 1 - elif ch_p == ']': - p_depth -= 1 + if ch_p == '[': p_depth += 1 + elif ch_p == ']': p_depth -= 1 elif ch_p == '|' and p_depth == 0: pipe_idx = pi break pi += 1 if pipe_idx < seg_len: left_buf: str = pool.alloc(pipe_idx + 1) - if left_buf is None: - return type_name + if left_buf is None: return type_name string.strncpy(left_buf, type_name, pipe_idx) left_buf[pipe_idx] = '\0' right_str: str = type_name + pipe_idx + 1 right_len: sizet = string.strlen(right_str) right_buf: str = pool.alloc(right_len + 1) - if right_buf is None: - return type_name + if right_buf is None: return type_name string.strcpy(right_buf, right_str) l_n: str = self._norm_type_arg_name(pool, left_buf, from_imports) r_n: str = self._norm_type_arg_name(pool, right_buf, from_imports) - if l_n is None: - l_n = left_buf - if r_n is None: - r_n = right_buf + if l_n is None: l_n = left_buf + if r_n is None: r_n = right_buf # 【指针联合归一(2026-09-30,用户定口径)】`X*` ≡ `X | rawptr` # ≡ `rawptr[X]` ≡ `t.CPtr[X]` ⇒ 统一为 **`X*`**(T* 形)。裸指针标记 # 只贡献一层指针;这不是新类型规则,只是**书写形式的唯一规范形** @@ -644,16 +585,13 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): r_is_mk: int = self._is_ptr_marker_text(r_n) if l_is_mk == 0 and r_is_mk != 0: _star_r: str = self._ptr_star_text(pool, l_n) - if _star_r is not None: - return _star_r + if _star_r is not None: return _star_r if l_is_mk != 0 and r_is_mk == 0: _star_l: str = self._ptr_star_text(pool, r_n) - if _star_l is not None: - return _star_l + if _star_l is not None: return _star_l total: sizet = string.strlen(l_n) + 1 + string.strlen(r_n) + 1 out: str = pool.alloc(total) - if out is None: - return type_name + if out is None: return type_name out[0] = '\0' string.strcat(out, l_n) string.strcat(out, "|") @@ -676,8 +614,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): lb_idx = li2 break ld += 1 - elif type_name[li2] == ']': - ld -= 1 + elif type_name[li2] == ']': ld -= 1 li2 += 1 if lb_idx < seg_len and type_name[seg_len - 1] == ']': container_g: str = pool.alloc(lb_idx + 1) @@ -694,12 +631,9 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): cur_dep_g: int = 0 ci_g: sizet = 0 while ci_g < inner_len_g: - if inner_buf_g[ci_g] == '[': - cur_dep_g += 1 - elif inner_buf_g[ci_g] == ']': - cur_dep_g -= 1 - elif inner_buf_g[ci_g] == ',' and cur_dep_g == 0: - arg_cnt_g += 1 + if inner_buf_g[ci_g] == '[': cur_dep_g += 1 + elif inner_buf_g[ci_g] == ']': cur_dep_g -= 1 + elif inner_buf_g[ci_g] == ',' and cur_dep_g == 0: arg_cnt_g += 1 ci_g += 1 # [FIX] 第二参数是 elem_size(元素字节大小),不是参数个数! # str 是 i8*(8 字节)。此前误传 arg_cnt_g(参数个数,如 Mat4 @@ -721,12 +655,9 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): while ci_g <= inner_len_g: is_sep_g: int = 0 if ci_g < inner_len_g: - if inner_buf_g[ci_g] == '[': - cur_dep_g += 1 - elif inner_buf_g[ci_g] == ']': - cur_dep_g -= 1 - elif inner_buf_g[ci_g] == ',' and cur_dep_g == 0: - is_sep_g = 1 + if inner_buf_g[ci_g] == '[': cur_dep_g += 1 + elif inner_buf_g[ci_g] == ']': cur_dep_g -= 1 + elif inner_buf_g[ci_g] == ',' and cur_dep_g == 0: is_sep_g = 1 else: is_sep_g = 1 # 结尾 if is_sep_g != 0: @@ -740,10 +671,8 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): arg_list_g.append(abuf_g) else: anorm_g: str = self._norm_type_arg_name(pool, abuf_g, from_imports) - if anorm_g is not None: - arg_list_g.append(anorm_g) - else: - arg_list_g.append(abuf_g) + if anorm_g is not None: arg_list_g.append(anorm_g) + else: arg_list_g.append(abuf_g) _argi_g += 1 arg_start_g = ci_g + 1 ci_g += 1 @@ -764,17 +693,14 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if self._is_ptr_subscript_container_text(container_g) != 0 and len(arg_list_g) == 1: _only_arg_g: str = arg_list_g.get(0) _star_cg: str = self._ptr_star_text(pool, _only_arg_g) - if _star_cg is not None: - return _star_cg + if _star_cg is not None: return _star_cg # 重组 container[arg1,arg2,...] g_total: sizet = string.strlen(container_g) + 2 gi_g: sizet for gi_g in range(len(arg_list_g)): - if gi_g > 0: - g_total += 1 + if gi_g > 0: g_total += 1 g_arg: str = arg_list_g.get(gi_g) - if g_arg is not None: - g_total += string.strlen(g_arg) + if g_arg is not None: g_total += string.strlen(g_arg) g_total += 1 g_out: str = pool.alloc(g_total) if g_out is not None: @@ -782,11 +708,9 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): string.strcat(g_out, container_g) string.strcat(g_out, "[") for gi_g in range(len(arg_list_g)): - if gi_g > 0: - string.strcat(g_out, ",") + if gi_g > 0: string.strcat(g_out, ",") g_arg2: str = arg_list_g.get(gi_g) - if g_arg2 is not None: - string.strcat(g_out, g_arg2) + if g_arg2 is not None: string.strcat(g_out, g_arg2) string.strcat(g_out, "]") return g_out # ---- 1.6 尾随指针星号:先归一基名,再回贴星号(2026-10-01)---- @@ -804,8 +728,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 故统一为:剥掉全部尾随 '*' → 递归归一基名 → 回贴同样多的 '*'。 # `i8**` / `int*` / `T*` / 已带 SHA1 前缀的文本都逐字不变(基名归一回原样)。 _st_n: int = 0 - while seg_len > sizet(_st_n) and type_name[seg_len - sizet(_st_n) - 1] == '*': - _st_n += 1 + while seg_len > sizet(_st_n) and type_name[seg_len - sizet(_st_n) - 1] == '*': _st_n += 1 if _st_n > 0: _base_len_s: sizet = seg_len - sizet(_st_n) _base_buf_s: str = pool.alloc(_base_len_s + 1) @@ -818,16 +741,12 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): _si_s: int for _si_s in range(_st_n): _out_s = self._ptr_star_text(pool, _out_s) - if _out_s is None: - break - if _out_s is not None: - return _out_s + if _out_s is None: break + if _out_s is not None: return _out_s # ---- 2. 已规范化(SHA1 前缀)---- - if self._is_sha1_prefixed(type_name) != 0: - return type_name + if self._is_sha1_prefixed(type_name) != 0: return type_name # ---- 3. t.XXX / c.XXX 内置命名空间 ---- - if (type_name[0] == 't' or type_name[0] == 'c') and type_name[1] == '.': - return type_name + if (type_name[0] == 't' or type_name[0] == 'c') and type_name[1] == '.': return type_name # ---- 4. "mod.Class" Attribute ---- dot_pos: str = string.strchr(type_name, '.') if dot_pos is not None: @@ -847,8 +766,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 校正为类的**真定义模块**(别名/包的 re-export 会给出包 sha1) sha1a = self._class_true_def_sha1(pool, attr, sha1a) res_a: str = self._concat_sha1_class(pool, sha1a, attr) - if res_a is not None: - return res_a + if res_a is not None: return res_a # 4b. mod 本身是完整模块路径(无别名 import,如 w32.fileio) sha1b: str = self.Gen.CallGenBase._lookup_sha1_from_modname_raw(pool, mod_buf) if sha1b is not None: @@ -857,8 +775,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 1abcd…/d1ed… 分裂,见 _class_true_def_sha1 头注释)。 sha1b = self._class_true_def_sha1(pool, attr, sha1b) res_b: str = self._concat_sha1_class(pool, sha1b, attr) - if res_b is not None: - return res_b + if res_b is not None: return res_b return type_name return type_name # ---- 5. 裸名 "Class":查 from_imports 所属模块 SHA1 ---- @@ -868,8 +785,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 同上(`from ast import AST` 这类**包名** from-import 会给出包 sha1) sha1c = self._class_true_def_sha1(pool, type_name, sha1c) res_c: str = self._concat_sha1_class(pool, sha1c, type_name) - if res_c is not None: - return res_c + if res_c is not None: return res_c # ---- 5.2 裸名来自内建模块 t/c ⇒ 统一为 "t.X" / "c.X" ---- # 依据:内建伪模块 t/c **没有模块 SHA1**(规则 5 的"模块名 → sha1"表查不到), # 于是 `from t import CPtr` 之后写的**裸名** `CPtr` 会原样保留,而规则 3 保留的是 @@ -904,8 +820,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if string.strchr(type_name, '[') is None and string.strchr(type_name, '.') is None: _def_sha1: str = None _bare_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(type_name) - if _bare_entry is not None: - _def_sha1 = _bare_entry.ModuleSha1 + if _bare_entry is not None: _def_sha1 = _bare_entry.ModuleSha1 # "正在定义类所属模块"的唯一真源:ClassGenDef 在类定义入口用 # trans.ModuleSha1 登记(不像 TypeGenBase.CurrentModuleSha1 那样存在 # "A-pre/StubMerger 未设置或留着上一文件旧值"的窗口)。 @@ -946,8 +861,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): _tp_buf[0] = '\0' mlirlite.TypePrint(_tp_buf, 512, _bare_entry.Ty, pool) _tp_nm: str = _tp_buf - if _tp_nm[0] == '%' and _tp_nm[1] == '"': - _tp_nm += 2 + if _tp_nm[0] == '%' and _tp_nm[1] == '"': _tp_nm += 2 _sp_l: sizet = sizet(self._is_sha1_prefixed(_tp_nm)) if _sp_l != 0: _sha_b: str = pool.alloc(_sp_l) @@ -965,12 +879,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if _def_sha1 is None: _file_sha: str = self.Gen.StructGen.get_file_module_sha1() if _file_sha is not None: - if self.Gen.StructGen.is_file_class(pool, type_name) != 0: - _def_sha1 = _file_sha + if self.Gen.StructGen.is_file_class(pool, type_name) != 0: _def_sha1 = _file_sha if _def_sha1 is not None: res_d: str = self._concat_sha1_class(pool, _def_sha1, type_name) - if res_d is not None: - return res_d + if res_d is not None: return res_d # 取证(只加日志,不改返回值):一条 SHA1 证据都取不到 ⇒ 本次会保留裸名, # 可能与本类在别处解析出的"带前缀"形式分裂。把各处证据一次打出,便于一轮 # 定位是哪个来源缺失。两个触发条件: @@ -982,11 +894,9 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 裸名一旦被首次注册就会被永久复用。 _w_cls_cur: str = self.Gen.StructGen.CurDefClassName _w_need_log: int = 0 - if _bare_entry is not None and _bare_entry.ModuleSha1 is None: - _w_need_log = 1 + if _bare_entry is not None and _bare_entry.ModuleSha1 is None: _w_need_log = 1 if _def_mod is not None and _w_cls_cur is not None: - if string.strcmp(_w_cls_cur, type_name) != 0: - _w_need_log = 1 + if string.strcmp(_w_cls_cur, type_name) != 0: _w_need_log = 1 # 门控(2026-09-30):取证的前提是"这是个**类名**"——只有类名存在 # "{定义模块SHA1}.类" 这第二个形式可分裂。CTypedef(如 builtins.vp 的 # `typedef uint64 = t.CUInt64T`)/ 语言内置标量 / 泛型形参的名域就是它自身, @@ -996,14 +906,12 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 只对**结构体表里根本没有该名**(_bare_entry is None)的情形豁免:若它确 # 是已注册的类(如 .vpi 半条目)只是缺定义模块 SHA1,那是真正的归属缺口, # 照旧报出(不被同名 typedef 掩盖)。 - if _w_need_log != 0 and _bare_entry is None and self._is_non_class_type_name(pool, type_name) != 0: - _w_need_log = 0 + if _w_need_log != 0 and _bare_entry is None and self._is_non_class_type_name(pool, type_name) != 0: _w_need_log = 0 if _w_need_log != 0: _w_mod: str = "None" if _def_mod is not None: _w_mod = _def_mod _w_cls: str = "None" - if _w_cls_cur is not None: - _w_cls = _w_cls_cur + if _w_cls_cur is not None: _w_cls = _w_cls_cur _w_fi: str = "None" if from_imports is not None: _w_fi = from_imports _w_file: str = "None" @@ -1012,8 +920,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): _w_fbm: int = 0 if _def_mod is not None: _w_imc = self.Gen.StructGen.is_module_class(pool, _def_mod, type_name) - if self.Gen.StructGen.find_struct_by_module(type_name, _def_mod) is not None: - _w_fbm = 1 + if self.Gen.StructGen.find_struct_by_module(type_name, _def_mod) is not None: _w_fbm = 1 _w_ep: int = 0 if _bare_entry is not None: _w_ep = 1 _w_ty: str = "None" @@ -1040,29 +947,23 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): (空格/|/[/]/,等)才算独立标识符。strstr 子串匹配会把实参内部 的 'T' 误判为参数名 → 合法特化 list[AST*] 被误杀。 """ - if s is None or ident is None or ident[0] == '\0': - return 0 + if s is None or ident is None or ident[0] == '\0': return 0 s_len: sizet = string.strlen(s) id_len: sizet = string.strlen(ident) - if id_len == 0 or s_len < id_len: - return 0 + if id_len == 0 or s_len < id_len: return 0 i: sizet for i in range(s_len - id_len + 1): - if string.strncmp(s + i, ident, id_len) != 0: - continue + if string.strncmp(s + i, ident, id_len) != 0: continue # 左边界:i==0 或前一字符非标识符字符 left_ok: int = 1 if i > 0: lc: char = s[i - 1] - if (lc >= 'a' and lc <= 'z') or (lc >= 'A' and lc <= 'Z') or (lc >= '0' and lc <= '9') or lc == '_': - left_ok = 0 + if (lc >= 'a' and lc <= 'z') or (lc >= 'A' and lc <= 'Z') or (lc >= '0' and lc <= '9') or lc == '_': left_ok = 0 right_ok: int = 1 if i + id_len < s_len: rc: char = s[i + id_len] - if (rc >= 'a' and rc <= 'z') or (rc >= 'A' and rc <= 'Z') or (rc >= '0' and rc <= '9') or rc == '_': - right_ok = 0 - if left_ok != 0 and right_ok != 0: - return 1 + if (rc >= 'a' and rc <= 'z') or (rc >= 'A' and rc <= 'Z') or (rc >= '0' and rc <= '9') or rc == '_': right_ok = 0 + if left_ok != 0 and right_ok != 0: return 1 return 0 def _parse_type_string(self, pool: memhub.MemBuddy*, @@ -1075,17 +976,14 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): - 段内空格会导致 Name.id 带空格("ParsedArgs "、" t"),结构体/模块按名查找失败, 最终退化 i8*/i32,如 parse_args -> "ParsedArgs*" 解析出垃圾类型。 """ - if type_str is None or pool is None: - return None + if type_str is None or pool is None: return None # 跳过前导空格('|' 分割后的右段可能带前导空格) - while type_str[0] == ' ': - type_str += 1 + while type_str[0] == ' ': type_str += 1 seg_len: sizet = string.strlen(type_str) # 去除段尾随空格('|' 分割后的左段可能带尾随空格) - while seg_len > 0 and type_str[seg_len - 1] == ' ': - seg_len -= 1 + while seg_len > 0 and type_str[seg_len - 1] == ' ': seg_len -= 1 # 【`T*` 形反解析(2026-09-30)】泛型实参归一后指针类型一律是 `T*` 形 # (TypeGenResolve._norm_type_arg_name 的指针书写归一:rawptr[T] ≡ @@ -1095,8 +993,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # (下标形与联合形恒等价,都只追加 1 层指针),故按层数包成 rawptr[...]: # "{sha}.AST*" → rawptr[{sha}.AST];"i8**" → rawptr[rawptr[i8]]。 _st_cnt: int = 0 - while seg_len > sizet(_st_cnt) and type_str[seg_len - sizet(_st_cnt) - 1] == '*': - _st_cnt += 1 + while seg_len > sizet(_st_cnt) and type_str[seg_len - sizet(_st_cnt) - 1] == '*': _st_cnt += 1 if _st_cnt > 0: _base_len: sizet = seg_len - sizet(_st_cnt) _base_buf: str = pool.alloc(_base_len + 1) @@ -1123,19 +1020,16 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if pipe_idx < seg_len: # 左段复制到独立缓冲(trim 尾随空格),不破坏原字符串 left_len: sizet = pipe_idx - while left_len > 0 and type_str[left_len - 1] == ' ': - left_len -= 1 + while left_len > 0 and type_str[left_len - 1] == ' ': left_len -= 1 left_buf: bytes = stdlib.malloc(left_len + 1) - if left_buf is None: - return None + if left_buf is None: return None string.strncpy(left_buf, type_str, left_len) left_buf[left_len] = '\0' left_node: ast.AST* = self._parse_type_string(pool, left_buf, ctx) # 右段前导空格由递归入口跳过 right_node: ast.AST* = self._parse_type_string(pool, type_str + pipe_idx + 1, ctx) stdlib.free(left_buf) - if left_node is not None and right_node is not None: - return ast.BinOp(pool, left_node, ast.OpKind.BitOr, right_node) + if left_node is not None and right_node is not None: return ast.BinOp(pool, left_node, ast.OpKind.BitOr, right_node) return None # 检查是否包含 [ (Subscript):t.Callable[[int], int] 等。 @@ -1173,8 +1067,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): ci_m += 1 if close_idx_m < seg_len and close_idx_m == seg_len - 1 and has_nested_m == 0: base_len_m: sizet = bracket_idx - while base_len_m > 0 and type_str[base_len_m - 1] == ' ': - base_len_m -= 1 + while base_len_m > 0 and type_str[base_len_m - 1] == ' ': base_len_m -= 1 base_buf_m: bytes = stdlib.malloc(base_len_m + 1) inner_len_m: sizet = close_idx_m - bracket_idx - 1 inner_buf_m: bytes = stdlib.malloc(inner_len_m + 1) @@ -1187,19 +1080,15 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): slice_node_m: ast.AST* = self._parse_type_string(pool, inner_buf_m, ctx) stdlib.free(base_buf_m) stdlib.free(inner_buf_m) - if base_node_m is not None and slice_node_m is not None: - return ast.Subscript(pool, base_node_m, slice_node_m, ctx) + if base_node_m is not None and slice_node_m is not None: return ast.Subscript(pool, base_node_m, slice_node_m, ctx) else: - if base_buf_m is not None: - stdlib.free(base_buf_m) - if inner_buf_m is not None: - stdlib.free(inner_buf_m) + if base_buf_m is not None: stdlib.free(base_buf_m) + if inner_buf_m is not None: stdlib.free(inner_buf_m) # 优先 ast.parse_expression(单表达式入口,返回 Expression 包装节点) expr_node: rawptr[ast.Expression] = ast.parse_expression(type_str, pool) if expr_node is not None: expr_body: ast.AST* = expr_node.body - if expr_body is not None: - return expr_body + if expr_body is not None: return expr_body # 备选:ast.parse 文件级(TPV parser 的 _parse_test 单表达式入口对 # 复杂 slice 如 "t.Callable[[int], int]" 解析失败,但文件级 # _parse_expr_stmt 可解析裸表达式语句——vpi 同语法已验证 @@ -1211,8 +1100,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): st0: ast.AST* = ch_s.get(0) if st0 is not None and st0.kind() == ast.ASTKind.Expr: ex0: rawptr[ast.Expr] = rawptr[ast.Expr](st0) - if ex0.value is not None: - return ex0.value + if ex0.value is not None: return ex0.value return None # 检查是否包含 . (Attribute):只在有效段 [0, seg_len) 内查找 @@ -1226,19 +1114,16 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if dot_idx < seg_len: # 模块名段 trim 尾随空格 mod_len: sizet = dot_idx - while mod_len > 0 and type_str[mod_len - 1] == ' ': - mod_len -= 1 + while mod_len > 0 and type_str[mod_len - 1] == ' ': mod_len -= 1 mod_buf: bytes = stdlib.malloc(mod_len + 1) - if mod_buf is None: - return None + if mod_buf is None: return None string.strncpy(mod_buf, type_str, mod_len) mod_buf[mod_len] = '\0' module_node: ast.AST* = ast.Name(pool, mod_buf, ctx) # attr 段 trim 尾随空格 attr_str: str = type_str + dot_idx + 1 attr_len: sizet = string.strlen(attr_str) - while attr_len > 0 and attr_str[attr_len - 1] == ' ': - attr_len -= 1 + while attr_len > 0 and attr_str[attr_len - 1] == ' ': attr_len -= 1 attr_buf: bytes = stdlib.malloc(attr_len + 1) if attr_buf is None: stdlib.free(mod_buf) @@ -1252,8 +1137,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 普通 Name(trim 尾随空格,ast.Name 内部 _copy_str 复制) name_buf: bytes = stdlib.malloc(seg_len + 1) - if name_buf is None: - return None + if name_buf is None: return None string.strncpy(name_buf, type_str, seg_len) name_buf[seg_len] = '\0' name_node: ast.AST* = ast.Name(pool, name_buf, ctx) @@ -1276,8 +1160,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): VpiReader 等)使用——保证"库 typedef 走正常库分析、t/c 核心走内部特判" 在所有类型解析路径一致(阶段 1b/2 收敛)。 """ - if name is None: - return None + if name is None: return None if self.Gen.TypeGenCType.CTypedefResolveDepth < TypeGenMixin.MAX_CTYPEDEF_DEPTH: ts_rt: str = self.Gen.TypeGenCType.lookup_ctypedef(name) if ts_rt is not None and self.Gen.TypeGenCType.CTypedefFound != 0: @@ -1288,8 +1171,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): ity_rt: mlirlite.LLVMType* = self.resolve_annotation_type(pool, inner_rt, imported_modules, from_imports, trans, 1) self.Gen.TypeGenCType.CTypedefResolveDepth -= 1 self.Gen.TypeGenCType._ctypedef_pop_visiting() - if ity_rt is not None: - return ity_rt + if ity_rt is not None: return ity_rt # [builtins 最后匹配] 常规 typedef 表 + map_t_type 均 miss 后查 # includes/builtins.vp(如 rawptr: t.CTypedef = t.CPtr),命中展开递归解析。 # 与 resolve_annotation_type 的 Name/Subscript 兜底同一口径,保证 @@ -1302,15 +1184,13 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): self.Gen.TypeGenCType.CTypedefResolveDepth += 1 btd_ty_r: mlirlite.LLVMType* = self.resolve_annotation_type(pool, btd_node_r, imported_modules, from_imports, trans, 1) self.Gen.TypeGenCType.CTypedefResolveDepth -= 1 - if btd_ty_r is not None: - return btd_ty_r + if btd_ty_r is not None: return btd_ty_r # 库 typedef 兜底:stdint 等库模块的裸 typedef(UINT/DWORD/...)定义在 # 依赖源中,_vpi_register_typedef_closure 因时序/上下文未成功注入当前 # 文件 CTypedef 表时,直接读库源注册并解析(testcheck.SetConsoleOutputCP # 的 UINT 退化为 i8* 根因)。这是按权威源恢复正确类型,非静默降级。 lib_ts: str = self._lookup_library_typedef(pool, "stdint", name) - if lib_ts is None: - lib_ts = self._lookup_library_typedef(pool, "w32.win32base", name) + if lib_ts is None: lib_ts = self._lookup_library_typedef(pool, "w32.win32base", name) if lib_ts is not None: lib_node: ast.AST* = self._parse_type_string(pool, lib_ts, ast.ASTCtx.Load) if lib_node is not None: @@ -1318,8 +1198,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): self.Gen.TypeGenCType.CTypedefResolveDepth += 1 lib_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, lib_node, imported_modules, from_imports, trans, 1) self.Gen.TypeGenCType.CTypedefResolveDepth -= 1 - if lib_ty is not None: - return lib_ty + if lib_ty is not None: return lib_ty return self.map_t_type(pool, name) def get_type_size_bytes(self, pool: memhub.MemBuddy*, name: str, @@ -1330,11 +1209,9 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 供 __sizeof__/REnum 布局等派生表使用——库 typedef(BYTE/DWORD 等)尺寸 走正常库分析,消除各派生表对 stdint 别名的硬编码盲区(阶段 3 收敛)。 """ - if name is None: - return 0 + if name is None: return 0 ty_sz: mlirlite.LLVMType* = self.resolve_typedef_or_map(pool, name, imported_modules, from_imports) - if ty_sz is None: - return 0 + if ty_sz is None: return 0 bits_sz: int = self.Gen.TypeGenErr.get_llvm_type_bits(ty_sz) if bits_sz <= 0: # 浮点类型必须另取浮点位宽:get_llvm_type_bits 只认整数(Float/Double/ @@ -1345,8 +1222,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # `vector.Vector[CFloat64T]`(T.__sizeof__(),vector.vp:12)——同文件 # 第 15 行 Vector[CInt] 走整数路径正常,故只有浮点特化暴露。 bits_sz = self.Gen.ExprGenBase.get_llvm_float_bits(ty_sz) - if bits_sz <= 0: - return 0 + if bits_sz <= 0: return 0 return bits_sz // 8 def _build_lib_source_path(self, mod: str, sha1: str) -> str: """定位库模块源文件路径(stdlib 分配,调用方负责 free) @@ -1356,26 +1232,20 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): {Config.IncludesDir}/{mod 的 '.'→'/'}.vp——覆盖 sha1 映射表缺失或 incdir 未登记导致路径不可用的场景(stdint.size_t 展开根因排查)。 """ - if mod is None: - return None + if mod is None: return None if sha1 is not None: p_t: str = self.Gen.ExprGenCdef._build_source_path_from_sha1(sha1) - if p_t is not None: - return p_t - if Config.IncludesDir is None: - return None + if p_t is not None: return p_t + if Config.IncludesDir is None: return None m_len: sizet = string.strlen(mod) p_len: sizet = m_len + 4 full_len: sizet = string.strlen(Config.IncludesDir) + p_len + 1 p_buf: str = stdlib.malloc(p_len) - if p_buf is None: - return None + if p_buf is None: return None mi: sizet for mi in range(m_len): - if mod[mi] == '.': - p_buf[mi] = '/' - else: - p_buf[mi] = mod[mi] + if mod[mi] == '.': p_buf[mi] = '/' + else: p_buf[mi] = mod[mi] p_buf[m_len] = '\0' full_buf: str = stdlib.malloc(full_len) if full_buf is None: @@ -1393,15 +1263,12 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): pool 生命周期存活,clear_ctypedefs 负责释放置空。 格式:连续 "alias\0target\0" 段。 """ - if alias is None or target is None: - return + if alias is None or target is None: return # 去重:别名已注册过则跳过 - if self._resolve_import_alias(alias) is not None: - return + if self._resolve_import_alias(alias) is not None: return if self.Gen.TypeGenCType.ImportAliasBuf is None: self.Gen.TypeGenCType.ImportAliasBuf = stdlib.malloc(256) - if self.Gen.TypeGenCType.ImportAliasBuf is None: - return + if self.Gen.TypeGenCType.ImportAliasBuf is None: return # 整体清零:别名段以空 alias('\0')终结,_resolve_import_alias 靠 # 末尾 '\0' 判定结束。只写 buf[0]='\0' 会导致追加后残留垃圾字节, # 遍历读到未写入区域 → 越界读(ASan heap-buffer-overflow)。 @@ -1412,17 +1279,13 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 找缓冲末尾(跳过已有 "alias\0target\0" 对,遇首字节 '\0' 即结尾) cur: sizet = 0 while True: - if buf[cur] == '\0': - break - while buf[cur] != '\0': - cur += 1 + if buf[cur] == '\0': break + while buf[cur] != '\0': cur += 1 cur += 1 # 跳过 alias 段的 '\0' - while buf[cur] != '\0': - cur += 1 + while buf[cur] != '\0': cur += 1 cur += 1 # 跳过 target 段的 '\0' # +3 = alias + '\0' + target + '\0' + 空 alias 终结 '\0' - if cur + al_len + tg_len + 3 > 256: - return + if cur + al_len + tg_len + 3 > 256: return string.strcpy(buf + cur, alias) cur += al_len buf[cur] = '\0' @@ -1436,28 +1299,22 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 命中返回目标模块名(指向 ImportAliasBuf 内部,无需 free), miss 返回 None。 """ - if mod is None: - return None + if mod is None: return None buf: bytes = self.Gen.TypeGenCType.ImportAliasBuf - if buf is None: - return None + if buf is None: return None mod_len: sizet = string.strlen(mod) cur: sizet = 0 while True: - if buf[cur] == '\0': - break + if buf[cur] == '\0': break al_start: sizet = cur - while buf[cur] != '\0': - cur += 1 + while buf[cur] != '\0': cur += 1 al_len: sizet = cur - al_start cur += 1 tg_start: sizet = cur - while buf[cur] != '\0': - cur += 1 + while buf[cur] != '\0': cur += 1 cur += 1 if al_len == mod_len: - if string.strncmp(buf + al_start, mod, mod_len) == 0: - return buf + tg_start + if string.strncmp(buf + al_start, mod, mod_len) == 0: return buf + tg_start return None def _parse_typedef_line(self, out_buf: str, buf: str, line_start: sizet, line_len: sizet) -> int: @@ -1469,13 +1326,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 只识别不注册;非法形态(缺 NAME / 缺 '=' / 缺 VALUE / 注释行)返回 0。 约束:NAME < 128、VALUE <= 190(out_buf 容量需 >= 320)。 """ - if buf is None or out_buf is None or line_len == 0: - return 0 + if buf is None or out_buf is None or line_len == 0: return 0 lead: sizet = 0 - while lead < line_len and (buf[line_start + lead] == ' ' or buf[line_start + lead] == '\t'): - lead += 1 - if lead >= line_len or buf[line_start + lead] == '#': - return 0 + while lead < line_len and (buf[line_start + lead] == ' ' or buf[line_start + lead] == '\t'): lead += 1 + if lead >= line_len or buf[line_start + lead] == '#': return 0 name_s: sizet = 0 name_l: sizet = 0 vs: sizet = 0 @@ -1484,20 +1338,14 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): is_sugar = 1 if is_sugar != 0: k: sizet = lead + 7 - while k < line_len and (buf[line_start + k] == ' ' or buf[line_start + k] == '\t'): - k += 1 + while k < line_len and (buf[line_start + k] == ' ' or buf[line_start + k] == '\t'): k += 1 name_s = k - while k < line_len and buf[line_start + k] != ' ' and buf[line_start + k] != '\t' and buf[line_start + k] != '=' and buf[line_start + k] != '\r': - k += 1 + while k < line_len and buf[line_start + k] != ' ' and buf[line_start + k] != '\t' and buf[line_start + k] != '=' and buf[line_start + k] != '\r': k += 1 name_l = k - name_s - while k < line_len and (buf[line_start + k] == ' ' or buf[line_start + k] == '\t'): - k += 1 - if name_l == 0 or name_l >= 128: - return 0 - if k >= line_len or buf[line_start + k] != '=': - return 0 - if k + 1 < line_len and buf[line_start + k + 1] == '=': - return 0 + while k < line_len and (buf[line_start + k] == ' ' or buf[line_start + k] == '\t'): k += 1 + if name_l == 0 or name_l >= 128: return 0 + if k >= line_len or buf[line_start + k] != '=': return 0 + if k + 1 < line_len and buf[line_start + k + 1] == '=': return 0 vs = k + 1 else: j: sizet = 0 @@ -1507,33 +1355,23 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if ch == ':': fc = 1 break - if ch == '#' or ch == '\r': - break + if ch == '#' or ch == '\r': break j += 1 - if fc == 0: - return 0 + if fc == 0: return 0 name_l = j - while name_l > 0 and buf[line_start + name_l - 1] == ' ': - name_l -= 1 - if name_l == 0 or name_l >= 128: - return 0 + while name_l > 0 and buf[line_start + name_l - 1] == ' ': name_l -= 1 + if name_l == 0 or name_l >= 128: return 0 rest: str = buf + line_start + j + 1 - if string.strstr(rest, "t.CTypedef") is None: - return 0 + if string.strstr(rest, "t.CTypedef") is None: return 0 eq: str = string.strstr(rest, "=") - if eq is None: - return 0 + if eq is None: return 0 vs = sizet(uint64(eq) - uint64(buf)) - line_start + 1 - while vs < line_len and (buf[line_start + vs] == ' ' or buf[line_start + vs] == '\t'): - vs += 1 + while vs < line_len and (buf[line_start + vs] == ' ' or buf[line_start + vs] == '\t'): vs += 1 ve: sizet = line_len - while ve > vs and (buf[line_start + ve - 1] == ' ' or buf[line_start + ve - 1] == '\t' or buf[line_start + ve - 1] == '\r'): - ve -= 1 - if ve <= vs: - return 0 + while ve > vs and (buf[line_start + ve - 1] == ' ' or buf[line_start + ve - 1] == '\t' or buf[line_start + ve - 1] == '\r'): ve -= 1 + if ve <= vs: return 0 vlen: sizet = ve - vs - if vlen > 190: - vlen = 190 + if vlen > 190: vlen = 190 ci: sizet = 0 while ci < name_l: out_buf[ci] = buf[line_start + name_s + ci] @@ -1556,8 +1394,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 定位 builtins 源文件按 "NAME: t.CTypedef = TYPE" 逐行扫描,命中即 注册到本地 CTypedef 表并返回类型表达式;表内已注册直接返回。 """ - if name is None: - return None + if name is None: return None # 详细报错诊断:记录本次 builtins 最后匹配请求与结果(未命中 = None)。 # 必须经 store_builtins_diag 复制进自有缓冲——name 常是调用方的临时 # 段缓冲(VpiReader._resolve_single_vpi_type_str 的 seg_buf malloc 后 @@ -1578,15 +1415,13 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): self.Gen.TypeGenCType.LastBuiltinsTypedefResult = self.Gen.TypeGenCType.store_builtins_diag(1, b_hit_r) return b_hit_r # 本文件已扫过 builtins 源(表内无 = 非 builtins typedef):不再重复读文件 - if self.Gen.TypeGenCType.BuiltinsTypedefScanned != 0: - return None + if self.Gen.TypeGenCType.BuiltinsTypedefScanned != 0: return None # builtins 模块 SHA1 → 源文件路径(SHA1 存储器查不到时 _build_lib_source_path # 回退 {IncludesDir}/builtins.vp;仍找不到则静默返回 None——builtins 缺失 # 属上游配置问题,不在此 fail-fast) b_sha1: str = StubMergerStore.LookupSha1ByModName("builtins") b_path: str = self._build_lib_source_path("builtins", b_sha1) - if b_path is None: - return None + if b_path is None: return None BUF_B: sizet = 65536 b_buf: bytes = stdlib.malloc(BUF_B) if b_buf is None: @@ -1602,8 +1437,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if b_read <= 0: stdlib.free(b_buf) return None - if b_read < LONG(BUF_B): - b_buf[sizet(b_read)] = 0 + if b_read < LONG(BUF_B): b_buf[sizet(b_read)] = 0 # 逐行扫描并注册 builtins 全部 "NAME: t.CTypedef = TYPE"(一次读文件 # 注册全部,置 scanned 标记后同文件后续查表即中;对齐 # register_ctypedef_from_source 的文本匹配策略)。已存在的表条目 @@ -1620,31 +1454,26 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if b_imp_len > 0: # 跳过行首空白 b_imp_s: sizet = 0 - while b_imp_s < b_imp_len and b_buf[b_imp_ls + b_imp_s] == ' ': - b_imp_s += 1 + while b_imp_s < b_imp_len and b_buf[b_imp_ls + b_imp_s] == ' ': b_imp_s += 1 # "import" 前缀 if b_imp_len - b_imp_s >= 6: if b_buf[b_imp_ls + b_imp_s] == 'i' and b_buf[b_imp_ls + b_imp_s + 1] == 'm' and b_buf[b_imp_ls + b_imp_s + 2] == 'p' and b_buf[b_imp_ls + b_imp_s + 3] == 'o' and b_buf[b_imp_ls + b_imp_s + 4] == 'r' and b_buf[b_imp_ls + b_imp_s + 5] == 't': # 找 " as " 分隔 b_as_i: sizet = b_imp_s + 6 while b_as_i < b_imp_len - 3: - if b_buf[b_imp_ls + b_as_i] == ' ' and b_buf[b_imp_ls + b_as_i + 1] == 'a' and b_buf[b_imp_ls + b_as_i + 2] == 's' and b_buf[b_imp_ls + b_as_i + 3] == ' ': - break + if b_buf[b_imp_ls + b_as_i] == ' ' and b_buf[b_imp_ls + b_as_i + 1] == 'a' and b_buf[b_imp_ls + b_as_i + 2] == 's' and b_buf[b_imp_ls + b_as_i + 3] == ' ': break b_as_i += 1 if b_as_i < b_imp_len - 3: # target = "import" 之后跳过空格到 " as " 前 # (b_imp_s+6 是 "import" 后首个字符,可能是空格, # 不跳过会带上前导空格 → " stdint" 查 SHA1 失败) b_tgt_s: sizet = b_imp_s + 6 - while b_tgt_s < b_imp_len and b_buf[b_imp_ls + b_tgt_s] == ' ': - b_tgt_s += 1 + while b_tgt_s < b_imp_len and b_buf[b_imp_ls + b_tgt_s] == ' ': b_tgt_s += 1 b_tgt_e: sizet = b_as_i - while b_tgt_e > b_tgt_s and b_buf[b_imp_ls + b_tgt_e - 1] == ' ': - b_tgt_e -= 1 + while b_tgt_e > b_tgt_s and b_buf[b_imp_ls + b_tgt_e - 1] == ' ': b_tgt_e -= 1 # alias = " as " 之后到行尾(trim 尾随空格/\r) b_al_s: sizet = b_as_i + 4 - while b_al_s < b_imp_len and b_buf[b_imp_ls + b_al_s] == ' ': - b_al_s += 1 + while b_al_s < b_imp_len and b_buf[b_imp_ls + b_al_s] == ' ': b_al_s += 1 b_al_e: sizet = b_imp_len while b_al_e > b_al_s and (b_buf[b_imp_ls + b_al_e - 1] == ' ' or b_buf[b_imp_ls + b_al_e - 1] == '\r'): @@ -1684,14 +1513,12 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # t.CTypedef = stdint.size_t → 注册 sizet), # 使表内直接持有最终类型表达式,下游查表即中 b_tb_x: str = self._expand_typedef_ref(pool, b_tb) - if b_tb_x is not None: - self.Gen.TypeGenCType.register_ctypedef(pool, b_nb, b_tb_x) + if b_tb_x is not None: self.Gen.TypeGenCType.register_ctypedef(pool, b_nb, b_tb_x) if string.strcmp(b_nb, name) == 0: # 独立复制:b_td_buf 会被后续行覆盖 b_vl: sizet = string.strlen(b_tb) b_res = pool.alloc(b_vl + 1) - if b_res is not None: - string.strcpy(b_res, b_tb) + if b_res is not None: string.strcpy(b_res, b_tb) b_line_start = b_i + 1 b_i += 1 # 置扫描完成标记:同文件内后续 miss 直接查表,不再重复读 builtins 源 @@ -1704,8 +1531,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): b_final_r = self._expand_typedef_ref(pool, b_res) self.Gen.TypeGenCType.LastBuiltinsTypedefResult = self.Gen.TypeGenCType.store_builtins_diag(1, b_final_r) stdlib.free(b_buf) - if b_final_r is not None: - return b_final_r + if b_final_r is not None: return b_final_r return None def _register_lib_typedef_cache(self, mod: str, name_src: str, name_len: sizet, type_str: str) -> None: @@ -1715,74 +1541,59 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 首次扫描某模块时对该模块全部 typedef 调用一次;结果跨文件/Phase 存活, 后续同模块查询只查表,不再读库源。 """ - if mod is None or name_src is None or type_str is None or name_len == 0: - return + if mod is None or name_src is None or type_str is None or name_len == 0: return perm: memhub.MemBuddy* = CompilerFactory.factory.PermPool - if perm is None: - return + if perm is None: return if self.LibTypedefTypeMap is None: self.LibTypedefTypeMap = hashtable.HashTable(perm) - if self.LibTypedefTypeMap is None: - return + if self.LibTypedefTypeMap is None: return mod_len: sizet = string.strlen(mod) key_len: sizet = mod_len + 1 + name_len key_buf: str = perm.alloc(key_len + 1) - if key_buf is None: - return + if key_buf is None: return string.strncpy(key_buf, mod, mod_len) key_buf[mod_len] = '|' string.strncpy(key_buf + mod_len + 1, name_src, name_len) key_buf[key_len] = '\0' # 同名首次为准(与逐次读源命中第一处声明的语义一致) - if self.LibTypedefTypeMap.__contains__(key_buf) != 0: - return + if self.LibTypedefTypeMap.__contains__(key_buf) != 0: return tlen: sizet = string.strlen(type_str) type_copy: str = perm.alloc(tlen + 1) - if type_copy is None: - return + if type_copy is None: return string.strcpy(type_copy, type_str) self.LibTypedefTypeMap.set_str(key_buf, type_copy) def _mark_lib_module_scanned(self, mod: str) -> None: """置库模块「已扫描」标记(PermPool 持久):其后同模块查询只查缓存表""" - if mod is None: - return + if mod is None: return # 缓存表未建成(PermPool 分配失败)时不得置标记——否则后续查询只查空表 # 会误返回 None(改变语义);此时不标记、留待下次重试读源。 - if self.LibTypedefTypeMap is None: - return + if self.LibTypedefTypeMap is None: return perm: memhub.MemBuddy* = CompilerFactory.factory.PermPool - if perm is None: - return + if perm is None: return if self.LibTypedefScannedMods is None: self.LibTypedefScannedMods = hashtable.HashTable(perm) - if self.LibTypedefScannedMods is None: - return - if self.LibTypedefScannedMods.__contains__(mod) != 0: - return + if self.LibTypedefScannedMods is None: return + if self.LibTypedefScannedMods.__contains__(mod) != 0: return mlen: sizet = string.strlen(mod) mcopy: str = perm.alloc(mlen + 1) - if mcopy is None: - return + if mcopy is None: return string.strcpy(mcopy, mod) self.LibTypedefScannedMods.set_str(mcopy, mcopy) def _lookup_lib_typedef_cache(self, mod: str, attr: str) -> str: """查持久缓存表:命中返回该模块源中的原始类型表达式,未命中返回 None""" - if self.LibTypedefTypeMap is None or mod is None or attr is None: - return None + if self.LibTypedefTypeMap is None or mod is None or attr is None: return None mod_len: sizet = string.strlen(mod) attr_len: sizet = string.strlen(attr) key_len: sizet = mod_len + 1 + attr_len key_buf: bytes = stdlib.malloc(key_len + 1) - if key_buf is None: - return None + if key_buf is None: return None string.strncpy(key_buf, mod, mod_len) key_buf[mod_len] = '|' string.strncpy(key_buf + mod_len + 1, attr, attr_len) key_buf[key_len] = '\0' v: t.CPtr = self.LibTypedefTypeMap.__getitem__(key_buf) stdlib.free(key_buf) - if v is None: - return None + if v is None: return None return t.CPtr(v) def _lookup_library_typedef(self, pool: memhub.MemBuddy*, mod: str, attr: str) -> str: @@ -1798,26 +1609,22 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 缓存表,不再做文件 I/O 与全文扫描。缓存按模块名(内容)索引,库源在 单次编译内不变,故命中值与逐次读源等价。| miss 仍返回 None。 """ - if mod is None or attr is None: - return None + if mod is None or attr is None: return None # builtins import 别名还原真实模块名(__stdint → stdint):builtins.vp # 用 `import stdint as __stdint`,typedef 值 `__stdint.size_t` 等价 # `stdint.size_t`;不还原则 SHA1 查找/路径定位全 miss。 m_real: str = self._resolve_import_alias(mod) - if m_real is None: - m_real = mod + if m_real is None: m_real = mod # [门禁命中] 该库模块源已扫描过 → 只查持久缓存表,不再读文件; # 命中值仍注册进当前文件 CTypedef 表(保持原实现每次读源命中的副作用)。 if self.LibTypedefScannedMods is not None: if self.LibTypedefScannedMods.__contains__(m_real) != 0: ts_hit: str = self._lookup_lib_typedef_cache(m_real, attr) - if ts_hit is not None: - self.Gen.TypeGenCType.register_ctypedef(pool, attr, ts_hit) + if ts_hit is not None: self.Gen.TypeGenCType.register_ctypedef(pool, attr, ts_hit) return ts_hit m_sha1: str = StubMergerStore.LookupSha1ByModName(m_real) m_path: str = self._build_lib_source_path(m_real, m_sha1) - if m_path is None: - return None + if m_path is None: return None BUF_L: sizet = 65536 m_buf: bytes = stdlib.malloc(BUF_L) if m_buf is None: @@ -1833,8 +1640,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if m_read <= 0: stdlib.free(m_buf) return None - if m_read < LONG(BUF_L): - m_buf[sizet(m_read)] = 0 + if m_read < LONG(BUF_L): m_buf[sizet(m_read)] = 0 m_total: sizet = string.strlen(m_buf) m_i: sizet = 0 m_ls: sizet = 0 @@ -1860,14 +1666,12 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if m_res is None and string.strcmp(m_nb, attr) == 0: m_vl: sizet = string.strlen(m_tb) m_res = pool.alloc(m_vl + 1) - if m_res is not None: - string.strcpy(m_res, m_tb) + if m_res is not None: string.strcpy(m_res, m_tb) m_ls = m_i + 1 m_i += 1 # 置该模块已扫描标记:同模块后续查询只查持久缓存表,不再重复读源 self._mark_lib_module_scanned(m_real) - if m_res is not None: - self.Gen.TypeGenCType.register_ctypedef(pool, attr, m_res) + if m_res is not None: self.Gen.TypeGenCType.register_ctypedef(pool, attr, m_res) stdlib.free(m_buf) return m_res def _expand_typedef_ref(self, pool: memhub.MemBuddy*, @@ -1880,33 +1684,25 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): attr 在 mod 源中的底层类型表达式。含 '[' / '|' 的复合表达式原样返回 (由常规解析路径处理);t/c 内置命名空间原样返回;递归限深防环。 """ - if type_str is None or depth > 16: - return type_str + if type_str is None or depth > 16: return type_str # 复合表达式(联合/泛型)不在此展开 - if string.strchr(type_str, '[') is not None or string.strchr(type_str, '|') is not None: - return type_str + if string.strchr(type_str, '[') is not None or string.strchr(type_str, '|') is not None: return type_str # 拆分 "mod.attr"(取最后一个 '.',支持 w32.win32base.HANDLE) dot_pos: str = string.strrchr(type_str, '.') - if dot_pos is None: - return type_str + if dot_pos is None: return type_str mod_len: sizet = sizet(uint64(dot_pos) - uint64(type_str)) attr: str = dot_pos + 1 - if mod_len == 0 or attr is None or attr[0] == '\0': - return type_str - if mod_len == 1 and (type_str[0] == 't' or type_str[0] == 'c'): - return type_str + if mod_len == 0 or attr is None or attr[0] == '\0': return type_str + if mod_len == 1 and (type_str[0] == 't' or type_str[0] == 'c'): return type_str mod_buf: str = pool.alloc(mod_len + 1) - if mod_buf is None: - return type_str + if mod_buf is None: return type_str string.strncpy(mod_buf, type_str, mod_len) mod_buf[mod_len] = '\0' # 库模块权威 typedef(源扫描 + 注册);miss 回退表内 attr(闭包注入) lib_ty: str = self._lookup_library_typedef(pool, mod_buf, attr) - if lib_ty is not None: - return self._expand_typedef_ref(pool, lib_ty, depth + 1) + if lib_ty is not None: return self._expand_typedef_ref(pool, lib_ty, depth + 1) ts_x: str = self.Gen.TypeGenCType.lookup_ctypedef(attr) - if ts_x is not None and self.Gen.TypeGenCType.CTypedefFound != 0 and string.strcmp(ts_x, type_str) != 0: - return self._expand_typedef_ref(pool, ts_x, depth + 1) + if ts_x is not None and self.Gen.TypeGenCType.CTypedefFound != 0 and string.strcmp(ts_x, type_str) != 0: return self._expand_typedef_ref(pool, ts_x, depth + 1) return type_str def _long_llvm_ty(self, pool: memhub.MemBuddy*) -> mlirlite.LLVMType*: """C 的 long / unsigned long 的目标平台 LLVM 类型 @@ -1920,8 +1716,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): (Config.TargetTriple,缺省 x86_64-pc-windows-gnu)。 """ triple: str = Config.TargetTriple - if triple is None: - triple = "x86_64-pc-windows-gnu" + if triple is None: triple = "x86_64-pc-windows-gnu" if string.strstr(triple, "windows") is not None or string.strstr(triple, "win32") is not None or string.strstr(triple, "mingw") is not None or string.strstr(triple, "msvc") is not None: return mlirlite.Int32(pool) return mlirlite.Int64(pool) @@ -1935,24 +1730,18 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # t.Callable[] / t.Callable[[]] / callable[] / callable[[]] # ============================================================ def _IsCallableSubscriptValue(self, value_node: ast.AST*) -> int: - if value_node is None: - return 0 + if value_node is None: return 0 vk: int = value_node.kind() if vk == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(value_node) - if at.attr is None: - return 0 - if string.strcmp(at.attr, "Callable") == 0: - return 1 + if at.attr is None: return 0 + if string.strcmp(at.attr, "Callable") == 0: return 1 return 0 if vk == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(value_node) - if nm.id is None: - return 0 - if string.strcmp(nm.id, "callable") == 0: - return 1 - if string.strcmp(nm.id, "Callable") == 0: - return 1 + if nm.id is None: return 0 + if string.strcmp(nm.id, "callable") == 0: return 1 + if string.strcmp(nm.id, "Callable") == 0: return 1 return 0 # ============================================================ @@ -1973,27 +1762,22 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): node: ast.AST*, imported_modules: str, from_imports: str) -> mlirlite.LLVMType*: - if node is None: - return None + if node is None: return None cls_nm: str = None sha1: str = None k: int = node.kind() if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(node) - if at.attr is None or at.value is None: - return None - if at.value.kind() != ast.ASTKind.Name: - return None + if at.attr is None or at.value is None: return None + if at.value.kind() != ast.ASTKind.Name: return None mod_nm: ast.Name* = ast.Name*(at.value) - if mod_nm.id is None: - return None + if mod_nm.id is None: return None cls_nm = at.attr mod_buf: str = mod_nm.id # 4a. mod 是 import 别名时先经 from_imports 反查完整模块名 if from_imports is not None: orig_mod: str = self.Gen.ImportsGen.lookup_from_import(from_imports, mod_buf, 0) - if orig_mod is not None: - sha1 = self.Gen.CallGenBase._lookup_sha1_from_modname_raw(pool, orig_mod) + if orig_mod is not None: sha1 = self.Gen.CallGenBase._lookup_sha1_from_modname_raw(pool, orig_mod) # 4a'. `import X as Y`(同模块的 from_imports 里存 "Y:X")单独反查—— # 与 extract_class_name_from_annotation 的别名还原同源(现场: # GenTypes.vp 的 `import lib.core.Gen.Type.TypeSpec as TSpec`, @@ -2004,8 +1788,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): sha1 = self.Gen.CallGenBase._lookup_sha1_from_modname_raw(pool, alias_mod) stdlib.free(alias_mod) # 4b. mod 本身是完整模块路径(无别名 import) - if sha1 is None: - sha1 = self.Gen.CallGenBase._lookup_sha1_from_modname_raw(pool, mod_buf) + if sha1 is None: sha1 = self.Gen.CallGenBase._lookup_sha1_from_modname_raw(pool, mod_buf) # 4c. vpi 注入期:模块段 = 本 stub 自己的模块名(或其末段)⇒ 归属即 # CurDefModuleSha1(inject_class 入口 mark_module_class 建立), # 与 Name 分支的注入窗口证据同口径:同一 stub 内写成 @@ -2017,25 +1800,20 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if inj_nm_a2 is not None: inj_seg_a2: str = inj_nm_a2 dot_a2: str = string.strrchr(inj_nm_a2, '.') - if dot_a2 is not None: - inj_seg_a2 = dot_a2 + 1 + if dot_a2 is not None: inj_seg_a2 = dot_a2 + 1 nm_eq_a2: int = string.strcmp(inj_nm_a2, mod_buf) seg_eq_a2: int = string.strcmp(inj_seg_a2, mod_buf) - if nm_eq_a2 == 0 or seg_eq_a2 == 0: - sha1 = inj_mod_a2 + if nm_eq_a2 == 0 or seg_eq_a2 == 0: sha1 = inj_mod_a2 elif k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) - if nm.id is None: - return None + if nm.id is None: return None cls_nm = nm.id - if from_imports is not None: - sha1 = self.Gen.CallGenBase._lookup_mod_sha1(pool, from_imports, cls_nm, 0) + if from_imports is not None: sha1 = self.Gen.CallGenBase._lookup_mod_sha1(pool, from_imports, cls_nm, 0) # 本文件顶层类(如自我引用 JsonValue*,或同文件内前向引用): # register_file_classes 已登记"名字 → 本文件模块 SHA1"(规则 5.5 证据⑤同源), # 用它前向声明——与 TPC 的同类前向引用同等处理。 if sha1 is None: - if self.Gen.StructGen.is_file_class(pool, cls_nm) != 0: - sha1 = self.Gen.StructGen.get_file_module_sha1() + if self.Gen.StructGen.is_file_class(pool, cls_nm) != 0: sha1 = self.Gen.StructGen.get_file_module_sha1() # vpi 注入期的"本模块"归属:inject_class 入口已 mark_module_class(src_sha1, # real_name) 登记"{src_sha1}.{类名}"(**名字归属**,与 struct 是否已登记 # 无关),并把 CurDefModuleSha1 指向本次注入的 stub 源模块。注入期 @@ -2051,19 +1829,14 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if sha1 is None: inj_mod_n: str = self.Gen.StructGen.CurDefModuleSha1 if inj_mod_n is not None: - if self.Gen.StructGen.is_module_class(pool, inj_mod_n, cls_nm) != 0: - sha1 = inj_mod_n - else: - return None - if cls_nm is None or sha1 is None or sha1[0] == '\0': - return None + if self.Gen.StructGen.is_module_class(pool, inj_mod_n, cls_nm) != 0: sha1 = inj_mod_n + else: return None + if cls_nm is None or sha1 is None or sha1[0] == '\0': return None # 校正为类的**真定义模块**(包重导出会给包 sha1) sha1 = self._class_true_def_sha1(pool, cls_nm, sha1) - if sha1 is None or sha1[0] == '\0': - return None + if sha1 is None or sha1[0] == '\0': return None entry: GenTypes.StructEntry* = self.Gen.StructGen.ensure_forward_class(pool, sha1, cls_nm) - if entry is None or entry.Ty is None: - return None + if entry is None or entry.Ty is None: return None return mlirlite.Ptr(pool, entry.Ty) def map_t_type(self, pool: memhub.MemBuddy*, @@ -2072,58 +1845,37 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 注意: str = i8* = str = bytes """ - if type_name is None: - return None + if type_name is None: return None # 基本整数类型 - if string.strcmp(type_name, "CInt") == 0: - return mlirlite.Int32(pool) - elif string.strcmp(type_name, "CChar") == 0: - return mlirlite.Int8(pool) - elif string.strcmp(type_name, "CShort") == 0: - return mlirlite.Int16(pool) + if string.strcmp(type_name, "CInt") == 0: return mlirlite.Int32(pool) + elif string.strcmp(type_name, "CChar") == 0: return mlirlite.Int8(pool) + elif string.strcmp(type_name, "CShort") == 0: return mlirlite.Int16(pool) elif string.strcmp(type_name, "CLong") == 0: # long 宽度随目标平台:Windows LLP64 = 32 位(对齐 TPC),LP64 = 64 位 return self._long_llvm_ty(pool) - elif string.strcmp(type_name, "CLongLong") == 0: - return mlirlite.Int64(pool) + elif string.strcmp(type_name, "CLongLong") == 0: return mlirlite.Int64(pool) # 精确宽度有符号类型 - elif string.strcmp(type_name, "CInt8T") == 0: - return mlirlite.Int8(pool) - elif string.strcmp(type_name, "CInt16T") == 0: - return mlirlite.Int16(pool) - elif string.strcmp(type_name, "CInt32T") == 0: - return mlirlite.Int32(pool) - elif string.strcmp(type_name, "CInt64T") == 0: - return mlirlite.Int64(pool) + elif string.strcmp(type_name, "CInt8T") == 0: return mlirlite.Int8(pool) + elif string.strcmp(type_name, "CInt16T") == 0: return mlirlite.Int16(pool) + elif string.strcmp(type_name, "CInt32T") == 0: return mlirlite.Int32(pool) + elif string.strcmp(type_name, "CInt64T") == 0: return mlirlite.Int64(pool) # 精确宽度无符号类型 - elif string.strcmp(type_name, "CUInt8T") == 0: - return mlirlite.Int8(pool) - elif string.strcmp(type_name, "CUInt16T") == 0: - return mlirlite.Int16(pool) - elif string.strcmp(type_name, "CUInt32T") == 0: - return mlirlite.Int32(pool) - elif string.strcmp(type_name, "CUInt64T") == 0: - return mlirlite.Int64(pool) + elif string.strcmp(type_name, "CUInt8T") == 0: return mlirlite.Int8(pool) + elif string.strcmp(type_name, "CUInt16T") == 0: return mlirlite.Int16(pool) + elif string.strcmp(type_name, "CUInt32T") == 0: return mlirlite.Int32(pool) + elif string.strcmp(type_name, "CUInt64T") == 0: return mlirlite.Int64(pool) # 浮点类型 - elif string.strcmp(type_name, "CFloat") == 0: - return mlirlite.Float(pool) - elif string.strcmp(type_name, "CDouble") == 0: - return mlirlite.Double(pool) + elif string.strcmp(type_name, "CFloat") == 0: return mlirlite.Float(pool) + elif string.strcmp(type_name, "CDouble") == 0: return mlirlite.Double(pool) # 精确宽度浮点类型(t.py 的 float_map: 8/16→half, 32→float, 64→double, 128→fp128) - elif string.strcmp(type_name, "CFloat8T") == 0: - return mlirlite.Half(pool) - elif string.strcmp(type_name, "CFloat16T") == 0: - return mlirlite.Half(pool) - elif string.strcmp(type_name, "CFloat32T") == 0: - return mlirlite.Float(pool) - elif string.strcmp(type_name, "CFloat64T") == 0: - return mlirlite.Double(pool) - elif string.strcmp(type_name, "CFloat128T") == 0: - return mlirlite.FP128(pool) + elif string.strcmp(type_name, "CFloat8T") == 0: return mlirlite.Half(pool) + elif string.strcmp(type_name, "CFloat16T") == 0: return mlirlite.Half(pool) + elif string.strcmp(type_name, "CFloat32T") == 0: return mlirlite.Float(pool) + elif string.strcmp(type_name, "CFloat64T") == 0: return mlirlite.Double(pool) + elif string.strcmp(type_name, "CFloat128T") == 0: return mlirlite.FP128(pool) # 指针/void: t.CPtr = i8*, str = i8* = str = bytes - elif string.strcmp(type_name, "CPtr") == 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + elif string.strcmp(type_name, "CPtr") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) # 无签名函数指针: t.Callable(裸名) → i8*,与带完整签名的 # t.Callable[[A, B], Ret](见 resolve_annotation_type 的 Subscript 分支) # 同一 LLVM 表示:函数值按 TPV 惯例 bitcast 为 i8* 存储/传递。 @@ -2131,57 +1883,42 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # `call {c.AsmInp(func, ...)}`),不作编译器间接调用。 # 大写裸名同时服务 `from t import Callable` 与 Attribute 分支的 t.Callable # (Attribute 分支传 at.attr = "Callable")。 - elif string.strcmp(type_name, "Callable") == 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + elif string.strcmp(type_name, "Callable") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) # 小写别名 callable:注解位置等价于 t.Callable(`func: callable = 函数名`)。 - elif string.strcmp(type_name, "callable") == 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + elif string.strcmp(type_name, "callable") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) # 裸名 void 是 t.CVoid 的别名(用户 2026-10-01 定):单独出现即 LLVM void; # `void*`(= `void*`)由下方 BinOp 分支归并为 i8*。 - elif string.strcmp(type_name, "CVoid") == 0 or string.strcmp(type_name, "void") == 0: - return mlirlite.Void(pool) + elif string.strcmp(type_name, "CVoid") == 0 or string.strcmp(type_name, "void") == 0: return mlirlite.Void(pool) # CDefine: 编译期常量定义标记(X: t.CDefine = 64),底层为 32 位有符号整数 # (对齐 TPC t.CDefine Size=32 IsSigned=True;超大值由 DefineValue 路径升 i64)。 # 用作函数返回注解时表示宏函数(def MAKE_FLAG(bit) -> t.CDefine: return 1 << bit), # 返回类型即 i32。全局/字段的 CDefine 注解已由 is_cdefine_annotation 先行短路 # (不创建 LLVM 全局/字段,仅注册编译期常量),不会走到此处。 - elif string.strcmp(type_name, "CDefine") == 0: - return mlirlite.Int32(pool) + elif string.strcmp(type_name, "CDefine") == 0: return mlirlite.Int32(pool) # CNeedPtr/CAutoPtr: 参数自动取地址标记,LLVM 层均为通用指针 i8*。 # (TPC 中二者继承 CPtr;TPV 未实现调用点自动取地址,非指针实参应在调用点报错, # 而非静默降级为 i32 导致指针截断。) - elif string.strcmp(type_name, "CNeedPtr") == 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) - elif string.strcmp(type_name, "CAutoPtr") == 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + elif string.strcmp(type_name, "CNeedPtr") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + elif string.strcmp(type_name, "CAutoPtr") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) # 无符号修饰 - elif string.strcmp(type_name, "CUnsigned") == 0: - return mlirlite.Int32(pool) - elif string.strcmp(type_name, "CUnsignedInt") == 0: - return mlirlite.Int32(pool) - elif string.strcmp(type_name, "CUnsignedChar") == 0: - return mlirlite.Int8(pool) - elif string.strcmp(type_name, "CUnsignedShort") == 0: - return mlirlite.Int16(pool) + elif string.strcmp(type_name, "CUnsigned") == 0: return mlirlite.Int32(pool) + elif string.strcmp(type_name, "CUnsignedInt") == 0: return mlirlite.Int32(pool) + elif string.strcmp(type_name, "CUnsignedChar") == 0: return mlirlite.Int8(pool) + elif string.strcmp(type_name, "CUnsignedShort") == 0: return mlirlite.Int16(pool) elif string.strcmp(type_name, "CUnsignedLong") == 0: # unsigned long 同上:Windows LLP64 = 32 位(ULONG/DWORD 同宽),LP64 = 64 位 return self._long_llvm_ty(pool) - elif string.strcmp(type_name, "CUnsignedLongLong") == 0: - return mlirlite.Int64(pool) + elif string.strcmp(type_name, "CUnsignedLongLong") == 0: return mlirlite.Int64(pool) # size_t / ptr 类型 - elif string.strcmp(type_name, "CSizeT") == 0: - return mlirlite.Int64(pool) - elif string.strcmp(type_name, "CIntPtrT") == 0: - return mlirlite.Int64(pool) - elif string.strcmp(type_name, "CUIntPtrT") == 0: - return mlirlite.Int64(pool) + elif string.strcmp(type_name, "CSizeT") == 0: return mlirlite.Int64(pool) + elif string.strcmp(type_name, "CIntPtrT") == 0: return mlirlite.Int64(pool) + elif string.strcmp(type_name, "CUIntPtrT") == 0: return mlirlite.Int64(pool) # bool elif string.strcmp(type_name, "CBool") == 0: # bool = t.CBool = i1(LLVM 1 位整数,语义与 C _Bool 一致) return mlirlite.Int1(pool) # ptrdiff_t - elif string.strcmp(type_name, "CPtrDiffT") == 0: - return mlirlite.Int64(pool) + elif string.strcmp(type_name, "CPtrDiffT") == 0: return mlirlite.Int64(pool) # ============================================================ # stdint.vp 大写/定长/小写/指针/C 标准别名(INT/BYTE/DWORD/int8_t/ @@ -2193,12 +1930,9 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 内建小写裸名类型(float = t.CFloat = f32, double = t.CDouble = f64, # char = char = i8;int/bool 由 resolve_annotation_type Name 分支直通, # 小写 stdint 别名由 stdint.vp CTypedef 声明提供) - elif string.strcmp(type_name, "char") == 0: - return mlirlite.Int8(pool) - elif string.strcmp(type_name, "float") == 0: - return mlirlite.Float(pool) - elif string.strcmp(type_name, "double") == 0: - return mlirlite.Double(pool) + elif string.strcmp(type_name, "char") == 0: return mlirlite.Int8(pool) + elif string.strcmp(type_name, "float") == 0: return mlirlite.Float(pool) + elif string.strcmp(type_name, "double") == 0: return mlirlite.Double(pool) return None def _is_t_attr(self, node: ast.AST*, attr_name: str, @@ -2211,19 +1945,14 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 裸名识别是必要功能:测试/库代码大量用 `from t import CPtr` 后直接写 `X*`、`CVoid` 参数注解等,若只认 t.XXX 会漏判。 """ - if node is None or attr_name is None: - return 0 + if node is None or attr_name is None: return 0 if node.kind() == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(node) - if at.attr is None: - return 0 - if string.strcmp(at.attr, attr_name) != 0: - return 0 - if at.value is None or at.value.kind() != ast.ASTKind.Name: - return 0 + if at.attr is None: return 0 + if string.strcmp(at.attr, attr_name) != 0: return 0 + if at.value is None or at.value.kind() != ast.ASTKind.Name: return 0 val_nm: ast.Name* = ast.Name*(at.value) - if val_nm.id is None: - return 0 + if val_nm.id is None: return 0 if string.strcmp(val_nm.id, "t") == 0: # t 是内建库(SHA1 豁免),可能不在 _imported_modules 中。 # 显式写 t.CPtr / t\.CVoid 即确指 t 模块,无需 imported_modules 确认。 @@ -2232,24 +1961,19 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 裸名形式: from t import attr_name → Name(id == attr_name) if node.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) - if nm.id is None: - return 0 - if string.strcmp(nm.id, attr_name) != 0: - return 0 + if nm.id is None: return 0 + if string.strcmp(nm.id, attr_name) != 0: return 0 # 裸名需确认 t 模块已导入(from t import X 会注册 t 到 _imported_modules) - if self.Gen.ImportsGen.is_module_imported(imported_modules, "t") == 0: - return 0 + if self.Gen.ImportsGen.is_module_imported(imported_modules, "t") == 0: return 0 return 1 return 0 def _is_cptr_marker(self, node: ast.AST*, imported_modules: str) -> int: """检测节点是否为 CPtr 指针标记,返回 1=是 / 0=否""" - if self._is_t_attr(node, "CPtr", imported_modules) != 0: - return 1 + if self._is_t_attr(node, "CPtr", imported_modules) != 0: return 1 if node is not None and node.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) - if nm.id is not None and string.strcmp(nm.id, "CPtr") == 0: - return 1 + if nm.id is not None and string.strcmp(nm.id, "CPtr") == 0: return 1 return 0 def _is_cptr_subscript(self, node: ast.AST*) -> int: """检测节点是否为 t.CPtr[T] 下标指针类型(t.CPtr[t.CPtr] / t.CPtr[int] 等) @@ -2258,19 +1982,14 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): CPtr 侧贡献 PtrCount,另一侧提供 BaseType)。t.CPtr[...] 不是 普通 CPtr 标记(_is_cptr_marker 只认 t.CPtr/CPtr 裸形式)。 """ - if node is None or node.kind() != ast.ASTKind.Subscript: - return 0 + if node is None or node.kind() != ast.ASTKind.Subscript: return 0 sub: ast.Subscript* = ast.Subscript*(node) - if sub.value is None or sub.value.kind() != ast.ASTKind.Attribute: - return 0 + if sub.value is None or sub.value.kind() != ast.ASTKind.Attribute: return 0 at: ast.Attribute* = ast.Attribute*(sub.value) - if at.attr is None or string.strcmp(at.attr, "CPtr") != 0: - return 0 - if at.value is None or at.value.kind() != ast.ASTKind.Name: - return 0 + if at.attr is None or string.strcmp(at.attr, "CPtr") != 0: return 0 + if at.value is None or at.value.kind() != ast.ASTKind.Name: return 0 nm: ast.Name* = ast.Name*(at.value) - if nm.id is None or string.strcmp(nm.id, "t") != 0: - return 0 + if nm.id is None or string.strcmp(nm.id, "t") != 0: return 0 return 1 def _is_tattr_marker(self, node: ast.AST*) -> int: """检测节点是否为 `t.attr.<名>` 属性标记(含调用形 `t.attr.<名>(...)`)。 @@ -2283,72 +2002,57 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 生成 `@g = global i8 ` 非法 IR(opt: constant expression type mismatch: got type 'ptr' but expected 'i8')。 """ - if node is None: - return 0 + if node is None: return 0 inner: ast.AST* = node if inner.kind() == ast.ASTKind.Call: cl: ast.Call* = ast.Call*(inner) - if cl.func is None: - return 0 + if cl.func is None: return 0 inner = cl.func - if inner.kind() != ast.ASTKind.Attribute: - return 0 + if inner.kind() != ast.ASTKind.Attribute: return 0 at: ast.Attribute* = ast.Attribute*(inner) - if at.attr is None or at.value is None: - return 0 - if at.value.kind() != ast.ASTKind.Attribute: - return 0 + if at.attr is None or at.value is None: return 0 + if at.value.kind() != ast.ASTKind.Attribute: return 0 root: ast.Attribute* = ast.Attribute*(at.value) - if root.attr is None or root.value is None: - return 0 - if root.value.kind() != ast.ASTKind.Name: - return 0 + if root.attr is None or root.value is None: return 0 + if root.value.kind() != ast.ASTKind.Name: return 0 rn: ast.Name* = ast.Name*(root.value) - if rn.id is None or string.strcmp(rn.id, "t") != 0: - return 0 - if string.strcmp(root.attr, "attr") != 0: - return 0 + if rn.id is None or string.strcmp(rn.id, "t") != 0: return 0 + if string.strcmp(root.attr, "attr") != 0: return 0 return 1 def _is_cvoid_marker(self, node: ast.AST*, imported_modules: str) -> int: """检测节点是否为 CVoid 指针标记,返回 1=是 / 0=否""" - if self._is_t_attr(node, "CVoid", imported_modules) != 0: - return 1 + if self._is_t_attr(node, "CVoid", imported_modules) != 0: return 1 if node is not None and node.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) # 裸名 CVoid(from t import CVoid)与内置别名 void(无需 import)同义 if nm.id is not None: - if string.strcmp(nm.id, "CVoid") == 0 or string.strcmp(nm.id, "void") == 0: - return 1 + if string.strcmp(nm.id, "CVoid") == 0 or string.strcmp(nm.id, "void") == 0: return 1 return 0 def annotation_to_str(self, annot: ast.AST*) -> str: """将类型注解 AST 转换为可读字符串,返回 None=无法提取 注意:返回的字符串可能由 malloc 分配,调用方无需释放(错误路径用)。 """ - if annot is None: - return "" + if annot is None: return "" k: int = annot.kind() # Constant 节点: 字符串注解 if k == ast.ASTKind.Constant: cn: ast.Constant* = ast.Constant*(annot) - if cn.const_kind == ast.CONST_STR and cn.str_val is not None: - return cn.str_val + if cn.const_kind == ast.CONST_STR and cn.str_val is not None: return cn.str_val return "" # Name 节点: bool, int, MemBuddy if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(annot) - if nm.id is not None: - return nm.id + if nm.id is not None: return nm.id return "" # Attribute 节点: t.CBool, memhub.MemBuddy if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(annot) - if at.attr is None: - return "" + if at.attr is None: return "" if at.value is not None: prefix: str = self.annotation_to_str(at.value) if prefix is not None: @@ -2396,8 +2100,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 会被提取成 "CStatic" → AnnotClassName 丢失无符号信息(N3: 模块级全局 uint32 比较生成 icmp sge/slt 而非 uge/ult)。 """ - if name is None: - return 0 + if name is None: return 0 if string.strcmp(name, "CStatic") == 0: return 1 if string.strcmp(name, "CVolatile") == 0: return 1 if string.strcmp(name, "CExport") == 0: return 1 @@ -2419,8 +2122,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 与特化注册名一致(消除 list[AST].set undefined symbol)。 pool 为 None 时,对 Subscript 只返回裸类名(如 "list"),保持向后兼容。 """ - if node is None: - return None + if node is None: return None k: int = node.kind() # Constant 节点: 字符串注解(如 'MemManager'),简单类名直接返回 @@ -2429,62 +2131,45 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if cn.const_kind == ast.CONST_STR and cn.str_val is not None: # 仅处理简单类名(不含 . 和 |),复杂形式返回 None if string.strchr(cn.str_val, 46) is None and string.strchr(cn.str_val, 124) is None: - if string.strcmp(cn.str_val, "str") == 0: - return None - if string.strcmp(cn.str_val, "char") == 0: - return None - if string.strcmp(cn.str_val, "int") == 0: - return None - if string.strcmp(cn.str_val, "bytes") == 0: - return None - if string.strcmp(cn.str_val, "bool") == 0: - return None - if string.strcmp(cn.str_val, "float") == 0: - return None - if string.strcmp(cn.str_val, "double") == 0: - return None + if string.strcmp(cn.str_val, "str") == 0: return None + if string.strcmp(cn.str_val, "char") == 0: return None + if string.strcmp(cn.str_val, "int") == 0: return None + if string.strcmp(cn.str_val, "bytes") == 0: return None + if string.strcmp(cn.str_val, "bool") == 0: return None + if string.strcmp(cn.str_val, "float") == 0: return None + if string.strcmp(cn.str_val, "double") == 0: return None return cn.str_val return None # Name 节点: MemBuddy → "MemBuddy" if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) - if nm.id is None: - return None + if nm.id is None: return None # 泛型特化上下文:T → 具体类型(特化方法体内局部变量注解 # 如 `cur: T*` 未被 _clone_classdef_for_spec 克隆替换, # 依赖此处在翻译时经上下文解析;否则 cur.annot="T", # 属性访问 cur.Next → lookup_field_by_class("T") 未注册报错) resolved_id: str = self.Gen.TypeGenBase.resolve_generic_type_name(nm.id) - if resolved_id is None: - return None + if resolved_id is None: return None # 跳过内置类型名 - if string.strcmp(resolved_id, "str") == 0: - return None - if string.strcmp(resolved_id, "char") == 0: - return None - if string.strcmp(resolved_id, "bytes") == 0: - return None - if string.strcmp(resolved_id, "bool") == 0: - return None - if string.strcmp(resolved_id, "float") == 0: - return None - if string.strcmp(resolved_id, "double") == 0: - return None + if string.strcmp(resolved_id, "str") == 0: return None + if string.strcmp(resolved_id, "char") == 0: return None + if string.strcmp(resolved_id, "bytes") == 0: return None + if string.strcmp(resolved_id, "bool") == 0: return None + if string.strcmp(resolved_id, "float") == 0: return None + if string.strcmp(resolved_id, "double") == 0: return None return resolved_id # Attribute 节点: memhub.MemBuddy → "memhub.MemBuddy"(模块限定名) if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(node) - if at.attr is None: - return None + if at.attr is None: return None # t.XXX 内置类型:返回 XXX(如 uint32 → "CUInt32T"), # 供 AnnotClassName 记录变量类型名(_type_name_unsigned 判断无符号性时使用)。 # 消费方(find_struct/lookup_field_by_class)对非结构体名返回 None 优雅降级。 if at.value is not None and at.value.kind() == ast.ASTKind.Name: val_nm2: ast.Name* = ast.Name*(at.value) - if val_nm2.id is not None and string.strcmp(val_nm2.id, "t") == 0: - return at.attr + if val_nm2.id is not None and string.strcmp(val_nm2.id, "t") == 0: return at.attr # import 别名还原:val_nm2.id 可能是 "import X as Y" 的别名 Y # (如 "import fat32_types as types" → types.fileinfo 实为 # fat32_types.fileinfo)。还原为模块真名后,AnnotClassName 存 @@ -2493,19 +2178,16 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): alias_mod2: str = None if from_imports is not None: alias_mod2 = StubMergerStore.LookupModNameByAlias(from_imports, val_nm2.id) - if alias_mod2 is not None: - real_mod2 = alias_mod2 + if alias_mod2 is not None: real_mod2 = alias_mod2 # 返回模块限定名 "module.Class"(如 "memhub.MemBuddy") mod_qual_buf: str = stdlib.malloc(string.strlen(real_mod2) + string.strlen(at.attr) + 2) if mod_qual_buf is not None: viperlib.snprintf(mod_qual_buf, string.strlen(real_mod2) + string.strlen(at.attr) + 2, "%s.%s", real_mod2, at.attr) - if alias_mod2 is not None: - stdlib.free(alias_mod2) + if alias_mod2 is not None: stdlib.free(alias_mod2) return mod_qual_buf - if alias_mod2 is not None: - stdlib.free(alias_mod2) + if alias_mod2 is not None: stdlib.free(alias_mod2) return at.attr # BinOp 节点: 联合类型 A | B @@ -2515,10 +2197,8 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): left_is_cptr: int = self._is_cptr_marker(bop.left, imported_modules) right_is_cptr: int = self._is_cptr_marker(bop.right, imported_modules) # 提取非 CPtr 一边的类名 - if left_is_cptr != 0 and right_is_cptr == 0: - return self.extract_class_name_from_annotation(bop.right, imported_modules, pool, from_imports) - if right_is_cptr != 0 and left_is_cptr == 0: - return self.extract_class_name_from_annotation(bop.left, imported_modules, pool, from_imports) + if left_is_cptr != 0 and right_is_cptr == 0: return self.extract_class_name_from_annotation(bop.right, imported_modules, pool, from_imports) + if right_is_cptr != 0 and left_is_cptr == 0: return self.extract_class_name_from_annotation(bop.left, imported_modules, pool, from_imports) # 无 CPtr 标记:尝试两边,但**优先真实类型**——限定宏 # (CStatic/CVolatile/CExport…)是存储类标记,若左侧是限定宏 # 而右侧才是类型,取左侧会把 AnnotClassName 记成 "CStatic", @@ -2526,12 +2206,9 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if left_is_cptr == 0 and right_is_cptr == 0: left_name: str = self.extract_class_name_from_annotation(bop.left, imported_modules, pool, from_imports) right_name: str = self.extract_class_name_from_annotation(bop.right, imported_modules, pool, from_imports) - if left_name is not None and self._is_storage_class_qualifier(left_name) == 0: - return left_name - if right_name is not None and self._is_storage_class_qualifier(right_name) == 0: - return right_name - if left_name is not None: - return left_name + if left_name is not None and self._is_storage_class_qualifier(left_name) == 0: return left_name + if right_name is not None and self._is_storage_class_qualifier(right_name) == 0: return right_name + if left_name is not None: return left_name return right_name return None @@ -2540,8 +2217,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 与 resolve_annotation_type 的 mangled name 格式一致,使 find_struct 能找到特化结构体 if k == ast.ASTKind.Subscript: sub: ast.Subscript* = ast.Subscript*(node) - if sub.value is None: - return None + if sub.value is None: return None # rawptr[T] 是内建裸指针(等价 t.CPtr[T]),AnnotClassName 应取 pointee # 类名 T(字段访问按 T 查结构体),而非 "rawptr" / "rawptr[T]"——否则 # lookup_field_by_class 报"类 'rawptr' 未注册"(json.__parser _peek @@ -2549,19 +2225,16 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if sub.value.kind() == ast.ASTKind.Name: rp_nm: ast.Name* = ast.Name*(sub.value) if rp_nm.id is not None and string.strcmp(rp_nm.id, "rawptr") == 0: - if sub.slice is not None: - return self.extract_class_name_from_annotation(sub.slice, imported_modules, pool, from_imports) + if sub.slice is not None: return self.extract_class_name_from_annotation(sub.slice, imported_modules, pool, from_imports) return None # 递归取 base 时必须把 from_imports 一并下传:否则同一份注解在派发名/查表键/ # 注册键三处算出的 mangled 名不一致(如 list[ast.AST*] 的元素段), # 出现「alloca 裸 list* / pass1 按 list[ast.ASTptr] / pass2 按 list[ast.ClassDefptr]」 # 的分裂崩溃。其余调用点均已传。 base_name: str = self.extract_class_name_from_annotation(sub.value, imported_modules, pool, from_imports) - if base_name is None: - return None + if base_name is None: return None # pool 不可用时,只返回裸类名(向后兼容) - if pool is None or sub.slice is None: - return base_name + if pool is None or sub.slice is None: return base_name # pool 可用:拼接 mangled name "base_name[slice_name]" # slice 是 Tuple 时用逗号分隔多个参数,否则单个参数 slice_name: str = None @@ -2584,28 +2257,22 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): tup_total: sizet = 1 ti_sn: sizet for ti_sn in range(tn_sn): - if ti_sn > 0: - tup_total += 1 + if ti_sn > 0: tup_total += 1 elt_node: ast.AST* = tup_elts_sn.get(ti_sn) elt_name_raw: str = self._get_type_name_from_annotation(pool, elt_node) elt_name: str = elt_name_raw - if _cntc_sn == 0 or ti_sn != 1: - elt_name = self._norm_type_arg_name(pool, elt_name_raw, from_imports) - if elt_name is not None: - tup_total += string.strlen(elt_name) + if _cntc_sn == 0 or ti_sn != 1: elt_name = self._norm_type_arg_name(pool, elt_name_raw, from_imports) + if elt_name is not None: tup_total += string.strlen(elt_name) tup_buf: str = pool.alloc(tup_total) if tup_buf is not None: tup_buf[0] = '\0' for ti_sn in range(tn_sn): - if ti_sn > 0: - string.strcat(tup_buf, ",") + if ti_sn > 0: string.strcat(tup_buf, ",") elt_node2: ast.AST* = tup_elts_sn.get(ti_sn) elt_name2_raw: str = self._get_type_name_from_annotation(pool, elt_node2) elt_name2: str = elt_name2_raw - if _cntc_sn == 0 or ti_sn != 1: - elt_name2 = self._norm_type_arg_name(pool, elt_name2_raw, from_imports) - if elt_name2 is not None: - string.strcat(tup_buf, elt_name2) + if _cntc_sn == 0 or ti_sn != 1: elt_name2 = self._norm_type_arg_name(pool, elt_name2_raw, from_imports) + if elt_name2 is not None: string.strcat(tup_buf, elt_name2) slice_name = tup_buf else: # 非 Tuple slice: list[AST*] → "ast.AST*" @@ -2613,13 +2280,11 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 与特化注册名一致(list[f467978339422f32.AST*]) slice_raw: str = self._get_type_name_from_annotation(pool, sub.slice) slice_name = self._norm_type_arg_name(pool, slice_raw, from_imports) - if slice_name is None: - return base_name + if slice_name is None: return base_name # 拼接 "base_name[slice_name]" mangled_total: sizet = string.strlen(base_name) + 1 + string.strlen(slice_name) + 1 + 1 mangled_buf: str = pool.alloc(mangled_total) - if mangled_buf is None: - return base_name + if mangled_buf is None: return base_name mangled_buf[0] = '\0' string.strcat(mangled_buf, base_name) string.strcat(mangled_buf, "[") @@ -2636,8 +2301,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): from_imports: str, depth: int = 0) -> mlirlite.LLVMType*: """解析泛型类类型注解(特化或查找已注册结构体),失败返回 None""" - if pool is None or sub is None or gen_cls_name is None: - return None + if pool is None or sub is None or gen_cls_name is None: return None # tuple[T1, T2, ...] → 匿名结构体 {T1, T2, ...}(多返回值打包, # 对齐 TPC LLVMTypeMapper._resolve_subscript 的 '{ ty1, ty2 }')。 # 用于函数 `-> tuple[str, t.CUnsignedShort]`(如 binascii.b2a_hqx) @@ -2658,28 +2322,21 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): tp_single.append(sub.slice) tp_elts = tp_single tp_count = 1 - if tp_count == 0 or tp_elts is None: - return None + if tp_count == 0 or tp_elts is None: return None tup_head: mlirlite.ParamNode* = None tup_tail: mlirlite.ParamNode* = None tui: sizet for tui in range(tp_count): tup_elt: ast.AST* = tp_elts.get(tui) - if tup_elt is None: - continue + if tup_elt is None: continue tup_ety: mlirlite.LLVMType* = self.resolve_annotation_type(pool, tup_elt, imported_modules, from_imports, trans, depth + 1) - if tup_ety is None: - return None + if tup_ety is None: return None tup_node: mlirlite.ParamNode* = mlirlite.new_param_node(pool, tup_ety) - if tup_node is None: - return None - if tup_head is None: - tup_head = tup_node - else: - mlirlite.paramnode_set_next(tup_tail, tup_node) + if tup_node is None: return None + if tup_head is None: tup_head = tup_node + else: mlirlite.paramnode_set_next(tup_tail, tup_node) tup_tail = tup_node - if tup_head is None: - return None + if tup_head is None: return None return mlirlite.Struct(pool, tup_head, tp_count, None) # 先收集类型实参名,再分配缓冲区拼接 mangled name(elem_size=8:str 是指针) gen_arg_names: list[str]* = list[str](pool, 8) @@ -2708,21 +2365,17 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if gen_ai > 0: gen_total += 1 # "," gen_atn: str = gen_arg_names.get(gen_ai) - if gen_atn is not None: - gen_total += string.strlen(gen_atn) + if gen_atn is not None: gen_total += string.strlen(gen_atn) gen_total += 1 # NUL gen_mangled: str = pool.alloc(gen_total) - if gen_mangled is None: - return None + if gen_mangled is None: return None gen_mangled[0] = '\0' string.strcat(gen_mangled, gen_cls_name) string.strcat(gen_mangled, "[") for gen_ai in range(gen_an): - if gen_ai > 0: - string.strcat(gen_mangled, ",") + if gen_ai > 0: string.strcat(gen_mangled, ",") gen_atn: str = gen_arg_names.get(gen_ai) - if gen_atn is not None: - string.strcat(gen_mangled, gen_atn) + if gen_atn is not None: string.strcat(gen_mangled, gen_atn) string.strcat(gen_mangled, "]") # [REPL 注入期] 只做类型/签名层面的事,**绝不触发模板体翻译**(特化延后)。 # @@ -2746,18 +2399,15 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if trans is not None and trans.ReplCtx is not None and VpiReader.ReplStubLayoutMode != 0: # 已登记的特化结构体(会话期先前注册)直接复用:本分支只读、不翻译 spec_ty_inj: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(gen_mangled) - if spec_ty_inj is not None: - return spec_ty_inj + if spec_ty_inj is not None: return spec_ty_inj # 归属模块 sha1:优先取**全局模板表**(步骤③'' 已按 includes 全量注册, # 与模块注入顺序无关 ⇒ 跨模块泛型如 GSList 也能拼出定义侧特化名); # 退回注入期逐模块登记的归属表(StubMergerStore.RegisterGenericOwner)。 inj_owner: str = self.Gen.ClassGenGeneric._find_generic_template_sha1(gen_cls_name) - if inj_owner is None: - inj_owner = StubMergerStore.LookupGenericOwnerSha1(gen_cls_name) + if inj_owner is None: inj_owner = StubMergerStore.LookupGenericOwnerSha1(gen_cls_name) if inj_owner is not None: ty_inj: mlirlite.LLVMType* = self._repl_opaque_class_ty(pool, inj_owner, gen_mangled) - if ty_inj is not None: - return ty_inj + if ty_inj is not None: return ty_inj # 归属未知(模板/归属均未登记)⇒ 保持原口径返回 None,由上层按 # "注解解析失败"明确报错(不伪造无模块前缀的类名) return None @@ -2798,18 +2448,12 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # → 按 gen_mangled 重查恒 miss → 静默退化为裸 list* → .get() 误分派截断。 # spec_name_chk 是特化侧返回的权威特化名,必须按它重查。 # 注:非联合实参(如 list[int])两侧命名一致,本步恒 miss 不改变行为。 - 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") + 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") # Phase B(declare_only==0)全量翻译时,泛型模板类的下标仍解析不出特化结构体 # ⇒ 上游注解必然退化(BinOp 分支落到 Ptr(i8) 丢类型,或退化到裸基类 list*), # 后续 .get() 按错误元素类型分派 → inttoptr 截断崩溃。禁止静默退化:报出查表键 @@ -2836,8 +2480,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): gowner_sha1: str = StubMergerStore.LookupGenericOwnerSha1(gen_cls_name) if gowner_sha1 is not None: ty_repl_g: mlirlite.LLVMType* = self._repl_opaque_class_ty(pool, gowner_sha1, gen_mangled) - if ty_repl_g is not None: - return ty_repl_g + if ty_repl_g is not None: return ty_repl_g # 未特化:返回 None(不报错,让后续流程处理) return None @@ -2856,8 +2499,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # ============================================================ def _check_bare_generic_annotation(self, node: ast.AST*) -> int: """裸泛型注解 fail-fast(返回 0;命中即 fatal_error 终止)""" - if node is None: - return 0 + if node is None: return 0 base_nm: str = None k: int = node.kind() if k == ast.ASTKind.Name: @@ -2866,13 +2508,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): elif k == ast.ASTKind.Attribute: at_bg: ast.Attribute* = ast.Attribute*(node) base_nm = at_bg.attr - else: - return 0 - if base_nm is None: - return 0 + else: return 0 + if base_nm is None: return 0 # 仅当基名确实是本项目已注册的泛型模板才判定为裸泛型注解 - if self.Gen.ClassGenGeneric._find_generic_template(base_nm) is None: - return 0 + 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"裸名会被当作无实参的裸泛型基类,元素类型丢失后方法调用会按错误元素" @@ -2895,14 +2534,12 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): trans: 翻译器对象(可选,用于触发泛型特化) depth: 递归深度(防御 AST 损坏成自引用环导致的无限递归) """ - if node is None: - return None + if node is None: return None # 递归深度守卫:AST 损坏成自引用环(子节点回指祖先)时,无守卫的 # BinOp/Subscript/Constant/Tuple 递归会无限加深直至栈耗尽(自举版 # TransPyV.exe 编译 FuncTest 时 ASan stack-overflow 首选嫌疑)。超过 # 128 层即 fail-fast 终止(fatal_type_error → sys.exit(1)),不静默兜底。 - if depth > 128: - self.Gen.TypeGenErr.fatal_type_error(node, "类型注解递归过深(AST 环或嵌套超过 128 层)") + if depth > 128: self.Gen.TypeGenErr.fatal_type_error(node, "类型注解递归过深(AST 环或嵌套超过 128 层)") # 裸泛型注解 fail-fast(集中守卫,见 _check_bare_generic_annotation): # 注解本身或 A* 的一侧是"已注册泛型模板类名"却没写 [类型实参] 即终止。 @@ -2913,19 +2550,16 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # Constant 节点: 字符串注解(如 'MemManager'),当作无引号的 Name/Attribute/BinOp 处理 if k == ast.ASTKind.Constant: cn: ast.Constant* = ast.Constant*(node) - if cn.const_kind == ast.CONST_NONE: - return mlirlite.Void(pool) + if cn.const_kind == ast.CONST_NONE: return mlirlite.Void(pool) if cn.const_kind == ast.CONST_STR and cn.str_val is not None: sub_node: ast.AST* = self._parse_type_string(pool, cn.str_val, ast.ASTCtx.Load) - if sub_node is not None: - return self.resolve_annotation_type(pool, sub_node, imported_modules, from_imports, trans, depth + 1) + if sub_node is not None: return self.resolve_annotation_type(pool, sub_node, imported_modules, from_imports, trans, depth + 1) return None # Name 节点: str, int, bytes, from-import 名称, class 名称等 if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) - if nm.id is None: - return None + if nm.id is None: return None # 内建定长数组构造子 array 是**软关键字**:只在类型/注解位置作为 # array[E, N] 生效;裸用(缺少下标与参数)在类型位置属误用 → fail-fast。 # 非类型位置(如 json.array(pool) 调用、from json import array)不受影响。 @@ -2975,8 +2609,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): self.Gen.TypeGenErr.fatal_error(nm, f"泛型类型实参污染:实参 '{gp_ta}' 包含类型参数名,无法特化", "TypeError") # 用具体类型名递归解析(支持 BinOp/Attribute 类型实参) 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) + if gp_sub_node is not None: return self.resolve_annotation_type(pool, gp_sub_node, imported_modules, from_imports, trans, depth + 1) # 已规范化 sha1 前缀名 "{16hex}.Class"(_norm_type_arg_name 产物,如泛型 # 实参 rawptr[7565e081d88517ac.AST] 的括号内层):模块段即 SHA1(天然 # 已编译),无需 import 检查。解析器把 "a.b" 折叠为单 Name(int 同款), @@ -3001,29 +2634,22 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): return sp_entry2.Ty # 兜底:按完整前缀名直接查(部分注册键即全名) sp_full2: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(nm.id) - if sp_full2 is not None: - return sp_full2 + if sp_full2 is not None: return sp_full2 return None # str = bytes = str = i8* - if string.strcmp(nm.id, "str") == 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) - elif string.strcmp(nm.id, "None") == 0: - return mlirlite.Void(pool) - elif string.strcmp(nm.id, "int") == 0: - return mlirlite.Int32(pool) + if string.strcmp(nm.id, "str") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + elif string.strcmp(nm.id, "None") == 0: return mlirlite.Void(pool) + elif string.strcmp(nm.id, "int") == 0: return mlirlite.Int32(pool) elif string.strcmp(nm.id, "char") == 0: # char = char = i8(与 map_t_type 中 CChar/char 映射一致) return mlirlite.Int8(pool) - elif string.strcmp(nm.id, "bytes") == 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + elif string.strcmp(nm.id, "bytes") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) elif string.strcmp(nm.id, "bool") == 0: # bool = t.CBool = i1(与 map_t_type 中 CBool 映射一致) return mlirlite.Int1(pool) # 裸名浮点类型: float = t.CFloat = f32, double = t.CDouble = f64 - elif string.strcmp(nm.id, "float") == 0: - return mlirlite.Float(pool) - elif string.strcmp(nm.id, "double") == 0: - return mlirlite.Double(pool) + elif string.strcmp(nm.id, "float") == 0: return mlirlite.Float(pool) + elif string.strcmp(nm.id, "double") == 0: return mlirlite.Double(pool) # class 名称: 查找已注册的 StructType,返回 StructType 本身(不包装 Ptr) # 这样 build_alloca 会分配结构体大小的空间,alloca 返回 struct_ty* # 命名空间隔离:严格模式下仅解析可见的结构体 @@ -3056,8 +2682,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if inj_mod_rn is not None: if string.strcmp(inj_mod_rn, trans.ModuleSha1) != 0: inj_e_rn: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(nm.id, inj_mod_rn) - if inj_e_rn is not None and inj_e_rn.Ty is not None: - return inj_e_rn.Ty + if inj_e_rn is not None and inj_e_rn.Ty is not None: return inj_e_rn.Ty # from-import 归属查找:注解里的裸名(或 import 别名)经 from_imports 定位到 # 定义模块,再按 (name, sha1) 精确取类——这是 stub 注入场景的正解:此刻 # trans.ModuleSha1 是"正在翻译的文件",而注解里的类归属 stub 源模块 @@ -3068,8 +2693,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): fi_mod: str = StubMergerStore.LookupModNameByAlias(from_imports, nm.id) if fi_mod is not None: fi_sha1: str = StubMergerStore.LookupSha1ByModName(fi_mod) - if fi_sha1 is None: - fi_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(fi_mod) + if fi_sha1 is None: fi_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(fi_mod) fi_sha1_rn = fi_sha1 stdlib.free(fi_mod) if fi_sha1 is not None: @@ -3084,8 +2708,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): return struct_ty # 枚举类(t.CEnum)裸名注解 → 底层整数类型 # 如 fat32_types.vp 内部 `res: FRESULT = ...`(FRESULT 是枚举非结构体) - if self.Gen.StmtGenDecl.is_enum_class(nm.id) == 1: - return self.Gen.StmtGenDecl.get_enum_base_type(nm.id) + if self.Gen.StmtGenDecl.is_enum_class(nm.id) == 1: return self.Gen.StmtGenDecl.get_enum_base_type(nm.id) # CTypedef 动态查表:查动态 CTypedef 表,递归解析类型表达式 # 用户自定义 CTypedef(如 MyHandle: t.CTypedef = VOIDPTR)在此解析 # 递归深度限制 MAX_CTYPEDEF_DEPTH 防止无限递归,循环检测防止 A→B→A @@ -3101,17 +2724,14 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): inner_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, inner_node, imported_modules, from_imports, trans, depth + 1) self.Gen.TypeGenCType.CTypedefResolveDepth -= 1 self.Gen.TypeGenCType._ctypedef_pop_visiting() - if inner_ty is not None: - return inner_ty - else: - self.Gen.TypeGenCType._ctypedef_pop_visiting() + if inner_ty is not None: return inner_ty + else: self.Gen.TypeGenCType._ctypedef_pop_visiting() # 兜底: 尝试 map_t_type 中的硬编码 typedef 映射(VOIDPTR, HANDLE, ULONG 等) # 这些是跨模块通用的 C typedef 名,即使 from-import 查找失败也能解析 # 注意:from-import 的结构体名若未注册,get_struct_type 已返回 None, # 此处 map_t_type 对结构体名也返回 None,由上层 declare_only 机制延迟到下一遍 mapped_ty_fallback: mlirlite.LLVMType* = self.map_t_type(pool, nm.id) - if mapped_ty_fallback is not None: - return mapped_ty_fallback + if mapped_ty_fallback is not None: return mapped_ty_fallback # [阶段1a] from-import 别名反查(正常库分析):from t import CInt as XXX # 裸名 XXX 不在 struct/CTypedef/map_t_type 任何表,反查原始名后递归解析。 # 支撑复杂别名链:YYY: t.CTypedef = XXX(typedef 值引用 from-import 别名)。 @@ -3120,21 +2740,18 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if orig_alias is not None and string.strcmp(orig_alias, nm.id) != 0: # 内部指针未 null 终止,复制到独立缓冲区(截断于空格/null) oa_len: sizet = 0 - while orig_alias[oa_len] != ' ' and orig_alias[oa_len] != '\0': - oa_len += 1 + while orig_alias[oa_len] != ' ' and orig_alias[oa_len] != '\0': oa_len += 1 if oa_len > 0: oa_buf: str = pool.alloc(oa_len + 1) if oa_buf is not None: oa_i: sizet - for oa_i in range(oa_len): - oa_buf[oa_i] = orig_alias[oa_i] + for oa_i in range(oa_len): oa_buf[oa_i] = orig_alias[oa_i] oa_buf[oa_len] = '\0' # 用原始名重建节点递归解析(depth 守卫复用 resolve 上限) orig_node_a: ast.AST* = self._parse_type_string(pool, oa_buf, nm.ctx) if orig_node_a is not None: alias_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, orig_node_a, imported_modules, from_imports, trans, depth + 1) - if alias_ty is not None: - return alias_ty + if alias_ty is not None: return alias_ty # [builtins 最后匹配] 常规路径全部 miss 后的最终兜底:查 # includes/builtins.vp 的 CTypedef 声明(如 rawptr: t.CTypedef = # t.CPtr)。命中展开类型表达式后递归解析,仍失败才由调用方报错。 @@ -3143,21 +2760,18 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): btd_node_n: ast.AST* = self._parse_type_string(pool, btd_n, nm.ctx) if btd_node_n is not None: btd_ty_n: mlirlite.LLVMType* = self.resolve_annotation_type(pool, btd_node_n, imported_modules, from_imports, trans, depth + 1) - if btd_ty_n is not None: - return btd_ty_n + if btd_ty_n is not None: return btd_ty_n # 库 typedef 兜底:stdint / w32.win32base 等库模块的裸 typedef # (BYTEPTR/DWORD/HANDLE/LPCSTR/...)定义在依赖源中,_vpi_register_typedef_closure # 因时序/上下文未注入时,直接读库源注册并解析(string.vp BYTEPTR、 # win32process STARTUPINFOA 字段 HANDLE 根因)。与 resolve_typedef_or_map 同口径。 lib_ts_n: str = self._lookup_library_typedef(pool, "stdint", nm.id) - if lib_ts_n is None: - lib_ts_n = self._lookup_library_typedef(pool, "w32.win32base", nm.id) + if lib_ts_n is None: lib_ts_n = self._lookup_library_typedef(pool, "w32.win32base", nm.id) if lib_ts_n is not None: lib_node_n: ast.AST* = self._parse_type_string(pool, lib_ts_n, nm.ctx) if lib_node_n is not None: lib_ty_n: mlirlite.LLVMType* = self.resolve_annotation_type(pool, lib_node_n, imported_modules, from_imports, trans, depth + 1) - if lib_ty_n is not None: - return lib_ty_n + if lib_ty_n is not None: return lib_ty_n # [REPL 会话] 归属模块已知(from_imports 解析出 sha1;或本模块自身 = # 注入期 trans.ModuleSha1 = 当前 stub 的源模块 sha1)但该类未在会话 # StructTable 登记(M4.2 布局不可信被拒 / 字段类型不可解析被跳过)⇒ @@ -3173,19 +2787,16 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # "%{会话sha1}.{类名}" 这种宿主里不存在的类名 → 方法调用符号名误导), # 故排除该情形,保持原 fail-fast。 if own_sha_rn is None: - if trans.ModuleSha1 is not None and string.strcmp(trans.ModuleSha1, GenTypes.REPL_SESSION_SHA1) != 0: - own_sha_rn = trans.ModuleSha1 + if trans.ModuleSha1 is not None and string.strcmp(trans.ModuleSha1, GenTypes.REPL_SESSION_SHA1) != 0: own_sha_rn = trans.ModuleSha1 if own_sha_rn is not None: ty_repl_n: mlirlite.LLVMType* = self._repl_opaque_class_ty(pool, own_sha_rn, nm.id) - if ty_repl_n is not None: - return ty_repl_n + if ty_repl_n is not None: return ty_repl_n return None # Attribute 节点: int, uint64, namespace_defs.PlainStruct 等 if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(node) - if at.attr is None: - return None + if at.attr is None: return None # 检查 value 是否是 Name('t') 或 Name('c') if at.value is not None and at.value.kind() == ast.ASTKind.Name: val_name: ast.Name* = ast.Name*(at.value) @@ -3193,8 +2804,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # t/c 是内建库(SHA1 豁免),显式写 t.XXX 即确指内建库, # 不依赖 imported_modules(t 可能不在其中,如 vpi 注入上下文) is_builtin_attr: int = 0 - if string.strcmp(val_name.id, "t") == 0 or string.strcmp(val_name.id, "c") == 0: - is_builtin_attr = 1 + if string.strcmp(val_name.id, "t") == 0 or string.strcmp(val_name.id, "c") == 0: is_builtin_attr = 1 if is_builtin_attr == 0: # SHA1 前缀("{16hex}.Class",跨模块特化类型参数规范化名): # 模块段即 SHA1,天然"已导入"(SHA1 唯一对应已编译模块), @@ -3215,12 +2825,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): td_known: int = 0 # 模块名先按 builtins import 别名还原(__stdint → stdint) v_real: str = self._resolve_import_alias(val_name.id) - if v_real is None: - v_real = val_name.id + if v_real is None: v_real = val_name.id if StubMergerStore.LookupSha1ByModName(v_real) is not None: lib_td_v: str = self._lookup_library_typedef(pool, val_name.id, at.attr) - if lib_td_v is not None: - td_known = 1 + if lib_td_v is not None: td_known = 1 if td_known == 0: # 嵌套类 / 嵌套 struct:限定名 `外类.内类`(base 是**类名** # 而非模块名)。到达此处已确定 base 既非 t/c、非 SHA1 @@ -3228,8 +2836,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 故新增"扁平名 `外类_内类` 命中即返回"不会覆盖任何既有 # 成功路径(命名口径见 ClassGenDef._translate_nested_classdefs)。 nested_ty_q: mlirlite.LLVMType* = self._resolve_nested_class_type(pool, val_name.id, at.attr, trans) - if nested_ty_q is not None: - return nested_ty_q + if nested_ty_q is not None: return nested_ty_q return None # [阶段1b] 库 typedef 动态表优先(正常库分析):attr 是库声明 # 的 typedef 名(如 stdint.INT/BYTE)且表已注册 → 递归展开走库 @@ -3245,12 +2852,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): inner_ty_attr: mlirlite.LLVMType* = self.resolve_annotation_type(pool, inner_attr, imported_modules, from_imports, trans, depth + 1) self.Gen.TypeGenCType.CTypedefResolveDepth -= 1 self.Gen.TypeGenCType._ctypedef_pop_visiting() - if inner_ty_attr is not None: - return inner_ty_attr + if inner_ty_attr is not None: return inner_ty_attr # 先尝试内置类型映射(int 等) mapped_ty: mlirlite.LLVMType* = self.map_t_type(pool, at.attr) - if mapped_ty is not None: - return mapped_ty + if mapped_ty is not None: return mapped_ty # 模块限定类类型:Module.ClassName(命名空间隔离) # SHA1 前缀形态优先用完整名 "{sha1}.{Class}" 精确命中定义侧 # struct(get_struct_type 类名回退可能命中跨模块同名类) @@ -3264,10 +2869,8 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if is_builtin_attr == 0 and GenApi.is_sha1_hex16(val_name.id) != 0: mod_sha1_rv = val_name.id full_q: str = self._concat_sha1_class(pool, val_name.id, at.attr) - if full_q is not None: - full_attr_ty = self.Gen.StructGen.get_struct_type(full_q) - if full_attr_ty is not None: - return full_attr_ty + if full_q is not None: full_attr_ty = self.Gen.StructGen.get_struct_type(full_q) + if full_attr_ty is not None: return full_attr_ty # 跨模块限定名(Module.Class,Module 非 t/c/SHA1):按模块归属解析, # 禁止裸名回退抓跨模块同名类(根因:VKernel sched.Thread 被 # includes/vthreading.vp 同名 Thread 顶掉 → 'tid' 字段缺失)。 @@ -3289,19 +2892,16 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if inj_nm_a is not None: inj_seg_a: str = inj_nm_a dot_a: str = string.strrchr(inj_nm_a, '.') - if dot_a is not None: - inj_seg_a = dot_a + 1 + if dot_a is not None: inj_seg_a = dot_a + 1 nm_eq_a: int = string.strcmp(inj_nm_a, val_name.id) seg_eq_a: int = string.strcmp(inj_seg_a, val_name.id) - if nm_eq_a == 0 or seg_eq_a == 0: - mod_sha1_v = inj_mod_a + if nm_eq_a == 0 or seg_eq_a == 0: mod_sha1_v = inj_mod_a mod_sha1_rv = mod_sha1_v if mod_sha1_v is not None: full_q_v: str = self._concat_sha1_class(pool, mod_sha1_v, at.attr) if full_q_v is not None: full_ty_v: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(full_q_v) - if full_ty_v is not None: - return full_ty_v + if full_ty_v is not None: return full_ty_v mod_entry_v: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(at.attr, mod_sha1_v) if mod_entry_v is not None and mod_entry_v.Ty is not None: # 裸类名(含 mod.Class 限定名)恒为原型(见上方同口径注释) @@ -3320,23 +2920,19 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): full_q_td: str = self._concat_sha1_class(pool, mod_sha1_td, at.attr) if full_q_td is not None: full_ty_td: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(full_q_td) - if full_ty_td is not None: - return full_ty_td + if full_ty_td is not None: return full_ty_td mod_entry_td: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(at.attr, mod_sha1_td) - if mod_entry_td is not None and mod_entry_td.Ty is not None: - return mod_entry_td.Ty + if mod_entry_td is not None and mod_entry_td.Ty is not None: return mod_entry_td.Ty # 模块可解析但类未注册:不裸名回退(防跨库抓错), # 落到下方枚举/typedef 尝试;struct 缺失由调用侧暴露 # 模块名未登记(未编译/未扫描):同样不裸名回退 else: # t/c 内置库限定:裸名回退合法(内置类名无跨模块冲突) mod_struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(at.attr) - if mod_struct_ty is not None: - return mod_struct_ty + if mod_struct_ty is not None: return mod_struct_ty # 模块限定枚举类型:Module.EnumClass(如 fat32_types.FRESULT, # t.CEnum 枚举类非结构体,get_struct_type 查不到) - if self.Gen.StmtGenDecl.is_enum_class(at.attr) == 1: - return self.Gen.StmtGenDecl.get_enum_base_type(at.attr) + if self.Gen.StmtGenDecl.is_enum_class(at.attr) == 1: return self.Gen.StmtGenDecl.get_enum_base_type(at.attr) # 模块限定 typedef(posix.DIR = t.CTypedef = t\.CVoid* 等): # 与 Name 分支同一套 lookup_ctypedef + 递归解析(单层 Module.Typedef # 与嵌套 Attribute 都要支持)。 @@ -3350,29 +2946,24 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): mod_td_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, mod_td_inner, imported_modules, from_imports, trans, depth + 1) self.Gen.TypeGenCType.CTypedefResolveDepth -= 1 self.Gen.TypeGenCType._ctypedef_pop_visiting() - if mod_td_ty is not None: - return mod_td_ty - else: - self.Gen.TypeGenCType._ctypedef_pop_visiting() + if mod_td_ty is not None: return mod_td_ty + else: self.Gen.TypeGenCType._ctypedef_pop_visiting() # [REPL 会话] 模块限定名(memhub.MemManager 等)的归属模块已知, # 但该类未在会话 StructTable 登记(M4.2 布局不可信被拒 / 字段类型 # 不可解析被跳过)⇒ 用 opaque 具名类型占位(不写 StructTable ⇒ # 字段访问仍按"类未注册"明确报错)。批处理 trans.ReplCtx 恒 None。 if trans is not None and trans.ReplCtx is not None and mod_sha1_rv is not None: ty_repl_a: mlirlite.LLVMType* = self._repl_opaque_class_ty(pool, mod_sha1_rv, at.attr) - if ty_repl_a is not None: - return ty_repl_a + if ty_repl_a is not None: return ty_repl_a return None # 嵌套 Attribute: w32.win32base.SECURITY_ATTRIBUTES 等三级及以上限定名 # at.value 是 Attribute 而非 Name,递归提取最终类名(at.attr)查结构体表 # find_struct 支持模块限定名回退,此处用最外层 attr(简单类名)即可 if at.value is not None and at.value.kind() == ast.ASTKind.Attribute: nested_struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(at.attr) - if nested_struct_ty is not None: - return nested_struct_ty + if nested_struct_ty is not None: return nested_struct_ty # 嵌套模块限定的枚举类(fat32_types.FRESULT 三级名):查枚举基类型 - if self.Gen.StmtGenDecl.is_enum_class(at.attr) == 1: - return self.Gen.StmtGenDecl.get_enum_base_type(at.attr) + if self.Gen.StmtGenDecl.is_enum_class(at.attr) == 1: return self.Gen.StmtGenDecl.get_enum_base_type(at.attr) # 嵌套模块限定的 typedef(w32.win32base.HANDLE = t.CTypedef = VOIDPTR): # 与 Name 分支同一套 lookup_ctypedef + 递归 + map_t_type 兜底 # (不查则解析失败 → NameError)。 @@ -3386,13 +2977,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): nested_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, nested_inner, imported_modules, from_imports, trans, depth + 1) self.Gen.TypeGenCType.CTypedefResolveDepth -= 1 self.Gen.TypeGenCType._ctypedef_pop_visiting() - if nested_ty is not None: - return nested_ty - else: - self.Gen.TypeGenCType._ctypedef_pop_visiting() + if nested_ty is not None: return nested_ty + else: self.Gen.TypeGenCType._ctypedef_pop_visiting() mapped_ty_na: mlirlite.LLVMType* = self.map_t_type(pool, at.attr) - if mapped_ty_na is not None: - return mapped_ty_na + if mapped_ty_na is not None: return mapped_ty_na # 嵌套模块限定 typedef 兜底(w32.win32base.HANDLE = t.CTypedef = # VOIDPTR):与单层 Module.Typedef 分支同口径,但 value 是嵌套 # Attribute,需先拼完整模块路径(w32.win32base)再读库源扫描注册。 @@ -3405,8 +2993,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): td_node_na: ast.AST* = self._parse_type_string(pool, lib_td_na, at.ctx) if td_node_na is not None: td_ty_na: mlirlite.LLVMType* = self.resolve_annotation_type(pool, td_node_na, imported_modules, from_imports, trans, depth + 1) - if td_ty_na is not None: - return td_ty_na + if td_ty_na is not None: return td_ty_na return None # BinOp 节点: 联合类型注解 A | B @@ -3424,8 +3011,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 有 CPtr 标记:解析非 CPtr 一边的实际类型,包装为 Ptr # left 是 CPtr → other 是 right;right 是 CPtr → other 是 left other_node: ast.AST* = bop.left - if left_is_cptr != 0: - other_node = bop.right + if left_is_cptr != 0: other_node = bop.right # 检测另一边是否是 t\.CVoid (void* = i8*) # 严格验证完整形式(Attribute(t\.CVoid) 的 value 是 Name("t"), # 或裸名 CVoid 且 t 已导入),防止解析异常节点被误判为 CVoid。 @@ -3436,19 +3022,16 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if oat2.attr is not None and string.strcmp(oat2.attr, "CVoid") == 0: if oat2.value is not None and oat2.value.kind() == ast.ASTKind.Name: ov2: ast.Name* = ast.Name*(oat2.value) - if ov2.id is not None and string.strcmp(ov2.id, "t") == 0: - other_is_cvoid = 1 + if ov2.id is not None and string.strcmp(ov2.id, "t") == 0: other_is_cvoid = 1 elif other_node.kind() == ast.ASTKind.Name: onm2: ast.Name* = ast.Name*(other_node) if onm2.id is not None: if string.strcmp(onm2.id, "CVoid") == 0: - if self.Gen.ImportsGen.is_module_imported(imported_modules, "t") != 0: - other_is_cvoid = 1 + if self.Gen.ImportsGen.is_module_imported(imported_modules, "t") != 0: other_is_cvoid = 1 elif string.strcmp(onm2.id, "void") == 0: # 内置别名 void:t.CVoid 同义,无需 import t other_is_cvoid = 1 - if other_is_cvoid != 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + if other_is_cvoid != 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) other_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, other_node, imported_modules, from_imports, trans, depth + 1) # 解析结果本身即 void(如 `typedef 不透明结构体 = void` 的那个名字, # 或经 typedef 兜底解析出的 void)⇒ 与 CPtr 合并即 void* = i8*, @@ -3472,8 +3055,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 垃圾类名,字段类型错误(如 free_lists 从 i64* 变 i8*)导致 # 运行时 GEP 步长错误崩溃。 other_is_name: int = 0 - if other_node is not None and other_node.kind() == ast.ASTKind.Name: - other_is_name = 1 + if other_node is not None and other_node.kind() == ast.ASTKind.Name: other_is_name = 1 if other_ty is not None and other_is_name != 0: if self.Gen.StructGen.find_struct_by_type(other_ty) is None: # 泛型类型参数(T→int 等)经上下文替换解析出的合法标量 @@ -3521,18 +3103,14 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): td_res_is_ptr: int = 0 match other_ty: case mlirlite.LLVMType.Ptr(pointee_td): - if self.Gen.StructGen.find_struct_by_type(pointee_td) is not None: - td_res_is_ptr = 1 - else: - td_res_is_ptr = 0 + if self.Gen.StructGen.find_struct_by_type(pointee_td) is not None: td_res_is_ptr = 1 + else: td_res_is_ptr = 0 case _: td_res_is_ptr = 0 if td_res_is_ptr == 0: td_alias_ty: mlirlite.LLVMType* = self.resolve_typedef_or_map(pool, other_nm_td.id, imported_modules, from_imports, trans) - if td_alias_ty is not None: - keep_other_ty = 1 - if keep_other_ty == 0: - other_ty = None + if td_alias_ty is not None: keep_other_ty = 1 + if keep_other_ty == 0: other_ty = None if other_ty is None: # 严格模式(App 文件)下裸类名不可见时,回退到全局 # struct 注册表按类名查找。X* 是明确的指针包装 @@ -3545,12 +3123,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): other_cls_nm: str = None if other_node is not None and other_node.kind() == ast.ASTKind.Name: other_nm: ast.Name* = ast.Name*(other_node) - if other_nm.id is not None: - other_cls_nm = other_nm.id + if other_nm.id is not None: other_cls_nm = other_nm.id if other_cls_nm is not None: other_cls_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(other_cls_nm) - if other_cls_ty is not None: - return mlirlite.Ptr(pool, other_cls_ty) + if other_cls_ty is not None: return mlirlite.Ptr(pool, other_cls_ty) # 类名未注册:可能是前向自我引用(如 json 的 # 'JsonValue' | t.CPtr 字段引用自身类,类体处理中 # 尚未注册)、或 Phase A-pre 依赖类延迟到下一遍注册、 @@ -3562,8 +3138,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # fail-fast(误杀合法前向引用)。 _fwd_ptr_ty: mlirlite.LLVMType* = self._forward_declare_ptr_from_node( pool, other_node, imported_modules, from_imports) - if _fwd_ptr_ty is not None: - return _fwd_ptr_ty + if _fwd_ptr_ty is not None: return _fwd_ptr_ty return mlirlite.Ptr(pool, mlirlite.Int8(pool)) # `X*` **恒追加恰好 1 层**(用户口径,与 rawptr[T]/t.CPtr[T] 下标形 # 以及 `_parse_type_string` 的 `T*` 反解析三处同源): @@ -3634,12 +3209,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 故标记侧**跳过**(既不参与竞争,也不进入解析)。 if self._is_tattr_marker(bop.left) == 0: left_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, bop.left, imported_modules, from_imports, trans, depth + 1) - if left_ty is not None: - return left_ty + if left_ty is not None: return left_ty if self._is_tattr_marker(bop.right) == 0: right_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, bop.right, imported_modules, from_imports, trans, depth + 1) - if right_ty is not None: - return right_ty + if right_ty is not None: return right_ty return None # Subscript 节点: t.CArray[elem_ty, count] → [count x elem_ty] @@ -3649,19 +3222,16 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # slice 是 Tuple(elts=[elem_ty_node, count_node]) 或单 elem_ty_node 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 节点缺少 value") # 空下标形态(t.Callable[])的 slice 为 None:只有无签名函数指针允许, # 落到下方 Callable 分支按 i8* 处理;其它类型仍要求 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 节点缺少 value 或 slice") # 函数指针(裸名形态 callable / Callable):与 t.Callable 逐点等价, # 无签名(callable[] / callable[[]])或有签名(callable[[A, B], R]) # 统一 i8*。必须在本分支的 Name 路径(泛型特化 / CArray / builtins # typedef 兜底)之前判定,否则裸名 callable 会被当泛型类名查空。 # 完整签名的返回类型注册见 TypeGenErr.try_extract_callable_ret。 - if sub.value.kind() == ast.ASTKind.Name and self._IsCallableSubscriptValue(sub.value) != 0: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + if sub.value.kind() == ast.ASTKind.Name and self._IsCallableSubscriptValue(sub.value) != 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) # 泛型类类型注解: list[int] → 查找已特化的 struct(value 是 Name 泛型类名) if sub.value.kind() == ast.ASTKind.Name: gen_nm: ast.Name* = ast.Name*(sub.value) @@ -3675,24 +3245,20 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 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]") 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, "内建定长数组构造子 'array' 参数个数错误(期望 2 个):只接受 array[E, N]。正确示例: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, "内建定长数组构造子 'array' 的元素类型或长度为空:只接受 array[E, N]。正确示例: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]") 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 + 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]") + if count_arr <= 0: self.Gen.TypeGenErr.fatal_type_error(count_node_arr, "内建定长数组构造子 'array' 的长度必须为正数。正确示例:state: array[uint32, 4]") return mlirlite.Array(pool, elem_ty_arr, count_arr) # 裸名 CArray(from t import * 场景):与 t.CArray 语义等价——否则走泛型 # 模板查找失败 → 字段类型退化 Ptr(i8) → 默认值 List 字面量误走动态 list @@ -3701,28 +3267,22 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 单参数: CArray[elem_ty] → Ptr(elem_ty)(静态推导长度数组) if sub.slice.kind() != ast.ASTKind.Tuple: elem_n: mlirlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1) - if elem_n is None: - return None + if elem_n is None: return None return mlirlite.Ptr(pool, elem_n) # 双参数: CArray[elem_ty, count] → [count x elem_ty] tup_n: ast.Tuple* = ast.Tuple*(sub.slice) - if tup_n.elts is None or len(tup_n.elts) < 2: - return None + if tup_n.elts is None or len(tup_n.elts) < 2: return None elem_node_n: ast.AST* = tup_n.elts.get(0) count_node_n: ast.AST* = tup_n.elts.get(1) - if elem_node_n is None or count_node_n is None: - return None + if elem_node_n is None or count_node_n is None: return None elem_ty_n: mlirlite.LLVMType* = self.resolve_annotation_type(pool, elem_node_n, imported_modules, from_imports, trans, depth + 1) - if elem_ty_n is None: - return None + if elem_ty_n is None: return None # count=None → Ptr(elem)(等价单参) if count_node_n.kind() == ast.ASTKind.Constant: cnt_n: ast.Constant* = ast.Constant*(count_node_n) - if cnt_n.const_kind == ast.CONST_NONE: - return mlirlite.Ptr(pool, elem_ty_n) + if cnt_n.const_kind == ast.CONST_NONE: return mlirlite.Ptr(pool, elem_ty_n) count_n: int = self.Gen.TypeGenCType._eval_const_int_expr(count_node_n, pool, from_imports, imported_modules) - if self.Gen.TypeGenCType.ConstEvalOk == 0 or count_n <= 0: - return None + if self.Gen.TypeGenCType.ConstEvalOk == 0 or count_n <= 0: return None return mlirlite.Array(pool, elem_ty_n, count_n) # rawptr[T] 内建裸指针:等价 t.CPtr[T] → Ptr(T)(T 自身可含指针层级)。 # 与 t.CPtr[T] 语义一致;不处理则泛型特化/builtins 兜底失败 → @@ -3738,14 +3298,12 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if string.strcmp(gen_nm.id, "rawptr") == 0: if sub.slice.kind() != ast.ASTKind.Tuple: rp_elem: mlirlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1) - if rp_elem is None: - return None + if rp_elem is None: return None return mlirlite.Ptr(pool, rp_elem) return None gen_ty_nm: mlirlite.LLVMType* = self._resolve_generic_subscript_ty(pool, sub, gen_nm.id, trans, imported_modules, from_imports, depth + 1) - if gen_ty_nm is not None: - return gen_ty_nm + if gen_ty_nm is not None: return gen_ty_nm # 泛型特化 miss 时不能 return None 直接退出——否则下面的 # [builtins 最后匹配] 兜底永远不可达(rawptr[int] 根因)。 # 下方 builtins 兜底若也未命中,仍按旧行为返回 None(多遍 @@ -3768,26 +3326,21 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): fb_node: ast.AST* = self._parse_type_string(pool, fb_str, ast.ASTCtx.Load) if fb_node is not None: fb_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, fb_node, imported_modules, from_imports, trans, depth + 1) - if fb_ty is not None: - return fb_ty + if fb_ty is not None: return fb_ty return None # 检查 value 是否是 Attribute(t.CArray / t.Callable / 模块限定泛型类如 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, "不支持的 Subscript 类型注解(仅支持 t.CArray / t.Callable)") 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 缺少 attr") # 模块限定泛型类: numpy.ndarray[t.CDouble] → 裸类名 ndarray 走泛型特化 # (在 t.CArray / t.Callable 检查之前;模板已注册即视为泛型类) 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 必须通过模块名限定") 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 模块名为 None") # 函数指针类型: t.Callable[[A, B], Ret] → i8* # 与 TPV 函数传指针惯例一致(函数值 bitcast 为 i8* 存储,调用时按实参重建签名) if string.strcmp(arr_at.attr, "Callable") == 0: @@ -3814,12 +3367,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # CTypedef 动态表解析)。真实类型错误由 Phase A 收敛检查暴露。 _fwd_cptr_ty: mlirlite.LLVMType* = self._forward_declare_ptr_from_node( pool, sub.slice, imported_modules, from_imports) - if _fwd_cptr_ty is not None: - return _fwd_cptr_ty + 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, "不支持的 Subscript 类型注解(仅支持 t.CArray / t.Callable)") 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 模块未导入") # 单参数形式: t.CArray[elem_ty] → Ptr(elem_ty) @@ -3832,16 +3383,13 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): return mlirlite.Ptr(pool, elem_ty_single) # 双参数形式: 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 缺少 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 元素不足") 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 元素为 None") # 递归解析元素类型 elem_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, elem_node, imported_modules, from_imports, trans, depth + 1) if elem_ty is None: @@ -3857,17 +3405,14 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): count_val: int = 0 if count_node.kind() == ast.ASTKind.Constant: cnt_cn: ast.Constant* = ast.Constant*(count_node) - if cnt_cn.const_kind == ast.CONST_NONE: - return mlirlite.Ptr(pool, elem_ty) + if cnt_cn.const_kind == ast.CONST_NONE: return mlirlite.Ptr(pool, elem_ty) # 统一用 _eval_const_int_expr 计算常量整数表达式 # 支持 Constant(INT)、Name(CDefine)、BinOp(2*MAX 等算术/位运算) # 传入 pool/from_imports/imported_modules 支持跨模块 CDefine 查找 # (如 SHA512_BLOCK_LEN 定义在 hashlib/__sha512.vp,当前模块表不含) 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 必须是整数常量、None、CDefine 常量名或常量表达式") + if count_val <= 0: self.Gen.TypeGenErr.fatal_type_error(count_node, "t.CArray count 必须为正数") # 创建 ArrayType(不包装 Ptr) # 这样 build_alloca 会分配数组大小的空间,alloca 返回 [N x elem_ty]* return mlirlite.Array(pool, elem_ty, count_val) diff --git a/App/lib/core/Gen/Type/TypeSpec.vp b/App/lib/core/Gen/Type/TypeSpec.vp index 9b30b67..0a2252d 100644 --- a/App/lib/core/Gen/Type/TypeSpec.vp +++ b/App/lib/core/Gen/Type/TypeSpec.vp @@ -59,8 +59,7 @@ def _spec_name_eq(text: str, start: sizet, end: sizet, lit: str) -> int: ln: sizet = string.strlen(lit) if end - start != ln: return 0 for k in range(ln): - if text[start + k] != lit[k]: - return 0 + if text[start + k] != lit[k]: return 0 return 1 @@ -85,15 +84,13 @@ def SpecTypeNameBaseIs(name: str, base: str) -> int: # 基名上界:第一个 '['(泛型实参起点;无 '[' 则到串尾) end: sizet = n lb: str = string.strchr(name, '[') - if lb is not None: - end = sizet(uint64(lb) - uint64(name)) + if lb is not None: end = sizet(uint64(lb) - uint64(name)) # 基名下界:上界之前最后一个 '.' 之后(去模块名 / 模块 sha1 前缀) start: sizet = 0 dot: str = string.strchr(name, '.') while dot is not None: off: sizet = sizet(uint64(dot) - uint64(name)) - if off >= end: - break + if off >= end: break start = off + 1 dot = string.strchr(dot + 1, '.') return _spec_name_eq(name, start, end, base) @@ -105,63 +102,36 @@ def SpecTypeNameBaseIs(name: str, base: str) -> int: # ============================================================ def SpecSignFromTypeNameSpan(text: str, start: sizet, end: sizet) -> int: """按 text[start:end] 精确判定符号性,未覆盖返回 TS_SIGN_UNKNOWN""" - if text is None: - return TS_SIGN_UNKNOWN + if text is None: return TS_SIGN_UNKNOWN # --- t/c 核心无符号原语 --- - if _spec_name_eq(text, start, end, "CUInt8T") != 0: - return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUInt16T") != 0: - return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUInt32T") != 0: - return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUInt64T") != 0: - return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUnsignedChar") != 0: - return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUnsignedShort") != 0: - return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUnsignedInt") != 0: - return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUnsignedLong") != 0: - return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUnsignedLongLong") != 0: - return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CSizeT") != 0: - return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUIntPtrT") != 0: - return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CBool") != 0: - return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "CUInt8T") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "CUInt16T") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "CUInt32T") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "CUInt64T") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "CUnsignedChar") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "CUnsignedShort") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "CUnsignedInt") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "CUnsignedLong") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "CUnsignedLongLong") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "CSizeT") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "CUIntPtrT") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "CBool") != 0: return TS_SIGN_UNSIGNED # --- 内建小写标量 --- - if _spec_name_eq(text, start, end, "bool") != 0: - return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "bool") != 0: return TS_SIGN_UNSIGNED # --- t/c 核心有符号原语 --- - if _spec_name_eq(text, start, end, "CInt8T") != 0: - return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CInt16T") != 0: - return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CInt32T") != 0: - return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CInt64T") != 0: - return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CSignedChar") != 0: - return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CShort") != 0: - return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CInt") != 0: - return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CLong") != 0: - return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CLongLong") != 0: - return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CPtrDiffT") != 0: - return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CChar") != 0: - return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "int") != 0: - return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "char") != 0: - return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "CInt8T") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "CInt16T") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "CInt32T") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "CInt64T") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "CSignedChar") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "CShort") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "CInt") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "CLong") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "CLongLong") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "CPtrDiffT") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "CChar") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "int") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "char") != 0: return TS_SIGN_SIGNED return TS_SIGN_UNKNOWN @@ -170,8 +140,7 @@ def SpecSignFromTypeNameSpan(text: str, start: sizet, end: sizet) -> int: # ============================================================ def SpecSignFromTypeName(name: str) -> int: """按类型名精确判定符号性,未覆盖返回 TS_SIGN_UNKNOWN""" - if name is None: - return TS_SIGN_UNKNOWN + if name is None: return TS_SIGN_UNKNOWN return SpecSignFromTypeNameSpan(name, 0, string.strlen(name)) @@ -257,8 +226,7 @@ def _spec_key_hash(key: str) -> uint64: # ============================================================ def _spec_key_at(keys: bytes, index: int) -> str: """返回第 index 条键的 str 指针(指向 keys 缓冲内部,不可 free)""" - if keys is None or index < 0: - return None + if keys is None or index < 0: return None addr: uint64 = uint64(keys) + uint64(index * SPEC_TEXT_MAX) return rawptr(addr) @@ -270,20 +238,17 @@ def _spec_key_at(keys: bytes, index: int) -> str: # ============================================================ def _spec_index_find(arena: TypeSpecArena*, key: str, h: uint64) -> int: """查驻留哈希索引,命中返回条目下标;未命中返回 -1""" - if arena.Index is None or arena.IndexCap <= 0: - return -1 + if arena.Index is None or arena.IndexCap <= 0: return -1 mask: sizet = sizet(arena.IndexCap - 1) idx: sizet = sizet(h) & mask i: int = 0 while i < arena.IndexCap: slot: sizet* = (sizet*)(uint64(arena.Index) + uint64(idx * 8)) sv: sizet = slot[0] - if sv == 0: - return -1 + if sv == 0: return -1 ei: int = int(sv) - 1 ek: str = _spec_key_at(arena.Keys, ei) - if ek is not None and string.strcmp(ek, key) == 0: - return ei + if ek is not None and string.strcmp(ek, key) == 0: return ei idx = (idx + 1) & mask i += 1 return -1 @@ -296,8 +261,7 @@ def _spec_index_find(arena: TypeSpecArena*, key: str, h: uint64) -> int: # ============================================================ def _spec_index_insert(arena: TypeSpecArena*, key: str, h: uint64, ei: int) -> int: """把下标 ei 写入驻留哈希索引,返回 0=成功 / 1=不可用""" - if arena.Index is None or arena.IndexCap <= 0: - return 1 + if arena.Index is None or arena.IndexCap <= 0: return 1 mask: sizet = sizet(arena.IndexCap - 1) idx: sizet = sizet(h) & mask i: int = 0 @@ -317,20 +281,15 @@ def _spec_index_insert(arena: TypeSpecArena*, key: str, h: uint64, ei: int) -> i # ============================================================ def SpecArenaInit(arena: TypeSpecArena*, cap: int) -> int: """初始化驻留表;已初始化则直接返回 0""" - if arena is None: - return 1 - if arena.Keys is not None: - return 0 + if arena is None: return 1 + if arena.Keys is not None: return 0 use_cap: int = cap - if use_cap <= 0: - use_cap = SPEC_INTERN_MAX + if use_cap <= 0: use_cap = SPEC_INTERN_MAX pp: memhub.MemBuddy* = CompilerFactory.factory.PermPool keys: bytes = pp.alloc(use_cap * SPEC_TEXT_MAX) - if keys is None: - return 1 + if keys is None: return 1 specs: sizet* = pp.alloc(use_cap * 8) - if specs is None: - return 1 + if specs is None: return 1 string.memset(keys, 0, use_cap * SPEC_TEXT_MAX) string.memset(specs, 0, use_cap * 8) arena.Keys = keys @@ -341,8 +300,7 @@ def SpecArenaInit(arena: TypeSpecArena*, cap: int) -> int: # 分配失败则保持 None,InternSpec 自动回退线性扫描(语义完全一致), # 故不因索引失败而使整个初始化失败(不新增失败面)。 icap: int = 1 - while icap < use_cap * 2: - icap = icap * 2 + while icap < use_cap * 2: icap = icap * 2 idx_buf: sizet* = pp.alloc(icap * 8) if idx_buf is not None: string.memset(idx_buf, 0, icap * 8) @@ -362,8 +320,7 @@ def _spec_alloc() -> TypeSpec*: pp: memhub.MemBuddy* = CompilerFactory.factory.PermPool size: sizet = TypeSpec.__sizeof__() sp: TypeSpec* = (TypeSpec*)(pp.alloc(size)) - if sp is None: - return None + if sp is None: return None string.memset(sp, 0, size) sp.Kind = TS_UNKNOWN sp.Bits = 0 @@ -380,8 +337,7 @@ def _spec_alloc() -> TypeSpec*: def _spec_make(kind: int, bits: int, is_signed: int) -> TypeSpec*: """构造基础 TypeSpec(PermPool,不驻留)""" sp: TypeSpec* = _spec_alloc() - if sp is None: - return None + if sp is None: return None sp.Kind = kind sp.Bits = bits sp.IsSigned = is_signed @@ -393,14 +349,11 @@ def _spec_make(kind: int, bits: int, is_signed: int) -> TypeSpec*: # ============================================================ def _spec_set_struct_name(sp: TypeSpec*, name: str) -> int: """把类名深拷贝到 PermPool 并写入 BaseName,返回 0=成功 / 1=失败""" - if sp is None or name is None: - return 1 + if sp is None or name is None: return 1 n: sizet = string.strlen(name) - if n <= 0: - return 1 + if n <= 0: return 1 buf: str = CompilerFactory.factory.PermPool.alloc(n + 1) - if buf is None: - return 1 + if buf is None: return 1 string.strcpy(buf, name) sp.BaseName = buf return 0 @@ -413,8 +366,7 @@ def NewTypeSpec(arena: TypeSpecArena*, kind: int, bits: int, is_signed: int) -> TypeSpec*: """构造基础 TypeSpec 并驻留,失败返回 None""" sp: TypeSpec* = _spec_make(kind, bits, is_signed) - if sp is None: - return None + if sp is None: return None return InternSpec(arena, sp) @@ -425,10 +377,8 @@ def NewTypeStruct(arena: TypeSpecArena*, kind: int, base_name: str) -> TypeSpec*: """构造 struct/union/enum 类型(BaseName 深拷贝 + 驻留),失败返回 None""" sp: TypeSpec* = _spec_make(kind, 0, TS_SIGN_UNKNOWN) - if sp is None: - return None - if _spec_set_struct_name(sp, base_name) != 0: - return None + if sp is None: return None + if _spec_set_struct_name(sp, base_name) != 0: return None return InternSpec(arena, sp) @@ -438,17 +388,14 @@ def NewTypeStruct(arena: TypeSpecArena*, kind: int, def NewTypePtr(arena: TypeSpecArena*, elem: TypeSpec*) -> TypeSpec*: """构造指针类型:指向 elem(PtrLevel 逐层递增),失败返回 None""" - if elem is None: - return None + if elem is None: return None sp: TypeSpec* = _spec_make(TS_PTR, 0, TS_SIGN_UNKNOWN) - if sp is None: - return None + if sp is None: return None sp.Elem = elem sp.PtrLevel = elem.PtrLevel + 1 sp.ElemBits = elem.Bits sp.IsElemPtr = 0 - if elem.Kind == TS_PTR: - sp.IsElemPtr = 1 + if elem.Kind == TS_PTR: sp.IsElemPtr = 1 return InternSpec(arena, sp) @@ -458,17 +405,14 @@ def NewTypePtr(arena: TypeSpecArena*, def NewTypeArray(arena: TypeSpecArena*, elem: TypeSpec*, count: int) -> TypeSpec*: """构造数组类型:elem[count](count<=0 表示长度未知/动态),失败返回 None""" - if elem is None or count < 0: - return None + if elem is None or count < 0: return None sp: TypeSpec* = _spec_make(TS_ARRAY, 0, TS_SIGN_UNKNOWN) - if sp is None: - return None + if sp is None: return None sp.Elem = elem sp.ArrayCount = count sp.ElemBits = elem.Bits sp.IsElemPtr = 0 - if elem.Kind == TS_PTR: - sp.IsElemPtr = 1 + if elem.Kind == TS_PTR: sp.IsElemPtr = 1 return InternSpec(arena, sp) @@ -480,13 +424,10 @@ def NewTypeFunc(arena: TypeSpecArena*, ret: TypeSpec*, params: sizet*, count: int, is_vararg: int) -> TypeSpec*: """构造函数签名类型,失败返回 None""" - if ret is None or count < 0: - return None - if count > 0 and params is None: - return None + if ret is None or count < 0: return None + if count > 0 and params is None: return None sp: TypeSpec* = _spec_make(TS_FUNC, 0, TS_SIGN_UNKNOWN) - if sp is None: - return None + if sp is None: return None sp.Ret = ret sp.Params = params sp.ParamCount = count @@ -500,8 +441,7 @@ def NewTypeFunc(arena: TypeSpecArena*, ret: TypeSpec*, # ============================================================ def SpecBaseText(sp: TypeSpec*, buf: str, buf_size: sizet) -> int: """把基础类型写成规范文本;Ptr/Array/Func 不适用时返回 1""" - if sp is None or buf is None or buf_size == 0: - return 1 + if sp is None or buf is None or buf_size == 0: return 1 if sp.Kind == TS_INT: viperlib.snprintf(buf, buf_size, "i%d", sp.Bits) return 0 @@ -516,18 +456,15 @@ def SpecBaseText(sp: TypeSpec*, buf: str, buf_size: sizet) -> int: return 0 if sp.Kind == TS_STRUCT: # 名字键可能很长(sha1 + 泛型实参),先算所需长度,装不下即失败(不截断) - if sp.BaseName is None or 3 + string.strlen(sp.BaseName) + 1 > buf_size: - return 1 + if sp.BaseName is None or 3 + string.strlen(sp.BaseName) + 1 > buf_size: return 1 viperlib.snprintf(buf, buf_size, "st:%s", sp.BaseName) return 0 if sp.Kind == TS_UNION: - if sp.BaseName is None or 3 + string.strlen(sp.BaseName) + 1 > buf_size: - return 1 + if sp.BaseName is None or 3 + string.strlen(sp.BaseName) + 1 > buf_size: return 1 viperlib.snprintf(buf, buf_size, "un:%s", sp.BaseName) return 0 if sp.Kind == TS_ENUM: - if sp.BaseName is None or 3 + string.strlen(sp.BaseName) + 1 > buf_size: - return 1 + if sp.BaseName is None or 3 + string.strlen(sp.BaseName) + 1 > buf_size: return 1 viperlib.snprintf(buf, buf_size, "en:%s", sp.BaseName) return 0 if sp.Kind == TS_VOID: @@ -555,83 +492,60 @@ def SpecToText(sp: TypeSpec*, buf: str, buf_size: sizet) -> int: def _spec_to_text(sp: TypeSpec*, buf: str, buf_size: sizet, depth: int) -> int: """SpecToText 的递归实现(depth 上限 32)""" - if sp is None or buf is None or buf_size == 0 or depth > 32: - return 1 + if sp is None or buf is None or buf_size == 0 or depth > 32: return 1 buf[0] = '\0' if sp.Kind == TS_PTR: # p: + 内层 inner_buf: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX) - if inner_buf is None: - return 1 - if _spec_to_text(sp.Elem, inner_buf, SPEC_TEXT_MAX, depth + 1) != 0: - return 1 + if inner_buf is None: return 1 + if _spec_to_text(sp.Elem, inner_buf, SPEC_TEXT_MAX, depth + 1) != 0: return 1 pos_p: sizet = _spec_text_append(buf, buf_size, 0, "p:") - if pos_p >= buf_size: - return 1 + if pos_p >= buf_size: return 1 pos_p = _spec_text_append(buf, buf_size, pos_p, inner_buf) - if pos_p >= buf_size: - return 1 + if pos_p >= buf_size: return 1 return 0 if sp.Kind == TS_ARRAY: # arr[N]: + 内层 inner_buf_a: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX) - if inner_buf_a is None: - return 1 - if _spec_to_text(sp.Elem, inner_buf_a, SPEC_TEXT_MAX, depth + 1) != 0: - return 1 + if inner_buf_a is None: return 1 + if _spec_to_text(sp.Elem, inner_buf_a, SPEC_TEXT_MAX, depth + 1) != 0: return 1 prefix_a: str = CompilerFactory.factory.PermPool.alloc(64) - if prefix_a is None: - return 1 + if prefix_a is None: return 1 viperlib.snprintf(prefix_a, 64, "arr[%d]:", sp.ArrayCount) pos_a: sizet = _spec_text_append(buf, buf_size, 0, prefix_a) - if pos_a >= buf_size: - return 1 + if pos_a >= buf_size: return 1 pos_a = _spec_text_append(buf, buf_size, pos_a, inner_buf_a) - if pos_a >= buf_size: - return 1 + if pos_a >= buf_size: return 1 return 0 if sp.Kind == TS_FUNC: # fn(p1,p2,...)->ret(每次追加都检查溢出哨兵,绝不静默截断键) pos: sizet = 0 pos = _spec_text_append(buf, buf_size, pos, "fn(") - if pos >= buf_size: - return 1 + if pos >= buf_size: return 1 i: int = 0 while i < sp.ParamCount: if i > 0: pos = _spec_text_append(buf, buf_size, pos, ",") - if pos >= buf_size: - return 1 + if pos >= buf_size: return 1 param: TypeSpec* = _spec_param_at(sp, i) - if param is None: - return 1 + if param is None: return 1 param_buf: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX) - if param_buf is None: - return 1 - if _spec_to_text(param, param_buf, SPEC_TEXT_MAX, depth + 1) != 0: - return 1 + if param_buf is None: return 1 + if _spec_to_text(param, param_buf, SPEC_TEXT_MAX, depth + 1) != 0: return 1 pos = _spec_text_append(buf, buf_size, pos, param_buf) - if pos >= buf_size: - return 1 + if pos >= buf_size: return 1 i += 1 if sp.IsVarArg == 1: - if sp.ParamCount > 0: - pos = _spec_text_append(buf, buf_size, pos, ",...") - else: - pos = _spec_text_append(buf, buf_size, pos, "...") - if pos >= buf_size: - return 1 + if sp.ParamCount > 0: pos = _spec_text_append(buf, buf_size, pos, ",...") + else: pos = _spec_text_append(buf, buf_size, pos, "...") + if pos >= buf_size: return 1 pos = _spec_text_append(buf, buf_size, pos, ")->") - if pos >= buf_size: - return 1 + if pos >= buf_size: return 1 ret_buf: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX) - if ret_buf is None: - return 1 - if _spec_to_text(sp.Ret, ret_buf, SPEC_TEXT_MAX, depth + 1) != 0: - return 1 + if ret_buf is None: return 1 + if _spec_to_text(sp.Ret, ret_buf, SPEC_TEXT_MAX, depth + 1) != 0: return 1 pos = _spec_text_append(buf, buf_size, pos, ret_buf) - if pos >= buf_size: - return 1 + if pos >= buf_size: return 1 return 0 # 基础类型 return SpecBaseText(sp, buf, buf_size) @@ -643,8 +557,7 @@ def _spec_to_text(sp: TypeSpec*, buf: str, buf_size: sizet, # Spec 实例**(如长函数签名键被截断 ⇒ 某函数拿到别的函数的签名 Spec,格式化闸门误报)。 def _spec_text_append(buf: str, buf_size: sizet, pos: sizet, text: str) -> sizet: """把 text 追加到 buf 的 pos 处;装不下返回 buf_size(哨兵),否则返回新位置""" - if buf is None or text is None: - return buf_size + if buf is None or text is None: return buf_size tlen: sizet = string.strlen(text) i: sizet = 0 while i < tlen: @@ -663,12 +576,10 @@ def _spec_text_append(buf: str, buf_size: sizet, pos: sizet, text: str) -> sizet # ============================================================ def _spec_param_at(sp: TypeSpec*, index: int) -> TypeSpec*: """返回 Func 类型第 index 个参数的 TypeSpec 指针,越界返回 None""" - if sp is None or sp.Params is None or index < 0 or index >= sp.ParamCount: - return None + if sp is None or sp.Params is None or index < 0 or index >= sp.ParamCount: return None addr: uint64 = uint64(sp.Params) + uint64(index * 8) slot: sizet* = (sizet*)(addr) - if slot is None: - return None + if slot is None: return None return (TypeSpec*)(uint64(slot[0])) @@ -678,75 +589,55 @@ def _spec_param_at(sp: TypeSpec*, index: int) -> TypeSpec*: # ============================================================ def TextToSpec(text: str) -> TypeSpec*: """把规范文本解码为 TypeSpec(PermPool,不驻留),失败返回 None""" - if text is None: - return None + if text is None: return None return _text_to_spec(text, 0) def _text_to_spec(text: str, depth: int) -> TypeSpec*: """TextToSpec 的递归实现(depth 上限 32)""" - if text is None or depth > 32: - return None + if text is None or depth > 32: return None # 指针:p:INNER if string.strncmp(text, "p:", 2) == 0: inner: TypeSpec* = _text_to_spec(text + 2, depth + 1) - if inner is None: - return None + if inner is None: return None sp_p: TypeSpec* = _spec_make(TS_PTR, 0, TS_SIGN_UNKNOWN) - if sp_p is None: - return None + if sp_p is None: return None sp_p.Elem = inner sp_p.PtrLevel = inner.PtrLevel + 1 sp_p.ElemBits = inner.Bits - if inner.Kind == TS_PTR: - sp_p.IsElemPtr = 1 + if inner.Kind == TS_PTR: sp_p.IsElemPtr = 1 return sp_p # 数组:arr[N]:INNER if string.strncmp(text, "arr[", 4) == 0: rb: str = string.strchr(text, ']') - if rb is None: - return None + if rb is None: return None count: int = string.atoi(text + 4) - if count < 0: - return None + if count < 0: return None colon: str = string.strchr(rb, ':') - if colon is None: - return None + if colon is None: return None inner_a: TypeSpec* = _text_to_spec(colon + 1, depth + 1) - if inner_a is None: - return None + if inner_a is None: return None sp_a: TypeSpec* = _spec_make(TS_ARRAY, 0, TS_SIGN_UNKNOWN) - if sp_a is None: - return None + if sp_a is None: return None sp_a.Elem = inner_a sp_a.ArrayCount = count sp_a.ElemBits = inner_a.Bits - if inner_a.Kind == TS_PTR: - sp_a.IsElemPtr = 1 + if inner_a.Kind == TS_PTR: sp_a.IsElemPtr = 1 return sp_a # 函数:fn(...)->RET - if string.strncmp(text, "fn(", 3) == 0: - return _text_to_func(text, depth) + if string.strncmp(text, "fn(", 3) == 0: return _text_to_func(text, depth) # 结构体/联合/枚举:st:NAME / un:NAME / en:NAME - if string.strncmp(text, "st:", 3) == 0: - return _spec_make_struct(TS_STRUCT, text + 3) - if string.strncmp(text, "un:", 3) == 0: - return _spec_make_struct(TS_UNION, text + 3) - if string.strncmp(text, "en:", 3) == 0: - return _spec_make_struct(TS_ENUM, text + 3) - if string.strcmp(text, "bool") == 0: - return _spec_make(TS_BOOL, 1, TS_SIGN_UNSIGNED) - if string.strcmp(text, "void") == 0: - return _spec_make(TS_VOID, 0, TS_SIGN_UNKNOWN) + if string.strncmp(text, "st:", 3) == 0: return _spec_make_struct(TS_STRUCT, text + 3) + if string.strncmp(text, "un:", 3) == 0: return _spec_make_struct(TS_UNION, text + 3) + if string.strncmp(text, "en:", 3) == 0: return _spec_make_struct(TS_ENUM, text + 3) + if string.strcmp(text, "bool") == 0: return _spec_make(TS_BOOL, 1, TS_SIGN_UNSIGNED) + if string.strcmp(text, "void") == 0: return _spec_make(TS_VOID, 0, TS_SIGN_UNKNOWN) # i32 / u64 / f64 if text[0] == 'u' or text[0] == 'i' or text[0] == 'f': bits: int = string.atoi(text + 1) - if bits <= 0: - return None - if text[0] == 'u': - return _spec_make(TS_UINT, bits, TS_SIGN_UNSIGNED) - if text[0] == 'i': - return _spec_make(TS_INT, bits, TS_SIGN_SIGNED) + if bits <= 0: return None + if text[0] == 'u': return _spec_make(TS_UINT, bits, TS_SIGN_UNSIGNED) + if text[0] == 'i': return _spec_make(TS_INT, bits, TS_SIGN_SIGNED) return _spec_make(TS_FLOAT, bits, TS_SIGN_SIGNED) return None @@ -756,13 +647,10 @@ def _text_to_spec(text: str, depth: int) -> TypeSpec*: # ============================================================ def _spec_make_struct(kind: int, name: str) -> TypeSpec*: """构造 struct/union/enum 类型(不驻留),失败返回 None""" - if name is None or name[0] == '\0': - return None + if name is None or name[0] == '\0': return None sp: TypeSpec* = _spec_make(kind, 0, TS_SIGN_UNKNOWN) - if sp is None: - return None - if _spec_set_struct_name(sp, name) != 0: - return None + if sp is None: return None + if _spec_set_struct_name(sp, name) != 0: return None return sp @@ -772,27 +660,22 @@ def _spec_make_struct(kind: int, name: str) -> TypeSpec*: def _text_to_func(text: str, depth: int) -> TypeSpec*: """解析函数签名文本,失败返回 None""" lp: str = string.strchr(text, '(') - if lp is None: - return None + if lp is None: return None arrow: str = string.strstr(text, ")->") - if arrow is None: - return None + if arrow is None: return None # 参数段范围(lp+1 .. arrow-1) params_buf: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX) - if params_buf is None: - return None + if params_buf is None: return None params_buf[0] = '\0' nlen: sizet = sizet(uint64(arrow) - uint64(lp)) - 1 if nlen > 0: string.strncpy(params_buf, lp + 1, nlen) params_buf[nlen] = '\0' is_vararg: int = 0 - if string.strstr(params_buf, "...") is not None: - is_vararg = 1 + if string.strstr(params_buf, "...") is not None: is_vararg = 1 # 逐段解析参数(按顶层 ',' 分割;变参段 "..." 跳过) param_specs: sizet* = CompilerFactory.factory.PermPool.alloc(8 * 64) - if param_specs is None: - return None + if param_specs is None: return None pcount: int = 0 if nlen > 0: cur: str = params_buf @@ -801,33 +684,25 @@ def _text_to_func(text: str, depth: int) -> TypeSpec*: seg: str = cur if comma is not None: seg_make: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX) - if seg_make is None: - return None + if seg_make is None: return None seg_len: sizet = sizet(uint64(comma) - uint64(cur)) string.strncpy(seg_make, cur, seg_len) seg_make[seg_len] = '\0' seg = seg_make cur = comma + 1 - else: - cur = None - if string.strcmp(seg, "...") == 0: - continue - if pcount >= 64: - return None + else: cur = None + if string.strcmp(seg, "...") == 0: continue + if pcount >= 64: return None psp: TypeSpec* = _text_to_spec(seg, depth + 1) - if psp is None: - return None + if psp is None: return None slot_p: sizet* = (sizet*)(uint64(param_specs) + uint64(pcount * 8)) - if slot_p is None: - return None + if slot_p is None: return None slot_p[0] = sizet(psp) pcount += 1 ret: TypeSpec* = _text_to_spec(arrow + 3, depth + 1) - if ret is None: - return None + if ret is None: return None sp_f: TypeSpec* = _spec_make(TS_FUNC, 0, TS_SIGN_UNKNOWN) - if sp_f is None: - return None + if sp_f is None: return None sp_f.Ret = ret sp_f.Params = param_specs sp_f.ParamCount = pcount @@ -844,13 +719,10 @@ def _text_to_func(text: str, depth: int) -> TypeSpec*: def InternSpec(arena: TypeSpecArena*, sp: TypeSpec*) -> TypeSpec*: """按规范文本键驻留 TypeSpec;失败返回 None""" - if arena is None or sp is None: - return sp - if SpecArenaInit(arena, 0) != 0: - return None + if arena is None or sp is None: return sp + if SpecArenaInit(arena, 0) != 0: return None key_buf: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX) - if key_buf is None: - return None + if key_buf is None: return None if SpecToText(sp, key_buf, SPEC_TEXT_MAX) != 0: # 键装不下(长函数签名 / 深嵌套):**保留实例但放弃去重**。 # 这不是语义兜底 —— sp 本身完整正确,只是失去"同型共享"这一优化; @@ -864,8 +736,7 @@ def InternSpec(arena: TypeSpecArena*, found: int = _spec_index_find(arena, key_buf, key_hash) if found >= 0: slot_e: sizet* = (sizet*)(uint64(arena.Specs) + uint64(found * 8)) - if slot_e is None: - return None + if slot_e is None: return None return (TypeSpec*)(uint64(slot_e[0])) if arena.Index is None: # 索引不可用:回退原线性查找(规模与类型种数同阶) @@ -874,8 +745,7 @@ def InternSpec(arena: TypeSpecArena*, exist_key: str = _spec_key_at(arena.Keys, i) if exist_key is not None and string.strcmp(exist_key, key_buf) == 0: slot_e2: sizet* = (sizet*)(uint64(arena.Specs) + uint64(i * 8)) - if slot_e2 is None: - return None + if slot_e2 is None: return None return (TypeSpec*)(uint64(slot_e2[0])) i += 1 # 未命中:追加。**表满 = fail-fast**:不能返回 None——调用链会把 None 一路传到 @@ -962,8 +832,7 @@ def SpecWithSign(arena: TypeSpecArena*, sp: TypeSpec*, is_signed: int) -> TypeSpec*: """复制 sp 并覆盖整数符号性,驻留后返回;无变化返回原实例,失败返回 None""" - if sp is None: - return None + if sp is None: return None new_kind: int = sp.Kind new_signed: int = sp.IsSigned if is_signed == TS_SIGN_UNSIGNED and sp.Kind == TS_INT: @@ -972,11 +841,9 @@ def SpecWithSign(arena: TypeSpecArena*, elif is_signed == TS_SIGN_SIGNED and sp.Kind == TS_UINT: new_kind = TS_INT new_signed = TS_SIGN_SIGNED - if new_kind == sp.Kind: - return sp + if new_kind == sp.Kind: return sp cp: TypeSpec* = _spec_clone(sp) - if cp is None: - return None + if cp is None: return None cp.Kind = new_kind cp.IsSigned = new_signed # **清空 SourceName**:本函数走 InternSpec(键 = SpecToText,不含 SourceName), @@ -992,14 +859,11 @@ def SpecWithSign(arena: TypeSpecArena*, # ============================================================ def _spec_set_source_name(sp: TypeSpec*, name: str) -> int: """把注解来源名深拷贝到 PermPool 并写入 SourceName,返回 0=成功 / 1=失败""" - if sp is None or name is None: - return 1 + if sp is None or name is None: return 1 n: sizet = string.strlen(name) - if n <= 0: - return 1 + if n <= 0: return 1 buf: str = CompilerFactory.factory.PermPool.alloc(n + 1) - if buf is None: - return 1 + if buf is None: return 1 string.strcpy(buf, name) sp.SourceName = buf return 0 @@ -1020,15 +884,11 @@ def _spec_set_source_name(sp: TypeSpec*, name: str) -> int: # ============================================================ def SpecWithSource(sp: TypeSpec*, name: str) -> TypeSpec*: """复制 sp 并设置 SourceName(独立副本,不驻留);name 为空返回原实例""" - if sp is None or name is None or name[0] == '\0': - return sp - if sp.SourceName is not None and string.strcmp(sp.SourceName, name) == 0: - return sp + if sp is None or name is None or name[0] == '\0': return sp + if sp.SourceName is not None and string.strcmp(sp.SourceName, name) == 0: return sp cp: TypeSpec* = _spec_clone(sp) - if cp is None: - return sp - if _spec_set_source_name(cp, name) != 0: - return sp + if cp is None: return sp + if _spec_set_source_name(cp, name) != 0: return sp return cp @@ -1045,37 +905,30 @@ def SpecWithSource(sp: TypeSpec*, name: str) -> TypeSpec*: # ============================================================ def SpecWithElemBits(sp: TypeSpec*, elem_bits: int) -> TypeSpec*: """复制 sp 并设置 ElemBits(独立副本,不驻留);无变化返回原实例""" - if sp is None: - return sp - if sp.ElemBits == elem_bits: - return sp + if sp is None: return sp + if sp.ElemBits == elem_bits: return sp cp: TypeSpec* = _spec_clone(sp) - if cp is None: - return sp + if cp is None: return sp cp.ElemBits = elem_bits return cp def SpecSourceName(sp: TypeSpec*) -> str: """Spec 的注解来源名(未设置返回 None)""" - if sp is None: - return None + if sp is None: return None return sp.SourceName def SpecIsUnsigned(sp: TypeSpec*) -> int: """是否无符号整数(单一真源;未知返回 0)""" - if sp is None: - return 0 - if sp.IsSigned == TS_SIGN_UNSIGNED: - return 1 + if sp is None: return 0 + if sp.IsSigned == TS_SIGN_UNSIGNED: return 1 return 0 def SpecBitWidth(sp: TypeSpec*) -> int: """位宽(非整形/浮点返回 0)""" - if sp is None: - return 0 + if sp is None: return 0 return sp.Bits @@ -1089,8 +942,7 @@ def SpecBitWidth(sp: TypeSpec*) -> int: # 循环变量在 match **外**更新。 def SpecTypePtrLevel(ty: mlirlite.LLVMType*) -> int: """计算指针层级,0=非指针,1=一级指针,2=二级指针…""" - if ty is None: - return 0 + if ty is None: return 0 level: int = 0 cur: mlirlite.LLVMType* = ty while cur is not None: @@ -1116,8 +968,7 @@ def SpecTypePtrLevel(ty: mlirlite.LLVMType*) -> int: # ============================================================ def SpecTypeBits(ty: mlirlite.LLVMType*) -> int: """获取 LLVM 整数类型的位宽,非整数类型返回 0""" - if ty is None: - return 0 + if ty is None: return 0 match ty: case mlirlite.LLVMType.Int(bits): return bits @@ -1151,20 +1002,17 @@ define SPEC_LLVM_TEXT_MAX_DEPTH = 100 def SpecToLLVMText(sp: TypeSpec*, buf: str, buf_size: sizet) -> int: """TypeSpec → LLVM IR 类型文本(对齐 TypePrint),返回 0=成功 / 1=失败""" - if sp is None or buf is None or buf_size == 0: - return 1 + if sp is None or buf is None or buf_size == 0: return 1 buf[0] = '\0' return _spec_llvm_text(sp, buf, buf_size, 0) def _spec_llvm_append(buf: str, buf_size: sizet, src: str) -> int: """把 src 追加到 buf 末尾(有界,不越写),返回 0=成功 / 1=容量不足""" - if buf is None or src is None: - return 1 + if buf is None or src is None: return 1 pos: sizet = string.strlen(buf) n: sizet = string.strlen(src) - if pos + n + 1 > buf_size: - return 1 + if pos + n + 1 > buf_size: return 1 string.strcpy(buf + pos, src) return 0 @@ -1172,13 +1020,10 @@ def _spec_llvm_append(buf: str, buf_size: sizet, src: str) -> int: def _spec_llvm_text(sp: TypeSpec*, buf: str, buf_size: sizet, depth: int) -> int: """把 sp 的 LLVM 文本**追加**到 buf 末尾(buf 已有前缀时保持原前缀)""" - if sp is None or buf is None: - return 1 - if depth >= SPEC_LLVM_TEXT_MAX_DEPTH: - return 1 + if sp is None or buf is None: return 1 + if depth >= SPEC_LLVM_TEXT_MAX_DEPTH: return 1 pos: sizet = string.strlen(buf) - if pos + 1 >= buf_size: - return 1 + if pos + 1 >= buf_size: return 1 # --- 基础标量(无符号在 LLVM 文本层同样是 iN) --- if sp.Kind == TS_INT or sp.Kind == TS_UINT: viperlib.snprintf(buf + pos, buf_size - pos, "i%d", sp.Bits) @@ -1187,16 +1032,11 @@ def _spec_llvm_text(sp: TypeSpec*, buf: str, buf_size: sizet, viperlib.snprintf(buf + pos, buf_size - pos, "i1") return 0 if sp.Kind == TS_FLOAT: - if sp.Bits == 16: - viperlib.snprintf(buf + pos, buf_size - pos, "half") - elif sp.Bits == 32: - viperlib.snprintf(buf + pos, buf_size - pos, "float") - elif sp.Bits == 64: - viperlib.snprintf(buf + pos, buf_size - pos, "double") - elif sp.Bits == 128: - viperlib.snprintf(buf + pos, buf_size - pos, "fp128") - else: - viperlib.snprintf(buf + pos, buf_size - pos, "float%x", sp.Bits) + if sp.Bits == 16: viperlib.snprintf(buf + pos, buf_size - pos, "half") + elif sp.Bits == 32: viperlib.snprintf(buf + pos, buf_size - pos, "float") + elif sp.Bits == 64: viperlib.snprintf(buf + pos, buf_size - pos, "double") + elif sp.Bits == 128: viperlib.snprintf(buf + pos, buf_size - pos, "fp128") + else: viperlib.snprintf(buf + pos, buf_size - pos, "float%x", sp.Bits) return 0 if sp.Kind == TS_VOID: viperlib.snprintf(buf + pos, buf_size - pos, "void") @@ -1211,51 +1051,40 @@ def _spec_llvm_text(sp: TypeSpec*, buf: str, buf_size: sizet, if inner.BaseName is not None: viperlib.snprintf(buf + pos, buf_size - pos, "%%\"%s\"*", inner.BaseName) return 0 - if _spec_llvm_text(inner, buf, buf_size, depth + 1) != 0: - return 1 + if _spec_llvm_text(inner, buf, buf_size, depth + 1) != 0: return 1 pos2: sizet = string.strlen(buf) - if pos2 + 1 >= buf_size: - return 1 + if pos2 + 1 >= buf_size: return 1 buf[pos2] = '*' buf[pos2 + 1] = '\0' return 0 # --- 数组 --- if sp.Kind == TS_ARRAY: viperlib.snprintf(buf + pos, buf_size - pos, "[%d x ", sp.ArrayCount) - if _spec_llvm_text(sp.Elem, buf, buf_size, depth + 1) != 0: - return 1 + if _spec_llvm_text(sp.Elem, buf, buf_size, depth + 1) != 0: return 1 return _spec_llvm_append(buf, buf_size, "]") # --- 命名结构体 / 联合 / 枚举 --- if sp.Kind == TS_STRUCT or sp.Kind == TS_UNION or sp.Kind == TS_ENUM: - if sp.BaseName is None: - return 1 + if sp.BaseName is None: return 1 viperlib.snprintf(buf + pos, buf_size - pos, "%%\"%s\"", sp.BaseName) return 0 # --- 函数签名 --- if sp.Kind == TS_FUNC: - if _spec_llvm_text(sp.Ret, buf, buf_size, depth + 1) != 0: - return 1 - if _spec_llvm_append(buf, buf_size, " (") != 0: - return 1 + if _spec_llvm_text(sp.Ret, buf, buf_size, depth + 1) != 0: return 1 + if _spec_llvm_append(buf, buf_size, " (") != 0: return 1 i: int = 0 while i < sp.ParamCount: if i > 0: - if _spec_llvm_append(buf, buf_size, ", ") != 0: - return 1 + if _spec_llvm_append(buf, buf_size, ", ") != 0: return 1 ps: TypeSpec* = _spec_param_at(sp, i) - if ps is None: - return 1 - if _spec_llvm_text(ps, buf, buf_size, depth + 1) != 0: - return 1 + if ps is None: return 1 + if _spec_llvm_text(ps, buf, buf_size, depth + 1) != 0: return 1 i += 1 # 变参后缀(本 Spec 口径独有,见上方说明) if sp.IsVarArg == 1: if sp.ParamCount > 0: - if _spec_llvm_append(buf, buf_size, ", ...") != 0: - return 1 + if _spec_llvm_append(buf, buf_size, ", ...") != 0: return 1 else: - if _spec_llvm_append(buf, buf_size, "...") != 0: - return 1 + if _spec_llvm_append(buf, buf_size, "...") != 0: return 1 return _spec_llvm_append(buf, buf_size, ")") return 1 @@ -1282,12 +1111,10 @@ def _spec_llvm_text(sp: TypeSpec*, buf: str, buf_size: sizet, def SpecFromLLVMType(arena: TypeSpecArena*, ty: mlirlite.LLVMType*) -> TypeSpec*: """把已解析的 LLVM 类型翻译成 TypeSpec;不支持或为 None 时返回 None""" - if arena is None or ty is None: - return None + if arena is None or ty is None: return None match ty: case mlirlite.LLVMType.Int(bits): - if bits == 1: - return NewTypeSpec(arena, TS_BOOL, 1, TS_SIGN_UNSIGNED) + if bits == 1: return NewTypeSpec(arena, TS_BOOL, 1, TS_SIGN_UNSIGNED) return NewTypeSpec(arena, TS_INT, bits, TS_SIGN_SIGNED) case mlirlite.LLVMType.Float(bits): return NewTypeSpec(arena, TS_FLOAT, bits, TS_SIGN_SIGNED) @@ -1309,8 +1136,7 @@ def _spec_from_ptr(arena: TypeSpecArena*, pointee: mlirlite.LLVMType*) -> TypeSpec*: """Ptr(pointee) → TypeSpec(PtrLevel/ElemBits/IsElemPtr 由 NewTypePtr 填)""" inner: TypeSpec* = SpecFromLLVMType(arena, pointee) - if inner is None: - return None + if inner is None: return None return NewTypePtr(arena, inner) @@ -1319,8 +1145,7 @@ def _spec_from_array(arena: TypeSpecArena*, count: int) -> TypeSpec*: """[count x elem] → TypeSpec(ArrayCount/ElemBits/IsElemPtr 由 NewTypeArray 填)""" inner: TypeSpec* = SpecFromLLVMType(arena, elem_ty) - if inner is None: - return None + if inner is None: return None return NewTypeArray(arena, inner, count) @@ -1330,24 +1155,20 @@ def _spec_from_func(arena: TypeSpecArena*, pcount: int) -> TypeSpec*: """函数类型 → TypeSpec(形参沿 ParamNode 链表遍历;IsVarArg 恒 0,见上)""" ret_s: TypeSpec* = SpecFromLLVMType(arena, ret) - if ret_s is None: - return None + if ret_s is None: return None if pcount <= 0: no_params: sizet* = None return NewTypeFunc(arena, ret_s, no_params, 0, 0) params_arr: sizet* = CompilerFactory.factory.PermPool.alloc(8 * pcount) - if params_arr is None: - return None + if params_arr is None: return None node: mlirlite.ParamNode* = params i: int = 0 while node is not None and i < pcount: pty: mlirlite.LLVMType* = mlirlite.paramnode_get_ty(node) ps: TypeSpec* = SpecFromLLVMType(arena, pty) - if ps is None: - return None + if ps is None: return None slot: sizet* = (sizet*)(uint64(params_arr) + uint64(i * 8)) - if slot is None: - return None + if slot is None: return None slot[0] = sizet(ps) node = mlirlite.paramnode_get_next(node) i += 1 @@ -1357,8 +1178,7 @@ def _spec_from_func(arena: TypeSpecArena*, def _spec_from_struct(arena: TypeSpecArena*, sname: str) -> TypeSpec*: """有名结构体 → TS_STRUCT + BaseName;匿名结构体 → 无名 TS_STRUCT""" - if sname is not None: - return NewTypeStruct(arena, TS_STRUCT, sname) + if sname is not None: return NewTypeStruct(arena, TS_STRUCT, sname) return NewTypeSpec(arena, TS_STRUCT, 0, TS_SIGN_UNKNOWN) @@ -1371,64 +1191,47 @@ def _spec_from_struct(arena: TypeSpecArena*, def SpecSelfCheck() -> int: """TypeSpec 编解码自检,返回 0=通过 / 失败用例号""" arena: TypeSpecArena* = (TypeSpecArena*)(CompilerFactory.factory.PermPool.alloc(TypeSpecArena.__sizeof__())) - if arena is None: - return 1 + if arena is None: return 1 string.memset(arena, 0, TypeSpecArena.__sizeof__()) - if SpecArenaInit(arena, 64) != 0: - return 1 + if SpecArenaInit(arena, 64) != 0: return 1 # 1) u64 s_u64: TypeSpec* = NewTypeSpec(arena, TS_UINT, 64, TS_SIGN_UNSIGNED) - if s_u64 is None: - return 1 - if _check_roundtrip(s_u64, "u64") != 0: - return 1 + if s_u64 is None: return 1 + if _check_roundtrip(s_u64, "u64") != 0: return 1 # 2) i32 s_i32: TypeSpec* = NewTypeSpec(arena, TS_INT, 32, TS_SIGN_SIGNED) - if s_i32 is None: - return 2 - if _check_roundtrip(s_i32, "i32") != 0: - return 2 + if s_i32 is None: return 2 + if _check_roundtrip(s_i32, "i32") != 0: return 2 # 3) u64* s_p: TypeSpec* = NewTypePtr(arena, s_u64) - if s_p is None: - return 3 - if _check_roundtrip(s_p, "p:u64") != 0: - return 3 + if s_p is None: return 3 + if _check_roundtrip(s_p, "p:u64") != 0: return 3 # 4) i8[4] s_arr: TypeSpec* = NewTypeArray(arena, s_i32, 4) - if s_arr is None: - return 4 - if _check_roundtrip(s_arr, "arr[4]:i32") != 0: - return 4 + if s_arr is None: return 4 + if _check_roundtrip(s_arr, "arr[4]:i32") != 0: return 4 # 5) fn(i32,u64)->i32(变参) params: sizet* = CompilerFactory.factory.PermPool.alloc(8 * 2) - if params is None: - return 5 + if params is None: return 5 slot0: sizet* = (sizet*)(uint64(params)) - if slot0 is None: - return 5 + if slot0 is None: return 5 slot0[0] = sizet(s_i32) slot1: sizet* = (sizet*)(uint64(params) + 8) - if slot1 is None: - return 5 + if slot1 is None: return 5 slot1[0] = sizet(s_u64) s_fn: TypeSpec* = NewTypeFunc(arena, s_i32, params, 2, 1) - if s_fn is None: - return 5 - if _check_roundtrip(s_fn, "fn(i32,u64,...)->i32") != 0: - return 5 + if s_fn is None: return 5 + if _check_roundtrip(s_fn, "fn(i32,u64,...)->i32") != 0: return 5 # 6) 驻留去重:同一文本第二次应返回同一实例 s_u64_again: TypeSpec* = NewTypeSpec(arena, TS_UINT, 64, TS_SIGN_UNSIGNED) - if s_u64_again is None: - return 6 - if uint64(s_u64_again) != uint64(s_u64): - return 6 + if s_u64_again is None: return 6 + if uint64(s_u64_again) != uint64(s_u64): return 6 return 0 @@ -1437,23 +1240,15 @@ def SpecSelfCheck() -> int: # ============================================================ def _check_roundtrip(sp: TypeSpec*, expect: str) -> int: """编码比对 + 解码往返一致;返回 0=通过 / 1=失败""" - if sp is None or expect is None: - return 1 + if sp is None or expect is None: return 1 buf1: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX) - if buf1 is None: - return 1 - if SpecToText(sp, buf1, SPEC_TEXT_MAX) != 0: - return 1 - if string.strcmp(buf1, expect) != 0: - return 1 + if buf1 is None: return 1 + if SpecToText(sp, buf1, SPEC_TEXT_MAX) != 0: return 1 + if string.strcmp(buf1, expect) != 0: return 1 back: TypeSpec* = TextToSpec(buf1) - if back is None: - return 1 + if back is None: return 1 buf2: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX) - if buf2 is None: - return 1 - if SpecToText(back, buf2, SPEC_TEXT_MAX) != 0: - return 1 - if string.strcmp(buf2, expect) != 0: - return 1 + if buf2 is None: return 1 + if SpecToText(back, buf2, SPEC_TEXT_MAX) != 0: return 1 + if string.strcmp(buf2, expect) != 0: return 1 return 0 diff --git a/App/lib/core/Gen/VarGenMixin.vp b/App/lib/core/Gen/VarGenMixin.vp index 3a256f9..0f20c92 100644 --- a/App/lib/core/Gen/VarGenMixin.vp +++ b/App/lib/core/Gen/VarGenMixin.vp @@ -50,16 +50,14 @@ novirtual class VarGenMixin: var_count: int, name: str) -> mlirlite.Value*: """在变量表中按名称查找""" - if name is None or vars_ptr is None: - return None + if name is None or vars_ptr is None: return None entry_size: sizet = GenTypes.VarEntry.__sizeof__() for i in range(var_count): entry_addr: uint64 = uint64(vars_ptr) + i * entry_size entry: GenTypes.VarEntry* = GenTypes.VarEntry*(entry_addr) if entry.Name is not None and entry.Used != 0: # 快速路径:strcmp 判等蕴含首字符相等,首字符不同者跳过 strcmp - if entry.Name[0] == name[0] and string.strcmp(entry.Name, name) == 0: - return entry.Alloca + if entry.Name[0] == name[0] and string.strcmp(entry.Name, name) == 0: return entry.Alloca return None # ============================================================ @@ -69,15 +67,13 @@ novirtual class VarGenMixin: var_count: int, name: str) -> GenTypes.VarEntry*: """在变量表中按名称查找,返回 VarEntry 或 None""" - if name is None or vars_ptr is None: - return None + if name is None or vars_ptr is None: return None entry_size: sizet = GenTypes.VarEntry.__sizeof__() for i in range(var_count): entry_addr: uint64 = uint64(vars_ptr) + i * entry_size entry: GenTypes.VarEntry* = GenTypes.VarEntry*(entry_addr) if entry.Name is not None and entry.Used != 0: - if string.strcmp(entry.Name, name) == 0: - return entry + if string.strcmp(entry.Name, name) == 0: return entry return None # ============================================================ @@ -86,13 +82,11 @@ novirtual class VarGenMixin: def lookup_var_entry(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> GenTypes.VarEntry*: """从当前作用域逐级向上查找变量,返回 VarEntry 或 None""" - if symtab is None or name is None: - return None + if symtab is None or name is None: return None scope: rawptr[GenTypes.Scope] = symtab.Current while scope is not None: result: GenTypes.VarEntry* = self.find_var_entry(scope.Vars, scope.VarCount, name) - if result is not None: - return result + if result is not None: return result scope = scope.Parent return None @@ -116,25 +110,20 @@ novirtual class VarGenMixin: 类型信息缺失(SpecFromLLVMType 不适用致 Spec 为 None)时建 TS_UNKNOWN 承载注解名 —— TS_UNKNOWN 不表态任何具体类型,等价于原来的"Spec 缺失"。 """ - if symtab is None or name is None: - return 1 + if symtab is None or name is None: return 1 entry: GenTypes.VarEntry* = self.lookup_var_entry(symtab, name) - if entry is None: - return 1 + if entry is None: return 1 if class_name is None: # 无注解名:不写入(VarEntry 槽位不复用,原值恒为 None,与清空等价)。 return 0 arena_sn: TSpec.TypeSpecArena* = self.Gen.TypeGenBase.ensure_spec_arena() - if arena_sn is None: - return 1 + if arena_sn is None: return 1 if entry.Spec is None: entry.Spec = TSpec.NewTypeSpec(arena_sn, TSpec.TS_UNKNOWN, 0, TSpec.TS_SIGN_UNKNOWN) - if entry.Spec is None: - return 1 + if entry.Spec is None: return 1 sign: int = self.Gen.TypeGenCType.spec_sign_of_annot(class_name) - if sign != TSpec.TS_SIGN_UNKNOWN: - entry.Spec = TSpec.SpecWithSign(arena_sn, entry.Spec, sign) + if sign != TSpec.TS_SIGN_UNKNOWN: entry.Spec = TSpec.SpecWithSign(arena_sn, entry.Spec, sign) entry.Spec = TSpec.SpecWithSource(entry.Spec, class_name) return 0 @@ -146,8 +135,7 @@ novirtual class VarGenMixin: # ============================================================ def var_annot_class_name(self, entry: GenTypes.VarEntry*) -> str: """变量条目注解类名(Spec.SourceName);未设置返回 None""" - if entry is None: - return None + if entry is None: return None return TSpec.SpecSourceName(entry.Spec) # set_var_ptr_element — 标记变量为「指针元素(ptr-element)」语义 @@ -160,11 +148,9 @@ novirtual class VarGenMixin: def set_var_ptr_element(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> int: """标记变量为 ptr-element(Spec.ElemBits=64),返回 0=成功 / 1=失败""" - if symtab is None or name is None: - return 1 + if symtab is None or name is None: return 1 entry: GenTypes.VarEntry* = self.lookup_var_entry(symtab, name) - if entry is None: - return 1 + if entry is None: return 1 # ptr-element 变量的 alloca 是 Ptr(Ptr(Int8)),其值类型 Ptr(Int8) ⇒ Spec 必为 # PtrLevel>=1。不满足即上游异常(类型缺失/退化),fail-fast 暴露 —— # 若静默放过,读点 var_is_ptr_element 返回 0 → 下标按 1 字节误算(数据损坏)。 @@ -180,15 +166,11 @@ novirtual class VarGenMixin: # 但 Elem.Bits=64,不命中;纯 str/bytes/char* 变量 ElemBits=8,同样不命中。 def var_is_ptr_element(self, entry: GenTypes.VarEntry*) -> int: """变量是否为 ptr-element 语义(1=是 / 0=否)""" - if entry is None or entry.Spec is None: - return 0 + if entry is None or entry.Spec is None: return 0 sp: TSpec.TypeSpec* = entry.Spec - if sp.PtrLevel < 1 or sp.Elem is None: - return 0 - if sp.Elem.Bits != 8: - return 0 - if sp.ElemBits == 64: - return 1 + if sp.PtrLevel < 1 or sp.Elem is None: return 0 + if sp.Elem.Bits != 8: return 0 + if sp.ElemBits == 64: return 1 return 0 # set_var_volatile — 标记变量为 volatile(注解联合含 t.CVolatile) @@ -198,19 +180,16 @@ novirtual class VarGenMixin: def set_var_volatile(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> int: """标记变量为 volatile(VarEntry.IsVolatile=1),返回 0=成功 / 1=失败""" - if symtab is None or name is None: - return 1 + if symtab is None or name is None: return 1 entry: GenTypes.VarEntry* = self.lookup_var_entry(symtab, name) - if entry is None: - return 1 + if entry is None: return 1 entry.IsVolatile = 1 return 0 # var_is_volatile — 变量是否 volatile(读路径/写路径统一入口) def var_is_volatile(self, entry: GenTypes.VarEntry*) -> int: """变量条目是否 volatile(1=是 / 0=否;entry 为 None 时 0)""" - if entry is None: - return 0 + if entry is None: return 0 return entry.IsVolatile # set_var_pointee_volatile — 标记"指针所指物"为 volatile @@ -221,19 +200,16 @@ novirtual class VarGenMixin: def set_var_pointee_volatile(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> int: """标记变量所指物为 volatile(VarEntry.PointeeVolatile=1),返回 0=成功 / 1=失败""" - if symtab is None or name is None: - return 1 + if symtab is None or name is None: return 1 entry: GenTypes.VarEntry* = self.lookup_var_entry(symtab, name) - if entry is None: - return 1 + if entry is None: return 1 entry.PointeeVolatile = 1 return 0 # var_pointee_is_volatile — 变量所指物是否 volatile(解引用读写统一入口) def var_pointee_is_volatile(self, entry: GenTypes.VarEntry*) -> int: """变量条目所指物是否 volatile(1=是 / 0=否;entry 为 None 时 0)""" - if entry is None: - return 0 + if entry is None: return 0 return entry.PointeeVolatile # set_var_const — 标记变量为 const 对象(注解含 t.CConst 且类型非指针) @@ -244,19 +220,16 @@ novirtual class VarGenMixin: def set_var_const(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> int: """标记变量为 const 对象(VarEntry.IsConst=1),返回 0=成功 / 1=失败""" - if symtab is None or name is None: - return 1 + if symtab is None or name is None: return 1 entry: GenTypes.VarEntry* = self.lookup_var_entry(symtab, name) - if entry is None: - return 1 + if entry is None: return 1 entry.IsConst = 1 return 0 # var_is_const — 变量是否 const 对象(赋值/增量赋值/元素赋值拦截面统一入口) def var_is_const(self, entry: GenTypes.VarEntry*) -> int: """变量条目是否 const 对象(1=是 / 0=否;entry 为 None 时 0)""" - if entry is None: - return 0 + if entry is None: return 0 return entry.IsConst # ============================================================ @@ -267,10 +240,8 @@ novirtual class VarGenMixin: name: str, alloca: mlirlite.Value*) -> int: """添加变量到变量表""" - if name is None or alloca is None or vars_ptr is None: - return 1 - if var_count >= HT.MAX_VARS: - return 1 + if name is None or alloca is None or vars_ptr is None: return 1 + if var_count >= HT.MAX_VARS: return 1 entry_size: sizet = GenTypes.VarEntry.__sizeof__() entry_addr: uint64 = uint64(vars_ptr) + var_count * entry_size entry: GenTypes.VarEntry* = GenTypes.VarEntry*(entry_addr) @@ -281,8 +252,7 @@ novirtual class VarGenMixin: # AST tree 生命周期。 name_len: sizet = string.strlen(name) name_copy: bytes = stdlib.malloc(name_len + 1) - if name_copy is None: - return 1 + if name_copy is None: return 1 string.strcpy(name_copy, name) entry.Name = name_copy entry.Alloca = alloca @@ -304,14 +274,11 @@ novirtual class VarGenMixin: # ============================================================ def _spec_of_var_alloca(self, alloca: mlirlite.Value*) -> TSpec.TypeSpec*: """由 alloca 的值类型构造 TypeSpec,不适用/失败返回 None""" - if alloca is None or alloca.Ty is None: - return None + if alloca is None or alloca.Ty is None: return None ty: mlirlite.LLVMType* = alloca.Ty - if self.Gen.ExprGenBase.is_ptr_type(ty) != 0: - ty = ty.Pointee + if self.Gen.ExprGenBase.is_ptr_type(ty) != 0: ty = ty.Pointee arena: TSpec.TypeSpecArena* = self.Gen.TypeGenBase.ensure_spec_arena() - if arena is None: - return None + if arena is None: return None return TSpec.SpecFromLLVMType(arena, ty) # _alloca_at_entry - 在函数入口块生成 alloca(确保支配性) @@ -324,8 +291,7 @@ novirtual class VarGenMixin: 使用 mlirlite.build_alloca_at_entry 在入口块终止指令之前插入 alloca, 确保所有 alloca 在入口块,避免支配性违规。 """ - if builder is None or ty is None: - return None + if builder is None or ty is None: return None return mlirlite.build_alloca_at_entry(builder, ty) # get_or_create_var — 查找或创建变量 alloca(旧版兼容) @@ -337,13 +303,10 @@ novirtual class VarGenMixin: ty: mlirlite.LLVMType*) -> mlirlite.Value*: """查找或创建变量 alloca""" existing: mlirlite.Value* = self.find_var(vars_ptr, var_count, name) - if existing is not None: - return existing + if existing is not None: return existing alloca: mlirlite.Value* = self._alloca_at_entry(builder, ty) - if alloca is None: - return None - if self.add_var(vars_ptr, var_count, name, alloca) != 0: - return None + if alloca is None: return None + if self.add_var(vars_ptr, var_count, name, alloca) != 0: return None return alloca # ============================================================ @@ -354,15 +317,13 @@ novirtual class VarGenMixin: kind: int) -> rawptr[GenTypes.Scope]: """创建并初始化作用域节点""" scope: rawptr[GenTypes.Scope] = pool.alloc(GenTypes.Scope.__sizeof__()) - if scope is None: - return None + if scope is None: return None string.memset(scope, 0, GenTypes.Scope.__sizeof__()) scope.Parent = parent scope.Vars = self.init_vars(pool) scope.VarCount = 0 scope.Kind = kind - if scope.Vars is None: - return None + if scope.Vars is None: return None return scope # ============================================================ @@ -370,18 +331,15 @@ novirtual class VarGenMixin: # ============================================================ def init_symbol_table(self, pool: memhub.MemBuddy*) -> rawptr[GenTypes.SymbolTable]: """创建并初始化符号表,包含模块级根作用域""" - if pool is None: - return None + if pool is None: return None symtab: rawptr[GenTypes.SymbolTable] = pool.alloc(GenTypes.SymbolTable.__sizeof__()) - if symtab is None: - return None + if symtab is None: return None string.memset(symtab, 0, GenTypes.SymbolTable.__sizeof__()) symtab.Pool = pool # 创建根作用域(模块级) root: rawptr[GenTypes.Scope] = self._create_scope(pool, None, SCOPE_MODULE) - if root is None: - return None + if root is None: return None symtab.Root = root symtab.Current = root @@ -393,12 +351,10 @@ novirtual class VarGenMixin: def enter_scope(self, symtab: rawptr[GenTypes.SymbolTable], kind: int) -> rawptr[GenTypes.Scope]: """进入新作用域,返回新创建的作用域""" - if symtab is None: - return None + if symtab is None: return None pool: memhub.MemBuddy* = symtab.Pool scope: rawptr[GenTypes.Scope] = self._create_scope(pool, symtab.Current, kind) - if scope is None: - return None + if scope is None: return None symtab.Current = scope return scope @@ -407,8 +363,7 @@ novirtual class VarGenMixin: # ============================================================ def exit_scope(self, symtab: rawptr[GenTypes.SymbolTable]): """退出当前作用域,恢复到父作用域""" - if symtab is not None and symtab.Current is not None: - symtab.Current = symtab.Current.Parent + if symtab is not None and symtab.Current is not None: symtab.Current = symtab.Current.Parent # ============================================================ # define_var — 在当前作用域定义变量 @@ -417,14 +372,11 @@ novirtual class VarGenMixin: name: str, alloca: mlirlite.Value*) -> int: """在当前作用域定义变量,返回 0 成功""" - if symtab is None or name is None or alloca is None: - return 1 + if symtab is None or name is None or alloca is None: return 1 scope: rawptr[GenTypes.Scope] = symtab.Current - if scope is None: - return 1 + if scope is None: return 1 ret: int = self.add_var(scope.Vars, scope.VarCount, name, alloca) - if ret == 0: - scope.VarCount = scope.VarCount + 1 + if ret == 0: scope.VarCount = scope.VarCount + 1 return ret # ============================================================ @@ -434,14 +386,11 @@ novirtual class VarGenMixin: name: str, alloca: mlirlite.Value*) -> int: """在模块作用域定义变量,返回 0 成功""" - if symtab is None or name is None or alloca is None: - return 1 + if symtab is None or name is None or alloca is None: return 1 scope: rawptr[GenTypes.Scope] = symtab.Root - if scope is None: - return 1 + if scope is None: return 1 ret: int = self.add_var(scope.Vars, scope.VarCount, name, alloca) - if ret == 0: - scope.VarCount = scope.VarCount + 1 + if ret == 0: scope.VarCount = scope.VarCount + 1 return ret # ============================================================ @@ -450,13 +399,11 @@ novirtual class VarGenMixin: def lookup_var(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> mlirlite.Value*: """从当前作用域逐级向上查找变量,返回 alloca 或 None""" - if symtab is None or name is None: - return None + if symtab is None or name is None: return None scope: rawptr[GenTypes.Scope] = symtab.Current while scope is not None: result: mlirlite.Value* = self.find_var(scope.Vars, scope.VarCount, name) - if result is not None: - return result + if result is not None: return result scope = scope.Parent return None @@ -466,11 +413,9 @@ novirtual class VarGenMixin: def lookup_current(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> mlirlite.Value*: """仅在当前作用域查找变量""" - if symtab is None or name is None: - return None + if symtab is None or name is None: return None scope: rawptr[GenTypes.Scope] = symtab.Current - if scope is None: - return None + if scope is None: return None return self.find_var(scope.Vars, scope.VarCount, name) # ============================================================ @@ -479,11 +424,9 @@ novirtual class VarGenMixin: def lookup_module_var(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> mlirlite.Value*: """在模块作用域查找变量""" - if symtab is None or name is None: - return None + if symtab is None or name is None: return None scope: rawptr[GenTypes.Scope] = symtab.Root - if scope is None: - return None + if scope is None: return None return self.find_var(scope.Vars, scope.VarCount, name) # ============================================================ @@ -498,26 +441,21 @@ novirtual class VarGenMixin: Returns: 1=模块级作用域, 0=函数内作用域 """ - if symtab is None: - return 0 - if symtab.Root is None or symtab.Current is None: - return 0 + if symtab is None: return 0 + if symtab.Root is None or symtab.Current is None: return 0 # 比较指针:Current 与 Root 相同则为模块级 - if uint64(symtab.Current) == uint64(symtab.Root): - return 1 + if uint64(symtab.Current) == uint64(symtab.Root): return 1 return 0 # _lookup_through_match_scope — 穿越 match case 作用域查找变量 def _lookup_through_match_scope(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> mlirlite.Value*: """从当前作用域向上,仅穿越 SCOPE_MATCH 作用域查找变量 alloca""" - if symtab is None or name is None: - return None + if symtab is None or name is None: return None scope: rawptr[GenTypes.Scope] = symtab.Current while scope is not None: result: mlirlite.Value* = self.find_var(scope.Vars, scope.VarCount, name) - if result is not None: - return result + if result is not None: return result if scope.Kind == SCOPE_MATCH: scope = scope.Parent continue @@ -534,17 +472,13 @@ novirtual class VarGenMixin: ty: mlirlite.LLVMType*) -> mlirlite.Value*: """查找或创建变量 alloca(在当前作用域)""" existing: mlirlite.Value* = self.lookup_current(symtab, name) - if existing is not None: - return existing + if existing is not None: return existing # SCOPE_MATCH 隔离作用域对"赋值"必须透明: existing = self._lookup_through_match_scope(symtab, name) - if existing is not None: - return existing + 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 alloca is None: return None + if self.define_var(symtab, name, alloca) != 0: self.Gen.TypeGenErr.fatal_error(None, f"变量 '{name}' 注册失败(作用域变量数超过上限 MAX_VARS)", "InternalCompilerError") return alloca # ============================================================ @@ -561,19 +495,15 @@ novirtual class VarGenMixin: # ---- repl_find_entry — 会话表按名查找 ---- def repl_find_entry(self, ctx: rawptr[GenTypes.ReplCtx], name: str) -> rawptr[GenTypes.ReplVarEntry]: """在会话表中按名查找条目;ctx 无效或未登记返回 None""" - if ctx is None or name is None: - return None + if ctx is None or name is None: return None # 魔数校验:防止把非 ReplCtx 的指针当上下文用(宁可不拦截也不乱拦截) - if ctx.Marker != GenTypes.REPL_CTX_MARKER: - return None - if ctx.Table is None or ctx.Count <= 0: - return None + if ctx.Marker != GenTypes.REPL_CTX_MARKER: return None + if ctx.Table is None or ctx.Count <= 0: return None entry_size: sizet = GenTypes.ReplVarEntry.__sizeof__() for i in range(ctx.Count): entry_addr: uint64 = uint64(ctx.Table) + i * entry_size entry: rawptr[GenTypes.ReplVarEntry] = rawptr[GenTypes.ReplVarEntry](entry_addr) - if entry.Name is not None and string.strcmp(entry.Name, name) == 0: - return entry + if entry.Name is not None and string.strcmp(entry.Name, name) == 0: return entry return None # ---- repl_in_frag_scope — 当前最近函数作用域是否就是片段函数本体 ---- @@ -584,13 +514,11 @@ novirtual class VarGenMixin: (其函数作用域的父不是模块根)一律走原路径。if/while 分支不建新作用域, 故分支内的赋值同样命中(整行片段语义)。 """ - if symtab is None or symtab.Current is None or symtab.Root is None: - return 0 + if symtab is None or symtab.Current is None or symtab.Root is None: return 0 scope: rawptr[GenTypes.Scope] = symtab.Current while scope is not None: if scope.Kind == SCOPE_FUNCTION: - if scope.Parent is not None and uint64(scope.Parent) == uint64(symtab.Root): - return 1 + if scope.Parent is not None and uint64(scope.Parent) == uint64(symtab.Root): return 1 return 0 scope = scope.Parent return 0 @@ -600,8 +528,7 @@ novirtual class VarGenMixin: ctx: rawptr[GenTypes.ReplCtx], node: ast.AST*) -> mlirlite.Value*: """load 片段函数 ctx 形参(形参 alloca 由 FuncGenDef 建);失败 fail-fast""" - if trans is None or ctx is None or ctx.CtxParam is None: - return None + if trans is None or ctx is None or ctx.CtxParam is None: return None symtab: rawptr[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: @@ -627,35 +554,27 @@ novirtual class VarGenMixin: # (Repl.vp 的 "__repl_frag_%d")。非 REPL 路径 _cur_func 无该前缀 ⇒ 恒 0。 def repl_in_frag_entry_scope(self, trans: HT.Translator*) -> int: """1=当前正在翻译片段入口函数本体;0=其他(含被提升的会话函数本体)""" - if trans is None or trans._cur_func is None: - return 0 - if self.repl_in_frag_scope(trans.SymTab) == 0: - return 0 + if trans is None or trans._cur_func is None: return 0 + if self.repl_in_frag_scope(trans.SymTab) == 0: return 0 cur_nm: str = mlirlite.function_get_name(trans._cur_func) - if cur_nm is None: - return 0 + if cur_nm is None: return 0 pfx: str = GenTypes.REPL_ENTRY_PREFIX pl: sizet = string.strlen(pfx) - if string.strncmp(cur_nm, pfx, pl) != 0: - return 0 + if string.strncmp(cur_nm, pfx, pl) != 0: return 0 return 1 # ---- repl_find_func_entry — 会话函数表按名查找(M3) ---- def repl_find_func_entry(self, ctx: rawptr[GenTypes.ReplCtx], name: str) -> rawptr[GenTypes.ReplFuncEntry]: """在会话函数表中按名查找;ctx 无效/未登记返回 None(只读,不改表)""" - if ctx is None or name is None: - return None - if ctx.Marker != GenTypes.REPL_CTX_MARKER: - return None - if ctx.FuncTable is None or ctx.FuncCount <= 0: - return None + if ctx is None or name is None: return None + if ctx.Marker != GenTypes.REPL_CTX_MARKER: return None + if ctx.FuncTable is None or ctx.FuncCount <= 0: return None entry_size: sizet = GenTypes.ReplFuncEntry.__sizeof__() for i in range(ctx.FuncCount): entry_addr: uint64 = uint64(ctx.FuncTable) + i * entry_size entry: rawptr[GenTypes.ReplFuncEntry] = rawptr[GenTypes.ReplFuncEntry](entry_addr) - if entry.Name is not None and string.strcmp(entry.Name, name) == 0: - return entry + if entry.Name is not None and string.strcmp(entry.Name, name) == 0: return entry return None # ---- repl_func_ty — 签名 token → LLVM 类型(M3) ---- @@ -666,21 +585,16 @@ novirtual class VarGenMixin: def repl_func_ty(self, pool: memhub.MemBuddy*, tag: int, bits: int) -> mlirlite.LLVMType*: """签名 token → LLVM 类型;不支持的 token 返回 None""" - if pool is None: - return None - if tag == GenTypes.REPL_TY_INT: - return self.repl_scalar_ty(pool, bits, 0) - if tag == GenTypes.REPL_TY_FLOAT: - return self.repl_scalar_ty(pool, bits, 1) - if tag == GenTypes.REPL_TY_STR: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + if pool is None: return None + if tag == GenTypes.REPL_TY_INT: return self.repl_scalar_ty(pool, bits, 0) + if tag == GenTypes.REPL_TY_FLOAT: return self.repl_scalar_ty(pool, bits, 1) + if tag == GenTypes.REPL_TY_STR: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) return None # ---- repl_func_sig_label — 签名 token → 人类可读类型名(错误消息用) ---- def repl_func_sig_label(self, tag: int, bits: int) -> str: """签名 token → 显示名;未识别返回 "?"(VOID 显示为 void)""" - if tag == GenTypes.REPL_TY_VOID: - return "void" + if tag == GenTypes.REPL_TY_VOID: return "void" return self.repl_tag_label(tag, bits) # ---- repl_try_session_func_call — 会话函数间接调用(M3 核心) ---- @@ -709,19 +623,15 @@ novirtual class VarGenMixin: node: ast.AST*, hit: t.CPtr) -> mlirlite.Value*: """会话函数调用:命中返回 call 结果(void 函数返回 None 但 hit 已置 1)""" - if trans is None or trans.ReplCtx is None or pool is None or builder is None: - return None - if func_name is None or hit is None: - return None + if trans is None or trans.ReplCtx is None or pool is None or builder is None: return None + if func_name is None or hit is None: return None ctx: rawptr[GenTypes.ReplCtx] = trans.ReplCtx entry: rawptr[GenTypes.ReplFuncEntry] = self.repl_find_func_entry(ctx, func_name) - if entry is None: - return None + if entry is None: return None # 本判定与 M2 的读路径同口径:片段入口函数**或被提升的会话函数**体内允许 # 调用别的会话函数;片段内的嵌套闭包体(无 ctx 形参)不允许 ⇒ 返回未命中, # 由既有路径给出明确报错(不生成非法 IR)。 - if self.repl_in_frag_scope(trans.SymTab) == 0: - return None + 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") @@ -730,8 +640,7 @@ novirtual class VarGenMixin: self.Gen.TypeGenErr.fatal_error( node, f"REPL: 会话函数 '{func_name}' 期待 {entry.ParamCount} 个位置实参,调用处给了 {can} 个(M3 不支持默认参数/缺省补全)", "TypeError") return None ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, ctx, node) - if ctx_val is None: - return None + if ctx_val is None: return None i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, i8_ty) # ① 槽内取函数地址:槽地址是 i8**(Ptr(i8*)),load 得 i8* @@ -745,8 +654,7 @@ novirtual class VarGenMixin: return None # ② 签名构造前先取形参类型(token → LLVM 类型;不支持 ⇒ 明确报错) ptypes: t.CPtr = pool.alloc(8 * GenTypes.REPL_FUNC_PARAM_MAX) - if ptypes is None: - return None + if ptypes is None: return None string.memset(ptypes, 0, 8 * GenTypes.REPL_FUNC_PARAM_MAX) ai_chk: int for ai_chk in range(entry.ParamCount): @@ -801,14 +709,11 @@ novirtual class VarGenMixin: cur_ty = (mlirlite.LLVMType*)(pty_slot3[0]) pn: mlirlite.ParamNode* = mlirlite.new_param_node(pool, cur_ty) if pn is not None: - if fp_first is None: - fp_first = pn - if fp_prev is not None: - mlirlite.paramnode_set_next(fp_prev, pn) + if fp_first is None: fp_first = pn + if fp_prev is not None: mlirlite.paramnode_set_next(fp_prev, pn) fp_prev = pn func_ty: mlirlite.LLVMType* = mlirlite.Func(pool, ret_ty, fp_first, arg_count) - if func_ty is None: - return None + if func_ty is None: return None 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: @@ -827,21 +732,17 @@ novirtual class VarGenMixin: 用 i8 步长 GEP 做纯字节偏移(同 list_getitem_inline 的既有做法), 再 bitcast 到目标类型指针——槽步长与负载类型解耦。 """ - if pool is None or builder is None or ctx_val is None or val_ty is None: - return None + if pool is None or builder is None or ctx_val is None or val_ty is None: return None i8_ty: mlirlite.LLVMType* = mlirlite.Int8(pool) target_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, val_ty) off_val: mlirlite.Value* = mlirlite.const_int64(pool, int64(off)) - if off_val is None: - return None + if off_val is None: return None base: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, ctx_val, off_val) - if base is None: - return None + if base is None: return None # 同型时不发 bitcast:mlirlite 类型非 canonical(同类型不同实例地址不同), # 而 LLVM 拒绝 `bitcast i8* %x to i8*`(同型 cast 非法)——val_ty 为 i8 # (char 会话变量)时目标恰是 i8*,必须直接返回 GEP 结果。 - if base.Ty is not None and self.Gen.AssignGen._stg_ty_equal(pool, base.Ty, target_ptr_ty) != 0: - return base + if base.Ty is not None and self.Gen.AssignGen._stg_ty_equal(pool, base.Ty, target_ptr_ty) != 0: return base return mlirlite.build_bitcast(builder, base, target_ptr_ty) # ---- repl_scalar_ty — 位宽 → LLVM 标量类型 ---- @@ -849,21 +750,14 @@ novirtual class VarGenMixin: bits: int, is_float: int) -> mlirlite.LLVMType*: """按位宽还原 LLVM 标量类型;不支持的位宽返回 None""" if is_float != 0: - if bits == 32: - return mlirlite.Float(pool) - if bits == 64: - return mlirlite.Double(pool) + if bits == 32: return mlirlite.Float(pool) + if bits == 64: return mlirlite.Double(pool) return None - if bits == 1: - return mlirlite.Int1(pool) - if bits == 8: - return mlirlite.Int8(pool) - if bits == 16: - return mlirlite.Int16(pool) - if bits == 32: - return mlirlite.Int32(pool) - if bits == 64: - return mlirlite.Int64(pool) + if bits == 1: return mlirlite.Int1(pool) + if bits == 8: return mlirlite.Int8(pool) + if bits == 16: return mlirlite.Int16(pool) + if bits == 32: return mlirlite.Int32(pool) + if bits == 64: return mlirlite.Int64(pool) return None # ---- repl_llvm_ty — 条目 → LLVM 值类型(结构体按名重解析) ---- @@ -876,29 +770,21 @@ novirtual class VarGenMixin: 即回收,缓存指针会悬垂);当前片段不可见该结构体时返回 None 由调用点 给明确消息(跨片段类型可见性属 M4)。 """ - if entry is None or pool is None: - return None - if entry.Kind == GenTypes.REPL_KIND_UNTYPED: - return None - if entry.TyTag == GenTypes.REPL_TY_INT: - return self.repl_scalar_ty(pool, entry.Bits, 0) - if entry.TyTag == GenTypes.REPL_TY_FLOAT: - return self.repl_scalar_ty(pool, entry.Bits, 1) - if entry.TyTag == GenTypes.REPL_TY_STR: - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + if entry is None or pool is None: return None + if entry.Kind == GenTypes.REPL_KIND_UNTYPED: return None + if entry.TyTag == GenTypes.REPL_TY_INT: return self.repl_scalar_ty(pool, entry.Bits, 0) + if entry.TyTag == GenTypes.REPL_TY_FLOAT: return self.repl_scalar_ty(pool, entry.Bits, 1) + if entry.TyTag == GenTypes.REPL_TY_STR: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) if entry.TyTag == GenTypes.REPL_TY_PTR: if entry.TyName is not None: st: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type(entry.TyName) - if st is None: - return None + if st is None: return None return mlirlite.Ptr(pool, st) ptee: mlirlite.LLVMType* = self.repl_scalar_ty(pool, entry.Bits, 0) - if ptee is None: - ptee = mlirlite.Int8(pool) + if ptee is None: ptee = mlirlite.Int8(pool) return mlirlite.Ptr(pool, ptee) if entry.TyTag == GenTypes.REPL_TY_STRUCT: - if entry.TyName is None: - return None + if entry.TyName is None: return None return self.Gen.StructGen.get_struct_type(entry.TyName) return None @@ -910,61 +796,47 @@ novirtual class VarGenMixin: 结构体值另有体积约束:尺寸 > REPL_SLOT_SIZE 或对齐 > REPL_SLOT_SIZE 时 不可放入槽 → 返回 None(定型期 repl_seal 已先给明确报错,此处为防御)。 """ - if entry is None or pool is None: - return None + if entry is None or pool is None: return None vt: mlirlite.LLVMType* = self.repl_llvm_ty(pool, entry) - if vt is None: - return None + if vt is None: return None if entry.TyTag == GenTypes.REPL_TY_STRUCT: sz: int = self.repl_type_size(vt) al: int = self.repl_type_align(vt) - if sz <= 0 or al <= 0 or sz > GenTypes.REPL_SLOT_SIZE or al > GenTypes.REPL_SLOT_SIZE: - return None + if sz <= 0 or al <= 0 or sz > GenTypes.REPL_SLOT_SIZE or al > GenTypes.REPL_SLOT_SIZE: return None return vt # ---- repl_type_align / repl_type_size — 结构体值的尺寸/对齐(LLVM 标准布局) ---- def repl_type_align(self, ty: mlirlite.LLVMType*, depth: int = 0) -> int: """类型自然对齐字节;未知类型返回 0(deep=守卫递归深度)""" - if ty is None or depth > 64: - return 0 + if ty is None or depth > 64: return 0 ib: int = self.Gen.ExprGenBase.get_llvm_type_bits(ty) if ib != 0: - if ib <= 8: - return 1 - if ib <= 16: - return 2 - if ib <= 32: - return 4 + if ib <= 8: return 1 + if ib <= 16: return 2 + if ib <= 32: return 4 return 8 fb: int = self.Gen.ExprGenBase.get_llvm_float_bits(ty) if fb != 0: - if fb <= 16: - return 2 - if fb <= 32: - return 4 - return 8 - if self.Gen.ExprGenBase.is_ptr_type(ty) != 0: + if fb <= 16: return 2 + if fb <= 32: return 4 return 8 + if self.Gen.ExprGenBase.is_ptr_type(ty) != 0: return 8 elem_ty: mlirlite.LLVMType* = None match ty: case mlirlite.LLVMType.Array(elem_a, _cnt_a): elem_ty = elem_a case _: pass - if elem_ty is not None: - return self.repl_type_align(elem_ty, depth + 1) + if elem_ty is not None: return self.repl_type_align(elem_ty, depth + 1) fields: rawptr[mlirlite.ParamNode] = mlirlite.get_struct_fields(ty) - if fields is None: - return 0 + if fields is None: return 0 cur: rawptr[mlirlite.ParamNode] = fields best: int = 1 while cur is not None: fty: mlirlite.LLVMType* = mlirlite.paramnode_get_ty(cur) fa: int = self.repl_type_align(fty, depth + 1) - if fa <= 0: - return 0 - if fa > best: - best = fa + if fa <= 0: return 0 + if fa > best: best = fa cur = mlirlite.paramnode_get_next(cur) return best @@ -973,16 +845,12 @@ novirtual class VarGenMixin: 用于结构体值的"能否放入槽"判定(标量/指针见 repl_scalar_ty)。 """ - if ty is None or depth > 64: - return 0 + if ty is None or depth > 64: return 0 ib: int = self.Gen.ExprGenBase.get_llvm_type_bits(ty) - if ib != 0: - return (ib + 7) // 8 + if ib != 0: return (ib + 7) // 8 fb: int = self.Gen.ExprGenBase.get_llvm_float_bits(ty) - if fb != 0: - return fb // 8 - if self.Gen.ExprGenBase.is_ptr_type(ty) != 0: - return 8 + if fb != 0: return fb // 8 + if self.Gen.ExprGenBase.is_ptr_type(ty) != 0: return 8 elem_ty: mlirlite.LLVMType* = None cnt: int = 0 match ty: @@ -993,15 +861,12 @@ novirtual class VarGenMixin: pass if elem_ty is not None: es: int = self.repl_type_size(elem_ty, depth + 1) - if es <= 0 or cnt <= 0: - return 0 + if es <= 0 or cnt <= 0: return 0 return es * cnt fields: rawptr[mlirlite.ParamNode] = mlirlite.get_struct_fields(ty) - if fields is None: - return 0 + if fields is None: return 0 align_struct: int = self.repl_type_align(ty, depth + 1) - if align_struct <= 0: - return 0 + if align_struct <= 0: return 0 cur: rawptr[mlirlite.ParamNode] = fields off: int = 0 counted: int = 0 @@ -1009,19 +874,15 @@ novirtual class VarGenMixin: fty2: mlirlite.LLVMType* = mlirlite.paramnode_get_ty(cur) fsz: int = self.repl_type_size(fty2, depth + 1) fa2: int = self.repl_type_align(fty2, depth + 1) - if fsz <= 0 or fa2 <= 0: - return 0 + if fsz <= 0 or fa2 <= 0: return 0 rem: int = off % fa2 - if rem != 0: - off += fa2 - rem + if rem != 0: off += fa2 - rem off += fsz counted += 1 cur = mlirlite.paramnode_get_next(cur) - if counted <= 0: - return 0 + if counted <= 0: return 0 rem2: int = off % align_struct - if rem2 != 0: - off += align_struct - rem2 + if rem2 != 0: off += align_struct - rem2 return off # ---- repl_seal — 首次定型(已定型则校验类型标签一致) ---- @@ -1036,8 +897,7 @@ novirtual class VarGenMixin: - 已定型:TyTag 必须一致(int↔float↔指针不隐式换型,避免槽语义漂移), Bits 差异允许(由 coerce_to_type 做位宽对齐,常量溢出仍有既有 fail-fast)。 """ - if trans is None or entry is None or val_ty is None: - return 1 + 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") @@ -1057,8 +917,7 @@ novirtual class VarGenMixin: elif self.Gen.ExprGenBase.is_ptr_type(val_ty) != 0: ptee: mlirlite.LLVMType* = val_ty.Pointee pname: str = None - if ptee is not None: - pname = mlirlite.get_struct_name(ptee) + if ptee is not None: pname = mlirlite.get_struct_name(ptee) if pname is not None: tag = GenTypes.REPL_TY_PTR bits = 64 @@ -1074,12 +933,9 @@ novirtual class VarGenMixin: bits = 8 else: tag = GenTypes.REPL_TY_PTR - if pb != 0: - bits = pb - elif pf != 0: - bits = pf - else: - bits = 0 + if pb != 0: bits = pb + elif pf != 0: bits = pf + else: bits = 0 else: sname: str = mlirlite.get_struct_name(val_ty) if sname is not None: @@ -1116,8 +972,7 @@ novirtual class VarGenMixin: entry.TyTag = tag entry.Bits = bits entry.TyName = None - if tname is not None: - entry.TyName = self.repl_perm_strdup(perm, tname) + 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, @@ -1125,20 +980,17 @@ novirtual class VarGenMixin: f"不能再赋成 {self.repl_tag_label(tag, bits)}(如需换型请重启会话)", "TypeError") return 1 - if tname is not None and entry.TyName is None: - entry.TyName = self.repl_perm_strdup(perm, tname) + if tname is not None and entry.TyName is None: entry.TyName = self.repl_perm_strdup(perm, tname) return 0 # ---- repl_perm_strdup — 深拷贝到 PermPool(跨片段存活) ---- def repl_perm_strdup(self, pool: memhub.MemBuddy*, s: str) -> str: """把 s 深拷贝进 pool(调用方传 PermPool)供会话表长期持有;失败返回 None""" - if s is None or pool is None: - return None + if s is None or pool is None: return None n: sizet = string.strlen(s) buf: str = pool.alloc(n + 1) - if buf is None: - return None + if buf is None: return None string.strcpy(buf, s) return buf @@ -1146,29 +998,19 @@ novirtual class VarGenMixin: def repl_tag_label(self, tag: int, bits: int) -> str: """TyTag/Bits → 人类可读类型名(仅用于错误消息)""" if tag == GenTypes.REPL_TY_INT: - if bits == 1: - return "bool" - if bits == 8: - return "char" - if bits == 16: - return "int16" - if bits == 32: - return "int" - if bits == 64: - return "int64" + if bits == 1: return "bool" + if bits == 8: return "char" + if bits == 16: return "int16" + if bits == 32: return "int" + if bits == 64: return "int64" return "int?" if tag == GenTypes.REPL_TY_FLOAT: - if bits == 32: - return "float" - if bits == 64: - return "double" + if bits == 32: return "float" + if bits == 64: return "double" return "float?" - if tag == GenTypes.REPL_TY_STR: - return "str" - if tag == GenTypes.REPL_TY_PTR: - return "ptr" - if tag == GenTypes.REPL_TY_STRUCT: - return "struct" + if tag == GenTypes.REPL_TY_STR: return "str" + if tag == GenTypes.REPL_TY_PTR: return "ptr" + if tag == GenTypes.REPL_TY_STRUCT: return "struct" return "?" # ---- repl_ensure_entry — 首次遇到未定型的会话变量名时申请槽位 ---- @@ -1180,14 +1022,11 @@ novirtual class VarGenMixin: name: str, node: ast.AST*) -> rawptr[GenTypes.ReplVarEntry]: """按名取条目,未登记则分配槽位并登记;失败返回 None(已 fail-fast)""" - if trans is None or name is None: - return None + if trans is None or name is None: return None ctx: rawptr[GenTypes.ReplCtx] = trans.ReplCtx - if ctx is None or ctx.Marker != GenTypes.REPL_CTX_MARKER: - return None + if ctx is None or ctx.Marker != GenTypes.REPL_CTX_MARKER: return None hit: rawptr[GenTypes.ReplVarEntry] = self.repl_find_entry(ctx, name) - if hit is not None: - return hit + 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") return None @@ -1207,8 +1046,7 @@ novirtual class VarGenMixin: return None entry_size: sizet = GenTypes.ReplVarEntry.__sizeof__() entry: rawptr[GenTypes.ReplVarEntry] = rawptr[GenTypes.ReplVarEntry](uint64(ctx.Table) + uint64(ctx.Count) * uint64(entry_size)) - if entry is None: - return None + if entry is None: return None entry.Name = name_copy entry.TyName = None entry.Offset = GenTypes.REPL_SLOT_BASE + ctx.Count * GenTypes.REPL_SLOT_SIZE @@ -1221,8 +1059,7 @@ novirtual class VarGenMixin: # ---- repl_perm_pool — 会话数据的永久池(跨片段存活) ---- def repl_perm_pool(self, trans: HT.Translator*) -> memhub.MemBuddy*: """宿主注入的 PermPool(ctx.Perm);无 ctx/未注入返回 None""" - if trans is None or trans.ReplCtx is None: - return None + if trans is None or trans.ReplCtx is None: return None return trans.ReplCtx.Perm # ---- repl_emit_result — 把本片段结果写入 ctx 结果区 ---- @@ -1241,37 +1078,30 @@ novirtual class VarGenMixin: STRUCT→ kind=4,result_a = 0(结构体值内联在槽里,本身没有地址) 宿主只按 (kind, result_a, result_b) 读,不需要知道槽内类型。 """ - if trans is None or ctx_val is None or val is None: - return 1 + if trans is None or ctx_val is None or val is None: return 1 pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder - if pool is None or builder is None: - return 1 + if pool is None or builder is None: return 1 i64_ty: mlirlite.LLVMType* = mlirlite.Int64(pool) zero64: mlirlite.Value* = mlirlite.const_int64(pool, 0) if tag == GenTypes.REPL_TY_INT: iv: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, val, i64_ty, node, trans) - if iv is None: - return 1 + if iv is None: return 1 if self._repl_store_res_i32(trans, ctx_val, GenTypes.REPL_RES_KIND_OFF, GenTypes.REPL_RES_INT) != 0: return 1 - if self._repl_store_res_i64(trans, ctx_val, GenTypes.REPL_RES_A_OFF, iv) != 0: - return 1 + if self._repl_store_res_i64(trans, ctx_val, GenTypes.REPL_RES_A_OFF, iv) != 0: return 1 return self._repl_store_res_i64(trans, ctx_val, GenTypes.REPL_RES_B_OFF, zero64) if tag == GenTypes.REPL_TY_FLOAT: dv: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, val, mlirlite.Double(pool), node, trans) - if dv is None: - return 1 + if dv is None: return 1 # double → i64 位模式(bitcast,不做数值转换):宿主按位重解释回 double dbits: mlirlite.Value* = mlirlite.build_bitcast(builder, dv, i64_ty) - if dbits is None: - return 1 + if dbits is None: return 1 if self._repl_store_res_i32(trans, ctx_val, GenTypes.REPL_RES_KIND_OFF, GenTypes.REPL_RES_FLOAT) != 0: return 1 - if self._repl_store_res_i64(trans, ctx_val, GenTypes.REPL_RES_A_OFF, dbits) != 0: - return 1 + if self._repl_store_res_i64(trans, ctx_val, GenTypes.REPL_RES_A_OFF, dbits) != 0: return 1 return self._repl_store_res_i64(trans, ctx_val, GenTypes.REPL_RES_B_OFF, zero64) if tag == GenTypes.REPL_TY_STR or tag == GenTypes.REPL_TY_PTR: i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) @@ -1279,20 +1109,16 @@ novirtual class VarGenMixin: if val.Ty is not None and self.Gen.ExprGenBase.is_ptr_type(val.Ty) != 0 and self.Gen.AssignGen._stg_ty_equal(pool, val.Ty, i8_ptr_ty) == 0: # 已是指向 i8 的指针(str/bytes/t.CPtr)时跳过——LLVM 拒绝同型 bitcast pv = mlirlite.build_bitcast(builder, val, i8_ptr_ty) - if pv is None: - return 1 + if pv is None: return 1 # 指针 → i64(ptrtoint):宿主按整数读回后再 inttoptr 成地址 pbits: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, pv, i64_ty, node, trans) - if pbits is None: - return 1 + if pbits is None: return 1 kind: int = GenTypes.REPL_RES_OBJ - if tag == GenTypes.REPL_TY_STR: - kind = GenTypes.REPL_RES_STR + if tag == GenTypes.REPL_TY_STR: kind = GenTypes.REPL_RES_STR if self._repl_store_res_i32(trans, ctx_val, GenTypes.REPL_RES_KIND_OFF, kind) != 0: return 1 - if self._repl_store_res_i64(trans, ctx_val, GenTypes.REPL_RES_A_OFF, pbits) != 0: - return 1 + if self._repl_store_res_i64(trans, ctx_val, GenTypes.REPL_RES_A_OFF, pbits) != 0: return 1 return self._repl_store_res_i64(trans, ctx_val, GenTypes.REPL_RES_B_OFF, zero64) if tag == GenTypes.REPL_TY_STRUCT: # 结构体值:内联在会话槽里,值本身没有地址 ⇒ 结果区只报"类别" @@ -1300,8 +1126,7 @@ novirtual class VarGenMixin: if self._repl_store_res_i32(trans, ctx_val, GenTypes.REPL_RES_KIND_OFF, GenTypes.REPL_RES_OBJ) != 0: return 1 - if self._repl_store_res_i64(trans, ctx_val, GenTypes.REPL_RES_A_OFF, zero64) != 0: - return 1 + if self._repl_store_res_i64(trans, ctx_val, GenTypes.REPL_RES_A_OFF, zero64) != 0: return 1 return self._repl_store_res_i64(trans, ctx_val, GenTypes.REPL_RES_B_OFF, zero64) return 1 @@ -1311,13 +1136,11 @@ novirtual class VarGenMixin: off: int, val: mlirlite.Value*) -> int: """把 i64 值写到 ctx 结果区的 off 偏移(0=成功)""" - if trans is None or ctx_val is None or val is None: - return 1 + if trans is None or ctx_val is None or val is None: return 1 pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder slot: mlirlite.Value* = self.repl_slot_ptr(pool, builder, ctx_val, off, mlirlite.Int64(pool)) - if slot is None: - return 1 + if slot is None: return 1 mlirlite.build_store(builder, val, slot) return 0 @@ -1326,18 +1149,14 @@ novirtual class VarGenMixin: off: int, val: int) -> int: """把 i32 常量写到 ctx 结果区的 off 偏移(kind / var_count 等,0=成功)""" - if trans is None or ctx_val is None: - return 1 + if trans is None or ctx_val is None: return 1 pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder - if pool is None or builder is None: - return 1 + if pool is None or builder is None: return 1 slot: mlirlite.Value* = self.repl_slot_ptr(pool, builder, ctx_val, off, mlirlite.Int32(pool)) - if slot is None: - return 1 + if slot is None: return 1 cv: mlirlite.Value* = mlirlite.const_int32(pool, val) - if cv is None: - return 1 + if cv is None: return 1 mlirlite.build_store(builder, cv, slot) return 0 @@ -1349,13 +1168,10 @@ novirtual class VarGenMixin: 返回 None 表示"不是会话变量",调用方继续原有查找/报错路径。 """ - if trans is None or trans.ReplCtx is None or name is None: - return None + if trans is None or trans.ReplCtx is None or name is None: return None entry: rawptr[GenTypes.ReplVarEntry] = self.repl_find_entry(trans.ReplCtx, name) - if entry is None: - return None - if self.repl_in_frag_scope(trans.SymTab) == 0: - return None + 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 = ...')", @@ -1371,8 +1187,7 @@ novirtual class VarGenMixin: "NameError") return None ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node) - if ctx_val is None: - return None + 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") @@ -1389,13 +1204,10 @@ novirtual class VarGenMixin: 就是该槽的地址:后续经该指针的读写直接作用于会话变量(地址同一性)。 未登记/未定型/不在片段函数本体返回 None,由调用方继续原有查找与报错路径。 """ - if trans is None or trans.ReplCtx is None or name is None: - return None + if trans is None or trans.ReplCtx is None or name is None: return None entry: rawptr[GenTypes.ReplVarEntry] = self.repl_find_entry(trans.ReplCtx, name) - if entry is None: - return None - if self.repl_in_frag_scope(trans.SymTab) == 0: - return None + 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)", @@ -1409,8 +1221,7 @@ novirtual class VarGenMixin: "NameError") return None ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node) - if ctx_val is None: - return None + 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") @@ -1429,8 +1240,7 @@ novirtual class VarGenMixin: 槽内一律"值本身"(标量/指针/≤16B 结构体值内联),无装箱间接层 ⇒ 槽地址即值地址(c.Addr 的地址同一性由此成立)。 """ - if trans is None or entry is None or ctx_val is None or rhs_val is None: - return 1 + if trans is None or entry is None or ctx_val is None or rhs_val is None: return 1 pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder slot_ty: mlirlite.LLVMType* = self.repl_slot_ty(pool, entry) @@ -1475,21 +1285,16 @@ novirtual class VarGenMixin: 作用域判据用 repl_in_frag_entry_scope(M3):被提升的会话函数体内不做 会话槽写入(那里 `y = 1` 是局部变量、形参同名遮蔽也走局部)——详见该谓词注释。 """ - if trans is None or trans.ReplCtx is None or name is None or rhs_val is None: - return 0 + if trans is None or trans.ReplCtx is None or name is None or rhs_val is None: return 0 entry: rawptr[GenTypes.ReplVarEntry] = self.repl_find_entry(trans.ReplCtx, name) - if entry is None: - return 0 - if self.repl_in_frag_entry_scope(trans) == 0: - return 0 + 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") return 1 - if self.repl_seal(trans, entry, rhs_val.Ty, rhs_node) != 0: - 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) - if ctx_val is None: - return 1 + if ctx_val is None: return 1 self.repl_store_slot(trans, entry, ctx_val, rhs_val, node) return 1 @@ -1506,13 +1311,10 @@ novirtual class VarGenMixin: 作用域判据用 repl_in_frag_entry_scope(M3):被提升的会话函数体内 `x: int = 1` 是局部声明(Python 语义),不占会话槽。 """ - if trans is None or trans.ReplCtx is None or name is None: - return 0 + if trans is None or trans.ReplCtx is None or name is None: return 0 entry: rawptr[GenTypes.ReplVarEntry] = self.repl_find_entry(trans.ReplCtx, name) - if entry is None: - return 0 - if self.repl_in_frag_entry_scope(trans) == 0: - return 0 + if entry is None: return 0 + if self.repl_in_frag_entry_scope(trans) == 0: return 0 pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder if annot_node is None: @@ -1528,8 +1330,7 @@ novirtual class VarGenMixin: f"(片段无 import;仅内建名 int/str/bytes/bool/float/double/char 等可解析)", "NameError") return 1 - if self.repl_seal(trans, entry, annot_ty, node) != 0: - return 1 + if self.repl_seal(trans, entry, annot_ty, node) != 0: return 1 if value_node is None: # 仅定型(x: int):不产生值;结果区本行由宿主清零 ⇒ 无结果 return 1 @@ -1544,8 +1345,7 @@ novirtual class VarGenMixin: self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的初值翻译失败", "TypeError") return 1 ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, node) - if ctx_val is None: - return 1 + if ctx_val is None: return 1 self.repl_store_slot(trans, entry, ctx_val, rhs_val, node) return 1 @@ -1560,13 +1360,10 @@ novirtual class VarGenMixin: 作用域判据用 repl_in_frag_entry_scope(M3):被提升的会话函数体内 `x += 1` 按 Python 局部语义处理(不写会话槽)。 """ - if trans is None or trans.ReplCtx is None or name is None: - return 0 + if trans is None or trans.ReplCtx is None or name is None: return 0 entry: rawptr[GenTypes.ReplVarEntry] = self.repl_find_entry(trans.ReplCtx, name) - if entry is None: - return 0 - if self.repl_in_frag_entry_scope(trans) == 0: - return 0 + if entry is None: return 0 + if self.repl_in_frag_entry_scope(trans) == 0: return 0 pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder if entry.TyTag == GenTypes.REPL_TY_STRUCT: @@ -1575,8 +1372,7 @@ novirtual class VarGenMixin: "TypeError") return 1 cur_val: mlirlite.Value* = self.repl_try_read(trans, name, node) - if cur_val is None: - return 1 + 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") @@ -1596,8 +1392,7 @@ novirtual class VarGenMixin: 非 REPL 模式不调用本函数(translate_expr_stmt 只在 REPL 分支调用), 故"表达式语句除调用外一律忽略"的原行为不变。 """ - if trans is None or trans.ReplCtx is None or value_node is None: - return 1 + if trans is None or trans.ReplCtx is None or value_node is None: return 1 pool: memhub.MemBuddy* = trans.Pool builder: mlirlite.IRBuilder* = trans._cur_builder val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, value_node, None, 0, trans) @@ -1605,8 +1400,7 @@ novirtual class VarGenMixin: self.Gen.TypeGenErr.fatal_error(value_node, "REPL: 表达式片段求值失败", "TypeError") return 1 ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, value_node) - if ctx_val is None: - return 1 + if ctx_val is None: return 1 # 类型分类用宿主的影子条目(不占会话槽、不进表):每次先复位为未定型 sh: rawptr[GenTypes.ReplVarEntry] = trans.ReplCtx.Scratch if sh is None: @@ -1616,6 +1410,5 @@ novirtual class VarGenMixin: sh.TyTag = 0 sh.Bits = 0 sh.TyName = None - if self.repl_seal(trans, sh, val.Ty, value_node) != 0: - return 1 + if self.repl_seal(trans, sh, val.Ty, value_node) != 0: return 1 return self.repl_emit_result(trans, ctx_val, val, sh.TyTag, sh.Bits, value_node) diff --git a/App/lib/core/IncludesScanner.vp b/App/lib/core/IncludesScanner.vp index a521eaf..2683898 100644 --- a/App/lib/core/IncludesScanner.vp +++ b/App/lib/core/IncludesScanner.vp @@ -117,8 +117,7 @@ def add_file_entry(result: ScanResult*, if inc_dir is not None: inc_len: sizet = string.strlen(inc_dir) inc_buf: str = stdlib.malloc(inc_len + 1) - if inc_buf is None: - return 1 + if inc_buf is None: return 1 string.strcpy(inc_buf, inc_dir) entry.IncDir = inc_buf @@ -178,28 +177,24 @@ def scan_directory_recursive(pool: memhub.MemBuddy*, result: ScanResult*, inc_dir: str) -> int: """递归扫描目录,收集 .vp/.py 文件(inc_dir 为所属 includes 根目录)""" - if pool is None or root_dir is None or result is None: - return 1 + if pool is None or root_dir is None or result is None: return 1 # 子目录递归失败计数(不静默忽略,汇总处 fail-fast 终止) subdir_failed: int = 0 # 构造搜索模式: root_dir/* root_len: sizet = string.strlen(root_dir) pattern: bytes = stdlib.malloc(root_len + 4) - if pattern is None: - return 1 + if pattern is None: return 1 viperlib.snprintf(pattern, root_len + 4, "%s/*", root_dir) # find_data 缓冲 +16 余量:TPV 的 WIN32_FIND_DATAA.__sizeof__() 小于 Windows 实际写入,越界写会破坏相邻堆块 fd_size_s: sizet = win32file.WIN32_FIND_DATAA.__sizeof__() find_data: rawptr[win32file.WIN32_FIND_DATAA] = stdlib.malloc(fd_size_s + 16) - if find_data is None: - return 1 + if find_data is None: return 1 string.memset(find_data, 0, fd_size_s + 16) handle: win32base.HANDLE = win32file.FindFirstFileA(pattern, find_data) - if handle == win32base.INVALID_HANDLE_VALUE: - return 1 + if handle == win32base.INVALID_HANDLE_VALUE: return 1 # 遍历所有文件和子目录 while True: @@ -211,15 +206,13 @@ def scan_directory_recursive(pool: memhub.MemBuddy*, fname1: char = fname[1] if fname1 == '\0': # "." - if win32file.FindNextFileA(handle, find_data) == 0: - break + if win32file.FindNextFileA(handle, find_data) == 0: break continue elif fname1 == '.': fname2: char = fname[2] if fname2 == '\0': # ".." - if win32file.FindNextFileA(handle, find_data) == 0: - break + if win32file.FindNextFileA(handle, find_data) == 0: break continue # 检查是否为目录 @@ -228,40 +221,32 @@ def scan_directory_recursive(pool: memhub.MemBuddy*, # 构造完整路径 fname_len: sizet = string.strlen(fname) full_path: bytes = Utils.JoinPath(root_dir, fname) - if full_path is None: - break + if full_path is None: break # 构造相对路径 prefix_len: sizet = 0 - if rel_prefix is not None: - prefix_len = string.strlen(rel_prefix) + if rel_prefix is not None: prefix_len = string.strlen(rel_prefix) rel_path: bytes = None - if rel_prefix is not None and prefix_len > 0: - rel_path = Utils.JoinPath(rel_prefix, fname) + if rel_prefix is not None and prefix_len > 0: rel_path = Utils.JoinPath(rel_prefix, fname) else: rel_path = stdlib.malloc(fname_len + 1) - if rel_path is None: - break + if rel_path is None: break string.strcpy(rel_path, fname) - if rel_path is None: - break + if rel_path is None: break if is_dir != 0: # 递归扫描子目录 - if scan_directory_recursive(pool, full_path, rel_path, result, inc_dir) != 0: - subdir_failed += 1 + if scan_directory_recursive(pool, full_path, rel_path, result, inc_dir) != 0: subdir_failed += 1 else: # 检查是否为 .vp 源文件(Viper 源仅 .vp,不再识别 .py) is_py: int = 0 - if Utils.is_vp_at(fname, 0, fname_len) != 0: - is_py = 1 + if Utils.is_vp_at(fname, 0, fname_len) != 0: is_py = 1 if is_py != 0: # 跳过 __pycache__ 目录下的文件 is_pycache: int = 0 if rel_prefix is not None: - if string.strcmp(rel_prefix, "__pycache__") == 0: - is_pycache = 1 + if string.strcmp(rel_prefix, "__pycache__") == 0: is_pycache = 1 if is_pycache == 0: # 计算 SHA1 @@ -269,16 +254,13 @@ def scan_directory_recursive(pool: memhub.MemBuddy*, 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") + else: VLogger.warning(f"SHA1 计算失败: {full_path}", "scan") # 继续搜索下一个文件 - if win32file.FindNextFileA(handle, find_data) == 0: - break + 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"子目录扫描失败 {subdir_failed} 个", "scan") return 0 @@ -289,30 +271,23 @@ def scan_directory_recursive(pool: memhub.MemBuddy*, def scan_includes(pool: memhub.MemBuddy*, includes_dirs: str) -> ScanResult*: """扫描 includes 目录(支持空格分隔的多目录),返回所有 .vp/.py 文件的扫描结果""" - if pool is None or includes_dirs is None: - return None + if pool is None or includes_dirs is None: return None result: ScanResult* = create_scan_result(pool) - if result is None: - return None + if result is None: return None # 解析空格分隔的多 includes 目录(如 "../../includes ./includes"),逐目录递归扫描合并 dirs_total: sizet = string.strlen(includes_dirs) d_i: sizet = 0 while d_i < dirs_total: - while d_i < dirs_total and includes_dirs[d_i] == ' ': - d_i += 1 - if d_i >= dirs_total: - break + while d_i < dirs_total and includes_dirs[d_i] == ' ': d_i += 1 + if d_i >= dirs_total: break d_start: sizet = d_i - while d_i < dirs_total and includes_dirs[d_i] != ' ': - d_i += 1 + while d_i < dirs_total and includes_dirs[d_i] != ' ': d_i += 1 d_len: sizet = d_i - d_start - if d_len == 0: - continue + 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("includes 目录分配失败,终止扫描", "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) @@ -327,16 +302,14 @@ def scan_includes(pool: memhub.MemBuddy*, def find_entry_by_module(result: ScanResult*, module_name: str) -> FileEntry*: """按模块名查找文件条目""" - if result is None or module_name is None: - return None + if result is None or module_name is None: return None entry_size: sizet = FileEntry.__sizeof__() for i in range(result.Count): entry_addr: uint64 = uint64(result.Entries) + i * entry_size entry: FileEntry* = (FileEntry*)(entry_addr) if entry is not None: if entry.ModuleName is not None: - if string.strcmp(entry.ModuleName, module_name) == 0: - return entry + if string.strcmp(entry.ModuleName, module_name) == 0: return entry return None @@ -351,8 +324,7 @@ def _PathExistsA(path: str) -> int: (约 592 字节,差距 >270 字节),会越界写坏相邻堆块(BFS 输出槽 0x2e 崩溃根因)。GetFileAttributesA 只返回属性值,无越界风险。 """ - if path is None: - return 0 + if path is None: return 0 attr: ULONG = win32file.GetFileAttributesA(path) if attr == 0xFFFFFFFF: # INVALID_FILE_ATTRIBUTES return 0 @@ -376,15 +348,13 @@ def _TryResolveModuleFile(inc_dir: str, rel_seg: bytes, rel_len: sizet, suffix: str, out_abs_path: t.CPtr, out_rel_path: t.CPtr, out_inc_dir: t.CPtr) -> int: - if inc_dir is None or rel_seg is None or suffix is None: - return 0 + if inc_dir is None or rel_seg is None or suffix is None: return 0 inc_len: sizet = string.strlen(inc_dir) suf_len: sizet = string.strlen(suffix) # 候选绝对路径: {inc}/{rel}{suffix}(手写拼接,避免 %. *s 精度修饰符) cand_len: sizet = inc_len + 1 + rel_len + suf_len cand: bytes = stdlib.malloc(cand_len + 1) - if cand is None: - return 0 + if cand is None: return 0 string.strcpy(cand, inc_dir) cand[inc_len] = '/' string.strncpy(cand + inc_len + 1, rel_seg, rel_len) @@ -418,13 +388,11 @@ def _TryResolveModuleFile(inc_dir: str, rel_seg: bytes, rel_len: sizet, if out_abs_path is not None: abs_slot: sizet* = (sizet*)(out_abs_path) abs_slot[0] = sizet(cand) - else: - stdlib.free(cand) + else: stdlib.free(cand) if out_rel_path is not None: rel_slot: sizet* = (sizet*)(out_rel_path) rel_slot[0] = sizet(rel_path) - else: - stdlib.free(rel_path) + else: stdlib.free(rel_path) if out_inc_dir is not None and inc_buf is not None: inc_slot: sizet* = (sizet*)(out_inc_dir) inc_slot[0] = sizet(inc_buf) @@ -451,22 +419,17 @@ def _TryResolveModuleFile(inc_dir: str, rel_seg: bytes, rel_len: sizet, def ResolveModuleToPath(includes_dirs: str, mod_name: str, out_abs_path: t.CPtr, out_rel_path: t.CPtr, out_inc_dir: t.CPtr) -> int: - if includes_dirs is None or mod_name is None: - return 1 + if includes_dirs is None or mod_name is None: return 1 mn_len: sizet = string.strlen(mod_name) - if mn_len == 0: - return 1 + if mn_len == 0: return 1 # mod_name → 相对路径段(. → /):ast.parser → ast/parser rel_seg: bytes = stdlib.malloc(mn_len + 1) - if rel_seg is None: - return 1 + if rel_seg is None: return 1 rel_len: sizet = 0 for mi in range(mn_len): ch_m: char = mod_name[mi] - if ch_m == '.': - rel_seg[rel_len] = '/' - else: - rel_seg[rel_len] = ch_m + if ch_m == '.': rel_seg[rel_len] = '/' + else: rel_seg[rel_len] = ch_m rel_len += 1 rel_seg[rel_len] = '\0' @@ -474,19 +437,14 @@ def ResolveModuleToPath(includes_dirs: str, mod_name: str, d_total: sizet = string.strlen(includes_dirs) d_i: sizet = 0 while d_i < d_total: - while d_i < d_total and includes_dirs[d_i] == ' ': - d_i += 1 - if d_i >= d_total: - break + while d_i < d_total and includes_dirs[d_i] == ' ': d_i += 1 + if d_i >= d_total: break d_start: sizet = d_i - while d_i < d_total and includes_dirs[d_i] != ' ': - d_i += 1 + while d_i < d_total and includes_dirs[d_i] != ' ': d_i += 1 d_len: sizet = d_i - d_start - if d_len == 0: - continue + if d_len == 0: continue inc_dir_buf: bytes = stdlib.malloc(d_len + 1) - if inc_dir_buf is None: - continue + if inc_dir_buf is None: continue string.strncpy(inc_dir_buf, includes_dirs + d_start, d_len) inc_dir_buf[d_len] = '\0' # 候选 1: {inc}/{rel}.vp(文件模块) @@ -500,9 +458,7 @@ def ResolveModuleToPath(includes_dirs: str, mod_name: str, out_abs_path, out_rel_path, out_inc_dir) != 0: found = 1 stdlib.free(inc_dir_buf) - if found != 0: - break + if found != 0: break stdlib.free(rel_seg) - if found != 0: - return 0 + if found != 0: return 0 return 1 diff --git a/App/lib/core/Repl.vp b/App/lib/core/Repl.vp index 586bae6..685877b 100644 --- a/App/lib/core/Repl.vp +++ b/App/lib/core/Repl.vp @@ -221,18 +221,14 @@ novirtual class ReplSigOut: # ============================================================ def ReplFindProject(Out: bytes, Cap: int, Diag: bytes, DiagCap: int) -> int: """cwd → exe 同目录 查找 repl.vpj:1=命中(写 Out),0=未命中(写 Diag)""" - if Out is None or Diag is None: - return 0 - if Cap < 64 or DiagCap < 64: - return 0 + if Out is None or Diag is None: return 0 + if Cap < 64 or DiagCap < 64: return 0 # 两个候选各用独立缓冲:未命中时两条路径都要进诊断文本 c1: bytes = stdlib.malloc(Cap) c2: bytes = stdlib.malloc(Cap) if c1 is None or c2 is None: - if c1 is not None: - stdlib.free(c1) - if c2 is not None: - stdlib.free(c2) + if c1 is not None: stdlib.free(c1) + if c2 is not None: stdlib.free(c2) return 0 c1[0] = 0 c2[0] = 0 @@ -249,8 +245,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 失败)") # ② exe 同目录/repl.vpj(GetModuleFileNameA(NULL) 取自身全路径) n_exe: ULONG = w32file.GetModuleFileNameA(None, c2, ULONG(Cap)) if n_exe > 0: @@ -276,8 +271,7 @@ 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 失败)") # 两处都没有:诊断文本(需要 --project + 两个已查位置 + 模板位置) viperlib.snprintf(Diag, DiagCap, " 已查找(1): %s\n" @@ -430,13 +424,11 @@ ReplIncClsMissing: int = 0 # 路径是否为"存在的普通文件"(GetFileAttributesA:只返回属性值,无输出缓冲、无越界风险) def _is_file(path: str) -> int: """1=存在且非目录;0=不存在/是目录/参数错误""" - if path is None: - return 0 + if path is None: return 0 attr: ULONG = w32file.GetFileAttributesA(path) if attr == 0xFFFFFFFF: # INVALID_FILE_ATTRIBUTES return 0 - if (attr & w32file.FILE_ATTRIBUTE_DIRECTORY) != 0: - return 0 + if (attr & w32file.FILE_ATTRIBUTE_DIRECTORY) != 0: return 0 return 1 @@ -463,22 +455,18 @@ def _is_file(path: str) -> int: def ReplFindHostImplib() -> int: """定位宿主 import lib(.dll.a):1=命中(写 ReplHostImplib),0=未找到""" global ReplHostImplib - if _perm_pool is None: - return 0 + if _perm_pool is None: return 0 ReplHostImplib = None exe_buf: bytes = _perm_pool.alloc(_REPL_PATH_CAP) cand: bytes = _perm_pool.alloc(_REPL_PATH_CAP) - if exe_buf is None or cand is None: - return 0 + if exe_buf is None or cand is None: return 0 exe_buf[0] = 0 cand[0] = 0 n_exe: ULONG = w32file.GetModuleFileNameA(None, exe_buf, ULONG(_REPL_PATH_CAP)) - if n_exe <= 0: - return 0 + if n_exe <= 0: return 0 el: int = int(n_exe) # 防御:截断时写入内容可能未 NUL 结尾(与 ReplFindProject 同口径) - if el >= _REPL_PATH_CAP: - el = _REPL_PATH_CAP - 1 + if el >= _REPL_PATH_CAP: el = _REPL_PATH_CAP - 1 exe_buf[el] = 0 # 拆目录/文件名:dlen = 目录前缀长度(含分隔符) dlen: int = 0 @@ -510,8 +498,7 @@ def _read_line(h: win32base.HANDLE, buf: bytes, cap: int) -> int: 剥离 CR(兼容 CRLF 输入),遇 LF 结束;缓冲区满时停止(余量留作下一行)。 """ - if buf is None or cap < 2: - return -1 + if buf is None or cap < 2: return -1 total: int = 0 bytes_read: ULONG = 0 ok: BOOL = 0 @@ -531,16 +518,14 @@ def _read_line(h: win32base.HANDLE, buf: bytes, cap: int) -> int: continue total += 1 buf[total] = 0 - if eof != 0 and total == 0: - return -1 + if eof != 0 and total == 0: return -1 return total # 统计顶层语句数(Module.children) def _count_top_stmts(tree: ast.AST*) -> int: """返回 Module 的顶层语句数(children 为空时为 0)。""" - if tree is None or tree.children is None: - return 0 + if tree is None or tree.children is None: return 0 stmts: list[ast.AST*]* = tree.children return int(len(stmts)) @@ -567,25 +552,18 @@ def _line_starts_block(line: str, n: int) -> int: 故把它纳入"进入续行"判据零误报面;这是 M3 会话函数能用 @decorator 的前提 (装饰器行不以 ':' 结尾,否则用户无法把装饰器连同 def 一起送进一个块)。 """ - if line is None or n <= 0: - return 0 + if line is None or n <= 0: return 0 s: int = 0 - while s < n and (line[s] == ' ' or line[s] == '\t'): - s += 1 - if s >= n: - return 0 - if line[s] == '@': - return 1 + while s < n and (line[s] == ' ' or line[s] == '\t'): s += 1 + if s >= n: return 0 + if line[s] == '@': return 1 i: int = n while i > 0: ch: char = line[i - 1] - if ch != ' ' and ch != '\t': - break + if ch != ' ' and ch != '\t': break i -= 1 - if i <= 0: - return 0 - if line[i - 1] == ':': - return 1 + if i <= 0: return 0 + if line[i - 1] == ':': return 1 return 0 @@ -593,8 +571,7 @@ def _line_starts_block(line: str, n: int) -> int: def _block_append(line: str, n: int) -> int: """把 n 字节行追加到会话块缓冲;0=成功,1=容量不足(此时缓冲内容未改)""" global ReplBlockLen - if ReplBlockBuf is None or line is None or n <= 0: - return 1 + if ReplBlockBuf is None or line is None or n <= 0: return 1 sep: int = 0 if ReplBlockLen > 0: sep = 1 # 行间 '\n' @@ -612,24 +589,21 @@ def _block_append(line: str, n: int) -> int: # ctx 头视图(int64 解释):宿主读写 magic/kind/result_a... def _ctx_head() -> rawptr[GenTypes.ReplResult]: """ctx 头视图;会话未初始化返回 None""" - if ReplCtxBuf is None: - return None + if ReplCtxBuf is None: return None return rawptr[GenTypes.ReplResult](ReplCtxBuf) # ctx 头视图(double 解释 result_a):回显浮点结果用 def _ctx_float_head() -> rawptr[ReplFloatView]: """ctx 头浮点视图;会话未初始化返回 None""" - if ReplCtxBuf is None: - return None + if ReplCtxBuf is None: return None return rawptr[ReplFloatView](ReplCtxBuf) # 结果回显:按 result_kind 读 ctx 结果区并打印 def _repl_echo_result(frag_name: str, res: rawptr[GenTypes.ReplResult]) -> int: """按 result_kind 回显本片段结果;0=已处理(含"无结果")""" - if frag_name is None or res is None: - return 1 + if frag_name is None or res is None: return 1 k: int = res.Kind if k == GenTypes.REPL_RES_NONE: # 声明类片段(如 `x: int`):本行无结果 @@ -639,8 +613,7 @@ def _repl_echo_result(frag_name: str, res: rawptr[GenTypes.ReplResult]) -> int: return 0 if k == GenTypes.REPL_RES_FLOAT: fv: rawptr[ReplFloatView] = _ctx_float_head() - if fv is None: - return 1 + if fv is None: return 1 stdio.printf("%s => %f\n", frag_name, fv.F) return 0 if k == GenTypes.REPL_RES_STR: @@ -676,12 +649,10 @@ def _repl_echo_result(frag_name: str, res: rawptr[GenTypes.ReplResult]) -> int: # 串深拷贝进 pool(调用方给池;池/串无效或分配失败返回 None) def _repl_str_dup(pool: memhub.MemBuddy*, s: str) -> str: """深拷贝 s 到 pool;失败返回 None""" - if pool is None or s is None: - return None + if pool is None or s is None: return None n: int = int(string.strlen(s)) b: str = pool.alloc(n + 1) - if b is None: - return None + if b is None: return None string.memcpy(b, s, sizet(n)) b[n] = 0 return b @@ -691,11 +662,9 @@ def _repl_str_dup(pool: memhub.MemBuddy*, s: str) -> str: def ReplInitSessionSha1() -> int: """0=成功;非 0=永久池/分配失败""" global ReplSessionSha1 - if _perm_pool is None: - return 1 + if _perm_pool is None: return 1 ReplSessionSha1 = _repl_str_dup(_perm_pool, GenTypes.REPL_SESSION_SHA1) - if ReplSessionSha1 is None: - return 1 + if ReplSessionSha1 is None: return 1 return 0 @@ -703,13 +672,11 @@ def ReplInitSessionSha1() -> int: def _repl_base_cdefine_find(name: str) -> int: """基线里按名查找 CDefine 条目下标;未命中返回 -1""" - if name is None or ReplBaseCDefineNames is None: - return -1 + if name is None or ReplBaseCDefineNames is None: return -1 i: int for i in range(ReplBaseCDefineCount): nm: str = rawptr(ReplBaseCDefineNames[i]) - if nm is not None and string.strcmp(nm, name) == 0: - return i + if nm is not None and string.strcmp(nm, name) == 0: return i return -1 @@ -720,21 +687,16 @@ def ReplBaselineRestore(pool: memhub.MemBuddy*) -> int: 回灌在 clear_* 之后、翻译之前调用 ⇒ 片段内的名字解析能同时看到 "会话基线(先前片段/先前 import 带进来的)∪ 本片段新增"。 """ - if pool is None or ReplBaseCDefineNames is None: - return 1 - if GenApi._g_gen is None: - return 1 + if pool is None or ReplBaseCDefineNames is None: return 1 + if GenApi._g_gen is None: return 1 i: int for i in range(ReplBaseCDefineCount): nm: str = rawptr(ReplBaseCDefineNames[i]) val: str = rawptr(ReplBaseCDefineValues[i]) kind: int = int(ReplBaseCDefineKinds[i]) - if nm is None or val is None: - continue - if kind == 0: - GenApi.register_cdefine_constant(pool, nm, int64(string.atoll(val))) - elif kind == 1: - GenApi.register_cdefine_double(pool, nm, string.atof(val)) + if nm is None or val is None: continue + if kind == 0: GenApi.register_cdefine_constant(pool, nm, int64(string.atoll(val))) + elif kind == 1: GenApi.register_cdefine_double(pool, nm, string.atof(val)) else: # 字符串 CDefine:GenApi 无同名壳,经 gen 单例直达(与 clear_cdefine_constants # 的壳同款调用形态) @@ -742,8 +704,7 @@ def ReplBaselineRestore(pool: memhub.MemBuddy*) -> int: for i in range(ReplBaseCTypedefCount): tn: str = rawptr(ReplBaseCTypedefNames[i]) tv: str = rawptr(ReplBaseCTypedefTypeStrs[i]) - if tn is None or tv is None: - continue + if tn is None or tv is None: continue GenApi.register_ctypedef(pool, tn, tv) return 0 @@ -755,8 +716,7 @@ def ReplBaselineCapture() -> int: 无需回滚内容;截断只是防御性的一致性保障)。新条目深拷贝进 PermPool。 """ global ReplBaseCDefineCount, ReplBaseCTypedefCount - if _perm_pool is None or GenApi._g_gen is None: - return 1 + if _perm_pool is None or GenApi._g_gen is None: return 1 cdef_names: list[str]* = GenApi._g_gen.TypeGenCDef.CDefineNames if cdef_names is not None: cdef_vals: list[str]* = GenApi._g_gen.TypeGenCDef.CDefineValues @@ -766,26 +726,18 @@ def ReplBaselineCapture() -> int: i: sizet for i in range(n): nm: str = cdef_names.get(i) - if nm is None: - continue - if _repl_base_cdefine_find(nm) >= 0: - continue - if ReplBaseCDefineCount >= _REPL_BASE_CDEFINE_MAX: - break + if nm is None: continue + if _repl_base_cdefine_find(nm) >= 0: continue + if ReplBaseCDefineCount >= _REPL_BASE_CDEFINE_MAX: break val: str = None - if cdef_vals is not None: - val = cdef_vals.get(i) - if val is None: - continue + if cdef_vals is not None: val = cdef_vals.get(i) + if val is None: continue kind: int = 0 - if cdef_str is not None and int(cdef_str.get(i)) == 1: - kind = 2 - elif cdef_dbl is not None and int(cdef_dbl.get(i)) == 1: - kind = 1 + if cdef_str is not None and int(cdef_str.get(i)) == 1: kind = 2 + elif cdef_dbl is not None and int(cdef_dbl.get(i)) == 1: kind = 1 nc: str = _repl_str_dup(_perm_pool, nm) vc: str = _repl_str_dup(_perm_pool, val) - if nc is None or vc is None: - continue + if nc is None or vc is None: continue j: int = ReplBaseCDefineCount ReplBaseCDefineNames[j] = sizet(nc) ReplBaseCDefineValues[j] = sizet(vc) @@ -798,10 +750,8 @@ def ReplBaselineCapture() -> int: i2: sizet for i2 in range(cn2): tn: str = ct_names.get(i2) - if tn is None: - continue - if ReplBaseCTypedefCount >= _REPL_BASE_CTYPEDEF_MAX: - break + if tn is None: continue + if ReplBaseCTypedefCount >= _REPL_BASE_CTYPEDEF_MAX: break dup_hit: int = 0 k: int for k in range(ReplBaseCTypedefCount): @@ -809,17 +759,13 @@ def ReplBaselineCapture() -> int: if ex is not None and string.strcmp(ex, tn) == 0: dup_hit = 1 break - if dup_hit != 0: - continue + if dup_hit != 0: continue tv: str = None - if ct_vals is not None: - tv = ct_vals.get(i2) - if tv is None: - continue + if ct_vals is not None: tv = ct_vals.get(i2) + if tv is None: continue tnc: str = _repl_str_dup(_perm_pool, tn) tvc: str = _repl_str_dup(_perm_pool, tv) - if tnc is None or tvc is None: - continue + if tnc is None or tvc is None: continue j2: int = ReplBaseCTypedefCount ReplBaseCTypedefNames[j2] = sizet(tnc) ReplBaseCTypedefTypeStrs[j2] = sizet(tvc) @@ -830,10 +776,8 @@ def ReplBaselineCapture() -> int: def ReplBaselineTruncate(cd_cnt: int, ct_cnt: int) -> None: """把基线水位截断回片段开始时的值(失败片段的增量不得进基线)""" global ReplBaseCDefineCount, ReplBaseCTypedefCount - if cd_cnt >= 0 and cd_cnt <= ReplBaseCDefineCount: - ReplBaseCDefineCount = cd_cnt - if ct_cnt >= 0 and ct_cnt <= ReplBaseCTypedefCount: - ReplBaseCTypedefCount = ct_cnt + if cd_cnt >= 0 and cd_cnt <= ReplBaseCDefineCount: ReplBaseCDefineCount = cd_cnt + if ct_cnt >= 0 and ct_cnt <= ReplBaseCTypedefCount: ReplBaseCTypedefCount = ct_cnt # ---- 片段 import lib:登记 / 追加到链接命令行 ---- @@ -841,13 +785,10 @@ def ReplBaselineTruncate(cd_cnt: int, ct_cnt: int) -> None: def ReplFragImplibRecord(implib_path: str) -> int: """登记一个片段 import lib(PermPool 深拷贝);1=已登记,0=未登记(上限/分配失败)""" global ReplFragImplibCount - if implib_path is None or ReplFragImplibs is None or _perm_pool is None: - return 0 - if ReplFragImplibCount >= _REPL_FRAG_IMPLIB_MAX: - return 0 + if implib_path is None or ReplFragImplibs is None or _perm_pool is None: return 0 + if ReplFragImplibCount >= _REPL_FRAG_IMPLIB_MAX: return 0 dup: str = _repl_str_dup(_perm_pool, implib_path) - if dup is None: - return 0 + if dup is None: return 0 ReplFragImplibs[ReplFragImplibCount] = sizet(dup) ReplFragImplibCount += 1 return 1 @@ -856,19 +797,15 @@ def ReplFragImplibRecord(implib_path: str) -> int: # 把已登记的全部片段 import lib 追加到命令缓冲(空格分隔); # 返回新的位置(-1 = 容量不足,调用方按"不带片段 import lib"重试也不可——直接报错) def _repl_cmd_append_implibs(cmd: bytes, cap: int, pos: int) -> int: - if cmd is None or ReplFragImplibs is None: - return pos + if cmd is None or ReplFragImplibs is None: return pos i: int for i in range(ReplFragImplibCount): p: str = rawptr(ReplFragImplibs[i]) - if p is None: - continue + if p is None: continue pos = _repl_cat_str(cmd, cap, pos, " ") - if pos < 0: - return -1 + if pos < 0: return -1 pos = _repl_cat_str(cmd, cap, pos, p) - if pos < 0: - return -1 + if pos < 0: return -1 return pos @@ -900,19 +837,14 @@ def ReplInitIncludesClasses(mb: memhub.MemBuddy*, longjmp 到已返回帧"会在提示符出现前把进程带走。 """ global ReplIncClsMods, ReplIncClsFail, ReplIncClsMissing - if mb is None or sr is None or vpi_dir is None or sr.Entries is None: - return 1 - if ReplJmpBuf is None or _perm_pool is None: - return 1 + if mb is None or sr is None or vpi_dir is None or sr.Entries is None: return 1 + if ReplJmpBuf is None or _perm_pool is None: return 1 n_mod: int = int(sr.Count) - if n_mod <= 0: - return 1 - if n_mod > _REPL_INC_CLS_MOD_MAX: - n_mod = _REPL_INC_CLS_MOD_MAX + if n_mod <= 0: return 1 + if n_mod > _REPL_INC_CLS_MOD_MAX: n_mod = _REPL_INC_CLS_MOD_MAX # 每模块状态(8 字节/槽,PermPool):0=未尝试/待重试、1=已完成(成功或确认不可用) st: sizet* = _perm_pool.alloc(_REPL_INC_CLS_MOD_MAX * 8) - if st is None: - return 1 + if st is None: return 1 string.memset(st, 0, _REPL_INC_CLS_MOD_MAX * 8) # 注入目标:临时 LLVM 模块 + 临时翻译器(只用其注解解析上下文;模块本身丢弃) # 结构体注册走永久分配(StdlibAlloc=1)⇒ 条目/字段/类型跨片段存活。 @@ -923,8 +855,7 @@ def ReplInitIncludesClasses(mb: memhub.MemBuddy*, GenApi.set_current_file_type(vpi_dir) tmp_mod: mlirlite.LLVMModule* = mlirlite.new_module(_perm_pool, _REPL_INC_MOD_NAME) tr_inc: rawptr[HandlesTranslator.Translator] = _perm_pool.alloc(HandlesTranslator.Translator.__sizeof__()) - if tmp_mod is None or tr_inc is None: - return 1 + if tmp_mod is None or tr_inc is None: return 1 tr_inc.__before_init__() tr_inc.__init__() # 给临时翻译器一套真状态(函数表/符号表/名集合缓冲区 + Pool):VpiReader 的 @@ -953,8 +884,7 @@ def ReplInitIncludesClasses(mb: memhub.MemBuddy*, pass_ok: int = 0 i: int for i in range(n_mod): - if int(st[i]) != 0: - continue + if int(st[i]) != 0: continue # 启动预算(每个模块一次取时;GetTickCount64 无系统调用开销): # 超预算即停手,剩余待注册模块留给片段 `import` 的按需路径。 if int(win32base.GetTickCount64() - budget_t0) > _REPL_INC_CLS_BUDGET_MS: @@ -987,8 +917,7 @@ def ReplInitIncludesClasses(mb: memhub.MemBuddy*, "会话中不可用(不影响其它模块;先按 project.vpj " "构建一次宿主可生成全部存根)\n", ent.Sha1) warn_left -= 1 - else: - warn_dropped += 1 + else: warn_dropped += 1 stdlib.free(vpi_path) mb.reset_to(vm) st[i] = sizet(1) @@ -1013,8 +942,7 @@ def ReplInitIncludesClasses(mb: memhub.MemBuddy*, stdio.printf("includes 类注册: 模块 %d 的 .vpi 注入中断" "(其类可能不完整;会话继续)\n", i) warn_left -= 1 - else: - warn_dropped += 1 + else: warn_dropped += 1 mb.reset_to(vm) continue ok_m: int = VpiReader.ParseVpiIntoModule(_perm_pool, tmp_mod, vpi_path, tr_inc) @@ -1028,20 +956,17 @@ def ReplInitIncludesClasses(mb: memhub.MemBuddy*, stdio.printf("includes 类注册: 模块 %s 的 .vpi 注入失败" "(该模块的类不完整/不可用;会话继续)\n", ent.Sha1) warn_left -= 1 - else: - warn_dropped += 1 + else: warn_dropped += 1 stdlib.free(vpi_path) mb.reset_to(vm) # 本遍没有任何模块成功 ⇒ 后续遍不会带来新信息(失败的模块留在待重试集里, # 但重试同样会失败;省下全部重试的解析开销) - if pass_ok == 0: - break + if pass_ok == 0: break # 汇总(聚合告警):逐模块告警已按上限截断,这里给出全部计数与未尝试模块数。 skip_cnt: int = 0 si: int for si in range(n_mod): - if int(st[si]) == 0: - skip_cnt += 1 + if int(st[si]) == 0: skip_cnt += 1 stdio.printf("includes 类: 已注册 %d 个模块的 vpi 类(失败 %d,缺存根 %d," "未尝试/待重试 %d,省略告警 %d)\n", ReplIncClsMods, ReplIncClsFail, ReplIncClsMissing, @@ -1071,25 +996,19 @@ def ReplInitSession() -> int: global ReplBaseCDefineCount, ReplBaseCTypedefNames, ReplBaseCTypedefTypeStrs global ReplBaseCTypedefCount, ReplSavedCDefineCount, ReplSavedCTypedefCount global ReplIncClsMods, ReplIncClsFail, ReplIncClsMissing - if _perm_pool is None: - return 1 + if _perm_pool is None: return 1 # ① %TEMP% 前缀(GetTempPathA 返回值含结尾反斜杠;0 表示失败) tmp_buf: bytes = _perm_pool.alloc(_REPL_TMP_CAP) - if tmp_buf is None: - return 1 + if tmp_buf is None: return 1 tmp_len: ULONG = w32file.GetTempPathA(_REPL_TMP_CAP, tmp_buf) - if tmp_len == 0: - return 1 - if int(tmp_len) >= _REPL_TMP_CAP: - return 1 + if tmp_len == 0: return 1 + if int(tmp_len) >= _REPL_TMP_CAP: return 1 # ② 会话目录:TransPyV_repl/(pid 隔离并发会话;路径统一用 '/') ReplTmpDir = _perm_pool.alloc(_REPL_PATH_CAP) - if ReplTmpDir is None: - return 1 + if ReplTmpDir is None: return 1 viperlib.snprintf(ReplTmpDir, _REPL_PATH_CAP, "%sTransPyV_repl/%u", tmp_buf, win32process.GetCurrentProcessId()) - if BuildPipeline.ensure_dir(ReplTmpDir) != 0: - return 1 + if BuildPipeline.ensure_dir(ReplTmpDir) != 0: return 1 # ③ 常驻缓冲(会话期存活,不按片段反复分配) ReplNameBuf = _perm_pool.alloc(_REPL_NAME_CAP) ReplSrcBuf = _perm_pool.alloc(_REPL_FRAG_SRC_CAP) @@ -1099,12 +1018,9 @@ def ReplInitSession() -> int: ReplBlockBuf = _perm_pool.alloc(_REPL_BLOCK_CAP) ReplBlockLen = 0 ReplInBlock = 0 - if ReplNameBuf is None or ReplSrcBuf is None or ReplSrcPath is None: - return 1 - if ReplIrBuf is None or ReplNeedleBuf is None: - return 1 - if ReplBlockBuf is None: - return 1 + if ReplNameBuf is None or ReplSrcBuf is None or ReplSrcPath is None: return 1 + if ReplIrBuf is None or ReplNeedleBuf is None: return 1 + if ReplBlockBuf is None: return 1 ReplBlockBuf[0] = 0 # ③' M3 常驻缓冲:提升源码 / 会话函数名表 / 签名 token scratch / 诊断与渲染缓冲 ReplLiftBuf = _perm_pool.alloc(_REPL_LIFT_CAP) @@ -1116,10 +1032,8 @@ def ReplInitSession() -> int: ReplMsgName = _perm_pool.alloc(_REPL_FN_NAME_MAX) ReplSigText = _perm_pool.alloc(_REPL_SIG_TEXT_CAP) ReplSigText2 = _perm_pool.alloc(_REPL_SIG_TEXT_CAP) - if ReplLiftBuf is None or ReplLiftNames is None or ReplSigTags is None or ReplSigBits is None or ReplSigResult is None: - return 1 - if ReplLineShow is None or ReplMsgName is None or ReplSigText is None or ReplSigText2 is None: - return 1 + if ReplLiftBuf is None or ReplLiftNames is None or ReplSigTags is None or ReplSigBits is None or ReplSigResult is None: return 1 + if ReplLineShow is None or ReplMsgName is None or ReplSigText is None or ReplSigText2 is None: return 1 ReplLiftBuf[0] = 0 ReplLiftNames[0] = 0 ReplLiftNameCount = 0 @@ -1127,23 +1041,19 @@ def ReplInitSession() -> int: ReplSavedFuncCount = 0 # ④ ctx 会话内存(片段首形参指向它):头 64B + 变量槽 64×16B + 函数指针槽 32×16B,全部清零 ReplCtxBuf = _perm_pool.alloc(_REPL_CTX_SIZE) - if ReplCtxBuf is None: - return 1 + if ReplCtxBuf is None: return 1 string.memset(ReplCtxBuf, 0, _REPL_CTX_SIZE) # ⑤ 会话变量表 + 影子条目(PermPool;条目名/结构体名由 Gen 侧深拷贝进同一池) entry_size: sizet = GenTypes.ReplVarEntry.__sizeof__() ReplVarTable = _perm_pool.alloc(entry_size * GenTypes.REPL_VAR_CAP) - if ReplVarTable is None: - return 1 + if ReplVarTable is None: return 1 string.memset(ReplVarTable, 0, entry_size * GenTypes.REPL_VAR_CAP) ReplScratch = _perm_pool.alloc(entry_size) - if ReplScratch is None: - return 1 + if ReplScratch is None: return 1 string.memset(ReplScratch, 0, entry_size) # 影子条目的名字(错误消息可读:"") repl_scratch_name: str = _perm_pool.alloc(8) - if repl_scratch_name is None: - return 1 + if repl_scratch_name is None: return 1 viperlib.snprintf(repl_scratch_name, 8, "%s", "") ReplScratch.Name = repl_scratch_name ReplScratch.TyName = None @@ -1154,17 +1064,14 @@ def ReplInitSession() -> int: # ⑤' 会话函数表(M3;PermPool,宿主写、Gen 只读)——条目数组清零 func_entry_size: sizet = GenTypes.ReplFuncEntry.__sizeof__() ReplFuncTable: rawptr[GenTypes.ReplFuncEntry] = _perm_pool.alloc(func_entry_size * GenTypes.REPL_FUNC_CAP) - if ReplFuncTable is None: - return 1 + if ReplFuncTable is None: return 1 string.memset(ReplFuncTable, 0, func_entry_size * GenTypes.REPL_FUNC_CAP) # ⑥ 会话上下文对象(Gen 侧唯一开关:trans.ReplCtx) ReplCtxObj = _perm_pool.alloc(GenTypes.ReplCtx.__sizeof__()) - if ReplCtxObj is None: - return 1 + if ReplCtxObj is None: return 1 string.memset(ReplCtxObj, 0, GenTypes.ReplCtx.__sizeof__()) ctx_param: str = _perm_pool.alloc(_REPL_NAME_CAP) - if ctx_param is None: - return 1 + if ctx_param is None: return 1 viperlib.snprintf(ctx_param, _REPL_NAME_CAP, "%s", GenTypes.REPL_CTX_PARAM) ReplCtxObj.Marker = GenTypes.REPL_CTX_MARKER ReplCtxObj.Table = ReplVarTable @@ -1181,8 +1088,7 @@ def ReplInitSession() -> int: ReplSavedFuncCount = 0 # ⑦ ctx 固定头:magic/version 由宿主写一次(片段只读约定,不校验) head: rawptr[GenTypes.ReplResult] = _ctx_head() - if head is None: - return 1 + if head is None: return 1 head.Magic = GenTypes.REPL_CTX_MAGIC head.Version = GenTypes.REPL_CTX_VERSION head.Kind = GenTypes.REPL_RES_NONE @@ -1192,18 +1098,15 @@ def ReplInitSession() -> int: head.VarCount = 0 head.LastFrag = 0 # ⑧ M4 常驻状态:会话 sha1 + 片段 import lib 表 + 会话基线(CDefine/CTypedef) - if ReplInitSessionSha1() != 0: - return 1 + if ReplInitSessionSha1() != 0: return 1 ReplFragImplibs = _perm_pool.alloc(_REPL_FRAG_IMPLIB_ARR_CAP) ReplBaseCDefineNames = _perm_pool.alloc(8 * _REPL_BASE_CDEFINE_MAX) ReplBaseCDefineValues = _perm_pool.alloc(8 * _REPL_BASE_CDEFINE_MAX) ReplBaseCDefineKinds = _perm_pool.alloc(8 * _REPL_BASE_CDEFINE_MAX) ReplBaseCTypedefNames = _perm_pool.alloc(8 * _REPL_BASE_CTYPEDEF_MAX) ReplBaseCTypedefTypeStrs = _perm_pool.alloc(8 * _REPL_BASE_CTYPEDEF_MAX) - if ReplFragImplibs is None or ReplBaseCDefineNames is None or ReplBaseCDefineValues is None or ReplBaseCDefineKinds is None: - return 1 - if ReplBaseCTypedefNames is None or ReplBaseCTypedefTypeStrs is None: - return 1 + if ReplFragImplibs is None or ReplBaseCDefineNames is None or ReplBaseCDefineValues is None or ReplBaseCDefineKinds is None: return 1 + if ReplBaseCTypedefNames is None or ReplBaseCTypedefTypeStrs is None: return 1 string.memset(ReplFragImplibs, 0, _REPL_FRAG_IMPLIB_ARR_CAP) string.memset(ReplBaseCDefineNames, 0, 8 * _REPL_BASE_CDEFINE_MAX) string.memset(ReplBaseCDefineValues, 0, 8 * _REPL_BASE_CDEFINE_MAX) @@ -1268,10 +1171,8 @@ def _repl_gen_includes_vpi(mb: memhub.MemBuddy*, reset_to:读文件/parse/generate 的瞬时分配不跨文件累积(对齐 Phase1 1b-pre)。 """ global ReplIncVpiNew, ReplIncVpiReuse, ReplIncVpiFail - if mb is None or sr is None or vpi_dir is None: - return -1 - if sr.Entries is None: - return -1 + if mb is None or sr is None or vpi_dir is None: return -1 + if sr.Entries is None: return -1 es: sizet = IncludesScanner.FileEntry.__sizeof__() dl: sizet = string.strlen(vpi_dir) n: int @@ -1322,8 +1223,7 @@ def _repl_gen_includes_vpi(mb: memhub.MemBuddy*, ReplIncVpiFail += 1 mb.reset_to(fm) continue - if bytes_read < _REPL_SRC_BUF_CAP: - src_buf[bytes_read] = 0 + if bytes_read < _REPL_SRC_BUF_CAP: src_buf[bytes_read] = 0 # 解析(AST 全部分配在本文件的 mb 窗口内) lx: ast.Lexer* = ast.new_lexer(mb) tree: ast.AST* = None @@ -1353,10 +1253,8 @@ def _repl_gen_includes_vpi(mb: memhub.MemBuddy*, pf.write(pyi_buf, pos) pf.close() ReplIncVpiNew += 1 - else: - ReplIncVpiFail += 1 - else: - ReplIncVpiFail += 1 + else: ReplIncVpiFail += 1 + else: ReplIncVpiFail += 1 stdlib.free(pyi_buf) stdlib.free(src_buf) stdlib.free(vpi_path) @@ -1375,8 +1273,7 @@ def ReplInitIncludes(mb: memhub.MemBuddy*) -> int: 故收尾不放在本函数内。 """ global ReplIncMods, ReplIncMs - if mb is None: - return 1 + 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)," @@ -1384,8 +1281,7 @@ def ReplInitIncludes(mb: memhub.MemBuddy*) -> int: return 1 # .vpi 目录与片段侧一致:优先工程临时目录,无工程配置时退回会话目录 vpi_dir: str = Config.TempDir - if vpi_dir is None: - vpi_dir = ReplTmpDir + if vpi_dir is None: vpi_dir = ReplTmpDir if vpi_dir is None: stdio.printf("REPL: 无可用 .vpi 目录(Config.TempDir 与会话目录均为空)," "跳过 includes 初始化\n") @@ -1432,8 +1328,7 @@ def ReplInitIncludes(mb: memhub.MemBuddy*) -> int: # 两遍预注册建),表内容与插入顺序不受影响 ⇒ 批处理逐字不变。 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 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") @@ -1497,13 +1392,10 @@ def ReplInitIncludes(mb: memhub.MemBuddy*) -> int: # 把一行(可能非 NUL 结尾)截断拷进会话缓冲,供 %s 打印 def _repl_show_line(p: bytes, n: int) -> str: """行片段 → 会话缓冲里的 NUL 结尾串(截断到 118 字节)""" - if ReplLineShow is None or p is None: - return "(?)" + if ReplLineShow is None or p is None: return "(?)" m: int = n - if m > 118: - m = 118 - if m < 0: - m = 0 + if m > 118: m = 118 + if m < 0: m = 0 string.memcpy(ReplLineShow, p, sizet(m)) ReplLineShow[m] = 0 return ReplLineShow @@ -1512,38 +1404,31 @@ def _repl_show_line(p: bytes, n: int) -> str: # 行长度(到 '\n' 或 NUL 为止) def _repl_line_len(p: bytes) -> int: n: int = 0 - while p[n] != '\n' and p[n] != 0: - n += 1 + while p[n] != '\n' and p[n] != 0: n += 1 return n # 前导空白字节数 def _repl_indent_len(p: bytes, n: int) -> int: i: int = 0 - while i < n and (p[i] == ' ' or p[i] == '\t'): - i += 1 + while i < n and (p[i] == ' ' or p[i] == '\t'): i += 1 return i # 在 [ind, n) 处是否以关键词 kw 开头(且 kw 后是空白) def _repl_line_has_kw(p: bytes, n: int, ind: int, kw: str) -> int: k: int = int(string.strlen(kw)) - if ind + k + 1 > n: - return 0 - if string.strncmp(p + ind, kw, sizet(k)) != 0: - return 0 + if ind + k + 1 > n: return 0 + if string.strncmp(p + ind, kw, sizet(k)) != 0: return 0 c: char = p[ind + k] - if c != ' ' and c != '\t': - return 0 + if c != ' ' and c != '\t': return 0 return 1 # 追加字节段到 dst(维护末尾 NUL);返回新长度,-1=容量不足 def _repl_cat(dst: bytes, cap: int, pos: int, src: bytes, n: int) -> int: - if dst is None or src is None or pos < 0 or n < 0: - return -1 - if pos + n + 1 > cap: - return -1 + if dst is None or src is None or pos < 0 or n < 0: return -1 + if pos + n + 1 > cap: return -1 string.memcpy(dst + pos, src, sizet(n)) pos += n dst[pos] = 0 @@ -1552,16 +1437,14 @@ def _repl_cat(dst: bytes, cap: int, pos: int, src: bytes, n: int) -> int: # 追加 NUL 结尾串到 dst;返回新长度,-1=容量不足 def _repl_cat_str(dst: bytes, cap: int, pos: int, s: str) -> int: - if s is None: - return pos + if s is None: return pos return _repl_cat(dst, cap, pos, s, int(string.strlen(s))) # 提升出的函数名入表(保留前缀检查 + 同片段查重 + 上限);0=成功,1=拒绝(已打印) def _repl_lift_add_name(name: str) -> int: global ReplLiftNameCount - if name is None or ReplLiftNames is None: - return 1 + if name is None or ReplLiftNames is None: return 1 # 保留前缀:片段入口函数名("__repl_frag_")是 Gen 侧判定"片段入口作用域"的 # 依据(会话变量的写路径只在该作用域生效),用户不得占用该前缀 pfx: str = GenTypes.REPL_ENTRY_PREFIX @@ -1587,20 +1470,16 @@ def _repl_lift_add_name(name: str) -> int: #("export def <名>(__repl_ctx__: bytes, <原形参表>) -> <原返回注解>:",其余逐字保留) # 名字写入 name_out(NUL 结尾)。返回 0=成功;1=规则拒绝(已打印);2=缓冲不足 def _repl_lift_def_header(line: bytes, n: int, name_out: bytes, name_cap: int) -> int: - if n < 5 or name_out is None or ReplLiftBuf is None: - return 1 + if n < 5 or name_out is None or ReplLiftBuf is None: return 1 p: int = 3 # 跳过 "def" - while p < n and (line[p] == ' ' or line[p] == '\t'): - p += 1 + while p < n and (line[p] == ' ' or line[p] == '\t'): p += 1 # 名字(标识符字符) ns: int = p while p < n: c: char = line[p] is_id: int = 0 - if (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z') or (c >= '0' and c <= '9') or c == '_': - is_id = 1 - if is_id == 0: - break + if (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z') or (c >= '0' and c <= '9') or c == '_': is_id = 1 + if is_id == 0: break p += 1 nlen: int = p - ns if nlen <= 0: @@ -1616,8 +1495,7 @@ def _repl_lift_def_header(line: bytes, n: int, name_out: bytes, name_cap: int) - if p < n and line[p] == '[': d: int = 0 while p < n: - if line[p] == '[': - d += 1 + if line[p] == '[': d += 1 elif line[p] == ']': d -= 1 if d == 0: @@ -1637,8 +1515,7 @@ def _repl_lift_def_header(line: bytes, n: int, name_out: bytes, name_cap: int) - q: int = lp while q < n: c2: char = line[q] - if c2 == '(': - d2 += 1 + if c2 == '(': d2 += 1 elif c2 == ')': d2 -= 1 if d2 == 0: @@ -1682,10 +1559,8 @@ def _repl_lift_def_header(line: bytes, n: int, name_out: bytes, name_cap: int) - pos: int = int(string.strlen(ReplLiftBuf)) pos = _repl_cat_str(ReplLiftBuf, _REPL_LIFT_CAP, pos, "export ") pos = _repl_cat(ReplLiftBuf, _REPL_LIFT_CAP, pos, line, lp + 1) - if empty != 0: - pos = _repl_cat_str(ReplLiftBuf, _REPL_LIFT_CAP, pos, "__repl_ctx__: bytes") - else: - pos = _repl_cat_str(ReplLiftBuf, _REPL_LIFT_CAP, pos, "__repl_ctx__: bytes, ") + if empty != 0: pos = _repl_cat_str(ReplLiftBuf, _REPL_LIFT_CAP, pos, "__repl_ctx__: bytes") + else: pos = _repl_cat_str(ReplLiftBuf, _REPL_LIFT_CAP, pos, "__repl_ctx__: bytes, ") 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: @@ -1699,8 +1574,7 @@ def _repl_lift_def_header(line: bytes, n: int, name_out: bytes, name_cap: int) - # 返回 0=成功;1=规则拒绝(已打印);2=缓冲不足。成功时 ReplWrapPos 更新为片段体末尾位置。 def _repl_split_body(body: bytes) -> int: global ReplWrapPos - if body is None or ReplLiftBuf is None or ReplSrcBuf is None: - return 2 + if body is None or ReplLiftBuf is None or ReplSrcBuf is None: return 2 total: int = int(string.strlen(body)) i: int = 0 pos: int = ReplWrapPos @@ -1712,16 +1586,14 @@ def _repl_split_body(body: bytes) -> int: n: int = _repl_line_len(body + i) ind: int = _repl_indent_len(body + i, n) blank: int = 0 - if ind >= n: - blank = 1 + if ind >= n: blank = 1 if in_lift != 0: if blank != 0: # 纯空白行:留在提升块内(函数体里的空行,对缩进无语义) lp0: int = int(string.strlen(ReplLiftBuf)) lp0 = _repl_cat(ReplLiftBuf, _REPL_LIFT_CAP, lp0, body + i, n) lp0 = _repl_cat_str(ReplLiftBuf, _REPL_LIFT_CAP, lp0, "\n") - if lp0 < 0: - return 2 + if lp0 < 0: return 2 i += n + 1 continue if ind > 0: @@ -1739,8 +1611,7 @@ def _repl_split_body(body: bytes) -> int: lp1: int = int(string.strlen(ReplLiftBuf)) lp1 = _repl_cat(ReplLiftBuf, _REPL_LIFT_CAP, lp1, body + i, n) lp1 = _repl_cat_str(ReplLiftBuf, _REPL_LIFT_CAP, lp1, "\n") - if lp1 < 0: - return 2 + if lp1 < 0: return 2 i += n + 1 continue # 顶格非空行 ⇒ 提升块结束,本行按"未进入提升"重新判定(不推进 i) @@ -1753,8 +1624,7 @@ def _repl_split_body(body: bytes) -> int: pos = _repl_cat_str(ReplSrcBuf, _REPL_FRAG_SRC_CAP, pos, " ") pos = _repl_cat(ReplSrcBuf, _REPL_FRAG_SRC_CAP, pos, body + i, n) pos = _repl_cat_str(ReplSrcBuf, _REPL_FRAG_SRC_CAP, pos, "\n") - if pos < 0: - return 2 + if pos < 0: return 2 i += n + 1 continue # 顶格非空行 @@ -1765,16 +1635,13 @@ def _repl_split_body(body: bytes) -> int: lp2: int = int(string.strlen(ReplLiftBuf)) lp2 = _repl_cat(ReplLiftBuf, _REPL_LIFT_CAP, lp2, body + i, n) lp2 = _repl_cat_str(ReplLiftBuf, _REPL_LIFT_CAP, lp2, "\n") - if lp2 < 0: - return 2 + if lp2 < 0: return 2 i += n + 1 continue if _repl_line_has_kw(body + i, n, 0, "def") != 0: rc_h: int = _repl_lift_def_header(body + i, n, name_buf, _REPL_FN_NAME_MAX) - if rc_h != 0: - return rc_h - if _repl_lift_add_name(name_buf) != 0: - return 1 + if rc_h != 0: return rc_h + if _repl_lift_add_name(name_buf) != 0: return 1 in_lift = 1 need_header = 0 in_body = 1 @@ -1787,8 +1654,7 @@ def _repl_split_body(body: bytes) -> int: pos = _repl_cat_str(ReplSrcBuf, _REPL_FRAG_SRC_CAP, pos, " ") pos = _repl_cat(ReplSrcBuf, _REPL_FRAG_SRC_CAP, pos, body + i, n) pos = _repl_cat_str(ReplSrcBuf, _REPL_FRAG_SRC_CAP, pos, "\n") - if pos < 0: - return 2 + if pos < 0: return 2 i += n + 1 if need_header != 0: stdio.printf("M3: 装饰器之后缺少 def 头行(片段末尾)\n") @@ -1800,10 +1666,8 @@ def _repl_split_body(body: bytes) -> int: # 多行块的包裹装配(提升 + 包裹):返回 0=成功;1=规则拒绝(已打印);2=缓冲不足 def _repl_build_frag_src_multi(name: str, body: bytes) -> int: global ReplWrapPos - if name is None or body is None: - return 2 - if ReplLiftBuf is None or ReplLiftNames is None or ReplSrcBuf is None: - return 2 + if name is None or body is None: return 2 + if ReplLiftBuf is None or ReplLiftNames is None or ReplSrcBuf is None: return 2 # 提升缓冲与名表水位已由调用方 _build_frag_src 每片段清零(单行路径也必须清零, # 故清零点在调用方而非此处);这里只负责装配 # 片段函数头(与单行模板同一形态);片段体随后逐行 4 空格 @@ -1812,18 +1676,15 @@ def _repl_build_frag_src_multi(name: str, body: bytes) -> int: name, GenTypes.REPL_CTX_PARAM) ReplWrapPos = int(string.strlen(ReplSrcBuf)) rc: int = _repl_split_body(body) - if rc != 0: - return rc + if rc != 0: return rc pos: int = ReplWrapPos pos = _repl_cat_str(ReplSrcBuf, _REPL_FRAG_SRC_CAP, pos, " return 0\n") - if pos < 0: - return 2 + if pos < 0: return 2 # 提升出的模块级 def 追加在片段入口函数之后(同为模块级,顺序无关) lift_len: int = int(string.strlen(ReplLiftBuf)) if lift_len > 0: pos = _repl_cat(ReplSrcBuf, _REPL_FRAG_SRC_CAP, pos, ReplLiftBuf, lift_len) - if pos < 0: - return 2 + if pos < 0: return 2 ReplWrapPos = pos return 0 @@ -1843,32 +1704,27 @@ def _repl_build_frag_src_multi(name: str, body: bytes) -> int: # 会话函数表按名查找(宿主侧;与 Gen 侧 repl_find_func_entry 同口径) def _repl_func_entry_find(name: str) -> rawptr[GenTypes.ReplFuncEntry]: """1=命中条目;None=未登记/表未建""" - if ReplCtxObj is None or ReplCtxObj.FuncTable is None or name is None: - return None + if ReplCtxObj is None or ReplCtxObj.FuncTable is None or name is None: return None es: sizet = GenTypes.ReplFuncEntry.__sizeof__() i: int for i in range(ReplCtxObj.FuncCount): e: rawptr[GenTypes.ReplFuncEntry] = rawptr[GenTypes.ReplFuncEntry](uint64(ReplCtxObj.FuncTable) + uint64(i) * uint64(es)) - if e.Name is not None and string.strcmp(e.Name, name) == 0: - return e + if e.Name is not None and string.strcmp(e.Name, name) == 0: return e return None # 提升出的第 idx 个函数名(NUL 结尾);越界返回 None def _repl_lift_name(idx: int) -> str: - if ReplLiftNames is None or idx < 0 or idx >= ReplLiftNameCount: - return None + if ReplLiftNames is None or idx < 0 or idx >= ReplLiftNameCount: return None return ReplLiftNames + idx * _REPL_FN_NAME_MAX # 深拷贝到 PermPool(会话表条目名等跨片段存活的数据) def _repl_perm_dup(s: str) -> str: - if s is None or _perm_pool is None: - return None + if s is None or _perm_pool is None: return None n: sizet = string.strlen(s) b: str = _perm_pool.alloc(n + 1) - if b is None: - return None + if b is None: return None string.strcpy(b, s) return b @@ -1876,20 +1732,17 @@ def _repl_perm_dup(s: str) -> str: # 签名解析结果 → 人类可读串("((int, str) -> int)"式;写进调用方缓冲) def _repl_sig_to_text(tag: int, bits: int, pc: int) -> str: """把 ReplSigResult + ReplSigTags/Bits 渲染成 "(P1, P2) -> R"(PermPool 缓冲)""" - if ReplSigText is None: - return "(?)" + if ReplSigText is None: return "(?)" pos: int = _repl_cat_str(ReplSigText, _REPL_SIG_TEXT_CAP, 0, "(") i: int = 0 while i < pc: - if i > 0: - pos = _repl_cat_str(ReplSigText, _REPL_SIG_TEXT_CAP, pos, ", ") + if i > 0: pos = _repl_cat_str(ReplSigText, _REPL_SIG_TEXT_CAP, pos, ", ") pos = _repl_cat_str(ReplSigText, _REPL_SIG_TEXT_CAP, pos, _repl_tag_text(int(ReplSigTags[i]), int(ReplSigBits[i]))) i += 1 pos = _repl_cat_str(ReplSigText, _REPL_SIG_TEXT_CAP, pos, ") -> ") pos = _repl_cat_str(ReplSigText, _REPL_SIG_TEXT_CAP, pos, _repl_tag_text(tag, bits)) - if pos < 0: - return "(?)" + if pos < 0: return "(?)" return ReplSigText @@ -1897,8 +1750,7 @@ def _repl_sig_to_text(tag: int, bits: int, pc: int) -> str: # ① EH 出参 ② 类型不受支持 ③ 首形参不是 ctx ④ 形参过多 ⑤ 模型里找不到函数 # ⑥ 重定义签名不一致 ⑦ 表容量不足。任一项失败 ⇒ 打印原因并返回 1(整片段不执行)。 def _repl_precheck_session_funcs(mod: mlirlite.LLVMModule*) -> int: - if ReplLiftNameCount <= 0: - return 0 + if ReplLiftNameCount <= 0: return 0 if ReplCtxObj is None or ReplCtxObj.FuncTable is None or ReplSigResult is None: stdio.printf("M3: 会话函数表/签名缓冲未初始化(会话初始化失败)\n") return 1 @@ -1906,8 +1758,7 @@ def _repl_precheck_session_funcs(mod: mlirlite.LLVMModule*) -> int: idx: int for idx in range(ReplLiftNameCount): nm: str = _repl_lift_name(idx) - if nm is None: - return 1 + if nm is None: return 1 rc: int = _repl_model_func_sig(mod, nm, ReplSigResult) if rc == 1: stdio.printf("M3: 定义片段模型里找不到函数 '%s'(提升未生效?)\n", nm) @@ -1943,8 +1794,7 @@ def _repl_precheck_session_funcs(mod: mlirlite.LLVMModule*) -> int: # 重定义:只允许**同签名**覆盖(换签名会让先前片段里已编好的调用点按旧 ABI # 调新代码 ⇒ 静默 UB)。签名一致时只更新槽内地址(段号随之刷新)。 sig_same: int = 1 - if old.RetTag != ReplSigResult.RetTag or old.RetBits != ReplSigResult.RetBits or old.ParamCount != ReplSigResult.ParamCount: - sig_same = 0 + if old.RetTag != ReplSigResult.RetTag or old.RetBits != ReplSigResult.RetBits or old.ParamCount != ReplSigResult.ParamCount: sig_same = 0 if sig_same != 0: pi: int = 0 while pi < old.ParamCount: @@ -1971,21 +1821,18 @@ def _repl_precheck_session_funcs(mod: mlirlite.LLVMModule*) -> int: # 已有条目的签名渲染(重定义冲突诊断用;写进 ReplSigText2) def _repl_entry_sig_text(e: rawptr[GenTypes.ReplFuncEntry]) -> str: - if e is None or ReplSigText2 is None: - return "(?)" + if e is None or ReplSigText2 is None: return "(?)" pos: int = _repl_cat_str(ReplSigText2, _REPL_SIG_TEXT_CAP, 0, "(") i: int = 0 while i < e.ParamCount: - if i > 0: - pos = _repl_cat_str(ReplSigText2, _REPL_SIG_TEXT_CAP, pos, ", ") + if i > 0: pos = _repl_cat_str(ReplSigText2, _REPL_SIG_TEXT_CAP, pos, ", ") pos = _repl_cat_str(ReplSigText2, _REPL_SIG_TEXT_CAP, pos, _repl_tag_text(int(e.ParamTags[i]), int(e.ParamBits[i]))) i += 1 pos = _repl_cat_str(ReplSigText2, _REPL_SIG_TEXT_CAP, pos, ") -> ") pos = _repl_cat_str(ReplSigText2, _REPL_SIG_TEXT_CAP, pos, _repl_tag_text(e.RetTag, e.RetBits)) - if pos < 0: - return "(?)" + if pos < 0: return "(?)" return ReplSigText2 @@ -1993,16 +1840,14 @@ def _repl_entry_sig_text(e: rawptr[GenTypes.ReplFuncEntry]) -> str: # 返回 0=成功;1=失败(已打印;调用方按 ReplSavedFuncCount 回滚表水位后放弃本片段) def _repl_register_session_funcs(h_lib: win32base.HANDLE, frag_no: int, mod: mlirlite.LLVMModule*) -> int: - if ReplLiftNameCount <= 0: - return 0 + if ReplLiftNameCount <= 0: return 0 if ReplCtxObj is None or ReplCtxObj.FuncTable is None or ReplCtxBuf is None: stdio.printf("M3: 会话函数表/ctx 未初始化\n") return 1 idx: int for idx in range(ReplLiftNameCount): nm: str = _repl_lift_name(idx) - if nm is None: - return 1 + if nm is None: return 1 # 导出符号名 = 裸名:定义端 `export def` ⇒ has_export=1 不加 SHA1 前缀 # (FuncGenDef.vp:482),且 REPL 片段 ModuleSha1=None 使 _mangle_name 原样返回 # (FuncGenBase.vp:264);-shared 未用 DEF 文件 ⇒ 全部符号自动进导出表(M1 实测) @@ -2067,60 +1912,42 @@ def _repl_register_session_funcs(h_lib: win32base.HANDLE, frag_no: int, # token → 显示名(仅用于日志/诊断) def _repl_tag_text(tag: int, bits: int) -> str: - if tag == GenTypes.REPL_TY_VOID: - return "void" + if tag == GenTypes.REPL_TY_VOID: return "void" if tag == GenTypes.REPL_TY_INT: - if bits == 1: - return "bool" - if bits == 8: - return "char" - if bits == 16: - return "int16" - if bits == 32: - return "int" - if bits == 64: - return "int64" + if bits == 1: return "bool" + if bits == 8: return "char" + if bits == 16: return "int16" + if bits == 32: return "int" + if bits == 64: return "int64" return "int?" if tag == GenTypes.REPL_TY_FLOAT: - if bits == 32: - return "float" - if bits == 64: - return "double" + if bits == 32: return "float" + if bits == 64: return "double" return "float?" - if tag == GenTypes.REPL_TY_STR: - return "str" + if tag == GenTypes.REPL_TY_STR: return "str" return "?" # LLVMType* → 打包 token(tag*1000 + bits);0=不支持。 # 支持集合与旧字符串版一致:i1/i8/i16/i32/i64、float/double、Ptr(Int8)(str/bytes/rawptr)。 def _repl_ty_ptr_token(ty: mlirlite.LLVMType*) -> int: - if ty is None: - return 0 + if ty is None: return 0 match ty: case mlirlite.LLVMType.Int(bits): - if bits == 1: - return GenTypes.REPL_TY_INT * 1000 + 1 - if bits == 8: - return GenTypes.REPL_TY_INT * 1000 + 8 - if bits == 16: - return GenTypes.REPL_TY_INT * 1000 + 16 - if bits == 32: - return GenTypes.REPL_TY_INT * 1000 + 32 - if bits == 64: - return GenTypes.REPL_TY_INT * 1000 + 64 + if bits == 1: return GenTypes.REPL_TY_INT * 1000 + 1 + if bits == 8: return GenTypes.REPL_TY_INT * 1000 + 8 + if bits == 16: return GenTypes.REPL_TY_INT * 1000 + 16 + if bits == 32: return GenTypes.REPL_TY_INT * 1000 + 32 + if bits == 64: return GenTypes.REPL_TY_INT * 1000 + 64 return 0 case mlirlite.LLVMType.Float(bits): - if bits == 32: - return GenTypes.REPL_TY_FLOAT * 1000 + 32 - if bits == 64: - return GenTypes.REPL_TY_FLOAT * 1000 + 64 + if bits == 32: return GenTypes.REPL_TY_FLOAT * 1000 + 32 + if bits == 64: return GenTypes.REPL_TY_FLOAT * 1000 + 64 return 0 case mlirlite.LLVMType.Ptr(pointee): match pointee: case mlirlite.LLVMType.Int(bits): - if bits == 8: - return GenTypes.REPL_TY_STR * 1000 + 8 + if bits == 8: return GenTypes.REPL_TY_STR * 1000 + 8 return 0 case _: return 0 @@ -2130,11 +1957,9 @@ def _repl_ty_ptr_token(ty: mlirlite.LLVMType*) -> int: # 诊断用:LLVMType* → 可读名(不支持的签名报错打印用);无名字返回 "(unsupported)" def _repl_ty_name(ty: mlirlite.LLVMType*) -> str: - if ty is None: - return "(none)" + if ty is None: return "(none)" nm: str = mlirlite.get_struct_name(ty) - if nm is not None: - return nm + if nm is not None: return nm return "(unsupported)" @@ -2145,8 +1970,7 @@ def _repl_ty_name(ty: mlirlite.LLVMType*) -> str: # 4=首形参不是 ctx;5=形参过多(> REPL_FUNC_PARAM_MAX) def _repl_model_func_sig(mod: mlirlite.LLVMModule*, name: str, out: rawptr[ReplSigOut]) -> int: - if name is None or out is None or mod is None: - return 1 + if name is None or out is None or mod is None: return 1 out.RetTag = GenTypes.REPL_TY_VOID out.RetBits = 0 out.ParamCount = 0 @@ -2154,13 +1978,11 @@ def _repl_model_func_sig(mod: mlirlite.LLVMModule*, name: str, out.Bad = 0 out.BadType = None fn: mlirlite.Function* = GenApi.find_func_in_module(mod, name) - if fn is None: - return 1 + if fn is None: return 1 # ① 返回类型 rt_ty: mlirlite.LLVMType* = mlirlite.function_get_ret_ty(fn) is_void: int = 0 - if rt_ty is None: - is_void = 1 + if rt_ty is None: is_void = 1 else: match rt_ty: case mlirlite.LLVMType.Void(): @@ -2186,21 +2008,17 @@ def _repl_model_func_sig(mod: mlirlite.LLVMModule*, name: str, p_nm: str = mlirlite.param_get_name(p_cur) # 参数名可能带/不带前导 '%'(打印端按需补 '%'),统一剥掉前导 '%' bare_nm: str = p_nm - if bare_nm is not None and bare_nm[0] == '%': - bare_nm = bare_nm + 1 + if bare_nm is not None and bare_nm[0] == '%': bare_nm = bare_nm + 1 if pi == 0: - if _repl_ty_ptr_token(p_ty) != GenTypes.REPL_TY_STR * 1000 + 8: - return 4 - if bare_nm is None or string.strcmp(bare_nm, GenTypes.REPL_CTX_PARAM) != 0: - return 4 + if _repl_ty_ptr_token(p_ty) != GenTypes.REPL_TY_STR * 1000 + 8: return 4 + if bare_nm is None or string.strcmp(bare_nm, GenTypes.REPL_CTX_PARAM) != 0: return 4 else: # EH 出参(raise 语义) if bare_nm is not None: if string.strcmp(bare_nm, "__eh_msg_out__") == 0 or string.strcmp(bare_nm, "__eh_code_out__") == 0: out.EHTag = 1 return 3 - if out.ParamCount >= GenTypes.REPL_FUNC_PARAM_MAX: - return 5 + if out.ParamCount >= GenTypes.REPL_FUNC_PARAM_MAX: return 5 tk: int = _repl_ty_ptr_token(p_ty) if tk == 0: out.Bad = 1 @@ -2230,8 +2048,7 @@ def _repl_model_func_sig(mod: mlirlite.LLVMModule*, name: str, def _build_frag_src(name: str, body: str) -> int: """装配包裹源码:单行=既有模板(逐字不变);多行=提升 + 逐行 4 空格""" global ReplLiftNameCount - if name is None or body is None: - return 2 + if name is None or body is None: return 2 # 每片段装配前清零上一片段留下的提升状态(名表水位 + 提升缓冲): # **单行路径不提升任何函数**,若不清零,上一片段提升出的名字会被本片段的 # 注册前校验(_repl_precheck_session_funcs 按 ReplLiftNameCount 逐名遍历)当成 @@ -2257,15 +2074,13 @@ def _build_frag_src(name: str, body: str) -> int: # 行为与改动前 run 里的单行逻辑逐语句一致(moved,非新增)。 def _exec_repl_src(mb: memhub.MemBuddy*, src: str) -> int: """解析 + 执行一份片段源码;0=已处理(含各类诊断已打印)""" - if src is None: - return 1 + if src is None: return 1 tree: ast.AST* = ast.parse(src, mb) if tree is None: 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 = "(未知)" + if em is None: em = "(未知)" stdio.printf("ParseError: 第 %d 行第 %d 列: %s\n", el, ec, em) return 0 if _count_top_stmts(tree) <= 0: @@ -2297,8 +2112,7 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: """片段 → DLL → 调用 → ctx 回显;0=成功""" global ReplFragFn, ReplFragNo, ReplSavedVarCount, ReplSavedFuncCount global ReplSavedCDefineCount, ReplSavedCTypedefCount - if mb is None or src is None: - return 1 + 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") return 1 @@ -2337,8 +2151,7 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: # (块内其余行由 ③ 的逐行装配统一加 4 空格、原相对缩进保留)。 body: str = src if body is not None: - while body[0] == ' ' or body[0] == '\t': - body = body + 1 + while body[0] == ' ' or body[0] == '\t': body = body + 1 # ③ 包裹模板:ctx 形参(bytes ⇒ i8*,名与 GenTypes.REPL_CTX_PARAM 同源) # export → 不加 SHA1 前缀(parser 改写返回注解为 |t.CExport; @@ -2368,8 +2181,7 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: # temp_dir 供依赖 .vpi 注入使用:优先用工程临时目录(含 includes 存根), # 无工程配置时退回本会话目录 vpi_dir: str = Config.TempDir - if vpi_dir is None: - vpi_dir = ReplTmpDir + if vpi_dir is None: vpi_dir = ReplTmpDir GenApi.set_temp_dir(vpi_dir) # CallGenBase.TempDir/TempDirLen(跨模块返回类型 .vpi/.text.ll 查找、CExport 判定 # 的目录)只由 SetTempDir 设置(CallGenBase.vp:824-828);批处理在 RunPhase1 开头 @@ -2404,15 +2216,13 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: # 量级 KB/片段)。不含 class 的片段仍用 mb,行为与 M2/M3 逐字一致。 parse_pool: memhub.MemBuddy* = mb if _perm_pool is not None: - if string.strstr(ReplSrcBuf, "class ") is not None: - parse_pool = _perm_pool + if string.strstr(ReplSrcBuf, "class ") is not None: parse_pool = _perm_pool tree: ast.AST* = ast.parse(ReplSrcBuf, parse_pool) if tree is None: 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 = "(未知)" + if em is None: em = "(未知)" stdio.printf("片段 %s: 包裹源码解析失败(第 %d 行第 %d 列: %s)\n", ReplNameBuf, el, ec, em) return 1 @@ -2448,8 +2258,7 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: needs_implib: int = 0 if ReplSessionSha1 is not None and ReplNeedleBuf is not None: viperlib.snprintf(ReplNeedleBuf, _REPL_NEEDLE_CAP, "@\"%s.", ReplSessionSha1) - if string.strstr(ReplIrBuf, ReplNeedleBuf) is not None: - needs_implib = 1 + if string.strstr(ReplIrBuf, ReplNeedleBuf) is not None: needs_implib = 1 # ⑧ 导出符号探针(单端 MLIR 文本):签名必须是 `(%__repl_ctx__: !llvm.ptr) -> i32`。 # MLIR 记法(includes/mlirlite/README.md §2.2):`llvm.func @名(%形参: 类型) -> 返回 {` @@ -2469,8 +2278,7 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: # 首形参非 ctx / 形参过多 / 模型里找不到函数 / 重定义签名不一致 / 表容量不足) # ⇒ 任一不通过就整片段不执行(无部分副作用;ctx 槽与表都不动)。 # ReplLiftNameCount 为 0(本片段没有提升任何会话函数)时立即返回 0。 - if _repl_precheck_session_funcs(tr.Module) != 0: - return 1 + if _repl_precheck_session_funcs(tr.Module) != 0: return 1 # ⑨ 写 .ll(复用 BuildPipeline:切片路径 + ensure_dir) ir_len: sizet = string.strlen(ReplIrBuf) @@ -2484,11 +2292,9 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: # ⑩ llc → .obj(复用既有机制;失败路径内部 VLogger.error 报 module/exit/cmd 后 longjmp) cc_cmd: str = Config.CompilerCmd - if cc_cmd is None: - cc_cmd = "llc" + if cc_cmd is None: cc_cmd = "llc" cc_flags: str = Config.CompilerFlags - if cc_flags is None: - cc_flags = "-filetype=obj -relocation-model=pic" + if cc_flags is None: cc_flags = "-filetype=obj -relocation-model=pic" if BuildPipeline.compile_ll_to_obj(ir_path, ReplTmpDir, ReplNameBuf, cc_cmd, cc_flags) != 0: # 走不到这里的 llc 失败:compile_ll_to_obj 内部 VLogger.error 已打印 module/exit/cmd # 并 longjmp(BuildPipeline.vp:373-375)。能返回非 0 的只有其内部"分配失败"分支 @@ -2505,8 +2311,7 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: stdio.printf("片段 %s: .obj/.dll 路径构造失败\n", ReplNameBuf) return 1 linker_cmd: str = Config.LinkerCmd - if linker_cmd is None: - linker_cmd = "clang++" + if linker_cmd is None: linker_cmd = "clang++" cmd: bytes = mb.alloc(_REPL_CMD_CAP) if cmd is None: stdio.printf("片段 %s: 命令行缓冲分配失败\n", ReplNameBuf) @@ -2593,16 +2398,14 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: # 的语句一律不执行(只留下已加载但未被引用的 DLL),且由水位回滚丢弃半批登记。 # 本片段内对同名函数的调用仍走直接调用(模块内有 define)⇒ 注册只服务后续片段。 if _repl_register_session_funcs(h_lib, n, tr.Module) != 0: - if ReplCtxObj is not None: - ReplCtxObj.FuncCount = ReplSavedFuncCount + if ReplCtxObj is not None: ReplCtxObj.FuncCount = ReplSavedFuncCount return 1 # ⑬ 调用前复位结果区(kind=none),并刷新 var_count/last_frag(供检视/调试); # 存入 t.Callable 槽并间接调用(函数地址必须存活到调用之后,故不 FreeLibrary: # 会话模型下模块常驻,供后续片段复用) head: rawptr[GenTypes.ReplResult] = _ctx_head() - if head is None: - return 1 + if head is None: return 1 head.Kind = GenTypes.REPL_RES_NONE head.VarCount = ReplCtxObj.Count head.LastFrag = n @@ -2614,8 +2417,7 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int: if _repl_echo_result(ReplNameBuf, head) != 0: stdio.printf("片段 %s: 结果区读取失败\n", ReplNameBuf) return 1 - if r_rc != 0: - stdio.printf("片段 %s: 片段返回非零状态码 %d\n", ReplNameBuf, r_rc) + if r_rc != 0: stdio.printf("片段 %s: 片段返回非零状态码 %d\n", ReplNameBuf, r_rc) # ⑭' M4:片段**成功** ⇒ 把本片段新增的 CDefine/CTypedef 条目并入会话基线。 # 失败路径(早返回 / longjmp)不执行 ⇒ 基线天然不含失败片段的半成品; # 截断(ReplBaselineTruncate)只是水位一致性的防御性保障。 @@ -2664,8 +2466,7 @@ def run(mb: memhub.MemBuddy*) -> int: stdio.fflush(None) ReplJmpBuf = None VLogger.clear_repl_jmpbuf() - if lg is not None: - lg.set_jit_flag(False) + if lg is not None: lg.set_jit_flag(False) return 1 # 会话初始化:临时目录 + 常驻缓冲 + ctx(均 PermPool,见 ReplInitSession) @@ -2673,8 +2474,7 @@ def run(mb: memhub.MemBuddy*) -> int: stdio.printf("REPL: 会话初始化失败(临时目录/常驻缓冲/ctx)\n") ReplJmpBuf = None VLogger.clear_repl_jmpbuf() - if lg is not None: - lg.set_jit_flag(False) + if lg is not None: lg.set_jit_flag(False) return 1 h_in: win32base.HANDLE = w32file.GetStdHandle(w32file.STD_INPUT_HANDLE) @@ -2683,8 +2483,7 @@ def run(mb: memhub.MemBuddy*) -> int: stdio.printf("REPL: 行缓冲分配失败\n") ReplJmpBuf = None VLogger.clear_repl_jmpbuf() - if lg is not None: - lg.set_jit_flag(False) + if lg is not None: lg.set_jit_flag(False) return 1 stdio.printf("TransPyV REPL (M2/M3/M4) - 会话变量 + 会话函数(跨片段)+ ctx 回传结果;\n") @@ -2770,10 +2569,8 @@ def run(mb: memhub.MemBuddy*) -> int: ReplBlockLen = 0 while 1: # 提示符:续行 "... "、正常 ">>> "(与既有 ">>> " 同一打印点、同一刷新时机) - if ReplInBlock != 0: - stdio.printf("... ") - else: - stdio.printf(">>> ") + if ReplInBlock != 0: stdio.printf("... ") + else: stdio.printf(">>> ") stdio.fflush(None) n: int = _read_line(h_in, line, _REPL_LINE_CAP) eof_hit: int = 0 @@ -2797,14 +2594,12 @@ def run(mb: memhub.MemBuddy*) -> int: # M4:会话基线(CDefine/CTypedef)水位回滚(与上面的表水位同思路) ReplBaselineTruncate(ReplSavedCDefineCount, ReplSavedCTypedefCount) mb.reset_to(mark) - if eof_hit != 0: - break + if eof_hit != 0: break continue if eof_hit != 0: # EOF 结束:续行中且缓冲非空 ⇒ 先把已缓存块执行掉(等价空行终止); # 否则走既有退出路径(打印换行后退出) - if ReplInBlock != 0 and ReplBlockLen > 0: - _exec_repl_src(mb, ReplBlockBuf) + if ReplInBlock != 0 and ReplBlockLen > 0: _exec_repl_src(mb, ReplBlockBuf) ReplInBlock = 0 ReplBlockLen = 0 mb.reset_to(mark) @@ -2813,8 +2608,7 @@ def run(mb: memhub.MemBuddy*) -> int: if ReplInBlock != 0: if n == 0: # 空行结束续行:整块作为**一个**片段执行一次;块内错误只打印、会话存活 - if ReplBlockLen > 0: - _exec_repl_src(mb, ReplBlockBuf) + if ReplBlockLen > 0: _exec_repl_src(mb, ReplBlockBuf) ReplInBlock = 0 ReplBlockLen = 0 mb.reset_to(mark) @@ -2847,6 +2641,5 @@ def run(mb: memhub.MemBuddy*) -> int: # 会话结束才清空恢复点:中途从不清(保证流水线全程可 longjmp) ReplJmpBuf = None VLogger.clear_repl_jmpbuf() - if lg is not None: - lg.set_jit_flag(False) + if lg is not None: lg.set_jit_flag(False) return 0 diff --git a/App/lib/core/VLogger.vp b/App/lib/core/VLogger.vp index f8ba6fc..64b32ff 100644 --- a/App/lib/core/VLogger.vp +++ b/App/lib/core/VLogger.vp @@ -107,8 +107,7 @@ novirtual class Logger: return 0 def _reset_color(self) -> int: - if self._use_color: - return w32cmd.SetConsoleTextAttribute(self._console_handle, FOREGROUND_WHITE) + if self._use_color: return w32cmd.SetConsoleTextAttribute(self._console_handle, FOREGROUND_WHITE) return 0 # ============================================================ @@ -126,8 +125,7 @@ novirtual class Logger: stdio.printf("%s", level_str) self._reset_color() # category 可选 - if category is not None and category[0] != 0: - stdio.printf(" [%s]", category) + if category is not None and category[0] != 0: stdio.printf(" [%s]", category) stdio.printf(": %s\n", msg) return 0 @@ -185,10 +183,8 @@ novirtual class Logger: 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) + 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) self._reset_color() return 0 @@ -200,10 +196,8 @@ novirtual class Logger: 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) + 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) self._reset_color() return 0 diff --git a/App/lib/core/builtin/ViperBuild.vp b/App/lib/core/builtin/ViperBuild.vp index 37003cb..8b0ffad 100644 --- a/App/lib/core/builtin/ViperBuild.vp +++ b/App/lib/core/builtin/ViperBuild.vp @@ -113,41 +113,33 @@ _applied: int = 0 # ============================================================ def _DupStd(s: str) -> str: """stdlib.malloc 深拷贝(跨 reset_to 存活)""" - if s is None: - return None + if s is None: return None n: sizet = string.strlen(s) buf: str = stdlib.malloc(n + 1) - if buf is None: - return None + if buf is None: return None string.strcpy(buf, s) return buf def _DupScratch(s: str) -> str: """scratch 池深拷贝(不受主池 reset_to 影响)""" - if s is None or _scratch is None: - return None + if s is None or _scratch is None: return None n: sizet = string.strlen(s) buf: str = _scratch.alloc(n + 1) - if buf is None: - return None + if buf is None: return None string.strcpy(buf, s) return buf def _Join2(a: str, b: str) -> str: """a + "/" + b(a 为空返回 b)""" - if a is None: - return b - if b is None: - return a + if a is None: return b + if b is None: return a al: sizet = string.strlen(a) - if al == 0: - return b + if al == 0: return b bl: sizet = string.strlen(b) buf: str = stdlib.malloc(al + 1 + bl + 1) - if buf is None: - return None + if buf is None: return None string.strcpy(buf, a) buf[al] = '/' string.strcpy(buf + al + 1, b) @@ -156,8 +148,7 @@ def _Join2(a: str, b: str) -> str: def _DirOf(path: str) -> str: """返回 path 的目录(不含结尾分隔符);无分隔符返回 stdlib 分配的 """"" - if path is None: - return None + if path is None: return None n: sizet = string.strlen(path) i: sizet = n while i > 0: @@ -165,8 +156,7 @@ def _DirOf(path: str) -> str: ch: char = path[i] if ch == '/' or ch == '\\': buf: str = stdlib.malloc(i + 1) - if buf is None: - return None + if buf is None: return None string.strncpy(buf, path, i) buf[i] = '\0' return buf @@ -175,28 +165,23 @@ def _DirOf(path: str) -> str: def _BaseNameOf(path: str) -> str: """返回 path 的文件名(含扩展名)""" - if path is None: - return None + if path is None: return None n: sizet = string.strlen(path) start: sizet = 0 i: sizet = 0 while i < n: ch: char = path[i] - if ch == '/' or ch == '\\': - start = i + 1 + if ch == '/' or ch == '\\': start = i + 1 i += 1 return _DupStd(path + start) def _IsDir(path: str) -> int: """路径是否为已存在目录(1=是)""" - if path is None: - return 0 + if path is None: return 0 attr: ULONG = win32file.GetFileAttributesA(path) - if attr == 0xFFFFFFFF: - return 0 - if (attr & win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: - return 1 + if attr == 0xFFFFFFFF: return 0 + if (attr & win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: return 1 return 0 @@ -207,24 +192,16 @@ def _HasPrefix(s: str, prefix: str) -> int: 因写法差异被判成"入口不在 source 之下";prefix 为 "." 时(入口是裸文件名, source 规整成当前目录)恒真。 """ - if s is None: - return 0 - if prefix is None: - return 1 - if string.strcmp(prefix, ".") == 0: - return 1 - if string.strncmp(s, "./", 2) == 0: - s = s + 2 - if string.strncmp(prefix, "./", 2) == 0: - prefix = prefix + 2 + if s is None: return 0 + if prefix is None: return 1 + if string.strcmp(prefix, ".") == 0: return 1 + if string.strncmp(s, "./", 2) == 0: s = s + 2 + if string.strncmp(prefix, "./", 2) == 0: prefix = prefix + 2 pl: sizet = string.strlen(prefix) - if pl == 0: - return 1 + if pl == 0: return 1 sl: sizet = string.strlen(s) - if sl < pl: - return 0 - if string.strncmp(s, prefix, pl) == 0: - return 1 + if sl < pl: return 0 + if string.strncmp(s, prefix, pl) == 0: return 1 return 0 @@ -233,15 +210,13 @@ def _HasPrefix(s: str, prefix: str) -> int: # ============================================================ def _FindInList(names: list[str]*, name: str) -> int: """在 names 中线性查找 name,返回下标;未找到返回 -1""" - if names is None or name is None: - return -1 + if names is None or name is None: return -1 n: sizet = names.__len__() i: sizet = 0 while i < n: s: str = names.get(i) if s is not None: - if string.strcmp(s, name) == 0: - return int(i) + if string.strcmp(s, name) == 0: return int(i) i += 1 return -1 @@ -250,11 +225,9 @@ def _LookupStrConst(name: str) -> int: """名字 → 字符串常量(写 _g_out_str);0=失败""" global _g_out_str idx: int = _FindInList(_f_str_names, name) - if idx < 0: - return 0 + if idx < 0: return 0 v: str = _f_str_vals.get(sizet(idx)) - if v is None: - return 0 + if v is None: return 0 _g_out_str = v return 1 @@ -262,28 +235,23 @@ def _LookupStrConst(name: str) -> int: def _LookupListConst(name: str, out: list[str]*) -> int: """名字 → 列表常量(按 VB_SEP 拆分后写入 out);0=失败""" idx: int = _FindInList(_f_list_names, name) - if idx < 0: - return 0 + if idx < 0: return 0 v: str = _f_list_vals.get(sizet(idx)) - if v is None: - return 0 + if v is None: return 0 return _SplitInto(out, v) def _SplitInto(out: list[str]*, joined: str) -> int: """把 VB_SEP_CODE 连接的串拆成元素写入 out(空串表示空列表)""" - if out is None or joined is None: - return 0 + if out is None or joined is None: return 0 n: sizet = string.strlen(joined) - if n == 0: - return 1 + if n == 0: return 1 start: sizet = 0 i: sizet = 0 while i <= n: if i == n or joined[i] == char(VB_SEP_CODE): seg: str = stdlib.malloc(i - start + 1) - if seg is None: - return 0 + if seg is None: return 0 string.strncpy(seg, joined + start, i - start) seg[i - start] = '\0' out.append(_DupScratch(seg)) @@ -295,24 +263,19 @@ def _SplitInto(out: list[str]*, joined: str) -> int: def _JoinSep(lst: list[str]*) -> str: """list[str] → VB_SEP_CODE 连接串(池分配;空列表返回 None)""" - if lst is None: - return None + if lst is None: return None n: sizet = lst.__len__() - if n == 0: - return None + if n == 0: return None # 先测总长 total: sizet = 0 i: sizet = 0 while i < n: s: str = lst.get(i) - if s is not None: - total += string.strlen(s) + 1 + if s is not None: total += string.strlen(s) + 1 i += 1 - if total == 0: - return None + if total == 0: return None buf: str = _scratch.alloc(total + 1) - if buf is None: - return None + if buf is None: return None pos: sizet = 0 i = 0 while i < n: @@ -331,23 +294,18 @@ def _JoinSep(lst: list[str]*) -> str: def _JoinSpace(lst: list[str]*) -> str: """list[str] → 空格连接串(stdlib 分配;空列表返回 None)""" - if lst is None: - return None + if lst is None: return None n: sizet = lst.__len__() - if n == 0: - return None + if n == 0: return None total: sizet = 0 i: sizet = 0 while i < n: s: str = lst.get(i) - if s is not None: - total += string.strlen(s) + 1 + if s is not None: total += string.strlen(s) + 1 i += 1 - if total == 0: - return None + if total == 0: return None buf: str = stdlib.malloc(total + 1) - if buf is None: - return None + if buf is None: return None pos: sizet = 0 i = 0 while i < n: @@ -366,11 +324,9 @@ def _JoinSpace(lst: list[str]*) -> str: def _FirstSpaceTok(joined: str) -> str: """取空格分隔串的首个 token(stdlib 分配);空串/None 返回 None""" - if joined is None: - return None + if joined is None: return None n: sizet = string.strlen(joined) - if n == 0: - return None + if n == 0: return None sp: sizet = n i: sizet = 0 while i < n: @@ -379,8 +335,7 @@ def _FirstSpaceTok(joined: str) -> str: break i += 1 seg: str = stdlib.malloc(sp + 1) - if seg is None: - return None + if seg is None: return None string.strncpy(seg, joined, sp) seg[sp] = '\0' return seg @@ -396,29 +351,23 @@ def _EvalStr(node: ast.AST*) -> int: `+` 拼接(左/右递归)。 """ global _g_out_str - if node is None: - return 0 + if node is None: return 0 k: int = node.kind() if k == ast.ASTKind.Constant: cn: ast.Constant* = ast.Constant*(node) - if cn is None or cn.const_kind != ast.CONST_STR: - return 0 + if cn is None or cn.const_kind != ast.CONST_STR: return 0 _g_out_str = cn.str_val return 1 if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) - if nm is None or nm.id is None: - return 0 + if nm is None or nm.id is None: return 0 return _LookupStrConst(nm.id) if k == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(node) - if bop is None or bop.op != ast.OpKind.Add: - return 0 - if _EvalStr(bop.left) == 0: - return 0 + if bop is None or bop.op != ast.OpKind.Add: return 0 + if _EvalStr(bop.left) == 0: return 0 lv: str = _g_out_str - if _EvalStr(bop.right) == 0: - return 0 + if _EvalStr(bop.right) == 0: return 0 rv: str = _g_out_str _g_out_str = _ConcatStd(lv, rv) return 1 @@ -427,15 +376,12 @@ def _EvalStr(node: ast.AST*) -> int: def _ConcatStd(a: str, b: str) -> str: """字符串拼接(stdlib 分配)""" - if a is None: - return b - if b is None: - return a + if a is None: return b + if b is None: return a al: sizet = string.strlen(a) bl: sizet = string.strlen(b) buf: str = stdlib.malloc(al + bl + 1) - if buf is None: - return None + if buf is None: return None string.strcpy(buf, a) string.strcpy(buf + al, b) return buf @@ -447,59 +393,45 @@ def _EvalList(node: ast.AST*, out: list[str]*) -> int: 支持:list 字面量(元素为 str 常量表达式)、`*名字` 展开(引用 list 常量)、 `+` 拼接(左/右递归)。 """ - if node is None or out is None: - return 0 + if node is None or out is None: return 0 k: int = node.kind() if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) - if nm is None or nm.id is None: - return 0 + if nm is None or nm.id is None: return 0 return _LookupListConst(nm.id, out) if k == ast.ASTKind.List: lst: ast.List* = ast.List*(node) - if lst is None or lst.elts is None: - return 0 + if lst is None or lst.elts is None: return 0 n: sizet = lst.elts.__len__() i: sizet = 0 while i < n: e: ast.AST* = lst.elts.get(i) - if e is None: - return 0 + if e is None: return 0 if e.kind() == ast.ASTKind.Starred: st: ast.Starred* = ast.Starred*(e) - if st is None or st.value is None: - return 0 - if _EvalList(st.value, out) == 0: - return 0 + if st is None or st.value is None: return 0 + if _EvalList(st.value, out) == 0: return 0 else: - if _EvalStr(e) == 0: - return 0 + if _EvalStr(e) == 0: return 0 out.append(_DupScratch(_g_out_str)) i += 1 return 1 if k == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(node) - if bop is None or bop.op != ast.OpKind.Add: - return 0 - if _EvalList(bop.left, out) == 0: - return 0 - if _EvalList(bop.right, out) == 0: - return 0 + if bop is None or bop.op != ast.OpKind.Add: return 0 + if _EvalList(bop.left, out) == 0: return 0 + if _EvalList(bop.right, out) == 0: return 0 return 1 return 0 def _EvalBool(node: ast.AST*) -> int: """布尔常量求值;-1=非布尔常量""" - if node is None: - return -1 - if node.kind() != ast.ASTKind.Constant: - return -1 + if node is None: return -1 + if node.kind() != ast.ASTKind.Constant: return -1 cn: ast.Constant* = ast.Constant*(node) - if cn is None or cn.const_kind != ast.CONST_BOOL: - return -1 - if cn.int_val != 0: - return 1 + if cn is None or cn.const_kind != ast.CONST_BOOL: return -1 + if cn.int_val != 0: return 1 return 0 @@ -508,20 +440,16 @@ def _EvalBool(node: ast.AST*) -> int: # ============================================================ def _IsProjRef(node: ast.AST*) -> int: """节点是否直接引用 Project 宏对象(Name 或 Attribute 的 base);1=是""" - if node is None: - return 0 + if node is None: return 0 k: int = node.kind() if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) - if nm is None or nm.id is None: - return 0 - if _FindInList(_proj_vars, nm.id) >= 0: - return 1 + if nm is None or nm.id is None: return 0 + if _FindInList(_proj_vars, nm.id) >= 0: return 1 return 0 if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(node) - if at is None or at.value is None: - return 0 + if at is None or at.value is None: return 0 return _IsProjRef(at.value) return 0 @@ -536,27 +464,22 @@ def _ResetFileTables(pool: memhub.MemBuddy*) -> int: _f_str_vals = list[str](pool, 8) _f_list_names = list[str](pool, 8) _f_list_vals = list[str](pool, 8) - if _f_str_names is None or _f_str_vals is None: - return 1 - if _f_list_names is None or _f_list_vals is None: - return 1 + if _f_str_names is None or _f_str_vals is None: return 1 + if _f_list_names is None or _f_list_vals is None: return 1 return 0 def _AddPending(mod_name: str) -> None: """把待解析模块名记入 BFS 队列(scratch 池深拷贝)""" - if mod_name is None or _pending is None: - return - if string.strlen(mod_name) == 0: - return + if mod_name is None or _pending is None: return + if string.strlen(mod_name) == 0: return _pending.append(_DupScratch(mod_name)) def _HandleImport(stmt: ast.Import*) -> int: """处理 `import X [as Y]`:识别 viperbuild,其余模块登记入 BFS 队列""" global _alias, _saw_viperbuild - if stmt is None or stmt.names is None: - return 0 + if stmt is None or stmt.names is None: return 0 n: sizet = stmt.names.__len__() i: sizet = 0 while i < n: @@ -564,12 +487,9 @@ def _HandleImport(stmt: ast.Import*) -> int: if al is not None and al.name is not None: if string.strcmp(al.name, "viperbuild") == 0: _saw_viperbuild = 1 - if al.asname is not None: - _alias = _DupScratch(al.asname) - else: - _alias = _DupScratch("viperbuild") - else: - _AddPending(al.name) + if al.asname is not None: _alias = _DupScratch(al.asname) + else: _alias = _DupScratch("viperbuild") + else: _AddPending(al.name) i += 1 return 0 @@ -577,63 +497,48 @@ def _HandleImport(stmt: ast.Import*) -> int: def _HandleImportFrom(stmt: ast.ImportFrom*) -> int: """处理 `from X import Y`:识别 `from viperbuild import Project`,其余登记 BFS""" global _ctor_name, _saw_viperbuild - if stmt is None: - return 0 + if stmt is None: return 0 if stmt.level != 0: # 相对导入不参与工程本地闭包展开(无包上下文,跳过) return 0 - if stmt.module is None: - return 0 + if stmt.module is None: return 0 if string.strcmp(stmt.module, "viperbuild") != 0: _AddPending(stmt.module) return 0 _saw_viperbuild = 1 - if stmt.names is None: - return 0 + if stmt.names is None: return 0 n: sizet = stmt.names.__len__() i: sizet = 0 while i < n: al: ast.Alias* = ast.Alias*(stmt.names.get(i)) if al is not None and al.name is not None: if string.strcmp(al.name, "Project") == 0: - if al.asname is not None: - _ctor_name = _DupScratch(al.asname) - else: - _ctor_name = _DupScratch("Project") + if al.asname is not None: _ctor_name = _DupScratch(al.asname) + else: _ctor_name = _DupScratch("Project") i += 1 return 0 def _IsProjectCtor(vnode: ast.AST*) -> int: """判断表达式是否为 `vb.Project(...)` / `Project(...)`;1=是""" - if vnode is None: - return 0 - if vnode.kind() != ast.ASTKind.Call: - return 0 + if vnode is None: return 0 + if vnode.kind() != ast.ASTKind.Call: return 0 cl: ast.Call* = ast.Call*(vnode) - if cl is None or cl.func is None: - return 0 + if cl is None or cl.func is None: return 0 fk: int = cl.func.kind() if fk == ast.ASTKind.Attribute: 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: - return 0 + if at is None or at.attr is None or at.value is None: return 0 + if at.value.kind() != ast.ASTKind.Name: return 0 bn: ast.Name* = ast.Name*(at.value) - if bn is None or bn.id is None or _alias is None: - return 0 - if string.strcmp(bn.id, _alias) != 0: - return 0 - if string.strcmp(at.attr, "Project") == 0: - return 1 + if bn is None or bn.id is None or _alias is None: return 0 + if string.strcmp(bn.id, _alias) != 0: return 0 + if string.strcmp(at.attr, "Project") == 0: return 1 return 0 if fk == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(cl.func) - if nm is None or nm.id is None or _ctor_name is None: - return 0 - if string.strcmp(nm.id, _ctor_name) == 0: - return 1 + if nm is None or nm.id is None or _ctor_name is None: return 0 + if string.strcmp(nm.id, _ctor_name) == 0: return 1 return 0 @@ -643,8 +548,7 @@ def _ApplyCtorArgs(cl: ast.Call*) -> int: 位置参数与关键字参数都支持(位置在前:args[0]=name, args[1]=version)。 """ global _c_name, _c_version - if cl is None: - return 0 + if cl is None: return 0 if cl.args is not None: an: sizet = cl.args.__len__() if an > 2: @@ -660,8 +564,7 @@ def _ApplyCtorArgs(cl: ast.Call*) -> int: VLogger.error("viperbuild: Project(version) 必须是字符串常量", "viperbuild") return 1 _c_version = _DupStd(_g_out_str) - if cl.keywords is None: - return 0 + if cl.keywords is None: return 0 n: sizet = cl.keywords.__len__() i: sizet = 0 while i < n: @@ -688,8 +591,7 @@ def _SetField(fname: str, vnode: ast.AST*) -> int: """`proj. = ` / `config(=)`;0=成功""" global _c_source, _c_buildroot, _c_includes, _c_compiler, _c_linker global _c_static_libs, _c_dynamic_libs, _c_output, _c_name, _c_version - if fname is None or vnode is None: - return 1 + if fname is None or vnode is None: return 1 # ---- 字符串字段 ---- if string.strcmp(fname, "source") == 0: if _EvalStr(vnode) == 0: @@ -722,16 +624,11 @@ def _SetField(fname: str, vnode: ast.AST*) -> int: _c_version = _DupStd(_g_out_str) return 0 # ---- 列表字段 ---- - if string.strcmp(fname, "includes") == 0: - return _SetListField(0, vnode) - if string.strcmp(fname, "compiler") == 0: - return _SetListField(1, vnode) - 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) + if string.strcmp(fname, "includes") == 0: return _SetListField(0, vnode) + if string.strcmp(fname, "compiler") == 0: return _SetListField(1, vnode) + 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") return 1 @@ -739,59 +636,44 @@ def _SetField(fname: str, vnode: ast.AST*) -> int: def _SetListField(slot: int, vnode: ast.AST*) -> int: """列表字段赋值(slot: 0=includes 1=compiler 2=linker 3=static_libs 4=dynamic_libs)""" global _c_includes, _c_compiler, _c_linker, _c_static_libs, _c_dynamic_libs - if _scratch is None: - return 1 + if _scratch is None: return 1 tmp: list[str]* = list[str](_scratch, 8) - if tmp is None: - return 1 + if tmp is None: return 1 if _EvalList(vnode, tmp) == 0: VLogger.error("viperbuild: 列表字段必须是 list[str] 常量表达式", "viperbuild") return 1 joined: str = _JoinSpace(tmp) - if slot == 0: - _c_includes = joined - elif slot == 1: - _c_compiler = joined - elif slot == 2: - _c_linker = joined - elif slot == 3: - _c_static_libs = joined - else: - _c_dynamic_libs = joined + if slot == 0: _c_includes = joined + elif slot == 1: _c_compiler = joined + elif slot == 2: _c_linker = joined + elif slot == 3: _c_static_libs = joined + else: _c_dynamic_libs = joined return 0 def _HandleAssign(stmt: ast.Assign*) -> int: """处理赋值语句:常量定义 / `proj = vb.Project(...)` / `proj.<字段> = ...`""" - if stmt is None or stmt.targets is None or stmt.value is None: - return 0 - if stmt.targets.__len__() != 1: - return 0 + if stmt is None or stmt.targets is None or stmt.value is None: return 0 + if stmt.targets.__len__() != 1: return 0 tgt: ast.AST* = stmt.targets.get(0) - if tgt is None: - return 0 + if tgt is None: return 0 tk: int = tgt.kind() - if tk == ast.ASTKind.Name: - return _HandleNameBind(ast.Name*(tgt), stmt.value) - if tk == ast.ASTKind.Attribute: - return _HandleAttrAssign(ast.Attribute*(tgt), stmt.value) + if tk == ast.ASTKind.Name: return _HandleNameBind(ast.Name*(tgt), stmt.value) + if tk == ast.ASTKind.Attribute: return _HandleAttrAssign(ast.Attribute*(tgt), stmt.value) return 0 def _HandleAnnAssign(stmt: ast.AnnAssign*) -> int: """处理注解赋值(含 `define NAME = <字面量>` 脱糖出的 AnnAssign)""" - if stmt is None or stmt.target is None or stmt.value is None: - return 0 - if stmt.target.kind() != ast.ASTKind.Name: - return 0 + if stmt is None or stmt.target is None or stmt.value is None: return 0 + if stmt.target.kind() != ast.ASTKind.Name: return 0 return _HandleNameBind(ast.Name*(stmt.target), stmt.value) def _HandleNameBind(tgt: ast.Name*, vnode: ast.AST*) -> int: """`NAME = `:Project 实例绑定 / 字符串常量 / 列表常量""" global _c_has_project - if tgt is None or vnode is None or tgt.id is None: - return 0 + if tgt is None or vnode is None or tgt.id is None: return 0 # 右侧读取 Project 宏对象 ⇒ fatal(禁止读取) if _IsProjRef(vnode) != 0: VLogger.error(f"viperbuild: 禁止读取 Project 宏对象({tgt.id} = proj ...)", "viperbuild") @@ -824,15 +706,11 @@ def _HandleNameBind(tgt: ast.Name*, vnode: ast.AST*) -> int: def _HandleAttrAssign(tgt: ast.Attribute*, vnode: ast.AST*) -> int: """`proj.<字段> = <常量表达式>`""" - if tgt is None or tgt.attr is None or tgt.value is None: - return 0 - if tgt.value.kind() != ast.ASTKind.Name: - return 0 + if tgt is None or tgt.attr is None or tgt.value is None: return 0 + if tgt.value.kind() != ast.ASTKind.Name: return 0 bn: ast.Name* = ast.Name*(tgt.value) - if bn is None or bn.id is None: - return 0 - if _FindInList(_proj_vars, bn.id) < 0: - return 0 + 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") return 1 @@ -841,15 +719,13 @@ def _HandleAttrAssign(tgt: ast.Attribute*, vnode: ast.AST*) -> int: def _HandleConfigCall(cl: ast.Call*) -> int: """`proj.config(kw=...)`""" - if cl is None or cl.keywords is None: - return 0 + if cl is None or cl.keywords is None: return 0 n: sizet = cl.keywords.__len__() i: sizet = 0 while i < n: kw: ast.Keyword* = ast.Keyword*(cl.keywords.get(i)) if kw is not None and kw.arg is not None and kw.value is not None: - if _SetField(kw.arg, kw.value) != 0: - return 1 + if _SetField(kw.arg, kw.value) != 0: return 1 i += 1 return 0 @@ -857,14 +733,12 @@ def _HandleConfigCall(cl: ast.Call*) -> int: def _HandleBuildCall(cl: ast.Call*) -> int: """`proj.build(triple=, datalayout=, selfmachine=)`""" global _c_triple, _c_datalayout, _c_selfmachine, _c_has_build - if cl is None: - return 1 + if cl is None: return 1 if _c_has_build != 0: VLogger.error("viperbuild: proj.build() 只能调用一次", "viperbuild") return 1 _c_has_build = 1 - if cl.keywords is None: - return 0 + if cl.keywords is None: return 0 n: sizet = cl.keywords.__len__() i: sizet = 0 while i < n: @@ -895,14 +769,12 @@ def _HandleBuildCall(cl: ast.Call*) -> int: def _CallArgsHaveProjRef(cl: ast.Call*) -> int: """调用的实参/关键字里是否引用了 Project 宏对象(读即 fatal);1=是""" - if cl is None: - return 0 + if cl is None: return 0 if cl.args is not None: n: sizet = cl.args.__len__() i: sizet = 0 while i < n: - if _IsProjRef(cl.args.get(i)) != 0: - return 1 + if _IsProjRef(cl.args.get(i)) != 0: return 1 i += 1 if cl.keywords is not None: n = cl.keywords.__len__() @@ -910,22 +782,18 @@ def _CallArgsHaveProjRef(cl: ast.Call*) -> int: while i < n: kw: ast.Keyword* = ast.Keyword*(cl.keywords.get(i)) if kw is not None and kw.value is not None: - if _IsProjRef(kw.value) != 0: - return 1 + if _IsProjRef(kw.value) != 0: return 1 i += 1 return 0 def _HandleExprStmt(stmt: ast.Expr*) -> int: """表达式语句:识别 `proj.config(...)` / `proj.build(...)`;其余检查读取""" - if stmt is None or stmt.value is None: - return 0 + if stmt is None or stmt.value is None: return 0 v: ast.AST* = stmt.value - if v.kind() != ast.ASTKind.Call: - return 0 + if v.kind() != ast.ASTKind.Call: return 0 cl: ast.Call* = ast.Call*(v) - if cl is None or cl.func is None: - return 0 + if cl is None or cl.func is None: return 0 # 非 Project 方法调用:若实参里读了宏对象 ⇒ fatal(禁止读取) if cl.func.kind() != ast.ASTKind.Attribute: if _CallArgsHaveProjRef(cl) != 0: @@ -933,36 +801,30 @@ def _HandleExprStmt(stmt: ast.Expr*) -> int: 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 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") return 1 return 0 bn: ast.Name* = ast.Name*(at.value) - if bn is None or bn.id is None: - return 0 + 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") return 1 return 0 - if string.strcmp(at.attr, "config") == 0: - return _HandleConfigCall(cl) - if string.strcmp(at.attr, "build") == 0: - return _HandleBuildCall(cl) + 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") return 1 def _ScanFile(pool: memhub.MemBuddy*, path: str) -> int: """解析并扫描单个 .vp 文件;0=成功,1=失败(已报错),2=可跳过(不可读/非 .vp)""" - if path is None: - return 2 + if path is None: return 2 sl: sizet = string.strlen(path) - if sl == 0: - return 2 + if sl == 0: return 2 if Utils.is_vp_at(path, 0, sl) == 0: # 非 .vp:不参与闭包(.vpi/.vpnci 对编译器不可见) return 2 @@ -1007,18 +869,12 @@ def _ScanFile(pool: memhub.MemBuddy*, path: str) -> int: child: ast.AST* = body.get(ci) if child is not None: kd: int = child.kind() - if kd == ast.ASTKind.Import: - _HandleImport(ast.Import*(child)) - elif kd == ast.ASTKind.ImportFrom: - _HandleImportFrom(ast.ImportFrom*(child)) - elif kd == ast.ASTKind.Assign: - rc = _HandleAssign(ast.Assign*(child)) - elif kd == ast.ASTKind.AnnAssign: - rc = _HandleAnnAssign(ast.AnnAssign*(child)) - elif kd == ast.ASTKind.Expr: - rc = _HandleExprStmt(ast.Expr*(child)) - if rc != 0: - break + if kd == ast.ASTKind.Import: _HandleImport(ast.Import*(child)) + elif kd == ast.ASTKind.ImportFrom: _HandleImportFrom(ast.ImportFrom*(child)) + elif kd == ast.ASTKind.Assign: rc = _HandleAssign(ast.Assign*(child)) + elif kd == ast.ASTKind.AnnAssign: rc = _HandleAnnAssign(ast.AnnAssign*(child)) + elif kd == ast.ASTKind.Expr: rc = _HandleExprStmt(ast.Expr*(child)) + if rc != 0: break ci += 1 pool.reset_to(mark) @@ -1035,10 +891,8 @@ def _ResolveModuleToFile(module_name: str) -> str: 输出槽契约与 StubMergerBuild 一致:槽为 8 字节缓冲,写侧 sizet(ptr)、 读侧 rawptr(slot[0]);ResolveModuleToPath 返回的 abs/rel/inc 串由调用方 free。 """ - if module_name is None or _search_dirs is None: - return None - if string.strlen(module_name) == 0: - return None + if module_name is None or _search_dirs is None: return None + if string.strlen(module_name) == 0: return None out_abs: t.CPtr = stdlib.malloc(8) out_rel: t.CPtr = stdlib.malloc(8) out_inc: t.CPtr = stdlib.malloc(8) @@ -1058,14 +912,10 @@ def _ResolveModuleToFile(module_name: str) -> str: result: str = None if rcode == 0 and abs_slot[0] != 0: abs_path: str = rawptr(abs_slot[0]) - if abs_path is not None: - result = _DupScratch(abs_path) - if abs_slot[0] != 0: - stdlib.free(rawptr(abs_slot[0])) - if rel_slot[0] != 0: - stdlib.free(rawptr(rel_slot[0])) - if inc_slot[0] != 0: - stdlib.free(rawptr(inc_slot[0])) + if abs_path is not None: result = _DupScratch(abs_path) + if abs_slot[0] != 0: stdlib.free(rawptr(abs_slot[0])) + if rel_slot[0] != 0: stdlib.free(rawptr(rel_slot[0])) + if inc_slot[0] != 0: stdlib.free(rawptr(inc_slot[0])) stdlib.free(out_abs) stdlib.free(out_rel) stdlib.free(out_inc) @@ -1074,12 +924,9 @@ def _ResolveModuleToFile(module_name: str) -> str: def _Enqueue(path: str) -> None: """把文件路径加入 BFS 队列(worklist/visited 去重)""" - if path is None or _work is None: - return - if _FindInList(_visited, path) >= 0: - return - if _FindInList(_work, path) >= 0: - return + if path is None or _work is None: return + if _FindInList(_visited, path) >= 0: return + if _FindInList(_work, path) >= 0: return _work.append(_DupScratch(path)) @@ -1089,10 +936,8 @@ def _RunBfs(pool: memhub.MemBuddy*, entry_path: str) -> int: _work.append(_DupScratch(entry_path)) while _work.__len__() > 0: cur: str = _work.pop() - if cur is None: - continue - if _FindInList(_visited, cur) >= 0: - continue + 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") return 1 @@ -1103,8 +948,7 @@ def _RunBfs(pool: memhub.MemBuddy*, entry_path: str) -> int: VLogger.error("viperbuild: BFS 队列分配失败", "viperbuild") return 1 rc: int = _ScanFile(pool, cur) - if rc == 1: - return 1 + if rc == 1: return 1 # 解析本文件收集到的模块名 pn: sizet = _pending.__len__() pi: sizet = 0 @@ -1112,8 +956,7 @@ def _RunBfs(pool: memhub.MemBuddy*, entry_path: str) -> int: mod: str = _pending.get(pi) if mod is not None: dep: str = _ResolveModuleToFile(mod) - if dep is not None: - _Enqueue(dep) + if dep is not None: _Enqueue(dep) pi += 1 return 0 @@ -1141,8 +984,7 @@ def _DetectHost() -> int: buf[int(n)] = char(0) # "AMD64\0"(A=65 M=77 D=68 6=54 4=52) is_amd64: int = 0 - if buf[0] == char(65) and buf[1] == char(77) and buf[2] == char(68) and buf[3] == char(54) and buf[4] == char(52) and buf[5] == char(0): - is_amd64 = 1 + if buf[0] == char(65) and buf[1] == char(77) and buf[2] == char(68) and buf[3] == char(54) and buf[4] == char(52) and buf[5] == char(0): is_amd64 = 1 if is_amd64 != 0: _c_triple = "x86_64-pc-windows-gnu" _c_datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" @@ -1156,21 +998,18 @@ def _DetectHost() -> int: def _ProbeIncludes() -> str: """按 exe 所在目录向上 0..3 层探测 includes 目录;命中返回绝对路径,否则 None""" exe_buf: bytes = stdlib.malloc(VB_PATH_CAP) - if exe_buf is None: - return None + if exe_buf is None: return None exe_buf[0] = '\0' n_exe: ULONG = win32file.GetModuleFileNameA(None, exe_buf, ULONG(VB_PATH_CAP)) if n_exe <= 0: stdlib.free(exe_buf) return None el: int = int(n_exe) - if el >= VB_PATH_CAP: - el = VB_PATH_CAP - 1 + if el >= VB_PATH_CAP: el = VB_PATH_CAP - 1 exe_buf[el] = '\0' exe_dir: str = _DirOf(exe_buf) stdlib.free(exe_buf) - if exe_dir is None: - return None + if exe_dir is None: return None k: int = 0 while k <= 3: base: str = _DupStd(exe_dir) @@ -1179,8 +1018,7 @@ def _ProbeIncludes() -> str: base = _Join2(base, "..") j += 1 cand: str = _Join2(base, "includes") - if _IsDir(cand) != 0: - return cand + if _IsDir(cand) != 0: return cand k += 1 return None @@ -1188,8 +1026,7 @@ def _ProbeIncludes() -> str: def _DeriveOutputFromEntry(entry_path: str) -> str: """从入口文件名推导默认输出名(去扩展名 + ".exe")""" base: str = _BaseNameOf(entry_path) - if base is None: - return "app.exe" + if base is None: return "app.exe" n: sizet = string.strlen(base) cut: sizet = n i: sizet = 0 @@ -1199,8 +1036,7 @@ def _DeriveOutputFromEntry(entry_path: str) -> str: break i += 1 head: str = stdlib.malloc(cut + 5) - if head is None: - return "app.exe" + if head is None: return "app.exe" string.strncpy(head, base, cut) head[cut] = '.' head[cut + 1] = 'e' @@ -1224,25 +1060,21 @@ def _FinalizeCfg(entry_path: str) -> int: return 1 # ---- 默认值 ---- - if _c_source is None: - _c_source = _DupStd(_entry_dir) - if _c_buildroot is None: - _c_buildroot = _Join2(_c_source, ".tpv_build") + if _c_source is None: _c_source = _DupStd(_entry_dir) + if _c_buildroot is None: _c_buildroot = _Join2(_c_source, ".tpv_build") if _c_includes is None: probed: str = _ProbeIncludes() if probed is None: VLogger.error("viperbuild: 未能探测到 includes 目录(exe 目录向上 0..3 层均无 includes)", "viperbuild") return 1 _c_includes = probed - if _c_compiler is None: - _c_compiler = _DupStd("llc -filetype=obj -relocation-model=pic") + if _c_compiler is None: _c_compiler = _DupStd("llc -filetype=obj -relocation-model=pic") if _c_linker is None: # 内置默认 = 本仓 TransPyV/project.vpj 那份**已验证可用**的链接参数。 # 注意:不要带 -lgcc —— msys64/mingw64 + lld 下没有 libgcc, # 会以 "lld: error: unable to find library -lgcc" 直接链接失败。 _c_linker = _DupStd("clang++ -fuse-ld=lld -lmsvcrt -lucrt -lpthread -lmingwex -lkernel32 -Wl,--allow-multiple-definition -Wl,--stack,0x1000000 -Wl,--no-insert-timestamp -Wl,--export-all-symbols -g") - if _c_output is None: - _c_output = _DeriveOutputFromEntry(entry_path) + if _c_output is None: _c_output = _DeriveOutputFromEntry(entry_path) # ---- 入口文件必须位于 source 之下 ---- if _HasPrefix(entry_path, _c_source) == 0: @@ -1251,8 +1083,7 @@ def _FinalizeCfg(entry_path: str) -> int: # ---- 目标平台 ---- explicit_triple: int = 0 - if _c_triple is not None or _c_datalayout is not None: - explicit_triple = 1 + 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") return 1 @@ -1262,8 +1093,7 @@ def _FinalizeCfg(entry_path: str) -> int: return 1 else: # 都未给 或 selfmachine=True ⇒ 运行时探测本机 - if _DetectHost() != 0: - return 1 + if _DetectHost() != 0: return 1 # ---- 写回 Config ---- Config.ProjectName = _c_name @@ -1272,8 +1102,7 @@ def _FinalizeCfg(entry_path: str) -> int: Config.BuildDir = _c_buildroot Config.IncludesDirs = _c_includes Config.IncludesDir = _FirstSpaceTok(_c_includes) - if Config.IncludesDir is None: - Config.IncludesDir = _c_includes + if Config.IncludesDir is None: Config.IncludesDir = _c_includes Config.TargetTriple = _c_triple Config.TargetDataLayout = _c_datalayout Config.LinkerStaticLibs = _c_static_libs @@ -1290,8 +1119,7 @@ def _FinalizeCfg(entry_path: str) -> int: def _SplitToolCmd(joined: str, which: int) -> None: """把 `["cmd", flag...]` 空格连接串拆成 Config 的 Cmd/Flags(which: 0=compiler 1=linker)""" - if joined is None: - return + if joined is None: return n: sizet = string.strlen(joined) sp: sizet = n i: sizet = 0 @@ -1305,8 +1133,7 @@ def _SplitToolCmd(joined: str, which: int) -> None: string.strncpy(cmd, joined, sp) cmd[sp] = '\0' flags: str = None - if sp < n: - flags = _DupStd(joined + sp + 1) + if sp < n: flags = _DupStd(joined + sp + 1) if which == 0: Config.CompilerCmd = cmd Config.CompilerFlags = flags @@ -1376,8 +1203,7 @@ def DiscoverAndApply(mb: memhub.MemBuddy*, entry_path: str) -> int: # 裸文件名(无目录分隔符)→ _DirOf 返回空串;必须规整成 ".",否则 # ResolveModuleToPath("") 一个候选目录都不会尝试,入口同目录的依赖 # (往往是 viperbuild 配置所在模块)永远解析不到 ⇒ 误报"未找到 import viperbuild"。 - if string.strlen(_entry_dir) == 0: - _entry_dir = _DupStd(".") + if string.strlen(_entry_dir) == 0: _entry_dir = _DupStd(".") # 闭包搜索根:入口目录优先,其次当前目录 "."(配置模块可能不在入口目录内) _search_dirs = _ConcatStd(_DupStd(_entry_dir), _DupStd(" .")) @@ -1402,18 +1228,14 @@ def DiscoverAndApply(mb: memhub.MemBuddy*, entry_path: str) -> int: # 关键字/操作符表须在主池 reset 窗口之前建立(否则被回收 → 悬空崩溃) ast._init_tables(mb) - if _RunBfs(mb, entry_path) != 0: - return 1 + 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`(入口: {entry_path};已扫描 {_visited.__len__()} 个文件)", "viperbuild") + else: VLogger.error(f"viperbuild: 找到 `import viperbuild` 但依赖闭包内没有 `proj = vb.Project(...)` 绑定(入口: {entry_path})", "viperbuild") return 1 - if _FinalizeCfg(entry_path) != 0: - return 1 + if _FinalizeCfg(entry_path) != 0: return 1 _applied = 1 return 0 diff --git a/App/main.vp b/App/main.vp index 0db56a1..6ca2440 100644 --- a/App/main.vp +++ b/App/main.vp @@ -64,13 +64,11 @@ def main() -> int: detect_flag: int = 0 cmd_line_d: str = w32base.GetCommandLineA() - if cmd_line_d is not None and string.strstr(cmd_line_d, "--detection") is not None: - detect_flag = 1 + if cmd_line_d is not None and string.strstr(cmd_line_d, "--detection") is not None: detect_flag = 1 # --detection-deep:重诊断(每次 alloc 探测 + 周期全表扫描,极慢,默认关);须在 MemBuddy 构造前用原始命令行 strstr 取值 deep_detect_flag: int = 0 - if cmd_line_d is not None and string.strstr(cmd_line_d, "--detection-deep") is not None: - deep_detect_flag = 1 + if cmd_line_d is not None and string.strstr(cmd_line_d, "--detection-deep") is not None: deep_detect_flag = 1 # Initialize the mbuddy memory pool arena: bytes = stdlib.malloc(POOL_SIZE) @@ -130,8 +128,7 @@ def main() -> int: # 初始化 VLogger 并打印启动日志 VLogger.init_logger() log: VLogger.Logger = VLogger.logger - if log is None: - log.error("TransPyV Failed to parse parameters") + if log is None: log.error("TransPyV Failed to parse parameters") # 初始化命令行参数(Windows: GetCommandLineA, POSIX: /proc/self/cmdline) sys._init_argv() @@ -161,7 +158,7 @@ def main() -> int: parser.add_argument("--show-args", None, argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Show all parsed arguments") parser.add_argument("--repl", None, argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Start the interactive REPL (M2 session variables + M3 cross-fragment functions: fragment -> DLL -> call)") parser.add_argument("--build-dir", None, argparse.STRING, 0, None, False, argparse.STORE, "Override project.vpj build_dir (default ./.tpv_build; relative paths resolve against the project dir)") - parser.add_argument("--no-llvmpeephole", None, argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Disable all local mlirlite peephole passes (T2 store/load forward & ret-zero, T3 no-op bitcast) in FunctionPrint serialization") + parser.add_argument("--no-llvmpeephole", None, argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Disable all local mlirlite peephole passes (T2 store/load forward & ret-zero, T3 no-op bitcast) in FunctionPrint serialization") parser.add_argument("--version", "-v", argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Show version and exit") parser.add_argument("--help", "-h", argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Show help and exit") @@ -284,26 +281,16 @@ Target: %s # 后续 --clean/--rebuild-includes 经 Config.get_includes_binary_dir() 自动覆盖。 gb_asan: bool = args.get_bool("asan") gb_traceback: bool = args.get_bool("traceback") - if gb_asan: - BuildPipeline._asan_mode = True - else: - BuildPipeline._asan_mode = False - if gb_traceback: - BuildPipeline._traceback_mode = True - else: - BuildPipeline._traceback_mode = False - if gb_asan and gb_traceback: - Config._inc_bin_suffix = ".binary_traceback_asan" - 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: BuildPipeline._asan_mode = True + else: BuildPipeline._asan_mode = False + if gb_traceback: BuildPipeline._traceback_mode = True + else: BuildPipeline._traceback_mode = False + if gb_asan and gb_traceback: Config._inc_bin_suffix = ".binary_traceback_asan" + 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") # 开启任一模式都清空对应后缀的 includes 缓存,强制重建匹配当前模式的 obj if gb_asan or gb_traceback: mf_inc_bin_mode: str = Config.get_includes_binary_dir() @@ -354,21 +341,17 @@ Target: %s if proj_path is not None: log.banner("工程配置") 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") + if cfg_ret == 0: proj_loaded = 1 + else: log.warning(f"无法加载 project.vpj: {proj_path}", "config") else: # 尝试默认路径 project.vpj(当前目录和上级目录) # --src 模式走 viperbuild 内建配置,不得再隐式加载 project.vpj(否则污染配置来源) if src is None: proj_path = "project.vpj" - if Config.Load_project_config(proj_path) == 0: - proj_loaded = 1 + if Config.Load_project_config(proj_path) == 0: proj_loaded = 1 else: proj_path = "../project.vpj" - if Config.Load_project_config(proj_path) == 0: - proj_loaded = 1 + if Config.Load_project_config(proj_path) == 0: proj_loaded = 1 if proj_loaded == 1: # 提取 project.vpj 所在目录,将相对路径解析为基于该目录的路径 proj_len: sizet = string.strlen(proj_path) @@ -386,8 +369,7 @@ Target: %s string.memcpy(proj_dir, proj_path, slash_pos) proj_dir[slash_pos] = '\0' # [--build-dir] 覆盖 project.vpj 的 build_dir:须在 resolve_paths 前设置,使相对路径仍基于 project_dir 解析 - if build_dir is not None: - Config.BuildDir = build_dir + if build_dir is not None: Config.BuildDir = build_dir Config.resolve_paths(proj_dir) Config.print_config() @@ -455,23 +437,19 @@ Target: %s # === --phase 参数控制: 1=仅 stub 分离;2=仅 stub 合并+编译;all=两者都执行(默认) === phase_mode: str = phase - if phase_mode is None: - phase_mode = "all" + if phase_mode is None: phase_mode = "all" do_phase1: int = 0 do_phase2: int = 0 # 注意: 使用 string.strcmp 而非 ==,避免编译器 == 语义 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 + 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") # === Phase1: 扫描 includes(按需翻译)=== # 对 includes 目录中每个 .vp/.py 文件,若 stub 不存在则翻译并分离 stub if do_phase1 != 0 and Config.IncludesDirs is not None: ph1_temp: str = Config.TempDir - if ph1_temp is None: - ph1_temp = "." + if ph1_temp is None: ph1_temp = "." if Phase1Main.RunPhase1(mb, Config.IncludesDirs, ph1_temp, log) != 0: VLogger.error("Phase1 失败,终止编译", "Phase1") return 1