From f4a990c07443836f407bc34ddd0ad43a8fa3d30d Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 17 Aug 2026 05:46:40 +0800 Subject: [PATCH] =?UTF-8?q?refactor(gen):=20StmtGenMixin=20=E6=8C=89?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=9F=9F=E6=8B=86=E4=B8=BA=203=20=E6=96=87?= =?UTF-8?q?=E4=BB=B6=EF=BC=88500~1500=20=E8=A1=8C=E6=9E=B6=E6=9E=84?= =?UTF-8?q?=E8=AF=95=E7=82=B9=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit StmtGenMixin.vp(1715) → 顶层(763 语句分派中枢) + StmtGenDeclMixin(512 声明/枚举/nonlocal) + StmtGenCifMixin(520 CIf 求值/工厂)。继承链 Mixin→Decl→Cif,@t.NoVTable 静态绑定沿 MRO 解析;4 字段全留最底层父类保持组合布局;Generator.vp 与 Handles* 委托零改动。 --- App/lib/core/Gen/StmtGenCifMixin.vp | 519 ++++++++++++++ App/lib/core/Gen/StmtGenDeclMixin.vp | 511 ++++++++++++++ App/lib/core/Gen/StmtGenMixin.vp | 973 +-------------------------- 3 files changed, 1040 insertions(+), 963 deletions(-) create mode 100644 App/lib/core/Gen/StmtGenCifMixin.vp create mode 100644 App/lib/core/Gen/StmtGenDeclMixin.vp diff --git a/App/lib/core/Gen/StmtGenCifMixin.vp b/App/lib/core/Gen/StmtGenCifMixin.vp new file mode 100644 index 0000000..0b8fd00 --- /dev/null +++ b/App/lib/core/Gen/StmtGenCifMixin.vp @@ -0,0 +1,519 @@ +import t, c +from stdint import * +import ast +import llvmlite +import memhub +import string +import stdlib +import stdio +import viperlib +import lib.core.VLogger as VLogger +import lib.core.Handles.HandlesTranslator as HT +import lib.core.Handles.HandlesType as HandlesType +import lib.core.Handles.HandlesVar as HandlesVar +import lib.core.Handles.HandlesExpr as HandlesExpr +import lib.core.Handles.HandlesExprCall as HandlesExprCall +import lib.core.Handles.HandlesStruct as HandlesStruct +import lib.core.Handles.HandlesFunctions as HandlesFunctions +import lib.core.Handles.HandlesClassDef as HandlesClassDef +import lib.core.Handles.HandlesImports as HandlesImports +import lib.core.Handles.HandlesIf as HandlesIf +import lib.core.Handles.HandlesWhile as HandlesWhile +import lib.core.Handles.HandlesFor as HandlesFor +import lib.core.Handles.HandlesReturn as HandlesReturn +import lib.core.Handles.HandlesStruct as HandlesStruct +import lib.core.Handles.HandlesMatch as HandlesMatch +import lib.core.Handles.HandlesEnum as HandlesEnum +import lib.core.CompilerFactory as CompilerFactory +import lib.Projectrans.Config as Config +# ============================================================ +# StmtGenCifMixin - StmtGen 拆分 1/3:CIf 编译期求值 + NewXxxHandle 工厂 +# +# 按功能域从 StmtGenMixin.vp 拆出(500~1500 行/文件架构重构,试点): +# 簇 B(CIf 宏求值)+ NewIfHandle/NewWhileHandle/NewForHandle/ +# NewReturnHandle/NewMatchHandle 工厂。 +# 全部字段保留在本最底层父类(顺序 CifEvalOk->EnumTable->EnumCount-> +# DiagStmtCount 与 Generator 组合布局一致,见下方字段注释)。 +# +# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整)。 +# ============================================================ + + +# ============================================================ +# StmtGenCifMixin - CIf 求值 + 工厂(最底层父类) +# ============================================================ +@t.NoVTable +class StmtGenCifMixin: + """CIf 编译期求值 + NewXxxHandle 工厂(StmtGen 拆分 1/3,最底层)""" + + # --- 编译期 CIf 求值状态(原 HandlesIf._g_cif_eval_ok) --- + # 用 8 字节类型:Mixin 独立布局与 Generator 组合布局的字段对齐必须一致 + # (i32 首字段在组合布局中导致 EnumTable 相对偏移 4 vs 独立布局 8 的错位, + # this_adjust 无法同时修正,枚举表错位到相邻字段被覆盖——ASTCtx 丢失根因)。 + CifEvalOk: t.CSizeT + + # --- 枚举注册表(原 HandlesEnum._enum_table/_enum_count) --- + EnumTable: HandlesEnum.EnumEntry | t.CPtr + EnumCount: int + + # --- OOM 语句级诊断计数(translate_stmt 限频打印 used) --- + DiagStmtCount: int + + # ============================================================ + # 簇 B:编译期 CIf 宏求值(迁移自 HandlesIf.vp 模块级函数) + # ============================================================ + + def _is_cif_attr(self, attr: str) -> int: + """检查方法名是否为 CIf 系(CIf/CIfdef/CIfndef)""" + if attr is None: + return 0 + if string.strcmp(attr, "CIf") == 0: return 1 + if string.strcmp(attr, "CIfdef") == 0: return 1 + if string.strcmp(attr, "CIfndef") == 0: return 1 + return 0 + + def _is_cif_call(self, node: ast.AST | t.CPtr) -> int: + """检查 test 是否为 c.CIf(...)/c.CIfdef(...)/c.CIfndef(...)(或裸 CIf 系)调用""" + if node is None or node.kind() != ast.ASTKind.Call: + return 0 + cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node) + if cl.func is None: + return 0 + fk: int = cl.func.kind() + if fk == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) + if at.attr is None: + return 0 + if at.value is not None and at.value.kind() == ast.ASTKind.Name: + vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) + if vn.id is not None and string.strcmp(vn.id, "c") == 0: + return self._is_cif_attr(at.attr) + return 0 + if fk == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cl.func) + if nm.id is not None and self._is_cif_attr(nm.id) != 0: + return 1 + return 0 + + def _get_platform_macro_value(self, name: str) -> int: + """平台内置宏值(从目标三元组推导,对齐 TPC HandlesIf._get_platform_macros)。 + + 命中置 self.CifEvalOk=1;未命中置 0 返回 0。 + """ + self.CifEvalOk = 0 + if name is None: + return 0 + triple: str = Config.TargetTriple + if triple is None: + triple = "x86_64-pc-windows-gnu" + is_win: int = 0 + is_linux: int = 0 + is_x64: int = 0 + if string.strstr(triple, "windows") is not None \ + or string.strstr(triple, "win32") is not None \ + or string.strstr(triple, "mingw") is not None \ + or string.strstr(triple, "msvc") is not None: + is_win = 1 + if string.strstr(triple, "linux") is not None: + is_linux = 1 + if string.strstr(triple, "x86_64") is not None: + is_x64 = 1 + # 简化:本编译目标为 x86_64 Windows(_WIN64/WIN64 恒与 is_win 一致) + if string.strcmp(name, "_WIN32") == 0: self.CifEvalOk = is_win; return 1 if is_win else 0 + if string.strcmp(name, "WIN32") == 0: self.CifEvalOk = is_win; return 1 if is_win else 0 + if string.strcmp(name, "_WIN64") == 0: self.CifEvalOk = is_win; return 1 if is_win else 0 + if string.strcmp(name, "WIN64") == 0: self.CifEvalOk = is_win; return 1 if is_win else 0 + if string.strcmp(name, "__linux__") == 0: self.CifEvalOk = is_linux; return 1 if is_linux else 0 + if string.strcmp(name, "__x86_64__") == 0: self.CifEvalOk = is_x64; return 1 if is_x64 else 0 + if string.strcmp(name, "__x86_64") == 0: self.CifEvalOk = is_x64; return 1 if is_x64 else 0 + if string.strcmp(name, "_M_X64") == 0: self.CifEvalOk = is_x64; return 1 if is_x64 else 0 + if string.strcmp(name, "SIZEOF_VOID_P") == 0: self.CifEvalOk = 1; return 8 if is_x64 else 4 + if string.strcmp(name, "__SIZEOF_POINTER__") == 0: self.CifEvalOk = 1; return 8 if is_x64 else 4 + if string.strcmp(name, "NDEBUG") == 0: self.CifEvalOk = 1; return 0 + return 0 + + def _cif_name_value(self, pool: memhub.MemBuddy | t.CPtr, + trans: HT.Translator | t.CPtr, + name: str) -> int: + """查宏名值: 本地 CDefine → 跨模块 CDefine → 平台宏。 + + 命中置 self.CifEvalOk=1(值 0 也算命中,如 DISABLED=0);未命中置 0。 + """ + self.CifEvalOk = 0 + if name is None or trans is None: + return 0 + v: int = HandlesType.lookup_cdefine_constant(name) + if HandlesType.is_cdefine_found() != 0: + self.CifEvalOk = 1 + return v + v2: int = HandlesExpr._lookup_cross_module_cdefine( + pool, name, trans._from_imports, trans._imported_modules) + if HandlesType.is_cdefine_found() != 0: + self.CifEvalOk = 1 + return v2 + pv: int = self._get_platform_macro_value(name) + if self.CifEvalOk != 0: + return pv + return 0 + + def _cif_attr_value(self, pool: memhub.MemBuddy | t.CPtr, + trans: HT.Translator | t.CPtr, + at: ast.Attribute | t.CPtr) -> int: + """Attribute 宏值: platmacro.IS_WINDOWS → 本地 CDefine(attr) → 跨模块 CDefine。 + + 命中置 self.CifEvalOk=1;未命中置 0。 + """ + self.CifEvalOk = 0 + if at is None or at.attr is None or at.value is None or trans is None: + return 0 + if at.value.kind() != ast.ASTKind.Name: + return 0 + vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) + if vn.id is None: + return 0 + v: int = HandlesType.lookup_cdefine_constant(at.attr) + if HandlesType.is_cdefine_found() != 0: + self.CifEvalOk = 1 + return v + # 跨模块: 确定真实模块名(解析 from_imports 别名) + real_mod: str = vn.id + if trans._from_imports is not None: + resolved: str = HandlesImports.lookup_from_import( + trans._from_imports, vn.id, 0) + if resolved is not None: + rm_len: t.CSizeT = 0 + while resolved[rm_len] != ' ' and resolved[rm_len] != '\0' and resolved[rm_len] != ':': + rm_len += 1 + rm_buf: str = pool.alloc(rm_len + 1) + if rm_buf is not None: + for rm_i in range(rm_len): + rm_buf[rm_i] = resolved[rm_i] + rm_buf[rm_len] = '\0' + real_mod = rm_buf + fi_len: t.CSizeT = string.strlen(at.attr) + string.strlen(real_mod) + 2 + fi: str = pool.alloc(fi_len) + if fi is None: + return 0 + viperlib.snprintf(fi, fi_len, "%s:%s", at.attr, real_mod) + v2: int = HandlesExpr._lookup_cross_module_cdefine(pool, at.attr, fi) + if HandlesType.is_cdefine_found() != 0: + self.CifEvalOk = 1 + return v2 + return 0 + + def _cif_eval_node(self, pool: memhub.MemBuddy | t.CPtr, + trans: HT.Translator | t.CPtr, + node: ast.AST | t.CPtr) -> int: + """递归常量求值 CIf 表达式。 + + 支持: Constant(int) / Name(CDefine/跨模块/平台宏) / Attribute(跨模块 CDefine) + / BinOp(+ - * // % & | ^ << >>) / Compare(== != < > <= >=) + / BoolOp(and/or) / UnaryOp(not - + ~)。 + 成功置 self.CifEvalOk=1;失败(含运行时变量)置 0 返回 0。 + """ + if node is None: + self.CifEvalOk = 0 + return 0 + k: int = node.kind() + if k == ast.ASTKind.Constant: + cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) + if cn.const_kind == ast.CONST_INT: + self.CifEvalOk = 1 + return cn.int_val + self.CifEvalOk = 0 + return 0 + if k == ast.ASTKind.Call: + return self._cif_eval_call(pool, trans, node) + if k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) + if nm.id is None: + self.CifEvalOk = 0 + return 0 + return self._cif_name_value(pool, trans, nm.id) + if k == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) + return self._cif_attr_value(pool, trans, at) + if k == ast.ASTKind.UnaryOp: + uop: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(node) + if uop.operand is None: + self.CifEvalOk = 0 + return 0 + ov: int = self._cif_eval_node(pool, trans, uop.operand) + if self.CifEvalOk == 0: + return 0 + if uop.op == ast.OpKind.Not: return 1 if ov == 0 else 0 + if uop.op == ast.OpKind.USub: return -ov + if uop.op == ast.OpKind.UAdd: return ov + if uop.op == ast.OpKind.Invert: return ~ov + self.CifEvalOk = 0 + return 0 + if k == ast.ASTKind.BoolOp: + bo: ast.BoolOp | t.CPtr = (ast.BoolOp | t.CPtr)(node) + vals: list[ast.AST | t.CPtr] | t.CPtr = bo.values + if vals is None: + self.CifEvalOk = 0 + return 0 + bn: t.CSizeT = len(vals) + if bo.op == ast.OpKind.And: + for bi in range(bn): + rv: int = self._cif_eval_node(pool, trans, vals.get(bi)) + if self.CifEvalOk == 0: + return 0 + if rv == 0: + return 0 + return 1 + if bo.op == ast.OpKind.Or: + for bi in range(bn): + rv: int = self._cif_eval_node(pool, trans, vals.get(bi)) + if self.CifEvalOk == 0: + return 0 + if rv != 0: + return 1 + return 0 + self.CifEvalOk = 0 + return 0 + if k == ast.ASTKind.Compare: + cmp: ast.Compare | t.CPtr = (ast.Compare | t.CPtr)(node) + lv: int = self._cif_eval_node(pool, trans, cmp.left) + if self.CifEvalOk == 0: + return 0 + ops_list: list[t.CInt] | t.CPtr = (list[t.CInt] | t.CPtr)(cmp.ops) + comps: list[ast.AST | t.CPtr] | t.CPtr = cmp.comparators + if ops_list is None or comps is None: + self.CifEvalOk = 0 + return 0 + cc: t.CSizeT = len(comps) + ci: t.CSizeT + for ci in range(cc): + rv: int = self._cif_eval_node(pool, trans, comps.get(ci)) + if self.CifEvalOk == 0: + return 0 + op_id: int = ops_list.get(ci) + ok_cmp: int = 0 + if op_id == ast.OpKind.Eq: ok_cmp = 1 if lv == rv else 0 + elif op_id == ast.OpKind.Ne: ok_cmp = 1 if lv != rv else 0 + elif op_id == ast.OpKind.Lt: ok_cmp = 1 if lv < rv else 0 + elif op_id == ast.OpKind.Le: ok_cmp = 1 if lv <= rv else 0 + elif op_id == ast.OpKind.Gt: ok_cmp = 1 if lv > rv else 0 + elif op_id == ast.OpKind.Ge: ok_cmp = 1 if lv >= rv else 0 + else: + self.CifEvalOk = 0 + return 0 + if ok_cmp == 0: + return 0 + lv = rv + return 1 + if k == ast.ASTKind.BinOp: + bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) + lv: int = self._cif_eval_node(pool, trans, bop.left) + if self.CifEvalOk == 0: + return 0 + rv: int = self._cif_eval_node(pool, trans, bop.right) + if self.CifEvalOk == 0: + return 0 + if bop.op == ast.OpKind.Add: return lv + rv + if bop.op == ast.OpKind.Sub: return lv - rv + if bop.op == ast.OpKind.Mult: return lv * rv + if bop.op == ast.OpKind.Div: + # 整数常量除法:与 FloorDiv 一致(对齐 TPC ConstEvaluator L354-355) + if rv == 0: + self.CifEvalOk = 0 + return 0 + return lv // rv + if bop.op == ast.OpKind.FloorDiv: + if rv == 0: + self.CifEvalOk = 0 + return 0 + return lv // rv + if bop.op == ast.OpKind.Mod: + if rv == 0: + self.CifEvalOk = 0 + return 0 + return lv % rv + if bop.op == ast.OpKind.BitAnd: return lv & rv + if bop.op == ast.OpKind.BitOr: return lv | rv + if bop.op == ast.OpKind.BitXor: return lv ^ rv + if bop.op == ast.OpKind.LShift: return lv << rv + if bop.op == ast.OpKind.RShift: return lv >> rv + self.CifEvalOk = 0 + return 0 + self.CifEvalOk = 0 + return 0 + + def _eval_ctraits_isptr(self, symtab: HandlesVar.SymbolTable | t.CPtr, + name: str) -> int: + """ctraits.isptr(name) 编译期求值。 + + 按变量实际存储类型判断是否指针:alloca 的 pointee 为 Ptr 即指针 + (与 TPC ConstEvaluator._eval_compile_time_call 的 LLVM 类型判断一致)。 + 返回: 1=指针 0=非指针 -1=无法求值(变量不存在/无类型信息)。 + """ + if name is None or symtab is None: + return -1 + v: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(symtab, name) + if v is None or v.Ty is None: + return -1 + pointee: llvmlite.LLVMType | t.CPtr = v.Ty.Pointee + if pointee is not None and HandlesExpr.is_ptr_type(pointee) != 0: + return 1 + return 0 + + def _cif_eval_call(self, pool: memhub.MemBuddy | t.CPtr, + trans: HT.Translator | t.CPtr, + node: ast.AST | t.CPtr) -> int: + """编译期函数调用求值:ctraits.isptr(x)。 + + 命中置 self.CifEvalOk=1 返回 1/0;未识别调用置 0 返回 0。 + """ + self.CifEvalOk = 0 + if node is None or trans is None: + return 0 + cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node) + if cl is None or cl.func is None: + return 0 + fk: int = cl.func.kind() + if fk != ast.ASTKind.Attribute: + return 0 + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) + if at.value is None or at.attr is None: + return 0 + if at.value.kind() != ast.ASTKind.Name: + return 0 + vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) + if vn.id is None: + return 0 + if string.strcmp(vn.id, "ctraits") != 0 or string.strcmp(at.attr, "isptr") != 0: + return 0 + cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args + if cargs is None or len(cargs) < 1: + self.CifEvalOk = 0 + return 0 + arg0: ast.AST | t.CPtr = cargs.get(0) + if arg0 is None or arg0.kind() != ast.ASTKind.Name: + self.CifEvalOk = 0 + return 0 + nm0: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arg0) + if nm0.id is None: + self.CifEvalOk = 0 + return 0 + r: int = self._eval_ctraits_isptr(trans.SymTab, nm0.id) + if r < 0: + self.CifEvalOk = 0 + return 0 + self.CifEvalOk = 1 + return r + + def _evaluate_cif_test(self, pool: memhub.MemBuddy | t.CPtr, + trans: HT.Translator | t.CPtr, + test: ast.AST | t.CPtr) -> int: + """求值 CIf 调用(test 必须是 c.CIf 系调用)。 + + 成功: 置 self.CifEvalOk=1,返回条件值(0/1) + 失败(运行时变量/未知结构): 置 self.CifEvalOk=0,返回 0 + """ + self.CifEvalOk = 0 + cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(test) + if cl is None or cl.func is None: + return 0 + kind: str = None + fk: int = cl.func.kind() + if fk == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) + kind = at.attr + elif fk == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cl.func) + kind = nm.id + if kind is None: + return 0 + cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args + if cargs is None or len(cargs) < 1: + return 0 + arg0: ast.AST | t.CPtr = cargs.get(0) + if string.strcmp(kind, "CIf") == 0: + v: int = self._cif_eval_node(pool, trans, arg0) + if self.CifEvalOk == 0: + return 0 + return 1 if v != 0 else 0 + # CIfdef / CIfndef: 判定宏名是否已定义 + defined: int = 0 + if arg0 is not None and arg0.kind() == ast.ASTKind.Name: + nm0: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arg0) + if nm0.id is None: + return 0 + self._cif_name_value(pool, trans, nm0.id) + defined = self.CifEvalOk + elif arg0 is not None and arg0.kind() == ast.ASTKind.Constant: + cn0: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(arg0) + if cn0.const_kind == ast.CONST_STR and cn0.str_val is not None: + self._cif_name_value(pool, trans, cn0.str_val) + defined = self.CifEvalOk + else: + return 0 + elif arg0 is not None and arg0.kind() == ast.ASTKind.Attribute: + at0: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg0) + self._cif_attr_value(pool, trans, at0) + defined = self.CifEvalOk + else: + return 0 + # 定义判定本身成功(未定义名特判:不报错,defined=0 走 else) + self.CifEvalOk = 1 + if string.strcmp(kind, "CIfdef") == 0: + return 1 if defined != 0 else 0 + # CIfndef + return 0 if defined != 0 else 1 + + def NewIfHandle(self, pool: memhub.MemBuddy | t.CPtr, + trans: HT.Translator | t.CPtr) -> HandlesIf.IfHandle | t.CPtr: + """创建 IfHandle 实例(迁移自 HandlesIf.NewIfHandle)""" + h: HandlesIf.IfHandle | t.CPtr = pool.alloc(HandlesIf.IfHandle.__sizeof__()) + if h is None: + return None + string.memset(h, 0, HandlesIf.IfHandle.__sizeof__()) + h.Trans = trans + return h + + # ============================================================ + # 簇 C:循环/return/match 子 Handle 工厂(迁移自 + # HandlesWhile/HandlesFor/HandlesReturn/HandlesMatch) + # ============================================================ + + def NewWhileHandle(self, pool: memhub.MemBuddy | t.CPtr, + trans: HT.Translator | t.CPtr) -> HandlesWhile.WhileHandle | t.CPtr: + """创建 WhileHandle 实例(迁移自 HandlesWhile.NewWhileHandle)""" + h: HandlesWhile.WhileHandle | t.CPtr = pool.alloc(HandlesWhile.WhileHandle.__sizeof__()) + if h is None: + return None + string.memset(h, 0, HandlesWhile.WhileHandle.__sizeof__()) + h.Trans = trans + return h + + def NewForHandle(self, pool: memhub.MemBuddy | t.CPtr, + trans: HT.Translator | t.CPtr) -> HandlesFor.ForHandle | t.CPtr: + """创建 ForHandle 实例(迁移自 HandlesFor.NewForHandle)""" + h: HandlesFor.ForHandle | t.CPtr = pool.alloc(HandlesFor.ForHandle.__sizeof__()) + if h is None: + return None + string.memset(h, 0, HandlesFor.ForHandle.__sizeof__()) + h.Trans = trans + return h + + def NewReturnHandle(self, pool: memhub.MemBuddy | t.CPtr, + trans: HT.Translator | t.CPtr) -> HandlesReturn.ReturnHandle | t.CPtr: + """创建 ReturnHandle 实例(迁移自 HandlesReturn.NewReturnHandle)""" + h: HandlesReturn.ReturnHandle | t.CPtr = pool.alloc(HandlesReturn.ReturnHandle.__sizeof__()) + if h is None: + return None + string.memset(h, 0, HandlesReturn.ReturnHandle.__sizeof__()) + h.Trans = trans + return h + + def NewMatchHandle(self, pool: memhub.MemBuddy | t.CPtr, + trans: HT.Translator | t.CPtr) -> HandlesMatch.MatchHandle | t.CPtr: + """创建 MatchHandle 实例(迁移自 HandlesMatch.NewMatchHandle)""" + h: HandlesMatch.MatchHandle | t.CPtr = pool.alloc(HandlesMatch.MatchHandle.__sizeof__()) + if h is None: + return None + string.memset(h, 0, HandlesMatch.MatchHandle.__sizeof__()) + h.Trans = trans + return h + diff --git a/App/lib/core/Gen/StmtGenDeclMixin.vp b/App/lib/core/Gen/StmtGenDeclMixin.vp new file mode 100644 index 0000000..dc7d8d7 --- /dev/null +++ b/App/lib/core/Gen/StmtGenDeclMixin.vp @@ -0,0 +1,511 @@ +import t, c +from stdint import * +import ast +import llvmlite +import memhub +import string +import stdlib +import stdio +import viperlib +import lib.core.VLogger as VLogger +import lib.core.Handles.HandlesTranslator as HT +import lib.core.Handles.HandlesType as HandlesType +import lib.core.Handles.HandlesVar as HandlesVar +import lib.core.Handles.HandlesExpr as HandlesExpr +import lib.core.Handles.HandlesExprCall as HandlesExprCall +import lib.core.Handles.HandlesStruct as HandlesStruct +import lib.core.Handles.HandlesFunctions as HandlesFunctions +import lib.core.Handles.HandlesClassDef as HandlesClassDef +import lib.core.Handles.HandlesImports as HandlesImports +import lib.core.Handles.HandlesIf as HandlesIf +import lib.core.Handles.HandlesWhile as HandlesWhile +import lib.core.Handles.HandlesFor as HandlesFor +import lib.core.Handles.HandlesReturn as HandlesReturn +import lib.core.Handles.HandlesStruct as HandlesStruct +import lib.core.Handles.HandlesMatch as HandlesMatch +import lib.core.Handles.HandlesEnum as HandlesEnum +import lib.core.CompilerFactory as CompilerFactory +import lib.Projectrans.Config as Config +import lib.core.Gen.StmtGenCifMixin as StmtGenCifMixin + + +# ============================================================ +# StmtGenDeclMixin - StmtGen 拆分 2/3:声明/枚举/nonlocal 访问 +# +# 按功能域从 StmtGenMixin.vp 拆出(500~1500 行/文件架构重构,试点): +# translate_global/nonlocal/expr_stmt/pre_scan、break/continue、 +# nonlocal 闭包 env 访问、枚举注册表。继承 StmtGenCifMixin。 +# +# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整)。 +# ============================================================ + + +# ============================================================ +# 常量(与 HandlesEnum 保持一致,本地副本避免跨模块 CDefine 查找 bug) +# ============================================================ +ENUM_MAX: t.CDefine = 64 +ENUM_MEMBER_MAX: t.CDefine = 128 + +# ============================================================ +# StmtGenDeclMixin - 声明/枚举/nonlocal(中层级) +# ============================================================ +@t.NoVTable +class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin): + """声明/枚举/nonlocal 访问(StmtGen 拆分 2/3,继承 Cif)""" + + def translate_global(self, trans: HT.Translator | t.CPtr, + node: ast.AST | t.CPtr) -> int: + """翻译 global 语句:记录 global 变量名""" + gn: ast.Global | t.CPtr = (ast.Global | t.CPtr)(node) + if gn is None: + return 0 + names: list[ast.AST | t.CPtr] | t.CPtr = gn.names + if names is None: + return 0 + n: t.CSizeT = len(names) + for i in range(n): + nm_node: ast.AST | t.CPtr = names.get(i) + if nm_node is not None and nm_node.kind() == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(nm_node) + if nm.id is not None: + HT.add_global_name(trans, nm.id) + return 0 + + def translate_nonlocal(self, trans: HT.Translator | t.CPtr, + node: ast.AST | t.CPtr) -> int: + """翻译 nonlocal 语句:记录 nonlocal 变量名及其类型 + + 类型信息通过查找父作用域的 alloca 获取(用于 env 指针数组方案的类型恢复)。 + """ + nl: ast.Nonlocal | t.CPtr = (ast.Nonlocal | t.CPtr)(node) + if nl is None: + return 0 + names: list[ast.AST | t.CPtr] | t.CPtr = nl.names + if names is None: + return 0 + n: t.CSizeT = len(names) + for i in range(n): + nm_node: ast.AST | t.CPtr = names.get(i) + if nm_node is not None and nm_node.kind() == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(nm_node) + if nm.id is not None: + # 查找父作用域中的变量 alloca,获取类型信息 + var_ty: llvmlite.LLVMType | t.CPtr = None + var_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var( + trans.SymTab, nm.id) + if var_alloca is not None and var_alloca.Ty is not None: + var_ty = var_alloca.Ty.Pointee + # Void 类型视为无效(Pointee 访问异常时可能返回 Void), + # 类型无效直接报错终止(fail-fast),避免生成 + # "bitcast ... to void*" / "load void, void*" 非法 IR + if var_ty is not None: + match var_ty: + case llvmlite.LLVMType.Void(): + HandlesType.fatal_error(nm_node, f"nonlocal 变量 '{nm.id}' 类型无效(Void/无法解析)", "TypeError") + case _: + pass + HT.add_nonlocal_name(trans, nm.id, var_ty) + return 0 + + def translate_expr_stmt(self, trans: HT.Translator | t.CPtr, + node: ast.AST | t.CPtr) -> int: + """翻译表达式语句(printf 调用等)""" + ex: ast.Expr | t.CPtr = (ast.Expr | t.CPtr)(node) + if ex is None: + return 0 + call_node: ast.AST | t.CPtr = ex.value + if call_node is None: + return 0 + ck: int = call_node.kind() + if ck != ast.ASTKind.Call: + return 0 + + cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(call_node) + func_node: ast.AST | t.CPtr = cl.func + if func_node is None: + return 0 + + func_name: str = HandlesExpr.get_func_name(func_node) + if func_name is None: + # 函数名解析失败:直接报错终止(fail-fast) + HandlesType.fatal_error(call_node, "表达式语句的函数名解析失败", "SyntaxError") + + # printf / print 走特殊路径(print 是类型感知格式化,不映射到 printf) + if string.strcmp(func_name, "printf") == 0: + trans.ExprCallH.HandlePrintfCall(cl) + elif string.strcmp(func_name, "print") == 0: + trans.ExprCallH.HandlePrintCall(cl) + else: + # 通用函数调用(返回值丢弃) + trans.ExprCallH.HandleCall(call_node) + return 0 + + def pre_scan_allocas(self, trans: HT.Translator | t.CPtr, + node: ast.AST | t.CPtr) -> int: + """预扫描语句中的 AnnAssign,提前创建 alloca + + 返回新增的变量数 + """ + if node is None: + return 0 + return trans.AnnAssignH.PreScan(node) + + def pre_scan_scope_decls(self, trans: HT.Translator | t.CPtr, + node: ast.AST | t.CPtr) -> int: + """预扫描 Global/Nonlocal 声明,提前注册作用域名称""" + if node is None: + return 0 + k: int = node.kind() + if k == ast.ASTKind.Global: + return self.translate_global(trans, node) + if k == ast.ASTKind.Nonlocal: + return self.translate_nonlocal(trans, node) + return 0 + + def translate_break(self, trans: HT.Translator | t.CPtr) -> int: + """翻译 break 语句:跳转到循环 end 块""" + builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder + func: llvmlite.Function | t.CPtr = trans._cur_func + pool: memhub.MemBuddy | t.CPtr = trans.Pool + + if builder is None or func is None: + return 0 + + # 发射 br 到 break 目标 + if trans._break_bb is not None: + if llvmlite.builder_cur_block_is_terminated(builder) == 0: + llvmlite.build_br(builder, trans._break_bb) + + # 创建死代码 BB,用于后续语句(break 后面的代码不可达) + cnt: int = trans._label_counter + trans._label_counter = cnt + 1 + name_buf: str = pool.alloc(32) + viperlib.snprintf(name_buf, 32, "dead.%d", cnt) + dead_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) + llvmlite.position_at_end(builder, dead_bb) + return 0 + + def translate_continue(self, trans: HT.Translator | t.CPtr) -> int: + """翻译 continue 语句:跳转到循环 cond/incr 块""" + builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder + func: llvmlite.Function | t.CPtr = trans._cur_func + pool: memhub.MemBuddy | t.CPtr = trans.Pool + + if builder is None or func is None: + return 0 + + # 发射 br 到 continue 目标 + if trans._continue_bb is not None: + if llvmlite.builder_cur_block_is_terminated(builder) == 0: + llvmlite.build_br(builder, trans._continue_bb) + + # 创建死代码 BB,用于后续语句 + cnt: int = trans._label_counter + trans._label_counter = cnt + 1 + name_buf: str = pool.alloc(32) + viperlib.snprintf(name_buf, 32, "dead.%d", cnt) + dead_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) + llvmlite.position_at_end(builder, dead_bb) + return 0 + + def get_stmt_kind_name(self, node: ast.AST | t.CPtr) -> str: + """获取语句类型名""" + if node is None: + return None + return node.type_name() + + # ============================================================ + # 簇 D:nonlocal/闭包 env 访问(迁移自 HandlesNonlocal.vp) + # ============================================================ + + def _is_void_type(self, ty: llvmlite.LLVMType | t.CPtr) -> int: + """判断是否为 Void 类型,是则返回 1,否则 0""" + if ty is None: + return 0 + match ty: + case llvmlite.LLVMType.Void(): + return 1 + case _: + return 0 + + def get_env_ptr_var(self, trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr: + """获取或创建 _env_ptr 变量(存储闭包 env 指针)""" + env_var: llvmlite.Value | t.CPtr = HandlesVar.lookup_var( + trans.SymTab, "_env_ptr") + if env_var is not None: + return env_var + # 创建 alloca 存储 env + pool: memhub.MemBuddy | t.CPtr = trans.Pool + builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder + i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) + i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) + alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, i8_ptr_ty) + if alloca is None: + return None + HandlesVar.define_var(trans.SymTab, "_env_ptr", alloca) + return alloca + + def _load_raw_var_ptr(self, trans: HT.Translator | t.CPtr, + name: str) -> llvmlite.Value | t.CPtr: + """从闭包 env 加载 nonlocal 变量的原始指针(i8*) + + 返回 i8* 类型的 Value,调用方需 bitcast 为具体类型指针后 load/store。 + """ + idx: int = HT.get_nonlocal_index(trans, name) + if idx < 0: + return None + + pool: memhub.MemBuddy | t.CPtr = trans.Pool + builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder + i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) + i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) + i8_ptr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty) + + # 1. 加载 env_ptr + env_alloca: llvmlite.Value | t.CPtr = self.get_env_ptr_var(trans) + if env_alloca is None: + return None + env_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, env_alloca) + if env_ptr is None: + return None + + # 2. GEP to offset (idx * 8) — env 存储指针数组,每槽 8 字节 + offset_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, idx * 8) + addr: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, env_ptr, offset_val) + if addr is None: + return None + + # 3. Bitcast to i8** and load the raw pointer + ptr_addr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, addr, i8_ptr_ptr_ty) + if ptr_addr is None: + return None + return llvmlite.build_load(builder, i8_ptr_ty, ptr_addr) + + def load_nonlocal_var(self, trans: HT.Translator | t.CPtr, + name: str) -> llvmlite.Value | t.CPtr: + """从闭包 env 加载 nonlocal 变量值 + + 通过 HT.get_nonlocal_type 获取变量类型,bitcast 原始指针后 load。 + """ + raw_ptr: llvmlite.Value | t.CPtr = self._load_raw_var_ptr(trans, name) + if raw_ptr is None: + return None + + pool: memhub.MemBuddy | t.CPtr = trans.Pool + builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder + + # 获取变量类型(从注册时存储的类型信息) + var_ty: llvmlite.LLVMType | t.CPtr = HT.get_nonlocal_type(trans, name) + if var_ty is None or self._is_void_type(var_ty) != 0: + # 类型缺失/无效直接报错终止(fail-fast),避免生成 "load void, void*" 非法 IR + HandlesType.fatal_error(None, f"nonlocal 变量 '{name}' 类型缺失,无法 load", "TypeError") + + # bitcast raw i8* to var_ty* + var_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, var_ty) + var_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, raw_ptr, var_ptr_ty) + if var_ptr is None: + return None + return llvmlite.build_load(builder, var_ty, var_ptr) + + def get_nonlocal_var_ptr(self, trans: HT.Translator | t.CPtr, + name: str) -> llvmlite.Value | t.CPtr: + """获取 nonlocal 变量的存储指针(var_ty*),用于 store 操作 + + 返回的指针指向父函数的 alloca,store 操作对父函数可见。 + """ + raw_ptr: llvmlite.Value | t.CPtr = self._load_raw_var_ptr(trans, name) + if raw_ptr is None: + return None + + pool: memhub.MemBuddy | t.CPtr = trans.Pool + builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder + + # 获取变量类型 + var_ty: llvmlite.LLVMType | t.CPtr = HT.get_nonlocal_type(trans, name) + if var_ty is None or self._is_void_type(var_ty) != 0: + # 类型缺失/无效直接报错终止(fail-fast),避免生成 "bitcast ... to void*" 非法 IR + HandlesType.fatal_error(None, f"nonlocal 变量 '{name}' 类型缺失,无法 load", "TypeError") + + # bitcast raw i8* to var_ty* + var_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, var_ty) + return llvmlite.build_bitcast(builder, raw_ptr, var_ptr_ty) + + # ============================================================ + # 簇 E:枚举注册表(迁移自 HandlesEnum.vp) + # ============================================================ + + def init_enum_table(self, pool: memhub.MemBuddy | t.CPtr) -> int: + """初始化枚举注册表,返回 1 成功 + + 表用 stdlib 分配(跨 Phase1 1b 的 mark/reset_to 存活——枚举表是 + 跨文件持久表,pool 分配会被 reset 回收导致 Phase B 读垃圾, + enum_count 出现 512 等垃圾值 / entry.Name 解引用崩溃)。 + """ + if self.EnumTable is not None: + return 1 + + entry_size: t.CSizeT = HandlesEnum.EnumEntry.__sizeof__() + self.EnumTable = CompilerFactory.get_perm_pool().alloc(entry_size * ENUM_MAX) + if self.EnumTable is None: + return 0 + string.memset(self.EnumTable, 0, entry_size * ENUM_MAX) + self.EnumCount = 0 + return 1 + + def _get_enum_entry(self, i: int) -> HandlesEnum.EnumEntry | t.CPtr: + """获取第 i 个枚举条目""" + if self.EnumTable is None or i < 0 or i >= ENUM_MAX: + return None + entry_size: t.CSizeT = HandlesEnum.EnumEntry.__sizeof__() + addr: t.CUInt64T = t.CUInt64T(self.EnumTable) + i * entry_size + return (HandlesEnum.EnumEntry | t.CPtr)(t.CVoid(addr, t.CPtr)) + + def _get_enum_member(self, enum_entry: HandlesEnum.EnumEntry | t.CPtr, + i: int) -> HandlesEnum.EnumMember | t.CPtr: + """获取枚举中第 i 个成员条目""" + if enum_entry is None or i < 0 or i >= ENUM_MEMBER_MAX: + return None + member_size: t.CSizeT = HandlesEnum.EnumMember.__sizeof__() + addr: t.CUInt64T = t.CUInt64T(enum_entry.Members) + i * member_size + return (HandlesEnum.EnumMember | t.CPtr)(t.CVoid(addr, t.CPtr)) + + def register_enum(self, pool: memhub.MemBuddy | t.CPtr, + name: str, + base_ty: llvmlite.LLVMType | t.CPtr) -> HandlesEnum.EnumEntry | t.CPtr: + """注册枚举类型,返回 EnumEntry 指针""" + if self.init_enum_table(pool) == 0: + return None + + # 检查是否已注册 + existing: HandlesEnum.EnumEntry | t.CPtr = self.find_enum(name) + if existing is not None: + return existing + + if self.EnumCount >= ENUM_MAX: + fb_et: str = VLogger.fmt_buf() + if fb_et is not None: + viperlib.snprintf(fb_et, 1024, "table full, cannot register %s", name) + VLogger.error(fb_et, "ENUM") + return None + + entry: HandlesEnum.EnumEntry | t.CPtr = self._get_enum_entry(self.EnumCount) + if entry is None: + return None + + # 分配成员数组(永久池:跨 mark/reset 存活,对齐 EnumTable 永久池化) + member_size: t.CSizeT = HandlesEnum.EnumMember.__sizeof__() + entry.Members = CompilerFactory.get_perm_pool().alloc(member_size * ENUM_MEMBER_MAX) + if entry.Members is None: + return None + string.memset(entry.Members, 0, member_size * ENUM_MEMBER_MAX) + + # 复制类名(永久池深拷贝) + name_len: t.CSizeT = string.strlen(name) + name_buf: str = CompilerFactory.get_perm_pool().alloc(name_len + 1) + if name_buf is not None: + string.strcpy(name_buf, name) + entry.Name = name_buf + + # BaseTy 深拷贝:LLVMType 是 pool 分配,StdlibAlloc=1(Phase2 mark2 后) + # 时 reset 回收悬空 → Phase B 枚举访问 ConstInt(悬空 BaseTy) 生成 void + # 值(DecoratorMarkerTest `store void 2` llc 报错根因)。Phase1 1a + # (StdlibAlloc=0,mark1 前)保持 pool 存活,无需拷贝。 + # 注意:StdlibAlloc 是 StructGenMixin 字段,本 Mixin 方法体不能直接 + # self.StdlibAlloc(NoVTable 按本 Mixin 字段布局编译),走模块级委托。 + if HandlesStruct.get_stdlib_alloc() != 0: + base_ty_copy: llvmlite.LLVMType | t.CPtr = llvmlite.DeepCopyType( + CompilerFactory.get_perm_pool(), base_ty) + if base_ty_copy is not None: + entry.BaseTy = base_ty_copy + else: + entry.BaseTy = base_ty + else: + entry.BaseTy = base_ty + entry.MemberCount = 0 + + self.EnumCount += 1 + return entry + + def add_enum_member(self, pool: memhub.MemBuddy | t.CPtr, + enum_entry: HandlesEnum.EnumEntry | t.CPtr, + member_name: str, + member_val: t.CInt64T, + member_ty: llvmlite.LLVMType | t.CPtr) -> int: + """向枚举添加成员,返回成员索引(-1 失败)""" + if enum_entry is None or member_name is None or member_ty is None: + return -1 + + # 去重:同名成员已存在则跳过(跨模块同名枚举合并注册 / 同模块 + # 重复处理幂等——如 w32.fileio 与 fat32_types 都有 FRESULT) + for ei_d in range(enum_entry.MemberCount): + ex_d: HandlesEnum.EnumMember | t.CPtr = self._get_enum_member( + enum_entry, ei_d) + if ex_d is not None and ex_d.Name is not None: + if string.strcmp(ex_d.Name, member_name) == 0: + return ei_d + + if enum_entry.MemberCount >= ENUM_MEMBER_MAX: + fb_em: str = VLogger.fmt_buf() + if fb_em is not None: + viperlib.snprintf(fb_em, 1024, "member table full for %s", enum_entry.Name) + VLogger.error(fb_em, "ENUM") + return -1 + + idx: int = enum_entry.MemberCount + me: HandlesEnum.EnumMember | t.CPtr = self._get_enum_member(enum_entry, idx) + if me is None: + return -1 + + # 复制成员名(永久池深拷贝:成员表跨 mark/reset 存活) + name_len: t.CSizeT = string.strlen(member_name) + name_buf: str = CompilerFactory.get_perm_pool().alloc(name_len + 1) + if name_buf is not None: + string.strcpy(name_buf, member_name) + me.Name = name_buf + + me.Value = member_val + me.Ty = member_ty + + enum_entry.MemberCount = idx + 1 + return idx + + def find_enum(self, name: str) -> HandlesEnum.EnumEntry | t.CPtr: + """按枚举类名查找,返回 EnumEntry 或 None""" + if name is None or self.EnumTable is None: + return None + for i in range(self.EnumCount): + entry: HandlesEnum.EnumEntry | t.CPtr = self._get_enum_entry(i) + if entry is not None and entry.Name is not None: + if string.strcmp(entry.Name, name) == 0: + return entry + return None + + def lookup_enum_member(self, enum_name: str, + member_name: str) -> HandlesEnum.EnumMember | t.CPtr: + """按枚举类名和成员名查找,返回 EnumMember 或 None""" + if enum_name is None or member_name is None: + return None + entry: HandlesEnum.EnumEntry | t.CPtr = self.find_enum(enum_name) + if entry is None: + return None + for mi in range(entry.MemberCount): + me: HandlesEnum.EnumMember | t.CPtr = self._get_enum_member(entry, mi) + if me is not None and me.Name is not None: + if string.strcmp(me.Name, member_name) == 0: + return me + return None + + def is_enum_class(self, name: str) -> int: + """检查类名是否为已注册枚举,返回 1=是 / 0=否""" + if name is None: + return 0 + if self.find_enum(name) is not None: + return 1 + return 0 + + def get_enum_base_type(self, enum_name: str) -> llvmlite.LLVMType | t.CPtr: + """按枚举类名获取基准类型""" + entry: HandlesEnum.EnumEntry | t.CPtr = self.find_enum(enum_name) + if entry is not None: + return entry.BaseTy + return None diff --git a/App/lib/core/Gen/StmtGenMixin.vp b/App/lib/core/Gen/StmtGenMixin.vp index 4d9def5..1259d56 100644 --- a/App/lib/core/Gen/StmtGenMixin.vp +++ b/App/lib/core/Gen/StmtGenMixin.vp @@ -26,66 +26,28 @@ import lib.core.Handles.HandlesMatch as HandlesMatch import lib.core.Handles.HandlesEnum as HandlesEnum import lib.core.CompilerFactory as CompilerFactory import lib.Projectrans.Config as Config +import lib.core.Gen.StmtGenDeclMixin as StmtGenDeclMixin # ============================================================ -# StmtGenMixin - 语句/流程翻译 Mixin(P6 对象化重构 A 组) +# StmtGenMixin - 语句/流程翻译 Mixin(P6 对象化重构 A 组,拆分后顶层) # -# 迁移自 HandlesBody/HandlesIf/HandlesWhile/HandlesFor/HandlesReturn/ -# HandlesNonlocal/HandlesMatch/HandlesEnum 的模块级函数(trans 首参 -# 或无状态纯函数 + NewXxxHandle 工厂)→ 类方法;全局状态 -# (_g_cif_eval_ok/_enum_table/_enum_count)→ 本类字段。 -# -# 迁移原则(与 P1-P5 一致,行为零变化): -# 1. 方法保留原函数签名(含 trans/pool 首参),仅函数体内的 -# 本模块函数调用改为 self.xxx(...) -# 2. 外部模块调用(HandlesVar.xxx/HandlesExpr.xxx/HandlesType.xxx -# 等)保留模块前缀(对应模块保留委托层) -# 3. trans.XxxH.Handle(...) 子 Handle 分派保留(Handle 类不动, -# 由 HandlesTranslator._init_state 通过 NewXxxHandle 工厂创建) -# 4. 原 Handles 模块函数保留为"委托":本地模块级单例 _g_gen -# (BuildPipeline/main 注入)cast 成 Generator 类型调本类方法 -# 5. HandlesIf._g_cif_eval_ok → self.CifEvalOk;HandlesEnum -# _enum_table/_enum_count → self.EnumTable/self.EnumCount +# 按功能域拆分(500~1500 行/文件架构重构,试点): +# 顶层保留语句分派中枢簇 A(translate_stmt/try/raise/with/delete/ +# _eh_ret_default/_with_ctx_call);global/nonlocal/枚举/CIf 已拆至 +# StmtGenDeclMixin / StmtGenCifMixin(本类继承链 1/3、2/3)。 +# 外部引用(Generator.vp import + HandlesBody 委托)零改动。 # # @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整)。 # ============================================================ # ============================================================ -# 常量(与 HandlesEnum 保持一致,本地副本避免跨模块 CDefine 查找 bug) -# ============================================================ -ENUM_MAX: t.CDefine = 64 -ENUM_MEMBER_MAX: t.CDefine = 128 - - -# ============================================================ -# StmtGenMixin - 语句/流程翻译(P6 方法化) +# StmtGenMixin - 语句分派中枢(顶层) # ============================================================ @t.NoVTable -class StmtGenMixin: - """语句/流程翻译 Mixin(P6 方法化) - - 迁移自 HandlesBody/HandlesIf/HandlesWhile/HandlesFor/HandlesReturn/ - HandlesNonlocal/HandlesMatch/HandlesEnum 的模块级函数 - """ - - # --- 编译期 CIf 求值状态(原 HandlesIf._g_cif_eval_ok) --- - # 用 8 字节类型:Mixin 独立布局与 Generator 组合布局的字段对齐必须一致 - # (i32 首字段在组合布局中导致 EnumTable 相对偏移 4 vs 独立布局 8 的错位, - # this_adjust 无法同时修正,枚举表错位到相邻字段被覆盖——ASTCtx 丢失根因)。 - CifEvalOk: t.CSizeT - - # --- 枚举注册表(原 HandlesEnum._enum_table/_enum_count) --- - EnumTable: HandlesEnum.EnumEntry | t.CPtr - EnumCount: int - - # --- OOM 语句级诊断计数(translate_stmt 限频打印 used) --- - DiagStmtCount: int - - # ============================================================ - # 簇 A:语句分派/流程语句(迁移自 HandlesBody.vp) - # ============================================================ +class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin): + """语句/流程翻译 Mixin(拆分后顶层,继承 Decl)""" def translate_stmt(self, trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int: @@ -798,918 +760,3 @@ class StmtGenMixin: return HandlesExpr.translate_value( builder, pool, mod, call_node, trans._funcs, trans._func_count, trans) - - def translate_global(self, trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """翻译 global 语句:记录 global 变量名""" - gn: ast.Global | t.CPtr = (ast.Global | t.CPtr)(node) - if gn is None: - return 0 - names: list[ast.AST | t.CPtr] | t.CPtr = gn.names - if names is None: - return 0 - n: t.CSizeT = len(names) - for i in range(n): - nm_node: ast.AST | t.CPtr = names.get(i) - if nm_node is not None and nm_node.kind() == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(nm_node) - if nm.id is not None: - HT.add_global_name(trans, nm.id) - return 0 - - def translate_nonlocal(self, trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """翻译 nonlocal 语句:记录 nonlocal 变量名及其类型 - - 类型信息通过查找父作用域的 alloca 获取(用于 env 指针数组方案的类型恢复)。 - """ - nl: ast.Nonlocal | t.CPtr = (ast.Nonlocal | t.CPtr)(node) - if nl is None: - return 0 - names: list[ast.AST | t.CPtr] | t.CPtr = nl.names - if names is None: - return 0 - n: t.CSizeT = len(names) - for i in range(n): - nm_node: ast.AST | t.CPtr = names.get(i) - if nm_node is not None and nm_node.kind() == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(nm_node) - if nm.id is not None: - # 查找父作用域中的变量 alloca,获取类型信息 - var_ty: llvmlite.LLVMType | t.CPtr = None - var_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var( - trans.SymTab, nm.id) - if var_alloca is not None and var_alloca.Ty is not None: - var_ty = var_alloca.Ty.Pointee - # Void 类型视为无效(Pointee 访问异常时可能返回 Void), - # 类型无效直接报错终止(fail-fast),避免生成 - # "bitcast ... to void*" / "load void, void*" 非法 IR - if var_ty is not None: - match var_ty: - case llvmlite.LLVMType.Void(): - HandlesType.fatal_error(nm_node, f"nonlocal 变量 '{nm.id}' 类型无效(Void/无法解析)", "TypeError") - case _: - pass - HT.add_nonlocal_name(trans, nm.id, var_ty) - return 0 - - def translate_expr_stmt(self, trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """翻译表达式语句(printf 调用等)""" - ex: ast.Expr | t.CPtr = (ast.Expr | t.CPtr)(node) - if ex is None: - return 0 - call_node: ast.AST | t.CPtr = ex.value - if call_node is None: - return 0 - ck: int = call_node.kind() - if ck != ast.ASTKind.Call: - return 0 - - cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(call_node) - func_node: ast.AST | t.CPtr = cl.func - if func_node is None: - return 0 - - func_name: str = HandlesExpr.get_func_name(func_node) - if func_name is None: - # 函数名解析失败:直接报错终止(fail-fast) - HandlesType.fatal_error(call_node, "表达式语句的函数名解析失败", "SyntaxError") - - # printf / print 走特殊路径(print 是类型感知格式化,不映射到 printf) - if string.strcmp(func_name, "printf") == 0: - trans.ExprCallH.HandlePrintfCall(cl) - elif string.strcmp(func_name, "print") == 0: - trans.ExprCallH.HandlePrintCall(cl) - else: - # 通用函数调用(返回值丢弃) - trans.ExprCallH.HandleCall(call_node) - return 0 - - def pre_scan_allocas(self, trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """预扫描语句中的 AnnAssign,提前创建 alloca - - 返回新增的变量数 - """ - if node is None: - return 0 - return trans.AnnAssignH.PreScan(node) - - def pre_scan_scope_decls(self, trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """预扫描 Global/Nonlocal 声明,提前注册作用域名称""" - if node is None: - return 0 - k: int = node.kind() - if k == ast.ASTKind.Global: - return self.translate_global(trans, node) - if k == ast.ASTKind.Nonlocal: - return self.translate_nonlocal(trans, node) - return 0 - - def translate_break(self, trans: HT.Translator | t.CPtr) -> int: - """翻译 break 语句:跳转到循环 end 块""" - builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - func: llvmlite.Function | t.CPtr = trans._cur_func - pool: memhub.MemBuddy | t.CPtr = trans.Pool - - if builder is None or func is None: - return 0 - - # 发射 br 到 break 目标 - if trans._break_bb is not None: - if llvmlite.builder_cur_block_is_terminated(builder) == 0: - llvmlite.build_br(builder, trans._break_bb) - - # 创建死代码 BB,用于后续语句(break 后面的代码不可达) - cnt: int = trans._label_counter - trans._label_counter = cnt + 1 - name_buf: str = pool.alloc(32) - viperlib.snprintf(name_buf, 32, "dead.%d", cnt) - dead_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - llvmlite.position_at_end(builder, dead_bb) - return 0 - - def translate_continue(self, trans: HT.Translator | t.CPtr) -> int: - """翻译 continue 语句:跳转到循环 cond/incr 块""" - builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - func: llvmlite.Function | t.CPtr = trans._cur_func - pool: memhub.MemBuddy | t.CPtr = trans.Pool - - if builder is None or func is None: - return 0 - - # 发射 br 到 continue 目标 - if trans._continue_bb is not None: - if llvmlite.builder_cur_block_is_terminated(builder) == 0: - llvmlite.build_br(builder, trans._continue_bb) - - # 创建死代码 BB,用于后续语句 - cnt: int = trans._label_counter - trans._label_counter = cnt + 1 - name_buf: str = pool.alloc(32) - viperlib.snprintf(name_buf, 32, "dead.%d", cnt) - dead_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - llvmlite.position_at_end(builder, dead_bb) - return 0 - - def get_stmt_kind_name(self, node: ast.AST | t.CPtr) -> str: - """获取语句类型名""" - if node is None: - return None - return node.type_name() - - # ============================================================ - # 簇 B:编译期 CIf 宏求值(迁移自 HandlesIf.vp 模块级函数) - # ============================================================ - - def _is_cif_attr(self, attr: str) -> int: - """检查方法名是否为 CIf 系(CIf/CIfdef/CIfndef)""" - if attr is None: - return 0 - if string.strcmp(attr, "CIf") == 0: return 1 - if string.strcmp(attr, "CIfdef") == 0: return 1 - if string.strcmp(attr, "CIfndef") == 0: return 1 - return 0 - - def _is_cif_call(self, node: ast.AST | t.CPtr) -> int: - """检查 test 是否为 c.CIf(...)/c.CIfdef(...)/c.CIfndef(...)(或裸 CIf 系)调用""" - if node is None or node.kind() != ast.ASTKind.Call: - return 0 - cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node) - if cl.func is None: - return 0 - fk: int = cl.func.kind() - if fk == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) - if at.attr is None: - return 0 - if at.value is not None and at.value.kind() == ast.ASTKind.Name: - vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if vn.id is not None and string.strcmp(vn.id, "c") == 0: - return self._is_cif_attr(at.attr) - return 0 - if fk == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cl.func) - if nm.id is not None and self._is_cif_attr(nm.id) != 0: - return 1 - return 0 - - def _get_platform_macro_value(self, name: str) -> int: - """平台内置宏值(从目标三元组推导,对齐 TPC HandlesIf._get_platform_macros)。 - - 命中置 self.CifEvalOk=1;未命中置 0 返回 0。 - """ - self.CifEvalOk = 0 - if name is None: - return 0 - triple: str = Config.TargetTriple - if triple is None: - triple = "x86_64-pc-windows-gnu" - is_win: int = 0 - is_linux: int = 0 - is_x64: int = 0 - if string.strstr(triple, "windows") is not None \ - or string.strstr(triple, "win32") is not None \ - or string.strstr(triple, "mingw") is not None \ - or string.strstr(triple, "msvc") is not None: - is_win = 1 - if string.strstr(triple, "linux") is not None: - is_linux = 1 - if string.strstr(triple, "x86_64") is not None: - is_x64 = 1 - # 简化:本编译目标为 x86_64 Windows(_WIN64/WIN64 恒与 is_win 一致) - if string.strcmp(name, "_WIN32") == 0: self.CifEvalOk = is_win; return 1 if is_win else 0 - if string.strcmp(name, "WIN32") == 0: self.CifEvalOk = is_win; return 1 if is_win else 0 - if string.strcmp(name, "_WIN64") == 0: self.CifEvalOk = is_win; return 1 if is_win else 0 - if string.strcmp(name, "WIN64") == 0: self.CifEvalOk = is_win; return 1 if is_win else 0 - if string.strcmp(name, "__linux__") == 0: self.CifEvalOk = is_linux; return 1 if is_linux else 0 - if string.strcmp(name, "__x86_64__") == 0: self.CifEvalOk = is_x64; return 1 if is_x64 else 0 - if string.strcmp(name, "__x86_64") == 0: self.CifEvalOk = is_x64; return 1 if is_x64 else 0 - if string.strcmp(name, "_M_X64") == 0: self.CifEvalOk = is_x64; return 1 if is_x64 else 0 - if string.strcmp(name, "SIZEOF_VOID_P") == 0: self.CifEvalOk = 1; return 8 if is_x64 else 4 - if string.strcmp(name, "__SIZEOF_POINTER__") == 0: self.CifEvalOk = 1; return 8 if is_x64 else 4 - if string.strcmp(name, "NDEBUG") == 0: self.CifEvalOk = 1; return 0 - return 0 - - def _cif_name_value(self, pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr, - name: str) -> int: - """查宏名值: 本地 CDefine → 跨模块 CDefine → 平台宏。 - - 命中置 self.CifEvalOk=1(值 0 也算命中,如 DISABLED=0);未命中置 0。 - """ - self.CifEvalOk = 0 - if name is None or trans is None: - return 0 - v: int = HandlesType.lookup_cdefine_constant(name) - if HandlesType.is_cdefine_found() != 0: - self.CifEvalOk = 1 - return v - v2: int = HandlesExpr._lookup_cross_module_cdefine( - pool, name, trans._from_imports, trans._imported_modules) - if HandlesType.is_cdefine_found() != 0: - self.CifEvalOk = 1 - return v2 - pv: int = self._get_platform_macro_value(name) - if self.CifEvalOk != 0: - return pv - return 0 - - def _cif_attr_value(self, pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr, - at: ast.Attribute | t.CPtr) -> int: - """Attribute 宏值: platmacro.IS_WINDOWS → 本地 CDefine(attr) → 跨模块 CDefine。 - - 命中置 self.CifEvalOk=1;未命中置 0。 - """ - self.CifEvalOk = 0 - if at is None or at.attr is None or at.value is None or trans is None: - return 0 - if at.value.kind() != ast.ASTKind.Name: - return 0 - vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if vn.id is None: - return 0 - v: int = HandlesType.lookup_cdefine_constant(at.attr) - if HandlesType.is_cdefine_found() != 0: - self.CifEvalOk = 1 - return v - # 跨模块: 确定真实模块名(解析 from_imports 别名) - real_mod: str = vn.id - if trans._from_imports is not None: - resolved: str = HandlesImports.lookup_from_import( - trans._from_imports, vn.id, 0) - if resolved is not None: - rm_len: t.CSizeT = 0 - while resolved[rm_len] != ' ' and resolved[rm_len] != '\0' and resolved[rm_len] != ':': - rm_len += 1 - rm_buf: str = pool.alloc(rm_len + 1) - if rm_buf is not None: - for rm_i in range(rm_len): - rm_buf[rm_i] = resolved[rm_i] - rm_buf[rm_len] = '\0' - real_mod = rm_buf - fi_len: t.CSizeT = string.strlen(at.attr) + string.strlen(real_mod) + 2 - fi: str = pool.alloc(fi_len) - if fi is None: - return 0 - viperlib.snprintf(fi, fi_len, "%s:%s", at.attr, real_mod) - v2: int = HandlesExpr._lookup_cross_module_cdefine(pool, at.attr, fi) - if HandlesType.is_cdefine_found() != 0: - self.CifEvalOk = 1 - return v2 - return 0 - - def _cif_eval_node(self, pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """递归常量求值 CIf 表达式。 - - 支持: Constant(int) / Name(CDefine/跨模块/平台宏) / Attribute(跨模块 CDefine) - / BinOp(+ - * // % & | ^ << >>) / Compare(== != < > <= >=) - / BoolOp(and/or) / UnaryOp(not - + ~)。 - 成功置 self.CifEvalOk=1;失败(含运行时变量)置 0 返回 0。 - """ - if node is None: - self.CifEvalOk = 0 - return 0 - k: int = node.kind() - if k == ast.ASTKind.Constant: - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) - if cn.const_kind == ast.CONST_INT: - self.CifEvalOk = 1 - return cn.int_val - self.CifEvalOk = 0 - return 0 - if k == ast.ASTKind.Call: - return self._cif_eval_call(pool, trans, node) - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - if nm.id is None: - self.CifEvalOk = 0 - return 0 - return self._cif_name_value(pool, trans, nm.id) - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - return self._cif_attr_value(pool, trans, at) - if k == ast.ASTKind.UnaryOp: - uop: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(node) - if uop.operand is None: - self.CifEvalOk = 0 - return 0 - ov: int = self._cif_eval_node(pool, trans, uop.operand) - if self.CifEvalOk == 0: - return 0 - if uop.op == ast.OpKind.Not: return 1 if ov == 0 else 0 - if uop.op == ast.OpKind.USub: return -ov - if uop.op == ast.OpKind.UAdd: return ov - if uop.op == ast.OpKind.Invert: return ~ov - self.CifEvalOk = 0 - return 0 - if k == ast.ASTKind.BoolOp: - bo: ast.BoolOp | t.CPtr = (ast.BoolOp | t.CPtr)(node) - vals: list[ast.AST | t.CPtr] | t.CPtr = bo.values - if vals is None: - self.CifEvalOk = 0 - return 0 - bn: t.CSizeT = len(vals) - if bo.op == ast.OpKind.And: - for bi in range(bn): - rv: int = self._cif_eval_node(pool, trans, vals.get(bi)) - if self.CifEvalOk == 0: - return 0 - if rv == 0: - return 0 - return 1 - if bo.op == ast.OpKind.Or: - for bi in range(bn): - rv: int = self._cif_eval_node(pool, trans, vals.get(bi)) - if self.CifEvalOk == 0: - return 0 - if rv != 0: - return 1 - return 0 - self.CifEvalOk = 0 - return 0 - if k == ast.ASTKind.Compare: - cmp: ast.Compare | t.CPtr = (ast.Compare | t.CPtr)(node) - lv: int = self._cif_eval_node(pool, trans, cmp.left) - if self.CifEvalOk == 0: - return 0 - ops_list: list[t.CInt] | t.CPtr = (list[t.CInt] | t.CPtr)(cmp.ops) - comps: list[ast.AST | t.CPtr] | t.CPtr = cmp.comparators - if ops_list is None or comps is None: - self.CifEvalOk = 0 - return 0 - cc: t.CSizeT = len(comps) - ci: t.CSizeT - for ci in range(cc): - rv: int = self._cif_eval_node(pool, trans, comps.get(ci)) - if self.CifEvalOk == 0: - return 0 - op_id: int = ops_list.get(ci) - ok_cmp: int = 0 - if op_id == ast.OpKind.Eq: ok_cmp = 1 if lv == rv else 0 - elif op_id == ast.OpKind.Ne: ok_cmp = 1 if lv != rv else 0 - elif op_id == ast.OpKind.Lt: ok_cmp = 1 if lv < rv else 0 - elif op_id == ast.OpKind.Le: ok_cmp = 1 if lv <= rv else 0 - elif op_id == ast.OpKind.Gt: ok_cmp = 1 if lv > rv else 0 - elif op_id == ast.OpKind.Ge: ok_cmp = 1 if lv >= rv else 0 - else: - self.CifEvalOk = 0 - return 0 - if ok_cmp == 0: - return 0 - lv = rv - return 1 - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) - lv: int = self._cif_eval_node(pool, trans, bop.left) - if self.CifEvalOk == 0: - return 0 - rv: int = self._cif_eval_node(pool, trans, bop.right) - if self.CifEvalOk == 0: - return 0 - if bop.op == ast.OpKind.Add: return lv + rv - if bop.op == ast.OpKind.Sub: return lv - rv - if bop.op == ast.OpKind.Mult: return lv * rv - if bop.op == ast.OpKind.Div: - # 整数常量除法:与 FloorDiv 一致(对齐 TPC ConstEvaluator L354-355) - if rv == 0: - self.CifEvalOk = 0 - return 0 - return lv // rv - if bop.op == ast.OpKind.FloorDiv: - if rv == 0: - self.CifEvalOk = 0 - return 0 - return lv // rv - if bop.op == ast.OpKind.Mod: - if rv == 0: - self.CifEvalOk = 0 - return 0 - return lv % rv - if bop.op == ast.OpKind.BitAnd: return lv & rv - if bop.op == ast.OpKind.BitOr: return lv | rv - if bop.op == ast.OpKind.BitXor: return lv ^ rv - if bop.op == ast.OpKind.LShift: return lv << rv - if bop.op == ast.OpKind.RShift: return lv >> rv - self.CifEvalOk = 0 - return 0 - self.CifEvalOk = 0 - return 0 - - def _eval_ctraits_isptr(self, symtab: HandlesVar.SymbolTable | t.CPtr, - name: str) -> int: - """ctraits.isptr(name) 编译期求值。 - - 按变量实际存储类型判断是否指针:alloca 的 pointee 为 Ptr 即指针 - (与 TPC ConstEvaluator._eval_compile_time_call 的 LLVM 类型判断一致)。 - 返回: 1=指针 0=非指针 -1=无法求值(变量不存在/无类型信息)。 - """ - if name is None or symtab is None: - return -1 - v: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(symtab, name) - if v is None or v.Ty is None: - return -1 - pointee: llvmlite.LLVMType | t.CPtr = v.Ty.Pointee - if pointee is not None and HandlesExpr.is_ptr_type(pointee) != 0: - return 1 - return 0 - - def _cif_eval_call(self, pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """编译期函数调用求值:ctraits.isptr(x)。 - - 命中置 self.CifEvalOk=1 返回 1/0;未识别调用置 0 返回 0。 - """ - self.CifEvalOk = 0 - if node is None or trans is None: - return 0 - cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node) - if cl is None or cl.func is None: - return 0 - fk: int = cl.func.kind() - if fk != ast.ASTKind.Attribute: - return 0 - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) - if at.value is None or at.attr is None: - return 0 - if at.value.kind() != ast.ASTKind.Name: - return 0 - vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if vn.id is None: - return 0 - if string.strcmp(vn.id, "ctraits") != 0 or string.strcmp(at.attr, "isptr") != 0: - return 0 - cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args - if cargs is None or len(cargs) < 1: - self.CifEvalOk = 0 - return 0 - arg0: ast.AST | t.CPtr = cargs.get(0) - if arg0 is None or arg0.kind() != ast.ASTKind.Name: - self.CifEvalOk = 0 - return 0 - nm0: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arg0) - if nm0.id is None: - self.CifEvalOk = 0 - return 0 - r: int = self._eval_ctraits_isptr(trans.SymTab, nm0.id) - if r < 0: - self.CifEvalOk = 0 - return 0 - self.CifEvalOk = 1 - return r - - def _evaluate_cif_test(self, pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr, - test: ast.AST | t.CPtr) -> int: - """求值 CIf 调用(test 必须是 c.CIf 系调用)。 - - 成功: 置 self.CifEvalOk=1,返回条件值(0/1) - 失败(运行时变量/未知结构): 置 self.CifEvalOk=0,返回 0 - """ - self.CifEvalOk = 0 - cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(test) - if cl is None or cl.func is None: - return 0 - kind: str = None - fk: int = cl.func.kind() - if fk == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) - kind = at.attr - elif fk == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cl.func) - kind = nm.id - if kind is None: - return 0 - cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args - if cargs is None or len(cargs) < 1: - return 0 - arg0: ast.AST | t.CPtr = cargs.get(0) - if string.strcmp(kind, "CIf") == 0: - v: int = self._cif_eval_node(pool, trans, arg0) - if self.CifEvalOk == 0: - return 0 - return 1 if v != 0 else 0 - # CIfdef / CIfndef: 判定宏名是否已定义 - defined: int = 0 - if arg0 is not None and arg0.kind() == ast.ASTKind.Name: - nm0: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arg0) - if nm0.id is None: - return 0 - self._cif_name_value(pool, trans, nm0.id) - defined = self.CifEvalOk - elif arg0 is not None and arg0.kind() == ast.ASTKind.Constant: - cn0: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(arg0) - if cn0.const_kind == ast.CONST_STR and cn0.str_val is not None: - self._cif_name_value(pool, trans, cn0.str_val) - defined = self.CifEvalOk - else: - return 0 - elif arg0 is not None and arg0.kind() == ast.ASTKind.Attribute: - at0: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg0) - self._cif_attr_value(pool, trans, at0) - defined = self.CifEvalOk - else: - return 0 - # 定义判定本身成功(未定义名特判:不报错,defined=0 走 else) - self.CifEvalOk = 1 - if string.strcmp(kind, "CIfdef") == 0: - return 1 if defined != 0 else 0 - # CIfndef - return 0 if defined != 0 else 1 - - def NewIfHandle(self, pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr) -> HandlesIf.IfHandle | t.CPtr: - """创建 IfHandle 实例(迁移自 HandlesIf.NewIfHandle)""" - h: HandlesIf.IfHandle | t.CPtr = pool.alloc(HandlesIf.IfHandle.__sizeof__()) - if h is None: - return None - string.memset(h, 0, HandlesIf.IfHandle.__sizeof__()) - h.Trans = trans - return h - - # ============================================================ - # 簇 C:循环/return/match 子 Handle 工厂(迁移自 - # HandlesWhile/HandlesFor/HandlesReturn/HandlesMatch) - # ============================================================ - - def NewWhileHandle(self, pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr) -> HandlesWhile.WhileHandle | t.CPtr: - """创建 WhileHandle 实例(迁移自 HandlesWhile.NewWhileHandle)""" - h: HandlesWhile.WhileHandle | t.CPtr = pool.alloc(HandlesWhile.WhileHandle.__sizeof__()) - if h is None: - return None - string.memset(h, 0, HandlesWhile.WhileHandle.__sizeof__()) - h.Trans = trans - return h - - def NewForHandle(self, pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr) -> HandlesFor.ForHandle | t.CPtr: - """创建 ForHandle 实例(迁移自 HandlesFor.NewForHandle)""" - h: HandlesFor.ForHandle | t.CPtr = pool.alloc(HandlesFor.ForHandle.__sizeof__()) - if h is None: - return None - string.memset(h, 0, HandlesFor.ForHandle.__sizeof__()) - h.Trans = trans - return h - - def NewReturnHandle(self, pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr) -> HandlesReturn.ReturnHandle | t.CPtr: - """创建 ReturnHandle 实例(迁移自 HandlesReturn.NewReturnHandle)""" - h: HandlesReturn.ReturnHandle | t.CPtr = pool.alloc(HandlesReturn.ReturnHandle.__sizeof__()) - if h is None: - return None - string.memset(h, 0, HandlesReturn.ReturnHandle.__sizeof__()) - h.Trans = trans - return h - - def NewMatchHandle(self, pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr) -> HandlesMatch.MatchHandle | t.CPtr: - """创建 MatchHandle 实例(迁移自 HandlesMatch.NewMatchHandle)""" - h: HandlesMatch.MatchHandle | t.CPtr = pool.alloc(HandlesMatch.MatchHandle.__sizeof__()) - if h is None: - return None - string.memset(h, 0, HandlesMatch.MatchHandle.__sizeof__()) - h.Trans = trans - return h - - # ============================================================ - # 簇 D:nonlocal/闭包 env 访问(迁移自 HandlesNonlocal.vp) - # ============================================================ - - def _is_void_type(self, ty: llvmlite.LLVMType | t.CPtr) -> int: - """判断是否为 Void 类型,是则返回 1,否则 0""" - if ty is None: - return 0 - match ty: - case llvmlite.LLVMType.Void(): - return 1 - case _: - return 0 - - def get_env_ptr_var(self, trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr: - """获取或创建 _env_ptr 变量(存储闭包 env 指针)""" - env_var: llvmlite.Value | t.CPtr = HandlesVar.lookup_var( - trans.SymTab, "_env_ptr") - if env_var is not None: - return env_var - # 创建 alloca 存储 env - pool: memhub.MemBuddy | t.CPtr = trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, i8_ptr_ty) - if alloca is None: - return None - HandlesVar.define_var(trans.SymTab, "_env_ptr", alloca) - return alloca - - def _load_raw_var_ptr(self, trans: HT.Translator | t.CPtr, - name: str) -> llvmlite.Value | t.CPtr: - """从闭包 env 加载 nonlocal 变量的原始指针(i8*) - - 返回 i8* 类型的 Value,调用方需 bitcast 为具体类型指针后 load/store。 - """ - idx: int = HT.get_nonlocal_index(trans, name) - if idx < 0: - return None - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - i8_ptr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty) - - # 1. 加载 env_ptr - env_alloca: llvmlite.Value | t.CPtr = self.get_env_ptr_var(trans) - if env_alloca is None: - return None - env_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, env_alloca) - if env_ptr is None: - return None - - # 2. GEP to offset (idx * 8) — env 存储指针数组,每槽 8 字节 - offset_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, idx * 8) - addr: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, env_ptr, offset_val) - if addr is None: - return None - - # 3. Bitcast to i8** and load the raw pointer - ptr_addr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, addr, i8_ptr_ptr_ty) - if ptr_addr is None: - return None - return llvmlite.build_load(builder, i8_ptr_ty, ptr_addr) - - def load_nonlocal_var(self, trans: HT.Translator | t.CPtr, - name: str) -> llvmlite.Value | t.CPtr: - """从闭包 env 加载 nonlocal 变量值 - - 通过 HT.get_nonlocal_type 获取变量类型,bitcast 原始指针后 load。 - """ - raw_ptr: llvmlite.Value | t.CPtr = self._load_raw_var_ptr(trans, name) - if raw_ptr is None: - return None - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - - # 获取变量类型(从注册时存储的类型信息) - var_ty: llvmlite.LLVMType | t.CPtr = HT.get_nonlocal_type(trans, name) - if var_ty is None or self._is_void_type(var_ty) != 0: - # 类型缺失/无效直接报错终止(fail-fast),避免生成 "load void, void*" 非法 IR - HandlesType.fatal_error(None, f"nonlocal 变量 '{name}' 类型缺失,无法 load", "TypeError") - - # bitcast raw i8* to var_ty* - var_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, var_ty) - var_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, raw_ptr, var_ptr_ty) - if var_ptr is None: - return None - return llvmlite.build_load(builder, var_ty, var_ptr) - - def get_nonlocal_var_ptr(self, trans: HT.Translator | t.CPtr, - name: str) -> llvmlite.Value | t.CPtr: - """获取 nonlocal 变量的存储指针(var_ty*),用于 store 操作 - - 返回的指针指向父函数的 alloca,store 操作对父函数可见。 - """ - raw_ptr: llvmlite.Value | t.CPtr = self._load_raw_var_ptr(trans, name) - if raw_ptr is None: - return None - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - - # 获取变量类型 - var_ty: llvmlite.LLVMType | t.CPtr = HT.get_nonlocal_type(trans, name) - if var_ty is None or self._is_void_type(var_ty) != 0: - # 类型缺失/无效直接报错终止(fail-fast),避免生成 "bitcast ... to void*" 非法 IR - HandlesType.fatal_error(None, f"nonlocal 变量 '{name}' 类型缺失,无法 load", "TypeError") - - # bitcast raw i8* to var_ty* - var_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, var_ty) - return llvmlite.build_bitcast(builder, raw_ptr, var_ptr_ty) - - # ============================================================ - # 簇 E:枚举注册表(迁移自 HandlesEnum.vp) - # ============================================================ - - def init_enum_table(self, pool: memhub.MemBuddy | t.CPtr) -> int: - """初始化枚举注册表,返回 1 成功 - - 表用 stdlib 分配(跨 Phase1 1b 的 mark/reset_to 存活——枚举表是 - 跨文件持久表,pool 分配会被 reset 回收导致 Phase B 读垃圾, - enum_count 出现 512 等垃圾值 / entry.Name 解引用崩溃)。 - """ - if self.EnumTable is not None: - return 1 - - entry_size: t.CSizeT = HandlesEnum.EnumEntry.__sizeof__() - self.EnumTable = CompilerFactory.get_perm_pool().alloc(entry_size * ENUM_MAX) - if self.EnumTable is None: - return 0 - string.memset(self.EnumTable, 0, entry_size * ENUM_MAX) - self.EnumCount = 0 - return 1 - - def _get_enum_entry(self, i: int) -> HandlesEnum.EnumEntry | t.CPtr: - """获取第 i 个枚举条目""" - if self.EnumTable is None or i < 0 or i >= ENUM_MAX: - return None - entry_size: t.CSizeT = HandlesEnum.EnumEntry.__sizeof__() - addr: t.CUInt64T = t.CUInt64T(self.EnumTable) + i * entry_size - return (HandlesEnum.EnumEntry | t.CPtr)(t.CVoid(addr, t.CPtr)) - - def _get_enum_member(self, enum_entry: HandlesEnum.EnumEntry | t.CPtr, - i: int) -> HandlesEnum.EnumMember | t.CPtr: - """获取枚举中第 i 个成员条目""" - if enum_entry is None or i < 0 or i >= ENUM_MEMBER_MAX: - return None - member_size: t.CSizeT = HandlesEnum.EnumMember.__sizeof__() - addr: t.CUInt64T = t.CUInt64T(enum_entry.Members) + i * member_size - return (HandlesEnum.EnumMember | t.CPtr)(t.CVoid(addr, t.CPtr)) - - def register_enum(self, pool: memhub.MemBuddy | t.CPtr, - name: str, - base_ty: llvmlite.LLVMType | t.CPtr) -> HandlesEnum.EnumEntry | t.CPtr: - """注册枚举类型,返回 EnumEntry 指针""" - if self.init_enum_table(pool) == 0: - return None - - # 检查是否已注册 - existing: HandlesEnum.EnumEntry | t.CPtr = self.find_enum(name) - if existing is not None: - return existing - - if self.EnumCount >= ENUM_MAX: - fb_et: str = VLogger.fmt_buf() - if fb_et is not None: - viperlib.snprintf(fb_et, 1024, "table full, cannot register %s", name) - VLogger.error(fb_et, "ENUM") - return None - - entry: HandlesEnum.EnumEntry | t.CPtr = self._get_enum_entry(self.EnumCount) - if entry is None: - return None - - # 分配成员数组(永久池:跨 mark/reset 存活,对齐 EnumTable 永久池化) - member_size: t.CSizeT = HandlesEnum.EnumMember.__sizeof__() - entry.Members = CompilerFactory.get_perm_pool().alloc(member_size * ENUM_MEMBER_MAX) - if entry.Members is None: - return None - string.memset(entry.Members, 0, member_size * ENUM_MEMBER_MAX) - - # 复制类名(永久池深拷贝) - name_len: t.CSizeT = string.strlen(name) - name_buf: str = CompilerFactory.get_perm_pool().alloc(name_len + 1) - if name_buf is not None: - string.strcpy(name_buf, name) - entry.Name = name_buf - - # BaseTy 深拷贝:LLVMType 是 pool 分配,StdlibAlloc=1(Phase2 mark2 后) - # 时 reset 回收悬空 → Phase B 枚举访问 ConstInt(悬空 BaseTy) 生成 void - # 值(DecoratorMarkerTest `store void 2` llc 报错根因)。Phase1 1a - # (StdlibAlloc=0,mark1 前)保持 pool 存活,无需拷贝。 - # 注意:StdlibAlloc 是 StructGenMixin 字段,本 Mixin 方法体不能直接 - # self.StdlibAlloc(NoVTable 按本 Mixin 字段布局编译),走模块级委托。 - if HandlesStruct.get_stdlib_alloc() != 0: - base_ty_copy: llvmlite.LLVMType | t.CPtr = llvmlite.DeepCopyType( - CompilerFactory.get_perm_pool(), base_ty) - if base_ty_copy is not None: - entry.BaseTy = base_ty_copy - else: - entry.BaseTy = base_ty - else: - entry.BaseTy = base_ty - entry.MemberCount = 0 - - self.EnumCount += 1 - return entry - - def add_enum_member(self, pool: memhub.MemBuddy | t.CPtr, - enum_entry: HandlesEnum.EnumEntry | t.CPtr, - member_name: str, - member_val: t.CInt64T, - member_ty: llvmlite.LLVMType | t.CPtr) -> int: - """向枚举添加成员,返回成员索引(-1 失败)""" - if enum_entry is None or member_name is None or member_ty is None: - return -1 - - # 去重:同名成员已存在则跳过(跨模块同名枚举合并注册 / 同模块 - # 重复处理幂等——如 w32.fileio 与 fat32_types 都有 FRESULT) - for ei_d in range(enum_entry.MemberCount): - ex_d: HandlesEnum.EnumMember | t.CPtr = self._get_enum_member( - enum_entry, ei_d) - if ex_d is not None and ex_d.Name is not None: - if string.strcmp(ex_d.Name, member_name) == 0: - return ei_d - - if enum_entry.MemberCount >= ENUM_MEMBER_MAX: - fb_em: str = VLogger.fmt_buf() - if fb_em is not None: - viperlib.snprintf(fb_em, 1024, "member table full for %s", enum_entry.Name) - VLogger.error(fb_em, "ENUM") - return -1 - - idx: int = enum_entry.MemberCount - me: HandlesEnum.EnumMember | t.CPtr = self._get_enum_member(enum_entry, idx) - if me is None: - return -1 - - # 复制成员名(永久池深拷贝:成员表跨 mark/reset 存活) - name_len: t.CSizeT = string.strlen(member_name) - name_buf: str = CompilerFactory.get_perm_pool().alloc(name_len + 1) - if name_buf is not None: - string.strcpy(name_buf, member_name) - me.Name = name_buf - - me.Value = member_val - me.Ty = member_ty - - enum_entry.MemberCount = idx + 1 - return idx - - def find_enum(self, name: str) -> HandlesEnum.EnumEntry | t.CPtr: - """按枚举类名查找,返回 EnumEntry 或 None""" - if name is None or self.EnumTable is None: - return None - for i in range(self.EnumCount): - entry: HandlesEnum.EnumEntry | t.CPtr = self._get_enum_entry(i) - if entry is not None and entry.Name is not None: - if string.strcmp(entry.Name, name) == 0: - return entry - return None - - def lookup_enum_member(self, enum_name: str, - member_name: str) -> HandlesEnum.EnumMember | t.CPtr: - """按枚举类名和成员名查找,返回 EnumMember 或 None""" - if enum_name is None or member_name is None: - return None - entry: HandlesEnum.EnumEntry | t.CPtr = self.find_enum(enum_name) - if entry is None: - return None - for mi in range(entry.MemberCount): - me: HandlesEnum.EnumMember | t.CPtr = self._get_enum_member(entry, mi) - if me is not None and me.Name is not None: - if string.strcmp(me.Name, member_name) == 0: - return me - return None - - def is_enum_class(self, name: str) -> int: - """检查类名是否为已注册枚举,返回 1=是 / 0=否""" - if name is None: - return 0 - if self.find_enum(name) is not None: - return 1 - return 0 - - def get_enum_base_type(self, enum_name: str) -> llvmlite.LLVMType | t.CPtr: - """按枚举类名获取基准类型""" - entry: HandlesEnum.EnumEntry | t.CPtr = self.find_enum(enum_name) - if entry is not None: - return entry.BaseTy - return None