diff --git a/App/lib/core/BuildPipeline.vp b/App/lib/core/BuildPipeline.vp index 430bdeb..f141310 100644 --- a/App/lib/core/BuildPipeline.vp +++ b/App/lib/core/BuildPipeline.vp @@ -131,14 +131,20 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy | t.CPtr, file_path: str, tr.ModuleSha1 = sha1_val tr.CurrentPackage = current_package tr._declare_only = declare_only - # P1: 创建 Generator 骨架实例(对象化迁移宿主;暂未接入翻译逻辑, - # 仅验证 Gen/ 模块可被自举编译且构造正确) - gen: GenGenerator.Generator | t.CPtr = mb.alloc(GenGenerator.Generator.__sizeof__()) + # P2: 复用全局 gen 单例(App/main.vp 创建;HandlesType 等旧模块函数经 + # 延迟 import 委托到 gen 方法)。单例未注册时兜底创建(防御直接调用路径)。 + gen: GenGenerator.Generator | t.CPtr = GenGenerator.get_global_gen() if gen is None: - VLogger.error("Generator alloc failed", "GEN") - return None - gen.__before_init__() - gen.__init__(mb) + gen = mb.alloc(GenGenerator.Generator.__sizeof__()) + if gen is None: + VLogger.error("Generator alloc failed", "GEN") + return None + gen.__before_init__() + gen.__init__(mb) + GenGenerator.set_global_gen(gen) + # P2: 注入 HandlesType 模块级单例(委托函数经本地 _g_gen 访问, + # 避免函数体 import 包模块与 Generator 类/模块名歧义) + HandlesType.set_global_gen(gen) # 设置当前文件名(供报错使用) HandlesType.set_current_file(file_path) # 同步到 HandlesImports(import 时 SHA1 检查报错需要当前文件名,循环依赖无法直接读 HandlesType) diff --git a/App/lib/core/Gen/Generator.vp b/App/lib/core/Gen/Generator.vp index 484fa86..86984c0 100644 --- a/App/lib/core/Gen/Generator.vp +++ b/App/lib/core/Gen/Generator.vp @@ -1,30 +1,33 @@ import t, c from stdint import * import memhub +import llvmlite import lib.core.Gen.BaseGenMixin as BaseGenMixin +import lib.core.Gen.TypeGenMixin as TypeGenMixin +import lib.core.Handles.HandlesVar as HandlesVar +import lib.core.Handles.HandlesExprCall as HandlesExprCall # ============================================================ -# Generator - 生成器(P1 骨架) +# Generator - 生成器(P1 骨架 + P2 多继承 Mixin 组合) # -# 对象化重构宿主:单继承 BaseGenMixin(Viper 无多继承先例, -# 采用单继承 Mixin 链:BaseGen → TypeGen → StructGen → ExprGen -# → CallGen → FuncGen → ClassGen → StmtGen → ImportsGen,每层 -# 一个文件,避免 Generator 单文件膨胀)。 +# 对象化重构宿主(wiki/14-oo-refactor.md): +# @t.NoVTable + 多继承(BaseGen 状态 + TypeGen 类型映射),方法沿 +# MRO 直接调用(Viper 多继承已支持,M1-M4)。后续 P3-P6 追加 +# StructGen/ExprGen/CallGen/FuncGen/ClassGen/StmtGen/ImportsGen Mixin。 # -# @t.NoVTable:静态绑定(骨架无多态需求)。若未来需要运行时 -# 多态(如多后端生成器),再改 @t.CVTable。 +# 注意:Viper NoVTable 继承只合并字段、不转发父类方法符号(子类调 +# 父类方法 mangle 成子类名 → undefined reference),因此字段初始化 +# 全部内联,不调用父类 Init* 方法。 # ============================================================ @t.NoVTable -class Generator(BaseGenMixin.BaseGenMixin): - """生成器:对象化迁移的宿主""" +class Generator(BaseGenMixin.BaseGenMixin, TypeGenMixin.TypeGenMixin): + """生成器:多继承 Mixin 组合(对象化迁移宿主)""" def __init__(self, pool: memhub.MemBuddy | t.CPtr): - # 注意:不调用 self.InitBaseGen(Viper NoVTable 继承只合并字段、 - # 不转发父类方法符号,子类调父类方法会 mangle 成子类名 → 链接 - # undefined reference)。字段初始化直接内联。 if self is None: return + # ---- BaseGenMixin 字段 ---- self.Pool = pool self.Module = None self.Builder = None @@ -37,3 +40,44 @@ class Generator(BaseGenMixin.BaseGenMixin): self.CurFunc = None self.CurBuilder = None self.CurClassName = None + # ---- TypeGenMixin 字段 ---- + self.TraceFrames = None + self.TraceCount = 0 + self.TempDir = None + self.GenericTpNames = None + self.GenericTypeArgs = None + self.CDefineNames = None + self.CDefineValues = None + self.CDefineDoubleFlags = None + self.CDefineIsDouble = 0 + self.CDefineFound = 0 + self.CurrentModuleSha1 = None + self.CTypedefNames = None + self.CTypedefTypeStrs = None + self.CTypedefFound = 0 + self.CTypedefResolveDepth = 0 + self.CTypedefVisiting = None + self.CurrentFile = None + self.ConstEvalOk = 0 + + +# ============================================================ +# 全局生成器单例(对象化 P2 兼容层) +# +# 从 Gen/__init__.vp(包)迁入本模块(普通模块):TPC 的模块名注册 +# 只注册"普通模块短名"(如 Generator)与"完整包名"(如 lib.core.Gen), +# 不注册包短名(如 Gen)。HandlesType 等旧模块的函数体 import 若引 +# 用包短名会报 Unknown module,故单例存取放在非包模块,别名用短名。 +# ============================================================ +_g_gen: Generator | t.CPtr = None + + +def set_global_gen(gen: Generator | t.CPtr) -> None: + """注册全局生成器单例(App/main.vp 创建 gen 后调用)""" + global _g_gen + _g_gen = gen + + +def get_global_gen() -> Generator | t.CPtr: + """获取全局生成器单例(未注册返回 None)""" + return _g_gen diff --git a/App/lib/core/Gen/TypeGenMixin.vp b/App/lib/core/Gen/TypeGenMixin.vp new file mode 100644 index 0000000..22eab28 --- /dev/null +++ b/App/lib/core/Gen/TypeGenMixin.vp @@ -0,0 +1,2081 @@ +import t, c +from stdint import * +import ast +import llvmlite +import memhub +import string +import stdio +import sys +import stdlib +import viperlib +import w32.fileio as fileio +import lib.core.VLogger as VLogger +import lib.core.Handles.HandlesTranslator as HT +import lib.core.Handles.HandlesImports as HandlesImports +import lib.core.Handles.HandlesStruct as HandlesStruct +import lib.core.Handles.HandlesType as HandlesType + + +# ============================================================ +# TypeGenMixin - 类型映射与解析 Mixin(对象化 P2,wiki/14-oo-refactor.md) +# +# 从 HandlesType.vp 迁移: +# 全局状态(_g_trace_*/_g_temp_dir/_g_cdefine_*/_g_ctypedef_*/...)→ 本类字段 +# 模块级函数(map_t_type/resolve_annotation_type/...)→ 本类方法 +# +# 迁移原则(P2 阶段,行为零变化): +# 1. 方法保留原函数签名(含 pool 首参),仅函数体内的全局变量改为 self.字段 +# 2. HandlesType.vp 原函数保留为"一行委托":延迟 import Gen 取全局单例 → 调本类方法 +# 3. P4/P5 签名瘦身时再去 pool 参数、改用 self.Pool +# +# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整,无 vtable 开销)。 +# ============================================================ + + +# ============================================================ +# 常量(与 HandlesType 保持一致) +# ============================================================ +TRACE_MAX: t.CDefine = 32 +MAX_CTYPEDEF_DEPTH: t.CDefine = 10 +_SRC_BUF_SIZE: t.CDefine = 262144 + + +# ============================================================ +# TypeGenMixin - 类型映射/注解解析/编译期常量表/错误上报 +# ============================================================ +@t.NoVTable +class TypeGenMixin: + """类型映射与解析 Mixin(状态从 HandlesType 全局变量迁入)""" + + # --- 仿 Python Traceback 调用栈(原 _g_trace_frames/_g_trace_count) --- + TraceFrames: HandlesType.TraceFrame | t.CPtr # malloc 数组(TRACE_MAX 槽) + TraceCount: int + + # --- 全局 temp_dir(原 _g_temp_dir) --- + TempDir: str + + # --- 全局泛型特化上下文(原 _g_generic_tp_names/_g_generic_type_args) --- + GenericTpNames: list[str] | t.CPtr + GenericTypeArgs: list[str] | t.CPtr + + # --- 全局 CDefine 编译期常量表(原 _g_cdefine_*) --- + CDefineNames: list[str] | t.CPtr + CDefineValues: list[str] | t.CPtr + CDefineDoubleFlags: list[int] | t.CPtr + CDefineIsDouble: int + CDefineFound: int + + # --- 当前模块 SHA1(原 _g_current_module_sha1) --- + CurrentModuleSha1: str + + # --- 全局 CTypedef 表(原 _g_ctypedef_*) --- + CTypedefNames: list[str] | t.CPtr + CTypedefTypeStrs: list[str] | t.CPtr + CTypedefFound: int + CTypedefResolveDepth: int + CTypedefVisiting: list[str] | t.CPtr + + # --- 常量整数表达式计算成功标志(原 _g_const_eval_ok) --- + ConstEvalOk: int + + # --- 全局当前文件名(原 _g_current_file) --- + CurrentFile: str + + def InitTypeGen(self) -> int: + """初始化类型 Mixin 字段(子类构造时内联调用,规避 NoVTable 继承符号不转发)""" + if self is None: + return 1 + self.TraceFrames = None + self.TraceCount = 0 + self.TempDir = None + self.GenericTpNames = None + self.GenericTypeArgs = None + self.CDefineNames = None + self.CDefineValues = None + self.CDefineDoubleFlags = None + self.CDefineIsDouble = 0 + self.CDefineFound = 0 + self.CurrentModuleSha1 = None + self.CTypedefNames = None + self.CTypedefTypeStrs = None + self.CTypedefFound = 0 + self.CTypedefResolveDepth = 0 + self.CTypedefVisiting = None + self.ConstEvalOk = 0 + self.CurrentFile = None + return 0 + + # ============================================================ + # P2 迁移方法(函数体来自 HandlesType.vp,全局变量改 self.字段, + # 同模块函数调用改 self.方法;签名与 HandlesType 原函数一致) + # ============================================================ + + def _ensure_trace_init(self) -> int: + """确保调用栈已初始化(懒加载,用 malloc 不依赖 pool)""" + if self.TraceFrames is not None: + return 1 + entry_size: t.CSizeT = HandlesType.TraceFrame.__sizeof__() + self.TraceFrames = stdlib.malloc(entry_size * TRACE_MAX) + if self.TraceFrames is None: + return 0 + string.memset(self.TraceFrames, 0, entry_size * TRACE_MAX) + return 1 + + def _get_trace_frame(self, i: int) -> HandlesType.TraceFrame | t.CPtr: + """获取第 i 个 TraceFrame 槽位""" + if self.TraceFrames is None or i < 0 or i >= TRACE_MAX: + return None + entry_size: t.CSizeT = HandlesType.TraceFrame.__sizeof__() + addr: t.CUInt64T = t.CUInt64T(self.TraceFrames) + i * entry_size + return (HandlesType.TraceFrame | t.CPtr)(t.CVoid(addr, t.CPtr)) + + def push_trace(self, file_name: str, lineno: int, col_start: int = 0, col_end: int = 0): + """压入一个翻译上下文帧(进入新的翻译作用域时调用)""" + if self._ensure_trace_init() == 0: + return + if self.TraceCount >= TRACE_MAX: + return + frame: HandlesType.TraceFrame | t.CPtr = self._get_trace_frame(self.TraceCount) + if frame is None: + return + frame.file_name = file_name + frame.lineno = lineno + frame.col_start = col_start + frame.col_end = col_end + self.TraceCount += 1 + + def pop_trace(self): + """弹出栈顶帧(退出翻译作用域时调用)""" + if self.TraceCount <= 0: + return + self.TraceCount -= 1 + frame: HandlesType.TraceFrame | t.CPtr = self._get_trace_frame(self.TraceCount) + if frame is not None: + frame.file_name = None + frame.lineno = 0 + frame.col_start = 0 + frame.col_end = 0 + + def clear_trace(self): + """清空调用栈(每个文件翻译开始前调用)""" + i: int + for i in range(self.TraceCount): + frame: HandlesType.TraceFrame | t.CPtr = self._get_trace_frame(i) + if frame is not None: + frame.file_name = None + frame.lineno = 0 + frame.col_start = 0 + frame.col_end = 0 + self.TraceCount = 0 + + def set_temp_dir(self, temp_dir: str) -> None: + """设置全局 temp_dir(每个项目编译开始时由 BuildPipeline/Phase1 设置)""" + self.TempDir = temp_dir + + def get_temp_dir(self) -> str: + """获取全局 temp_dir""" + return self.TempDir + + def set_current_module_sha1(self, sha1: str) -> None: + """设置当前正在编译的模块 SHA1(Phase1 在模块开始翻译前调用)""" + self.CurrentModuleSha1 = sha1 + + def _dbg_check_ast_floats(self, mb: memhub.MemBuddy | t.CPtr, + tree: ast.AST | t.CPtr, tag: str): + """CHK-FLOAT: 遍历 AST 检查所有浮点 Constant 节点""" + if tree is None: + return + if tree.kind() == ast.ASTKind.Constant: + cn_f: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(tree) + if cn_f.const_kind == ast.CONST_FLOAT: + fb_chk: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb_chk is not None: + stdio.snprintf(fb_chk, 1024, "[CHK-FLOAT] %s ptr=%p float_val=%.17g", + tag, t.CSizeT(cn_f), cn_f.float_val) + VLogger.info(fb_chk, "CHK") + return + # AnnAssign: value/annotation/target 不在 children 里,单独遍历 + if tree.kind() == ast.ASTKind.AnnAssign: + aa_f: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(tree) + if aa_f.value is not None: + self._dbg_check_ast_floats(mb, aa_f.value, tag) + if aa_f.annotation is not None: + self._dbg_check_ast_floats(mb, aa_f.annotation, tag) + if aa_f.target is not None: + self._dbg_check_ast_floats(mb, aa_f.target, tag) + return + ch_f: list[ast.AST | t.CPtr] | t.CPtr = tree.children + if ch_f is not None: + n_f: t.CSizeT = ch_f.__len__() + i_f: t.CSizeT + for i_f in range(n_f): + c_f: ast.AST | t.CPtr = ch_f.get(i_f) + if c_f is not None: + self._dbg_check_ast_floats(mb, c_f, tag) + + def register_cdefine_constant(self, pool: memhub.MemBuddy | t.CPtr, + name: str, value: int) -> None: + """注册 CDefine 编译期常量到本地表 + + 值以十进制字符串存储。注意:value 是 32 位有符号整数, + 0xFFFFFFFF 会存储为 "-1",lookup 时用 found 标志区分"未找到"和值为 -1。 + """ + if self.CDefineNames is None: + self.CDefineNames = list[str](pool, 64) + self.CDefineValues = list[str](pool, 64) + self.CDefineDoubleFlags = list[int](pool, 64) + self.CDefineNames.append(name) + val_buf: str = pool.alloc(32) + if val_buf is not None: + viperlib.snprintf(val_buf, 32, "%d", value) + self.CDefineValues.append(val_buf) + else: + self.CDefineValues.append("0") + if self.CDefineDoubleFlags is not None: + self.CDefineDoubleFlags.append(0) + + def register_cdefine_double(self, pool: memhub.MemBuddy | t.CPtr, + name: str, value: double) -> None: + """注册浮点 CDefine 编译期常量(如 U_M_PI: t.CDefine = 3.14159...) + + 值以 %f 文本存储并标记浮点,供 translate_value 返回浮点常量。 + """ + if self.CDefineNames is None: + self.CDefineNames = list[str](pool, 64) + self.CDefineValues = list[str](pool, 64) + self.CDefineDoubleFlags = list[int](pool, 64) + self.CDefineNames.append(name) + val_buf: str = pool.alloc(32) + if val_buf is not None: + # 用 CRT stdio.snprintf 而非 viperlib.snprintf:viperlib 自实现格式化器的 + # %g 浮点路径有 bug(%.17g 输出错误值,如 pi 显示 3.1397985 而非 3.1415926, + # 位模式 %a 正确),会导致 CDefine 表存错文本 → lookup 生成错 LLVM 常量。 + stdio.snprintf(val_buf, 32, "%.17g", value) + self.CDefineValues.append(val_buf) + else: + self.CDefineValues.append("0") + if self.CDefineDoubleFlags is not None: + self.CDefineDoubleFlags.append(1) + # CDEF-DBG: 打印注册的浮点 CDefine(定位 llc ret i32 0) + fb_cd: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb_cd is not None: + stdio.snprintf(fb_cd, 1024, "REG-D: %s = %.17g (buf=%s)", + name, value, val_buf if val_buf is not None else "(null)") + VLogger.info(fb_cd, "CDEF-DBG") + + def lookup_cdefine_constant(self, name: str) -> int: + """查找 CDefine 编译期常量 + + 返回找到的值。由于 -1 是合法值(如 INVALID_HANDLE_VALUE=0xFFFFFFFF=-1), + 用全局 _g_cdefine_found 标志区分"未找到"和值为 -1。 + 调用方应在调用后检查 _g_cdefine_found。 + 浮点 CDefine 项返回整数部分(与 _g_cdefine_is_double 标志配合)。 + """ + self.CDefineFound = 0 + self.CDefineIsDouble = 0 + if self.CDefineNames is None: + return 0 + n: t.CSizeT = self.CDefineNames.__len__() + i: t.CSizeT + for i in range(n): + nm: str = self.CDefineNames.get(i) + if nm is not None and string.strcmp(nm, name) == 0: + val_str: str = self.CDefineValues.get(i) + if val_str is not None: + self.CDefineFound = 1 + if self.CDefineDoubleFlags is not None and self.CDefineDoubleFlags.get(i) == 1: + self.CDefineIsDouble = 1 + return string.atoi(val_str) + return string.atoi(val_str) + return 0 + + def lookup_cdefine_double(self, name: str) -> double: + """查找 CDefine 编译期常量,返回 double 值(浮点/整数统一) + + 与 lookup_cdefine_constant 共享 _g_cdefine_found / _g_cdefine_is_double + (found=1 且 is_double=1 → 浮点 CDefine,应返回浮点常量)。 + """ + self.CDefineFound = 0 + self.CDefineIsDouble = 0 + if self.CDefineNames is None: + return 0.0 + n: t.CSizeT = self.CDefineNames.__len__() + i: t.CSizeT + for i in range(n): + nm: str = self.CDefineNames.get(i) + if nm is not None and string.strcmp(nm, name) == 0: + val_str: str = self.CDefineValues.get(i) + if val_str is not None: + self.CDefineFound = 1 + if self.CDefineDoubleFlags is not None and self.CDefineDoubleFlags.get(i) == 1: + self.CDefineIsDouble = 1 + ret_d: double = string.atof(val_str) + # CDEF-DBG: 打印浮点查找命中 + fb_cd: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb_cd is not None: + stdio.snprintf(fb_cd, 1024, "LOOKUP-D: %s -> buf=%s atof=%.17g", name, val_str, ret_d) + VLogger.info(fb_cd, "CDEF-DBG") + return ret_d + ret_i2: double = double(string.atoi(val_str)) + # CDEF-DBG: 打印整数查找命中 + fb_cd: t.CChar | t.CPtr = VLogger.fmt_buf() + if fb_cd is not None: + viperlib.snprintf(fb_cd, 1024, "LOOKUP-I: %s -> buf=%s atoi=%d", name, val_str, string.atoi(val_str)) + VLogger.info(fb_cd, "CDEF-DBG") + return ret_i2 + return 0.0 + + def is_cdefine_double(self) -> int: + """检查最近一次 CDefine 查找命中的是否是浮点常量""" + return self.CDefineIsDouble + + def is_cdefine_found(self) -> int: + """检查上次 lookup_cdefine_constant 是否找到值""" + return self.CDefineFound + + def set_cdefine_found(self, val: int) -> None: + """设置 cdefine_found 标志(供跨模块查找函数使用)""" + self.CDefineFound = val + + def clear_cdefine_constants(self) -> None: + """清空 CDefine 常量表(模块切换时调用)""" + self.CDefineNames = None + self.CDefineValues = None + self.CDefineDoubleFlags = None + + def register_ctypedef(self, pool: memhub.MemBuddy | t.CPtr, + name: str, type_str: str) -> None: + """注册 CTypedef 到本地表 + + Args: + pool: 内存池 + name: CTypedef 名称(如 "HANDLE") + type_str: 类型表达式字符串(如 "VOIDPTR" 或 "t.CVoid | t.CPtr") + """ + if name is None or type_str is None or pool is None: + return + if self.CTypedefNames is None: + self.CTypedefNames = list[str](pool, 64) + self.CTypedefTypeStrs = list[str](pool, 64) + # 去重:若已存在同名 CTypedef,更新其类型字符串 + if self.CTypedefNames is not None: + exist_n: t.CSizeT = self.CTypedefNames.__len__() + ei: t.CSizeT + for ei in range(exist_n): + en: str = self.CTypedefNames.get(ei) + if en is not None and string.strcmp(en, name) == 0: + # 已存在,更新类型字符串 + self.CTypedefTypeStrs.set(ei, type_str) + return + self.CTypedefNames.append(name) + self.CTypedefTypeStrs.append(type_str) + + def lookup_ctypedef(self, name: str) -> str: + """查找 CTypedef,返回类型表达式字符串 + + 返回找到的类型表达式字符串,未找到返回 None。 + 调用方应在调用后检查 _g_ctypedef_found 标志区分"未找到"和"空字符串"。 + """ + self.CTypedefFound = 0 + if name is None: + return None + if self.CTypedefNames is None: + return None + n: t.CSizeT = self.CTypedefNames.__len__() + i: t.CSizeT + for i in range(n): + nm: str = self.CTypedefNames.get(i) + if nm is not None and string.strcmp(nm, name) == 0: + ts: str = self.CTypedefTypeStrs.get(i) + self.CTypedefFound = 1 + return ts + return None + + def is_ctypedef_found(self) -> int: + """检查上次 lookup_ctypedef 是否找到值""" + return self.CTypedefFound + + def clear_ctypedefs(self) -> None: + """清空 CTypedef 表(模块切换时调用)""" + self.CTypedefNames = None + self.CTypedefTypeStrs = None + self.CTypedefResolveDepth = 0 + self.CTypedefVisiting = None + + def _ctypedef_push_visiting(self, pool: memhub.MemBuddy | t.CPtr, name: str) -> int: + """将 CTypedef 名加入正在解析列表(循环检测) + + Returns: + 0=成功加入(无循环),1=检测到循环 + """ + if name is None: + return 0 + if self.CTypedefVisiting is None: + self.CTypedefVisiting = list[str](pool, 32) + if self.CTypedefVisiting is None: + return 0 + vn: t.CSizeT = self.CTypedefVisiting.__len__() + vi: t.CSizeT + for vi in range(vn): + vs: str = self.CTypedefVisiting.get(vi) + if vs is not None and string.strcmp(vs, name) == 0: + return 1 # 循环检测 + self.CTypedefVisiting.append(name) + return 0 + + def _ctypedef_pop_visiting(self) -> None: + """从正在解析列表弹出最后一个 CTypedef 名""" + if self.CTypedefVisiting is None: + return + vn: t.CSizeT = self.CTypedefVisiting.__len__() + if vn > 0: + self.CTypedefVisiting.pop() + + def _is_ctypedef_annotation(self, annotation: ast.AST | t.CPtr) -> int: + """检测类型注解是否为 t.CTypedef + + Args: + annotation: 类型注解 AST 节点 + + Returns: + 1=是 t.CTypedef,0=否 + """ + if annotation is None: + return 0 + if annotation.kind() != ast.ASTKind.Attribute: + return 0 + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annotation) + if at.attr is None: + return 0 + if string.strcmp(at.attr, "CTypedef") != 0: + return 0 + if at.value is None or at.value.kind() != ast.ASTKind.Name: + return 0 + mod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) + if mod_nm.id is None: + return 0 + if string.strcmp(mod_nm.id, "t") != 0: + return 0 + return 1 + + def ScanCTypedefDeclarations(self, pool: memhub.MemBuddy | t.CPtr, + tree: ast.AST | t.CPtr) -> int: + """扫描 AST 顶层节点,注册所有 NAME: t.CTypedef = Type 声明 + + 在 _translate_module_level 中、模块级变量预注册之前调用, + 确保 CTypedef 名称在类型解析时可用。 + + Args: + pool: 内存池 + tree: 模块 AST 根节点 + + Returns: + 注册的 CTypedef 数量 + """ + if pool is None or tree is None: + return 0 + ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children + if ch is None: + return 0 + n: t.CSizeT = ch.__len__() + count: int = 0 + i: t.CSizeT + for i in range(n): + child: ast.AST | t.CPtr = ch.get(i) + if child is None: + continue + if child.kind() != ast.ASTKind.AnnAssign: + continue + aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(child) + # 检测注解是否为 t.CTypedef + if self._is_ctypedef_annotation(aa.annotation) == 0: + continue + # 提取目标名称(必须是 Name 节点) + if aa.target is None or aa.target.kind() != ast.ASTKind.Name: + continue + tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target) + if tgt.id is None: + continue + # 提取类型表达式字符串(从 value AST 节点) + if aa.value is None: + continue + type_str: str = self._get_type_name_from_annotation(pool, aa.value) + if type_str is None: + continue + # 注册 CTypedef + self.register_ctypedef(pool, tgt.id, type_str) + count += 1 + return count + + def _eval_const_int_expr(self, node: ast.AST | t.CPtr) -> int: + """递归计算常量整数表达式""" + if node is None: + self.ConstEvalOk = 0 + return 0 + k: int = node.kind() + + # Constant: 整数字面量 + if k == ast.ASTKind.Constant: + cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) + if cn.const_kind == ast.CONST_INT: + self.ConstEvalOk = 1 + return cn.int_val + self.ConstEvalOk = 0 + return 0 + + # Name: CDefine 常量名 + if k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) + if nm.id is None: + self.ConstEvalOk = 0 + return 0 + val: int = self.lookup_cdefine_constant(nm.id) + if self.is_cdefine_found() == 0: + self.ConstEvalOk = 0 + return 0 + self.ConstEvalOk = 1 + return val + + # BinOp: 算术/位运算 + if k == ast.ASTKind.BinOp: + bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) + # 递归计算左操作数 + lv: int = self._eval_const_int_expr(bop.left) + if self.ConstEvalOk == 0: + return 0 + # 递归计算右操作数 + rv: int = self._eval_const_int_expr(bop.right) + if self.ConstEvalOk == 0: + return 0 + # 根据运算符执行计算 + if bop.op == ast.OpKind.Add: + self.ConstEvalOk = 1 + return lv + rv + if bop.op == ast.OpKind.Sub: + self.ConstEvalOk = 1 + return lv - rv + if bop.op == ast.OpKind.Mult: + self.ConstEvalOk = 1 + return lv * rv + if bop.op == ast.OpKind.FloorDiv: + if rv == 0: + self.ConstEvalOk = 0 + return 0 + self.ConstEvalOk = 1 + return lv // rv + if bop.op == ast.OpKind.BitOr: + self.ConstEvalOk = 1 + return lv | rv + if bop.op == ast.OpKind.BitAnd: + self.ConstEvalOk = 1 + return lv & rv + # 不支持的运算符 + self.ConstEvalOk = 0 + return 0 + + # 不支持的节点类型 + self.ConstEvalOk = 0 + return 0 + + def set_generic_context(self, tp_names: list[str] | t.CPtr, + type_args: list[str] | t.CPtr): + """设置泛型特化上下文(进入泛型类方法体翻译时调用)""" + self.GenericTpNames = tp_names + self.GenericTypeArgs = type_args + + def clear_generic_context(self): + """清除泛型特化上下文(离开泛型类方法体翻译时调用)""" + self.GenericTpNames = None + self.GenericTypeArgs = None + + def resolve_generic_type_name(self, name: str) -> str: + """如果 name 是泛型类型参数,返回对应的具体类型名;否则返回 name 本身 + + 用于表达式中的 T 替换(如 T.__sizeof__() → int.__sizeof__()) + """ + if name is None: + return name + if self.GenericTpNames is not None and self.GenericTypeArgs is not None: + rg_n: t.CSizeT = self.GenericTpNames.__len__() + rg_i: t.CSizeT + for rg_i in range(rg_n): + rg_tpn: str = self.GenericTpNames.get(rg_i) + if rg_tpn is not None and string.strcmp(name, rg_tpn) == 0: + rg_ta: str = self.GenericTypeArgs.get(rg_i) + if rg_ta is not None: + return rg_ta + return name + + def _get_type_name_from_annotation(self, pool: memhub.MemBuddy | t.CPtr, + node: ast.AST | t.CPtr) -> str: + """从类型注解节点提取类型名(支持 Name/Attribute/BinOp)""" + if node is None: + return None + k: int = node.kind() + # Constant: 字符串注解,直接返回字符串值 + if k == ast.ASTKind.Constant: + cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) + if cn.const_kind == ast.CONST_STR and cn.str_val is not None: + return cn.str_val + return None + # Name: 直接返回 id(泛型特化上下文内先做 T 替换,避免 ndarray[T] 中 T 未解析 + # 导致 _specialize_generic_class("ndarray", ["T"]) 二次递归崩溃) + if k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) + return self.resolve_generic_type_name(nm.id) + # Attribute: 构造 "module.attr" 格式 + if k == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) + if at.attr is None: + return None + if at.value is not None and at.value.kind() == ast.ASTKind.Name: + mod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) + if mod_nm.id is not None: + total: t.CSizeT = string.strlen(mod_nm.id) + 1 + string.strlen(at.attr) + 1 + buf: str = pool.alloc(total) + if buf is not None: + buf[0] = '\0' + string.strcat(buf, mod_nm.id) + string.strcat(buf, ".") + string.strcat(buf, at.attr) + return buf + return at.attr + # BinOp (BitOr): 构造 "left|right" 格式 + if k == ast.ASTKind.BinOp: + bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) + if bop.op == ast.OpKind.BitOr: + left_str: str = self._get_type_name_from_annotation(pool, bop.left) + right_str: str = self._get_type_name_from_annotation(pool, bop.right) + if left_str is not None and right_str is not None: + total2: t.CSizeT = string.strlen(left_str) + 1 + string.strlen(right_str) + 1 + buf2: str = pool.alloc(total2) + if buf2 is not None: + buf2[0] = '\0' + string.strcat(buf2, left_str) + string.strcat(buf2, "|") + string.strcat(buf2, right_str) + return buf2 + return None + return None + + def _parse_type_string(self, pool: memhub.MemBuddy | t.CPtr, + type_str: str, + ctx: t.CInt) -> ast.AST | t.CPtr: + """将类型名字符串解析为 AST 节点 + + 正确处理 '|' 与 '.' 周围的空格(如 "ParsedArgs | t.CPtr"): + - '|' 分割后左段可能带尾随空格("ParsedArgs "),右段可能带前导空格(" t.CPtr") + - 段内空格会导致 Name.id 带空格("ParsedArgs "、" t"),结构体/模块按名查找失败, + 最终退化 i8*/i32,如 parse_args -> "ParsedArgs | t.CPtr" 解析出垃圾类型。 + """ + if type_str is None or pool is None: + return None + + # 跳过前导空格('|' 分割后的右段可能带前导空格) + while type_str[0] == ' ': + type_str += 1 + + seg_len: t.CSizeT = string.strlen(type_str) + # 去除段尾随空格('|' 分割后的左段可能带尾随空格) + while seg_len > 0 and type_str[seg_len - 1] == ' ': + seg_len -= 1 + + # 检查是否包含 | (BinOp):只在有效段 [0, seg_len) 内查找 + pipe_idx: t.CSizeT = seg_len + pi: t.CSizeT = 0 + while pi < seg_len: + if type_str[pi] == '|': + pipe_idx = pi + break + pi += 1 + if pipe_idx < seg_len: + # 左段复制到独立缓冲(trim 尾随空格),不破坏原字符串 + left_len: t.CSizeT = pipe_idx + while left_len > 0 and type_str[left_len - 1] == ' ': + left_len -= 1 + left_buf: bytes = stdlib.malloc(left_len + 1) + if left_buf is None: + return None + string.strncpy(left_buf, type_str, left_len) + left_buf[left_len] = '\0' + left_node: ast.AST | t.CPtr = self._parse_type_string(pool, left_buf, ctx) + # 右段前导空格由递归入口跳过 + right_node: ast.AST | t.CPtr = self._parse_type_string( + pool, type_str + pipe_idx + 1, ctx) + stdlib.free(left_buf) + if left_node is not None and right_node is not None: + return ast.BinOp(pool, left_node, ast.OpKind.BitOr, right_node) + return None + + # 检查是否包含 . (Attribute):只在有效段 [0, seg_len) 内查找 + dot_idx: t.CSizeT = seg_len + di: t.CSizeT = 0 + while di < seg_len: + if type_str[di] == '.': + dot_idx = di + break + di += 1 + if dot_idx < seg_len: + # 模块名段 trim 尾随空格 + mod_len: t.CSizeT = dot_idx + while mod_len > 0 and type_str[mod_len - 1] == ' ': + mod_len -= 1 + mod_buf: bytes = stdlib.malloc(mod_len + 1) + if mod_buf is None: + return None + string.strncpy(mod_buf, type_str, mod_len) + mod_buf[mod_len] = '\0' + module_node: ast.AST | t.CPtr = ast.Name(pool, mod_buf, ctx) + # attr 段 trim 尾随空格 + attr_str: str = type_str + dot_idx + 1 + attr_len: t.CSizeT = string.strlen(attr_str) + while attr_len > 0 and attr_str[attr_len - 1] == ' ': + attr_len -= 1 + attr_buf: bytes = stdlib.malloc(attr_len + 1) + if attr_buf is None: + stdlib.free(mod_buf) + return None + string.strncpy(attr_buf, attr_str, attr_len) + attr_buf[attr_len] = '\0' + attr_node: ast.AST | t.CPtr = ast.Attribute(pool, module_node, attr_buf, ctx) + stdlib.free(mod_buf) + stdlib.free(attr_buf) + return attr_node + + # 普通 Name(trim 尾随空格,ast.Name 内部 _copy_str 复制) + name_buf: bytes = stdlib.malloc(seg_len + 1) + if name_buf is None: + return None + string.strncpy(name_buf, type_str, seg_len) + name_buf[seg_len] = '\0' + name_node: ast.AST | t.CPtr = ast.Name(pool, name_buf, ctx) + stdlib.free(name_buf) + return name_node + + def set_current_file(self, file_path: str): + """设置当前编译的文件名(供报错使用)""" + self.CurrentFile = file_path + + def get_current_file(self) -> str: + """获取当前编译的文件名(供报错归因使用)""" + return self.CurrentFile + + def _read_source_line(self, file_path: str, lineno: int) -> str: + """从源文件读取第 lineno 行内容""" + if file_path is None or lineno <= 0: + return None + f: fileio.File | t.CPtr = fileio.File(file_path, fileio.MODE.R) + if f.closed: + return None + buf: bytes = stdlib.malloc(_SRC_BUF_SIZE) + if buf is None: + f.close() + return None + bytes_read: LONG = f.read_all(buf, _SRC_BUF_SIZE) + f.close() + if bytes_read <= 0: + stdlib.free(buf) + return None + # 逐行查找第 lineno 行 + cur_line: int = 1 + line_start: t.CSizeT = 0 + for i in range(bytes_read): + if buf[i] == '\n': + if cur_line == lineno: + line_len: t.CSizeT = i - line_start + if line_len > 0 and buf[line_start + line_len - 1] == '\r': + line_len -= 1 + line_buf: bytes = stdlib.malloc(line_len + 1) + if line_buf is not None: + string.strncpy(line_buf, buf + line_start, line_len) + line_buf[line_len] = '\0' + stdlib.free(buf) + return line_buf + stdlib.free(buf) + return None + cur_line += 1 + line_start = i + 1 + stdlib.free(buf) + return None + + def read_source_line(self, file_path: str, lineno: int) -> str: + """公开包装:从源文件读取第 lineno 行内容(供 traceback 展示)""" + return self._read_source_line(file_path, lineno) + + def dump_parse_traceback(self, file_path: str): + """解析失败时以 Python 风格输出 traceback(仿 fatal_error)""" + err_line: int = ast.get_parse_err_line() + err_col: int = ast.get_parse_err_col() + err_msg: str = ast.get_parse_err_msg() + stdio.printf("Traceback (most recent call last):\n") + if file_path is None or file_path[0] == 0: + file_path = "" + if err_line > 0: + stdio.printf(' File "%s", line %d\n', file_path, err_line) + src: str = self._read_source_line(file_path, err_line) + if src is not None: + stdio.printf(" %s\n", src) + # 列标记:在出错 token 起始列下方标 ^(parser 的 col_offset 是 0-based, + # 前缀 4 空格 + err_col 个空格后落点恰好是该 token 首字符) + if err_col > 0: + stdio.printf(" ") + c: int + for c in range(err_col): + stdio.printf(" ") + stdio.printf("^\n") + stdlib.free(src) + else: + stdio.printf(' File "%s"\n', file_path) + if err_msg is None or err_msg[0] == 0: + err_msg = "语法错误" + stdio.printf("SyntaxError: %s\n", err_msg) + + def fatal_error(self, node: ast.AST | t.CPtr, msg: str, + err_type: str = "SyntaxError", + col_start: int = 0, col_end: int = 0): + """以 Python 风格报错并退出(支持多帧、错误类型、列范围) + + 向后兼容:err_type/col_start/col_end 有默认值,旧调用 fatal_error(node, msg) 仍可用。 + """ + stdio.printf("Traceback (most recent call last):\n") + # 输出调用栈帧(从底到顶) + i: int + for i in range(self.TraceCount): + frame: HandlesType.TraceFrame | t.CPtr = self._get_trace_frame(i) + if frame is not None and frame.file_name is not None: + if frame.lineno > 0: + stdio.printf(' File "%s", line %d\n', frame.file_name, frame.lineno) + src: str = self._read_source_line(frame.file_name, frame.lineno) + if src is not None: + stdio.printf(" %s\n", src) + stdlib.free(src) + else: + stdio.printf(' File "%s"\n', frame.file_name) + # 输出当前帧(node 对应的位置) + lineno: int = 0 + if node is not None: + lineno = node.lineno + file_name: str = self.CurrentFile + if file_name is None: + file_name = "" + # 行号合理性防御:先读取该行源码,验证 node.lineno 是否落在当前文件内。 + # 若读不到(文件不存在或行号超出范围),说明文件/行号归属不可信 + # (如 AST 树被内存复用/串扰后跨文件报错),打印警告而非误导性行号。 + src_line: str = None + line_ok: int = 1 + if lineno > 0 and string.strcmp(file_name, "") != 0: + src_line = self._read_source_line(file_name, lineno) + if src_line is None: + line_ok = 0 + if line_ok == 0: + stdio.printf(' File "%s", line %d (!! 无法读取该行源码:文件不存在或行号超出范围,错误可能来自被复用的 AST 树,请以错误消息为准)\n', + file_name, lineno) + else: + stdio.printf(' File "%s", line %d\n', file_name, lineno) + if src_line is not None: + stdio.printf(" %s\n", src_line) + # 列范围标记:在源代码行下方用 ^ 标记出错范围 + if col_start > 0 and col_end >= col_start: + stdio.printf(" ") + j: int + for j in range(col_end): + if j >= col_start - 1 and j < col_end: + stdio.printf("^") + else: + stdio.printf(" ") + stdio.printf("\n") + stdlib.free(src_line) + # 输出错误类型 + 消息 + if err_type is None or err_type[0] == 0: + err_type = "SyntaxError" + stdio.printf("%s: %s\n", err_type, msg) + sys.exit(1) + + def fatal_type_error(self, node: ast.AST | t.CPtr, msg: str, + col_start: int = 0, col_end: int = 0): + """以 Python 风格报错并退出(TypeError 版本)""" + self.fatal_error(node, msg, "TypeError", col_start, col_end) + + def try_extract_callable_ret(self, pool: memhub.MemBuddy | t.CPtr, + annot: ast.AST | t.CPtr, + imported_modules: str, + from_imports: str, + trans: HT.Translator | t.CPtr) -> llvmlite.LLVMType | t.CPtr: + """提取 t.Callable 注解的返回类型 LLVMType;非 Callable 注解返回 None""" + if annot is None or annot.kind() != ast.ASTKind.Subscript: + return None + sub_cr: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(annot) + if sub_cr.value is None or sub_cr.value.kind() != ast.ASTKind.Attribute: + return None + at_cr: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(sub_cr.value) + if at_cr.attr is None or string.strcmp(at_cr.attr, "Callable") != 0: + return None + # slice 必须是 Tuple(elts=[args_list, ret_node]) + if sub_cr.slice is None or sub_cr.slice.kind() != ast.ASTKind.Tuple: + return None + tp_cr: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(sub_cr.slice) + if tp_cr.elts is None or tp_cr.elts.__len__() != 2: + return None + ret_node_cr: ast.AST | t.CPtr = tp_cr.elts.get(1) + if ret_node_cr is None: + return None + return self.resolve_annotation_type(pool, ret_node_cr, imported_modules, from_imports, trans) + + def map_t_type(self, pool: memhub.MemBuddy | t.CPtr, + type_name: str) -> llvmlite.LLVMType | t.CPtr: + """将 t.CXxx / c.CXxx 类型名映射到 LLVMType + + 注意: t.CChar | t.CPtr = i8* = str = bytes + """ + if type_name is None: + return None + + # 基本整数类型 + if string.strcmp(type_name, "CInt") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(type_name, "CChar") == 0: + return llvmlite.Int8(pool) + elif string.strcmp(type_name, "CShort") == 0: + return llvmlite.Int16(pool) + elif string.strcmp(type_name, "CLong") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "CLongLong") == 0: + return llvmlite.Int64(pool) + # 精确宽度有符号类型 + elif string.strcmp(type_name, "CInt8T") == 0: + return llvmlite.Int8(pool) + elif string.strcmp(type_name, "CInt16T") == 0: + return llvmlite.Int16(pool) + elif string.strcmp(type_name, "CInt32T") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(type_name, "CInt64T") == 0: + return llvmlite.Int64(pool) + # 精确宽度无符号类型 + elif string.strcmp(type_name, "CUInt8T") == 0: + return llvmlite.Int8(pool) + elif string.strcmp(type_name, "CUInt16T") == 0: + return llvmlite.Int16(pool) + elif string.strcmp(type_name, "CUInt32T") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(type_name, "CUInt64T") == 0: + return llvmlite.Int64(pool) + # 浮点类型 + elif string.strcmp(type_name, "CFloat") == 0: + return llvmlite.Float(pool) + elif string.strcmp(type_name, "CDouble") == 0: + return llvmlite.Double(pool) + # 精确宽度浮点类型(t.py 的 float_map: 8/16→half, 32→float, 64→double, 128→fp128) + elif string.strcmp(type_name, "CFloat8T") == 0: + return llvmlite.Half(pool) + elif string.strcmp(type_name, "CFloat16T") == 0: + return llvmlite.Half(pool) + elif string.strcmp(type_name, "CFloat32T") == 0: + return llvmlite.Float(pool) + elif string.strcmp(type_name, "CFloat64T") == 0: + return llvmlite.Double(pool) + elif string.strcmp(type_name, "CFloat128T") == 0: + return llvmlite.FP128(pool) + # 指针/void: t.CPtr = i8*, t.CChar | t.CPtr = i8* = str = bytes + elif string.strcmp(type_name, "CPtr") == 0: + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + elif string.strcmp(type_name, "CVoid") == 0: + return llvmlite.Void(pool) + # CNeedPtr/CAutoPtr: 参数自动取地址标记,LLVM 层均为通用指针 i8*。 + # (TPC 中二者继承 CPtr;TPV 未实现调用点自动取地址,非指针实参应在调用点报错, + # 而非静默降级为 i32 导致指针截断。) + elif string.strcmp(type_name, "CNeedPtr") == 0: + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + elif string.strcmp(type_name, "CAutoPtr") == 0: + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + # 无符号修饰 + elif string.strcmp(type_name, "CUnsigned") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(type_name, "CUnsignedInt") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(type_name, "CUnsignedChar") == 0: + return llvmlite.Int8(pool) + elif string.strcmp(type_name, "CUnsignedShort") == 0: + return llvmlite.Int16(pool) + elif string.strcmp(type_name, "CUnsignedLong") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "CUnsignedLongLong") == 0: + return llvmlite.Int64(pool) + # size_t / ptr 类型 + elif string.strcmp(type_name, "CSizeT") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "CIntPtrT") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "CUIntPtrT") == 0: + return llvmlite.Int64(pool) + # bool + elif string.strcmp(type_name, "CBool") == 0: + # bool = t.CBool = i1(LLVM 1 位整数,语义与 C _Bool 一致) + return llvmlite.Int1(pool) + # ptrdiff_t + elif string.strcmp(type_name, "CPtrDiffT") == 0: + return llvmlite.Int64(pool) + + # ============================================================ + # stdint.py 大写别名(Win32/TransPyC 风格) + # ============================================================ + # 整数类型 + elif string.strcmp(type_name, "INT") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(type_name, "BOOL") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(type_name, "UINT") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(type_name, "BYTE") == 0: + return llvmlite.Int8(pool) + elif string.strcmp(type_name, "WORD") == 0: + return llvmlite.Int16(pool) + elif string.strcmp(type_name, "DWORD") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(type_name, "QWORD") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "TCHAR") == 0: + return llvmlite.Int8(pool) + elif string.strcmp(type_name, "VOID") == 0: + return llvmlite.Void(pool) + elif string.strcmp(type_name, "SHORT") == 0: + return llvmlite.Int16(pool) + elif string.strcmp(type_name, "USHORT") == 0: + return llvmlite.Int16(pool) + elif string.strcmp(type_name, "LONGLONG") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "ULONGLONG") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "LONG") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "ULONG") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "WCHAR") == 0: + return llvmlite.Int16(pool) + elif string.strcmp(type_name, "FLOAT") == 0: + return llvmlite.Float(pool) + elif string.strcmp(type_name, "DOUBLE") == 0: + return llvmlite.Double(pool) + # 小写裸名浮点类型(float = t.CFloat = f32, double = t.CDouble = f64) + elif string.strcmp(type_name, "float") == 0: + return llvmlite.Float(pool) + elif string.strcmp(type_name, "double") == 0: + return llvmlite.Double(pool) + elif string.strcmp(type_name, "FSIZE_t") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(type_name, "LBA_t") == 0: + return llvmlite.Int32(pool) + # 定长整数 + elif string.strcmp(type_name, "INT8") == 0: + return llvmlite.Int8(pool) + elif string.strcmp(type_name, "INT16") == 0: + return llvmlite.Int16(pool) + elif string.strcmp(type_name, "INT32") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(type_name, "INT64") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "UINT8") == 0: + return llvmlite.Int8(pool) + elif string.strcmp(type_name, "UINT16") == 0: + return llvmlite.Int16(pool) + elif string.strcmp(type_name, "UINT32") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(type_name, "UINT64") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "CHAR8") == 0: + return llvmlite.Int8(pool) + elif string.strcmp(type_name, "CHAR16") == 0: + return llvmlite.Int16(pool) + elif string.strcmp(type_name, "CHAR32") == 0: + return llvmlite.Int32(pool) + # 小写简写 + elif string.strcmp(type_name, "i8") == 0: + return llvmlite.Int8(pool) + elif string.strcmp(type_name, "i16") == 0: + return llvmlite.Int16(pool) + elif string.strcmp(type_name, "i32") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(type_name, "i64") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "u8") == 0: + return llvmlite.Int8(pool) + elif string.strcmp(type_name, "u16") == 0: + return llvmlite.Int16(pool) + elif string.strcmp(type_name, "u32") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(type_name, "u64") == 0: + return llvmlite.Int64(pool) + # size_t 系列 + elif string.strcmp(type_name, "SIZE_T") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "SSIZE_T") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "PTRDIFF_T") == 0: + return llvmlite.Int64(pool) + + # stdint 指针类型(XxxPTR = XxxType | t.CPtr) + elif string.strcmp(type_name, "INTPTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int32(pool)) + elif string.strcmp(type_name, "UINTPTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int32(pool)) + elif string.strcmp(type_name, "BYTEPTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + elif string.strcmp(type_name, "CHARLIST") == 0: + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + elif string.strcmp(type_name, "SHORTPTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int16(pool)) + elif string.strcmp(type_name, "USHORTPTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int16(pool)) + elif string.strcmp(type_name, "WCHARPTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int16(pool)) + elif string.strcmp(type_name, "CHARPTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + elif string.strcmp(type_name, "VOIDPTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + # Windows API 跨模块 typedef(win32base.py 中定义) + # HANDLE = VOIDPTR = i8*,LPCSTR = const char* = i8*,LPCWSTR = const wchar_t* = i16* + elif string.strcmp(type_name, "HANDLE") == 0: + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + elif string.strcmp(type_name, "LPCSTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + elif string.strcmp(type_name, "LPCWSTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int16(pool)) + elif string.strcmp(type_name, "INT8PTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + elif string.strcmp(type_name, "INT16PTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int16(pool)) + elif string.strcmp(type_name, "INT32PTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int32(pool)) + elif string.strcmp(type_name, "INT64PTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int64(pool)) + elif string.strcmp(type_name, "UINT8PTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + elif string.strcmp(type_name, "UINT16PTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int16(pool)) + elif string.strcmp(type_name, "UINT32PTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int32(pool)) + elif string.strcmp(type_name, "UINT64PTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int64(pool)) + elif string.strcmp(type_name, "CHAR8PTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + elif string.strcmp(type_name, "CHAR16PTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int16(pool)) + elif string.strcmp(type_name, "CHAR32PTR") == 0: + return llvmlite.Ptr(pool, llvmlite.Int32(pool)) + + # C 标准 小写 _t 类型 + elif string.strcmp(type_name, "int8_t") == 0: + return llvmlite.Int8(pool) + elif string.strcmp(type_name, "int16_t") == 0: + return llvmlite.Int16(pool) + elif string.strcmp(type_name, "int32_t") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(type_name, "int64_t") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "uint8_t") == 0: + return llvmlite.Int8(pool) + elif string.strcmp(type_name, "uint16_t") == 0: + return llvmlite.Int16(pool) + elif string.strcmp(type_name, "uint32_t") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(type_name, "uint64_t") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "size_t") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "ssize_t") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "ptrdiff_t") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "intptr_t") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "uintptr_t") == 0: + return llvmlite.Int64(pool) + elif string.strcmp(type_name, "wchar_t") == 0: + return llvmlite.Int16(pool) + elif string.strcmp(type_name, "char8_t") == 0: + return llvmlite.Int8(pool) + elif string.strcmp(type_name, "char16_t") == 0: + return llvmlite.Int16(pool) + elif string.strcmp(type_name, "char32_t") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(type_name, "_Bool") == 0: + return llvmlite.Int8(pool) + return None + + def _is_t_attr(self, node: ast.AST | t.CPtr, + attr_name: str, + imported_modules: str) -> int: + """检测节点是否是 t.attr_name 形式(含 from t import attr_name 的裸名) + + 支持两种写法(与 TPC 的 IsTModule 检查对齐): + - t.CPtr / t.CVoid(Attribute 形式) + - 裸名 CPtr / CVoid(from t import CPtr 形式) + 裸名识别是必要功能:测试/库代码大量用 `from t import CPtr` 后直接写 + `X | CPtr`、`CVoid` 参数注解等,若只认 t.XXX 会漏判。 + """ + if node is None or attr_name is None: + return 0 + if node.kind() == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) + if at.attr is None: + return 0 + if string.strcmp(at.attr, attr_name) != 0: + return 0 + if at.value is None or at.value.kind() != ast.ASTKind.Name: + return 0 + val_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) + if val_nm.id is None: + return 0 + if string.strcmp(val_nm.id, "t") == 0: + # t 是内建库(SHA1 豁免),可能不在 _imported_modules 中。 + # 显式写 t.CPtr / t.CVoid 即确指 t 模块,无需 imported_modules 确认。 + return 1 + return 0 + # 裸名形式: from t import attr_name → Name(id == attr_name) + if node.kind() == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) + if nm.id is None: + return 0 + if string.strcmp(nm.id, attr_name) != 0: + return 0 + # 裸名需确认 t 模块已导入(from t import X 会注册 t 到 _imported_modules) + if HandlesImports.is_module_imported(imported_modules, "t") == 0: + return 0 + return 1 + return 0 + + def _is_cptr_marker(self, node: ast.AST | t.CPtr, + imported_modules: str) -> int: + """检测节点是否为 CPtr 指针标记,返回 1=是 / 0=否""" + if self._is_t_attr(node, "CPtr", imported_modules) != 0: + return 1 + if node is not None and node.kind() == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) + if nm.id is not None and string.strcmp(nm.id, "CPtr") == 0: + return 1 + return 0 + + def _is_cvoid_marker(self, node: ast.AST | t.CPtr, + imported_modules: str) -> int: + """检测节点是否为 CVoid 指针标记,返回 1=是 / 0=否""" + if self._is_t_attr(node, "CVoid", imported_modules) != 0: + return 1 + if node is not None and node.kind() == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) + if nm.id is not None and string.strcmp(nm.id, "CVoid") == 0: + return 1 + return 0 + + def annotation_to_str(self, annot: ast.AST | t.CPtr) -> str: + """将类型注解 AST 转换为可读字符串,返回 None=无法提取 + + 注意:返回的字符串可能由 malloc 分配,调用方无需释放(错误路径用)。 + """ + if annot is None: + return "" + k: int = annot.kind() + + # Constant 节点: 字符串注解 + if k == ast.ASTKind.Constant: + cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(annot) + if cn.const_kind == ast.CONST_STR and cn.str_val is not None: + return cn.str_val + return "" + + # Name 节点: bool, int, MemBuddy + if k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(annot) + if nm.id is not None: + return nm.id + return "" + + # Attribute 节点: t.CBool, memhub.MemBuddy + if k == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annot) + if at.attr is None: + return "" + if at.value is not None: + prefix: str = self.annotation_to_str(at.value) + if prefix is not None: + buf: t.CChar | t.CPtr = stdlib.malloc( + string.strlen(prefix) + string.strlen(at.attr) + 2) + if buf is not None: + viperlib.snprintf(buf, + string.strlen(prefix) + string.strlen(at.attr) + 2, + "%s.%s", prefix, at.attr) + return buf + return at.attr + + # Subscript 节点: list[...], t.CArray[...] + if k == ast.ASTKind.Subscript: + sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(annot) + base: str = self.annotation_to_str(sub.value) + if base is not None: + buf2: t.CChar | t.CPtr = stdlib.malloc(string.strlen(base) + 5) + if buf2 is not None: + viperlib.snprintf(buf2, string.strlen(base) + 5, + "%s[...]", base) + return buf2 + return "" + + # BinOp 节点: A | B (联合类型) + if k == ast.ASTKind.BinOp: + bo: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(annot) + left_s: str = self.annotation_to_str(bo.left) + right_s: str = self.annotation_to_str(bo.right) + if left_s is not None and right_s is not None: + buf3: t.CChar | t.CPtr = stdlib.malloc( + string.strlen(left_s) + string.strlen(right_s) + 5) + if buf3 is not None: + viperlib.snprintf(buf3, + string.strlen(left_s) + string.strlen(right_s) + 5, + "%s | %s", left_s, right_s) + return buf3 + return "" + + return "" + + def extract_class_name_from_annotation(self, node: ast.AST | t.CPtr, + imported_modules: str, + pool: memhub.MemBuddy | t.CPtr = None) -> str: + """从类型注解 AST 中提取类名,返回 None=无法提取 + + pool 可用时,对泛型 Subscript(如 list[AST | t.CPtr])返回 mangled name + (如 "list[ast.AST|t.CPtr]"),与 resolve_annotation_type 的 mangled name 格式一致, + 使 find_struct 能找到特化的泛型结构体。 + pool 为 None 时,对 Subscript 只返回裸类名(如 "list"),保持向后兼容。 + """ + if node is None: + return None + k: int = node.kind() + + # Constant 节点: 字符串注解(如 'MemManager'),简单类名直接返回 + if k == ast.ASTKind.Constant: + cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) + if cn.const_kind == ast.CONST_STR and cn.str_val is not None: + # 仅处理简单类名(不含 . 和 |),复杂形式返回 None + if string.strchr(cn.str_val, 46) is None and string.strchr(cn.str_val, 124) is None: + if string.strcmp(cn.str_val, "str") == 0: + return None + if string.strcmp(cn.str_val, "int") == 0: + return None + if string.strcmp(cn.str_val, "bytes") == 0: + return None + if string.strcmp(cn.str_val, "bool") == 0: + return None + if string.strcmp(cn.str_val, "float") == 0: + return None + if string.strcmp(cn.str_val, "double") == 0: + return None + return cn.str_val + return None + + # Name 节点: MemBuddy → "MemBuddy" + if k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) + if nm.id is None: + return None + # 跳过内置类型名 + if string.strcmp(nm.id, "str") == 0: + return None + if string.strcmp(nm.id, "bytes") == 0: + return None + if string.strcmp(nm.id, "bool") == 0: + return None + if string.strcmp(nm.id, "float") == 0: + return None + if string.strcmp(nm.id, "double") == 0: + return None + return nm.id + + # Attribute 节点: memhub.MemBuddy → "memhub.MemBuddy"(模块限定名) + if k == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) + if at.attr is None: + return None + # t.XXX 内置类型:返回 XXX(如 t.CUInt32T → "CUInt32T"), + # 供 AnnotClassName 记录变量类型名(_type_name_unsigned 判断无符号性时使用)。 + # 消费方(find_struct/lookup_field_by_class)对非结构体名返回 None 优雅降级。 + if at.value is not None and at.value.kind() == ast.ASTKind.Name: + val_nm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) + if val_nm2.id is not None and string.strcmp(val_nm2.id, "t") == 0: + return at.attr + # 返回模块限定名 "module.Class"(如 "memhub.MemBuddy") + mod_qual_buf: t.CChar | t.CPtr = stdlib.malloc( + string.strlen(val_nm2.id) + string.strlen(at.attr) + 2) + if mod_qual_buf is not None: + viperlib.snprintf(mod_qual_buf, + string.strlen(val_nm2.id) + string.strlen(at.attr) + 2, + "%s.%s", val_nm2.id, at.attr) + return mod_qual_buf + return at.attr + + # BinOp 节点: 联合类型 A | B + if k == ast.ASTKind.BinOp: + bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) + if bop.op == ast.OpKind.BitOr: + left_is_cptr: int = self._is_cptr_marker(bop.left, imported_modules) + right_is_cptr: int = self._is_cptr_marker(bop.right, imported_modules) + # 提取非 CPtr 一边的类名 + if left_is_cptr != 0 and right_is_cptr == 0: + return self.extract_class_name_from_annotation(bop.right, imported_modules, pool) + if right_is_cptr != 0 and left_is_cptr == 0: + return self.extract_class_name_from_annotation(bop.left, imported_modules, pool) + # 无 CPtr 标记:尝试两边 + if left_is_cptr == 0 and right_is_cptr == 0: + left_name: str = self.extract_class_name_from_annotation(bop.left, imported_modules, pool) + if left_name is not None: + return left_name + return self.extract_class_name_from_annotation(bop.right, imported_modules, pool) + return None + + # BUG 1 方案3:Subscript 节点拼接 mangled name + # list[AST | t.CPtr] → "list[ast.AST|t.CPtr]"(pool 可用时) + # 与 resolve_annotation_type 的 mangled name 格式一致,使 find_struct 能找到特化结构体 + if k == ast.ASTKind.Subscript: + sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node) + if sub.value is None: + return None + base_name: str = self.extract_class_name_from_annotation(sub.value, imported_modules, pool) + if base_name is None: + return None + # pool 不可用时,只返回裸类名(向后兼容) + if pool is None or sub.slice is None: + return base_name + # pool 可用:拼接 mangled name "base_name[slice_name]" + # slice 是 Tuple 时用逗号分隔多个参数,否则单个参数 + slice_name: str = None + if sub.slice.kind() == ast.ASTKind.Tuple: + # Tuple slice: dict[str, int] → "str,int" + sub_tup: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(sub.slice) + if sub_tup.elts is not None: + tup_elts_sn: list[ast.AST | t.CPtr] | t.CPtr = sub_tup.elts + tn_sn: t.CSizeT = tup_elts_sn.__len__() + # 计算总长度 + tup_total: t.CSizeT = 1 + ti_sn: t.CSizeT + for ti_sn in range(tn_sn): + if ti_sn > 0: + tup_total += 1 + elt_node: ast.AST | t.CPtr = tup_elts_sn.get(ti_sn) + elt_name: str = self._get_type_name_from_annotation(pool, elt_node) + if elt_name is not None: + tup_total += string.strlen(elt_name) + tup_buf: str = pool.alloc(tup_total) + if tup_buf is not None: + tup_buf[0] = '\0' + for ti_sn in range(tn_sn): + if ti_sn > 0: + string.strcat(tup_buf, ",") + elt_node2: ast.AST | t.CPtr = tup_elts_sn.get(ti_sn) + elt_name2: str = self._get_type_name_from_annotation(pool, elt_node2) + if elt_name2 is not None: + string.strcat(tup_buf, elt_name2) + slice_name = tup_buf + else: + # 非 Tuple slice: list[AST | t.CPtr] → "ast.AST|t.CPtr" + slice_name = self._get_type_name_from_annotation(pool, sub.slice) + if slice_name is None: + return base_name + # 拼接 "base_name[slice_name]" + mangled_total: t.CSizeT = string.strlen(base_name) + 1 + string.strlen(slice_name) + 1 + 1 + mangled_buf: str = pool.alloc(mangled_total) + if mangled_buf is None: + return base_name + mangled_buf[0] = '\0' + string.strcat(mangled_buf, base_name) + string.strcat(mangled_buf, "[") + string.strcat(mangled_buf, slice_name) + string.strcat(mangled_buf, "]") + return mangled_buf + + return None + + def _resolve_generic_subscript_ty(self, pool: memhub.MemBuddy | t.CPtr, + sub: ast.Subscript | t.CPtr, + gen_cls_name: str, + trans: HT.Translator | t.CPtr, + imported_modules: str, + from_imports: str) -> llvmlite.LLVMType | t.CPtr: + """解析泛型类类型注解(特化或查找已注册结构体),失败返回 None""" + if pool is None or sub is None or gen_cls_name is None: + return None + # tuple[...] 类型注解:TransPyV 暂不支持 tuple 返回类型,返回 None 让上层默认处理 + # 避免走到 list[str](pool, 4) 构造路径崩溃(tuple 未定义为泛型类) + if string.strcmp(gen_cls_name, "tuple") == 0: + return None + # 先收集类型实参名,再分配缓冲区拼接 mangled name(elem_size=8:str 是指针) + gen_arg_names: list[str] | t.CPtr = list[str](pool, 8) + if sub.slice.kind() == ast.ASTKind.Tuple: + gen_tp: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(sub.slice) + gen_elts: list[ast.AST | t.CPtr] | t.CPtr = gen_tp.elts + if gen_elts is not None: + gen_en: t.CSizeT = gen_elts.__len__() + gen_ei: t.CSizeT + for gen_ei in range(gen_en): + gen_elt: ast.AST | t.CPtr = gen_elts.get(gen_ei) + gen_tn: str = self._get_type_name_from_annotation(pool, gen_elt) + gen_arg_names.append(gen_tn) + else: + gen_tn_single: str = self._get_type_name_from_annotation(pool, sub.slice) + gen_arg_names.append(gen_tn_single) + # 计算总长度并分配缓冲区 + gen_total: t.CSizeT = string.strlen(gen_cls_name) + 2 # "[" 和 "]" + gen_an: t.CSizeT = gen_arg_names.__len__() + gen_ai: t.CSizeT + for gen_ai in range(gen_an): + if gen_ai > 0: + gen_total += 1 # "," + gen_atn: str = gen_arg_names.get(gen_ai) + if gen_atn is not None: + gen_total += string.strlen(gen_atn) + gen_total += 1 # NUL + gen_mangled: str = pool.alloc(gen_total) + if gen_mangled is None: + return None + gen_mangled[0] = '\0' + string.strcat(gen_mangled, gen_cls_name) + string.strcat(gen_mangled, "[") + for gen_ai in range(gen_an): + if gen_ai > 0: + string.strcat(gen_mangled, ",") + gen_atn: str = gen_arg_names.get(gen_ai) + if gen_atn is not None: + string.strcat(gen_mangled, gen_atn) + string.strcat(gen_mangled, "]") + # 查找已特化的 struct(特化由实例化调用 list[int](pool) 触发) + gen_spec_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(gen_mangled) + if gen_spec_ty is not None: + # 治本修复:Phase B 补译泛型特化类方法体 + # Phase 1a(declare_only==1)特化时只注册结构体不译方法体(MethodsEmitted==0), + # Phase B(declare_only==0)解析字段类型命中已注册结构体时本会早返回, + # 导致方法体永远不生成 → GSList[Line].append 等符号只有 declare 无 define → 链接失败。 + # 此处 Phase B 且方法体未译时,调用 _specialize_generic_class 走其已注册分支补译方法体。 + if trans is not None and trans._declare_only == 0: + import lib.core.Handles.HandlesClassDef as HandlesClassDef + gen_spec_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(gen_mangled) + if gen_spec_entry is not None and gen_spec_entry.MethodsEmitted == 0: + HandlesClassDef._specialize_generic_class(trans, gen_cls_name, gen_arg_names) + return gen_spec_ty + # 未特化:尝试主动触发泛型特化(与 TPC _HandleSubscript 对齐) + # 当 trans 可用时,检查是否是泛型模板并触发特化 + if trans is not None: + import lib.core.Handles.HandlesClassDef as HandlesClassDef + import lib.core.Handles.HandlesExprCall as HandlesExprCall + template_cd_chk: ast.ClassDef | t.CPtr = HandlesClassDef._find_generic_template(gen_cls_name) + if template_cd_chk is not None: + type_args_chk: list[str] | t.CPtr = HandlesExprCall._extract_type_args_from_slice( + pool, sub.slice) + if type_args_chk is not None and type_args_chk.__len__() > 0: + spec_name_chk: str = HandlesClassDef._specialize_generic_class( + trans, gen_cls_name, type_args_chk) + if spec_name_chk is not None: + gen_spec_ty = HandlesStruct.get_struct_type(gen_mangled) + if gen_spec_ty is not None: + return gen_spec_ty + # 未特化:返回 None(不报错,让后续流程处理) + return None + + def resolve_annotation_type(self, pool: memhub.MemBuddy | t.CPtr, + node: ast.AST | t.CPtr, + imported_modules: str, + from_imports: str, + trans: HT.Translator | t.CPtr = None) -> llvmlite.LLVMType | t.CPtr: + """解析类型注解节点为 LLVMType + + Args: + pool: 内存分配器 + node: 类型注解 AST 节点(Name 或 Attribute) + imported_modules: 已导入模块名字符串(空格分隔) + from_imports: from-import 映射字符串("name:module name:module" 格式) + trans: 翻译器对象(可选,用于触发泛型特化) + """ + if node is None: + return None + + k: int = node.kind() + + # Constant 节点: 字符串注解(如 'MemManager'),当作无引号的 Name/Attribute/BinOp 处理 + if k == ast.ASTKind.Constant: + cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) + if cn.const_kind == ast.CONST_STR and cn.str_val is not None: + sub_node: ast.AST | t.CPtr = self._parse_type_string(pool, cn.str_val, ast.ASTCtx.Load) + if sub_node is not None: + return self.resolve_annotation_type(pool, sub_node, imported_modules, from_imports, trans) + return None + + # Name 节点: str, int, bytes, from-import 名称, class 名称等 + if k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) + if nm.id is None: + return None + # 泛型类型参数 T 替换:在泛型特化上下文中,将 T 替换为具体类型 + if self.GenericTpNames is not None and self.GenericTypeArgs is not None: + gp_n: t.CSizeT = self.GenericTpNames.__len__() + gp_i: t.CSizeT + for gp_i in range(gp_n): + gp_tpn: str = self.GenericTpNames.get(gp_i) + if gp_tpn is not None and string.strcmp(nm.id, gp_tpn) == 0: + gp_ta: str = self.GenericTypeArgs.get(gp_i) + if gp_ta is not None: + # 用具体类型名递归解析(支持 BinOp/Attribute 类型实参) + gp_sub_node: ast.AST | t.CPtr = self._parse_type_string(pool, gp_ta, nm.ctx) + if gp_sub_node is not None: + return self.resolve_annotation_type(pool, gp_sub_node, imported_modules, from_imports, trans) + # str = bytes = t.CChar | t.CPtr = i8* + if string.strcmp(nm.id, "str") == 0: + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + elif string.strcmp(nm.id, "int") == 0: + return llvmlite.Int32(pool) + elif string.strcmp(nm.id, "bytes") == 0: + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + elif string.strcmp(nm.id, "bool") == 0: + # bool = t.CBool = i1(与 map_t_type 中 CBool 映射一致) + return llvmlite.Int1(pool) + # 裸名浮点类型: float = t.CFloat = f32, double = t.CDouble = f64 + elif string.strcmp(nm.id, "float") == 0: + return llvmlite.Float(pool) + elif string.strcmp(nm.id, "double") == 0: + return llvmlite.Double(pool) + # class 名称: 查找已注册的 StructType,返回 StructType 本身(不包装 Ptr) + # 这样 build_alloca 会分配结构体大小的空间,alloca 返回 struct_ty* + # 命名空间隔离:严格模式下仅解析可见的结构体 + # 跨模块同名类优先:当前模块自身定义了同名类时,用 find_struct_by_module + # 命中本模块的类(如 main.vp 的 G5Node 不再被 g5container.vp 预注册的 + # G5Node 顶掉,避免 alloca 用本模块类型、load 用他模块类型的混用)。 + # 本模块未定义时回退按裸名全局查找(import 来的类走此路径)。 + if trans is not None and trans.ModuleSha1 is not None: + own_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(nm.id, trans.ModuleSha1) + if own_entry is not None and own_entry.Ty is not None: + return own_entry.Ty + if HandlesStruct.is_struct_visible(nm.id) != 0: + struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(nm.id) + if struct_ty is not None: + return struct_ty + # CTypedef 动态查表:查动态 CTypedef 表,递归解析类型表达式 + # 用户自定义 CTypedef(如 MyHandle: t.CTypedef = VOIDPTR)在此解析 + # 递归深度限制 MAX_CTYPEDEF_DEPTH 防止无限递归,循环检测防止 A→B→A + if self.CTypedefResolveDepth < MAX_CTYPEDEF_DEPTH: + ctypedef_str: str = self.lookup_ctypedef(nm.id) + if ctypedef_str is not None and self.CTypedefFound != 0: + # 循环检测:将当前 CTypedef 名加入正在解析列表 + if self._ctypedef_push_visiting(pool, nm.id) == 0: + # 用 _parse_type_string 把类型字符串转回 AST,递归解析 + inner_node: ast.AST | t.CPtr = self._parse_type_string(pool, ctypedef_str, nm.ctx) + if inner_node is not None: + self.CTypedefResolveDepth += 1 + inner_ty: llvmlite.LLVMType | t.CPtr = self.resolve_annotation_type( + pool, inner_node, imported_modules, from_imports, trans) + self.CTypedefResolveDepth -= 1 + self._ctypedef_pop_visiting() + if inner_ty is not None: + return inner_ty + else: + self._ctypedef_pop_visiting() + # 兜底: 尝试 map_t_type 中的硬编码 typedef 映射(VOIDPTR, HANDLE, ULONG 等) + # 这些是跨模块通用的 C typedef 名,即使 from-import 查找失败也能解析 + # 注意:from-import 的结构体名若未注册,get_struct_type 已返回 None, + # 此处 map_t_type 对结构体名也返回 None,由上层 declare_only 机制延迟到下一遍 + mapped_ty_fallback: llvmlite.LLVMType | t.CPtr = self.map_t_type(pool, nm.id) + if mapped_ty_fallback is not None: + return mapped_ty_fallback + return None + + # Attribute 节点: t.CInt, t.CUInt64T, namespace_defs.PlainStruct 等 + if k == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) + if at.attr is None: + return None + # 检查 value 是否是 Name('t') 或 Name('c') + if at.value is not None and at.value.kind() == ast.ASTKind.Name: + val_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) + if val_name.id is not None: + # t/c 是内建库(SHA1 豁免),显式写 t.XXX 即确指内建库, + # 不依赖 imported_modules(t 可能不在其中,如 vpi 注入上下文) + is_builtin_attr: int = 0 + if string.strcmp(val_name.id, "t") == 0 or string.strcmp(val_name.id, "c") == 0: + is_builtin_attr = 1 + if is_builtin_attr == 0: + mod_imp: int = HandlesImports.is_module_imported(imported_modules, val_name.id) + if mod_imp == 0: + return None + # 先尝试内置类型映射(int 等) + mapped_ty: llvmlite.LLVMType | t.CPtr = self.map_t_type(pool, at.attr) + if mapped_ty is not None: + return mapped_ty + # 模块限定类类型:Module.ClassName(命名空间隔离) + mod_struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(at.attr) + if mod_struct_ty is not None: + return mod_struct_ty + return None + # 嵌套 Attribute: w32.win32base.SECURITY_ATTRIBUTES 等三级及以上限定名 + # at.value 是 Attribute 而非 Name,递归提取最终类名(at.attr)查结构体表 + # find_struct 支持模块限定名回退,此处用最外层 attr(简单类名)即可 + if at.value is not None and at.value.kind() == ast.ASTKind.Attribute: + nested_struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(at.attr) + if nested_struct_ty is not None: + return nested_struct_ty + return None + + # BinOp 节点: 联合类型注解 A | B + # 处理三种语义: + # 1. ActualType | t.CPtr → Ptr(ActualType)(指针包装,如 MemBuddy | t.CPtr → MemBuddy*) + # 2. t.CVoid | t.CPtr → i8* (void* 等价于 i8*) + # 3. ActualType | DecoratorMarker → ActualType(忽略装饰器标记如 CExport/CExtern) + if k == ast.ASTKind.BinOp: + bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) + if bop.op == ast.OpKind.BitOr: + # 检测 t.CPtr 标记(指针包装标记,支持 t.CPtr 与 from t import CPtr 裸名) + left_is_cptr: int = self._is_cptr_marker(bop.left, imported_modules) + right_is_cptr: int = self._is_cptr_marker(bop.right, imported_modules) + if left_is_cptr != 0 or right_is_cptr != 0: + # 有 CPtr 标记:解析非 CPtr 一边的实际类型,包装为 Ptr + # left 是 CPtr → other 是 right;right 是 CPtr → other 是 left + other_node: ast.AST | t.CPtr = bop.left + if left_is_cptr != 0: + other_node = bop.right + # 检测另一边是否是 t.CVoid (void* = i8*) + # 严格验证完整形式(Attribute(t.CVoid) 的 value 是 Name("t"), + # 或裸名 CVoid 且 t 已导入),防止解析异常节点被误判为 CVoid。 + other_is_cvoid: int = 0 + if other_node is not None: + if other_node.kind() == ast.ASTKind.Attribute: + oat2: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(other_node) + if oat2.attr is not None and string.strcmp(oat2.attr, "CVoid") == 0: + if oat2.value is not None and oat2.value.kind() == ast.ASTKind.Name: + ov2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(oat2.value) + if ov2.id is not None and string.strcmp(ov2.id, "t") == 0: + other_is_cvoid = 1 + elif other_node.kind() == ast.ASTKind.Name: + onm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(other_node) + if onm2.id is not None and string.strcmp(onm2.id, "CVoid") == 0: + if HandlesImports.is_module_imported(imported_modules, "t") != 0: + other_is_cvoid = 1 + if other_is_cvoid != 0: + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + other_ty: llvmlite.LLVMType | t.CPtr = self.resolve_annotation_type( + pool, other_node, imported_modules, from_imports, trans) + # 仅裸名(Name)场景验证解析结果必须是已注册 struct: + # 损坏节点可能解析出基础类型垃圾(如 Int8 → Ptr(i8))。 + # Attribute 场景(Module.Class / t.XXX)resolve 结果直接可用 + # (如 t.CUInt64T → i64、memhub.MemBuddy → MemBuddy*), + # 不得踢进 fallback——否则按 Name 布局读 Attribute 字段会得到 + # 垃圾类名,字段类型错误(如 free_lists 从 i64* 变 i8*)导致 + # 运行时 GEP 步长错误崩溃。 + other_is_name: int = 0 + if other_node is not None and other_node.kind() == ast.ASTKind.Name: + other_is_name = 1 + if other_ty is not None and other_is_name != 0: + if HandlesStruct.find_struct_by_type(other_ty) is None: + other_ty = None + if other_ty is None: + # 严格模式(App 文件)下裸类名不可见时,回退到全局 + # struct 注册表按类名查找。X | t.CPtr 是明确的指针包装 + # 注解(如 vpi stub 的 "ParsedArgs | t.CPtr"),X 已注册 + # 时不应静默退化为 i8*——i8* 会让方法返回值的无注解变量 + # (如 args = parser.parse_args())类型退化,后续 obj.method + # get_class_name_by_type 查不到类名,误报 + # "跨模块调用 'args.get_str' 找不到模块 SHA1"。 + # 仅裸名(Name)场景回退:Attribute 场景 resolve 已成功。 + other_cls_nm: str = None + if other_node is not None and other_node.kind() == ast.ASTKind.Name: + other_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(other_node) + if other_nm.id is not None: + other_cls_nm = other_nm.id + if other_cls_nm is not None: + other_cls_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(other_cls_nm) + if other_cls_ty is not None: + return llvmlite.Ptr(pool, other_cls_ty) + # CPtr 单独使用或其他无效类型 → i8* + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + return llvmlite.Ptr(pool, other_ty) + + # 无 CPtr 标记:返回第一个非 None(装饰器标记如 CExport/CExtern 被忽略) + left_ty: llvmlite.LLVMType | t.CPtr = self.resolve_annotation_type( + pool, bop.left, imported_modules, from_imports, trans) + if left_ty is not None: + return left_ty + right_ty: llvmlite.LLVMType | t.CPtr = self.resolve_annotation_type( + pool, bop.right, imported_modules, from_imports, trans) + if right_ty is not None: + return right_ty + return None + + # Subscript 节点: t.CArray[elem_ty, count] → [count x elem_ty] + # t.CArray[elem_ty] → Ptr(elem_ty)(静态推导长度数组) + # list[int] → 特化类 struct type(泛型类类型注解) + # value 是 Attribute(Name('t'), 'CArray') 或 Name('list')(泛型类) + # slice 是 Tuple(elts=[elem_ty_node, count_node]) 或单 elem_ty_node + if k == ast.ASTKind.Subscript: + sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node) + if sub.value is None or sub.slice is None: + self.fatal_type_error(node, "Subscript 节点缺少 value 或 slice") + # 泛型类类型注解: list[int] → 查找已特化的 struct(value 是 Name 泛型类名) + if sub.value.kind() == ast.ASTKind.Name: + gen_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value) + if gen_nm.id is not None: + return self._resolve_generic_subscript_ty(pool, sub, gen_nm.id, trans, + imported_modules, from_imports) + # 检查 value 是否是 Attribute(t.CArray / t.Callable / 模块限定泛型类如 numpy.ndarray[T]) + if sub.value.kind() != ast.ASTKind.Attribute: + self.fatal_type_error(node, "不支持的 Subscript 类型注解(仅支持 t.CArray / t.Callable)") + arr_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(sub.value) + if arr_at.attr is None: + self.fatal_type_error(node, "Subscript Attribute 缺少 attr") + # 模块限定泛型类: numpy.ndarray[t.CDouble] → 裸类名 ndarray 走泛型特化 + # (在 t.CArray / t.Callable 检查之前;模板已注册即视为泛型类) + if trans is not None: + import lib.core.Handles.HandlesClassDef as HandlesClassDef + if HandlesClassDef._find_generic_template(arr_at.attr) is not None: + return self._resolve_generic_subscript_ty(pool, sub, arr_at.attr, trans, + imported_modules, from_imports) + if arr_at.value is None or arr_at.value.kind() != ast.ASTKind.Name: + self.fatal_type_error(node, "t.CArray / t.Callable 必须通过模块名限定") + arr_val_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arr_at.value) + if arr_val_name.id is None: + self.fatal_type_error(node, "Subscript 模块名为 None") + # 函数指针类型: t.Callable[[A, B], Ret] → i8* + # 与 TPV 函数传指针惯例一致(函数值 bitcast 为 i8* 存储,调用时按实参重建签名) + if string.strcmp(arr_at.attr, "Callable") == 0: + if HandlesImports.is_module_imported(imported_modules, arr_val_name.id) == 0: + self.fatal_type_error(node, "t.Callable 模块未导入") + return llvmlite.Ptr(pool, llvmlite.Int8(pool)) + if string.strcmp(arr_at.attr, "CArray") != 0: + self.fatal_type_error(node, "不支持的 Subscript 类型注解(仅支持 t.CArray / t.Callable)") + if HandlesImports.is_module_imported(imported_modules, arr_val_name.id) == 0: + self.fatal_type_error(node, "t.CArray 模块未导入") + # 单参数形式: t.CArray[elem_ty] → Ptr(elem_ty) + # 相当于 t.CArray[elem_ty, None],表示静态推导长度数组 + if sub.slice.kind() != ast.ASTKind.Tuple: + elem_ty_single: llvmlite.LLVMType | t.CPtr = self.resolve_annotation_type( + pool, sub.slice, imported_modules, from_imports, trans) + if elem_ty_single is None: + self.fatal_type_error(sub.slice, "t.CArray[?] 元素类型解析失败") + return llvmlite.Ptr(pool, elem_ty_single) + # 双参数形式: t.CArray[elem_ty, count] → [count x elem_ty] + tup: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(sub.slice) + if tup.elts is None: + self.fatal_type_error(node, "t.CArray Tuple 缺少 elts") + elts_list: list[ast.AST | t.CPtr] | t.CPtr = tup.elts + elts_n: t.CSizeT = elts_list.__len__() + if elts_n < 2: + self.fatal_type_error(node, "t.CArray Tuple 元素不足") + elem_node: ast.AST | t.CPtr = elts_list.get(0) + count_node: ast.AST | t.CPtr = elts_list.get(1) + if elem_node is None or count_node is None: + self.fatal_type_error(node, "t.CArray Tuple 元素为 None") + # 递归解析元素类型 + elem_ty: llvmlite.LLVMType | t.CPtr = self.resolve_annotation_type( + pool, elem_node, imported_modules, from_imports, trans) + if elem_ty is None: + self.fatal_type_error(elem_node, "t.CArray 元素类型解析失败") + # 解析 count(支持整数常量、None、CDefine 常量名、常量表达式如 2*MAX) + # t.CArray[elem_ty, None] 等价于单参数形式 → Ptr(elem_ty) + # t.CArray[elem_ty, NAME] 其中 NAME: t.CDefine = value → [value x elem_ty] + # t.CArray[elem_ty, 2 * MAX] 常量表达式静态计算 → [2*MAX x elem_ty] + count_val: int = 0 + if count_node.kind() == ast.ASTKind.Constant: + cnt_cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(count_node) + if cnt_cn.const_kind == ast.CONST_NONE: + return llvmlite.Ptr(pool, elem_ty) + # 统一用 _eval_const_int_expr 计算常量整数表达式 + # 支持 Constant(INT)、Name(CDefine)、BinOp(2*MAX 等算术/位运算) + count_val = self._eval_const_int_expr(count_node) + if self.ConstEvalOk == 0: + self.fatal_type_error(count_node, "t.CArray count 必须是整数常量、None、CDefine 常量名或常量表达式") + if count_val <= 0: + self.fatal_type_error(count_node, "t.CArray count 必须为正数") + # 创建 ArrayType(不包装 Ptr) + # 这样 build_alloca 会分配数组大小的空间,alloca 返回 [N x elem_ty]* + return llvmlite.Array(pool, elem_ty, count_val) + + # 未知 AST kind:fail-fast,不宽容返回 None + self.fatal_type_error(node, "不支持的类型注解语法") + + def has_decorator_marker(self, node: ast.AST | t.CPtr, + marker_name: str) -> int: + """检测类型注解中是否包含指定的装饰器标记""" + if node is None or marker_name is None: + return 0 + + k: int = node.kind() + + # Attribute 节点: t.CExtern, t.State, t.CExport, t.CInline + if k == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) + if at.attr is not None: + if string.strcmp(at.attr, marker_name) == 0: + return 1 + return 0 + + # BinOp 节点: int | t.CExtern(递归检测左右子节点) + if k == ast.ASTKind.BinOp: + bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) + if self.has_decorator_marker(bop.left, marker_name) != 0: + return 1 + if self.has_decorator_marker(bop.right, marker_name) != 0: + return 1 + return 0 + + return 0 + + def is_pass_body(self, body: list[ast.AST | t.CPtr] | t.CPtr) -> int: + """检测函数体是否为 pass(空体或仅含 pass 语句)""" + if body is None: + return 1 + bn: t.CSizeT = body.__len__() + if bn == 0: + return 1 + if bn == 1: + stmt: ast.AST | t.CPtr = body.get(0) + if stmt is not None and stmt.kind() == ast.ASTKind.Pass: + return 1 + return 0 + + def get_llvm_type_bits(self, ty: llvmlite.LLVMType | t.CPtr) -> int: + """获取 LLVM 整数类型的位宽,非整数类型返回 0""" + if ty is None: + return 0 + match ty: + case llvmlite.LLVMType.Int(bits): + return bits + case _: + return 0 + + def infer_expr_type(self, pool: memhub.MemBuddy | t.CPtr, + node: ast.AST | t.CPtr, + param_types: str) -> llvmlite.LLVMType | t.CPtr: + """推断表达式的 LLVM 类型 + + param_types 格式: "name:bits,name:bits,..." + """ + if node is None: + return llvmlite.Int32(pool) + + k: int = node.kind() + + if k == ast.ASTKind.Constant: + return llvmlite.Int32(pool) + + elif k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) + if nm.id is not None and param_types is not None: + # 在 param_types 中查找: "name:bits" 格式 + search_key: t.CChar | t.CPtr = pool.alloc(64) + if search_key is not None: + viperlib.snprintf(search_key, 64, "%s:", nm.id) + found: t.CChar | t.CPtr = string.strstr(param_types, search_key) + if found is not None: + colon_pos: t.CSizeT = string.strlen(nm.id) + 1 + bits_str: t.CChar | t.CPtr = found + colon_pos + bits: int = 0 + for bi in range(4): + ch: t.CChar = bits_str[bi] + if ch >= '0' and ch <= '9': + bits = bits * 10 + (ch - '0') + else: + break + if bits == 64: + return llvmlite.Int64(pool) + elif bits == 16: + return llvmlite.Int16(pool) + elif bits == 8: + return llvmlite.Int8(pool) + return llvmlite.Int32(pool) + + elif k == ast.ASTKind.BinOp: + binop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) + lhs_ty: llvmlite.LLVMType | t.CPtr = self.infer_expr_type( + pool, binop.left, param_types) + rhs_ty: llvmlite.LLVMType | t.CPtr = self.infer_expr_type( + pool, binop.right, param_types) + lhs_bits: int = self.get_llvm_type_bits(lhs_ty) + rhs_bits: int = self.get_llvm_type_bits(rhs_ty) + if lhs_bits >= rhs_bits: + return lhs_ty + return rhs_ty + + return llvmlite.Int32(pool) + + def infer_return_type(self, pool: memhub.MemBuddy | t.CPtr, + body: list[ast.AST | t.CPtr] | t.CPtr, + param_types: str) -> llvmlite.LLVMType | t.CPtr: + """扫描函数体中的 return 语句,推断返回类型""" + if body is None: + return llvmlite.Int32(pool) + + ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) + bn: t.CSizeT = body.__len__() + for bi in range(bn): + stmt: ast.AST | t.CPtr = body.get(bi) + if stmt is not None and stmt.kind() == ast.ASTKind.Return: + rt: ast.Return | t.CPtr = (ast.Return | t.CPtr)(stmt) + if rt.value is not None: + expr_ty: llvmlite.LLVMType | t.CPtr = self.infer_expr_type( + pool, rt.value, param_types) + if expr_ty is not None: + cur_bits: int = self.get_llvm_type_bits(ret_ty) + new_bits: int = self.get_llvm_type_bits(expr_ty) + if new_bits > cur_bits: + ret_ty = expr_ty + return ret_ty + + def build_param_types_str(self, pool: memhub.MemBuddy | t.CPtr, + args_node: ast.AST | t.CPtr) -> str: + """构建参数类型编码字符串 "name:bits,name:bits,..." """ + if args_node is None: + return None + ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) + if ags.args is None: + return None + alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args + an: t.CSizeT = alist.__len__() + if an == 0: + return None + + buf_size: t.CSizeT = an * 32 + 1 + buf: t.CChar | t.CPtr = pool.alloc(buf_size) + if buf is None: + return None + buf[0] = '\0' + + i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) + for ai in range(an): + arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai)) + if arg is not None and arg.arg is not None: + param_ty: llvmlite.LLVMType | t.CPtr = i32_ty + if arg.annotation is not None: + # 直接调用 map_t_type 解析 Attribute 注解 + if arg.annotation.kind() == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg.annotation) + if at.attr is not None: + resolved: llvmlite.LLVMType | t.CPtr = self.map_t_type(pool, at.attr) + if resolved is not None: + param_ty = resolved + bits: int = self.get_llvm_type_bits(param_ty) + if bits == 0: + bits = 32 + tmp: t.CChar | t.CPtr = pool.alloc(32) + if tmp is not None: + viperlib.snprintf(tmp, 32, "%s:%d", arg.arg, bits) + if ai > 0: + self._strappend(buf, buf_size, ",") + self._strappend(buf, buf_size, tmp) + return buf + + def _strappend(self, dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr): + """将 src 追加到 dst 末尾""" + if dst is None or src is None: + return + dlen: t.CSizeT = string.strlen(dst) + slen: t.CSizeT = string.strlen(src) + remain: t.CSizeT = dst_size - dlen + if remain <= 0: + return + # 内联 min(slen, remain - 1) 避免 builtin min 未定义(TransPyV 无 builtin min) + limit: t.CSizeT = slen + cap: t.CSizeT = remain - 1 + if cap < limit: + limit = cap + for i in range(limit): + dst[dlen + i] = src[i] + dst[dlen + i] = '\0' diff --git a/App/lib/core/Gen/__init__.vp b/App/lib/core/Gen/__init__.vp index dfa19ad..7898f45 100644 --- a/App/lib/core/Gen/__init__.vp +++ b/App/lib/core/Gen/__init__.vp @@ -1,6 +1,10 @@ # ============================================================ -# Gen - 对象化生成器(P1 骨架) +# Gen - 对象化生成器(P1 骨架 + P2 TypeGenMixin) # -# Generator: 翻译状态容器 + Mixin 组合(BaseGen 起步,后续按 -# wiki/14-oo-refactor.md 的 P2-P6 逐步吸收 Handles 模块)。 +# Generator: 翻译状态容器 + Mixin 组合(BaseGen 状态 + TypeGen 类型映射, +# 后续按 wiki/14-oo-refactor.md 的 P3-P6 逐步吸收 Handles 模块)。 +# +# 全局单例(set_global_gen/get_global_gen)已迁移至 +# lib.core.Gen.Generator 模块(P2 修复:TPC 不注册包短名,函数体 +# import 包名会报 Unknown module,非包模块短名可被注册)。 # ============================================================ diff --git a/App/lib/core/Handles/HandlesType.vp b/App/lib/core/Handles/HandlesType.vp index fca4db4..7ed5cb4 100644 --- a/App/lib/core/Handles/HandlesType.vp +++ b/App/lib/core/Handles/HandlesType.vp @@ -16,25 +16,23 @@ import lib.core.Handles.HandlesStruct as HandlesStruct # ============================================================ -# HandlesType - 类型映射与解析(模块级纯函数) +# HandlesType - 类型映射与解析(P2 对象化后的委托层) # # str = bytes = t.CChar | t.CPtr = i8* -# ============================================================ - - -# ============================================================ -# 全局当前文件名(每个文件翻译前由 BuildPipeline 设置) -# ============================================================ -_g_current_file: str = None - - -# ============================================================ -# 仿 Python Traceback 调用栈 # -# 在编译过程中通过 push_trace/pop_trace 维护翻译上下文栈, -# fatal_error 输出时从底到顶展示所有帧,形成多帧 traceback。 +# P2 对象化重构(wiki/14-oo-refactor.md): +# 全部函数已迁移为 lib.core.Gen.TypeGenMixin 的方法(全局状态迁入 +# gen 字段),本模块保留同名模块级函数作为"一行委托":延迟 import +# Gen 取全局单例(BuildPipeline/main 创建后 set_global_gen 注册), +# 再调用 gen 的对应方法。签名与旧函数完全一致,调用方零改动。 +# ============================================================ + + +# ============================================================ +# 常量(保留,供 TraceFrame 相关使用) # ============================================================ TRACE_MAX: t.CDefine = 32 +MAX_CTYPEDEF_DEPTH: t.CDefine = 10 @t.NoVTable @@ -45,2316 +43,528 @@ class TraceFrame: col_end: int # 列结束(1-based,0=不指定) -_g_trace_frames: TraceFrame | t.CPtr = None -_g_trace_count: int = 0 +# ============================================================ +# 全局 gen 单例(模块级镜像) +# +# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。 +# 委托函数用本地 _g_gen(cast 成 Generator 类型),避免函数体 +# import 包模块(TPC 不注册包短名)与 Generator 类/模块名歧义。 +# ============================================================ +_g_gen: t.CVoid | t.CPtr = None + + +def set_global_gen(gen: t.CVoid | t.CPtr) -> None: + """注入全局 gen 单例(BuildPipeline/main 调用)""" + global _g_gen + _g_gen = gen + + +# ============================================================ +# 委托函数:延迟 import Gen 取全局单例 → 调 gen 方法 +# (gen 未注册时正常流程不会发生;有返回值函数返回默认值) +# ============================================================ def _ensure_trace_init() -> int: - """确保调用栈已初始化(懒加载,用 malloc 不依赖 pool)""" - global _g_trace_frames - if _g_trace_frames is not None: - return 1 - entry_size: t.CSizeT = TraceFrame.__sizeof__() - _g_trace_frames = stdlib.malloc(entry_size * TRACE_MAX) - if _g_trace_frames is None: - return 0 - string.memset(_g_trace_frames, 0, entry_size * TRACE_MAX) - return 1 + """确保调用栈已初始化(委托到 gen._ensure_trace_init)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._ensure_trace_init() + return 0 def _get_trace_frame(i: int) -> TraceFrame | t.CPtr: - """获取第 i 个 TraceFrame 槽位""" - if _g_trace_frames is None or i < 0 or i >= TRACE_MAX: - return None - entry_size: t.CSizeT = TraceFrame.__sizeof__() - addr: t.CUInt64T = t.CUInt64T(_g_trace_frames) + i * entry_size - return (TraceFrame | t.CPtr)(t.CVoid(addr, t.CPtr)) + """获取第 i 个 TraceFrame 槽位(委托到 gen._get_trace_frame)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._get_trace_frame(i) + return None def push_trace(file_name: str, lineno: int, col_start: int = 0, col_end: int = 0): - """压入一个翻译上下文帧(进入新的翻译作用域时调用)""" - global _g_trace_count - if _ensure_trace_init() == 0: - return - if _g_trace_count >= TRACE_MAX: - return - frame: TraceFrame | t.CPtr = _get_trace_frame(_g_trace_count) - if frame is None: - return - frame.file_name = file_name - frame.lineno = lineno - frame.col_start = col_start - frame.col_end = col_end - _g_trace_count += 1 + """压入一个翻译上下文帧(委托到 gen.push_trace)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.push_trace(file_name, lineno, col_start, col_end) def pop_trace(): - """弹出栈顶帧(退出翻译作用域时调用)""" - global _g_trace_count - if _g_trace_count <= 0: - return - _g_trace_count -= 1 - frame: TraceFrame | t.CPtr = _get_trace_frame(_g_trace_count) - if frame is not None: - frame.file_name = None - frame.lineno = 0 - frame.col_start = 0 - frame.col_end = 0 + """弹出栈顶帧(委托到 gen.pop_trace)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.pop_trace() def clear_trace(): - """清空调用栈(每个文件翻译开始前调用)""" - global _g_trace_count - i: int - for i in range(_g_trace_count): - frame: TraceFrame | t.CPtr = _get_trace_frame(i) - if frame is not None: - frame.file_name = None - frame.lineno = 0 - frame.col_start = 0 - frame.col_end = 0 - _g_trace_count = 0 - - -# ============================================================ -# 全局 temp_dir(pyi 文件所在目录,由 BuildPipeline/Phase1 设置) -# -# 用于跨模块 CDefine 常量查找:当当前模块的 CDefine 表中找不到 -# 某个 Name 时,从 from_imports 解析出源模块,再从该模块的 pyi -# 文件中解析 CDefine 常量值。 -# ============================================================ -_g_temp_dir: str = None + """清空调用栈(委托到 gen.clear_trace)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.clear_trace() def set_temp_dir(temp_dir: str) -> None: - """设置全局 temp_dir(每个项目编译开始时由 BuildPipeline/Phase1 设置)""" - global _g_temp_dir - _g_temp_dir = temp_dir + """设置全局 temp_dir(委托到 gen.set_temp_dir)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.set_temp_dir(temp_dir) def get_temp_dir() -> str: - """获取全局 temp_dir""" - return _g_temp_dir - - -# ============================================================ -# 全局泛型特化上下文(由 _specialize_generic_class 设置/清除) -# -# 当翻译泛型类方法体时,需要将类型参数 T 替换为具体类型。 -# resolve_annotation_type 在解析 Name 节点时检查此上下文。 -# ============================================================ -_g_generic_tp_names: list[str] | t.CPtr = None -_g_generic_type_args: list[str] | t.CPtr = None - - -# ============================================================ -# 全局 CDefine 编译期常量表 -# -# 存储 NAME: t.CDefine = value 定义的常量, -# 供 t.CArray[elem_ty, NAME] 等 编译期类型解析使用。 -# 每个模块翻译开始时由 clear_cdefine_constants 清空。 -# ============================================================ -_g_cdefine_names: list[str] | t.CPtr = None -_g_cdefine_values: list[str] | t.CPtr = None -# 浮点 CDefine 标志(1=浮点常量,值存 %f 文本;0=整数常量) -_g_cdefine_double_flags: list[int] | t.CPtr = None -# 最近一次 lookup 是否浮点 CDefine(与 _g_cdefine_found 配合) -_g_cdefine_is_double: int = 0 - -# ============================================================ -# 当前模块 SHA1(Phase1 在模块开始翻译前设置,供报错使用) -# ============================================================ -_g_current_module_sha1: str = None + """获取全局 temp_dir(委托到 gen.get_temp_dir)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_temp_dir() + return None def set_current_module_sha1(sha1: str) -> None: - """设置当前正在编译的模块 SHA1(Phase1 在模块开始翻译前调用)""" - global _g_current_module_sha1 - _g_current_module_sha1 = sha1 + """设置当前正在编译的模块 SHA1(委托到 gen.set_current_module_sha1)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.set_current_module_sha1(sha1) -# ============================================================ -# _dbg_check_ast_floats - CHK-FLOAT 二分插桩(定位浮点 CDefine 值错误) -# -# 遍历 AST 树,打印所有 CONST_FLOAT 节点的 float_val。 -# 在多个时间点调用(PRE-TR=translate 前 / PRE-ML=模块级翻译前), -# 二分定位 Constant 节点 float_val 被覆写的具体阶段。 -# ============================================================ def _dbg_check_ast_floats(mb: memhub.MemBuddy | t.CPtr, tree: ast.AST | t.CPtr, tag: str): - """CHK-FLOAT: 遍历 AST 检查所有浮点 Constant 节点""" - if tree is None: - return - if tree.kind() == ast.ASTKind.Constant: - cn_f: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(tree) - if cn_f.const_kind == ast.CONST_FLOAT: - fb_chk: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_chk is not None: - stdio.snprintf(fb_chk, 1024, "[CHK-FLOAT] %s ptr=%p float_val=%.17g", - tag, t.CSizeT(cn_f), cn_f.float_val) - VLogger.info(fb_chk, "CHK") - return - # AnnAssign: value/annotation/target 不在 children 里,单独遍历 - if tree.kind() == ast.ASTKind.AnnAssign: - aa_f: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(tree) - if aa_f.value is not None: - _dbg_check_ast_floats(mb, aa_f.value, tag) - if aa_f.annotation is not None: - _dbg_check_ast_floats(mb, aa_f.annotation, tag) - if aa_f.target is not None: - _dbg_check_ast_floats(mb, aa_f.target, tag) - return - ch_f: list[ast.AST | t.CPtr] | t.CPtr = tree.children - if ch_f is not None: - n_f: t.CSizeT = ch_f.__len__() - i_f: t.CSizeT - for i_f in range(n_f): - c_f: ast.AST | t.CPtr = ch_f.get(i_f) - if c_f is not None: - _dbg_check_ast_floats(mb, c_f, tag) + """CHK-FLOAT: 遍历 AST 检查所有浮点 Constant 节点(委托到 gen._dbg_check_ast_floats)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g._dbg_check_ast_floats(mb, tree, tag) def register_cdefine_constant(pool: memhub.MemBuddy | t.CPtr, name: str, value: int) -> None: - """注册 CDefine 编译期常量到本地表 - - 值以十进制字符串存储。注意:value 是 32 位有符号整数, - 0xFFFFFFFF 会存储为 "-1",lookup 时用 found 标志区分"未找到"和值为 -1。 - """ - global _g_cdefine_names, _g_cdefine_values, _g_cdefine_double_flags - if _g_cdefine_names is None: - _g_cdefine_names = list[str](pool, 64) - _g_cdefine_values = list[str](pool, 64) - _g_cdefine_double_flags = list[int](pool, 64) - _g_cdefine_names.append(name) - val_buf: str = pool.alloc(32) - if val_buf is not None: - viperlib.snprintf(val_buf, 32, "%d", value) - _g_cdefine_values.append(val_buf) - else: - _g_cdefine_values.append("0") - if _g_cdefine_double_flags is not None: - _g_cdefine_double_flags.append(0) + """注册 CDefine 编译期常量到本地表(委托到 gen.register_cdefine_constant)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.register_cdefine_constant(pool, name, value) def register_cdefine_double(pool: memhub.MemBuddy | t.CPtr, name: str, value: double) -> None: - """注册浮点 CDefine 编译期常量(如 U_M_PI: t.CDefine = 3.14159...) - - 值以 %f 文本存储并标记浮点,供 translate_value 返回浮点常量。 - """ - global _g_cdefine_names, _g_cdefine_values, _g_cdefine_double_flags - if _g_cdefine_names is None: - _g_cdefine_names = list[str](pool, 64) - _g_cdefine_values = list[str](pool, 64) - _g_cdefine_double_flags = list[int](pool, 64) - _g_cdefine_names.append(name) - val_buf: str = pool.alloc(32) - if val_buf is not None: - # 用 CRT stdio.snprintf 而非 viperlib.snprintf:viperlib 自实现格式化器的 - # %g 浮点路径有 bug(%.17g 输出错误值,如 pi 显示 3.1397985 而非 3.1415926, - # 位模式 %a 正确),会导致 CDefine 表存错文本 → lookup 生成错 LLVM 常量。 - stdio.snprintf(val_buf, 32, "%.17g", value) - _g_cdefine_values.append(val_buf) - else: - _g_cdefine_values.append("0") - if _g_cdefine_double_flags is not None: - _g_cdefine_double_flags.append(1) - # CDEF-DBG: 打印注册的浮点 CDefine(定位 llc ret i32 0) - fb_cd: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_cd is not None: - stdio.snprintf(fb_cd, 1024, "REG-D: %s = %.17g (buf=%s)", - name, value, val_buf if val_buf is not None else "(null)") - VLogger.info(fb_cd, "CDEF-DBG") + """注册浮点 CDefine 编译期常量(委托到 gen.register_cdefine_double)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.register_cdefine_double(pool, name, value) def lookup_cdefine_constant(name: str) -> int: - """查找 CDefine 编译期常量 - - 返回找到的值。由于 -1 是合法值(如 INVALID_HANDLE_VALUE=0xFFFFFFFF=-1), - 用全局 _g_cdefine_found 标志区分"未找到"和值为 -1。 - 调用方应在调用后检查 _g_cdefine_found。 - 浮点 CDefine 项返回整数部分(与 _g_cdefine_is_double 标志配合)。 - """ - global _g_cdefine_found, _g_cdefine_is_double - _g_cdefine_found = 0 - _g_cdefine_is_double = 0 - if _g_cdefine_names is None: - return 0 - n: t.CSizeT = _g_cdefine_names.__len__() - i: t.CSizeT - for i in range(n): - nm: str = _g_cdefine_names.get(i) - if nm is not None and string.strcmp(nm, name) == 0: - val_str: str = _g_cdefine_values.get(i) - if val_str is not None: - _g_cdefine_found = 1 - if _g_cdefine_double_flags is not None and _g_cdefine_double_flags.get(i) == 1: - _g_cdefine_is_double = 1 - return string.atoi(val_str) - return string.atoi(val_str) + """查找 CDefine 编译期常量(委托到 gen.lookup_cdefine_constant)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.lookup_cdefine_constant(name) return 0 def lookup_cdefine_double(name: str) -> double: - """查找 CDefine 编译期常量,返回 double 值(浮点/整数统一) - - 与 lookup_cdefine_constant 共享 _g_cdefine_found / _g_cdefine_is_double - (found=1 且 is_double=1 → 浮点 CDefine,应返回浮点常量)。 - """ - global _g_cdefine_found, _g_cdefine_is_double - _g_cdefine_found = 0 - _g_cdefine_is_double = 0 - if _g_cdefine_names is None: - return 0.0 - n: t.CSizeT = _g_cdefine_names.__len__() - i: t.CSizeT - for i in range(n): - nm: str = _g_cdefine_names.get(i) - if nm is not None and string.strcmp(nm, name) == 0: - val_str: str = _g_cdefine_values.get(i) - if val_str is not None: - _g_cdefine_found = 1 - if _g_cdefine_double_flags is not None and _g_cdefine_double_flags.get(i) == 1: - _g_cdefine_is_double = 1 - ret_d: double = string.atof(val_str) - # CDEF-DBG: 打印浮点查找命中 - fb_cd: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_cd is not None: - stdio.snprintf(fb_cd, 1024, "LOOKUP-D: %s -> buf=%s atof=%.17g", name, val_str, ret_d) - VLogger.info(fb_cd, "CDEF-DBG") - return ret_d - ret_i2: double = double(string.atoi(val_str)) - # CDEF-DBG: 打印整数查找命中 - fb_cd: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_cd is not None: - viperlib.snprintf(fb_cd, 1024, "LOOKUP-I: %s -> buf=%s atoi=%d", name, val_str, string.atoi(val_str)) - VLogger.info(fb_cd, "CDEF-DBG") - return ret_i2 + """查找 CDefine 编译期常量,返回 double 值(委托到 gen.lookup_cdefine_double)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.lookup_cdefine_double(name) return 0.0 def is_cdefine_double() -> int: - """检查最近一次 CDefine 查找命中的是否是浮点常量""" - return _g_cdefine_is_double - - -_g_cdefine_found: int = 0 + """检查最近一次 CDefine 查找命中的是否是浮点常量(委托到 gen.is_cdefine_double)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.is_cdefine_double() + return 0 def is_cdefine_found() -> int: - """检查上次 lookup_cdefine_constant 是否找到值""" - return _g_cdefine_found + """检查上次 lookup_cdefine_constant 是否找到值(委托到 gen.is_cdefine_found)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.is_cdefine_found() + return 0 def set_cdefine_found(val: int) -> None: - """设置 cdefine_found 标志(供跨模块查找函数使用)""" - global _g_cdefine_found - _g_cdefine_found = val + """设置 cdefine_found 标志(委托到 gen.set_cdefine_found)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.set_cdefine_found(val) def clear_cdefine_constants() -> None: - """清空 CDefine 常量表(模块切换时调用)""" - global _g_cdefine_names, _g_cdefine_values, _g_cdefine_double_flags - _g_cdefine_names = None - _g_cdefine_values = None - _g_cdefine_double_flags = None - - -# ============================================================ -# 动态 CTypedef 表 -# -# 存储 NAME: t.CTypedef = Type 定义的类型别名, -# 供 resolve_annotation_type 动态解析用户自定义 CTypedef。 -# 每个模块翻译开始时由 clear_ctypedefs 清空(模块级隔离)。 -# 与 CDefine 表类似,但存储类型表达式字符串而非整数。 -# ============================================================ -_g_ctypedef_names: list[str] | t.CPtr = None -_g_ctypedef_type_strs: list[str] | t.CPtr = None - -# CTypedef 查找结果标志(区分"未找到"和"值为空字符串") -_g_ctypedef_found: int = 0 - -# CTypedef 递归解析深度计数器(防止无限递归) -_g_ctypedef_resolve_depth: int = 0 - -# CTypedef 递归解析最大深度 -MAX_CTYPEDEF_DEPTH: t.CDefine = 10 - -# CTypedef 循环检测已访问列表(存储正在解析的 CTypedef 名) -_g_ctypedef_visiting: list[str] | t.CPtr = None + """清空 CDefine 常量表(委托到 gen.clear_cdefine_constants)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.clear_cdefine_constants() def register_ctypedef(pool: memhub.MemBuddy | t.CPtr, name: str, type_str: str) -> None: - """注册 CTypedef 到本地表 - - Args: - pool: 内存池 - name: CTypedef 名称(如 "HANDLE") - type_str: 类型表达式字符串(如 "VOIDPTR" 或 "t.CVoid | t.CPtr") - """ - global _g_ctypedef_names, _g_ctypedef_type_strs - if name is None or type_str is None or pool is None: - return - if _g_ctypedef_names is None: - _g_ctypedef_names = list[str](pool, 64) - _g_ctypedef_type_strs = list[str](pool, 64) - # 去重:若已存在同名 CTypedef,更新其类型字符串 - if _g_ctypedef_names is not None: - exist_n: t.CSizeT = _g_ctypedef_names.__len__() - ei: t.CSizeT - for ei in range(exist_n): - en: str = _g_ctypedef_names.get(ei) - if en is not None and string.strcmp(en, name) == 0: - # 已存在,更新类型字符串 - _g_ctypedef_type_strs.set(ei, type_str) - return - _g_ctypedef_names.append(name) - _g_ctypedef_type_strs.append(type_str) + """注册 CTypedef 到本地表(委托到 gen.register_ctypedef)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.register_ctypedef(pool, name, type_str) def lookup_ctypedef(name: str) -> str: - """查找 CTypedef,返回类型表达式字符串 - - 返回找到的类型表达式字符串,未找到返回 None。 - 调用方应在调用后检查 _g_ctypedef_found 标志区分"未找到"和"空字符串"。 - """ - global _g_ctypedef_found - _g_ctypedef_found = 0 - if name is None: - return None - if _g_ctypedef_names is None: - return None - n: t.CSizeT = _g_ctypedef_names.__len__() - i: t.CSizeT - for i in range(n): - nm: str = _g_ctypedef_names.get(i) - if nm is not None and string.strcmp(nm, name) == 0: - ts: str = _g_ctypedef_type_strs.get(i) - _g_ctypedef_found = 1 - return ts + """查找 CTypedef,返回类型表达式字符串(委托到 gen.lookup_ctypedef)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.lookup_ctypedef(name) return None def is_ctypedef_found() -> int: - """检查上次 lookup_ctypedef 是否找到值""" - return _g_ctypedef_found + """检查上次 lookup_ctypedef 是否找到值(委托到 gen.is_ctypedef_found)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.is_ctypedef_found() + return 0 def clear_ctypedefs() -> None: - """清空 CTypedef 表(模块切换时调用)""" - global _g_ctypedef_names, _g_ctypedef_type_strs - global _g_ctypedef_resolve_depth, _g_ctypedef_visiting - _g_ctypedef_names = None - _g_ctypedef_type_strs = None - _g_ctypedef_resolve_depth = 0 - _g_ctypedef_visiting = None + """清空 CTypedef 表(委托到 gen.clear_ctypedefs)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.clear_ctypedefs() def _ctypedef_push_visiting(pool: memhub.MemBuddy | t.CPtr, name: str) -> int: - """将 CTypedef 名加入正在解析列表(循环检测) - - Returns: - 0=成功加入(无循环),1=检测到循环 - """ - global _g_ctypedef_visiting - if name is None: - return 0 - if _g_ctypedef_visiting is None: - _g_ctypedef_visiting = list[str](pool, 32) - if _g_ctypedef_visiting is None: - return 0 - vn: t.CSizeT = _g_ctypedef_visiting.__len__() - vi: t.CSizeT - for vi in range(vn): - vs: str = _g_ctypedef_visiting.get(vi) - if vs is not None and string.strcmp(vs, name) == 0: - return 1 # 循环检测 - _g_ctypedef_visiting.append(name) + """将 CTypedef 名加入正在解析列表(委托到 gen._ctypedef_push_visiting)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._ctypedef_push_visiting(pool, name) return 0 def _ctypedef_pop_visiting() -> None: - """从正在解析列表弹出最后一个 CTypedef 名""" - global _g_ctypedef_visiting - if _g_ctypedef_visiting is None: - return - vn: t.CSizeT = _g_ctypedef_visiting.__len__() - if vn > 0: - _g_ctypedef_visiting.pop() + """从正在解析列表弹出最后一个 CTypedef 名(委托到 gen._ctypedef_pop_visiting)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g._ctypedef_pop_visiting() def _is_ctypedef_annotation(annotation: ast.AST | t.CPtr) -> int: - """检测类型注解是否为 t.CTypedef - - Args: - annotation: 类型注解 AST 节点 - - Returns: - 1=是 t.CTypedef,0=否 - """ - if annotation is None: - return 0 - if annotation.kind() != ast.ASTKind.Attribute: - return 0 - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annotation) - if at.attr is None: - return 0 - if string.strcmp(at.attr, "CTypedef") != 0: - return 0 - if at.value is None or at.value.kind() != ast.ASTKind.Name: - return 0 - mod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if mod_nm.id is None: - return 0 - if string.strcmp(mod_nm.id, "t") != 0: - return 0 - return 1 + """检测类型注解是否为 t.CTypedef(委托到 gen._is_ctypedef_annotation)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._is_ctypedef_annotation(annotation) + return 0 def ScanCTypedefDeclarations(pool: memhub.MemBuddy | t.CPtr, tree: ast.AST | t.CPtr) -> int: - """扫描 AST 顶层节点,注册所有 NAME: t.CTypedef = Type 声明 - - 在 _translate_module_level 中、模块级变量预注册之前调用, - 确保 CTypedef 名称在类型解析时可用。 - - Args: - pool: 内存池 - tree: 模块 AST 根节点 - - Returns: - 注册的 CTypedef 数量 - """ - if pool is None or tree is None: - return 0 - ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children - if ch is None: - return 0 - n: t.CSizeT = ch.__len__() - count: int = 0 - i: t.CSizeT - for i in range(n): - child: ast.AST | t.CPtr = ch.get(i) - if child is None: - continue - if child.kind() != ast.ASTKind.AnnAssign: - continue - aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(child) - # 检测注解是否为 t.CTypedef - if _is_ctypedef_annotation(aa.annotation) == 0: - continue - # 提取目标名称(必须是 Name 节点) - if aa.target is None or aa.target.kind() != ast.ASTKind.Name: - continue - tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target) - if tgt.id is None: - continue - # 提取类型表达式字符串(从 value AST 节点) - if aa.value is None: - continue - type_str: str = _get_type_name_from_annotation(pool, aa.value) - if type_str is None: - continue - # 注册 CTypedef - register_ctypedef(pool, tgt.id, type_str) - count += 1 - return count + """扫描 AST 顶层节点,注册所有 NAME: t.CTypedef = Type 声明(委托到 gen.ScanCTypedefDeclarations)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.ScanCTypedefDeclarations(pool, tree) + return 0 -# 常量整数表达式计算成功标志(供 _eval_const_int_expr 使用) -_g_const_eval_ok: int = 0 - - -# ============================================================ -# _eval_const_int_expr - 递归计算常量整数表达式 -# -# 支持: -# - Constant (CONST_INT): 整数字面量 -# - Name: CDefine 常量名(通过 lookup_cdefine_constant 查找) -# - BinOp (Add/Sub/Mult/FloorDiv/BitOr/BitAnd): 递归计算左右操作数 -# -# 成功: 设置 _g_const_eval_ok=1, 返回计算值 -# 失败: 设置 _g_const_eval_ok=0, 返回 0 -# -# 用于 t.CArray count 的静态计算,如 2 * ZHUFF_MAX_CODES -# ============================================================ def _eval_const_int_expr(node: ast.AST | t.CPtr) -> int: - """递归计算常量整数表达式""" - global _g_const_eval_ok - if node is None: - _g_const_eval_ok = 0 - return 0 - k: int = node.kind() - - # Constant: 整数字面量 - if k == ast.ASTKind.Constant: - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) - if cn.const_kind == ast.CONST_INT: - _g_const_eval_ok = 1 - return cn.int_val - _g_const_eval_ok = 0 - return 0 - - # Name: CDefine 常量名 - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - if nm.id is None: - _g_const_eval_ok = 0 - return 0 - val: int = lookup_cdefine_constant(nm.id) - if is_cdefine_found() == 0: - _g_const_eval_ok = 0 - return 0 - _g_const_eval_ok = 1 - return val - - # BinOp: 算术/位运算 - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) - # 递归计算左操作数 - lv: int = _eval_const_int_expr(bop.left) - if _g_const_eval_ok == 0: - return 0 - # 递归计算右操作数 - rv: int = _eval_const_int_expr(bop.right) - if _g_const_eval_ok == 0: - return 0 - # 根据运算符执行计算 - if bop.op == ast.OpKind.Add: - _g_const_eval_ok = 1 - return lv + rv - if bop.op == ast.OpKind.Sub: - _g_const_eval_ok = 1 - return lv - rv - if bop.op == ast.OpKind.Mult: - _g_const_eval_ok = 1 - return lv * rv - if bop.op == ast.OpKind.FloorDiv: - if rv == 0: - _g_const_eval_ok = 0 - return 0 - _g_const_eval_ok = 1 - return lv // rv - if bop.op == ast.OpKind.BitOr: - _g_const_eval_ok = 1 - return lv | rv - if bop.op == ast.OpKind.BitAnd: - _g_const_eval_ok = 1 - return lv & rv - # 不支持的运算符 - _g_const_eval_ok = 0 - return 0 - - # 不支持的节点类型 - _g_const_eval_ok = 0 + """递归计算常量整数表达式(委托到 gen._eval_const_int_expr)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._eval_const_int_expr(node) return 0 def set_generic_context(tp_names: list[str] | t.CPtr, type_args: list[str] | t.CPtr): - """设置泛型特化上下文(进入泛型类方法体翻译时调用)""" - global _g_generic_tp_names, _g_generic_type_args - _g_generic_tp_names = tp_names - _g_generic_type_args = type_args + """设置泛型特化上下文(委托到 gen.set_generic_context)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.set_generic_context(tp_names, type_args) def clear_generic_context(): - """清除泛型特化上下文(离开泛型类方法体翻译时调用)""" - global _g_generic_tp_names, _g_generic_type_args - _g_generic_tp_names = None - _g_generic_type_args = None + """清除泛型特化上下文(委托到 gen.clear_generic_context)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.clear_generic_context() def resolve_generic_type_name(name: str) -> str: - """如果 name 是泛型类型参数,返回对应的具体类型名;否则返回 name 本身 - - 用于表达式中的 T 替换(如 T.__sizeof__() → int.__sizeof__()) - """ - if name is None: - return name - if _g_generic_tp_names is not None and _g_generic_type_args is not None: - rg_n: t.CSizeT = _g_generic_tp_names.__len__() - rg_i: t.CSizeT - for rg_i in range(rg_n): - rg_tpn: str = _g_generic_tp_names.get(rg_i) - if rg_tpn is not None and string.strcmp(name, rg_tpn) == 0: - rg_ta: str = _g_generic_type_args.get(rg_i) - if rg_ta is not None: - return rg_ta + """如果 name 是泛型类型参数,返回对应的具体类型名(委托到 gen.resolve_generic_type_name)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.resolve_generic_type_name(name) return name -# ============================================================ -# _get_type_name_from_annotation - 从类型注解节点提取类型名字符串 -# -# 用于泛型特化时构造 mangled name(如 "list[AST|t.CPtr]") -# -# Name(id="AST") -> "AST" -# Attribute(value=Name(id="t"), attr="CPtr") -> "t.CPtr" -# BinOp(Name("AST"), BitOr, Attribute(Name("t"), "CPtr")) -> "AST|t.CPtr" -# ============================================================ def _get_type_name_from_annotation(pool: memhub.MemBuddy | t.CPtr, node: ast.AST | t.CPtr) -> str: - """从类型注解节点提取类型名(支持 Name/Attribute/BinOp)""" - if node is None: - return None - k: int = node.kind() - # Constant: 字符串注解,直接返回字符串值 - if k == ast.ASTKind.Constant: - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) - if cn.const_kind == ast.CONST_STR and cn.str_val is not None: - return cn.str_val - return None - # Name: 直接返回 id(泛型特化上下文内先做 T 替换,避免 ndarray[T] 中 T 未解析 - # 导致 _specialize_generic_class("ndarray", ["T"]) 二次递归崩溃) - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - return resolve_generic_type_name(nm.id) - # Attribute: 构造 "module.attr" 格式 - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - if at.attr is None: - return None - if at.value is not None and at.value.kind() == ast.ASTKind.Name: - mod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if mod_nm.id is not None: - total: t.CSizeT = string.strlen(mod_nm.id) + 1 + string.strlen(at.attr) + 1 - buf: str = pool.alloc(total) - if buf is not None: - buf[0] = '\0' - string.strcat(buf, mod_nm.id) - string.strcat(buf, ".") - string.strcat(buf, at.attr) - return buf - return at.attr - # BinOp (BitOr): 构造 "left|right" 格式 - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) - if bop.op == ast.OpKind.BitOr: - left_str: str = _get_type_name_from_annotation(pool, bop.left) - right_str: str = _get_type_name_from_annotation(pool, bop.right) - if left_str is not None and right_str is not None: - total2: t.CSizeT = string.strlen(left_str) + 1 + string.strlen(right_str) + 1 - buf2: str = pool.alloc(total2) - if buf2 is not None: - buf2[0] = '\0' - string.strcat(buf2, left_str) - string.strcat(buf2, "|") - string.strcat(buf2, right_str) - return buf2 - return None + """从类型注解节点提取类型名(委托到 gen._get_type_name_from_annotation)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._get_type_name_from_annotation(pool, node) return None -# ============================================================ -# _parse_type_string - 将类型名字符串解析回 AST 节点 -# -# _get_type_name_from_annotation 的逆操作,用于泛型特化时 -# 从 type_args 字符串重建 AST 节点(_clone_annotation 和 -# resolve_annotation_type 的泛型上下文替换) -# -# "AST" -> Name("AST") -# "t.CPtr" -> Attribute(Name("t"), "CPtr") -# "AST|t.CPtr" -> BinOp(Name("AST"), BitOr, Attribute(Name("t"), "CPtr")) -# ============================================================ def _parse_type_string(pool: memhub.MemBuddy | t.CPtr, type_str: str, ctx: t.CInt) -> ast.AST | t.CPtr: - """将类型名字符串解析为 AST 节点 - - 正确处理 '|' 与 '.' 周围的空格(如 "ParsedArgs | t.CPtr"): - - '|' 分割后左段可能带尾随空格("ParsedArgs "),右段可能带前导空格(" t.CPtr") - - 段内空格会导致 Name.id 带空格("ParsedArgs "、" t"),结构体/模块按名查找失败, - 最终退化 i8*/i32,如 parse_args -> "ParsedArgs | t.CPtr" 解析出垃圾类型。 - """ - if type_str is None or pool is None: - return None - - # 跳过前导空格('|' 分割后的右段可能带前导空格) - while type_str[0] == ' ': - type_str += 1 - - seg_len: t.CSizeT = string.strlen(type_str) - # 去除段尾随空格('|' 分割后的左段可能带尾随空格) - while seg_len > 0 and type_str[seg_len - 1] == ' ': - seg_len -= 1 - - # 检查是否包含 | (BinOp):只在有效段 [0, seg_len) 内查找 - pipe_idx: t.CSizeT = seg_len - pi: t.CSizeT = 0 - while pi < seg_len: - if type_str[pi] == '|': - pipe_idx = pi - break - pi += 1 - if pipe_idx < seg_len: - # 左段复制到独立缓冲(trim 尾随空格),不破坏原字符串 - left_len: t.CSizeT = pipe_idx - while left_len > 0 and type_str[left_len - 1] == ' ': - left_len -= 1 - left_buf: bytes = stdlib.malloc(left_len + 1) - if left_buf is None: - return None - string.strncpy(left_buf, type_str, left_len) - left_buf[left_len] = '\0' - left_node: ast.AST | t.CPtr = _parse_type_string(pool, left_buf, ctx) - # 右段前导空格由递归入口跳过 - right_node: ast.AST | t.CPtr = _parse_type_string( - pool, type_str + pipe_idx + 1, ctx) - stdlib.free(left_buf) - if left_node is not None and right_node is not None: - return ast.BinOp(pool, left_node, ast.OpKind.BitOr, right_node) - return None - - # 检查是否包含 . (Attribute):只在有效段 [0, seg_len) 内查找 - dot_idx: t.CSizeT = seg_len - di: t.CSizeT = 0 - while di < seg_len: - if type_str[di] == '.': - dot_idx = di - break - di += 1 - if dot_idx < seg_len: - # 模块名段 trim 尾随空格 - mod_len: t.CSizeT = dot_idx - while mod_len > 0 and type_str[mod_len - 1] == ' ': - mod_len -= 1 - mod_buf: bytes = stdlib.malloc(mod_len + 1) - if mod_buf is None: - return None - string.strncpy(mod_buf, type_str, mod_len) - mod_buf[mod_len] = '\0' - module_node: ast.AST | t.CPtr = ast.Name(pool, mod_buf, ctx) - # attr 段 trim 尾随空格 - attr_str: str = type_str + dot_idx + 1 - attr_len: t.CSizeT = string.strlen(attr_str) - while attr_len > 0 and attr_str[attr_len - 1] == ' ': - attr_len -= 1 - attr_buf: bytes = stdlib.malloc(attr_len + 1) - if attr_buf is None: - stdlib.free(mod_buf) - return None - string.strncpy(attr_buf, attr_str, attr_len) - attr_buf[attr_len] = '\0' - attr_node: ast.AST | t.CPtr = ast.Attribute(pool, module_node, attr_buf, ctx) - stdlib.free(mod_buf) - stdlib.free(attr_buf) - return attr_node - - # 普通 Name(trim 尾随空格,ast.Name 内部 _copy_str 复制) - name_buf: bytes = stdlib.malloc(seg_len + 1) - if name_buf is None: - return None - string.strncpy(name_buf, type_str, seg_len) - name_buf[seg_len] = '\0' - name_node: ast.AST | t.CPtr = ast.Name(pool, name_buf, ctx) - stdlib.free(name_buf) - return name_node + """将类型名字符串解析为 AST 节点(委托到 gen._parse_type_string)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._parse_type_string(pool, type_str, ctx) + return None -# ============================================================ -# _parse_type_string_ptr 已移除 -# -# 原先用 t.CPtr 包装绕过旧编译器对 ast.AST|t.CPtr 跨模块返回类型 -# 推断为 i32 的 bug。现在已在 _infer_external_func_ret_ty 中注册 -# _parse_type_string 返回 i8*,外部模块直接调用 _parse_type_string。 -# ============================================================ - - -# ============================================================ -# set_current_file - 设置当前编译的文件名 -# -# 在 BuildPipeline.TranslateFileGetTrans 中每翻译一个文件前调用 -# ============================================================ def set_current_file(file_path: str): - """设置当前编译的文件名(供报错使用)""" - global _g_current_file - _g_current_file = file_path + """设置当前编译的文件名(委托到 gen.set_current_file)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.set_current_file(file_path) def get_current_file() -> str: - """获取当前编译的文件名(供报错归因使用)""" - return _g_current_file + """获取当前编译的文件名(委托到 gen.get_current_file)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_current_file() + return None -# ============================================================ -# _read_source_line - 从源文件读取第 lineno 行 -# -# 返回行内容字符串(不含换行符),失败返回 None -# ============================================================ -_SRC_BUF_SIZE: t.CDefine = 262144 - def _read_source_line(file_path: str, lineno: int) -> str: - """从源文件读取第 lineno 行内容""" - if file_path is None or lineno <= 0: - return None - f: fileio.File | t.CPtr = fileio.File(file_path, fileio.MODE.R) - if f.closed: - return None - buf: bytes = stdlib.malloc(_SRC_BUF_SIZE) - if buf is None: - f.close() - return None - bytes_read: LONG = f.read_all(buf, _SRC_BUF_SIZE) - f.close() - if bytes_read <= 0: - stdlib.free(buf) - return None - # 逐行查找第 lineno 行 - cur_line: int = 1 - line_start: t.CSizeT = 0 - for i in range(bytes_read): - if buf[i] == '\n': - if cur_line == lineno: - line_len: t.CSizeT = i - line_start - if line_len > 0 and buf[line_start + line_len - 1] == '\r': - line_len -= 1 - line_buf: bytes = stdlib.malloc(line_len + 1) - if line_buf is not None: - string.strncpy(line_buf, buf + line_start, line_len) - line_buf[line_len] = '\0' - stdlib.free(buf) - return line_buf - stdlib.free(buf) - return None - cur_line += 1 - line_start = i + 1 - stdlib.free(buf) + """从源文件读取第 lineno 行内容(委托到 gen._read_source_line)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._read_source_line(file_path, lineno) return None def read_source_line(file_path: str, lineno: int) -> str: - """公开包装:从源文件读取第 lineno 行内容(供 traceback 展示)""" - return _read_source_line(file_path, lineno) + """公开包装:从源文件读取第 lineno 行内容(委托到 gen.read_source_line)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.read_source_line(file_path, lineno) + return None -# ============================================================ -# dump_parse_traceback - 解析失败时以 Python 风格输出 traceback -# -# 格式(与 fatal_error 一致): -# Traceback (most recent call last): -# File "path", line N -# -# ^ ← 列标记(可选) -# SyntaxError: -# -# 数据来源: ast.get_parse_err_line/col/msg(parser 记录的首次错误) -# ============================================================ def dump_parse_traceback(file_path: str): - """解析失败时以 Python 风格输出 traceback(仿 fatal_error)""" - err_line: int = ast.get_parse_err_line() - err_col: int = ast.get_parse_err_col() - err_msg: str = ast.get_parse_err_msg() - stdio.printf("Traceback (most recent call last):\n") - if file_path is None or file_path[0] == 0: - file_path = "" - if err_line > 0: - stdio.printf(' File "%s", line %d\n', file_path, err_line) - src: str = _read_source_line(file_path, err_line) - if src is not None: - stdio.printf(" %s\n", src) - # 列标记:在出错 token 起始列下方标 ^(parser 的 col_offset 是 0-based, - # 前缀 4 空格 + err_col 个空格后落点恰好是该 token 首字符) - if err_col > 0: - stdio.printf(" ") - c: int - for c in range(err_col): - stdio.printf(" ") - stdio.printf("^\n") - stdlib.free(src) - else: - stdio.printf(' File "%s"\n', file_path) - if err_msg is None or err_msg[0] == 0: - err_msg = "语法错误" - stdio.printf("SyntaxError: %s\n", err_msg) + """解析失败时以 Python 风格输出 traceback(委托到 gen.dump_parse_traceback)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.dump_parse_traceback(file_path) -# ============================================================ -# fatal_error - 以 Python 风格报错并退出(支持多帧、错误类型、列范围) -# -# 格式: -# Traceback (most recent call last): -# File "path1", line N1 -# source code line 1 -# File "path2", line N2 -# source code line 2 -# ^^^^ ← 列范围标记(可选) -# TypeError: msg -# -# 参数: -# node: AST 节点(提供行号),可为 None -# msg: 错误消息 -# err_type: 错误类型字符串(默认 "SyntaxError") -# col_start: 列起始(1-based,0=不标记列范围) -# col_end: 列结束(1-based,0=不标记列范围) -# ============================================================ def fatal_error(node: ast.AST | t.CPtr, msg: str, err_type: str = "SyntaxError", col_start: int = 0, col_end: int = 0): - """以 Python 风格报错并退出(支持多帧、错误类型、列范围) - - 向后兼容:err_type/col_start/col_end 有默认值,旧调用 fatal_error(node, msg) 仍可用。 - """ - stdio.printf("Traceback (most recent call last):\n") - # 输出调用栈帧(从底到顶) - i: int - for i in range(_g_trace_count): - frame: TraceFrame | t.CPtr = _get_trace_frame(i) - if frame is not None and frame.file_name is not None: - if frame.lineno > 0: - stdio.printf(' File "%s", line %d\n', frame.file_name, frame.lineno) - src: str = _read_source_line(frame.file_name, frame.lineno) - if src is not None: - stdio.printf(" %s\n", src) - stdlib.free(src) - else: - stdio.printf(' File "%s"\n', frame.file_name) - # 输出当前帧(node 对应的位置) - lineno: int = 0 - if node is not None: - lineno = node.lineno - file_name: str = _g_current_file - if file_name is None: - file_name = "" - # 行号合理性防御:先读取该行源码,验证 node.lineno 是否落在当前文件内。 - # 若读不到(文件不存在或行号超出范围),说明文件/行号归属不可信 - # (如 AST 树被内存复用/串扰后跨文件报错),打印警告而非误导性行号。 - src_line: str = None - line_ok: int = 1 - if lineno > 0 and string.strcmp(file_name, "") != 0: - src_line = _read_source_line(file_name, lineno) - if src_line is None: - line_ok = 0 - if line_ok == 0: - stdio.printf(' File "%s", line %d (!! 无法读取该行源码:文件不存在或行号超出范围,错误可能来自被复用的 AST 树,请以错误消息为准)\n', - file_name, lineno) - else: - stdio.printf(' File "%s", line %d\n', file_name, lineno) - if src_line is not None: - stdio.printf(" %s\n", src_line) - # 列范围标记:在源代码行下方用 ^ 标记出错范围 - if col_start > 0 and col_end >= col_start: - stdio.printf(" ") - j: int - for j in range(col_end): - if j >= col_start - 1 and j < col_end: - stdio.printf("^") - else: - stdio.printf(" ") - stdio.printf("\n") - stdlib.free(src_line) - # 输出错误类型 + 消息 - if err_type is None or err_type[0] == 0: - err_type = "SyntaxError" - stdio.printf("%s: %s\n", err_type, msg) - sys.exit(1) + """以 Python 风格报错并退出(委托到 gen.fatal_error)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.fatal_error(node, msg, err_type, col_start, col_end) -# ============================================================ -# fatal_type_error - 类型错误别名(err_type="TypeError") -# ============================================================ def fatal_type_error(node: ast.AST | t.CPtr, msg: str, col_start: int = 0, col_end: int = 0): - """以 Python 风格报错并退出(TypeError 版本)""" - fatal_error(node, msg, "TypeError", col_start, col_end) + """以 Python 风格报错并退出(TypeError 版本,委托到 gen.fatal_type_error)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g.fatal_type_error(node, msg, col_start, col_end) -# ============================================================ -# try_extract_callable_ret - 提取 t.Callable 注解的返回类型 -# -# t.Callable[[A, B], Ret] → Ret 的 LLVMType; -# 非 Callable 注解返回 None。供函数指针变量签名缓存使用。 -# ============================================================ def try_extract_callable_ret(pool: memhub.MemBuddy | t.CPtr, annot: ast.AST | t.CPtr, imported_modules: str, from_imports: str, trans: HT.Translator | t.CPtr) -> llvmlite.LLVMType | t.CPtr: - """提取 t.Callable 注解的返回类型 LLVMType;非 Callable 注解返回 None""" - if annot is None or annot.kind() != ast.ASTKind.Subscript: - return None - sub_cr: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(annot) - if sub_cr.value is None or sub_cr.value.kind() != ast.ASTKind.Attribute: - return None - at_cr: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(sub_cr.value) - if at_cr.attr is None or string.strcmp(at_cr.attr, "Callable") != 0: - return None - # slice 必须是 Tuple(elts=[args_list, ret_node]) - if sub_cr.slice is None or sub_cr.slice.kind() != ast.ASTKind.Tuple: - return None - tp_cr: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(sub_cr.slice) - if tp_cr.elts is None or tp_cr.elts.__len__() != 2: - return None - ret_node_cr: ast.AST | t.CPtr = tp_cr.elts.get(1) - if ret_node_cr is None: - return None - return resolve_annotation_type(pool, ret_node_cr, imported_modules, from_imports, trans) - -# ============================================================ -# 将 t.CXxx 类型名映射到 LLVMType(纯函数) -# ============================================================ -def map_t_type(pool: memhub.MemBuddy | t.CPtr, - type_name: str) -> llvmlite.LLVMType | t.CPtr: - """将 t.CXxx / c.CXxx 类型名映射到 LLVMType - - 注意: t.CChar | t.CPtr = i8* = str = bytes - """ - if type_name is None: - return None - - # 基本整数类型 - if string.strcmp(type_name, "CInt") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "CChar") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "CShort") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "CLong") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "CLongLong") == 0: - return llvmlite.Int64(pool) - # 精确宽度有符号类型 - elif string.strcmp(type_name, "CInt8T") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "CInt16T") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "CInt32T") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "CInt64T") == 0: - return llvmlite.Int64(pool) - # 精确宽度无符号类型 - elif string.strcmp(type_name, "CUInt8T") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "CUInt16T") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "CUInt32T") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "CUInt64T") == 0: - return llvmlite.Int64(pool) - # 浮点类型 - elif string.strcmp(type_name, "CFloat") == 0: - return llvmlite.Float(pool) - elif string.strcmp(type_name, "CDouble") == 0: - return llvmlite.Double(pool) - # 精确宽度浮点类型(t.py 的 float_map: 8/16→half, 32→float, 64→double, 128→fp128) - elif string.strcmp(type_name, "CFloat8T") == 0: - return llvmlite.Half(pool) - elif string.strcmp(type_name, "CFloat16T") == 0: - return llvmlite.Half(pool) - elif string.strcmp(type_name, "CFloat32T") == 0: - return llvmlite.Float(pool) - elif string.strcmp(type_name, "CFloat64T") == 0: - return llvmlite.Double(pool) - elif string.strcmp(type_name, "CFloat128T") == 0: - return llvmlite.FP128(pool) - # 指针/void: t.CPtr = i8*, t.CChar | t.CPtr = i8* = str = bytes - elif string.strcmp(type_name, "CPtr") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "CVoid") == 0: - return llvmlite.Void(pool) - # CNeedPtr/CAutoPtr: 参数自动取地址标记,LLVM 层均为通用指针 i8*。 - # (TPC 中二者继承 CPtr;TPV 未实现调用点自动取地址,非指针实参应在调用点报错, - # 而非静默降级为 i32 导致指针截断。) - elif string.strcmp(type_name, "CNeedPtr") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "CAutoPtr") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - # 无符号修饰 - elif string.strcmp(type_name, "CUnsigned") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "CUnsignedInt") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "CUnsignedChar") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "CUnsignedShort") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "CUnsignedLong") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "CUnsignedLongLong") == 0: - return llvmlite.Int64(pool) - # size_t / ptr 类型 - elif string.strcmp(type_name, "CSizeT") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "CIntPtrT") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "CUIntPtrT") == 0: - return llvmlite.Int64(pool) - # bool - elif string.strcmp(type_name, "CBool") == 0: - # bool = t.CBool = i1(LLVM 1 位整数,语义与 C _Bool 一致) - return llvmlite.Int1(pool) - # ptrdiff_t - elif string.strcmp(type_name, "CPtrDiffT") == 0: - return llvmlite.Int64(pool) - - # ============================================================ - # stdint.py 大写别名(Win32/TransPyC 风格) - # ============================================================ - # 整数类型 - elif string.strcmp(type_name, "INT") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "BOOL") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "UINT") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "BYTE") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "WORD") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "DWORD") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "QWORD") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "TCHAR") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "VOID") == 0: - return llvmlite.Void(pool) - elif string.strcmp(type_name, "SHORT") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "USHORT") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "LONGLONG") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "ULONGLONG") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "LONG") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "ULONG") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "WCHAR") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "FLOAT") == 0: - return llvmlite.Float(pool) - elif string.strcmp(type_name, "DOUBLE") == 0: - return llvmlite.Double(pool) - # 小写裸名浮点类型(float = t.CFloat = f32, double = t.CDouble = f64) - elif string.strcmp(type_name, "float") == 0: - return llvmlite.Float(pool) - elif string.strcmp(type_name, "double") == 0: - return llvmlite.Double(pool) - elif string.strcmp(type_name, "FSIZE_t") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "LBA_t") == 0: - return llvmlite.Int32(pool) - # 定长整数 - elif string.strcmp(type_name, "INT8") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "INT16") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "INT32") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "INT64") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "UINT8") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "UINT16") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "UINT32") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "UINT64") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "CHAR8") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "CHAR16") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "CHAR32") == 0: - return llvmlite.Int32(pool) - # 小写简写 - elif string.strcmp(type_name, "i8") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "i16") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "i32") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "i64") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "u8") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "u16") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "u32") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "u64") == 0: - return llvmlite.Int64(pool) - # size_t 系列 - elif string.strcmp(type_name, "SIZE_T") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "SSIZE_T") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "PTRDIFF_T") == 0: - return llvmlite.Int64(pool) - - # stdint 指针类型(XxxPTR = XxxType | t.CPtr) - elif string.strcmp(type_name, "INTPTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int32(pool)) - elif string.strcmp(type_name, "UINTPTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int32(pool)) - elif string.strcmp(type_name, "BYTEPTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "CHARLIST") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "SHORTPTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int16(pool)) - elif string.strcmp(type_name, "USHORTPTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int16(pool)) - elif string.strcmp(type_name, "WCHARPTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int16(pool)) - elif string.strcmp(type_name, "CHARPTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "VOIDPTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - # Windows API 跨模块 typedef(win32base.py 中定义) - # HANDLE = VOIDPTR = i8*,LPCSTR = const char* = i8*,LPCWSTR = const wchar_t* = i16* - elif string.strcmp(type_name, "HANDLE") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "LPCSTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "LPCWSTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int16(pool)) - elif string.strcmp(type_name, "INT8PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "INT16PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int16(pool)) - elif string.strcmp(type_name, "INT32PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int32(pool)) - elif string.strcmp(type_name, "INT64PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int64(pool)) - elif string.strcmp(type_name, "UINT8PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "UINT16PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int16(pool)) - elif string.strcmp(type_name, "UINT32PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int32(pool)) - elif string.strcmp(type_name, "UINT64PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int64(pool)) - elif string.strcmp(type_name, "CHAR8PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "CHAR16PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int16(pool)) - elif string.strcmp(type_name, "CHAR32PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int32(pool)) - - # C 标准 小写 _t 类型 - elif string.strcmp(type_name, "int8_t") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "int16_t") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "int32_t") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "int64_t") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "uint8_t") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "uint16_t") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "uint32_t") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "uint64_t") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "size_t") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "ssize_t") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "ptrdiff_t") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "intptr_t") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "uintptr_t") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "wchar_t") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "char8_t") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "char16_t") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "char32_t") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "_Bool") == 0: - return llvmlite.Int8(pool) + """提取 t.Callable 注解的返回类型 LLVMType(委托到 gen.try_extract_callable_ret)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.try_extract_callable_ret(pool, annot, imported_modules, from_imports, trans) + return None + + +def map_t_type(pool: memhub.MemBuddy | t.CPtr, + type_name: str) -> llvmlite.LLVMType | t.CPtr: + """将 t.CXxx / c.CXxx 类型名映射到 LLVMType(委托到 gen.map_t_type)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.map_t_type(pool, type_name) return None -# ============================================================ -# _is_t_attr - 检测节点是否是 t.attr_name 形式(如 t.CPtr, t.CVoid) -# -# 用于联合类型注解中检测指针包装标记 (t.CPtr) 和 void 标记 (t.CVoid) -# ============================================================ def _is_t_attr(node: ast.AST | t.CPtr, attr_name: str, imported_modules: str) -> int: - """检测节点是否是 t.attr_name 形式(含 from t import attr_name 的裸名) - - 支持两种写法(与 TPC 的 IsTModule 检查对齐): - - t.CPtr / t.CVoid(Attribute 形式) - - 裸名 CPtr / CVoid(from t import CPtr 形式) - 裸名识别是必要功能:测试/库代码大量用 `from t import CPtr` 后直接写 - `X | CPtr`、`CVoid` 参数注解等,若只认 t.XXX 会漏判。 - """ - if node is None or attr_name is None: - return 0 - if node.kind() == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - if at.attr is None: - return 0 - if string.strcmp(at.attr, attr_name) != 0: - return 0 - if at.value is None or at.value.kind() != ast.ASTKind.Name: - return 0 - val_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if val_nm.id is None: - return 0 - if string.strcmp(val_nm.id, "t") == 0: - # t 是内建库(SHA1 豁免),可能不在 _imported_modules 中。 - # 显式写 t.CPtr / t.CVoid 即确指 t 模块,无需 imported_modules 确认。 - return 1 - return 0 - # 裸名形式: from t import attr_name → Name(id == attr_name) - if node.kind() == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - if nm.id is None: - return 0 - if string.strcmp(nm.id, attr_name) != 0: - return 0 - # 裸名需确认 t 模块已导入(from t import X 会注册 t 到 _imported_modules) - if HandlesImports.is_module_imported(imported_modules, "t") == 0: - return 0 - return 1 + """检测节点是否是 t.attr_name 形式(委托到 gen._is_t_attr)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._is_t_attr(node, attr_name, imported_modules) return 0 -# ============================================================ -# _is_cptr_marker / _is_cvoid_marker — 检测联合类型中的指针标记 -# -# 支持两种形式(与 TPC 的 IsTModule 检查对齐): -# - t.CPtr / t.CVoid(Attribute 形式) -# - 裸名 CPtr / CVoid(from t import CPtr 形式) -# 裸名识别避免了 `X | CPtr` 落入"无 CPtr 标记"分支导致联合被解析为 -# 非指针一边(如 CUInt8T | CPtr 被错误解析为 i8 而非 i8*)。 -# ============================================================ def _is_cptr_marker(node: ast.AST | t.CPtr, imported_modules: str) -> int: - """检测节点是否为 CPtr 指针标记,返回 1=是 / 0=否""" - if _is_t_attr(node, "CPtr", imported_modules) != 0: - return 1 - if node is not None and node.kind() == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - if nm.id is not None and string.strcmp(nm.id, "CPtr") == 0: - return 1 + """检测节点是否为 CPtr 指针标记(委托到 gen._is_cptr_marker)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._is_cptr_marker(node, imported_modules) return 0 def _is_cvoid_marker(node: ast.AST | t.CPtr, imported_modules: str) -> int: - """检测节点是否为 CVoid 指针标记,返回 1=是 / 0=否""" - if _is_t_attr(node, "CVoid", imported_modules) != 0: - return 1 - if node is not None and node.kind() == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - if nm.id is not None and string.strcmp(nm.id, "CVoid") == 0: - return 1 + """检测节点是否为 CVoid 指针标记(委托到 gen._is_cvoid_marker)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._is_cvoid_marker(node, imported_modules) return 0 -# ============================================================ -# extract_class_name_from_annotation - 从类型注解 AST 中提取类名 -# -# 用于联合类型简化为 i8* 时,回退查找结构体类名。 -# 支持: -# Name 节点 (MemBuddy) → "MemBuddy" -# Attribute 节点 (memhub.MemBuddy) → "MemBuddy" -# BinOp 联合类型 (MemBuddy | t.CPtr) → 非 CPtr 一边的类名 -# ============================================================ - - -# ============================================================ -# annotation_to_str - 将类型注解 AST 转换为可读字符串(用于错误消息) -# -# 与 extract_class_name_from_annotation 不同,此函数不跳过任何类型名, -# 纯粹用于错误消息显示。支持递归处理嵌套类型。 -# -# 支持的节点: -# Name → "bool", "int", "MemBuddy" -# Attribute → "t.CBool", "memhub.MemBuddy" -# Subscript → "list[...]", "t.CArray[...]" -# Constant (字符串注解) → 字符串值 -# BinOp (A | B) → "A | B" -# ============================================================ def annotation_to_str(annot: ast.AST | t.CPtr) -> str: - """将类型注解 AST 转换为可读字符串,返回 None=无法提取 - - 注意:返回的字符串可能由 malloc 分配,调用方无需释放(错误路径用)。 - """ - if annot is None: - return "" - k: int = annot.kind() - - # Constant 节点: 字符串注解 - if k == ast.ASTKind.Constant: - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(annot) - if cn.const_kind == ast.CONST_STR and cn.str_val is not None: - return cn.str_val - return "" - - # Name 节点: bool, int, MemBuddy - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(annot) - if nm.id is not None: - return nm.id - return "" - - # Attribute 节点: t.CBool, memhub.MemBuddy - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annot) - if at.attr is None: - return "" - if at.value is not None: - prefix: str = annotation_to_str(at.value) - if prefix is not None: - buf: t.CChar | t.CPtr = stdlib.malloc( - string.strlen(prefix) + string.strlen(at.attr) + 2) - if buf is not None: - viperlib.snprintf(buf, - string.strlen(prefix) + string.strlen(at.attr) + 2, - "%s.%s", prefix, at.attr) - return buf - return at.attr - - # Subscript 节点: list[...], t.CArray[...] - if k == ast.ASTKind.Subscript: - sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(annot) - base: str = annotation_to_str(sub.value) - if base is not None: - buf2: t.CChar | t.CPtr = stdlib.malloc(string.strlen(base) + 5) - if buf2 is not None: - viperlib.snprintf(buf2, string.strlen(base) + 5, - "%s[...]", base) - return buf2 - return "" - - # BinOp 节点: A | B (联合类型) - if k == ast.ASTKind.BinOp: - bo: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(annot) - left_s: str = annotation_to_str(bo.left) - right_s: str = annotation_to_str(bo.right) - if left_s is not None and right_s is not None: - buf3: t.CChar | t.CPtr = stdlib.malloc( - string.strlen(left_s) + string.strlen(right_s) + 5) - if buf3 is not None: - viperlib.snprintf(buf3, - string.strlen(left_s) + string.strlen(right_s) + 5, - "%s | %s", left_s, right_s) - return buf3 - return "" - - return "" - - -# ============================================================ -# extract_class_name_from_annotation -# ============================================================ -def extract_class_name_from_annotation(node: ast.AST | t.CPtr, - imported_modules: str, - pool: memhub.MemBuddy | t.CPtr = None) -> str: - """从类型注解 AST 中提取类名,返回 None=无法提取 - - pool 可用时,对泛型 Subscript(如 list[AST | t.CPtr])返回 mangled name - (如 "list[ast.AST|t.CPtr]"),与 resolve_annotation_type 的 mangled name 格式一致, - 使 find_struct 能找到特化的泛型结构体。 - pool 为 None 时,对 Subscript 只返回裸类名(如 "list"),保持向后兼容。 - """ - if node is None: - return None - k: int = node.kind() - - # Constant 节点: 字符串注解(如 'MemManager'),简单类名直接返回 - if k == ast.ASTKind.Constant: - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) - if cn.const_kind == ast.CONST_STR and cn.str_val is not None: - # 仅处理简单类名(不含 . 和 |),复杂形式返回 None - if string.strchr(cn.str_val, 46) is None and string.strchr(cn.str_val, 124) is None: - if string.strcmp(cn.str_val, "str") == 0: - return None - if string.strcmp(cn.str_val, "int") == 0: - return None - if string.strcmp(cn.str_val, "bytes") == 0: - return None - if string.strcmp(cn.str_val, "bool") == 0: - return None - if string.strcmp(cn.str_val, "float") == 0: - return None - if string.strcmp(cn.str_val, "double") == 0: - return None - return cn.str_val - return None - - # Name 节点: MemBuddy → "MemBuddy" - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - if nm.id is None: - return None - # 跳过内置类型名 - if string.strcmp(nm.id, "str") == 0: - return None - if string.strcmp(nm.id, "int") == 0: - return None - if string.strcmp(nm.id, "bytes") == 0: - return None - if string.strcmp(nm.id, "bool") == 0: - return None - if string.strcmp(nm.id, "float") == 0: - return None - if string.strcmp(nm.id, "double") == 0: - return None - return nm.id - - # Attribute 节点: memhub.MemBuddy → "memhub.MemBuddy"(模块限定名) - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - if at.attr is None: - return None - # t.XXX 内置类型:返回 XXX(如 t.CUInt32T → "CUInt32T"), - # 供 AnnotClassName 记录变量类型名(_type_name_unsigned 判断无符号性时使用)。 - # 消费方(find_struct/lookup_field_by_class)对非结构体名返回 None 优雅降级。 - if at.value is not None and at.value.kind() == ast.ASTKind.Name: - val_nm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if val_nm2.id is not None and string.strcmp(val_nm2.id, "t") == 0: - return at.attr - # 返回模块限定名 "module.Class"(如 "memhub.MemBuddy") - mod_qual_buf: t.CChar | t.CPtr = stdlib.malloc( - string.strlen(val_nm2.id) + string.strlen(at.attr) + 2) - if mod_qual_buf is not None: - viperlib.snprintf(mod_qual_buf, - string.strlen(val_nm2.id) + string.strlen(at.attr) + 2, - "%s.%s", val_nm2.id, at.attr) - return mod_qual_buf - return at.attr - - # BinOp 节点: 联合类型 A | B - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) - if bop.op == ast.OpKind.BitOr: - left_is_cptr: int = _is_cptr_marker(bop.left, imported_modules) - right_is_cptr: int = _is_cptr_marker(bop.right, imported_modules) - # 提取非 CPtr 一边的类名 - if left_is_cptr != 0 and right_is_cptr == 0: - return extract_class_name_from_annotation(bop.right, imported_modules, pool) - if right_is_cptr != 0 and left_is_cptr == 0: - return extract_class_name_from_annotation(bop.left, imported_modules, pool) - # 无 CPtr 标记:尝试两边 - if left_is_cptr == 0 and right_is_cptr == 0: - left_name: str = extract_class_name_from_annotation(bop.left, imported_modules, pool) - if left_name is not None: - return left_name - return extract_class_name_from_annotation(bop.right, imported_modules, pool) - return None - - # BUG 1 方案3:Subscript 节点拼接 mangled name - # list[AST | t.CPtr] → "list[ast.AST|t.CPtr]"(pool 可用时) - # 与 resolve_annotation_type 的 mangled name 格式一致,使 find_struct 能找到特化结构体 - if k == ast.ASTKind.Subscript: - sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node) - if sub.value is None: - return None - base_name: str = extract_class_name_from_annotation(sub.value, imported_modules, pool) - if base_name is None: - return None - # pool 不可用时,只返回裸类名(向后兼容) - if pool is None or sub.slice is None: - return base_name - # pool 可用:拼接 mangled name "base_name[slice_name]" - # slice 是 Tuple 时用逗号分隔多个参数,否则单个参数 - slice_name: str = None - if sub.slice.kind() == ast.ASTKind.Tuple: - # Tuple slice: dict[str, int] → "str,int" - sub_tup: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(sub.slice) - if sub_tup.elts is not None: - tup_elts_sn: list[ast.AST | t.CPtr] | t.CPtr = sub_tup.elts - tn_sn: t.CSizeT = tup_elts_sn.__len__() - # 计算总长度 - tup_total: t.CSizeT = 1 - ti_sn: t.CSizeT - for ti_sn in range(tn_sn): - if ti_sn > 0: - tup_total += 1 - elt_node: ast.AST | t.CPtr = tup_elts_sn.get(ti_sn) - elt_name: str = _get_type_name_from_annotation(pool, elt_node) - if elt_name is not None: - tup_total += string.strlen(elt_name) - tup_buf: str = pool.alloc(tup_total) - if tup_buf is not None: - tup_buf[0] = '\0' - for ti_sn in range(tn_sn): - if ti_sn > 0: - string.strcat(tup_buf, ",") - elt_node2: ast.AST | t.CPtr = tup_elts_sn.get(ti_sn) - elt_name2: str = _get_type_name_from_annotation(pool, elt_node2) - if elt_name2 is not None: - string.strcat(tup_buf, elt_name2) - slice_name = tup_buf - else: - # 非 Tuple slice: list[AST | t.CPtr] → "ast.AST|t.CPtr" - slice_name = _get_type_name_from_annotation(pool, sub.slice) - if slice_name is None: - return base_name - # 拼接 "base_name[slice_name]" - mangled_total: t.CSizeT = string.strlen(base_name) + 1 + string.strlen(slice_name) + 1 + 1 - mangled_buf: str = pool.alloc(mangled_total) - if mangled_buf is None: - return base_name - mangled_buf[0] = '\0' - string.strcat(mangled_buf, base_name) - string.strcat(mangled_buf, "[") - string.strcat(mangled_buf, slice_name) - string.strcat(mangled_buf, "]") - return mangled_buf - + """将类型注解 AST 转换为可读字符串(委托到 gen.annotation_to_str)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.annotation_to_str(annot) + return None + + +def extract_class_name_from_annotation(node: ast.AST | t.CPtr, + imported_modules: str, + pool: memhub.MemBuddy | t.CPtr = None) -> str: + """从类型注解 AST 中提取类名(委托到 gen.extract_class_name_from_annotation)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.extract_class_name_from_annotation(node, imported_modules, pool) return None -# ============================================================ -# _resolve_generic_subscript_ty - 解析泛型类类型注解 -# (list[int] / numpy.ndarray[t.CDouble]) -# -# 收集 slice 类型实参,构造 mangled name("list[int]"),查找已特化结构体; -# 未特化时检查是否泛型模板并主动触发特化。Name 泛型类与模块限定泛型类 -# (Attribute value,如 numpy.ndarray[t.CDouble])共用此逻辑。 -# ============================================================ def _resolve_generic_subscript_ty(pool: memhub.MemBuddy | t.CPtr, sub: ast.Subscript | t.CPtr, gen_cls_name: str, trans: HT.Translator | t.CPtr, imported_modules: str, from_imports: str) -> llvmlite.LLVMType | t.CPtr: - """解析泛型类类型注解(特化或查找已注册结构体),失败返回 None""" - if pool is None or sub is None or gen_cls_name is None: - return None - # tuple[...] 类型注解:TransPyV 暂不支持 tuple 返回类型,返回 None 让上层默认处理 - # 避免走到 list[str](pool, 4) 构造路径崩溃(tuple 未定义为泛型类) - if string.strcmp(gen_cls_name, "tuple") == 0: - return None - # 先收集类型实参名,再分配缓冲区拼接 mangled name(elem_size=8:str 是指针) - gen_arg_names: list[str] | t.CPtr = list[str](pool, 8) - if sub.slice.kind() == ast.ASTKind.Tuple: - gen_tp: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(sub.slice) - gen_elts: list[ast.AST | t.CPtr] | t.CPtr = gen_tp.elts - if gen_elts is not None: - gen_en: t.CSizeT = gen_elts.__len__() - gen_ei: t.CSizeT - for gen_ei in range(gen_en): - gen_elt: ast.AST | t.CPtr = gen_elts.get(gen_ei) - gen_tn: str = _get_type_name_from_annotation(pool, gen_elt) - gen_arg_names.append(gen_tn) - else: - gen_tn_single: str = _get_type_name_from_annotation(pool, sub.slice) - gen_arg_names.append(gen_tn_single) - # 计算总长度并分配缓冲区 - gen_total: t.CSizeT = string.strlen(gen_cls_name) + 2 # "[" 和 "]" - gen_an: t.CSizeT = gen_arg_names.__len__() - gen_ai: t.CSizeT - for gen_ai in range(gen_an): - if gen_ai > 0: - gen_total += 1 # "," - gen_atn: str = gen_arg_names.get(gen_ai) - if gen_atn is not None: - gen_total += string.strlen(gen_atn) - gen_total += 1 # NUL - gen_mangled: str = pool.alloc(gen_total) - if gen_mangled is None: - return None - gen_mangled[0] = '\0' - string.strcat(gen_mangled, gen_cls_name) - string.strcat(gen_mangled, "[") - for gen_ai in range(gen_an): - if gen_ai > 0: - string.strcat(gen_mangled, ",") - gen_atn: str = gen_arg_names.get(gen_ai) - if gen_atn is not None: - string.strcat(gen_mangled, gen_atn) - string.strcat(gen_mangled, "]") - # 查找已特化的 struct(特化由实例化调用 list[int](pool) 触发) - gen_spec_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(gen_mangled) - if gen_spec_ty is not None: - # 治本修复:Phase B 补译泛型特化类方法体 - # Phase 1a(declare_only==1)特化时只注册结构体不译方法体(MethodsEmitted==0), - # Phase B(declare_only==0)解析字段类型命中已注册结构体时本会早返回, - # 导致方法体永远不生成 → GSList[Line].append 等符号只有 declare 无 define → 链接失败。 - # 此处 Phase B 且方法体未译时,调用 _specialize_generic_class 走其已注册分支补译方法体。 - if trans is not None and trans._declare_only == 0: - import lib.core.Handles.HandlesClassDef as HandlesClassDef - gen_spec_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(gen_mangled) - if gen_spec_entry is not None and gen_spec_entry.MethodsEmitted == 0: - HandlesClassDef._specialize_generic_class(trans, gen_cls_name, gen_arg_names) - return gen_spec_ty - # 未特化:尝试主动触发泛型特化(与 TPC _HandleSubscript 对齐) - # 当 trans 可用时,检查是否是泛型模板并触发特化 - if trans is not None: - import lib.core.Handles.HandlesClassDef as HandlesClassDef - import lib.core.Handles.HandlesExprCall as HandlesExprCall - template_cd_chk: ast.ClassDef | t.CPtr = HandlesClassDef._find_generic_template(gen_cls_name) - if template_cd_chk is not None: - type_args_chk: list[str] | t.CPtr = HandlesExprCall._extract_type_args_from_slice( - pool, sub.slice) - if type_args_chk is not None and type_args_chk.__len__() > 0: - spec_name_chk: str = HandlesClassDef._specialize_generic_class( - trans, gen_cls_name, type_args_chk) - if spec_name_chk is not None: - gen_spec_ty = HandlesStruct.get_struct_type(gen_mangled) - if gen_spec_ty is not None: - return gen_spec_ty - # 未特化:返回 None(不报错,让后续流程处理) + """解析泛型类类型注解(委托到 gen._resolve_generic_subscript_ty)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g._resolve_generic_subscript_ty(pool, sub, gen_cls_name, trans, + imported_modules, from_imports) return None -# ============================================================ -# 解析类型注解节点为 LLVMType -# -# 支持的注解形式: -# - int → i32 -# - t.CUInt64T → i64 -# - str → i8* (t.CChar | t.CPtr = i8* = bytes) -# - int → i32 -# - bytes → i8* -# ============================================================ def resolve_annotation_type(pool: memhub.MemBuddy | t.CPtr, node: ast.AST | t.CPtr, imported_modules: str, from_imports: str, trans: HT.Translator | t.CPtr = None) -> llvmlite.LLVMType | t.CPtr: - """解析类型注解节点为 LLVMType - - Args: - pool: 内存分配器 - node: 类型注解 AST 节点(Name 或 Attribute) - imported_modules: 已导入模块名字符串(空格分隔) - from_imports: from-import 映射字符串("name:module name:module" 格式) - trans: 翻译器对象(可选,用于触发泛型特化) - """ - if node is None: - return None - - global _g_ctypedef_resolve_depth - k: int = node.kind() - - # Constant 节点: 字符串注解(如 'MemManager'),当作无引号的 Name/Attribute/BinOp 处理 - if k == ast.ASTKind.Constant: - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) - if cn.const_kind == ast.CONST_STR and cn.str_val is not None: - sub_node: ast.AST | t.CPtr = _parse_type_string(pool, cn.str_val, ast.ASTCtx.Load) - if sub_node is not None: - return resolve_annotation_type(pool, sub_node, imported_modules, from_imports, trans) - return None - - # Name 节点: str, int, bytes, from-import 名称, class 名称等 - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - if nm.id is None: - return None - # 泛型类型参数 T 替换:在泛型特化上下文中,将 T 替换为具体类型 - if _g_generic_tp_names is not None and _g_generic_type_args is not None: - gp_n: t.CSizeT = _g_generic_tp_names.__len__() - gp_i: t.CSizeT - for gp_i in range(gp_n): - gp_tpn: str = _g_generic_tp_names.get(gp_i) - if gp_tpn is not None and string.strcmp(nm.id, gp_tpn) == 0: - gp_ta: str = _g_generic_type_args.get(gp_i) - if gp_ta is not None: - # 用具体类型名递归解析(支持 BinOp/Attribute 类型实参) - gp_sub_node: ast.AST | t.CPtr = _parse_type_string(pool, gp_ta, nm.ctx) - if gp_sub_node is not None: - return resolve_annotation_type(pool, gp_sub_node, imported_modules, from_imports, trans) - # str = bytes = t.CChar | t.CPtr = i8* - if string.strcmp(nm.id, "str") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(nm.id, "int") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(nm.id, "bytes") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(nm.id, "bool") == 0: - # bool = t.CBool = i1(与 map_t_type 中 CBool 映射一致) - return llvmlite.Int1(pool) - # 裸名浮点类型: float = t.CFloat = f32, double = t.CDouble = f64 - elif string.strcmp(nm.id, "float") == 0: - return llvmlite.Float(pool) - elif string.strcmp(nm.id, "double") == 0: - return llvmlite.Double(pool) - # class 名称: 查找已注册的 StructType,返回 StructType 本身(不包装 Ptr) - # 这样 build_alloca 会分配结构体大小的空间,alloca 返回 struct_ty* - # 命名空间隔离:严格模式下仅解析可见的结构体 - # 跨模块同名类优先:当前模块自身定义了同名类时,用 find_struct_by_module - # 命中本模块的类(如 main.vp 的 G5Node 不再被 g5container.vp 预注册的 - # G5Node 顶掉,避免 alloca 用本模块类型、load 用他模块类型的混用)。 - # 本模块未定义时回退按裸名全局查找(import 来的类走此路径)。 - if trans is not None and trans.ModuleSha1 is not None: - own_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(nm.id, trans.ModuleSha1) - if own_entry is not None and own_entry.Ty is not None: - return own_entry.Ty - if HandlesStruct.is_struct_visible(nm.id) != 0: - struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(nm.id) - if struct_ty is not None: - return struct_ty - # CTypedef 动态查表:查动态 CTypedef 表,递归解析类型表达式 - # 用户自定义 CTypedef(如 MyHandle: t.CTypedef = VOIDPTR)在此解析 - # 递归深度限制 MAX_CTYPEDEF_DEPTH 防止无限递归,循环检测防止 A→B→A - if _g_ctypedef_resolve_depth < MAX_CTYPEDEF_DEPTH: - ctypedef_str: str = lookup_ctypedef(nm.id) - if ctypedef_str is not None and _g_ctypedef_found != 0: - # 循环检测:将当前 CTypedef 名加入正在解析列表 - if _ctypedef_push_visiting(pool, nm.id) == 0: - # 用 _parse_type_string 把类型字符串转回 AST,递归解析 - inner_node: ast.AST | t.CPtr = _parse_type_string(pool, ctypedef_str, nm.ctx) - if inner_node is not None: - _g_ctypedef_resolve_depth += 1 - inner_ty: llvmlite.LLVMType | t.CPtr = resolve_annotation_type( - pool, inner_node, imported_modules, from_imports, trans) - _g_ctypedef_resolve_depth -= 1 - _ctypedef_pop_visiting() - if inner_ty is not None: - return inner_ty - else: - _ctypedef_pop_visiting() - # 兜底: 尝试 map_t_type 中的硬编码 typedef 映射(VOIDPTR, HANDLE, ULONG 等) - # 这些是跨模块通用的 C typedef 名,即使 from-import 查找失败也能解析 - # 注意:from-import 的结构体名若未注册,get_struct_type 已返回 None, - # 此处 map_t_type 对结构体名也返回 None,由上层 declare_only 机制延迟到下一遍 - mapped_ty_fallback: llvmlite.LLVMType | t.CPtr = map_t_type(pool, nm.id) - if mapped_ty_fallback is not None: - return mapped_ty_fallback - return None - - # Attribute 节点: t.CInt, t.CUInt64T, namespace_defs.PlainStruct 等 - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - if at.attr is None: - return None - # 检查 value 是否是 Name('t') 或 Name('c') - if at.value is not None and at.value.kind() == ast.ASTKind.Name: - val_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if val_name.id is not None: - # t/c 是内建库(SHA1 豁免),显式写 t.XXX 即确指内建库, - # 不依赖 imported_modules(t 可能不在其中,如 vpi 注入上下文) - is_builtin_attr: int = 0 - if string.strcmp(val_name.id, "t") == 0 or string.strcmp(val_name.id, "c") == 0: - is_builtin_attr = 1 - if is_builtin_attr == 0: - mod_imp: int = HandlesImports.is_module_imported(imported_modules, val_name.id) - if mod_imp == 0: - return None - # 先尝试内置类型映射(int 等) - mapped_ty: llvmlite.LLVMType | t.CPtr = map_t_type(pool, at.attr) - if mapped_ty is not None: - return mapped_ty - # 模块限定类类型:Module.ClassName(命名空间隔离) - mod_struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(at.attr) - if mod_struct_ty is not None: - return mod_struct_ty - return None - # 嵌套 Attribute: w32.win32base.SECURITY_ATTRIBUTES 等三级及以上限定名 - # at.value 是 Attribute 而非 Name,递归提取最终类名(at.attr)查结构体表 - # find_struct 支持模块限定名回退,此处用最外层 attr(简单类名)即可 - if at.value is not None and at.value.kind() == ast.ASTKind.Attribute: - nested_struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(at.attr) - if nested_struct_ty is not None: - return nested_struct_ty - return None - - # BinOp 节点: 联合类型注解 A | B - # 处理三种语义: - # 1. ActualType | t.CPtr → Ptr(ActualType)(指针包装,如 MemBuddy | t.CPtr → MemBuddy*) - # 2. t.CVoid | t.CPtr → i8* (void* 等价于 i8*) - # 3. ActualType | DecoratorMarker → ActualType(忽略装饰器标记如 CExport/CExtern) - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) - if bop.op == ast.OpKind.BitOr: - # 检测 t.CPtr 标记(指针包装标记,支持 t.CPtr 与 from t import CPtr 裸名) - left_is_cptr: int = _is_cptr_marker(bop.left, imported_modules) - right_is_cptr: int = _is_cptr_marker(bop.right, imported_modules) - if left_is_cptr != 0 or right_is_cptr != 0: - # 有 CPtr 标记:解析非 CPtr 一边的实际类型,包装为 Ptr - # left 是 CPtr → other 是 right;right 是 CPtr → other 是 left - other_node: ast.AST | t.CPtr = bop.left - if left_is_cptr != 0: - other_node = bop.right - # 检测另一边是否是 t.CVoid (void* = i8*) - # 严格验证完整形式(Attribute(t.CVoid) 的 value 是 Name("t"), - # 或裸名 CVoid 且 t 已导入),防止解析异常节点被误判为 CVoid。 - other_is_cvoid: int = 0 - if other_node is not None: - if other_node.kind() == ast.ASTKind.Attribute: - oat2: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(other_node) - if oat2.attr is not None and string.strcmp(oat2.attr, "CVoid") == 0: - if oat2.value is not None and oat2.value.kind() == ast.ASTKind.Name: - ov2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(oat2.value) - if ov2.id is not None and string.strcmp(ov2.id, "t") == 0: - other_is_cvoid = 1 - elif other_node.kind() == ast.ASTKind.Name: - onm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(other_node) - if onm2.id is not None and string.strcmp(onm2.id, "CVoid") == 0: - if HandlesImports.is_module_imported(imported_modules, "t") != 0: - other_is_cvoid = 1 - if other_is_cvoid != 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - other_ty: llvmlite.LLVMType | t.CPtr = resolve_annotation_type( - pool, other_node, imported_modules, from_imports, trans) - # 仅裸名(Name)场景验证解析结果必须是已注册 struct: - # 损坏节点可能解析出基础类型垃圾(如 Int8 → Ptr(i8))。 - # Attribute 场景(Module.Class / t.XXX)resolve 结果直接可用 - # (如 t.CUInt64T → i64、memhub.MemBuddy → MemBuddy*), - # 不得踢进 fallback——否则按 Name 布局读 Attribute 字段会得到 - # 垃圾类名,字段类型错误(如 free_lists 从 i64* 变 i8*)导致 - # 运行时 GEP 步长错误崩溃。 - other_is_name: int = 0 - if other_node is not None and other_node.kind() == ast.ASTKind.Name: - other_is_name = 1 - if other_ty is not None and other_is_name != 0: - if HandlesStruct.find_struct_by_type(other_ty) is None: - other_ty = None - if other_ty is None: - # 严格模式(App 文件)下裸类名不可见时,回退到全局 - # struct 注册表按类名查找。X | t.CPtr 是明确的指针包装 - # 注解(如 vpi stub 的 "ParsedArgs | t.CPtr"),X 已注册 - # 时不应静默退化为 i8*——i8* 会让方法返回值的无注解变量 - # (如 args = parser.parse_args())类型退化,后续 obj.method - # get_class_name_by_type 查不到类名,误报 - # "跨模块调用 'args.get_str' 找不到模块 SHA1"。 - # 仅裸名(Name)场景回退:Attribute 场景 resolve 已成功。 - other_cls_nm: str = None - if other_node is not None and other_node.kind() == ast.ASTKind.Name: - other_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(other_node) - if other_nm.id is not None: - other_cls_nm = other_nm.id - if other_cls_nm is not None: - other_cls_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(other_cls_nm) - if other_cls_ty is not None: - return llvmlite.Ptr(pool, other_cls_ty) - # CPtr 单独使用或其他无效类型 → i8* - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - return llvmlite.Ptr(pool, other_ty) - - # 无 CPtr 标记:返回第一个非 None(装饰器标记如 CExport/CExtern 被忽略) - left_ty: llvmlite.LLVMType | t.CPtr = resolve_annotation_type( - pool, bop.left, imported_modules, from_imports, trans) - if left_ty is not None: - return left_ty - right_ty: llvmlite.LLVMType | t.CPtr = resolve_annotation_type( - pool, bop.right, imported_modules, from_imports, trans) - if right_ty is not None: - return right_ty - return None - - # Subscript 节点: t.CArray[elem_ty, count] → [count x elem_ty] - # t.CArray[elem_ty] → Ptr(elem_ty)(静态推导长度数组) - # list[int] → 特化类 struct type(泛型类类型注解) - # value 是 Attribute(Name('t'), 'CArray') 或 Name('list')(泛型类) - # slice 是 Tuple(elts=[elem_ty_node, count_node]) 或单 elem_ty_node - if k == ast.ASTKind.Subscript: - sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node) - if sub.value is None or sub.slice is None: - fatal_type_error(node, "Subscript 节点缺少 value 或 slice") - # 泛型类类型注解: list[int] → 查找已特化的 struct(value 是 Name 泛型类名) - if sub.value.kind() == ast.ASTKind.Name: - gen_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value) - if gen_nm.id is not None: - return _resolve_generic_subscript_ty(pool, sub, gen_nm.id, trans, - imported_modules, from_imports) - # 检查 value 是否是 Attribute(t.CArray / t.Callable / 模块限定泛型类如 numpy.ndarray[T]) - if sub.value.kind() != ast.ASTKind.Attribute: - fatal_type_error(node, "不支持的 Subscript 类型注解(仅支持 t.CArray / t.Callable)") - arr_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(sub.value) - if arr_at.attr is None: - fatal_type_error(node, "Subscript Attribute 缺少 attr") - # 模块限定泛型类: numpy.ndarray[t.CDouble] → 裸类名 ndarray 走泛型特化 - # (在 t.CArray / t.Callable 检查之前;模板已注册即视为泛型类) - if trans is not None: - import lib.core.Handles.HandlesClassDef as HandlesClassDef - if HandlesClassDef._find_generic_template(arr_at.attr) is not None: - return _resolve_generic_subscript_ty(pool, sub, arr_at.attr, trans, - imported_modules, from_imports) - if arr_at.value is None or arr_at.value.kind() != ast.ASTKind.Name: - fatal_type_error(node, "t.CArray / t.Callable 必须通过模块名限定") - arr_val_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arr_at.value) - if arr_val_name.id is None: - fatal_type_error(node, "Subscript 模块名为 None") - # 函数指针类型: t.Callable[[A, B], Ret] → i8* - # 与 TPV 函数传指针惯例一致(函数值 bitcast 为 i8* 存储,调用时按实参重建签名) - if string.strcmp(arr_at.attr, "Callable") == 0: - if HandlesImports.is_module_imported(imported_modules, arr_val_name.id) == 0: - fatal_type_error(node, "t.Callable 模块未导入") - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - if string.strcmp(arr_at.attr, "CArray") != 0: - fatal_type_error(node, "不支持的 Subscript 类型注解(仅支持 t.CArray / t.Callable)") - if HandlesImports.is_module_imported(imported_modules, arr_val_name.id) == 0: - fatal_type_error(node, "t.CArray 模块未导入") - # 单参数形式: t.CArray[elem_ty] → Ptr(elem_ty) - # 相当于 t.CArray[elem_ty, None],表示静态推导长度数组 - if sub.slice.kind() != ast.ASTKind.Tuple: - elem_ty_single: llvmlite.LLVMType | t.CPtr = resolve_annotation_type( - pool, sub.slice, imported_modules, from_imports, trans) - if elem_ty_single is None: - fatal_type_error(sub.slice, "t.CArray[?] 元素类型解析失败") - return llvmlite.Ptr(pool, elem_ty_single) - # 双参数形式: t.CArray[elem_ty, count] → [count x elem_ty] - tup: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(sub.slice) - if tup.elts is None: - fatal_type_error(node, "t.CArray Tuple 缺少 elts") - elts_list: list[ast.AST | t.CPtr] | t.CPtr = tup.elts - elts_n: t.CSizeT = elts_list.__len__() - if elts_n < 2: - fatal_type_error(node, "t.CArray Tuple 元素不足") - elem_node: ast.AST | t.CPtr = elts_list.get(0) - count_node: ast.AST | t.CPtr = elts_list.get(1) - if elem_node is None or count_node is None: - fatal_type_error(node, "t.CArray Tuple 元素为 None") - # 递归解析元素类型 - elem_ty: llvmlite.LLVMType | t.CPtr = resolve_annotation_type( - pool, elem_node, imported_modules, from_imports, trans) - if elem_ty is None: - fatal_type_error(elem_node, "t.CArray 元素类型解析失败") - # 解析 count(支持整数常量、None、CDefine 常量名、常量表达式如 2*MAX) - # t.CArray[elem_ty, None] 等价于单参数形式 → Ptr(elem_ty) - # t.CArray[elem_ty, NAME] 其中 NAME: t.CDefine = value → [value x elem_ty] - # t.CArray[elem_ty, 2 * MAX] 常量表达式静态计算 → [2*MAX x elem_ty] - count_val: int = 0 - if count_node.kind() == ast.ASTKind.Constant: - cnt_cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(count_node) - if cnt_cn.const_kind == ast.CONST_NONE: - return llvmlite.Ptr(pool, elem_ty) - # 统一用 _eval_const_int_expr 计算常量整数表达式 - # 支持 Constant(INT)、Name(CDefine)、BinOp(2*MAX 等算术/位运算) - count_val = _eval_const_int_expr(count_node) - if _g_const_eval_ok == 0: - fatal_type_error(count_node, "t.CArray count 必须是整数常量、None、CDefine 常量名或常量表达式") - if count_val <= 0: - fatal_type_error(count_node, "t.CArray count 必须为正数") - # 创建 ArrayType(不包装 Ptr) - # 这样 build_alloca 会分配数组大小的空间,alloca 返回 [N x elem_ty]* - return llvmlite.Array(pool, elem_ty, count_val) - - # 未知 AST kind:fail-fast,不宽容返回 None - fatal_type_error(node, "不支持的类型注解语法") + """解析类型注解节点为 LLVMType(委托到 gen.resolve_annotation_type)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.resolve_annotation_type(pool, node, imported_modules, from_imports, trans) + return None -# ============================================================ -# has_decorator_marker - 检测类型注解中是否包含指定的装饰器标记 -# -# 支持联合类型注解:int | t.CExtern | t.CExport -# 递归检测 BinOp 节点的左右子节点。 -# -# marker_name 取值: "CExtern", "CExport", "CInline", "State" -# ============================================================ def has_decorator_marker(node: ast.AST | t.CPtr, marker_name: str) -> int: - """检测类型注解中是否包含指定的装饰器标记""" - if node is None or marker_name is None: - return 0 - - k: int = node.kind() - - # Attribute 节点: t.CExtern, t.State, t.CExport, t.CInline - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - if at.attr is not None: - if string.strcmp(at.attr, marker_name) == 0: - return 1 - return 0 - - # BinOp 节点: int | t.CExtern(递归检测左右子节点) - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) - if has_decorator_marker(bop.left, marker_name) != 0: - return 1 - if has_decorator_marker(bop.right, marker_name) != 0: - return 1 - return 0 - + """检测类型注解中是否包含指定的装饰器标记(委托到 gen.has_decorator_marker)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.has_decorator_marker(node, marker_name) return 0 -# ============================================================ -# is_pass_body - 检测函数体是否为 pass(空体) -# -# pass 体函数用于声明外部函数(t.CExtern / t.State), -# 翻译器应生成 declare 而非 define。 -# ============================================================ def is_pass_body(body: list[ast.AST | t.CPtr] | t.CPtr) -> int: - """检测函数体是否为 pass(空体或仅含 pass 语句)""" - if body is None: - return 1 - bn: t.CSizeT = body.__len__() - if bn == 0: - return 1 - if bn == 1: - stmt: ast.AST | t.CPtr = body.get(0) - if stmt is not None and stmt.kind() == ast.ASTKind.Pass: - return 1 + """检测函数体是否为 pass(委托到 gen.is_pass_body)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.is_pass_body(body) return 0 -# ============================================================ -# 获取 LLVM 整数类型的位宽 -# ============================================================ def get_llvm_type_bits(ty: llvmlite.LLVMType | t.CPtr) -> int: - """获取 LLVM 整数类型的位宽,非整数类型返回 0""" - if ty is None: - return 0 - match ty: - case llvmlite.LLVMType.Int(bits): - return bits - case _: - return 0 + """获取 LLVM 整数类型的位宽(委托到 gen.get_llvm_type_bits)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.get_llvm_type_bits(ty) + return 0 -# ============================================================ -# 推断表达式的 LLVM 类型 -# ============================================================ def infer_expr_type(pool: memhub.MemBuddy | t.CPtr, node: ast.AST | t.CPtr, param_types: str) -> llvmlite.LLVMType | t.CPtr: - """推断表达式的 LLVM 类型 - - param_types 格式: "name:bits,name:bits,..." - """ - if node is None: - return llvmlite.Int32(pool) - - k: int = node.kind() - - if k == ast.ASTKind.Constant: - return llvmlite.Int32(pool) - - elif k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - if nm.id is not None and param_types is not None: - # 在 param_types 中查找: "name:bits" 格式 - search_key: t.CChar | t.CPtr = pool.alloc(64) - if search_key is not None: - viperlib.snprintf(search_key, 64, "%s:", nm.id) - found: t.CChar | t.CPtr = string.strstr(param_types, search_key) - if found is not None: - colon_pos: t.CSizeT = string.strlen(nm.id) + 1 - bits_str: t.CChar | t.CPtr = found + colon_pos - bits: int = 0 - for bi in range(4): - ch: t.CChar = bits_str[bi] - if ch >= '0' and ch <= '9': - bits = bits * 10 + (ch - '0') - else: - break - if bits == 64: - return llvmlite.Int64(pool) - elif bits == 16: - return llvmlite.Int16(pool) - elif bits == 8: - return llvmlite.Int8(pool) - return llvmlite.Int32(pool) - - elif k == ast.ASTKind.BinOp: - binop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) - lhs_ty: llvmlite.LLVMType | t.CPtr = infer_expr_type( - pool, binop.left, param_types) - rhs_ty: llvmlite.LLVMType | t.CPtr = infer_expr_type( - pool, binop.right, param_types) - lhs_bits: int = get_llvm_type_bits(lhs_ty) - rhs_bits: int = get_llvm_type_bits(rhs_ty) - if lhs_bits >= rhs_bits: - return lhs_ty - return rhs_ty - - return llvmlite.Int32(pool) + """推断表达式的 LLVM 类型(委托到 gen.infer_expr_type)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.infer_expr_type(pool, node, param_types) + return None -# ============================================================ -# 推断函数返回类型 -# ============================================================ def infer_return_type(pool: memhub.MemBuddy | t.CPtr, body: list[ast.AST | t.CPtr] | t.CPtr, param_types: str) -> llvmlite.LLVMType | t.CPtr: - """扫描函数体中的 return 语句,推断返回类型""" - if body is None: - return llvmlite.Int32(pool) - - ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - bn: t.CSizeT = body.__len__() - for bi in range(bn): - stmt: ast.AST | t.CPtr = body.get(bi) - if stmt is not None and stmt.kind() == ast.ASTKind.Return: - rt: ast.Return | t.CPtr = (ast.Return | t.CPtr)(stmt) - if rt.value is not None: - expr_ty: llvmlite.LLVMType | t.CPtr = infer_expr_type( - pool, rt.value, param_types) - if expr_ty is not None: - cur_bits: int = get_llvm_type_bits(ret_ty) - new_bits: int = get_llvm_type_bits(expr_ty) - if new_bits > cur_bits: - ret_ty = expr_ty - return ret_ty + """扫描函数体中的 return 语句,推断返回类型(委托到 gen.infer_return_type)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.infer_return_type(pool, body, param_types) + return None -# ============================================================ -# 构建参数类型编码字符串 -# ============================================================ def build_param_types_str(pool: memhub.MemBuddy | t.CPtr, args_node: ast.AST | t.CPtr) -> str: - """构建参数类型编码字符串 "name:bits,name:bits,..." """ - if args_node is None: - return None - ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) - if ags.args is None: - return None - alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args - an: t.CSizeT = alist.__len__() - if an == 0: - return None - - buf_size: t.CSizeT = an * 32 + 1 - buf: t.CChar | t.CPtr = pool.alloc(buf_size) - if buf is None: - return None - buf[0] = '\0' - - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - for ai in range(an): - arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai)) - if arg is not None and arg.arg is not None: - param_ty: llvmlite.LLVMType | t.CPtr = i32_ty - if arg.annotation is not None: - # 直接调用 map_t_type 解析 Attribute 注解 - if arg.annotation.kind() == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg.annotation) - if at.attr is not None: - resolved: llvmlite.LLVMType | t.CPtr = map_t_type(pool, at.attr) - if resolved is not None: - param_ty = resolved - bits: int = get_llvm_type_bits(param_ty) - if bits == 0: - bits = 32 - tmp: t.CChar | t.CPtr = pool.alloc(32) - if tmp is not None: - viperlib.snprintf(tmp, 32, "%s:%d", arg.arg, bits) - if ai > 0: - _strappend(buf, buf_size, ",") - _strappend(buf, buf_size, tmp) - return buf + """构建参数类型编码字符串(委托到 gen.build_param_types_str)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + return g.build_param_types_str(pool, args_node) + return None -# ============================================================ -# 辅助函数 -# ============================================================ def _strappend(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr): - """将 src 追加到 dst 末尾""" - if dst is None or src is None: - return - dlen: t.CSizeT = string.strlen(dst) - slen: t.CSizeT = string.strlen(src) - remain: t.CSizeT = dst_size - dlen - if remain <= 0: - return - # 内联 min(slen, remain - 1) 避免 builtin min 未定义(TransPyV 无 builtin min) - limit: t.CSizeT = slen - cap: t.CSizeT = remain - 1 - if cap < limit: - limit = cap - for i in range(limit): - dst[dlen + i] = src[i] - dst[dlen + i] = '\0' \ No newline at end of file + """将 src 追加到 dst 末尾(委托到 gen._strappend)""" + import lib.core.Gen.Generator as Generator + g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr)) + if g is not None: + g._strappend(dst, dst_size, src) diff --git a/App/main.vp b/App/main.vp index 9f7aad1..4802287 100644 --- a/App/main.vp +++ b/App/main.vp @@ -22,6 +22,7 @@ import lib.core.IncludesScanner as IncludesScanner import lib.core.StubMerger as StubMerger import lib.core.Phase1 as Phase1 import lib.core.Phase2 as Phase2 +import lib.core.Gen.Generator as GenGenerator import lib.Projectrans.Config as Config import lib.Projectrans.Utils as Utils import llvmlite @@ -77,6 +78,18 @@ def main() -> int: VLogger._mbuddy = (memhub.MemBuddy | t.CPtr)(mb) lib.InitLib((memhub.MemBuddy | t.CPtr)(mb)) + # P2: 创建项目级 Generator 单例(Phase1/Phase2/BuildPipeline 全程复用; + # HandlesType 等旧模块函数经延迟 import 委托到 gen 方法,实现对象化过渡) + gen: GenGenerator.Generator | t.CPtr = mb.alloc(GenGenerator.Generator.__sizeof__()) + if gen is None: + stdio.printf("FAIL: Generator alloc failed\n") + return 1 + gen.__before_init__() + gen.__init__(mb) + GenGenerator.set_global_gen(gen) + # P2: 注入 HandlesType 模块级单例(Phase1 阶段即调用 HandlesType 状态函数) + HandlesType.set_global_gen(gen) + # 初始化 VLogger 并打印启动日志 log: VLogger.Logger | t.CPtr = VLogger.get_logger() if log is not None: