snapshot before regression test
This commit is contained in:
832
lib/core/Handles/HandlesBase.py
Normal file
832
lib/core/Handles/HandlesBase.py
Normal file
@@ -0,0 +1,832 @@
|
||||
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'
|
||||
Reference in New Issue
Block a user