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:
1 parent
593332636f
commit
f4a990c074
3 files changed
+1040
-963
No files matched your search
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in new issue
Block a user