StmtGenMixin.vp(1715) → 顶层(763 语句分派中枢) + StmtGenDeclMixin(512 声明/枚举/nonlocal) + StmtGenCifMixin(520 CIf 求值/工厂)。继承链 Mixin→Decl→Cif,@t.NoVTable 静态绑定沿 MRO 解析;4 字段全留最底层父类保持组合布局;Generator.vp 与 Handles* 委托零改动。
512 lines
22 KiB
Plaintext
512 lines
22 KiB
Plaintext
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
|