进行了优化,减少了上帝结构体的符号表占用

This commit is contained in:
2026-06-18 22:12:14 +08:00
parent d7b98cc9c5
commit 19f2787db0
32 changed files with 1245 additions and 1083 deletions

Binary file not shown.

View File

@@ -506,8 +506,6 @@ class TransPyC:
# 从源代码直接预扫描 import 语句,注册别名 # 从源代码直接预扫描 import 语句,注册别名
# 注意:不能依赖 Tree 中的 import 节点,因为 ParsePythonFile 可能修改了 AST # 注意:不能依赖 Tree 中的 import 节点,因为 ParsePythonFile 可能修改了 AST
if not getattr(self.translator, '_ImportAliases', None):
self.translator._ImportAliases = {}
if not getattr(self.translator, '_ImportedModules', None): if not getattr(self.translator, '_ImportedModules', None):
self.translator._ImportedModules = set() self.translator._ImportedModules = set()
_prescan_tree = ast.parse(self.code) _prescan_tree = ast.parse(self.code)
@@ -519,14 +517,14 @@ class TransPyC:
continue continue
self.translator._ImportedModules.add(_name) self.translator._ImportedModules.add(_name)
if _alias.asname: if _alias.asname:
self.translator._ImportAliases[_alias.asname] = _name self.translator.SymbolTable.import_aliases[_alias.asname] = _name
elif isinstance(_node, ast.ImportFrom): elif isinstance(_node, ast.ImportFrom):
_module_name = _node.module _module_name = _node.module
if _module_name and _module_name not in ('c', 't'): if _module_name and _module_name not in ('c', 't'):
self.translator._ImportedModules.add(_module_name) self.translator._ImportedModules.add(_module_name)
for _alias in _node.names: for _alias in _node.names:
if _alias.asname: if _alias.asname:
self.translator._ImportAliases[_alias.asname] = f"{_module_name}.{_alias.name}" self.translator.SymbolTable.import_aliases[_alias.asname] = f"{_module_name}.{_alias.name}"
# 解析代码以提取类型信息(用于 EmbeddedAssignments 和 TypedefAssignments # 解析代码以提取类型信息(用于 EmbeddedAssignments 和 TypedefAssignments
# 创建临时文件路径用于解析 # 创建临时文件路径用于解析

View File

@@ -80,7 +80,7 @@ class AnnAssignHandle(BaseHandle):
ClassName = CN ClassName = CN
break break
IsUnion = False IsUnion = False
if ClassName and ClassName in self.Trans.SymbolTable: if ClassName and self.Trans.SymbolTable.has(ClassName):
TypeInfo = self.Trans.SymbolTable[ClassName] TypeInfo = self.Trans.SymbolTable[ClassName]
if TypeInfo.IsUnion: if TypeInfo.IsUnion:
IsUnion = True IsUnion = True
@@ -161,7 +161,7 @@ class AnnAssignHandle(BaseHandle):
info = CTypeInfo() info = CTypeInfo()
info.IsDefine = True info.IsDefine = True
info.DefineValue = Node.value.value info.DefineValue = Node.value.value
self.Trans.SymbolTable[VarName] = info self.Trans.SymbolTable.insert(VarName, info)
Gen._record_var_signedness(VarName, TypeInfo.IsUInt) Gen._record_var_signedness(VarName, TypeInfo.IsUInt)
return return
if TypeInfo.IsStr or (isinstance(Node.annotation, ast.Name) and Node.annotation.id == 'str'): if TypeInfo.IsStr or (isinstance(Node.annotation, ast.Name) and Node.annotation.id == 'str'):

View File

@@ -139,10 +139,9 @@ class AssignHandle:
StructType = Gen.structs[ClassName] StructType = Gen.structs[ClassName]
IsUnion = False IsUnion = False
if ClassName in self.Trans.SymbolTable: TypeInfo = self.Trans.SymbolTable.lookup(ClassName)
TypeInfo = self.Trans.SymbolTable[ClassName] if TypeInfo and TypeInfo.IsUnion:
if TypeInfo.IsUnion: IsUnion = True
IsUnion = True
if IsUnion: if IsUnion:
Value = self.HandleExprLlvm(Node.value) Value = self.HandleExprLlvm(Node.value)
@@ -435,10 +434,10 @@ class AssignHandle:
CReturnTypes = [None] * len(ret_type.elements) CReturnTypes = [None] * len(ret_type.elements)
if not CReturnTypes: if not CReturnTypes:
sym_key = FuncName sym_key = FuncName
if sym_key not in self.Trans.SymbolTable: if not self.Trans.SymbolTable.has(sym_key):
if ModulePath: if ModulePath:
sym_key = f"{ModulePath}.{FuncName}" sym_key = f"{ModulePath}.{FuncName}"
sym_info = self.Trans.SymbolTable.get(sym_key) sym_info = self.Trans.SymbolTable.lookup(sym_key)
if sym_info and sym_info.IsFunction: if sym_info and sym_info.IsFunction:
ret_type_info = sym_info.FuncPtrReturn ret_type_info = sym_info.FuncPtrReturn
param_type_infos = [pt for _, pt in (sym_info.FuncPtrParams or [])] param_type_infos = [pt for _, pt in (sym_info.FuncPtrParams or [])]
@@ -615,7 +614,7 @@ class AssignHandle:
ClassName = self.Trans._CurrentCpythonObjectClass ClassName = self.Trans._CurrentCpythonObjectClass
if ClassName and ClassName in Gen.structs: if ClassName and ClassName in Gen.structs:
PropKey = f'{ClassName}.{AttrName}' PropKey = f'{ClassName}.{AttrName}'
PropInfo = self.Trans.SymbolTable.get(PropKey) PropInfo = self.Trans.SymbolTable.lookup(PropKey)
if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList: if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList:
SelfVar = Gen._get_var_ptr('self') SelfVar = Gen._get_var_ptr('self')
if SelfVar: if SelfVar:
@@ -726,14 +725,13 @@ class AssignHandle:
ClassName = CN ClassName = CN
IsUnion = False IsUnion = False
if ClassName and ClassName in self.Trans.SymbolTable: TypeInfo = self.Trans.SymbolTable.lookup(ClassName)
TypeInfo = self.Trans.SymbolTable[ClassName] if TypeInfo and TypeInfo.IsUnion:
if TypeInfo.IsUnion: IsUnion = True
IsUnion = True
if ClassName and ClassName in Gen.structs: if ClassName and ClassName in Gen.structs:
PropKey = f'{ClassName}.{AttrName}' PropKey = f'{ClassName}.{AttrName}'
PropInfo = self.Trans.SymbolTable.get(PropKey) PropInfo = self.Trans.SymbolTable.lookup(PropKey)
if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList: if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList:
ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value) ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value)
SetterFunc = Gen._get_function(PropKey + '$set') SetterFunc = Gen._get_function(PropKey + '$set')
@@ -856,8 +854,7 @@ class AssignHandle:
self._StoreWithCoerce(Value, MemberPtr) self._StoreWithCoerce(Value, MemberPtr)
if not ClassName: if not ClassName:
imported_modules = getattr(self.Trans, '_ImportedModules', None) imported_modules = getattr(self.Trans, '_ImportedModules', None)
import_aliases = getattr(self.Trans, '_ImportAliases', {}) resolved_mod = self.Trans.SymbolTable.resolve_alias(VarName)
resolved_mod = import_aliases.get(VarName, VarName)
if imported_modules and (VarName in imported_modules or resolved_mod in imported_modules): if imported_modules and (VarName in imported_modules or resolved_mod in imported_modules):
PossibleKeys = [f"{VarName}.{AttrName}", AttrName] PossibleKeys = [f"{VarName}.{AttrName}", AttrName]
for mod_name in imported_modules: for mod_name in imported_modules:
@@ -1185,7 +1182,7 @@ class AssignHandle:
if isinstance(Node.target, ast.Name): if isinstance(Node.target, ast.Name):
VarName = Node.target.id VarName = Node.target.id
EffectiveAnnotation = Node.annotation EffectiveAnnotation = Node.annotation
if VarName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(VarName):
Info = self.Trans.SymbolTable[VarName] Info = self.Trans.SymbolTable[VarName]
if Info.get('type') == 'typedef': if Info.get('type') == 'typedef':
return return
@@ -1200,7 +1197,7 @@ class AssignHandle:
elem_type_node = slice_node.elts[0] elem_type_node = slice_node.elts[0]
count_node = slice_node.elts[1] count_node = slice_node.elts[1]
if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs: if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs:
SymEntry = self.Trans.SymbolTable.get(elem_type_node.id) SymEntry = self.Trans.SymbolTable.lookup(elem_type_node.id)
if SymEntry and isinstance(SymEntry, CTypeInfo) and SymEntry.IsFuncPtr: if SymEntry and isinstance(SymEntry, CTypeInfo) and SymEntry.IsFuncPtr:
ElemType = ir.IntType(8).as_pointer() ElemType = ir.IntType(8).as_pointer()
else: else:
@@ -1220,7 +1217,7 @@ class AssignHandle:
if isinstance(count_node, ast.Constant) and isinstance(count_node.value, int): if isinstance(count_node, ast.Constant) and isinstance(count_node.value, int):
ArrayCount = count_node.value ArrayCount = count_node.value
elif isinstance(count_node, ast.Name): elif isinstance(count_node, ast.Name):
if count_node.id in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(count_node.id):
SymInfo = self.Trans.SymbolTable[count_node.id] SymInfo = self.Trans.SymbolTable[count_node.id]
if isinstance(SymInfo.value, int): if isinstance(SymInfo.value, int):
ArrayCount = SymInfo.value ArrayCount = SymInfo.value
@@ -1324,7 +1321,7 @@ class AssignHandle:
if TTypeInfo: if TTypeInfo:
TTypeInfo.IsTypedef = True TTypeInfo.IsTypedef = True
TTypeInfo.Name = VarName TTypeInfo.Name = VarName
self.Trans.SymbolTable[VarName] = TTypeInfo self.Trans.SymbolTable.insert(VarName, TTypeInfo)
if IsCDefine: if IsCDefine:
if Node.value: if Node.value:
define_constants = vars(Gen).setdefault('_define_constants', {}) define_constants = vars(Gen).setdefault('_define_constants', {})
@@ -1494,12 +1491,12 @@ class AssignHandle:
enum_class_name = parts[-2] enum_class_name = parts[-2]
member_name = parts[-1] member_name = parts[-1]
qualified_name = f"{enum_class_name}.{member_name}" qualified_name = f"{enum_class_name}.{member_name}"
if qualified_name in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(qualified_name):
info = self.Trans.SymbolTable[qualified_name] info = self.Trans.SymbolTable[qualified_name]
if info.IsEnumMember and info.EnumName: if info.IsEnumMember and info.EnumName:
return info.EnumName return info.EnumName
under_name = f"{enum_class_name}_{member_name}" under_name = f"{enum_class_name}_{member_name}"
if under_name in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(under_name):
info = self.Trans.SymbolTable[under_name] info = self.Trans.SymbolTable[under_name]
if info.IsEnumMember and info.EnumName: if info.IsEnumMember and info.EnumName:
return info.EnumName return info.EnumName
@@ -1529,7 +1526,7 @@ class AssignHandle:
FuncName = Node.value.func.id FuncName = Node.value.func.id
if FuncName in Gen.structs: if FuncName in Gen.structs:
IsUnion = False IsUnion = False
if FuncName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(FuncName):
TypeInfo = self.Trans.SymbolTable[FuncName] TypeInfo = self.Trans.SymbolTable[FuncName]
if TypeInfo.IsUnion: if TypeInfo.IsUnion:
IsUnion = True IsUnion = True

View File

@@ -359,44 +359,16 @@ class CTypeInfo:
@staticmethod @staticmethod
def FromTypeName(TypeName: str) -> "CTypeInfo": def FromTypeName(TypeName: str) -> "CTypeInfo":
"""从简单类型名构造 CTypeInfo不经过 FromStr 字符串解析)""" """从简单类型名构造 CTypeInfo不经过 FromStr 字符串解析)"""
from lib.core.Handles.HandlesBase import BuiltinTypeMap from lib.core.TypeAnnotationResolver import TypeAnnotationResolver
return TypeAnnotationResolver.from_type_name(TypeName)
# Handle pointer types like 'CUInt32T *', 'void *', etc.
ptr_count = 0
base_name = TypeName
while base_name.endswith(' *') or base_name.endswith('*'):
ptr_count += 1
base_name = base_name.rstrip(' *').rstrip()
entry = BuiltinTypeMap.Get(base_name)
if entry:
TypeClass, base_ptr = entry
info = CTypeInfo()
info.BaseType = TypeClass
info.PtrCount = base_ptr + ptr_count
return info
# Handle LLVM primitive type names (e.g., 'i64', 'double' from generic type inference)
llvm_map = CTypeInfo._get_llvm_primitive_map()
llvm_entry = llvm_map.get(base_name)
if llvm_entry:
TypeClass, base_ptr = llvm_entry
info = CTypeInfo()
info.BaseType = TypeClass
info.PtrCount = base_ptr + ptr_count
return info
# Fallback with pointer count
info = CTypeInfo.CreateFromTypeName(TypeName)
if ptr_count > 0:
info.PtrCount = ptr_count
return info
# FromStr 已移除 - 类型解析不再经过中间字符串格式 # FromStr 已移除 - 类型解析不再经过中间字符串格式
# typedef 展开直接走 CTypeInfo 对象,不经过字符串解析 # typedef 展开直接走 CTypeInfo 对象,不经过字符串解析
@staticmethod @staticmethod
def TryEvalConstExpr(node, SymbolTable): def TryEvalConstExpr(node, SymbolTable):
from lib.core.ConstEvaluator import ConstEvaluator from lib.core.TypeAnnotationResolver import TypeAnnotationResolver
return ConstEvaluator.eval_with_symtab(node, SymbolTable) return TypeAnnotationResolver.try_eval_const_expr(node, SymbolTable)
@classmethod @classmethod
def FromNode(cls, Node: ast.AST, SymbolTable: dict) -> "CTypeInfo": def FromNode(cls, Node: ast.AST, SymbolTable: dict) -> "CTypeInfo":
@@ -406,658 +378,9 @@ class CTypeInfo:
Node: AST 节点(如 ast.Name, ast.Attribute 等) Node: AST 节点(如 ast.Name, ast.Attribute 等)
SymbolTable: 符号表字典 SymbolTable: 符号表字典
""" """
if isinstance(Node, (ast.Constant, ast.Str)): from lib.core.TypeAnnotationResolver import TypeAnnotationResolver
return cls._FromNode_Constant(Node, SymbolTable) return TypeAnnotationResolver.from_node(Node, SymbolTable)
if isinstance(Node, ast.Name):
return cls._FromNode_Name(Node, SymbolTable)
if isinstance(Node, ast.Call):
return cls._FromNode_Call(Node, SymbolTable)
if isinstance(Node, ast.BinOp) and isinstance(Node.op, ast.BitOr):
return cls._FromNode_BinOp(Node, SymbolTable)
if isinstance(Node, ast.Subscript):
return cls._FromNode_Subscript(Node, SymbolTable)
if isinstance(Node, ast.Attribute):
return cls._FromNode_Attribute(Node, SymbolTable)
return cls()
@classmethod
def _FromNode_Constant(cls, Node: ast.AST, SymbolTable: dict) -> "CTypeInfo":
"""处理 ast.Constant / ast.Str 节点"""
if isinstance(Node, ast.Constant):
TypeName = Node.value
else:
TypeName = Node.s
return cls.FromTypeName(TypeName)
@classmethod
def _FromNode_Name(cls, Node: ast.Name, SymbolTable: dict) -> "CTypeInfo":
"""处理 ast.Name 节点"""
from lib.includes import t
TypeName = Node.id
TypeObj = CTypeHelper.GetTModuleCType(TypeName)
if TypeObj is None:
TypeObj = getattr(t, TypeName, None)
if isinstance(TypeObj, type) and issubclass(TypeObj, t.CType) and TypeObj is not t.CType:
if TypeObj == t.CPtr:
Result = cls()
Result.PtrCount = 1
Result.BaseType = t.CVoid()
return Result
if TypeObj == t.State:
Result = cls()
Result.IsState = True
Result.BaseType = t.CVoid()
return Result
Inst = TypeObj()
Result = cls()
Result.BaseType = TypeObj
if hasattr(Inst, 'CName') and Inst.CName:
Result.Name = Inst.CName
if hasattr(Inst, 'IsSigned'):
Result.IsSigned = Inst.IsSigned
return Result
if TypeName in SymbolTable:
Entry = SymbolTable[TypeName]
if Entry:
if isinstance(Entry, CTypeInfo):
if Entry.IsTypedef:
if Entry.BaseType and (not isinstance(Entry.BaseType, (t._CTypedef,)) or Entry.PtrCount > 0):
Result = Entry.Copy()
Result.IsTypedef = True
Result.Name = TypeName
return Result
if Entry.OriginalType:
if isinstance(Entry.OriginalType, CTypeInfo) and Entry.OriginalType.IsFuncPtr:
Result = cls()
Result.IsFuncPtr = True
Result.FuncPtrReturn = Entry.OriginalType.FuncPtrReturn or CTypeInfo.VoidTypeInfo()
Result.FuncPtrParams = list(Entry.OriginalType.FuncPtrParams) if Entry.OriginalType.FuncPtrParams else []
Result.IsTypedef = True
Result.Name = TypeName
return Result
elif isinstance(Entry.OriginalType, CTypeInfo):
Resolved = Entry.OriginalType.Copy()
elif isinstance(Entry.OriginalType, str) and Entry.OriginalType == 'Callable':
Result = cls()
Result.IsFuncPtr = True
Result.FuncPtrReturn = CTypeInfo.VoidTypeInfo()
Result.FuncPtrParams = []
Result.IsTypedef = True
Result.Name = TypeName
return Result
elif isinstance(Entry.OriginalType, str):
Resolved = cls.FromTypeName(Entry.OriginalType)
else:
Resolved = Entry.OriginalType
Resolved.IsTypedef = True
Resolved.Name = TypeName
return Resolved
TypeEntry = BuiltinTypeMap.Get(TypeName)
if TypeEntry:
Result = cls()
Result.BaseType = TypeEntry[0]()
Result.PtrCount = TypeEntry[1]
Result.IsTypedef = True
Result.Name = TypeName
return Result
return Entry
if Entry.IsEnum:
Result = cls()
Result.BaseType = t.CInt()
Result.IsEnum = True
Result.Name = TypeName
return Result
if getattr(Entry, 'IsExceptionClass', None):
Result = cls()
Result.BaseType = t.CInt()
Result.IsExceptionClass = True
Result.Name = TypeName
return Result
if Entry.BaseType is None and (Entry.IsStruct or Entry.Name):
Entry.BaseType = t.CStruct(name=TypeName)
Entry.IsStruct = True
return Entry
elif isinstance(Entry, dict):
if Entry.get('type') == 'typedef':
OriginalType = Entry.get('OriginalType', '')
if OriginalType:
if OriginalType == 'Callable':
Result = cls()
Result.IsFuncPtr = True
Result.FuncPtrReturn = CTypeInfo.VoidTypeInfo()
Result.FuncPtrParams = []
Result.IsTypedef = True
Result.Name = TypeName
return Result
Resolved = cls.FromTypeName(OriginalType)
Resolved.IsTypedef = True
Resolved.Name = TypeName
return Resolved
TypeEntry = BuiltinTypeMap.Get(TypeName)
if TypeEntry:
Result = cls()
Result.BaseType = TypeEntry[0]()
Result.PtrCount = TypeEntry[1]
Result.IsTypedef = True
Result.Name = TypeName
return Result
Result = cls()
Result.BaseType = t._CTypedef(TypeName)
Result.IsTypedef = True
Result.Name = TypeName
return Result
# 特殊处理 str 类型,它应该是 char*(指针)
if TypeName in ('str', 'bytes'):
Result = cls()
Result.BaseType = t.CChar()
Result.PtrCount = 1
return Result
if TypeName == 'irq_handler_t':
pass
return cls.FromTypeName(TypeName)
@classmethod
def _FromNode_Call(cls, Node: ast.Call, SymbolTable: dict) -> "CTypeInfo":
"""处理 ast.Call 节点"""
from lib.includes import t
if isinstance(Node.func, ast.Name) and Node.func.id == 'callable':
Result = cls()
Result.IsFuncPtr = True
Result.FuncPtrReturn = CTypeInfo.VoidTypeInfo()
Result.FuncPtrParams = []
try:
if len(Node.args) > 0:
RetInfo = cls.FromNode(Node.args[0], SymbolTable)
if RetInfo:
Result.FuncPtrReturn = RetInfo
for kw in Node.keywords:
ParamInfo = cls.FromNode(kw.value, SymbolTable)
if ParamInfo:
Result.FuncPtrParams.append((kw.arg or '', ParamInfo))
except Exception as _e:
if __import__('lib.constants.config', fromlist=['mode']).mode == "strict":
import warnings; warnings.warn(f"异常被忽略: {_e}")
return Result
if isinstance(Node.func, ast.Attribute):
if isinstance(Node.func.value, ast.Name) and Node.func.value.id == 't':
if Node.func.attr == 'Bit' and len(Node.args) > 0:
Result = cls()
Result.BaseType = t.CInt()
Result.IsBitField = True
if isinstance(Node.args[0], ast.Constant) and isinstance(Node.args[0].value, int):
Result.BitWidth = Node.args[0].value
else:
Result.BitWidth = 1
return Result
return cls()
@classmethod
def _FromNode_BinOp(cls, Node: ast.BinOp, SymbolTable: dict) -> "CTypeInfo":
"""处理 ast.BinOp (BitOr) 节点"""
from lib.includes import t
LeftInfo = cls.FromNode(Node.left, SymbolTable)
RightInfo = cls.FromNode(Node.right, SymbolTable)
if LeftInfo.IsState or RightInfo.IsState:
Result = cls()
Result.IsState = True
NonStateInfo = LeftInfo if not LeftInfo.IsState else RightInfo
StateInfo = LeftInfo if LeftInfo.IsState else RightInfo
if NonStateInfo.BaseType and (not isinstance(NonStateInfo.BaseType, (t._CTypedef,)) or NonStateInfo.PtrCount > 0):
Result.BaseType = NonStateInfo.BaseType
elif NonStateInfo.IsTypedef and NonStateInfo.Name:
if NonStateInfo.BaseType and (not isinstance(NonStateInfo.BaseType, (t._CTypedef,)) or NonStateInfo.PtrCount > 0):
Result.BaseType = NonStateInfo.BaseType
Result.PtrCount = NonStateInfo.PtrCount
Result.IsTypedef = True
Result.Name = NonStateInfo.Name
if NonStateInfo.OriginalType:
Result.OriginalType = NonStateInfo.OriginalType
else:
Result.BaseType = t.CStruct(name=NonStateInfo.Name)
Result.IsStruct = True
Result.IsTypedef = True
Result.Name = NonStateInfo.Name
if NonStateInfo.OriginalType:
Result.OriginalType = NonStateInfo.OriginalType
else:
Result.BaseType = t.CVoid()
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if not Result.Storage:
Result.Storage = t.CExport()
if LeftInfo.Storage and not isinstance(LeftInfo.Storage, t.CExport):
Result.Storage = LeftInfo.Storage
elif RightInfo.Storage and not isinstance(RightInfo.Storage, t.CExport):
Result.Storage = RightInfo.Storage
if LeftInfo.DataConst or RightInfo.DataConst:
Result.DataConst = True
if LeftInfo.VarConst or RightInfo.VarConst:
Result.VarConst = True
return Result
if LeftInfo.IsPtr or RightInfo.IsPtr:
Result = cls()
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
NonPtrInfo = LeftInfo if not LeftInfo.IsPtr else RightInfo
PtrInfo = RightInfo if RightInfo.IsPtr else LeftInfo
if NonPtrInfo.BaseType and (not isinstance(NonPtrInfo.BaseType, (t._CTypedef,)) or NonPtrInfo.PtrCount > 0):
Result.BaseType = NonPtrInfo.BaseType
elif NonPtrInfo.IsTypedef and NonPtrInfo.Name:
if NonPtrInfo.BaseType and (not isinstance(NonPtrInfo.BaseType, (t._CTypedef,)) or NonPtrInfo.PtrCount > 0):
Result.BaseType = NonPtrInfo.BaseType
Result.IsTypedef = True
Result.Name = NonPtrInfo.Name
if NonPtrInfo.OriginalType:
Result.OriginalType = NonPtrInfo.OriginalType
else:
Result.BaseType = t.CStruct(name=NonPtrInfo.Name)
Result.IsStruct = True
elif PtrInfo.BaseType and (not isinstance(PtrInfo.BaseType, (t._CTypedef,)) or PtrInfo.PtrCount > 0):
Result.BaseType = PtrInfo.BaseType
else:
Result.BaseType = t.CUnsignedChar()
if LeftInfo.DataConst or RightInfo.DataConst:
Result.DataConst = True
if LeftInfo.VarConst or RightInfo.VarConst:
Result.VarConst = True
if LeftInfo.DataVolatile or RightInfo.DataVolatile:
Result.DataVolatile = True
if LeftInfo.VarVolatile or RightInfo.VarVolatile:
Result.VarVolatile = True
if LeftInfo.Storage:
Result.Storage = LeftInfo.Storage
elif RightInfo.Storage:
Result.Storage = RightInfo.Storage
return Result
if LeftInfo.DataConst or RightInfo.DataConst:
Result = cls()
BaseTypeSide = LeftInfo if not LeftInfo.DataConst else RightInfo
QualSide = LeftInfo if LeftInfo.DataConst else RightInfo
Result.BaseType = BaseTypeSide.BaseType if BaseTypeSide.BaseType and (not isinstance(BaseTypeSide.BaseType, t.CVoid) or BaseTypeSide.PtrCount > 0) else QualSide.BaseType
if not Result.BaseType:
Result.BaseType = t.CInt()
Result.DataConst = True
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if LeftInfo.VarConst or RightInfo.VarConst:
Result.VarConst = True
if LeftInfo.DataVolatile or RightInfo.DataVolatile:
Result.DataVolatile = True
if LeftInfo.Storage:
Result.Storage = LeftInfo.Storage
elif RightInfo.Storage:
Result.Storage = RightInfo.Storage
return Result
if LeftInfo.DataVolatile or RightInfo.DataVolatile:
Result = cls()
BaseTypeSide = LeftInfo if not LeftInfo.DataVolatile else RightInfo
QualSide = LeftInfo if LeftInfo.DataVolatile else RightInfo
Result.BaseType = BaseTypeSide.BaseType if BaseTypeSide.BaseType and (not isinstance(BaseTypeSide.BaseType, t.CVoid) or BaseTypeSide.PtrCount > 0) else QualSide.BaseType
if not Result.BaseType:
Result.BaseType = t.CInt()
Result.DataVolatile = True
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if LeftInfo.VarConst or RightInfo.VarConst:
Result.VarConst = True
if LeftInfo.Storage:
Result.Storage = LeftInfo.Storage
elif RightInfo.Storage:
Result.Storage = RightInfo.Storage
return Result
if LeftInfo.Storage or RightInfo.Storage:
Result = cls()
BaseTypeSide = LeftInfo if not LeftInfo.Storage else RightInfo
StorageSide = LeftInfo if LeftInfo.Storage else RightInfo
if BaseTypeSide.IsState or StorageSide.IsState:
Result.IsState = True
Result.BaseType = t.CVoid()
Result.Storage = LeftInfo.Storage if LeftInfo.Storage else RightInfo.Storage
return Result
Result.BaseType = BaseTypeSide.BaseType if BaseTypeSide.BaseType and (not isinstance(BaseTypeSide.BaseType, t.CVoid) or BaseTypeSide.PtrCount > 0) else StorageSide.BaseType
if not Result.BaseType:
Result.BaseType = t.CInt()
Result.Storage = LeftInfo.Storage if LeftInfo.Storage else RightInfo.Storage
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if LeftInfo.DataConst or RightInfo.DataConst:
Result.DataConst = True
if LeftInfo.VarConst or RightInfo.VarConst:
Result.VarConst = True
return Result
# 检查是否有位域类型 (t.Bit)
if LeftInfo.IsBitField:
Result = cls()
Result.BaseType = LeftInfo.BaseType if LeftInfo.BaseType else t.CInt()
Result.IsBitField = True
Result.BitWidth = LeftInfo.BitWidth
return Result
if RightInfo.IsBitField:
Result = cls()
Result.BaseType = RightInfo.BaseType if RightInfo.BaseType else t.CInt()
Result.IsBitField = True
Result.BitWidth = RightInfo.BitWidth
return Result
# 处理字节序类型 (t.BigEndian, t.LittleEndian)
if LeftInfo.ByteOrder:
Result = cls()
Result.BaseType = LeftInfo.BaseType if LeftInfo.BaseType else t.CInt()
Result.ByteOrder = LeftInfo.ByteOrder
return Result
if RightInfo.ByteOrder:
Result = cls()
Result.BaseType = RightInfo.BaseType if RightInfo.BaseType else t.CInt()
Result.ByteOrder = RightInfo.ByteOrder
return Result
if LeftInfo.IsFuncPtr or RightInfo.IsFuncPtr:
Result = cls()
FuncPtrSide = LeftInfo if LeftInfo.IsFuncPtr else RightInfo
Result.IsFuncPtr = True
Result.FuncPtrParams = list(FuncPtrSide.FuncPtrParams)
Result.FuncPtrReturn = FuncPtrSide.FuncPtrReturn
if LeftInfo.Storage:
Result.Storage = LeftInfo.Storage
elif RightInfo.Storage:
Result.Storage = RightInfo.Storage
return Result
if LeftInfo.IsTypedef and RightInfo.BaseType:
if LeftInfo.BaseType and (not isinstance(LeftInfo.BaseType, (t._CTypedef,)) or LeftInfo.PtrCount > 0):
Result = LeftInfo.Copy()
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if RightInfo.Storage:
Result.Storage = RightInfo.Storage
return Result
return RightInfo
if RightInfo.IsTypedef and LeftInfo.BaseType:
if RightInfo.BaseType and (not isinstance(RightInfo.BaseType, (t._CTypedef,)) or RightInfo.PtrCount > 0):
Result = RightInfo.Copy()
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if LeftInfo.Storage:
Result.Storage = LeftInfo.Storage
return Result
return LeftInfo
if LeftInfo.BaseType:
return LeftInfo
elif RightInfo.BaseType:
return RightInfo
return cls()
@classmethod
def _FromNode_Subscript(cls, Node: ast.Subscript, SymbolTable: dict) -> "CTypeInfo":
"""处理 ast.Subscript 节点"""
from lib.includes import t
base = Node.value
if isinstance(base, ast.Attribute):
if isinstance(base.value, ast.Name) and base.value.id == 't' and base.attr == 'Bit':
Result = cls()
Result.BaseType = t.CInt()
Result.IsBitField = True
if isinstance(Node.slice, ast.Constant) and isinstance(Node.slice.value, int):
Result.BitWidth = Node.slice.value
else:
Result.BitWidth = 1
return Result
if isinstance(base, ast.Name) and base.id == 'list':
slice_node = Node.slice
elts = []
if isinstance(slice_node, ast.Tuple):
elts = slice_node.elts
elif isinstance(slice_node, (ast.Attribute, ast.Name, ast.Subscript)):
elts = [slice_node]
if elts:
ElemInfo = cls.FromNode(elts[0], SymbolTable)
if ElemInfo and ElemInfo.BaseType:
Result = cls()
Result.BaseType = ElemInfo.BaseType
Result.PtrCount = ElemInfo.PtrCount
Result.ArrayDims = list(ElemInfo.ArrayDims)
if len(elts) >= 2:
count_val = cls.TryEvalConstExpr(elts[1], SymbolTable)
if count_val is not None and isinstance(count_val, int) and count_val > 0:
Result.ArrayDims.insert(0, str(count_val))
else:
Result.PtrCount += 1
if ElemInfo.IsPtr and not ElemInfo.ArrayDims:
Result.PtrCount = max(Result.PtrCount, 1)
return Result
if isinstance(base, ast.Attribute):
parts = []
current = base
while isinstance(current, ast.Attribute):
parts.insert(0, current.attr)
current = current.value
if isinstance(current, ast.Name):
parts.insert(0, current.id)
if parts and parts[0] == 't' and parts[-1] == t.CPtr.__name__:
Result = cls()
Result.BaseType = t.CVoid()
Result.PtrCount = 1
slice_node = Node.slice
if isinstance(slice_node, ast.Subscript):
InnerInfo = cls.FromNode(slice_node, SymbolTable)
if InnerInfo:
if InnerInfo.PtrCount > 0:
Result.PtrCount += InnerInfo.PtrCount
if InnerInfo.BaseType and not isinstance(InnerInfo.BaseType, t.CVoid):
Result.BaseType = InnerInfo.BaseType
elif isinstance(slice_node, ast.Attribute):
SliceInfo = cls.FromNode(slice_node, SymbolTable)
if SliceInfo:
if SliceInfo.IsPtr:
Result.PtrCount += SliceInfo.PtrCount
elif SliceInfo.BaseType and not isinstance(SliceInfo.BaseType, t.CVoid):
Result.BaseType = SliceInfo.BaseType
elif isinstance(slice_node, ast.Name):
SliceType = getattr(t, slice_node.id, None)
if SliceType == t.CPtr:
Result.PtrCount += 1
else:
SliceInfo = cls.FromNode(slice_node, SymbolTable)
if SliceInfo and SliceInfo.BaseType and not isinstance(SliceInfo.BaseType, t.CVoid):
Result.BaseType = SliceInfo.BaseType
return Result
if parts and parts[0] == 't' and parts[-1] == 'Callable':
Result = cls()
Result.IsFuncPtr = True
slice_node = Node.slice
if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2:
params_list = slice_node.elts[0]
return_node = slice_node.elts[1]
ParamTypes = []
if isinstance(params_list, ast.List):
for elt in params_list.elts:
ParamTypeInfo = cls.FromNode(elt, SymbolTable)
if ParamTypeInfo:
ParamTypes.append(('', ParamTypeInfo))
if not ParamTypes:
ParamTypes.append(('', cls.FromTypeName('void')))
Result.FuncPtrParams = ParamTypes
ReturnTypeInfo = cls.FromNode(return_node, SymbolTable)
Result.FuncPtrReturn = ReturnTypeInfo if ReturnTypeInfo else CTypeInfo.VoidTypeInfo()
return Result
return cls()
@classmethod
def _FromNode_Attribute(cls, Node: ast.Attribute, SymbolTable: dict) -> "CTypeInfo":
"""处理 ast.Attribute 节点"""
from lib.includes import t
ModuleParts = []
Current = Node
while isinstance(Current, ast.Attribute):
ModuleParts.insert(0, Current.attr)
Current = Current.value
if isinstance(Current, ast.Name):
ModuleParts.insert(0, Current.id)
if len(ModuleParts) >= 2:
TypeName = ModuleParts[-1]
ModulePath = '.'.join(ModuleParts[:-1])
elif len(ModuleParts) == 1:
TypeName = ModuleParts[0]
ModulePath = None
else:
return cls()
# 解析 import 别名: 如 import vpsdk.window as window -> window -> vpsdk.window
if ModulePath:
resolved = False
if hasattr(SymbolTable, 'translator'):
import_aliases = getattr(SymbolTable.translator, '_ImportAliases', {})
if ModulePath in import_aliases:
ModulePath = import_aliases[ModulePath]
resolved = True
if not resolved and ModulePath in SymbolTable:
entry = SymbolTable[ModulePath]
if isinstance(entry, CTypeInfo) and getattr(entry, 'IsModuleAlias', False):
resolved_name = getattr(entry, 'ResolvedModule', None)
if resolved_name:
ModulePath = resolved_name
if ModulePath == 't' or (ModulePath and ModulePath.startswith('t.')):
TypeClass = CTypeHelper.GetTModuleCType(TypeName)
if TypeClass is None:
TypeClass = getattr(t, TypeName, None)
if TypeClass is not None and TypeClass.HasPosition(t.CType.POINTER):
Info = cls()
Info.PtrCount = 1
if TypeClass == t.CArrayPtr:
Info.IsArrayPtr = True
Info.BaseType = t.CVoid
return Info
if TypeClass is not None and TypeClass.IsStorageClass():
Info = cls()
Info.Storage = TypeClass()
if TypeClass == t.State:
Info.IsState = True
Info.BaseType = t.CVoid()
return Info
if TypeClass is not None and TypeClass.IsTypeQualifier():
Info = cls()
if TypeClass == t.CConst:
Info.DataConst = True
elif TypeClass == t.CVolatile:
Info.DataVolatile = True
return Info
if (TypeClass is not None
and isinstance(TypeClass, type)
and issubclass(TypeClass, t.CType)
and TypeClass is not t.CType
and TypeClass.HasPosition(t.CType.BASE)):
if TypeClass == t.State:
Result = cls()
Result.IsState = True
Result.BaseType = t.CVoid()
return Result
Inst = TypeClass()
Result = cls()
Result.BaseType = TypeClass
if hasattr(Inst, 'CName') and Inst.CName:
Result.Name = Inst.CName
if hasattr(Inst, 'IsSigned'):
Result.IsSigned = Inst.IsSigned
return Result
CNAME = CTypeHelper.GetCName(TypeName)
if CNAME:
return cls.FromTypeName(CNAME)
# 处理字节序类型
if TypeName == 'BigEndian':
Result = cls()
Result.BaseType = t.CInt()
Result.ByteOrder = 'big'
return Result
if TypeName == 'LittleEndian':
Result = cls()
Result.BaseType = t.CInt()
Result.ByteOrder = 'little'
return Result
FullName = f"{ModulePath}.{TypeName}" if ModulePath else TypeName
if TypeName in SymbolTable:
Entry = SymbolTable[TypeName]
if Entry and getattr(Entry, 'IsTypedef', None):
Resolved = Entry.Copy()
if Resolved.BaseType is None:
Resolved.BaseType = t._CTypedef(TypeName)
return Resolved
if Entry and getattr(Entry, 'IsEnum', None):
Result = cls()
Result.BaseType = t.CInt()
Result.IsEnum = True
Result.Name = TypeName
return Result
if Entry and getattr(Entry, 'IsExceptionClass', None):
Result = cls()
Result.BaseType = t.CInt()
Result.IsExceptionClass = True
Result.Name = TypeName
return Result
if Entry:
Result = Entry.Copy()
if Result.BaseType is None and (Result.IsStruct or Result.IsCpythonObject or Result.Name):
Result.BaseType = t.CStruct(name=TypeName)
Result.IsStruct = True
return Result
return cls()
if FullName in SymbolTable:
Info = SymbolTable[FullName]
if Info and Info.IsTypedef:
OriginalType = Info.get('OriginalType', '')
if OriginalType and 'typedef' in OriginalType:
parts = OriginalType.split()
if len(parts) >= 2:
BaseType_name = parts[1]
if not BaseType_name.startswith('C'):
BaseType_name = 'C' + BaseType_name
CNAME = CTypeHelper.GetCName(BaseType_name)
if CNAME:
return cls.FromTypeName(CNAME)
Result = cls()
Result.BaseType = t._CTypedef(TypeName)
Result.IsTypedef = True
return Result
if Info:
Result = Info.Copy()
if Result.BaseType is None and (Result.IsStruct or Result.IsCpythonObject or Result.Name):
Result.BaseType = t.CStruct(name=TypeName)
Result.IsStruct = True
return Result
return cls()
return cls()
@classmethod
def _HandleArraySubscript(cls, Node, SymbolTable):
if not isinstance(Node, ast.Subscript):
return None
dims = []
current = Node
while isinstance(current, ast.Subscript):
if isinstance(current.slice, ast.Constant) and isinstance(current.slice.value, int):
dims.insert(0, str(current.slice.value))
elif isinstance(current.slice, ast.Name):
dims.insert(0, current.slice.id)
else:
return None
current = current.value
base_info = cls.FromNode(current, SymbolTable)
if base_info and base_info.BaseType:
base_info.ArrayDims = dims
return base_info
return None
def Copy(self) -> "CTypeInfo": def Copy(self) -> "CTypeInfo":
NewInfo = CTypeInfo() NewInfo = CTypeInfo()

View File

@@ -51,7 +51,7 @@ class ClassHandle(BaseHandle):
ExcTypeInfo.Name = ClassName ExcTypeInfo.Name = ClassName
ExcTypeInfo.IsExceptionClass = True ExcTypeInfo.IsExceptionClass = True
ExcTypeInfo.value = code ExcTypeInfo.value = code
self.Trans.SymbolTable[ClassName] = ExcTypeInfo self.Trans.SymbolTable.insert(ClassName, ExcTypeInfo)
def _is_generic_class(self, Node): def _is_generic_class(self, Node):
if hasattr(Node, 'type_params') and Node.type_params: if hasattr(Node, 'type_params') and Node.type_params:
@@ -660,7 +660,7 @@ class ClassHandle(BaseHandle):
UnionNode = CTypeInfo() UnionNode = CTypeInfo()
UnionNode.Name = ClassName UnionNode.Name = ClassName
UnionNode.IsUnion = True UnionNode.IsUnion = True
self.Trans.SymbolTable[ClassName] = UnionNode self.Trans.SymbolTable.insert(ClassName, UnionNode)
def _EmitREnumLlvm(self, Node, Gen): def _EmitREnumLlvm(self, Node, Gen):
ClassName = Node.name ClassName = Node.name
@@ -767,14 +767,14 @@ class ClassHandle(BaseHandle):
MemberNode.EnumName = ClassName MemberNode.EnumName = ClassName
MemberNode.Lineno = lineno MemberNode.Lineno = lineno
MemberNode.IsEnumMember = True MemberNode.IsEnumMember = True
self.Trans.SymbolTable[VariantName] = MemberNode self.Trans.SymbolTable.insert(VariantName, MemberNode)
RenumTypeInfo = CTypeInfo() RenumTypeInfo = CTypeInfo()
RenumTypeInfo.Name = ClassName RenumTypeInfo.Name = ClassName
RenumTypeInfo.BaseType = t.REnum(ClassName) RenumTypeInfo.BaseType = t.REnum(ClassName)
RenumTypeInfo.IsRenum = True RenumTypeInfo.IsRenum = True
RenumTypeInfo.IsEnum = True RenumTypeInfo.IsEnum = True
RenumTypeInfo.RenumVariants = variant_names RenumTypeInfo.RenumVariants = variant_names
self.Trans.SymbolTable[ClassName] = RenumTypeInfo self.Trans.SymbolTable.insert(ClassName, RenumTypeInfo)
def _RegisterEnumMembers(self, Node): def _RegisterEnumMembers(self, Node):
ClassName = Node.name ClassName = Node.name
@@ -782,7 +782,7 @@ class ClassHandle(BaseHandle):
EnumTypeInfo.Name = ClassName EnumTypeInfo.Name = ClassName
EnumTypeInfo.BaseType = t.CEnum(ClassName) EnumTypeInfo.BaseType = t.CEnum(ClassName)
EnumTypeInfo.IsEnum = True EnumTypeInfo.IsEnum = True
self.Trans.SymbolTable[ClassName] = EnumTypeInfo self.Trans.SymbolTable.insert(ClassName, EnumTypeInfo)
from lib.core.Exportable import EnumMember as ExportEnumMember from lib.core.Exportable import EnumMember as ExportEnumMember
enum_export = self.Trans.Exportable.add_enum( enum_export = self.Trans.Exportable.add_enum(
name=ClassName, name=ClassName,
@@ -806,7 +806,7 @@ class ClassHandle(BaseHandle):
next_enum_value = value + 1 next_enum_value = value + 1
elif isinstance(item.value, ast.Name): elif isinstance(item.value, ast.Name):
value = item.value.id value = item.value.id
if value in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(value):
ref_info = self.Trans.SymbolTable[value] ref_info = self.Trans.SymbolTable[value]
if ref_info.value is not None and isinstance(ref_info.value, int): if ref_info.value is not None and isinstance(ref_info.value, int):
next_enum_value = ref_info.value + 1 next_enum_value = ref_info.value + 1
@@ -820,7 +820,7 @@ class ClassHandle(BaseHandle):
MemberNode.EnumName = ClassName MemberNode.EnumName = ClassName
MemberNode.Lineno = item.lineno MemberNode.Lineno = item.lineno
MemberNode.IsEnumMember = True MemberNode.IsEnumMember = True
self.Trans.SymbolTable[VarName] = MemberNode self.Trans.SymbolTable.insert(VarName, MemberNode)
enum_export.members.append(ExportEnumMember( enum_export.members.append(ExportEnumMember(
name=VarName, name=VarName,
value=value, value=value,
@@ -840,7 +840,7 @@ class ClassHandle(BaseHandle):
next_enum_value = value + 1 next_enum_value = value + 1
elif isinstance(item.value, ast.Name): elif isinstance(item.value, ast.Name):
value = item.value.id value = item.value.id
if value in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(value):
ref_info = self.Trans.SymbolTable[value] ref_info = self.Trans.SymbolTable[value]
if ref_info.value is not None and isinstance(ref_info.value, int): if ref_info.value is not None and isinstance(ref_info.value, int):
next_enum_value = ref_info.value + 1 next_enum_value = ref_info.value + 1
@@ -854,7 +854,7 @@ class ClassHandle(BaseHandle):
MemberNode.EnumName = ClassName MemberNode.EnumName = ClassName
MemberNode.Lineno = item.lineno MemberNode.Lineno = item.lineno
MemberNode.IsEnumMember = True MemberNode.IsEnumMember = True
self.Trans.SymbolTable[VarName] = MemberNode self.Trans.SymbolTable.insert(VarName, MemberNode)
enum_export.members.append(ExportEnumMember( enum_export.members.append(ExportEnumMember(
name=VarName, name=VarName,
value=value, value=value,

View File

@@ -39,7 +39,7 @@ class DeleteHandle(BaseHandle):
ClassName = self.Trans._CurrentCpythonObjectClass ClassName = self.Trans._CurrentCpythonObjectClass
if ClassName: if ClassName:
PropKey = f'{ClassName}.{AttrName}' PropKey = f'{ClassName}.{AttrName}'
PropInfo = self.Trans.SymbolTable.get(PropKey) PropInfo = self.Trans.SymbolTable.lookup(PropKey)
if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList: if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList:
SelfVar = Gen._get_var_ptr('self') SelfVar = Gen._get_var_ptr('self')
if SelfVar: if SelfVar:
@@ -53,7 +53,7 @@ class DeleteHandle(BaseHandle):
ClassName = self.Trans.ExprHandler._get_var_class(target.value, Gen) ClassName = self.Trans.ExprHandler._get_var_class(target.value, Gen)
if ClassName: if ClassName:
PropKey = f'{ClassName}.{AttrName}' PropKey = f'{ClassName}.{AttrName}'
PropInfo = self.Trans.SymbolTable.get(PropKey) PropInfo = self.Trans.SymbolTable.lookup(PropKey)
if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList: if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList:
obj_val = self.Trans.ExprHandler.HandleExprLlvm(target.value) obj_val = self.Trans.ExprHandler.HandleExprLlvm(target.value)
if obj_val: if obj_val:

View File

@@ -328,7 +328,7 @@ class ExprHandle(BaseHandle):
# 如果 _define_constants 中没有,尝试从符号表查找 # 如果 _define_constants 中没有,尝试从符号表查找
if VarName not in getattr(Gen, '_define_constants', {}): if VarName not in getattr(Gen, '_define_constants', {}):
try: try:
sym_info = self.translator.SymbolTable.get(VarName) sym_info = self.translator.SymbolTable.lookup(VarName)
if sym_info and sym_info.IsDefine and sym_info.DefineValue is not None: if sym_info and sym_info.IsDefine and sym_info.DefineValue is not None:
val = sym_info.DefineValue val = sym_info.DefineValue
if isinstance(val, int): if isinstance(val, int):
@@ -398,7 +398,7 @@ class ExprHandle(BaseHandle):
return ir.Constant(ir.IntType(8).as_pointer(), None) return ir.Constant(ir.IntType(8).as_pointer(), None)
if VarName == 'True' or VarName == 'False': if VarName == 'True' or VarName == 'False':
return ir.Constant(ir.IntType(32), 1 if VarName == 'True' else 0) return ir.Constant(ir.IntType(32), 1 if VarName == 'True' else 0)
if VarName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(VarName):
SymInfo = self.Trans.SymbolTable[VarName] SymInfo = self.Trans.SymbolTable[VarName]
if SymInfo.IsEnumMember and isinstance(SymInfo.value, int): if SymInfo.IsEnumMember and isinstance(SymInfo.value, int):
return ir.Constant(ir.IntType(32), SymInfo.value) return ir.Constant(ir.IntType(32), SymInfo.value)

View File

@@ -91,7 +91,7 @@ class ExprAttrHandle(BaseHandle):
if key not in PossibleKeys: if key not in PossibleKeys:
PossibleKeys.append(key) PossibleKeys.append(key)
for lookup_key in PossibleKeys: for lookup_key in PossibleKeys:
SymInfo = self.Trans.SymbolTable.get(lookup_key) SymInfo = self.Trans.SymbolTable.lookup(lookup_key)
if SymInfo and SymInfo.IsDefine and SymInfo.DefineValue is not None: if SymInfo and SymInfo.IsDefine and SymInfo.DefineValue is not None:
return self._make_define_constant(Gen, SymInfo.DefineValue) return self._make_define_constant(Gen, SymInfo.DefineValue)
# 也检查 _define_constants # 也检查 _define_constants
@@ -104,10 +104,9 @@ class ExprAttrHandle(BaseHandle):
def _lookup_module_global(self, Gen, VarName, AttrName): def _lookup_module_global(self, Gen, VarName, AttrName):
"""在模块全局变量中查找 import 的属性""" """在模块全局变量中查找 import 的属性"""
imported_modules = getattr(self.Trans, '_ImportedModules', None) imported_modules = getattr(self.Trans, '_ImportedModules', None)
import_aliases = getattr(self.Trans, '_ImportAliases', {})
if not imported_modules: if not imported_modules:
return None return None
resolved_mod = import_aliases.get(VarName, VarName) resolved_mod = self.Trans.SymbolTable.resolve_alias(VarName)
if VarName not in imported_modules and resolved_mod not in imported_modules: if VarName not in imported_modules and resolved_mod not in imported_modules:
return None return None
PossibleKeys = [f"{VarName}.{AttrName}", AttrName] PossibleKeys = [f"{VarName}.{AttrName}", AttrName]
@@ -201,7 +200,7 @@ class ExprAttrHandle(BaseHandle):
return None return None
# 检查 property getter # 检查 property getter
PropKey = f'{ClassName}.{Node.attr}' PropKey = f'{ClassName}.{Node.attr}'
PropInfo = self.Trans.SymbolTable.get(PropKey) PropInfo = self.Trans.SymbolTable.lookup(PropKey)
if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList: if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList:
SelfVar = Gen._get_var_ptr('self') SelfVar = Gen._get_var_ptr('self')
if SelfVar: if SelfVar:
@@ -233,10 +232,10 @@ class ExprAttrHandle(BaseHandle):
def _handle_attr_enum(self, Node, VarName): def _handle_attr_enum(self, Node, VarName):
"""处理枚举成员访问 (VarName 是枚举类型名)""" """处理枚举成员访问 (VarName 是枚举类型名)"""
SymInfo = self.Trans.SymbolTable.get(VarName) SymInfo = self.Trans.SymbolTable.lookup(VarName)
if not SymInfo or not SymInfo.IsEnum: if not SymInfo or not SymInfo.IsEnum:
return None return None
if Node.attr in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(Node.attr):
MemberInfo = self.Trans.SymbolTable[Node.attr] MemberInfo = self.Trans.SymbolTable[Node.attr]
if MemberInfo.IsEnumMember and MemberInfo.EnumName == VarName: if MemberInfo.IsEnumMember and MemberInfo.EnumName == VarName:
if isinstance(MemberInfo.value, int): if isinstance(MemberInfo.value, int):
@@ -284,7 +283,7 @@ class ExprAttrHandle(BaseHandle):
# 检查 property getter # 检查 property getter
PropKey = f'{ClassName}.{AttrName}' PropKey = f'{ClassName}.{AttrName}'
PropInfo = self.Trans.SymbolTable.get(PropKey) PropInfo = self.Trans.SymbolTable.lookup(PropKey)
if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList: if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList:
ObjVal = self.HandleExprLlvm(Node.value) ObjVal = self.HandleExprLlvm(Node.value)
GetterFunc = Gen._get_function(PropKey) GetterFunc = Gen._get_function(PropKey)
@@ -294,7 +293,7 @@ class ExprAttrHandle(BaseHandle):
return Gen.builder.call(GetterFunc, [ObjVal], name=f"prop_{PropKey}") return Gen.builder.call(GetterFunc, [ObjVal], name=f"prop_{PropKey}")
# 获取类型信息 # 获取类型信息
TypeInfo = self.Trans.SymbolTable.get(ClassName) TypeInfo = self.Trans.SymbolTable.lookup(ClassName)
IsUnion = TypeInfo.IsUnion if TypeInfo else False IsUnion = TypeInfo.IsUnion if TypeInfo else False
IsCenum = TypeInfo.IsEnum if TypeInfo else False IsCenum = TypeInfo.IsEnum if TypeInfo else False
IsRenum = TypeInfo.IsRenum if TypeInfo else False IsRenum = TypeInfo.IsRenum if TypeInfo else False
@@ -320,7 +319,7 @@ class ExprAttrHandle(BaseHandle):
# CEnum 处理 # CEnum 处理
if IsCenum: if IsCenum:
for qname in (f"{ClassName}.{AttrName}", f"{ClassName}_{AttrName}"): for qname in (f"{ClassName}.{AttrName}", f"{ClassName}_{AttrName}"):
if qname in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(qname):
info = self.Trans.SymbolTable[qname] info = self.Trans.SymbolTable[qname]
if info.IsEnumMember and isinstance(info.value, int): if info.IsEnumMember and isinstance(info.value, int):
return ir.Constant(ir.IntType(32), info.value) return ir.Constant(ir.IntType(32), info.value)
@@ -817,8 +816,7 @@ class ExprAttrHandle(BaseHandle):
ClassName = Gen.global_struct_class.get(VarName) ClassName = Gen.global_struct_class.get(VarName)
if not ClassName: if not ClassName:
imported_modules = getattr(self.Trans, '_ImportedModules', None) imported_modules = getattr(self.Trans, '_ImportedModules', None)
import_aliases = getattr(self.Trans, '_ImportAliases', {}) resolved_mod = self.Trans.SymbolTable.resolve_alias(VarName)
resolved_mod = import_aliases.get(VarName, VarName)
if imported_modules and (VarName in imported_modules or resolved_mod in imported_modules): if imported_modules and (VarName in imported_modules or resolved_mod in imported_modules):
AttrName = Node.attr AttrName = Node.attr
ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {})
@@ -1035,7 +1033,6 @@ class ExprAttrHandle(BaseHandle):
imported_modules = getattr(self.Trans, '_ImportedModules', None) imported_modules = getattr(self.Trans, '_ImportedModules', None)
if not imported_modules: if not imported_modules:
return None return None
import_aliases = getattr(self.Trans, '_ImportAliases', {})
parts = self._build_attr_path(Node) parts = self._build_attr_path(Node)
if len(parts) < 2: if len(parts) < 2:
return None return None
@@ -1046,7 +1043,7 @@ class ExprAttrHandle(BaseHandle):
possible_keys.append(full_path) possible_keys.append(full_path)
if module_parts: if module_parts:
ModulePath = '.'.join(module_parts) ModulePath = '.'.join(module_parts)
resolved_first = import_aliases.get(module_parts[0], module_parts[0]) resolved_first = self.Trans.SymbolTable.resolve_alias(module_parts[0])
if resolved_first != module_parts[0]: if resolved_first != module_parts[0]:
resolved_parts = [resolved_first] + module_parts[1:] resolved_parts = [resolved_first] + module_parts[1:]
resolved_path = '.'.join(resolved_parts) resolved_path = '.'.join(resolved_parts)
@@ -1061,7 +1058,7 @@ class ExprAttrHandle(BaseHandle):
if key not in possible_keys: if key not in possible_keys:
possible_keys.append(key) possible_keys.append(key)
for lookup_key in possible_keys: for lookup_key in possible_keys:
SymInfo = self.Trans.SymbolTable.get(lookup_key) SymInfo = self.Trans.SymbolTable.lookup(lookup_key)
if SymInfo and SymInfo.IsDefine and SymInfo.DefineValue is not None: if SymInfo and SymInfo.IsDefine and SymInfo.DefineValue is not None:
val = SymInfo.DefineValue val = SymInfo.DefineValue
if isinstance(val, int): if isinstance(val, int):
@@ -1077,17 +1074,16 @@ class ExprAttrHandle(BaseHandle):
imported_modules = getattr(self.Trans, '_ImportedModules', None) imported_modules = getattr(self.Trans, '_ImportedModules', None)
if not imported_modules: if not imported_modules:
return None return None
import_aliases = getattr(self.Trans, '_ImportAliases', {}) resolved_module = self.Trans.SymbolTable.resolve_alias(module_alias)
resolved_module = import_aliases.get(module_alias, module_alias)
if resolved_module not in imported_modules and module_alias not in imported_modules: if resolved_module not in imported_modules and module_alias not in imported_modules:
return None return None
enum_keys = [enum_class_name, f"{resolved_module}.{enum_class_name}"] enum_keys = [enum_class_name, f"{resolved_module}.{enum_class_name}"]
for enum_key in enum_keys: for enum_key in enum_keys:
if enum_key in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(enum_key):
SymInfo = self.Trans.SymbolTable[enum_key] SymInfo = self.Trans.SymbolTable[enum_key]
if SymInfo.IsEnum: if SymInfo.IsEnum:
for qname in (f"{enum_key}.{member_name}", f"{enum_key}_{member_name}"): for qname in (f"{enum_key}.{member_name}", f"{enum_key}_{member_name}"):
if qname in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(qname):
info = self.Trans.SymbolTable[qname] info = self.Trans.SymbolTable[qname]
if info.IsEnumMember and isinstance(info.value, int): if info.IsEnumMember and isinstance(info.value, int):
return ir.Constant(ir.IntType(32), info.value) return ir.Constant(ir.IntType(32), info.value)

View File

@@ -528,7 +528,7 @@ class ExprBuiltinHandle(BaseHandle):
type_info = Gen.var_type_info[arg_name] type_info = Gen.var_type_info[arg_name]
if isinstance(type_info, dict) and type_info.get('type') == 'enum': if isinstance(type_info, dict) and type_info.get('type') == 'enum':
enum_type_name = type_info.get('name') enum_type_name = type_info.get('name')
if not enum_type_name and arg_name in self.Trans.SymbolTable: if not enum_type_name and self.Trans.SymbolTable.has(arg_name):
TypeInfo = self.Trans.SymbolTable[arg_name] TypeInfo = self.Trans.SymbolTable[arg_name]
if TypeInfo.IsEnum: if TypeInfo.IsEnum:
enum_type_name = arg_name enum_type_name = arg_name
@@ -537,7 +537,7 @@ class ExprBuiltinHandle(BaseHandle):
enum_class_name = None enum_class_name = None
if isinstance(arg.value, ast.Name): if isinstance(arg.value, ast.Name):
LastPart = arg.attr LastPart = arg.attr
if LastPart in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(LastPart):
AttrInfo = self.Trans.SymbolTable[LastPart] AttrInfo = self.Trans.SymbolTable[LastPart]
if AttrInfo.IsEnumMember and AttrInfo.EnumName: if AttrInfo.IsEnumMember and AttrInfo.EnumName:
enum_type_name = AttrInfo.EnumName enum_type_name = AttrInfo.EnumName
@@ -552,7 +552,7 @@ class ExprBuiltinHandle(BaseHandle):
qualified_name_under = f"{enum_class_name}_{LastPart}" qualified_name_under = f"{enum_class_name}_{LastPart}"
enum_member_found = None enum_member_found = None
for qname in (qualified_name_dot, qualified_name_under): for qname in (qualified_name_dot, qualified_name_under):
if qname in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(qname):
info = self.Trans.SymbolTable[qname] info = self.Trans.SymbolTable[qname]
if info.IsEnumMember and info.EnumName == enum_class_name: if info.IsEnumMember and info.EnumName == enum_class_name:
enum_member_found = info enum_member_found = info

View File

@@ -316,7 +316,7 @@ class ExprCallHandle(BaseHandle):
return self._HandleTypeLlvm(Node) return self._HandleTypeLlvm(Node)
if Gen._has_function(FuncName): if Gen._has_function(FuncName):
return self._HandleClosureCallLlvm(Node, FuncName) return self._HandleClosureCallLlvm(Node, FuncName)
if FuncName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(FuncName):
SymInfo = self.Trans.SymbolTable[FuncName] SymInfo = self.Trans.SymbolTable[FuncName]
if SymInfo.IsEnum: if SymInfo.IsEnum:
if Node.args: if Node.args:
@@ -430,12 +430,12 @@ class ExprCallHandle(BaseHandle):
return self._HandleSizeofLlvm(SizeofNode) return self._HandleSizeofLlvm(SizeofNode)
ModulePath = self._get_ModulePath(Node.func.value) ModulePath = self._get_ModulePath(Node.func.value)
if ModulePath: if ModulePath:
aliases = getattr(self.Trans, '_ImportAliases', {})
first_part = ModulePath.split('.')[0] first_part = ModulePath.split('.')[0]
if first_part in aliases: resolved_first = self.Trans.SymbolTable.resolve_alias(first_part)
ModulePath = aliases[first_part] + ModulePath[len(first_part):] if resolved_first != first_part:
ModulePath = resolved_first + ModulePath[len(first_part):]
is_instance_var = isinstance(Node.func.value, ast.Name) and Node.func.value.id in Gen.var_struct_class and Node.func.value.id not in Gen.ModuleSha1Map is_instance_var = isinstance(Node.func.value, ast.Name) and Node.func.value.id in Gen.var_struct_class and Node.func.value.id not in Gen.ModuleSha1Map
is_class_name = isinstance(Node.func.value, ast.Name) and (Node.func.value.id in Gen.structs or (Node.func.value.id in self.Trans.SymbolTable and self.Trans.SymbolTable[Node.func.value.id].IsStruct)) is_class_name = isinstance(Node.func.value, ast.Name) and (Node.func.value.id in Gen.structs or self.Trans.SymbolTable.is_struct(Node.func.value.id))
if is_instance_var and not is_class_name: if is_instance_var and not is_class_name:
return self._HandleMethodCallLlvm(Node) return self._HandleMethodCallLlvm(Node)
FuncAttr = Node.func.attr FuncAttr = Node.func.attr
@@ -445,7 +445,7 @@ class ExprCallHandle(BaseHandle):
return result return result
if hasattr(self.Trans.ClassHandler, '_generic_class_templates') and FuncAttr in self.Trans.ClassHandler._generic_class_templates: if hasattr(self.Trans.ClassHandler, '_generic_class_templates') and FuncAttr in self.Trans.ClassHandler._generic_class_templates:
return self._HandleGenericClassNewLlvm(Node, FuncAttr) return self._HandleGenericClassNewLlvm(Node, FuncAttr)
if FuncAttr in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(FuncAttr):
SymInfo = self.Trans.SymbolTable[FuncAttr] SymInfo = self.Trans.SymbolTable[FuncAttr]
if SymInfo.IsStruct: if SymInfo.IsStruct:
if FuncAttr not in Gen.structs: if FuncAttr not in Gen.structs:
@@ -456,14 +456,14 @@ class ExprCallHandle(BaseHandle):
return result return result
if SymInfo.IsEnumMember and SymInfo.EnumName: if SymInfo.IsEnumMember and SymInfo.EnumName:
EnumName = SymInfo.EnumName EnumName = SymInfo.EnumName
if EnumName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(EnumName):
EnumInfo = self.Trans.SymbolTable[EnumName] EnumInfo = self.Trans.SymbolTable[EnumName]
if EnumInfo.IsRenum: if EnumInfo.IsRenum:
result = self._HandleREnumConstructLlvm(Node, EnumName, FuncAttr, SymInfo.value) result = self._HandleREnumConstructLlvm(Node, EnumName, FuncAttr, SymInfo.value)
if result is not None: if result is not None:
return result return result
FullAttrKey = f"{ModulePath}.{FuncAttr}" FullAttrKey = f"{ModulePath}.{FuncAttr}"
if FullAttrKey in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(FullAttrKey):
SymInfo = self.Trans.SymbolTable[FullAttrKey] SymInfo = self.Trans.SymbolTable[FullAttrKey]
if SymInfo.IsStruct: if SymInfo.IsStruct:
if FuncAttr not in Gen.structs: if FuncAttr not in Gen.structs:
@@ -478,7 +478,7 @@ class ExprCallHandle(BaseHandle):
if result is not None: if result is not None:
return result return result
FullAttrKey = f"{ModulePath}.{FuncAttr}" FullAttrKey = f"{ModulePath}.{FuncAttr}"
if FullAttrKey in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(FullAttrKey):
SymInfo = self.Trans.SymbolTable[FullAttrKey] SymInfo = self.Trans.SymbolTable[FullAttrKey]
if SymInfo.IsTypedef: if SymInfo.IsTypedef:
return ir.Constant(ir.IntType(32), 0) return ir.Constant(ir.IntType(32), 0)
@@ -533,7 +533,7 @@ class ExprCallHandle(BaseHandle):
raise Exception(f"Undefined method: 't.{FuncAttr}'") raise Exception(f"Undefined method: 't.{FuncAttr}'")
if isinstance(Node.func.value, ast.Attribute): if isinstance(Node.func.value, ast.Attribute):
inner_attr = Node.func.value.attr inner_attr = Node.func.value.attr
if inner_attr in Gen.structs or (inner_attr in self.Trans.SymbolTable and self.Trans.SymbolTable[inner_attr].IsStruct): if inner_attr in Gen.structs or self.Trans.SymbolTable.is_struct(inner_attr):
static_result = self._HandleStaticMethodCallLlvm(Node, inner_attr, FuncAttr) static_result = self._HandleStaticMethodCallLlvm(Node, inner_attr, FuncAttr)
if static_result is not None: if static_result is not None:
return static_result return static_result
@@ -557,22 +557,21 @@ class ExprCallHandle(BaseHandle):
return Gen.builder.call(Gen._get_function(mangled_name), CallArgs, name=f"call_{FuncAttr}") return Gen.builder.call(Gen._get_function(mangled_name), CallArgs, name=f"call_{FuncAttr}")
if MethodResult is None or IsZeroResult: if MethodResult is None or IsZeroResult:
imported = getattr(self.Trans, '_ImportedModules', set()) imported = getattr(self.Trans, '_ImportedModules', set())
aliases = getattr(self.Trans, '_ImportAliases', {})
ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {})
IsKnown = (ModulePath in imported or ModulePath in aliases or IsKnown = (ModulePath in imported or ModulePath in self.Trans.SymbolTable.import_aliases or
ModulePath in ModuleSha1Map) ModulePath in ModuleSha1Map)
if not IsKnown and ModulePath and '.' in ModulePath: if not IsKnown and ModulePath and '.' in ModulePath:
LastPart = ModulePath.split('.')[-1] LastPart = ModulePath.split('.')[-1]
IsKnown = (LastPart in imported or LastPart in aliases or IsKnown = (LastPart in imported or LastPart in self.Trans.SymbolTable.import_aliases or
LastPart in ModuleSha1Map) LastPart in ModuleSha1Map)
# 最后尝试: 用 FuncAttr 直接查找 Gen.functions_find_function 会遍历 SHA1 前缀) # 最后尝试: 用 FuncAttr 直接查找 Gen.functions_find_function 会遍历 SHA1 前缀)
if FuncAttr and ModulePath and ModulePath not in {'t', 'c'}: if FuncAttr and ModulePath and ModulePath not in {'t', 'c'}:
# 先检查 FuncAttr 是否是函数/变量,如果是则跳过 struct 声明 # 先检查 FuncAttr 是否是函数/变量,如果是则跳过 struct 声明
_attr_sym = self.Trans.SymbolTable.get(FuncAttr) _attr_sym = self.Trans.SymbolTable.lookup(FuncAttr)
_is_func_or_var = _attr_sym and (_attr_sym.IsFunction or _attr_sym.IsVariable) _is_func_or_var = _attr_sym and (_attr_sym.IsFunction or _attr_sym.IsVariable)
if not _is_func_or_var and ModulePath: if not _is_func_or_var and ModulePath:
_full_key = f"{ModulePath}.{FuncAttr}" _full_key = f"{ModulePath}.{FuncAttr}"
_full_sym = self.Trans.SymbolTable.get(_full_key) _full_sym = self.Trans.SymbolTable.lookup(_full_key)
if _full_sym and (_full_sym.IsFunction or _full_sym.IsVariable): if _full_sym and (_full_sym.IsFunction or _full_sym.IsVariable):
_is_func_or_var = True _is_func_or_var = True
# 优先检查 FuncAttr 是否为 struct/类构造器 # 优先检查 FuncAttr 是否为 struct/类构造器
@@ -585,7 +584,7 @@ class ExprCallHandle(BaseHandle):
# 检查 FullAttrKey 是否为 struct如 hashlib.md5 # 检查 FullAttrKey 是否为 struct如 hashlib.md5
if ModulePath: if ModulePath:
FullAttrKey = f"{ModulePath}.{FuncAttr}" FullAttrKey = f"{ModulePath}.{FuncAttr}"
if FullAttrKey in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(FullAttrKey):
FullSymInfo = self.Trans.SymbolTable[FullAttrKey] FullSymInfo = self.Trans.SymbolTable[FullAttrKey]
if FullSymInfo.IsStruct or FullSymInfo.IsCpythonObject: if FullSymInfo.IsStruct or FullSymInfo.IsCpythonObject:
if FuncAttr not in Gen.structs: if FuncAttr not in Gen.structs:
@@ -648,7 +647,7 @@ class ExprCallHandle(BaseHandle):
def _ensure_struct_declared(self, class_name): def _ensure_struct_declared(self, class_name):
Gen = self.Trans.LlvmGen Gen = self.Trans.LlvmGen
# 如果名称是函数或变量,不应创建 struct # 如果名称是函数或变量,不应创建 struct
SymInfo = self.Trans.SymbolTable.get(class_name) SymInfo = self.Trans.SymbolTable.lookup(class_name)
if SymInfo and (SymInfo.IsFunction or SymInfo.IsVariable): if SymInfo and (SymInfo.IsFunction or SymInfo.IsVariable):
return return
if class_name in Gen.structs: if class_name in Gen.structs:
@@ -660,7 +659,7 @@ class ExprCallHandle(BaseHandle):
return return
else: else:
return return
SymInfo = self.Trans.SymbolTable.get(class_name) SymInfo = self.Trans.SymbolTable.lookup(class_name)
if SymInfo and SymInfo.Members: if SymInfo and SymInfo.Members:
member_types = [] member_types = []
if isinstance(SymInfo.Members, dict): if isinstance(SymInfo.Members, dict):
@@ -719,7 +718,7 @@ class ExprCallHandle(BaseHandle):
if ClassName not in Gen.structs: if ClassName not in Gen.structs:
self._ensure_struct_declared(ClassName) self._ensure_struct_declared(ClassName)
SymKey = f'{ClassName}.{MethodName}' SymKey = f'{ClassName}.{MethodName}'
SymInfo = self.Trans.SymbolTable.get(SymKey) or self.Trans.SymbolTable.get(MethodName) SymInfo = self.Trans.SymbolTable.lookup(SymKey) or self.Trans.SymbolTable.lookup(MethodName)
if SymInfo and SymInfo.IsFunction: if SymInfo and SymInfo.IsFunction:
ret_type_info = SymInfo.FuncPtrReturn ret_type_info = SymInfo.FuncPtrReturn
if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType: if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType:
@@ -761,7 +760,7 @@ class ExprCallHandle(BaseHandle):
return None return None
CallArgs = [] CallArgs = []
SymKey = f'{ClassName}.{MethodName}' SymKey = f'{ClassName}.{MethodName}'
SymInfo = self.Trans.SymbolTable.get(SymKey) or self.Trans.SymbolTable.get(MethodName) SymInfo = self.Trans.SymbolTable.lookup(SymKey) or self.Trans.SymbolTable.lookup(MethodName)
is_static_call = SymInfo is not None and FuncMeta.STATIC_METHOD in SymInfo.MetaList is_static_call = SymInfo is not None and FuncMeta.STATIC_METHOD in SymInfo.MetaList
is_classmethod_call = SymInfo is not None and FuncMeta.CLASS_METHOD in SymInfo.MetaList is_classmethod_call = SymInfo is not None and FuncMeta.CLASS_METHOD in SymInfo.MetaList
# @classmethod: 在参数列表前插入 cls栈上分配的类实例指针 # @classmethod: 在参数列表前插入 cls栈上分配的类实例指针
@@ -1208,14 +1207,12 @@ class ExprCallHandle(BaseHandle):
# 解析 import 别名: 如 window -> vpsdk.window # 解析 import 别名: 如 window -> vpsdk.window
if ModulePath and ModulePath not in ('c', 't'): if ModulePath and ModulePath not in ('c', 't'):
import_aliases = getattr(self.Trans, '_ImportAliases', {}) ModulePath = self.Trans.SymbolTable.resolve_alias(ModulePath)
if ModulePath in import_aliases:
ModulePath = import_aliases[ModulePath]
is_user_module = (ModulePath and ModulePath not in ('c', 't') and is_user_module = (ModulePath and ModulePath not in ('c', 't') and
(ModulePath in Gen.ModuleSha1Map or (ModulePath in Gen.ModuleSha1Map or
ModulePath in getattr(self.Trans, '_ImportedModules', set()) or ModulePath in getattr(self.Trans, '_ImportedModules', set()) or
ModulePath in getattr(self.Trans, '_ImportAliases', {}))) ModulePath in self.Trans.SymbolTable.import_aliases))
if ModulePath and ModulePath not in ('c', 't') and not is_user_module: if ModulePath and ModulePath not in ('c', 't') and not is_user_module:
is_user_module = (ModulePath in Gen.ModuleSha1Map or is_user_module = (ModulePath in Gen.ModuleSha1Map or
ModulePath.split('.')[-1] in Gen.ModuleSha1Map or ModulePath.split('.')[-1] in Gen.ModuleSha1Map or
@@ -1229,12 +1226,12 @@ class ExprCallHandle(BaseHandle):
if is_user_module: if is_user_module:
mangled_name = Gen._mangle_func_name(func_name, ModulePath) mangled_name = Gen._mangle_func_name(func_name, ModulePath)
sym_key = f'{ModulePath}.{func_name}' sym_key = f'{ModulePath}.{func_name}'
sym_info = self.Trans.SymbolTable.get(sym_key) or self.Trans.SymbolTable.get(func_name) sym_info = self.Trans.SymbolTable.lookup(sym_key) or self.Trans.SymbolTable.lookup(func_name)
is_inline = sym_info and (sym_info.IsInline or isinstance(sym_info.Storage, t.CInline)) is_inline = sym_info and (sym_info.IsInline or isinstance(sym_info.Storage, t.CInline))
if is_inline and sym_info.InlineBody: if is_inline and sym_info.InlineBody:
self._HandleInlineExpandLlvm(Node, sym_info) self._HandleInlineExpandLlvm(Node, sym_info)
return ir.Constant(ir.IntType(32), 1) return ir.Constant(ir.IntType(32), 1)
sym_info_exact = self.Trans.SymbolTable.get(sym_key) sym_info_exact = self.Trans.SymbolTable.lookup(sym_key)
if sym_info_exact: if sym_info_exact:
exact_params = sym_info_exact.FuncPtrParams exact_params = sym_info_exact.FuncPtrParams
exact_param_names = [pn for pn, _ in exact_params] exact_param_names = [pn for pn, _ in exact_params]
@@ -1276,9 +1273,9 @@ class ExprCallHandle(BaseHandle):
Gen.functions[func_name] = func_decl Gen.functions[func_name] = func_decl
return self._HandleClosureCallLlvm(Node, decl_name) return self._HandleClosureCallLlvm(Node, decl_name)
sym_key = f'{ModulePath}.{func_name}' sym_key = f'{ModulePath}.{func_name}'
sym_info = self.Trans.SymbolTable.get(sym_key) sym_info = self.Trans.SymbolTable.lookup(sym_key)
if not sym_info: if not sym_info:
sym_info = self.Trans.SymbolTable.get(func_name) sym_info = self.Trans.SymbolTable.lookup(func_name)
if sym_info: if sym_info:
is_func = sym_info.IsFunction is_func = sym_info.IsFunction
sym_is_variadic = sym_info.IsVariadic sym_is_variadic = sym_info.IsVariadic
@@ -1407,9 +1404,9 @@ class ExprCallHandle(BaseHandle):
return self._HandleClosureCallLlvm(Node, decl_name) return self._HandleClosureCallLlvm(Node, decl_name)
sym_key = f'{ModulePath}.{func_name}' if ModulePath else func_name sym_key = f'{ModulePath}.{func_name}' if ModulePath else func_name
sym_info = self.Trans.SymbolTable.get(sym_key) sym_info = self.Trans.SymbolTable.lookup(sym_key)
if not sym_info: if not sym_info:
sym_info = self.Trans.SymbolTable.get(func_name) sym_info = self.Trans.SymbolTable.lookup(func_name)
if sym_info: if sym_info:
is_func = sym_info.IsFunction is_func = sym_info.IsFunction
sym_is_variadic = sym_info.IsVariadic sym_is_variadic = sym_info.IsVariadic
@@ -1576,7 +1573,7 @@ class ExprCallHandle(BaseHandle):
def _HandleTypedefCastLlvm(self, Node, TypedefName): def _HandleTypedefCastLlvm(self, Node, TypedefName):
Gen = self.Trans.LlvmGen Gen = self.Trans.LlvmGen
SymInfo = self.Trans.SymbolTable.get(TypedefName) SymInfo = self.Trans.SymbolTable.lookup(TypedefName)
if not SymInfo or not SymInfo.IsTypedef: if not SymInfo or not SymInfo.IsTypedef:
return ir.Constant(ir.IntType(32), 0) return ir.Constant(ir.IntType(32), 0)
TargetType = Gen._ctype_to_llvm(SymInfo) TargetType = Gen._ctype_to_llvm(SymInfo)
@@ -1829,7 +1826,7 @@ class ExprCallHandle(BaseHandle):
ClassName = Gen.var_struct_class.get(VarName) ClassName = Gen.var_struct_class.get(VarName)
if ClassName: if ClassName:
SymKey = f'{ClassName}.{MethodName}' SymKey = f'{ClassName}.{MethodName}'
SymInfo = self.Trans.SymbolTable.get(SymKey) SymInfo = self.Trans.SymbolTable.lookup(SymKey)
if SymInfo and SymInfo.MetaList: if SymInfo and SymInfo.MetaList:
if FuncMeta.STATIC_METHOD in SymInfo.MetaList: if FuncMeta.STATIC_METHOD in SymInfo.MetaList:
return self._HandleStaticMethodCallLlvm(Node, ClassName, MethodName) return self._HandleStaticMethodCallLlvm(Node, ClassName, MethodName)
@@ -1901,7 +1898,7 @@ class ExprCallHandle(BaseHandle):
if is_float: if is_float:
return ir.Constant(ir.FloatType() if target_bits == 32 else ir.DoubleType(), 0.0) return ir.Constant(ir.FloatType() if target_bits == 32 else ir.DoubleType(), 0.0)
return ir.Constant(ir.IntType(target_bits) if target_bits > 0 else ir.IntType(32), 0) return ir.Constant(ir.IntType(target_bits) if target_bits > 0 else ir.IntType(32), 0)
if MethodName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(MethodName):
SymInfo = self.Trans.SymbolTable[MethodName] SymInfo = self.Trans.SymbolTable[MethodName]
if SymInfo.IsTypedef: if SymInfo.IsTypedef:
return self._HandleTypedefCastLlvm(Node, MethodName) return self._HandleTypedefCastLlvm(Node, MethodName)
@@ -1982,9 +1979,8 @@ class ExprCallHandle(BaseHandle):
ObjVal = tmp ObjVal = tmp
if isinstance(Node.func.value, ast.Name): if isinstance(Node.func.value, ast.Name):
ModuleName = Node.func.value.id ModuleName = Node.func.value.id
aliases = getattr(self.Trans, '_ImportAliases', {})
imported = getattr(self.Trans, '_ImportedModules', set()) imported = getattr(self.Trans, '_ImportedModules', set())
actual_module = aliases.get(ModuleName, ModuleName) actual_module = self.Trans.SymbolTable.resolve_alias(ModuleName)
if ModuleName in imported or actual_module in imported: if ModuleName in imported or actual_module in imported:
mangled_name = Gen._mangle_func_name(MethodName, actual_module) mangled_name = Gen._mangle_func_name(MethodName, actual_module)
if Gen._has_function(mangled_name): if Gen._has_function(mangled_name):
@@ -2657,7 +2653,7 @@ class ExprCallHandle(BaseHandle):
type_info = Gen.var_type_info[arg_name] type_info = Gen.var_type_info[arg_name]
if isinstance(type_info, dict) and type_info.get('type') == 'enum': if isinstance(type_info, dict) and type_info.get('type') == 'enum':
enum_type_name = type_info.get('name') enum_type_name = type_info.get('name')
if not enum_type_name and arg_name in self.Trans.SymbolTable: if not enum_type_name and self.Trans.SymbolTable.has(arg_name):
TypeInfo = self.Trans.SymbolTable[arg_name] TypeInfo = self.Trans.SymbolTable[arg_name]
if TypeInfo.IsEnum: if TypeInfo.IsEnum:
enum_type_name = arg_name enum_type_name = arg_name
@@ -2666,7 +2662,7 @@ class ExprCallHandle(BaseHandle):
enum_class_name = None enum_class_name = None
if isinstance(arg.value, ast.Name): if isinstance(arg.value, ast.Name):
LastPart = arg.attr LastPart = arg.attr
if LastPart in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(LastPart):
AttrInfo = self.Trans.SymbolTable[LastPart] AttrInfo = self.Trans.SymbolTable[LastPart]
if AttrInfo.IsEnumMember and AttrInfo.EnumName: if AttrInfo.IsEnumMember and AttrInfo.EnumName:
enum_type_name = AttrInfo.EnumName enum_type_name = AttrInfo.EnumName
@@ -2681,7 +2677,7 @@ class ExprCallHandle(BaseHandle):
qualified_name_under = f"{enum_class_name}_{LastPart}" qualified_name_under = f"{enum_class_name}_{LastPart}"
enum_member_found = None enum_member_found = None
for qname in (qualified_name_dot, qualified_name_under): for qname in (qualified_name_dot, qualified_name_under):
if qname in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(qname):
info = self.Trans.SymbolTable[qname] info = self.Trans.SymbolTable[qname]
if info.IsEnumMember and info.EnumName == enum_class_name: if info.IsEnumMember and info.EnumName == enum_class_name:
enum_member_found = info enum_member_found = info
@@ -3425,7 +3421,7 @@ class ExprCallHandle(BaseHandle):
type_str = 'int' type_str = 'int'
type_name = attr_name type_name = attr_name
elif isinstance(arg_node, ast.Name): elif isinstance(arg_node, ast.Name):
var_info = self.Trans.SymbolTable.get(arg_node.id) var_info = self.Trans.SymbolTable.lookup(arg_node.id)
if var_info and isinstance(var_info, dict): if var_info and isinstance(var_info, dict):
var_type = var_info.get('type', '') var_type = var_info.get('type', '')
if var_type in ('double', 'float'): if var_type in ('double', 'float'):

View File

@@ -144,7 +144,7 @@ class ExprUtils:
return ir.IntType(32) return ir.IntType(32)
elif isinstance(node, ast.Attribute): elif isinstance(node, ast.Attribute):
attr_name = node.attr attr_name = node.attr
if attr_name in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(attr_name):
AttrInfo = self.Trans.SymbolTable[attr_name] AttrInfo = self.Trans.SymbolTable[attr_name]
if getattr(AttrInfo, 'IsEnumMember', None): if getattr(AttrInfo, 'IsEnumMember', None):
return ir.IntType(32) return ir.IntType(32)

View File

@@ -188,7 +188,7 @@ class FunctionHandle(BaseHandle):
elif isinstance(val.func, ast.Attribute): elif isinstance(val.func, ast.Attribute):
callee_name = getattr(val.func, 'attr', None) callee_name = getattr(val.func, 'attr', None)
if callee_name: if callee_name:
sym = self.Trans.SymbolTable.get(callee_name) sym = self.Trans.SymbolTable.lookup(callee_name)
if sym and isinstance(sym, dict): if sym and isinstance(sym, dict):
ret_type_str = sym.get('return_type', '') ret_type_str = sym.get('return_type', '')
if ret_type_str and ret_type_str != 'int': if ret_type_str and ret_type_str != 'int':
@@ -203,7 +203,7 @@ class FunctionHandle(BaseHandle):
var_name = val.id var_name = val.id
if var_name in local_var_types: if var_name in local_var_types:
return local_var_types[var_name] return local_var_types[var_name]
var_info = self.Trans.SymbolTable.get(var_name) var_info = self.Trans.SymbolTable.lookup(var_name)
if var_info and isinstance(var_info, dict): if var_info and isinstance(var_info, dict):
var_type = var_info.get('type', '') var_type = var_info.get('type', '')
if var_type and var_type != 'int': if var_type and var_type != 'int':
@@ -259,7 +259,7 @@ class FunctionHandle(BaseHandle):
break break
if isinstance(val.value, ast.Name): if isinstance(val.value, ast.Name):
var_name = val.value.id var_name = val.value.id
var_info = self.Trans.SymbolTable.get(var_name) var_info = self.Trans.SymbolTable.lookup(var_name)
if var_info and isinstance(var_info, dict): if var_info and isinstance(var_info, dict):
var_type = var_info.get('type', '') var_type = var_info.get('type', '')
if var_type.startswith('list[') or var_type.startswith('List['): if var_type.startswith('list[') or var_type.startswith('List['):
@@ -1386,7 +1386,7 @@ class FunctionHandle(BaseHandle):
if self.Trans.VarScopes: if self.Trans.VarScopes:
self.Trans.VarScopes.pop() self.Trans.VarScopes.pop()
self.Trans.FunctionReturnTypes[FuncName] = ReturnTypeInfo self.Trans.FunctionReturnTypes[FuncName] = ReturnTypeInfo
if FuncName not in self.Trans.SymbolTable: if not self.Trans.SymbolTable.has(FuncName):
FuncInfo = CTypeInfo() FuncInfo = CTypeInfo()
FuncInfo.Name = FuncName FuncInfo.Name = FuncName
FuncInfo.IsFunction = True FuncInfo.IsFunction = True
@@ -1395,7 +1395,7 @@ class FunctionHandle(BaseHandle):
FuncInfo.IsInline = True FuncInfo.IsInline = True
FuncInfo.InlineBody = Node.body FuncInfo.InlineBody = Node.body
FuncInfo.InlineParams = [arg.arg for arg in Node.args.args] FuncInfo.InlineParams = [arg.arg for arg in Node.args.args]
self.Trans.SymbolTable[FuncName] = FuncInfo self.Trans.SymbolTable.insert(FuncName, FuncInfo)
else: else:
existing = self.Trans.SymbolTable[FuncName] existing = self.Trans.SymbolTable[FuncName]
if existing.MetaList == FuncMeta.NONE and func_meta != FuncMeta.NONE: if existing.MetaList == FuncMeta.NONE and func_meta != FuncMeta.NONE:
@@ -1407,7 +1407,7 @@ class FunctionHandle(BaseHandle):
# property setter/deleter: 在原始 PropKey不带后缀下注册 MetaList # property setter/deleter: 在原始 PropKey不带后缀下注册 MetaList
if FuncMeta.PROPERTY_SETTER in func_meta or FuncMeta.PROPERTY_DELETER in func_meta: if FuncMeta.PROPERTY_SETTER in func_meta or FuncMeta.PROPERTY_DELETER in func_meta:
BasePropKey = f"{ClassName}.{RawFuncName}" if ClassName else RawFuncName BasePropKey = f"{ClassName}.{RawFuncName}" if ClassName else RawFuncName
if BasePropKey in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(BasePropKey):
base_existing = self.Trans.SymbolTable[BasePropKey] base_existing = self.Trans.SymbolTable[BasePropKey]
if func_meta != FuncMeta.NONE: if func_meta != FuncMeta.NONE:
base_existing.MetaList = base_existing.MetaList | func_meta base_existing.MetaList = base_existing.MetaList | func_meta
@@ -1416,5 +1416,5 @@ class FunctionHandle(BaseHandle):
PropInfo.Name = BasePropKey PropInfo.Name = BasePropKey
PropInfo.IsFunction = True PropInfo.IsFunction = True
PropInfo.MetaList = func_meta PropInfo.MetaList = func_meta
self.Trans.SymbolTable[BasePropKey] = PropInfo self.Trans.SymbolTable.insert(BasePropKey, PropInfo)
return func return func

View File

@@ -71,10 +71,8 @@ class IfHandle(BaseHandle):
Gen = self.Trans.LlvmGen Gen = self.Trans.LlvmGen
if hasattr(Gen, '_define_constants') and name in Gen._define_constants: if hasattr(Gen, '_define_constants') and name in Gen._define_constants:
return True return True
if name in self.Trans.SymbolTable: if self.Trans.SymbolTable.is_define(name):
info = self.Trans.SymbolTable[name] return True
if info.IsDefine:
return True
platform_macros = self._get_platform_macros() platform_macros = self._get_platform_macros()
return name in platform_macros return name in platform_macros
@@ -84,7 +82,7 @@ class IfHandle(BaseHandle):
val = Gen._define_constants[name] val = Gen._define_constants[name]
if isinstance(val, (int, float)): if isinstance(val, (int, float)):
return val return val
if name in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(name):
info = self.Trans.SymbolTable[name] info = self.Trans.SymbolTable[name]
if info.IsDefine: if info.IsDefine:
val = info.DefineValue val = info.DefineValue

View File

@@ -45,20 +45,18 @@ class ImportHandle(BaseHandle):
def _EmitImportDeclarationsLlvm(self, Node, Gen): def _EmitImportDeclarationsLlvm(self, Node, Gen):
if not getattr(self.Trans, '_ImportedModules', None): if not getattr(self.Trans, '_ImportedModules', None):
self.Trans._ImportedModules = set() self.Trans._ImportedModules = set()
if not getattr(self.Trans, '_ImportAliases', None):
self.Trans._ImportAliases = {}
for alias in Node.names: for alias in Node.names:
name = alias.name name = alias.name
if name in ('c', 't'): if name in ('c', 't'):
continue continue
self.Trans._ImportedModules.add(name) self.Trans._ImportedModules.add(name)
if alias.asname: if alias.asname:
self.Trans._ImportAliases[alias.asname] = name self.Trans.SymbolTable.import_aliases[alias.asname] = name
# 同时在符号表中注册模块别名,以便 CTypeInfo.FromNode 能解析 # 同时在符号表中注册模块别名,以便 CTypeInfo.FromNode 能解析
AliasInfo = CTypeInfo() AliasInfo = CTypeInfo()
AliasInfo.IsModuleAlias = True AliasInfo.IsModuleAlias = True
AliasInfo.ResolvedModule = name AliasInfo.ResolvedModule = name
self.Trans.SymbolTable[alias.asname] = AliasInfo self.Trans.SymbolTable.insert(alias.asname, AliasInfo)
current_module = self._get_current_module_name() current_module = self._get_current_module_name()
self._EmitModuleDeclarationsLlvm(name, Gen, register_module_name=current_module) self._EmitModuleDeclarationsLlvm(name, Gen, register_module_name=current_module)
@@ -73,14 +71,14 @@ class ImportHandle(BaseHandle):
# into _define_constants so they can be found by _HandleNameLlvm # into _define_constants so they can be found by _HandleNameLlvm
if not asname or asname == name: if not asname or asname == name:
# Check if this name is a CDefine constant in SymbolTable # Check if this name is a CDefine constant in SymbolTable
sym_info = self.Trans.SymbolTable.get(name) sym_info = self.Trans.SymbolTable.lookup(name)
if sym_info and sym_info.IsDefine and sym_info.DefineValue is not None: if sym_info and sym_info.IsDefine and sym_info.DefineValue is not None:
define_constants = vars(Gen).setdefault('_define_constants', {}) define_constants = vars(Gen).setdefault('_define_constants', {})
if name not in define_constants: if name not in define_constants:
define_constants[name] = sym_info.DefineValue define_constants[name] = sym_info.DefineValue
# Also check with module prefix # Also check with module prefix
for prefix_key in [f"{module}.{name}", name]: for prefix_key in [f"{module}.{name}", name]:
sym_info2 = self.Trans.SymbolTable.get(prefix_key) sym_info2 = self.Trans.SymbolTable.lookup(prefix_key)
if sym_info2 and sym_info2.IsDefine and sym_info2.DefineValue is not None: if sym_info2 and sym_info2.IsDefine and sym_info2.DefineValue is not None:
define_constants = vars(Gen).setdefault('_define_constants', {}) define_constants = vars(Gen).setdefault('_define_constants', {})
if name not in define_constants: if name not in define_constants:
@@ -94,8 +92,8 @@ class ImportHandle(BaseHandle):
Gen.functions[asname] = Gen.functions[name] Gen.functions[asname] = Gen.functions[name]
if name in Gen.structs: if name in Gen.structs:
Gen.structs[asname] = Gen.structs[name] Gen.structs[asname] = Gen.structs[name]
if name in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(name):
self.Trans.SymbolTable[asname] = self.Trans.SymbolTable[name] self.Trans.SymbolTable.insert(asname, self.Trans.SymbolTable[name])
if name in Gen.variables: if name in Gen.variables:
Gen.variables[asname] = Gen.variables[name] Gen.variables[asname] = Gen.variables[name]
if name in Gen.global_vars: if name in Gen.global_vars:
@@ -107,7 +105,7 @@ class ImportHandle(BaseHandle):
for key in list(self.Trans.SymbolTable.keys()): for key in list(self.Trans.SymbolTable.keys()):
if key.startswith(f'{name}.'): if key.startswith(f'{name}.'):
suffix = key[len(name):] suffix = key[len(name):]
self.Trans.SymbolTable[f'{asname}{suffix}'] = self.Trans.SymbolTable[key] self.Trans.SymbolTable.insert(f'{asname}{suffix}', self.Trans.SymbolTable[key])
for meta_dict in (Gen.class_members, Gen.class_member_defaults, for meta_dict in (Gen.class_members, Gen.class_member_defaults,
Gen.class_member_signeds, Gen.class_member_bitfields, Gen.class_member_signeds, Gen.class_member_bitfields,
Gen.class_member_byteorders, Gen.class_member_bitoffsets, Gen.class_member_byteorders, Gen.class_member_bitoffsets,
@@ -127,8 +125,6 @@ class ImportHandle(BaseHandle):
if module in ('c', 't'): if module in ('c', 't'):
if not getattr(self.Trans, '_ImportedModules', None): if not getattr(self.Trans, '_ImportedModules', None):
self.Trans._ImportedModules = set() self.Trans._ImportedModules = set()
if not getattr(self.Trans, '_ImportAliases', None):
self.Trans._ImportAliases = {}
self.Trans._ImportedModules.add(module) self.Trans._ImportedModules.add(module)
if not hasattr(self.Trans, '_t_c_imported_names'): if not hasattr(self.Trans, '_t_c_imported_names'):
self.Trans._t_c_imported_names = {} self.Trans._t_c_imported_names = {}
@@ -139,8 +135,6 @@ class ImportHandle(BaseHandle):
return return
if not getattr(self.Trans, '_ImportedModules', None): if not getattr(self.Trans, '_ImportedModules', None):
self.Trans._ImportedModules = set() self.Trans._ImportedModules = set()
if not getattr(self.Trans, '_ImportAliases', None):
self.Trans._ImportAliases = {}
current_module = self._get_current_module_name() current_module = self._get_current_module_name()
if Node.level and Node.level > 0: if Node.level and Node.level > 0:
current_file = getattr(self.Trans, 'CurrentFile', '') or '' current_file = getattr(self.Trans, 'CurrentFile', '') or ''
@@ -190,7 +184,7 @@ class ImportHandle(BaseHandle):
self.Trans._ImportedModules.add(alias.name) self.Trans._ImportedModules.add(alias.name)
self._LoadModuleDeclarationsFromFile(sub_path, Gen, module_name=alias.name, register_module_name=current_module) self._LoadModuleDeclarationsFromFile(sub_path, Gen, module_name=alias.name, register_module_name=current_module)
if alias.asname: if alias.asname:
self.Trans._ImportAliases[alias.asname] = alias.name self.Trans.SymbolTable.import_aliases[alias.asname] = alias.name
found_sub = True found_sub = True
break break
if not found_sub: if not found_sub:
@@ -206,7 +200,7 @@ class ImportHandle(BaseHandle):
self.Trans._ImportedModules.add(sub_ModulePath) self.Trans._ImportedModules.add(sub_ModulePath)
self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=alias.name, register_module_name=current_module) self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=alias.name, register_module_name=current_module)
if alias.asname: if alias.asname:
self.Trans._ImportAliases[alias.asname] = alias.name self.Trans.SymbolTable.import_aliases[alias.asname] = alias.name
self._RegisterFromImportAliases(Node, Gen, module or pkg_name) self._RegisterFromImportAliases(Node, Gen, module or pkg_name)
return return
self.Trans._ImportedModules.add(module) self.Trans._ImportedModules.add(module)
@@ -725,19 +719,19 @@ class ImportHandle(BaseHandle):
if isinstance(ValueTypeInfo, CTypeInfo) and (ValueTypeInfo.BaseType or ValueTypeInfo.PtrCount > 0): if isinstance(ValueTypeInfo, CTypeInfo) and (ValueTypeInfo.BaseType or ValueTypeInfo.PtrCount > 0):
ValueTypeInfo.IsTypedef = True ValueTypeInfo.IsTypedef = True
ValueTypeInfo.Name = VarName ValueTypeInfo.Name = VarName
self.Trans.SymbolTable[VarName] = ValueTypeInfo self.Trans.SymbolTable.insert(VarName, ValueTypeInfo)
if module_name: if module_name:
FullName = f"{module_name}.{VarName}" FullName = f"{module_name}.{VarName}"
self.Trans.SymbolTable[FullName] = ValueTypeInfo self.Trans.SymbolTable.insert(FullName, ValueTypeInfo)
return return
TTypeInfo = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.annotation) TTypeInfo = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.annotation)
if TTypeInfo: if TTypeInfo:
TTypeInfo.IsTypedef = True TTypeInfo.IsTypedef = True
TTypeInfo.Name = VarName TTypeInfo.Name = VarName
self.Trans.SymbolTable[VarName] = TTypeInfo self.Trans.SymbolTable.insert(VarName, TTypeInfo)
if module_name: if module_name:
FullName = f"{module_name}.{VarName}" FullName = f"{module_name}.{VarName}"
self.Trans.SymbolTable[FullName] = TTypeInfo self.Trans.SymbolTable.insert(FullName, TTypeInfo)
return return
if IsCDefine: if IsCDefine:
@@ -948,7 +942,7 @@ class ImportHandle(BaseHandle):
info.Lineno = lineno info.Lineno = lineno
info.file = FilePath info.file = FilePath
# 直接添加到 SymbolTable 字典 # 直接添加到 SymbolTable 字典
self.Trans.SymbolTable[FullName] = info self.Trans.SymbolTable.insert(FullName, info)
def _check_annotation_for_state(self, annotation) -> bool: def _check_annotation_for_state(self, annotation) -> bool:
import ast import ast
@@ -1020,7 +1014,7 @@ class ImportHandle(BaseHandle):
ParamTypes = [] ParamTypes = []
is_method = is_class_method or '.__' in FuncName is_method = is_class_method or '.__' in FuncName
class_name_for_method = FuncName.split('.')[0] if '.' in FuncName else None class_name_for_method = FuncName.split('.')[0] if '.' in FuncName else None
class_is_cpython = class_name_for_method and class_name_for_method in self.Trans.SymbolTable and self.Trans.SymbolTable[class_name_for_method].IsCpythonObject class_is_cpython = class_name_for_method and self.Trans.SymbolTable.is_struct(class_name_for_method)
for i, Arg in enumerate(Node.args.args): for i, Arg in enumerate(Node.args.args):
if i == 0 and is_method: if i == 0 and is_method:
# self parameter of a method should always be a pointer to the struct # self parameter of a method should always be a pointer to the struct
@@ -1107,12 +1101,12 @@ class ImportHandle(BaseHandle):
func_meta |= FuncMeta.PROPERTY_GETTER func_meta |= FuncMeta.PROPERTY_GETTER
elif d.attr == 'deleter': elif d.attr == 'deleter':
func_meta |= FuncMeta.PROPERTY_DELETER func_meta |= FuncMeta.PROPERTY_DELETER
if FuncName not in self.Trans.SymbolTable: if not self.Trans.SymbolTable.has(FuncName):
FuncInfo = CTypeInfo() FuncInfo = CTypeInfo()
FuncInfo.Name = FuncName FuncInfo.Name = FuncName
FuncInfo.IsFunction = True FuncInfo.IsFunction = True
FuncInfo.MetaList = func_meta FuncInfo.MetaList = func_meta
self.Trans.SymbolTable[FuncName] = FuncInfo self.Trans.SymbolTable.insert(FuncName, FuncInfo)
else: else:
existing = self.Trans.SymbolTable[FuncName] existing = self.Trans.SymbolTable[FuncName]
if existing.MetaList == FuncMeta.NONE and func_meta != FuncMeta.NONE: if existing.MetaList == FuncMeta.NONE and func_meta != FuncMeta.NONE:
@@ -1120,16 +1114,16 @@ class ImportHandle(BaseHandle):
# 同时注册带模块前缀的符号,以便 module.func_name 查找能命中 # 同时注册带模块前缀的符号,以便 module.func_name 查找能命中
if source_module_name and source_module_name not in ('c', 't'): if source_module_name and source_module_name not in ('c', 't'):
FullSymKey = f"{source_module_name}.{FuncName}" FullSymKey = f"{source_module_name}.{FuncName}"
if FullSymKey not in self.Trans.SymbolTable: if not self.Trans.SymbolTable.has(FullSymKey):
FullFuncInfo = CTypeInfo() FullFuncInfo = CTypeInfo()
FullFuncInfo.Name = FullSymKey FullFuncInfo.Name = FullSymKey
FullFuncInfo.IsFunction = True FullFuncInfo.IsFunction = True
FullFuncInfo.MetaList = func_meta FullFuncInfo.MetaList = func_meta
self.Trans.SymbolTable[FullSymKey] = FullFuncInfo self.Trans.SymbolTable.insert(FullSymKey, FullFuncInfo)
# property setter/deleter: 在原始 PropKey不带后缀下注册 MetaList # property setter/deleter: 在原始 PropKey不带后缀下注册 MetaList
if FuncMeta.PROPERTY_SETTER in func_meta or FuncMeta.PROPERTY_DELETER in func_meta: if FuncMeta.PROPERTY_SETTER in func_meta or FuncMeta.PROPERTY_DELETER in func_meta:
BasePropKey = FuncName.replace('$set', '').replace('$del', '') BasePropKey = FuncName.replace('$set', '').replace('$del', '')
if BasePropKey in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(BasePropKey):
base_existing = self.Trans.SymbolTable[BasePropKey] base_existing = self.Trans.SymbolTable[BasePropKey]
if func_meta != FuncMeta.NONE: if func_meta != FuncMeta.NONE:
base_existing.MetaList = base_existing.MetaList | func_meta base_existing.MetaList = base_existing.MetaList | func_meta
@@ -1138,7 +1132,7 @@ class ImportHandle(BaseHandle):
PropInfo.Name = BasePropKey PropInfo.Name = BasePropKey
PropInfo.IsFunction = True PropInfo.IsFunction = True
PropInfo.MetaList = func_meta PropInfo.MetaList = func_meta
self.Trans.SymbolTable[BasePropKey] = PropInfo self.Trans.SymbolTable.insert(BasePropKey, PropInfo)
if register_module_name and register_module_name != source_module_name: if register_module_name and register_module_name != source_module_name:
ReexportName = Gen._mangle_func_name(FuncName, module_name=register_module_name) ReexportName = Gen._mangle_func_name(FuncName, module_name=register_module_name)
Gen.functions[ReexportName] = func Gen.functions[ReexportName] = func
@@ -1208,14 +1202,14 @@ class ImportHandle(BaseHandle):
CInfo.IsStruct = True CInfo.IsStruct = True
if module_name: if module_name:
FullName = f"{module_name}.{ClassName}" FullName = f"{module_name}.{ClassName}"
self.Trans.SymbolTable[FullName] = CInfo self.Trans.SymbolTable.insert(FullName, CInfo)
self.Trans.SymbolTable[ClassName] = CInfo self.Trans.SymbolTable.insert(ClassName, CInfo)
if IsCenum: if IsCenum:
EnumTypeNode = CTypeInfo() EnumTypeNode = CTypeInfo()
EnumTypeNode.Name = ClassName EnumTypeNode.Name = ClassName
EnumTypeNode.BaseType = t.CEnum(ClassName) EnumTypeNode.BaseType = t.CEnum(ClassName)
EnumTypeNode.IsEnum = True EnumTypeNode.IsEnum = True
self.Trans.SymbolTable[ClassName] = EnumTypeNode self.Trans.SymbolTable.insert(ClassName, EnumTypeNode)
for item in Node.body: for item in Node.body:
VarName = None VarName = None
if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name):
@@ -1237,9 +1231,9 @@ class ImportHandle(BaseHandle):
MemberNode.EnumName = ClassName MemberNode.EnumName = ClassName
MemberNode.Lineno = item.lineno MemberNode.Lineno = item.lineno
MemberNode.IsEnumMember = True MemberNode.IsEnumMember = True
self.Trans.SymbolTable[VarName] = MemberNode self.Trans.SymbolTable.insert(VarName, MemberNode)
self.Trans.SymbolTable[f"{ClassName}.{VarName}"] = MemberNode self.Trans.SymbolTable.insert(f"{ClassName}.{VarName}", MemberNode)
self.Trans.SymbolTable[f"{ClassName}_{VarName}"] = MemberNode self.Trans.SymbolTable.insert(f"{ClassName}_{VarName}", MemberNode)
return return
self._TryLoadStructFromStub(ClassName, Gen) self._TryLoadStructFromStub(ClassName, Gen)
source_sha1 = None source_sha1 = None
@@ -1334,19 +1328,19 @@ class ImportHandle(BaseHandle):
func_meta |= FuncMeta.PROPERTY_DELETER func_meta |= FuncMeta.PROPERTY_DELETER
# setter/deleter 的 SymKey 使用带后缀的函数名 # setter/deleter 的 SymKey 使用带后缀的函数名
SymKey = DeclFuncName SymKey = DeclFuncName
if SymKey not in self.Trans.SymbolTable: if not self.Trans.SymbolTable.has(SymKey):
FuncInfo = CTypeInfo() FuncInfo = CTypeInfo()
FuncInfo.Name = SymKey FuncInfo.Name = SymKey
FuncInfo.IsFunction = True FuncInfo.IsFunction = True
FuncInfo.MetaList = func_meta FuncInfo.MetaList = func_meta
self.Trans.SymbolTable[SymKey] = FuncInfo self.Trans.SymbolTable.insert(SymKey, FuncInfo)
else: else:
existing = self.Trans.SymbolTable[SymKey] existing = self.Trans.SymbolTable[SymKey]
if existing.MetaList == FuncMeta.NONE and func_meta != FuncMeta.NONE: if existing.MetaList == FuncMeta.NONE and func_meta != FuncMeta.NONE:
existing.MetaList = func_meta existing.MetaList = func_meta
# setter/deleter: 同时在原始 PropKey不带后缀下注册 MetaList # setter/deleter: 同时在原始 PropKey不带后缀下注册 MetaList
if is_item_prop_setter or is_item_prop_deleter: if is_item_prop_setter or is_item_prop_deleter:
if FuncFullName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(FuncFullName):
base_existing = self.Trans.SymbolTable[FuncFullName] base_existing = self.Trans.SymbolTable[FuncFullName]
if func_meta != FuncMeta.NONE: if func_meta != FuncMeta.NONE:
base_existing.MetaList = base_existing.MetaList | func_meta base_existing.MetaList = base_existing.MetaList | func_meta
@@ -1355,7 +1349,7 @@ class ImportHandle(BaseHandle):
PropInfo.Name = FuncFullName PropInfo.Name = FuncFullName
PropInfo.IsFunction = True PropInfo.IsFunction = True
PropInfo.MetaList = func_meta PropInfo.MetaList = func_meta
self.Trans.SymbolTable[FuncFullName] = PropInfo self.Trans.SymbolTable.insert(FuncFullName, PropInfo)
if has_methods: if has_methods:
if IsCVTable: if IsCVTable:
Gen._cross_module_vtable_classes.add(ClassName) Gen._cross_module_vtable_classes.add(ClassName)

View File

@@ -19,9 +19,8 @@ class MatchHandle(BaseHandle):
SubjectPtr = None SubjectPtr = None
if isinstance(Node.subject, ast.Name): if isinstance(Node.subject, ast.Name):
VarName = Node.subject.id VarName = Node.subject.id
if VarName in self.Trans.SymbolTable: TypeInfo = self.Trans.SymbolTable.lookup(VarName)
TypeInfo = self.Trans.SymbolTable[VarName] if TypeInfo and TypeInfo.IsRenum:
if TypeInfo.IsRenum:
IsRenumMatch = True IsRenumMatch = True
RenumName = TypeInfo.Name RenumName = TypeInfo.Name
SubjectPtr = Gen._loadVar(VarName) SubjectPtr = Gen._loadVar(VarName)
@@ -35,11 +34,11 @@ class MatchHandle(BaseHandle):
VariantName = cls_node.id VariantName = cls_node.id
elif isinstance(cls_node, ast.Attribute): elif isinstance(cls_node, ast.Attribute):
VariantName = cls_node.attr VariantName = cls_node.attr
if VariantName and VariantName in self.Trans.SymbolTable: if VariantName and self.Trans.SymbolTable.has(VariantName):
SymInfo = self.Trans.SymbolTable[VariantName] SymInfo = self.Trans.SymbolTable[VariantName]
if SymInfo.IsEnumMember and SymInfo.EnumName: if SymInfo.IsEnumMember and SymInfo.EnumName:
EnumName = SymInfo.EnumName EnumName = SymInfo.EnumName
if EnumName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(EnumName):
EnumInfo = self.Trans.SymbolTable[EnumName] EnumInfo = self.Trans.SymbolTable[EnumName]
if EnumInfo.IsRenum: if EnumInfo.IsRenum:
IsRenumMatch = True IsRenumMatch = True
@@ -207,7 +206,7 @@ class MatchHandle(BaseHandle):
VariantName = cls_node.attr VariantName = cls_node.attr
if VariantName: if VariantName:
TagValue = None TagValue = None
if VariantName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(VariantName):
SymInfo = self.Trans.SymbolTable[VariantName] SymInfo = self.Trans.SymbolTable[VariantName]
if SymInfo.IsEnumMember: if SymInfo.IsEnumMember:
TagValue = SymInfo.value TagValue = SymInfo.value

View File

@@ -59,7 +59,7 @@ class HandlesTypeMerge(BaseHandle):
) )
ast.copy_location(virtual_attr, Node) ast.copy_location(virtual_attr, Node)
return self.GetCTypeInfo(virtual_attr) return self.GetCTypeInfo(virtual_attr)
if TypeName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(TypeName):
Entry = self.Trans.SymbolTable[TypeName] Entry = self.Trans.SymbolTable[TypeName]
if Entry and Entry.IsTypedef: if Entry and Entry.IsTypedef:
if isinstance(Entry, CTypeInfo) and Entry.BaseType: if isinstance(Entry, CTypeInfo) and Entry.BaseType:
@@ -113,12 +113,12 @@ class HandlesTypeMerge(BaseHandle):
# 解析 import 别名: 如 import fat32_types as types -> types -> fat32_types # 解析 import 别名: 如 import fat32_types as types -> types -> fat32_types
if ModulePath: if ModulePath:
import_aliases = getattr(self.Trans, '_ImportAliases', {}) import_aliases = self.Trans.SymbolTable.import_aliases
if ModulePath in import_aliases: if ModulePath in import_aliases:
ModulePath = import_aliases[ModulePath] ModulePath = import_aliases[ModulePath]
else: else:
# 也尝试在符号表中查找模块别名 # 也尝试在符号表中查找模块别名
if ModulePath in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(ModulePath):
entry = self.Trans.SymbolTable[ModulePath] entry = self.Trans.SymbolTable[ModulePath]
if isinstance(entry, CTypeInfo) and entry.IsModuleAlias: if isinstance(entry, CTypeInfo) and entry.IsModuleAlias:
resolved = entry.ResolvedModule resolved = entry.ResolvedModule
@@ -185,7 +185,7 @@ class HandlesTypeMerge(BaseHandle):
FullName = f"{ModulePath}.{TypeName}" if ModulePath else TypeName FullName = f"{ModulePath}.{TypeName}" if ModulePath else TypeName
if TypeName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(TypeName):
Entry = self.Trans.SymbolTable[TypeName] Entry = self.Trans.SymbolTable[TypeName]
if Entry and Entry.IsTypedef: if Entry and Entry.IsTypedef:
if isinstance(Entry, CTypeInfo) and Entry.BaseType: if isinstance(Entry, CTypeInfo) and Entry.BaseType:
@@ -213,7 +213,7 @@ class HandlesTypeMerge(BaseHandle):
return Result return Result
return CTypeInfo() return CTypeInfo()
if FullName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(FullName):
Info = self.Trans.SymbolTable[FullName] Info = self.Trans.SymbolTable[FullName]
if Info and Info.IsTypedef: if Info and Info.IsTypedef:
if isinstance(Info, CTypeInfo) and Info.BaseType and (not isinstance(Info.BaseType, (t._CTypedef,)) or Info.PtrCount > 0): if isinstance(Info, CTypeInfo) and Info.BaseType and (not isinstance(Info.BaseType, (t._CTypedef,)) or Info.PtrCount > 0):
@@ -233,22 +233,22 @@ class HandlesTypeMerge(BaseHandle):
return Result return Result
return Info.Copy() if Info else CTypeInfo() return Info.Copy() if Info else CTypeInfo()
if TypeName not in self.Trans.SymbolTable: if not self.Trans.SymbolTable.has(TypeName):
if not self._IsTModuleType(TypeName) and not (ModulePath and ModulePath.startswith(('t.', 'c.'))): if not self._IsTModuleType(TypeName) and not (ModulePath and ModulePath.startswith(('t.', 'c.'))):
IsEnumMember = False IsEnumMember = False
FirstName = ModuleParts[0] FirstName = ModuleParts[0]
if FirstName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(FirstName):
Entry = self.Trans.SymbolTable[FirstName] Entry = self.Trans.SymbolTable[FirstName]
if Entry and Entry.IsEnum: if Entry and Entry.IsEnum:
IsEnumMember = True IsEnumMember = True
if not IsEnumMember and FullName in self.Trans.SymbolTable: if not IsEnumMember and self.Trans.SymbolTable.has(FullName):
Entry = self.Trans.SymbolTable[FullName] Entry = self.Trans.SymbolTable[FullName]
if Entry and Entry.IsEnumMember: if Entry and Entry.IsEnumMember:
IsEnumMember = True IsEnumMember = True
IsVariable = False IsVariable = False
if not IsEnumMember and FullName in self.Trans.SymbolTable: if not IsEnumMember and self.Trans.SymbolTable.has(FullName):
Entry = self.Trans.SymbolTable[FullName] Entry = self.Trans.SymbolTable[FullName]
if Entry and Entry.TypeCls is not None: if Entry and Entry.TypeCls is not None:
IsVariable = True IsVariable = True
@@ -263,7 +263,7 @@ class HandlesTypeMerge(BaseHandle):
FirstName = ModuleParts[0] FirstName = ModuleParts[0]
FullName = f"{ModulePath}.{TypeName}" if ModulePath else TypeName FullName = f"{ModulePath}.{TypeName}" if ModulePath else TypeName
if FullName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(FullName):
Info = self.Trans.SymbolTable[FullName] Info = self.Trans.SymbolTable[FullName]
if Info and Info.IsEnumMember: if Info and Info.IsEnumMember:
Result = CTypeInfo() Result = CTypeInfo()
@@ -288,7 +288,7 @@ class HandlesTypeMerge(BaseHandle):
return Result return Result
return Info.Copy() if Info else CTypeInfo() return Info.Copy() if Info else CTypeInfo()
if FirstName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(FirstName):
Entry = self.Trans.SymbolTable[FirstName] Entry = self.Trans.SymbolTable[FirstName]
if Entry: if Entry:
Result = CTypeInfo() Result = CTypeInfo()
@@ -307,7 +307,7 @@ class HandlesTypeMerge(BaseHandle):
EnumName = None EnumName = None
else: else:
EnumName = CTypeHelper.StripTypePrefix(Entry.OriginalType) EnumName = CTypeHelper.StripTypePrefix(Entry.OriginalType)
if EnumName and EnumName in self.Trans.SymbolTable: if EnumName and self.Trans.SymbolTable.has(EnumName):
EnumEntry = self.Trans.SymbolTable[EnumName] EnumEntry = self.Trans.SymbolTable[EnumName]
if EnumEntry and EnumEntry.IsEnum: if EnumEntry and EnumEntry.IsEnum:
Result.BaseType = t._CTypedef(TypeName) Result.BaseType = t._CTypedef(TypeName)
@@ -315,7 +315,7 @@ class HandlesTypeMerge(BaseHandle):
return Result return Result
if FirstName in self.Trans.GeneratedTypes: if FirstName in self.Trans.GeneratedTypes:
if FirstName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(FirstName):
Entry = self.Trans.SymbolTable[FirstName] Entry = self.Trans.SymbolTable[FirstName]
if Entry and Entry.IsEnum: if Entry and Entry.IsEnum:
Result.BaseType = t.CEnum(TypeName) Result.BaseType = t.CEnum(TypeName)
@@ -357,12 +357,12 @@ class HandlesTypeMerge(BaseHandle):
AttrInfo.OriginalType = OriginalInfo AttrInfo.OriginalType = OriginalInfo
except Exception: except Exception:
AttrInfo.OriginalType = self._MakeCTypeInfoFromName(Attr().CName) if hasattr(Attr(), 'CName') else None AttrInfo.OriginalType = self._MakeCTypeInfoFromName(Attr().CName) if hasattr(Attr(), 'CName') else None
self.Trans.SymbolTable[AttrName] = AttrInfo self.Trans.SymbolTable.insert(AttrName, AttrInfo)
except Exception as e: except Exception as e:
self.Trans._UserTypeModules[ModuleName] = None self.Trans._UserTypeModules[ModuleName] = None
FullName = f'{ModulePath}.{TypeName}' if ModulePath else TypeName FullName = f'{ModulePath}.{TypeName}' if ModulePath else TypeName
if FullName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(FullName):
Entry = self.Trans.SymbolTable[FullName] Entry = self.Trans.SymbolTable[FullName]
if Entry and Entry.IsTypedef: if Entry and Entry.IsTypedef:
if isinstance(Entry, CTypeInfo) and Entry.BaseType: if isinstance(Entry, CTypeInfo) and Entry.BaseType:
@@ -383,7 +383,7 @@ class HandlesTypeMerge(BaseHandle):
return Result return Result
return Entry.Copy() if Entry else CTypeInfo() return Entry.Copy() if Entry else CTypeInfo()
if TypeName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(TypeName):
Entry = self.Trans.SymbolTable[TypeName] Entry = self.Trans.SymbolTable[TypeName]
if Entry and Entry.IsTypedef: if Entry and Entry.IsTypedef:
if isinstance(Entry, CTypeInfo) and Entry.BaseType: if isinstance(Entry, CTypeInfo) and Entry.BaseType:
@@ -417,7 +417,7 @@ class HandlesTypeMerge(BaseHandle):
IsEnumMember = False IsEnumMember = False
if ModuleParts and len(ModuleParts) >= 2: if ModuleParts and len(ModuleParts) >= 2:
FirstName = ModuleParts[0] FirstName = ModuleParts[0]
if FirstName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(FirstName):
Entry = self.Trans.SymbolTable[FirstName] Entry = self.Trans.SymbolTable[FirstName]
if Entry and Entry.IsEnum: if Entry and Entry.IsEnum:
return TypeName return TypeName

View File

@@ -23,7 +23,7 @@ class WithHandle(BaseHandle):
elif isinstance(context_expr.func, ast.Attribute): elif isinstance(context_expr.func, ast.Attribute):
ClassName = context_expr.func.attr ClassName = context_expr.func.attr
if ClassName and ClassName not in Gen.structs: if ClassName and ClassName not in Gen.structs:
if ClassName in self.Trans.SymbolTable: if self.Trans.SymbolTable.has(ClassName):
SymInfo = self.Trans.SymbolTable[ClassName] SymInfo = self.Trans.SymbolTable[ClassName]
if SymInfo.IsStruct or SymInfo.IsRenum: if SymInfo.IsStruct or SymInfo.IsRenum:
pass pass

View File

@@ -171,7 +171,7 @@ class BaseGenMixin:
return existing return existing
if clean_name in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum', 'Void', 'void'}: if clean_name in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum', 'Void', 'void'}:
return ir.IntType(8) return ir.IntType(8)
if hasattr(self, 'SymbolTable') and self.SymbolTable and clean_name in self.SymbolTable: if hasattr(self, 'SymbolTable') and self.SymbolTable and self.SymbolTable.has(clean_name):
Entry = self.SymbolTable[clean_name] Entry = self.SymbolTable[clean_name]
if Entry.IsTypedef: if Entry.IsTypedef:
resolved_str = self._resolve_typedef(clean_name) resolved_str = self._resolve_typedef(clean_name)
@@ -235,7 +235,7 @@ class BaseGenMixin:
return int(llvm_str[1:]) return int(llvm_str[1:])
# 2. 再查 SymbolTable用户定义的 typedef # 2. 再查 SymbolTable用户定义的 typedef
if hasattr(self, 'SymbolTable') and self.SymbolTable and name in self.SymbolTable: if hasattr(self, 'SymbolTable') and self.SymbolTable and self.SymbolTable.has(name):
Entry = self.SymbolTable[name] Entry = self.SymbolTable[name]
if Entry.IsTypedef: if Entry.IsTypedef:
if Entry.BaseType: if Entry.BaseType:

View File

@@ -205,7 +205,7 @@ class StructGenMixin:
all_classes = set(self.class_methods.keys()) | set(self.class_members.keys()) all_classes = set(self.class_methods.keys()) | set(self.class_members.keys())
for ClassName in all_classes: for ClassName in all_classes:
is_packed = ClassName in self.class_packed is_packed = ClassName in self.class_packed
if hasattr(self, 'SymbolTable') and self.SymbolTable and ClassName in self.SymbolTable: if hasattr(self, 'SymbolTable') and self.SymbolTable and self.SymbolTable.has(ClassName):
Entry = self.SymbolTable[ClassName] Entry = self.SymbolTable[ClassName]
if Entry.IsExceptionClass: if Entry.IsExceptionClass:
continue continue
@@ -302,7 +302,7 @@ class StructGenMixin:
# Step 4: 创建最终的 structs 并设置正确的成员类型 # Step 4: 创建最终的 structs 并设置正确的成员类型
for ClassName in all_classes: for ClassName in all_classes:
if hasattr(self, 'SymbolTable') and self.SymbolTable and ClassName in self.SymbolTable: if hasattr(self, 'SymbolTable') and self.SymbolTable and self.SymbolTable.has(ClassName):
Entry = self.SymbolTable[ClassName] Entry = self.SymbolTable[ClassName]
if Entry.IsExceptionClass: if Entry.IsExceptionClass:
continue continue

View File

@@ -58,7 +58,7 @@ class TypeConvertMixin:
if not name or not hasattr(self, 'SymbolTable') or not self.SymbolTable: if not name or not hasattr(self, 'SymbolTable') or not self.SymbolTable:
return None return None
entry = self.SymbolTable.get(name) entry = self.SymbolTable.lookup(name)
if not entry or not isinstance(entry, _CTypeInfo): if not entry or not isinstance(entry, _CTypeInfo):
return None return None
@@ -129,7 +129,7 @@ class TypeConvertMixin:
typedef_name = getattr(BaseType, 'value', '') or (type_info.Name if type_info else '') typedef_name = getattr(BaseType, 'value', '') or (type_info.Name if type_info else '')
if typedef_name and hasattr(self, 'SymbolTable') and self.SymbolTable: if typedef_name and hasattr(self, 'SymbolTable') and self.SymbolTable:
from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo
entry = self.SymbolTable.get(typedef_name) entry = self.SymbolTable.lookup(typedef_name)
if entry and isinstance(entry, _CTypeInfo) and entry.BaseType: if entry and isinstance(entry, _CTypeInfo) and entry.BaseType:
if not isinstance(entry.BaseType, _t._CTypedef) or entry.PtrCount > 0: if not isinstance(entry.BaseType, _t._CTypedef) or entry.PtrCount > 0:
return self._base_ctype_to_llvm(entry.BaseType, entry) return self._base_ctype_to_llvm(entry.BaseType, entry)
@@ -173,7 +173,7 @@ class TypeConvertMixin:
current = type_name current = type_name
while current not in visited: while current not in visited:
visited.add(current) visited.add(current)
if hasattr(self, 'SymbolTable') and self.SymbolTable and current in self.SymbolTable: if hasattr(self, 'SymbolTable') and self.SymbolTable and self.SymbolTable.has(current):
Entry = self.SymbolTable[current] Entry = self.SymbolTable[current]
if isinstance(Entry, dict) and Entry.get('type') == 'typedef': if isinstance(Entry, dict) and Entry.get('type') == 'typedef':
OriginalType = Entry.get('OriginalType', '') OriginalType = Entry.get('OriginalType', '')
@@ -394,7 +394,7 @@ class TypeConvertMixin:
if IsPtr and not isinstance(basic_stripped, ir.VoidType): if IsPtr and not isinstance(basic_stripped, ir.VoidType):
return ir.PointerType(basic_stripped) return ir.PointerType(basic_stripped)
return basic_stripped return basic_stripped
if hasattr(self, 'SymbolTable') and self.SymbolTable and type_str in self.SymbolTable: if hasattr(self, 'SymbolTable') and self.SymbolTable and self.SymbolTable.has(type_str):
_Entry = self.SymbolTable[type_str] _Entry = self.SymbolTable[type_str]
if _Entry.IsTypedef: if _Entry.IsTypedef:
resolved_str = self._resolve_typedef(type_str) resolved_str = self._resolve_typedef(type_str)
@@ -429,7 +429,7 @@ class TypeConvertMixin:
if IsPtr and not isinstance(basic_last, ir.VoidType): if IsPtr and not isinstance(basic_last, ir.VoidType):
return ir.PointerType(basic_last) return ir.PointerType(basic_last)
return basic_last return basic_last
if hasattr(self, 'SymbolTable') and self.SymbolTable and LastPart in self.SymbolTable: if hasattr(self, 'SymbolTable') and self.SymbolTable and self.SymbolTable.has(LastPart):
_Entry = self.SymbolTable[LastPart] _Entry = self.SymbolTable[LastPart]
if _Entry.IsTypedef: if _Entry.IsTypedef:
resolved_str = self._resolve_typedef(LastPart) resolved_str = self._resolve_typedef(LastPart)

220
lib/core/LLVMTypeMapper.py Normal file
View File

@@ -0,0 +1,220 @@
"""LLVMTypeMapper — AST 注解节点到 LLVM IR 类型字符串的映射器
从 SymbolTable 中提取的类型解析逻辑,职责单一:
将 Python AST 注解节点翻译为 LLVM IR 类型字符串(如 'i32', 'i8*', '{ i32, i8* }')。
原 SymbolTable 上的 4 个方法:
- _GetLLVMTypeStr → LLVMTypeMapper.get_llvm_type_str
- _GetFuncRetTypeStr → LLVMTypeMapper.get_func_ret_type_str
- _GetFuncParamTypeStr → LLVMTypeMapper.get_func_param_type_str
- _ResolveTypedefValueType → LLVMTypeMapper.resolve_typedef_value_type
"""
from __future__ import annotations
import ast
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from lib.core.SymbolTable import SymbolTable
from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper
class LLVMTypeMapper:
"""AST 注解节点 → LLVM IR 类型字符串 映射器"""
def __init__(self, symtab: SymbolTable):
self._symtab = symtab
# ==================================================================
# 公共 API
# ==================================================================
def get_llvm_type_str(self, node) -> str:
"""将 AST 注解节点转换为 LLVM IR 类型字符串"""
if node is None:
self._symtab.diagnostics.warn('', 0, "类型注解为 None回退到 i32")
return 'i32'
if isinstance(node, ast.Name):
return self._resolve_name(node)
elif isinstance(node, ast.Attribute):
return self._resolve_attribute(node)
elif isinstance(node, ast.Subscript):
return self._resolve_subscript(node)
elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
return self._resolve_bitor(node)
elif isinstance(node, ast.Constant):
if isinstance(node.value, bool):
return 'i8'
return 'i32'
elif isinstance(node, ast.Call):
return self._resolve_call(node)
self._symtab.diagnostics.warn('', 0, f"无法解析类型节点 {type(node).__name__},回退到 i32")
return 'i32'
def get_func_ret_type_str(self, returns_node) -> str:
"""提取函数返回类型的 LLVM 字符串"""
if returns_node is None:
return 'i32'
if isinstance(returns_node, ast.BinOp) and isinstance(returns_node.op, ast.BitOr):
left_str = self.get_llvm_type_str(returns_node.left)
right_str = self.get_llvm_type_str(returns_node.right)
if right_str and right_str.endswith('*'):
return right_str
if left_str and left_str.endswith('*'):
return left_str
if left_str and left_str not in ('i32', 'void', 'i64'):
return left_str
if right_str and right_str not in ('i32', 'void', 'i64'):
return right_str
return left_str
result = self.get_llvm_type_str(returns_node)
return result if result else 'i32'
def get_func_param_type_str(self, annotation_node) -> str:
"""提取函数参数类型的 LLVM 字符串"""
if annotation_node is None:
return 'i8*'
if isinstance(annotation_node, ast.BinOp) and isinstance(annotation_node.op, ast.BitOr):
left_str = self.get_llvm_type_str(annotation_node.left)
right_str = self.get_llvm_type_str(annotation_node.right)
if right_str and right_str.endswith('*'):
return right_str
if left_str and left_str.endswith('*'):
return left_str
if right_str and right_str not in ('i32', 'void', 'i64'):
return right_str
if left_str and left_str not in ('i32', 'void', 'i64'):
return left_str
if left_str and left_str.endswith('*'):
return left_str
return right_str if right_str else left_str
result = self.get_llvm_type_str(annotation_node)
return result if result else 'i8*'
def resolve_typedef_value_type(self, node) -> str:
"""解析 typedef 值表达式的 C 类型字符串"""
if node is None:
return ''
if isinstance(node, ast.Name):
if node.id in self._symtab:
Entry = self._symtab[node.id]
if Entry.IsTypedef and Entry.OriginalType:
return Entry.OriginalType
return ''
if isinstance(node, ast.Attribute):
if isinstance(node.value, ast.Name) and node.value.id == 't':
CName = CTypeHelper.GetCName(node.attr)
if CName and CName == '*':
return 'ptr'
if CName:
return CName
return ''
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
left_str = self.resolve_typedef_value_type(node.left)
right_str = self.resolve_typedef_value_type(node.right)
if right_str == 'ptr' or (right_str and right_str.endswith('*')):
base = left_str if left_str and left_str != 'ptr' else ''
return base + ' *' if base else 'void *'
if left_str == 'ptr' or (left_str and left_str.endswith('*')):
base = right_str if right_str and right_str != 'ptr' else ''
return base + ' *' if base else 'void *'
if right_str and right_str not in ('ptr', 'void', 'i32', 'i64'):
return right_str
if left_str and left_str not in ('ptr', 'void', 'i32', 'i64'):
return left_str
return left_str if left_str else right_str
return ''
# ==================================================================
# 内部解析方法
# ==================================================================
def _resolve_name(self, node: ast.Name) -> str:
"""解析 ast.Name 节点"""
id_map = {
'str': 'i8*', 'int': 'i32', 'bool': 'i8',
'float': 'double', 'None': 'void',
'UINT8PTR': 'i8*', 'INT8PTR': 'i8*', 'BYTEPTR': 'i8*',
'UINT16PTR': 'i16*', 'INT16PTR': 'i16*',
'UINT32PTR': 'i32*', 'INT32PTR': 'i32*',
'UINT64PTR': 'i64*', 'INT64PTR': 'i64*',
}
if node.id in id_map:
return id_map[node.id]
# 查找 SymbolTable 中的 typedef
if node.id in self._symtab:
entry = self._symtab[node.id]
if entry and entry.IsTypedef and entry.OriginalType:
if isinstance(entry.OriginalType, CTypeInfo) and entry.OriginalType.IsFuncPtr:
return 'i8*'
elif isinstance(entry.OriginalType, CTypeInfo) and entry.OriginalType.BaseType:
return entry.OriginalType.ToString()
elif isinstance(entry.OriginalType, str):
return entry.OriginalType
self._symtab.diagnostics.warn('', 0, f"无法解析 Name 类型 '{node.id}',回退到 i32")
return 'i32'
def _resolve_attribute(self, node: ast.Attribute) -> str:
"""解析 ast.Attribute 节点"""
attr_name = node.attr if hasattr(node, 'attr') else ''
from lib.includes.t import CTypeRegistry
llvm_str = CTypeRegistry.NameToLLVM(attr_name)
if llvm_str is not None:
return llvm_str
if attr_name in ('CState', 'CDefine', 'CTypedef', 'CExtern', 'CStatic', 'CConst', 'State'):
return ''
if attr_name in ('CCharPtr', 'CIntPtr', 'CVoidPtr', 'CArrayPtr'):
return 'i8*'
if attr_name == 'CVoidPtr':
return 'i8*'
if attr_name and attr_name[0].isupper() and attr_name not in CTypeRegistry._name_to_class:
return f'%struct.{attr_name}*'
if attr_name and attr_name not in CTypeRegistry._name_to_class:
return f'%struct.{attr_name}*'
self._symtab.diagnostics.warn('', 0, f"无法解析 Attribute 类型 '{attr_name}',回退到 i32")
return 'i32'
def _resolve_subscript(self, node: ast.Subscript) -> str:
"""解析 ast.Subscript 节点"""
if isinstance(node.value, ast.Name) and node.value.id == 'tuple':
slice_node = node.slice
elem_types = []
if isinstance(slice_node, ast.Tuple):
for elt in slice_node.elts:
elem_types.append(self.get_llvm_type_str(elt))
else:
elem_types.append(self.get_llvm_type_str(slice_node))
if elem_types:
return '{ ' + ', '.join(elem_types) + ' }'
if isinstance(node.value, ast.Name) and node.value.id == 'list':
slice_node = node.slice
if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) >= 1:
elem_type = self.get_llvm_type_str(slice_node.elts[0])
else:
elem_type = self.get_llvm_type_str(slice_node)
return elem_type + '*'
self._symtab.diagnostics.warn('', 0, "无法解析 Subscript 类型,回退到 i32")
return 'i32'
def _resolve_bitor(self, node: ast.BinOp) -> str:
"""解析 ast.BinOp(BitOr) 节点"""
left = self.get_llvm_type_str(node.left)
right = self.get_llvm_type_str(node.right)
if right and right.endswith('*'):
return right
if left and left.endswith('*'):
return left
if left and left not in ('i32', 'void', 'i64'):
return left
if right and right not in ('i32', 'void', 'i64'):
return right
return left if left else right
def _resolve_call(self, node: ast.Call) -> str:
"""解析 ast.Call 节点"""
if isinstance(node.func, ast.Attribute):
if hasattr(node.func.value, 'id') and node.func.value.id == 't':
return self.get_llvm_type_str(ast.Attribute(value=ast.Name(id='t'), attr=node.func.attr))
self._symtab.diagnostics.warn('', 0, "无法解析 Call 类型,回退到 i32")
return 'i32'

View File

@@ -19,6 +19,9 @@ class SymbolTable:
self._symbols: Dict[str, CTypeInfo] = {} self._symbols: Dict[str, CTypeInfo] = {}
from lib.core.DiagnosticCollector import DiagnosticCollector from lib.core.DiagnosticCollector import DiagnosticCollector
self.diagnostics = DiagnosticCollector() self.diagnostics = DiagnosticCollector()
from lib.core.LLVMTypeMapper import LLVMTypeMapper
self._type_mapper = LLVMTypeMapper(self)
self.import_aliases: Dict[str, str] = {}
def clear(self): def clear(self):
self._symbols.clear() self._symbols.clear()
@@ -69,6 +72,99 @@ class SymbolTable:
def __iter__(self) -> Iterator[str]: def __iter__(self) -> Iterator[str]:
return iter(self._symbols) return iter(self._symbols)
# ==================================================================
# 服务接口 — 语义化的符号查询与操作方法
# ==================================================================
def lookup(self, name: str) -> CTypeInfo | None:
"""查找符号,不存在返回 None替代 `SymbolTable.get(name)`"""
return self._symbols.get(name)
def has(self, name: str) -> bool:
"""检查符号是否存在(替代 `name in SymbolTable`"""
return name in self._symbols
def lookup_struct(self, name: str) -> CTypeInfo | None:
"""查找结构体符号,非结构体返回 None"""
entry = self._symbols.get(name)
if entry and (entry.IsStruct or entry.IsCpythonObject):
return entry
return None
def lookup_enum(self, name: str) -> CTypeInfo | None:
"""查找枚举符号,非枚举返回 None"""
entry = self._symbols.get(name)
if entry and entry.IsEnum:
return entry
return None
def lookup_typedef(self, name: str) -> CTypeInfo | None:
"""查找 typedef 符号,非 typedef 返回 None"""
entry = self._symbols.get(name)
if entry and entry.IsTypedef:
return entry
return None
def lookup_function(self, name: str) -> CTypeInfo | None:
"""查找函数符号,非函数返回 None"""
entry = self._symbols.get(name)
if entry and (entry.IsFunction or entry.IsFuncPtr):
return entry
return None
def lookup_define(self, name: str) -> CTypeInfo | None:
"""查找常量定义符号,非 define 返回 None"""
entry = self._symbols.get(name)
if entry and entry.IsDefine:
return entry
return None
def is_struct(self, name: str) -> bool:
"""检查名称是否为结构体"""
entry = self._symbols.get(name)
return entry is not None and (entry.IsStruct or entry.IsCpythonObject)
def is_enum(self, name: str) -> bool:
"""检查名称是否为枚举"""
entry = self._symbols.get(name)
return entry is not None and entry.IsEnum
def is_typedef(self, name: str) -> bool:
"""检查名称是否为 typedef"""
entry = self._symbols.get(name)
return entry is not None and entry.IsTypedef
def is_function(self, name: str) -> bool:
"""检查名称是否为函数"""
entry = self._symbols.get(name)
return entry is not None and (entry.IsFunction or entry.IsFuncPtr)
def is_variable(self, name: str) -> bool:
"""检查名称是否为变量"""
entry = self._symbols.get(name)
return entry is not None and entry.IsVariable
def is_define(self, name: str) -> bool:
"""检查名称是否为常量定义"""
entry = self._symbols.get(name)
return entry is not None and entry.IsDefine
def insert(self, name: str, info: CTypeInfo):
"""插入符号(替代 `SymbolTable[name] = info`"""
self._symbols[name] = info
def resolve_alias(self, module_path: str) -> str:
"""解析 import 别名,无别名返回原路径"""
return self.import_aliases.get(module_path, module_path)
def find_by_suffix(self, suffix: str) -> list[tuple[str, CTypeInfo]]:
"""按名称后缀模糊查找符号(替代遍历 + endswith 匹配)"""
results = []
for name, info in self._symbols.items():
if name.endswith(suffix):
results.append((name, info))
return results
def ToDict(self) -> Dict[str, Any]: def ToDict(self) -> Dict[str, Any]:
"""序列化为字典格式""" """序列化为字典格式"""
@@ -217,183 +313,24 @@ class SymbolTable:
return [] return []
# ================================================================== # ==================================================================
# 类型解析辅助方法(供 TypeResolver 通过 SymbolTable 引用调用 # 类型解析辅助方法(委托到 LLVMTypeMapper
# ================================================================== # ==================================================================
def _GetLLVMTypeStr(self, node): def _GetLLVMTypeStr(self, node):
if node is None: return self._type_mapper.get_llvm_type_str(node)
self.diagnostics.warn('', 0, "类型注解为 None回退到 i32")
return 'i32'
if isinstance(node, ast.Name):
if node.id == 'str':
return 'i8*'
elif node.id == 'int':
return 'i32'
elif node.id == 'bool':
return 'i8'
elif node.id == 'float':
return 'double'
elif node.id == 'None':
return 'void'
elif node.id in ('UINT8PTR', 'INT8PTR', 'BYTEPTR'):
return 'i8*'
elif node.id in ('UINT16PTR', 'INT16PTR'):
return 'i16*'
elif node.id in ('UINT32PTR', 'INT32PTR'):
return 'i32*'
elif node.id in ('UINT64PTR', 'INT64PTR'):
return 'i64*'
else:
if node.id in self:
entry = self[node.id]
if entry and entry.IsTypedef and entry.OriginalType:
if isinstance(entry.OriginalType, CTypeInfo) and entry.OriginalType.IsFuncPtr:
return 'i8*'
elif isinstance(entry.OriginalType, CTypeInfo) and entry.OriginalType.BaseType:
return entry.OriginalType.ToString()
elif isinstance(entry.OriginalType, str):
return entry.OriginalType
self.diagnostics.warn('', 0, f"无法解析 Name 类型 '{node.id}',回退到 i32")
return 'i32'
elif isinstance(node, ast.Attribute):
attr_name = node.attr if hasattr(node, 'attr') else ''
from lib.includes.t import CTypeRegistry
llvm_str = CTypeRegistry.NameToLLVM(attr_name)
if llvm_str is not None:
return llvm_str
if attr_name in ('CState', 'CDefine', 'CTypedef', 'CExtern', 'CStatic', 'CConst', 'State'):
return ''
if attr_name in ('CCharPtr', 'CIntPtr', 'CVoidPtr', 'CArrayPtr'):
return 'i8*'
if attr_name == 'CVoidPtr':
return 'i8*'
if attr_name and attr_name[0].isupper() and attr_name not in CTypeRegistry._name_to_class:
return f'%struct.{attr_name}*'
if attr_name and attr_name not in CTypeRegistry._name_to_class:
return f'%struct.{attr_name}*'
self.diagnostics.warn('', 0, f"无法解析 Attribute 类型 '{attr_name}',回退到 i32")
return 'i32'
elif isinstance(node, ast.Subscript):
if isinstance(node.value, ast.Name) and node.value.id == 'tuple':
slice_node = node.slice
elem_types = []
if isinstance(slice_node, ast.Tuple):
for elt in slice_node.elts:
elem_types.append(self._GetLLVMTypeStr(elt))
else:
elem_types.append(self._GetLLVMTypeStr(slice_node))
if elem_types:
return '{ ' + ', '.join(elem_types) + ' }'
if isinstance(node.value, ast.Name) and node.value.id == 'list':
slice_node = node.slice
if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) >= 1:
elem_type = self._GetLLVMTypeStr(slice_node.elts[0])
else:
elem_type = self._GetLLVMTypeStr(slice_node)
return elem_type + '*'
self.diagnostics.warn('', 0, f"无法解析 Subscript 类型,回退到 i32")
return 'i32'
elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
left = self._GetLLVMTypeStr(node.left)
right = self._GetLLVMTypeStr(node.right)
if right and right.endswith('*'):
return right
if left and left.endswith('*'):
return left
if left and left not in ('i32', 'void', 'i64'):
return left
if right and right not in ('i32', 'void', 'i64'):
return right
return left if left else right
elif isinstance(node, ast.Constant):
if isinstance(node.value, bool):
return 'i8'
return 'i32'
elif isinstance(node, ast.Call):
if isinstance(node.func, ast.Attribute):
if hasattr(node.func.value, 'id') and node.func.value.id == 't':
return self._GetLLVMTypeStr(ast.Attribute(value=ast.Name(id='t'), attr=node.func.attr))
self.diagnostics.warn('', 0, "无法解析 Call 类型,回退到 i32")
return 'i32'
self.diagnostics.warn('', 0, f"无法解析类型节点 {type(node).__name__},回退到 i32")
return 'i32'
def _GetFuncRetTypeStr(self, returns_node): def _GetFuncRetTypeStr(self, returns_node):
if returns_node is None: return self._type_mapper.get_func_ret_type_str(returns_node)
return 'i32'
actual = returns_node
if isinstance(returns_node, ast.BinOp) and isinstance(returns_node.op, ast.BitOr):
left_str = self._GetLLVMTypeStr(returns_node.left)
right_str = self._GetLLVMTypeStr(returns_node.right)
if right_str and right_str.endswith('*'):
return right_str
if left_str and left_str.endswith('*'):
return left_str
if left_str and left_str not in ('i32', 'void', 'i64'):
return left_str
if right_str and right_str not in ('i32', 'void', 'i64'):
return right_str
return left_str
result = self._GetLLVMTypeStr(actual)
return result if result else 'i32'
@staticmethod @staticmethod
def _CheckAnnotationHasCInline(annotation_node) -> bool: def _CheckAnnotationHasCInline(annotation_node) -> bool:
return _CheckAnnotationHasCInline(annotation_node) return _CheckAnnotationHasCInline(annotation_node)
def _GetFuncParamTypeStr(self, annotation_node): def _GetFuncParamTypeStr(self, annotation_node):
if annotation_node is None: return self._type_mapper.get_func_param_type_str(annotation_node)
return 'i8*'
actual = annotation_node
if isinstance(annotation_node, ast.BinOp) and isinstance(annotation_node.op, ast.BitOr):
left_str = self._GetLLVMTypeStr(annotation_node.left)
right_str = self._GetLLVMTypeStr(annotation_node.right)
if right_str and right_str.endswith('*'):
return right_str
if left_str and left_str.endswith('*'):
return left_str
if right_str and right_str not in ('i32', 'void', 'i64'):
return right_str
if left_str and left_str not in ('i32', 'void', 'i64'):
return left_str
if left_str and left_str.endswith('*'):
return left_str
return right_str if right_str else left_str
result = self._GetLLVMTypeStr(actual)
return result if result else 'i8*'
def _ResolveTypedefValueType(self, node): def _ResolveTypedefValueType(self, node):
if node is None: return self._type_mapper.resolve_typedef_value_type(node)
return ''
if isinstance(node, ast.Name):
if node.id in self:
Entry = self[node.id]
if Entry.IsTypedef and Entry.OriginalType:
return Entry.OriginalType
return ''
if isinstance(node, ast.Attribute):
if isinstance(node.value, ast.Name) and node.value.id == 't':
CName = CTypeHelper.GetCName(node.attr)
if CName and CName == '*':
return 'ptr'
if CName:
return CName
return ''
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
left_str = self._ResolveTypedefValueType(node.left)
right_str = self._ResolveTypedefValueType(node.right)
if right_str == 'ptr' or (right_str and right_str.endswith('*')):
base = left_str if left_str and left_str != 'ptr' else ''
return base + ' *' if base else 'void *'
if left_str == 'ptr' or (left_str and left_str.endswith('*')):
base = right_str if right_str and right_str != 'ptr' else ''
return base + ' *' if base else 'void *'
if right_str and right_str not in ('ptr', 'void', 'i32', 'i64'):
return right_str
if left_str and left_str not in ('ptr', 'void', 'i32', 'i64'):
return left_str
return left_str if left_str else right_str
return ''
# ================================================================== # ==================================================================
# 符号插入方法(供 SymbolInserter / PackageReexporter 调用) # 符号插入方法(供 SymbolInserter / PackageReexporter 调用)

View File

@@ -17,6 +17,8 @@ class TypeResolver:
def __init__(self, symbol_table: SymbolTable): def __init__(self, symbol_table: SymbolTable):
self._symtab = symbol_table self._symtab = symbol_table
from lib.core.LLVMTypeMapper import LLVMTypeMapper
self._type_mapper = LLVMTypeMapper(symbol_table)
def resolve(self, module_symbols: ModuleSymbols) -> ModuleSymbols: def resolve(self, module_symbols: ModuleSymbols) -> ModuleSymbols:
"""解析所有类型信息,就地更新 ModuleSymbols""" """解析所有类型信息,就地更新 ModuleSymbols"""
@@ -119,8 +121,8 @@ class TypeResolver:
return return
if isinstance(td.value, ast.BinOp) and isinstance(td.value.op, ast.BitOr): if isinstance(td.value, ast.BinOp) and isinstance(td.value.op, ast.BitOr):
left_type = self._symtab._ResolveTypedefValueType(td.value.left) left_type = self._type_mapper.resolve_typedef_value_type(td.value.left)
right_type = self._symtab._ResolveTypedefValueType(td.value.right) right_type = self._type_mapper.resolve_typedef_value_type(td.value.right)
is_ptr_type = right_type == 'ptr' or left_type == 'ptr' is_ptr_type = right_type == 'ptr' or left_type == 'ptr'
if is_ptr_type: if is_ptr_type:
base_name = left_type if left_type != 'ptr' else (right_type if right_type != 'ptr' else '') base_name = left_type if left_type != 'ptr' else (right_type if right_type != 'ptr' else '')
@@ -156,11 +158,11 @@ class TypeResolver:
def _resolve_function(self, func: FuncSymbolData): def _resolve_function(self, func: FuncSymbolData):
"""解析函数的返回类型和参数类型""" """解析函数的返回类型和参数类型"""
func.ret_type = self._symtab._GetFuncRetTypeStr(func.returns_node) func.ret_type = self._type_mapper.get_func_ret_type_str(func.returns_node)
func.param_types = [] func.param_types = []
for _arg_name, annotation in func.params: for _arg_name, annotation in func.params:
if annotation: if annotation:
func.param_types.append(self._symtab._GetFuncParamTypeStr(annotation)) func.param_types.append(self._type_mapper.get_func_param_type_str(annotation))
else: else:
func.param_types.append('i8*') func.param_types.append('i8*')

View File

@@ -55,7 +55,7 @@ class AnnotationLoaderMixin:
EnumNode.set('source', 'annotation_module') EnumNode.set('source', 'annotation_module')
EnumNode.library_name = lib_name EnumNode.library_name = lib_name
EnumNode.file = source_file EnumNode.file = source_file
self.SymbolTable[AttrName] = EnumNode self.SymbolTable.insert(AttrName, EnumNode)
if lib_name: if lib_name:
FullName = f'{lib_name}.{AttrName}' FullName = f'{lib_name}.{AttrName}'
full_EnumNode = CTypeInfo() full_EnumNode = CTypeInfo()
@@ -65,7 +65,7 @@ class AnnotationLoaderMixin:
full_EnumNode.set('source', 'annotation_module') full_EnumNode.set('source', 'annotation_module')
full_EnumNode.library_name = lib_name full_EnumNode.library_name = lib_name
full_EnumNode.file = source_file full_EnumNode.file = source_file
self.SymbolTable[FullName] = full_EnumNode self.SymbolTable.insert(FullName, full_EnumNode)
# 枚举成员也需要注册 # 枚举成员也需要注册
for MemberName in dir(attr): for MemberName in dir(attr):
if not MemberName.startswith('_'): if not MemberName.startswith('_'):
@@ -78,12 +78,12 @@ class AnnotationLoaderMixin:
MemberNode.EnumName = AttrName MemberNode.EnumName = AttrName
MemberNode.library_name = lib_name MemberNode.library_name = lib_name
MemberNode.IsEnumMember = True MemberNode.IsEnumMember = True
self.SymbolTable[MemberName] = MemberNode self.SymbolTable.insert(MemberName, MemberNode)
self.SymbolTable[f"{AttrName}.{MemberName}"] = MemberNode self.SymbolTable.insert(f"{AttrName}.{MemberName}", MemberNode)
self.SymbolTable[f"{AttrName}_{MemberName}"] = MemberNode self.SymbolTable.insert(f"{AttrName}_{MemberName}", MemberNode)
if lib_name: if lib_name:
self.SymbolTable[f"{lib_name}.{AttrName}.{MemberName}"] = MemberNode self.SymbolTable.insert(f"{lib_name}.{AttrName}.{MemberName}", MemberNode)
self.SymbolTable[f"{lib_name}_{AttrName}_{MemberName}"] = MemberNode self.SymbolTable.insert(f"{lib_name}_{AttrName}_{MemberName}", MemberNode)
count += 1 count += 1
# 检查是否是 CType 子类typedef 别名) # 检查是否是 CType 子类typedef 别名)
elif isinstance(attr, type) and issubclass(attr, CType) and attr is not CType: elif isinstance(attr, type) and issubclass(attr, CType) and attr is not CType:
@@ -101,7 +101,7 @@ class AnnotationLoaderMixin:
TypedefNode.set('source', 'annotation_module') TypedefNode.set('source', 'annotation_module')
TypedefNode.library_name = lib_name TypedefNode.library_name = lib_name
TypedefNode.file = source_file TypedefNode.file = source_file
self.SymbolTable[AttrName] = TypedefNode self.SymbolTable.insert(AttrName, TypedefNode)
if lib_name and FullName != AttrName: if lib_name and FullName != AttrName:
FullTypedef_node = CTypeInfo() FullTypedef_node = CTypeInfo()
FullTypedef_node.Name = FullName FullTypedef_node.Name = FullName
@@ -110,7 +110,7 @@ class AnnotationLoaderMixin:
FullTypedef_node.set('source', 'annotation_module') FullTypedef_node.set('source', 'annotation_module')
FullTypedef_node.library_name = lib_name FullTypedef_node.library_name = lib_name
FullTypedef_node.file = source_file FullTypedef_node.file = source_file
self.SymbolTable[FullName] = FullTypedef_node self.SymbolTable.insert(FullName, FullTypedef_node)
count += 1 count += 1
# 检查是否是下划线前缀的 CType 子类(如 _CTypedef -> CTypedef # 检查是否是下划线前缀的 CType 子类(如 _CTypedef -> CTypedef
elif AttrName.startswith('_') and len(AttrName) > 1: elif AttrName.startswith('_') and len(AttrName) > 1:
@@ -119,7 +119,7 @@ class AnnotationLoaderMixin:
if PublicAttr is not None and not isinstance(attr, type): if PublicAttr is not None and not isinstance(attr, type):
continue continue
if isinstance(attr, type) and issubclass(attr, CType) and attr is not CType: if isinstance(attr, type) and issubclass(attr, CType) and attr is not CType:
if PublicName not in self.SymbolTable: if not self.SymbolTable.has(PublicName):
if lib_name: if lib_name:
FullName = f'{lib_name}.{PublicName}' FullName = f'{lib_name}.{PublicName}'
else: else:
@@ -131,7 +131,7 @@ class AnnotationLoaderMixin:
TypedefNode.set('source', 'annotation_module') TypedefNode.set('source', 'annotation_module')
TypedefNode.library_name = lib_name TypedefNode.library_name = lib_name
TypedefNode.file = source_file TypedefNode.file = source_file
self.SymbolTable[PublicName] = TypedefNode self.SymbolTable.insert(PublicName, TypedefNode)
if lib_name and FullName != PublicName: if lib_name and FullName != PublicName:
FullTypedef_node = CTypeInfo() FullTypedef_node = CTypeInfo()
FullTypedef_node.Name = FullName FullTypedef_node.Name = FullName
@@ -140,7 +140,7 @@ class AnnotationLoaderMixin:
FullTypedef_node.set('source', 'annotation_module') FullTypedef_node.set('source', 'annotation_module')
FullTypedef_node.library_name = lib_name FullTypedef_node.library_name = lib_name
FullTypedef_node.file = source_file FullTypedef_node.file = source_file
self.SymbolTable[FullName] = FullTypedef_node self.SymbolTable.insert(FullName, FullTypedef_node)
count += 1 count += 1
return count return count
@@ -208,14 +208,14 @@ class AnnotationLoaderMixin:
if isinstance(base, ast.Name) and base.id == 'CType': if isinstance(base, ast.Name) and base.id == 'CType':
# 这个类继承自 CType是 typedef 别名 # 这个类继承自 CType是 typedef 别名
# 更新符号表中的类型为 typedef # 更新符号表中的类型为 typedef
if ClassName in self.SymbolTable: if self.SymbolTable.has(ClassName):
TypedefNode = CTypeInfo() TypedefNode = CTypeInfo()
TypedefNode.Name = ClassName TypedefNode.Name = ClassName
TypedefNode.IsTypedef = True TypedefNode.IsTypedef = True
TypedefNode.OriginalType = self.SymbolTable[ClassName].get('OriginalType', f'struct {ClassName}') TypedefNode.OriginalType = self.SymbolTable[ClassName].get('OriginalType', f'struct {ClassName}')
TypedefNode.set('source', 'annotation_module') TypedefNode.set('source', 'annotation_module')
TypedefNode.set('is_ctype_subclass', True) TypedefNode.set('is_ctype_subclass', True)
self.SymbolTable[ClassName] = TypedefNode self.SymbolTable.insert(ClassName, TypedefNode)
except Exception as _e: except Exception as _e:
from lib.core.VLogger import get_logger as _vlog from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _ConfigMode from lib.constants.config import mode as _ConfigMode
@@ -230,7 +230,7 @@ class AnnotationLoaderMixin:
TypeInfo = self.SymbolTable[TypeName].copy() TypeInfo = self.SymbolTable[TypeName].copy()
TypeInfo['source'] = 'annotation_module' TypeInfo['source'] = 'annotation_module'
TypeInfo['original_name'] = TypeName TypeInfo['original_name'] = TypeName
self.SymbolTable[FullName] = TypeInfo self.SymbolTable.insert(FullName, TypeInfo)
count += 1 count += 1
# 再次遍历 AST查找注解文件中的 typedef 语句AnnAssign with t.CTypedef # 再次遍历 AST查找注解文件中的 typedef 语句AnnAssign with t.CTypedef
@@ -283,9 +283,9 @@ class AnnotationLoaderMixin:
MemberNode.EnumName = TypePrefix MemberNode.EnumName = TypePrefix
MemberNode.library_name = TypePrefix MemberNode.library_name = TypePrefix
MemberNode.IsEnumMember = True MemberNode.IsEnumMember = True
self.SymbolTable[TargetName] = MemberNode self.SymbolTable.insert(TargetName, MemberNode)
self.SymbolTable[f"{TypePrefix}.{TargetName}"] = MemberNode self.SymbolTable.insert(f"{TypePrefix}.{TargetName}", MemberNode)
self.SymbolTable[f"{TypePrefix}_{TargetName}"] = MemberNode self.SymbolTable.insert(f"{TypePrefix}_{TargetName}", MemberNode)
try: try:
with open(ModuleName, 'r', encoding='utf-8') as f: with open(ModuleName, 'r', encoding='utf-8') as f:
@@ -315,13 +315,13 @@ class AnnotationLoaderMixin:
for TargetName, original_name in typedef_annots: for TargetName, original_name in typedef_annots:
# 检查原始类型是否在符号表中(带前缀或不带前缀) # 检查原始类型是否在符号表中(带前缀或不带前缀)
orig_with_prefix = f'{TypePrefix}.{original_name}' orig_with_prefix = f'{TypePrefix}.{original_name}'
if orig_with_prefix in self.SymbolTable: if self.SymbolTable.has(orig_with_prefix):
# 添加带前缀的 typedef 别名 # 添加带前缀的 typedef 别名
FullTypedef_name = f'{TypePrefix}.{TargetName}' FullTypedef_name = f'{TypePrefix}.{TargetName}'
TypedefNode = CTypeInfo() TypedefNode = CTypeInfo()
TypedefNode.Name = FullTypedef_name TypedefNode.Name = FullTypedef_name
TypedefNode.IsTypedef = True TypedefNode.IsTypedef = True
orig_entry = self.SymbolTable.get(orig_with_prefix, {}) orig_entry = self.SymbolTable.lookup(orig_with_prefix)
orig_type_str = f'struct {original_name}' orig_type_str = f'struct {original_name}'
if isinstance(orig_entry, dict): if isinstance(orig_entry, dict):
if orig_entry.get('type') == 'typedef': if orig_entry.get('type') == 'typedef':
@@ -335,7 +335,7 @@ class AnnotationLoaderMixin:
TypedefNode.OriginalType = orig_type_str TypedefNode.OriginalType = orig_type_str
TypedefNode.set('source', 'annotation_module') TypedefNode.set('source', 'annotation_module')
TypedefNode.set('original_name', TargetName) TypedefNode.set('original_name', TargetName)
self.SymbolTable[FullTypedef_name] = TypedefNode self.SymbolTable.insert(FullTypedef_name, TypedefNode)
count += 1 count += 1
self.AnnotationModules.add(lib_name) self.AnnotationModules.add(lib_name)

View File

@@ -57,7 +57,7 @@ class LlvmGeneratorMixin:
sym_info = _CTypeInfo() sym_info = _CTypeInfo()
sym_info.IsDefine = True sym_info.IsDefine = True
sym_info.DefineValue = val sym_info.DefineValue = val
self.SymbolTable[Node.target.id] = sym_info self.SymbolTable.insert(Node.target.id, sym_info)
elif isinstance(Node, ast.Assign): elif isinstance(Node, ast.Assign):
for target in Node.targets: for target in Node.targets:
if isinstance(target, ast.Name): if isinstance(target, ast.Name):
@@ -86,7 +86,7 @@ class LlvmGeneratorMixin:
sym_info = _CTypeInfo() sym_info = _CTypeInfo()
sym_info.IsDefine = True sym_info.IsDefine = True
sym_info.DefineValue = val sym_info.DefineValue = val
self.SymbolTable[target.id] = sym_info self.SymbolTable.insert(target.id, sym_info)
# 预扫描所有顶层函数定义,填充 FunctionDefCache不创建 LLVM 声明) # 预扫描所有顶层函数定义,填充 FunctionDefCache不创建 LLVM 声明)
# 这样类方法编译时遇到未声明的函数可以按需前向声明 # 这样类方法编译时遇到未声明的函数可以按需前向声明
@@ -287,8 +287,6 @@ class LlvmGeneratorMixin:
self.VarScopes = [{}] # 全局作用域 self.VarScopes = [{}] # 全局作用域
# 预扫描 import 语句,注册别名,确保类型解析时能正确解析模块别名 # 预扫描 import 语句,注册别名,确保类型解析时能正确解析模块别名
if not getattr(self, '_ImportAliases', None):
self._ImportAliases = {}
if not getattr(self, '_ImportedModules', None): if not getattr(self, '_ImportedModules', None):
self._ImportedModules = set() self._ImportedModules = set()
for Node in ast.iter_child_nodes(Tree): for Node in ast.iter_child_nodes(Tree):
@@ -299,14 +297,14 @@ class LlvmGeneratorMixin:
continue continue
self._ImportedModules.add(name) self._ImportedModules.add(name)
if alias.asname: if alias.asname:
self._ImportAliases[alias.asname] = name self.SymbolTable.import_aliases[alias.asname] = name
elif isinstance(Node, ast.ImportFrom): elif isinstance(Node, ast.ImportFrom):
module_name = Node.module module_name = Node.module
if module_name and module_name not in ('c', 't'): if module_name and module_name not in ('c', 't'):
self._ImportedModules.add(module_name) self._ImportedModules.add(module_name)
for alias in Node.names: for alias in Node.names:
if alias.asname: if alias.asname:
self._ImportAliases[alias.asname] = f"{module_name}.{alias.name}" self.SymbolTable.import_aliases[alias.asname] = f"{module_name}.{alias.name}"
for Node in ast.iter_child_nodes(Tree): for Node in ast.iter_child_nodes(Tree):
if isinstance(Node, ast.ClassDef): if isinstance(Node, ast.ClassDef):
@@ -373,7 +371,7 @@ class LlvmGeneratorMixin:
TypedefNode.OriginalType = f'struct {ClassName}' TypedefNode.OriginalType = f'struct {ClassName}'
TypedefNode.set('IsComplete', True) TypedefNode.set('IsComplete', True)
TypedefNode.file = '<stdin>' TypedefNode.file = '<stdin>'
self.SymbolTable[TypedefKey] = TypedefNode self.SymbolTable.insert(TypedefKey, TypedefNode)
for item in Node.body: for item in Node.body:
if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name):
@@ -414,18 +412,18 @@ class LlvmGeneratorMixin:
StructNode.IsStruct = True StructNode.IsStruct = True
StructNode.Members = members or {} StructNode.Members = members or {}
StructNode.file = '<stdin>' StructNode.file = '<stdin>'
if ClassName in self.SymbolTable: if self.SymbolTable.has(ClassName):
existing = self.SymbolTable[ClassName] existing = self.SymbolTable[ClassName]
if hasattr(existing, 'IsCpythonObject') and existing.IsCpythonObject: if hasattr(existing, 'IsCpythonObject') and existing.IsCpythonObject:
StructNode.IsCpythonObject = True StructNode.IsCpythonObject = True
self.SymbolTable[ClassName] = StructNode self.SymbolTable.insert(ClassName, StructNode)
elif isinstance(Node, ast.FunctionDef): elif isinstance(Node, ast.FunctionDef):
FuncName = Node.name FuncName = Node.name
FuncNode = CTypeInfo() FuncNode = CTypeInfo()
FuncNode.Name = FuncName FuncNode.Name = FuncName
FuncNode.IsFunction = True FuncNode.IsFunction = True
FuncNode.file = '<stdin>' FuncNode.file = '<stdin>'
self.SymbolTable[FuncName] = FuncNode self.SymbolTable.insert(FuncName, FuncNode)
elif isinstance(Node, ast.AnnAssign): elif isinstance(Node, ast.AnnAssign):
if isinstance(Node.target, ast.Name): if isinstance(Node.target, ast.Name):
VarName = Node.target.id VarName = Node.target.id
@@ -447,7 +445,7 @@ class LlvmGeneratorMixin:
if isinstance(Node.value, ast.Name): if isinstance(Node.value, ast.Name):
OriginalType = Node.value.id OriginalType = Node.value.id
if OriginalType in self.GeneratedTypes: if OriginalType in self.GeneratedTypes:
if OriginalType in self.SymbolTable: if self.SymbolTable.has(OriginalType):
OriginalInfo = self.SymbolTable[OriginalType] OriginalInfo = self.SymbolTable[OriginalType]
if isinstance(OriginalInfo, dict): if isinstance(OriginalInfo, dict):
actual_type = OriginalInfo.get('type', 'struct') actual_type = OriginalInfo.get('type', 'struct')
@@ -468,7 +466,7 @@ class LlvmGeneratorMixin:
TypedefNode.IsTypedef = True TypedefNode.IsTypedef = True
TypedefNode.OriginalType = f'enum {OriginalType}' TypedefNode.OriginalType = f'enum {OriginalType}'
TypedefNode.file = '<stdin>' TypedefNode.file = '<stdin>'
self.SymbolTable[VarName] = TypedefNode self.SymbolTable.insert(VarName, TypedefNode)
elif actual_type == 'typedef': elif actual_type == 'typedef':
TypedefNode = CTypeInfo() TypedefNode = CTypeInfo()
TypedefNode.Name = VarName TypedefNode.Name = VarName
@@ -481,7 +479,7 @@ class LlvmGeneratorMixin:
TypedefNode.OriginalType = f'struct {OriginalType}' TypedefNode.OriginalType = f'struct {OriginalType}'
TypedefNode.set('PendingTypedef', True) TypedefNode.set('PendingTypedef', True)
TypedefNode.file = '<stdin>' TypedefNode.file = '<stdin>'
self.SymbolTable[VarName] = TypedefNode self.SymbolTable.insert(VarName, TypedefNode)
else: else:
TypedefNode = CTypeInfo() TypedefNode = CTypeInfo()
TypedefNode.Name = VarName TypedefNode.Name = VarName
@@ -489,11 +487,11 @@ class LlvmGeneratorMixin:
TypedefNode.OriginalType = f'struct {OriginalType}' TypedefNode.OriginalType = f'struct {OriginalType}'
TypedefNode.set('PendingTypedef', True) TypedefNode.set('PendingTypedef', True)
TypedefNode.file = '<stdin>' TypedefNode.file = '<stdin>'
self.SymbolTable[VarName] = TypedefNode self.SymbolTable.insert(VarName, TypedefNode)
self.GeneratedTypes.add(VarName) self.GeneratedTypes.add(VarName)
continue continue
else: else:
if OriginalType in self.SymbolTable: if self.SymbolTable.has(OriginalType):
OriginalInfo = self.SymbolTable[OriginalType] OriginalInfo = self.SymbolTable[OriginalType]
if isinstance(OriginalInfo, dict): if isinstance(OriginalInfo, dict):
actual_type = OriginalInfo.get('type', 'struct') actual_type = OriginalInfo.get('type', 'struct')
@@ -520,7 +518,7 @@ class LlvmGeneratorMixin:
TypedefNode.OriginalType = f'struct {OriginalType}' TypedefNode.OriginalType = f'struct {OriginalType}'
TypedefNode.set('PendingTypedef', True) TypedefNode.set('PendingTypedef', True)
TypedefNode.file = '<stdin>' TypedefNode.file = '<stdin>'
self.SymbolTable[VarName] = TypedefNode self.SymbolTable.insert(VarName, TypedefNode)
self.GeneratedTypes.add(VarName) self.GeneratedTypes.add(VarName)
if isinstance(OriginalInfo, dict): if isinstance(OriginalInfo, dict):
OriginalInfo['skip_generation'] = True OriginalInfo['skip_generation'] = True
@@ -532,7 +530,7 @@ class LlvmGeneratorMixin:
TypedefNode.OriginalType = f'struct {OriginalType}' TypedefNode.OriginalType = f'struct {OriginalType}'
TypedefNode.set('PendingTypedef', True) TypedefNode.set('PendingTypedef', True)
TypedefNode.file = '<stdin>' TypedefNode.file = '<stdin>'
self.SymbolTable[VarName] = TypedefNode self.SymbolTable.insert(VarName, TypedefNode)
self.GeneratedTypes.add(VarName) self.GeneratedTypes.add(VarName)
if isinstance(OriginalInfo, dict): if isinstance(OriginalInfo, dict):
OriginalInfo['skip_generation'] = True OriginalInfo['skip_generation'] = True
@@ -544,7 +542,7 @@ class LlvmGeneratorMixin:
TypedefNode.OriginalType = f'enum {OriginalType}' TypedefNode.OriginalType = f'enum {OriginalType}'
TypedefNode.set('PendingTypedef', True) TypedefNode.set('PendingTypedef', True)
TypedefNode.file = '<stdin>' TypedefNode.file = '<stdin>'
self.SymbolTable[VarName] = TypedefNode self.SymbolTable.insert(VarName, TypedefNode)
self.GeneratedTypes.add(VarName) self.GeneratedTypes.add(VarName)
if isinstance(OriginalInfo, dict): if isinstance(OriginalInfo, dict):
OriginalInfo['skip_generation'] = True OriginalInfo['skip_generation'] = True
@@ -558,7 +556,7 @@ class LlvmGeneratorMixin:
TypedefNode.IsTypedef = True TypedefNode.IsTypedef = True
TypedefNode.OriginalType = CName TypedefNode.OriginalType = CName
TypedefNode.file = '<stdin>' TypedefNode.file = '<stdin>'
self.SymbolTable[VarName] = TypedefNode self.SymbolTable.insert(VarName, TypedefNode)
self.GeneratedTypes.add(VarName) self.GeneratedTypes.add(VarName)
continue continue
@@ -574,7 +572,7 @@ class LlvmGeneratorMixin:
var_node.IsVariable = True var_node.IsVariable = True
var_node.PtrCount = 1 if IsPtr else 0 var_node.PtrCount = 1 if IsPtr else 0
var_node.file = '<stdin>' var_node.file = '<stdin>'
self.SymbolTable[VarName] = var_node self.SymbolTable.insert(VarName, var_node)
self.LlvmGen = LlvmCodeGenerator( self.LlvmGen = LlvmCodeGenerator(
triple=getattr(self, 'triple', None), triple=getattr(self, 'triple', None),

View File

@@ -328,7 +328,7 @@ class PythonParserMixin:
EnumNode.Name = ClassName EnumNode.Name = ClassName
EnumNode.IsEnum = True EnumNode.IsEnum = True
EnumNode.set('file', '<stdin>') EnumNode.set('file', '<stdin>')
self.SymbolTable[ClassName] = EnumNode self.SymbolTable.insert(ClassName, EnumNode)
# 注册 enum 成员 # 注册 enum 成员
for item in node.body: for item in node.body:
@@ -341,9 +341,9 @@ class PythonParserMixin:
MemberNode.EnumName = ClassName MemberNode.EnumName = ClassName
MemberNode.library_name = None MemberNode.library_name = None
MemberNode.IsEnumMember = True MemberNode.IsEnumMember = True
self.SymbolTable[MemberName] = MemberNode self.SymbolTable.insert(MemberName, MemberNode)
self.SymbolTable[f"{ClassName}.{MemberName}"] = MemberNode self.SymbolTable.insert(f"{ClassName}.{MemberName}", MemberNode)
self.SymbolTable[f"{ClassName}_{MemberName}"] = MemberNode self.SymbolTable.insert(f"{ClassName}_{MemberName}", MemberNode)
continue continue
@@ -397,14 +397,14 @@ class PythonParserMixin:
StructNode.set('file', '<stdin>') StructNode.set('file', '<stdin>')
StructNode.set('IsAnonymous', IsAnonymous) StructNode.set('IsAnonymous', IsAnonymous)
StructNode.set('IsCpythonObject', IsCpythonObject) StructNode.set('IsCpythonObject', IsCpythonObject)
self.SymbolTable[ClassName] = StructNode self.SymbolTable.insert(ClassName, StructNode)
elif isinstance(node, ast.FunctionDef): elif isinstance(node, ast.FunctionDef):
FuncName = node.name FuncName = node.name
FuncNode = CTypeInfo() FuncNode = CTypeInfo()
FuncNode.Name = FuncName FuncNode.Name = FuncName
FuncNode.IsFunction = True FuncNode.IsFunction = True
FuncNode.set('file', '<stdin>') FuncNode.set('file', '<stdin>')
self.SymbolTable[FuncName] = FuncNode self.SymbolTable.insert(FuncName, FuncNode)
elif isinstance(node, ast.AnnAssign): elif isinstance(node, ast.AnnAssign):
if isinstance(node.target, ast.Name): if isinstance(node.target, ast.Name):
VarName = node.target.id VarName = node.target.id
@@ -443,7 +443,7 @@ class PythonParserMixin:
var_node.IsVariable = True var_node.IsVariable = True
var_node.set('IsPtr', IsPtr) var_node.set('IsPtr', IsPtr)
var_node.set('file', '<stdin>') var_node.set('file', '<stdin>')
self.SymbolTable[VarName] = var_node self.SymbolTable.insert(VarName, var_node)
except Exception as e: except Exception as e:
print(f'Warning: Failed to parse Python file {FilePath}: {e}') print(f'Warning: Failed to parse Python file {FilePath}: {e}')

View File

@@ -0,0 +1,704 @@
from __future__ import annotations
import ast
from lib.core.Handles.HandlesBase import CTypeInfo, BuiltinTypeMap, CTypeHelper
class TypeAnnotationResolver:
"""从 AST 节点解析类型注解,独立于 CTypeInfo 数据模型。"""
@staticmethod
def from_type_name(TypeName: str) -> CTypeInfo:
"""从简单类型名构造 CTypeInfo不经过 FromStr 字符串解析)"""
# Handle pointer types like 'CUInt32T *', 'void *', etc.
ptr_count = 0
base_name = TypeName
while base_name.endswith(' *') or base_name.endswith('*'):
ptr_count += 1
base_name = base_name.rstrip(' *').rstrip()
entry = BuiltinTypeMap.Get(base_name)
if entry:
TypeClass, base_ptr = entry
info = CTypeInfo()
info.BaseType = TypeClass
info.PtrCount = base_ptr + ptr_count
return info
# Handle LLVM primitive type names (e.g., 'i64', 'double' from generic type inference)
llvm_map = CTypeInfo._get_llvm_primitive_map()
llvm_entry = llvm_map.get(base_name)
if llvm_entry:
TypeClass, base_ptr = llvm_entry
info = CTypeInfo()
info.BaseType = TypeClass
info.PtrCount = base_ptr + ptr_count
return info
# Fallback with pointer count
info = CTypeInfo.CreateFromTypeName(TypeName)
if ptr_count > 0:
info.PtrCount = ptr_count
return info
@staticmethod
def try_eval_const_expr(node, SymbolTable):
from lib.core.ConstEvaluator import ConstEvaluator
return ConstEvaluator.eval_with_symtab(node, SymbolTable)
@staticmethod
def from_node(Node: ast.AST, SymbolTable: dict) -> CTypeInfo:
"""从 AST 节点解析 CTypeInfo
Args:
Node: AST 节点(如 ast.Name, ast.Attribute 等)
SymbolTable: 符号表字典
"""
if isinstance(Node, (ast.Constant, ast.Str)):
return TypeAnnotationResolver._from_node_constant(Node, SymbolTable)
if isinstance(Node, ast.Name):
return TypeAnnotationResolver._from_node_name(Node, SymbolTable)
if isinstance(Node, ast.Call):
return TypeAnnotationResolver._from_node_call(Node, SymbolTable)
if isinstance(Node, ast.BinOp) and isinstance(Node.op, ast.BitOr):
return TypeAnnotationResolver._from_node_binop(Node, SymbolTable)
if isinstance(Node, ast.Subscript):
return TypeAnnotationResolver._from_node_subscript(Node, SymbolTable)
if isinstance(Node, ast.Attribute):
return TypeAnnotationResolver._from_node_attribute(Node, SymbolTable)
return CTypeInfo()
@staticmethod
def _from_node_constant(Node: ast.AST, SymbolTable: dict) -> CTypeInfo:
"""处理 ast.Constant / ast.Str 节点"""
if isinstance(Node, ast.Constant):
TypeName = Node.value
else:
TypeName = Node.s
return TypeAnnotationResolver.from_type_name(TypeName)
@staticmethod
def _from_node_name(Node: ast.Name, SymbolTable: dict) -> CTypeInfo:
"""处理 ast.Name 节点"""
from lib.includes import t
TypeName = Node.id
TypeObj = CTypeHelper.GetTModuleCType(TypeName)
if TypeObj is None:
TypeObj = getattr(t, TypeName, None)
if isinstance(TypeObj, type) and issubclass(TypeObj, t.CType) and TypeObj is not t.CType:
if TypeObj == t.CPtr:
Result = CTypeInfo()
Result.PtrCount = 1
Result.BaseType = t.CVoid()
return Result
if TypeObj == t.State:
Result = CTypeInfo()
Result.IsState = True
Result.BaseType = t.CVoid()
return Result
Inst = TypeObj()
Result = CTypeInfo()
Result.BaseType = TypeObj
if hasattr(Inst, 'CName') and Inst.CName:
Result.Name = Inst.CName
if hasattr(Inst, 'IsSigned'):
Result.IsSigned = Inst.IsSigned
return Result
if TypeName in SymbolTable:
Entry = SymbolTable[TypeName]
if Entry:
if isinstance(Entry, CTypeInfo):
if Entry.IsTypedef:
if Entry.BaseType and (not isinstance(Entry.BaseType, (t._CTypedef,)) or Entry.PtrCount > 0):
Result = Entry.Copy()
Result.IsTypedef = True
Result.Name = TypeName
return Result
if Entry.OriginalType:
if isinstance(Entry.OriginalType, CTypeInfo) and Entry.OriginalType.IsFuncPtr:
Result = CTypeInfo()
Result.IsFuncPtr = True
Result.FuncPtrReturn = Entry.OriginalType.FuncPtrReturn or CTypeInfo.VoidTypeInfo()
Result.FuncPtrParams = list(Entry.OriginalType.FuncPtrParams) if Entry.OriginalType.FuncPtrParams else []
Result.IsTypedef = True
Result.Name = TypeName
return Result
elif isinstance(Entry.OriginalType, CTypeInfo):
Resolved = Entry.OriginalType.Copy()
elif isinstance(Entry.OriginalType, str) and Entry.OriginalType == 'Callable':
Result = CTypeInfo()
Result.IsFuncPtr = True
Result.FuncPtrReturn = CTypeInfo.VoidTypeInfo()
Result.FuncPtrParams = []
Result.IsTypedef = True
Result.Name = TypeName
return Result
elif isinstance(Entry.OriginalType, str):
Resolved = TypeAnnotationResolver.from_type_name(Entry.OriginalType)
else:
Resolved = Entry.OriginalType
Resolved.IsTypedef = True
Resolved.Name = TypeName
return Resolved
TypeEntry = BuiltinTypeMap.Get(TypeName)
if TypeEntry:
Result = CTypeInfo()
Result.BaseType = TypeEntry[0]()
Result.PtrCount = TypeEntry[1]
Result.IsTypedef = True
Result.Name = TypeName
return Result
return Entry
if Entry.IsEnum:
Result = CTypeInfo()
Result.BaseType = t.CInt()
Result.IsEnum = True
Result.Name = TypeName
return Result
if Entry.IsExceptionClass:
Result = CTypeInfo()
Result.BaseType = t.CInt()
Result.IsExceptionClass = True
Result.Name = TypeName
return Result
if Entry.BaseType is None and (Entry.IsStruct or Entry.Name):
Entry.BaseType = t.CStruct(name=TypeName)
Entry.IsStruct = True
return Entry
elif isinstance(Entry, dict):
if Entry.get('type') == 'typedef':
OriginalType = Entry.get('OriginalType', '')
if OriginalType:
if OriginalType == 'Callable':
Result = CTypeInfo()
Result.IsFuncPtr = True
Result.FuncPtrReturn = CTypeInfo.VoidTypeInfo()
Result.FuncPtrParams = []
Result.IsTypedef = True
Result.Name = TypeName
return Result
Resolved = TypeAnnotationResolver.from_type_name(OriginalType)
Resolved.IsTypedef = True
Resolved.Name = TypeName
return Resolved
TypeEntry = BuiltinTypeMap.Get(TypeName)
if TypeEntry:
Result = CTypeInfo()
Result.BaseType = TypeEntry[0]()
Result.PtrCount = TypeEntry[1]
Result.IsTypedef = True
Result.Name = TypeName
return Result
Result = CTypeInfo()
Result.BaseType = t._CTypedef(TypeName)
Result.IsTypedef = True
Result.Name = TypeName
return Result
# 特殊处理 str 类型,它应该是 char*(指针)
if TypeName in ('str', 'bytes'):
Result = CTypeInfo()
Result.BaseType = t.CChar()
Result.PtrCount = 1
return Result
if TypeName == 'irq_handler_t':
pass
return TypeAnnotationResolver.from_type_name(TypeName)
@staticmethod
def _from_node_call(Node: ast.Call, SymbolTable: dict) -> CTypeInfo:
"""处理 ast.Call 节点"""
from lib.includes import t
if isinstance(Node.func, ast.Name) and Node.func.id == 'callable':
Result = CTypeInfo()
Result.IsFuncPtr = True
Result.FuncPtrReturn = CTypeInfo.VoidTypeInfo()
Result.FuncPtrParams = []
try:
if len(Node.args) > 0:
RetInfo = TypeAnnotationResolver.from_node(Node.args[0], SymbolTable)
if RetInfo:
Result.FuncPtrReturn = RetInfo
for kw in Node.keywords:
ParamInfo = TypeAnnotationResolver.from_node(kw.value, SymbolTable)
if ParamInfo:
Result.FuncPtrParams.append((kw.arg or '', ParamInfo))
except Exception as _e:
if __import__('lib.constants.config', fromlist=['mode']).mode == "strict":
import warnings; warnings.warn(f"异常被忽略: {_e}")
return Result
if isinstance(Node.func, ast.Attribute):
if isinstance(Node.func.value, ast.Name) and Node.func.value.id == 't':
if Node.func.attr == 'Bit' and len(Node.args) > 0:
Result = CTypeInfo()
Result.BaseType = t.CInt()
Result.IsBitField = True
if isinstance(Node.args[0], ast.Constant) and isinstance(Node.args[0].value, int):
Result.BitWidth = Node.args[0].value
else:
Result.BitWidth = 1
return Result
return CTypeInfo()
@staticmethod
def _from_node_binop(Node: ast.BinOp, SymbolTable: dict) -> CTypeInfo:
"""处理 ast.BinOp (BitOr) 节点"""
from lib.includes import t
LeftInfo = TypeAnnotationResolver.from_node(Node.left, SymbolTable)
RightInfo = TypeAnnotationResolver.from_node(Node.right, SymbolTable)
if LeftInfo.IsState or RightInfo.IsState:
Result = CTypeInfo()
Result.IsState = True
NonStateInfo = LeftInfo if not LeftInfo.IsState else RightInfo
StateInfo = LeftInfo if LeftInfo.IsState else RightInfo
if NonStateInfo.BaseType and (not isinstance(NonStateInfo.BaseType, (t._CTypedef,)) or NonStateInfo.PtrCount > 0):
Result.BaseType = NonStateInfo.BaseType
elif NonStateInfo.IsTypedef and NonStateInfo.Name:
if NonStateInfo.BaseType and (not isinstance(NonStateInfo.BaseType, (t._CTypedef,)) or NonStateInfo.PtrCount > 0):
Result.BaseType = NonStateInfo.BaseType
Result.PtrCount = NonStateInfo.PtrCount
Result.IsTypedef = True
Result.Name = NonStateInfo.Name
if NonStateInfo.OriginalType:
Result.OriginalType = NonStateInfo.OriginalType
else:
Result.BaseType = t.CStruct(name=NonStateInfo.Name)
Result.IsStruct = True
Result.IsTypedef = True
Result.Name = NonStateInfo.Name
if NonStateInfo.OriginalType:
Result.OriginalType = NonStateInfo.OriginalType
else:
Result.BaseType = t.CVoid()
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if not Result.Storage:
Result.Storage = t.CExport()
if LeftInfo.Storage and not isinstance(LeftInfo.Storage, t.CExport):
Result.Storage = LeftInfo.Storage
elif RightInfo.Storage and not isinstance(RightInfo.Storage, t.CExport):
Result.Storage = RightInfo.Storage
if LeftInfo.DataConst or RightInfo.DataConst:
Result.DataConst = True
if LeftInfo.VarConst or RightInfo.VarConst:
Result.VarConst = True
return Result
if LeftInfo.IsPtr or RightInfo.IsPtr:
Result = CTypeInfo()
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
NonPtrInfo = LeftInfo if not LeftInfo.IsPtr else RightInfo
PtrInfo = RightInfo if RightInfo.IsPtr else LeftInfo
if NonPtrInfo.BaseType and (not isinstance(NonPtrInfo.BaseType, (t._CTypedef,)) or NonPtrInfo.PtrCount > 0):
Result.BaseType = NonPtrInfo.BaseType
elif NonPtrInfo.IsTypedef and NonPtrInfo.Name:
if NonPtrInfo.BaseType and (not isinstance(NonPtrInfo.BaseType, (t._CTypedef,)) or NonPtrInfo.PtrCount > 0):
Result.BaseType = NonPtrInfo.BaseType
Result.IsTypedef = True
Result.Name = NonPtrInfo.Name
if NonPtrInfo.OriginalType:
Result.OriginalType = NonPtrInfo.OriginalType
else:
Result.BaseType = t.CStruct(name=NonPtrInfo.Name)
Result.IsStruct = True
elif PtrInfo.BaseType and (not isinstance(PtrInfo.BaseType, (t._CTypedef,)) or PtrInfo.PtrCount > 0):
Result.BaseType = PtrInfo.BaseType
else:
Result.BaseType = t.CUnsignedChar()
if LeftInfo.DataConst or RightInfo.DataConst:
Result.DataConst = True
if LeftInfo.VarConst or RightInfo.VarConst:
Result.VarConst = True
if LeftInfo.DataVolatile or RightInfo.DataVolatile:
Result.DataVolatile = True
if LeftInfo.VarVolatile or RightInfo.VarVolatile:
Result.VarVolatile = True
if LeftInfo.Storage:
Result.Storage = LeftInfo.Storage
elif RightInfo.Storage:
Result.Storage = RightInfo.Storage
return Result
if LeftInfo.DataConst or RightInfo.DataConst:
Result = CTypeInfo()
BaseTypeSide = LeftInfo if not LeftInfo.DataConst else RightInfo
QualSide = LeftInfo if LeftInfo.DataConst else RightInfo
Result.BaseType = BaseTypeSide.BaseType if BaseTypeSide.BaseType and (not isinstance(BaseTypeSide.BaseType, t.CVoid) or BaseTypeSide.PtrCount > 0) else QualSide.BaseType
if not Result.BaseType:
Result.BaseType = t.CInt()
Result.DataConst = True
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if LeftInfo.VarConst or RightInfo.VarConst:
Result.VarConst = True
if LeftInfo.DataVolatile or RightInfo.DataVolatile:
Result.DataVolatile = True
if LeftInfo.Storage:
Result.Storage = LeftInfo.Storage
elif RightInfo.Storage:
Result.Storage = RightInfo.Storage
return Result
if LeftInfo.DataVolatile or RightInfo.DataVolatile:
Result = CTypeInfo()
BaseTypeSide = LeftInfo if not LeftInfo.DataVolatile else RightInfo
QualSide = LeftInfo if LeftInfo.DataVolatile else RightInfo
Result.BaseType = BaseTypeSide.BaseType if BaseTypeSide.BaseType and (not isinstance(BaseTypeSide.BaseType, t.CVoid) or BaseTypeSide.PtrCount > 0) else QualSide.BaseType
if not Result.BaseType:
Result.BaseType = t.CInt()
Result.DataVolatile = True
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if LeftInfo.VarConst or RightInfo.VarConst:
Result.VarConst = True
if LeftInfo.Storage:
Result.Storage = LeftInfo.Storage
elif RightInfo.Storage:
Result.Storage = RightInfo.Storage
return Result
if LeftInfo.Storage or RightInfo.Storage:
Result = CTypeInfo()
BaseTypeSide = LeftInfo if not LeftInfo.Storage else RightInfo
StorageSide = LeftInfo if LeftInfo.Storage else RightInfo
if BaseTypeSide.IsState or StorageSide.IsState:
Result.IsState = True
Result.BaseType = t.CVoid()
Result.Storage = LeftInfo.Storage if LeftInfo.Storage else RightInfo.Storage
return Result
Result.BaseType = BaseTypeSide.BaseType if BaseTypeSide.BaseType and (not isinstance(BaseTypeSide.BaseType, t.CVoid) or BaseTypeSide.PtrCount > 0) else StorageSide.BaseType
if not Result.BaseType:
Result.BaseType = t.CInt()
Result.Storage = LeftInfo.Storage if LeftInfo.Storage else RightInfo.Storage
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if LeftInfo.DataConst or RightInfo.DataConst:
Result.DataConst = True
if LeftInfo.VarConst or RightInfo.VarConst:
Result.VarConst = True
return Result
# 检查是否有位域类型 (t.Bit)
if LeftInfo.IsBitField:
Result = CTypeInfo()
Result.BaseType = LeftInfo.BaseType if LeftInfo.BaseType else t.CInt()
Result.IsBitField = True
Result.BitWidth = LeftInfo.BitWidth
return Result
if RightInfo.IsBitField:
Result = CTypeInfo()
Result.BaseType = RightInfo.BaseType if RightInfo.BaseType else t.CInt()
Result.IsBitField = True
Result.BitWidth = RightInfo.BitWidth
return Result
# 处理字节序类型 (t.BigEndian, t.LittleEndian)
if LeftInfo.ByteOrder:
Result = CTypeInfo()
Result.BaseType = LeftInfo.BaseType if LeftInfo.BaseType else t.CInt()
Result.ByteOrder = LeftInfo.ByteOrder
return Result
if RightInfo.ByteOrder:
Result = CTypeInfo()
Result.BaseType = RightInfo.BaseType if RightInfo.BaseType else t.CInt()
Result.ByteOrder = RightInfo.ByteOrder
return Result
if LeftInfo.IsFuncPtr or RightInfo.IsFuncPtr:
Result = CTypeInfo()
FuncPtrSide = LeftInfo if LeftInfo.IsFuncPtr else RightInfo
Result.IsFuncPtr = True
Result.FuncPtrParams = list(FuncPtrSide.FuncPtrParams)
Result.FuncPtrReturn = FuncPtrSide.FuncPtrReturn
if LeftInfo.Storage:
Result.Storage = LeftInfo.Storage
elif RightInfo.Storage:
Result.Storage = RightInfo.Storage
return Result
if LeftInfo.IsTypedef and RightInfo.BaseType:
if LeftInfo.BaseType and (not isinstance(LeftInfo.BaseType, (t._CTypedef,)) or LeftInfo.PtrCount > 0):
Result = LeftInfo.Copy()
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if RightInfo.Storage:
Result.Storage = RightInfo.Storage
return Result
return RightInfo
if RightInfo.IsTypedef and LeftInfo.BaseType:
if RightInfo.BaseType and (not isinstance(RightInfo.BaseType, (t._CTypedef,)) or RightInfo.PtrCount > 0):
Result = RightInfo.Copy()
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
if LeftInfo.Storage:
Result.Storage = LeftInfo.Storage
return Result
return LeftInfo
if LeftInfo.BaseType:
return LeftInfo
elif RightInfo.BaseType:
return RightInfo
return CTypeInfo()
@staticmethod
def _from_node_subscript(Node: ast.Subscript, SymbolTable: dict) -> CTypeInfo:
"""处理 ast.Subscript 节点"""
from lib.includes import t
base = Node.value
if isinstance(base, ast.Attribute):
if isinstance(base.value, ast.Name) and base.value.id == 't' and base.attr == 'Bit':
Result = CTypeInfo()
Result.BaseType = t.CInt()
Result.IsBitField = True
if isinstance(Node.slice, ast.Constant) and isinstance(Node.slice.value, int):
Result.BitWidth = Node.slice.value
else:
Result.BitWidth = 1
return Result
if isinstance(base, ast.Name) and base.id == 'list':
slice_node = Node.slice
elts = []
if isinstance(slice_node, ast.Tuple):
elts = slice_node.elts
elif isinstance(slice_node, (ast.Attribute, ast.Name, ast.Subscript)):
elts = [slice_node]
if elts:
ElemInfo = TypeAnnotationResolver.from_node(elts[0], SymbolTable)
if ElemInfo and ElemInfo.BaseType:
Result = CTypeInfo()
Result.BaseType = ElemInfo.BaseType
Result.PtrCount = ElemInfo.PtrCount
Result.ArrayDims = list(ElemInfo.ArrayDims)
if len(elts) >= 2:
count_val = TypeAnnotationResolver.try_eval_const_expr(elts[1], SymbolTable)
if count_val is not None and isinstance(count_val, int) and count_val > 0:
Result.ArrayDims.insert(0, str(count_val))
else:
Result.PtrCount += 1
if ElemInfo.IsPtr and not ElemInfo.ArrayDims:
Result.PtrCount = max(Result.PtrCount, 1)
return Result
if isinstance(base, ast.Attribute):
parts = []
current = base
while isinstance(current, ast.Attribute):
parts.insert(0, current.attr)
current = current.value
if isinstance(current, ast.Name):
parts.insert(0, current.id)
if parts and parts[0] == 't' and parts[-1] == t.CPtr.__name__:
Result = CTypeInfo()
Result.BaseType = t.CVoid()
Result.PtrCount = 1
slice_node = Node.slice
if isinstance(slice_node, ast.Subscript):
InnerInfo = TypeAnnotationResolver.from_node(slice_node, SymbolTable)
if InnerInfo:
if InnerInfo.PtrCount > 0:
Result.PtrCount += InnerInfo.PtrCount
if InnerInfo.BaseType and not isinstance(InnerInfo.BaseType, t.CVoid):
Result.BaseType = InnerInfo.BaseType
elif isinstance(slice_node, ast.Attribute):
SliceInfo = TypeAnnotationResolver.from_node(slice_node, SymbolTable)
if SliceInfo:
if SliceInfo.IsPtr:
Result.PtrCount += SliceInfo.PtrCount
elif SliceInfo.BaseType and not isinstance(SliceInfo.BaseType, t.CVoid):
Result.BaseType = SliceInfo.BaseType
elif isinstance(slice_node, ast.Name):
SliceType = getattr(t, slice_node.id, None)
if SliceType == t.CPtr:
Result.PtrCount += 1
else:
SliceInfo = TypeAnnotationResolver.from_node(slice_node, SymbolTable)
if SliceInfo and SliceInfo.BaseType and not isinstance(SliceInfo.BaseType, t.CVoid):
Result.BaseType = SliceInfo.BaseType
return Result
if parts and parts[0] == 't' and parts[-1] == 'Callable':
Result = CTypeInfo()
Result.IsFuncPtr = True
slice_node = Node.slice
if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2:
params_list = slice_node.elts[0]
return_node = slice_node.elts[1]
ParamTypes = []
if isinstance(params_list, ast.List):
for elt in params_list.elts:
ParamTypeInfo = TypeAnnotationResolver.from_node(elt, SymbolTable)
if ParamTypeInfo:
ParamTypes.append(('', ParamTypeInfo))
if not ParamTypes:
ParamTypes.append(('', TypeAnnotationResolver.from_type_name('void')))
Result.FuncPtrParams = ParamTypes
ReturnTypeInfo = TypeAnnotationResolver.from_node(return_node, SymbolTable)
Result.FuncPtrReturn = ReturnTypeInfo if ReturnTypeInfo else CTypeInfo.VoidTypeInfo()
return Result
return CTypeInfo()
@staticmethod
def _from_node_attribute(Node: ast.Attribute, SymbolTable: dict) -> CTypeInfo:
"""处理 ast.Attribute 节点"""
from lib.includes import t
ModuleParts = []
Current = Node
while isinstance(Current, ast.Attribute):
ModuleParts.insert(0, Current.attr)
Current = Current.value
if isinstance(Current, ast.Name):
ModuleParts.insert(0, Current.id)
if len(ModuleParts) >= 2:
TypeName = ModuleParts[-1]
ModulePath = '.'.join(ModuleParts[:-1])
elif len(ModuleParts) == 1:
TypeName = ModuleParts[0]
ModulePath = None
else:
return CTypeInfo()
# 解析 import 别名: 如 import vpsdk.window as window -> window -> vpsdk.window
if ModulePath:
resolved = False
import_aliases = SymbolTable.import_aliases
if ModulePath in import_aliases:
ModulePath = import_aliases[ModulePath]
resolved = True
if not resolved and ModulePath in SymbolTable:
entry = SymbolTable[ModulePath]
if isinstance(entry, CTypeInfo) and entry.IsModuleAlias:
resolved_name = entry.ResolvedModule
if resolved_name:
ModulePath = resolved_name
if ModulePath == 't' or (ModulePath and ModulePath.startswith('t.')):
TypeClass = CTypeHelper.GetTModuleCType(TypeName)
if TypeClass is None:
TypeClass = getattr(t, TypeName, None)
if TypeClass is not None and TypeClass.HasPosition(t.CType.POINTER):
Info = CTypeInfo()
Info.PtrCount = 1
if TypeClass == t.CArrayPtr:
Info.IsArrayPtr = True
Info.BaseType = t.CVoid
return Info
if TypeClass is not None and TypeClass.IsStorageClass():
Info = CTypeInfo()
Info.Storage = TypeClass()
if TypeClass == t.State:
Info.IsState = True
Info.BaseType = t.CVoid()
return Info
if TypeClass is not None and TypeClass.IsTypeQualifier():
Info = CTypeInfo()
if TypeClass == t.CConst:
Info.DataConst = True
elif TypeClass == t.CVolatile:
Info.DataVolatile = True
return Info
if (TypeClass is not None
and isinstance(TypeClass, type)
and issubclass(TypeClass, t.CType)
and TypeClass is not t.CType
and TypeClass.HasPosition(t.CType.BASE)):
if TypeClass == t.State:
Result = CTypeInfo()
Result.IsState = True
Result.BaseType = t.CVoid()
return Result
Inst = TypeClass()
Result = CTypeInfo()
Result.BaseType = TypeClass
if hasattr(Inst, 'CName') and Inst.CName:
Result.Name = Inst.CName
if hasattr(Inst, 'IsSigned'):
Result.IsSigned = Inst.IsSigned
return Result
CNAME = CTypeHelper.GetCName(TypeName)
if CNAME:
return TypeAnnotationResolver.from_type_name(CNAME)
# 处理字节序类型
if TypeName == 'BigEndian':
Result = CTypeInfo()
Result.BaseType = t.CInt()
Result.ByteOrder = 'big'
return Result
if TypeName == 'LittleEndian':
Result = CTypeInfo()
Result.BaseType = t.CInt()
Result.ByteOrder = 'little'
return Result
FullName = f"{ModulePath}.{TypeName}" if ModulePath else TypeName
if TypeName in SymbolTable:
Entry = SymbolTable[TypeName]
if Entry and Entry.IsTypedef:
Resolved = Entry.Copy()
if Resolved.BaseType is None:
Resolved.BaseType = t._CTypedef(TypeName)
return Resolved
if Entry and Entry.IsEnum:
Result = CTypeInfo()
Result.BaseType = t.CInt()
Result.IsEnum = True
Result.Name = TypeName
return Result
if Entry and Entry.IsExceptionClass:
Result = CTypeInfo()
Result.BaseType = t.CInt()
Result.IsExceptionClass = True
Result.Name = TypeName
return Result
if Entry:
Result = Entry.Copy()
if Result.BaseType is None and (Result.IsStruct or Result.IsCpythonObject or Result.Name):
Result.BaseType = t.CStruct(name=TypeName)
Result.IsStruct = True
return Result
return CTypeInfo()
if FullName in SymbolTable:
Info = SymbolTable[FullName]
if Info and Info.IsTypedef:
OriginalType = Info.get('OriginalType', '')
if OriginalType and 'typedef' in OriginalType:
parts = OriginalType.split()
if len(parts) >= 2:
BaseType_name = parts[1]
if not BaseType_name.startswith('C'):
BaseType_name = 'C' + BaseType_name
CNAME = CTypeHelper.GetCName(BaseType_name)
if CNAME:
return TypeAnnotationResolver.from_type_name(CNAME)
Result = CTypeInfo()
Result.BaseType = t._CTypedef(TypeName)
Result.IsTypedef = True
return Result
if Info:
Result = Info.Copy()
if Result.BaseType is None and (Result.IsStruct or Result.IsCpythonObject or Result.Name):
Result.BaseType = t.CStruct(name=TypeName)
Result.IsStruct = True
return Result
return CTypeInfo()
return CTypeInfo()
@staticmethod
def _handle_array_subscript(Node, SymbolTable):
if not isinstance(Node, ast.Subscript):
return None
dims = []
current = Node
while isinstance(current, ast.Subscript):
if isinstance(current.slice, ast.Constant) and isinstance(current.slice.value, int):
dims.insert(0, str(current.slice.value))
elif isinstance(current.slice, ast.Name):
dims.insert(0, current.slice.id)
else:
return None
current = current.value
base_info = TypeAnnotationResolver.from_node(current, SymbolTable)
if base_info and base_info.BaseType:
base_info.ArrayDims = dims
return base_info
return None