import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import sys
import stdlib
import viperlib
import w32.fileio as fileio
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesStruct as HandlesStruct


# ============================================================
# HandlesType - 类型映射与解析（模块级纯函数）
#
# str = bytes = t.CChar | t.CPtr = i8*
# ============================================================


# ============================================================
# 全局当前文件名（每个文件翻译前由 BuildPipeline 设置）
# ============================================================
_g_current_file: str = None


# ============================================================
# 全局泛型特化上下文（由 _specialize_generic_class 设置/清除）
#
# 当翻译泛型类方法体时，需要将类型参数 T 替换为具体类型。
# resolve_annotation_type 在解析 Name 节点时检查此上下文。
# ============================================================
_g_generic_tp_names: list[str] | t.CPtr = None
_g_generic_type_args: list[str] | t.CPtr = None


# ============================================================
# 全局 CDefine 编译期常量表
#
# 存储 NAME: t.CDefine = value 定义的常量，
# 供 t.CArray[elem_ty, NAME] 等 编译期类型解析使用。
# 每个模块翻译开始时由 clear_cdefine_constants 清空。
# ============================================================
_g_cdefine_names: list[str] | t.CPtr = None
_g_cdefine_values: list[str] | t.CPtr = None


def register_cdefine_constant(pool: memhub.MemBuddy | t.CPtr,
                              name: str, value: int) -> None:
    """注册 CDefine 编译期常量到全局表"""
    global _g_cdefine_names, _g_cdefine_values
    if _g_cdefine_names is None:
        _g_cdefine_names = list[str](pool, 64)
        _g_cdefine_values = list[str](pool, 64)
    _g_cdefine_names.append(name)
    val_buf: str = pool.alloc(32)
    if val_buf is not None:
        viperlib.snprintf(val_buf, 32, "%d", value)
        _g_cdefine_values.append(val_buf)
    else:
        _g_cdefine_values.append("0")


def lookup_cdefine_constant(name: str) -> int:
    """查找 CDefine 编译期常量，返回值或 -1（未找到）"""
    if _g_cdefine_names is None:
        return -1
    n: t.CSizeT = _g_cdefine_names.__len__()
    i: t.CSizeT
    for i in range(n):
        nm: str = _g_cdefine_names.get(i)
        if nm is not None and string.strcmp(nm, name) == 0:
            val_str: str = _g_cdefine_values.get(i)
            if val_str is not None:
                return string.atoi(val_str)
    return -1


def clear_cdefine_constants() -> None:
    """清空 CDefine 常量表（模块切换时调用）"""
    global _g_cdefine_names, _g_cdefine_values
    _g_cdefine_names = None
    _g_cdefine_values = None


def set_generic_context(tp_names: list[str] | t.CPtr,
                        type_args: list[str] | t.CPtr):
    """设置泛型特化上下文（进入泛型类方法体翻译时调用）"""
    global _g_generic_tp_names, _g_generic_type_args
    _g_generic_tp_names = tp_names
    _g_generic_type_args = type_args


def clear_generic_context():
    """清除泛型特化上下文（离开泛型类方法体翻译时调用）"""
    global _g_generic_tp_names, _g_generic_type_args
    _g_generic_tp_names = None
    _g_generic_type_args = None


def resolve_generic_type_name(name: str) -> str:
    """如果 name 是泛型类型参数，返回对应的具体类型名；否则返回 name 本身

    用于表达式中的 T 替换（如 T.__sizeof__() → int.__sizeof__()）
    """
    if name is None:
        return name
    if _g_generic_tp_names is not None and _g_generic_type_args is not None:
        rg_n: t.CSizeT = _g_generic_tp_names.__len__()
        rg_i: t.CSizeT
        for rg_i in range(rg_n):
            rg_tpn: str = _g_generic_tp_names.get(rg_i)
            if rg_tpn is not None and string.strcmp(name, rg_tpn) == 0:
                rg_ta: str = _g_generic_type_args.get(rg_i)
                if rg_ta is not None:
                    return rg_ta
    return name


# ============================================================
# _get_type_name_from_annotation - 从类型注解节点提取类型名字符串
#
# 用于泛型特化时构造 mangled name（如 "list[AST|t.CPtr]"）
#
# Name(id="AST") -> "AST"
# Attribute(value=Name(id="t"), attr="CPtr") -> "t.CPtr"
# BinOp(Name("AST"), BitOr, Attribute(Name("t"), "CPtr")) -> "AST|t.CPtr"
# ============================================================
def _get_type_name_from_annotation(pool: memhub.MemBuddy | t.CPtr,
                                   node: ast.AST | t.CPtr) -> str:
    """从类型注解节点提取类型名（支持 Name/Attribute/BinOp）"""
    if node is None:
        return None
    k: int = node.kind()
    # Constant: 字符串注解，直接返回字符串值
    if k == ast.ASTKind.Constant:
        cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
        if cn.const_kind == ast.CONST_STR and cn.str_val is not None:
            return cn.str_val
        return None
    # Name: 直接返回 id
    if k == ast.ASTKind.Name:
        nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
        return nm.id
    # Attribute: 构造 "module.attr" 格式
    if k == ast.ASTKind.Attribute:
        at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
        if at.attr is None:
            return None
        if at.value is not None and at.value.kind() == ast.ASTKind.Name:
            mod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
            if mod_nm.id is not None:
                total: t.CSizeT = string.strlen(mod_nm.id) + 1 + string.strlen(at.attr) + 1
                buf: str = pool.alloc(total)
                if buf is not None:
                    buf[0] = '\0'
                    string.strcat(buf, mod_nm.id)
                    string.strcat(buf, ".")
                    string.strcat(buf, at.attr)
                    return buf
        return at.attr
    # BinOp (BitOr): 构造 "left|right" 格式
    if k == ast.ASTKind.BinOp:
        bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
        if bop.op == ast.OpKind.BitOr:
            left_str: str = _get_type_name_from_annotation(pool, bop.left)
            right_str: str = _get_type_name_from_annotation(pool, bop.right)
            if left_str is not None and right_str is not None:
                total2: t.CSizeT = string.strlen(left_str) + 1 + string.strlen(right_str) + 1
                buf2: str = pool.alloc(total2)
                if buf2 is not None:
                    buf2[0] = '\0'
                    string.strcat(buf2, left_str)
                    string.strcat(buf2, "|")
                    string.strcat(buf2, right_str)
                    return buf2
        return None
    return None


# ============================================================
# _parse_type_string - 将类型名字符串解析回 AST 节点
#
# _get_type_name_from_annotation 的逆操作，用于泛型特化时
# 从 type_args 字符串重建 AST 节点（_clone_annotation 和
# resolve_annotation_type 的泛型上下文替换）
#
# "AST" -> Name("AST")
# "t.CPtr" -> Attribute(Name("t"), "CPtr")
# "AST|t.CPtr" -> BinOp(Name("AST"), BitOr, Attribute(Name("t"), "CPtr"))
# ============================================================
def _parse_type_string(pool: memhub.MemBuddy | t.CPtr,
                       type_str: str,
                       ctx: t.CInt) -> ast.AST | t.CPtr:
    """将类型名字符串解析为 AST 节点"""
    if type_str is None or pool is None:
        return None

    # 检查是否包含 | (BinOp)
    pipe_pos: str = string.strchr(type_str, 124)  # '|' = 124
    if pipe_pos is not None:
        # 临时将 | 替换为 \0，分割左右部分
        old_char: t.CInt = pipe_pos[0]
        pipe_pos[0] = 0
        left_node: ast.AST | t.CPtr = _parse_type_string(pool, type_str, ctx)
        right_str: str = pipe_pos + 1
        pipe_pos[0] = old_char
        right_node: ast.AST | t.CPtr = _parse_type_string(pool, right_str, ctx)
        if left_node is not None and right_node is not None:
            return ast.BinOp(pool, left_node, ast.OpKind.BitOr, right_node)
        return None

    # 检查是否包含 . (Attribute)
    dot_pos: str = string.strchr(type_str, 46)  # '.' = 46
    if dot_pos is not None:
        old_char2: t.CInt = dot_pos[0]
        dot_pos[0] = 0
        module_node: ast.AST | t.CPtr = ast.Name(pool, type_str, ctx)
        attr_str: str = dot_pos + 1
        dot_pos[0] = old_char2
        if module_node is not None:
            return ast.Attribute(pool, module_node, attr_str, ctx)
        return None

    # 普通 Name
    return ast.Name(pool, type_str, ctx)


# ============================================================
# set_current_file - 设置当前编译的文件名
#
# 在 BuildPipeline.TranslateFileGetTrans 中每翻译一个文件前调用
# ============================================================
def set_current_file(file_path: str):
    """设置当前编译的文件名（供报错使用）"""
    global _g_current_file
    _g_current_file = file_path


# ============================================================
# _read_source_line - 从源文件读取第 lineno 行
#
# 返回行内容字符串（不含换行符），失败返回 None
# ============================================================
_SRC_BUF_SIZE: t.CDefine = 262144

def _read_source_line(file_path: str, lineno: int) -> str:
    """从源文件读取第 lineno 行内容"""
    if file_path is None or lineno <= 0:
        return None
    f: fileio.File | t.CPtr = fileio.File(file_path, fileio.MODE.R)
    if f.closed:
        return None
    buf: bytes = stdlib.malloc(_SRC_BUF_SIZE)
    if buf is None:
        f.close()
        return None
    bytes_read: LONG = f.read_all(buf, _SRC_BUF_SIZE)
    f.close()
    if bytes_read <= 0:
        stdlib.free(buf)
        return None
    # 逐行查找第 lineno 行
    cur_line: int = 1
    line_start: t.CSizeT = 0
    for i in range(bytes_read):
        if buf[i] == '\n':
            if cur_line == lineno:
                line_len: t.CSizeT = i - line_start
                if line_len > 0 and buf[line_start + line_len - 1] == '\r':
                    line_len -= 1
                line_buf: bytes = stdlib.malloc(line_len + 1)
                if line_buf is not None:
                    string.strncpy(line_buf, buf + line_start, line_len)
                    line_buf[line_len] = '\0'
                    stdlib.free(buf)
                    return line_buf
                stdlib.free(buf)
                return None
            cur_line += 1
            line_start = i + 1
    stdlib.free(buf)
    return None


# ============================================================
# fatal_error - 以 Python 风格报错并退出（带源代码行）
#
# 格式:
#   Traceback (most recent call last):
#     File "path", line N
#       source code line
#   SyntaxError: msg
# ============================================================
def fatal_error(node: ast.AST | t.CPtr, msg: str):
    """以 Python 风格报错并退出（带源代码行）"""
    lineno: int = 0
    if node is not None:
        lineno = node.lineno
    file_name: str = _g_current_file
    if file_name is None:
        file_name = "<unknown>"
    stdio.printf("Traceback (most recent call last):\n")
    stdio.printf('  File "%s", line %d\n', file_name, lineno)
    if lineno > 0 and file_name != "<unknown>":
        src_line: str = _read_source_line(file_name, lineno)
        if src_line is not None:
            stdio.printf("    %s\n", src_line)
            stdlib.free(src_line)
    stdio.printf("SyntaxError: %s\n", msg)
    sys.exit(1)


# ============================================================
# fatal_type_error - 兼容别名（指向 fatal_error）
# ============================================================
def fatal_type_error(node: ast.AST | t.CPtr, msg: str):
    """以 Python 风格报错并退出（fatal_error 的别名）"""
    fatal_error(node, msg)

# ============================================================
# 将 t.CXxx 类型名映射到 LLVMType（纯函数）
# ============================================================
def map_t_type(pool: memhub.MemBuddy | t.CPtr,
               type_name: str) -> llvmlite.LLVMType | t.CPtr:
    """将 t.CXxx / c.CXxx 类型名映射到 LLVMType

    注意: t.CChar | t.CPtr = i8* = str = bytes
    """
    if type_name is None:
        return None

    # 基本整数类型
    if string.strcmp(type_name, "CInt") == 0:
        return llvmlite.Int32(pool)
    elif string.strcmp(type_name, "CChar") == 0:
        return llvmlite.Int8(pool)
    elif string.strcmp(type_name, "CShort") == 0:
        return llvmlite.Int16(pool)
    elif string.strcmp(type_name, "CLong") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "CLongLong") == 0:
        return llvmlite.Int64(pool)
    # 精确宽度有符号类型
    elif string.strcmp(type_name, "CInt8T") == 0:
        return llvmlite.Int8(pool)
    elif string.strcmp(type_name, "CInt16T") == 0:
        return llvmlite.Int16(pool)
    elif string.strcmp(type_name, "CInt32T") == 0:
        return llvmlite.Int32(pool)
    elif string.strcmp(type_name, "CInt64T") == 0:
        return llvmlite.Int64(pool)
    # 精确宽度无符号类型
    elif string.strcmp(type_name, "CUInt8T") == 0:
        return llvmlite.Int8(pool)
    elif string.strcmp(type_name, "CUInt16T") == 0:
        return llvmlite.Int16(pool)
    elif string.strcmp(type_name, "CUInt32T") == 0:
        return llvmlite.Int32(pool)
    elif string.strcmp(type_name, "CUInt64T") == 0:
        return llvmlite.Int64(pool)
    # 浮点类型
    elif string.strcmp(type_name, "CFloat") == 0:
        return llvmlite.Float(pool)
    elif string.strcmp(type_name, "CDouble") == 0:
        return llvmlite.Double(pool)
    # 指针/void: t.CPtr = i8*, t.CChar | t.CPtr = i8* = str = bytes
    elif string.strcmp(type_name, "CPtr") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int8(pool))
    elif string.strcmp(type_name, "CVoid") == 0:
        return llvmlite.Void(pool)
    # 无符号修饰
    elif string.strcmp(type_name, "CUnsigned") == 0:
        return llvmlite.Int32(pool)
    elif string.strcmp(type_name, "CUnsignedInt") == 0:
        return llvmlite.Int32(pool)
    elif string.strcmp(type_name, "CUnsignedChar") == 0:
        return llvmlite.Int8(pool)
    elif string.strcmp(type_name, "CUnsignedShort") == 0:
        return llvmlite.Int16(pool)
    elif string.strcmp(type_name, "CUnsignedLong") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "CUnsignedLongLong") == 0:
        return llvmlite.Int64(pool)
    # size_t / ptr 类型
    elif string.strcmp(type_name, "CSizeT") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "CIntPtrT") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "CUIntPtrT") == 0:
        return llvmlite.Int64(pool)
    # bool
    elif string.strcmp(type_name, "CBool") == 0:
        return llvmlite.Int8(pool)
    # ptrdiff_t
    elif string.strcmp(type_name, "CPtrDiffT") == 0:
        return llvmlite.Int64(pool)

    # ============================================================
    # stdint.py 大写别名（Win32/TransPyC 风格）
    # ============================================================
    # 整数类型
    elif string.strcmp(type_name, "INT") == 0:
        return llvmlite.Int32(pool)
    elif string.strcmp(type_name, "BOOL") == 0:
        return llvmlite.Int32(pool)
    elif string.strcmp(type_name, "UINT") == 0:
        return llvmlite.Int32(pool)
    elif string.strcmp(type_name, "BYTE") == 0:
        return llvmlite.Int8(pool)
    elif string.strcmp(type_name, "WORD") == 0:
        return llvmlite.Int16(pool)
    elif string.strcmp(type_name, "DWORD") == 0:
        return llvmlite.Int32(pool)
    elif string.strcmp(type_name, "QWORD") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "TCHAR") == 0:
        return llvmlite.Int8(pool)
    elif string.strcmp(type_name, "VOID") == 0:
        return llvmlite.Void(pool)
    elif string.strcmp(type_name, "SHORT") == 0:
        return llvmlite.Int16(pool)
    elif string.strcmp(type_name, "USHORT") == 0:
        return llvmlite.Int16(pool)
    elif string.strcmp(type_name, "LONGLONG") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "ULONGLONG") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "LONG") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "ULONG") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "WCHAR") == 0:
        return llvmlite.Int16(pool)
    elif string.strcmp(type_name, "FLOAT") == 0:
        return llvmlite.Float(pool)
    elif string.strcmp(type_name, "DOUBLE") == 0:
        return llvmlite.Double(pool)
    elif string.strcmp(type_name, "FSIZE_t") == 0:
        return llvmlite.Int32(pool)
    elif string.strcmp(type_name, "LBA_t") == 0:
        return llvmlite.Int32(pool)
    # 定长整数
    elif string.strcmp(type_name, "INT8") == 0:
        return llvmlite.Int8(pool)
    elif string.strcmp(type_name, "INT16") == 0:
        return llvmlite.Int16(pool)
    elif string.strcmp(type_name, "INT32") == 0:
        return llvmlite.Int32(pool)
    elif string.strcmp(type_name, "INT64") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "UINT8") == 0:
        return llvmlite.Int8(pool)
    elif string.strcmp(type_name, "UINT16") == 0:
        return llvmlite.Int16(pool)
    elif string.strcmp(type_name, "UINT32") == 0:
        return llvmlite.Int32(pool)
    elif string.strcmp(type_name, "UINT64") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "CHAR8") == 0:
        return llvmlite.Int8(pool)
    elif string.strcmp(type_name, "CHAR16") == 0:
        return llvmlite.Int16(pool)
    elif string.strcmp(type_name, "CHAR32") == 0:
        return llvmlite.Int32(pool)
    # 小写简写
    elif string.strcmp(type_name, "i8") == 0:
        return llvmlite.Int8(pool)
    elif string.strcmp(type_name, "i16") == 0:
        return llvmlite.Int16(pool)
    elif string.strcmp(type_name, "i32") == 0:
        return llvmlite.Int32(pool)
    elif string.strcmp(type_name, "i64") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "u8") == 0:
        return llvmlite.Int8(pool)
    elif string.strcmp(type_name, "u16") == 0:
        return llvmlite.Int16(pool)
    elif string.strcmp(type_name, "u32") == 0:
        return llvmlite.Int32(pool)
    elif string.strcmp(type_name, "u64") == 0:
        return llvmlite.Int64(pool)
    # size_t 系列
    elif string.strcmp(type_name, "SIZE_T") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "SSIZE_T") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "PTRDIFF_T") == 0:
        return llvmlite.Int64(pool)

    # stdint 指针类型（XxxPTR = XxxType | t.CPtr）
    elif string.strcmp(type_name, "INTPTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int32(pool))
    elif string.strcmp(type_name, "UINTPTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int32(pool))
    elif string.strcmp(type_name, "BYTEPTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int8(pool))
    elif string.strcmp(type_name, "CHARLIST") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int8(pool))
    elif string.strcmp(type_name, "SHORTPTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int16(pool))
    elif string.strcmp(type_name, "USHORTPTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int16(pool))
    elif string.strcmp(type_name, "WCHARPTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int16(pool))
    elif string.strcmp(type_name, "CHARPTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int8(pool))
    elif string.strcmp(type_name, "VOIDPTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int8(pool))
    elif string.strcmp(type_name, "INT8PTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int8(pool))
    elif string.strcmp(type_name, "INT16PTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int16(pool))
    elif string.strcmp(type_name, "INT32PTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int32(pool))
    elif string.strcmp(type_name, "INT64PTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int64(pool))
    elif string.strcmp(type_name, "UINT8PTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int8(pool))
    elif string.strcmp(type_name, "UINT16PTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int16(pool))
    elif string.strcmp(type_name, "UINT32PTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int32(pool))
    elif string.strcmp(type_name, "UINT64PTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int64(pool))
    elif string.strcmp(type_name, "CHAR8PTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int8(pool))
    elif string.strcmp(type_name, "CHAR16PTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int16(pool))
    elif string.strcmp(type_name, "CHAR32PTR") == 0:
        return llvmlite.Ptr(pool, llvmlite.Int32(pool))

    # C 标准 <stdint.h> 小写 _t 类型
    elif string.strcmp(type_name, "int8_t") == 0:
        return llvmlite.Int8(pool)
    elif string.strcmp(type_name, "int16_t") == 0:
        return llvmlite.Int16(pool)
    elif string.strcmp(type_name, "int32_t") == 0:
        return llvmlite.Int32(pool)
    elif string.strcmp(type_name, "int64_t") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "uint8_t") == 0:
        return llvmlite.Int8(pool)
    elif string.strcmp(type_name, "uint16_t") == 0:
        return llvmlite.Int16(pool)
    elif string.strcmp(type_name, "uint32_t") == 0:
        return llvmlite.Int32(pool)
    elif string.strcmp(type_name, "uint64_t") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "size_t") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "ssize_t") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "ptrdiff_t") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "intptr_t") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "uintptr_t") == 0:
        return llvmlite.Int64(pool)
    elif string.strcmp(type_name, "wchar_t") == 0:
        return llvmlite.Int16(pool)
    elif string.strcmp(type_name, "char8_t") == 0:
        return llvmlite.Int8(pool)
    elif string.strcmp(type_name, "char16_t") == 0:
        return llvmlite.Int16(pool)
    elif string.strcmp(type_name, "char32_t") == 0:
        return llvmlite.Int32(pool)
    elif string.strcmp(type_name, "_Bool") == 0:
        return llvmlite.Int8(pool)
    return None


# ============================================================
# _is_t_attr - 检测节点是否是 t.attr_name 形式（如 t.CPtr, t.CVoid）
#
# 用于联合类型注解中检测指针包装标记 (t.CPtr) 和 void 标记 (t.CVoid)
# ============================================================
def _is_t_attr(node: ast.AST | t.CPtr,
               attr_name: str,
               imported_modules: str) -> int:
    """检测节点是否是 t.attr_name 形式"""
    if node is None or attr_name is None:
        return 0
    if node.kind() != ast.ASTKind.Attribute:
        return 0
    at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
    if at.attr is None:
        return 0
    if string.strcmp(at.attr, attr_name) != 0:
        return 0
    if at.value is None or at.value.kind() != ast.ASTKind.Name:
        return 0
    val_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
    if val_nm.id is None:
        return 0
    if HandlesImports.is_module_imported(imported_modules, val_nm.id) == 0:
        return 0
    if string.strcmp(val_nm.id, "t") == 0:
        return 1
    return 0


# ============================================================
# extract_class_name_from_annotation - 从类型注解 AST 中提取类名
#
# 用于联合类型简化为 i8* 时，回退查找结构体类名。
# 支持:
#   Name 节点 (MemBuddy) → "MemBuddy"
#   Attribute 节点 (memhub.MemBuddy) → "MemBuddy"
#   BinOp 联合类型 (MemBuddy | t.CPtr) → 非 CPtr 一边的类名
# ============================================================
def extract_class_name_from_annotation(node: ast.AST | t.CPtr,
                                       imported_modules: str) -> str:
    """从类型注解 AST 中提取类名，返回 None=无法提取"""
    if node is None:
        return None
    k: int = node.kind()

    # Constant 节点: 字符串注解（如 'MemManager'），简单类名直接返回
    if k == ast.ASTKind.Constant:
        cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
        if cn.const_kind == ast.CONST_STR and cn.str_val is not None:
            # 仅处理简单类名（不含 . 和 |），复杂形式返回 None
            if string.strchr(cn.str_val, 46) is None and string.strchr(cn.str_val, 124) is None:
                if string.strcmp(cn.str_val, "str") == 0:
                    return None
                if string.strcmp(cn.str_val, "int") == 0:
                    return None
                if string.strcmp(cn.str_val, "bytes") == 0:
                    return None
                return cn.str_val
        return None

    # Name 节点: MemBuddy → "MemBuddy"
    if k == ast.ASTKind.Name:
        nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
        if nm.id is None:
            return None
        # 跳过内置类型名
        if string.strcmp(nm.id, "str") == 0:
            return None
        if string.strcmp(nm.id, "int") == 0:
            return None
        if string.strcmp(nm.id, "bytes") == 0:
            return None
        return nm.id

    # Attribute 节点: memhub.MemBuddy → "memhub.MemBuddy"（模块限定名）
    if k == ast.ASTKind.Attribute:
        at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
        if at.attr is None:
            return None
        # 跳过 t.XXX 形式（内置类型）
        if at.value is not None and at.value.kind() == ast.ASTKind.Name:
            val_nm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
            if val_nm2.id is not None and string.strcmp(val_nm2.id, "t") == 0:
                return None
            # 返回模块限定名 "module.Class"（如 "memhub.MemBuddy"）
            mod_qual_buf: t.CChar | t.CPtr = stdlib.malloc(
                string.strlen(val_nm2.id) + string.strlen(at.attr) + 2)
            if mod_qual_buf is not None:
                viperlib.snprintf(mod_qual_buf,
                    string.strlen(val_nm2.id) + string.strlen(at.attr) + 2,
                    "%s.%s", val_nm2.id, at.attr)
                return mod_qual_buf
        return at.attr

    # BinOp 节点: 联合类型 A | B
    if k == ast.ASTKind.BinOp:
        bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
        if bop.op == ast.OpKind.BitOr:
            left_is_cptr: int = _is_t_attr(bop.left, "CPtr", imported_modules)
            right_is_cptr: int = _is_t_attr(bop.right, "CPtr", imported_modules)
            # 提取非 CPtr 一边的类名
            if left_is_cptr != 0 and right_is_cptr == 0:
                return extract_class_name_from_annotation(bop.right, imported_modules)
            if right_is_cptr != 0 and left_is_cptr == 0:
                return extract_class_name_from_annotation(bop.left, imported_modules)
            # 无 CPtr 标记：尝试两边
            if left_is_cptr == 0 and right_is_cptr == 0:
                left_name: str = extract_class_name_from_annotation(bop.left, imported_modules)
                if left_name is not None:
                    return left_name
                return extract_class_name_from_annotation(bop.right, imported_modules)
        return None

    # Subscript 节点: list[AST | t.CPtr] → "list"
    if k == ast.ASTKind.Subscript:
        sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node)
        if sub.value is not None:
            return extract_class_name_from_annotation(sub.value, imported_modules)
        return None

    return None


# ============================================================
# 解析类型注解节点为 LLVMType
#
# 支持的注解形式:
# - int      → i32
# - t.CUInt64T  → i64
# - str         → i8*  (t.CChar | t.CPtr = i8* = bytes)
# - int         → i32
# - bytes       → i8*
# ============================================================
def resolve_annotation_type(pool: memhub.MemBuddy | t.CPtr,
                            node: ast.AST | t.CPtr,
                            imported_modules: str,
                            from_imports: str) -> llvmlite.LLVMType | t.CPtr:
    """解析类型注解节点为 LLVMType

    Args:
        pool: 内存分配器
        node: 类型注解 AST 节点（Name 或 Attribute）
        imported_modules: 已导入模块名字符串（空格分隔）
        from_imports: from-import 映射字符串（"name:module name:module" 格式）
    """
    if node is None:
        return None

    k: int = node.kind()

    # Constant 节点: 字符串注解（如 'MemManager'），当作无引号的 Name/Attribute/BinOp 处理
    if k == ast.ASTKind.Constant:
        cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
        if cn.const_kind == ast.CONST_STR and cn.str_val is not None:
            sub_node: ast.AST | t.CPtr = _parse_type_string(pool, cn.str_val, ast.Ctx.Load)
            if sub_node is not None:
                return resolve_annotation_type(pool, sub_node, imported_modules, from_imports)
        return None

    # Name 节点: str, int, bytes, from-import 名称, class 名称等
    if k == ast.ASTKind.Name:
        nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
        if nm.id is None:
            return None
        # 泛型类型参数 T 替换：在泛型特化上下文中，将 T 替换为具体类型
        if _g_generic_tp_names is not None and _g_generic_type_args is not None:
            gp_n: t.CSizeT = _g_generic_tp_names.__len__()
            gp_i: t.CSizeT
            for gp_i in range(gp_n):
                gp_tpn: str = _g_generic_tp_names.get(gp_i)
                if gp_tpn is not None and string.strcmp(nm.id, gp_tpn) == 0:
                    gp_ta: str = _g_generic_type_args.get(gp_i)
                    if gp_ta is not None:
                        # 用具体类型名递归解析（支持 BinOp/Attribute 类型实参）
                        gp_sub_node: ast.AST | t.CPtr = _parse_type_string(pool, gp_ta, nm.ctx)
                        if gp_sub_node is not None:
                            return resolve_annotation_type(pool, gp_sub_node, imported_modules, from_imports)
        # str = bytes = t.CChar | t.CPtr = i8*
        if string.strcmp(nm.id, "str") == 0:
            return llvmlite.Ptr(pool, llvmlite.Int8(pool))
        elif string.strcmp(nm.id, "int") == 0:
            return llvmlite.Int32(pool)
        elif string.strcmp(nm.id, "bytes") == 0:
            return llvmlite.Ptr(pool, llvmlite.Int8(pool))
        # class 名称: 查找已注册的 StructType，返回 StructType 本身（不包装 Ptr）
        # 这样 build_alloca 会分配结构体大小的空间，alloca 返回 struct_ty*
        # 命名空间隔离：严格模式下仅解析可见的结构体
        if HandlesStruct.is_struct_visible(nm.id) != 0:
            struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(nm.id)
            if struct_ty is not None:
                return struct_ty
        # from-import 名称: 查找 from_imports 获取模块名后映射
        mod_name: str = HandlesImports.lookup_from_import(from_imports, nm.id)
        if mod_name is not None:
            return map_t_type(pool, nm.id)
        return None

    # Attribute 节点: t.CInt, t.CUInt64T, namespace_defs.PlainStruct 等
    if k == ast.ASTKind.Attribute:
        at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
        if at.attr is None:
            return None
        # 检查 value 是否是 Name('t') 或 Name('c')
        if at.value is not None and at.value.kind() == ast.ASTKind.Name:
            val_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
            if val_name.id is not None:
                # 仅当模块已导入时才解析
                mod_imp: int = HandlesImports.is_module_imported(imported_modules, val_name.id)
                if mod_imp == 0:
                    return None
                # 先尝试内置类型映射（int 等）
                mapped_ty: llvmlite.LLVMType | t.CPtr = map_t_type(pool, at.attr)
                if mapped_ty is not None:
                    return mapped_ty
                # 模块限定类类型：Module.ClassName（命名空间隔离）
                mod_struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(at.attr)
                if mod_struct_ty is not None:
                    return mod_struct_ty
                return None
        return None

    # BinOp 节点: 联合类型注解 A | B
    # 处理三种语义:
    # 1. ActualType | t.CPtr → Ptr(ActualType)（指针包装，如 MemBuddy | t.CPtr → MemBuddy*）
    # 2. t.CVoid | t.CPtr → i8* (void* 等价于 i8*)
    # 3. ActualType | DecoratorMarker → ActualType（忽略装饰器标记如 CExport/CExtern）
    if k == ast.ASTKind.BinOp:
        bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
        if bop.op == ast.OpKind.BitOr:
            # 检测 t.CPtr 标记（指针包装标记）
            left_is_cptr: int = _is_t_attr(bop.left, "CPtr", imported_modules)
            right_is_cptr: int = _is_t_attr(bop.right, "CPtr", imported_modules)

            if left_is_cptr != 0 or right_is_cptr != 0:
                # 有 CPtr 标记：解析非 CPtr 一边的实际类型，包装为 Ptr
                # left 是 CPtr → other 是 right；right 是 CPtr → other 是 left
                other_node: ast.AST | t.CPtr = bop.left
                if left_is_cptr != 0:
                    other_node = bop.right
                # 检测另一边是否是 t.CVoid (void* = i8*)
                other_is_cvoid: int = _is_t_attr(other_node, "CVoid", imported_modules)
                if other_is_cvoid != 0:
                    return llvmlite.Ptr(pool, llvmlite.Int8(pool))
                other_ty: llvmlite.LLVMType | t.CPtr = resolve_annotation_type(
                    pool, other_node, imported_modules, from_imports)
                if other_ty is None:
                    # CPtr 单独使用或其他无效类型 → i8*
                    return llvmlite.Ptr(pool, llvmlite.Int8(pool))
                return llvmlite.Ptr(pool, other_ty)

            # 无 CPtr 标记：返回第一个非 None（装饰器标记如 CExport/CExtern 被忽略）
            left_ty: llvmlite.LLVMType | t.CPtr = resolve_annotation_type(
                pool, bop.left, imported_modules, from_imports)
            if left_ty is not None:
                return left_ty
            right_ty: llvmlite.LLVMType | t.CPtr = resolve_annotation_type(
                pool, bop.right, imported_modules, from_imports)
            if right_ty is not None:
                return right_ty
        return None

    # Subscript 节点: t.CArray[elem_ty, count] → [count x elem_ty]
    #                t.CArray[elem_ty]       → Ptr(elem_ty)（静态推导长度数组）
    #                list[int]               → 特化类 struct type（泛型类类型注解）
    # value 是 Attribute(Name('t'), 'CArray') 或 Name('list')（泛型类）
    # slice 是 Tuple(elts=[elem_ty_node, count_node]) 或单 elem_ty_node
    if k == ast.ASTKind.Subscript:
        sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node)
        if sub.value is None or sub.slice is None:
            fatal_type_error(node, "Subscript 节点缺少 value 或 slice")
        # 泛型类类型注解: list[int] → 查找已特化的 struct
        # value 是 Name（泛型类名），slice 是类型实参
        if sub.value.kind() == ast.ASTKind.Name:
            gen_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value)
            if gen_nm.id is not None:
                # 先收集类型实参名，再分配缓冲区拼接 mangled name
                gen_arg_names: list[str] | t.CPtr = list[str](pool, 4)
                if sub.slice.kind() == ast.ASTKind.Tuple:
                    gen_tp: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(sub.slice)
                    gen_elts: list[ast.AST | t.CPtr] | t.CPtr = gen_tp.elts
                    if gen_elts is not None:
                        gen_en: t.CSizeT = gen_elts.__len__()
                        gen_ei: t.CSizeT
                        for gen_ei in range(gen_en):
                            gen_elt: ast.AST | t.CPtr = gen_elts.get(gen_ei)
                            gen_tn: str = _get_type_name_from_annotation(pool, gen_elt)
                            gen_arg_names.append(gen_tn)
                else:
                    gen_tn_single: str = _get_type_name_from_annotation(pool, sub.slice)
                    gen_arg_names.append(gen_tn_single)
                # 计算总长度并分配缓冲区
                gen_total: t.CSizeT = string.strlen(gen_nm.id) + 2  # "[" 和 "]"
                gen_an: t.CSizeT = gen_arg_names.__len__()
                gen_ai: t.CSizeT
                for gen_ai in range(gen_an):
                    if gen_ai > 0:
                        gen_total += 1  # ","
                    gen_atn: str = gen_arg_names.get(gen_ai)
                    if gen_atn is not None:
                        gen_total += string.strlen(gen_atn)
                gen_total += 1  # NUL
                gen_mangled: str = pool.alloc(gen_total)
                if gen_mangled is None:
                    return None
                gen_mangled[0] = '\0'
                string.strcat(gen_mangled, gen_nm.id)
                string.strcat(gen_mangled, "[")
                for gen_ai in range(gen_an):
                    if gen_ai > 0:
                        string.strcat(gen_mangled, ",")
                    gen_atn: str = gen_arg_names.get(gen_ai)
                    if gen_atn is not None:
                        string.strcat(gen_mangled, gen_atn)
                string.strcat(gen_mangled, "]")
                # 查找已特化的 struct（特化由实例化调用 list[int](pool) 触发）
                gen_spec_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(gen_mangled)
                if gen_spec_ty is not None:
                    return gen_spec_ty
                # 未特化：返回 None（不报错，让后续流程处理）
                return None
        # 检查 value 是否是 Attribute(Name('t'), 'CArray')
        if sub.value.kind() != ast.ASTKind.Attribute:
            fatal_type_error(node, "不支持的 Subscript 类型注解（仅支持 t.CArray）")
        arr_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(sub.value)
        if arr_at.attr is None:
            fatal_type_error(node, "Subscript Attribute 缺少 attr")
        if string.strcmp(arr_at.attr, "CArray") != 0:
            fatal_type_error(node, "不支持的 Subscript 类型注解（仅支持 t.CArray）")
        if arr_at.value is None or arr_at.value.kind() != ast.ASTKind.Name:
            fatal_type_error(node, "t.CArray 必须通过模块名限定")
        arr_val_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arr_at.value)
        if arr_val_name.id is None:
            fatal_type_error(node, "t.CArray 模块名为 None")
        if HandlesImports.is_module_imported(imported_modules, arr_val_name.id) == 0:
            fatal_type_error(node, "t.CArray 模块未导入")
        # 单参数形式: t.CArray[elem_ty] → Ptr(elem_ty)
        # 相当于 t.CArray[elem_ty, None]，表示静态推导长度数组
        if sub.slice.kind() != ast.ASTKind.Tuple:
            elem_ty_single: llvmlite.LLVMType | t.CPtr = resolve_annotation_type(
                pool, sub.slice, imported_modules, from_imports)
            if elem_ty_single is None:
                fatal_type_error(sub.slice, "t.CArray[?] 元素类型解析失败")
            return llvmlite.Ptr(pool, elem_ty_single)
        # 双参数形式: t.CArray[elem_ty, count] → [count x elem_ty]
        tup: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(sub.slice)
        if tup.elts is None:
            fatal_type_error(node, "t.CArray Tuple 缺少 elts")
        elts_list: list[ast.AST | t.CPtr] | t.CPtr = tup.elts
        elts_n: t.CSizeT = elts_list.__len__()
        if elts_n < 2:
            fatal_type_error(node, "t.CArray Tuple 元素不足")
        elem_node: ast.AST | t.CPtr = elts_list.get(0)
        count_node: ast.AST | t.CPtr = elts_list.get(1)
        if elem_node is None or count_node is None:
            fatal_type_error(node, "t.CArray Tuple 元素为 None")
        # 递归解析元素类型
        elem_ty: llvmlite.LLVMType | t.CPtr = resolve_annotation_type(
            pool, elem_node, imported_modules, from_imports)
        if elem_ty is None:
            fatal_type_error(elem_node, "t.CArray 元素类型解析失败")
        # 解析 count（必须是整数常量、None 或 CDefine 常量名）
        # t.CArray[elem_ty, None] 等价于单参数形式 → Ptr(elem_ty)
        # t.CArray[elem_ty, NAME] 其中 NAME: t.CDefine = value → [value x elem_ty]
        count_val: int = 0
        if count_node.kind() == ast.ASTKind.Constant:
            cnt_cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(count_node)
            if cnt_cn.const_kind == ast.CONST_NONE:
                return llvmlite.Ptr(pool, elem_ty)
            if cnt_cn.const_kind != ast.CONST_INT:
                fatal_type_error(count_node, "t.CArray count 必须是整数常量、None 或 CDefine 常量名")
            count_val = cnt_cn.int_val
        elif count_node.kind() == ast.ASTKind.Name:
            # CDefine 常量名查找
            cnt_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(count_node)
            if cnt_nm.id is None:
                fatal_type_error(count_node, "t.CArray count Name 节点 id 为 None")
            looked_up: int = lookup_cdefine_constant(cnt_nm.id)
            if looked_up < 0:
                fatal_type_error(count_node, "t.CArray count 不是已注册的 CDefine 常量")
            count_val = looked_up
        else:
            fatal_type_error(count_node, "t.CArray count 必须是整数常量、None 或 CDefine 常量名")
        if count_val <= 0:
            fatal_type_error(count_node, "t.CArray count 必须为正数")
        # 创建 ArrayType（不包装 Ptr）
        # 这样 build_alloca 会分配数组大小的空间，alloca 返回 [N x elem_ty]*
        return llvmlite.Array(pool, elem_ty, count_val)

    # 未知 AST kind：fail-fast，不宽容返回 None
    fatal_type_error(node, "不支持的类型注解语法")


# ============================================================
# has_decorator_marker - 检测类型注解中是否包含指定的装饰器标记
#
# 支持联合类型注解：int | t.CExtern | t.CExport
# 递归检测 BinOp 节点的左右子节点。
#
# marker_name 取值: "CExtern", "CExport", "CInline", "State"
# ============================================================
def has_decorator_marker(node: ast.AST | t.CPtr,
                         marker_name: str) -> int:
    """检测类型注解中是否包含指定的装饰器标记"""
    if node is None or marker_name is None:
        return 0

    k: int = node.kind()

    # Attribute 节点: t.CExtern, t.State, t.CExport, t.CInline
    if k == ast.ASTKind.Attribute:
        at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
        if at.attr is not None:
            if string.strcmp(at.attr, marker_name) == 0:
                return 1
        return 0

    # BinOp 节点: int | t.CExtern（递归检测左右子节点）
    if k == ast.ASTKind.BinOp:
        bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
        if has_decorator_marker(bop.left, marker_name) != 0:
            return 1
        if has_decorator_marker(bop.right, marker_name) != 0:
            return 1
        return 0

    return 0


# ============================================================
# is_pass_body - 检测函数体是否为 pass（空体）
#
# pass 体函数用于声明外部函数（t.CExtern / t.State），
# 翻译器应生成 declare 而非 define。
# ============================================================
def is_pass_body(body: list[ast.AST | t.CPtr] | t.CPtr) -> int:
    """检测函数体是否为 pass（空体或仅含 pass 语句）"""
    if body is None:
        return 1
    bn: t.CSizeT = body.__len__()
    if bn == 0:
        return 1
    if bn == 1:
        stmt: ast.AST | t.CPtr = body.get(0)
        if stmt is not None and stmt.kind() == ast.ASTKind.Pass:
            return 1
    return 0


# ============================================================
# 获取 LLVM 整数类型的位宽
# ============================================================
def get_llvm_type_bits(ty: llvmlite.LLVMType | t.CPtr) -> int:
    """获取 LLVM 整数类型的位宽，非整数类型返回 0"""
    if ty is None:
        return 0
    match ty:
        case llvmlite.LLVMType.Int(bits):
            return bits
        case _:
            return 0


# ============================================================
# 推断表达式的 LLVM 类型
# ============================================================
def infer_expr_type(pool: memhub.MemBuddy | t.CPtr,
                    node: ast.AST | t.CPtr,
                    param_types: str) -> llvmlite.LLVMType | t.CPtr:
    """推断表达式的 LLVM 类型

    param_types 格式: "name:bits,name:bits,..."
    """
    if node is None:
        return llvmlite.Int32(pool)

    k: int = node.kind()

    if k == ast.ASTKind.Constant:
        return llvmlite.Int32(pool)

    elif k == ast.ASTKind.Name:
        nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
        if nm.id is not None and param_types is not None:
            # 在 param_types 中查找: "name:bits" 格式
            search_key: t.CChar | t.CPtr = pool.alloc(64)
            if search_key is not None:
                viperlib.snprintf(search_key, 64, "%s:", nm.id)
                found: t.CChar | t.CPtr = string.strstr(param_types, search_key)
                if found is not None:
                    colon_pos: t.CSizeT = string.strlen(nm.id) + 1
                    bits_str: t.CChar | t.CPtr = found + colon_pos
                    bits: int = 0
                    for bi in range(4):
                        ch: t.CChar = bits_str[bi]
                        if ch >= '0' and ch <= '9':
                            bits = bits * 10 + (ch - '0')
                        else:
                            break
                    if bits == 64:
                        return llvmlite.Int64(pool)
                    elif bits == 16:
                        return llvmlite.Int16(pool)
                    elif bits == 8:
                        return llvmlite.Int8(pool)
        return llvmlite.Int32(pool)

    elif k == ast.ASTKind.BinOp:
        binop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
        lhs_ty: llvmlite.LLVMType | t.CPtr = infer_expr_type(
            pool, binop.left, param_types)
        rhs_ty: llvmlite.LLVMType | t.CPtr = infer_expr_type(
            pool, binop.right, param_types)
        lhs_bits: int = get_llvm_type_bits(lhs_ty)
        rhs_bits: int = get_llvm_type_bits(rhs_ty)
        if lhs_bits >= rhs_bits:
            return lhs_ty
        return rhs_ty

    return llvmlite.Int32(pool)


# ============================================================
# 推断函数返回类型
# ============================================================
def infer_return_type(pool: memhub.MemBuddy | t.CPtr,
                      body: list[ast.AST | t.CPtr] | t.CPtr,
                      param_types: str) -> llvmlite.LLVMType | t.CPtr:
    """扫描函数体中的 return 语句，推断返回类型"""
    if body is None:
        return llvmlite.Int32(pool)

    ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
    bn: t.CSizeT = body.__len__()
    for bi in range(bn):
        stmt: ast.AST | t.CPtr = body.get(bi)
        if stmt is not None and stmt.kind() == ast.ASTKind.Return:
            rt: ast.Return | t.CPtr = (ast.Return | t.CPtr)(stmt)
            if rt.value is not None:
                expr_ty: llvmlite.LLVMType | t.CPtr = infer_expr_type(
                    pool, rt.value, param_types)
                if expr_ty is not None:
                    cur_bits: int = get_llvm_type_bits(ret_ty)
                    new_bits: int = get_llvm_type_bits(expr_ty)
                    if new_bits > cur_bits:
                        ret_ty = expr_ty
    return ret_ty


# ============================================================
# 构建参数类型编码字符串
# ============================================================
def build_param_types_str(pool: memhub.MemBuddy | t.CPtr,
                          args_node: ast.AST | t.CPtr) -> str:
    """构建参数类型编码字符串 "name:bits,name:bits,..." """
    if args_node is None:
        return None
    ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
    if ags.args is None:
        return None
    alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args
    an: t.CSizeT = alist.__len__()
    if an == 0:
        return None

    buf_size: t.CSizeT = an * 32 + 1
    buf: t.CChar | t.CPtr = pool.alloc(buf_size)
    if buf is None:
        return None
    buf[0] = '\0'

    i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
    for ai in range(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:
                # 直接调用 map_t_type 解析 Attribute 注解
                if arg.annotation.kind() == ast.ASTKind.Attribute:
                    at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg.annotation)
                    if at.attr is not None:
                        resolved: llvmlite.LLVMType | t.CPtr = map_t_type(pool, at.attr)
                        if resolved is not None:
                            param_ty = resolved
            bits: int = get_llvm_type_bits(param_ty)
            if bits == 0:
                bits = 32
            tmp: t.CChar | t.CPtr = pool.alloc(32)
            if tmp is not None:
                viperlib.snprintf(tmp, 32, "%s:%d", arg.arg, bits)
                if ai > 0:
                    _strappend(buf, buf_size, ",")
                _strappend(buf, buf_size, tmp)
    return buf


# ============================================================
# 辅助函数
# ============================================================
def _strappend(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
    for i in range(min(slen, remain - 1)):
        dst[dlen + i] = src[i]
    dst[dlen + i] = '\0'