239 lines
8.3 KiB
Python
239 lines
8.3 KiB
Python
import t, c
|
||
from stdint import *
|
||
import memhub
|
||
import string
|
||
import llvmlite
|
||
import stdio
|
||
import viperlib
|
||
import lib.core.VLogger as VLogger
|
||
|
||
|
||
# ============================================================
|
||
# HandlesEnum - 枚举类型注册和成员查找
|
||
#
|
||
# 管理 t.CEnum 派生类的成员信息:
|
||
# - 枚举名 → EnumEntry(基准类型 + 成员表)
|
||
# - 成员名 → EnumMember(值、类型)
|
||
#
|
||
# 使用全局数组存储,线性查找(枚举数量通常很少)
|
||
# ============================================================
|
||
|
||
ENUM_MAX: t.CDefine = 64
|
||
ENUM_MEMBER_MAX: t.CDefine = 64
|
||
|
||
|
||
# ============================================================
|
||
# EnumMember - 枚举成员条目
|
||
# ============================================================
|
||
@t.NoVTable
|
||
class EnumMember:
|
||
Name: t.CChar | t.CPtr # 成员名(字符串)
|
||
Value: t.CInt64T # 成员的整数值
|
||
Ty: llvmlite.LLVMType | t.CPtr # 成员的 LLVM 类型(用于混用类型场景)
|
||
|
||
|
||
# ============================================================
|
||
# EnumEntry - 枚举类型条目
|
||
# ============================================================
|
||
@t.NoVTable
|
||
class EnumEntry:
|
||
Name: t.CChar | t.CPtr # 枚举类名
|
||
BaseTy: llvmlite.LLVMType | t.CPtr # 基准类型(所有成员类型中最大的)
|
||
MemberCount: int # 成员数量
|
||
Members: EnumMember | t.CPtr # 成员数组(ENUM_MEMBER_MAX 个槽位)
|
||
|
||
|
||
# ============================================================
|
||
# 全局注册表(静态分配)
|
||
# ============================================================
|
||
_enum_table: EnumEntry | t.CPtr = None
|
||
_enum_count: int = 0
|
||
|
||
|
||
# ============================================================
|
||
# init_enum_table — 初始化枚举注册表
|
||
# ============================================================
|
||
def init_enum_table(pool: memhub.MemBuddy | t.CPtr) -> int:
|
||
"""初始化枚举注册表,返回 1 成功"""
|
||
global _enum_table
|
||
global _enum_count
|
||
|
||
if _enum_table is not None:
|
||
return 1
|
||
|
||
entry_size: t.CSizeT = EnumEntry.__sizeof__()
|
||
_enum_table = pool.alloc(entry_size * ENUM_MAX)
|
||
if _enum_table is None:
|
||
return 0
|
||
string.memset(_enum_table, 0, entry_size * ENUM_MAX)
|
||
_enum_count = 0
|
||
return 1
|
||
|
||
|
||
# ============================================================
|
||
# _get_enum_entry — 获取第 i 个 EnumEntry 槽位
|
||
# ============================================================
|
||
def _get_enum_entry(i: int) -> EnumEntry | t.CPtr:
|
||
"""获取第 i 个枚举条目"""
|
||
if _enum_table is None or i < 0 or i >= ENUM_MAX:
|
||
return None
|
||
entry_size: t.CSizeT = EnumEntry.__sizeof__()
|
||
addr: t.CUInt64T = t.CUInt64T(_enum_table) + i * entry_size
|
||
return (EnumEntry | t.CPtr)(t.CVoid(addr, t.CPtr))
|
||
|
||
|
||
# ============================================================
|
||
# _get_enum_member — 获取枚举中第 i 个 EnumMember 槽位
|
||
# ============================================================
|
||
def _get_enum_member(enum_entry: EnumEntry | t.CPtr, i: int) -> EnumMember | t.CPtr:
|
||
"""获取枚举中第 i 个成员条目"""
|
||
if enum_entry is None or i < 0 or i >= ENUM_MEMBER_MAX:
|
||
return None
|
||
member_size: t.CSizeT = EnumMember.__sizeof__()
|
||
addr: t.CUInt64T = t.CUInt64T(enum_entry.Members) + i * member_size
|
||
return (EnumMember | t.CPtr)(t.CVoid(addr, t.CPtr))
|
||
|
||
|
||
# ============================================================
|
||
# register_enum — 注册枚举类型
|
||
#
|
||
# 返回 EnumEntry 指针,可用于添加成员
|
||
# ============================================================
|
||
def register_enum(pool: memhub.MemBuddy | t.CPtr,
|
||
name: str,
|
||
base_ty: llvmlite.LLVMType | t.CPtr) -> EnumEntry | t.CPtr:
|
||
"""注册枚举类型,返回 EnumEntry 指针"""
|
||
if init_enum_table(pool) == 0:
|
||
return None
|
||
|
||
# 检查是否已注册
|
||
existing: EnumEntry | t.CPtr = find_enum(name)
|
||
if existing is not None:
|
||
return existing
|
||
|
||
if _enum_count >= ENUM_MAX:
|
||
fb_et: t.CChar | t.CPtr = 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: EnumEntry | t.CPtr = _get_enum_entry(_enum_count)
|
||
if entry is None:
|
||
return None
|
||
|
||
# 分配成员数组
|
||
member_size: t.CSizeT = EnumMember.__sizeof__()
|
||
entry.Members = 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: t.CChar | t.CPtr = pool.alloc(name_len + 1)
|
||
if name_buf is not None:
|
||
string.strcpy(name_buf, name)
|
||
entry.Name = name_buf
|
||
|
||
entry.BaseTy = base_ty
|
||
entry.MemberCount = 0
|
||
|
||
_enum_count += 1
|
||
return entry
|
||
|
||
|
||
# ============================================================
|
||
# add_enum_member — 向枚举添加成员
|
||
# ============================================================
|
||
def add_enum_member(pool: memhub.MemBuddy | t.CPtr,
|
||
enum_entry: 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
|
||
|
||
if enum_entry.MemberCount >= ENUM_MEMBER_MAX:
|
||
fb_em: t.CChar | t.CPtr = 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: EnumMember | t.CPtr = _get_enum_member(enum_entry, idx)
|
||
if me is None:
|
||
return -1
|
||
|
||
# 复制成员名
|
||
name_len: t.CSizeT = string.strlen(member_name)
|
||
name_buf: t.CChar | t.CPtr = 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
|
||
|
||
|
||
# ============================================================
|
||
# find_enum — 按枚举类名查找
|
||
# ============================================================
|
||
def find_enum(name: str) -> EnumEntry | t.CPtr:
|
||
"""按枚举类名查找,返回 EnumEntry 或 None"""
|
||
if name is None or _enum_table is None:
|
||
return None
|
||
for i in range(_enum_count):
|
||
entry: EnumEntry | t.CPtr = _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
|
||
|
||
|
||
# ============================================================
|
||
# lookup_enum_member — 按枚举类名和成员名查找
|
||
# ============================================================
|
||
def lookup_enum_member(enum_name: str,
|
||
member_name: str) -> EnumMember | t.CPtr:
|
||
"""按枚举类名和成员名查找,返回 EnumMember 或 None"""
|
||
if enum_name is None or member_name is None:
|
||
return None
|
||
entry: EnumEntry | t.CPtr = find_enum(enum_name)
|
||
if entry is None:
|
||
return None
|
||
for mi in range(entry.MemberCount):
|
||
me: EnumMember | t.CPtr = _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
|
||
|
||
|
||
# ============================================================
|
||
# is_enum_class — 检查类名是否为已注册枚举
|
||
# ============================================================
|
||
def is_enum_class(name: str) -> int:
|
||
"""检查类名是否为已注册枚举,返回 1=是 / 0=否"""
|
||
if name is None:
|
||
return 0
|
||
if find_enum(name) is not None:
|
||
return 1
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# get_enum_base_type — 按枚举类名获取基准类型
|
||
# ============================================================
|
||
def get_enum_base_type(enum_name: str) -> llvmlite.LLVMType | t.CPtr:
|
||
"""按枚举类名获取基准类型"""
|
||
entry: EnumEntry | t.CPtr = find_enum(enum_name)
|
||
if entry is not None:
|
||
return entry.BaseTy
|
||
return None
|