import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import viperlib
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesEnum as HandlesEnum


# 枚举成员临时数组最大数量（本地常量）
ENUM_MEMBER_MAX_LOCAL: t.CDefine = 64


# ============================================================
# HandlesClassDef - class 定义处理
#
# 解析 class 定义，创建 LLVM StructType 并注册字段信息
#
# 纯内存结构体（无方法）的 class 定义:
#   class Point:
#       x: t.CInt
#       y: t.CInt
#
# 生成 LLVM 类型: { i32, i32 }
# 注册字段: x→index 0, y→index 1
# ============================================================


# ============================================================
# _is_cenum_base — 检查 base 节点是否为 t.CEnum
#
# 支持 Name(id='CEnum') 和 Attribute(value=Name('t'), attr='CEnum')
# ============================================================
def _is_cenum_base(base_node: ast.AST | t.CPtr) -> int:
    """检查 base 节点是否为 t.CEnum，返回 1=是 / 0=否"""
    if base_node is None:
        return 0
    k: int = base_node.kind()
    # Name('CEnum') 形式（from t import CEnum）
    if k == ast.ASTKind.Name:
        nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node)
        if nm.id is not None and string.strcmp(nm.id, "CEnum") == 0:
            return 1
        return 0
    # Attribute(t.CEnum) 形式
    if k == ast.ASTKind.Attribute:
        at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node)
        if at.attr is not None and string.strcmp(at.attr, "CEnum") == 0:
            return 1
        return 0
    return 0


# ============================================================
# _is_enum_class — 检查 ClassDef 是否继承自 t.CEnum
# ============================================================
def _is_enum_class(cd: ast.ClassDef | t.CPtr) -> int:
    """检查 ClassDef 是否继承自 t.CEnum，返回 1=是 / 0=否"""
    if cd is None or cd.bases is None:
        return 0
    bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases
    bn: t.CSizeT = bases.__len__()
    if bn == 0:
        return 0
    for bi in range(bn):
        base_node: ast.AST | t.CPtr = bases.get(bi)
        if base_node is None:
            continue
        if _is_cenum_base(base_node) == 1:
            return 1
    return 0


# ============================================================
# _is_cunion_base — 检查 base 节点是否为 t.CUnion
#
# 支持 Name(id='CUnion') 和 Attribute(value=Name('t'), attr='CUnion')
# ============================================================
def _is_cunion_base(base_node: ast.AST | t.CPtr) -> int:
    """检查 base 节点是否为 t.CUnion，返回 1=是 / 0=否"""
    if base_node is None:
        return 0
    k: int = base_node.kind()
    # Name('CUnion') 形式（from t import CUnion）
    if k == ast.ASTKind.Name:
        nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node)
        if nm.id is not None and string.strcmp(nm.id, "CUnion") == 0:
            return 1
        return 0
    # Attribute(t.CUnion) 形式
    if k == ast.ASTKind.Attribute:
        at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node)
        if at.attr is not None and string.strcmp(at.attr, "CUnion") == 0:
            return 1
        return 0
    return 0


# ============================================================
# _is_union_class — 检查 ClassDef 是否继承自 t.CUnion
# ============================================================
def _is_union_class(cd: ast.ClassDef | t.CPtr) -> int:
    """检查 ClassDef 是否继承自 t.CUnion，返回 1=是 / 0=否"""
    if cd is None or cd.bases is None:
        return 0
    bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases
    bn: t.CSizeT = bases.__len__()
    if bn == 0:
        return 0
    for bi in range(bn):
        base_node: ast.AST | t.CPtr = bases.get(bi)
        if base_node is None:
            continue
        if _is_cunion_base(base_node) == 1:
            return 1
    return 0


# ============================================================
# VTable 装饰器检测和继承关系判断
# ============================================================

# 标记基类集合（非真实父类，仅作为类型标记）
_MARKER_BASES: t.CDefine = 8
# 使用字符串比较代替集合，标记基类列表
# Object, CVTable, Exception, CEnum, Enum, CStruct, CUnion, REnum


# ============================================================
# _has_decorator — 检查 ClassDef/FunctionDef 的 decorator_list 中是否有指定装饰器
#
# 支持 @t.Name 和 @Name 两种形式
# 返回 1=有 / 0=无
# ============================================================
def _has_decorator(decorator_list: list[ast.AST | t.CPtr] | t.CPtr,
                   deco_name: str) -> int:
    """检查 decorator_list 中是否有指定装饰器名"""
    if decorator_list is None:
        return 0
    dn: t.CSizeT = decorator_list.__len__()
    if dn == 0:
        return 0
    for di in range(dn):
        deco: ast.AST | t.CPtr = decorator_list.get(di)
        if deco is None:
            continue
        k: int = deco.kind()
        # @t.NoVTable 形式（Attribute）
        if k == ast.ASTKind.Attribute:
            at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(deco)
            if at.attr is not None and string.strcmp(at.attr, deco_name) == 0:
                # 检查 value 是 Name('t')
                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, "t") == 0:
                        return 1
                return 0
        # @NoVTable 形式（Name，from t import NoVTable）
        if k == ast.ASTKind.Name:
            nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(deco)
            if nm.id is not None and string.strcmp(nm.id, deco_name) == 0:
                return 1
    return 0


# ============================================================
# _is_marker_base — 检查基类名是否为标记基类（非真实父类）
#
# 标记基类: Object, CVTable, Exception, CEnum, Enum, CStruct, CUnion, REnum
# ============================================================
def _is_marker_base(base_name: str) -> int:
    """检查基类名是否为标记基类，返回 1=是 / 0=否"""
    if base_name is None:
        return 0
    if string.strcmp(base_name, "Object") == 0:
        return 1
    if string.strcmp(base_name, "CVTable") == 0:
        return 1
    if string.strcmp(base_name, "Exception") == 0:
        return 1
    if string.strcmp(base_name, "CEnum") == 0:
        return 1
    if string.strcmp(base_name, "Enum") == 0:
        return 1
    if string.strcmp(base_name, "CStruct") == 0:
        return 1
    if string.strcmp(base_name, "CUnion") == 0:
        return 1
    if string.strcmp(base_name, "REnum") == 0:
        return 1
    return 0


# ============================================================
# _get_base_name — 从 base AST 节点提取基类名
#
# 支持 Name(id), Attribute(attr), Subscript
# ============================================================
def _get_base_name(base_node: ast.AST | t.CPtr) -> str:
    """从 base AST 节点提取基类名，返回 None=失败"""
    if base_node is None:
        return None
    k: int = base_node.kind()
    # Name(id) 形式
    if k == ast.ASTKind.Name:
        nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node)
        return nm.id
    # Attribute(attr) 形式
    if k == ast.ASTKind.Attribute:
        at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node)
        return at.attr
    return None


# ============================================================
# _get_parent_class — 获取 ClassDef 的真实父类名（非标记基类）
#
# 遍历 bases，返回第一个非标记基类的名字，None=无真实父类
# ============================================================
def _get_parent_class(cd: ast.ClassDef | t.CPtr) -> str:
    """获取 ClassDef 的真实父类名，返回 None=无真实父类"""
    if cd is None or cd.bases is None:
        return None
    bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases
    bn: t.CSizeT = bases.__len__()
    if bn == 0:
        return None
    for bi in range(bn):
        base_node: ast.AST | t.CPtr = bases.get(bi)
        if base_node is None:
            continue
        bname: str = _get_base_name(base_node)
        if bname is not None and _is_marker_base(bname) == 0:
            return bname
    return None


# ============================================================
# _has_any_func_cvtable — 检查类中是否有任何函数标记了 @t.CVTable
#
# 用于类级别未启用虚表时，检查函数级 @t.CVTable 是否触发虚表。
# 跳过 __init__ 和 __before_init__（构造函数不进入虚表）。
# ============================================================
def _has_any_func_cvtable(cd: ast.ClassDef | t.CPtr) -> int:
    """检查类中是否有任何函数标记了 @t.CVTable，返回 1=有 / 0=无"""
    if cd is None or cd.children is None:
        return 0
    children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
    cn: t.CSizeT = children.__len__()
    for ci in range(cn):
        stmt: ast.AST | t.CPtr = children.get(ci)
        if stmt is None:
            continue
        if stmt.kind() != ast.ASTKind.FunctionDef:
            continue
        fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt)
        if fd is None or fd.name is None:
            continue
        # 跳过构造函数
        if string.strcmp(fd.name, "__init__") == 0:
            continue
        if string.strcmp(fd.name, "__before_init__") == 0:
            continue
        if string.strcmp(fd.name, "__new__") == 0:
            continue
        if fd.decorator_list is not None:
            if _has_decorator(fd.decorator_list, "CVTable") == 1:
                return 1
    return 0


# ============================================================
# _should_method_be_virtual — 判断方法是否应该进入虚表
#
# 规则（优先级从高到低）:
#   1. 函数有 @t.NoVTable → 排除（返回 0）
#   2. 函数有 @t.CVTable → 包含（返回 1）
#   3. 类有 @t.CVTable → 包含（返回 1）
#   4. 有继承关系（父类非 NoVTable）→ 包含（返回 1）
#   5. 默认 → 排除（返回 0）
# ============================================================
def _should_method_be_virtual(cd: ast.ClassDef | t.CPtr,
                               fd: ast.FunctionDef | t.CPtr,
                               trans: HT.Translator | t.CPtr = None) -> int:
    """判断方法是否应该进入虚表，返回 1=包含 / 0=排除"""
    if fd is None:
        return 0
    # 1. 检查函数级 @t.NoVTable（最高优先级，排除）
    if fd.decorator_list is not None:
        if _has_decorator(fd.decorator_list, "NoVTable") == 1:
            return 0
        # 2. 检查函数级 @t.CVTable（明确包含）
        if _has_decorator(fd.decorator_list, "CVTable") == 1:
            return 1

    # 3. 检查类级别 @t.CVTable
    if cd is not None and cd.decorator_list is not None:
        if _has_decorator(cd.decorator_list, "CVTable") == 1:
            return 1

    # 4. 检查继承关系
    parent_name: str = _get_parent_class(cd)
    if parent_name is not None:
        # 用 SHA1 感知查找父类，规避跨模块同名找错
        is_nvt: int = 0
        if trans is not None:
            p_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
                parent_name, trans.ModuleSha1)
            if p_entry is not None:
                is_nvt = p_entry.IsNoVTable
        else:
            is_nvt = HandlesStruct.is_novtable_by_name(parent_name)
        if is_nvt != 1:
            return 1  # 有继承且父类非 NoVTable

    # 5. 默认排除
    return 0


# ============================================================
# _detect_vtable_status — 检测类是否应该启用虚表
#
# 规则:
#   1. @t.CVTable → 有虚表
#   2. 有真实父类且非 NoVTable → 有虚表（自动启用）
#   3. @t.NoVTable → 检查函数级 @t.CVTable，有则启用
#   4. 默认 → 检查函数级 @t.CVTable，有则启用
#
# 返回: 1=有虚表 / 0=无虚表
# ============================================================
def _detect_vtable_status(cd: ast.ClassDef | t.CPtr,
                          trans: HT.Translator | t.CPtr = None) -> int:
    """检测类是否应该启用虚表"""
    if cd is None:
        return 0

    # 检查类装饰器
    if cd.decorator_list is not None:
        # @t.CVTable 优先级最高，直接启用
        if _has_decorator(cd.decorator_list, "CVTable") == 1:
            return 1
        # @t.NoVTable：类级别禁用，但检查函数级 @t.CVTable
        if _has_decorator(cd.decorator_list, "NoVTable") == 1:
            return _has_any_func_cvtable(cd)

    # 检查是否有真实父类（继承自动启用 CVTable）
    parent_name: str = _get_parent_class(cd)
    if parent_name is not None:
        # 用 SHA1 感知查找父类，规避跨模块同名找错
        is_nvt: int = 0
        if trans is not None:
            p_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
                parent_name, trans.ModuleSha1)
            if p_entry is not None:
                is_nvt = p_entry.IsNoVTable
        else:
            is_nvt = HandlesStruct.is_novtable_by_name(parent_name)
        if is_nvt == 1:
            # 父类是 NoVTable，检查函数级 @t.CVTable
            return _has_any_func_cvtable(cd)
        return 1  # 有父类且非 NoVTable，自动启用虚表

    # 默认（无装饰器无继承），检查函数级 @t.CVTable
    return _has_any_func_cvtable(cd)


# ============================================================
# _resolve_enum_member_type — 解析枚举成员的类型
#
# - t.State → 默认 i32
# - int / t.CInt8T / t.CInt16T / t.CInt32T / t.CInt64T 等 → 对应整数类型
# - 联合注解（t.State | t.CInt8T）递归查找实际类型
# ============================================================
def _resolve_enum_member_type(pool: memhub.MemBuddy | t.CPtr,
                              ann_node: ast.AST | t.CPtr,
                              imported_modules: str,
                              from_imports: str) -> llvmlite.LLVMType | t.CPtr:
    """解析枚举成员的类型注解为 LLVM 整数类型"""
    if ann_node is None:
        return llvmlite.Int32(pool)

    k: int = ann_node.kind()

    # Attribute 节点: t.State / int / t.CInt8T 等
    if k == ast.ASTKind.Attribute:
        at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(ann_node)
        if at.attr is None:
            return llvmlite.Int32(pool)
        # t.State → 默认 i32
        if string.strcmp(at.attr, "State") == 0:
            return llvmlite.Int32(pool)
        # 其他 t.CXxx 类型
        ty: llvmlite.LLVMType | t.CPtr = HandlesType.map_t_type(pool, at.attr)
        if ty is not None:
            return ty
        return llvmlite.Int32(pool)

    # Name 节点: from-import 形式（State / CInt）
    if k == ast.ASTKind.Name:
        nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(ann_node)
        if nm.id is None:
            return llvmlite.Int32(pool)
        if string.strcmp(nm.id, "State") == 0:
            return llvmlite.Int32(pool)
        ty2: llvmlite.LLVMType | t.CPtr = HandlesType.map_t_type(pool, nm.id)
        if ty2 is not None:
            return ty2
        return llvmlite.Int32(pool)

    # BinOp 节点: t.State | t.CInt8T（递归查找实际类型）
    if k == ast.ASTKind.BinOp:
        bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(ann_node)
        if bop.op == ast.OpKind.BitOr:
            left_ty: llvmlite.LLVMType | t.CPtr = _resolve_enum_member_type(
                pool, bop.left, imported_modules, from_imports)
            # 跳过 t.State（i32 默认），优先返回具体类型
            left_bits: int = HandlesType.get_llvm_type_bits(left_ty)
            if left_bits != 0 and not _is_state_annotation(bop.left):
                return left_ty
            right_ty: llvmlite.LLVMType | t.CPtr = _resolve_enum_member_type(
                pool, bop.right, imported_modules, from_imports)
            if right_ty is not None and not _is_state_annotation(bop.right):
                return right_ty
            # 两边都是 State 或无法确定，返回较宽的
            right_bits: int = HandlesType.get_llvm_type_bits(right_ty)
            if left_bits >= right_bits:
                return left_ty
            return right_ty
        return llvmlite.Int32(pool)

    return llvmlite.Int32(pool)


# ============================================================
# _is_state_annotation — 检查注解节点是否为 t.State
# ============================================================
def _is_state_annotation(node: ast.AST | t.CPtr) -> int:
    """检查注解节点是否为 t.State，返回 1=是 / 0=否"""
    if node is None:
        return 0
    k: int = node.kind()
    if k == ast.ASTKind.Attribute:
        at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
        if at.attr is not None and string.strcmp(at.attr, "State") == 0:
            return 1
        return 0
    if k == ast.ASTKind.Name:
        nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
        if nm.id is not None and string.strcmp(nm.id, "State") == 0:
            return 1
        return 0
    return 0


# ============================================================
# _extract_int_value — 从 AST 节点提取整数值
#
# 支持 Constant(int) 和 UnaryOp(USub, Constant(int))
# ============================================================
def _extract_int_value(node: ast.AST | t.CPtr) -> t.CInt64T:
    """从 AST 节点提取整数值，失败返回 0"""
    if node is None:
        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:
            return cn.int_val
        return 0
    if k == ast.ASTKind.UnaryOp:
        uo: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(node)
        if uo.op == ast.OpKind.USub:
            inner: t.CInt64T = _extract_int_value(uo.operand)
            return -inner
        return 0
    return 0


# ============================================================
# _translate_enum_def — 翻译枚举类定义
#
# 遍历 class body 中的 AnnAssign，收集成员名、类型、值
# 自动赋值：无值时从上一值+1递增（首值默认 0）
# 基准类型：所有成员类型中 Bits 最大的（t.State 视为 i32）
# ============================================================
def _translate_enum_def(trans: HT.Translator | t.CPtr,
                        cd: ast.ClassDef | t.CPtr) -> int:
    """翻译枚举类定义，返回 0"""
    if cd is None or cd.name is None or trans is None:
        return 0

    pool: memhub.MemBuddy | t.CPtr = trans.Pool
    class_name: str = cd.name

    # 已注册则跳过
    if HandlesEnum.is_enum_class(class_name) == 1:
        return 0

    children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
    if children is None:
        stdio.printf("[ENUM] %s has no body\n", class_name)
        return 0

    cn: t.CSizeT = children.__len__()

    # 临时数组存储成员信息
    member_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL)
    member_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL)
    member_values_buf: t.CInt64T | t.CPtr = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL)
    if member_names_buf is None or member_types_buf is None or member_values_buf is None:
        return 0
    string.memset(member_names_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL)
    string.memset(member_types_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL)
    string.memset(member_values_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL)

    member_count: int = 0
    next_val: t.CInt64T = 0

    for ci in range(cn):
        stmt: ast.AST | t.CPtr = children.get(ci)
        if stmt is None:
            continue
        sk: int = stmt.kind()

        if sk == ast.ASTKind.AnnAssign:
            aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(stmt)
            if aa is None or aa.target is None:
                continue

            # 获取成员名
            if aa.target.kind() != ast.ASTKind.Name:
                continue
            tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
            if tgt.id is None:
                continue

            # 解析成员类型
            member_ty: llvmlite.LLVMType | t.CPtr = _resolve_enum_member_type(
                pool, aa.annotation, trans._imported_modules, trans._from_imports)

            # 解析成员值
            has_value: int = 0
            cur_val: t.CInt64T = 0
            if aa.value is not None:
                cur_val = _extract_int_value(aa.value)
                has_value = 1
            else:
                cur_val = next_val

            # 下一个自动值
            next_val = cur_val + 1

            # 存储
            if member_count < ENUM_MEMBER_MAX_LOCAL:
                member_names_buf[member_count] = t.CSizeT(tgt.id)
                member_types_buf[member_count] = t.CSizeT(member_ty)
                member_values_buf[member_count] = cur_val
                member_count += 1

    if member_count == 0:
        stdio.printf("[ENUM] %s has no members\n", class_name)
        return 0

    # 确定基准类型：所有成员类型中 Bits 最大的
    base_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
    max_bits: int = 0
    for mi in range(member_count):
        ty_addr: t.CSizeT = member_types_buf[mi]
        if ty_addr == 0:
            continue
        mty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(
            t.CVoid(ty_addr, t.CPtr))
        bits: int = HandlesType.get_llvm_type_bits(mty)
        if bits > max_bits:
            max_bits = bits
            base_ty = mty

    # 注册枚举
    entry: HandlesEnum.EnumEntry | t.CPtr = HandlesEnum.register_enum(
        pool, class_name, base_ty)
    if entry is None:
        stdio.printf("[ENUM] failed to register %s\n", class_name)
        return 0

    # 添加成员
    for mi in range(member_count):
        fname_addr: t.CSizeT = member_names_buf[mi]
        if fname_addr == 0:
            continue
        mname: str = (str | t.CPtr)(t.CVoid(fname_addr, t.CPtr))
        fty_addr2: t.CSizeT = member_types_buf[mi]
        if fty_addr2 == 0:
            continue
        mty2: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(
            t.CVoid(fty_addr2, t.CPtr))
        mval: t.CInt64T = member_values_buf[mi]
        if mname is not None and mty2 is not None:
            HandlesEnum.add_enum_member(pool, entry, mname, mval, mty2)

    stdio.printf("[ENUM] registered %s with %d members, base_bits=%d\n",
                 class_name, member_count, max_bits)
    return 0


# ============================================================
# _get_type_size — 计算 LLVM 类型的字节大小
#
# 用于联合体确定最大字段大小
# ============================================================
def _get_type_size(ty: llvmlite.LLVMType | t.CPtr) -> int:
    """计算 LLVM 类型的字节大小"""
    if ty is None:
        return 0
    match ty:
        case llvmlite.LLVMType.Int(bits):
            return (bits + 7) // 8
        case llvmlite.LLVMType.Float(bits):
            return bits // 8
        case llvmlite.LLVMType.Ptr(pointee):
            return 8
        case llvmlite.LLVMType.Array(elem_ty, count):
            return _get_type_size(elem_ty) * count
        case llvmlite.LLVMType.Struct(fields, fcount, name):
            total: int = 0
            cur: llvmlite.ParamNode | t.CPtr = fields
            i: int = 0
            while cur is not None and i < fcount:
                if cur.Ty is not None:
                    fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(cur.Ty)
                    total += _get_type_size(fty)
                cur = cur.Next
                i += 1
            return total
        case _:
            return 8


# ============================================================
# _translate_union_def — 翻译联合体定义
#
# 联合体语法:
#   class MyUnion(t.CUnion):
#       a: t.CInt
#       b: t.CFloat
#       c: t.CInt64T
#
# 实现方式:
#   - 收集所有字段类型
#   - 计算最大字段字节大小 max_size
#   - LLVM 类型 = Struct([Array(Int8, max_size)])  # { [N x i8] }
#   - 注册到 HandlesStruct 并标记 IsUnion=1
#   - 字段访问通过 bitcast 实现（HandlesExpr 中处理）
# ============================================================
def _translate_union_def(trans: HT.Translator | t.CPtr,
                         cd: ast.ClassDef | t.CPtr) -> int:
    """翻译联合体定义，返回 0"""
    if cd is None or cd.name is None or trans is None:
        return 0

    pool: memhub.MemBuddy | t.CPtr = trans.Pool
    class_name: str = cd.name

    # 命名空间隔离：标记为当前文件可见（必须在 existing 检查之前）
    HandlesStruct.add_visible_struct(pool, class_name)

    # 检查是否已注册（用 SHA1 区分跨模块同名类）
    existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
        class_name, trans.ModuleSha1)
    if existing is not None:
        # Phase B: 将已存在的命名结构体注册到当前模块
        if existing.Ty is not None:
            llvmlite.module_add_named_type(trans.Module, pool, existing.Ty)
        # SHA1 已在 register_struct 时设置，无需再补
        return 0

    children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
    if children is None:
        stdio.printf("[UNION] %s has no body\n", class_name)
        return 0

    cn: t.CSizeT = children.__len__()

    # 临时数组存储字段信息
    field_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
    field_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
    if field_names_buf is None or field_types_buf is None:
        return 0
    string.memset(field_names_buf, 0, 8 * 32)
    string.memset(field_types_buf, 0, 8 * 32)

    field_count: int = 0
    max_size: int = 0

    for ci in range(cn):
        stmt: ast.AST | t.CPtr = children.get(ci)
        if stmt is None:
            continue
        sk: int = stmt.kind()

        if sk == ast.ASTKind.AnnAssign:
            aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(stmt)
            if aa is None or aa.target is None:
                continue

            # 获取字段名
            if aa.target.kind() != ast.ASTKind.Name:
                continue
            tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
            if tgt.id is None:
                continue

            # 解析字段类型
            field_ty: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
                pool, aa.annotation, trans._imported_modules, trans._from_imports)
            if field_ty is None:
                field_ty = llvmlite.Int32(pool)

            # 计算字段大小，更新 max_size
            fsize: int = _get_type_size(field_ty)
            if fsize > max_size:
                max_size = fsize

            # 存储到数组
            if field_count < 32:
                field_names_buf[field_count] = t.CSizeT(tgt.id)
                field_types_buf[field_count] = t.CSizeT(field_ty)
                field_count += 1

    if field_count == 0:
        stdio.printf("[UNION] %s has no fields\n", class_name)
        return 0

    if max_size < 1:
        max_size = 1

    # 创建联合体的 LLVM 类型: Struct([Array(Int8, max_size)])
    # 即 { [max_size x i8] }
    i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
    array_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Array(pool, i8_ty, max_size)

    # 构建 ParamNode 链表（单字段：字节数组）
    pnode: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__())
    if pnode is None:
        return 0
    string.memset(pnode, 0, llvmlite.ParamNode.__sizeof__())
    pnode.Ty = array_ty

    # 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName"
    union_type_name: str = class_name
    if trans.ModuleSha1 is not None:
        union_name_buf: t.CChar | t.CPtr = pool.alloc(64)
        if union_name_buf is not None:
            viperlib.snprintf(union_name_buf, 64, "%s.%s", trans.ModuleSha1, class_name)
            union_type_name = union_name_buf

    union_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, pnode, 1, union_type_name)
    if union_ty is None:
        stdio.printf("[UNION] failed to create type for %s\n", class_name)
        return 0

    # 注册命名结构体到模块
    llvmlite.module_add_named_type(trans.Module, pool, union_ty)

    # 注册到 HandlesStruct（传递 SHA1 在注册时直接设置，避免跨模块同名找错 entry）
    entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.register_struct(
        pool, class_name, union_ty, trans.ModuleSha1)
    if entry is None:
        stdio.printf("[UNION] failed to register %s\n", class_name)
        return 0

    # 标记为当前文件可见（命名空间隔离）
    HandlesStruct.add_visible_struct(pool, class_name)

    # 标记为联合体（直接用 entry，规避跨模块同名 find_struct 找错）
    entry.IsUnion = 1

    # 添加字段信息（所有字段 Index=0，因为共享偏移 0）
    for fi in range(field_count):
        fname_addr: t.CSizeT = field_names_buf[fi]
        if fname_addr == 0:
            continue
        fname: str = (str | t.CPtr)(t.CVoid(fname_addr, t.CPtr))
        fty_addr2: t.CSizeT = field_types_buf[fi]
        if fty_addr2 == 0:
            continue
        fty2: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(
            t.CVoid(fty_addr2, t.CPtr))
        if fname is not None and fty2 is not None:
            HandlesStruct.add_field(pool, entry, fname, fty2, None, None)

    stdio.printf("[UNION] registered %s with %d fields, max_size=%d\n",
                 class_name, field_count, max_size)
    return 0


# ============================================================
# translate_class_def — 翻译 class 定义
#
# 遍历 class body 中的 AnnAssign 语句，收集字段类型
# 创建 LLVM StructType 并注册到 HandlesStruct
# ============================================================
# ============================================================
# 泛型类模板存储（模块级）
#
# 泛型类 class list[T]: 不直接发射 IR，而是存储为模板，
# 等遇到 list[int](pool) 实例化时触发 _specialize_generic_class
# ============================================================

_generic_class_names: list[str] | t.CPtr = None
_generic_class_nodes: list[ast.ClassDef | t.CPtr] | t.CPtr = None


def _is_generic_class(cd: ast.ClassDef | t.CPtr) -> int:
    """检查 ClassDef 是否有类型参数（泛型类），返回 1=是 / 0=否"""
    if cd is None:
        return 0
    tp: list[str] | t.CPtr = cd.type_params
    if tp is None:
        return 0
    if tp.__len__() == 0:
        return 0
    return 1


def _register_generic_template(pool: memhub.MemBuddy | t.CPtr,
                               cd: ast.ClassDef | t.CPtr):
    """注册泛型类模板（类名 + ClassDef 节点）"""
    global _generic_class_names, _generic_class_nodes
    if _generic_class_names is None:
        _generic_class_names = list[str](pool, 8)
        _generic_class_nodes = list[ast.ClassDef | t.CPtr](pool, 8)
    # 检查是否已注册
    cn: t.CSizeT = _generic_class_names.__len__()
    i: t.CSizeT
    for i in range(cn):
        nm: str = _generic_class_names.get(i)
        if nm is not None and string.strcmp(nm, cd.name) == 0:
            return
    _generic_class_names.append(cd.name)
    _generic_class_nodes.append(cd)


def _find_generic_template(class_name: str) -> ast.ClassDef | t.CPtr:
    """查找泛型类模板，返回 ClassDef 节点或 None"""
    if _generic_class_names is None or class_name is None:
        return None
    cn: t.CSizeT = _generic_class_names.__len__()
    i: t.CSizeT
    for i in range(cn):
        nm: str = _generic_class_names.get(i)
        if nm is not None and string.strcmp(nm, class_name) == 0:
            return _generic_class_nodes.get(i)
    return None


def _mangle_generic_class_name(pool: memhub.MemBuddy | t.CPtr,
                               class_name: str,
                               type_args: list[str] | t.CPtr) -> str:
    """生成特化类名: list + [int] -> list[int]

    分配新缓冲区拼接，避免原地 strcat 导致缓冲区溢出
    """
    if class_name is None or type_args is None or pool is None:
        return class_name
    n: t.CSizeT = type_args.__len__()
    if n == 0:
        return class_name
    # 计算总长度: class_name + "[" + arg0 + "," + arg1 + ... + "]" + NUL
    total_len: t.CSizeT = string.strlen(class_name) + 2  # "[" 和 "]"
    i: t.CSizeT
    for i in range(n):
        if i > 0:
            total_len += 1  # ","
        ta: str = type_args.get(i)
        if ta is not None:
            total_len += string.strlen(ta)
    total_len += 1  # NUL
    # 分配新缓冲区
    mangled: str = pool.alloc(total_len)
    if mangled is None:
        return class_name
    mangled[0] = '\0'
    string.strcat(mangled, class_name)
    string.strcat(mangled, "[")
    for i in range(n):
        if i > 0:
            string.strcat(mangled, ",")
        ta: str = type_args.get(i)
        if ta is not None:
            string.strcat(mangled, ta)
    string.strcat(mangled, "]")
    return mangled


# ============================================================
# 类型注解拷贝（用于泛型特化）
#
# _clone_annotation: 拷贝类型注解表达式，替换类型参数 T 为具体类型
# _clone_arguments:  拷贝 Arguments 节点，替换 arg annotation 中的 T
# _clone_classdef_for_spec: 拷贝 ClassDef 用于泛型特化
# ============================================================

def _clone_annotation(pool: memhub.MemBuddy | t.CPtr,
                      node: ast.AST | t.CPtr,
                      tp_names: list[str] | t.CPtr,
                      type_args: list[str] | t.CPtr) -> ast.AST | t.CPtr:
    """拷贝类型注解表达式，替换类型参数 T 为具体类型名

    tp_names: 类型参数名列表 ['T']
    type_args: 类型实参名列表 ['int']
    """
    if node is None:
        return None
    k: int = node.kind()

    # Name: 可能是类型参数 T
    if k == ast.ASTKind.Name:
        nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
        if nm.id is not None:
            n: t.CSizeT = tp_names.__len__() if tp_names is not None else 0
            i: t.CSizeT
            for i in range(n):
                tpn: str = tp_names.get(i)
                if tpn is not None and string.strcmp(nm.id, tpn) == 0:
                    ta: str = type_args.get(i)
                    # 类型实参可能是复合类型（如 "AST|t.CPtr"），用 _parse_type_string 解析
                    return HandlesType._parse_type_string(pool, ta, nm.ctx)
            return ast.Name(pool, nm.id, nm.ctx)
        return None

    # Attribute: t.CPtr 等
    if k == ast.ASTKind.Attribute:
        at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
        new_value: ast.AST | t.CPtr = _clone_annotation(pool, at.value, tp_names, type_args)
        return ast.Attribute(pool, new_value, at.attr, at.ctx)

    # BinOp: T | t.CPtr 等
    if k == ast.ASTKind.BinOp:
        bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
        new_left: ast.AST | t.CPtr = _clone_annotation(pool, bop.left, tp_names, type_args)
        new_right: ast.AST | t.CPtr = _clone_annotation(pool, bop.right, tp_names, type_args)
        return ast.BinOp(pool, new_left, bop.op, new_right)

    # Subscript: list[int] 等
    if k == ast.ASTKind.Subscript:
        sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node)
        new_value2: ast.AST | t.CPtr = _clone_annotation(pool, sub.value, tp_names, type_args)
        new_slice: ast.AST | t.CPtr = _clone_annotation(pool, sub.slice, tp_names, type_args)
        return ast.Subscript(pool, new_value2, new_slice, sub.ctx)

    # Tuple: (T, int) 等
    if k == ast.ASTKind.Tuple:
        tup: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(node)
        new_elts: list[ast.AST | t.CPtr] | t.CPtr = list[ast.AST | t.CPtr](pool, 8)
        if tup.elts is not None:
            en: t.CSizeT = tup.elts.__len__()
            ei: t.CSizeT
            for ei in range(en):
                el: ast.AST | t.CPtr = tup.elts.get(ei)
                new_el: ast.AST | t.CPtr = _clone_annotation(pool, el, tp_names, type_args)
                if new_el is not None:
                    new_elts.append(new_el)
        return ast.Tuple(pool, new_elts, tup.ctx)

    # Constant: 默认值等
    if k == ast.ASTKind.Constant:
        cnst: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
        return ast.Constant(pool, cnst.const_kind, cnst.int_val, cnst.float_val,
                            cnst.str_val, cnst.lineno, cnst.col_offset)

    # 其他: 直接引用（不拷贝）
    return node


def _clone_arguments(pool: memhub.MemBuddy | t.CPtr,
                     args: ast.AST | t.CPtr,
                     tp_names: list[str] | t.CPtr,
                     type_args: list[str] | t.CPtr) -> ast.AST | t.CPtr:
    """拷贝 Arguments 节点，替换 arg annotation 中的 T"""
    if args is None:
        return None
    if args.kind() != ast.ASTKind.Arguments:
        return args
    old_args: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args)
    # 拷贝 args 列表，替换每个 Arg 的 annotation
    new_arg_list: list[ast.AST | t.CPtr] | t.CPtr = list[ast.AST | t.CPtr](pool, 8)
    if old_args.args is not None:
        an: t.CSizeT = old_args.args.__len__()
        ai: t.CSizeT
        for ai in range(an):
            arg_node: ast.AST | t.CPtr = old_args.args.get(ai)
            if arg_node is None:
                continue
            if arg_node.kind() == ast.ASTKind.Arg:
                ag: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(arg_node)
                new_anno: ast.AST | t.CPtr = _clone_annotation(pool, ag.annotation, tp_names, type_args)
                new_arg: ast.Arg | t.CPtr = ast.Arg(pool, ag.arg, new_anno)
                new_arg_list.append(new_arg)
            else:
                new_arg_list.append(arg_node)
    return ast.Arguments(pool, new_arg_list, old_args.vararg, old_args.kwarg,
                         old_args.defaults, old_args.kw_defaults)


def _clone_classdef_for_spec(pool: memhub.MemBuddy | t.CPtr,
                             cd: ast.ClassDef | t.CPtr,
                             spec_name: str,
                             tp_names: list[str] | t.CPtr,
                             type_args: list[str] | t.CPtr) -> ast.ClassDef | t.CPtr:
    """拷贝 ClassDef 节点用于泛型特化

    - 替换类名为 spec_name
    - 清除 type_params（特化后不是泛型类）
    - 拷贝 children 中的 AnnAssign 和 FunctionDef，替换类型注解中的 T
    - 方法体直接引用原始节点（通过 type_map 上下文处理 T）
    """
    # 创建新 ClassDef（type_params=None 表示非泛型）
    new_cd: ast.ClassDef | t.CPtr = ast.ClassDef(pool, spec_name, cd.bases, cd.keywords,
                                                  cd.decorator_list, None)
    # 拷贝 children
    if cd.children is not None:
        cn: t.CSizeT = cd.children.__len__()
        ci: t.CSizeT
        for ci in range(cn):
            child: ast.AST | t.CPtr = cd.children.get(ci)
            if child is None:
                continue
            ck: int = child.kind()

            if ck == ast.ASTKind.AnnAssign:
                aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(child)
                new_target: ast.AST | t.CPtr = aa.target
                new_anno2: ast.AST | t.CPtr = _clone_annotation(pool, aa.annotation, tp_names, type_args)
                new_value3: ast.AST | t.CPtr = aa.value
                new_aa: ast.AnnAssign | t.CPtr = ast.AnnAssign(pool, new_target, new_anno2, new_value3, aa.simple)
                new_cd.append(new_aa)

            elif ck == ast.ASTKind.FunctionDef:
                fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child)
                new_args2: ast.AST | t.CPtr = _clone_arguments(pool, fd.args, tp_names, type_args)
                new_returns2: ast.AST | t.CPtr = _clone_annotation(pool, fd.returns, tp_names, type_args)
                new_fd: ast.FunctionDef | t.CPtr = ast.FunctionDef(pool, fd.name, new_args2,
                                                                    fd.decorator_list, new_returns2, 0)
                # 方法体直接引用原始节点
                if fd.children is not None:
                    bcn: t.CSizeT = fd.children.__len__()
                    bci: t.CSizeT
                    for bci in range(bcn):
                        body_stmt: ast.AST | t.CPtr = fd.children.get(bci)
                        if body_stmt is not None:
                            new_fd.append(body_stmt)
                new_cd.append(new_fd)

            else:
                new_cd.append(child)

    return new_cd


# ============================================================
# 泛型特化缓存（模块级）
# ============================================================

_spec_keys: list[str] | t.CPtr = None
_spec_names: list[str] | t.CPtr = None


def _find_cached_spec(spec_key: str) -> str:
    """查找已缓存的特化名，未找到返回 None"""
    if _spec_keys is None or spec_key is None:
        return None
    n: t.CSizeT = _spec_keys.__len__()
    i: t.CSizeT
    for i in range(n):
        k: str = _spec_keys.get(i)
        if k is not None and string.strcmp(k, spec_key) == 0:
            return _spec_names.get(i)
    return None


def _cache_spec(pool: memhub.MemBuddy | t.CPtr, spec_key: str, spec_name: str):
    """缓存特化结果"""
    global _spec_keys, _spec_names
    if _spec_keys is None:
        _spec_keys = list[str](pool, 8)
        _spec_names = list[str](pool, 8)
    _spec_keys.append(spec_key)
    _spec_names.append(spec_name)


def _specialize_generic_class(trans: HT.Translator | t.CPtr,
                              class_name: str,
                              type_args: list[str] | t.CPtr) -> str:
    """特化泛型类，返回特化类名

    1. 查找泛型模板
    2. 生成特化名
    3. 检查缓存
    4. 拷贝 ClassDef 节点（替换类型注解中的 T）
    5. 设置 type_map 上下文（用于方法体中的 T 替换）
    6. 调用 translate_class_def 翻译特化类
    7. 返回特化名
    """
    if trans is None or class_name is None or type_args is None:
        return None

    pool: memhub.MemBuddy | t.CPtr = trans.Pool

    # 1. 查找泛型模板
    template_cd: ast.ClassDef | t.CPtr = _find_generic_template(class_name)
    if template_cd is None:
        return None

    # 2. 生成特化名
    spec_name: str = _mangle_generic_class_name(pool, class_name, type_args)
    if spec_name is None:
        return None

    # 3. 检查缓存（spec_key 包含所有类型实参，避免多参数泛型缓存冲突）
    # 分配新缓冲区避免原地 strcat 溢出
    sk_n: t.CSizeT = type_args.__len__()
    sk_total: t.CSizeT = string.strlen(class_name) + 2  # "<" 和 ">"
    sk_i: t.CSizeT
    for sk_i in range(sk_n):
        if sk_i > 0:
            sk_total += 1  # ","
        sk_ta: str = type_args.get(sk_i)
        if sk_ta is not None:
            sk_total += string.strlen(sk_ta)
    sk_total += 1  # NUL
    spec_key: str = pool.alloc(sk_total)
    if spec_key is None:
        return None
    spec_key[0] = '\0'
    string.strcat(spec_key, class_name)
    string.strcat(spec_key, "<")
    for sk_i in range(sk_n):
        if sk_i > 0:
            string.strcat(spec_key, ",")
        sk_ta: str = type_args.get(sk_i)
        if sk_ta is not None:
            string.strcat(spec_key, sk_ta)
    string.strcat(spec_key, ">")
    cached: str = _find_cached_spec(spec_key)
    if cached is not None:
        return cached

    # 4. 检查是否已注册（Phase B 重复特化）
    existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name)
    if existing is not None:
        _cache_spec(pool, spec_key, spec_name)
        return spec_name

    # 预注册缓存（防止递归）
    _cache_spec(pool, spec_key, spec_name)

    # 5. 拷贝 ClassDef 节点
    tp_names: list[str] | t.CPtr = template_cd.type_params
    spec_cd: ast.ClassDef | t.CPtr = _clone_classdef_for_spec(
        pool, template_cd, spec_name, tp_names, type_args)
    if spec_cd is None:
        return None

    # 6. 设置 type_map 上下文（用于方法体中的 T 替换）
    trans.GenericTypeParamNames = tp_names
    trans.GenericTypeArgs = type_args
    HandlesType.set_generic_context(tp_names, type_args)

    # 7. 翻译特化类
    translate_class_def(trans, spec_cd)

    # 8. 清除 type_map 上下文
    trans.GenericTypeParamNames = None
    trans.GenericTypeArgs = None
    HandlesType.clear_generic_context()

    return spec_name


def translate_class_def(trans: HT.Translator | t.CPtr,
                        node: ast.AST | t.CPtr) -> int:
    """翻译 class 定义，返回 0"""
    if node is None or trans is None:
        return 0

    cd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(node)
    if cd is None or cd.name is None:
        return 0

    pool: memhub.MemBuddy | t.CPtr = trans.Pool
    class_name: str = cd.name

    # 命名空间隔离：标记为当前文件可见（必须在 existing 检查之前，
    # 因为 Phase B 时结构体已注册会提前 return，否则永远无法标记本地类）
    HandlesStruct.add_visible_struct(pool, class_name)

    # 枚举类：交给 HandlesEnum 处理
    if _is_enum_class(cd) == 1:
        return _translate_enum_def(trans, cd)

    # 联合体类：交给联合体处理
    if _is_union_class(cd) == 1:
        return _translate_union_def(trans, cd)

    # 泛型类：存储为模板，不发射 IR（等实例化时特化）
    if _is_generic_class(cd) == 1:
        _register_generic_template(pool, cd)
        return 0

    # 检查是否已注册（用 SHA1 区分跨模块同名类）
    existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
        class_name, trans.ModuleSha1)
    if existing is not None:
        # 结构体已注册（Phase B 重新翻译），但仍需在当前模块中翻译方法
        if existing.Ty is not None:
            # Phase B: 将已存在的命名结构体注册到当前模块（输出类型定义行）
            llvmlite.module_add_named_type(trans.Module, pool, existing.Ty)
            _translate_oop_methods(trans, cd, existing.Ty, class_name)
        # SHA1 已在 register_struct 时设置，无需再补
        return 0

    # ============================================================
    # VTable 检测：判断是否启用虚表
    # ============================================================
    has_vtable: int = _detect_vtable_status(cd, trans)
    parent_name: str = _get_parent_class(cd)
    is_novtable_deco: int = 0
    if cd.decorator_list is not None:
        if _has_decorator(cd.decorator_list, "NoVTable") == 1:
            is_novtable_deco = 1

    # ============================================================
    # 1. 遍历 class body，收集字段信息
    # ============================================================
    # 用 CSizeT 数组存储指针值（64 位系统上 8 字节）
    field_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
    field_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
    field_defaults_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
    field_annot_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
    if field_names_buf is None or field_types_buf is None or field_defaults_buf is None:
        return 0
    if field_annot_buf is None:
        return 0
    string.memset(field_names_buf, 0, 8 * 32)
    string.memset(field_types_buf, 0, 8 * 32)
    string.memset(field_defaults_buf, 0, 8 * 32)
    string.memset(field_annot_buf, 0, 8 * 32)

    field_count: int = 0

    # ============================================================
    # 1.5 继承父类字段（字段展平）
    #
    # 父类字段排在子类字段之前，结构体布局:
    #   [vtable_ptr?, parent_field1, ..., child_field1, ...]
    # 跳过父类的 __vtable__ 字段（子类会有自己的 vtable 指针）
    # ============================================================
    if parent_name is not None:
        # 用 SHA1 感知查找父类，规避跨模块同名找错
        parent_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
            parent_name, trans.ModuleSha1)
        if parent_entry is not None:
            pfc: int = parent_entry.FieldCount
            for pfi in range(pfc):
                pfe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry(
                    parent_entry, pfi)
                if pfe is None:
                    continue
                pfn: str = HandlesStruct.get_field_name_ptr(pfe)
                if pfn is None:
                    continue
                # 跳过父类的 vtable 指针字段
                if string.strcmp(pfn, "__vtable__") == 0:
                    continue
                if field_count < 32:
                    pft: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_field_type_ptr(pfe)
                    pfd: ast.AST | t.CPtr = HandlesStruct.get_field_default_ptr(pfe)
                    pfa: str = HandlesStruct.get_field_annot_class_name(pfe)
                    field_names_buf[field_count] = t.CSizeT(pfn)
                    field_types_buf[field_count] = t.CSizeT(pft)
                    if pfd is not None:
                        field_defaults_buf[field_count] = t.CSizeT(pfd)
                    else:
                        field_defaults_buf[field_count] = 0
                    if pfa is not None:
                        stored_val: t.CSizeT = t.CSizeT(pfa)
                        field_annot_buf[field_count] = stored_val
                    else:
                        field_annot_buf[field_count] = 0
                    field_count += 1

    children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
    if children is None:
        return 0

    cn: t.CSizeT = children.__len__()
    for ci in range(cn):
        stmt: ast.AST | t.CPtr = children.get(ci)
        if stmt is None:
            continue
        sk: int = stmt.kind()

        if sk != ast.ASTKind.AnnAssign: continue

        # AnnAssign(target=Name(id), annotation=type, value=...)
        aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(stmt)
        if aa is None or aa.target is None:
            continue

        # 获取字段名
        if aa.target.kind() != ast.ASTKind.Name:
            continue
        tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
        if tgt.id is None:
            continue

        # 跳过编译期元数据字段（__provides__/__requires__/__require_must__）
        # 这些字段只用于 with 上下文的静态可达性检查，不生成运行时代码
        # 避免类体中 list 字面量翻译失败（类体无 pool 变量上下文）
        if string.strcmp(tgt.id, "__provides__") == 0:
            continue
        if string.strcmp(tgt.id, "__requires__") == 0:
            continue
        if string.strcmp(tgt.id, "__require_must__") == 0:
            continue

        # 解析字段类型
        field_ty: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
            pool, aa.annotation, trans._imported_modules, trans._from_imports)
        if field_ty is None:
            field_ty = llvmlite.Int32(pool)

        # 存储到数组（指针转 CSizeT）
        if field_count < 32:
            diag_name_val: t.CSizeT = t.CSizeT(tgt.id)
            field_names_buf[field_count] = diag_name_val
            field_types_buf[field_count] = t.CSizeT(field_ty)
            # 存储默认值 AST 指针（None=无默认值）
            if aa.value is not None:
                field_defaults_buf[field_count] = t.CSizeT(aa.value)
            else:
                field_defaults_buf[field_count] = 0
            # 提取原始类型注解的类名（联合类型简化为 Ptr(i8) 时回退查找结构体）
            if aa.annotation is not None:
                annot_cn: str = HandlesType.extract_class_name_from_annotation(
                    aa.annotation, trans._imported_modules)
                if annot_cn is not None:
                    diag_cn_val: t.CSizeT = t.CSizeT(annot_cn)
                    field_annot_buf[field_count] = diag_cn_val
                else:
                    field_annot_buf[field_count] = 0
            else:
                field_annot_buf[field_count] = 0
            field_count += 1

    if field_count == 0:
        stdio.printf("[CLASS] %s has no fields\n", class_name)
        return 0

    # ============================================================
    # 2. 创建 LLVM StructType
    # ============================================================
    # 构建 ParamNode 链表
    first_node: llvmlite.ParamNode | t.CPtr = None
    prev_node: llvmlite.ParamNode | t.CPtr = None
    total_field_count: int = field_count

    # 如果有虚表，首字段添加 i8* vtable 指针
    if has_vtable == 1:
        i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool))
        vtable_node: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__())
        if vtable_node is None:
            stdio.printf("[CLASS] failed to alloc vtable node for %s\n", class_name)
            return 0
        string.memset(vtable_node, 0, llvmlite.ParamNode.__sizeof__())
        vtable_node.Ty = i8_ptr_ty
        first_node = vtable_node
        prev_node = vtable_node
        total_field_count = field_count + 1

    for fi in range(field_count):
        fty_addr: t.CSizeT = field_types_buf[fi]
        if fty_addr == 0:
            continue
        fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr, t.CPtr))

        # 创建 ParamNode
        pnode: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__())
        if pnode is None:
            continue
        string.memset(pnode, 0, llvmlite.ParamNode.__sizeof__())
        pnode.Ty = fty

        if first_node is None:
            first_node = pnode
        if prev_node is not None:
            prev_node.Next = pnode
        prev_node = pnode

    # 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName"
    type_name: str = class_name
    if trans.ModuleSha1 is not None:
        name_buf: t.CChar | t.CPtr = pool.alloc(64)
        if name_buf is not None:
            viperlib.snprintf(name_buf, 64, "%s.%s", trans.ModuleSha1, class_name)
            type_name = name_buf

    # 创建 StructType（命名结构体）
    struct_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, first_node, total_field_count, type_name)
    if struct_ty is None:
        stdio.printf("[CLASS] failed to create StructType for %s\n", class_name)
        return 0

    # 注册命名结构体到模块（输出 %"name" = type { ... } 定义行）
    llvmlite.module_add_named_type(trans.Module, pool, struct_ty)

    # 扫描字段类型，为跨模块结构体引用添加 opaque 声明
    # 例如 list[int].__pool__ 引用 memhub.MemManager，需要在当前模块添加 %"sha1.MemManager" = type opaque
    for fi in range(field_count):
        fty_addr_op: t.CSizeT = field_types_buf[fi]
        if fty_addr_op == 0:
            continue
        fty_op: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr_op, t.CPtr))
        llvmlite.module_ensure_opaque_for_type(trans.Module, pool, fty_op)

    # ============================================================
    # 3. 注册到 HandlesStruct
    # ============================================================
    entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.register_struct(
        pool, class_name, struct_ty, trans.ModuleSha1)
    if entry is None:
        stdio.printf("[CLASS] failed to register %s\n", class_name)
        return 0

    # 标记 VTable 状态（直接用 entry，规避跨模块同名 find_struct 找错）
    if has_vtable == 1:
        entry.HasVTable = 1
    if is_novtable_deco == 1:
        entry.IsNoVTable = 1
    if parent_name is not None:
        entry.ParentName = parent_name

    # 添加字段信息
    # 如果有虚表，先添加 __vtable__ 字段占位（索引 0），用户字段从索引 1 开始
    if has_vtable == 1:
        i8_ptr_ty2: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool))
        HandlesStruct.add_field(pool, entry, "__vtable__", i8_ptr_ty2, None, None)

    for fi in range(field_count):
        fname_addr: t.CSizeT = field_names_buf[fi]
        if fname_addr == 0:
            continue
        fname: str = (str | t.CPtr)(t.CVoid(fname_addr, t.CPtr))
        fty_addr2: t.CSizeT = field_types_buf[fi]
        if fty_addr2 == 0:
            continue
        fty2: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr2, t.CPtr))
        # 恢复默认值 AST 指针
        fdef_addr: t.CSizeT = field_defaults_buf[fi]
        fdef: ast.AST | t.CPtr = None
        if fdef_addr != 0:
            fdef = (ast.AST | t.CPtr)(t.CVoid(fdef_addr, t.CPtr))
        # 恢复注解类名指针
        fannot_addr: t.CSizeT = field_annot_buf[fi]
        fannot: t.CChar | t.CPtr = None
        if fannot_addr != 0:
            fannot = (t.CChar | t.CPtr)(t.CVoid(fannot_addr, t.CPtr))
        if fname is not None and fty2 is not None:
            HandlesStruct.add_field(pool, entry, fname, fty2, fdef, fannot)

    stdio.printf("[CLASS] registered %s with %d fields (vtable=%d)\n",
                 class_name, field_count, has_vtable)

    # Phase 1a 声明模式：只注册 struct，不翻译方法体
    if trans._declare_only == 1:
        return 0

    # ============================================================
    # 4. OOP 方法处理：扫描 FunctionDef，标记 OOP，翻译方法，生成 __before_init__
    # ============================================================
    _translate_oop_methods(trans, cd, struct_ty, class_name)

    return 0


# ============================================================
# VTable 生成
#
# 生成 VTable 全局变量:
#   @"SHA1.ClassName.vtable" = internal constant { i8*, i8*, ... } {
#       i8* bitcast (ret (params)* @"SHA1.ClassName.method1" to i8*),
#       ...
#   }
#
# VTable 槽位顺序: class body 中 FunctionDef 的出现顺序
# ============================================================

VTBL_METHOD_MAX: t.CDefine = 32


# _vtable_strcat — 将 src 追加到 dst 末尾
def _vtable_strcat(dst: t.CChar | t.CPtr, dst_size: t.CSizeT,
                   src: t.CChar | t.CPtr):
    """将 src 追加到 dst 末尾"""
    if dst is None or src is None:
        return
    dlen: t.CSizeT = string.strlen(dst)
    slen: t.CSizeT = string.strlen(src)
    remain: t.CSizeT = dst_size - dlen
    if remain <= 0:
        return
    i: t.CSizeT = 0
    while i < slen and i + 1 < remain:
        dst[dlen + i] = src[i]
        i += 1
    dst[dlen + i] = '\0'


# _vtable_name_needs_quote — 检查 LLVM 标识符是否需要引号
def _vtable_name_needs_quote(name: str) -> int:
    """检查 LLVM 标识符是否需要引号（以数字开头或含 '.'）"""
    if name is None:
        return 0
    if '0' <= name[0] <= '9':
        return 1
    for i in name:
        if i == '.':
            return 1
    return 0


# _format_func_type_str — 从 Function 对象生成函数类型字符串
#
# 格式: ret_ty (param1_ty, param2_ty, ...)
# 例如: void ({i32, i32}*, i32)
def _format_func_type_str(pool: memhub.MemBuddy | t.CPtr,
                          buf: t.CChar | t.CPtr, buf_size: t.CSizeT,
                          func: llvmlite.Function | t.CPtr) -> int:
    """从 Function 对象生成函数类型字符串"""
    if buf is None or func is None or buf_size == 0:
        return 0
    buf[0] = '\0'

    # 打印返回类型（使用访问器函数避免跨模块直接字段访问）
    ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(func)
    ret_buf: t.CChar | t.CPtr = pool.alloc(128)
    if ret_buf is not None and ret_ty is not None:
        ret_buf[0] = '\0'
        llvmlite.TypePrint(ret_buf, 128, ret_ty, pool)
        _vtable_strcat(buf, buf_size, ret_buf)
    _vtable_strcat(buf, buf_size, " (")

    # 遍历参数（使用访问器函数避免跨模块直接字段访问）
    cur: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(func)
    first: int = 1
    param_buf: t.CChar | t.CPtr = pool.alloc(128)
    while cur is not None:
        if first == 0:
            _vtable_strcat(buf, buf_size, ", ")
        if param_buf is not None:
            param_buf[0] = '\0'
            param_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(cur)
            if param_ty is not None:
                llvmlite.TypePrint(param_buf, 128, param_ty, pool)
                _vtable_strcat(buf, buf_size, param_buf)
        cur = llvmlite.param_get_next(cur)
        first = 0
    _vtable_strcat(buf, buf_size, ")")
    return 1


# _generate_vtable — 生成 VTable 全局变量
#
# 1. 收集 class body 中所有 FunctionDef 作为虚方法
# 2. 构造 VTable 类型 { i8*, i8*, ... }
# 3. 构造初始化字符串 { i8* bitcast (...), ... }
# 4. 创建全局变量 @"SHA1.ClassName.vtable"
# 5. 存储虚方法名列表到 StructEntry
def _generate_vtable(trans: HT.Translator | t.CPtr,
                     cd: ast.ClassDef | t.CPtr,
                     class_name: str) -> int:
    """生成 VTable 全局变量"""
    if trans is None or cd is None or class_name is None:
        return 0

    # 懒导入
    import lib.core.Handles.HandlesFunctions as HandlesFunctions
    import lib.core.Handles.HandlesExprCall as HandlesExprCall

    pool: memhub.MemBuddy | t.CPtr = trans.Pool
    mod: llvmlite.LLVMModule | t.CPtr = trans.Module

    children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
    if children is None:
        return 0
    cn: t.CSizeT = children.__len__()

    # 1. 收集虚方法信息
    full_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * VTBL_METHOD_MAX)
    method_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * VTBL_METHOD_MAX)
    # 记录每个方法的父类 SHA1（非 0=继承方法用父模块 SHA1 mangling，0=当前类方法）
    method_parent_sha1s: t.CSizeT | t.CPtr = pool.alloc(8 * VTBL_METHOD_MAX)
    if full_names_buf is None or method_names_buf is None or method_parent_sha1s is None:
        return 0
    string.memset(full_names_buf, 0, 8 * VTBL_METHOD_MAX)
    string.memset(method_names_buf, 0, 8 * VTBL_METHOD_MAX)
    string.memset(method_parent_sha1s, 0, 8 * VTBL_METHOD_MAX)

    method_count: int = 0

    # ============================================================
    # 1.5 继承父类虚方法
    #
    # 父类虚方法排在子类虚方法之前，保持 vtable 槽位顺序一致。
    # 如果子类覆盖了方法，full_name 用子类的；否则用父类的。
    # 用 SHA1 感知查找，规避跨模块同名 find_struct 找错
    # ============================================================
    vt_self_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
        class_name, trans.ModuleSha1)
    parent_name: str = None
    if vt_self_entry is not None:
        parent_name = vt_self_entry.ParentName
    if parent_name is not None:
        # 查找父类 entry（优先同模块 SHA1 匹配）
        vt_parent_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
            parent_name, trans.ModuleSha1)
        if vt_parent_entry is None:
            # 跨模块继承: 父类在不同模块定义（SHA1 不同），回退到按类名查找
            vt_parent_entry = HandlesStruct.find_struct(parent_name)
        parent_vt_count: int = 0
        if vt_parent_entry is not None:
            parent_vt_count = vt_parent_entry.VTableMethodCount
        if parent_vt_count > 0:
            for pvi in range(parent_vt_count):
                if method_count >= VTBL_METHOD_MAX:
                    break
                pmethod_name: str = None
                if vt_parent_entry is not None:
                    pmethod_name = HandlesStruct.get_vtable_method_name(parent_name, pvi)
                if pmethod_name is None:
                    continue
                # 检查子类是否覆盖了该方法，以及是否标记 @t.NoVTable
                child_overrides: int = 0
                child_nvt: int = 0
                for ci2 in range(cn):
                    stmt2: ast.AST | t.CPtr = children.get(ci2)
                    if stmt2 is None:
                        continue
                    if stmt2.kind() != ast.ASTKind.FunctionDef:
                        continue
                    fd2: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt2)
                    if fd2 is not None and fd2.name is not None:
                        if string.strcmp(fd2.name, pmethod_name) == 0:
                            child_overrides = 1
                            # 检查子类覆盖方法是否标记 @t.NoVTable
                            if fd2.decorator_list is not None:
                                if _has_decorator(fd2.decorator_list, "NoVTable") == 1:
                                    child_nvt = 1
                            break
                # 构造 full_name
                # 子类覆盖且未标记 NoVTable → 用子类实现
                # 子类未覆盖 或 子类覆盖但标记 NoVTable → 用父类实现（保持 vtable 槽位）
                pfname_buf: t.CChar | t.CPtr = pool.alloc(128)
                if pfname_buf is not None:
                    if child_overrides == 1 and child_nvt == 0:
                        viperlib.snprintf(pfname_buf, 128, "%s.%s", class_name, pmethod_name)
                    else:
                        viperlib.snprintf(pfname_buf, 128, "%s.%s", parent_name, pmethod_name)
                    full_names_buf[method_count] = t.CSizeT(pfname_buf)
                # 复制方法名（短名）
                pmname_len: t.CSizeT = string.strlen(pmethod_name)
                pmname_buf: t.CChar | t.CPtr = pool.alloc(pmname_len + 1)
                if pmname_buf is not None:
                    string.strcpy(pmname_buf, pmethod_name)
                    method_names_buf[method_count] = t.CSizeT(pmname_buf)
                # 记录 mangling 用的 SHA1（继承未覆盖的方法用父模块 SHA1）
                if child_overrides == 1 and child_nvt == 0:
                    # 子类覆盖: 用当前模块 SHA1（保持 0）
                    method_parent_sha1s[method_count] = 0
                else:
                    # 继承未覆盖: 用父类模块 SHA1
                    if vt_parent_entry is not None and vt_parent_entry.ModuleSha1 is not None:
                        method_parent_sha1s[method_count] = t.CSizeT(vt_parent_entry.ModuleSha1)
                method_count += 1

    # 2. 收集当前类的虚方法（跳过已从父类继承的）
    for ci in range(cn):
        stmt: ast.AST | t.CPtr = children.get(ci)
        if stmt is None:
            continue
        if stmt.kind() != ast.ASTKind.FunctionDef:
            continue
        fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt)
        if fd is None or fd.name is None:
            continue
        if method_count >= VTBL_METHOD_MAX:
            break

        mname: str = fd.name
        # 跳过构造函数和特殊方法（不应放入虚表）
        if string.strcmp(mname, "__init__") == 0:
            continue
        if string.strcmp(mname, "__before_init__") == 0:
            continue
        if string.strcmp(mname, "__new__") == 0:
            continue
        # 函数级装饰器过滤：判断方法是否应该进入虚表
        if _should_method_be_virtual(cd, fd, trans) == 0:
            continue
        # 检查是否已从父类继承（避免重复）
        already_in_vt: int = 0
        for mi in range(method_count):
            exist_addr: t.CSizeT = method_names_buf[mi]
            if exist_addr != 0:
                exist_name: str = (str | t.CPtr)(t.CVoid(exist_addr, t.CPtr))
                if exist_name is not None and string.strcmp(exist_name, mname) == 0:
                    already_in_vt = 1
                    break
        if already_in_vt == 1:
            continue
        # 构造 full_name = "ClassName.method_name"
        fname_buf: t.CChar | t.CPtr = pool.alloc(128)
        if fname_buf is not None:
            viperlib.snprintf(fname_buf, 128, "%s.%s", class_name, mname)
            full_names_buf[method_count] = t.CSizeT(fname_buf)

        # 复制方法名
        mname_len: t.CSizeT = string.strlen(mname)
        mname_buf: t.CChar | t.CPtr = pool.alloc(mname_len + 1)
        if mname_buf is not None:
            string.strcpy(mname_buf, mname)
            method_names_buf[method_count] = t.CSizeT(mname_buf)

        method_count += 1

    if method_count == 0:
        return 0

    # 2. 构造 VTable 类型: { i8*, i8*, ..., i8* }
    i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
    i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)

    first_node: llvmlite.ParamNode | t.CPtr = None
    tail_node: llvmlite.ParamNode | t.CPtr = None
    for i in range(method_count):
        pnode: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, i8_ptr_ty)
        if pnode is None:
            continue
        tail_node = llvmlite.param_list_append(first_node, tail_node, pnode)
        if first_node is None:
            first_node = tail_node

    vtable_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, first_node, method_count, None)
    if vtable_ty is None:
        return 0

    # 3. 构造初始化字符串
    init_buf: t.CChar | t.CPtr = pool.alloc(4096)
    if init_buf is None:
        return 0
    init_buf[0] = '\0'
    _vtable_strcat(init_buf, 4096, "{ ")

    for i in range(method_count):
        if i > 0:
            _vtable_strcat(init_buf, 4096, ", ")

        full_name_addr: t.CSizeT = full_names_buf[i]
        if full_name_addr == 0:
            _vtable_strcat(init_buf, 4096, "i8* null")
            continue

        full_name: str = (str | t.CPtr)(t.CVoid(full_name_addr, t.CPtr))

        # 检查是否是继承方法（method_parent_sha1s 非 0 表示用父模块 SHA1 mangling）
        parent_sha1_addr: t.CSizeT = method_parent_sha1s[i]
        if parent_sha1_addr != 0:
            # 继承方法: 用父类模块 SHA1 做 mangling
            parent_sha1: str = (str | t.CPtr)(t.CVoid(parent_sha1_addr, t.CPtr))
            mangled_name: str = HandlesFunctions._mangle_name_with_sha1(parent_sha1, full_name)
            # 从全局函数表查找（跨模块函数不在当前模块表中）
            func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_global(full_name)
        else:
            # 当前类方法: 用当前模块 SHA1
            mangled_name: str = HandlesFunctions._mangle_name(trans, full_name)
            func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_table(
                trans._funcs, trans._func_count, full_name)
            # 当前模块表找不到时，回退到全局表
            if func is None:
                func = HandlesExprCall.find_func_global(full_name)

        if func is None:
            _vtable_strcat(init_buf, 4096, "i8* null")
            continue

        # 构造函数类型字符串
        func_ty_buf: t.CChar | t.CPtr = pool.alloc(512)
        if func_ty_buf is None:
            _vtable_strcat(init_buf, 4096, "i8* null")
            continue
        _format_func_type_str(pool, func_ty_buf, 512, func)

        # 构造 bitcast 字符串: i8* bitcast (func_ty* @mangled to i8*)
        _vtable_strcat(init_buf, 4096, "i8* bitcast (")
        _vtable_strcat(init_buf, 4096, func_ty_buf)
        _vtable_strcat(init_buf, 4096, "* @")

        if _vtable_name_needs_quote(mangled_name) != 0:
            _vtable_strcat(init_buf, 4096, "\"")
            _vtable_strcat(init_buf, 4096, mangled_name)
            _vtable_strcat(init_buf, 4096, "\"")
        else:
            _vtable_strcat(init_buf, 4096, mangled_name)
        _vtable_strcat(init_buf, 4096, " to i8*)")

    _vtable_strcat(init_buf, 4096, " }")

    # 4. 构造 VTable 全局变量名
    vtable_name_buf: t.CChar | t.CPtr = pool.alloc(128)
    if vtable_name_buf is None:
        return 0
    viperlib.snprintf(vtable_name_buf, 128, "%s.vtable", class_name)
    vtable_mangled: str = HandlesFunctions._mangle_name(trans, vtable_name_buf)

    # 5. 创建全局变量
    gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(
        pool, vtable_mangled, vtable_ty)
    if gv is None:
        return 0
    gv.Initializer = init_buf
    gv.IsConstant = 1
    gv.Linkage = "internal"

    # 添加到模块
    llvmlite.module_add_global(mod, gv)

    # 6. 存储虚方法名列表到 StructEntry（直接用 entry，规避跨模块同名 find_struct 找错）
    if vt_self_entry is not None:
        vt_self_entry.VTableMethods = method_names_buf
        vt_self_entry.VTableMethodCount = method_count

    stdio.printf("[VTABLE] generated vtable for %s with %d methods\n",
                 class_name, method_count)
    return 0


# ============================================================
# OOP 方法翻译
#
# 存在任意 FunctionDef 的 class 自动升级为 OOP 结构体。
# 方法翻译为 SHA1.ClassName.method_name(self: Ptr(StructTy), ...) 函数。
# self 参数直接注册为 SSA 值（不创建 alloca），使 self.field 能通过 GEP 直接访问。
# ============================================================


# ============================================================
# _translate_oop_methods — 扫描 class body 中的方法并翻译
#
# 遍历 ClassDef.children，对每个 FunctionDef:
#   - 标记 OOP（mark_as_oop）
#   - 如果是 __init__，标记 has_init
#   - 翻译方法（生成 SHA1.ClassName.method_name 函数）
# 翻译完所有方法后，生成 __before_init__ 函数
# ============================================================
def _translate_oop_methods(trans: HT.Translator | t.CPtr,
                           cd: ast.ClassDef | t.CPtr,
                           struct_ty: llvmlite.LLVMType | t.CPtr,
                           class_name: str) -> int:
    """扫描 class body 中的方法并翻译，生成 __before_init__"""
    if trans is None or cd is None or struct_ty is None or class_name is None:
        return 0

    children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
    if children is None:
        return 0

    cn: t.CSizeT = children.__len__()
    has_method: int = 0
    has_init: int = 0
    has_new: int = 0

    # 提前用类型指针定位 entry（规避跨模块同名类 find_struct 找错）
    oop_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty)

    # 第一遍：检测是否有方法，标记 OOP
    for ci in range(cn):
        stmt: ast.AST | t.CPtr = children.get(ci)
        if stmt is None:
            continue
        if stmt.kind() == ast.ASTKind.FunctionDef:
            has_method = 1
            fd_check: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt)
            if fd_check is not None and fd_check.name is not None:
                if string.strcmp(fd_check.name, "__init__") == 0:
                    has_init = 1
                if string.strcmp(fd_check.name, "__new__") == 0:
                    has_new = 1

    if has_method == 0:
        # 子类没有自己的方法，但可能继承了父类的虚方法
        # 用 oop_entry 直接获取 ParentName，规避 find_struct 按名查找找错
        parent_name: str = None
        if oop_entry is not None:
            parent_name = oop_entry.ParentName
        if parent_name is not None:
            parent_vt_count: int = HandlesStruct.get_vtable_method_count(parent_name)
            if parent_vt_count > 0:
                has_method = 1  # 标记为有方法（继承的虚方法）
        if has_method == 0:
            return 0

    # 标记为 OOP 结构体
    if oop_entry is not None:
        oop_entry.IsOOP = 1
        if has_init != 0:
            oop_entry.HasInit = 1
        if has_new != 0:
            oop_entry.HasNew = 1

    # 第二遍：翻译每个方法
    for ci in range(cn):
        stmt: ast.AST | t.CPtr = children.get(ci)
        if stmt is None:
            continue
        if stmt.kind() == ast.ASTKind.FunctionDef:
            fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt)
            if fd is not None and fd.name is not None:
                _translate_method(trans, fd, struct_ty, class_name)

    # 如果有虚表，先生成 VTable 全局变量（设置 VTableMethodCount）
    # 必须在 __before_init__ 之前，否则 __before_init__ 读不到 VTableMethodCount
    # 用 oop_entry 直接检查，规避跨模块同名 find_struct 找错
    has_vt_flag: int = 0
    if oop_entry is not None:
        has_vt_flag = oop_entry.HasVTable
    if has_vt_flag == 1:
        _generate_vtable(trans, cd, class_name)

    # 生成 __before_init__ 函数（零值填充 + 默认值赋值 + vtable 指针设置）
    _generate_before_init(trans, struct_ty, class_name)

    return 0


# ============================================================
# _translate_method — 翻译单个方法
#
# 生成: define <ret_ty> @SHA1.ClassName.method_name(Ptr(StructTy) %self, ...)
#
# self 参数处理：
#   - 类型 Ptr(struct_ty)，直接注册为 SSA 值（不创建 alloca）
#   - 使 self.field 能通过 GEP 直接访问原始结构体
# ============================================================
def _translate_method(trans: HT.Translator | t.CPtr,
                      fd: ast.FunctionDef | t.CPtr,
                      struct_ty: llvmlite.LLVMType | t.CPtr,
                      class_name: str) -> int:
    """翻译单个方法，返回 0"""
    if trans is None or fd is None or struct_ty is None or class_name is None:
        return 0

    # 懒导入
    import lib.core.Handles.HandlesFunctions as HandlesFunctions
    import lib.core.Handles.HandlesVar as HandlesVar
    import lib.core.Handles.HandlesBody as HandlesBody
    import lib.core.Handles.HandlesType as HandlesType
    import lib.core.Handles.HandlesExprCall as HandlesExprCall

    pool: memhub.MemBuddy | t.CPtr = trans.Pool
    mod: llvmlite.LLVMModule | t.CPtr = trans.Module
    imported_modules: str = trans._imported_modules
    from_imports: str = trans._from_imports
    funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs
    func_count: int = trans._func_count

    i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
    self_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty)

    method_name: str = fd.name

    # 构建方法全名: ClassName.method_name
    full_name_buf: t.CChar | t.CPtr = pool.alloc(128)
    if full_name_buf is None:
        return 0
    viperlib.snprintf(full_name_buf, 128, "%s.%s", class_name, method_name)
    full_name: str = full_name_buf

    # SHA1 命名空间混淆
    mangled_name: str = HandlesFunctions._mangle_name(trans, full_name)

    # 推断返回类型
    ret_ty: llvmlite.LLVMType | t.CPtr = None
    if fd.returns is not None:
        ret_ty = HandlesType.resolve_annotation_type(
            pool, fd.returns, imported_modules, from_imports)
    if ret_ty is None and fd.returns is not None:
        if HandlesType.has_decorator_marker(fd.returns, "State") != 0:
            ret_ty = llvmlite.Void(pool)
    if ret_ty is None:
        # __init__ 和 __before_init__ 返回 void
        if string.strcmp(method_name, "__init__") == 0:
            ret_ty = llvmlite.Void(pool)
        # __new__ 返回 Ptr(struct_ty)（结构体指针作为存储空间）
        elif string.strcmp(method_name, "__new__") == 0:
            ret_ty = llvmlite.Ptr(pool, struct_ty)
        else:
            param_types_str: str = HandlesType.build_param_types_str(pool, fd.args)
            ret_ty = HandlesType.infer_return_type(
                pool, fd.children, param_types_str)

    # 创建 LLVM 函数
    func: llvmlite.Function | t.CPtr = llvmlite.create_function(
        pool, mod, mangled_name, ret_ty)
    if func is None:
        return 0

    # 注册到函数表（用 ClassName.method_name 作为查找名，支持后缀匹配）
    max_funcs: int = 256
    if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, full_name, func, max_funcs) == 0:
        trans._func_count = func_count + 1

    # 添加 self 参数（Ptr(struct_ty)）
    llvmlite.add_param(pool, func, self_ptr_ty, "%self")

    # 添加其他参数（支持类型注解，跳过索引 0 的 self 参数）
    args_node: ast.Arguments | t.CPtr = fd.args
    if args_node is not None:
        ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
        if ags.args is not None:
            alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args
            an: t.CSizeT = alist.__len__()
            for ai in range(1, an):
                arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai))
                if arg is not None and arg.arg is not None:
                    param_ty: llvmlite.LLVMType | t.CPtr = i32_ty
                    if arg.annotation is not None:
                        resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
                            pool, arg.annotation, imported_modules, from_imports)
                        if resolved is not None:
                            param_ty = resolved
                    pname: t.CChar | t.CPtr = pool.alloc(32)
                    if pname is not None:
                        viperlib.snprintf(pname, 32, "%%%s", arg.arg)
                    llvmlite.add_param(pool, func, param_ty, pname)

    # 创建 entry 块
    entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry")
    if entry_blk is None:
        return 0

    # 创建方法专属 builder
    func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func)
    if func_builder is None:
        return 0
    llvmlite.position_at_end(func_builder, entry_blk)

    # 进入函数作用域
    HandlesVar.enter_scope(trans.SymTab, HandlesVar.SCOPE_FUNCTION)

    # 注册 self 为 SSA 值（不创建 alloca，不 store）
    # 这样 self.field 通过 lookup_var 获取 Ptr(struct_ty) 后直接 GEP
    self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, "%self")
    HandlesVar.define_var(trans.SymTab, "self", self_val)
    # 设置 self 的类型注解类名（属性访问 lookup_field 回退查找用）
    HandlesVar.set_var_annot_class_name(trans.SymTab, "self", class_name)

    # 为其他参数创建 alloca 并 store（与普通函数一致，跳过索引 0 的 self 参数）
    if args_node is not None:
        ags2: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
        if ags2.args is not None:
            alist2: list[ast.AST | t.CPtr] | t.CPtr = ags2.args
            an2: t.CSizeT = alist2.__len__()
            for ai2 in range(1, an2):
                arg2: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist2.get(ai2))
                if arg2 is not None and arg2.arg is not None:
                    param_ty2: llvmlite.LLVMType | t.CPtr = i32_ty
                    if arg2.annotation is not None:
                        resolved2: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
                            pool, arg2.annotation, imported_modules, from_imports)
                        if resolved2 is not None:
                            param_ty2 = resolved2
                    alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, param_ty2)
                    if alloca is not None:
                        HandlesVar.define_var(trans.SymTab, arg2.arg, alloca)
                        # 存储原始类型注解的类名（方法调用检测时，Ptr(i8) 回退到类名查找结构体）
                        if arg2.annotation is not None:
                            cls_nm_oc: str = HandlesType.extract_class_name_from_annotation(
                                arg2.annotation, imported_modules)
                            if cls_nm_oc is not None:
                                HandlesVar.set_var_annot_class_name(
                                    trans.SymTab, arg2.arg, cls_nm_oc)
                        pname2: t.CChar | t.CPtr = pool.alloc(32)
                        if pname2 is not None:
                            viperlib.snprintf(pname2, 32, "%%%s", arg2.arg)
                        param_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(
                            pool, param_ty2, pname2)
                        llvmlite.build_store(func_builder, param_val, alloca)

    # 保存模块级作用域状态
    old_func: llvmlite.Function | t.CPtr = trans._cur_func
    old_builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
    old_global_count: int = trans._global_name_count
    old_nonlocal_count: int = trans._nonlocal_name_count
    old_env_count: int = trans._closure_env_count

    trans._cur_func = func
    trans._cur_builder = func_builder
    HT.clear_scope_names(trans)

    # 预扫描方法体：为局部变量提前创建 alloca
    body: list[ast.AST | t.CPtr] | t.CPtr = fd.children
    if body is not None:
        bn: t.CSizeT = body.__len__()
        for bi in range(bn):
            stmt: ast.AST | t.CPtr = body.get(bi)
            if stmt is not None:
                HandlesBody.pre_scan_allocas(trans, stmt)

    # 翻译方法体
    if body is not None:
        bn2: t.CSizeT = body.__len__()
        for bi2 in range(bn2):
            stmt2: ast.AST | t.CPtr = body.get(bi2)
            if stmt2 is not None:
                HandlesBody.translate_stmt(trans, stmt2)

    # 如果返回类型为 void，添加 ret void；否则添加隐式 ret 0
    is_void: int = 0
    if ret_ty is not None:
        match ret_ty:
            case llvmlite.LLVMType.Void():
                is_void = 1

    if is_void != 0:
        if llvmlite.builder_cur_block_is_terminated(func_builder) == 0:
            llvmlite.build_ret_void(func_builder)
    else:
        last_is_return: int = 0
        if body is not None:
            bn3: t.CSizeT = body.__len__()
            if bn3 > 0:
                last_stmt: ast.AST | t.CPtr = body.get(bn3 - 1)
                if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return:
                    last_is_return = 1
        if last_is_return == 0:
            if llvmlite.builder_cur_block_is_terminated(func_builder) == 0:
                # __new__ 返回指针类型，隐式返回 null 指针
                if string.strcmp(method_name, "__new__") == 0:
                    null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, ret_ty, "null")
                    llvmlite.build_ret(func_builder, null_val)
                else:
                    zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
                    llvmlite.build_ret(func_builder, zero_val)

    # 恢复模块级作用域
    HandlesVar.exit_scope(trans.SymTab)
    trans._cur_func = old_func
    trans._cur_builder = old_builder
    trans._global_name_count = old_global_count
    trans._nonlocal_name_count = old_nonlocal_count
    trans._closure_env_count = old_env_count

    return 0


# ============================================================
# _generate_before_init — 生成 __before_init__ 函数
#
# 生成: define void @SHA1.ClassName.__before_init__(Ptr(StructTy) %self)
#
# 执行:
#   1. store zeroinitializer 到 %self（零值填充）
#   2. 逐字段 store 默认值（如有）
#   3. ret void
# ============================================================
def _generate_before_init(trans: HT.Translator | t.CPtr,
                          struct_ty: llvmlite.LLVMType | t.CPtr,
                          class_name: str) -> int:
    """生成 __before_init__ 函数，返回 0"""
    if trans is None or struct_ty is None or class_name is None:
        return 0

    import lib.core.Handles.HandlesFunctions as HandlesFunctions
    import lib.core.Handles.HandlesVar as HandlesVar
    import lib.core.Handles.HandlesExpr as HandlesExpr
    import lib.core.Handles.HandlesExprCall as HandlesExprCall

    pool: memhub.MemBuddy | t.CPtr = trans.Pool
    mod: llvmlite.LLVMModule | t.CPtr = trans.Module
    funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs
    func_count: int = trans._func_count

    self_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty)
    void_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool)

    # 构建函数名: ClassName.__before_init__
    full_name_buf: t.CChar | t.CPtr = pool.alloc(128)
    if full_name_buf is None:
        return 0
    viperlib.snprintf(full_name_buf, 128, "%s.__before_init__", class_name)
    full_name: str = full_name_buf

    mangled_name: str = HandlesFunctions._mangle_name(trans, full_name)

    # 创建函数
    func: llvmlite.Function | t.CPtr = llvmlite.create_function(
        pool, mod, mangled_name, void_ty)
    if func is None:
        return 0

    # 注册到函数表
    max_funcs: int = 256
    if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, full_name, func, max_funcs) == 0:
        trans._func_count = func_count + 1

    # 添加 self 参数
    llvmlite.add_param(pool, func, self_ptr_ty, "%self")

    # 创建 entry 块 + builder
    entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry")
    if entry_blk is None:
        return 0
    func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func)
    if func_builder is None:
        return 0
    llvmlite.position_at_end(func_builder, entry_blk)

    # 注册 self 为 SSA 值
    self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, "%self")

    # 1. 零值填充: store zeroinitializer, Ptr(struct_ty)* %self
    zero: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, struct_ty)
    if zero is not None:
        llvmlite.build_store(func_builder, zero, self_val)

    # 1.5 如果有虚表，store vtable 全局地址到 __vtable__ 字段（索引 0）
    # 用 find_struct_by_type 定位 entry，规避跨模块同名 find_struct 找错
    bi_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty)
    bi_has_vt: int = 0
    if bi_entry is not None:
        bi_has_vt = bi_entry.HasVTable
    if bi_has_vt == 1:
        vt_method_count: int = 0
        if bi_entry is not None:
            vt_method_count = bi_entry.VTableMethodCount
        if vt_method_count > 0:
            # 构造 vtable 类型 { i8*, i8*, ..., i8* }
            vt_i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
            vt_i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, vt_i8_ty)

            vt_first_node: llvmlite.ParamNode | t.CPtr = None
            vt_prev_node: llvmlite.ParamNode | t.CPtr = None
            for vti in range(vt_method_count):
                vtnode: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, vt_i8_ptr_ty)
                if vtnode is None:
                    continue
                if vt_first_node is None:
                    vt_first_node = vtnode
                if vt_prev_node is not None:
                    llvmlite.paramnode_set_next(vt_prev_node, vtnode)
                vt_prev_node = vtnode

            vt_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, vt_first_node, vt_method_count, None)
            vt_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, vt_ty)

            # 构造 vtable 全局变量名
            vt_name_buf: t.CChar | t.CPtr = pool.alloc(128)
            if vt_name_buf is not None:
                viperlib.snprintf(vt_name_buf, 128, "%s.vtable", class_name)
                vt_full_name: str = vt_name_buf
                vt_mangled: str = HandlesFunctions._mangle_name(trans, vt_full_name)

                # GEP 到 __vtable__ 字段（索引 0）
                vt_slot: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
                    func_builder, struct_ty, vt_i8_ptr_ty, self_val, 0)
                if vt_slot is not None:
                    # 创建全局变量引用 Value
                    vt_ref: llvmlite.Value | t.CPtr = llvmlite.new_value(pool)
                    if vt_ref is not None:
                        llvmlite.value_set_ty(vt_ref, vt_ptr_ty)
                        llvmlite.value_set_isconst(vt_ref, 1)
                        # Name 格式: @"mangled" 或 @mangled
                        vt_ref_name: t.CChar | t.CPtr = pool.alloc(256)
                        if vt_ref_name is not None:
                            vt_ref_name[0] = '\0'
                            if _vtable_name_needs_quote(vt_mangled) != 0:
                                viperlib.snprintf(vt_ref_name, 256, "@\"%s\"", vt_mangled)
                            else:
                                viperlib.snprintf(vt_ref_name, 256, "@%s", vt_mangled)
                            llvmlite.value_set_name(vt_ref, vt_ref_name)

                        # bitcast 到 i8*
                        vt_as_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
                            func_builder, vt_ref, vt_i8_ptr_ty)
                        if vt_as_i8 is not None:
                            llvmlite.build_store(func_builder, vt_as_i8, vt_slot)

    # 2. 逐字段 store 默认值（用 bi_entry 直接访问，规避跨模块同名 find_struct 找错）
    if bi_entry is not None:
        for fi in range(bi_entry.FieldCount):
            fe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry(
                bi_entry, fi)
            if fe is None or fe.DefaultVal is None:
                continue
            # 翻译默认值表达式
            default_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
                func_builder, pool, mod, fe.DefaultVal, None, 0, trans)
            if default_val is None:
                continue
            # GEP 到字段
            field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
                func_builder, struct_ty, fe.Ty, self_val, fe.Index)
            if field_ptr is None:
                continue
            # 类型转换并 store
            default_val = HandlesExpr.coerce_to_type(func_builder, default_val, fe.Ty)
            llvmlite.build_store(func_builder, default_val, field_ptr)

    # 3. ret void
    llvmlite.build_ret_void(func_builder)

    return 0
