refactor(gen): StmtGenMixin 按功能域拆为 3 文件(500~1500 行架构试点)

StmtGenMixin.vp(1715) → 顶层(763 语句分派中枢) + StmtGenDeclMixin(512 声明/枚举/nonlocal) + StmtGenCifMixin(520 CIf 求值/工厂)。继承链 Mixin→Decl→Cif,@t.NoVTable 静态绑定沿 MRO 解析;4 字段全留最底层父类保持组合布局;Generator.vp 与 Handles* 委托零改动。
This commit is contained in:
TermiNexus committed 2026-08-17 05:46:40 +08:00
1 parent 593332636f
commit f4a990c074
3 files changed
+1040 -963

No files matched your search

+519
View File
@@ -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
+511
View File
@@ -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
+10 -963
View File
@@ -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