diff --git a/App/lib/Phase/BuildPipeline.vp b/App/lib/Phase/BuildPipeline.vp index 6a80ee7..533aa7a 100644 --- a/App/lib/Phase/BuildPipeline.vp +++ b/App/lib/Phase/BuildPipeline.vp @@ -82,7 +82,7 @@ def _ir_sibling_path(ir_path: str, suffix: str) -> str: return buf # 源代码缓冲区大小(1MB) -SRC_BUF_SIZE: t.CDefine = 1048576 # 2^20 = 1MB +define SRC_BUF_SIZE = 1048576 # 2^20 = 1MB # .vpi 存根缓冲区大小(256KB,与 Phase1 一致) PYI_BUF_SIZE: sizet = 262144 @@ -128,7 +128,7 @@ def _append_traceback_dbghelp(linker_flags: str) -> str: # 写盘并登记路径。WriteStackMap 链接后按登记表读取,结合 llvm-objdump 归一地址。 # 仅 --traceback 时产生;关闭时不写任何旁文件、不登记。 # ============================================================ -TB_VPCALL_MAX: t.CDefine = 8192 +define TB_VPCALL_MAX = 8192 _tb_vpcall_buf: bytes = None # TB_VPCALL_MAX * 8:每槽一个 char*(stdlib 分配,进程内一次性) _tb_vpcall_n: int = 0 @@ -147,7 +147,7 @@ def _tb_register_vpcall(path: str) -> int: if _tb_vpcall_n >= TB_VPCALL_MAX: VLogger.error("--traceback: .vpcall 路径表溢出(模块数超上限),终止编译", "TRACEBACK") return 1 - slot: str | t.CPtr = (str | t.CPtr)(uint64(_tb_vpcall_buf) + sizet(_tb_vpcall_n) * 8) + slot: str* = (str*)(uint64(_tb_vpcall_buf) + sizet(_tb_vpcall_n) * 8) slot[0] = path _tb_vpcall_n += 1 return 0 @@ -581,7 +581,7 @@ def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: s # - 依赖 CreateProcessA + Win32 句柄接口的多线程安全性 # ============================================================ # llc 并行最大线程数(参考 TPC Phase2Translator n_workers=os.cpu_count(),本机 16 核) -LLC_MAX_THREADS: t.CDefine = 16 +define LLC_MAX_THREADS = 16 # LlcTask.FailStage:worker 写"失败发生在哪一步" # 0 = 未失败/成功;1 = mlir-opt 校验;2 = mlir-translate 降级;3 = ASan opt 插桩;4 = llc @@ -611,7 +611,7 @@ class LlcTask: FailStage: int # worker 写:失败发生在哪一步 -def init_llc_task(task: LlcTask | t.CPtr, ir_path: str, output_dir: str, +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: @@ -675,7 +675,7 @@ def init_llc_task(task: LlcTask | t.CPtr, ir_path: str, output_dir: str, return 0 -def free_llc_task(task: LlcTask | t.CPtr): +def free_llc_task(task: LlcTask*): """释放任务的命令串;记录本身是任务数组的连续槽(非独立 malloc), 由调用方对数组整体 stdlib.free(此前对槽 free 导致 double-free)""" if task is None: @@ -745,9 +745,9 @@ def _run_cmd_wait(cmd: str) -> int: # 栈垃圾,多线程并发调用时垃圾随机 → dwFlags 垃圾位让 CreateProcessA # 用垃圾句柄作子进程 stdio → 子进程行为不定/父进程线程崩溃(ClassArrayTest # e5fb worker 崩溃、edd8 正常的原因)。si/sa/pi 全部显式清零。 - string.memset(t.CPtr(c.Addr(si)), 0, win32process.STARTUPINFOA.__sizeof__()) - string.memset(t.CPtr(c.Addr(sa)), 0, w32.win32base.SECURITY_ATTRIBUTES.__sizeof__()) - string.memset(t.CPtr(c.Addr(pi)), 0, win32process.PROCESS_INFORMATION.__sizeof__()) + string.memset(t.CPtr(&si), 0, win32process.STARTUPINFOA.__sizeof__()) + string.memset(t.CPtr(&sa), 0, w32.win32base.SECURITY_ATTRIBUTES.__sizeof__()) + string.memset(t.CPtr(&pi), 0, win32process.PROCESS_INFORMATION.__sizeof__()) sa.nLength = w32.win32base.SECURITY_ATTRIBUTES.__sizeof__() sa.lpSecurityDescriptor = t.CPtr(0) sa.bInheritHandle = 1 @@ -756,7 +756,7 @@ def _run_cmd_wait(cmd: str) -> int: # si.dwFlags 保持 memset 后的 0(不置 STARTF_USESTDHANDLES、不设 std 句柄) ok: int = win32process.CreateProcessA( t.CPtr(0), cmd_line, t.CPtr(0), t.CPtr(0), 1, 0, - t.CPtr(0), t.CPtr(0), t.CPtr(c.Addr(si)), t.CPtr(c.Addr(pi))) + t.CPtr(0), t.CPtr(0), t.CPtr(&si), t.CPtr(&pi)) # CreateProcessA 失败诊断:GetLastError 必须在返回后立即取(此后 stdlib.free/ # CloseHandle/SetConsoleTextAttribute 等都会覆盖它)。用 warning 不用 error—— # VLogger.error 会 sys.exit(1),而本函数可能在 worker 线程里执行;warning 只走 @@ -769,7 +769,7 @@ def _run_cmd_wait(cmd: str) -> int: return -1 win32sync.WaitForSingleObject(pi.hProcess, w32.win32base.INFINITE) exit_code: uint32 = 0 - win32process.GetExitCodeProcess(pi.hProcess, t.CPtr(c.Addr(exit_code))) + win32process.GetExitCodeProcess(pi.hProcess, t.CPtr(&exit_code)) w32.win32base.CloseHandle(pi.hProcess) w32.win32base.CloseHandle(pi.hThread) return int(exit_code) @@ -779,7 +779,7 @@ def _llc_task_worker(arg: t.CPtr) -> t.CPtr: """llc 线程入口:只调 _run_cmd_wait(),不做任何池分配(线程安全) Result 仅在命令链执行完后写入(初始 -1;join 超时保持 -1 → 报失败); ExitCode 记录失败命令的退出码,供主线程打印""" - task: LlcTask | t.CPtr = (LlcTask | t.CPtr)(arg) + task: LlcTask* = (LlcTask*)(arg) if task is None: return t.CPtr(0) # MLIR 后端:先校验(mlir-opt)→ 降级(mlir-translate),再 ASan opt → llc @@ -826,7 +826,7 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int: # --phase2command 模式:不 spawn 线程,把 opt(ASan)+ llc 命令全部写入 bat if _phase2_cmd_path is not None: for pi2 in range(task_count): - tsk_p: LlcTask | t.CPtr = (LlcTask | t.CPtr)(uint64(tasks) + sizet(pi2) * LlcTask.__sizeof__()) + tsk_p: LlcTask* = (LlcTask*)(uint64(tasks) + sizet(pi2) * LlcTask.__sizeof__()) if tsk_p is None: continue if tsk_p.MlirOptCmd is not None: @@ -856,7 +856,7 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int: batch_n = task_count - batch_start # 本批 spawn for j in range(batch_n): - tsk: LlcTask | t.CPtr = (LlcTask | t.CPtr)(uint64(tasks) + sizet(batch_start + j) * slot_size) + tsk: LlcTask* = (LlcTask*)(uint64(tasks) + sizet(batch_start + j) * slot_size) th: rawptr[vthreading.Thread] = vthreading.Thread(_llc_task_worker, t.CPtr(tsk)) th.start() # start() 后立即取出句柄(Thread 对象栈地址可能被后续构造复用, @@ -870,7 +870,7 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int: w32.win32base.CloseHandle(h_j) # 本批结果检查 for j in range(batch_n): - tsk2: LlcTask | t.CPtr = (LlcTask | t.CPtr)(uint64(tasks) + sizet(batch_start + j) * slot_size) + tsk2: LlcTask* = (LlcTask*)(uint64(tasks) + sizet(batch_start + j) * slot_size) if tsk2 is not None and tsk2.Result != 0: # 失败:按 FailStage 定位到**具体哪一步**并打印对应该步的命令。 # 此前一律打印 LlcCmd + "llc 编译失败":MLIR 后端下 mlir-opt / @@ -902,7 +902,7 @@ def _CollectObjFilesImpl(base_dir: str, bd_len: sizet, 支持切片子目录(如 dir/43/{sha1}.obj)。 """ - find_data: w32.win32file.WIN32_FIND_DATAA | t.CPtr = _mbuddy.alloc(w32.win32file.WIN32_FIND_DATAA.__sizeof__()) + find_data: w32.win32file.WIN32_FIND_DATAA* = _mbuddy.alloc(w32.win32file.WIN32_FIND_DATAA.__sizeof__()) if find_data is None: VLogger.warning("_CollectObjFilesImpl 分配 find_data 失败,少收集 .obj", "collect") return out_pos @@ -1401,22 +1401,22 @@ def link_objs_to_exe(obj_paths: str, obj_paths_len: sizet, # row record: u64 rva | u64 file_path | u32 line | u32 pad | u64 func_name(可空) # func_name 仅我方 .vpcall 派生行携带(objdump 标签名);DWARF 行写 0,序列化时 # 回退到 DWARF 子程序表查名。 -TB_ROW_SIZE: t.CDefine = 32 -TB_ROW_OFF_FILE: t.CDefine = 8 -TB_ROW_OFF_LINE: t.CDefine = 16 -TB_ROW_OFF_FUNC: t.CDefine = 24 +define TB_ROW_SIZE = 32 +define TB_ROW_OFF_FILE = 8 +define TB_ROW_OFF_LINE = 16 +define TB_ROW_OFF_FUNC = 24 # func record: u64 low_rva | u64 high_rva | u64 name -TB_FUNC_SIZE: t.CDefine = 24 +define TB_FUNC_SIZE = 24 # dir record: u32 idx | u32 pad | u64 name -TB_DIR_SIZE: t.CDefine = 16 +define TB_DIR_SIZE = 16 # file record: u32 idx | u32 dir_index | u64 name | u64 resolved_path -TB_FILE_SIZE: t.CDefine = 32 +define TB_FILE_SIZE = 32 # initial capacities for the (growable) row / func tables -TB_ROW_CAP0: t.CDefine = 65536 -TB_FUNC_CAP0: t.CDefine = 65536 +define TB_ROW_CAP0 = 65536 +define TB_FUNC_CAP0 = 65536 # fixed per-CU table capacities (exceeding either aborts the build) -TB_DIR_CAP: t.CDefine = 4096 -TB_FILE_CAP: t.CDefine = 65536 +define TB_DIR_CAP = 4096 +define TB_FILE_CAP = 65536 class TbPeLayout: @@ -1769,7 +1769,7 @@ def _tb_resolve_file(mb: memhub.MemBuddy*, files: bytes, fcount: int, path = _tb_join(mb, base, name) if path is None or string.strlen(path) == 0: path = "??" - _tb_wr_u64(files, roff + 24, t.CUInt64T(path)) + _tb_wr_u64(files, roff + 24, uint64(path)) return path @@ -1783,7 +1783,7 @@ def _tb_grow_rec(mb: memhub.MemBuddy*, buf: bytes, old_cap: int, return nb -def _tb_emit_row(mb: memhub.MemBuddy*, d: TbDump | t.CPtr, +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 @@ -1797,18 +1797,18 @@ def _tb_emit_row(mb: memhub.MemBuddy*, d: TbDump | t.CPtr, d.RowCap = ncap off: sizet = sizet(d.RowCount) * TB_ROW_SIZE _tb_wr_u64(d.RowBuf, off, addr) - _tb_wr_u64(d.RowBuf, off + TB_ROW_OFF_FILE, t.CUInt64T(path)) + _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 = t.CUInt64T(fname) + fv = uint64(fname) _tb_wr_u64(d.RowBuf, off + TB_ROW_OFF_FUNC, fv) d.RowCount = d.RowCount + 1 d.RawRowCount = d.RawRowCount + 1 return 0 -def _tb_emit_func(mb: memhub.MemBuddy*, d: TbDump | t.CPtr, +def _tb_emit_func(mb: memhub.MemBuddy*, d: TbDump*, low: uint64, high: uint64, name: str) -> int: if d is None: return 1 @@ -1823,7 +1823,7 @@ def _tb_emit_func(mb: memhub.MemBuddy*, d: TbDump | t.CPtr, off: sizet = sizet(d.FuncCount) * TB_FUNC_SIZE _tb_wr_u64(d.FuncBuf, off, low) _tb_wr_u64(d.FuncBuf, off + 8, high) - _tb_wr_u64(d.FuncBuf, off + 16, t.CUInt64T(name)) + _tb_wr_u64(d.FuncBuf, off + 16, uint64(name)) d.FuncCount = d.FuncCount + 1 return 0 @@ -1850,7 +1850,7 @@ def _tb_func_name_for(fbuf: bytes, fcount: int, rva: uint64) -> str: return None -def _tb_intern(p: TbPool | t.CPtr, s: str) -> uint64: +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 @@ -1870,9 +1870,9 @@ def _tb_intern(p: TbPool | t.CPtr, s: str) -> uint64: return off -def _tb_read_pe_layout(mb: memhub.MemBuddy*, exe_path: str) -> TbPeLayout | t.CPtr: +def _tb_read_pe_layout(mb: memhub.MemBuddy*, exe_path: str) -> TbPeLayout*: """Read (ImageBase, SizeOfImage, .text RVA) from the PE headers.""" - lay: TbPeLayout | t.CPtr = TbPeLayout() + lay: TbPeLayout* = TbPeLayout() if lay is None: return None f: rawptr[fileio.File] = fileio.File(exe_path, fileio.MODE.R) @@ -1938,9 +1938,9 @@ def _tb_read_pe_layout(mb: memhub.MemBuddy*, exe_path: str) -> TbPeLayout | t.CP return lay -def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump | t.CPtr: +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 | t.CPtr = TbDump() + d: TbDump* = TbDump() if d is None: return None LINE_CAP: sizet = 8192 @@ -2003,7 +2003,7 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump | t.CPtr: if pkind == 1 and pname is not None and file_count < TB_FILE_CAP: _tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE, uint64(pidx)) _tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE + 4, uint64(pdir)) - _tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 8, t.CUInt64T(pname)) + _tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 8, uint64(pname)) _tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 24, uint64(0)) file_count += 1 pkind = 0 @@ -2016,7 +2016,7 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump | t.CPtr: if pkind == 1 and pname is not None and file_count < TB_FILE_CAP: _tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE, uint64(pidx)) _tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE + 4, uint64(pdir)) - _tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 8, t.CUInt64T(pname)) + _tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 8, uint64(pname)) _tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 24, uint64(0)) file_count += 1 pname = None @@ -2028,7 +2028,7 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump | t.CPtr: if pkind == 1 and pname is not None and file_count < TB_FILE_CAP: _tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE, uint64(pidx)) _tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE + 4, uint64(pdir)) - _tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 8, t.CUInt64T(pname)) + _tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 8, uint64(pname)) _tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 24, uint64(0)) file_count += 1 pname = None @@ -2038,7 +2038,7 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump | t.CPtr: if val is not None and _tb_len_trimmed(val) > 0: if dir_count < TB_DIR_CAP: _tb_wr_u32(dirs, sizet(dir_count) * TB_DIR_SIZE, uint64(pidx)) - _tb_wr_u64(dirs, sizet(dir_count) * TB_DIR_SIZE + 8, t.CUInt64T(_tb_unquote(mb, val))) + _tb_wr_u64(dirs, sizet(dir_count) * TB_DIR_SIZE + 8, uint64(_tb_unquote(mb, val))) dir_count += 1 pkind = 0 else: @@ -2051,7 +2051,7 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump | t.CPtr: else: if dir_count < TB_DIR_CAP and val2 is not None: _tb_wr_u32(dirs, sizet(dir_count) * TB_DIR_SIZE, uint64(pidx)) - _tb_wr_u64(dirs, sizet(dir_count) * TB_DIR_SIZE + 8, t.CUInt64T(val2)) + _tb_wr_u64(dirs, sizet(dir_count) * TB_DIR_SIZE + 8, uint64(val2)) dir_count += 1 pkind = 0 continue @@ -2064,7 +2064,7 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump | t.CPtr: if pkind == 1 and pname is not None and file_count < TB_FILE_CAP: _tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE, uint64(pidx)) _tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE + 4, uint64(pdir)) - _tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 8, t.CUInt64T(pname)) + _tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 8, uint64(pname)) _tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 24, uint64(0)) file_count += 1 pkind = 0 @@ -2075,7 +2075,7 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump | t.CPtr: if pkind == 1 and pname is not None and file_count < TB_FILE_CAP: _tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE, uint64(pidx)) _tb_wr_u32(files, sizet(file_count) * TB_FILE_SIZE + 4, uint64(pdir)) - _tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 8, t.CUInt64T(pname)) + _tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 8, uint64(pname)) _tb_wr_u64(files, sizet(file_count) * TB_FILE_SIZE + 24, uint64(0)) file_count += 1 pkind = 0 @@ -2177,26 +2177,26 @@ def _tb_parse_dump(mb: memhub.MemBuddy*, dump: str) -> TbDump | t.CPtr: # ============================================================ # 调用记录:u64 caller | u64 callee | u64 file | u32 line | u32 next(组内下一个, NONE=尾) -TB_CR_SIZE: t.CDefine = 32 -TB_CR_OFF_CALLER: t.CDefine = 0 -TB_CR_OFF_CALLEE: t.CDefine = 8 -TB_CR_OFF_FILE: t.CDefine = 16 -TB_CR_OFF_LINE: t.CDefine = 24 -TB_CR_OFF_NEXT: t.CDefine = 28 +define TB_CR_SIZE = 32 +define TB_CR_OFF_CALLER = 0 +define TB_CR_OFF_CALLEE = 8 +define TB_CR_OFF_FILE = 16 +define TB_CR_OFF_LINE = 24 +define TB_CR_OFF_NEXT = 28 # 函数记录:u64 sym | u64 file | u32 defline | u32 pad -TB_FR_SIZE: t.CDefine = 24 -TB_FR_OFF_SYM: t.CDefine = 0 -TB_FR_OFF_FILE: t.CDefine = 8 -TB_FR_OFF_DEFLINE: t.CDefine = 16 +define TB_FR_SIZE = 24 +define TB_FR_OFF_SYM = 0 +define TB_FR_OFF_FILE = 8 +define TB_FR_OFF_DEFLINE = 16 # 组哈希槽(以 (caller,callee) 为键;开放寻址 + 线性探测): # u64 caller | u64 callee | u32 used | u32 head | u32 tail | u32 cursor -TB_GRP_SIZE: t.CDefine = 32 -TB_GRP_OFF_CALLER: t.CDefine = 0 -TB_GRP_OFF_CALLEE: t.CDefine = 8 -TB_GRP_OFF_USED: t.CDefine = 16 -TB_GRP_OFF_HEAD: t.CDefine = 20 -TB_GRP_OFF_TAIL: t.CDefine = 24 -TB_GRP_OFF_CURSOR: t.CDefine = 28 +define TB_GRP_SIZE = 32 +define TB_GRP_OFF_CALLER = 0 +define TB_GRP_OFF_CALLEE = 8 +define TB_GRP_OFF_USED = 16 +define TB_GRP_OFF_HEAD = 20 +define TB_GRP_OFF_TAIL = 24 +define TB_GRP_OFF_CURSOR = 28 # 无效索引哨兵(u32 全 1) TB_IDX_NONE: uint64 = 0xFFFFFFFF @@ -2258,8 +2258,8 @@ def _tb_grp_get(grp: bytes, cap: int, caller: str, callee: str, do_insert: int) 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, t.CUInt64T(caller)) - _tb_wr_u64(grp, off + TB_GRP_OFF_CALLEE, t.CUInt64T(callee)) + _tb_wr_u64(grp, off + TB_GRP_OFF_CALLER, uint64(caller)) + _tb_wr_u64(grp, off + TB_GRP_OFF_CALLEE, uint64(callee)) _tb_wr_u32(grp, off + TB_GRP_OFF_HEAD, uint64(TB_IDX_NONE)) _tb_wr_u32(grp, off + TB_GRP_OFF_TAIL, uint64(TB_IDX_NONE)) _tb_wr_u32(grp, off + TB_GRP_OFF_CURSOR, uint64(TB_IDX_NONE)) @@ -2273,8 +2273,8 @@ def _tb_grp_get(grp: bytes, cap: int, caller: str, callee: str, do_insert: int) return -1 -def _tb_cp_init(mb: memhub.MemBuddy*) -> TbCallParse | t.CPtr: - cp: TbCallParse | t.CPtr = TbCallParse() +def _tb_cp_init(mb: memhub.MemBuddy*) -> TbCallParse*: + cp: TbCallParse* = TbCallParse() if cp is None: return None cp.CrCap = 1024 @@ -2288,7 +2288,7 @@ def _tb_cp_init(mb: memhub.MemBuddy*) -> TbCallParse | t.CPtr: return cp -def _tb_cp_add_cr(mb: memhub.MemBuddy*, cp: TbCallParse | t.CPtr, +def _tb_cp_add_cr(mb: memhub.MemBuddy*, cp: TbCallParse*, caller: str, callee: str, file: str, line: int) -> int: if cp.CrN >= cp.CrCap: ncap: int = cp.CrCap * 2 @@ -2299,16 +2299,16 @@ def _tb_cp_add_cr(mb: memhub.MemBuddy*, cp: TbCallParse | t.CPtr, cp.Cr = nb cp.CrCap = ncap off: sizet = sizet(cp.CrN) * TB_CR_SIZE - _tb_wr_u64(cp.Cr, off + TB_CR_OFF_CALLER, t.CUInt64T(caller)) - _tb_wr_u64(cp.Cr, off + TB_CR_OFF_CALLEE, t.CUInt64T(callee)) - _tb_wr_u64(cp.Cr, off + TB_CR_OFF_FILE, t.CUInt64T(file)) + _tb_wr_u64(cp.Cr, off + TB_CR_OFF_CALLER, uint64(caller)) + _tb_wr_u64(cp.Cr, off + TB_CR_OFF_CALLEE, uint64(callee)) + _tb_wr_u64(cp.Cr, off + TB_CR_OFF_FILE, uint64(file)) _tb_wr_u32(cp.Cr, off + TB_CR_OFF_LINE, uint64(line)) _tb_wr_u32(cp.Cr, off + TB_CR_OFF_NEXT, uint64(TB_IDX_NONE)) cp.CrN = cp.CrN + 1 return 0 -def _tb_cp_add_fr(mb: memhub.MemBuddy*, cp: TbCallParse | t.CPtr, +def _tb_cp_add_fr(mb: memhub.MemBuddy*, cp: TbCallParse*, sym: str, file: str, defline: int) -> int: if cp.FrN >= cp.FrCap: ncap: int = cp.FrCap * 2 @@ -2319,8 +2319,8 @@ def _tb_cp_add_fr(mb: memhub.MemBuddy*, cp: TbCallParse | t.CPtr, cp.Fr = nb cp.FrCap = ncap off: sizet = sizet(cp.FrN) * TB_FR_SIZE - _tb_wr_u64(cp.Fr, off + TB_FR_OFF_SYM, t.CUInt64T(sym)) - _tb_wr_u64(cp.Fr, off + TB_FR_OFF_FILE, t.CUInt64T(file)) + _tb_wr_u64(cp.Fr, off + TB_FR_OFF_SYM, uint64(sym)) + _tb_wr_u64(cp.Fr, off + TB_FR_OFF_FILE, uint64(file)) _tb_wr_u32(cp.Fr, off + TB_FR_OFF_DEFLINE, uint64(defline)) cp.FrN = cp.FrN + 1 return 0 @@ -2347,7 +2347,7 @@ def _tb_read_whole(mb: memhub.MemBuddy*, path: str) -> str: def _tb_parse_f_line(mb: memhub.MemBuddy*, s: str, a: sizet, b: sizet, - cp: TbCallParse | t.CPtr) -> int: + cp: TbCallParse*) -> int: """解析 `F\t\t\t`。""" p: sizet = a while p < b and _tb_cc(s, p) != 9: @@ -2376,7 +2376,7 @@ def _tb_parse_f_line(mb: memhub.MemBuddy*, s: str, a: sizet, b: sizet, def _tb_parse_c_line(mb: memhub.MemBuddy*, s: str, a: sizet, b: sizet, - cp: TbCallParse | t.CPtr) -> int: + cp: TbCallParse*) -> int: """解析 `C\t\t\t\t`。""" p: sizet = a while p < b and _tb_cc(s, p) != 9: @@ -2412,7 +2412,7 @@ def _tb_parse_c_line(mb: memhub.MemBuddy*, s: str, a: sizet, b: sizet, def _tb_parse_vpcall_file(mb: memhub.MemBuddy*, path: str, - cp: TbCallParse | t.CPtr) -> int: + cp: TbCallParse*) -> int: whole: str = _tb_read_whole(mb, path) if whole is None: VLogger.error(f"--traceback: 读取 .vpcall 失败:{path},终止编译", "TRACEBACK") @@ -2439,12 +2439,12 @@ def _tb_parse_vpcall_file(mb: memhub.MemBuddy*, path: str, return 0 -def _tb_load_vpcalls(mb: memhub.MemBuddy*, cp: TbCallParse | t.CPtr) -> int: +def _tb_load_vpcalls(mb: memhub.MemBuddy*, cp: TbCallParse*) -> int: if _tb_vpcall_buf is None or _tb_vpcall_n <= 0: return 0 k: int = 0 while k < _tb_vpcall_n: - slot: str | t.CPtr = (str | t.CPtr)(uint64(_tb_vpcall_buf) + sizet(k) * 8) + 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: @@ -2453,7 +2453,7 @@ def _tb_load_vpcalls(mb: memhub.MemBuddy*, cp: TbCallParse | t.CPtr) -> int: return 0 -def _tb_build_groups(mb: memhub.MemBuddy*, cp: TbCallParse | t.CPtr) -> int: +def _tb_build_groups(mb: memhub.MemBuddy*, cp: TbCallParse*) -> int: """把所有 C 记录按 (caller,callee) 串成组链表(组槽存 head/tail/cursor)。""" if cp.CrN <= 0: return 0 @@ -2486,8 +2486,8 @@ def _tb_build_groups(mb: memhub.MemBuddy*, cp: TbCallParse | t.CPtr) -> int: return 0 -def _tb_emit_call_row(mb: memhub.MemBuddy*, d: TbDump | t.CPtr, - cp: TbCallParse | t.CPtr, img_lo: uint64, +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: @@ -2508,8 +2508,8 @@ def _tb_emit_call_row(mb: memhub.MemBuddy*, d: TbDump | t.CPtr, return _tb_emit_row(mb, d, ret_va, file, line, caller) -def _tb_emit_entry_row(mb: memhub.MemBuddy*, d: TbDump | t.CPtr, - cp: TbCallParse | t.CPtr, img_lo: uint64, +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: @@ -2560,7 +2560,7 @@ def _tb_run_objdump(mb: memhub.MemBuddy*, exe_path: str) -> str: def _tb_scan_objdump(mb: memhub.MemBuddy*, dump: str, img_lo: uint64, - d: TbDump | t.CPtr, cp: TbCallParse | t.CPtr) -> int: + d: TbDump*, cp: TbCallParse*) -> int: """解析 `llvm-objdump -d` 文本,匹配 C/F 记录并把我方行写入 d。""" dlen: sizet = string.strlen(dump) pos: sizet = 0 @@ -2679,7 +2679,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: VLogger.error("--traceback: WriteStackMap 参数为空,终止编译", "TRACEBACK") return 1 - lay: TbPeLayout | t.CPtr = _tb_read_pe_layout(mb, exe_path) + lay: TbPeLayout* = _tb_read_pe_layout(mb, exe_path) if lay is None or lay.Ok == 0: VLogger.error(f"--traceback: 只支持 Windows PE 产物,但 {exe_path} 不是有效 PE(这是 --traceback 的要求)", "TRACEBACK") return 1 @@ -2710,7 +2710,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: VLogger.error("--traceback: llvm-dwarfdump 无输出,终止编译", "TRACEBACK") return 1 - d: TbDump | t.CPtr = _tb_parse_dump(mb, dump) + d: TbDump* = _tb_parse_dump(mb, dump) if d is None: return 1 @@ -2718,7 +2718,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: # DWARF 行仅覆盖链接进来的 mingw CRT(我方 .vp 函数无 .debug_line);这里用编译器 # 落盘的 .vpcall + objdump 反汇编补上「返回地址 → 调用点行 / 函数入口行」。 if _tb_vpcall_n > 0: - cp: TbCallParse | t.CPtr = _tb_cp_init(mb) + cp: TbCallParse* = _tb_cp_init(mb) if cp is None: VLogger.error("--traceback: 调用点解析状态分配失败,终止编译", "TRACEBACK") return 1 @@ -2876,7 +2876,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int: if nm0 is not None: pool_need += string.strlen(nm0) + 1 i += 1 - p: TbPool | t.CPtr = TbPool() + p: TbPool* = TbPool() if p is None: VLogger.error("--traceback: 字符串池对象分配失败,终止编译", "TRACEBACK") return 1 @@ -2990,7 +2990,7 @@ def run_pipeline(ir_buf: bytes, ir_len: sizet, temp_dir: str, output_dir: str, module_name: str, cc_cmd: str, cc_flags: str, linker_cmd: str, linker_flags: str, linker_output: str, - includes_binary_dir: str, linker_static_libs: str = None, linker_dynamic_libs: str = None) -> BuildResult | t.CPtr: + includes_binary_dir: str, linker_static_libs: str = None, linker_dynamic_libs: str = None) -> BuildResult*: """执行完整编译管线 Args: @@ -3010,7 +3010,7 @@ def run_pipeline(ir_buf: bytes, ir_len: sizet, Returns: BuildResult 对象 """ - result: BuildResult | t.CPtr = BuildResult() + result: BuildResult* = BuildResult() if result is None: return None diff --git a/App/lib/Phase/Phase1/Phase1Main.vp b/App/lib/Phase/Phase1/Phase1Main.vp index 434efe5..09c0fc6 100644 --- a/App/lib/Phase/Phase1/Phase1Main.vp +++ b/App/lib/Phase/Phase1/Phase1Main.vp @@ -508,7 +508,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, topo_order, topo_count_box, temp_dir, td_len_ts_call) if ret_topo == 0: - tc_ptr: t.CPtr = (int | t.CPtr)(topo_count_box) + tc_ptr: t.CPtr = (int*)(topo_count_box) if tc_ptr is not None: topo_count = tc_ptr[0] VLogger.info(f"拓扑排序: {class_count_scanned} 个类, {topo_count} 个文件按依赖顺序处理", "Phase1") @@ -551,7 +551,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, file_idx: int = i if topo_count > 0: od_addr: uint64 = uint64(topo_order) + i * 4 - od_ptr: t.CPtr = (int | t.CPtr)(t.CPtr(od_addr)) + od_ptr: t.CPtr = (int*)(t.CPtr(od_addr)) if od_ptr is not None: file_idx = od_ptr[0] @@ -839,7 +839,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, 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 | t.CPtr)(od_addr_b) + od_ptr_b: t.CPtr = (int*)(od_addr_b) 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 @@ -1101,8 +1101,8 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, # dump stub IR(declarations only) # 1MB 不够:ast/parser.vp 的 text.ll 超 1MB 被截断 → 合并 IR 尾部丢字 # (opt: "end of file in global variable name"),提至 8MB。 - PHASE1_IR_SIZE: sizet = 8388608 - # FULL dump = stub + text(同一模块),留 2× 余量 + PHASE1_IR_SIZE: sizet = 8388608 + # FULL dump = stub + text(同一模块),留 2× 余量 PHASE1_FULL_SIZE: sizet = 16777216 stub_buf: bytes = stdlib.malloc(PHASE1_IR_SIZE) if stub_buf is None: diff --git a/App/lib/Phase/Phase1/Phase1Scan.vp b/App/lib/Phase/Phase1/Phase1Scan.vp index 251536a..b16c2c6 100644 --- a/App/lib/Phase/Phase1/Phase1Scan.vp +++ b/App/lib/Phase/Phase1/Phase1Scan.vp @@ -154,12 +154,12 @@ def _ScanClassInheritance(mb: memhub.MemBuddy*, if tp_scan is not None: file_has_generic = 1 if generic_file_count_box is not None: - gfc_ptr_scan: t.CPtr = (int | t.CPtr)(generic_file_count_box) + gfc_ptr_scan: t.CPtr = (int*)(generic_file_count_box) if gfc_ptr_scan is not None: gfc_scan: int = gfc_ptr_scan[0] 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 | t.CPtr)(gi_addr_scan) + gi_ptr_scan: t.CPtr = (int*)(gi_addr_scan) if gi_ptr_scan is not None: gi_ptr_scan[0] = i gfc_ptr_scan[0] = gfc_scan + 1 @@ -405,7 +405,7 @@ def _FindClassDefSha1(class_names_buf: bytes, def_sha1s_buf: bytes, # _ScanTreeForContainers - 递归扫描 AST 检测 list/dict 容器使用 # # TPV 的 AST 中语句块挂在 children,而表达式/注解树全部以结构体字段挂载(value/slice/func/args/annotation/targets/returns/bases/left/right 等); -# 只递归 children 会漏掉 list[...] | t.CPtr、list[...](...)、字段注解等非语句块位置,故每个节点先递归表达式承载字段、再递归 children。 +# 只递归 children 会漏掉 list[...]*、list[...](...)、字段注解等非语句块位置,故每个节点先递归表达式承载字段、再递归 children。 # 命中即置 need_list/need_dict;误报无害(最多多编译两个空壳模块)。 # ============================================================ diff --git a/App/lib/Phase/Phase1/Phase1Topo.vp b/App/lib/Phase/Phase1/Phase1Topo.vp index f21e015..478f96d 100644 --- a/App/lib/Phase/Phase1/Phase1Topo.vp +++ b/App/lib/Phase/Phase1/Phase1Topo.vp @@ -141,7 +141,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, # 读取当前依赖数量 cnt_addr: uint64 = uint64(file_dep_counts) + fi * 4 - cnt_ptr: t.CPtr = (int | t.CPtr)(cnt_addr) + cnt_ptr: t.CPtr = (int*)(cnt_addr) if cnt_ptr is None: break cur_cnt: int = cnt_ptr[0] @@ -209,7 +209,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, 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 | t.CPtr)(cnt_addr_imp) + cnt_ptr_imp: t.CPtr = (int*)(cnt_addr_imp) if cnt_ptr_imp is None: break cur_cnt_imp: int = cnt_ptr_imp[0] @@ -235,9 +235,9 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, # 依赖为 0 的先处理,处理后减少依赖它的文件入度 for fi in range(file_count): cnt_addr3: uint64 = uint64(file_dep_counts) + fi * 4 - cnt_ptr3: t.CPtr = (int | t.CPtr)(cnt_addr3) + cnt_ptr3: t.CPtr = (int*)(cnt_addr3) ind_addr3: uint64 = uint64(file_indegrees) + fi * 4 - ind_ptr3: t.CPtr = (int | t.CPtr)(ind_addr3) + 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] @@ -249,12 +249,12 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, for fi in range(file_count): # 检查处理状态 proc_addr4: uint64 = uint64(file_processed) + fi * 4 - proc_ptr4: t.CPtr = (int | t.CPtr)(proc_addr4) + proc_ptr4: t.CPtr = (int*)(proc_addr4) if proc_ptr4 is None or proc_ptr4[0] != 0: continue # 检查入度 ind_addr4: uint64 = uint64(file_indegrees) + fi * 4 - ind_ptr4: t.CPtr = (int | t.CPtr)(ind_addr4) + ind_ptr4: t.CPtr = (int*)(ind_addr4) if ind_ptr4 is None or ind_ptr4[0] > 0: continue @@ -268,7 +268,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, if string.strcmp(ent_r.Sha1, target_sha1) == 0: # 写入输出索引数组 out_idx_addr: uint64 = uint64(out_order) + out_idx * 4 - out_int_ptr: t.CPtr = (int | t.CPtr)(out_idx_addr) + out_int_ptr: t.CPtr = (int*)(out_idx_addr) if out_int_ptr is not None: out_int_ptr[0] = ri out_idx += 1 @@ -281,12 +281,12 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, # 减少依赖该文件的其他文件的入度 for fj in range(file_count): proc_addr5: uint64 = uint64(file_processed) + fj * 4 - proc_ptr5: t.CPtr = (int | t.CPtr)(proc_addr5) + proc_ptr5: t.CPtr = (int*)(proc_addr5) 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 | t.CPtr)(cnt_addr5) + cnt_ptr5: t.CPtr = (int*)(cnt_addr5) if cnt_ptr5 is None: continue fj_dep_cnt: int = cnt_ptr5[0] @@ -294,7 +294,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, 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 | t.CPtr)(ind_addr5) + ind_ptr5: t.CPtr = (int*)(ind_addr5) if ind_ptr5 is not None: ind_ptr5[0] = ind_ptr5[0] - 1 break @@ -310,7 +310,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, if rem_idx is not None and rem_depcnt is not None: for fi in range(file_count): proc_addr7: uint64 = uint64(file_processed) + fi * 4 - proc_ptr7: t.CPtr = (int | t.CPtr)(proc_addr7) + proc_ptr7: t.CPtr = (int*)(proc_addr7) if proc_ptr7 is not None and proc_ptr7[0] == 0: rem_idx[rem_count] = fi rem_depcnt[rem_count] = 0 @@ -324,7 +324,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, if fi_b == fi_a: continue cnt_addr_b: uint64 = uint64(file_dep_counts) + fi_b * 4 - cnt_ptr_b: t.CPtr = (int | t.CPtr)(cnt_addr_b) + cnt_ptr_b: t.CPtr = (int*)(cnt_addr_b) if cnt_ptr_b is None: continue cnt_b: int = cnt_ptr_b[0] @@ -347,7 +347,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, for i_a in range(rem_count): fi_a2: int = rem_idx[i_a] proc_addr8: uint64 = uint64(file_processed) + fi_a2 * 4 - proc_ptr8: t.CPtr = (int | t.CPtr)(proc_addr8) + proc_ptr8: t.CPtr = (int*)(proc_addr8) if proc_ptr8 is None or proc_ptr8[0] != 0: continue target_sha1_2: str = file_sha1s_buf + fi_a2 * Phase1.SHA1_LEN @@ -357,7 +357,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, if ent_r2 is not None and ent_r2.Sha1 is not None: 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 | t.CPtr)(out_idx_addr2) + out_int_ptr2: t.CPtr = (int*)(out_idx_addr2) if out_int_ptr2 is not None: out_int_ptr2[0] = ri out_idx += 1 @@ -367,7 +367,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, stdlib.free(rem_depcnt) # 写入输出数量 - out_count_ptr: t.CPtr = (int | t.CPtr)(out_count) + out_count_ptr: t.CPtr = (int*)(out_count) if out_count_ptr is not None: out_count_ptr[0] = out_idx diff --git a/App/lib/Phase/Phase1/__init__.vp b/App/lib/Phase/Phase1/__init__.vp index 69ceea2..d3eb948 100644 --- a/App/lib/Phase/Phase1/__init__.vp +++ b/App/lib/Phase/Phase1/__init__.vp @@ -6,14 +6,14 @@ import memhub _mbuddy: memhub.MemBuddy* # 源代码缓冲区大小(1MB) -SRC_BUF_SIZE: t.CDefine = 1048576 +define SRC_BUF_SIZE = 1048576 # vpi 缓冲区大小(256KB) PYI_BUF_SIZE: sizet = 262144 # 拓扑排序相关常量 -MAX_CLASSES: t.CDefine = 512 -MAX_FILE_DEPS: t.CDefine = 256 -MAX_DEP_EDGES: t.CDefine = 16 -SHA1_LEN: t.CDefine = 17 -CLASS_NAME_LEN: t.CDefine = 64 +define MAX_CLASSES = 512 +define MAX_FILE_DEPS = 256 +define MAX_DEP_EDGES = 16 +define SHA1_LEN = 17 +define CLASS_NAME_LEN = 64 diff --git a/App/lib/Phase/Phase2/__init__.vp b/App/lib/Phase/Phase2/__init__.vp index 1d52326..32d2121 100644 --- a/App/lib/Phase/Phase2/__init__.vp +++ b/App/lib/Phase/Phase2/__init__.vp @@ -33,10 +33,10 @@ import lib.Stub.StubGen.Converter as StubConverter _mbuddy: memhub.MemBuddy* # 源代码缓冲区大小(1MB) -SRC_BUF_SIZE: t.CDefine = 1048576 +define SRC_BUF_SIZE = 1048576 # 最大源文件数(递归扫描子目录后文件数增多;过小会截断文件列表 → 链接 undefined symbol,故留余量) -MAX_SRC_FILES: t.CDefine = 128 +define MAX_SRC_FILES = 128 @t.NoVTable class SrcFileEntry: @@ -52,7 +52,7 @@ class SrcFileEntry: # ============================================================ def _ScanDirForPyFiles(mb: memhub.MemBuddy*, dir_path: str, - entries: SrcFileEntry | t.CPtr, + entries: SrcFileEntry*, entry_size: sizet, file_count: int, max_files: int) -> int: """递归扫描目录,收集 .vp/.py 文件到 entries,返回新的 file_count""" @@ -68,7 +68,7 @@ def _ScanDirForPyFiles(mb: memhub.MemBuddy*, viperlib.snprintf(pattern, dir_len + 16, "%s/*", dir_path) find_data_size: sizet = w32.win32file.WIN32_FIND_DATAA.__sizeof__() - find_data: w32.win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(find_data_size + 16) + find_data: w32.win32file.WIN32_FIND_DATAA* = stdlib.malloc(find_data_size + 16) if find_data is None: stdlib.free(pattern) return file_count @@ -130,7 +130,7 @@ def _ScanDirForPyFiles(mb: memhub.MemBuddy*, sha1_val: str = IncludesScanner.compute_file_sha1(mb, full_path) if sha1_val is not None: ea: uint64 = uint64(entries) + file_count * entry_size - ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(ea) + ent: SrcFileEntry* = (SrcFileEntry*)(ea) if ent is not None: ent.Path = full_path ent.Sha1 = sha1_val @@ -158,7 +158,7 @@ def _ScanDirForPyFiles(mb: memhub.MemBuddy*, # ============================================================ def _ScanDirForAsmFiles(mb: memhub.MemBuddy*, dir_path: str, - entries: SrcFileEntry | t.CPtr, + entries: SrcFileEntry*, entry_size: sizet, file_count: int, max_files: int) -> int: """递归扫描目录,收集 .s 汇编文件到 entries,返回新的 file_count""" @@ -174,7 +174,7 @@ def _ScanDirForAsmFiles(mb: memhub.MemBuddy*, viperlib.snprintf(pattern, dir_len + 16, "%s/*", dir_path) find_data_size: sizet = w32.win32file.WIN32_FIND_DATAA.__sizeof__() - find_data: w32.win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(find_data_size + 16) + find_data: w32.win32file.WIN32_FIND_DATAA* = stdlib.malloc(find_data_size + 16) if find_data is None: stdlib.free(pattern) return file_count @@ -231,7 +231,7 @@ def _ScanDirForAsmFiles(mb: memhub.MemBuddy*, sha1_val: str = IncludesScanner.compute_file_sha1(mb, full_path) if sha1_val is not None: ea: uint64 = uint64(entries) + file_count * entry_size - ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(ea) + ent: SrcFileEntry* = (SrcFileEntry*)(ea) if ent is not None: ent.Path = full_path ent.Sha1 = sha1_val @@ -257,7 +257,7 @@ def _ScanDirForAsmFiles(mb: memhub.MemBuddy*, # 重复注册由 _register_generic_template 查重跳过。 # ============================================================ def _PreRegisterAppGenericTemplates(mb: memhub.MemBuddy*, - entries: SrcFileEntry | t.CPtr, + entries: SrcFileEntry*, file_count: int, entry_size: sizet) -> int: """mark2 前预注册 App 源文件的泛型类模板,返回处理到的泛型类数量""" @@ -266,7 +266,7 @@ def _PreRegisterAppGenericTemplates(mb: memhub.MemBuddy*, handled: int = 0 for i in range(file_count): ea_pa: uint64 = uint64(entries) + i * entry_size - ent_pa: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(ea_pa) + ent_pa: SrcFileEntry* = (SrcFileEntry*)(ea_pa) if ent_pa is None or ent_pa.Path is None or ent_pa.Sha1 is None: continue # 读取文件 @@ -643,7 +643,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, # === 1. 递归扫描 source_dir 下的 .vp/.py 文件(包括子目录)=== entry_size: sizet = SrcFileEntry.__sizeof__() - entries: SrcFileEntry | t.CPtr = stdlib.malloc(MAX_SRC_FILES * entry_size) + entries: SrcFileEntry* = stdlib.malloc(MAX_SRC_FILES * entry_size) if entries is None: return 1 string.memset(entries, 0, MAX_SRC_FILES * entry_size) @@ -652,7 +652,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, VLogger.info(f"共 {file_count} 个源文件", "project") # 扫描 .s 汇编文件(独立数组,不参与 Phase A 翻译,Phase B 后 llvm-mc 汇编) - asm_entries: SrcFileEntry | t.CPtr = stdlib.malloc(MAX_SRC_FILES * entry_size) + asm_entries: SrcFileEntry* = stdlib.malloc(MAX_SRC_FILES * entry_size) if asm_entries is None: stdlib.free(entries) return 1 @@ -717,7 +717,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, app_filled: int = 0 for i in range(file_count): ea_am: uint64 = uint64(entries) + i * entry_size - ent_am: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(ea_am) + ent_am: SrcFileEntry* = (SrcFileEntry*)(ea_am) if ent_am is None or ent_am.Path is None or ent_am.Sha1 is None: continue # 计算相对路径(去除 source_dir 前缀,保留目录结构) @@ -759,7 +759,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, vpi_failed_p2: int = 0 for i_vp2 in range(file_count): ea_vp2: uint64 = uint64(entries) + i_vp2 * entry_size - ent_vp2: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(ea_vp2) + ent_vp2: SrcFileEntry* = (SrcFileEntry*)(ea_vp2) if ent_vp2 is None or ent_vp2.Path is None or ent_vp2.Sha1 is None: vpi_failed_p2 += 1 VLogger.error("[Phase A-pre-vpi] 源文件条目无效(Path/Sha1 缺失),跳过", "PhaseA") @@ -890,7 +890,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, is_app_file_inc: int = 0 for i_app_inc in range(file_count): ea_app_inc: uint64 = uint64(entries) + i_app_inc * entry_size - ent_app_inc: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(ea_app_inc) + ent_app_inc: SrcFileEntry* = (SrcFileEntry*)(ea_app_inc) if ent_app_inc is not None and ent_app_inc.Sha1 is not None \ and string.strcmp(ent_app_inc.Sha1, inc_sha1_pre) == 0: is_app_file_inc = 1 @@ -951,18 +951,18 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, struct_count_before: int = GenApi.get_struct_count() for i in range(file_count): ea_pre: uint64 = uint64(entries) + i * entry_size - ent_pre: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(ea_pre) + ent_pre: SrcFileEntry* = (SrcFileEntry*)(ea_pre) 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 pkg_pre = GenApi.compute_package_from_relpath(mb, rel_path_pre) - # App 预注册传 pre_allow_dep_inject=1:声明期也做导入处理 + 依赖 vpi 注入, - # 使类字段注解在预注册期即与阶段 A 同上下文(否则包重导出类 - # list[ast.ClassDef*] 的票名前缀会在预注册期被冻结成包前缀,与阶段 A - # 解析出的真定义前缀分裂 → 结构体布局不兼容,见 Translator 字段说明)。 - tr_pre: rawptr[HandlesTranslator.Translator] = BuildPipeline.TranslateFileGetTrans( + # App 预注册传 pre_allow_dep_inject=1:声明期也做导入处理 + 依赖 vpi 注入, + # 使类字段注解在预注册期即与阶段 A 同上下文(否则包重导出类 + # list[ast.ClassDef*] 的票名前缀会在预注册期被冻结成包前缀,与阶段 A + # 解析出的真定义前缀分裂 → 结构体布局不兼容,见 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") @@ -1009,7 +1009,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, if done_flags[i] != 0: continue ea: uint64 = uint64(entries) + i * entry_size - ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(ea) + ent: SrcFileEntry* = (SrcFileEntry*)(ea) # 计时点 0:本文件处理开始(translate 段起点) t_pa0: uint64 = w32.win32base.GetTickCount64() if ent is None or ent.Path is None: @@ -1159,7 +1159,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, for i_err in range(file_count): if done_flags[i_err] == 0: ea_err: uint64 = uint64(entries) + i_err * entry_size - ent_err: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(ea_err) + 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) @@ -1214,7 +1214,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, for i in range(file_count): ea: uint64 = uint64(entries) + i * entry_size - ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(ea) + ent: SrcFileEntry* = (SrcFileEntry*)(ea) if ent is None or ent.Path is None or ent.Sha1 is None: continue # 单文件三步计时起点(GetTickCount64,ms) @@ -1310,7 +1310,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, asm_compiled: int = 0 for ai_as in range(asm_file_count): ea_as: uint64 = uint64(asm_entries) + ai_as * entry_size - ent_as: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(ea_as) + ent_as: SrcFileEntry* = (SrcFileEntry*)(ea_as) 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( @@ -1380,7 +1380,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, stdlib.free(app_deps_buf) app_deps_buf = None - # 从全局存储器获取 SHA1/模块名 数组:复制局部副本(bytes),避免 store 联合返回值(bytes|t.CPtr)跨函数传参/索引的地址异常。 + # 从全局存储器获取 SHA1/模块名 数组:复制局部副本(bytes),避免 store 联合返回值(bytes*)跨函数传参/索引的地址异常。 # rel/incdir 仅本函数内按索引读取(不跨函数传参),保留 store 指针。 td_len_pb: sizet = string.strlen(temp_dir) store_sha1_arr_mi: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 17) @@ -1416,7 +1416,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, app_skip_mi: int = 0 for ai_mi in range(file_count): ea_ap: uint64 = uint64(entries) + ai_mi * entry_size - ent_ap: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(ea_ap) + ent_ap: SrcFileEntry* = (SrcFileEntry*)(ea_ap) if ent_ap is not None and ent_ap.Sha1 is not None: if string.strcmp(ent_ap.Sha1, inc_sha1_mi) == 0: app_skip_mi = 1 @@ -1426,7 +1426,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, # 检查 .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") - check_fd_mi: w32.win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(w32.win32file.WIN32_FIND_DATAA.__sizeof__()) + check_fd_mi: w32.win32file.WIN32_FIND_DATAA* = stdlib.malloc(w32.win32file.WIN32_FIND_DATAA.__sizeof__()) obj_exists_mi: int = 0 if check_pat_mi is not None and check_fd_mi is not None: string.memset(check_fd_mi, 0, w32.win32file.WIN32_FIND_DATAA.__sizeof__()) @@ -1529,12 +1529,12 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, ifff.write(inc_full_buf, inc_full_len) ifff.close() stdlib.free(inc_full_path) - stdlib.free(inc_full_buf) - # --traceback: 取出本模块的调试调用点记录并写 .vpcall。 - if BuildPipeline._traceback_mode != 0: - vpcall_text_mi: str = mlirlite.DebugTakeText() - if vpcall_text_mi is not None: - BuildPipeline.WriteCallSidecar(temp_dir, inc_sha1_mi, vpcall_text_mi) + stdlib.free(inc_full_buf) + # --traceback: 取出本模块的调试调用点记录并写 .vpcall。 + if BuildPipeline._traceback_mode != 0: + vpcall_text_mi: str = mlirlite.DebugTakeText() + if vpcall_text_mi is not None: + BuildPipeline.WriteCallSidecar(temp_dir, inc_sha1_mi, vpcall_text_mi) stdlib.free(vpcall_text_mi) # 重试读 full.ll inc_combined_len_mi = StubMergerBuild.LoadFullIR(temp_dir, inc_sha1_mi, inc_combined_mi, COMBINED_IR_SIZE) @@ -1683,7 +1683,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, app_skip_pc: int = 0 for ai_pc in range(file_count): ea_pc: uint64 = uint64(entries) + ai_pc * entry_size - ent_pc: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(ea_pc) + ent_pc: SrcFileEntry* = (SrcFileEntry*)(ea_pc) if ent_pc is not None and ent_pc.Sha1 is not None: if string.strcmp(ent_pc.Sha1, rsha1_pc) == 0: app_skip_pc = 1 diff --git a/App/lib/Projectrans/Config.vp b/App/lib/Projectrans/Config.vp index 6e220bb..3c35285 100644 --- a/App/lib/Projectrans/Config.vp +++ b/App/lib/Projectrans/Config.vp @@ -88,75 +88,75 @@ def Load_project_config(path: str) -> int: if bytes_read <= 0: return 1 # 解析 JSON - root: JsonValue | t.CPtr = json_parse(_mbuddy, buf) + root: JsonValue* = json_parse(_mbuddy, buf) if root is None: return 1 if not root.is_object(): return 1 # 读取顶层字段(使用显式 __getitem__ 调用,兼容旧编译器二进制) - sd_val: JsonValue | t.CPtr = root["source_dir"] + sd_val: JsonValue* = root["source_dir"] SourceDir = sd_val.as_string() if sd_val is not None else None # build_dir: 统一构建目录(默认 ./.tpv_build),temp 和 output 作为其子目录 - bd_val: JsonValue | t.CPtr = root["build_dir"] + 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" - name_val: JsonValue | t.CPtr = root["name"] + name_val: JsonValue* = root["name"] ProjectName = name_val.as_string() if name_val is not None else None - ver_val: JsonValue | t.CPtr = root["version"] + ver_val: JsonValue* = root["version"] ProjectVersion = ver_val.as_string() if ver_val is not None else None # 读取 compiler 子对象 - compiler: JsonValue | t.CPtr = root["compiler"] + compiler: JsonValue* = root["compiler"] if compiler is not None and compiler.is_object(): - cc_cmd_val: JsonValue | t.CPtr = compiler["cmd"] + cc_cmd_val: JsonValue* = compiler["cmd"] CompilerCmd = cc_cmd_val.as_string() if cc_cmd_val is not None else None # 读取 compiler.flags 数组,拼接成空格分隔的字符串 - cc_flags_val: JsonValue | t.CPtr = compiler["flags"] + cc_flags_val: JsonValue* = compiler["flags"] CompilerFlags = _join_flags_array(cc_flags_val) # 读取 linker 子对象 - linker: JsonValue | t.CPtr = root["linker"] + linker: JsonValue* = root["linker"] if linker is not None and linker.is_object(): - ld_cmd_val: JsonValue | t.CPtr = linker["cmd"] + ld_cmd_val: JsonValue* = linker["cmd"] LinkerCmd = ld_cmd_val.as_string() if ld_cmd_val is not None else None - ld_out_val: JsonValue | t.CPtr = linker["output"] + ld_out_val: JsonValue* = linker["output"] LinkerOutput = ld_out_val.as_string() if ld_out_val is not None else None # 读取 linker.flags 数组,拼接成空格分隔的字符串 - ld_flags_val: JsonValue | t.CPtr = linker["flags"] + ld_flags_val: JsonValue* = linker["flags"] LinkerFlags = _join_flags_array(ld_flags_val) # 读取 linker.static_libs 数组:显式静态链接文件(.a/.obj), # 先拼接原样字符串,resolve_paths 中再基于 project_dir 解析绝对路径 - sl_val: JsonValue | t.CPtr = linker["static_libs"] + sl_val: JsonValue* = linker["static_libs"] LinkerStaticLibs = _join_flags_array(sl_val) # 读取 linker.dynamic_libs 数组:显式动态链接文件(.dll/.so), # 同样先拼接原样字符串,resolve_paths 中基于 project_dir 解析绝对路径 - dl_val: JsonValue | t.CPtr = linker["dynamic_libs"] + dl_val: JsonValue* = linker["dynamic_libs"] LinkerDynamicLibs = _join_flags_array(dl_val) # 读取 target 子对象 - target: JsonValue | t.CPtr = root["target"] + target: JsonValue* = root["target"] if target is not None and target.is_object(): - tgt_triple_val: JsonValue | t.CPtr = target["triple"] + tgt_triple_val: JsonValue* = target["triple"] TargetTriple = tgt_triple_val.as_string() if tgt_triple_val is not None else None - tgt_dl_val: JsonValue | t.CPtr = target["datalayout"] + tgt_dl_val: JsonValue* = target["datalayout"] TargetDataLayout = tgt_dl_val.as_string() if tgt_dl_val is not None else None # 读取 options 子对象 # Sha1SliceLevel: SHA1 切片层数(默认 1,每层取 SHA1 前 2 字符作为子目录:0=不切片, 1=b7/, 2=b7/90/) - options: JsonValue | t.CPtr = root["options"] + options: JsonValue* = root["options"] Sha1SliceLevel = 1 StrictMode = 1 if options is not None and options.is_object(): - sl: JsonValue | t.CPtr = options["sha1_slice_level"] + sl: JsonValue* = options["sha1_slice_level"] if sl is not None and sl.is_int(): Sha1SliceLevel = sl.as_int() - sm: JsonValue | t.CPtr = options["strict_mode"] + sm: JsonValue* = options["strict_mode"] if sm is not None and sm.is_bool(): StrictMode = 1 if sm.as_bool() else 0 # 读取 includes 数组(支持多目录:首元素存 IncludesDir,全部拼接存 IncludesDirs) - includes_val: JsonValue | t.CPtr = root["includes"] + includes_val: JsonValue* = root["includes"] if includes_val is not None and includes_val.is_array(): arr_len: sizet = len(includes_val) inc_buf: bytes = stdlib.malloc(2048) @@ -164,7 +164,7 @@ def Load_project_config(path: str) -> int: inc_buf[0] = '\0' inc_pos: sizet = 0 for inc_i in range(arr_len): - inc_item: JsonValue | t.CPtr = includes_val.get_item(inc_i) + inc_item: JsonValue* = includes_val.get_item(inc_i) if inc_item is None or not inc_item.is_string(): continue inc_str: str = inc_item.as_string() @@ -186,7 +186,7 @@ def Load_project_config(path: str) -> int: return 0 -def _join_flags_array(flags_val: JsonValue | t.CPtr) -> str: +def _join_flags_array(flags_val: JsonValue*) -> str: """将 JSON 字符串数组拼接成空格分隔的字符串 用于 linker.flags 和 compiler.flags 数组。 @@ -208,7 +208,7 @@ def _join_flags_array(flags_val: JsonValue | t.CPtr) -> str: # 第一遍:计算总长度(所有 flag 长度 + 空格分隔符) total_len: sizet = 0 for i in range(arr_len): - item: JsonValue | t.CPtr = flags_val.get_item(i) + item: JsonValue* = flags_val.get_item(i) if item is not None and item.is_string(): s: str = item.as_string() if s is not None: diff --git a/App/lib/Projectrans/Utils.vp b/App/lib/Projectrans/Utils.vp index cdd09c3..049dfb9 100644 --- a/App/lib/Projectrans/Utils.vp +++ b/App/lib/Projectrans/Utils.vp @@ -207,7 +207,7 @@ def CleanDir(dir_path: str) -> int: return -1 viperlib.snprintf(pattern, dir_len + 8, "%s/*", dir_path) - find_data: w32.win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(w32.win32file.WIN32_FIND_DATAA.__sizeof__()) + find_data: w32.win32file.WIN32_FIND_DATAA* = stdlib.malloc(w32.win32file.WIN32_FIND_DATAA.__sizeof__()) if find_data is None: stdlib.free(pattern) return -1 diff --git a/App/lib/Stub/StubGen/Converter.vp b/App/lib/Stub/StubGen/Converter.vp index 745cc74..46d899c 100644 --- a/App/lib/Stub/StubGen/Converter.vp +++ b/App/lib/Stub/StubGen/Converter.vp @@ -104,8 +104,8 @@ _g_pyi_cdefine_found: int = 0 # 本文件 CDefine 值缓存(vpi 生成专用):vpi 生成早于翻译阶段注册(全局表为空),_GeneratePyiFromAst 开头按声明顺序注册,Name 引用先查本缓存。 # 两个缓存必须是 C 数组(int64* / i8**)而非 list[T]——list[int].get 会误解析为 list[str].get(返回元素地址)、list[str] 联合接收者的 .get 会误分派为 HashTable.get(索引 inttoptr 成 key 指针 → 零页崩溃);索引一律用 t.CPtr(base + i*8) + e[0]。 -_g_pyi_cdef_names: str | t.CPtr = None -_g_pyi_cdef_vals: int64 | t.CPtr = None +_g_pyi_cdef_names: str* = None +_g_pyi_cdef_vals: int64* = None _g_pyi_cdef_count: int = 0 @@ -117,7 +117,7 @@ def _lookup_cdefine_for_pyi(name: str) -> int64: # 循环上限用 _g_pyi_cdef_count,且绝不能用 len()/.get:i8** 指针数组上 len() 回退 strlen(基址当字符串算长度 → 垃圾小值 → 靠后注册项查不到),.get 会被误分派为 HashTable.get(索引 inttoptr 成 key 指针 → 零页崩溃);用 t.CPtr(base + i*8) + e[0] 依次取名。 pn: sizet = sizet(_g_pyi_cdef_count) for pi in range(pn): - entry_pc: str | t.CPtr = (str | t.CPtr)(uint64(_g_pyi_cdef_names) + pi * 8) + entry_pc: str* = (str*)(uint64(_g_pyi_cdef_names) + pi * 8) pnm: str = entry_pc[0] if pnm is not None and string.strcmp(pnm, name) == 0: _g_pyi_cdefine_found = 1 @@ -310,7 +310,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, if k == ast.ASTKind.Compare: cmp_t: rawptr[ast.Compare] = rawptr[ast.Compare](annot) pos = _PyiTypeStr(buf, buf_size, pos, cmp_t.left, depth + 1) - ops_ct: list[int] | t.CPtr = (list[int] | t.CPtr)(cmp_t.ops) + ops_ct: list[int]* = (list[int]*)(cmp_t.ops) cmps_ct: list[ast.AST*]* = cmp_t.comparators if ops_ct is not None: on_ct: sizet = len(ops_ct) @@ -826,8 +826,8 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, 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 | t.CPtr)(mb.alloc(sizet(_g_pyi_cdef_count) * 8)) - _g_pyi_cdef_vals = (int64 | t.CPtr)(mb.alloc(sizet(_g_pyi_cdef_count) * 8)) + _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)) # 第二遍:按声明顺序注册(BinOp 内 Name 引用依赖先前注册项) pci: sizet = 0 cdi: int = 0 @@ -842,7 +842,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, ann_pc: ast.Attribute* = ast.Attribute*(aa_pc.annotation) if ann_pc.attr is not None and string.strcmp(ann_pc.attr, "CDefine") == 0: if _g_pyi_cdef_names is not None and _g_pyi_cdef_vals is not None: - slot_pc: str | t.CPtr = (str | t.CPtr)(uint64(_g_pyi_cdef_names) + cdi * 8) + slot_pc: str* = (str*)(uint64(_g_pyi_cdef_names) + cdi * 8) slot_pc[0] = tgt_pc.id _g_pyi_cdef_vals[cdi] = _eval_cdefine_value_cache(aa_pc.value) cdi += 1 @@ -1159,7 +1159,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, if inferred == 1: pos = _PyiEmit(buf, buf_size, pos, "int") elif inferred == 2: - pos = _PyiEmit(buf, buf_size, pos, "t.CDouble") + pos = _PyiEmit(buf, buf_size, pos, "double") elif inferred == 3: pos = _PyiEmit(buf, buf_size, pos, "str") elif inferred == 4: diff --git a/App/lib/Stub/StubGen/VpiReader.vp b/App/lib/Stub/StubGen/VpiReader.vp index cdaf662..4244010 100644 --- a/App/lib/Stub/StubGen/VpiReader.vp +++ b/App/lib/Stub/StubGen/VpiReader.vp @@ -26,7 +26,7 @@ import lib.Projectrans.Config as Config # 该机制仅在 ReplStubLayoutMode != 0(REPL 会话初始化)时生效,批处理恒 0。 # ============================================================ -_REPL_STUB_CLS_MAX: t.CDefine = 1024 +define _REPL_STUB_CLS_MAX = 1024 _REPL_STUB_FIELD_MAX: int = 128 _REPL_STUB_VT_MAX: int = 128 _REPL_STUB_TXT_CAP: sizet = 4194304 @@ -42,22 +42,22 @@ _REPL_STUB_NOCOUNT_OPAQUE: int = -2 # meta 里该 key 是 OPAQUE(无 body # 布局"不可用 ⇒ 明确拒绝"的原因码(_repl_stub_warn_nodata):把"数据缺失" # (上层数据没到位,补 meta/重跑即可消除)与"判据拒绝"(数据在但不可信,绝不放行) # 在文案与汇总计数上分开 —— 两类都会走到"不登记 StructEntry",但成因完全不同。 -_REPL_SU_NOSTUB: t.CDefine = 1 # 数据缺失:整个模块没有 {sha1}.meta -_REPL_SU_NOCLASS: t.CDefine = 2 # 判据拒绝:meta 存在但无该类的 STRUCT 行 -_REPL_SU_OPAQUE: t.CDefine = 3 # 判据拒绝:meta 里该类为 OPAQUE(无 body) -_REPL_SU_PARENT: t.CDefine = 4 # 上游无数据:父类布局不可用/未在会话注册(走 _repl_stub_warn_parent) +define _REPL_SU_NOSTUB = 1 # 数据缺失:整个模块没有 {sha1}.meta +define _REPL_SU_NOCLASS = 2 # 判据拒绝:meta 存在但无该类的 STRUCT 行 +define _REPL_SU_OPAQUE = 3 # 判据拒绝:meta 里该类为 OPAQUE(无 body) +define _REPL_SU_PARENT = 4 # 上游无数据:父类布局不可用/未在会话注册(走 _repl_stub_warn_parent) # ReplStubClass.Flags / MethodFlags 位 -_REPL_SF_CVTABLE: t.CDefine = 1 -_REPL_SF_NOVTABLE: t.CDefine = 2 -_REPL_SF_ANYFUNC: t.CDefine = 4 -_REPL_SF_PACKED: t.CDefine = 8 +define _REPL_SF_CVTABLE = 1 +define _REPL_SF_NOVTABLE = 2 +define _REPL_SF_ANYFUNC = 4 +define _REPL_SF_PACKED = 8 # ReplStubClass.State -_REPL_SS_REFUSED: t.CDefine = 0 # 布局不可信:永不登记(字段访问明确失败) -_REPL_SS_OK: t.CDefine = 1 # 完整布局已登记 -_REPL_SS_PENDING: t.CDefine = 2 # 父类尚未就绪:留待收尾遍 -_REPL_SS_EMPTY: t.CDefine = 3 # 无父类/无虚表/字段类型不可解析:交既有 vpi 注入口径 +define _REPL_SS_REFUSED = 0 # 布局不可信:永不登记(字段访问明确失败) +define _REPL_SS_OK = 1 # 完整布局已登记 +define _REPL_SS_PENDING = 2 # 父类尚未就绪:留待收尾遍 +define _REPL_SS_EMPTY = 3 # 无父类/无虚表/字段类型不可解析:交既有 vpi 注入口径 class ReplStubClass: Key: str # ".<类名>"(= 定义侧命名结构体名) @@ -97,9 +97,9 @@ class ReplStubClass: # 故改文本提取:ParseVpiIntoModule 读 .vpi stub 时从 vpi_buf 原始文本(函数末尾才释放,始终有效)按行提取 "def m(...) -> Ret:" 的返回注解字符串缓存到 stdlib(持久,不受 pool 状态影响); # HandlesExprCall._lookup_method_ret_ty_via_vpi 按 sha1.类名.方法名 查表并用 _resolve_vpi_ret_annot_str 纯字符串解析为 LLVMType,返回类型始终来自方法定义处,无白名单/无硬编码。 # ============================================================ -VPI_RET_MAX: t.CDefine = 4096 -VPI_KEY_LEN: t.CDefine = 224 -VPI_RET_LEN: t.CDefine = 224 +define VPI_RET_MAX = 4096 +define VPI_KEY_LEN = 224 +define VPI_RET_LEN = 224 _g_vpi_ret_keys: bytes = None _g_vpi_ret_strs: bytes = None @@ -113,9 +113,9 @@ _g_vpi_ret_cap: int = 0 # 调用点缺参(fill 无法超 declare 补)→ 被调函数按 x64 ABI 读残留寄存器/栈槽垃圾。故与返回注解同源:从 vpi_buf 原始文本按行提取参数注解串缓存, # 注入 declare 时若 tree 参数数不足则用缓存补全,保证 declare 与 define 参数数一致。 # ============================================================ -VPI_PARAM_MAX: t.CDefine = 4096 -VPI_PARAM_KEY_LEN: t.CDefine = 224 -VPI_PARAM_LEN: t.CDefine = 1024 +define VPI_PARAM_MAX = 4096 +define VPI_PARAM_KEY_LEN = 224 +define VPI_PARAM_LEN = 1024 # ============================================================ # 键表开放寻址索引(名 → 槽下标) @@ -127,12 +127,12 @@ VPI_PARAM_LEN: t.CDefine = 1024 # 顺序递增排列,查找取链上首个"当前键相等"者 = 原线性扫描首个命中(首注册 # 优先)。可信判据 = Built == Count;不可信/未命中一律回退原线性扫描。 # ============================================================ -VPI_RET_IDX_CAP: t.CDefine = 8192 -VPI_PARAM_IDX_CAP: t.CDefine = 8192 +define VPI_RET_IDX_CAP = 8192 +define VPI_PARAM_IDX_CAP = 8192 # 索引哈希常量(32 位 FNV-1a,与 StructGenMixin 范式一致) -VPI_IDX_FNV_OFFSET: t.CDefine = 2166136261 -VPI_IDX_FNV_PRIME: t.CDefine = 16777619 -VPI_IDX_FNV_MASK: t.CDefine = 4294967295 +define VPI_IDX_FNV_OFFSET = 2166136261 +define VPI_IDX_FNV_PRIME = 16777619 +define VPI_IDX_FNV_MASK = 4294967295 _g_vpi_param_keys: bytes = None _g_vpi_param_strs: bytes = None @@ -845,7 +845,7 @@ def _resolve_vpi_param_annot_seg_template(pool: memhub.MemBuddy*, 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|t.CPtr): + # 类型形参 token(如 T)→ 特化实参(如 str / rawptr[AST] / AST*): # 模板注解按源码原样缓存,不替换则 `item: T` 解析不出类型(None 跳过) tparam_t: bytes = stdlib.malloc(tplen_t + 1) if tparam_t is not None: @@ -1069,7 +1069,7 @@ def _vpi_param_annot_seg_is(src_sha1: str, cls_name: str, method_name: str, self 占位(空串)。本函数只做逐字节等值比较,不解析、不做模板类型形参替换 ——调用方是跨模块调用的**热路径**(每个实参一次),不能在此分配/解析。 典型用途:判定定义侧形参注解是否为**裸** `str` / `bytes`(用于"str/bytes - 不是通用指针通配"这条规则;`str | t.CPtr` 这类组合段不等值,不受影响)。 + 不是通用指针通配"这条规则;`str*` 这类组合段不等值,不受影响)。 """ if want is None or seg_idx < 0: return 0 @@ -1264,8 +1264,8 @@ def _lookup_vpi_ret_annot(src_sha1: str, cls_name: str, method_name: str) -> str if hit_r >= 0: stdlib.free(key_buf) return _g_vpi_ret_strs + hit_r * VPI_RET_LEN - # 泛型特化归一化匹配:list[AST|t.CPtr].get → list[T].get 模板缓存。 - # 命中后把模板注解中的类型参数名(如 T)替换为实参(AST|t.CPtr)再返回。 + # 泛型特化归一化匹配:list[AST*].get → list[T].get 模板缓存。 + # 命中后把模板注解中的类型参数名(如 T)替换为实参(AST*)再返回。 # 不依赖模板类已注册/特化已发生(base.vp 可能先于 list 模块翻译)。 if cls_name is not None: lbkt_v: str = string.strchr(cls_name, '[') @@ -1324,13 +1324,13 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*, if seg is None or pool is None: return None # 【指针实参唯一规范形 `T*`(用户定口径,2026-09-30)】`rawptr[T]` ≡ - # `t.CPtr[T]` ≡ `T | t.CPtr` ⇒ 一律折叠为 `T*`(见 TypeGenResolve + # `t.CPtr[T]` ≡ `T*` ⇒ 一律折叠为 `T*`(见 TypeGenResolve # ._norm_type_arg_name 规则 1.0/1.5)。为什么必须在此补:_subst_template_arg # 会用**特化类名 `[...]` 内的已归一实参文本**(如 "{sha}.AST*")替换模板注解 # 里的 T,替换结果再送到本函数解析;本函数此前只认 `rawptr[` / `t.CPtr[` / # 裸 `t.CPtr`,遇到 `{sha}.AST*` 会落到下方 strrchr('.') 取末段得 "AST*" → # 查 struct miss → **静默**返回 None(跨模块参数/返回宽度被悄悄收窄)。 - # 现场:Test/AstTest/App/main.vp:21 的 `list[ast.AST | t.CPtr] | t.CPtr` 特化链。 + # 现场:Test/AstTest/App/main.vp:21 的 `list[ast.AST*] | t.CPtr` 特化链。 # 最小改法:把尾随 `*`(先跳尾随空格)按层数重写回**已存在**的 `rawptr[...]` # 文本形再走原分支(与 `rawptr[` 分支逐字等价,不新写 Ptr 包装逻辑): # "{sha}.AST*" → "rawptr[{sha}.AST]";"i8**" → "rawptr[rawptr[i8]]"。 @@ -1482,7 +1482,7 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*, # # 纯字符串解析,避免 _parse_type_string 跨模块构造 ast.Name/ast.BinOp 时节点 kind() 异常(可能退化为裸函数调用)导致 resolve 得到垃圾类型(如 Ptr(i8))。 # -# 支持: "str"/"bytes" → i8*; "int" → i32; "bool" → i1; "char" 等 → map_t_type 映射; "X | t.CPtr" → Ptr(Struct X); "t.CPtr" → i8*; "memhub.MemBuddy*" → Ptr(Struct MemBuddy)。 +# 支持: "str"/"bytes" → i8*; "int" → i32; "bool" → i1; "char" 等 → map_t_type 映射; "X*" → Ptr(Struct X); "t.CPtr" → i8*; "memhub.MemBuddy*" → Ptr(Struct MemBuddy)。 # ============================================================ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, ret_annot: str, @@ -1576,13 +1576,13 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, # first_wl =1 段是白名单裸标量名(int/char/str/bytes/bool/float/double) # first_td =1 段是裸 typedef 别名且已成功解析出**非指针**类型(N13, # 如 sizet/uint64 ⇒ i64):判据=“解析是否成功”,与定义侧 - # TypeGenResolve.resolve_annotation_type 的 BinOp(A | t.CPtr) + # TypeGenResolve.resolve_annotation_type 的 BinOp(A*) # 分支同源(同一 resolve_typedef_or_map 口径)。 first_qual: int = 0 first_wl: int = 0 first_td: int = 0 # CPtr 下标段(t.CPtr[T]/c.CPtr[T],含嵌套)的联合合并参数:cptr_sub_lvl = 该段解析后的外层 Ptr 层数 N(如 t.CPtr[t.CPtr] ⇒ 2);cptr_sub_ty = 该段解析出的类型本身。 - # 与定义侧 `X | t.CPtr[T]` 分支同口径:CPtr 侧贡献 N 层指针、另一侧提供基类型 ⇒ Ptr^N(基类型)。 + # 与定义侧 `X*[T]` 分支同口径:CPtr 侧贡献 N 层指针、另一侧提供基类型 ⇒ Ptr^N(基类型)。 # 与 has_cptr(裸 t.CPtr 段)分开记录:裸标记恒「追加 1 层」且有 struct 吸收特例,下标路径无吸收,两者在定义侧分属互斥分支。 cptr_sub_lvl: int = 0 cptr_sub_ty: mlirlite.LLVMType* = None @@ -1595,7 +1595,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, pos += 1 seg_start: sizet = pos # 只在**顶层**切 `|`:`[...]` 内的 `|` 属于泛型实参内部的联合注解,裸切会把首段 - # 截成 `list[ast.AST`(来自 `list[ast.AST | t.CPtr] | t.CPtr`),该段再经 + # 截成 `list[ast.AST`(来自 `list[ast.AST*] | t.CPtr`),该段再经 # strrchr('.') 落到 `AST` ⇒ 定义侧解析成 `AST*`(元素的指针),而正确答案是 # list 专化结构的指针(至少也应落 i8* 通配)。深度计数按 `[`/`]`,与 # _cache_vpi_param_annots_text 的顶层逗号切分同口径。 @@ -1624,7 +1624,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, seg_buf[seg_len2] = '\0' # CPtr 下标段(t.CPtr[T]/c.CPtr[T],含嵌套如 t.CPtr[t.CPtr]): # 必须先行识别,不能落普通段分支取 first_ty——定义侧 - # TypeGenResolve.vp L2596-2639 对 `X | t.CPtr[T]` 是"CPtr 侧贡献 + # TypeGenResolve.vp L2596-2639 对 `X*[T]` 是"CPtr 侧贡献 # N 层指针、另一侧给基类型 ⇒ Ptr^N(X)",与"把该段本身当联合取值" # 语义不同(如 X=struct S、t.CPtr[t.CPtr]:定义侧 Ptr(Ptr(S)), # 取该段本身则得 i8**)。此处只记录 N 与段类型,末尾统一合并。 @@ -1652,7 +1652,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, 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.CVoid") == 0 or string.strcmp(seg_buf, "CVoid") == 0 \ + 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) 这种非法类型 @@ -1665,7 +1665,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, # 记录该段属性(N12):定义侧 TypeGenResolve.resolve_annotation_type # 对**裸名** pointee 仅在它解析为已注册结构体、泛型参数名或白名单 # 裸标量时才保留 pointee,否则联合坍缩为 i8*;stub 侧此前无条件 - # Ptr(first_ty) → `uint64 | t.CPtr` 两侧不一致(定义 i8* vs declare i64*)。 + # Ptr(first_ty) → `uint64*` 两侧不一致(定义 i8* vs declare i64*)。 if string.strchr(seg_buf, 46) is not None: first_qual = 1 if string.strcmp(seg_buf, "int") == 0 or \ @@ -1700,7 +1700,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, pass # 复刻定义侧规则(N12/N13):限定名 / 白名单裸标量 / 已注册结构体 / 可解析的非指针裸 typedef 别名 → 保留 pointee; # 其余(解析失败、裸枚举名、指针别名)→ 联合坍缩为 i8*,与定义侧 resolve_annotation_type 对称(两侧同型即收敛)。 - # 指针别名(first_td 不置位,如 VOIDPTR = CVoid|CPtr → i8*):`| t.CPtr` + # 指针别名(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) @@ -1809,7 +1809,7 @@ def _extract_sha1_from_path(vpi_path: str) -> str: # → 参数类型解析失败退化为 i8_ptr_ty → 调用侧整数实参触发「整数隐式转指针已禁止」CastError 误报。 # 本函数在被读 stub 的 import 闭包上递归注册 CTypedef/CDefine(防环、限深),使注解解析上下文完整,参数/返回类型不再静默退化。 # ============================================================ -_TYPEDEF_VISIT_MAX: t.CDefine = 1024 +define _TYPEDEF_VISIT_MAX = 1024 _g_vpi_typedef_visited: bytes = None _g_vpi_typedef_visited_count: int = 0 @@ -2348,7 +2348,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, else: src_mod_buf[sri_src] = ch_src src_mod_buf[sr_len_src] = '\0' - imported_modules = StubMergerStore.AppendImportedModule( + imported_modules = StubMergerStore.AppendImportedModule( pool, imported_modules, src_mod_buf) stdlib.free(src_mod_buf) @@ -2549,7 +2549,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, # 故在重导出注册发现「源 entry 为空」时,按需把 sub_sha1 的 vpi 注入当前模块再重试注册(注入过程递归触发同一逻辑,依赖闭包自动补齐,与加载顺序无关)。 # 防重入表按 sha1 去重(环直接短路);注入失败不改语义,照原逻辑 return 0,不把可恢复问题升级为 fatal。 # ============================================================ -VPI_INJ_MAX: t.CDefine = 1024 +define VPI_INJ_MAX = 1024 _vpi_inj_sha1s: bytes = None _vpi_inj_count: int = 0 _vpi_inj_depth: int = 0 @@ -3105,7 +3105,7 @@ def _AggregateParamTy(mod: mlirlite.LLVMModule*, # ============================================================ # _inject_global_variable_declare - 从 vpi AnnAssign 创建模块级全局变量 declare # -# vpi 里模块级全局变量(如 tokens.vp 的 _op_head: OpEntry | t.CPtr = None)需在当前模块创建 external global 声明(短名 @name,COFF 按名链接), +# vpi 里模块级全局变量(如 tokens.vp 的 _op_head: OpEntry* = None)需在当前模块创建 external global 声明(短名 @name,COFF 按名链接), # 否则跨模块 from-import 读取全局变量时 find_global_in_module 找不到 → 误杀「跨模块全局变量类型未知(stub 未注入)」。 # ============================================================ def _inject_global_variable_declare(pool: memhub.MemBuddy*, @@ -3272,8 +3272,8 @@ def _inject_function_declare(pool: memhub.MemBuddy*, # 依赖版本会占用该名字 → forward_declare_functions 见名已存在即 continue # (FuncGenDef.vp:178-182)→ 本文件自己的签名被静默丢弃,调用点改按依赖签名 # coerce。现场:includes/socket.vp 的 - # `extern def connect(fd: u64, addr: SocketAddr | t.CPtr, addrlen: INT)` - # 被 w32.winsock2 的 `connect(..., WSASocketAddr | t.CPtr, ...)` 顶掉 → + # `extern def connect(fd: u64, addr: SocketAddr*, addrlen: INT)` + # 被 w32.winsock2 的 `connect(..., WSASocketAddr*, ...)` 顶掉 → # socket.vp:236 `connect(self.fd, c.Addr(addr), 16)` 报 # 「指针隐式转指针已禁止:SocketAddr* → WSASocketAddr*」。 # 判据只用**裸名**:带 SHA1 前缀的依赖函数名与本文件同名声明不会相互顶替。 diff --git a/App/lib/Stub/StubMerger/StubMergerBuild.vp b/App/lib/Stub/StubMerger/StubMergerBuild.vp index d0d9568..0c1e377 100644 --- a/App/lib/Stub/StubMerger/StubMergerBuild.vp +++ b/App/lib/Stub/StubMerger/StubMergerBuild.vp @@ -363,7 +363,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, stdlib.free(mod_buf) continue # 输出槽防御性初始化(成功路径必全写;未找到/未命中时仅 free 槽本身) - # 槽联合必须用 (sizet*):t.CPtr|t.CPtr 会被折叠成 t.CPtr, + # 槽联合必须用 (sizet*):t.CPtr* 会被折叠成 t.CPtr, # [0] 变成 1 字节访问 → 指针被截断(0x2e 崩溃根因)。CSizeT 成员为 # 8 字节:写侧 sizet(ptr),读侧必须用 rawptr(slot[0]) 做 u64→ # 指针转换;str(slot[0]) 是内置"数字转字符串"(snprintf 到栈缓冲并返回 diff --git a/App/lib/Stub/StubMerger/StubMergerStore.vp b/App/lib/Stub/StubMerger/StubMergerStore.vp index 4b557e6..bafe0cd 100644 --- a/App/lib/Stub/StubMerger/StubMergerStore.vp +++ b/App/lib/Stub/StubMerger/StubMergerStore.vp @@ -422,7 +422,7 @@ def LookupSha1ByModName(mod_name: str) -> str: # 批处理不登记(表恒空 ⇒ 查询恒 None ⇒ 批处理路径一字不改)。 # 容量:includes 现有 6 个泛型类定义(list/dict 系 + Vector/GSList/ndarray),取 32 槽。 # ============================================================ -GENERIC_OWNER_MAX: t.CDefine = 32 +define GENERIC_OWNER_MAX = 32 _generic_owner_names: bytes = None _generic_owner_sha1s: bytes = None _generic_owner_count: int = 0 diff --git a/App/lib/Stub/StubMerger/StubMergerTopo.vp b/App/lib/Stub/StubMerger/StubMergerTopo.vp index b84350c..92fcb45 100644 --- a/App/lib/Stub/StubMerger/StubMergerTopo.vp +++ b/App/lib/Stub/StubMerger/StubMergerTopo.vp @@ -103,7 +103,7 @@ def BuildTopoSortedIndices(store_count: int, store_sha1_arr: bytes, dsha1: str = StubMergerIR._FindSha1ByModName(store_sha1_arr, store_mod_arr, store_count, dname_buf) stdlib.free(dname_buf) if dsha1 is not None and StubMergerCollect._is_in_sha1_set(dsha1, reachable_set, reachable_count) != 0: - # 中间 int 变量累加:绕过联合类型(CSizeT|CPtr)+ 整数的指针算术编译 bug + # 中间 int 变量累加:绕过联合类型(CSizeT*)+ 整数的指针算术编译 bug indg: int = indegree[si] indg = indg + 1 indegree[si] = indg diff --git a/App/lib/Stub/StubMerger/__init__.vp b/App/lib/Stub/StubMerger/__init__.vp index 7be1054..18b9ced 100644 --- a/App/lib/Stub/StubMerger/__init__.vp +++ b/App/lib/Stub/StubMerger/__init__.vp @@ -30,16 +30,16 @@ import lib.Projectrans.Config as Config _mbuddy: memhub.MemBuddy* # 最大 includes SHA1 数(用于过滤) -MAX_INCLUDES_SHA1: t.CDefine = 1024 +define MAX_INCLUDES_SHA1 = 1024 # stub/text 读取缓冲区大小 # 1MB 不够:ast/parser.vp 的 text.ll >1MB,读取本地 text.ll 单次截断 # → 尾部丢字(opt: "end of file in global variable name")。 -STUB_READ_BUF_SIZE: t.CDefine = 8388608 +define STUB_READ_BUF_SIZE = 8388608 # 最大 includes 条目数 -MAX_INCLUDES: t.CDefine = 1024 +define MAX_INCLUDES = 1024 # 可达性分析 worklist/processed 缓冲区大小(8192 不够:递归扫描 source_dir # 后 worklist 含全部 App 文件 imports 的拼接 + BFS 依赖展开,追加82 溢出) -REACH_WORKLIST_BUF: t.CDefine = 65536 +define REACH_WORKLIST_BUF = 65536 # 全局 SHA1 映射存储器(内存中,不依赖 _sha1_map.txt 文件) # Phase1 扫描完成后填充,供所有函数使用 @@ -57,9 +57,9 @@ _includes_deps_str: bytes # 依赖字符串数组(每个 512 字节,MAX_IN _includes_deps_count: int # 条目数 # 单条依赖字符串最大长度 -MAX_DEPS_STR_LEN: t.CDefine = 512 +define MAX_DEPS_STR_LEN = 512 # rel_path 最大长度 -MAX_REL_PATH_LEN: t.CDefine = 256 +define MAX_REL_PATH_LEN = 256 # includes 根目录最大长度(绝对路径,多 includes 支持) -MAX_INC_DIR_LEN: t.CDefine = 512 +define MAX_INC_DIR_LEN = 512 diff --git a/App/lib/core/Gen/AssignGenMixin.vp b/App/lib/core/Gen/AssignGenMixin.vp index 23df469..5c3c961 100644 --- a/App/lib/core/Gen/AssignGenMixin.vp +++ b/App/lib/core/Gen/AssignGenMixin.vp @@ -119,7 +119,7 @@ novirtual class AssignGenMixin: # Case 4: Call — 如 t.CUnsignedLong(-11) if k == ast.ASTKind.Call: cl: ast.Call* = ast.Call*(val_node) - # 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__(), + # 必须先把属性赋给显式类型为 list[...]* 的局部变量再调用 __len__(), # 否则编译器无法识别属性返回的 list 类型,GEP base 会变成 i32 0 导致 llc 报错 cl_args_list: list[ast.AST*]* = cl.args if cl_args_list is not None and len(cl_args_list) > 0: @@ -216,7 +216,7 @@ novirtual class AssignGenMixin: 只看联合**首个**操作数(与 TPC 的"首个非 void 基类型胜出"同口径): `T | t.CDefine`(define 常量与 TPC 展开产物)⇒ T; - `t.CDefine | T`(既有手写惯用法,如 CODE_SEG: t.CDefine | t.CUInt16T)⇒ + `t.CDefine | T`(既有手写惯用法,如 CODE_SEG: t.CDefine | uint16)⇒ 首个是 CDefine 标记 ⇒ 无显式类型 ⇒ **既有声明行为逐字不变**。 """ if annot is None: @@ -236,7 +236,7 @@ novirtual class AssignGenMixin: 名称解析与 TPC EnumMemberAnnotationIntWidth 同源:t 模块类型名走 TypeGenResolve.map_t_type(CLong/CSizeT 等平台相关宽度由它权威给出); - `int` / `bool` 两个"注解直通名"补在此表(TPC: int → t.CInt 32 位、 + `int` / `bool` 两个"注解直通名"补在此表(TPC: int → int 32 位、 bool → 8 位,与 include/builtins 口径一致)。 """ if annot is None: @@ -473,8 +473,8 @@ novirtual class AssignGenMixin: f"[TPV] define 常量数值不可存储: 常量 '{name}' 的初始值 {text} 超出 64 位" f"(本语言最宽的整数类型为 64 位,按有符号/无符号两种解释的可存储范围为 " f"-9223372036854775808..18446744073709551615,不存在更宽的整数类型 ⇒ 需要扩容)。" - f"禁止静默截断/降级,已终止编译。可用整数类型: t.CInt8T/t.CUInt8T、" - f"t.CInt16T/t.CUInt16T、t.CInt32T/t.CUInt32T、t.CInt64T/t.CUInt64T" + f"禁止静默截断/降级,已终止编译。可用整数类型: int8/uint8、" + f"int16/uint16、int32/uint32、int64/uint64" f"(或 int8/uint8/…/uint64、char、sizet)。" f"修法: 把值改到 64 位范围内,或为该数字引入更大的整数类型(扩容)。", "TypeError") @@ -502,7 +502,7 @@ novirtual class AssignGenMixin: f"最小可容纳宽度 W_min: {wmin} 位;声明类型位宽 {bits} 位," f"该声明可存储范围: {lo}..{hi}。" f"禁止静默截断/降级,已终止编译。" - f"修法: 把显式类型改为更宽的类型(如 t.CInt32T / t.CInt64T / uint64)," + f"修法: 把显式类型改为更宽的类型(如 int32 / int64 / uint64)," f"或修正该字面量。", "TypeError") @@ -545,7 +545,7 @@ novirtual class AssignGenMixin: f"需要至少 {wmin} 位(最小可容纳宽度 W_min)," f"但使用处(变量声明注解)只提供 {bits} 位。" f"禁止静默截断/降级,已终止编译。" - f"修法: 把变量声明注解加宽到至少 {wmin} 位(如 t.CInt{wmin}T / CUInt{wmin}T)," + f"修法: 把变量声明注解加宽到至少 {wmin} 位(如 int{wmin}T / CUInt{wmin}T)," f"或改用更小的常量值。", "TypeError") @@ -600,8 +600,8 @@ novirtual class AssignGenMixin: # 源文件重读恢复(最可靠:AST 节点 float_val 可能被 pool 操作覆写, # 源文件文本不受影响;用输出参数绕开跨模块 double 返回值传递 bug) use_val: double = cn_fp.float_val - rec_d: t.CDouble = 0.0 - if self._recover_cdefine_float(name, t.CPtr(c.Addr(rec_d))) != 0: + rec_d: double = 0.0 + if self._recover_cdefine_float(name, t.CPtr(&rec_d)) != 0: use_val = rec_d else: # 源文件恢复失败:直接报错终止(fail-fast),避免注册被 pool 覆写的错误浮点值 @@ -627,14 +627,14 @@ novirtual class AssignGenMixin: """检查最近一次 _recover_cdefine_float 是否成功""" return self.RecoverFound - def _recover_float_literal(self, name: str, out: t.CDouble | t.CPtr, + def _recover_float_literal(self, name: str, out: double*, require_cdefine: int) -> int: """从当前模块源文件按变量名恢复浮点字面量,写入 out[0],成功返回 1 用输出参数传递 double,避免 TPV 跨模块 double 返回值传递 bug。 require_cdefine=1:只认带 t.CDefine 的行(CDefine 注册路径); =0:模块级普通浮点全局也接受(handle_module_level_var 路径, - 如 torch `LCG_M: t.CDouble = 2147483647.0`)。 + 如 torch `LCG_M: double = 2147483647.0`)。 """ self.RecoverFound = 0 fp: str = self.Gen.TypeGenResolve.get_current_file() @@ -767,7 +767,7 @@ novirtual class AssignGenMixin: stdlib.free(buf) return 0 - def _recover_cdefine_float(self, name: str, out: t.CDouble | t.CPtr) -> int: + def _recover_cdefine_float(self, name: str, out: double*) -> int: """CDefine 浮点值恢复(只认带 t.CDefine 的行),见 _recover_float_literal""" return self._recover_float_literal(name, out, 1) @@ -800,19 +800,19 @@ novirtual class AssignGenMixin: return 0 # ============================================================ - # _is_ptr_element_annotation - 检查注解是否为 bytes|t.CPtr 或 str|t.CPtr + # _is_ptr_element_annotation - 检查注解是否为 bytes* 或 str* # # 返回 1=是(下标按 8 字节步长, i8** 语义), 0=否(下标按 1 字节步长, i8* 语义) # # 规则: - # bytes|t.CPtr / str|t.CPtr → i8**(8 字节步长)→ 返回 1 - # char|t.CPtr / int8|t.CPtr → i8*(1 字节步长)→ 返回 0 + # bytes* / str* → i8**(8 字节步长)→ 返回 1 + # char* / int8* → i8*(1 字节步长)→ 返回 0 # 纯 bytes / str → i8*(1 字节步长)→ 返回 0 # # 注: 注解中的 "|" 是"和"的意思(组合类型),非右值中的位或运算 # ============================================================ def _is_ptr_element_annotation(self, annot: ast.AST*) -> int: - """检查注解是否为 bytes|t.CPtr 或 str|t.CPtr 形式""" + """检查注解是否为 bytes* 或 str* 形式""" if annot is None: return 0 k: int = annot.kind() @@ -825,7 +825,7 @@ novirtual class AssignGenMixin: return 1 if self._annotation_contains_name(annot, "bytes") != 0: return 1 - # 泛型类型参数/嵌套联合 | t.CPtr(如 _list.vp 的 elem_ptr: T | t.CPtr): + # 泛型类型参数/嵌套联合 | t.CPtr(如 _list.vp 的 elem_ptr: T*): # 先经泛型上下文解析 T 的具体类型——纯标量(int/float 等 sizeof≠8)时 # 元素按标量自身大小(list[int] elem_size=4 匹配 i32),不能按 8 字节 # 指针槽(否则 8 字节写 / 4 字节步长互相覆盖,pop 读到 0); @@ -848,7 +848,7 @@ novirtual class AssignGenMixin: if self._is_scalar_ty_name(gp_resolved) != 0: return 0 return 1 - # 64 位标量数值类型 | CPtr(如 CUInt64T | CPtr / CSizeT | CPtr): + # 64 位标量数值类型 | CPtr(如 CUInt64T* / CSizeT*): # 联合解析后同样退化为指针表示,元素为 8 字节(i64 或指针)。 # 下标必须按 8 字节步长读写——否则 GEP 步长 1 + trunc i8 截断, # 指针存进数组只剩低 1 字节(BuddyTest OOM/fill 的 ptrs 数组全错位: @@ -889,9 +889,9 @@ novirtual class AssignGenMixin: def _is_addrlike_call(self, node: ast.AST*) -> int: """检查 rhs 是否为 c.Addr/c.Deref 等显式指针操作调用。 - 此类调用返回指针(如 c.Addr(obj) 返回对象 storage 地址,类型 Ptr(Struct)), + 此类调用返回指针(如 &obj 返回对象 storage 地址,类型 Ptr(Struct)), 但语义是"取地址/解引用",不是对象值引用/构造——storage 绑定分支不应捕获: - X = c.Addr(Y) 应直接 store &Y 到 @X(X 与 Y 指向同一对象),若误绑定则 + X = &Y 应直接 store &Y 到 @X(X 与 Y 指向同一对象),若误绑定则 @X 自指 X.stg 并值复制 Y 的当前值(devfs DevFSObject 脱钩根因)。 """ if node is None or node.kind() != ast.ASTKind.Call: @@ -938,7 +938,7 @@ novirtual class AssignGenMixin: def _is_scalar_ty_name(self, ty_name: str) -> int: """判断类型名是否为已知纯标量(整数/浮点/字符),白名单判定 - 泛型 T | t.CPtr(如 _list.vp 的 elem_ptr)经 Fix A(TypeGenMixin 联合 + 泛型 T*(如 _list.vp 的 elem_ptr)经 Fix A(TypeGenMixin 联合 解析保留泛型标量)后 alloca 变 Ptr(标量):T 为纯标量(int/float/double/ i64 等)时下标按标量自身大小步长,不能再按 8 字节指针槽——否则 Ptr(标量) alloca + IsPtrElement 路径(load 标量当指针)产生非法 IR。 @@ -1206,7 +1206,7 @@ novirtual class AssignGenMixin: # 读对象首字的**唯一可用**写法是 `c.Deref((uint64*)(p))`(正常发射 # `bitcast p → i64*` + `load i64`:b5883dc9c114a604.ll:10611-10613); # 写成 `rawptr(*(uint64*)(p))` 会被折成裸 0(同文件 :10382),不可用。 - elem_vptr: uint64 = c.Deref((uint64*)(elem_node)) + elem_vptr: uint64 = *((uint64*)(elem_node)) if elem_vptr == 0: ctx_vt: str = "" if owner_ctx is not None: @@ -1930,7 +1930,7 @@ novirtual class AssignGenMixin: annot: ast.AST* = aa.annotation if annot is not None: # 泛型特化补救(在解析之前无条件执行,_specialize_generic_class 幂等): - # 注解可能是 list[X](Subscript)或 list[X] | t.CPtr(含 CPtr 的 BinOp)。 + # 注解可能是 list[X](Subscript)或 list[X]*(含 CPtr 的 BinOp)。 # 若泛型类尚未特化,resolve_annotation_type 会把 list[X] 退化为不透明 # 基类 list*(丢掉元素类型)——预建的 alloca 因此变成 list*,之后 # body_list.get(i) 会分派到默认 list[int] 特化(返回 i32)→ inttoptr @@ -1965,7 +1965,7 @@ novirtual class AssignGenMixin: 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) - # 检查是否为 bytes|t.CPtr 或 str|t.CPtr(i8** 语义,8 字节步长) + # 检查是否为 bytes* 或 str*(i8** 语义,8 字节步长) if self._is_ptr_element_annotation(annot) != 0: self.Gen.VarGen.set_var_ptr_element(trans.SymTab, nm.id) # const 对象(注解含 t.CConst 且声明类型非指针):整个作用域内 @@ -2001,7 +2001,7 @@ novirtual class AssignGenMixin: """泛型注解预特化(见上方注释),返回 1=已尝试 / 0=不适用""" if annot is None or trans is None: return 0 - # 取注解中的泛型 Subscript 一侧:Subscript 本身,或 A | t.CPtr 的 Subscript 分支 + # 取注解中的泛型 Subscript 一侧:Subscript 本身,或 A* 的 Subscript 分支 spec_annot: ast.Subscript* = None if annot.kind() == ast.ASTKind.Subscript: spec_annot = ast.Subscript*(annot) @@ -2042,7 +2042,7 @@ novirtual class AssignGenMixin: var_ty: mlirlite.LLVMType*) -> int: """fail-fast:泛型注解解析成了「裸泛型基类指针」(丢失类型实参) - 场景:注解是泛型下标 `list[X]` 或 `list[X] | t.CPtr`,但 + 场景:注解是泛型下标 `list[X]` 或 `list[X]*`,但 `resolve_annotation_type` 退化成裸基类 `list*`(没有 `[...]`) ⇒ 之后该变量的任何泛型方法调用(`.get()`/`.set()`/...)都会按**错误** 元素类型特化(实测 `list[int].get` 返回 i32)⇒ `inttoptr` 把 i32 当 @@ -2057,7 +2057,7 @@ novirtual class AssignGenMixin: """ if aa is None or annot is None or var_ty is None: return 0 - # 取注解里的泛型 Subscript 一侧:Subscript 本身,或 A | t.CPtr 的 Subscript 分支 + # 取注解里的泛型 Subscript 一侧:Subscript 本身,或 A* 的 Subscript 分支 ann_sub: ast.Subscript* = None if annot.kind() == ast.ASTKind.Subscript: ann_sub = ast.Subscript*(annot) @@ -2159,7 +2159,7 @@ novirtual class AssignGenMixin: # - 独立局部:换一个不与全局重名的变量名 # 目的:不让错误延后到 RHS 的 coerce_to_type,暴露成与根因无关的 # 「指针隐式转整数」(如 PointerTest/App/main.vp:46 `_g_ptr: int = None`: - # 全局已是 t.CUInt32T | t.CPtr)。范围仅函数内——模块级自身的重复注解 + # 全局已是 t.CUInt32T*)。范围仅函数内——模块级自身的重复注解 # 不归本检查(模块级由 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 \ @@ -2457,7 +2457,7 @@ novirtual class AssignGenMixin: "TypeError") # FakeDuck: str 变量创建影子结构体 {var}__meta__(per-instance 字段存储) - # 仅裸 str 注解(Name("str"))且 _str 已注册时创建;bytes / char|t.CPtr 不创建。 + # 仅裸 str 注解(Name("str"))且 _str 已注册时创建;bytes / char* 不创建。 # a 保持为 i8*(可 printf/len),a__meta__ 存 __data__/__mbuddy__ 等字段, # 属性读写(fd3)与方法调用(fd5)均通过该影子解析。 fd_str_ty: mlirlite.LLVMType* = None @@ -2487,7 +2487,7 @@ novirtual class AssignGenMixin: 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) - # 检查是否为 bytes|t.CPtr 或 str|t.CPtr(i8** 语义,8 字节步长) + # 检查是否为 bytes* 或 str*(i8** 语义,8 字节步长) if self._is_ptr_element_annotation(annot) != 0: self.Gen.VarGen.set_var_ptr_element(trans.SymTab, nm.id) @@ -2995,7 +2995,7 @@ novirtual class AssignGenMixin: sub_pointee: mlirlite.LLVMType* = sub_alloca.Ty.Pointee cls_nm_set: str = self.Gen.StructGen.get_class_name_by_type(pool, sub_pointee) obj_val_set: mlirlite.Value* = mlirlite.build_load(builder, sub_pointee, sub_alloca) - # 指针类型变量 (X|t.CPtr): sub_pointee 是 Ptr(Struct), + # 指针类型变量 (X*): sub_pointee 是 Ptr(Struct), # 需 load 获取 Ptr(Struct) 再检查 inner struct if cls_nm_set is None and obj_val_set is not None \ and self.Gen.ExprGenBase.is_ptr_type(sub_pointee) != 0 \ @@ -3021,7 +3021,7 @@ novirtual class AssignGenMixin: field_pointee_set: mlirlite.LLVMType* = field_ptr_set.Ty.Pointee cls_nm_attr: str = self.Gen.StructGen.get_class_name_by_type(pool, field_pointee_set) obj_val_attr: mlirlite.Value* = field_ptr_set - # field_ptr 是 Ptr(Ptr(Struct)) (X|t.CPtr 字段): + # field_ptr 是 Ptr(Ptr(Struct)) (X* 字段): # load 解引用获取 Ptr(Struct) if cls_nm_attr is None \ and self.Gen.ExprGenBase.is_ptr_type(field_pointee_set) != 0 \ @@ -3290,7 +3290,7 @@ novirtual class AssignGenMixin: alloca: mlirlite.Value* = self.Gen.VarGen.get_or_create_sym(trans.SymTab, pool, builder, nm.id, rhs_val.Ty) if alloca is not None: # 无注解赋值:从 RHS 表达式推断类名设置变量注解 - # (联合类型 X|t.CPtr 简化为 Ptr(i8),属性访问按需过滤需要 + # (联合类型 X* 简化为 Ptr(i8),属性访问按需过滤需要 # AnnotClassName 才能定位结构体字段) cls_inf: str = self._infer_rhs_annot(pool, mod, asgn.value, trans, rhs_val) if cls_inf is not None: @@ -3332,7 +3332,7 @@ novirtual class AssignGenMixin: # # 不拦(判据刻意收窄,避免误伤): # · 元素是标量(rawptr[int] 等):元素类型不是 Struct,直接返回; - # · 元素本身是指针(rawptr[rawptr[T]]、rawptr[T]|t.CPtr、str|t.CPtr): + # · 元素本身是指针(rawptr[rawptr[T]]、rawptr[T]*、str*): # elem_ptr.Ty.Pointee 是 Ptr,不是 Struct,直接返回; # · 数组槽(t.CArray[T,N] / 内建 Array):subscript_base_store_kind==1, # `v[i] = T(...)`(构造函数返回临时对象地址)是合法的整对象复制; @@ -3360,7 +3360,7 @@ novirtual class AssignGenMixin: if elem_ty is None: return # 元素必须是对象(结构体)。标量元素(rawptr[int])与指针元素 - # (rawptr[rawptr[T]] / X|t.CPtr)在此返回。 + # (rawptr[rawptr[T]] / X*)在此返回。 if elem_ty.kind() != mlirlite.LLVMType.Struct: return rhs_inner_wo: mlirlite.LLVMType* = None @@ -3403,7 +3403,7 @@ novirtual class AssignGenMixin: f"而不是按指针写 {ptr_sz_wo} 字节。若该地址实际按 8 字节槽存放指针" f"(如 rawptr[T] 缓冲/空闲链表),每写一个元素就越界 {over_wo} 字节," f"直接写穿相邻块。修法:把指针槽的基座类型写成指针元素形态" - f"(`rawptr[T] | t.CPtr` 或 `rawptr[rawptr[T]]`)后再赋值;" + f"(`rawptr[T]*` 或 `rawptr[rawptr[T]]`)后再赋值;" f"或把基座显式转为 t.CPtr(无类型指针)后按 8 字节指针语义写入。", "TypeError", col_s_wo, col_e_wo) @@ -3411,7 +3411,7 @@ novirtual class AssignGenMixin: # _infer_rhs_annot - 从 RHS 表达式推断变量注解类名 # # 无注解赋值(如 v = Vec2(...) / v3 = v1 + v2)时,变量 AnnotClassName - # 缺失会导致后续属性访问(.x)无法"按需过滤":联合类型 X|t.CPtr 在 LLVM + # 缺失会导致后续属性访问(.x)无法"按需过滤":联合类型 X* 在 LLVM # 中简化为 Ptr(i8),不携带类名,无法定位结构体字段(字段未找到 → fast-fail)。 # 此函数按 RHS 结构推断类名: # Call → 类实例化(func 为已注册结构体名才采用,避免普通函数误标); @@ -3560,7 +3560,7 @@ novirtual class AssignGenMixin: while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'): s += 1 # 段尾另需剥 '*':实参归一后段文本是 `{sha}.AST*`(旧形态 - # `{sha}.AST | t.CPtr` 按 '|' 分段能落到 `{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] == '*'): @@ -3579,7 +3579,7 @@ novirtual class AssignGenMixin: while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'): s += 1 # 段尾另需剥 '*':实参归一后段文本是 `{sha}.AST*`(旧形态 - # `{sha}.AST | t.CPtr` 按 '|' 分段能落到 `{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] == '*'): diff --git a/App/lib/core/Gen/AsyncGenMixin.vp b/App/lib/core/Gen/AsyncGenMixin.vp index 9181332..51e006b 100644 --- a/App/lib/core/Gen/AsyncGenMixin.vp +++ b/App/lib/core/Gen/AsyncGenMixin.vp @@ -135,7 +135,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if cnt >= HT.MAX_CORO_VARS: break addr: uint64 = uint64(trans._coro_params) + cnt * 8 - slot: str | t.CPtr = (str | t.CPtr)(addr) + slot: str* = (str*)(addr) slot[0] = aname cnt = cnt + 1 trans._coro_param_count = cnt @@ -678,7 +678,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if cnt >= HT.MAX_CORO_VARS: return addr: uint64 = uint64(trans._coro_locals) + cnt * 8 - slot: str | t.CPtr = (str | t.CPtr)(addr) + slot: str* = (str*)(addr) slot[0] = name trans._coro_local_count = cnt + 1 @@ -896,7 +896,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if cnt >= HT.MAX_CORO_FUNCS: return addr: uint64 = uint64(trans._coro_wake_names) + cnt * 8 - slot: str | t.CPtr = (str | t.CPtr)(addr) + slot: str* = (str*)(addr) slot[0] = name trans._coro_wake_idxs[cnt] = wake_idx trans._coro_wake_count = cnt + 1 @@ -909,7 +909,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): i: int = 0 for i in range(trans._coro_wake_count): addr: uint64 = uint64(trans._coro_wake_names) + i * 8 - slot: str | t.CPtr = (str | t.CPtr)(addr) + slot: str* = (str*)(addr) if slot[0] is not None and string.strcmp(slot[0], name) == 0: return trans._coro_wake_idxs[i] return -1 @@ -1624,7 +1624,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if trans is None or trans._coro_params is None: return None addr: uint64 = uint64(trans._coro_params) + idx * 8 - slot: str | t.CPtr = (str | t.CPtr)(addr) + slot: str* = (str*)(addr) return slot[0] # ============================================================ @@ -1835,7 +1835,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): check_bbs[hi + 1] = sizet(mlirlite.create_block(pool, func, chk_name)) handler_bbs[hi] = sizet(mlirlite.create_block(pool, func, exc_name)) unmatched_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.try_reraise") - codes_buf: int | t.CPtr = pool.alloc(256) + codes_buf: int* = pool.alloc(256) # 每个 handler:check 链 for hi in range(nhandlers): h_node: ast.AST* = tr.handlers.get(hi) @@ -2413,7 +2413,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): i: int = 0 for i in range(cnt): addr: uint64 = uint64(trans._async_funcs) + i * 8 - slot: str | t.CPtr = (str | t.CPtr)(addr) + slot: str* = (str*)(addr) if slot[0] is not None and string.strcmp(slot[0], name) == 0: return 1 return 0 @@ -2430,13 +2430,13 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): i: int = 0 for i in range(cnt): addr: uint64 = uint64(trans._coro_var_async) + i * 16 - pair: str | t.CPtr = (str | t.CPtr)(addr) + 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 pair2_addr: uint64 = uint64(trans._coro_var_async) + cnt * 16 - pair2: str | t.CPtr = (str | t.CPtr)(pair2_addr) + pair2: str* = (str*)(pair2_addr) pair2[0] = var_name pair2[1] = func_name trans._coro_var_async_count = cnt + 1 @@ -2451,13 +2451,13 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): i: int = 0 for i in range(cnt): addr: uint64 = uint64(trans._async_funcs) + i * 8 - slot: str | t.CPtr = (str | t.CPtr)(addr) + 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 addr2: uint64 = uint64(trans._async_funcs) + cnt * 8 - slot2: str | t.CPtr = (str | t.CPtr)(addr2) + slot2: str* = (str*)(addr2) slot2[0] = name trans._async_func_count = cnt + 1 return 0 @@ -2474,14 +2474,14 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): i: int = 0 for i in range(cnt): addr: uint64 = uint64(trans._coro_frames) + i * 16 - pair: str | t.CPtr = (str | t.CPtr)(addr) + pair: str* = (str*)(addr) 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 pair2_addr: uint64 = uint64(trans._coro_frames) + cnt * 16 - pair2: str | t.CPtr = (str | t.CPtr)(pair2_addr) + pair2: str* = (str*)(pair2_addr) pair2[0] = name pair2[1] = str(frame_ty) trans._coro_frame_count = cnt + 1 @@ -2496,7 +2496,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): i: int = 0 for i in range(cnt): addr: uint64 = uint64(trans._coro_frames) + i * 16 - pair: str | t.CPtr = (str | t.CPtr)(addr) + pair: str* = (str*)(addr) if pair[0] is not None and string.strcmp(pair[0], name) == 0: if pair[1] is not None: ty_addr: sizet = sizet(pair[1]) @@ -2513,7 +2513,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): i: int = 0 for i in range(cnt): addr: uint64 = uint64(trans._coro_var_async) + i * 16 - pair: str | t.CPtr = (str | t.CPtr)(addr) + pair: str* = (str*)(addr) if pair[0] is not None and string.strcmp(pair[0], var_name) == 0: return pair[1] return None @@ -2644,5 +2644,5 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase): if trans is None or trans._coro_locals is None: return None addr: uint64 = uint64(trans._coro_locals) + idx * 8 - slot: str | t.CPtr = (str | t.CPtr)(addr) + slot: str* = (str*)(addr) return slot[0] diff --git a/App/lib/core/Gen/Call/CallGenCBuiltin.vp b/App/lib/core/Gen/Call/CallGenCBuiltin.vp index f0f6d71..7b18284 100644 --- a/App/lib/core/Gen/Call/CallGenCBuiltin.vp +++ b/App/lib/core/Gen/Call/CallGenCBuiltin.vp @@ -45,9 +45,9 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): mod: mlirlite.LLVMModule*, cl: ast.Call*, trans: HT.Translator* = None) -> mlirlite.Value*: - """c.Deref(ptr) → load,宽度只由 ptr 的 pointee 类型决定 + """*ptr → load,宽度只由 ptr 的 pointee 类型决定 pointee 是 i8(t.CPtr / void* / str / bytes)恒读 1 字节;不再按赋值 - 目标注解(CurAssignAnnot)反推宽度——那会让同一处 c.Deref(i8*) 的读取 + 目标注解(CurAssignAnnot)反推宽度——那会让同一处 *(i8*) 的读取 宽度取决于它是否恰好出现在带注解赋值的 RHS 里。需要按更宽类型读时, 由调用点显式给出元素类型指针后再解引用(见下方读取分支注释)。 """ @@ -63,7 +63,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # 读取宽度只由指针类型决定:按 pointee 类型 load 一个元素。 # pointee 是 i8(t.CPtr / void* / str / bytes)即恒读 1 字节。 # 需要 4/8 字节等更宽读取时,必须在调用点把指针显式变成有元素类型的 - # 指针再解引用(c.Deref((rawptr[T])(p)) / c.Deref((T | t.CPtr)(x))), + # 指针再解引用(c.Deref((rawptr[T])(p)) / c.Deref((T*)(x))), # 不再由赋值目标注解反推——否则同一处 c.Deref(i8*) 的宽度会随上下文 # (是否带注解赋值的 RHS)而变。 if self.Gen.ExprGenBase.is_ptr_type(ptr_val.Ty) != 0: @@ -81,7 +81,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): cl: ast.Call*, trans: HT.Translator* = None) -> mlirlite.Value*: """c.DerefAs(ptr, val) → store val to ptr(bitcast 后 store) - 单参形式 c.DerefAs(ptr) → 读取 ptr 指向的值(等价 c.Deref(ptr))。 + 单参形式 c.DerefAs(ptr) → 读取 ptr 指向的值(等价 *ptr)。 """ if cl is None: return None @@ -250,7 +250,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): mod: mlirlite.LLVMModule*, cl: ast.Call*, trans: HT.Translator* = None) -> mlirlite.Value*: - """c.Addr(var) → 返回变量的 alloca 指针(不 load)""" + """&var → 返回变量的 alloca 指针(不 load)""" if cl is None: return None cargs: list[ast.AST*]* = cl.args @@ -462,7 +462,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): return mlirlite.build_gep_struct(builder, struct_ty, fe_addr.Ty, obj_ptr, fe_addr.Index) # Subscript 形式: c.Addr(arr[i]) / c.Addr(a.b[i][j]) → 元素地址(GEP,不 load) - # 统一走 get_subscript_ptr(递归处理嵌套下标、数组/指针/str|t.CPtr 形态)。 + # 统一走 get_subscript_ptr(递归处理嵌套下标、数组/指针/str* 形态)。 # 此前仅处理单层数组 GEP:嵌套下标(c.Addr(self.lines[line_idx][0]), # vpui.vp L985)的 value 是内层 Subscript,translate_value 把内层加载成 # 数组值([80 x i8])→ 非 Ptr → return None → 跌落跨模块函数调用生成 @@ -671,7 +671,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): def _resolve_register(self, attr_name: str) -> str: - """将 t.ASM_DESCR.XXX 的属性名映射到约束字符串值""" + """将 ASM_DESCR.XXX 的属性名映射到约束字符串值""" if attr_name is None: return "" @@ -836,7 +836,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): 支持两种等价写法(裸名写法省去 c. 前缀),裸名统一返回规范名, 使调用点的 string.strcmp 判定无需分支: - - 内联汇编:c.AsmInp/c.AsmOut ↔ asminp/asmout("AsmInp"/"AsmOut") + - 内联汇编: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: @@ -894,7 +894,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): """添加操作数到数组,返回新计数(失败返回原计数) 去重:f-string 模板内嵌的 AsmOut/AsmInp 与 out=/inp= 声明指向 - 同一变量时会重复收集(如 vrandom.vp 的 c.Asm(f"...{AsmOut(v)}", + 同一变量时会重复收集(如 vrandom.vp 的 __asm__(f"...{AsmOut(v)}", out=[AsmOut(v)])),同一 (Value, IsOutput) 只保留第一个, 避免约束数多于 asm 返回元素数(llc: output constraints mismatch)。 """ @@ -905,7 +905,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # 且裸机链接要求裸名 —— 必须将对应定义标记为 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"c.Asm 操作数(AsmInp/AsmOut)不允许带 SHA1 混淆头的符号 '{val.Name}',请将对应函数/全局定义标记为 t.CExport(裸名)", "TypeError") + 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) @@ -933,7 +933,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): mod: mlirlite.LLVMModule*, cl: ast.Call*, trans: HT.Translator* = None) -> mlirlite.Value*: - """翻译 c.Asm 内联汇编,返回结果 Value(无输出时返回 None)""" + """翻译 __asm__ 内联汇编,返回结果 Value(无输出时返回 None)""" if cl is None: return None @@ -954,9 +954,9 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # 的寄存器 → 寄存器错乱/零页崩溃) # 类型必须是**单级**裸缓冲(t.CPtr = i8*):pool.alloc 返回 t.CPtr、 # string.memset 首参也是 t.CPtr;每槽按 8 字节字符串指针写入由下方的 - # `cl_ptr: str | t.CPtr = (str | t.CPtr)(cl_addr)` 显式 cast 完成 - # (与 includes/_dict.vp 的一致模式:缓冲单级、槽视图 str | t.CPtr)。 - # 此前声明成 str | t.CPtr(=i8**) 与 alloc/memset 层数不符,隐式指针转换 + # `cl_ptr: str* = (str*)(cl_addr)` 显式 cast 完成 + # (与 includes/_dict.vp 的一致模式:缓冲单级、槽视图 str*)。 + # 此前声明成 str*(=i8**) 与 alloc/memset 层数不符,隐式指针转换 # 禁止"层数不同",首行即报错。 clobbers: t.CPtr = pool.alloc(8 * ASM_MAX_CLOBBERS) if clobbers is None: @@ -984,7 +984,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): string.memset(out_ptys, 0, 8 * ASM_MAX_OPERANDS) # 分配 fv 索引数组(记录每个 FormattedValue 对应的操作数原始索引) - fv_orig_indices: int | t.CPtr = pool.alloc(4 * ASM_MAX_OPERANDS) + fv_orig_indices: int* = pool.alloc(4 * ASM_MAX_OPERANDS) if fv_orig_indices is None: return None string.memset(fv_orig_indices, 0, 4 * ASM_MAX_OPERANDS) @@ -1190,7 +1190,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if cstr is None or cstr[0] == '\0': continue if clobber_count < ASM_MAX_CLOBBERS: cl_addr: uint64 = uint64(clobbers) + clobber_count * 8 - cl_ptr: str | t.CPtr = (str | t.CPtr)(cl_addr) + cl_ptr: str* = (str*)(cl_addr) cl_ptr[0] = cstr clobber_count += 1 @@ -1211,7 +1211,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if pstr is None or pstr[0] == '\0': continue if clobber_count < ASM_MAX_CLOBBERS: pcl_addr: uint64 = uint64(clobbers) + clobber_count * 8 - pcl_ptr: str | t.CPtr = (str | t.CPtr)(pcl_addr) + pcl_ptr: str* = (str*)(pcl_addr) pcl_ptr[0] = pstr clobber_count += 1 @@ -1239,7 +1239,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if output_count > 1: # 多输出返回类型 {T1, T2, ...} 的字段链表是 ParamNode 链 # (new_param_node 返回 rawptr[ParamNode]、Struct 形参 rawptr[ParamNode]、 - # ParamNode.Next: ParamNode|CPtr),原先误注解为 Function*(不相关类) + # ParamNode.Next: ParamNode*),原先误注解为 Function*(不相关类) # → 1264/1268 两处会被判 struct↔struct 隐式转换禁止。 out_pn_head: mlirlite.ParamNode* = None out_pn_last: mlirlite.ParamNode* = None @@ -1269,7 +1269,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): 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, "c.Asm 输出操作数类型缺失(变量 alloca 类型退化)", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, "__asm__ 输出操作数类型缺失(变量 alloca 类型退化)", "TypeError") ret_ty = mlirlite.Int32(pool) else: out_op: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, first_output_idx) @@ -1282,7 +1282,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if out_pt is not None: ret_ty = out_pt else: - self.Gen.TypeGenErr.fatal_error(cl, "c.Asm 输出操作数类型缺失(变量 alloca 类型退化)", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, "__asm__ 输出操作数类型缺失(变量 alloca 类型退化)", "TypeError") ret_ty = mlirlite.Int32(pool) # 判断 void — 直接基于 output_count 判断,避免 match 类型匹配问题 @@ -1306,7 +1306,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): ret_re = re_op.Value.Ty.Pointee break if ret_re is None: - self.Gen.TypeGenErr.fatal_error(cl, "c.Asm 输出操作数类型缺失(变量 alloca 类型退化)", "TypeError") + self.Gen.TypeGenErr.fatal_error(cl, "__asm__ 输出操作数类型缺失(变量 alloca 类型退化)", "TypeError") ret_ty = ret_re case _: pass @@ -1317,8 +1317,8 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # new_order[new_idx] = orig_idx — 新位置对应原索引 # orig_to_new[orig_idx] = new_idx — 原索引映射到新位置(用于占位符编号) # ============================================================ - new_order: int | t.CPtr = pool.alloc(4 * (operand_count + 1)) - orig_to_new: int | t.CPtr = pool.alloc(4 * (operand_count + 1)) + 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 @@ -1405,7 +1405,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # 追加 clobber 约束 ~{name} for cidx in range(clobber_count): cl_addr2: uint64 = uint64(clobbers) + cidx * 8 - cname: str = (str | t.CPtr)(cl_addr2)[0] + cname: str = (str*)(cl_addr2)[0] if cname is None or cname[0] == '\0': continue if first_const == 0: @@ -1418,10 +1418,10 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): # ============================================================ # 6. 构建参数列表文本(仅输入操作数) # ============================================================ - # 每个实参 = 类型文本(MLIR 内联具名结构体完整字段体,可达 512 字节) - # + 值名;固定 ASM_ARGS_BUF_SIZE(512) 只够一个短类型,须按操作数个数给足。 - asm_arg_cap: sizet = sizet(operand_count + 1) * 544 + 64 - args_buf: str = pool.alloc(asm_arg_cap) + # 每个实参 = 类型文本(MLIR 内联具名结构体完整字段体,可达 512 字节) + # + 值名;固定 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 args_buf[0] = '\0' diff --git a/App/lib/core/Gen/Call/CallGenCall.vp b/App/lib/core/Gen/Call/CallGenCall.vp index 84c5cc0..55224a5 100644 --- a/App/lib/core/Gen/Call/CallGenCall.vp +++ b/App/lib/core/Gen/Call/CallGenCall.vp @@ -585,7 +585,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): # 修复: 构造器调用 __init__(ptr, base, 4096) 时 size 形参是 i64 (sizet), # 但 4096 字面量按 i32 传递,未提升导致运行时 size 高 32 位垃圾, # 破坏伙伴分配器的池大小元数据(如 total=2048)引发 calloc 失败/OOM。 - # self 在运算符重载路径 2(lhs 为 X|t.CPtr 联合简化的 Vec3** 对象指针)时 + # self 在运算符重载路径 2(lhs 为 X* 联合简化的 Vec3** 对象指针)时 # 与形参 Vec3* 不匹配,需 bitcast(coerce 指针→指针生成 bitcast), # 否则 call 参数类型与声明不一致 llc 报错。 if found_func is not None and head is not None: @@ -936,7 +936,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): mi_s0 += 1 # 泛型特化方法调用:特化函数可能尚未注册(如 ast.base 用 - # list[AST|t.CPtr].get)。主动触发特化(幂等,MethodsEmitted 防重入), + # list[AST*].get)。主动触发特化(幂等,MethodsEmitted 防重入), # 特化后重新查找即可命中,返回类型来自特化函数定义(天然精确)。 gen_done: int = 0 # text.ll 查找结果提升为函数级并显式初始化:gen_done==1 成功时 @@ -1242,7 +1242,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): self.Gen.TypeGenErr.fatal_error(cl, f"this-adjust 父类结构体未注册: 方法'{method_name}'定义类'{mc_anc}'的 struct 未找到", "InternalCompilerError") # self 参数按声明首参类型 coerce:跨模块 declare self 是类指针 # (%"sha1.Class"*,见 VpiReader._inject_method_declare),而对象指针 - # 可能是 i8*(X|t.CPtr 联合简化)或 this-adjust 后的祖先指针,需 + # 可能是 i8*(X* 联合简化)或 this-adjust 后的祖先指针,需 # bitcast 匹配声明签名(对齐 _call_method_on_ptr 的 coerce 块), # 否则 llc 报 call 参数类型与 declare 不一致。 if found_func is not None: @@ -1696,7 +1696,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase): self.Gen.TypeGenErr.fatal_error(cl, "list.append: 找不到 _list 模块 SHA1(依赖模块未编译)", "InternalCompilerError") if ap_sha1 is not None: # 特化类名提取:list.append 的符号名是 - # {sha1}.list[AST|CPtr].append(带类型参数特化名),而非 + # {sha1}.list[AST*].append(带类型参数特化名),而非 # {sha1}.list.append。lm_obj 类型即特化结构体 Ptr(list[...]), # 从类型解析特化类名拼接调用名,否则 ld.lld undefined symbol ap_spec_nm: str = None diff --git a/App/lib/core/Gen/Call/CallGenCtor.vp b/App/lib/core/Gen/Call/CallGenCtor.vp index 4d0d706..76c78e4 100644 --- a/App/lib/core/Gen/Call/CallGenCtor.vp +++ b/App/lib/core/Gen/Call/CallGenCtor.vp @@ -9,7 +9,7 @@ import stdlib import viperlib import lib.core.VLogger as VLogger import lib.core.Gen.Translator as HT -import lib.core.Gen.GenTypes as GenTypes +import lib.core.Gen.GenTypes as GenTypes import lib.core.Gen.Type.TypeSpec as TSpec from . import CallGenBase @@ -742,7 +742,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): list[int] -> ["int"] dict[str, int] -> ["str", "int"] - list[AST | t.CPtr] -> ["f467978339422f32.AST|t.CPtr"] + list[AST*] -> ["f467978339422f32.AST*"] from_imports 可用时,各类型实参经 TypeGenResolve._norm_type_arg_name 规范化为 "{定义模块SHA1}.{Class}"(ast.AST/AST → f467978339422f32.AST), @@ -780,16 +780,16 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # _ptr_layer_type_arg - 构造推断类型实参的指针层补足(与注解侧同票名) # # 口径来源(用户定,2026-09-30):指针类型实参**唯一规范形是 `T*`** - # (rawptr[T] ≡ t.CPtr[T] ≡ T | t.CPtr;见 TypeGenResolve._norm_type_arg_name)。 + # (rawptr[T] ≡ t.CPtr[T] ≡ T*;见 TypeGenResolve._norm_type_arg_name)。 # 为什么必须补:_infer_generic_ctor_type_arg 的 Name/Attribute 分支把 # 「注解类名」(AnnotClassName)直接当泛型类型实参返回,而 # TypeGenResolve.extract_class_name_from_annotation 对 `rawptr[AST]` 只返回 - # pointee "AST"、对 `AST | t.CPtr` 也只返回 "AST"(丢指针层)⇒ 构造侧推出 - # `{sha}.AST`,注解侧(Box[rawptr[AST]] / Box[AST | t.CPtr])归一形却是 + # pointee "AST"、对 `AST*` 也只返回 "AST"(丢指针层)⇒ 构造侧推出 + # `{sha}.AST`,注解侧(Box[rawptr[AST]] / Box[AST*])归一形却是 # `{sha}.AST*`,同一 `Box(x)` 隐式特化会分裂成两个结构体(undefined symbol / # 同布局两 struct)。 # 判据:变量/字段的**值类型**指针层级由 Spec.PtrLevel 承载(`x: AST` 为 0; - # `x: rawptr[AST]` / `x: AST | t.CPtr` 为 1),即"注解本身是指针形"。 + # `x: rawptr[AST]` / `x: AST*` 为 1),即"注解本身是指针形"。 # 顺序:**先经 _norm_type_arg_name 归一再加 `*`** —— 裸名 "AST*" 不再是可查 # 类名,_norm 无法给它补 SHA1 前缀 ⇒ 会与 "{sha}.AST*" 分裂;故必须先归一成 # `{定义模块SHA1}.{类}` 再补层。仅当归一结果确为类名(带 SHA1 前缀)时补; @@ -889,7 +889,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if ve_i is not None: # 注解类名经 _ptr_layer_type_arg:走 _norm_type_arg_name 归一后, # 变量值类型为指针(Spec.PtrLevel>0,如 `x: rawptr[AST]` / - # `x: AST | t.CPtr`)时补足 `*`,与注解侧归一形 `{sha}.AST*` 同票名。 + # `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: @@ -900,7 +900,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # 同样只查表)。取不到 ⇒ None ⇒ 调用方 fail-fast。 if k == ast.ASTKind.Attribute: # 同上:字段值类型为指针时(FieldEntry.Spec.PtrLevel>0,如字段注解 - # `AST | t.CPtr`)补足 `*`。_resolve_attr_field_entry 为只读非 fatal + # `AST*`)补足 `*`。_resolve_attr_field_entry 为只读非 fatal # 解析,仅支持单层基座;更深的属性链取不到 PtrLevel 时保持原样(原行为)。 cn_at_i: str = self.Gen.ExprGenAttr._resolve_attr_field_class(pool, trans, arg_node) pl_at_i: int = 0 @@ -1113,7 +1113,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): ctx_annot = trans.CurFuncRetAnnot if ctx_annot is None: return None # 取注解里的泛型 Subscript 一侧(与 _prespecialize_generic_annotation 同构: - # 支持 `X[T]` 与 `X[T] | t.CPtr` 两种形态) + # 支持 `X[T]` 与 `X[T]*` 两种形态) spec_annot: ast.Subscript* = None if ctx_annot.kind() == ast.ASTKind.Subscript: spec_annot = ast.Subscript*(ctx_annot) @@ -1177,7 +1177,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): string.memset(extra_args, 0, 8 * 32) # 槽占用标志(0=空 1=已填),用于关键字定位后的连续性校验。 # 尺寸口径 = extra_args 同源:槽位数固定 32(下标 0..31,由下方 - # `ai >= 32` / `slot_kw >= 32` 守卫界定),元素类型 = sizet|t.CPtr ⇒ 步长 + # `ai >= 32` / `slot_kw >= 32` 守卫界定),元素类型 = sizet* ⇒ 步长 # 8 字节 ⇒ 必须 32 * 8 = 256 字节。原写 alloc(32) 是"按 1 字节/槽"的 # 第二份真相源,与 `arg_filled[i] = 1` 的 8 字节步长写自相矛盾:只要实参 # 数/关键字槽位 ≥ 4(下标 4 落在偏移 32)即越界写穿本块尾 canary 与右邻 diff --git a/App/lib/core/Gen/Call/CallGenDispatch.vp b/App/lib/core/Gen/Call/CallGenDispatch.vp index 485185c..2fa75cc 100644 --- a/App/lib/core/Gen/Call/CallGenDispatch.vp +++ b/App/lib/core/Gen/Call/CallGenDispatch.vp @@ -244,9 +244,9 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if fp is not None: fp = mlirlite.param_get_next(fp) ai += 1 - # build_call 的第二参是**被调符号名字符串**(callee: str),不是 Function*—— - # 传 Function* 会被当成字符串读到结构体首字段(Next 指针),发射出 - # `call i32 @(i32 7)`(空名字)这种非法 IR。这里用查找时同一符号名。 + # build_call 的第二参是**被调符号名字符串**(callee: str),不是 Function*—— + # 传 Function* 会被当成字符串读到结构体首字段(Next 指针),发射出 + # `call i32 @(i32 7)`(空名字)这种非法 IR。这里用查找时同一符号名。 return mlirlite.build_call(builder, spec_name, head, int(can), ret_ty, 0) def _tc_h1_super_ctraits(self, pool: memhub.MemBuddy*, @@ -317,7 +317,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): """c.Deref/Asm/LLVMIR 等特殊调用(未命中返回 None) hit_box: 命中标记(t.CPtr,[0]=1 表示已识别为 c.* 特殊调用)。 - 仅对 c.Asm/c.LLVMIR 等返回 None(void,无返回值)的调用置位—— + 仅对 __asm__/c.LLVMIR 等返回 None(void,无返回值)的调用置位—— translate_c_asm/translate_c_llvmir 成功处理 void 时返回 None, 若不加 hit_box 会被 translate_call 误判为"未命中"继续走外部函数路径。 """ @@ -532,7 +532,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): tc_mod_nm: ast.Name* = ast.Name*(tc_at.value) if tc_mod_nm.id is not None and string.strcmp(tc_mod_nm.id, "t") == 0: # t.CType 特殊形式:t.CType(value, TypeName, t.CPtr) → - # 把 value 转为 TypeName|t.CPtr(TypeName* 指针)。TypeName + # 把 value 转为 TypeName*(TypeName* 指针)。TypeName # 是类型名(Name/Attribute),不是值表达式——此前被当普通 # 参数翻译 → NameError: 未定义名称 'memory_block' # (VKernel mm.vp merge_blocks 根因)。CType 不是 map_t_type @@ -581,7 +581,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # t.CType 语法已确认:即使类型解析失败也不跌落到跨模块 FATAL return None # CConst const 标记:CConst(val, t.CPtr) → Ptr(i8)(const void*)。 - # CConst 不是 map_t_type 具名类型——t.CConst|char|t.CPtr 注解 = + # CConst 不是 map_t_type 具名类型——t.CConst|char* 注解 = # const char*(i8*),显式调用 t.CConst(addr, t.CPtr) 把整数地址转 # const 指针。此前 map_t_type 失败 → 跌落跨模块函数调用 → 生成 # call @CConst(裸名,无 obj 定义)→ ld.lld undefined symbol: @@ -825,17 +825,17 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): break sz_resolved_name = sz_cls_name # 指针包装类型检查必须在 dot-strip 之前:类型实参可能带 sha1 - # 前缀内嵌点号(rawptr[7565e081d88517ac.AST]、f4679...AST|t.CPtr), + # 前缀内嵌点号(rawptr[7565e081d88517ac.AST]、f4679...AST*), # strrchr('.') 会把括号内 ".AST"/".CPtr" 剥掉 → "AST]"/"CPtr", # 前缀/联合判断永远失配 → 落回把接收者 Name(T) 当实例翻译 → # NameError: 未定义名称 'T'(SlotsBugTest rawptr[list[rawptr[AST]]] 根因)。 - # 联合类型(X | t.CPtr)与新一代指针包装 rawptr[X] 均按指针大小 8。 + # 联合类型(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) # 归一后的指针唯一规范形 `T*`(TypeGenResolve._norm_type_arg_name - # 的指针书写归一:rawptr[T] ≡ t.CPtr[T] ≡ T|t.CPtr ≡ T*) + # 的指针书写归一:rawptr[T] ≡ t.CPtr[T] ≡ T* ≡ T*) # ⇒ **尾随** '*' 一律按指针大小 8(多级 `**` 同为 8)。 # 判据必须是"尾随",不能用 strrchr:接收者是 # `list[{sha}.AST*]`(元素为指针的容器)时串内也含 '*', @@ -843,7 +843,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # 缺本判据时 `T.__sizeof__()` 的实参串 `{sha}.AST*` 既不命中 # '|' 也不命中 'rawptr[',落回把接收者 Name(T) 当实例翻译 → # NameError: 未定义名称 'T'(现场 Test/AstTest/App/main.vp:21 - # 特化 list[ast.AST|t.CPtr] → includes/_list.vp:36)。 + # 特化 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 @@ -1708,13 +1708,13 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): expr_obj: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, expr_method_at.value, funcs_ptr, func_count, trans) if expr_obj is not None and expr_obj.Ty is not None: expr_cls_nm: str = None - # 递归解 Ptr:识别 X|t.CPtr 联合简化的 Ptr(Ptr(Struct)) + # 递归解 Ptr:识别 X* 联合简化的 Ptr(Ptr(Struct)) # (如 (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) - # 回退:LLVM 类型为 Ptr(i8)(方法返回 X|t.CPtr 无类型信息)时, + # 回退:LLVM 类型为 Ptr(i8)(方法返回 X* 无类型信息)时, # 从接收者表达式结构推断类名(链式调用 c2.scale(2.0).move(...) # 的 scale 返回 Ptr(i8),经 infer_expr_class → vpi 返回注解) # 跨 Mixin 不能 self 调用 ExprGenMixin 方法,经全局单例 @@ -1979,9 +1979,9 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): self.Gen.TypeGenErr.fatal_error(cl, "list.append: 找不到 _list 模块 SHA1(依赖模块未编译)", "InternalCompilerError") if ap_sha1 is not None: # 特化类名提取:list.append 的符号名是 - # {sha1}.list[AST|CPtr].append(带类型参数特化名), + # {sha1}.list[AST*].append(带类型参数特化名), # 而非 {sha1}.list.append。lm_obj 类型即特化结构体 - # Ptr(list[AST|CPtr]),从类型解析特化类名拼接调用名, + # Ptr(list[AST*]),从类型解析特化类名拼接调用名, # 否则 ld.lld undefined symbol(定义端是特化名)。 ap_spec_nm: str = None ap_struct_ty: mlirlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(lm_obj) @@ -1990,9 +1990,9 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if ap_spec_nm is None: ap_spec_nm = "list" # 触发泛型特化翻译(幂等,MethodsEmitted 防重入): - # list[AST|CPtr].append 的 define 方法体在特化类翻译时 + # list[AST*].append 的 define 方法体在特化类翻译时 # 生成。仅构造调用名不触发特化会导致定义缺失 - # (ld.lld undefined symbol: list[AST|CPtr].append)。 + # (ld.lld undefined symbol: list[AST*].append)。 if trans is not None and ap_spec_nm is not None: lbkt_ap: str = string.strchr(ap_spec_nm, '[') if lbkt_ap is not None: @@ -2028,7 +2028,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # 调用名 "{sha1}.{spec}.append": # sha1(16) + '.'(1) + spec + '.append'(7) + NUL(1) = spec + 25。 # 此前 +8 少 1 字节,snprintf 截断末尾 'd' → - # undefined symbol: ...list[AST|CPtr].appen(缺 d)。 + # undefined symbol: ...list[AST*].appen(缺 d)。 ap_mlen: sizet = string.strlen(ap_sha1) + string.strlen(ap_spec_nm) + 26 ap_mangled: str = pool.alloc(ap_mlen) if ap_mangled is not None: diff --git a/App/lib/core/Gen/Call/CallGenLeafKit.vp b/App/lib/core/Gen/Call/CallGenLeafKit.vp index a64afcd..4f7a465 100644 --- a/App/lib/core/Gen/Call/CallGenLeafKit.vp +++ b/App/lib/core/Gen/Call/CallGenLeafKit.vp @@ -277,7 +277,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): if obj_val is None or obj_val.Ty is None: # obj 类型推断失败:fail-fast,绝不返回 True 掩盖 self.Gen.TypeGenErr.fatal_error(cls_node, "isinstance() 参数类型推断失败", "TypeError") - # 对象指针规整:二级指针(变量 alloca / 联合 Class|t.CPtr)先 load + # 对象指针规整:二级指针(变量 alloca / 联合 Class*)先 load obj_ptr: mlirlite.Value* = obj_val match obj_val.Ty: case mlirlite.LLVMType.Ptr(inner_ty): @@ -1336,8 +1336,8 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): return 0 # 提取常量快照到 stdlib if default_count > 0: - kinds: int | t.CPtr = CompilerFactory.factory.PermPool.alloc(default_count * 4) - ints: int64 | t.CPtr = CompilerFactory.factory.PermPool.alloc(default_count * 8) + kinds: int* = CompilerFactory.factory.PermPool.alloc(default_count * 4) + ints: int64* = CompilerFactory.factory.PermPool.alloc(default_count * 8) strs: sizet* = CompilerFactory.factory.PermPool.alloc(default_count * 8) if kinds is not None and ints is not None and strs is not None: string.memset(kinds, 0, default_count * 4) diff --git a/App/lib/core/Gen/Call/CallGenLib.vp b/App/lib/core/Gen/Call/CallGenLib.vp index 0bd5265..d9dc7ce 100644 --- a/App/lib/core/Gen/Call/CallGenLib.vp +++ b/App/lib/core/Gen/Call/CallGenLib.vp @@ -268,7 +268,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): # 转换校验,于是"把结构体/类/数组/函数指针传给 str 形参"会被静默放行 # ⇒ 后续把该指针当 C 字符串用时生成非法 IR(现场:把 Function* 传给 # `callee: str`,发射出 `call i32 @(i32 7)` 空符号名,直到 llc 才炸)。 - # 判据:定义侧形参注解**恰为**裸 str/bytes(组合段如 `str|t.CPtr` 不 + # 判据:定义侧形参注解**恰为**裸 str/bytes(组合段如 `str*` 不 # 等值、不受影响),且实参是指向聚合类型的指针。判据与报错统一委托 # ExprGenBase._str_rejects_ptr_kind / fail_if_str_annot_agg_ptr(单一 # 真源,字符数组 [N x i8] 衰减与其在同模块路径同口径豁免)。 @@ -444,7 +444,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase): # Config 模块函数(跨模块调用时 stub 未注入,返回 i8* 被 inttoptr i32 截断导致路径损坏) if string.strcmp(func_name, "get_includes_binary_dir") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) - # HandlesType 模块函数(返回 ast.AST|t.CPtr 联合类型,跨模块推断为 i32 导致指针截断) + # HandlesType 模块函数(返回 ast.AST* 联合类型,跨模块推断为 i32 导致指针截断) if string.strcmp(bare_name, "_parse_type_string") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) diff --git a/App/lib/core/Gen/Call/CallGenMixin.vp b/App/lib/core/Gen/Call/CallGenMixin.vp index a4a5214..6c72dcb 100644 --- a/App/lib/core/Gen/Call/CallGenMixin.vp +++ b/App/lib/core/Gen/Call/CallGenMixin.vp @@ -196,7 +196,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): self.Gen.TypeGenErr.fatal_error(gen_nm_node, gt_err) self.Gen.TypeGenErr.fatal_error(gen_nm_node, "泛型类模板未找到") if func_name is None: - # 检查是否是 (A | t.CPtr)(value) 形式的类型转换 + # 检查是否是 (A*)(value) 形式的类型转换 # BinOp 节点作为 Call func: 联合类型注解用作类型转换 if cl.func is not None and cl.func.kind() == ast.ASTKind.BinOp and trans is not None: binop_ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, cl.func, trans._imported_modules, trans._from_imports, trans, 0) @@ -385,7 +385,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): 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|CPtr)存 0 指针 → p.v 解引用 NULL 段错误 + # (如 Plain*)存 0 指针 → p.v 解引用 NULL 段错误 # (TpvIsinstanceTest Plain 场景崩溃根因)。 ctor_is_novt: int = 0 if gen_ctor_entry is not None: @@ -1019,7 +1019,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # Ptr(i8)(TypeGenResolve.vp:2525-2531),与 t.CPtr 的 # Spec 完全同型 ⇒ 类型层无区分度,标记只能由注解名承载。 # 原 strstr 子串匹配会误命中含 "CPtr" 的类名(如 CPtrHolder)。 - # 已知局限(与改造前一致,非回归):`Foo | t.CPtr` 的 + # 已知局限(与改造前一致,非回归):`Foo*` 的 # SourceName 只留 "Foo"(取非 CPtr 侧类名)⇒ 此处判为非标记。 if TSpec.SpecTypeNameBaseIs(fp_annot, "CPtr") != 0: is_cptr_annot_fp = 1 diff --git a/App/lib/core/Gen/Call/CallGenProp.vp b/App/lib/core/Gen/Call/CallGenProp.vp index c3956d8..48b4616 100644 --- a/App/lib/core/Gen/Call/CallGenProp.vp +++ b/App/lib/core/Gen/Call/CallGenProp.vp @@ -156,8 +156,8 @@ novirtual class CallGenProp(CallGenBase.CallGenBase): if annot_val is not None: # [D32] 取「模块限定名」末段时只按**括号外**的 '.' 切分。 # 此前用 string.strrchr 在整个串上找最后一个 '.':泛型特化名 - # "list[e94ef9e139461915.AST|t.CPtr]" 的 '.' 落在 '[' 内 ⇒ - # 返回 "AST|t.CPtr]" 这种垃圾短名 ⇒ 后续按它查表必落空, + # "list[e94ef9e139461915.AST*]" 的 '.' 落在 '[' 内 ⇒ + # 返回 "AST*]" 这种垃圾短名 ⇒ 后续按它查表必落空, # 进而可能被兜底成任意特化(.get() 误分派)。 n_av: sizet = string.strlen(annot_val) last_dot_av: sizet = n_av @@ -345,7 +345,7 @@ novirtual class CallGenProp(CallGenBase.CallGenBase): # list[T] 是内置泛型容器(_list.vp),其方法(append/get/set/pop/clear/ # __iter__/__len__/__getitem__/__setitem__)由 translate_call 的 list # 内置分支内联 GEP 处理,不注册为方法函数。若 obj.method() 检测把 - # list 特化 struct(如 list[AST | CPtr])误当普通结构体走 + # list 特化 struct(如 list[AST*])误当普通结构体走 # _translate_method_call,会查不到 append 返回类型 → fail-fast # (NewAstTest body.append 根因)。此判断用于跳过 method_call 路径。 # @@ -357,7 +357,7 @@ novirtual class CallGenProp(CallGenBase.CallGenBase): method_name: str) -> int: """判断 (class_name, method_name) 是否是 list 泛型内置方法""" if class_name is None or method_name is None: return 0 - # 类名必须以 "list" 开头(list / list[AST | CPtr] 特化名) + # 类名必须以 "list" 开头(list / list[AST*] 特化名) if string.strncmp(class_name, "list", 4) != 0: return 0 # 方法名必须是 list 内置方法集合 if string.strcmp(method_name, "append") == 0: return 1 diff --git a/App/lib/core/Gen/Call/CallGenVa.vp b/App/lib/core/Gen/Call/CallGenVa.vp index 726b92f..0970b6b 100644 --- a/App/lib/core/Gen/Call/CallGenVa.vp +++ b/App/lib/core/Gen/Call/CallGenVa.vp @@ -53,7 +53,7 @@ novirtual class CallGenVa(CallGenBase.CallGenBase): 支持的类型表达式: int / int32 → i32 int64 → i64 - t.CDouble → double + double → double t.CPtr / str → i8* str / bytes → i8* 无类型参数时默认 i32(vsnprintf 中 va_arg(ap) 常用于读取 i32) diff --git a/App/lib/core/Gen/Call/CallGenVt.vp b/App/lib/core/Gen/Call/CallGenVt.vp index 438e069..364129c 100644 --- a/App/lib/core/Gen/Call/CallGenVt.vp +++ b/App/lib/core/Gen/Call/CallGenVt.vp @@ -162,7 +162,7 @@ novirtual class CallGenVt(CallGenBase.CallGenBase): 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|t.CPtr 变量(Ptr(Ptr))load 解引用取对象指针 + # X* 变量(Ptr(Ptr))load 解引用取对象指针 match obj_ptr_v.Ty: case mlirlite.LLVMType.Ptr(inner_v): match inner_v: diff --git a/App/lib/core/Gen/Class/ClassGenBase.vp b/App/lib/core/Gen/Class/ClassGenBase.vp index b411edf..e30e3e5 100644 --- a/App/lib/core/Gen/Class/ClassGenBase.vp +++ b/App/lib/core/Gen/Class/ClassGenBase.vp @@ -81,7 +81,7 @@ novirtual class ClassGenBase: # --- 类编译期元数据表(__provides__/__requires__/__require_must__) --- # perm_pool 分配(跨 mark/reset 存活):每槽 kind(4B) + cls(64B) + field(64B) # FakeDuck:_str.__requires__=['__mbuddy__'] 等(FakeDuck 移植点 1) - ClassMetaKinds: int | t.CPtr + ClassMetaKinds: int* ClassMetaClss: bytes ClassMetaFields: bytes ClassMetaCount: int @@ -131,18 +131,18 @@ novirtual class ClassGenBase: # 可能失效(VectorGenericTest 特化 Vector[int].__init__ 的 T.__sizeof__() # NameError 根因方向);注册时展平深拷贝到 stdlib,特化时从本表恢复。 # 每槽指向一个空格分隔、NUL 结尾的 stdlib 缓冲区(如 "T" 或 "T K")。 - GenericClassTpParams: sizet* - - # --- 泛型函数模板表(与上面 GenericClass* 同构:键 "{sha1}.{fname}" 定位 - # 模板节点/来源 SHA1/来源文件/类型参数名)。 - # 必须与其它字段一起声明在类顶——方法中间的字段注解可能被编译器当作 - # 局部声明处理,破坏 Mixin 布局/this_adjust 对齐(见 _exception_codes_tmp_count)。 - # 之前只写了 __before_init__ 里的赋值而漏了这里,导致 ClassGenGeneric - # 上的读取触发 fast-fail:属性 'GenericFuncKeys' 在类中找不到。 --- - GenericFuncKeys: list[str]* - GenericFuncNodes: list[ast.FunctionDef*]* - GenericFuncSha1s: list[str]* - GenericFuncFiles: list[str]* + GenericClassTpParams: sizet* + + # --- 泛型函数模板表(与上面 GenericClass* 同构:键 "{sha1}.{fname}" 定位 + # 模板节点/来源 SHA1/来源文件/类型参数名)。 + # 必须与其它字段一起声明在类顶——方法中间的字段注解可能被编译器当作 + # 局部声明处理,破坏 Mixin 布局/this_adjust 对齐(见 _exception_codes_tmp_count)。 + # 之前只写了 __before_init__ 里的赋值而漏了这里,导致 ClassGenGeneric + # 上的读取触发 fast-fail:属性 'GenericFuncKeys' 在类中找不到。 --- + GenericFuncKeys: list[str]* + GenericFuncNodes: list[ast.FunctionDef*]* + GenericFuncSha1s: list[str]* + GenericFuncFiles: list[str]* GenericFuncTpParams: sizet* # --- vtable 方法收集表(原 _g_vt_full_names/_g_vt_method_names/ @@ -695,7 +695,7 @@ novirtual class ClassGenBase: 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 | t.CPtr, + 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: @@ -705,7 +705,7 @@ novirtual class ClassGenBase: 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 | t.CPtr, + def _collect_desc_codes_rec(self, name: str, out_codes: int*, max_codes: int, depth: int) -> None: """递归收集 name 编码 + 全部子孙编码(BFS 语义对齐 TPC)""" if depth > 32: @@ -828,7 +828,7 @@ novirtual class ClassGenBase: i: int for i in range(self.MethodMetaCount): if string.strcmp(self.MethodMetaKeys + i * META_KEY_LEN, key_buf) == 0: - flags_ptr: t.CPtr = (int | t.CPtr)(uint64(self.MethodMetaFlags) + i * 4) + flags_ptr: t.CPtr = (int*)(uint64(self.MethodMetaFlags) + i * 4) # 按位或合并:同一属性名先 @property(getter=4) 再 @x.setter(8)/ # @x.deleter(16) 会多次注册(如 Config.value / Counter.value)。 # 若整值替换,后注册的位会覆盖 GETTER 位 → _try_property_getter_attr @@ -841,7 +841,7 @@ novirtual class ClassGenBase: # 槽位定长 META_KEY_LEN=128 字节,key 超长时 strncpy 钳制防越界写相邻槽 string.strncpy(self.MethodMetaKeys + self.MethodMetaCount * META_KEY_LEN, key_buf, META_KEY_LEN - 1) - flags_ptr2: t.CPtr = (int | t.CPtr)(uint64(self.MethodMetaFlags) + self.MethodMetaCount * 4) + flags_ptr2: t.CPtr = (int*)(uint64(self.MethodMetaFlags) + self.MethodMetaCount * 4) flags_ptr2[0] = meta self.MethodMetaCount += 1 stdlib.free(key_buf) @@ -861,7 +861,7 @@ novirtual class ClassGenBase: i: int for i in range(self.MethodMetaCount): if string.strcmp(self.MethodMetaKeys + i * META_KEY_LEN, key_buf) == 0: - flags_ptr: t.CPtr = (int | t.CPtr)(uint64(self.MethodMetaFlags) + i * 4) + flags_ptr: t.CPtr = (int*)(uint64(self.MethodMetaFlags) + i * 4) found = flags_ptr[0] break stdlib.free(key_buf) diff --git a/App/lib/core/Gen/Class/ClassGenDef.vp b/App/lib/core/Gen/Class/ClassGenDef.vp index c007c3d..ccd829f 100644 --- a/App/lib/core/Gen/Class/ClassGenDef.vp +++ b/App/lib/core/Gen/Class/ClassGenDef.vp @@ -392,7 +392,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): # Phase A-pre(declare_only=1):依赖的类可能尚未注册,延迟到下一遍 # Phase B(declare_only=0):真正的类型解析错误,fast-fail 终止该类翻译 # 不再用 i32 回退(会导致结构体布局错误 + GEP 索引错乱) - # 例外:泛型 Subscript(如 list[AST|t.CPtr])未特化时回退为 Ptr(i8), + # 例外:泛型 Subscript(如 list[AST*])未特化时回退为 Ptr(i8), # 因为泛型特化可能延迟到构造调用时。AnnotClassName 会携带 mangled name # 供 translate_attribute 做后续 bitcast。 is_generic_sub: int = 0 @@ -441,7 +441,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase): else: field_defaults_buf[field_count] = 0 # 提取原始类型注解的类名(联合类型简化为 Ptr(i8) 时回退查找结构体) - # BUG 1 方案3:传 pool 使泛型 Subscript 返回 mangled name(如 "list[ast.AST|t.CPtr]") + # BUG 1 方案3:传 pool 使泛型 Subscript 返回 mangled name(如 "list[ast.AST*]") if aa.annotation is not None: annot_cn: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(aa.annotation, trans._imported_modules, pool, trans._from_imports) if annot_cn is not None: diff --git a/App/lib/core/Gen/Class/ClassGenEnum.vp b/App/lib/core/Gen/Class/ClassGenEnum.vp index 3165678..3307050 100644 --- a/App/lib/core/Gen/Class/ClassGenEnum.vp +++ b/App/lib/core/Gen/Class/ClassGenEnum.vp @@ -186,7 +186,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): def _enum_member_annotation_is_ptr(self, ann_node: ast.AST*) -> int: """枚举成员注解(**含联合类型逐边**)是否含指针类型,1=是 / 0=否 - 联合形态必须逐边检查:`t.CInt | t.CPtr` 在 _resolve_enum_member_type 的 + 联合形态必须逐边检查:`int*` 在 _resolve_enum_member_type 的 BinOp 分支会"优先返回具体整数类型"(源码 L94-105)——只看解析结果会把 含指针的联合静默当整数,故在解析前按注解树拦。 """ @@ -335,7 +335,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 | t.CPtr = 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 string.memset(member_names_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL) @@ -365,7 +365,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # [枚举规格 fail-fast] 成员不允许指针类型:t.CPtr / CNeedPtr / # CAutoPtr / rawptr[...] / str / bytes,以及**联合类型里夹带指针** - # 的形态(t.CInt | t.CPtr)。必须先于类型解析——联合分支会优先返回 + # 的形态(t.CInt*)。必须先于类型解析——联合分支会优先返回 # 具体整数类型、rawptr[...] 又是 Subscript(非 Name/Attribute/BinOp) # 会在解析里报笼统的"注解解析失败",两者都盖不住"指针成员"这个真因。 if self._enum_member_annotation_is_ptr(aa.annotation) == 1: @@ -884,7 +884,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # 直接注册变体字段名别名(避免 CSizeT→str 转换问题) # 同时解析成员实际类型(对齐 TPC class_members,供 match # 绑定 bitcast 槽位地址用)。自引用注解(如 - # LLVMType|t.CPtr 引用自身类)此时解析失败返回 None → + # LLVMType* 引用自身类)此时解析失败返回 None → # 不存类型,绑定回退槽位类型。variant_cd.name 在 1a reset # 后悬空,注册内部会 strcpy 到 perm_pool。 if vnm is not None and vnm.id is not None: @@ -1352,7 +1352,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): """注册 REnum 变体字段名别名到全局表 field_ty: 变体成员的实际 LLVM 类型(可选;自引用类型如 - LLVMType|t.CPtr 在注册期解析失败时为 None,match 绑定回退槽位类型)。 + LLVMType* 在注册期解析失败时为 None,match 绑定回退槽位类型)。 variant_name: 所属变体名(可选;match 绑定按 (class, 变体, 位置) 定位成员) """ if pool is None or class_name is None or field_name is None: diff --git a/App/lib/core/Gen/Class/ClassGenGeneric.vp b/App/lib/core/Gen/Class/ClassGenGeneric.vp index 3cc98e0..2bfa589 100644 --- a/App/lib/core/Gen/Class/ClassGenGeneric.vp +++ b/App/lib/core/Gen/Class/ClassGenGeneric.vp @@ -442,10 +442,10 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): 位宽 无符号 有符号 / 默认 i1 bool (bool 唯一) - i8 t.CUInt8T char - i16 t.CUInt16T t.CInt16T(无裸名别名) - i32 t.CUInt32T int - i64 t.CUInt64T t.CInt64T(无裸名别名) + i8 uint8 char + i16 uint16 int16(无裸名别名) + i32 uint32 int + i64 uint64 int64(无裸名别名) f16 t.CFloat16T (浮点无符号性) f32 float f64 double @@ -489,19 +489,19 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): if string.strcmp(buf, "i1") == 0: return "bool" if string.strcmp(buf, "i8") == 0: # 无符号 i8(CUInt8T/CUnsignedChar)走裸名 char 会静默变号 - if sign == TSpec.TS_SIGN_UNSIGNED: return "t.CUInt8T" + if sign == TSpec.TS_SIGN_UNSIGNED: return "uint8" return "char" if string.strcmp(buf, "i16") == 0: - if sign == TSpec.TS_SIGN_UNSIGNED: return "t.CUInt16T" - if sign == TSpec.TS_SIGN_SIGNED: return "t.CInt16T" + if sign == TSpec.TS_SIGN_UNSIGNED: return "uint16" + if sign == TSpec.TS_SIGN_SIGNED: return "int16" return None if string.strcmp(buf, "i32") == 0: # 无符号 i32(CUInt32T/CSizeT/CUIntPtrT)走裸名 int 会静默变号 - if sign == TSpec.TS_SIGN_UNSIGNED: return "t.CUInt32T" + if sign == TSpec.TS_SIGN_UNSIGNED: return "uint32" return "int" if string.strcmp(buf, "i64") == 0: - if sign == TSpec.TS_SIGN_UNSIGNED: return "t.CUInt64T" - if sign == TSpec.TS_SIGN_SIGNED: return "t.CInt64T" + if sign == TSpec.TS_SIGN_UNSIGNED: return "uint64" + if sign == TSpec.TS_SIGN_SIGNED: return "int64" return None # ---- 浮点:位宽精确(无符号性概念,无歧义)---- if string.strcmp(buf, "half") == 0: return "t.CFloat16T" @@ -950,7 +950,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): tpn: str = tp_names.get(i) if tpn is not None and string.strcmp(nm.id, tpn) == 0: ta: str = type_args.get(i) - # 类型实参可能是复合类型(如 "AST|t.CPtr"),用 _parse_type_string 解析 + # 类型实参可能是复合类型(如 "AST*"),用 _parse_type_string 解析 parsed_node: ast.AST* = self.Gen.TypeGenResolve._parse_type_string(pool, ta, nm.ctx) return parsed_node return ast.Name(pool, nm.id, nm.ctx) @@ -962,7 +962,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): new_value: ast.AST* = self._clone_annotation(pool, at.value, tp_names, type_args) return ast.Attribute(pool, new_value, at.attr, at.ctx) - # BinOp: T | t.CPtr 等 + # BinOp: T* 等 if k == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(node) new_left: ast.AST* = self._clone_annotation(pool, bop.left, tp_names, type_args) @@ -1167,25 +1167,25 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): string.strcpy(ts_buf_r, trigger_sha1) entry_rt.SpecTriggerSha1 = ts_buf_r return 1 - def _tp_names_for_spec(self, pool: memhub.MemBuddy*, class_name: str, - template_cd: ast.ClassDef*) -> list[str]*: - """取特化用的类型参数名列表(优先 stdlib 深拷贝表,退化模板节点) - - 两条来源都拿不到/为空时 fail-fast,**绝不**用空泛型上下文继续特化: - 空上下文会让模板方法体里的类型形参(如 `T.__sizeof__()`)落到普通名字 - 查找 → 报 "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 - self.Gen.TypeGenErr.fatal_error(None, - f"泛型类模板 '{class_name}' 的类型参数名缺失(GenericClassTpParams 对应槽为空," - f"模板节点也无 type_params)——拒绝用空泛型上下文特化", "InternalCompilerError") - return None - + def _tp_names_for_spec(self, pool: memhub.MemBuddy*, class_name: str, + template_cd: ast.ClassDef*) -> list[str]*: + """取特化用的类型参数名列表(优先 stdlib 深拷贝表,退化模板节点) + + 两条来源都拿不到/为空时 fail-fast,**绝不**用空泛型上下文继续特化: + 空上下文会让模板方法体里的类型形参(如 `T.__sizeof__()`)落到普通名字 + 查找 → 报 "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 + self.Gen.TypeGenErr.fatal_error(None, + f"泛型类模板 '{class_name}' 的类型参数名缺失(GenericClassTpParams 对应槽为空," + f"模板节点也无 type_params)——拒绝用空泛型上下文特化", "InternalCompilerError") + return None + def _specialize_generic_class(self, trans: HT.Translator*, class_name: str, type_args: list[str]*) -> str: @@ -1253,7 +1253,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): pre_existing: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(spec_name) if pre_existing is not None and pre_existing.MethodsEmitted == 0: # 防重入:先标记 MethodsEmitted=1,避免补译过程中方法体/返回类型注解 - # 再次触发 _specialize_generic_class(如 __iter__ 返回 list[T]|t.CPtr) + # 再次触发 _specialize_generic_class(如 __iter__ 返回 list[T]*) # 导致无限递归补译 → OOM。补译完成后已设置,无需恢复。 # 注意:此处提前置位后调用 _translate_oop_methods 必须传 reemit=1 # (补译模式),否则其 MethodsEmitted==1 防重复检查会拦截补译, diff --git a/App/lib/core/Gen/Class/ClassGenVTable.vp b/App/lib/core/Gen/Class/ClassGenVTable.vp index b0f2bf7..1779ef2 100644 --- a/App/lib/core/Gen/Class/ClassGenVTable.vp +++ b/App/lib/core/Gen/Class/ClassGenVTable.vp @@ -510,7 +510,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): return 0 # 防重入:方法体翻译前先标记 MethodsEmitted=1。 - # 根因:若等全部方法译完再标记,翻译 __iter__(返回 list[T]|t.CPtr)时, + # 根因:若等全部方法译完再标记,翻译 __iter__(返回 list[T]*)时, # 返回类型注解会再次触发 _specialize_generic_class,此时 MethodsEmitted # 仍为 0,走补译分支把同一特化类方法全部重发 → invalid redefinition。 if oop_entry is not None: @@ -712,7 +712,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): if decl_reuse == 0: # 提取默认参数信息(普通方法 args[0] 是 self,不含在 param_count 中; # @staticmethod 无 self,param_count 为完整参数数) - # 注意: 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__(), + # 注意: 必须先把属性赋给显式类型为 list[...]* 的局部变量再调用 __len__(), # 否则编译器无法识别属性返回的 list 类型,GEP base 会变成 i32 0 导致 llc 报错 md_defaults: t.CPtr = None md_default_count: int = 0 diff --git a/App/lib/core/Gen/DebugInfoGen.vp b/App/lib/core/Gen/DebugInfoGen.vp index d1d14bd..a7cc4fd 100644 --- a/App/lib/core/Gen/DebugInfoGen.vp +++ b/App/lib/core/Gen/DebugInfoGen.vp @@ -49,15 +49,15 @@ _g_depth: int = 0 # current DISubprogram was pushed on (e.g. an async state machine emitted inside # a bracketed function): such instructions must carry no !dbg, otherwise LLVM's # verifier rejects "!dbg attachment points at wrong subprogram for function". -DBG_STACK_MAX: t.CDefine = 256 +define DBG_STACK_MAX = 256 _g_stk_sp: sizet* = None _g_stk_ref: str = None _g_stk_bld: str = None # DILocation cache: direct-mapped, up to 8-way linear probe, key (sp, line, col). -DBG_LOC_SLOTS: t.CDefine = 8192 -DBG_LOC_PROBE: t.CDefine = 8 -DBG_LOC_KEY_STRIDE: t.CDefine = 3 +define DBG_LOC_SLOTS = 8192 +define DBG_LOC_PROBE = 8 +define DBG_LOC_KEY_STRIDE = 3 _g_loc_key: sizet* = None _g_loc_ref: str = None _g_loc_used: bytes = None @@ -264,7 +264,7 @@ def _EnsureModuleNodes(pool: memhub.MemBuddy*) -> int: # _LocRefAt - read a cached DILocation ref string pointer # ============================================================ def _LocRefAt(slot: int) -> str: - slotp: str | t.CPtr = (str | t.CPtr)(uint64(_g_loc_ref) + sizet(slot) * 8) + slotp: str* = (str*)(uint64(_g_loc_ref) + sizet(slot) * 8) r: str = slotp[0] return r @@ -309,7 +309,7 @@ def _EnsureLocation(pool: memhub.MemBuddy*, sp: int, line: int, col: int) -> str _g_loc_key[kbase2] = sizet(sp) _g_loc_key[kbase2 + 1] = sizet(line) _g_loc_key[kbase2 + 2] = sizet(c) - rslot: str | t.CPtr = (str | t.CPtr)(uint64(_g_loc_ref) + sizet(slot2) * 8) + rslot: str* = (str*)(uint64(_g_loc_ref) + sizet(slot2) * 8) rslot[0] = lref _g_loc_used[slot2] = 1 return lref @@ -365,9 +365,9 @@ def PushFunction(pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mlirlite.function_set_dbg(func, sp_ref) # save the enclosing function's DI context (LIFO), then switch to this one _g_stk_sp[_g_depth] = sizet(_g_cur_sp + 1) - rslot: str | t.CPtr = (str | t.CPtr)(uint64(_g_stk_ref) + sizet(_g_depth) * 8) + rslot: str* = (str*)(uint64(_g_stk_ref) + sizet(_g_depth) * 8) rslot[0] = _g_cur_entry_ref - bslot: str | t.CPtr = (str | t.CPtr)(uint64(_g_stk_bld) + sizet(_g_depth) * 8) + bslot: str* = (str*)(uint64(_g_stk_bld) + sizet(_g_depth) * 8) bslot[0] = _g_cur_builder _g_depth += 1 _g_cur_sp = sp_id @@ -395,9 +395,9 @@ def PopFunction(builder: mlirlite.IRBuilder*) -> int: return 0 _g_depth -= 1 _g_cur_sp = int(_g_stk_sp[_g_depth]) - 1 - rslot: str | t.CPtr = (str | t.CPtr)(uint64(_g_stk_ref) + sizet(_g_depth) * 8) + rslot: str* = (str*)(uint64(_g_stk_ref) + sizet(_g_depth) * 8) _g_cur_entry_ref = rslot[0] - bslot: str | t.CPtr = (str | t.CPtr)(uint64(_g_stk_bld) + sizet(_g_depth) * 8) + 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) diff --git a/App/lib/core/Gen/Expr/ExprGenAttr.vp b/App/lib/core/Gen/Expr/ExprGenAttr.vp index 32d1c80..9a2a1ee 100644 --- a/App/lib/core/Gen/Expr/ExprGenAttr.vp +++ b/App/lib/core/Gen/Expr/ExprGenAttr.vp @@ -351,7 +351,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): mod: mlirlite.LLVMModule*, at_value: ast.AST*, trans: HT.Translator* = None) -> mlirlite.Value*: - """检测 at.value 是否为 c.Deref(ptr) 调用,返回 ptr 指针(不做 load)""" + """检测 at.value 是否为 *ptr 调用,返回 ptr 指针(不做 load)""" if at_value is None or at_value.kind() != ast.ASTKind.Call: return None cl_cd: ast.Call* = ast.Call*(at_value) @@ -398,12 +398,12 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): VLogger.error(diag_buf_an, "ATTR") return None - # static 符号(禁止跨模块使用):`mod.name` 命中别的模块登记的 static 符号 - # 即 fail-fast。逻辑全部收敛在 _CheckStaticCrossModule 内——不在此内联展开 - # (内联会让本函数的类型推断受干扰:新增分支/跨函数调用改变了后续变量 - # 的推断结果,曾导致本函数 L765 的 `match obj_ptr.Ty` 报"指针隐式转整数")。 - self._CheckStaticCrossModule(pool, trans, at) - + # static 符号(禁止跨模块使用):`mod.name` 命中别的模块登记的 static 符号 + # 即 fail-fast。逻辑全部收敛在 _CheckStaticCrossModule 内——不在此内联展开 + # (内联会让本函数的类型推断受干扰:新增分支/跨函数调用改变了后续变量 + # 的推断结果,曾导致本函数 L765 的 `match obj_ptr.Ty` 报"指针隐式转整数")。 + self._CheckStaticCrossModule(pool, trans, at) + # 魔法属性 __doc__:查询 docstring 登记表(预注册阶段从 AST 提取), # 命中则当前模块内联生成字符串常量返回;未命中(无 docstring 的 # 函数/类/方法)返回 null 指针(i8*)。支持本模块与跨模块符号: @@ -760,7 +760,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): 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|t.CPtr)由 _deref_if_ptr_ptr load 解引用 + # 地址语义),指针字段(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) @@ -770,7 +770,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if obj_ptr is None or obj_ptr.Ty is None: return None - # 如果 obj_ptr 是 Ptr(Ptr(Struct))(X|t.CPtr 变量的 alloca), + # 如果 obj_ptr 是 Ptr(Ptr(Struct))(X* 变量的 alloca), # load 解引用获取 Ptr(Struct) obj_ptr = self._deref_if_ptr_ptr(builder, obj_ptr) @@ -800,7 +800,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if alias_fe is not None and alias_fe.Ty is not None: alias_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, alias_fe.Ty, obj_ptr, alias_idx) if alias_ptr is not None: - # REnum 变体字段按声明类型读取(对齐 match 绑定 _lookup_renum_member_ty):槽位是 i32/i64(布局按最大字段大小),直接 load 得整数位模式,赋给 X|t.CPtr 指针变量会触发 int→ptr 禁令误报。用别名表存的成员声明类型(自引用退化为 i8*)把槽位地址 bitcast 后按声明类型 load——同宽无信息丢失,指针字段读出真正的指针值 + # REnum 变体字段按声明类型读取(对齐 match 绑定 _lookup_renum_member_ty):槽位是 i32/i64(布局按最大字段大小),直接 load 得整数位模式,赋给 X* 指针变量会触发 int→ptr 禁令误报。用别名表存的成员声明类型(自引用退化为 i8*)把槽位地址 bitcast 后按声明类型 load——同宽无信息丢失,指针字段读出真正的指针值 decl_ty_rn: mlirlite.LLVMType* = self.Gen.ClassGenEnum._lookup_renum_field_alias_ty(renum_se.Name, at.attr) if decl_ty_rn is not None: decl_ptr_rn: mlirlite.LLVMType* = mlirlite.Ptr(pool, decl_ty_rn) @@ -854,7 +854,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): 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|t.CPtr 简化为 Ptr(i8)), + # 原始 struct_ty 可能是 i8(X* 简化为 Ptr(i8)), # 需用实际结构体类型做 GEP,否则 GEP i8 失败 if field_info is not None: annot_se: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(base_class) @@ -889,7 +889,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if field_ptr is not None: # [FIX 2026-08-31] REnum 变体字段按声明类型读取(与主路径 # 变体别名回退一致):field_info 是 _pN 槽位(i32/i64), - # 直接 load 得整数位模式 → 赋给 X|t.CPtr 指针变量触发 int→ptr + # 直接 load 得整数位模式 → 赋给 X* 指针变量触发 int→ptr # 误报。bitcast 槽位地址后按声明类型 load(同宽无信息丢失)。 rn_rd_se: GenTypes.StructEntry* = \ self.Gen.StructGen.find_struct_by_type(struct_ty) @@ -908,7 +908,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): 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 | t.CPtr)被编译为 i8*, + # 联合类型字段(如 Token*)被编译为 i8*, # 若 AnnotClassName 指示了具体结构体类型,bitcast 为正确的结构体指针。 # 注意:仅当字段类型本身是指针时才 bitcast(指针→指针); # 内嵌结构体字段(field_ty=Struct)load 出的是结构体值, @@ -988,7 +988,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): allow_module_global: int = 0) -> str: """解析属性链(a.b.c)中 c 字段的注解类名。 - 联合类型字段(X | t.CPtr)被简化为 Ptr(i8),属性链写入时 + 联合类型字段(X*)被简化为 Ptr(i8),属性链写入时 (如 lx.tokens_tail.next = tok)obj_ptr.Ty 是 Ptr(i8), lookup_field(i8, ...) 必然失败。此函数沿属性链递归解析 最终字段的 AnnotClassName(如 tokens_tail → 'Token'), @@ -1043,8 +1043,8 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): # ============================================================ # _base_class_from_cast_base - 指针强转基座 `T*(x)` 的类名 # - # `T*(x)` 被 parser 的 _consume_ptr_suffix_call 解析成 `(T | t.CPtr)(x)` - # 强转调用(与手写 `(T | t.CPtr)(x)` 逐字同形),与 `t.CPtr` 取联合后结果 + # `T*(x)` 被 parser 的 _consume_ptr_suffix_call 解析成 `(T*)(x)` + # 强转调用(与手写 `(T*)(x)` 逐字同形),与 `t.CPtr` 取联合后结果 # 的 LLVM 类型是**简化后的 i8***。于是 `(ast.Call*(vinner)).IsVolatile` # 这类强转基座的字段访问/写入里 lookup_field(i8, ...) 必然失败。 # @@ -1076,7 +1076,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): bo_cb: ast.BinOp* = ast.BinOp*(cl_cb.func) if bo_cb.op != ast.OpKind.BitOr: return None - # 联合一侧是 t.CPtr 标记(`T | t.CPtr` / `T**` 展开的嵌套联合)时取另一侧; + # 联合一侧是 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: @@ -1259,7 +1259,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): 仅当基址可解析到具体 VarEntry(Name)/ FieldEntry(Attribute)时生效; 基址是函数返回/下标/调用/更复杂表达式时返回 0(明确不支持)。 - 消费点:p[i] / p.field / c.Deref(p) 的 load/store 据此加 LLVM volatile。 + 消费点:p[i] / p.field / *p 的 load/store 据此加 LLVM volatile。 """ if base_node is None or trans is None: return 0 @@ -1363,7 +1363,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if obj_ptr is None or obj_ptr.Ty is None: return None - # 如果 obj_ptr 是 Ptr(Ptr(Struct))(X|t.CPtr 变量的 alloca), + # 如果 obj_ptr 是 Ptr(Ptr(Struct))(X* 变量的 alloca), # load 解引用获取 Ptr(Struct) obj_ptr = self._deref_if_ptr_ptr(builder, obj_ptr) @@ -1413,7 +1413,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): 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|t.CPtr 简化为 Ptr(i8)), + # 原始 struct_ty 可能是 i8(X* 简化为 Ptr(i8)), # 需用实际结构体类型做 GEP,否则 GEP i8 失败 if field_info is not None: annot_se: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(base_class) diff --git a/App/lib/core/Gen/Expr/ExprGenBase.vp b/App/lib/core/Gen/Expr/ExprGenBase.vp index 2dca86b..766305a 100644 --- a/App/lib/core/Gen/Expr/ExprGenBase.vp +++ b/App/lib/core/Gen/Expr/ExprGenBase.vp @@ -224,7 +224,7 @@ novirtual class ExprGenBase: # # 属性访问的 Subscript 基座(如 lst[i].x)需要区分: # - list[T] 变量:translate_subscript 走 __getitem__ 内联返回元素地址 - # - 普通结构体指针数组(如 pts: Point | t.CPtr):get_subscript_ptr 返回元素地址 + # - 普通结构体指针数组(如 pts: Point*):get_subscript_ptr 返回元素地址 # 路由错误会让 list[T] 被当作结构体数组 GEP,访问错位崩溃。 # ============================================================ def _is_list_subscript_base(self, pool: memhub.MemBuddy*, @@ -282,7 +282,7 @@ novirtual class ExprGenBase: # 属性访问的 Subscript 基座路由依据: # - list[T] / OOP 定义 __getitem__ 的类(如 dict[key])→ translate_value # (translate_subscript 走 __getitem__ 内联/方法调用返回元素值或地址) - # - 普通结构体指针数组(如 pts: Point | t.CPtr)→ get_subscript_ptr + # - 普通结构体指针数组(如 pts: Point*)→ get_subscript_ptr # (GEP 元素地址,避免结构体值 base=非指针 报错) # ============================================================ def _sub_base_uses_getitem(self, pool: memhub.MemBuddy*, @@ -301,9 +301,9 @@ novirtual class ExprGenBase: # ============================================================ # _deref_if_ptr_ptr - 如果 obj_ptr 是 Ptr(Ptr(...)),load 解引用 # - # 用于支持 X|t.CPtr 类型变量的属性访问: + # 用于支持 X* 类型变量的属性访问: # - 值类型变量 (cnt: Counter): alloca 类型是 Ptr(Struct) → 不解引用 - # - 指针类型变量 (r: Vec2|t.CPtr): alloca 类型是 Ptr(Ptr(Struct)) → load 解引用 + # - 指针类型变量 (r: Vec2*): alloca 类型是 Ptr(Ptr(Struct)) → load 解引用 # ============================================================ def _deref_if_ptr_ptr(self, builder: mlirlite.IRBuilder*, obj_ptr: mlirlite.Value*) -> mlirlite.Value*: @@ -344,8 +344,8 @@ novirtual class ExprGenBase: v = (ast.Return*(node)).value if v is None: return node - return v - # ============================================================ + return v + # ============================================================ # IsNoneValue - 判据:源值是否为 None(空值常量),返回 1=是 / 0=否 # # None 是特殊的空值常量:语义上「无值」,按语言规则**允许隐式转换为任意 @@ -437,7 +437,7 @@ novirtual class ExprGenBase: # 调用方从**注解来源**给出:赋值侧 trans.CurAssignAnnot、返回侧 # trans.CurFuncRetAnnot、形参侧 vpi/函数签名注解段。 # - # 只认**裸名**:`str` / `bytes`。`str | t.CPtr` 的语义是 i8**(指针槽, + # 只认**裸名**:`str` / `bytes`。`str*` 的语义是 i8**(指针槽, # 见 AssignGenMixin._is_ptr_element_annotation),不是字符串值本体,不适用。 # ============================================================ def _annot_name_is_bare_str(self, txt: str) -> int: @@ -864,18 +864,18 @@ novirtual class ExprGenBase: # (inttoptr 要求同宽,对齐 MatchGenMixin 模式),再 inttoptr 成空指针。 if val.IsConst == 1 and val.IntVal == 0: return mlirlite.build_inttoptr(builder, mlirlite.const_int64(builder.Pool, 0), target_ty) - m_i2p: str = "整数隐式转指针已禁止:必须显式强转为指针(如 t.CPtr(x))才能把整数赋给指针类型" - self.Gen.TypeGenErr.fatal_error(self._value_node_of(node), - m_i2p, "CastError") + m_i2p: str = "整数隐式转指针已禁止:必须显式强转为指针(如 t.CPtr(x))才能把整数赋给指针类型" + self.Gen.TypeGenErr.fatal_error(self._value_node_of(node), + m_i2p, "CastError") return val # Pointer -> integer: rejected (symmetric with the integer -> pointer rule above). # No implicit pointer <-> integer conversion is allowed; an explicit cast is # required. (The old code silently did ptrtoint, and for 8-bit targets fell # through to the build_load branch below, copying the pointee's first byte.) if self.is_ptr_type(val.Ty) != 0 and target_bits != 0 and self.is_ptr_type(target_ty) == 0: - m_p2i: str = "指针隐式转整数已禁止:必须显式强转(如 uint64(p) / t.CInt64T(p) / int(p))才能把指针赋给整数类型" - self.Gen.TypeGenErr.fatal_error(self._value_node_of(node), - m_p2i, "CastError") + m_p2i: str = "指针隐式转整数已禁止:必须显式强转(如 uint64(p) / int64(p) / int(p))才能把指针赋给整数类型" + self.Gen.TypeGenErr.fatal_error(self._value_node_of(node), + m_p2i, "CastError") return val if val_bits != 0 and target_bits != 0: if val_bits == target_bits: @@ -981,7 +981,7 @@ novirtual class ExprGenBase: return val return mlirlite.build_load(builder, target_ty, val) self.Gen.TypeGenErr.fatal_error(self._value_node_of(node), - f"指针隐式转非指针值已禁止:必须显式解引用(c.Deref(p) / *p)或显式强转(uint64(p))", "CastError") + f"指针隐式转非指针值已禁止:必须显式解引用(*p / *p)或显式强转(uint64(p))", "CastError") return val # 指针 → 指针: 隐式转换须满足两条新规则(见 _ptr_cast_reason 单一真源): # 规则 1 通用指针(t.CPtr / i8*)与任何 T* 双向互转都放行; diff --git a/App/lib/core/Gen/Expr/ExprGenCdef.vp b/App/lib/core/Gen/Expr/ExprGenCdef.vp index 39e7ddb..213c7eb 100644 --- a/App/lib/core/Gen/Expr/ExprGenCdef.vp +++ b/App/lib/core/Gen/Expr/ExprGenCdef.vp @@ -1187,7 +1187,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): f"(该位宽按有符号/无符号两种解释可接受的范围: {lo}..{hi})。" f"禁止静默截断/降级,已终止编译。" f"修法: 把使用处{ctx}的类型加宽到至少 {wmin} 位" - f"(如 t.CInt{wmin}T / CUInt{wmin}T 及更宽类型),或改用更小的常量值。", + f"(如 int{wmin}T / CUInt{wmin}T 及更宽类型),或改用更小的常量值。", "TypeError") return None return mlirlite.const_int(pool, bits, self._cdefine_bits_value(value, bits)) \ No newline at end of file diff --git a/App/lib/core/Gen/Expr/ExprGenCls.vp b/App/lib/core/Gen/Expr/ExprGenCls.vp index d2dc5ac..16cc659 100644 --- a/App/lib/core/Gen/Expr/ExprGenCls.vp +++ b/App/lib/core/Gen/Expr/ExprGenCls.vp @@ -258,7 +258,7 @@ novirtual class ExprGenCls(ExprGenBase.ExprGenBase): # infer_expr_class - 从表达式推断结构体类名(共享推断) # # 无注解赋值(HandlesAssign)与方法调用分派(CallGenMixin)共用: - # 联合类型 X|t.CPtr 简化为 Ptr(i8),不含类名,需按表达式结构推断: + # 联合类型 X* 简化为 Ptr(i8),不含类名,需按表达式结构推断: # Call → 类实例化(func 为已注册结构体名);func 为 Attribute # 时是方法调用,经 vpi 返回注解缓存解析返回类名 # Name → 源变量的 AnnotClassName @@ -415,7 +415,7 @@ novirtual class ExprGenCls(ExprGenBase.ExprGenBase): while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'): s += 1 # 段尾另需剥 '*':实参归一后段文本是 `{sha}.AST*`(旧形态 - # `{sha}.AST | t.CPtr` 按 '|' 分段能落到 `{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] == '*'): @@ -440,7 +440,7 @@ novirtual class ExprGenCls(ExprGenBase.ExprGenBase): while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'): s += 1 # 段尾另需剥 '*':实参归一后段文本是 `{sha}.AST*`(旧形态 - # `{sha}.AST | t.CPtr` 按 '|' 分段能落到 `{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] == '*'): diff --git a/App/lib/core/Gen/Expr/ExprGenName.vp b/App/lib/core/Gen/Expr/ExprGenName.vp index cd7c9af..f9dd292 100644 --- a/App/lib/core/Gen/Expr/ExprGenName.vp +++ b/App/lib/core/Gen/Expr/ExprGenName.vp @@ -97,7 +97,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if self.Gen.ExprGenCdef._is_cdefine_name_pattern(nm_id) != 0: if trans is not None: # ALL_CAPS 也可能是普通变量(如 Gargantua 的 - # CAM/FWD/RIGHT/UP: V3|t.CPtr 模块级全局)。若当前作用域 + # CAM/FWD/RIGHT/UP: V3* 模块级全局)。若当前作用域 # (含模块级 Root,lookup_var 逐级上溯)已存在同名变量, # 优先按变量处理,跳过跨模块 CDefine 查找——否则 ALL_CAPS # 命中 star-import 模块(from stdint import *)→ 无谓读源 @@ -385,17 +385,17 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): or string.strcmp(nm_id, "CIf") == 0 or string.strcmp(nm_id, "CIfdef") == 0 \ or string.strcmp(nm_id, "CIfndef") == 0: return None - # 诊断:把当前泛型上下文一并报出 —— "未定义名称 'T'" 常与真因(泛型上下文 - # 为空 / 装不上)严重脱节:形参 0 个 ⇒ 上下文根本没建起来;形参 >0 而实参 0 - # 个 ⇒ 实参表丢了;两者皆 >0 ⇒ 上下文在、但该名字不在其中。一眼可分。 - # (现场 includes/vector.vp:12 `T.__sizeof__()`,Vector[CFloat64T] 特化) - ctx_txt: str = "" - 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) - ctx_txt = f"(当前泛型上下文: 类型形参 {ctp_n} 个 / 类型实参 {cta_n} 个)" + # 诊断:把当前泛型上下文一并报出 —— "未定义名称 'T'" 常与真因(泛型上下文 + # 为空 / 装不上)严重脱节:形参 0 个 ⇒ 上下文根本没建起来;形参 >0 而实参 0 + # 个 ⇒ 实参表丢了;两者皆 >0 ⇒ 上下文在、但该名字不在其中。一眼可分。 + # (现场 includes/vector.vp:12 `T.__sizeof__()`,Vector[CFloat64T] 特化) + ctx_txt: str = "" + 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) + ctx_txt = f"(当前泛型上下文: 类型形参 {ctp_n} 个 / 类型实参 {cta_n} 个)" self.Gen.TypeGenErr.fatal_error(node, f"未定义名称 '{nm_id}'{ctx_txt}", "NameError") return None # ============================================================ @@ -481,7 +481,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): 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|t.CPtr]): + # list[rawptr[7565e081d88517ac.AST]] / list[sha1.Foo*]): # 元素槽存对象指针(8 字节)。从元素类型文本还原对象指针 LLVM 类型 # Ptr(%Struct),使 list.get/__getitem__/pop 内联返回值的 LLVM 类型 # 携带元素原型类——链式方法调用(mod.children.get(0).kind())的接收者 @@ -500,7 +500,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # _list_elem_obj_ty_from_struct_name — 从 list 特化类型名还原元素对象指针类型 # # struct_name 形如 "{_list_sha1}.list[rawptr[{sha1}.AST]]" 或 - # "{_list_sha1}.list[{sha1}.AST|t.CPtr]"(联合元素)。取 '[' 与最后 ']' + # "{_list_sha1}.list[{sha1}.AST*]"(联合元素)。取 '[' 与最后 ']' # 之间的元素描述文本:剥 rawptr[...] 包装、按 '|' 联合分段、去首尾空白, # 逐段按已注册结构体还原(元素类带模块 SHA1 前缀时 find_struct 走 # find_struct_by_module 精确匹配,规避跨模块同名歧义);命中返回 @@ -857,10 +857,10 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): return mlirlite.build_load(builder, elem_ty_list, casted_addr_list) return None # inner_ty 是 Ptr 说明 alloca.Ty 是三重指针 Ptr(Ptr(Ptr(...))), - # 即 X|t.CPtr 当 X 本身是指针类型 (如 T=AST|t.CPtr, T|t.CPtr=AST**)。 + # 即 X* 当 X 本身是指针类型 (如 T=AST*, T*=AST**)。 # 此时 [i] 应该是指针解引用 (步长 sizeof(ptr)=8), 而非调用 # 结构体的 __getitem__ 方法 (会错误生成 AST.__getitem__ 调用)。 - # 对比 HashTable|t.CPtr: alloca.Ty=HashTable**, inner_ty=Struct(HashTable) + # 对比 HashTable*: alloca.Ty=HashTable**, inner_ty=Struct(HashTable) # (非 Ptr), 仍走下面的方法调用转发路径。 if self.is_ptr_type(inner_ty) != 0: ptr_val_pp: mlirlite.Value* = mlirlite.build_load(builder, pointee, alloca) @@ -870,7 +870,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # volatile 指针指向物:解引用 load 带 volatile return mlirlite.build_load(builder, inner_ty, elem_ptr_pp, vol_sub_rd) return None - # 自定义结构体 (如 HashTable|t.CPtr, JsonValue|t.CPtr): + # 自定义结构体 (如 HashTable*, JsonValue*): # 仅当类定义了 __getitem__(当前模块定义或跨模块 stub declare 注入) # 才转发方法调用;否则普通结构体指针按下标做 GEP 数组访问 # (对齐 TPC _HandleSubscriptLlvm: if ClassName and has_function(__getitem__)) @@ -896,14 +896,14 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # volatile 指针指向物:解引用 load 带 volatile return mlirlite.build_load(builder, inner_ty, elem_rd_g, vol_sub_rd) return None - # bytes|t.CPtr / str|t.CPtr: alloca 是 i8**, + # bytes* / str*: alloca 是 i8**, # 直接 GEP 按 i8* 步长(8 字节),load i8* # 仅当 inner_ty 不是自定义结构体时才走指针遍历 if trans is not None: ve_pe_ts: GenTypes.VarEntry* = \ self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id) if self.Gen.VarGen.var_is_ptr_element(ve_pe_ts) != 0: - # bytes|t.CPtr / str|t.CPtr / T|t.CPtr:变量存指针值(i8*), + # bytes* / str* / T*:变量存指针值(i8*), # elem[i] 语义 = load [指针值 + i*8](8 字节指针元素)。 # 必须先 load alloca 得指针值,再 GEP i8*(步长 8)—— # 否则 GEP base 用 alloca(&elem_ptr)读到栈变量而非数据区, @@ -925,7 +925,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): return None case _: # 联合类型变量(IsPtrElement=1,如 _list.vp 的 - # elem_ptr: T | t.CPtr 退化为 i8*):pointee=i8 但 + # elem_ptr: T* 退化为 i8*):pointee=i8 但 # 元素是 8 字节指针,须按 i8* 步长 GEP + load i8*—— # 否则 list.get 只读 1 字节,指针截断 inttoptr 崩溃。 if trans is not None: @@ -991,7 +991,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): case _: pass # 64-bit scalar pointer fields (e.g. `sizet*`, `uint64*`, written as - # `t.CUInt64T | t.CPtr`) keep the declared element type here: the slot is + # `t.CUInt64T*`) keep the declared element type here: the slot is # a u64, so it is read as i64 -- same element type the write path uses # (see get_subscript_ptr). Loading it as i8* fabricated a pointer value # out of an integer slot and forced the caller through an implicit @@ -1027,7 +1027,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # ============================================================ def _annot_is_64bit_scalar(self, annot: str) -> int: """注解是否为 64 位标量 | t.CPtr 联合(AnnotClassName 为提取出的 - 非 CPtr 侧类型名,如 int64|t.CPtr → "CInt64T")。此类联合的 + 非 CPtr 侧类型名,如 int64* → "CInt64T")。此类联合的 8 字节单元格存 i64 标量,下标元素类型应为 Int64 而非指针。""" if annot is None: return 0 if string.strstr(annot, "CInt64T") is not None: return 1 @@ -1140,14 +1140,14 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): return mlirlite.build_gep_array(builder, pointee, elem_ty, alloca, idx_val) case mlirlite.LLVMType.Ptr(inner_ty): # inner_ty 是 Ptr 说明 alloca.Ty 是三重指针, - # 即 X|t.CPtr 当 X 本身是指针类型 (如 T=AST|t.CPtr, T|t.CPtr=AST**)。 + # 即 X* 当 X 本身是指针类型 (如 T=AST*, T*=AST**)。 # 此时 [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) return None - # 自定义结构体 (如 HashTable|t.CPtr, JsonValue|t.CPtr): + # 自定义结构体 (如 HashTable*, JsonValue*): # 仅当类定义了 __setitem__(当前模块定义或跨模块 stub declare 注入) # 才返回 None 触发 __setitem__ 重载;否则普通结构体指针按下标 # 做 GEP 数组访问(走下方指针遍历路径) @@ -1158,22 +1158,22 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): 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 - # bytes|t.CPtr / str|t.CPtr: alloca 是 i8**, + # bytes* / str*: alloca 是 i8**, # 直接 GEP 按 i8* 步长(8 字节),不 load # 仅当 inner_ty 不是自定义结构体时才走指针遍历 if trans is not None: ve_pe: GenTypes.VarEntry* = \ self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id) if self.Gen.VarGen.var_is_ptr_element(ve_pe) != 0: - # bytes|t.CPtr / str|t.CPtr / T|t.CPtr:变量存指针值, + # bytes* / str* / T*:变量存指针值, # 下标语义 = [指针值 + i*8](8 字节指针元素)。必须先 load # alloca 得指针值,再 GEP——否则 GEP base 用 alloca(&elem_ptr) # 读到栈变量而非数据区,赋值写不进 list 数据 # (data 全 0xbaadf00d,dump 虚调用读错 vtable 崩溃)。 ptr_val_pe: mlirlite.Value* = mlirlite.build_load(builder, pointee, alloca) if ptr_val_pe is not None: - # [FIX 2026-08-30] 64 位标量联合(int64|t.CPtr / - # uint64|t.CPtr / sizet|t.CPtr):8 字节单元格存 + # [FIX 2026-08-30] 64 位标量联合(int64* / + # uint64* / sizet*):8 字节单元格存 # i64 标量(viperlib %n 的 np[0]=write_count 是解引用写入, # 语义 *np=(i64)x)。GEP 元素必须用 Int64(标量)而非指针, # 否则元素类型为指针 → i64 存储触发整数隐式转指针 @@ -1201,13 +1201,13 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # alloca 是 Ptr(标量), 直接 GEP 获取第 idx 个元素指针 # 支持 arg_vals[i] = val 这类参数数组下标赋值 # 联合类型变量(IsPtrElement=1,如 _list.vp 的 - # elem_ptr: T | t.CPtr 退化为 i8*):pointee=i8 但 + # elem_ptr: T* 退化为 i8*):pointee=i8 但 # 元素是 8 字节指针,须按 i8* 步长 GEP(防只写 1 字节截断) if trans is not None: ve_pe_cs: GenTypes.VarEntry* = \ self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id) if self.Gen.VarGen.var_is_ptr_element(ve_pe_cs) != 0: - # T|t.CPtr(退化为 i8*,如 _list.vp 的 elem_ptr)变量 + # T*(退化为 i8*,如 _list.vp 的 elem_ptr)变量 # 存数据区指针,元素为 8 字节指针:必须先 load alloca # 得指针值,再按 i8* 步长 GEP——否则 GEP base 用 alloca # (&elem_ptr)算到栈地址,赋值写不进 list 数据区 diff --git a/App/lib/core/Gen/Expr/ExprGenOps.vp b/App/lib/core/Gen/Expr/ExprGenOps.vp index 675de03..015bd81 100644 --- a/App/lib/core/Gen/Expr/ExprGenOps.vp +++ b/App/lib/core/Gen/Expr/ExprGenOps.vp @@ -271,7 +271,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): return 0 if k == ast.ASTKind.Subscript: # 数组/指针下标: md5_buf[i](t.CArray[uint8, N])或 buf[i] - # (形参 uint8 | t.CPtr)元素是无符号整型 → printf("%02x", ...) zext。 + # (形参 uint8*)元素是无符号整型 → printf("%02x", ...) zext。 sub_su: ast.Subscript* = ast.Subscript*(node) if sub_su.value is not None and sub_su.value.kind() == ast.ASTKind.Name: snm_su: ast.Name* = ast.Name*(sub_su.value) @@ -427,7 +427,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): 真源按顶层 '|' 分段、去括号/空白、取 `IDENT[INNER]` 的元素、去模块限定前缀, 再走精确名白名单 + CTypedef 链展开 —— 已覆盖原 `_annot_str_unsigned_scan` - 对复合注解(`t.CArray[uint8, 16]` / `uint8 | t.CPtr`)的全部能力, + 对复合注解(`t.CArray[uint8, 16]` / `uint8*`)的全部能力, 且无子串假阳性。UNKNOWN = 不表态 ⇒ 返回 0。 """ if annot is not None: @@ -444,7 +444,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if cmp is None: return None - ops_list: list[int] | t.CPtr = (list[int] | t.CPtr)(cmp.ops) + ops_list: list[int]* = (list[int]*)(cmp.ops) if ops_list is None or len(ops_list) == 0: return None op: int = ops_list.get(0) @@ -907,7 +907,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): 不能在这里再套 alloca+store:那会得到 Ptr(Ptr(Struct))(存放地址的槽 地址),赋值端还得 load 一次才回落,语义也从"对象地址"变成"槽地址"。 · 其它返回值(标量、按值返回的结构体值等):rvalue 的地址只能靠临时槽 - 承载——入口 alloca 同类型槽 → store → 返回槽地址(与 c.Addr(expr) 的 + 承载——入口 alloca 同类型槽 → store → 返回槽地址(与 &expr 的 Call 形式同口径,见 CallGenCBuiltin.translate_c_addr)。 """ if call_val is None or call_val.Ty is None: @@ -1549,7 +1549,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): lhs_alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id) if lhs_alloca is not None: ovl_self1: mlirlite.Value* = lhs_alloca - # alloca 是 Ptr(Ptr(Struct))(X|t.CPtr 对象存储槽)时, + # alloca 是 Ptr(Ptr(Struct))(X* 对象存储槽)时, # load 出对象指针作为 self——若把槽地址当 self,dunder 内 # load 槽内容(对象指针值)当字段读 → 垃圾(MultiInheritTest # Vec2Both __add__ 输出 (1.0,2.0) 根因;get_struct_type_from_value @@ -1567,7 +1567,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if lhs is None: return None - # === 运算符重载路径 2: lhs 是 Ptr(Struct)(如 Counter|t.CPtr 变量 load 后)=== + # === 运算符重载路径 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 diff --git a/App/lib/core/Gen/Func/FuncGenDef.vp b/App/lib/core/Gen/Func/FuncGenDef.vp index 47a3644..9e879f6 100644 --- a/App/lib/core/Gen/Func/FuncGenDef.vp +++ b/App/lib/core/Gen/Func/FuncGenDef.vp @@ -183,7 +183,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): continue # 提取默认参数信息 - # 注意: 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__(), + # 注意: 必须先把属性赋给显式类型为 list[...]* 的局部变量再调用 __len__(), # 否则编译器无法识别属性返回的 list 类型,GEP base 会变成 i32 0 导致 llc 报错 fd_args_node: ast.Arguments* = fd.args fd_defaults: t.CPtr = None @@ -987,21 +987,21 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): _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。 - # merge 可达(分支 br 到 merge,如 testcheck.check 的 if/else 无 return) - # 时不是结构性不可达,需正常收尾(下方 ConstZero / fail-fast):可达块的 - # unreachable 是 UB,llc 不生成任何指令 ⇒ 执行掉进布局紧随其后的块。 - # ★ 可达性判据**只用 `_ctrl_merge_reachable`**(MatchGenMixin 逐臂真正 - # `br end_bb` 时才置 1,并由"用本 match 自身的 br 记录覆盖"写回): - # 实测反面教材 —— includes/mlirlite/__types.vp::_TypePrintDepth 末句 - # `match ty:` 带 `case _:`,各臂只 snprintf 后 br 到 merge;旧判据(追加92 - # 的 MatchHasWildcardArm 子句)按"穷尽 ⇒ 流程不可能掉出末尾"推断,给这个 - # 可达 merge 生成了 unreachable ⇒ 打印完 "i32" 后掉进同一 switch 的跳转表, - # 用上一条 snprintf 的返回值("i%d" → 3)当 tag 取 table[3] = Array 臂, - # 把 Int 的 Bits(32) 当指针递归解引用 ⇒ AV at 0x20。 - # 穷尽性 ≠ 各臂都终止:只有"有没有 br 到 merge"才是可达性。 + elif last_is_ctrl != 0 and trans._ctrl_merge_reachable == 0: + # 追加90:非 void 函数末句是控制流且 merge 块**结构性**不可达 + # (全分支 return,无 br 到 merge)→ LLVM 语义 unreachable。 + # merge 可达(分支 br 到 merge,如 testcheck.check 的 if/else 无 return) + # 时不是结构性不可达,需正常收尾(下方 ConstZero / fail-fast):可达块的 + # unreachable 是 UB,llc 不生成任何指令 ⇒ 执行掉进布局紧随其后的块。 + # ★ 可达性判据**只用 `_ctrl_merge_reachable`**(MatchGenMixin 逐臂真正 + # `br end_bb` 时才置 1,并由"用本 match 自身的 br 记录覆盖"写回): + # 实测反面教材 —— includes/mlirlite/__types.vp::_TypePrintDepth 末句 + # `match ty:` 带 `case _:`,各臂只 snprintf 后 br 到 merge;旧判据(追加92 + # 的 MatchHasWildcardArm 子句)按"穷尽 ⇒ 流程不可能掉出末尾"推断,给这个 + # 可达 merge 生成了 unreachable ⇒ 打印完 "i32" 后掉进同一 switch 的跳转表, + # 用上一条 snprintf 的返回值("i%d" → 3)当 tag 取 table[3] = Array 臂, + # 把 Int 的 Bits(32) 当指针递归解引用 ⇒ AV at 0x20。 + # 穷尽性 ≠ 各臂都终止:只有"有没有 br 到 merge"才是可达性。 mlirlite.build_unreachable(func_builder) elif fd.returns is None: # 无返回类型注解 → 无返回值过程函数,默认零值返回 diff --git a/App/lib/core/Gen/Func/FuncGenMixin.vp b/App/lib/core/Gen/Func/FuncGenMixin.vp index d4c2fdc..f723228 100644 --- a/App/lib/core/Gen/Func/FuncGenMixin.vp +++ b/App/lib/core/Gen/Func/FuncGenMixin.vp @@ -93,7 +93,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): case _: pty_n = resolved_n if param_count < 64 and param_tys is not None: - pty_slot_n: str | t.CPtr = (str | t.CPtr)(uint64(param_tys) + param_count * 8) + pty_slot_n: str* = (str*)(uint64(param_tys) + param_count * 8) pty_slot_n[0] = pty_n pname_n: str = pool.alloc(32) if pname_n is not None: @@ -142,7 +142,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): 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 | t.CPtr = (str | t.CPtr)(ty_addr_n) + 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 @@ -306,7 +306,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): for ni in range(nested_nonlocal_count): # 从 _nonlocal_names 缓冲区读取名称 name_addr: uint64 = uint64(trans._nonlocal_names) + ni * 8 - nl_slot: str | t.CPtr = (str | t.CPtr)(name_addr) + nl_slot: str* = (str*)(name_addr) nl_name: str = nl_slot[0] if nl_name is None: continue @@ -1180,7 +1180,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): cap_slot: str = cap_names + ci * 64 if cap_slot[0] == '\0': continue ty_addr3: uint64 = uint64(cap_tys) + ci * 8 - ty_slot3: str | t.CPtr = (str | t.CPtr)(ty_addr3) + ty_slot3: str* = (str*)(ty_addr3) cap_ty: mlirlite.LLVMType* = (mlirlite.LLVMType*)(ty_slot3[0]) if cap_ty is None: continue off_val: mlirlite.Value* = mlirlite.const_int32(pool, ci * 8) @@ -1200,7 +1200,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): # 10. 参数 alloca for pi3 in range(param_count): ty_addr4: uint64 = uint64(param_tys) + pi3 * 8 - ty_slot4: str | t.CPtr = (str | t.CPtr)(ty_addr4) + ty_slot4: str* = (str*)(ty_addr4) p_ty3: mlirlite.LLVMType* = (mlirlite.LLVMType*)(ty_slot4[0]) if p_ty3 is None: # fail-fast:lambda 参数类型槽缺失(内部状态不一致),不再静默保持 i32 @@ -1260,11 +1260,11 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): if cap_slot3[0] == '\0': continue al_addr: uint64 = uint64(cap_allocas) + ci3 * 8 - al_slot: str | t.CPtr = (str | t.CPtr)(al_addr) + al_slot: str* = (str*)(al_addr) var_alloca2: mlirlite.Value* = (mlirlite.Value*)(al_slot[0]) if var_alloca2 is None: continue ty_addr5: uint64 = uint64(cap_tys) + ci3 * 8 - ty_slot5: str | t.CPtr = (str | t.CPtr)(ty_addr5) + ty_slot5: str* = (str*)(ty_addr5) cap_ty2: mlirlite.LLVMType* = (mlirlite.LLVMType*)(ty_slot5[0]) if cap_ty2 is None: continue # 堆存储大小:位宽/8,至少 8 字节(容纳指针/标量) @@ -1374,9 +1374,9 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): if cap_count >= 64: return cap_count string.strncpy(cap_names + cap_count * 64, nm.id, 63) - al_slot: str | t.CPtr = (str | t.CPtr)(uint64(cap_allocas) + cap_count * 8) + al_slot: str* = (str*)(uint64(cap_allocas) + cap_count * 8) al_slot[0] = alloca - ty_slot: str | t.CPtr = (str | t.CPtr)(uint64(cap_tys) + cap_count * 8) + ty_slot: str* = (str*)(uint64(cap_tys) + cap_count * 8) ty_slot[0] = pointee return cap_count + 1 # 递归遍历常见表达式子节点 diff --git a/App/lib/core/Gen/GenTypes.vp b/App/lib/core/Gen/GenTypes.vp index c380d40..4176bf0 100644 --- a/App/lib/core/Gen/GenTypes.vp +++ b/App/lib/core/Gen/GenTypes.vp @@ -18,33 +18,33 @@ import lib.core.Gen.Type.TypeSpec as TSpec # ============================================================ # 类编译期元数据(原 HandlesType.CLASS_META_*) # ============================================================ -CLASS_META_PROVIDES: t.CDefine = 1 -CLASS_META_REQUIRES: t.CDefine = 2 -CLASS_META_REQUIRE_MUST: t.CDefine = 3 +define CLASS_META_PROVIDES = 1 +define CLASS_META_REQUIRES = 2 +define CLASS_META_REQUIRE_MUST = 3 # ============================================================ # 属性/静态/类方法元数据(原 HandlesClassDef.META_*) # ============================================================ -META_STATIC: t.CDefine = 1 -META_CLASS: t.CDefine = 2 -META_PROP_GETTER: t.CDefine = 4 -META_PROP_SETTER: t.CDefine = 8 -META_PROP_DELETER: t.CDefine = 16 +define META_STATIC = 1 +define META_CLASS = 2 +define META_PROP_GETTER = 4 +define META_PROP_SETTER = 8 +define META_PROP_DELETER = 16 # ============================================================ # 结构体容量(原 HandlesStruct.FIELD_MAX/FIELD_NAME_MAX/PARENT_MAX/MRO_MAX) # ============================================================ -FIELD_MAX: t.CDefine = 256 -FIELD_NAME_MAX: t.CDefine = 64 -PARENT_MAX: t.CDefine = 64 -MRO_MAX: t.CDefine = 64 +define FIELD_MAX = 256 +define FIELD_NAME_MAX = 64 +define PARENT_MAX = 64 +define MRO_MAX = 64 # ============================================================ # for 迭代序列种类(原 HandlesFor.SEQ_KIND_*) # ============================================================ -SEQ_KIND_RANGE: t.CDefine = 1 -SEQ_KIND_STR: t.CDefine = 2 -SEQ_KIND_LIST: t.CDefine = 3 +define SEQ_KIND_RANGE = 1 +define SEQ_KIND_STR = 2 +define SEQ_KIND_LIST = 3 # ============================================================ # TraceFrame - 仿 Python Traceback 调用栈帧(原 HandlesType.TraceFrame) @@ -84,7 +84,7 @@ class VarEntry: # 1=该变量是 **const 对象**(注解含 t.CConst 且声明类型**不是指针**): # 整个作用域内禁止对该变量名赋值 / 增量赋值 / 元素赋值(fail-fast)。 # 与 TPC 的 Gen.var_const_flags / global_const_flags 同判据、同报文,见 - # Debugger/type-descriptors.md。指针类型(如 `p: t.CConst | T | t.CPtr`)的 + # Debugger/type-descriptors.md。指针类型(如 `p: t.CConst | T*`)的 # CConst 只约束 pointee,不使指针变量自身不可写,故不置 1。 # 追加在末尾:既有字段偏移不变,__sizeof__() 自动纳入,条目数组步长同步。 IsConst: int @@ -95,8 +95,8 @@ class VarEntry: # ============================================================ novirtual class Scope: """作用域节点""" - Parent: Scope | t.CPtr - Vars: VarEntry | t.CPtr + Parent: Scope* + Vars: VarEntry* VarCount: int Kind: int @@ -107,8 +107,8 @@ novirtual class Scope: novirtual class SymbolTable: """嵌套作用域符号表""" Pool: memhub.MemBuddy* - Root: Scope | t.CPtr - Current: Scope | t.CPtr + Root: Scope* + Current: Scope* # ============================================================ @@ -147,7 +147,7 @@ novirtual class StructEntry: Name: str # 类名 Ty: mlirlite.LLVMType* # LLVM StructType FieldCount: int # 字段数量 - Fields: FieldEntry | t.CPtr # 字段数组(FIELD_MAX 个槽位) + Fields: FieldEntry* # 字段数组(FIELD_MAX 个槽位) IsUnion: int # 1=联合体 / 0=普通结构体 IsPacked: int # 1=@c.Attribute(t.attr.packed) 打包结构体(无字段填充) Align: int # @c.Attribute(t.attr.aligned(N)) 对齐字节数(0=默认,如 fpu_context=16) @@ -166,7 +166,7 @@ novirtual class StructEntry: SpecTriggerSha1: str # 泛型特化类的触发文件 SHA1(None=非特化类)。特化类 ModuleSha1=模板 # sha1(方法名带模板前缀),作废重译时 reset_module_methods_emitted # 按触发文件 sha1 精确重置 MethodsEmitted,防特化方法体残留 1 不补译 - # → 链接 undefined symbol(list[ast.ClassDef|t.CPtr].* 根因) + # → 链接 undefined symbol(list[ast.ClassDef*].* 根因) IsForwardDecl: int # 1=前向声明占位条目(Ty=不透明具名结构体 {sha}.Class,FieldCount=0; # 定义侧随后**原位填充**同一 Ty 对象并清零本标记)。 # 语义对齐 TPC:未注册类 → 具名空 CStruct 占位 + 后续 set_body 填充。 @@ -188,7 +188,7 @@ novirtual class EnumEntry: Name: str # 枚举类名 BaseTy: mlirlite.LLVMType* # 基准类型(所有成员类型中最大的) MemberCount: int # 成员数量 - Members: EnumMember | t.CPtr # 成员数组(ENUM_MEMBER_MAX 个槽位) + Members: EnumMember* # 成员数组(ENUM_MEMBER_MAX 个槽位) # ============================================================ @@ -208,7 +208,7 @@ novirtual class FuncEntry: """函数表条目""" Name: str Func: mlirlite.Function* - Defaults: t.CPtr # defaults 列表节点指针 (list[AST | CPtr]),None=无默认值 + Defaults: t.CPtr # defaults 列表节点指针 (list[AST*]),None=无默认值 DefaultCount: int # 默认值数量 ParamCount: int # 形参数量(不含 self) # TypeSpec(S3 条目双写):Kind=TS_FUNC 的**整签名**(Ret/Params/ParamCount/IsVarArg @@ -225,14 +225,14 @@ novirtual class FuncDefaultsEntry: """默认参数表条目""" Name: str ModuleSha1: str # 定义该函数的模块 SHA1(限定名去重,避免跨模块同名串味) - Defaults: t.CPtr # defaults 列表节点指针 (list[AST | CPtr])(pool 内,可能被 reset) + Defaults: t.CPtr # defaults 列表节点指针 (list[AST*])(pool 内,可能被 reset) DefaultCount: int ParamCount: int # 形参数量(不含 self) # 常量快照(stdlib 分配,跨文件永久存活): # 注册时提取每个默认值 Constant 的值,跨模块调用时优先用快照重建常量 IR, # 避免读取已被 1b reset_to(mark1) 回收的 pool 内 AST。 - ConstKinds: int | t.CPtr # const_kind 数组(DefaultCount 个 i32) - ConstInts: int64 | t.CPtr # int_val 数组(DefaultCount 个 i64) + ConstKinds: int* # const_kind 数组(DefaultCount 个 i32) + ConstInts: int64* # int_val 数组(DefaultCount 个 i64) ConstStrs: sizet* # str_val 指针数组(DefaultCount 个 i8*) @@ -279,24 +279,24 @@ novirtual class FuncDefaultsEntry: # GetProcAddress(裸名) 取得地址并写入槽;后续片段的调用点从槽 load 地址后 # 间接调用 ⇒ 函数代码只有一份(在定义片段里),调用点不复制代码。 # ============================================================ -REPL_CTX_MARKER: t.CDefine = 1397571916 # 宿主侧对象标记(自比对;非 ctx 头字段) -REPL_CTX_MAGIC: t.CDefine = 0x5245504C # 'REPL'(ctx 头 +0,小端字节序为 R E P L) -REPL_CTX_VERSION: t.CDefine = 2 # ctx 头 +4(1 → 2:尾部追加函数指针槽区) -REPL_SLOT_SIZE: t.CDefine = 16 # 每个会话变量占用字节数(步长) -REPL_SLOT_BASE: t.CDefine = 64 # 槽区起点 = 固定头字节数(= +40..63 保留之后) -REPL_CTX_PARAM: t.CDefine = "__repl_ctx__" # 包裹模板里 ctx 形参名(与 Repl.vp 同源) -REPL_VAR_CAP: t.CDefine = 64 # 会话变量上限(变量区 = 64 + 64*16 = 1088 字节) +define REPL_CTX_MARKER = 1397571916 # 宿主侧对象标记(自比对;非 ctx 头字段) +define REPL_CTX_MAGIC = 0x5245504C # 'REPL'(ctx 头 +0,小端字节序为 R E P L) +define REPL_CTX_VERSION = 2 # ctx 头 +4(1 → 2:尾部追加函数指针槽区) +define REPL_SLOT_SIZE = 16 # 每个会话变量占用字节数(步长) +define REPL_SLOT_BASE = 64 # 槽区起点 = 固定头字节数(= +40..63 保留之后) +define REPL_CTX_PARAM = "__repl_ctx__" # 包裹模板里 ctx 形参名(与 Repl.vp 同源) +define REPL_VAR_CAP = 64 # 会话变量上限(变量区 = 64 + 64*16 = 1088 字节) # 会话函数指针槽区(M3):起点紧跟变量区,步长与变量槽一致(16B,低 8 字节存地址) -REPL_FUNC_BASE: t.CDefine = 1088 # = REPL_SLOT_BASE + REPL_VAR_CAP*REPL_SLOT_SIZE -REPL_FUNC_SLOT_SIZE: t.CDefine = 16 # 每个会话函数占用字节数(步长) -REPL_FUNC_CAP: t.CDefine = 32 # 会话函数上限(函数区 = 32*16 = 512 字节) +define REPL_FUNC_BASE = 1088 # = REPL_SLOT_BASE + REPL_VAR_CAP*REPL_SLOT_SIZE +define REPL_FUNC_SLOT_SIZE = 16 # 每个会话函数占用字节数(步长) +define REPL_FUNC_CAP = 32 # 会话函数上限(函数区 = 32*16 = 512 字节) # ctx 总字节数 = 64 + 64*16 + 32*16 = 1600(宿主 Repl._REPL_CTX_SIZE 必须一致) -REPL_CTX_SIZE: t.CDefine = 1600 +define REPL_CTX_SIZE = 1600 # 会话函数的形参上限(签名 token 数组定长;超出 ⇒ 注册期明确报错) -REPL_FUNC_PARAM_MAX: t.CDefine = 8 +define REPL_FUNC_PARAM_MAX = 8 # 片段入口函数名前缀(Repl.vp 生成 "__repl_frag_%d";用于区分"片段入口函数"与 # 被提升的会话函数本体——前者是会话变量写入的作用域,后者只读会话槽) -REPL_ENTRY_PREFIX: t.CDefine = "__repl_frag_" +define REPL_ENTRY_PREFIX = "__repl_frag_" # 会话模块 SHA1(M4):片段翻译器的 ModuleSha1 取此**稳定**值 ⇒ 片段内定义的类型 # 名形如 "<16位hex>.",且**跨片段逐字一致**——这是"先前片段定义的类在后续 # 片段可见/可用"的基础(类型名是跨片段查找的唯一键)。 @@ -310,35 +310,35 @@ REPL_ENTRY_PREFIX: t.CDefine = "__repl_frag_" # 与裸名约定的关系:`export def`(含片段入口与会话函数)走 has_export 分支取裸名 # (FuncGenDef.vp:482-485),**不受**该值影响;受影响的只有类/方法/模块级全局 # 等经 _mangle_name/_mangle_name_with_sha1 命名的符号。 -REPL_SESSION_SHA1: t.CDefine = "71f67b7cb405f0e4" +define REPL_SESSION_SHA1 = "71f67b7cb405f0e4" # ctx 头字段偏移(与 ReplResult 字段顺序/宽度一一对应) -REPL_RES_KIND_OFF: t.CDefine = 8 # i32 -REPL_RES_A_OFF: t.CDefine = 16 # u64 -REPL_RES_B_OFF: t.CDefine = 24 # u64 -REPL_RES_VARCOUNT_OFF: t.CDefine = 32 # i32 -REPL_RES_LASTFRAG_OFF: t.CDefine = 36 # i32 +define REPL_RES_KIND_OFF = 8 # i32 +define REPL_RES_A_OFF = 16 # u64 +define REPL_RES_B_OFF = 24 # u64 +define REPL_RES_VARCOUNT_OFF = 32 # i32 +define REPL_RES_LASTFRAG_OFF = 36 # i32 # 结果 Kind(宿主按此回显) -REPL_RES_NONE: t.CDefine = 0 # 本片段无结果(如仅声明) -REPL_RES_INT: t.CDefine = 1 # 整数(读 result_a 位模式) -REPL_RES_FLOAT: t.CDefine = 2 # float64(读 result_a 的 double 位模式) -REPL_RES_STR: t.CDefine = 3 # str/bytes(读 result_a 指针 + result_b 长度) -REPL_RES_OBJ: t.CDefine = 4 # 结构体/其它指针(读 result_a 地址) +define REPL_RES_NONE = 0 # 本片段无结果(如仅声明) +define REPL_RES_INT = 1 # 整数(读 result_a 位模式) +define REPL_RES_FLOAT = 2 # float64(读 result_a 的 double 位模式) +define REPL_RES_STR = 3 # str/bytes(读 result_a 指针 + result_b 长度) +define REPL_RES_OBJ = 4 # 结构体/其它指针(读 result_a 地址) # 会话变量类型标签(ReplVarEntry.TyTag) -REPL_TY_INT: t.CDefine = 1 -REPL_TY_FLOAT: t.CDefine = 2 -REPL_TY_STR: t.CDefine = 3 # i8*(str/bytes) -REPL_TY_PTR: t.CDefine = 4 # 其他指针(Bits=pointee 位宽 / TyName=结构体名) -REPL_TY_STRUCT: t.CDefine = 5 # 结构体值(按声明类型内联在槽里;≤ 槽容量) +define REPL_TY_INT = 1 +define REPL_TY_FLOAT = 2 +define REPL_TY_STR = 3 # i8*(str/bytes) +define REPL_TY_PTR = 4 # 其他指针(Bits=pointee 位宽 / TyName=结构体名) +define REPL_TY_STRUCT = 5 # 结构体值(按声明类型内联在槽里;≤ 槽容量) # 会话变量存放形态(ReplVarEntry.Kind) -REPL_KIND_UNTYPED: t.CDefine = 0 # 已登记槽位但尚未定型(未赋值/无注解) -REPL_KIND_SCALAR: t.CDefine = 1 # 值内联存槽(标量/指针/≤16B 结构体值) +define REPL_KIND_UNTYPED = 0 # 已登记槽位但尚未定型(未赋值/无注解) +define REPL_KIND_SCALAR = 1 # 值内联存槽(标量/指针/≤16B 结构体值) # 会话函数签名的返回类型 token(M3;只用于 ReplFuncEntry.RetTag) -REPL_TY_VOID: t.CDefine = 0 # 无返回值(void;不作为形参 token) +define REPL_TY_VOID = 0 # 无返回值(void;不作为形参 token) # ============================================================ @@ -428,7 +428,7 @@ novirtual class ReplResult: Version: int # REPL_CTX_VERSION Kind: int # REPL_RES_* Reserved0: int # 保留(0) - A: t.CInt64T # result_a - B: t.CInt64T # result_b + A: int64 # result_a + B: int64 # result_b VarCount: int # 已分配槽数(宿主写,供检视) LastFrag: int # 最近执行的片段号(宿主写,供检视) diff --git a/App/lib/core/Gen/ImportsGenMixin.vp b/App/lib/core/Gen/ImportsGenMixin.vp index 1311bad..f87aaf2 100644 --- a/App/lib/core/Gen/ImportsGenMixin.vp +++ b/App/lib/core/Gen/ImportsGenMixin.vp @@ -28,7 +28,7 @@ import lib.core.VLogger as VLogger # ============================================================ # 常量(与 HandlesImports 保持一致) # ============================================================ -MAX_REEXPORT: t.CDefine = 512 +define MAX_REEXPORT = 512 # ============================================================ @@ -977,12 +977,12 @@ novirtual class ImportsGenMixin: fi_target = jb_t trans._from_imports = self.add_from_import(trans.Pool, trans._from_imports, local_name, fi_target, orig_name) - # static 符号(禁止跨模块使用):from mod import name 命中源 - # 模块登记的 static 符号 → fail-fast。逻辑收敛在 - # _CheckStaticFromImport 内(不内联——内联新增分支会干扰本函数 - # 的类型推断,与 ExprGenAttr/CallGenMixin 同款处理)。 - self._CheckStaticFromImport(trans, fi_target, alias.name, node) - # 命名空间隔离:from-import 的名称标记为可见结构体 + # static 符号(禁止跨模块使用):from mod import name 命中源 + # 模块登记的 static 符号 → fail-fast。逻辑收敛在 + # _CheckStaticFromImport 内(不内联——内联新增分支会干扰本函数 + # 的类型推断,与 ExprGenAttr/CallGenMixin 同款处理)。 + self._CheckStaticFromImport(trans, fi_target, alias.name, node) + # 命名空间隔离:from-import 的名称标记为可见结构体 self.Gen.StructGen.add_visible_struct(trans.Pool, local_name) # 注册 re-export 映射:当前模块 re-export 了 local_name, # 源模块为 fi_target(from . import Y 时是子模块名 vpsdk.Y, diff --git a/App/lib/core/Gen/MatchGenMixin.vp b/App/lib/core/Gen/MatchGenMixin.vp index 0bb6e97..532ec79 100644 --- a/App/lib/core/Gen/MatchGenMixin.vp +++ b/App/lib/core/Gen/MatchGenMixin.vp @@ -480,8 +480,8 @@ novirtual class MatchGenMixin: # BB 指针数组、case 值指针数组、default 标记数组、nobreak 标记数组 bb_arr: sizet* = pool.alloc(8 * MAX_MATCH_CASES) cv_arr: sizet* = pool.alloc(8 * MAX_MATCH_CASES) - def_arr: int | t.CPtr = pool.alloc(4 * MAX_MATCH_CASES) - nb_arr: int | t.CPtr = pool.alloc(4 * MAX_MATCH_CASES) + def_arr: int* = pool.alloc(4 * MAX_MATCH_CASES) + nb_arr: int* = pool.alloc(4 * MAX_MATCH_CASES) # pass1 缓存的 mc 指针数组(pass2 复用,避免重索引) mc_arr: sizet* = pool.alloc(8 * MAX_MATCH_CASES) if bb_arr is None or cv_arr is None or def_arr is None or nb_arr is None \ @@ -1020,8 +1020,8 @@ novirtual class MatchGenMixin: 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 | t.CPtr = pool.alloc(4 * MAX_MATCH_CASES) - nb_arr: int | t.CPtr = pool.alloc(4 * 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: @@ -1350,8 +1350,8 @@ novirtual class MatchGenMixin: bb_arr: sizet* = pool.alloc(8 * MAX_MATCH_CASES) cv_arr: sizet* = pool.alloc(8 * MAX_MATCH_CASES) - def_arr: int | t.CPtr = pool.alloc(4 * MAX_MATCH_CASES) - nb_arr: int | t.CPtr = pool.alloc(4 * MAX_MATCH_CASES) + def_arr: int* = pool.alloc(4 * MAX_MATCH_CASES) + nb_arr: int* = pool.alloc(4 * MAX_MATCH_CASES) # 每个已收集臂的 MatchOr 节点指针(0 = 非 MatchOr):`case 1 | 2:` 需为 # 每个备选各产出一个 switch case 值(同一 body BB),故此处记录节点, # 建 sw 链时逐备选展开。非 MatchOr 恒为 0,走原单 cv 路径逐字不变。 @@ -1648,8 +1648,8 @@ novirtual class MatchGenMixin: 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 | t.CPtr = pool.alloc(4 * MAX_MATCH_CASES) - nb_arr: int | t.CPtr = pool.alloc(4 * MAX_MATCH_CASES) + def_arr: int* = pool.alloc(4 * MAX_MATCH_CASES) + nb_arr: int* = pool.alloc(4 * MAX_MATCH_CASES) mc_arr: sizet* = pool.alloc(8 * MAX_MATCH_CASES) cv_arr: sizet* = pool.alloc(8 * MAX_MATCH_CASES) # 每个已收集臂的 MatchOr 节点指针(0 = 非 MatchOr):check 链需把 diff --git a/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp b/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp index 8c17470..0f70aa2 100644 --- a/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp +++ b/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp @@ -258,7 +258,7 @@ novirtual class StmtGenCifMixin: lv: int = self._cif_eval_node(pool, trans, cmp.left) if self.CifEvalOk == 0: return 0 - ops_list: list[int] | t.CPtr = (list[int] | t.CPtr)(cmp.ops) + ops_list: list[int]* = (list[int]*)(cmp.ops) comps: list[ast.AST*]* = cmp.comparators if ops_list is None or comps is None: self.CifEvalOk = 0 @@ -630,7 +630,7 @@ novirtual class StmtGenCifMixin: ret_is_ptr: int = self.Gen.ExprGenBase.is_ptr_type(ret_ty_rt) # ptr 类型不一致性:val 是整数但 ret 是 ptr(或反之),必须转换 if val_is_ptr != ret_is_ptr: - # [FIX 2026-08-30] __new__ 返回类型是类指针(T | t.CPtr 语义): + # [FIX 2026-08-30] __new__ 返回类型是类指针(T* 语义): # 返回的实例存储指针来自跨模块调用(如 pool.alloc),Phase A # 依赖未就绪时其返回类型退化为默认 i32。此时 int→ptr 是退化 # 指针重建而非隐式转换错误——允许 inttoptr,文件保持 pending @@ -2203,7 +2203,7 @@ novirtual class StmtGenCifMixin: # 对象有效性校验(vptr 非 0,硬约定与证据见 AssignGenMixin.vp:1174-1183): # @t.CVTable 类对象首字即 vptr,为 0 时下游任意虚调用(kind()/dump())都会 # `load [0+slot]` ⇒ ASan READ at 0x0。读首字的唯一可用写法是 c.Deref((uint64*)(p))。 - if c.Deref((uint64*)(first_el)) == 0: + if *((uint64*)(first_el)) == 0: self.Gen.TypeGenErr.fatal_error(for_node, f"列表字面量迭代遇到【对象无效】的 AST 元素(vptr 为 0):第 0 个元素指针非 0" f"(地址 {uint64(first_el)})但其对象首字(vtable 指针)为 0,元素计数 {elts_count};" @@ -2235,7 +2235,7 @@ novirtual class StmtGenCifMixin: f"但元素计数为 {elts_count}(元素与计数不一致);上层某处产生了空 AST 元素,已终止编译。", "ValueError") # 对象有效性校验(vptr 非 0),同第 0 元素处:同族"取元素后即用"路径。 - if c.Deref((uint64*)(el_node)) == 0: + if *((uint64*)(el_node)) == 0: self.Gen.TypeGenErr.fatal_error(for_node, f"列表字面量迭代遇到【对象无效】的 AST 元素(vptr 为 0):第 {i} 个元素指针非 0" f"(地址 {uint64(el_node)})但其对象首字(vtable 指针)为 0,元素计数 {elts_count};" diff --git a/App/lib/core/Gen/Stmt/StmtGenMixin.vp b/App/lib/core/Gen/Stmt/StmtGenMixin.vp index 299eba4..914247f 100644 --- a/App/lib/core/Gen/Stmt/StmtGenMixin.vp +++ b/App/lib/core/Gen/Stmt/StmtGenMixin.vp @@ -251,9 +251,9 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): # 注意:list[ptr](pool, N) 第二参数是 elem_size 不是容量! # 指针元素必须显式传 8(T.__sizeof__ 对联合类型不可靠), # 否则 append 按 N 字节步长错位存取 → 读出垃圾指针(崩溃)。 - except_bbs: list[rawptr[mlirlite.BasicBlock]] | t.CPtr = \ + except_bbs: list[rawptr[mlirlite.BasicBlock]]* = \ list[rawptr[mlirlite.BasicBlock]](pool, 8) - match_bbs: list[rawptr[mlirlite.BasicBlock]] | t.CPtr = \ + match_bbs: list[rawptr[mlirlite.BasicBlock]]* = \ list[rawptr[mlirlite.BasicBlock]](pool, 8) if except_bbs is None or match_bbs is None: return 0 @@ -319,7 +319,7 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): # 匹配编码缓冲:必须是 int*(i32 步长)——collect_descendant_codes 按 # out_codes[i](4 字节)写入;用 sizet*(8 字节)读会读出 64 位拼接垃圾 # (多码时 code[i+1]<<32|code[i];单码时高位恰为 0 掩盖)。 - codes_buf_t: int | t.CPtr = pool.alloc(64 * 4) + codes_buf_t: int* = pool.alloc(64 * 4) if codes_buf_t is None: return 0 n_codes_t: int = 0 diff --git a/App/lib/core/Gen/StructGenMixin.vp b/App/lib/core/Gen/StructGenMixin.vp index c02d0a4..96aa167 100644 --- a/App/lib/core/Gen/StructGenMixin.vp +++ b/App/lib/core/Gen/StructGenMixin.vp @@ -27,22 +27,22 @@ import lib.core.Gen.GenApi as GenApi # ============================================================ # 常量(与 HandlesStruct 保持一致) # ============================================================ -STRUCT_MAX: t.CDefine = 512 +define STRUCT_MAX = 512 # 名 | 类型 下标索引槽数(2 的幂且 > 2*STRUCT_MAX ⇒ 负载 < 0.5,探测必然终止) -STRUCT_IDX_CAP: t.CDefine = 1024 +define STRUCT_IDX_CAP = 1024 # 字段槽位上限制(与 HandlesStruct 保持一致):Generator 43 Mixin 展平后约 120 字段, # 上限取 64 会导致第 9+ 父类字段丢失 → __init__ 写属性失败。 -FIELD_MAX: t.CDefine = 256 -FIELD_NAME_MAX: t.CDefine = 64 +define FIELD_MAX = 256 +define FIELD_NAME_MAX = 64 # 多继承(MRO)支持:单类最大父类数 / MRO 链最大长度(Generator 43 父类; # PARENT_MAX=16 时第 17+ 父类字段丢失 → __init__ 写 self.DiagStmtCount 失败) -PARENT_MAX: t.CDefine = 64 -MRO_MAX: t.CDefine = 64 +define PARENT_MAX = 64 +define MRO_MAX = 64 # 索引哈希常量(32 位 FNV-1a,常量均 < 2^63 以避开大十进制字面量解析风险) -FNV32_OFFSET: t.CDefine = 2166136261 -FNV32_PRIME: t.CDefine = 16777619 -FNV32_MASK: t.CDefine = 4294967295 +define FNV32_OFFSET = 2166136261 +define FNV32_PRIME = 16777619 +define FNV32_MASK = 4294967295 # ============================================================ @@ -351,9 +351,9 @@ novirtual class StructGenMixin: 声明被静默丢弃**,调用点改按依赖的签名 coerce。 现场:includes/socket.vp 的 - `extern def connect(fd: u64, addr: SocketAddr | t.CPtr, addrlen: INT)` - 被 w32.winsock2 的 `connect(..., WSASocketAddr | t.CPtr, ...)` 顶掉 → - socket.vp:236 `connect(self.fd, c.Addr(addr), 16)` 报 + `extern def connect(fd: u64, addr: SocketAddr*, addrlen: INT)` + 被 w32.winsock2 的 `connect(..., WSASocketAddr*, ...)` 顶掉 → + socket.vp:236 `connect(self.fd, &addr, 16)` 报 「指针隐式转指针已禁止:%"…SocketAddr"* → %"…WSASocketAddr"*」。 注入侧据本表跳过"本文件已声明的裸名"(VpiReader._inject_function_declare), @@ -889,7 +889,7 @@ novirtual class StructGenMixin: # (!424 = 本函数 :587 行;!426 = :590 行;两者之间无任何指令)。 # 对照可用写法(List 分支,同文件 :10611-10615):`bitcast AST* → i64*` + # `load i64` + `inttoptr i64 → i8*` + `bitcast List* → i8**` + `store i8*`。 - vt_ptr_c: t.CPtr = t.CPtr(c.Deref((uint64*)(default_val))) + vt_ptr_c: t.CPtr = t.CPtr(*((uint64*)(default_val))) c.DerefAs(dst_c, vt_ptr_c) # 拷贝位置字段(报错定位用) dst_c.lineno = src_c.lineno @@ -920,15 +920,15 @@ novirtual class StructGenMixin: if dst_l is None: return None string.memset(dst_l, 0, ast.List.__sizeof__()) # 拷贝 vtable 指针(AST 是 @t.CVTable,kind() 虚调用依赖首字段 vptr) - vt_l: t.CPtr = t.CPtr(c.Deref((uint64*)(default_val))) - c.DerefAs(dst_l, vt_l) + vt_l: t.CPtr = t.CPtr(*((uint64*)(default_val))) + *dst_l = vt_l # 拷贝位置字段与 ctx dst_l.lineno = src_l.lineno dst_l.col_offset = src_l.col_offset dst_l.end_lineno = src_l.end_lineno dst_l.end_col_offset = src_l.end_col_offset dst_l.ctx = src_l.ctx - # 深拷贝 elts:stdlib 手动构造 list[AST | t.CPtr] 容器 + # 深拷贝 elts:stdlib 手动构造 list[AST*] 容器 src_elts_l: list[ast.AST*]* = src_l.elts if src_elts_l is not None: cnt_l: sizet = len(src_elts_l) @@ -984,7 +984,7 @@ novirtual class StructGenMixin: # "结构体赋值"编译成 48 字节 load + 48 字节 store,而本 # 缓冲只申请 cnt_l*elem_sz_l ⇒ 每槽越界 40 字节,写穿本块 # canary 与右邻空闲块首字(三代 [FREEFRAME] 现场根因)。 - # 按本仓既有合并规则(hashtable.vp:82-85):`X | t.CPtr` + # 按本仓既有合并规则(hashtable.vp:82-85):`X*` # = Ptr(resolve(X)) ⇒ 取下标得到**指针元素** ⇒ 8 字节 # 指针 store,与申请宽度同源。 slot_l: ast.AST** = (ast.AST**)(uint64(data_l) + li_l * elem_sz_l) @@ -1426,8 +1426,8 @@ novirtual class StructGenMixin: def _last_dot_outside_brackets(self, s: str) -> str: """返回字符串中最后一个位于 [...] 括号外的 '.' 指针,无则 None - 泛型特化类名含下标(如 'numpy.ndarray[t.CDouble]'、 - 'list[f467978339422f32.AST|t.CPtr]'),下标内部也含 '.'(t.CDouble + 泛型特化类名含下标(如 'numpy.ndarray[double]'、 + 'list[f467978339422f32.AST*]'),下标内部也含 '.'(double 的模块限定 / sha1.AST)。strrchr 直接找最后一个 '.' 会落到下标内部, 把模块名截错('numpy.ndarray[t' → sha1 映射表无法解析,NumpyTest lookup_field_by_class FAIL 根因)。从末尾扫描并跟踪括号深度, @@ -1512,7 +1512,7 @@ novirtual class StructGenMixin: # 模块段是 16 位 hex = SHA1 字面量("{16hex}.Class" 类键形态, # 泛型类型实参 _norm_type_arg_name 规范化产物,如 # "29fdb5e25dc949f4.Param"——GSList[Param] 特化方法体内 - # `cur: T | t.CPtr = self.Head` 经 resolve_generic_type_name + # `cur: T* = self.Head` 经 resolve_generic_type_name # 替换 T 为实参串后 AnnotClassName 即该形态):模块段即模块 # SHA1,类已注册就证明该模块已编译,直接按 name+sha1 精确匹配, # 不走 _resolve_module_sha1(store 键是模块名不是 sha1,查 @@ -1706,7 +1706,7 @@ novirtual class StructGenMixin: def get_struct_type_from_value(self, val: mlirlite.Value*) -> mlirlite.LLVMType*: """从 Value 的类型推断结构体类型 - 递归解 Ptr:支持 X|t.CPtr 联合简化产生的 Ptr(Ptr(Struct)) 对象指针 + 递归解 Ptr:支持 X* 联合简化产生的 Ptr(Ptr(Struct)) 对象指针 (如运算符重载中间结果 a*2.0 的 Vec3**),否则 try_operator_overload 重载识别失败回退原生运算,对指针生成非法 sub 指令(llc: invalid operand type for instruction)。 @@ -2158,8 +2158,8 @@ novirtual class StructGenMixin: if string.strchr(sname, 46) is None: return # 非跨模块引用,无需处理 # 提取类名(第一个 '.' 之后的部分) - # 必须用 strchr 而非 strrchr:泛型特化名如 "list[ast.AST|t.CPtr]" - # 内部含 '.'(ast.AST),strrchr 会错误地把类名解析为 "AST|t.CPtr]" + # 必须用 strchr 而非 strrchr:泛型特化名如 "list[ast.AST*]" + # 内部含 '.'(ast.AST),strrchr 会错误地把类名解析为 "AST*]" dot_pos: str = string.strchr(sname, '.') if dot_pos is None: return diff --git a/App/lib/core/Gen/Translator.vp b/App/lib/core/Gen/Translator.vp index ae9ce4e..3184681 100644 --- a/App/lib/core/Gen/Translator.vp +++ b/App/lib/core/Gen/Translator.vp @@ -135,11 +135,11 @@ novirtual class Translator: _coro_uses_sleep: int # 函数体是否用 coro_sleep(预扫描置位) _coro_extra_types: str # 额外槽类型表(i8 数组:1=i32 2=i64) _coro_extra_count: int # 额外槽总数 - _coro_await_slots: int | t.CPtr # __await_N 的帧相对槽 index(预扫描填) - _coro_for_slots: int | t.CPtr # range-For N 的 __f_idx 帧相对槽 index(预扫描填) + _coro_await_slots: int* # __await_N 的帧相对槽 index(预扫描填) + _coro_for_slots: int* # range-For N 的 __f_idx 帧相对槽 index(预扫描填) # per-async wake 槽 index 表(coro_run/gather 轮询反查用) _coro_wake_names: str # char* 数组(8B/项) - _coro_wake_idxs: int | t.CPtr # i32 数组(4B/项,-1=无 wake 槽) + _coro_wake_idxs: int* # i32 数组(4B/项,-1=无 wake 槽) _coro_wake_count: int # 导入模块跟踪 @@ -581,19 +581,19 @@ novirtual class Translator: # "非基本类型指针不可隐式转换"报出。 # 登记只依赖 tree + 本文件模块 SHA1,与导入、类定义窗口、类定义顺序都无关, # 故提到门之前,三种模式(1a=1 / 1a-pre=2 / 全量=0)共用。 - GenApi.register_file_classes(pool, self.ModuleSha1, tree) - # 本文件顶层函数名预登记(同址、同目的):依赖 vpi 注入的**裸名**声明 - # (extern/state/export 不带 SHA1 前缀)若与本文件自己的声明同名,会先占用 - # 该名字,使本文件声明在 forward_declare_functions 被静默丢弃(调用点改按 - # 依赖签名 coerce)。现场:includes/socket.vp 的 extern def connect 被 - # w32.winsock2 的 connect 顶掉 → socket.vp:236 报 - # 「指针隐式转指针已禁止:SocketAddr* → WSASocketAddr*」。 - GenApi.register_file_funcs(pool, tree) - # viperbuild 宏语句擦除:把模块级 `import viperbuild` 配套的宏语句 - # proj = vb.Project(...) / proj.<字段> = ... / proj.config(...) / proj.build(...) - # 从 tree.children 里摘掉(Pass 0 已在配置面消费;翻译期若留着重放会被当真实 - # 调用 codegen ⇒ `vb.Project` 未定义类)。位置必须在下面 import 处理/变量预注册/ - # translate_children 之前,使三者看到同一份已擦除的 children。 + GenApi.register_file_classes(pool, self.ModuleSha1, tree) + # 本文件顶层函数名预登记(同址、同目的):依赖 vpi 注入的**裸名**声明 + # (extern/state/export 不带 SHA1 前缀)若与本文件自己的声明同名,会先占用 + # 该名字,使本文件声明在 forward_declare_functions 被静默丢弃(调用点改按 + # 依赖签名 coerce)。现场:includes/socket.vp 的 extern def connect 被 + # w32.winsock2 的 connect 顶掉 → socket.vp:236 报 + # 「指针隐式转指针已禁止:SocketAddr* → WSASocketAddr*」。 + GenApi.register_file_funcs(pool, tree) + # viperbuild 宏语句擦除:把模块级 `import viperbuild` 配套的宏语句 + # proj = vb.Project(...) / proj.<字段> = ... / proj.config(...) / proj.build(...) + # 从 tree.children 里摘掉(Pass 0 已在配置面消费;翻译期若留着重放会被当真实 + # 调用 codegen ⇒ `vb.Project` 未定义类)。位置必须在下面 import 处理/变量预注册/ + # translate_children 之前,使三者看到同一份已擦除的 children。 self._erase_viperbuild_macros(pool, tree) # 先处理导入语句,再创建前向声明,解决前向引用问题。 # 两道门分开: @@ -636,242 +636,242 @@ novirtual class Translator: # CTypedef 声明由 Phase1 1b 文本扫描注册(RegisterCTypedefFromSource)—— # AST 字符串字段 token 零拷贝指向 src_buf,跨阶段内容不稳定,此处 AST 扫描 # 读 attr 会 0xC0000005,故移除。 - # 跨模块 .vpi 注入:加载依赖模块的 .vpi,把函数 declare 注入当前模块。 - # 注入条件 = 全量翻译,或 **App 预注册**(_pre_allow_dep_inject):后者必须 - # 与阶段 A 同上下文,否则预注册期解析出的类字段票名(包重导出类的 - # 真定义前缀校正依赖包别名 entry)会与阶段 A 分裂。includes 预注册 - # (Phase A-pre-inc)不置位该开关 ⇒ 仍不注入,避免依赖环自锁。 - if self._imported_modules is not None: - # 错误上下文帧:当前模块触发依赖 stub 加载的 import 位置 - GenApi.push_trace(GenApi.get_current_file(), cur_imp_lineno) - StubMergerBuild.LoadDepVpiIntoModule(pool, mod, self._imported_modules, self._from_imports, GenApi.get_temp_dir(), self) - GenApi.pop_trace() - # 文件级类名预登记已提前到本函数开头执行(覆盖三种 _declare_only 模式; - # 为什么必须早于模块级变量/前向声明,见那里的说明)。 - # 模块级变量预注册 + 函数前向声明:仍**只在全量翻译**做(声明期跳过, - # 保持 Phase A-pre"只注册 struct/enum/union"的语义)。 - if self._declare_only == 0: - # 预注册模块级变量(AnnAssign/Assign)到 SymTab - # 解决时序问题:class Logger 的 __init__ 引用 _mbuddy 时, - # _mbuddy 的 AnnAssign 在 AST 中位于 class Logger 之后, - # 按 AST 顺序翻译时 _mbuddy 尚未注册 → lookup_var 返回 None → rhs_val is None - # 预处理先于 translate_children 注册所有模块级变量, - # 后续 translate_children 遍历到同一 AnnAssign 时 handle_module_level_var - # 通过 lookup_module_var 检测已存在并跳过(HandlesMain.py:206-209) - if ch is not None: - for ci in range(cn_count): - child: ast.AST* = ch.get(ci) - 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) - # 创建前向声明 + # 跨模块 .vpi 注入:加载依赖模块的 .vpi,把函数 declare 注入当前模块。 + # 注入条件 = 全量翻译,或 **App 预注册**(_pre_allow_dep_inject):后者必须 + # 与阶段 A 同上下文,否则预注册期解析出的类字段票名(包重导出类的 + # 真定义前缀校正依赖包别名 entry)会与阶段 A 分裂。includes 预注册 + # (Phase A-pre-inc)不置位该开关 ⇒ 仍不注入,避免依赖环自锁。 + if self._imported_modules is not None: + # 错误上下文帧:当前模块触发依赖 stub 加载的 import 位置 + GenApi.push_trace(GenApi.get_current_file(), cur_imp_lineno) + StubMergerBuild.LoadDepVpiIntoModule(pool, mod, self._imported_modules, self._from_imports, GenApi.get_temp_dir(), self) + GenApi.pop_trace() + # 文件级类名预登记已提前到本函数开头执行(覆盖三种 _declare_only 模式; + # 为什么必须早于模块级变量/前向声明,见那里的说明)。 + # 模块级变量预注册 + 函数前向声明:仍**只在全量翻译**做(声明期跳过, + # 保持 Phase A-pre"只注册 struct/enum/union"的语义)。 + if self._declare_only == 0: + # 预注册模块级变量(AnnAssign/Assign)到 SymTab + # 解决时序问题:class Logger 的 __init__ 引用 _mbuddy 时, + # _mbuddy 的 AnnAssign 在 AST 中位于 class Logger 之后, + # 按 AST 顺序翻译时 _mbuddy 尚未注册 → lookup_var 返回 None → rhs_val is None + # 预处理先于 translate_children 注册所有模块级变量, + # 后续 translate_children 遍历到同一 AnnAssign 时 handle_module_level_var + # 通过 lookup_module_var 检测已存在并跳过(HandlesMain.py:206-209) + if ch is not None: + for ci in range(cn_count): + child: ast.AST* = ch.get(ci) + 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) + # 创建前向声明 GenApi.forward_declare_functions(self, tree) added: int = GenApi.translate_children(self, tree) - # ============================================================ - # _erase_viperbuild_macros - 擦除模块级 viperbuild 宏语句 - # ------------------------------------------------------------ - # viperbuild 是**编译器内建宏库**(编译期配置面),其用法形如: - # import viperbuild as vb - # proj = vb.Project("Test", "1.0.0") - # proj.build(selfmachine=True) - # 这些是**宏语句**:Pass 0(lib.core.builtin.ViperBuild)已从依赖闭包把它们消费成 - # Config 配置;翻译期若原样放行,`vb.Project`/`proj.build` 会被当真实调用 - # codegen(未定义类/函数)⇒ 报错。故此处把整组语句从 tree.children 摘除。 - # 只处理**模块级顶层语句**(配置不允许写在函数体里)。 - # ============================================================ - 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 - 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 - 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 - cl: ast.Call* = ast.Call*(value) - 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 - 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 - 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 - return 0 - if fk == ast.ASTKind.Name: - 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 - 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 - 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 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - ch: list[ast.AST*]* = tree.children - cn: sizet = len(ch) - if cn == 0: - return 0 - # ① 找 viperbuild 的本地名 / Project 构造名 - alias: str = None - ctor: str = None - ci: sizet = 0 - while ci < cn: - child: ast.AST* = ch.get(ci) - if child is not None: - kd: int = child.kind() - if kd == ast.ASTKind.Import: - names: list[ast.AST*]* = ast.Import*(child).names - if names is not None: - ni: sizet = 0 - while ni < len(names): - 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" - ni += 1 - elif kd == ast.ASTKind.ImportFrom: - ifr: ast.ImportFrom* = ast.ImportFrom*(child) - if ifr is not None and ifr.level == 0 and ifr.names is not None: - if ifr.module is not None and string.strcmp(ifr.module, "viperbuild") == 0: - ni: sizet = 0 - while ni < len(ifr.names): - 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" - ni += 1 - ci += 1 - 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 - 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) - ci += 1 - if erased != 0: - tree.children = kept - return erased - + # ============================================================ + # _erase_viperbuild_macros - 擦除模块级 viperbuild 宏语句 + # ------------------------------------------------------------ + # viperbuild 是**编译器内建宏库**(编译期配置面),其用法形如: + # import viperbuild as vb + # proj = vb.Project("Test", "1.0.0") + # proj.build(selfmachine=True) + # 这些是**宏语句**:Pass 0(lib.core.builtin.ViperBuild)已从依赖闭包把它们消费成 + # Config 配置;翻译期若原样放行,`vb.Project`/`proj.build` 会被当真实调用 + # codegen(未定义类/函数)⇒ 报错。故此处把整组语句从 tree.children 摘除。 + # 只处理**模块级顶层语句**(配置不允许写在函数体里)。 + # ============================================================ + 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 + 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 + 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 + cl: ast.Call* = ast.Call*(value) + 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 + 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 + 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 + return 0 + if fk == ast.ASTKind.Name: + 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 + 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 + 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 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + ch: list[ast.AST*]* = tree.children + cn: sizet = len(ch) + if cn == 0: + return 0 + # ① 找 viperbuild 的本地名 / Project 构造名 + alias: str = None + ctor: str = None + ci: sizet = 0 + while ci < cn: + child: ast.AST* = ch.get(ci) + if child is not None: + kd: int = child.kind() + if kd == ast.ASTKind.Import: + names: list[ast.AST*]* = ast.Import*(child).names + if names is not None: + ni: sizet = 0 + while ni < len(names): + 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" + ni += 1 + elif kd == ast.ASTKind.ImportFrom: + ifr: ast.ImportFrom* = ast.ImportFrom*(child) + if ifr is not None and ifr.level == 0 and ifr.names is not None: + if ifr.module is not None and string.strcmp(ifr.module, "viperbuild") == 0: + ni: sizet = 0 + while ni < len(ifr.names): + 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" + ni += 1 + ci += 1 + 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 + 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) + ci += 1 + if erased != 0: + tree.children = kept + return erased + # 容器模块自动可见性注入(对齐 TPC _inject_auto_imports) # TPC 在翻译前自动注入 `import _list / import _dict (+json)`,使 list/dict 内建容器类 # 在符号表中可见;TPV 用可见性机制等效替代:_list.vp/_dict.vp 已由 Phase1 注册, @@ -1231,9 +1231,9 @@ def InjectTracebackInstallCtor(tr: rawptr[Translator]) -> int: # ============================================================ novirtual class Mixin: """所有 Handle 的非多态基类:持有 Translator 回指针 + 共享委托方法""" - Trans: Translator | t.CPtr + Trans: Translator* - def InitMixin(self, trans: Translator | t.CPtr) -> int: + def InitMixin(self, trans: Translator*) -> int: """初始化 Mixin 字段(子类 __init__ 中调用)""" self.Trans = trans return 0 diff --git a/App/lib/core/Gen/TranslatorGenMixin.vp b/App/lib/core/Gen/TranslatorGenMixin.vp index cb57200..fad01ae 100644 --- a/App/lib/core/Gen/TranslatorGenMixin.vp +++ b/App/lib/core/Gen/TranslatorGenMixin.vp @@ -510,8 +510,8 @@ novirtual class TranslatorGenMixin: fc: int = se.FieldCount if fc <= start_idx: return None - # 每个字段元素 = 类型前缀(MLIR 形态可达 _TY_TEXT_CAP 字节)+ 值文本; - # 160 是按旧的短类型估的,会截断。 + # 每个字段元素 = 类型前缀(MLIR 形态可达 _TY_TEXT_CAP 字节)+ 值文本; + # 160 是按旧的短类型估的,会截断。 buf_size: sizet = 256 + sizet(fc) * 576 buf: str = pool.alloc(buf_size) if buf is None: @@ -708,11 +708,11 @@ novirtual class TranslatorGenMixin: resolved_stg_ty: mlirlite.LLVMType* = None # 对象类全局:静态 storage 类型(BSS 实例) resolved_stg_entry: GenTypes.StructEntry* = None # 对象类全局:对应 StructEntry(vtable 初始化用) init_val: int64 = 0 - init_fval: t.CDouble = 0.0 # init_kind==4(浮点字面量)时的数值 + init_fval: double = 0.0 # init_kind==4(浮点字面量)时的数值 init_kind: int = 0 # 0=none, 1=int, 2=list, 3=str, 4=float init_str_val: str = None init_list_node: ast.List* = None - # = None 显式初始化(如 tokens.vp `_kw_head: KwEntry | t.CPtr = None`): + # = None 显式初始化(如 tokens.vp `_kw_head: KwEntry* = None`): # 对象类全局的懒初始化指针语义——必须保持 NULL,不能创建 BSS storage # (storage 会让 @g = &g.stg 恒非 NULL,破坏 `if _kw_head != None` 守卫, # 懒初始化代码永不执行)。 @@ -775,7 +775,7 @@ novirtual class TranslatorGenMixin: resolved_stg_entry = gv_entry resolved = mlirlite.Ptr(pool, resolved) elif resolved.kind() == mlirlite.LLVMType.Ptr: - # 对象类联合注解(T | t.CPtr → T*):同样创建 storage;否则入口/方法 + # 对象类联合注解(T* → T*):同样创建 storage;否则入口/方法 # 虚调用 load @g 得 NULL → 读 [NULL] 拿 vtable → #PF。 # var_ty 保持 Ptr(联合注解语义:指针全局),storage 承载对象实例。 pointee_uv: mlirlite.LLVMType* = resolved.Pointee @@ -888,7 +888,7 @@ novirtual class TranslatorGenMixin: self.Gen.TypeGenErr.fatal_error(node, f"模块级变量 '{var_name}' 用浮点字面量初始化,但注解不是浮点类型", "TypeError") return 0 - if self.Gen.AssignGen._recover_float_literal(var_name, t.CPtr(c.Addr(init_fval)), 0) != 1: + if self.Gen.AssignGen._recover_float_literal(var_name, t.CPtr(&init_fval), 0) != 1: self.Gen.TypeGenErr.fatal_error(node, f"模块级浮点变量 '{var_name}' 初始化值源文件恢复失败", "InternalCompilerError") return 0 @@ -1178,7 +1178,7 @@ novirtual class TranslatorGenMixin: # 前者是变量自身限定(BinOp 联合),后者是 rawptr 下标实参标记。 if self.Gen.TypeGenErr.has_pointee_volatile_marker(annot_node) != 0: self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, var_name) - # 设置 AnnotClassName(联合类型如 Logger|t.CPtr 简化为 Ptr(i8) 时, + # 设置 AnnotClassName(联合类型如 Logger* 简化为 Ptr(i8) 时, # 属性访问需要通过 AnnotClassName 回退到类名查找结构体) if k == ast.ASTKind.AnnAssign: aa_ml: ast.AnnAssign* = ast.AnnAssign*(node) @@ -1186,7 +1186,7 @@ novirtual class TranslatorGenMixin: 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) - # 模块级 str|t.CPtr / bytes|t.CPtr 全局:标记 IsPtrElement + # 模块级 str* / bytes* 全局:标记 IsPtrElement # (i8** 语义,var[i] 按 8 字节指针步长),对齐 TPC 的 # global_var_ptr_element(_argv 等字符串指针数组)。否则 # var[i] 退化为 1 字节字符步长 GEP + load i8 截断指针。 @@ -1296,7 +1296,7 @@ novirtual class TranslatorGenMixin: VLogger.error("global 变量数量超过上限,请减少 global 声明或增大 MAX_GLOBAL_NAMES", "ScopeDecl") return entry_addr: uint64 = uint64(trans._global_names) + trans._global_name_count * 8 - slot_ptr: str | t.CPtr = (str | t.CPtr)(entry_addr) + slot_ptr: str* = (str*)(entry_addr) slot_ptr[0] = name trans._global_name_count += 1 @@ -1306,7 +1306,7 @@ novirtual class TranslatorGenMixin: return 0 for i in range(trans._global_name_count): entry_addr: uint64 = uint64(trans._global_names) + i * 8 - slot_ptr: str | t.CPtr = (str | t.CPtr)(entry_addr) + slot_ptr: str* = (str*)(entry_addr) entry: str = slot_ptr[0] if entry is not None: if string.strcmp(entry, name) == 0: @@ -1329,13 +1329,13 @@ novirtual class TranslatorGenMixin: if self.is_nonlocal_name(trans, name) != 0: # 已存在:更新类型信息(可能在预扫描时类型未知,正式翻译时更新) # _nonlocal_types 每槽 8 字节,存 LLVMType* 指针。 - # 用 str|t.CPtr (i8**) 二级指针存取(与 _nonlocal_names 模式一致), + # 用 str* (i8**) 二级指针存取(与 _nonlocal_names 模式一致), # [0] 解引用只拷贝 8 字节指针,避免值拷贝 24+ 字节 LLVMType 结构体溢出。 if var_ty is not None and trans._nonlocal_types is not None: idx: int = self.get_nonlocal_index(trans, name) if idx >= 0: ty_addr: uint64 = uint64(trans._nonlocal_types) + idx * 8 - ty_slot: str | t.CPtr = (str | t.CPtr)(ty_addr) + ty_slot: str* = (str*)(ty_addr) ty_slot[0] = var_ty return if trans._nonlocal_name_count >= HT.MAX_GLOBAL_NAMES: @@ -1350,12 +1350,12 @@ novirtual class TranslatorGenMixin: VLogger.error("nonlocal 变量数量超过上限,请减少 nonlocal 声明或增大 MAX_GLOBAL_NAMES", "ScopeDecl") return entry_addr: uint64 = uint64(trans._nonlocal_names) + trans._nonlocal_name_count * 8 - slot_ptr: str | t.CPtr = (str | t.CPtr)(entry_addr) + slot_ptr: str* = (str*)(entry_addr) slot_ptr[0] = name - # 存储类型信息(用 str|t.CPtr = i8** 二级指针,与 _nonlocal_names 一致) + # 存储类型信息(用 str* = i8** 二级指针,与 _nonlocal_names 一致) if trans._nonlocal_types is not None: ty_addr2: uint64 = uint64(trans._nonlocal_types) + trans._nonlocal_name_count * 8 - ty_slot2: str | t.CPtr = (str | t.CPtr)(ty_addr2) + ty_slot2: str* = (str*)(ty_addr2) # var_ty 为 None 时直接报错终止(fail-fast),不再默认 i32 stored_ty: mlirlite.LLVMType* = var_ty if stored_ty is None: @@ -1377,7 +1377,7 @@ novirtual class TranslatorGenMixin: if idx < 0: return None ty_addr: uint64 = uint64(trans._nonlocal_types) + idx * 8 - ty_slot: str | t.CPtr = (str | t.CPtr)(ty_addr) + ty_slot: str* = (str*)(ty_addr) return (mlirlite.LLVMType*)(ty_slot[0]) def is_nonlocal_name(self, trans: HT.Translator*, name: str) -> int: @@ -1386,7 +1386,7 @@ novirtual class TranslatorGenMixin: return 0 for i in range(trans._nonlocal_name_count): entry_addr: uint64 = uint64(trans._nonlocal_names) + i * 8 - slot_ptr: str | t.CPtr = (str | t.CPtr)(entry_addr) + slot_ptr: str* = (str*)(entry_addr) entry: str = slot_ptr[0] if entry is not None: if string.strcmp(entry, name) == 0: @@ -1399,7 +1399,7 @@ novirtual class TranslatorGenMixin: return -1 for i in range(trans._nonlocal_name_count): entry_addr: uint64 = uint64(trans._nonlocal_names) + i * 8 - slot_ptr: str | t.CPtr = (str | t.CPtr)(entry_addr) + slot_ptr: str* = (str*)(entry_addr) entry: str = slot_ptr[0] if entry is not None: if string.strcmp(entry, name) == 0: diff --git a/App/lib/core/Gen/Type/TypeGenBase.vp b/App/lib/core/Gen/Type/TypeGenBase.vp index ae86d2f..8ce06ce 100644 --- a/App/lib/core/Gen/Type/TypeGenBase.vp +++ b/App/lib/core/Gen/Type/TypeGenBase.vp @@ -45,8 +45,8 @@ novirtual class TypeGenBase: # --- 全局 CDefine 编译期常量表(原 _g_cdefine_*) --- CDefineNames: list[str]* CDefineValues: list[str]* - CDefineDoubleFlags: list[int] | t.CPtr - CDefineStrFlags: list[int] | t.CPtr # 1=字符串值(如 ZLIB_VERSION: t.CDefine = "1.3.2") + CDefineDoubleFlags: list[int]* + CDefineStrFlags: list[int]* # 1=字符串值(如 ZLIB_VERSION: t.CDefine = "1.3.2") CDefineIsDouble: int CDefineIsStr: int CDefineFound: int @@ -63,8 +63,8 @@ novirtual class TypeGenBase: # CONST_INT 递归查找只做一次。 XmodCdefNames: list[str]* XmodCdefValues: list[str]* - XmodCdefDoubleFlags: list[int] | t.CPtr - XmodCdefStrFlags: list[int] | t.CPtr + XmodCdefDoubleFlags: list[int]* + XmodCdefStrFlags: list[int]* # --- 当前模块 SHA1(原 _g_current_module_sha1) --- CurrentModuleSha1: str diff --git a/App/lib/core/Gen/Type/TypeGenCDef.vp b/App/lib/core/Gen/Type/TypeGenCDef.vp index bf6cd69..9c097ca 100644 --- a/App/lib/core/Gen/Type/TypeGenCDef.vp +++ b/App/lib/core/Gen/Type/TypeGenCDef.vp @@ -159,8 +159,8 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): tp: memhub.MemBuddy* = self._cdefine_table_pool(pool) tn: list[str]* = list[str](tp, 64) tv: list[str]* = list[str](tp, 64) - td: list[int] | t.CPtr = list[int](tp, 64) - tsf: list[int] | t.CPtr = list[int](tp, 64) + td: list[int]* = list[int](tp, 64) + tsf: list[int]* = list[int](tp, 64) # 建表失败(池不可用/耗尽)⇒ 明确报错并返回,绝不让下面的 append # 落到 None 或未初始化地址(原实现无检查 ⇒ append 写进 NULL/0xCD 区崩) if tn is None or tv is None or td is None or tsf is None: @@ -213,8 +213,8 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): tp: memhub.MemBuddy* = self._cdefine_table_pool(pool) tn: list[str]* = list[str](tp, 64) tv: list[str]* = list[str](tp, 64) - td: list[int] | t.CPtr = list[int](tp, 64) - tsf: list[int] | t.CPtr = list[int](tp, 64) + td: list[int]* = list[int](tp, 64) + tsf: list[int]* = list[int](tp, 64) if tn is None or tv is None or td is None or tsf is None: self.Gen.TypeGenErr.fatal_error(None, "CDefine 浮点表分配失败(表本体池不可用或耗尽)", "MemoryError") return @@ -269,8 +269,8 @@ novirtual class TypeGenCDef(TypeGenBase.TypeGenBase): tp: memhub.MemBuddy* = self._cdefine_table_pool(pool) tn: list[str]* = list[str](tp, 64) tv: list[str]* = list[str](tp, 64) - td: list[int] | t.CPtr = list[int](tp, 64) - tsf: list[int] | t.CPtr = list[int](tp, 64) + td: list[int]* = list[int](tp, 64) + tsf: list[int]* = list[int](tp, 64) if tn is None or tv is None or td is None or tsf is None: self.Gen.TypeGenErr.fatal_error(None, "CDefine 字符串表分配失败(表本体池不可用或耗尽)", "MemoryError") return diff --git a/App/lib/core/Gen/Type/TypeGenCType.vp b/App/lib/core/Gen/Type/TypeGenCType.vp index 6d813e6..cc8a084 100644 --- a/App/lib/core/Gen/Type/TypeGenCType.vp +++ b/App/lib/core/Gen/Type/TypeGenCType.vp @@ -326,7 +326,7 @@ class TypeGenCType(TypeGenBase.TypeGenBase): 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: - """顶层 '|' 分段,返回首个能确定的符号性(`X | t.CPtr` 取 X)""" + """顶层 '|' 分段,返回首个能确定的符号性(`X*` 取 X)""" seg_start: sizet = start bracket_depth: int = 0 i: sizet = start diff --git a/App/lib/core/Gen/Type/TypeGenErr.vp b/App/lib/core/Gen/Type/TypeGenErr.vp index 16d4fc1..08a459f 100644 --- a/App/lib/core/Gen/Type/TypeGenErr.vp +++ b/App/lib/core/Gen/Type/TypeGenErr.vp @@ -240,12 +240,12 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): """检测指针注解 rawptr[...] 的下标实参是否含 t.CVolatile 标记,1=是 / 0=否 语义:rawptr[t.CVolatile | T] 等价 C 的 volatile T*,即"指针所指对象按 - volatile 访问"——解引用(p[i] / p.field / c.Deref(p))的 load/store 带 + volatile 访问"——解引用(p[i] / p.field / *p)的 load/store 带 LLVM volatile。与 has_decorator_marker 的区别:后者检测变量/字段**自身** - 的可见性限定(如 `locked: t.CVolatile | t.CInt`),对 Subscript 节点返回 0; + 的可见性限定(如 `locked: t.CVolatile | int`),对 Subscript 节点返回 0; 本函数专检 rawptr 的 pointee 侧标记(下标实参子树),两者互不串味。 标注形态(vast.parse 实证): - rawptr[t.CVolatile | t.CInt] + rawptr[t.CVolatile | int] → Subscript(value=Name('rawptr'), slice=BinOp(BitOr, Attribute(t,CVolatile), Attribute(t,CInt))) 多级指针 rawptr[rawptr[t.CVolatile|T]] 的 slice 是 Subscript, @@ -272,7 +272,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): ② 声明类型的 LLVM 形态**不是指针**(TPC 用 PtrCount==0 表达同一件事)。 `t.CConst` 在本语言里承载「指向的数据 const」(对齐 TPC 的 DataConst 语义), 对非指针类型该限定退化为「该对象自身 const」⇒ 登记为 const 变量/字段; - 对指针类型(`p: t.CConst | T | t.CPtr`)限定只作用于 pointee ⇒ 指针变量自身 + 对指针类型(`p: t.CConst | T*`)限定只作用于 pointee ⇒ 指针变量自身 仍可重新赋值,不登记。 """ if self.has_decorator_marker(node, "CConst", 0) == 0: diff --git a/App/lib/core/Gen/Type/TypeGenResolve.vp b/App/lib/core/Gen/Type/TypeGenResolve.vp index ab0c8c2..ce3a023 100644 --- a/App/lib/core/Gen/Type/TypeGenResolve.vp +++ b/App/lib/core/Gen/Type/TypeGenResolve.vp @@ -387,8 +387,8 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 依据是容器本身的定义(不是我猜的):TPC 侧 t.CArray 明写"第一个参数为元素类型, 第二个参数为数组大小(整数或常量名)"(lib/includes/t.py CArray);`list[T, N]` - 与 includes/_list.vp 的堆上 STL 容器 `list` 无关(`list[T, N]` 不是定长数组); - 这里把 list 一并纳入,只是因为历史写法 `list[E, N]` 的第 2 实参是常量, + 与 includes/_list.vp 的堆上 STL 容器 `list` 无关(`list[T, N]` 不是定长数组); + 这里把 list 一并纳入,只是因为历史写法 `list[E, N]` 的第 2 实参是常量, 须避免它被误当类名归一。 故这两个容器的第 2 实参是常量表达式 —— 对它做"裸类名 → {定义模块SHA1}.类"归一 既无意义,又会落进 `_norm_type_arg_name` 规则 5.5 的"保留裸名"取证 ⇒ 误报为 @@ -420,14 +420,14 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): `SymbolUtils.NormalizeGenericArgName` 同样原样保留)⇒ 对它报 ERROR 是纯噪声。 现场(2026-09-30):includes/traceback.vp:532 `FrameAddr: t.CArray[uint64, TRACEBACK_FRAME_BUF]` 的实参 'uint64' 是 - includes/builtins.vp 的 `typedef uint64 = t.CUInt64T`,不进类归属是**预期**, + includes/builtins.vp 的 `typedef uint64 = uint64`,不进类归属是**预期**, 却每次编译刷一条 ERROR。 判据(正向白名单,逐条可查,不猜): ① CTypedef 动态表命中 —— typedef 唯一真源(Phase1 1b 的 register_ctypedef_from_source 文本扫描注册;表在文件边界被 clear 后重建, 故紧跟 ② 的 builtins 兜底,与 `resolve_typedef_or_map` 的"统一口径"一致); - ② builtins.vp 的 typedef(如 `typedef uint64 = t.CUInt64T`):builtins 始终 + ② builtins.vp 的 typedef(如 `typedef uint64 = uint64`):builtins 始终 在编译链内,但其 typedef 不随当前文件 from_imports 注入 ⇒ 表可能 miss, 必须走与 `resolve_typedef_or_map` 同一兜底(命中即注册进表,幂等); ③ 语言内置标量/字符串名 —— 与 `_resolve_annot_type_name` 的跳过清单同口径; @@ -471,7 +471,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # _is_ptr_marker_text - 文本是否为"裸指针标记"(t.CPtr / c.CPtr / CPtr) # # 用途:泛型类型实参**文本**归一(_norm_type_arg_name)的唯一判据 —— - # 用户定口径(2026-09-30):`rawptr[T]` ≡ `t.CPtr[T]` ≡ `T | t.CPtr` + # 用户定口径(2026-09-30):`rawptr[T]` ≡ `t.CPtr[T]` ≡ `T*` # ⇒ 统一为 **`T*`**。裸标记只贡献一层指针、自身不是类型名。 # (形式无关:四种写法在类型域恒等价——`rawptr[T]` / `t.CPtr[T]` 一律追加 1 层。) # @@ -544,13 +544,13 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): 收敛同一类型的不同书写(ast.AST / AST → f467978339422f32.AST), 消除跨模块特化名分裂(undefined symbol: 7cadfe07e983fd90.list[AST].set 根因: - 一侧注解写 "list[ast.AST*]"、另一侧写 "list[AST | t.CPtr]", + 一侧注解写 "list[ast.AST*]"、另一侧写 "list[AST*]", 生成两个不同特化名 → 结构体/方法注册与调用不一致)。 规则(自顶向下): 1. 联合类型 "A|B"('|' 分割):左右段各自规范化后重组 1.0【指针书写归一(2026-09-30,用户定口径)】指针类型实参**唯一规范形 - 是 `T*`**:`rawptr[T]` ≡ `t.CPtr[T]` ≡ `T | t.CPtr` + 是 `T*`**:`rawptr[T]` ≡ `t.CPtr[T]` ≡ `T*` ⇒ 一律折叠为 `T*`(裸标记只贡献一层指针)。与 TPC 侧 SymbolUtils.ResolveTypeArgStr/AddPointerLayers 逐字同形,两侧必须 同票名(否则 .vpi/.stub.ll 的结构体名与方法符号名分叉)。 @@ -595,7 +595,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): return type_name # ---- 1. 顶层联合 "A|B"('|' 仅在括号外才分割)---- # 括号感知:list[A|B] 的 '|' 在 '[' 内不是顶层联合,应留给第 1.5 步 - # 泛型 slice 递归处理;list[A]|t.CPtr 的 '|' 在括号外才是联合分割。 + # 泛型 slice 递归处理;list[A]* 的 '|' 在括号外才是联合分割。 seg_len: sizet = string.strlen(type_name) if seg_len == 0: return type_name @@ -630,16 +630,16 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): l_n = left_buf if r_n is None: r_n = right_buf - # 【指针联合归一(2026-09-30,用户定口径)】`X | t.CPtr` ≡ `X | rawptr` + # 【指针联合归一(2026-09-30,用户定口径)】`X*` ≡ `X | rawptr` # ≡ `rawptr[X]` ≡ `t.CPtr[X]` ⇒ 统一为 **`X*`**(T* 形)。裸指针标记 # 只贡献一层指针;这不是新类型规则,只是**书写形式的唯一规范形** # (四种写法在类型域恒等价:下标形与联合形都只追加 1 层指针)。 # 为什么必须归一:同一元素类型 `AST*` 若一半写 `rawptr[AST]`、一半写 - # `AST|t.CPtr`,泛型特化名会分裂成两个结构体(现场 + # `AST*`,泛型特化名会分裂成两个结构体(现场 # Test/AstTest/App/main.vp:63 `classify_list(ifn.orelse, ...)`: - # 源 %"….list[rawptr[.AST]]"* vs 目标 %"….list[.AST|t.CPtr]"* + # 源 %"….list[rawptr[.AST]]"* vs 目标 %"….list[.AST*]"* # ⇒ 指针隐式转换规则按"不同非基本类型"拒绝,属假报错)。 - # 判据只拦"一侧恰为裸标记"这一确定形态;多层标记链(X|t.CPtr|t.CPtr) + # 判据只拦"一侧恰为裸标记"这一确定形态;多层标记链(X*|t.CPtr) # 与其它联合维持原有重组行为(不回归)。 l_is_mk: int = self._is_ptr_marker_text(l_n) r_is_mk: int = self._is_ptr_marker_text(r_n) @@ -753,12 +753,12 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 直接产出 "<实参规范化文本>*",与 TPC 侧 # SymbolUtils.ResolveTypeArgStr+AddPointerLayers 的逐字口径一致。 # 不做这一步时,同一元素类型(都是 AST*)会分裂成 - # `list[rawptr[.AST]]` 与 `list[.AST|t.CPtr]` 两个特化体 + # `list[rawptr[.AST]]` 与 `list[.AST*]` 两个特化体 # ⇒ 调用点被严格指针规则按"不同非基本类型"拒绝(现场 # Test/AstTest/App/main.vp:63,假报错)。多实参(异常写法)不拦。 # 【判据必须用**下标容器**判据(2026-09-30)】不能复用 # _is_ptr_marker_text(它只认 CPtr 一族,用于联合写法): - # 复用它会让 `rawptr[T]` 漏折叠 ⇒ 与 `T | t.CPtr` 折叠后的 + # 复用它会让 `rawptr[T]` 漏折叠 ⇒ 与 `T*` 折叠后的 # `T*` 并存两个特化体(现场 _list.vp:83 return self 的 # CastError:list[.AST*] ↔ list[rawptr[.AST]])。 # 详见 _is_ptr_subscript_container_text 的头注释。 @@ -792,7 +792,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): string.strcat(g_out, "]") return g_out # ---- 1.6 尾随指针星号:先归一基名,再回贴星号(2026-10-01)---- - # parser 把源码 `X*` 展开为 `X | t.CPtr`,但**泛型实参文本**里的星号是原样 + # parser 把源码 `X*` 展开为 `X*`,但**泛型实参文本**里的星号是原样 # 带进来的(如字段 `list[ast.ClassDef*]` 的实参段文本就是 "ast.ClassDef*")。 # 不剥离时规则 4 的 attr 会带上星号变成 "ClassDef*": # ① `_class_true_def_sha1` 按名查不到 "ClassDef*" ⇒ 真定义模块校正失效 ⇒ @@ -801,7 +801,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # `list[e70bd9b4487d921d.ClassDef*]` ⇒ TPV 报「指针隐式转指针已禁止」, # 且该票名在全部产物里从未定义为实体结构体); # ② 与 TPC 名称域不一致 —— SymbolUtils.ResolveTypeArgStr 的 BinOp 分支明确 - # 规定 `X | t.CPtr` ≡ `rawptr[X]` ≡ `t.CPtr[X]` → `{sha}.X*`(先解析基 + # 规定 `X*` ≡ `rawptr[X]` ≡ `t.CPtr[X]` → `{sha}.X*`(先解析基 # 类型 X,再 AddPointerLayers 追加星号)。 # 故统一为:剥掉全部尾随 '*' → 递归归一基名 → 回贴同样多的 '*'。 # `i8**` / `int*` / `T*` / 已带 SHA1 前缀的文本都逐字不变(基名归一回原样)。 @@ -1040,10 +1040,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): def _str_contains_ident(self, s: str, ident: str) -> int: """检查 s 中是否包含独立标识符 ident(两侧非字母/数字/下划线) - 用于泛型实参污染检测:单字符参数名(如 'T')在实参串 "AST|t.CPtr" + 用于泛型实参污染检测:单字符参数名(如 'T')在实参串 "AST*" 中作为 AST/CPtr 内部字符出现时不算污染——必须两侧是边界 (空格/|/[/]/,等)才算独立标识符。strstr 子串匹配会把实参内部 - 的 'T' 误判为参数名 → 合法特化 list[AST|t.CPtr] 被误杀。 + 的 'T' 误判为参数名 → 合法特化 list[AST*] 被误杀。 """ if s is None or ident is None or ident[0] == '\0': return 0 @@ -1077,10 +1077,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): ctx: int) -> ast.AST*: """将类型名字符串解析为 AST 节点 - 正确处理 '|' 与 '.' 周围的空格(如 "ParsedArgs | t.CPtr"): + 正确处理 '|' 与 '.' 周围的空格(如 "ParsedArgs*"): - '|' 分割后左段可能带尾随空格("ParsedArgs "),右段可能带前导空格(" t.CPtr") - 段内空格会导致 Name.id 带空格("ParsedArgs "、" t"),结构体/模块按名查找失败, - 最终退化 i8*/i32,如 parse_args -> "ParsedArgs | t.CPtr" 解析出垃圾类型。 + 最终退化 i8*/i32,如 parse_args -> "ParsedArgs*" 解析出垃圾类型。 """ if type_str is None or pool is None: return None @@ -1096,7 +1096,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 【`T*` 形反解析(2026-09-30)】泛型实参归一后指针类型一律是 `T*` 形 # (TypeGenResolve._norm_type_arg_name 的指针书写归一:rawptr[T] ≡ - # t.CPtr[T] ≡ T|t.CPtr ≡ T*),而本函数负责把**类型名文本**还原成注解 AST + # t.CPtr[T] ≡ T* ≡ T*),而本函数负责把**类型名文本**还原成注解 AST # (典型调用方:ClassGenGeneric._clone_annotation 把泛型参数 T 替换为 # 已归一的实参文本)⇒ 必须能解析尾随 '*'。语义与 `rawptr[T]` 逐字等价 # (下标形与联合形恒等价,都只追加 1 层指针),故按层数包成 rawptr[...]: @@ -2054,7 +2054,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): cls_nm = nm.id if from_imports is not None: sha1 = self.Gen.CallGenBase._lookup_mod_sha1(pool, from_imports, cls_nm, 0) - # 本文件顶层类(如自我引用 JsonValue | t.CPtr,或同文件内前向引用): + # 本文件顶层类(如自我引用 JsonValue*,或同文件内前向引用): # register_file_classes 已登记"名字 → 本文件模块 SHA1"(规则 5.5 证据⑤同源), # 用它前向声明——与 TPC 的同类前向引用同等处理。 if sha1 is None: @@ -2068,7 +2068,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 成功(还没 register_struct),它的归属同样可判——据此前向声明为具名占位 # "{src_sha1}.{类名}",而不是退化成 Ptr(i8)。 # 现场:Translator.vp 的 `class Translator`(:84) 与 `class Mixin`(:1011), - # 字段 `Mixin.Trans: Translator | t.CPtr` 在 Translator.vpi 注入到 + # 字段 `Mixin.Trans: Translator*` 在 Translator.vpi 注入到 # CallGenLeafKit.vp 时解析(self.Trans.Pool 属性访问失败根因):若本遍 # Translator 尚未登记就退化成 i8*,随后 Mixin 因 field_count>0 被判"注册 # 成功"、i8* 被永久冻结(inject_class 的已注册检查直接早退)。 @@ -2161,7 +2161,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): elif string.strcmp(type_name, "callable") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) # 裸名 void 是 t.CVoid 的别名(用户 2026-10-01 定):单独出现即 LLVM void; - # `void*`(= `void | t.CPtr`)由下方 BinOp 分支归并为 i8*。 + # `void*`(= `void*`)由下方 BinOp 分支归并为 i8*。 elif string.strcmp(type_name, "CVoid") == 0 or string.strcmp(type_name, "void") == 0: return mlirlite.Void(pool) # CDefine: 编译期常量定义标记(X: t.CDefine = 64),底层为 32 位有符号整数 @@ -2233,7 +2233,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): - t.CPtr / t\.CVoid(Attribute 形式) - 裸名 CPtr / CVoid(from t import CPtr 形式) 裸名识别是必要功能:测试/库代码大量用 `from t import CPtr` 后直接写 - `X | CPtr`、`CVoid` 参数注解等,若只认 t.XXX 会漏判。 + `X*`、`CVoid` 参数注解等,若只认 t.XXX 会漏判。 """ if node is None or attr_name is None: return 0 @@ -2278,7 +2278,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): def _is_cptr_subscript(self, node: ast.AST*) -> int: """检测节点是否为 t.CPtr[T] 下标指针类型(t.CPtr[t.CPtr] / t.CPtr[int] 等) - 用于联合类型 X | t.CPtr[T] 的指针层级合并(TPC 联合合并规则: + 用于联合类型 X*[T] 的指针层级合并(TPC 联合合并规则: CPtr 侧贡献 PtrCount,另一侧提供 BaseType)。t.CPtr[...] 不是 普通 CPtr 标记(_is_cptr_marker 只认 t.CPtr/CPtr 裸形式)。 """ @@ -2435,8 +2435,8 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): from_imports: str = None) -> str: """从类型注解 AST 中提取类名,返回 None=无法提取 - pool 可用时,对泛型 Subscript(如 list[AST | t.CPtr])返回 mangled name - (如 "list[f467978339422f32.AST|t.CPtr]"),与 resolve_annotation_type 的 + pool 可用时,对泛型 Subscript(如 list[AST*])返回 mangled name + (如 "list[f467978339422f32.AST*]"),与 resolve_annotation_type 的 mangled name 格式一致,使 find_struct 能找到特化的泛型结构体。 from_imports 可用时,slice 类型参数经 _norm_type_arg_name 规范化为 "{定义模块SHA1}.{Class}"(ast.AST/AST → f467978339422f32.AST), @@ -2476,7 +2476,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if nm.id is None: return None # 泛型特化上下文:T → 具体类型(特化方法体内局部变量注解 - # 如 `cur: T | t.CPtr` 未被 _clone_classdef_for_spec 克隆替换, + # 如 `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) @@ -2560,7 +2560,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): return None # BUG 1 方案3:Subscript 节点拼接 mangled name - # list[AST | t.CPtr] → "list[ast.AST|t.CPtr]"(pool 可用时) + # list[AST*] → "list[ast.AST*]"(pool 可用时) # 与 resolve_annotation_type 的 mangled name 格式一致,使 find_struct 能找到特化结构体 if k == ast.ASTKind.Subscript: sub: ast.Subscript* = ast.Subscript*(node) @@ -2632,9 +2632,9 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): string.strcat(tup_buf, elt_name2) slice_name = tup_buf else: - # 非 Tuple slice: list[AST | t.CPtr] → "ast.AST|t.CPtr" + # 非 Tuple slice: list[AST*] → "ast.AST*" # 类型参数经 _norm_type_arg_name 规范化为 "{SHA1}.Class", - # 与特化注册名一致(list[f467978339422f32.AST|t.CPtr]) + # 与特化注册名一致(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: @@ -2819,7 +2819,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): gen_spec_ty = self.Gen.StructGen.get_struct_type(gen_mangled) # gen_mangled 由本函数自行拼接,而 _specialize_generic_class 内部还会对 # 每个实参再规范化一次,两处命名可能不一致(如元素注解 `ast.AST*` - # 本函数拼 "list[.AST|t.CPtr]",特化侧规范化 "list[.ASTptr]") + # 本函数拼 "list[.AST*]",特化侧规范化 "list[.ASTptr]") # → 按 gen_mangled 重查恒 miss → 静默退化为裸 list* → .get() 误分派截断。 # spec_name_chk 是特化侧返回的权威特化名,必须按它重查。 # 注:非联合实参(如 list[int])两侧命名一致,本步恒 miss 不改变行为。 @@ -2868,7 +2868,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): return None # ============================================================ - # _check_bare_generic_annotation - fail-fast:注解(或其 A | t.CPtr 联合的一侧) + # _check_bare_generic_annotation - fail-fast:注解(或其 A* 联合的一侧) # 里出现"已注册的泛型模板类名"却没写 [类型实参] 的裸用法(如 GSList、vector.Vector)。 # # 与 AssignGenMixin._fail_on_degenerated_generic_annotation 互补:后者防"写了实参 @@ -2931,7 +2931,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): self.Gen.TypeGenErr.fatal_type_error(node, "类型注解递归过深(AST 环或嵌套超过 128 层)") # 裸泛型注解 fail-fast(集中守卫,见 _check_bare_generic_annotation): - # 注解本身或 A | t.CPtr 的一侧是"已注册泛型模板类名"却没写 [类型实参] 即终止。 + # 注解本身或 A* 的一侧是"已注册泛型模板类名"却没写 [类型实参] 即终止。 self._check_bare_generic_annotation(node) k: int = node.kind() @@ -2970,7 +2970,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if gp_ta is not None: # 自映射/污染实参防护(泛型循环套用): # 1) 实参与参数名完全一致(T→T) - # 2) 实参串包含任一类型参数名(如 "T | t.CPtr"、" T "、 + # 2) 实参串包含任一类型参数名(如 "T*"、" T "、 # "list[T]")——_parse_type_string 解析后仍会产出 # Name(参数名) → 递归再次进入本分支 → 无条件自递归 # 无退出条件 → 编译卡死。该递归不经 _specialize_generic_class @@ -2989,13 +2989,13 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # "独立标识符"参数名(两侧非字母/数字/_)。否则 strstr # 把实参内部字符误判为参数名——"e9dfb296a8674aee.AST| # t.CPtr" 含 'T' 字符但 T 在 AST/CPtr 内部不是独立 - # 参数名 → 合法特化 list[AST|t.CPtr] 被误杀(_list.vp - # L57 elem_ptr: T | t.CPtr 根因)。 + # 参数名 → 合法特化 list[AST*] 被误杀(_list.vp + # L57 elem_ptr: T* 根因)。 if gp_pn is not None and self._str_contains_ident(gp_ta, gp_pn) != 0: polluted = 1 break if polluted != 0: - # 实参串包含类型参数名(如 "T | t.CPtr"/"list[T]"): + # 实参串包含类型参数名(如 "T*"/"list[T]"): # 解析后仍产出 Name(参数名) → 无条件自递归卡死。编译期 # 报错(此前 return None 静默退化)。 self.Gen.TypeGenErr.fatal_error(nm, f"泛型类型实参污染:实参 '{gp_ta}' 包含类型参数名,无法特化", "TypeError") @@ -3021,8 +3021,8 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): sp_entry2: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(nm.id + sp_len2, sp_sha_buf2) if sp_entry2 is not None and sp_entry2.Ty is not None: # 裸类名恒为**原型**(struct 本身,值/布局语义),不再看 HasNew: - # 堆对象引用必须显式写 `T*` / `T | t.CPtr` / `rawptr[T]` - # (用户 2026-10-01 定;TPC 侧注解链路本无 __new__ 升指针逻辑, + # 堆对象引用必须显式写 `T*` / `T*` / `rawptr[T]` + # (用户 2026-10-01 定;TPC 侧注解链路本无 __new__ 升指针逻辑, # 天然同口径,故 TPC 无需同步改)。 return sp_entry2.Ty # 兜底:按完整前缀名直接查(部分注册键即全名) @@ -3062,27 +3062,27 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if own_entry is not None and own_entry.Ty is not None: # 裸类名恒为**原型**(struct 本身):注解说的是"类型/布局", # 不再按 HasNew 自动升成 Ptr(struct)。堆对象引用一律显式写 - # `T*` / `T | t.CPtr` / `rawptr[T]`(用户 2026-10-01 定; + # `T*` / `T*` / `rawptr[T]`(用户 2026-10-01 定; # TPC 侧注解链路本无 __new__ 升指针逻辑,天然同口径, # 故 TPC 无需同步改)。旧行为(有 __new__ ⇒ Ptr(struct))是 # 为兼容 `d: dict = dict(bd)` 这类"裸名 + 构造"写法而设, # 代价是同一类型出现"裸名=指针 / 联合=再加一层"的分裂 # (现场 includes/json/__init__.vp:90 CastError)。 - return own_entry.Ty - # vpi 注入期:CurDefModuleSha1 = **本次注入的 stub 源模块**(inject_class 入口 - # 的 mark_module_class 建立)。注入期 trans.ModuleSha1 是"正在翻译的文件", - # 故上面的本模块查找必然落空。此处按同一口径认"被注入 stub 自己声明的类": - # 已登记条目、或先前由指针前向声明建立的具名占位,都返回原型(裸类名恒为原型, - # 见上),使同一 stub 内"先声明/先被引用"的类在后继字段注解里口径一致,不再 - # 绕经"联合回退 → 前向声明 → 退化为 Ptr(i8)"那条链。 - # 注:此处**不新建**占位——值语义位置凭空建不透明原型会得到不可用布局; - # 占位创建仍归 _forward_declare_ptr_from_node(指针语境)。 - if trans is not None and trans.ModuleSha1 is not None: - inj_mod_rn: str = self.Gen.StructGen.CurDefModuleSha1 - 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 own_entry.Ty + # vpi 注入期:CurDefModuleSha1 = **本次注入的 stub 源模块**(inject_class 入口 + # 的 mark_module_class 建立)。注入期 trans.ModuleSha1 是"正在翻译的文件", + # 故上面的本模块查找必然落空。此处按同一口径认"被注入 stub 自己声明的类": + # 已登记条目、或先前由指针前向声明建立的具名占位,都返回原型(裸类名恒为原型, + # 见上),使同一 stub 内"先声明/先被引用"的类在后继字段注解里口径一致,不再 + # 绕经"联合回退 → 前向声明 → 退化为 Ptr(i8)"那条链。 + # 注:此处**不新建**占位——值语义位置凭空建不透明原型会得到不可用布局; + # 占位创建仍归 _forward_declare_ptr_from_node(指针语境)。 + if trans is not None and trans.ModuleSha1 is not None: + inj_mod_rn: str = self.Gen.StructGen.CurDefModuleSha1 + 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 # from-import 归属查找:注解里的裸名(或 import 别名)经 from_imports 定位到 # 定义模块,再按 (name, sha1) 精确取类——这是 stub 注入场景的正解:此刻 @@ -3365,7 +3365,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 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) - # 模块限定 typedef(posix.DIR = t.CTypedef = t\.CVoid|t.CPtr 等): + # 模块限定 typedef(posix.DIR = t.CTypedef = t\.CVoid* 等): # 与 Name 分支同一套 lookup_ctypedef + 递归解析(单层 Module.Typedef # 与嵌套 Attribute 都要支持)。 if self.Gen.TypeGenCType.CTypedefResolveDepth < TypeGenMixin.MAX_CTYPEDEF_DEPTH: @@ -3439,7 +3439,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # BinOp 节点: 联合类型注解 A | B # 处理三种语义: - # 1. ActualType | t.CPtr → Ptr(ActualType)(指针包装,如 MemBuddy | t.CPtr → MemBuddy*) + # 1. ActualType* → Ptr(ActualType)(指针包装,如 MemBuddy* → MemBuddy*) # 2. t.CPtr → i8* (void* 等价于 i8*) # 3. ActualType | DecoratorMarker → ActualType(忽略装饰器标记如 CExport/CExtern) if k == ast.ASTKind.BinOp: @@ -3477,20 +3477,20 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): other_is_cvoid = 1 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*, - # 与上方 other_is_cvoid 分支同一结论(否则会拼出非法的 Ptr(void))。 - # **必须守 None**:`X*`(parser 展开为 BinOp `X | t.CPtr`)在 Phase 1a - # prescan 时 X 很可能尚未注册(类定义在函数之后),resolve 返回 None; - # 对 None 做 case 匹配会按 REnum tag 解引用空指针(ASan 现场:address 0x0 - # READ,栈 _prescan_funcdef_signatures → resolve_annotation_type)。 - # None 交由下方既有 `if other_ty is None:` 分支处理。 - if other_ty is not None: - match other_ty: - case mlirlite.LLVMType.Void(): - return mlirlite.Ptr(pool, mlirlite.Int8(pool)) - case _: + 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*, + # 与上方 other_is_cvoid 分支同一结论(否则会拼出非法的 Ptr(void))。 + # **必须守 None**:`X*`(parser 展开为 BinOp `X*`)在 Phase 1a + # prescan 时 X 很可能尚未注册(类定义在函数之后),resolve 返回 None; + # 对 None 做 case 匹配会按 REnum tag 解引用空指针(ASan 现场:address 0x0 + # READ,栈 _prescan_funcdef_signatures → resolve_annotation_type)。 + # None 交由下方既有 `if other_ty is None:` 分支处理。 + if other_ty is not None: + match other_ty: + case mlirlite.LLVMType.Void(): + return mlirlite.Ptr(pool, mlirlite.Int8(pool)) + case _: pass # 仅裸名(Name)场景验证解析结果必须是已注册 struct: # 损坏节点可能解析出基础类型垃圾(如 Int8 → Ptr(i8))。 @@ -3507,7 +3507,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 泛型类型参数(T→int 等)经上下文替换解析出的合法标量 # 必须保留——"Name 且未注册 struct 即丢弃"本为拦截损坏 # 节点解析出基础类型垃圾,但会误杀泛型替换的合法标量, - # 导致 T | t.CPtr(T=int)退化为 i8*:list[int] elem_ptr + # 导致 T*(T=int)退化为 i8*:list[int] elem_ptr # 按 8 字节槽写、elem_size=4 步长读 → 元素互相覆盖, # pop 读到 0(ListTest 根因)。泛型参数名放行。 keep_other_ty: int = 0 @@ -3523,7 +3523,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): keep_other_ty = 1 break # 内建标量类型名(int/str/bytes/bool/float/double)是合法 - # 标量,不是损坏节点解析出的垃圾:int | t.CPtr 应解析为 + # 标量,不是损坏节点解析出的垃圾:int* 应解析为 # i32*(int 指针),若按"Name 未注册 struct 即丢弃"踢掉 # int → 联合退化为 i8* → int_ptr[0]=val 写 1 字节截断、 # 读回符号扩展(DictTest key5=500 读出 -12 根因)。 @@ -3547,7 +3547,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # (对齐 TPC HandlesTypeMerge._MergeAllComponentTypes)。 # 指针层数口径(本处 / VpiReader 注入侧 / 调用侧三处必须同步):`| t.CPtr` # **恒为"追加恰好 1 层指针",无例外**——裸类名恒为原型 struct, - # `X | t.CPtr` 由 Ptr(struct) 天然得到 X*,不再需要"pointee 是已注册 + # `X*` 由 Ptr(struct) 天然得到 X*,不再需要"pointee 是已注册 # struct 就吸收这 1 层"的旧补偿(该补偿曾把指针型 T 的 `T*` 降一层)。 if keep_other_ty == 0 and other_node is not None and other_node.kind() == ast.ASTKind.Name: other_nm_td: ast.Name* = ast.Name*(other_node) @@ -3569,8 +3569,8 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): other_ty = None if other_ty is None: # 严格模式(App 文件)下裸类名不可见时,回退到全局 - # struct 注册表按类名查找。X | t.CPtr 是明确的指针包装 - # 注解(如 vpi stub 的 "ParsedArgs | t.CPtr"),X 已注册 + # struct 注册表按类名查找。X* 是明确的指针包装 + # 注解(如 vpi stub 的 "ParsedArgs*"),X 已注册 # 时不应静默退化为 i8*——i8* 会让方法返回值的无注解变量 # (如 args = parser.parse_args())类型退化,后续 obj.method # get_class_name_by_type 查不到类名,误报 @@ -3599,26 +3599,26 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if _fwd_ptr_ty is not None: return _fwd_ptr_ty return mlirlite.Ptr(pool, mlirlite.Int8(pool)) - # `X | t.CPtr` **恒追加恰好 1 层**(用户口径,与 rawptr[T]/t.CPtr[T] 下标形 + # `X*` **恒追加恰好 1 层**(用户口径,与 rawptr[T]/t.CPtr[T] 下标形 # 以及 `_parse_type_string` 的 `T*` 反解析三处同源): - # T* ≡ rawptr[T] ≡ t.CPtr[T] ≡ T | t.CPtr + # T* ≡ rawptr[T] ≡ t.CPtr[T] ≡ T* # 这里原先还有一段"struct 引用语义吸收"(other_ty 若已是 Ptr(已注册 struct) # 就直接返回它、吞掉 CPtr 这层),那是"裸类名自动升指针"时代的补偿: # 当时裸类名/引号注解解析成 Ptr(struct),所以要吸收;自 2026-10-01 起 # 裸类名恒为**原型 struct**(见本文件 Name/Attribute 各分支), - # `X | t.CPtr` 由 Ptr(struct) 天然得到 X*,吸收已无正当对象 + # `X*` 由 Ptr(struct) 天然得到 X*,吸收已无正当对象 # (json/__init__.vp:90 的引号注解 `'JsonValue' | t.CPtr` 现在 other_ty # 就是 struct,吸收本就不触发,删除后行为不变)。 # 而**泛型形参实例化为指针类型**时(`list[rawptr[AST]]` 里 `T` 的实参文本是 - # `{sha}.AST*`,parser 把源码 `T*` 解析成 BinOp `T | t.CPtr`)other_ty 正是 + # `{sha}.AST*`,parser 把源码 `T*` 解析成 BinOp `T*`)other_ty 正是 # Ptr(已注册 struct) ⇒ 误吸收把 `T*` 降成 AST*(应为 AST**), # 现场 includes/_list.vp:54 `elem_ptr[0] = item` 被误判为"左值元素是对象 # AST(48 字节)、右值是指针"而 fail-fast。 return mlirlite.Ptr(pool, other_ty) # t.CPtr[...] 下标指针标记(普通 _is_cptr_marker 不识别 Subscript): - # X | t.CPtr[T] → 指针层级合并(对齐 TPC HandlesTypeMerge.py L864-884: - # CPtr 侧贡献 PtrCount,另一侧提供 BaseType),如 uint8 | t.CPtr[t.CPtr] → u8**。 + # X*[T] → 指针层级合并(对齐 TPC HandlesTypeMerge.py L864-884: + # CPtr 侧贡献 PtrCount,另一侧提供 BaseType),如 uint8*[t.CPtr] → u8**。 # 不处理会落到"无 CPtr 标记"分支返回左值 i8 → c.Deref 报"参数不是指针类型"。 cptr_sub_side: ast.AST* = None cptr_other: ast.AST* = None @@ -3762,7 +3762,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # rawptr[T] 内建裸指针:等价 t.CPtr[T] → Ptr(T)(T 自身可含指针层级)。 # 与 t.CPtr[T] 语义一致;不处理则泛型特化/builtins 兜底失败 → # "函数返回类型解析失败:注解不可解析"。 - # **恒追加 1 层,无例外**:`rawptr[T]` ≡ `t.CPtr[T]` ≡ `T*` ≡ `T | t.CPtr`。 + # **恒追加 1 层,无例外**:`rawptr[T]` ≡ `t.CPtr[T]` ≡ `T*` ≡ `T*`。 # 旧实现在此处做"切片是裸类引用(解析结果为 Ptr(已注册 struct))就吸收这层" # ——那是"裸类名自动升指针"时代的补偿;自 2026-10-01 起裸类名恒为**原型** # (struct 值),`Ptr(struct)` 天然就是 X*,补偿已无对象,反而在**泛型形参 @@ -3834,7 +3834,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 指针类型: t.CPtr[T] → Ptr(T)(T 自身可含指针层级):t.CPtr[t.CPtr] → i8**, # t.CPtr[int] → i32*(DeclarationGenerator.py L1014-1016 文档化语法)。 # **恒追加 1 层,无例外**(与 rawptr[T] 分支同口径):`t.CPtr[T]` ≡ `T*` - # ≡ `T | t.CPtr`。此处原先也做"切片是裸类引用就吸收一层",同 rawptr[T] + # ≡ `T*`。此处原先也做"切片是裸类引用就吸收一层",同 rawptr[T] # 分支:裸类名恒为原型后该补偿无对象,且会在 T 实例化为指针类型时吃掉 # 真层数(`t.CPtr[T]` 应得 T**)。 if string.strcmp(arr_at.attr, "CPtr") == 0: @@ -3846,7 +3846,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 元素类型依赖未就绪(如 t.CPtr[类]/rawptr[类] 中类尚未注册, # rawptr[T] 经 builtins typedef 归一到本分支):优先**前向声明** # 具名占位 {sha}.Class 并返回 Ptr(占位.Ty),保住类身份(对齐 - # X|t.CPtr 分支与 TPC);无法确定类名/模块时仍返回 None 交上层 + # X* 分支与 TPC);无法确定类名/模块时仍返回 None 交上层 # 多遍收敛,不在此 fatal 中断 Phase 1a 预注册(UINT 等只经 # CTypedef 动态表解析)。真实类型错误由 Phase A 收敛检查暴露。 _fwd_cptr_ty: mlirlite.LLVMType* = self._forward_declare_ptr_from_node( diff --git a/App/lib/core/Gen/Type/TypeSpec.vp b/App/lib/core/Gen/Type/TypeSpec.vp index 11c4202..9b30b67 100644 --- a/App/lib/core/Gen/Type/TypeSpec.vp +++ b/App/lib/core/Gen/Type/TypeSpec.vp @@ -178,8 +178,8 @@ def SpecSignFromTypeName(name: str) -> int: # ============================================================ # TypeSpec - 类型描述符 # -# 元素语义三字段(ElemBits/IsElemPtr/DerefBase):`str | t.CPtr`、`bytes | t.CPtr`、 -# 泛型 `T | t.CPtr`、`64 位标量 | t.CPtr` 退化后的 LLVM 类型都是单层 Ptr(i8), +# 元素语义三字段(ElemBits/IsElemPtr/DerefBase):`str*`、`bytes*`、 +# 泛型 `T*`、`64 位标量 | t.CPtr` 退化后的 LLVM 类型都是单层 Ptr(i8), # PtrLevel=1 同时对应两种相反语义,仅靠指针层级无法区分 ⇒ 靠「元素宽度 + 元素是否 # 指针 + 基址是否需二次解引用」三元组区分(替代旧的单一布尔 IsPtrElement)。 # ============================================================ @@ -195,10 +195,10 @@ class TypeSpec: BaseName: str # 结构体/枚举/类名(带模块 sha1;PermPool 深拷贝) # SourceName: 注解侧「来源名」(替代 AnnotClassName)。 # 与 BaseName 的区别是命名域:BaseName = LLVM 结构体注册名(跨模块/特化时形如 - # {16hex sha1}.Class 或 list[...|t.CPtr]),由 SpecFromLLVMType 反推; + # {16hex sha1}.Class 或 list[...*]),由 SpecFromLLVMType 反推; # SourceName = 注解**书写形态**的名字(裸名 / 模块限定名 / t.XXX 裸 attr 名 / # Subscript mangled 名),由注解侧 SpecWithSource 填写。 - # 为何需要:`X | t.CPtr` 联合被简化为 Ptr(i8) 后 BaseName 恒为 None(类名已丢), + # 为何需要:`X*` 联合被简化为 Ptr(i8) 后 BaseName 恒为 None(类名已丢), # 而属性访问/方法分派/结构体查找仍要靠注解侧名字恢复。 # **不参与驻留键**:注解名种类远多于类型种类(每个泛型 mangled 名/别名各一份), # 入键会让 InternSpec 条目暴增且线性查找变慢;驻留本意只是跨 reset 存活, @@ -268,7 +268,7 @@ def _spec_key_at(keys: bytes, index: int) -> str: # 槽存 index+1(0=空槽);线性探测,逐槽比较键文本——必须按键内容区分, # 不能只比哈希(否则冲突键会误命中并返回错误实例)。 # ============================================================ -def _spec_index_find(arena: TypeSpecArena | t.CPtr, key: str, h: uint64) -> int: +def _spec_index_find(arena: TypeSpecArena*, key: str, h: uint64) -> int: """查驻留哈希索引,命中返回条目下标;未命中返回 -1""" if arena.Index is None or arena.IndexCap <= 0: return -1 @@ -294,7 +294,7 @@ def _spec_index_find(arena: TypeSpecArena | t.CPtr, key: str, h: uint64) -> int: # 返回 0=成功 / 1=索引不可用或已满。仅在追加新条目后调用 # (条目只增不删,故无需墓碑;槽数 > 2*Cap ⇒ 必然存在空槽,探测终止)。 # ============================================================ -def _spec_index_insert(arena: TypeSpecArena | t.CPtr, key: str, h: uint64, ei: int) -> 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 @@ -315,7 +315,7 @@ def _spec_index_insert(arena: TypeSpecArena | t.CPtr, key: str, h: uint64, ei: i # SpecArenaInit - 初始化驻留表(幂等;cap<=0 时用 SPEC_INTERN_MAX) # 返回 0=成功 / 1=失败(分配失败 fail-fast 由调用方处理,此处返回错误码) # ============================================================ -def SpecArenaInit(arena: TypeSpecArena | t.CPtr, cap: int) -> int: +def SpecArenaInit(arena: TypeSpecArena*, cap: int) -> int: """初始化驻留表;已初始化则直接返回 0""" if arena is None: return 1 @@ -409,7 +409,7 @@ def _spec_set_struct_name(sp: TypeSpec*, name: str) -> int: # ============================================================ # NewTypeSpec - 构造基础类型(驻留) # ============================================================ -def NewTypeSpec(arena: TypeSpecArena | t.CPtr, kind: int, +def NewTypeSpec(arena: TypeSpecArena*, kind: int, bits: int, is_signed: int) -> TypeSpec*: """构造基础 TypeSpec 并驻留,失败返回 None""" sp: TypeSpec* = _spec_make(kind, bits, is_signed) @@ -421,7 +421,7 @@ def NewTypeSpec(arena: TypeSpecArena | t.CPtr, kind: int, # ============================================================ # NewTypeStruct - 构造结构体/枚举/类类型(驻留) # ============================================================ -def NewTypeStruct(arena: TypeSpecArena | t.CPtr, kind: int, +def NewTypeStruct(arena: TypeSpecArena*, kind: int, base_name: str) -> TypeSpec*: """构造 struct/union/enum 类型(BaseName 深拷贝 + 驻留),失败返回 None""" sp: TypeSpec* = _spec_make(kind, 0, TS_SIGN_UNKNOWN) @@ -435,7 +435,7 @@ def NewTypeStruct(arena: TypeSpecArena | t.CPtr, kind: int, # ============================================================ # NewTypePtr - 构造指针类型(PtrLevel = 元素 PtrLevel + 1,驻留) # ============================================================ -def NewTypePtr(arena: TypeSpecArena | t.CPtr, +def NewTypePtr(arena: TypeSpecArena*, elem: TypeSpec*) -> TypeSpec*: """构造指针类型:指向 elem(PtrLevel 逐层递增),失败返回 None""" if elem is None: @@ -455,7 +455,7 @@ def NewTypePtr(arena: TypeSpecArena | t.CPtr, # ============================================================ # NewTypeArray - 构造数组类型(ArrayCount 个 elem,驻留) # ============================================================ -def NewTypeArray(arena: TypeSpecArena | t.CPtr, elem: TypeSpec*, +def NewTypeArray(arena: TypeSpecArena*, elem: TypeSpec*, count: int) -> TypeSpec*: """构造数组类型:elem[count](count<=0 表示长度未知/动态),失败返回 None""" if elem is None or count < 0: @@ -476,7 +476,7 @@ def NewTypeArray(arena: TypeSpecArena | t.CPtr, elem: TypeSpec*, # NewTypeFunc - 构造函数签名类型(ret + 参数数组 + 变参,驻留) # params:TypeSpec* 连续数组(由调用方预先构造并保证存活);count 个 # ============================================================ -def NewTypeFunc(arena: TypeSpecArena | t.CPtr, ret: TypeSpec*, +def NewTypeFunc(arena: TypeSpecArena*, ret: TypeSpec*, params: sizet*, count: int, is_vararg: int) -> TypeSpec*: """构造函数签名类型,失败返回 None""" @@ -841,7 +841,7 @@ def _text_to_func(text: str, depth: int) -> TypeSpec*: # 静默丢失类型信息);**键文本**装不下 SPEC_TEXT_MAX → 保留实例但放弃去重 # (绝不写入截断键)。 # ============================================================ -def InternSpec(arena: TypeSpecArena | t.CPtr, +def InternSpec(arena: TypeSpecArena*, sp: TypeSpec*) -> TypeSpec*: """按规范文本键驻留 TypeSpec;失败返回 None""" if arena is None or sp is None: @@ -958,7 +958,7 @@ def _spec_clone(sp: TypeSpec*) -> TypeSpec*: # # 仅当符号性实际变化才复制并驻留,否则返回原实例。驻留去重 ⇒ 同「结构+符号」共享一份。 # ============================================================ -def SpecWithSign(arena: TypeSpecArena | t.CPtr, +def SpecWithSign(arena: TypeSpecArena*, sp: TypeSpec*, is_signed: int) -> TypeSpec*: """复制 sp 并覆盖整数符号性,驻留后返回;无变化返回原实例,失败返回 None""" @@ -1008,7 +1008,7 @@ def _spec_set_source_name(sp: TypeSpec*, name: str) -> int: # ============================================================ # SpecWithSource - 复制 Spec 并附上注解侧来源名(独立副本,**不驻留**) # -# 用途(S4 注解侧填 Spec 的「类名块」):`X | t.CPtr` 简化成 Ptr(i8) 后 Spec 里 +# 用途(S4 注解侧填 Spec 的「类名块」):`X*` 简化成 Ptr(i8) 后 Spec 里 # 没有类名,而属性访问/方法分派/结构体查找要靠注解侧名字恢复,故在注解侧把 # 来源名附到 Spec 上(SourceName),供消费点逐步切读(替代 AnnotClassName)。 # @@ -1035,8 +1035,8 @@ def SpecWithSource(sp: TypeSpec*, name: str) -> TypeSpec*: # ============================================================ # SpecWithElemBits - 复制 Spec 并覆盖元素槽位宽(独立副本,**不驻留**) # -# 用途(S4 的 IsPtrElement 替代):`str | t.CPtr` / `bytes | t.CPtr` / -# `T | t.CPtr` / `64 位标量 | t.CPtr` 在 LLVM 层**都是单层 Ptr(i8)** +# 用途(S4 的 IsPtrElement 替代):`str*` / `bytes*` / +# `T*` / `64 位标量 | t.CPtr` 在 LLVM 层**都是单层 Ptr(i8)** # (PtrLevel=1 同时对应两种相反语义),无法据类型区分"1 字节步长"与 # "8 字节槽步长";区分只能靠注解判定 ⇒ 注解侧把元素槽宽覆盖为 8 字节。 # @@ -1146,7 +1146,7 @@ def SpecTypeBits(ty: mlirlite.LLVMType*) -> int: # # 返回 0=已写入 / 1=不适用或失败(调用方显式处置,不静默兜底) # ============================================================ -SPEC_LLVM_TEXT_MAX_DEPTH: t.CDefine = 100 +define SPEC_LLVM_TEXT_MAX_DEPTH = 100 def SpecToLLVMText(sp: TypeSpec*, buf: str, buf_size: sizet) -> int: @@ -1279,7 +1279,7 @@ def _spec_llvm_text(sp: TypeSpec*, buf: str, buf_size: sizet, # # 本函数当前**无调用点**(S2 只入库;接线在后续步骤)。 # ============================================================ -def SpecFromLLVMType(arena: TypeSpecArena | t.CPtr, +def SpecFromLLVMType(arena: TypeSpecArena*, ty: mlirlite.LLVMType*) -> TypeSpec*: """把已解析的 LLVM 类型翻译成 TypeSpec;不支持或为 None 时返回 None""" if arena is None or ty is None: @@ -1305,7 +1305,7 @@ def SpecFromLLVMType(arena: TypeSpecArena | t.CPtr, return None -def _spec_from_ptr(arena: TypeSpecArena | t.CPtr, +def _spec_from_ptr(arena: TypeSpecArena*, pointee: mlirlite.LLVMType*) -> TypeSpec*: """Ptr(pointee) → TypeSpec(PtrLevel/ElemBits/IsElemPtr 由 NewTypePtr 填)""" inner: TypeSpec* = SpecFromLLVMType(arena, pointee) @@ -1314,7 +1314,7 @@ def _spec_from_ptr(arena: TypeSpecArena | t.CPtr, return NewTypePtr(arena, inner) -def _spec_from_array(arena: TypeSpecArena | t.CPtr, +def _spec_from_array(arena: TypeSpecArena*, elem_ty: mlirlite.LLVMType*, count: int) -> TypeSpec*: """[count x elem] → TypeSpec(ArrayCount/ElemBits/IsElemPtr 由 NewTypeArray 填)""" @@ -1324,7 +1324,7 @@ def _spec_from_array(arena: TypeSpecArena | t.CPtr, return NewTypeArray(arena, inner, count) -def _spec_from_func(arena: TypeSpecArena | t.CPtr, +def _spec_from_func(arena: TypeSpecArena*, ret: mlirlite.LLVMType*, params: mlirlite.ParamNode*, pcount: int) -> TypeSpec*: @@ -1354,7 +1354,7 @@ def _spec_from_func(arena: TypeSpecArena | t.CPtr, return NewTypeFunc(arena, ret_s, params_arr, pcount, 0) -def _spec_from_struct(arena: TypeSpecArena | t.CPtr, +def _spec_from_struct(arena: TypeSpecArena*, sname: str) -> TypeSpec*: """有名结构体 → TS_STRUCT + BaseName;匿名结构体 → 无名 TS_STRUCT""" if sname is not None: @@ -1370,7 +1370,7 @@ def _spec_from_struct(arena: TypeSpecArena | t.CPtr, # ============================================================ def SpecSelfCheck() -> int: """TypeSpec 编解码自检,返回 0=通过 / 失败用例号""" - arena: TypeSpecArena | t.CPtr = (TypeSpecArena | t.CPtr)(CompilerFactory.factory.PermPool.alloc(TypeSpecArena.__sizeof__())) + arena: TypeSpecArena* = (TypeSpecArena*)(CompilerFactory.factory.PermPool.alloc(TypeSpecArena.__sizeof__())) if arena is None: return 1 string.memset(arena, 0, TypeSpecArena.__sizeof__()) diff --git a/App/lib/core/Gen/VarGenMixin.vp b/App/lib/core/Gen/VarGenMixin.vp index e5b9ad6..7a509b0 100644 --- a/App/lib/core/Gen/VarGenMixin.vp +++ b/App/lib/core/Gen/VarGenMixin.vp @@ -111,7 +111,7 @@ novirtual class VarGenMixin: [S4] 原 VarEntry.AnnotClassName 字段已删除,注解名统一承载在 Spec.SourceName: - 整数符号性:SpecFromLLVMType 反推恒 TS_INT(LLVM iN 不分符号), 注解名携带真实无符号性(uint32/CUInt32T 等)→ 切 TS_INT→TS_UINT; - - 来源名:`X | t.CPtr` 简化为 Ptr(i8) 后 Spec 里没有类名,附上供 + - 来源名:`X*` 简化为 Ptr(i8) 后 Spec 里没有类名,附上供 属性访问/方法分派恢复(消费点经 var_annot_class_name 读取)。 类型信息缺失(SpecFromLLVMType 不适用致 Spec 为 None)时建 TS_UNKNOWN 承载注解名 —— TS_UNKNOWN 不表态任何具体类型,等价于原来的"Spec 缺失"。 @@ -151,7 +151,7 @@ novirtual class VarGenMixin: return TSpec.SpecSourceName(entry.Spec) # set_var_ptr_element — 标记变量为「指针元素(ptr-element)」语义 - # 注解为 bytes|t.CPtr / str|t.CPtr / T|t.CPtr / 64位标量|t.CPtr 的变量,其 + # 注解为 bytes* / str* / T* / 64位标量|t.CPtr 的变量,其 # LLVM 类型退化为 i8*(Ptr(Int8)),但下标访问应按 8 字节槽步长(i8** 语义), # 而非 1 字节步长(i8* 语义)。 # 该语义由 Spec.ElemBits 承载:上述四类在 LLVM 层都是 Ptr(Int8)(ElemBits=8, @@ -177,7 +177,7 @@ novirtual class VarGenMixin: # var_is_ptr_element - 变量是否「指针元素」语义(Spec.ElemBits 承载) # 判据:PtrLevel>=1 且元素位宽为 8(LLVM 层退化后的 i8*)且 ElemBits==64 # (注解侧覆盖的 8 字节槽)。后两个条件缺一不可:真实 i64* 变量 ElemBits 也为 64 - # 但 Elem.Bits=64,不命中;纯 str/bytes/char|t.CPtr 变量 ElemBits=8,同样不命中。 + # 但 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: @@ -754,7 +754,7 @@ novirtual class VarGenMixin: if pty_chk is None: self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 第 {ai_chk + 1} 个形参的类型 token 不受支持(M3 支持 iN/float/double/i8*)", "TypeError") return None - pty_slot: str | t.CPtr = (str | t.CPtr)(uint64(ptypes) + ai_chk * 8) + pty_slot: str* = (str*)(uint64(ptypes) + ai_chk * 8) pty_slot[0] = pty_chk # ③ 实参:首实参 = 本片段 ctx,其后按签名类型逐个翻译并 coerce head: mlirlite.Value* = ctx_val @@ -767,7 +767,7 @@ novirtual class VarGenMixin: if arg is None: self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话函数 '{func_name}' 的第 {ai + 1} 个实参缺失", "SyntaxError") return None - pty_slot2: str | t.CPtr = (str | t.CPtr)(uint64(ptypes) + ai * 8) + pty_slot2: str* = (str*)(uint64(ptypes) + ai * 8) pty: mlirlite.LLVMType* = (mlirlite.LLVMType*)(pty_slot2[0]) arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, pty) if arg_val is None: @@ -797,7 +797,7 @@ novirtual class VarGenMixin: for pi in range(arg_count): cur_ty: mlirlite.LLVMType* = i8_ptr_ty if pi > 0: - pty_slot3: str | t.CPtr = (str | t.CPtr)(uint64(ptypes) + (pi - 1) * 8) + pty_slot3: str* = (str*)(uint64(ptypes) + (pi - 1) * 8) cur_ty = (mlirlite.LLVMType*)(pty_slot3[0]) pn: mlirlite.ParamNode* = mlirlite.new_param_node(pool, cur_ty) if pn is not None: @@ -831,7 +831,7 @@ novirtual class VarGenMixin: 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, t.CInt64T(off)) + off_val: mlirlite.Value* = mlirlite.const_int64(pool, int64(off)) if off_val is None: return None base: mlirlite.Value* = mlirlite.build_gep(builder, i8_ty, ctx_val, off_val) @@ -1387,7 +1387,7 @@ novirtual class VarGenMixin: node: ast.AST*) -> mlirlite.Value*: """会话变量取址:返回槽地址(Ptr(值类型)) - 值只存一份(宿主持有的 ctx arena)且内联在槽里,故 c.Addr(x) 得到的 + 值只存一份(宿主持有的 ctx arena)且内联在槽里,故 &x 得到的 就是该槽的地址:后续经该指针的读写直接作用于会话变量(地址同一性)。 未登记/未定型/不在片段函数本体返回 None,由调用方继续原有查找与报错路径。 """ diff --git a/App/lib/core/IncludesScanner.vp b/App/lib/core/IncludesScanner.vp index 4dbe297..a521eaf 100644 --- a/App/lib/core/IncludesScanner.vp +++ b/App/lib/core/IncludesScanner.vp @@ -411,7 +411,7 @@ def _TryResolveModuleFile(inc_dir: str, rel_seg: bytes, rel_len: sizet, return 0 string.strcpy(inc_buf, inc_dir) # 写输出槽(stdlib 深拷贝,调用方负责 free) - # 槽联合必须用 (sizet*):t.CPtr|t.CPtr 会被折叠成 t.CPtr, + # 槽联合必须用 (sizet*):t.CPtr* 会被折叠成 t.CPtr, # [0] 变成 1 字节访问 → 指针被截断(0x2e 崩溃根因)。CSizeT 成员为 # 8 字节,写入用 sizet(ptr) 直接转换;读取用 t\.CVoid(u64, t.CPtr) # 转回指针(t\.CVoid 仅配合 t.CPtr 表示 void* 强转)。 diff --git a/App/lib/core/Repl.vp b/App/lib/core/Repl.vp index 1357a91..e8dafec 100644 --- a/App/lib/core/Repl.vp +++ b/App/lib/core/Repl.vp @@ -91,75 +91,75 @@ _perm_pool: memhub.MemBuddy* # ⇒ ≤ 1024)+ 包裹头尾开销 512 ⇒ ≤ 26112。 # 缩进是"块路径"的唯一放大项,故上界必须按"行数上界"而非"行数×行长"估; # 提升行按原文进入模块区(不缩进),其代价低于按 4 空格放大的上界,故不再附加项。 -_REPL_FRAG_SRC_CAP: t.CDefine = 26624 +define _REPL_FRAG_SRC_CAP = 26624 # 提升出的模块级 def 源码缓冲容量(含 NUL):提升行原文 ≤ 8192 + 注入 ≤ 1024 -_REPL_LIFT_CAP: t.CDefine = 12288 +define _REPL_LIFT_CAP = 12288 # 单片段最多提升的会话函数数(≤ GenTypes.REPL_FUNC_CAP;超出 ⇒ 明确报错) -_REPL_LIFT_MAX: t.CDefine = 16 +define _REPL_LIFT_MAX = 16 # 会话函数名长度上限(写入 ReplLiftNames 的槽宽 = 上限 + 1) -_REPL_FN_NAME_MAX: t.CDefine = 64 +define _REPL_FN_NAME_MAX = 64 # 会话函数名表容量(_REPL_LIFT_MAX 个定长槽) -_REPL_FN_NAMES_CAP: t.CDefine = 1024 +define _REPL_FN_NAMES_CAP = 1024 # 诊断显示缓冲(把非 NUL 结尾的行/名字截断后供 %s 打印) -_REPL_DIAG_CAP: t.CDefine = 128 +define _REPL_DIAG_CAP = 128 # 签名渲染缓冲容量("(int, str) -> int" 最长 ≈ 8×(5+2)+8+8 < 96) -_REPL_SIG_TEXT_CAP: t.CDefine = 192 +define _REPL_SIG_TEXT_CAP = 192 # 片段符号名/探针缓冲容量("__repl_frag_" / "llvm.func @(%__repl_ctx__: !llvm.ptr) -> i32") -_REPL_NAME_CAP: t.CDefine = 64 -_REPL_NEEDLE_CAP: t.CDefine = 128 +define _REPL_NAME_CAP = 64 +define _REPL_NEEDLE_CAP = 128 # 临时文件路径缓冲容量(目录/源文件路径) -_REPL_PATH_CAP: t.CDefine = 512 +define _REPL_PATH_CAP = 512 # 完整模块 IR 文本容量(与 App/main.vp IR_BUF_SIZE 一致) -_REPL_IR_CAP: t.CDefine = 262144 +define _REPL_IR_CAP = 262144 # GetTempPathA 输出缓冲容量(MAX_PATH) -_REPL_TMP_CAP: t.CDefine = 260 +define _REPL_TMP_CAP = 260 # 外部命令(clang++ -shared)命令行容量。 # M4 扩容 1024 → 16384:片段链接命令行现在除了宿主 import lib,还要带上**先前 # 片段**的 import lib(每个 ≈ 80~110 字节路径),否则"片段 N 定义的类/方法"在 # 后续片段里是 undefined symbol(见 ReplFragImplibs 段)。 -_REPL_CMD_CAP: t.CDefine = 16384 +define _REPL_CMD_CAP = 16384 # includes 源文件读取缓冲(与 Phase1.SRC_BUF_SIZE / BuildPipeline.SRC_BUF_SIZE 一致) -_REPL_SRC_BUF_CAP: t.CDefine = 1048576 +define _REPL_SRC_BUF_CAP = 1048576 # .vpi 存根缓冲(与 BuildPipeline.PYI_BUF_SIZE 一致) -_REPL_VPI_BUF_CAP: t.CDefine = 262144 +define _REPL_VPI_BUF_CAP = 262144 # ---- M4:会话 sha1 / 片段 import lib / 会话基线(CDefine + CTypedef)---- # 先前片段 import lib 的槽数上限(每个"IR 里出现会话前缀符号"的片段最多一条; # 判据是"出现过"而非"定义过" ⇒ 纯调用片段也会占一个槽,故留足余量) -_REPL_FRAG_IMPLIB_MAX: t.CDefine = 128 +define _REPL_FRAG_IMPLIB_MAX = 128 # 片段 import lib 记录数组容量(槽数 × 8 字节指针) -_REPL_FRAG_IMPLIB_ARR_CAP: t.CDefine = 1024 +define _REPL_FRAG_IMPLIB_ARR_CAP = 1024 # 会话基线(CDefine)条目上限:每片段重建表时按基线回灌 -_REPL_BASE_CDEFINE_MAX: t.CDefine = 512 +define _REPL_BASE_CDEFINE_MAX = 512 # 会话基线(CTypedef)条目上限 -_REPL_BASE_CTYPEDEF_MAX: t.CDefine = 512 +define _REPL_BASE_CTYPEDEF_MAX = 512 # includes 类注册(会话初始化做一次):参与 vpi 注入的模块数上限 -_REPL_INC_CLS_MOD_MAX: t.CDefine = 512 +define _REPL_INC_CLS_MOD_MAX = 512 # includes 类注册的收敛遍数(字段类型依赖同批其它类 ⇒ 多遍收敛) -_REPL_INC_CLS_PASSES: t.CDefine = 3 +define _REPL_INC_CLS_PASSES = 3 # includes 类注册的结构体表水位守卫(STRUCT_MAX = 512;预留余量) -_REPL_INC_CLS_STRUCT_GUARD: t.CDefine = 448 +define _REPL_INC_CLS_STRUCT_GUARD = 448 # includes 类注册的逐模块告警行上限(超出只累计计数,由汇总行给出总数) -_REPL_INC_CLS_WARN_MAX: t.CDefine = 3 +define _REPL_INC_CLS_WARN_MAX = 3 # includes 类注册(会话初始化)的启动时间预算(ms):多遍 vpi 注入 + 逐类布局校验是 # 会话启动的主要耗时,且失败模块会在后续遍重试 ⇒ 模块数 × 遍数的上界虽有限,但 # 上界本身可能很长(缺存根时每模块仍要读一遍 .vpi + 解析 + 注入了 declare)。 # 超预算即停止"启动期注册",剩余模块留待片段 `import` 时按既有 on-demand 路径注册。 # 取舍:宁可让部分 includes 类在启动后仍不可用(且明确告知),也不能让启动"看起来 # 死了"——提示符必须先出现(REPL 可用性 > 启动期注册完整度)。 -_REPL_INC_CLS_BUDGET_MS: t.CDefine = 20000 +define _REPL_INC_CLS_BUDGET_MS = 20000 # includes 类注册用的临时 LLVM 模块名(.vpi 注入的目标模块,会话初始化时一次) -_REPL_INC_MOD_NAME: t.CDefine = "repl_inc_init" +define _REPL_INC_MOD_NAME = "repl_inc_init" # ctx 会话缓冲字节数 = 固定头 64 + 槽数上限 64 × 槽步长 16 #(M3 追加函数指针槽区:+ 函数上限 32 × 槽步长 16 ⇒ 64 + 1024 + 512 = 1600) # 必须与 GenTypes.REPL_CTX_SIZE / REPL_SLOT_BASE / REPL_VAR_CAP / REPL_SLOT_SIZE / # REPL_FUNC_BASE / REPL_FUNC_CAP / REPL_FUNC_SLOT_SIZE 一致 -_REPL_CTX_SIZE: t.CDefine = 1600 +define _REPL_CTX_SIZE = 1600 # 模板工程文件名(--repl 未给 --project 时在 cwd → exe 同目录查找) -_REPL_PROJECT_FILE: t.CDefine = "repl.vpj" +define _REPL_PROJECT_FILE = "repl.vpj" # cwd 候选后缀:GetCurrentDirectoryA 返回值不含结尾分隔符,故须补 '/' -_REPL_PROJECT_SEP_FILE: t.CDefine = "/repl.vpj" +define _REPL_PROJECT_SEP_FILE = "/repl.vpj" # 上述两种后缀的最长长度 + NUL 余量(候选缓冲余量检查用) -_REPL_PROJECT_PROBE_CAP: t.CDefine = 16 +define _REPL_PROJECT_PROBE_CAP = 16 # ============================================================ @@ -175,7 +175,7 @@ novirtual class ReplFloatView: Version: int Kind: int Reserved0: int - F: t.CDouble + F: double # ============================================================ @@ -1998,7 +1998,7 @@ def _repl_entry_sig_text(e: rawptr[GenTypes.ReplFuncEntry]) -> str: # 注册(DLL 加载成功后调用):GetProcAddress(裸名) → 写 ctx 函数指针槽 → 追加/更新表 # 返回 0=成功;1=失败(已打印;调用方按 ReplSavedFuncCount 回滚表水位后放弃本片段) -def _repl_register_session_funcs(h_lib: win32base.HANDLE, frag_no: int, +def _repl_register_session_funcs(h_lib: win32base.HANDLE, frag_no: int, mod: mlirlite.LLVMModule*) -> int: if ReplLiftNameCount <= 0: return 0