239 lines
8.3 KiB
Plaintext
239 lines
8.3 KiB
Plaintext
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, _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:
|
|
global _enum_count
|
|
"""注册枚举类型,返回 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
|