619 lines
23 KiB
Python
619 lines
23 KiB
Python
from __future__ import annotations
|
||
from typing import TYPE_CHECKING, Dict, Tuple
|
||
if TYPE_CHECKING:
|
||
from lib.core.translator import Translator
|
||
from lib.constants import config as _config
|
||
from lib.includes import t
|
||
|
||
import ast
|
||
from typing import List, Dict
|
||
from enum import IntFlag, auto
|
||
from lib.core.TypeSpec import TypeSpec, SymbolMeta, FIELD_ROUTES
|
||
|
||
|
||
EXCEPTION_CODE_MAP = {
|
||
'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 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):
|
||
object.__setattr__(self, '_ts', TypeSpec())
|
||
sm = 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
|
||
|
||
def __setattr__(self, name, value):
|
||
"""属性设置路由 — 将旧字段名委托到 _ts/_sm/_kind_flags"""
|
||
if name == 'BaseType':
|
||
# BaseType 有复杂的 property setter(自动设置 IsStruct/IsEnum/IsUnion)
|
||
CTypeInfo.BaseType.fset(self, value)
|
||
return
|
||
if name in ('_ts', '_sm', 'ts', 'sm', 'kind'):
|
||
# _ts/_sm 内部字段直接设置;ts/sm/kind 是只读 property,禁止设置
|
||
if name in ('ts', 'sm', 'kind'):
|
||
raise AttributeError(f"'CTypeInfo' attribute '{name}' is read-only")
|
||
object.__setattr__(self, name, value)
|
||
return
|
||
if name in FIELD_ROUTES:
|
||
target, field = FIELD_ROUTES[name]
|
||
if target == 'ts':
|
||
setattr(self._ts, field, value)
|
||
elif target == 'sm':
|
||
setattr(self._sm, field, value)
|
||
elif target == 'kf':
|
||
self._sm._kind_flags[field] = value
|
||
return
|
||
object.__setattr__(self, name, value)
|
||
|
||
def __getattr__(self, name):
|
||
"""属性读取路由 — 将旧字段名委托到 _ts/_sm/_kind_flags"""
|
||
try:
|
||
ts = object.__getattribute__(self, '_ts')
|
||
sm = object.__getattribute__(self, '_sm')
|
||
except AttributeError:
|
||
raise AttributeError(f"'CTypeInfo' object has no attribute '{name}'")
|
||
if name in FIELD_ROUTES:
|
||
target, field = FIELD_ROUTES[name]
|
||
if target == 'ts':
|
||
return getattr(ts, field)
|
||
elif target == 'sm':
|
||
return getattr(sm, field)
|
||
elif target == 'kf':
|
||
return sm._kind_flags.get(field, False)
|
||
raise AttributeError(f"'CTypeInfo' object has no attribute '{name}'")
|
||
|
||
|
||
|
||
@property
|
||
def BaseType(self) -> t.CType | tuple:
|
||
return self._ts._base_type
|
||
|
||
@BaseType.setter
|
||
def BaseType(self, value: t.CType | type | tuple | List):
|
||
"""设置 BaseType,接受以下类型:
|
||
|
||
- None: 清空
|
||
- t.CType 实例: 单个类型,自动设置 IsStruct/IsEnum/IsUnion 标志
|
||
- type (CType 子类): 如 t.CStruct,自动实例化
|
||
- tuple/list of t.CType: 多个组合类型
|
||
"""
|
||
ts = self._ts
|
||
kf = self._sm._kind_flags
|
||
|
||
if value is None:
|
||
ts._base_type = None
|
||
kf['IsStruct'] = False
|
||
kf['IsEnum'] = False
|
||
kf['IsUnion'] = False
|
||
kf['IsRenum'] = False
|
||
return
|
||
|
||
if isinstance(value, (tuple, list)):
|
||
ts._base_type = tuple(value)
|
||
for v in value:
|
||
if isinstance(v, t.CStruct):
|
||
kf['IsStruct'] = True
|
||
elif isinstance(v, t.CEnum):
|
||
kf['IsEnum'] = True
|
||
elif isinstance(v, t.CUnion):
|
||
kf['IsUnion'] = True
|
||
elif isinstance(v, t.REnum):
|
||
kf['IsRenum'] = True
|
||
kf['IsEnum'] = 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):
|
||
kf['IsStruct'] = True
|
||
kf['IsEnum'] = False
|
||
kf['IsUnion'] = False
|
||
kf['IsRenum'] = False
|
||
elif isinstance(value, t.REnum):
|
||
kf['IsRenum'] = True
|
||
kf['IsEnum'] = True
|
||
kf['IsStruct'] = False
|
||
kf['IsUnion'] = False
|
||
elif isinstance(value, t.CEnum):
|
||
kf['IsEnum'] = True
|
||
kf['IsStruct'] = False
|
||
kf['IsUnion'] = False
|
||
kf['IsRenum'] = False
|
||
elif isinstance(value, t.CUnion):
|
||
kf['IsUnion'] = True
|
||
kf['IsStruct'] = False
|
||
kf['IsEnum'] = False
|
||
kf['IsRenum'] = 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):
|
||
"""获取 CType 类(从 BaseType 推断)"""
|
||
bt = self._ts._base_type
|
||
if bt:
|
||
return type(bt)
|
||
kf = self._sm._kind_flags
|
||
if kf.get('IsStruct'):
|
||
return t.CStruct
|
||
if kf.get('IsEnum'):
|
||
return t.CEnum
|
||
if kf.get('IsUnion'):
|
||
return t.CUnion
|
||
if kf.get('IsTypedef'):
|
||
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 = 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 = self._ts._base_type
|
||
return isinstance(bt, t.CType) and getattr(bt, 'IsSigned', None) is False
|
||
|
||
@property
|
||
def IsFloat(self) -> bool:
|
||
bt = 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)
|
||
|
||
@property
|
||
def IsDouble(self) -> bool:
|
||
bt = self._ts._base_type
|
||
return isinstance(bt, t.CDouble) or isinstance(bt, t.CFloat64T)
|
||
|
||
@property
|
||
def IsPointerToChar(self) -> bool:
|
||
return isinstance(self._ts._base_type, t.CChar) and self._ts.ptr_count > 0
|
||
|
||
def ToString(self) -> str:
|
||
ts = self._ts
|
||
sm = self._sm
|
||
kf = sm._kind_flags
|
||
bt = ts._base_type
|
||
|
||
if ts.is_func_ptr:
|
||
return 'Callable'
|
||
parts = []
|
||
|
||
if ts.storage and not isinstance(ts.storage, t.CExport):
|
||
parts.append(ts.storage.CName)
|
||
|
||
if ts.data_const or ts.data_volatile:
|
||
qualifiers = []
|
||
if ts.data_const:
|
||
qualifiers.append("const")
|
||
if ts.data_volatile:
|
||
qualifiers.append("volatile")
|
||
parts.append("_".join(qualifiers))
|
||
|
||
if kf.get('IsTypedef') and sm.name:
|
||
return sm.name
|
||
elif kf.get('IsRenum') and sm.name:
|
||
base_name = sm.name
|
||
elif bt:
|
||
base_name = getattr(bt, 'CName', None) or (bt if isinstance(bt, str) else str(bt))
|
||
else:
|
||
base_name = "void"
|
||
|
||
if ts.is_array_ptr:
|
||
ptr_str = ""
|
||
if ts.ptr_count > 0:
|
||
ptr_str = "*" * ts.ptr_count
|
||
if ts.array_ptr:
|
||
inner = 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()
|
||
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 = None
|
||
|
||
@classmethod
|
||
def _get_llvm_primitive_map(cls):
|
||
if cls._LLVM_PRIMITIVE_MAP is not None:
|
||
return cls._LLVM_PRIMITIVE_MAP
|
||
from lib.includes import t as _t
|
||
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, SymbolTable):
|
||
from lib.core.TypeAnnotationResolver import TypeAnnotationResolver
|
||
return TypeAnnotationResolver.try_eval_const_expr(node, SymbolTable)
|
||
|
||
@classmethod
|
||
def FromNode(cls, Node: ast.AST, SymbolTable: dict) -> "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()
|
||
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, default=None):
|
||
"""获取额外属性"""
|
||
return self._sm._extra.get(key, default)
|
||
|
||
def set(self, key, value):
|
||
"""设置额外属性"""
|
||
self._sm._extra[key] = value
|
||
|
||
@staticmethod
|
||
def VoidTypeInfo() -> "CTypeInfo":
|
||
info = CTypeInfo()
|
||
info.BaseType = t.CVoid()
|
||
return info
|
||
|
||
def ToLLVM(self, Gen):
|
||
from llvmlite import ir as _ir
|
||
if Gen is None:
|
||
return _ir.IntType(32)
|
||
return Gen._ctype_to_llvm(self)
|
||
|
||
def ToLLVMBase(self, Gen):
|
||
from llvmlite import ir as _ir
|
||
if Gen is None:
|
||
return _ir.IntType(32)
|
||
return Gen._base_ctype_to_llvm(self.BaseType, self)
|
||
|
||
def __str__(self) -> str:
|
||
return self.ToString()
|
||
|
||
def __repr__(self) -> str:
|
||
ts = self._ts
|
||
kf = self._sm._kind_flags
|
||
return f"CTypeInfo(BaseType={ts._base_type}, PtrCount={ts.ptr_count}, IsTypedef={kf.get('IsTypedef', False)}, OriginalType={ts.original_type!r}, VarConst={ts.var_const}, DataConst={ts.data_const})"
|
||
|
||
|
||
class CTypeHelper:
|
||
|
||
@staticmethod
|
||
def GetTModuleCType(TypeName: str):
|
||
from lib.includes.t import CTypeRegistry
|
||
result = CTypeRegistry.GetClassByName(TypeName)
|
||
if result is not None:
|
||
return result
|
||
TypeClass = getattr(t, TypeName, None)
|
||
if TypeClass and isinstance(TypeClass, type) and issubclass(TypeClass, t.CType):
|
||
return TypeClass
|
||
FallbackClass = 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:
|
||
from lib.includes.t import CTypeRegistry
|
||
if isinstance(type_or_name, str):
|
||
cls = CTypeRegistry.GetClassByName(type_or_name)
|
||
if cls is None:
|
||
cls = CTypeHelper.GetTModuleCType(type_or_name)
|
||
if cls:
|
||
return CTypeRegistry.CTypeToCName(cls) or type_or_name
|
||
return type_or_name
|
||
elif isinstance(type_or_name, type) and issubclass(type_or_name, t.CType):
|
||
return CTypeRegistry.CTypeToCName(type_or_name) or ''
|
||
return ''
|
||
|
||
@staticmethod
|
||
def StripTypePrefix(TypeStr: str) -> str:
|
||
for prefix in ('struct ', 'enum ', 'union '):
|
||
if TypeStr.startswith(prefix):
|
||
return TypeStr[len(prefix):].strip()
|
||
return TypeStr
|
||
|
||
@staticmethod
|
||
def IsVoidType(TypeStr: str) -> bool:
|
||
from lib.includes.t import CTypeRegistry
|
||
cls = CTypeRegistry.GetClassByName(TypeStr) or CTypeRegistry.CNameToClass(TypeStr)
|
||
if cls:
|
||
return CTypeRegistry.CTypeToLLVM(cls) == 'void'
|
||
return TypeStr == 'void' or TypeStr == 'struct void' or TypeStr == 'union void'
|
||
|
||
@staticmethod
|
||
def IsStrType(TypeStr: str) -> bool:
|
||
from lib.includes.t import CTypeRegistry
|
||
resolved = CTypeRegistry.ResolveName(TypeStr)
|
||
if resolved:
|
||
ctype_cls, ptr_level = resolved
|
||
if CTypeRegistry.CTypeToLLVM(ctype_cls) == 'i8' and ptr_level > 0:
|
||
return True
|
||
return TypeStr in ('str', 'bytes', 'struct str', 'union str', 'c_char')
|
||
|
||
|
||
class BuiltinTypeMap:
|
||
"""
|
||
内置类型映射表 - 字符串到 (CType类, PtrCount) 的映射
|
||
|
||
用法:BuiltinTypeMap.Get('int') -> (t.CInt, 0)
|
||
BuiltinTypeMap.Get('BYTEPTR') -> (t.CUnsignedChar, 1)
|
||
"""
|
||
|
||
_map = None
|
||
|
||
@classmethod
|
||
def _build_map(cls):
|
||
if cls._map is not None:
|
||
return cls._map
|
||
from lib.includes.t import CTypeRegistry
|
||
CTypeRegistry._build()
|
||
cls._map = {}
|
||
for cname, ctype_cls in CTypeRegistry._cname_to_class.items():
|
||
cls._map[cname] = (ctype_cls, 0)
|
||
for pyname, ctype_cls in CTypeRegistry._name_to_class.items():
|
||
pos = getattr(ctype_cls, 'position', frozenset())
|
||
if t.CType.POINTER in pos and t.CType.BASE not in pos:
|
||
cls._map[pyname] = (ctype_cls, 1)
|
||
elif pyname not in cls._map:
|
||
cls._map[pyname] = (ctype_cls, 0)
|
||
_SPECIAL = {
|
||
'str': (t.CChar, 1), 'bytes': (t.CChar, 1), 'unsigned': (t.CUnsigned, 0),
|
||
'signed': (t.CInt, 0), 'signed int': (t.CInt, 0),
|
||
'signed char': (t.CSignedChar, 0), 'bool': (t.CBool, 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
|
||
_PTR_ALIASES = {
|
||
'INTPTR': (t.CInt, 1), 'UINTPTR': (t.CUnsignedInt, 1),
|
||
'VOIDPTR': (t.CVoid, 1), 'BYTEPTR': (t.CUnsignedChar, 1),
|
||
'CHAR8PTR': (t.CChar8T, 1), 'CHAR16PTR': (t.CChar16T, 1),
|
||
'CHAR32PTR': (t.CChar32T, 1),
|
||
}
|
||
for k, v in _PTR_ALIASES.items():
|
||
if k not in cls._map:
|
||
cls._map[k] = v
|
||
_FLOAT_ALIASES = {
|
||
'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):
|
||
"""获取类型类和指针层级"""
|
||
return cls._build_map().get(type_name)
|
||
|
||
|
||
class BaseHandle:
|
||
def __init__(self, translator: "Translator") -> None:
|
||
self.Trans: Translator = translator
|
||
self._CurrentCpythonObjectClass: str = None
|
||
|
||
@staticmethod
|
||
def _attr(obj, name, default=None):
|
||
if obj is None:
|
||
return default
|
||
return getattr(obj, name, default)
|
||
|
||
@staticmethod
|
||
def _is_char_pointer(val):
|
||
"""检查值是否为 char* (i8*) 指针"""
|
||
from llvmlite import ir
|
||
if not isinstance(val.type, ir.PointerType):
|
||
return False
|
||
pointee = val.type.pointee
|
||
return isinstance(pointee, ir.IntType) and pointee.width == 8
|
||
|
||
def HandleExprLlvm(self, Node, VarType=None):
|
||
return self.Trans.ExprHandler.HandleExprLlvm(Node, VarType)
|
||
|
||
def HandleBodyLlvm(self, Body):
|
||
return self.Trans.BodyHandler.HandleBodyLlvm(Body)
|
||
|
||
def _get_int_ptr(self, Node):
|
||
import ast
|
||
from llvmlite import ir
|
||
Gen = 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 = self.HandleExprLlvm(Node.value)
|
||
if not obj_val:
|
||
return None
|
||
if isinstance(obj_val.type, ir.PointerType):
|
||
pointee = obj_val.type.pointee
|
||
if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)):
|
||
StructName = 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 = self.Trans.ExprHandler._get_llvm_member_offset(Node.attr, StructName, Gen)
|
||
member_ptr = 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 = getattr(t, TypeName, None)
|
||
if TypeClass and isinstance(TypeClass, type):
|
||
if issubclass(TypeClass, t.CType):
|
||
return True
|
||
FallbackClass = getattr(t, f'_{TypeName}', None)
|
||
if FallbackClass and isinstance(FallbackClass, type):
|
||
if issubclass(FallbackClass, t.CType):
|
||
return True
|
||
return False
|
||
|
||
|
||
StrictMode = _config.mode == 'strict'
|
||
|
||
|