import t, c
from stdint import *
import memhub
import string
import llvmlite
import stdio
import ast
import hashtable


# ============================================================
# HandlesStruct - 结构体类型注册和字段查找
#
# 管理 class 定义的结构体类型信息:
# - 类名 → LLVM StructType
# - 字段名 → 字段索引和类型
#
# 使用全局数组存储，线性查找（结构体数量通常很少）
# ============================================================

STRUCT_MAX: t.CDefine = 512
FIELD_MAX: t.CDefine = 32
FIELD_NAME_MAX: t.CDefine = 64


# ============================================================
# FieldEntry - 字段信息条目
# ============================================================
@t.NoVTable
class FieldEntry:
    Name: t.CChar | t.CPtr           # 字段名（字符串）
    Index: int                    # 字段在结构体中的索引
    Ty: llvmlite.LLVMType | t.CPtr   # 字段的 LLVM 类型
    DefaultVal: ast.AST | t.CPtr     # 默认值 AST 节点（None=无默认值）
    AnnotClassName: t.CChar | t.CPtr    # 原始类型注解的类名（str 别名在结构体字段中触发编译器 bug，改用显式联合类型）


# ============================================================
# StructEntry - 结构体注册条目
# ============================================================
@t.NoVTable
class StructEntry:
    Name: t.CChar | t.CPtr               # 类名
    Ty: llvmlite.LLVMType | t.CPtr       # LLVM StructType
    FieldCount: int                  # 字段数量
    Fields: FieldEntry | t.CPtr         # 字段数组（FIELD_MAX 个槽位）
    IsUnion: int                     # 1=联合体 / 0=普通结构体
    IsOOP: int                       # 1=OOP结构体（有方法） / 0=纯内存结构体
    HasInit: int                     # 1=有__init__方法 / 0=无
    HasNew: int                      # 1=有__new__方法 / 0=无
    HasVTable: int                   # 1=有虚表 / 0=无虚表
    IsNoVTable: int                  # 1=明确标记 @t.NoVTable / 0=未标记
    ParentName: t.CChar | t.CPtr        # 父类名（None=无父类）
    VTableMethodCount: int           # 虚表中的方法数量
    VTableMethods: t.CChar | t.CPtr     # 虚表方法名数组（每个方法名 str，VTableMethodCount 个）
    ModuleSha1: t.CChar | t.CPtr        # 定义该类的模块 SHA1（None=无 SHA1）


# ============================================================
# 全局注册表（静态分配）
# ============================================================
_struct_table: StructEntry | t.CPtr = None
_struct_count: int = 0


# ============================================================
# 跨模块命名空间隔离：per-file 结构体可见性
#
# _visible_structs: 当前文件可见的结构体名（HashTable，O(1) 查找）
# _strict_visibility: 1=严格模式（仅本地+import可见）/ 0=宽松模式（全部可见）
#
# 每个文件翻译前调用 reset_visible_structs 重置
# ============================================================
_visible_structs: hashtable.HashTable | t.CPtr = None
_strict_visibility: int = 0


# ============================================================
# reset_visible_structs — 重置可见性状态（每个文件翻译前调用）
# ============================================================
def reset_visible_structs(pool: memhub.MemBuddy | t.CPtr, strict: int):
    """重置可见性状态（每个文件翻译前调用）

    pool: 内存分配器（严格模式下创建 HashTable）
    strict: 1=严格模式（用户文件），0=宽松模式（includes 文件）
    """
    global _visible_structs
    global _strict_visibility
    _strict_visibility = strict
    if strict != 0:
        # 严格模式：创建新的 HashTable 记录可见结构体
        _visible_structs = hashtable.HashTable(pool)
    else:
        # 宽松模式：全部可见，不需要 HashTable
        _visible_structs = None


# ============================================================
# add_visible_struct — 添加可见结构体名
# ============================================================
def add_visible_struct(pool: memhub.MemBuddy | t.CPtr, name: str):
    """添加可见结构体名（类定义时和 from-import 时调用）"""
    global _visible_structs
    if name is None:
        return
    # 宽松模式：全部可见，无需记录
    if _strict_visibility == 0:
        return
    if _visible_structs is None:
        return
    # 已存在则跳过（HashTable.__setitem__ 会覆盖，此处提前检查避免重复分配）
    if _visible_structs.__contains__(name) != 0:
        return
    _visible_structs.set_int(name, 1)


# ============================================================
# is_struct_visible — 检查结构体是否在当前文件可见
# ============================================================
def is_struct_visible(name: str) -> int:
    """检查结构体是否可见，返回 1=可见 / 0=不可见"""
    if _strict_visibility == 0:
        return 1
    if name is None or _visible_structs is None:
        return 0
    return _visible_structs.__contains__(name)


# ============================================================
# 初始化结构体注册表
# ============================================================
def init_struct_table(pool: memhub.MemBuddy | t.CPtr) -> int:
    """初始化结构体注册表，返回 1 成功"""
    global _struct_table
    global _struct_count

    if _struct_table is not None:
        return 1

    entry_size: t.CSizeT = StructEntry.__sizeof__()
    _struct_table = pool.alloc(entry_size * STRUCT_MAX)
    if _struct_table is None:
        return 0
    string.memset(_struct_table, 0, entry_size * STRUCT_MAX)
    _struct_count = 0
    return 1


# ============================================================
# _get_struct_entry — 获取第 i 个 StructEntry 槽位
# ============================================================
def _get_struct_entry(i: int) -> StructEntry | t.CPtr:
    """获取第 i 个结构体条目"""
    if _struct_table is None or i < 0 or i >= STRUCT_MAX:
        return None
    entry_size: t.CSizeT = StructEntry.__sizeof__()
    addr: t.CUInt64T = t.CUInt64T(_struct_table) + i * entry_size
    return (StructEntry | t.CPtr)(t.CVoid(addr, t.CPtr))


# ============================================================
# _get_field_entry — 获取结构体中第 i 个 FieldEntry 槽位
# ============================================================
def _get_field_entry(struct_entry: StructEntry | t.CPtr, i: int) -> FieldEntry | t.CPtr:
    """获取结构体中第 i 个字段条目"""
    if struct_entry is None or i < 0 or i >= FIELD_MAX:
        return None
    field_size: t.CSizeT = FieldEntry.__sizeof__()
    addr: t.CUInt64T = t.CUInt64T(struct_entry.Fields) + i * field_size
    return (FieldEntry | t.CPtr)(t.CVoid(addr, t.CPtr))


# ============================================================
# register_struct — 注册结构体类型
#
# 返回 StructEntry 指针，可用于添加字段
# ============================================================
def register_struct(pool: memhub.MemBuddy | t.CPtr,
                    name: str,
                    struct_ty: llvmlite.LLVMType | t.CPtr,
                    sha1: str = None) -> StructEntry | t.CPtr:
    """注册结构体类型，返回 StructEntry 指针

    用类型指针去重（is 比较），不用类名去重。
    这样跨模块同名类可以共存，各自有独立的字段定义。
    sha1 参数在注册时直接设置 ModuleSha1（避免 set_struct_sha1 找错 entry）。
    """
    if init_struct_table(pool) == 0:
        return None

    # 用类型指针去重（同一类型不重复注册，支持跨模块同名类）
    for i in range(_struct_count):
        existing: StructEntry | t.CPtr = _get_struct_entry(i)
        if existing is not None and existing.Ty is not None:
            if existing.Ty is struct_ty:
                return existing

    if _struct_count >= STRUCT_MAX:
        stdio.printf("[STRUCT] table full, cannot register %s\n", name)
        return None

    entry: StructEntry | t.CPtr = _get_struct_entry(_struct_count)
    if entry is None:
        return None

    # 分配字段数组
    field_size: t.CSizeT = FieldEntry.__sizeof__()
    entry.Fields = pool.alloc(field_size * FIELD_MAX)
    if entry.Fields is None:
        return None
    string.memset(entry.Fields, 0, field_size * FIELD_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.Ty = struct_ty
    entry.FieldCount = 0

    # 注册时直接设置 SHA1（避免 set_struct_sha1 跨模块同名时找错 entry）
    if sha1 is not None:
        sha1_len: t.CSizeT = string.strlen(sha1)
        sha1_buf: t.CChar | t.CPtr = pool.alloc(sha1_len + 1)
        if sha1_buf is not None:
            string.strcpy(sha1_buf, sha1)
            entry.ModuleSha1 = sha1_buf

    _struct_count += 1
    return entry


# ============================================================
# set_struct_sha1 — 设置结构体所属模块的 SHA1
#
# 在翻译类定义时调用，记录类所属模块的 SHA1。
# 跨模块方法调用时（如 __before_init__/__init__），通过 SHA1
# 构造正确的函数名（"{sha1}.{ClassName}.{method}"）。
# ============================================================
def set_struct_sha1(pool: memhub.MemBuddy | t.CPtr,
                    class_name: str, sha1: str) -> int:
    """设置结构体所属模块的 SHA1，返回 1=成功 / 0=失败"""
    if class_name is None or sha1 is None:
        return 0
    entry: StructEntry | t.CPtr = find_struct(class_name)
    if entry is None:
        return 0
    # 复制 SHA1 字符串（避免悬空指针）
    sha1_len: t.CSizeT = string.strlen(sha1)
    sha1_buf: t.CChar | t.CPtr = pool.alloc(sha1_len + 1)
    if sha1_buf is None:
        return 0
    string.strcpy(sha1_buf, sha1)
    entry.ModuleSha1 = sha1_buf
    return 1


# ============================================================
# get_struct_sha1 — 获取结构体所属模块的 SHA1
#
# 跨模块方法调用时使用，返回 None=无 SHA1（本模块定义或无 SHA1）
# ============================================================
def get_struct_sha1(class_name: str) -> str:
    """获取结构体所属模块的 SHA1，返回 None=无 SHA1"""
    if class_name is None or _struct_table is None:
        return None
    entry: StructEntry | t.CPtr = find_struct(class_name)
    if entry is None:
        return None
    return entry.ModuleSha1


# ============================================================
# add_field — 向结构体添加字段信息
# ============================================================
def add_field(pool: memhub.MemBuddy | t.CPtr,
              struct_entry: StructEntry | t.CPtr,
              field_name: str,
              field_ty: llvmlite.LLVMType | t.CPtr,
              default_val: ast.AST | t.CPtr = None,
              annot_class_name: t.CChar | t.CPtr = None) -> int:
    """向结构体添加字段，返回字段索引（-1 失败）

    default_val: 字段默认值 AST 节点（可选，None=无默认值）
    annot_class_name: 原始类型注解的类名（可选，用于联合类型字段的方法调用解析）
    """
    if struct_entry is None or field_name is None or field_ty is None:
        return -1

    if struct_entry.FieldCount >= FIELD_MAX:
        stdio.printf("[STRUCT] field table full for %s\n", struct_entry.Name)
        return -1

    idx: int = struct_entry.FieldCount
    fe: FieldEntry | t.CPtr = _get_field_entry(struct_entry, idx)
    if fe is None:
        return -1

    # 复制字段名
    name_len: t.CSizeT = string.strlen(field_name)
    name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1)
    if name_buf is not None:
        string.strcpy(name_buf, field_name)
        fe.Name = name_buf

    fe.Index = idx
    fe.Ty = field_ty
    fe.DefaultVal = default_val
    fe.AnnotClassName = annot_class_name

    struct_entry.FieldCount = idx + 1
    return idx


# ============================================================
# find_struct — 按类名查找结构体
# ============================================================
def find_struct(name: str) -> StructEntry | t.CPtr:
    """按类名查找结构体，返回 StructEntry 或 None"""
    if name is None or _struct_table is None:
        return None
    for i in range(_struct_count):
        entry: StructEntry | t.CPtr = _get_struct_entry(i)
        if entry is not None and entry.Name is not None:
            if string.strcmp(entry.Name, name) == 0:
                return entry
    return None


# ============================================================
# find_struct_by_module — 按类名 + SHA1 查找结构体
#
# 跨模块同名类区分：Phase B 重新翻译时，必须找到当前模块
# 注册的结构体（而非第一个同名条目），否则 struct type、
# 字段布局、GEP 索引全部错误。
# ============================================================
def find_struct_by_module(name: str, sha1: str) -> StructEntry | t.CPtr:
    """按类名 + SHA1 查找结构体，返回 StructEntry 或 None

    SHA1 非 None 时：精确匹配 name+sha1，未找到返回 None（不回退，避免跨模块同名找错）
    SHA1 为 None 时：回退到 find_struct(name) 按类名查找第一个
    """
    if name is None or _struct_table is None:
        return None
    if sha1 is not None:
        for i in range(_struct_count):
            entry: StructEntry | t.CPtr = _get_struct_entry(i)
            if entry is not None and entry.Name is not None:
                if string.strcmp(entry.Name, name) == 0:
                    if entry.ModuleSha1 is not None:
                        if string.strcmp(entry.ModuleSha1, sha1) == 0:
                            return entry
        # SHA1 查找失败：不回退到 find_struct（会返回跨模块同名错误 entry）
        # 返回 None 让调用方创建新类型，避免 Phase B 用错误类型短路
        return None
    # 无 SHA1：按类名查找第一个
    return find_struct(name)


# ============================================================
# find_struct_by_type — 按类型指针查找结构体（is 身份比较）
#
# 用于 _translate_oop_methods 等已有 struct_ty 的场景，
# 直接用指针身份定位 entry，规避跨模块同名类 find_struct 找错的问题。
# ============================================================
def find_struct_by_type(struct_ty: llvmlite.LLVMType | t.CPtr) -> StructEntry | t.CPtr:
    """按类型指针查找结构体（is 比较），返回 StructEntry 或 None"""
    if struct_ty is None or _struct_table is None:
        return None
    for i in range(_struct_count):
        entry: StructEntry | t.CPtr = _get_struct_entry(i)
        if entry is not None and entry.Ty is not None:
            if entry.Ty is struct_ty:
                return entry
    return None


# ============================================================
# lookup_field — 按结构体类型和字段名查找字段信息
# ============================================================
def lookup_field(struct_ty: llvmlite.LLVMType | t.CPtr,
                 field_name: str) -> FieldEntry | t.CPtr:
    """按结构体类型和字段名查找字段信息

    两遍查找策略（跨模块同名类冲突的根本修复）:
    第一遍: 类型指针 is 身份比较（最高优先级，类型唯一确定 entry）
    第二遍: 名称回退（is 未匹配时，按类名/strstr 匹配，字段未找到时 continue）
    """
    if struct_ty is None or field_name is None or _struct_table is None:
        return None

    # ============================================================
    # 两遍查找策略（跨模块同名类冲突的根本修复）:
    #
    # 第一遍: 用类型指针 is 身份比较（最高优先级）
    #   - is 匹配唯一确定 entry，字段未找到直接返回 None
    #   - 规避联合类型 == BUG，且不受遍历顺序影响
    #
    # 第二遍: 名称回退（is 未匹配到任何 entry 时才执行）
    #   - 用于未注册类型或 is 不可靠的场景
    #   - 名称匹配但字段未找到时 continue（继续检查其他同名 entry）
    # ============================================================

    # 第一遍: is 身份比较
    for i in range(_struct_count):
        entry: StructEntry | t.CPtr = _get_struct_entry(i)
        if entry is not None and entry.Ty is not None:
            if entry.Ty is struct_ty:
                # is 匹配，查找字段
                for fi in range(entry.FieldCount):
                    fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi)
                    if fe is not None and fe.Name is not None:
                        if string.strcmp(fe.Name, field_name) == 0:
                            return fe
                # is 匹配但字段未找到（类型唯一确定，无需继续）
                return None

    # 第二遍: 名称回退（is 未匹配到）
    ty_name: str = _extract_struct_name(struct_ty)
    if ty_name is not None:
        for i in range(_struct_count):
            entry: StructEntry | t.CPtr = _get_struct_entry(i)
            if entry is not None and entry.Name is not None:
                matched: int = 0
                if string.strcmp(entry.Name, ty_name) == 0:
                    matched = 1
                elif string.strstr(ty_name, entry.Name) is not None:
                    matched = 1
                if matched != 0:
                    # 查找字段
                    for fi in range(entry.FieldCount):
                        fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi)
                        if fe is not None and fe.Name is not None:
                            if string.strcmp(fe.Name, field_name) == 0:
                                return fe
                    # 名称匹配但字段未找到，继续检查其他同名 entry（跨模块同名）
                    continue
    # 所有条目都未匹配
    return None


# ============================================================
# lookup_field_by_class — 按类名和字段名查找字段信息
# ============================================================
def lookup_field_by_class(class_name: str,
                          field_name: str,
                          sha1: str = None) -> FieldEntry | t.CPtr:
    """按类名和字段名查找字段信息

    优先用 SHA1 匹配（跨模块同名类区分），无 SHA1 时按类名查找第一个
    """
    if class_name is None or field_name is None:
        return None

    # 优先用 SHA1 匹配（跨模块同名类区分）
    if sha1 is not None:
        sha1_matched: int = 0
        for i in range(_struct_count):
            entry: StructEntry | t.CPtr = _get_struct_entry(i)
            if entry is not None and entry.Name is not None:
                if string.strcmp(entry.Name, class_name) == 0:
                    if entry.ModuleSha1 is not None:
                        if string.strcmp(entry.ModuleSha1, sha1) == 0:
                            sha1_matched = 1
                            # SHA1 + 类名匹配，查找字段
                            for fi in range(entry.FieldCount):
                                fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi)
                                if fe is not None and fe.Name is not None:
                                    if string.strcmp(fe.Name, field_name) == 0:
                                        return fe
                            return None

    # 回退: 无 SHA1 或 SHA1 匹配失败，按类名查找第一个
    entry = find_struct(class_name)
    if entry is None:
        return None
    for fi in range(entry.FieldCount):
        fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi)
        if fe is not None and fe.Name is not None:
            if string.strcmp(fe.Name, field_name) == 0:
                return fe
    return None


# ============================================================
# get_struct_type — 按类名获取结构体的 LLVM 类型
# ============================================================
def get_struct_type(class_name: str) -> llvmlite.LLVMType | t.CPtr:
    """按类名获取结构体的 LLVM 类型"""
    entry: StructEntry | t.CPtr = find_struct(class_name)
    if entry is not None:
        return entry.Ty
    return None


# ============================================================
# get_field_by_index — 按类名和字段索引获取字段信息
#
# 用于构造函数 Point(10, 20) 按顺序访问字段
# ============================================================
def get_field_by_index(class_name: str,
                       idx: int) -> FieldEntry | t.CPtr:
    """按类名和字段索引获取字段信息"""
    if class_name is None:
        return None
    entry: StructEntry | t.CPtr = find_struct(class_name)
    if entry is None:
        return None
    if idx < 0 or idx >= entry.FieldCount:
        return None
    return _get_field_entry(entry, idx)


# ============================================================
# struct_has_defaults — 检查结构体是否有任何带默认值的字段
# ============================================================
def struct_has_defaults(class_name: str) -> int:
    """检查结构体是否有任何带默认值的字段，返回 1=有 / 0=无"""
    if class_name is None:
        return 0
    entry: StructEntry | t.CPtr = find_struct(class_name)
    if entry is None:
        return 0
    for fi in range(entry.FieldCount):
        fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi)
        if fe is not None and fe.DefaultVal is not None:
            return 1
    return 0


# ============================================================
# get_struct_type_from_value — 从 LLVM Value 的类型推断结构体类型
#
# 如果 value 是 Ptr(Struct(...))，返回 Struct 类型
# ============================================================
def _is_struct_type(ty: llvmlite.LLVMType | t.CPtr) -> int:
    """检查 ty 是否是 Struct 类型（独立函数，规避嵌套 match 编译器 BUG）"""
    if ty is None:
        return 0
    match ty:
        case llvmlite.LLVMType.Struct(fields, fcount, name):
            return 1
        case _:
            return 0


def get_struct_type_from_value(val: llvmlite.Value | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
    """从 Value 的类型推断结构体类型"""
    if val is None or val.Ty is None:
        return None
    match val.Ty:
        case llvmlite.LLVMType.Ptr(pointee):
            if _is_struct_type(pointee) != 0:
                return pointee
            return None
        case _:
            return None


# ============================================================
# 联合体支持函数
# ============================================================

# ============================================================
# mark_as_union — 标记已注册的结构体为联合体
#
# 联合体用 Struct([Array(Int8, max_size)]) 表示，
# 注册时用 register_struct 注册类型，再用此函数标记 IsUnion=1
# ============================================================
def mark_as_union(name: str) -> int:
    """标记已注册的结构体为联合体，返回 1=成功 / 0=失败"""
    if name is None:
        return 0
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None:
        return 0
    entry.IsUnion = 1
    return 1


# ============================================================
# is_union_by_name — 按类名检查是否为联合体
# ============================================================
def is_union_by_name(name: str) -> int:
    """按类名检查是否为联合体，返回 1=是 / 0=否"""
    if name is None:
        return 0
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None:
        return 0
    return entry.IsUnion


# ============================================================
# is_union_by_type — 按类型指针检查是否为联合体
# ============================================================
def is_union_by_type(struct_ty: llvmlite.LLVMType | t.CPtr) -> int:
    """按类型指针检查是否为联合体，返回 1=是 / 0=否

    先尝试类型指针 == 比较，失败时回退到名称匹配
    """
    if struct_ty is None or _struct_table is None:
        return 0
    ty_name: str = _extract_struct_name(struct_ty)
    for i in range(_struct_count):
        entry: StructEntry | t.CPtr = _get_struct_entry(i)
        if entry is not None and entry.Ty is not None:
            matched: int = 0
            if entry.Ty is struct_ty:
                matched = 1
            elif ty_name is not None and entry.Name is not None:
                if string.strcmp(entry.Name, ty_name) == 0:
                    matched = 1
                elif string.strstr(ty_name, entry.Name) is not None:
                    matched = 1
            if matched != 0:
                return entry.IsUnion
    return 0


# ============================================================
# OOP 支持函数
# ============================================================

# ============================================================
# mark_as_oop — 标记已注册的结构体为 OOP（有方法）
# ============================================================
def mark_as_oop(name: str) -> int:
    """标记已注册的结构体为 OOP，返回 1=成功 / 0=失败"""
    if name is None:
        return 0
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None:
        return 0
    entry.IsOOP = 1
    return 1


# ============================================================
# is_oop_by_name — 按类名检查是否为 OOP 结构体
# ============================================================
def is_oop_by_name(name: str) -> int:
    """按类名检查是否为 OOP 结构体，返回 1=是 / 0=否"""
    if name is None:
        return 0
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None:
        return 0
    return entry.IsOOP


# ============================================================
# mark_has_init — 标记结构体拥有 __init__ 方法
# ============================================================
def mark_has_init(name: str) -> int:
    """标记结构体拥有 __init__ 方法，返回 1=成功 / 0=失败"""
    if name is None:
        return 0
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None:
        return 0
    entry.HasInit = 1
    return 1


# ============================================================
# has_init_by_name — 按类名检查是否有 __init__ 方法
# ============================================================
def has_init_by_name(name: str) -> int:
    """按类名检查是否有 __init__ 方法，返回 1=有 / 0=无"""
    if name is None:
        return 0
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None:
        return 0
    return entry.HasInit


# ============================================================
# mark_has_new — 标记结构体拥有 __new__ 方法
# ============================================================
def mark_has_new(name: str) -> int:
    """标记结构体拥有 __new__ 方法，返回 1=成功 / 0=失败"""
    if name is None:
        return 0
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None:
        return 0
    entry.HasNew = 1
    return 1


# ============================================================
# has_new_by_name — 按类名检查是否有 __new__ 方法
# ============================================================
def has_new_by_name(name: str) -> int:
    """按类名检查是否有 __new__ 方法，返回 1=有 / 0=无"""
    if name is None:
        return 0
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None:
        return 0
    return entry.HasNew


# ============================================================
# get_class_name_by_type — 按 LLVM 类型指针查找类名
#
# 用于方法调用：从变量类型 Ptr(Struct(...)) 反查类名，
# 以构造 ClassName.method_name 进行方法查找
# ============================================================
def get_class_name_by_type(pool: memhub.MemBuddy | t.CPtr,
                           struct_ty: llvmlite.LLVMType | t.CPtr) -> str:
    """按类型指针查找类名，返回类名字符串或 None"""
    if struct_ty is None or _struct_table is None:
        return None
    for i in range(_struct_count):
        entry: StructEntry | t.CPtr = _get_struct_entry(i)
        if entry is not None and entry.Ty is not None:
            if entry.Ty is struct_ty:
                return entry.Name
    # 回退: 类型指针比较失败时，遍历所有注册的结构体按名称匹配
    # 提取 struct_ty 的 Name 字段（可能是 "SHA1.ClassName" 格式）
    ty_name: str = _extract_struct_name(struct_ty)
    if ty_name is not None:
        for j in range(_struct_count):
            entry2: StructEntry | t.CPtr = _get_struct_entry(j)
            if entry2 is not None and entry2.Name is not None:
                # 构造 "SHA1.ClassName" 格式进行比较
                entry2_sha1: str = entry2.ModuleSha1
                if entry2_sha1 is not None:
                    full_nm: t.CChar | t.CPtr = pool.alloc(128)
                    if full_nm is not None:
                        viperlib.snprintf(full_nm, 128, "%s.%s", entry2_sha1, entry2.Name)
                        if string.strcmp(full_nm, ty_name) == 0:
                            return entry2.Name
                # 也直接比较类名（struct_ty 的 Name 可能无 SHA1 前缀）
                if string.strcmp(entry2.Name, ty_name) == 0:
                    return entry2.Name
                # 最后回退: strstr 检查包含关系
                # ty_name 可能是 "SHA1.Counter"，entry2.Name 是 "Counter"
                if string.strstr(ty_name, entry2.Name) is not None:
                    return entry2.Name
    return None


# ============================================================
# _extract_struct_name — 从 LLVMType 提取 Struct 变体的 Name 字段
# ============================================================
def _extract_struct_name(ty: llvmlite.LLVMType | t.CPtr) -> str:
    """从 LLVMType 提取 Struct 变体的 Name 字段，返回 None 非 Struct"""
    if ty is None:
        return None
    match ty:
        case llvmlite.LLVMType.Struct(fields, fcount, name):
            return name
        case _:
            return None


# ============================================================
# VTable 支持函数
# ============================================================

# ============================================================
# mark_has_vtable — 标记结构体拥有虚表
# ============================================================
def mark_has_vtable(name: str) -> int:
    """标记结构体拥有虚表，返回 1=成功 / 0=失败"""
    if name is None:
        return 0
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None:
        return 0
    entry.HasVTable = 1
    return 1


# ============================================================
# has_vtable_by_name — 按类名检查是否有虚表
# ============================================================
def has_vtable_by_name(name: str) -> int:
    """按类名检查是否有虚表，返回 1=有 / 0=无"""
    if name is None:
        return 0
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None:
        return 0
    return entry.HasVTable


# ============================================================
# mark_novtable — 标记结构体为 @t.NoVTable
# ============================================================
def mark_novtable(name: str) -> int:
    """标记结构体为 NoVTable，返回 1=成功 / 0=失败"""
    if name is None:
        return 0
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None:
        return 0
    entry.IsNoVTable = 1
    return 1


# ============================================================
# is_novtable_by_name — 按类名检查是否为 NoVTable
# ============================================================
def is_novtable_by_name(name: str) -> int:
    """按类名检查是否为 NoVTable，返回 1=是 / 0=否"""
    if name is None:
        return 0
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None:
        return 0
    return entry.IsNoVTable


# ============================================================
# set_parent_name — 设置父类名
# ============================================================
def set_parent_name(name: str, parent_name: str) -> int:
    """设置结构体的父类名，返回 1=成功 / 0=失败"""
    if name is None:
        return 0
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None:
        return 0
    entry.ParentName = parent_name
    return 1


# ============================================================
# get_parent_name — 获取父类名
# ============================================================
def get_parent_name(name: str) -> str:
    """获取结构体的父类名，返回 None=无父类"""
    if name is None:
        return None
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None:
        return None
    return entry.ParentName


# ============================================================
# set_vtable_methods — 设置虚表方法名数组
#
# methods 是一个 str 数组（每个元素是方法名字符串指针），
# count 是方法数量。数组直接引用，不复制。
# ============================================================
def set_vtable_methods(name: str, methods: t.CChar | t.CPtr, count: int) -> int:
    """设置虚表方法名数组，返回 1=成功 / 0=失败"""
    if name is None:
        return 0
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None:
        return 0
    entry.VTableMethods = methods
    entry.VTableMethodCount = count
    return 1


# ============================================================
# get_vtable_method_index — 获取方法在虚表中的索引
#
# 在 VTableMethods 数组中查找方法名，返回索引（-1=未找到）
# ============================================================
def get_vtable_method_index(name: str, method_name: str) -> int:
    """获取方法在虚表中的索引，返回 -1=未找到"""
    if name is None or method_name is None:
        return -1
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None or entry.VTableMethods is None:
        return -1
    # VTableMethods 字段声明为 t.CChar*，但实际存储的是 t.CSizeT 数组
    # 必须转换为 t.CSizeT* 才能正确读取 8 字节指针值
    methods_arr: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(t.CVoid(entry.VTableMethods, t.CPtr))
    for i in range(entry.VTableMethodCount):
        mname_addr: t.CSizeT = methods_arr[i]
        if mname_addr == 0:
            continue
        mname: str = (str | t.CPtr)(t.CVoid(mname_addr, t.CPtr))
        if mname is not None and string.strcmp(mname, method_name) == 0:
            return i
    return -1


# ============================================================
# get_vtable_method_count — 获取虚表方法数量
# ============================================================
def get_vtable_method_count(name: str) -> int:
    """获取虚表方法数量"""
    if name is None:
        return 0
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None:
        return 0
    return entry.VTableMethodCount


# ============================================================
# get_vtable_method_name — 获取虚表中第 idx 个方法名
#
# 返回方法名字符串指针，None=越界或未设置
# ============================================================
def get_vtable_method_name(name: str, idx: int) -> str:
    """获取虚表中第 idx 个方法名，返回 None=越界"""
    if name is None or idx < 0:
        return None
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None or entry.VTableMethods is None:
        return None
    if idx >= entry.VTableMethodCount:
        return None
    methods_arr: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(t.CVoid(entry.VTableMethods, t.CPtr))
    mname_addr: t.CSizeT = methods_arr[idx]
    if mname_addr == 0:
        return None
    return (str | t.CPtr)(t.CVoid(mname_addr, t.CPtr))


# ============================================================
# get_field_count — 获取结构体字段数量（访问器，绕过 stub 类型限制）
# ============================================================
def get_field_count(name: str) -> int:
    """获取结构体字段数量，返回 -1=未找到"""
    if name is None:
        return -1
    entry: StructEntry | t.CPtr = find_struct(name)
    if entry is None:
        return -1
    return entry.FieldCount


# ============================================================
# get_field_name_ptr — 获取 FieldEntry 的字段名指针（访问器）
# ============================================================
def get_field_name_ptr(fe: FieldEntry | t.CPtr) -> str:
    """获取 FieldEntry 的字段名，返回 None=未设置"""
    if fe is None:
        return None
    return fe.Name


# ============================================================
# get_field_type_ptr — 获取 FieldEntry 的字段类型指针（访问器）
# ============================================================
def get_field_type_ptr(fe: FieldEntry | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
    """获取 FieldEntry 的字段类型，返回 None=未设置"""
    if fe is None:
        return None
    return fe.Ty


# ============================================================
# get_field_default_ptr — 获取 FieldEntry 的默认值 AST 指针（访问器）
# ============================================================
def get_field_default_ptr(fe: FieldEntry | t.CPtr) -> ast.AST | t.CPtr:
    """获取 FieldEntry 的默认值 AST 节点，返回 None=无默认值"""
    if fe is None:
        return None
    return fe.DefaultVal


# ============================================================
# get_field_annot_class_name — 获取 FieldEntry 的注解类名（访问器）
# ============================================================
def get_field_annot_class_name(fe: FieldEntry | t.CPtr) -> str:
    """获取 FieldEntry 的原始类型注解类名，返回 None=未设置"""
    if fe is None:
        return None
    return fe.AnnotClassName
