from __future__ import annotations
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
    from lib.core.translator import Translator
    from lib.core.LlvmCodeGenerator import LlvmCodeGenerator
import ast
import llvmlite.ir as ir
from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo
from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode
from lib.includes import t
from lib.core.SymbolUtils import IsListAnnotation, ParseListAnnotation, FindStructNameInAnnotation, AnnotationContainsName


class AnnAssignHandle(BaseHandle):
    def _StoreOrStrCopy(self, VarName: str, VarPtr: ir.Value, Value: ir.Value) -> None:
        Gen: LlvmCodeGenerator = self.Trans.LlvmGen
        DestPtr: ir.Value = Gen._load(VarPtr, name=VarName)
        if isinstance(DestPtr.type, ir.PointerType) and isinstance(DestPtr.type.pointee, ir.IntType) and DestPtr.type.pointee.width == 8:
            if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, ir.IntType) and Value.type.pointee.width == 8:
                if 'llvm.memcpy' not in Gen.functions:
                    memcpy_type: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(32), ir.IntType(1)])
                    Gen.functions['llvm.memcpy'] = ir.Function(Gen.module, memcpy_type, name='llvm.memcpy')
                if isinstance(DestPtr.type.pointee, ir.IntType) and not isinstance(DestPtr.type.pointee, ir.IntType(8)):
                    DestPtr = Gen.builder.bitcast(DestPtr, ir.PointerType(ir.IntType(8)), name=f"strcpy_dst_cast_{VarName}")
                if isinstance(Value.type.pointee, ir.IntType) and not isinstance(Value.type.pointee, ir.IntType(8)):
                    Value = Gen.builder.bitcast(Value, ir.PointerType(ir.IntType(8)), name=f"strcpy_src_cast_{VarName}")
                size: ir.Constant = ir.Constant(ir.IntType(64), 8)
                align: ir.Constant = ir.Constant(ir.IntType(32), 1)
                isvolatile: ir.Constant = ir.Constant(ir.IntType(1), 0)
                Gen.builder.call(Gen.functions['llvm.memcpy'], [DestPtr, Value, size, align, isvolatile], name=f"strcpy_call_{VarName}")
                return
        try:
            CastedVal: ir.Value = Gen.builder.bitcast(Value, VarPtr.type.pointee, name=f"cast_{VarName}")
            Gen._store(CastedVal, VarPtr)
        except Exception:  # 回退：bitcast 失败时 alloca 新变量
            NewVar: ir.AllocaInstr = Gen._allocaEntry(Value.type, name=VarName)
            Gen._store(Value, NewVar)
            Gen.variables[VarName] = NewVar

    def _HandleAttributeStoreLlvm(self, Target: ast.Attribute, Value: ir.Value) -> None:
        Gen: LlvmCodeGenerator = self.Trans.LlvmGen
        AttrName: str = Target.attr
        if isinstance(Target.value, ast.Name) and Target.value.id == 'self':
            ClassName: str | None = self._CurrentCpythonObjectClass
            if not ClassName:
                self_var: ir.Value | None = Gen.variables.get('self')
                if self_var:
                    var_type: ir.Type = self_var.type
                    if isinstance(var_type, ir.PointerType) and isinstance(var_type.pointee, ir.PointerType):
                        var_type = var_type.pointee
                    if isinstance(var_type, ir.PointerType):
                        pointee: ir.Type = var_type.pointee
                        for cn, st in Gen.structs.items():
                            if st == pointee:
                                ClassName = cn
                                break
            if ClassName and ClassName in Gen.structs:
                SelfVar: ir.Value | None = Gen._get_var_ptr('self')
                if SelfVar:
                    SelfPtr: ir.Value = Gen._load(SelfVar, name="self")
                    offset: int = Gen._get_member_offset(AttrName, ClassName)
                    MemberPtr: ir.Value = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName)
                    self._StoreWithCoerce(Value, MemberPtr)
        elif isinstance(Target.value, ast.Name):
            VarName: str = Target.value.id

            # FakeDuck: 检查是否有影子结构体 a__meta__ (str 变量的 per-instance 字段存储)
            # 直接通过 a.__field__ = value 访问影子结构体字段 (语法糖)
            _fd_meta_name: str = f"{VarName}__meta__"
            if _fd_meta_name in Gen.variables and '_str' in Gen.structs:
                _fd_offset = Gen._get_member_offset(AttrName, '_str')
                if _fd_offset is not None:
                    _fd_meta_ptr: ir.Value = Gen.variables[_fd_meta_name]
                    _fd_field_ptr: ir.Value = Gen.builder.gep(_fd_meta_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), _fd_offset)], name=f"{VarName}_{AttrName}_ptr")
                    self._StoreWithCoerce(Value, _fd_field_ptr)
                    return

            ClassName: str | None = Gen.var_struct_class.get(VarName)
            if not ClassName:
                for CN in Gen.structs:
                    if VarName == CN.lower() or VarName.startswith(CN):
                        ClassName = CN
                        break
            if not ClassName and VarName in Gen.variables:
                VarPtr: ir.Value = Gen.variables[VarName]
                if isinstance(VarPtr.type, ir.PointerType):
                    pointee: ir.Type = VarPtr.type.pointee
                    if isinstance(pointee, ir.PointerType):
                        pointee = pointee.pointee
                    for CN, ST in Gen.structs.items():
                        if pointee == ST:
                            ClassName = CN
                            break
            IsUnion: bool = False
            if ClassName:
                ClassTypeInfo: Any = self.Trans.SymbolTable.lookup(ClassName)
                if ClassTypeInfo:
                    if ClassTypeInfo.IsUnion:
                        IsUnion = True
            if ClassName and ClassName in Gen.structs:
                ObjVal: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(Target.value)
                if ObjVal:
                    if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.IntType) and ObjVal.type.pointee.width == 8:
                        ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}")
                    if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType):
                        ObjVal = Gen._load(ObjVal, name=f"Load_{ClassName}")
                    if isinstance(ObjVal.type, ir.PointerType) and ObjVal.type.pointee == Gen.structs[ClassName]:
                        if IsUnion:
                            NestedStructName: str = f"{ClassName}_{AttrName}"
                            if NestedStructName in Gen.structs:
                                NestedStructType: ir.Type = Gen.structs[NestedStructName]
                                ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(NestedStructType), name=f"cast_{NestedStructName}")
                                offset: int = Gen._get_member_offset(AttrName, NestedStructName)
                                if offset is not None and offset < len(NestedStructType.elements):
                                    MemberPtr: ir.Value = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName)
                                    self._StoreWithCoerce(Value, MemberPtr)
                                return
                        offset: int = Gen._get_member_offset(AttrName, ClassName)
                        MemberPtr: ir.Value = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName)
                        self._StoreWithCoerce(Value, MemberPtr)
        elif isinstance(Target.value, ast.Attribute):
            ObjVal: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(Target.value)
            if ObjVal and isinstance(ObjVal.type, ir.PointerType):
                pointee: ir.Type = ObjVal.type.pointee
                if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)):
                    for CN, ST in Gen.structs.items():
                        if pointee == ST:
                            offset: int = Gen._get_member_offset(AttrName, CN)
                            MemberPtr: ir.Value = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName)
                            self._StoreWithCoerce(Value, MemberPtr)
                            break

    def _StoreWithCoerce(self, Value: ir.Value, Ptr: ir.Value) -> None:
        Gen: LlvmCodeGenerator = self.Trans.LlvmGen
        if isinstance(Ptr.type, ir.PointerType):
            TargetType: ir.Type = Ptr.type.pointee
            if Value.type != TargetType:
                if isinstance(TargetType, ir.IntType) and isinstance(Value.type, ir.IntType):
                    if TargetType.width < Value.type.width:
                        Value = Gen.builder.trunc(Value, TargetType, name="trunc")
                    else:
                        Value = Gen.builder.zext(Value, TargetType, name="zext")
                elif isinstance(TargetType, ir.PointerType) and isinstance(Value.type, ir.PointerType):
                    Value = Gen.builder.bitcast(Value, TargetType, name="ptr_bitcast")
                elif isinstance(TargetType, ir.PointerType) and isinstance(Value.type, ir.IntType):
                    Value = Gen.builder.inttoptr(Value, TargetType, name="int_to_ptr")
                elif isinstance(TargetType, ir.IntType) and isinstance(Value.type, ir.PointerType):
                    Value = Gen.builder.ptrtoint(Value, TargetType, name="ptr_to_int")
        Gen._store(Value, Ptr)

    def _HandleGenericListLiteralAssign(self, VarName: str, Node: ast.AnnAssign, Gen: LlvmCodeGenerator, list_sub: ast.Subscript) -> None:
        """处理 list[T] = [...] → 构造 list[T] 对象 + append 序列。

        将 list 字面量翻译为：
          1. 特化 list[T] 类
          2. alloca + __before_init__ + __new__(pool) + __before_init__ + __init__(pool)
          3. 对每个元素调用 append(elem)
          4. 将堆指针存入变量
        list_sub 是从注解中提取的 list[...] Subscript 节点（支持 list[T] 和 list[T] | t.CPtr）
        """
        # 1. 解析元素类型
        slice_node: ast.expr = list_sub.slice
        result: tuple[str, str] | None = self.Trans.ExprCallHandle._resolve_generic_slice_type(slice_node)
        if result is None:
            return
        type_arg: str = result[0]
        type_name: str = result[1]

        # 2. 特化 list[T] 类
        spec_name: str | None = self.Trans.ClassHandler._specialize_generic_class(
            'list', [type_arg], Gen, type_names=[type_name])
        if spec_name is None:
            return

        # 3. 获取结构体类型
        StructType: ir.Type | None = Gen.structs.get(spec_name)
        if StructType is None:
            return
        if isinstance(StructType, ir.PointerType):
            StructType = StructType.pointee

        # 4. 查找 pool 变量（pool / _mbuddy / mbuddy / mb）
        pool_val: ir.Value | None = None
        for pool_name in ('pool', '_mbuddy', 'mbuddy', 'mb'):
            if pool_name in Gen.variables:
                pool_var: ir.Value = Gen.variables[pool_name]
                if isinstance(pool_var.type, ir.PointerType):
                    pointee: ir.Type = pool_var.type.pointee
                    if isinstance(pointee, ir.PointerType):
                        # alloca of pointer → load
                        pool_val = Gen._load(pool_var, name=f"pool_load_{VarName}")
                    else:
                        pool_val = pool_var
                else:
                    pool_val = pool_var
                break
        if pool_val is None:
            return

        # 5. alloca 临时结构体
        alloca_ptr: ir.AllocaInstr = Gen._allocaEntry(StructType, name=f"{VarName}_alloca")

        # 6. 调用 __before_init__(alloca_ptr)
        before_init_name: str = f'{spec_name}.__before_init__'
        before_init_func: ir.Function | None = None
        if Gen._has_function(before_init_name):
            before_init_func = Gen._get_function(before_init_name)
            Gen.builder.call(before_init_func, [alloca_ptr], name=f"before_init_{VarName}")

        # 7. 调用 __new__(alloca_ptr, pool_val) → heap_ptr
        new_method_name: str = f'{spec_name}.__new__'
        heap_ptr: ir.Value = alloca_ptr
        has_new: bool = Gen._find_function(new_method_name) is not None
        if has_new:
            new_func: ir.Function | None = Gen._find_function(new_method_name)
            if new_func:
                new_args: list[ir.Value] = [alloca_ptr, pool_val]
                self.Trans.ExprCallHandle._fill_default_args(new_args, new_func, new_method_name)
                new_args = Gen._apply_auto_addr(new_method_name, new_args)
                adjusted_new: list[ir.Value] = Gen._adjust_args(new_args, new_func)
                heap_ptr = Gen.builder.call(new_func, adjusted_new, name=f"new_{VarName}")
                # 转换返回指针类型
                target_ptr_type: ir.PointerType = ir.PointerType(StructType)
                if isinstance(heap_ptr.type, ir.PointerType) and heap_ptr.type != target_ptr_type:
                    heap_ptr = Gen.builder.bitcast(heap_ptr, target_ptr_type, name=f"new_{VarName}_cast")
                elif isinstance(heap_ptr.type, ir.IntType) and target_ptr_type:
                    if heap_ptr.type.width < 64:
                        i64_val: ir.Value = Gen.builder.zext(heap_ptr, ir.IntType(64), name=f"new_{VarName}_i64")
                        heap_ptr = Gen.builder.inttoptr(i64_val, target_ptr_type, name=f"new_{VarName}_ptr")
                    else:
                        heap_ptr = Gen.builder.inttoptr(heap_ptr, target_ptr_type, name=f"new_{VarName}_ptr")
                # 对堆指针重新调用 __before_init__
                if before_init_func:
                    Gen.builder.call(before_init_func, [heap_ptr], name=f"before_init_{VarName}_heap")

        # 8. 调用 __init__(heap_ptr, pool_val, elem_size=0)
        init_name: str = f'{spec_name}.__init__'
        if Gen._has_function(init_name):
            init_func: ir.Function | None = Gen._get_function(init_name)
            if init_func:
                elem_size_val: ir.Constant = ir.Constant(ir.IntType(64), 0)
                init_args: list[ir.Value] = [heap_ptr, pool_val, elem_size_val]
                self.Trans.ExprCallHandle._fill_default_args(init_args, init_func, init_name)
                init_args = Gen._apply_auto_addr(init_name, init_args)
                adjusted_init: list[ir.Value] = Gen._adjust_args(init_args, init_func)
                Gen.builder.call(init_func, adjusted_init, name=f"init_{VarName}")

        # 9. 对每个元素调用 append(heap_ptr, elem_val)
        append_name: str = f'{spec_name}.append'
        append_func: ir.Function | None = Gen._find_function(append_name)
        if append_func and Node.value and isinstance(Node.value, ast.List):
            elts: list[ast.expr] = Node.value.elts
            for i, elem_node in enumerate(elts):
                elem_val: ir.Value | None = self.HandleExprLlvm(elem_node)
                if elem_val:
                    append_args: list[ir.Value] = [heap_ptr, elem_val]
                    self.Trans.ExprCallHandle._fill_default_args(append_args, append_func, append_name)
                    append_args = Gen._apply_auto_addr(append_name, append_args)
                    adjusted_append: list[ir.Value] = Gen._adjust_args(append_args, append_func)
                    Gen.builder.call(append_func, adjusted_append, name=f"append_{VarName}_{i}")

        # 10. 创建变量并存储堆指针
        # 判断变量类型：list[T] | t.CPtr → i8*；list[T] → Ptr(StructType)
        is_cptr_union: bool = isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr)
        if is_cptr_union:
            # list[T] | t.CPtr → 变量类型为 i8*
            i8_ptr_type: ir.PointerType = ir.PointerType(ir.IntType(8))
            var: ir.AllocaInstr = Gen._allocaEntry(i8_ptr_type, name=VarName)
            # bitcast heap_ptr (Ptr(StructType)) → i8*
            if isinstance(heap_ptr.type, ir.PointerType) and heap_ptr.type != i8_ptr_type:
                stored_val: ir.Value = Gen.builder.bitcast(heap_ptr, i8_ptr_type, name=f"store_cast_{VarName}")
            else:
                stored_val = heap_ptr
            Gen._store(stored_val, var)
        else:
            # list[T] → 变量类型为 Ptr(StructType)
            var = Gen._allocaEntry(ir.PointerType(StructType), name=VarName)
            Gen._store(heap_ptr, var)
        Gen.variables[VarName] = var
        Gen.var_struct_class[VarName] = spec_name
        Gen.global_struct_class[VarName] = spec_name
        Gen._record_var_signedness(VarName, False)

    def _HandleAnnAssignLlvm(self, Node: ast.AnnAssign) -> None:
        Gen: LlvmCodeGenerator = self.Trans.LlvmGen
        self.Trans._current_assign_node = Node
        try:
            self._HandleAnnAssignLlvmInner(Node)
        finally:
            self.Trans._current_assign_node = None

    def _HandleAnnAssignLlvmInner(self, Node: ast.AnnAssign) -> None:
        Gen: LlvmCodeGenerator = self.Trans.LlvmGen
        if isinstance(Node.target, ast.Name):
            VarName: str = Node.target.id
            TypeInfo: CTypeInfo | None = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.annotation)
            if TypeInfo is None:
                TypeInfo = CTypeInfo()
                TypeInfo.BaseType = t.CInt()
            IsPtr: bool = TypeInfo.IsPtr

            if TypeInfo.IsDefine:
                if Node.value and isinstance(Node.value, ast.Constant):
                    if not hasattr(Gen, '_define_constants'):
                        Gen._define_constants = {}
                    Gen._define_constants[VarName] = Node.value.value
                    info: CTypeInfo = CTypeInfo()
                    info.IsDefine = True
                    info.DefineValue = Node.value.value
                    self.Trans.SymbolTable.insert(VarName, info)
                    Gen._record_var_signedness(VarName, TypeInfo.IsUInt)
                elif Node.value:
                    # 非 Constant 表达式：尝试编译期求值（如 t.CSizeT().Size // 8）
                    from lib.core.ConstEvaluator import ConstEvaluator, EvalContext
                    ctx = EvalContext(Gen=Gen, symtab=self.Trans.SymbolTable, translator=self.Trans)
                    eval_val = ConstEvaluator.eval_full(Node.value, ctx)
                    if eval_val is not None and isinstance(eval_val, (int, float)):
                        if not hasattr(Gen, '_define_constants'):
                            Gen._define_constants = {}
                        Gen._define_constants[VarName] = eval_val
                        info: CTypeInfo = CTypeInfo()
                        info.IsDefine = True
                        info.DefineValue = eval_val
                        self.Trans.SymbolTable.insert(VarName, info)
                        Gen._record_var_signedness(VarName, TypeInfo.IsUInt)
                return
            if TypeInfo.IsStr or (isinstance(Node.annotation, ast.Name) and Node.annotation.id == 'str'):
                TypeInfo = CTypeInfo()
                TypeInfo.BaseType = t.CChar()
                TypeInfo.PtrCount = 1
                IsPtr = True
                # FakeDuck: 为 str 变量创建影子结构体 a__meta__ (栈上, per-instance)
                # a 保持为 char* 用于 printf; a__meta__ 存储 __data__ 和 __mbuddy__ 字段
                # 仅对 str 类型创建，bytes 和 t.CChar|t.CPtr 不创建
                if '_str' in Gen.structs and isinstance(Node.annotation, ast.Name) and Node.annotation.id == 'str':
                    _meta_name: str = f"{VarName}__meta__"
                    _meta_var: ir.AllocaInstr = Gen._allocaEntry(Gen.structs['_str'], name=_meta_name)
                    Gen.variables[_meta_name] = _meta_var
                # 标记指针到 str/bytes 的变量 (BinOp 注解如 str | t.CPtr)
                # elem_ptr[0] 应加载/存储 8 字节 (指针), 而非 1 字节 (字符)
                # 仅当注解包含 str 或 bytes 时设置（t.CChar | t.CPtr 不应设置，它是纯字符指针）
                if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr):
                    if AnnotationContainsName(Node.annotation, 'str') or AnnotationContainsName(Node.annotation, 'bytes'):
                        Gen.var_ptr_element[VarName] = True
                        # 同时记录到全局字典，使全局变量在跨函数访问时仍能用 8 字节指针步长
                        Gen.global_var_ptr_element[VarName] = True
            parse_result = ParseListAnnotation(Node.annotation)
            if parse_result:
                elem_type_node: ast.expr = parse_result.elem_type_node
                ElemType, ElemTypeInfo = self.ResolveListElementType(
                    elem_type_node, Gen,
                    handle_str=True, void_fallback_width=32,
                )
                if parse_result.is_pointer:
                    # 单参数 list[type] → 指针
                    # 但如果有列表字面量初始化值 [a, b, c]，则按数组 list[type, N] 处理
                    if not (Node.value and isinstance(Node.value, ast.List)):
                        VarType: ir.Type = ir.PointerType(ElemType)
                        var: ir.AllocaInstr = Gen._allocaEntry(VarType, name=VarName)
                        Gen.variables[VarName] = var
                        Gen._record_var_signedness(VarName, False)
                        if self.Trans.VarScopes:
                            self.Trans.VarScopes[-1][VarName] = ElemTypeInfo
                        return
                    # 有列表字面量值，继续走数组路径（count_node=None 时从列表长度推断）
                count_node: ast.expr | None = parse_result.count_node
                ArrayCount: int = self.ParseArrayCount(count_node, Gen, Node.value, mode='local')
                VarType = ir.ArrayType(ElemType, ArrayCount)
                var = Gen._allocaEntry(VarType, name=VarName)
                Gen.variables[VarName] = var
                Gen._record_var_signedness(VarName, False)
                if Node.value and isinstance(Node.value, ast.List):
                    InitConstants: list[ir.Constant] | None = self.Trans._BuildArrayInitConstants(Node.value, ElemType, elem_type_node, ArrayCount, Gen, byte_order=ElemTypeInfo.ByteOrder if ElemTypeInfo else '')
                    if InitConstants:
                        try:
                            InitVal: ir.Constant = ir.Constant(VarType, InitConstants)
                            Gen.builder.store(InitVal, var)
                        except Exception as _e:
                            if _config_mode == "strict":
                                self.Trans.LogWarning(f"异常被忽略: {_e}")
                elif Node.value and isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str):
                    str_val: str = Node.value.value + '\x00'
                    str_bytes: bytearray = bytearray(str_val, 'utf-8')
                    if isinstance(VarType, ir.ArrayType) and len(str_bytes) < VarType.count:
                        str_bytes.extend(b'\x00' * (VarType.count - len(str_bytes)))
                    try:
                        InitVal: ir.Constant = ir.Constant(VarType, str_bytes[:VarType.count] if isinstance(VarType, ir.ArrayType) else str_bytes)
                        Gen.builder.store(InitVal, var)
                    except Exception as _e:
                        if _config_mode == "strict":
                            self.Trans.LogWarning(f"异常被忽略: {_e}")
                if self.Trans.VarScopes:
                    self.Trans.VarScopes[-1][VarName] = ElemTypeInfo
                # 记录数组元素字节序
                if ElemTypeInfo and ElemTypeInfo.ByteOrder == 'big' and isinstance(ElemType, ir.IntType) and ElemType.width in (16, 32, 64):
                    Gen.local_var_byteorders[VarName] = 'big'
                return
            # list[T] 泛型类注解 + list 字面量值 → 构造 list[T] 对象 + append 序列
            # （list[str] = ["a", "b"] 不应走 C 数组路径，而应构造 list[str] 对象）
            # 支持两种注解形式：list[T] 和 list[T] | t.CPtr
            list_sub: ast.Subscript | None = None
            if (isinstance(Node.annotation, ast.Subscript)
                    and isinstance(Node.annotation.value, ast.Name)
                    and Node.annotation.value.id == 'list'):
                list_sub = Node.annotation
            elif (isinstance(Node.annotation, ast.BinOp)
                    and isinstance(Node.annotation.op, ast.BitOr)):
                for side in (Node.annotation.left, Node.annotation.right):
                    if (isinstance(side, ast.Subscript)
                            and isinstance(side.value, ast.Name)
                            and side.value.id == 'list'):
                        list_sub = side
                        break
            if (list_sub is not None
                    and not isinstance(list_sub.slice, ast.Tuple)
                    and Node.value is not None
                    and isinstance(Node.value, ast.List)
                    and hasattr(self.Trans.ClassHandler, '_generic_class_templates')
                    and 'list' in self.Trans.ClassHandler._generic_class_templates):
                self._HandleGenericListLiteralAssign(VarName, Node, Gen, list_sub)
                return
            if TypeInfo.IsVoid and isinstance(Node.annotation, ast.BinOp):
                found: str | None = FindStructNameInAnnotation(Node.annotation, Gen.structs)
                if found:
                    TypeInfo = CTypeInfo()
                    TypeInfo.BaseType = t.CStruct(name=found)
                    TypeInfo.PtrCount = 1
                    IsPtr = True
                elif isinstance(Node.annotation.left, ast.Attribute):
                    AttrTypeInfo: CTypeInfo | None = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.annotation.left)
                    if AttrTypeInfo and AttrTypeInfo.BaseType:
                        TypeInfo = AttrTypeInfo
                        TypeInfo.PtrCount = max(TypeInfo.PtrCount, 1)
                        IsPtr = True
            # 对于局部变量声明 s: TestStruct（不带 | t.CPtr），应为栈上结构体而非指针
            # GetCTypeInfo 默认设置 PtrCount=1，但纯结构体名注解应为值类型
            if (isinstance(Node.annotation, ast.Name)
                    and Node.annotation.id in Gen.structs
                    and TypeInfo.IsStruct
                    and Node.annotation.id not in Gen.class_vtable):
                TypeInfo.PtrCount = 0
                IsPtr = False
            VarType: ir.Type = Gen._ctype_to_llvm(TypeInfo)
            if not IsPtr and TypeInfo.IsStruct and TypeInfo.Name:
                stripped: str = TypeInfo.Name
                if stripped in Gen.class_vtable and stripped in Gen.structs:
                    VarType = ir.PointerType(Gen.structs[stripped])
                    IsPtr = True
            if isinstance(VarType, ir.IdentifiedStructType):
                struct_name: str = getattr(VarType, 'name', '')
                if struct_name and Gen.class_vtable:
                    for cls_name in Gen.class_vtable:
                        if struct_name.endswith(f'.{cls_name}') or struct_name == cls_name:
                            VarType = ir.PointerType(VarType)
                            IsPtr = True
                            break
            if isinstance(VarType, ir.VoidType):
                VarType = ir.IntType(32)
            IsUnsigned: bool = TypeInfo.IsUInt
            # 修复 3: BinOp 注解（如 ast.Arguments | t.CPtr）的 var_struct_class 设置
            # TypeInfo.Name 由 _HandleSubscript 设置（特化名如 list[sha1.ASTptr]）或
            # GetCTypeInfo 设置（普通结构体名），经 _MergeCTypeInfoInto 传播后保留。
            # 此处确保 BinOp 注解的变量也能被 _get_var_class 识别，避免方法调用分派
            # fallthrough 到 char pointer fallback 错误匹配其他类（如 AST.__len__）。
            # 使用 not in 条件，不覆盖后续 L337-339/L396-398 对 ast.Name 注解的精确设置。
            if TypeInfo.IsStruct and TypeInfo.Name and TypeInfo.Name in Gen.structs:
                if VarName not in Gen.var_struct_class:
                    Gen.var_struct_class[VarName] = TypeInfo.Name
                    Gen.global_struct_class[VarName] = TypeInfo.Name
            if VarName in Gen._reg_values:
                OldVal: ir.Value = Gen._reg_values[VarName]
                if isinstance(OldVal.type, ir.PointerType):
                    var: ir.AllocaInstr = Gen._allocaEntry(OldVal.type, name=VarName)
                    Gen._store(OldVal, var)
                    Gen.variables[VarName] = var
                    del Gen._reg_values[VarName]
                    if Node.value:
                        InitValue: ir.Value | None = self.HandleExprLlvm(Node.value, VarType=VarType)
                        if InitValue:
                            self._StoreOrStrCopy(VarName, var, InitValue)
                    Gen._record_var_signedness(VarName, IsUnsigned)
                    return
                del Gen._reg_values[VarName]
            InitValue: ir.Value | None = None
            if Node.value:
                InitValue = self.HandleExprLlvm(Node.value, VarType=VarType)
            if VarName in Gen._reg_values:
                del Gen._reg_values[VarName]
            if VarName in Gen.variables and Gen.variables[VarName] is not None:
                if InitValue and isinstance(InitValue.type, ir.PointerType):
                    pointee: ir.Type = InitValue.type.pointee
                    if isinstance(pointee, ir.IdentifiedStructType):
                        struct_name: str = getattr(pointee, 'name', '')
                        is_vtable_class: bool = False
                        for cls_name in Gen.class_vtable:
                            if struct_name.endswith(f'.{cls_name}') or struct_name == cls_name:
                                is_vtable_class = True
                                break
                        if is_vtable_class:
                            var: ir.AllocaInstr = Gen._allocaEntry(InitValue.type, name=VarName)
                            Gen._store(InitValue, var)
                            Gen.variables[VarName] = var
                            if isinstance(Node.annotation, ast.Name) and Node.annotation.id in Gen.structs:
                                Gen.var_struct_class[VarName] = Node.annotation.id
                                Gen.global_struct_class[VarName] = Node.annotation.id
                            Gen._record_var_signedness(VarName, IsUnsigned)
                            return
                if InitValue:
                    try:
                        VarPtr: ir.Value = Gen.variables[VarName]
                        if isinstance(VarPtr.type, ir.PointerType):
                            TargetType: ir.Type = VarPtr.type.pointee
                            if InitValue.type != TargetType:
                                if isinstance(InitValue.type, ir.IntType) and isinstance(TargetType, ir.IntType):
                                    if TargetType.width > InitValue.type.width:
                                        InitValue = Gen.builder.zext(InitValue, TargetType, name=f"zext_{VarName}")
                                    elif TargetType.width < InitValue.type.width:
                                        InitValue = Gen.builder.trunc(InitValue, TargetType, name=f"trunc_{VarName}")
                                elif isinstance(InitValue.type, ir.PointerType) and isinstance(TargetType, ir.PointerType):
                                    InitValue = Gen.builder.bitcast(InitValue, TargetType, name=f"cast_{VarName}")
                        Gen._store(InitValue, VarPtr)
                    except Exception as _e:
                        if _config_mode == "strict":
                            self.Trans.LogWarning(f"异常被忽略: {_e}")
                Gen._record_var_signedness(VarName, IsUnsigned)
                return
            if VarName in Gen.global_vars:
                if VarName in Gen.module.globals:
                    GVar: ir.GlobalVariable = Gen.module.globals[VarName]
                    if InitValue:
                        Gen._store(InitValue, GVar)
                    Gen.variables[VarName] = GVar
                Gen._record_var_signedness(VarName, IsUnsigned)
                return
            var: ir.AllocaInstr = Gen._allocaEntry(VarType, name=VarName)
            if InitValue and isinstance(InitValue.type, ir.PointerType):
                pointee: ir.Type = InitValue.type.pointee
                # 当 InitValue 是 i8* (t.CPtr) 且注解是 Gen.structs 中的结构体名时，
                # bitcast 为对应的结构体指针，以便正确存储和设置 var_struct_class
                # 例如: sub: dict = sub_p (sub_p 是 t.CPtr)
                if (isinstance(pointee, ir.IntType) and pointee.width == 8
                        and isinstance(Node.annotation, ast.Name)
                        and Node.annotation.id in Gen.structs):
                    TargetStructType: ir.Type = Gen.structs[Node.annotation.id]
                    if isinstance(TargetStructType, ir.PointerType):
                        TargetStructType = TargetStructType.pointee
                    InitValue = Gen.builder.bitcast(InitValue, ir.PointerType(TargetStructType), name=f"cast_{VarName}_to_{Node.annotation.id}")
                    pointee = InitValue.type.pointee
                if isinstance(pointee, ir.IdentifiedStructType):
                    struct_name: str = getattr(pointee, 'name', '')
                    is_vtable_class: bool = False
                    for cls_name in Gen.class_vtable:
                        if struct_name.endswith(f'.{cls_name}') or struct_name == cls_name:
                            is_vtable_class = True
                            break
                    if is_vtable_class and not isinstance(VarType, ir.PointerType):
                        var = Gen._allocaEntry(InitValue.type, name=VarName)
                        VarType = InitValue.type
                        IsPtr = True
                        Gen._store(InitValue, var)
                        Gen.variables[VarName] = var
                        if isinstance(Node.annotation, ast.Name) and Node.annotation.id in Gen.structs:
                            Gen.var_struct_class[VarName] = Node.annotation.id
                            Gen.global_struct_class[VarName] = Node.annotation.id
                        Gen._record_var_signedness(VarName, IsUnsigned)
                        return
                    for CN, ST in Gen.structs.items():
                        if pointee is ST or pointee == ST:
                            if CN != Gen.var_struct_class.get(VarName):
                                Gen.var_struct_class[VarName] = CN
                                Gen.global_struct_class[VarName] = CN
                            if isinstance(VarType, ir.PointerType) and VarType.pointee is not ST and VarType.pointee != ST:
                                var = Gen._allocaEntry(ir.PointerType(pointee), name=VarName)
                                VarType = ir.PointerType(pointee)
                            break
            if InitValue:
                try:
                    if InitValue.type != VarType:
                        if isinstance(InitValue.type, ir.IntType) and isinstance(VarType, ir.IntType):
                            if VarType.width > InitValue.type.width:
                                InitValue = Gen.builder.zext(InitValue, VarType, name=f"zext_{VarName}")
                            elif VarType.width < InitValue.type.width:
                                InitValue = Gen.builder.trunc(InitValue, VarType, name=f"trunc_{VarName}")
                        elif isinstance(InitValue.type, ir.PointerType) and isinstance(VarType, ir.PointerType):
                            InitValue = Gen.builder.bitcast(InitValue, VarType, name=f"cast_{VarName}")
                        elif isinstance(VarType, ir.PointerType) and isinstance(InitValue.type, ir.IntType):
                            InitValue = Gen.builder.inttoptr(InitValue, VarType, name=f"int2ptr_{VarName}")
                        elif isinstance(VarType, ir.IntType) and isinstance(InitValue.type, ir.PointerType):
                            InitValue = Gen.builder.ptrtoint(InitValue, VarType, name=f"ptr2int_{VarName}")
                    # 大端局部变量：存储时 bswap
                    InitValue = Gen._apply_bswap_if_big(InitValue, TypeInfo.ByteOrder, f"bswap_store_{VarName}")
                    Gen._store(InitValue, var)
                except Exception as _e:
                    if _config_mode == "strict":
                        self.Trans.LogWarning(f"异常被忽略: {_e}")
            Gen.variables[VarName] = var
            Gen._record_var_signedness(VarName, IsUnsigned)
            # FakeDuck: 初始化影子结构体 a__meta__ 的字段
            _meta_name_check: str = f"{VarName}__meta__"
            if _meta_name_check in Gen.variables and '_str' in Gen.structs:
                _meta_var_init: ir.Value = Gen.variables[_meta_name_check]
                _str_st: ir.Type = Gen.structs['_str']
                # __data__ 字段 = 字符串指针
                _data_off = Gen._get_member_offset('__data__', '_str')
                if _data_off is not None and InitValue:
                    _data_ptr = Gen.builder.gep(_meta_var_init, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), _data_off)], name=f"{VarName}_meta_data")
                    Gen._store(InitValue, _data_ptr)
                # __mbuddy__ 字段 = NULL
                _mpool_off = Gen._get_member_offset('__mbuddy__', '_str')
                if _mpool_off is not None:
                    _mpool_ptr = Gen.builder.gep(_meta_var_init, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), _mpool_off)], name=f"{VarName}_meta_mbuddy")
                    Gen._store(ir.Constant(ir.PointerType(ir.IntType(8)), None), _mpool_ptr)
                # FakeDuck: 从 with 上下文自动注入 requires 字段（如 __mbuddy__）
                self.Trans.ExprCallHandle._InjectRequiresFields(_meta_var_init, '_str', Gen)
            # 记录局部变量字节序
            if TypeInfo.ByteOrder == 'big':
                if isinstance(VarType, ir.IntType) and VarType.width in (16, 32, 64):
                    Gen.local_var_byteorders[VarName] = 'big'
                elif isinstance(VarType, ir.ArrayType) and isinstance(VarType.element, ir.IntType) and VarType.element.width in (16, 32, 64):
                    Gen.local_var_byteorders[VarName] = 'big'

            if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr):
                found_struct: str | None = FindStructNameInAnnotation(Node.annotation, Gen.structs)
                if found_struct:
                    Gen.var_struct_class[VarName] = found_struct
                    Gen.global_struct_class[VarName] = found_struct

            if InitValue and isinstance(InitValue.type, ir.PointerType):
                pointee: ir.Type = InitValue.type.pointee
                if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)):
                    for CN, ST in Gen.structs.items():
                        if pointee == ST:
                            Gen._var_to_heap_ptr[VarName] = InitValue
                            if CN != Gen.var_struct_class.get(VarName):
                                Gen.var_struct_class[VarName] = CN
                                Gen.global_struct_class[VarName] = CN
                            break

            if self.Trans.VarScopes:
                if TypeInfo:
                    self.Trans.VarScopes[-1][VarName] = TypeInfo
                else:
                    DefaultInfo: CTypeInfo = CTypeInfo()
                    DefaultInfo.BaseType = t.CInt
                    self.Trans.VarScopes[-1][VarName] = DefaultInfo
        elif isinstance(Node.target, ast.Attribute):
            if isinstance(Node.target.value, ast.Name) and Node.target.value.id == 'self':
                if Node.value:
                    AttrVarType: Any = None
                    try:
                        if IsListAnnotation(Node.annotation):
                            slice_node: ast.AST = Node.annotation.slice
                            if isinstance(slice_node, ast.Name):
                                AttrVarType = f't.CArray[{slice_node.id}]'
                            elif isinstance(slice_node, ast.Tuple):
                                elts: str = ', '.join(getattr(e, 'id', str(e)) for e in slice_node.elts)
                                AttrVarType = f't.CArray[{elts}]'
                            elif isinstance(slice_node, ast.Attribute):
                                # 还原 t.xxx 形式（如 t.CInt、t.CArray）
                                if isinstance(slice_node.value, ast.Name):
                                    AttrVarType = f't.CArray[{slice_node.value.id}.{slice_node.attr}]'
                                else:
                                    AttrVarType = f't.CArray[{ast.unparse(slice_node)}]'
                        if AttrVarType is None:
                            AttrTypeInfo: CTypeInfo | None = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable)
                            if AttrTypeInfo:
                                AttrVarType = Gen._ctype_to_llvm(AttrTypeInfo)
                    except Exception as _e:
                        if _config_mode == "strict":
                            raise
                        _vlog().warning(f"解析类型失败: {_e}", "Exception")
                    Value: ir.Value | None = self.HandleExprLlvm(Node.value, VarType=AttrVarType)
                    if Value:
                        self._HandleAttributeStoreLlvm(Node.target, Value)
                        AttrName: str = Node.target.attr
                        len_name: str = f'{AttrName}__len'
                        ClassName: str | None = self._CurrentCpythonObjectClass
                        if not ClassName:
                            self_var: ir.Value | None = Gen.variables.get('self')
                            if self_var:
                                var_type: ir.Type = self_var.type
                                if isinstance(var_type, ir.PointerType) and isinstance(var_type.pointee, ir.PointerType):
                                    var_type = var_type.pointee
                                if isinstance(var_type, ir.PointerType):
                                    pointee: ir.Type = var_type.pointee
                                    for cn, st in Gen.structs.items():
                                        if st == pointee:
                                            ClassName = cn
                                            break
                        if ClassName and ClassName in Gen.class_members:
                            for m_name, m_type in Gen.class_members[ClassName]:
                                if m_name == len_name:
                                    list_len: ir.Constant | None = None
                                    if isinstance(Node.value, ast.List):
                                        list_len = ir.Constant(ir.IntType(64), len(Node.value.elts))
                                    if list_len is not None:
                                        SelfVar: ir.Value | None = Gen._get_var_ptr('self')
                                        if SelfVar:
                                            SelfPtr: ir.Value = Gen._load(SelfVar, name="self")
                                            offset: int = Gen._get_member_offset(len_name, ClassName)
                                            LenPtr: ir.Value = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=len_name)
                                            Gen._store(list_len, LenPtr)
                                    break