from __future__ import annotations from typing import TYPE_CHECKING, List, Any if TYPE_CHECKING: from lib.core.translator import Translator from lib.core.LlvmCodeGenerator import LlvmCodeGenerator import ast from enum import IntFlag, auto from llvmlite import ir as _ir from lib.constants import config as _config from lib.includes import t from lib.includes.t import CTypeRegistry from lib.core.TypeSpec import TypeSpec, SymbolMeta, FIELD_ROUTES from lib.core.VLogger import get_logger as _vlog EXCEPTION_CODE_MAP: dict[str, int] = { 'ValueError': 1, 'TypeError': 2, 'RuntimeError': 3, 'ZeroDivisionError': 4, 'IndexError': 5, 'KeyError': 6, 'IOError': 7, 'OSError': 8, 'AssertionError': 9, 'Exception': 99, } class FuncMeta(IntFlag): NONE = 0 STATIC_METHOD = auto() PROPERTY_GETTER = auto() PROPERTY_SETTER = auto() PROPERTY_DELETER = auto() CLASS_METHOD = auto() ABSTRACT = auto() class _Delegated: """CTypeInfo 旧字段名委托描述符 — 静态委托到 _ts/_sm 的字段 替代旧的 FIELD_ROUTES + __setattr__/__getattr__ 动态路由: 描述符在类创建时绑定,访问时直接走 __get__/__set__, 无 dict 查找和字符串比较的运行时开销。 """ __slots__ = ('_target_attr', '_field_name') def __init__(self, target_attr: str, field_name: str) -> None: self._target_attr: str = target_attr # '_ts' or '_sm' self._field_name: str = field_name def __get__(self, obj: Any, objtype: type | None = None) -> Any: if obj is None: return self target: Any = object.__getattribute__(obj, self._target_attr) return getattr(target, self._field_name) def __set__(self, obj: Any, value: Any) -> None: target: Any = object.__getattribute__(obj, self._target_attr) setattr(target, self._field_name, value) class CTypeInfo: """ C 类型信息对象 - 统一符号表条目和类型计算 设计原则: - BaseType 是 CType 实例(来自 t 模块),永远不使用硬编码字符串 - 描述符分为两种: - VarConst/VarVolatile: 变量本身(指针)的限定符,如 int * const - DataConst/DataVolatile: 指向数据的限定符,如 const int * 属性(类型计算): - BaseType: t.CType - 基础类型实例 (如 t.CInt(), t.CVoid()) - PtrCount: int - 指针层数 - VarConst: bool - 变量本身(指针)是否 const,如 int * const - VarVolatile: bool - 变量本身(指针)是否 volatile - DataConst: bool - 指向的数据是否 const,如 const int * - DataVolatile: bool - 指向的数据是否 volatile - ArrayDims: List[str] - 数组维度 - Storage: t.CType - 存储类 (static, extern 等) - IsFuncPtr: bool - 是否函数指针 - FuncPtrParams: List[Tuple[str, CTypeInfo]] - 函数指针参数列表,每个元素是 (参数名, 参数类型) - FuncPtrReturn: CTypeInfo - 函数指针返回类型 - IsBitField: bool - 是否位域 - BitWidth: int - 位域宽度 - IsTypedef/IsStruct/IsEnum/IsUnion: bool - 类型种类 属性(符号表元数据): - Name: str - 名称(struct/enum/union/typedef 名) - Members: Dict[str, CTypeInfo] - 成员字典(用于 struct/union) - OriginalType: str - typedef 的原始类型 - DeclaredType: str - 声明类型 - CreturnTypes: list - C 返回类型列表 - Lineno: int - 定义行号 - IsAnonymous: bool - 是否匿名类型 - IsCpythonObject: bool - 是否 CPython 对象 - IsEnumMember: bool - 是否枚举成员 """ def __init__(self) -> None: object.__setattr__(self, '_ts', TypeSpec()) sm: SymbolMeta = SymbolMeta() sm.meta_list = FuncMeta.NONE object.__setattr__(self, '_sm', sm) # --- 新公共 API:供新代码直接访问 TypeSpec / SymbolMeta / SymbolKind --- @property def ts(self) -> TypeSpec: """TypeSpec — 纯类型描述(只读)""" return self._ts @property def sm(self) -> SymbolMeta: """SymbolMeta — 符号表元数据(只读)""" return self._sm @property def kind(self) -> 'SymbolKind': """SymbolKind — 符号类型种类枚举""" return self._sm.kind # 注:旧字段名(PtrCount/IsStruct/Name 等)的委托通过 _Delegated 描述符实现, # 在模块末尾从 FIELD_ROUTES 静态绑定,无需 __setattr__/__getattr__ 动态路由 @property def BaseType(self) -> t.CType | tuple | None: return self._ts._base_type @BaseType.setter def BaseType(self, value: t.CType | type | tuple | List | None) -> None: """设置 BaseType,接受以下类型: - None: 清空 - t.CType 实例: 单个类型,自动设置 IsStruct/IsEnum/IsUnion 标志 - type (CType 子类): 如 t.CStruct,自动实例化 - tuple/list of t.CType: 多个组合类型 """ ts: TypeSpec = self._ts sm: SymbolMeta = self._sm if value is None: ts._base_type = None sm.is_struct = False sm.is_enum = False sm.is_union = False sm.is_renum = False return if isinstance(value, (tuple, list)): ts._base_type = tuple(value) for v in value: if isinstance(v, t.CStruct): sm.is_struct = True elif isinstance(v, t.CEnum): sm.is_enum = True elif isinstance(v, t.CUnion): sm.is_union = True elif isinstance(v, t.REnum): sm.is_renum = True sm.is_enum = True return if isinstance(value, type) and issubclass(value, t.CType): ts._base_type = value() return if isinstance(value, t.CType): ts._base_type = value if isinstance(value, t.CStruct): sm.is_struct = True sm.is_enum = False sm.is_union = False sm.is_renum = False elif isinstance(value, t.REnum): sm.is_renum = True sm.is_enum = True sm.is_struct = False sm.is_union = False elif isinstance(value, t.CEnum): sm.is_enum = True sm.is_struct = False sm.is_union = False sm.is_renum = False elif isinstance(value, t.CUnion): sm.is_union = True sm.is_struct = False sm.is_enum = False sm.is_renum = False return raise TypeError(f"BaseType must be t.CType instance, type subclass, or tuple of t.CType, got {type(value)}") @property def TypeCls(self) -> type | None: """获取 CType 类(从 BaseType 推断)""" bt: t.CType | tuple | None = self._ts._base_type if bt: return type(bt) sm: SymbolMeta = self._sm if sm.is_struct: return t.CStruct if sm.is_enum: return t.CEnum if sm.is_union: return t.CUnion if sm.is_typedef: return t._CTypedef return None @property def IsPtr(self) -> bool: return self._ts.ptr_count > 0 @property def IsVoid(self) -> bool: return isinstance(self._ts._base_type, t.CVoid) @property def IsStr(self) -> bool: return isinstance(self._ts._base_type, t.CChar) and self._ts.ptr_count > 0 @property def IsInt(self) -> bool: bt: t.CType | tuple | None = self._ts._base_type return isinstance(bt, t.CType) and getattr(bt, 'IsSigned', None) is not None and bt.IsSigned is True and not isinstance(bt, t.CVoid) @property def IsUInt(self) -> bool: bt: t.CType | tuple | None = self._ts._base_type return isinstance(bt, t.CType) and getattr(bt, 'IsSigned', None) is False @property def IsFloat(self) -> bool: bt: t.CType | tuple | None = self._ts._base_type return isinstance(bt, t.CType) and getattr(bt, 'IsSigned', None) is None and getattr(bt, 'Size', 0) in (32, 64, 128) and not isinstance(bt, t.CVoid) def ToString(self) -> str: ts: TypeSpec = self._ts sm: SymbolMeta = self._sm bt: t.CType | tuple | None = ts._base_type if ts.is_func_ptr: return 'Callable' parts: list[str] = [] if ts.storage and not isinstance(ts.storage, t.CExport): parts.append(type(ts.storage).__name__) if ts.data_const or ts.data_volatile: qualifiers: list[str] = [] if ts.data_const: qualifiers.append("const") if ts.data_volatile: qualifiers.append("volatile") parts.append("_".join(qualifiers)) if sm.is_typedef and sm.name: return sm.name elif sm.is_renum and sm.name: base_name: str = sm.name elif bt: if isinstance(bt, str): base_name = bt elif isinstance(bt, type) and issubclass(bt, t.CType): base_name = bt.__name__ elif isinstance(bt, t.CType): # 对命名的 CType(CStruct/CEnum/CUnion/REnum),优先使用其 name 属性 # 否则回退到类名(如 'CInt'、'CChar') _named: str | None = getattr(bt, 'name', None) base_name = _named if _named else type(bt).__name__ else: base_name = str(bt) else: base_name = "void" if ts.is_array_ptr: ptr_str: str = "" if ts.ptr_count > 0: ptr_str = "*" * ts.ptr_count if ts.array_ptr: inner: str = ts.array_ptr.ToString() if ptr_str: parts.append(f"{base_name} {ptr_str}({inner})") else: parts.append(f"{base_name} ({inner})") else: if ptr_str: parts.append(f"{base_name} {ptr_str}()") else: parts.append(f"{base_name} ()") elif ts.array_ptr: inner = ts.array_ptr.ToString() if ts.ptr_count > 0: parts.append(f"{base_name} {'*' * ts.ptr_count}({inner})") else: parts.append(f"{base_name} ({inner})") else: parts.append(base_name) if ts.ptr_count > 0: parts.append("*" * ts.ptr_count) if ts.var_const: parts.append("const") if ts.var_volatile: parts.append("volatile") for dim in ts.array_dims: if dim: parts.append(f"[{dim}]") else: parts.append("[]") return " ".join(parts) if parts else "void" @staticmethod def CreateFromTypeName(TypeName: str) -> "CTypeInfo": """从类型名字符串创建 CTypeInfo(兼容旧 API)""" info: CTypeInfo = CTypeInfo() if TypeName.startswith('struct '): info.BaseType = t.CStruct(name=TypeName[7:].strip()) if TypeName[7:].strip() else t.CStruct() elif TypeName.startswith('enum '): info.BaseType = t.CEnum(name=TypeName[5:].strip()) if TypeName[5:].strip() else t.CEnum() elif TypeName.startswith('union '): info.BaseType = t.CUnion(name=TypeName[6:].strip()) if TypeName[6:].strip() else t.CUnion() else: info.BaseType = t.CStruct(name=TypeName) return info # LLVM primitive type name → (CTypeClass, PtrCount) mapping # Used when generic type inference produces LLVM type names like 'i64', 'double', etc. _LLVM_PRIMITIVE_MAP: dict[str, tuple[type, int]] | None = None @classmethod def _get_llvm_primitive_map(cls) -> dict[str, tuple[type, int]]: if cls._LLVM_PRIMITIVE_MAP is not None: return cls._LLVM_PRIMITIVE_MAP cls._LLVM_PRIMITIVE_MAP = { 'void': (t.CVoid, 0), 'i1': (t.CInt, 0), 'i8': (t.CChar, 0), 'i16': (t.CShort, 0), 'i32': (t.CInt, 0), 'i64': (t.CLong, 0), 'i128': (t.CInt, 0), 'float': (t.CFloat, 0), 'double': (t.CDouble, 0), 'fp128': (t.CFloat128T, 0), } return cls._LLVM_PRIMITIVE_MAP @staticmethod def FromTypeName(TypeName: str) -> "CTypeInfo": """从简单类型名构造 CTypeInfo(不经过 FromStr 字符串解析)""" from lib.core.TypeAnnotationResolver import TypeAnnotationResolver return TypeAnnotationResolver.from_type_name(TypeName) # FromStr 已移除 - 类型解析不再经过中间字符串格式 # typedef 展开直接走 CTypeInfo 对象,不经过字符串解析 @staticmethod def TryEvalConstExpr(node: ast.AST, SymbolTable: Any) -> Any: from lib.core.TypeAnnotationResolver import TypeAnnotationResolver return TypeAnnotationResolver.try_eval_const_expr(node, SymbolTable) @classmethod def FromNode(cls, Node: ast.AST, SymbolTable: Any) -> "CTypeInfo": """从 AST 节点解析 CTypeInfo(类方法) Args: Node: AST 节点(如 ast.Name, ast.Attribute 等) SymbolTable: 符号表字典 """ from lib.core.TypeAnnotationResolver import TypeAnnotationResolver return TypeAnnotationResolver.from_node(Node, SymbolTable) def Copy(self) -> "CTypeInfo": NewInfo: CTypeInfo = CTypeInfo() NewInfo._ts = self._ts.copy() NewInfo._sm = self._sm.copy() # CTypeInfo 引用字段需要深拷贝 if isinstance(NewInfo._ts.func_ptr_return, CTypeInfo): NewInfo._ts.func_ptr_return = NewInfo._ts.func_ptr_return.Copy() if isinstance(NewInfo._ts.original_type, CTypeInfo): NewInfo._ts.original_type = NewInfo._ts.original_type.Copy() if NewInfo._ts.array_ptr: NewInfo._ts.array_ptr = NewInfo._ts.array_ptr.Copy() return NewInfo def get(self, key: str, default: Any = None) -> Any: """获取额外属性""" return self._sm._extra.get(key, default) def set(self, key: str, value: Any) -> None: """设置额外属性""" self._sm._extra[key] = value @staticmethod def VoidTypeInfo() -> "CTypeInfo": info: CTypeInfo = CTypeInfo() info.BaseType = t.CVoid() return info def ToLLVM(self, Gen: LlvmCodeGenerator) -> _ir.Type: if Gen is None: return _ir.IntType(32) return Gen._ctype_to_llvm(self) def __str__(self) -> str: return self.ToString() def __repr__(self) -> str: ts: TypeSpec = self._ts sm: SymbolMeta = self._sm return f"CTypeInfo(BaseType={ts._base_type}, PtrCount={ts.ptr_count}, IsTypedef={sm.is_typedef}, OriginalType={ts.original_type!r}, VarConst={ts.var_const}, DataConst={ts.data_const})" # 从 FIELD_ROUTES 静态绑定 _Delegated 描述符到 CTypeInfo 类 # 这是一次性配置(类创建期执行),替代运行时 __setattr__/__getattr__ 动态路由 for _old_name, (_target, _field) in FIELD_ROUTES.items(): setattr(CTypeInfo, _old_name, _Delegated('_' + _target, _field)) del _old_name, _target, _field class CTypeHelper: @staticmethod def GetTModuleCType(TypeName: str) -> type | None: result: type | None = CTypeRegistry.GetClassByName(TypeName) if result is not None: return result TypeClass: type | None = getattr(t, TypeName, None) if TypeClass and isinstance(TypeClass, type) and issubclass(TypeClass, t.CType): return TypeClass FallbackClass: type | None = getattr(t, f'_{TypeName}', None) if FallbackClass and isinstance(FallbackClass, type) and issubclass(FallbackClass, t.CType): return FallbackClass return None @staticmethod def GetCName(type_or_name: str | type) -> str: if isinstance(type_or_name, str): cls: type | None = CTypeRegistry.GetClassByName(type_or_name) if cls is None: cls = CTypeHelper.GetTModuleCType(type_or_name) if cls: return cls.__name__ return type_or_name elif isinstance(type_or_name, type) and issubclass(type_or_name, t.CType): return type_or_name.__name__ return '' class BuiltinTypeMap: """ 内置类型映射表 - 字符串到 (CType类, PtrCount) 的映射 用法:BuiltinTypeMap.Get('int') -> (t.CInt, 0) BuiltinTypeMap.Get('BYTEPTR') -> (t.CUnsignedChar, 1) """ _map: dict[str, tuple[type, int]] | None = None @classmethod def _build_map(cls) -> dict[str, tuple[type, int]]: if cls._map is not None: return cls._map CTypeRegistry._build() cls._map = {} # 仅使用 Python 类名 → (CType 类, ptr_level) 映射。 # C 类型名(如 'int'、'int32_t')不再通过 _cname_to_class 提供。 # C 头文件 stub 生成器使用独立的硬编码表(CTypeMapper._CNAME_TO_PY)。 for pyname, ctype_cls in CTypeRegistry._name_to_class.items(): pos: frozenset = getattr(ctype_cls, 'position', frozenset()) if t.CType.POINTER in pos and t.CType.BASE not in pos: cls._map[pyname] = (ctype_cls, 1) else: cls._map[pyname] = (ctype_cls, 0) # 保留一些常用的字符串速记(这些不是 CName,而是硬编码的便捷别名)。 # 包含 Python 内置类型名(int/float/bool)和 C 类型名速记(char/short/long 等)。 _SPECIAL: dict[str, tuple[type, int]] = { # Python 内置类型名 'str': (t.CChar, 1), 'bytes': (t.CChar, 1), 'int': (t.CInt, 0), 'float': (t.CFloat, 0), 'bool': (t.CBool, 0), # C 类型名速记 'char': (t.CChar, 0), 'short': (t.CShort, 0), 'long': (t.CLong, 0), 'long long': (t.CLongLong, 0), 'double': (t.CDouble, 0), 'unsigned': (t.CUnsigned, 0), 'signed': (t.CInt, 0), 'signed int': (t.CInt, 0), 'signed char': (t.CSignedChar, 0), 'void': (t.CVoid, 0), 'Void': (t.CVoid, 0), } for k, v in _SPECIAL.items(): if k not in cls._map: cls._map[k] = v _FLOAT_ALIASES: dict[str, tuple[type, int]] = { 'FLOAT8': (t.CFloat8T, 0), 'FLOAT16': (t.CFloat16T, 0), 'FLOAT32': (t.CFloat32T, 0), 'FLOAT64': (t.CFloat64T, 0), 'FLOAT128': (t.CFloat128T, 0), } for k, v in _FLOAT_ALIASES.items(): if k not in cls._map: cls._map[k] = v return cls._map @classmethod def Get(cls, type_name: str) -> tuple[type, int] | None: """获取类型类和指针层级""" return cls._build_map().get(type_name) class BaseHandle: def __init__(self, translator: "Translator") -> None: self.Trans: Translator = translator self._CurrentCpythonObjectClass: str | None = None @staticmethod def _is_char_pointer(val: _ir.Value) -> bool: """检查值是否为 char* (i8*) 指针""" if not isinstance(val.type, _ir.PointerType): return False pointee: _ir.Type = val.type.pointee return isinstance(pointee, _ir.IntType) and pointee.width == 8 def HandleExprLlvm(self, Node: ast.AST, VarType: _ir.Type | str | None = None) -> _ir.Value | None: return self.Trans.ExprHandler.HandleExprLlvm(Node, VarType) def HandleBodyLlvm(self, Body: ast.AST | list[ast.stmt]) -> Any: return self.Trans.BodyHandler.HandleBodyLlvm(Body) def _get_int_ptr(self, Node: ast.AST) -> _ir.Value | None: Gen: LlvmCodeGenerator = self.Trans.LlvmGen if isinstance(Node, ast.Name): if Node.id in Gen.variables: return Gen.variables[Node.id] elif isinstance(Node, ast.Attribute): obj_val: Any = self.HandleExprLlvm(Node.value) if not obj_val: return None if isinstance(obj_val.type, _ir.PointerType): pointee: _ir.Type = obj_val.type.pointee if isinstance(pointee, (_ir.IdentifiedStructType, _ir.LiteralStructType)): StructName: str | None = None if isinstance(pointee, _ir.IdentifiedStructType): StructName = pointee.name if not StructName: for ClassName, struct_type in Gen.structs.items(): if struct_type == pointee: StructName = ClassName break if StructName and StructName in Gen.structs: offset: int = self.Trans.ExprHandler._get_llvm_member_offset(Node.attr, StructName, Gen) member_ptr: Any = Gen.builder.gep(obj_val, [_ir.Constant(_ir.IntType(32), 0), _ir.Constant(_ir.IntType(32), offset)], name=f"{Node.attr}_ptr") return member_ptr return None def _IsTModuleType(self, TypeName: str) -> bool: if TypeName in ('t', 'State', 'Bit', 'Anonymous', 'Postdefinition'): return True TypeClass: type | None = getattr(t, TypeName, None) if TypeClass and isinstance(TypeClass, type): if issubclass(TypeClass, t.CType): return True FallbackClass: type | None = getattr(t, f'_{TypeName}', None) if FallbackClass and isinstance(FallbackClass, type): if issubclass(FallbackClass, t.CType): return True return False def ResolveListElementType( self, elem_type_node: ast.expr, Gen: Any, *, check_func_ptr: bool = False, handle_str: bool = False, void_fallback_width: int = 32, fallback_to_cint: bool = False, ) -> tuple[Any, CTypeInfo | None]: """解析 list 元素类型,返回 (LLVM类型, CTypeInfo|None)。 统一处理结构体、str、函数指针、VoidType 回退等变体。 Args: check_func_ptr: 是否检查函数指针(全局变量路径需要) handle_str: 是否处理 str → i8*(局部变量路径需要) void_fallback_width: VoidType 回退宽度 (32 或 8) fallback_to_cint: 无类型信息时回退到 CInt """ elem_type_info: CTypeInfo | None = CTypeInfo.FromNode(elem_type_node, self.Trans.SymbolTable) # 结构体类型 if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs: if check_func_ptr: sym_entry: CTypeInfo | None = self.Trans.SymbolTable.lookup(elem_type_node.id) if sym_entry and isinstance(sym_entry, CTypeInfo) and sym_entry.IsFuncPtr: return _ir.IntType(8).as_pointer(), elem_type_info return Gen.structs[elem_type_node.id], elem_type_info # str → i8* if handle_str and isinstance(elem_type_node, ast.Name) and elem_type_node.id == 'str': return _ir.PointerType(_ir.IntType(8)), elem_type_info # 函数指针检查 if check_func_ptr and elem_type_info and elem_type_info.IsFuncPtr: return _ir.IntType(8).as_pointer(), elem_type_info # 回退到 CInt if elem_type_info is None and fallback_to_cint: elem_type_info = CTypeInfo() elem_type_info.BaseType = t.CInt() elem_type: Any = Gen._ctype_to_llvm(elem_type_info) if isinstance(elem_type, _ir.VoidType): elem_type = _ir.IntType(void_fallback_width) return elem_type, elem_type_info def ParseArrayCount( self, count_node: ast.expr | None, Gen: Any, value_node: ast.expr | None = None, *, mode: str = 'global', ) -> int: """解析数组计数,返回计数(默认 1)。 统一处理 Constant/Name/Attribute/BinOp/None 等形式。 None 或 Constant(None) 时从 value_node 推断(List 长度或 str 长度+1)。 Args: count_node: 计数 AST 节点 value_node: 赋值右侧值节点(用于 count_node 为 None 时推断) mode: 'global' 使用 _eval_global_count + SymbolTable + _define_constants; 'local' 使用 TryEvalConstExpr """ # None 或 Constant(None) → 从 value_node 推断 if count_node is None or (isinstance(count_node, ast.Constant) and count_node.value is None): if value_node and isinstance(value_node, ast.List): return len(value_node.elts) if value_node and isinstance(value_node, ast.Constant) and isinstance(value_node.value, str): return len(value_node.value) + 1 return 1 # Constant(int) if isinstance(count_node, ast.Constant) and isinstance(count_node.value, int): return count_node.value if mode == 'global': # Name → SymbolTable + _define_constants if isinstance(count_node, ast.Name): ArrayCount: int = 1 if self.Trans.SymbolTable.has(count_node.id): sym_info: Any = self.Trans.SymbolTable[count_node.id] if isinstance(sym_info.value, int): ArrayCount = sym_info.value if ArrayCount == 1 and count_node.id in Gen._define_constants: def_val: Any = Gen._define_constants[count_node.id] if isinstance(def_val, int): ArrayCount = def_val return ArrayCount # Attribute / BinOp → _eval_global_count if isinstance(count_node, (ast.Attribute, ast.BinOp)): eval_fn: Any = getattr(self, '_eval_global_count', None) if eval_fn is not None: ev: int | None = eval_fn(count_node, Gen) if ev is not None: return ev return 1 else: # local mode → TryEvalConstExpr eval_count: Any = CTypeInfo.TryEvalConstExpr(count_node, self.Trans.SymbolTable) if eval_count is not None and isinstance(eval_count, int) and eval_count > 0: return eval_count return 1 return 1 def ResolveAnnotationType(self, annotation: ast.expr) -> CTypeInfo | None: """解析注解类型,BinOp(BitOr) 优先使用 MergeTypes,其他使用 FromNode。 统一处理函数返回类型和参数类型的 BinOp 联合类型解析。 """ if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): merger: Any = getattr(self.Trans, 'TypeMergeHandler', None) if merger: info: CTypeInfo | None = merger.MergeTypes(annotation) if info is not None and isinstance(info, CTypeInfo): return info return CTypeInfo.FromNode(annotation, self.Trans.SymbolTable) def CollectAnnAssignMember( self, item: ast.AST, Gen: Any ) -> tuple[str, _ir.Type, CTypeInfo | None] | None: """从 ast.AnnAssign 节点解析成员信息。 返回 (VarName, MemberType, TypeInfo);TypeInfo 为 None 表示解析回退到 i32。 非 AnnAssign/Name 目标时返回 None。 """ if not isinstance(item, ast.AnnAssign) or not isinstance(item.target, ast.Name): return None VarName: str = item.target.id try: TypeInfo: CTypeInfo | None = self.ResolveAnnotationType(item.annotation) if TypeInfo is None: TypeInfo = CTypeInfo() TypeInfo.BaseType = t.CInt() MemberType: _ir.Type = Gen._ctype_to_llvm(TypeInfo) if isinstance(MemberType, _ir.VoidType): MemberType = _ir.PointerType(_ir.IntType(8)) return VarName, MemberType, TypeInfo except Exception as e: _vlog().warning(f"HandlesBase: 忽略异常 {e}", exc_info=e) return VarName, _ir.IntType(32), None def LookupFunctionSymbol(self, name: str, *, module_path: str | None = None) -> CTypeInfo | None: """查找函数符号,先尝试 module_path.name,再回退到 name。 统一处理 HandlesExprCall / HandlesAssign 中重复的二级查找模式。 返回 CTypeInfo(不限定 IsFunction),由调用方检查标志位。 """ st = self.Trans.SymbolTable if module_path: sym: CTypeInfo | None = st.lookup(f'{module_path}.{name}') if sym: return sym return st.lookup(name) def BuildLLVMFuncTypeFromSig( self, sym_info: CTypeInfo, Gen: Any, *, mangled_name: str | None = None, use_infer_fallback: bool = False, ) -> tuple[Any, list[Any], bool] | None: """从 CTypeInfo 函数签名构建 LLVM 函数类型。 返回 (ret_type, llvm_param_types, is_variadic),非函数返回 None。 统一处理 FuncPtrReturn/FuncPtrParams → ToLLVM 转换、VoidType 回退。 Args: mangled_name: 用于 _infer_return_type + stub 查找回退 use_infer_fallback: 为 True 时启用 _infer_return_type + stub 查找回退链 """ if not sym_info.IsFunction: return None is_variadic: bool = sym_info.IsVariadic ret_type_info = sym_info.FuncPtrReturn if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType: ret_type: Any = ret_type_info.ToLLVM(Gen) elif use_infer_fallback and mangled_name: inferred: Any = Gen._infer_return_type(mangled_name) if isinstance(inferred, _ir.IntType) and inferred.width == 32: try: stub_ft: Any = self.Trans.ImportHandler._LookupStubFuncType(mangled_name, Gen) if stub_ft and hasattr(stub_ft, 'return_type'): inferred = stub_ft.return_type except Exception: pass ret_type = inferred else: ret_type = Gen._CType2LLVM('i32', False) param_type_infos = [pt for _, pt in (sym_info.FuncPtrParams or [])] if isinstance(ret_type, _ir.VoidType): ret_type = _ir.IntType(32) llvm_param_types: list[Any] = [] for pt in param_type_infos: if isinstance(pt, CTypeInfo) and pt.BaseType: lp: Any = pt.ToLLVM(Gen) else: lp = Gen._CType2LLVM(pt if isinstance(pt, str) else 'i32', '*' in pt if isinstance(pt, str) else False) if isinstance(lp, _ir.VoidType): lp = _ir.IntType(8).as_pointer() llvm_param_types.append(lp) return ret_type, llvm_param_types, is_variadic def GetOrCreateFuncDecl( self, name: str, ret_type: Any, param_types: list[Any], Gen: Any, *, is_variadic: bool = False, replace_name: str | None = None, ) -> Any: """创建或替换 LLVM 函数声明。 若 name 已存在且类型不匹配,通过 _replace_function_decl 替换。 replace_name 传递给 _replace_function_decl(通常为未 mangle 的 func_name)。 """ if name not in Gen.functions: func_type = _ir.FunctionType(ret_type, param_types, var_arg=is_variadic) func_decl = _ir.Function(Gen.module, func_type, name=name) Gen.functions[name] = func_decl else: existing = Gen.functions[name] existing_type = getattr(existing, 'ftype', None) new_type = _ir.FunctionType(ret_type, param_types, var_arg=is_variadic) if existing_type and existing_type != new_type: replaced = self.Trans.FunctionHandler._replace_function_decl(Gen, replace_name or name, new_type) if replaced and replaced != existing: Gen.functions[name] = replaced return Gen.functions[name] def GetOrCreateStubFuncDecl( self, decl_name: str, stub_func_type: Any, Gen: Any, *, alias: str | None = None, check_existing: bool = True, ) -> Any: """创建 stub 函数声明,可选注册别名。 check_existing=False 时跳过存在性检查(用于确定不存在的场景)。 """ if check_existing and decl_name in Gen.functions: func_decl = Gen.functions[decl_name] else: func_decl = _ir.Function(Gen.module, stub_func_type, name=decl_name) Gen.functions[decl_name] = func_decl if alias and alias != decl_name: if not check_existing or alias not in Gen.functions: Gen.functions[alias] = func_decl return func_decl StrictMode: bool = _config.mode == 'strict'