diff --git a/TODO b/TODO index 715c0f9..a381065 100644 --- a/TODO +++ b/TODO @@ -4,3 +4,4 @@ main 收集 元类型 @p.set 函数的描述符用装饰器而不是返回值 +崩溃/返回作用域 回调 \ No newline at end of file diff --git a/Test/CPythonTest/temp/_shared_sym.pkl b/Test/CPythonTest/temp/_shared_sym.pkl index b106faf..59d9977 100644 Binary files a/Test/CPythonTest/temp/_shared_sym.pkl and b/Test/CPythonTest/temp/_shared_sym.pkl differ diff --git a/Test/TestProject/temp/_shared_sym.pkl b/Test/TestProject/temp/_shared_sym.pkl index fbd62a4..72361f0 100644 Binary files a/Test/TestProject/temp/_shared_sym.pkl and b/Test/TestProject/temp/_shared_sym.pkl differ diff --git a/Test/TestProject2/temp/_shared_sym.pkl b/Test/TestProject2/temp/_shared_sym.pkl index 46cbf6c..0d372ae 100644 Binary files a/Test/TestProject2/temp/_shared_sym.pkl and b/Test/TestProject2/temp/_shared_sym.pkl differ diff --git a/Test/TestProject3/temp/_shared_sym.pkl b/Test/TestProject3/temp/_shared_sym.pkl index 4a45d9a..92438b1 100644 Binary files a/Test/TestProject3/temp/_shared_sym.pkl and b/Test/TestProject3/temp/_shared_sym.pkl differ diff --git a/Test/ZlibTest/temp/_shared_sym.pkl b/Test/ZlibTest/temp/_shared_sym.pkl index 12fffe1..d42f8d0 100644 Binary files a/Test/ZlibTest/temp/_shared_sym.pkl and b/Test/ZlibTest/temp/_shared_sym.pkl differ diff --git a/Test/test_out.txt b/Test/test_out.txt new file mode 100644 index 0000000..f302d06 --- /dev/null +++ b/Test/test_out.txt @@ -0,0 +1 @@ +UnicodeEncodeError: 'gbk' codec can't encode character '\ufffd' in position 3: illegal multibyte sequence diff --git a/Test/test_output.txt b/Test/test_output.txt new file mode 100644 index 0000000..5838da2 --- /dev/null +++ b/Test/test_output.txt @@ -0,0 +1 @@ +====================================================================== diff --git a/lib/core/Handles/HandlesBase.py b/lib/core/Handles/HandlesBase.py index 94d0b9b..b958144 100644 --- a/lib/core/Handles/HandlesBase.py +++ b/lib/core/Handles/HandlesBase.py @@ -7,7 +7,8 @@ from lib.includes import t import ast from typing import List, Dict -from enum import IntFlag, auto +from enum import IntFlag, auto +from lib.core.TypeSpec import TypeSpec, SymbolMeta, FIELD_ROUTES EXCEPTION_CODE_MAP = { @@ -66,57 +67,72 @@ class CTypeInfo: """ def __init__(self): - self._BaseType: t.CType = None - self.PtrCount: int = 0 - self.VarConst: bool = False - self.VarVolatile: bool = False - self.DataConst: bool = False - self.DataVolatile: bool = False - self.ArrayDims: List[str] = [] - self.Storage: t.CType = None - self.IsFuncPtr: bool = False - self.FuncPtrParams: List[Tuple[str, 'CTypeInfo']] = [] # 函数指针参数列表:(参数名, 参数类型) - self.FuncParamNames: List[str] = [] # 函数参数名列表 - self.FuncPtrReturn: "CTypeInfo" = None - self.IsBitField: bool = False - self.BitWidth: int = 0 - self.ByteOrder: str = "" # "big", "little", or "" - self.IsTypedef: bool = False - self.IsStruct: bool = False - self.IsEnum: bool = False - self.IsUnion: bool = False - self.IsRenum: bool = False - self.RenumVariants: list = [] - self.Name: str = "" - self.Members: Dict[str, 'CTypeInfo'] = {} - self.OriginalType: "CTypeInfo" = None - self.DeclaredType: str = "" - self.CreturnTypes: list = [] - self.Lineno: int = 0 - self.file: str = "" - self.IsAnonymous: bool = False - self.IsCpythonObject: bool = False - self.IsEnumMember: bool = False - self.IsVariadic: bool = False - self.IsVariable: bool = False - self.IsFunction: bool = False - self.MetaList: FuncMeta = FuncMeta.NONE - self.IsArrayPtr: bool = False - self.ArrayPtr: 'CTypeInfo' = None - self.IsState: bool = False - self.IsDefine: bool = False - self.DefineValue = None - self.IsInline: bool = False - self.InlineBody: list = None - self.InlineParams: list = None - self.ModuleName: str = "" - self._extra: dict = {} + object.__setattr__(self, '_ts', TypeSpec()) + sm = SymbolMeta() + sm.meta_list = FuncMeta.NONE + object.__setattr__(self, '_sm', sm) + + # --- 新公共 API:供新代码直接访问 TypeSpec / SymbolMeta / SymbolKind --- + @property + def ts(self) -> TypeSpec: + """TypeSpec — 纯类型描述(只读)""" + return self._ts + + @property + def sm(self) -> SymbolMeta: + """SymbolMeta — 符号表元数据(只读)""" + return self._sm + + @property + def kind(self) -> 'SymbolKind': + """SymbolKind — 符号类型种类枚举""" + return self._sm.kind + + def __setattr__(self, name, value): + """属性设置路由 — 将旧字段名委托到 _ts/_sm/_kind_flags""" + if name == 'BaseType': + # BaseType 有复杂的 property setter(自动设置 IsStruct/IsEnum/IsUnion) + CTypeInfo.BaseType.fset(self, value) + return + if name in ('_ts', '_sm', 'ts', 'sm', 'kind'): + # _ts/_sm 内部字段直接设置;ts/sm/kind 是只读 property,禁止设置 + if name in ('ts', 'sm', 'kind'): + raise AttributeError(f"'CTypeInfo' attribute '{name}' is read-only") + object.__setattr__(self, name, value) + return + if name in FIELD_ROUTES: + target, field = FIELD_ROUTES[name] + if target == 'ts': + setattr(self._ts, field, value) + elif target == 'sm': + setattr(self._sm, field, value) + elif target == 'kf': + self._sm._kind_flags[field] = value + return + object.__setattr__(self, name, value) + + def __getattr__(self, name): + """属性读取路由 — 将旧字段名委托到 _ts/_sm/_kind_flags""" + try: + ts = object.__getattribute__(self, '_ts') + sm = object.__getattribute__(self, '_sm') + except AttributeError: + raise AttributeError(f"'CTypeInfo' object has no attribute '{name}'") + if name in FIELD_ROUTES: + target, field = FIELD_ROUTES[name] + if target == 'ts': + return getattr(ts, field) + elif target == 'sm': + return getattr(sm, field) + elif target == 'kf': + return sm._kind_flags.get(field, False) + raise AttributeError(f"'CTypeInfo' object has no attribute '{name}'") @property def BaseType(self) -> t.CType | tuple: - return self._BaseType + return self._ts._base_type @BaseType.setter def BaseType(self, value: t.CType | type | tuple | List): @@ -127,54 +143,57 @@ class CTypeInfo: - type (CType 子类): 如 t.CStruct,自动实例化 - tuple/list of t.CType: 多个组合类型 """ + ts = self._ts + kf = self._sm._kind_flags + if value is None: - self._BaseType = None - self.IsStruct = False - self.IsEnum = False - self.IsUnion = False - self.IsRenum = False + ts._base_type = None + kf['IsStruct'] = False + kf['IsEnum'] = False + kf['IsUnion'] = False + kf['IsRenum'] = False return if isinstance(value, (tuple, list)): - self._BaseType = tuple(value) + ts._base_type = tuple(value) for v in value: if isinstance(v, t.CStruct): - self.IsStruct = True + kf['IsStruct'] = True elif isinstance(v, t.CEnum): - self.IsEnum = True + kf['IsEnum'] = True elif isinstance(v, t.CUnion): - self.IsUnion = True + kf['IsUnion'] = True elif isinstance(v, t.REnum): - self.IsRenum = True - self.IsEnum = True + kf['IsRenum'] = True + kf['IsEnum'] = True return if isinstance(value, type) and issubclass(value, t.CType): - self._BaseType = value() + ts._base_type = value() return if isinstance(value, t.CType): - self._BaseType = value + ts._base_type = value if isinstance(value, t.CStruct): - self.IsStruct = True - self.IsEnum = False - self.IsUnion = False - self.IsRenum = False + kf['IsStruct'] = True + kf['IsEnum'] = False + kf['IsUnion'] = False + kf['IsRenum'] = False elif isinstance(value, t.REnum): - self.IsRenum = True - self.IsEnum = True - self.IsStruct = False - self.IsUnion = False + kf['IsRenum'] = True + kf['IsEnum'] = True + kf['IsStruct'] = False + kf['IsUnion'] = False elif isinstance(value, t.CEnum): - self.IsEnum = True - self.IsStruct = False - self.IsUnion = False - self.IsRenum = False + kf['IsEnum'] = True + kf['IsStruct'] = False + kf['IsUnion'] = False + kf['IsRenum'] = False elif isinstance(value, t.CUnion): - self.IsUnion = True - self.IsStruct = False - self.IsEnum = False - self.IsRenum = False + kf['IsUnion'] = True + kf['IsStruct'] = False + kf['IsEnum'] = False + kf['IsRenum'] = False return raise TypeError(f"BaseType must be t.CType instance, type subclass, or tuple of t.CType, got {type(value)}") @@ -182,82 +201,92 @@ class CTypeInfo: @property def TypeCls(self): """获取 CType 类(从 BaseType 推断)""" - if self.BaseType: - return type(self.BaseType) - if self.IsStruct: + bt = self._ts._base_type + if bt: + return type(bt) + kf = self._sm._kind_flags + if kf.get('IsStruct'): return t.CStruct - if self.IsEnum: + if kf.get('IsEnum'): return t.CEnum - if self.IsUnion: + if kf.get('IsUnion'): return t.CUnion - if self.IsTypedef: + if kf.get('IsTypedef'): return t._CTypedef return None @property def IsPtr(self) -> bool: - return self.PtrCount > 0 + return self._ts.ptr_count > 0 @property def IsVoid(self) -> bool: - return isinstance(self.BaseType, t.CVoid) + return isinstance(self._ts._base_type, t.CVoid) @property def IsStr(self) -> bool: - return isinstance(self.BaseType, t.CChar) and self.PtrCount > 0 + return isinstance(self._ts._base_type, t.CChar) and self._ts.ptr_count > 0 @property def IsInt(self) -> bool: - return isinstance(self.BaseType, t.CType) and getattr(self.BaseType, 'IsSigned', None) is not None and self.BaseType.IsSigned is True and not self.IsVoid + bt = self._ts._base_type + return isinstance(bt, t.CType) and getattr(bt, 'IsSigned', None) is not None and bt.IsSigned is True and not isinstance(bt, t.CVoid) @property def IsUInt(self) -> bool: - return isinstance(self.BaseType, t.CType) and getattr(self.BaseType, 'IsSigned', None) is False + bt = self._ts._base_type + return isinstance(bt, t.CType) and getattr(bt, 'IsSigned', None) is False @property def IsFloat(self) -> bool: - bt = self.BaseType + bt = self._ts._base_type return isinstance(bt, t.CType) and getattr(bt, 'IsSigned', None) is None and getattr(bt, 'Size', 0) in (32, 64, 128) and not isinstance(bt, t.CVoid) @property def IsDouble(self) -> bool: - return isinstance(self.BaseType, t.CDouble) or (isinstance(self.BaseType, t.CFloat64T)) + bt = self._ts._base_type + return isinstance(bt, t.CDouble) or isinstance(bt, t.CFloat64T) @property def IsPointerToChar(self) -> bool: - return isinstance(self.BaseType, t.CChar) and self.PtrCount > 0 + return isinstance(self._ts._base_type, t.CChar) and self._ts.ptr_count > 0 def ToString(self) -> str: - if self.IsFuncPtr: + ts = self._ts + sm = self._sm + kf = sm._kind_flags + bt = ts._base_type + + if ts.is_func_ptr: return 'Callable' parts = [] - if self.Storage and not isinstance(self.Storage, t.CExport): - parts.append(self.Storage.CName) + if ts.storage and not isinstance(ts.storage, t.CExport): + parts.append(ts.storage.CName) - if self.DataConst or self.DataVolatile: + if ts.data_const or ts.data_volatile: qualifiers = [] - if self.DataConst: + if ts.data_const: qualifiers.append("const") - if self.DataVolatile: + if ts.data_volatile: qualifiers.append("volatile") parts.append("_".join(qualifiers)) - if self.IsTypedef and self.Name: - return self.Name - elif self.IsRenum and self.Name: - base_name = self.Name - elif self.BaseType: - base_name = getattr(self.BaseType, 'CName', None) or (self.BaseType if isinstance(self.BaseType, str) else str(self.BaseType)) + if kf.get('IsTypedef') and sm.name: + return sm.name + elif kf.get('IsRenum') and sm.name: + base_name = sm.name + elif bt: + base_name = getattr(bt, 'CName', None) or (bt if isinstance(bt, str) else str(bt)) else: base_name = "void" - if self.IsArrayPtr: + if ts.is_array_ptr: ptr_str = "" - if self.PtrCount > 0: - ptr_str = "*" * self.PtrCount - if self.ArrayPtr: - inner = self.ArrayPtr.ToString() + if ts.ptr_count > 0: + ptr_str = "*" * ts.ptr_count + if ts.array_ptr: + inner = ts.array_ptr.ToString() if ptr_str: parts.append(f"{base_name} {ptr_str}({inner})") else: @@ -267,22 +296,22 @@ class CTypeInfo: parts.append(f"{base_name} {ptr_str}()") else: parts.append(f"{base_name} ()") - elif self.ArrayPtr: - inner = self.ArrayPtr.ToString() - if self.PtrCount > 0: - parts.append(f"{base_name} {'*' * self.PtrCount}({inner})") + elif ts.array_ptr: + inner = ts.array_ptr.ToString() + if ts.ptr_count > 0: + parts.append(f"{base_name} {'*' * ts.ptr_count}({inner})") else: parts.append(f"{base_name} ({inner})") else: parts.append(base_name) - if self.PtrCount > 0: - parts.append("*" * self.PtrCount) - if self.VarConst: + if ts.ptr_count > 0: + parts.append("*" * ts.ptr_count) + if ts.var_const: parts.append("const") - if self.VarVolatile: + if ts.var_volatile: parts.append("volatile") - for dim in self.ArrayDims: + for dim in ts.array_dims: if dim: parts.append(f"[{dim}]") else: @@ -1098,58 +1127,28 @@ class CTypeInfo: def Copy(self) -> "CTypeInfo": NewInfo = CTypeInfo() - NewInfo.BaseType = self.BaseType - NewInfo.PtrCount = self.PtrCount - NewInfo.VarConst = self.VarConst - NewInfo.VarVolatile = self.VarVolatile - NewInfo.DataConst = self.DataConst - NewInfo.DataVolatile = self.DataVolatile - NewInfo.ArrayDims = list(self.ArrayDims) - NewInfo.Storage = self.Storage - NewInfo.IsFuncPtr = self.IsFuncPtr - NewInfo.FuncPtrParams = list(self.FuncPtrParams) - NewInfo.FuncParamNames = list(self.FuncParamNames) - NewInfo.FuncPtrReturn = self.FuncPtrReturn.Copy() if isinstance(self.FuncPtrReturn, CTypeInfo) else self.FuncPtrReturn - NewInfo.IsBitField = self.IsBitField - NewInfo.BitWidth = self.BitWidth - NewInfo.IsTypedef = self.IsTypedef - NewInfo.IsStruct = self.IsStruct - NewInfo.IsEnum = self.IsEnum - NewInfo.IsUnion = self.IsUnion - NewInfo.IsRenum = self.IsRenum - NewInfo.RenumVariants = list(self.RenumVariants) - NewInfo.Name = self.Name - NewInfo.Members = dict(self.Members) - NewInfo.OriginalType = self.OriginalType.Copy() if isinstance(self.OriginalType, CTypeInfo) else self.OriginalType - NewInfo.DeclaredType = self.DeclaredType - NewInfo.CreturnTypes = list(self.CreturnTypes) - NewInfo.Lineno = self.Lineno - NewInfo.file = self.file - NewInfo.IsAnonymous = self.IsAnonymous - NewInfo.IsCpythonObject = self.IsCpythonObject - NewInfo.IsEnumMember = self.IsEnumMember - NewInfo.IsVariadic = self.IsVariadic - NewInfo.IsVariable = self.IsVariable - NewInfo.IsFunction = self.IsFunction - NewInfo.MetaList = self.MetaList - NewInfo.IsArrayPtr = self.IsArrayPtr - NewInfo.ArrayPtr = self.ArrayPtr.Copy() if self.ArrayPtr else None - NewInfo.IsState = self.IsState - NewInfo.IsDefine = self.IsDefine - NewInfo.DefineValue = self.DefineValue - NewInfo.IsInline = self.IsInline - NewInfo.InlineBody = self.InlineBody - NewInfo.InlineParams = list(self.InlineParams) if self.InlineParams else None - NewInfo._extra = dict(self._extra) + NewInfo._ts = self._ts.copy() + NewInfo._sm = self._sm.copy() + # CTypeInfo 引用字段需要深拷贝 + if isinstance(NewInfo._ts.func_ptr_return, CTypeInfo): + NewInfo._ts.func_ptr_return = NewInfo._ts.func_ptr_return.Copy() + if isinstance(NewInfo._ts.original_type, CTypeInfo): + NewInfo._ts.original_type = NewInfo._ts.original_type.Copy() + if NewInfo._ts.array_ptr: + NewInfo._ts.array_ptr = NewInfo._ts.array_ptr.Copy() + # 实例上的动态属性也需要拷贝(如 IsSigned 等) + for key, val in self.__dict__.items(): + if key not in ('_ts', '_sm'): + object.__setattr__(NewInfo, key, val) return NewInfo def get(self, key, default=None): """获取额外属性""" - return self._extra.get(key, default) + return self._sm._extra.get(key, default) def set(self, key, value): """设置额外属性""" - self._extra[key] = value + self._sm._extra[key] = value @staticmethod def VoidTypeInfo() -> "CTypeInfo": @@ -1173,7 +1172,9 @@ class CTypeInfo: return self.ToString() def __repr__(self) -> str: - return f"CTypeInfo(BaseType={self.BaseType}, PtrCount={self.PtrCount}, IsTypedef={self.IsTypedef}, OriginalType={self.OriginalType!r}, VarConst={self.VarConst}, DataConst={self.DataConst})" + ts = self._ts + kf = self._sm._kind_flags + return f"CTypeInfo(BaseType={ts._base_type}, PtrCount={ts.ptr_count}, IsTypedef={kf.get('IsTypedef', False)}, OriginalType={ts.original_type!r}, VarConst={ts.var_const}, DataConst={ts.data_const})" class CTypeHelper: diff --git a/lib/core/Handles/HandlesClassDef.py b/lib/core/Handles/HandlesClassDef.py index 9c72ecb..f8e4689 100644 --- a/lib/core/Handles/HandlesClassDef.py +++ b/lib/core/Handles/HandlesClassDef.py @@ -3,7 +3,6 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: from lib.core.translator import Translator from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta -from lib.core.SymbolNode import SymbolNode from lib.includes import t import ast import llvmlite.ir as ir @@ -658,13 +657,10 @@ class ClassHandle(BaseHandle): union_type = ir.IdentifiedStructType(Gen.module, ClassName) union_type.set_body(ir.ArrayType(ir.IntType(8), max_size)) Gen.structs[ClassName] = union_type - UnionNode = SymbolNode.CreateClass( - name=ClassName, - TypeKind='union', - lineno=Node.lineno, - file='' - ) - self.Trans.SymbolTable[ClassName] = UnionNode.attributes + UnionNode = CTypeInfo() + UnionNode.Name = ClassName + UnionNode.IsUnion = True + self.Trans.SymbolTable[ClassName] = UnionNode def _EmitREnumLlvm(self, Node, Gen): ClassName = Node.name diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index e1f08ef..c4d3913 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -567,10 +567,18 @@ class ExprCallHandle(BaseHandle): LastPart in ModuleSha1Map) # 最后尝试: 用 FuncAttr 直接查找 Gen.functions(_find_function 会遍历 SHA1 前缀) if FuncAttr and ModulePath and ModulePath not in {'t', 'c'}: + # 先检查 FuncAttr 是否是函数/变量,如果是则跳过 struct 声明 + _attr_sym = self.Trans.SymbolTable.get(FuncAttr) + _is_func_or_var = _attr_sym and (getattr(_attr_sym, 'IsFunction', False) or getattr(_attr_sym, 'IsVariable', False)) + if not _is_func_or_var and ModulePath: + _full_key = f"{ModulePath}.{FuncAttr}" + _full_sym = self.Trans.SymbolTable.get(_full_key) + if _full_sym and (getattr(_full_sym, 'IsFunction', False) or getattr(_full_sym, 'IsVariable', False)): + _is_func_or_var = True # 优先检查 FuncAttr 是否为 struct/类构造器 - if FuncAttr not in Gen.structs: + if not _is_func_or_var and FuncAttr not in Gen.structs: self._ensure_struct_declared(FuncAttr) - if FuncAttr in Gen.structs: + if not _is_func_or_var and FuncAttr in Gen.structs: result = self._HandleClassNewLlvm(Node, FuncAttr) if result is not None: return result @@ -639,6 +647,10 @@ class ExprCallHandle(BaseHandle): def _ensure_struct_declared(self, class_name): Gen = self.Trans.LlvmGen + # 如果名称是函数或变量,不应创建 struct + SymInfo = self.Trans.SymbolTable.get(class_name) + if SymInfo and (getattr(SymInfo, 'IsFunction', False) or getattr(SymInfo, 'IsVariable', False)): + return if class_name in Gen.structs: existing = Gen.structs[class_name] if isinstance(existing, ir.IdentifiedStructType) and (existing.elements is None or len(existing.elements) == 0): diff --git a/lib/core/LLVMCG/BaseGen.py b/lib/core/LLVMCG/BaseGen.py index e944925..5c80522 100644 --- a/lib/core/LLVMCG/BaseGen.py +++ b/lib/core/LLVMCG/BaseGen.py @@ -190,6 +190,10 @@ class BaseGenMixin: return ir.IntType(32) if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass: return ir.IntType(32) + if hasattr(Entry, 'IsFunction') and Entry.IsFunction: + return ir.PointerType(ir.IntType(8)) + if hasattr(Entry, 'IsVariable') and Entry.IsVariable: + return ir.PointerType(ir.IntType(8)) if hasattr(Entry, 'BaseType'): from lib.includes import t as _t if isinstance(Entry.BaseType, type) and issubclass(Entry.BaseType, _t.CEnum): diff --git a/lib/core/LLVMCG/FuncGen.py b/lib/core/LLVMCG/FuncGen.py index faadbf2..8f77325 100644 --- a/lib/core/LLVMCG/FuncGen.py +++ b/lib/core/LLVMCG/FuncGen.py @@ -2,6 +2,7 @@ from __future__ import annotations import ast import os import llvmlite.ir as ir +from lib.core.Handles.HandlesBase import CTypeInfo class FuncGenMixin: @@ -9,6 +10,9 @@ class FuncGenMixin: def setup_from_symbol_table(self, SymbolTable): self.SymbolTable = SymbolTable for name, info in SymbolTable.items(): + if isinstance(info, CTypeInfo): + # CTypeInfo 对象:struct/union 由 StructGen 处理,此处只处理 dict 格式 + continue if not isinstance(info, dict): if hasattr(info, 'get'): info = dict(info) if hasattr(info, '__iter__') else {} @@ -25,7 +29,7 @@ class FuncGenMixin: if isinstance(MemberInfo, dict): MemberType = self._type_str_to_llvm(MemberInfo.get('type', 'int'), MemberInfo.get('IsPtr', False)) self.class_members[ClassName].append((MemberName, MemberType)) - elif isinstance(MemberInfo, _CTypeInfo): + elif isinstance(MemberInfo, CTypeInfo): MemberType = self._ctype_to_llvm(MemberInfo) if MemberType is None: MemberType = self._type_str_to_llvm(MemberInfo.ToString(), MemberInfo.IsPtr) diff --git a/lib/core/SymbolNode.py b/lib/core/SymbolNode.py index d32e497..3ef6a7e 100644 --- a/lib/core/SymbolNode.py +++ b/lib/core/SymbolNode.py @@ -79,8 +79,31 @@ class SymbolNode: 'type': self.type, 'lineno': self.lineno, 'file': self.file, - **self.attributes.entry } + # 序列化 CTypeInfo 属性 + attrs = self.attributes + if attrs.BaseType: + result['BaseType'] = str(attrs.BaseType) + if attrs.PtrCount: + result['PtrCount'] = attrs.PtrCount + if attrs.IsTypedef: + result['IsTypedef'] = True + if attrs.IsStruct: + result['IsStruct'] = True + if attrs.IsEnum: + result['IsEnum'] = True + if attrs.IsUnion: + result['IsUnion'] = True + if attrs.IsFunction: + result['IsFunction'] = True + if attrs.IsVariable: + result['IsVariable'] = True + if attrs.IsDefine: + result['IsDefine'] = True + if attrs.OriginalType: + result['OriginalType'] = str(attrs.OriginalType) + if attrs._sm._extra: + result.update(attrs._sm._extra) if self.children: result['children'] = {name: child.ToDict() for name, child in self.children.items()} @@ -118,7 +141,7 @@ class SymbolNode: node.attributes.Lineno = lineno else: if TypeName is not None: - node.attributes.BaseType = CTypeInfo.create_FromTypeName(TypeName) + node.attributes.BaseType = CTypeInfo.CreateFromTypeName(TypeName) if IsPtr: node.attributes.PtrCount = 1 if dims: @@ -158,7 +181,7 @@ class SymbolNode: CTypeMember.PtrCount = max(CTypeMember.PtrCount, 1) node.attributes.Members[MemberName] = CTypeMember if TypeKind == 'struct': - node.attributes.is_struct = True + node.attributes.IsStruct = True elif TypeKind == 'enum': node.attributes.IsEnum = True elif TypeKind == 'union': @@ -198,7 +221,7 @@ class SymbolNode: if IsUnion: node.attributes.IsUnion = True else: - node.attributes.is_struct = True + node.attributes.IsStruct = True return node @classmethod diff --git a/lib/core/SymbolTable.py b/lib/core/SymbolTable.py index 8358bf3..c6626c4 100644 --- a/lib/core/SymbolTable.py +++ b/lib/core/SymbolTable.py @@ -2,7 +2,6 @@ from __future__ import annotations from typing import TYPE_CHECKING if TYPE_CHECKING: from lib.core.translator import Translator -from lib.core.SymbolNode import SymbolNode from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper from lib.includes import t from typing import Any, Dict, Iterator @@ -45,81 +44,167 @@ def _AnnotationContainsTType(node, TypeName: str) -> bool: return False -class SymbolTable: - def __init__(self, translator: "Translator"): - self.translator = translator - self._root = SymbolNode(name='root', NodeType='root') - - def clear(self): - self._root = SymbolNode(name='root', NodeType='root') - - def get(self, name: str, default=None) -> CTypeInfo: - node = self._FindNode(name) - if node: - return node.attributes - return default - - def set(self, name: str, value: Any): - self._InsertNode(name, value) - self._cached_len = -1 - - def update(self, symbols: Dict[str, Any]): - for name, value in symbols.items(): - self.set(name, value) - - def keys(self) -> Iterator[str]: - return self._CollectKeys(self._root) - - def values(self) -> Iterator[CTypeInfo]: - for node in self._CollectNodes(self._root): - yield node.attributes - - def items(self) -> Iterator[tuple[str, CTypeInfo]]: - for node in self._CollectNodes(self._root): - yield node.name, node.attributes - - def pop(self, name: str, *args) -> CTypeInfo: - node = self._FindNode(name) - if node and node.parent: - node.parent.RemoveChild(node.name) - return node.attributes - if args: - return args[0] - raise KeyError(name) - - def __getitem__(self, name: str) -> CTypeInfo: - node = self._FindNode(name) - if node: - return node.attributes - raise KeyError(name) - - def __setitem__(self, name: str, value: Any): - self.set(name, value) - - def __delitem__(self, name: str): - node = self._FindNode(name) - if node and node.parent: - node.parent.RemoveChild(node.name) - self._cached_len = -1 - else: - raise KeyError(name) - - def __contains__(self, name: str) -> bool: - return self._FindNode(name) is not None - - def __len__(self) -> int: - if not hasattr(self, '_cached_len') or self._cached_len < 0: - self._cached_len = sum(1 for _ in self._CollectNodes(self._root)) - return self._cached_len - - def __iter__(self) -> Iterator[str]: - return self.keys() - - def ToDict(self) -> Dict[str, Any]: - return self._root.ToDict() - - def FromDict(self, symbols: Dict[str, Any]): - self._root = SymbolNode.FromDict('root', symbols) +class SymbolTable: + def __init__(self, translator: "Translator"): + self.translator = translator + self._symbols: Dict[str, CTypeInfo] = {} + + def clear(self): + self._symbols.clear() + + def get(self, name: str, default=None) -> CTypeInfo: + return self._symbols.get(name, default) + + def set(self, name: str, value: Any): + if isinstance(value, CTypeInfo): + self._symbols[name] = value + else: + # 兼容旧代码传入 dict 的情况 + info = self._CTypeInfoFromDict(name, value) + self._symbols[name] = info + + def update(self, symbols: Dict[str, Any]): + for name, value in symbols.items(): + self.set(name, value) + + def keys(self) -> Iterator[str]: + return iter(self._symbols.keys()) + + def values(self) -> Iterator[CTypeInfo]: + return iter(self._symbols.values()) + + def items(self) -> Iterator[tuple[str, CTypeInfo]]: + return iter(self._symbols.items()) + + def pop(self, name: str, *args) -> CTypeInfo: + return self._symbols.pop(name, *args) + + def __getitem__(self, name: str) -> CTypeInfo: + if name in self._symbols: + return self._symbols[name] + raise KeyError(name) + + def __setitem__(self, name: str, value: Any): + self.set(name, value) + + def __delitem__(self, name: str): + del self._symbols[name] + + def __contains__(self, name: str) -> bool: + return name in self._symbols + + def __len__(self) -> int: + return len(self._symbols) + + def __iter__(self) -> Iterator[str]: + return iter(self._symbols) + + def ToDict(self) -> Dict[str, Any]: + """序列化为字典格式""" + result = {} + for name, info in self._symbols.items(): + entry = {'name': name} + if info.BaseType: + entry['BaseType'] = str(info.BaseType) + if info.PtrCount: + entry['PtrCount'] = info.PtrCount + if info.IsTypedef: + entry['IsTypedef'] = True + if info.IsStruct: + entry['IsStruct'] = True + if info.IsEnum: + entry['IsEnum'] = True + if info.IsUnion: + entry['IsUnion'] = True + if info.IsFunction: + entry['IsFunction'] = True + if info.IsVariable: + entry['IsVariable'] = True + if info.IsDefine: + entry['IsDefine'] = True + if info.OriginalType: + entry['OriginalType'] = str(info.OriginalType) + if info.Lineno: + entry['lineno'] = info.Lineno + if info.file: + entry['file'] = info.file + if info.Members: + entry['members'] = info.Members + extra = info._sm._extra + if extra: + entry.update(extra) + result[name] = entry + return result + + def FromDict(self, symbols: Dict[str, Any]): + """从字典格式反序列化""" + self._symbols.clear() + for name, attrs in symbols.items(): + if isinstance(attrs, dict): + info = self._CTypeInfoFromDict(name, attrs) + self._symbols[name] = info + elif isinstance(attrs, CTypeInfo): + self._symbols[name] = attrs + + def _CTypeInfoFromDict(self, name: str, attrs: dict) -> CTypeInfo: + """从旧 dict 格式创建 CTypeInfo(兼容旧代码)""" + info = CTypeInfo() + info.Name = name + node_type = attrs.get('type', '') + + if node_type == 'struct' or attrs.get('IsStruct'): + info.IsStruct = True + elif node_type == 'enum' or attrs.get('IsEnum'): + info.IsEnum = True + elif node_type == 'union' or attrs.get('IsUnion'): + info.IsUnion = True + elif node_type == 'typedef' or attrs.get('IsTypedef'): + info.IsTypedef = True + elif node_type == 'function' or attrs.get('IsFunction'): + info.IsFunction = True + elif node_type == 'variable' or attrs.get('IsVariable'): + info.IsVariable = True + elif node_type == 'define' or attrs.get('IsDefine'): + info.IsDefine = True + elif node_type == 'enum_member' or attrs.get('IsEnumMember'): + info.IsEnumMember = True + + if 'PtrCount' in attrs: + info.PtrCount = attrs['PtrCount'] + if 'OriginalType' in attrs: + info.OriginalType = attrs['OriginalType'] + if 'lineno' in attrs: + info.Lineno = attrs['lineno'] + if 'file' in attrs: + info.file = attrs['file'] + if 'members' in attrs: + info.Members = attrs['members'] + if 'IsPtr' in attrs: + info.IsPtr = attrs['IsPtr'] + if 'dims' in attrs: + info.ArrayDims = attrs['dims'] + if 'IsCpythonObject' in attrs: + info.IsCpythonObject = attrs['IsCpythonObject'] + if 'IsAnonymous' in attrs: + info.IsAnonymous = attrs['IsAnonymous'] + if 'IsPacked' in attrs: + info.IsPacked = attrs['IsPacked'] + if 'EnumName' in attrs: + info.EnumName = attrs['EnumName'] + if 'DefineValue' in attrs: + info.DefineValue = attrs['DefineValue'] + + # 其他属性存入 _extra + skip_keys = {'type', 'PtrCount', 'OriginalType', 'lineno', 'file', + 'members', 'IsPtr', 'dims', 'IsCpythonObject', 'IsAnonymous', + 'IsPacked', 'EnumName', 'DefineValue', + 'IsStruct', 'IsEnum', 'IsUnion', 'IsTypedef', + 'IsFunction', 'IsVariable', 'IsDefine', 'IsEnumMember'} + for key, value in attrs.items(): + if key not in skip_keys: + info.set(key, value) + + return info def LoadModuleSymbols(self, FullModulePath: str, asname: str, lineno: int = 0) -> list[str]: return self._LoadSymbolsFromFile(FullModulePath, asname, lineno) @@ -693,102 +778,70 @@ class SymbolTable: return '' def _InsertClassSymbol(self, FullName: str, TypeKind: str, lineno: int, FilePath: str, members: dict, IsCpythonObject: bool, IsPacked: bool = False): - parts = FullName.split('.') - current = self._root + info = CTypeInfo() + info.Lineno = lineno + info.file = FilePath + info.Members = members if members else {} - for i, part in enumerate(parts[:-1]): - if not current.HasChild(part): - node = SymbolNode(name=part, NodeType='namespace') - current.AddChild(node) - current = current.GetChild(part) + if TypeKind == 'struct': + info.IsStruct = True + elif TypeKind == 'union': + info.IsUnion = True + elif TypeKind == 'enum': + info.IsEnum = True + elif TypeKind == 'exception': + info.IsStruct = True + info.IsExceptionClass = True - LastPart = parts[-1] - node = SymbolNode.CreateClass( - name=LastPart, - TypeKind=TypeKind, - members=members, - lineno=lineno, - file=FilePath, - IsCpythonObject=IsCpythonObject, - IsPacked=IsPacked - ) - current.AddChild(node) + if IsCpythonObject: + info.IsCpythonObject = True + if IsPacked: + info.IsPacked = True + + self._symbols[FullName] = info def _InsertEnumMemberSymbol(self, FullName: str, EnumName: str, lineno: int, FilePath: str): - from lib.core.Handles.HandlesBase import CTypeInfo - parts = FullName.split('.') - current = self._root - - for i, part in enumerate(parts[:-1]): - if not current.HasChild(part): - node = SymbolNode(name=part, NodeType='namespace') - current.AddChild(node) - current = current.GetChild(part) - - LastPart = parts[-1] info = CTypeInfo() info.IsEnumMember = True info.EnumName = EnumName info.Lineno = lineno info.file = FilePath - node = SymbolNode(name=LastPart, NodeType='enum_member') - node.attributes = info - current.AddChild(node) - + self._symbols[FullName] = info + def _InsertTypedefSymbol(self, FullName: str, OriginalType_kind: str | None, OriginalClass, lineno: int, FilePath: str, members: dict | None = None): - parts = FullName.split('.') - current = self._root + info = CTypeInfo() + info.IsTypedef = True + info.Lineno = lineno + info.file = FilePath + if members: + info.Members = members - for i, part in enumerate(parts[:-1]): - if not current.HasChild(part): - node = SymbolNode(name=part, NodeType='namespace') - current.AddChild(node) - current = current.GetChild(part) - - LastPart = parts[-1] if isinstance(OriginalClass, CTypeInfo): - OriginalType = OriginalClass + info.OriginalType = OriginalClass elif OriginalType_kind == 'typedef' and OriginalClass and isinstance(OriginalClass, str) and ('*' in OriginalClass): OriginalType = OriginalClass if OriginalType == 'CVoid *': OriginalType = 'void *' + info.OriginalType = OriginalType elif OriginalType_kind == 'typedef' and OriginalClass == 'void': - OriginalType = 'void *' + info.OriginalType = 'void *' elif OriginalType_kind == 'typedef' and OriginalClass: - OriginalType = OriginalClass + info.OriginalType = OriginalClass elif OriginalType_kind and OriginalClass and isinstance(OriginalClass, str): - OriginalType = f'{OriginalType_kind} {OriginalClass}' + info.OriginalType = f'{OriginalType_kind} {OriginalClass}' else: - OriginalType = OriginalClass - node = SymbolNode.CreateTypedef( - name=LastPart, - OriginalType=OriginalType, - members=members, - lineno=lineno, - file=FilePath - ) - current.AddChild(node) + info.OriginalType = OriginalClass + + self._symbols[FullName] = info def _InsertModuleSymbol(self, name: str, lineno: int, FilePath: str): - node = SymbolNode.CreateModule( - name=name, - lineno=lineno, - file=FilePath - ) - self._root.AddChild(node) + info = CTypeInfo() + info.IsModuleAlias = True + info.Lineno = lineno + info.file = FilePath + self._symbols[name] = info def _InsertFuncSymbol(self, FullName: str, RetType, ParamTypes: list, lineno: int, FilePath: str, IsVariadic: bool = False, IsInline: bool = False): - parts = FullName.split('.') - current = self._root - - for i, part in enumerate(parts[:-1]): - if not current.HasChild(part): - node = SymbolNode(name=part, NodeType='namespace') - current.AddChild(node) - current = current.GetChild(part) - - LastPart = parts[-1] - from lib.core.Handles.HandlesBase import CTypeInfo info = CTypeInfo() info.IsFunction = True if isinstance(RetType, str): @@ -804,30 +857,15 @@ class SymbolTable: info.Storage = t.CInline() info.Lineno = lineno info.file = FilePath - node = SymbolNode(name=LastPart, NodeType='function') - node.attributes = info - current.AddChild(node) + self._symbols[FullName] = info def _InsertDefineSymbol(self, FullName: str, DefineValue, lineno: int, FilePath: str): - parts = FullName.split('.') - current = self._root - - for i, part in enumerate(parts[:-1]): - if not current.HasChild(part): - node = SymbolNode(name=part, NodeType='namespace') - current.AddChild(node) - current = current.GetChild(part) - - LastPart = parts[-1] - from lib.core.Handles.HandlesBase import CTypeInfo info = CTypeInfo() info.IsDefine = True info.DefineValue = DefineValue info.Lineno = lineno info.file = FilePath - node = SymbolNode(name=LastPart, NodeType='define') - node.attributes = info - current.AddChild(node) + self._symbols[FullName] = info def _eval_const_expr(self, node): """计算常量表达式的值""" @@ -882,117 +920,15 @@ class SymbolTable: return None def _InsertAnonymousSymbol(self, FullName: str, IsUnion: bool, members: dict, lineno: int, FilePath: str): - parts = FullName.split('.') - current = self._root - - for i, part in enumerate(parts[:-1]): - if not current.HasChild(part): - node = SymbolNode(name=part, NodeType='namespace') - current.AddChild(node) - current = current.GetChild(part) - - LastPart = parts[-1] - node = SymbolNode.CreateAnonymous( - name=LastPart, - IsUnion=IsUnion, - members=members, - lineno=lineno, - file=FilePath - ) - current.AddChild(node) - - def _FindNode(self, name: str) -> SymbolNode | None: - if '.' not in name: - return self._root.GetChild(name) - - parts = name.split('.') - current = self._root - - for part in parts: - if current.HasChild(part): - current = current.GetChild(part) - else: - return None - - return current - - def _InsertNode(self, name: str, attributes: dict | "CTypeInfo"): - from lib.core.Handles.HandlesBase import CTypeInfo - parts = name.split('.') - current = self._root - - for part in parts[:-1]: - if not current.HasChild(part): - node = SymbolNode(name=part, NodeType='namespace') - current.AddChild(node) - current = current.GetChild(part) - - LastPart = parts[-1] - - if isinstance(attributes, CTypeInfo): - node = SymbolNode(name=LastPart, NodeType='type', lineno=attributes.Lineno or 0) - node.attributes = attributes - current.AddChild(node) - return - - NodeType = attributes.get('type', 'unknown') - - # 根据节点类型使用相应的工厂函数 - if NodeType == 'member': - node = SymbolNode.CreateMember( - name=LastPart, - TypeName=attributes.get('type', ''), - IsPtr=attributes.get('IsPtr', False), - dims=attributes.get('dims', []), - lineno=attributes.get('lineno', 0), - file=attributes.get('file', '') - ) - elif NodeType == 'typedef': - node = SymbolNode.CreateTypedef( - name=LastPart, - OriginalType=attributes.get('OriginalType', ''), - members=attributes.get('members', None), - lineno=attributes.get('lineno', 0), - file=attributes.get('file', '') - ) - elif NodeType == 'module': - node = SymbolNode.CreateModule( - name=LastPart, - lineno=attributes.get('lineno', 0), - file=attributes.get('file', '') - ) - elif attributes.get('IsAnonymous'): - node = SymbolNode.CreateAnonymous( - name=LastPart, - IsUnion=NodeType == 'union', - members=attributes.get('members', {}), - lineno=attributes.get('lineno', 0), - file=attributes.get('file', '') - ) + info = CTypeInfo() + if IsUnion: + info.IsUnion = True else: - # 其他类型(struct, union, enum, function, variable 等) - node = SymbolNode.CreateClass( - name=LastPart, - TypeKind=NodeType, - members=attributes.get('members', None), - lineno=attributes.get('lineno', 0), - file=attributes.get('file', ''), - IsCpythonObject=attributes.get('IsCpythonObject', False) - ) - - # 设置其他属性 - for key, value in attributes.items(): - if key not in ('type', 'lineno', 'file', 'members', 'IsCpythonObject', 'IsAnonymous'): - node.set(key, value) - - current.AddChild(node) + info.IsStruct = True + info.IsAnonymous = True + info.Members = members if members else {} + info.Lineno = lineno + info.file = FilePath + self._symbols[FullName] = info - def _CollectKeys(self, node: SymbolNode) -> Iterator[str]: - for name, child in node.children.items(): - yield child.name - yield from self._CollectKeys(child) - - def _CollectNodes(self, node: SymbolNode) -> Iterator[SymbolNode]: - for child in node.children.values(): - yield child - yield from self._CollectNodes(child) + diff --git a/lib/core/Translator/AnnotationLoader.py b/lib/core/Translator/AnnotationLoader.py index 91dec3d..8d17636 100644 --- a/lib/core/Translator/AnnotationLoader.py +++ b/lib/core/Translator/AnnotationLoader.py @@ -4,7 +4,6 @@ import ast import sys import os -from lib.core.SymbolNode import SymbolNode from lib.core.Handles.HandlesBase import CTypeInfo from lib.includes import t @@ -48,28 +47,25 @@ class AnnotationLoaderMixin: # 优先检查是否是 CEnum 子类(枚举) if isinstance(attr, type) and issubclass(attr, CEnum) and attr is not CEnum: # 注册枚举类型 - EnumNode = SymbolNode.CreateClass( - name=AttrName, - TypeKind='enum', - lineno=0 - ) + EnumNode = CTypeInfo() + EnumNode.Name = AttrName + EnumNode.BaseType = t.CEnum() + EnumNode.IsEnum = True EnumNode.set('enum_class', attr) EnumNode.set('source', 'annotation_module') - EnumNode.set('library_name', lib_name) - EnumNode.set('file', source_file) - self.SymbolTable[AttrName] = EnumNode.attributes + EnumNode.library_name = lib_name + EnumNode.file = source_file + self.SymbolTable[AttrName] = EnumNode if lib_name: FullName = f'{lib_name}.{AttrName}' - full_EnumNode = SymbolNode.CreateClass( - name=FullName, - TypeKind='enum', - lineno=0 - ) + full_EnumNode = CTypeInfo() + full_EnumNode.Name = FullName + full_EnumNode.IsEnum = True full_EnumNode.set('enum_class', attr) full_EnumNode.set('source', 'annotation_module') - full_EnumNode.set('library_name', lib_name) - full_EnumNode.set('file', source_file) - self.SymbolTable[FullName] = full_EnumNode.attributes + full_EnumNode.library_name = lib_name + full_EnumNode.file = source_file + self.SymbolTable[FullName] = full_EnumNode # 枚举成员也需要注册 for MemberName in dir(attr): if not MemberName.startswith('_'): @@ -98,27 +94,23 @@ class AnnotationLoaderMixin: else: FullName = AttrName # 同时注册带前缀和不带前缀的名称(都是 typedef 别名) - TypedefNode = SymbolNode.CreateClass( - name=AttrName, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', attr().CName) + TypedefNode = CTypeInfo() + TypedefNode.Name = AttrName + TypedefNode.IsTypedef = True + TypedefNode.OriginalType = attr().CName TypedefNode.set('source', 'annotation_module') - TypedefNode.set('library_name', lib_name) - TypedefNode.set('file', source_file) - self.SymbolTable[AttrName] = TypedefNode.attributes + TypedefNode.library_name = lib_name + TypedefNode.file = source_file + self.SymbolTable[AttrName] = TypedefNode if lib_name and FullName != AttrName: - FullTypedef_node = SymbolNode.CreateClass( - name=FullName, - TypeKind='typedef', - lineno=0 - ) - FullTypedef_node.set('OriginalType', attr().CName) + FullTypedef_node = CTypeInfo() + FullTypedef_node.Name = FullName + FullTypedef_node.IsTypedef = True + FullTypedef_node.OriginalType = attr().CName FullTypedef_node.set('source', 'annotation_module') - FullTypedef_node.set('library_name', lib_name) - FullTypedef_node.set('file', source_file) - self.SymbolTable[FullName] = FullTypedef_node.attributes + FullTypedef_node.library_name = lib_name + FullTypedef_node.file = source_file + self.SymbolTable[FullName] = FullTypedef_node count += 1 # 检查是否是下划线前缀的 CType 子类(如 _CTypedef -> CTypedef) elif AttrName.startswith('_') and len(AttrName) > 1: @@ -132,27 +124,23 @@ class AnnotationLoaderMixin: FullName = f'{lib_name}.{PublicName}' else: FullName = PublicName - TypedefNode = SymbolNode.CreateClass( - name=PublicName, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', attr().CName) + TypedefNode = CTypeInfo() + TypedefNode.Name = PublicName + TypedefNode.IsTypedef = True + TypedefNode.OriginalType = attr().CName TypedefNode.set('source', 'annotation_module') - TypedefNode.set('library_name', lib_name) - TypedefNode.set('file', source_file) - self.SymbolTable[PublicName] = TypedefNode.attributes + TypedefNode.library_name = lib_name + TypedefNode.file = source_file + self.SymbolTable[PublicName] = TypedefNode if lib_name and FullName != PublicName: - FullTypedef_node = SymbolNode.CreateClass( - name=FullName, - TypeKind='typedef', - lineno=0 - ) - FullTypedef_node.set('OriginalType', attr().CName) + FullTypedef_node = CTypeInfo() + FullTypedef_node.Name = FullName + FullTypedef_node.IsTypedef = True + FullTypedef_node.OriginalType = attr().CName FullTypedef_node.set('source', 'annotation_module') - FullTypedef_node.set('library_name', lib_name) - FullTypedef_node.set('file', source_file) - self.SymbolTable[FullName] = FullTypedef_node.attributes + FullTypedef_node.library_name = lib_name + FullTypedef_node.file = source_file + self.SymbolTable[FullName] = FullTypedef_node count += 1 return count @@ -221,15 +209,13 @@ class AnnotationLoaderMixin: # 这个类继承自 CType,是 typedef 别名 # 更新符号表中的类型为 typedef if ClassName in self.SymbolTable: - TypedefNode = SymbolNode.CreateClass( - name=ClassName, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', self.SymbolTable[ClassName].get('OriginalType', f'struct {ClassName}')) + TypedefNode = CTypeInfo() + TypedefNode.Name = ClassName + TypedefNode.IsTypedef = True + TypedefNode.OriginalType = self.SymbolTable[ClassName].get('OriginalType', f'struct {ClassName}') TypedefNode.set('source', 'annotation_module') TypedefNode.set('is_ctype_subclass', True) - self.SymbolTable[ClassName] = TypedefNode.attributes + self.SymbolTable[ClassName] = TypedefNode except Exception as _e: from lib.core.VLogger import get_logger as _vlog from lib.constants.config import mode as _ConfigMode @@ -332,11 +318,9 @@ class AnnotationLoaderMixin: if orig_with_prefix in self.SymbolTable: # 添加带前缀的 typedef 别名 FullTypedef_name = f'{TypePrefix}.{TargetName}' - TypedefNode = SymbolNode.CreateClass( - name=FullTypedef_name, - TypeKind='typedef', - lineno=0 - ) + TypedefNode = CTypeInfo() + TypedefNode.Name = FullTypedef_name + TypedefNode.IsTypedef = True orig_entry = self.SymbolTable.get(orig_with_prefix, {}) orig_type_str = f'struct {original_name}' if isinstance(orig_entry, dict): @@ -348,10 +332,10 @@ class AnnotationLoaderMixin: orig_type_str = getattr(orig_entry, 'OriginalType', f'struct {original_name}') elif hasattr(orig_entry, 'IsEnum') and orig_entry.IsEnum: orig_type_str = f'enum {original_name}' - TypedefNode.set('OriginalType', orig_type_str) + TypedefNode.OriginalType = orig_type_str TypedefNode.set('source', 'annotation_module') TypedefNode.set('original_name', TargetName) - self.SymbolTable[FullTypedef_name] = TypedefNode.attributes + self.SymbolTable[FullTypedef_name] = TypedefNode count += 1 self.AnnotationModules.add(lib_name) diff --git a/lib/core/Translator/LlvmGenerator.py b/lib/core/Translator/LlvmGenerator.py index a56d18a..294bea0 100644 --- a/lib/core/Translator/LlvmGenerator.py +++ b/lib/core/Translator/LlvmGenerator.py @@ -6,7 +6,6 @@ import re import llvmlite.ir as ir from lib.core.LlvmCodeGenerator import LlvmCodeGenerator -from lib.core.SymbolNode import SymbolNode from lib.core.Handles.HandlesBase import CTypeInfo from lib.includes import t from lib.constants.config import mode as _config_mode @@ -368,15 +367,13 @@ class LlvmGeneratorMixin: if IsTypedef: TypedefKey = TypedefName if TypedefName else ClassName - TypedefNode = SymbolNode.CreateClass( - name=TypedefKey, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', f'struct {ClassName}') + TypedefNode = CTypeInfo() + TypedefNode.Name = TypedefKey + TypedefNode.IsTypedef = True + TypedefNode.OriginalType = f'struct {ClassName}' TypedefNode.set('IsComplete', True) - TypedefNode.set('file', '') - self.SymbolTable[TypedefKey] = TypedefNode.attributes + TypedefNode.file = '' + self.SymbolTable[TypedefKey] = TypedefNode for item in Node.body: if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): @@ -412,27 +409,23 @@ class LlvmGeneratorMixin: self.LogWarning(f"异常被忽略: {_e}") if not IsTypedef: - StructNode = SymbolNode.CreateClass( - name=ClassName, - TypeKind='struct', - members=members, - lineno=0 - ) - StructNode.set('file', '') + StructNode = CTypeInfo() + StructNode.Name = ClassName + StructNode.IsStruct = True + StructNode.Members = members or {} + StructNode.file = '' if ClassName in self.SymbolTable: existing = self.SymbolTable[ClassName] if hasattr(existing, 'IsCpythonObject') and existing.IsCpythonObject: - StructNode.set('IsCpythonObject', True) - self.SymbolTable[ClassName] = StructNode.attributes + StructNode.IsCpythonObject = True + self.SymbolTable[ClassName] = StructNode elif isinstance(Node, ast.FunctionDef): FuncName = Node.name - FuncNode = SymbolNode.CreateClass( - name=FuncName, - TypeKind='function', - lineno=0 - ) - FuncNode.set('file', '') - self.SymbolTable[FuncName] = FuncNode.attributes + FuncNode = CTypeInfo() + FuncNode.Name = FuncName + FuncNode.IsFunction = True + FuncNode.file = '' + self.SymbolTable[FuncName] = FuncNode elif isinstance(Node, ast.AnnAssign): if isinstance(Node.target, ast.Name): VarName = Node.target.id @@ -470,39 +463,33 @@ class LlvmGeneratorMixin: else: actual_type = 'struct' if actual_type == 'enum': - TypedefNode = SymbolNode.CreateClass( - name=VarName, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', f'enum {OriginalType}') - TypedefNode.set('file', '') - self.SymbolTable[VarName] = TypedefNode.attributes + TypedefNode = CTypeInfo() + TypedefNode.Name = VarName + TypedefNode.IsTypedef = True + TypedefNode.OriginalType = f'enum {OriginalType}' + TypedefNode.file = '' + self.SymbolTable[VarName] = TypedefNode elif actual_type == 'typedef': - TypedefNode = SymbolNode.CreateClass( - name=VarName, - TypeKind='typedef', - lineno=0 - ) + TypedefNode = CTypeInfo() + TypedefNode.Name = VarName + TypedefNode.IsTypedef = True if isinstance(OriginalInfo, dict): - TypedefNode.set('OriginalType', OriginalInfo.get('OriginalType', f'struct {OriginalType}')) + TypedefNode.OriginalType = OriginalInfo.get('OriginalType', f'struct {OriginalType}') elif isinstance(OriginalInfo, CTypeInfo) and OriginalInfo.OriginalType: - TypedefNode.set('OriginalType', OriginalInfo.OriginalType) + TypedefNode.OriginalType = OriginalInfo.OriginalType else: - TypedefNode.set('OriginalType', f'struct {OriginalType}') + TypedefNode.OriginalType = f'struct {OriginalType}' TypedefNode.set('PendingTypedef', True) - TypedefNode.set('file', '') - self.SymbolTable[VarName] = TypedefNode.attributes + TypedefNode.file = '' + self.SymbolTable[VarName] = TypedefNode else: - TypedefNode = SymbolNode.CreateClass( - name=VarName, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', f'struct {OriginalType}') + TypedefNode = CTypeInfo() + TypedefNode.Name = VarName + TypedefNode.IsTypedef = True + TypedefNode.OriginalType = f'struct {OriginalType}' TypedefNode.set('PendingTypedef', True) - TypedefNode.set('file', '') - self.SymbolTable[VarName] = TypedefNode.attributes + TypedefNode.file = '' + self.SymbolTable[VarName] = TypedefNode self.GeneratedTypes.add(VarName) continue else: @@ -522,48 +509,42 @@ class LlvmGeneratorMixin: else: actual_type = 'struct' if actual_type == 'typedef': - TypedefNode = SymbolNode.CreateClass( - name=VarName, - TypeKind='typedef', - lineno=0 - ) + TypedefNode = CTypeInfo() + TypedefNode.Name = VarName + TypedefNode.IsTypedef = True if isinstance(OriginalInfo, dict): - TypedefNode.set('OriginalType', OriginalInfo.get('OriginalType', f'struct {OriginalType}')) + TypedefNode.OriginalType = OriginalInfo.get('OriginalType', f'struct {OriginalType}') elif isinstance(OriginalInfo, CTypeInfo) and OriginalInfo.OriginalType: - TypedefNode.set('OriginalType', OriginalInfo.OriginalType) + TypedefNode.OriginalType = OriginalInfo.OriginalType else: - TypedefNode.set('OriginalType', f'struct {OriginalType}') + TypedefNode.OriginalType = f'struct {OriginalType}' TypedefNode.set('PendingTypedef', True) - TypedefNode.set('file', '') - self.SymbolTable[VarName] = TypedefNode.attributes + TypedefNode.file = '' + self.SymbolTable[VarName] = TypedefNode self.GeneratedTypes.add(VarName) if isinstance(OriginalInfo, dict): OriginalInfo['skip_generation'] = True continue elif actual_type == 'struct': - TypedefNode = SymbolNode.CreateClass( - name=VarName, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', f'struct {OriginalType}') + TypedefNode = CTypeInfo() + TypedefNode.Name = VarName + TypedefNode.IsTypedef = True + TypedefNode.OriginalType = f'struct {OriginalType}' TypedefNode.set('PendingTypedef', True) - TypedefNode.set('file', '') - self.SymbolTable[VarName] = TypedefNode.attributes + TypedefNode.file = '' + self.SymbolTable[VarName] = TypedefNode self.GeneratedTypes.add(VarName) if isinstance(OriginalInfo, dict): OriginalInfo['skip_generation'] = True continue elif actual_type == 'enum': - TypedefNode = SymbolNode.CreateClass( - name=VarName, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', f'enum {OriginalType}') + TypedefNode = CTypeInfo() + TypedefNode.Name = VarName + TypedefNode.IsTypedef = True + TypedefNode.OriginalType = f'enum {OriginalType}' TypedefNode.set('PendingTypedef', True) - TypedefNode.set('file', '') - self.SymbolTable[VarName] = TypedefNode.attributes + TypedefNode.file = '' + self.SymbolTable[VarName] = TypedefNode self.GeneratedTypes.add(VarName) if isinstance(OriginalInfo, dict): OriginalInfo['skip_generation'] = True @@ -572,14 +553,12 @@ class LlvmGeneratorMixin: from lib.core.Handles.HandlesBase import CTypeHelper CName = CTypeHelper.GetCName(Node.value.attr) if CName: - TypedefNode = SymbolNode.CreateClass( - name=VarName, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', CName) - TypedefNode.set('file', '') - self.SymbolTable[VarName] = TypedefNode.attributes + TypedefNode = CTypeInfo() + TypedefNode.Name = VarName + TypedefNode.IsTypedef = True + TypedefNode.OriginalType = CName + TypedefNode.file = '' + self.SymbolTable[VarName] = TypedefNode self.GeneratedTypes.add(VarName) continue @@ -590,14 +569,12 @@ class LlvmGeneratorMixin: except Exception as _e: if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": self.LogWarning(f"异常被忽略: {_e}") - var_node = SymbolNode.CreateClass( - name=VarName, - TypeKind='variable', - lineno=0 - ) - var_node.set('IsPtr', IsPtr) - var_node.set('file', '') - self.SymbolTable[VarName] = var_node.attributes + var_node = CTypeInfo() + var_node.Name = VarName + var_node.IsVariable = True + var_node.PtrCount = 1 if IsPtr else 0 + var_node.file = '' + self.SymbolTable[VarName] = var_node self.LlvmGen = LlvmCodeGenerator( triple=getattr(self, 'triple', None), diff --git a/lib/core/Translator/PythonParser.py b/lib/core/Translator/PythonParser.py index 2dcea13..23a09f5 100644 --- a/lib/core/Translator/PythonParser.py +++ b/lib/core/Translator/PythonParser.py @@ -7,7 +7,6 @@ import json import struct from lib.utils.helpers import DetectFileType -from lib.core.SymbolNode import SymbolNode from lib.core.Handles.HandlesBase import CTypeInfo from lib.includes import t from lib.constants.config import mode as _ConfigMode @@ -325,13 +324,11 @@ class PythonParserMixin: if IsCenum: # 注册为 enum 类型 - EnumNode = SymbolNode.CreateClass( - name=ClassName, - TypeKind='enum', - lineno=0 - ) + EnumNode = CTypeInfo() + EnumNode.Name = ClassName + EnumNode.IsEnum = True EnumNode.set('file', '') - self.SymbolTable[ClassName] = EnumNode.attributes + self.SymbolTable[ClassName] = EnumNode # 注册 enum 成员 for item in node.body: @@ -393,25 +390,21 @@ class PythonParserMixin: if _ConfigMode == "strict": raise _vlog().warning(f"解析结构体成员失败: {_e}", "Exception") - StructNode = SymbolNode.CreateClass( - name=ClassName, - TypeKind='struct', - members=members, - lineno=0, - IsCpythonObject=IsCpythonObject - ) + StructNode = CTypeInfo() + StructNode.Name = ClassName + StructNode.IsStruct = True + StructNode.Members = members or {} StructNode.set('file', '') StructNode.set('IsAnonymous', IsAnonymous) - self.SymbolTable[ClassName] = StructNode.attributes + StructNode.set('IsCpythonObject', IsCpythonObject) + self.SymbolTable[ClassName] = StructNode elif isinstance(node, ast.FunctionDef): FuncName = node.name - FuncNode = SymbolNode.CreateClass( - name=FuncName, - TypeKind='function', - lineno=0 - ) + FuncNode = CTypeInfo() + FuncNode.Name = FuncName + FuncNode.IsFunction = True FuncNode.set('file', '') - self.SymbolTable[FuncName] = FuncNode.attributes + self.SymbolTable[FuncName] = FuncNode elif isinstance(node, ast.AnnAssign): if isinstance(node.target, ast.Name): VarName = node.target.id @@ -445,14 +438,12 @@ class PythonParserMixin: if _ConfigMode == "strict": raise _vlog().warning(f"获取类型信息失败(ParsePythonFile): {_e}", "Exception") - var_node = SymbolNode.CreateClass( - name=VarName, - TypeKind='variable', - lineno=0 - ) + var_node = CTypeInfo() + var_node.Name = VarName + var_node.IsVariable = True var_node.set('IsPtr', IsPtr) var_node.set('file', '') - self.SymbolTable[VarName] = var_node.attributes + self.SymbolTable[VarName] = var_node except Exception as e: print(f'Warning: Failed to parse Python file {FilePath}: {e}') diff --git a/lib/core/TypeSpec.py b/lib/core/TypeSpec.py new file mode 100644 index 0000000..ec741fe --- /dev/null +++ b/lib/core/TypeSpec.py @@ -0,0 +1,302 @@ +"""TypeSpec, SymbolMeta, SymbolKind — CTypeInfo 的拆分类型 + +Phase 1 重构:将 CTypeInfo 的 40+ 平铺字段拆分为三个聚焦的类型: +- TypeSpec: 纯类型描述(BaseType + 指针 + 限定符 + 数组维度等) +- SymbolMeta: 符号表元数据(名称、行号、文件、类型种类、成员等) +- SymbolKind: 枚举类型种类(从 _kind_flags 派生,供新代码使用) + +设计原则: +- CTypeInfo 内部组合 TypeSpec + SymbolMeta +- 旧 property 委托到新字段,外部代码零修改 +- 渐进式迁移:先加新字段,后删旧字段 +- _kind_flags 保持独立 bool(因为 IsTypedef 和 IsStruct 可以同时为 True) +- SymbolKind 从 _kind_flags 派生,供新代码使用 +""" +from __future__ import annotations + +import enum +from typing import TYPE_CHECKING, List, Dict, Tuple, Any, Optional + +if TYPE_CHECKING: + from lib.core.Handles.HandlesBase import CTypeInfo + from lib.includes import t + + +class SymbolKind(enum.Enum): + """符号类型种类 — 从 _kind_flags 派生的主类型 + + 注意:IsTypedef 与 IsStruct/IsEnum/IsUnion 正交(可以同时为 True), + 因此 SymbolKind 只反映"主类型",IsTypedef 需要单独查询。 + """ + UNKNOWN = 0 + VARIABLE = 1 + FUNCTION = 2 + STRUCT = 3 + UNION = 4 + ENUM = 5 + DEFINE = 6 + ENUM_MEMBER = 7 + MODULE = 8 + EXCEPTION = 9 + RENUM = 10 + FUNC_PTR = 11 + STATE = 12 + CPYTHON_OBJECT = 13 + + +# CTypeInfo 旧字段 → (目标, 新字段名) 的路由表 +# 目标: 'ts' = TypeSpec, 'sm' = SymbolMeta, 'kf' = _kind_flags +FIELD_ROUTES = { + # --- TypeSpec 字段 --- + 'PtrCount': ('ts', 'ptr_count'), + 'VarConst': ('ts', 'var_const'), + 'VarVolatile': ('ts', 'var_volatile'), + 'DataConst': ('ts', 'data_const'), + 'DataVolatile': ('ts', 'data_volatile'), + 'ArrayDims': ('ts', 'array_dims'), + 'Storage': ('ts', 'storage'), + 'IsFuncPtr': ('ts', 'is_func_ptr'), + 'FuncPtrParams': ('ts', 'func_ptr_params'), + 'FuncParamNames': ('ts', 'func_param_names'), + 'FuncPtrReturn': ('ts', 'func_ptr_return'), + 'IsVariadic': ('ts', 'is_variadic'), + 'IsBitField': ('ts', 'is_bitfield'), + 'BitWidth': ('ts', 'bit_width'), + 'ByteOrder': ('ts', 'byte_order'), + 'IsArrayPtr': ('ts', 'is_array_ptr'), + 'ArrayPtr': ('ts', 'array_ptr'), + 'IsState': ('ts', 'is_state'), + 'OriginalType': ('ts', 'original_type'), + + # --- SymbolMeta 字段 --- + 'Name': ('sm', 'name'), + 'Lineno': ('sm', 'lineno'), + 'file': ('sm', 'file'), + 'ModuleName': ('sm', 'module_name'), + 'Members': ('sm', 'members'), + 'IsCpythonObject':('sm', 'is_cpython_object'), + 'IsPacked': ('sm', 'is_packed'), + 'IsAnonymous': ('sm', 'is_anonymous'), + 'IsInline': ('sm', 'is_inline'), + 'InlineBody': ('sm', 'inline_body'), + 'InlineParams': ('sm', 'inline_params'), + 'RenumVariants': ('sm', 'renum_variants'), + 'DeclaredType': ('sm', 'declared_type'), + 'CreturnTypes': ('sm', 'creturn_types'), + 'MetaList': ('sm', 'meta_list'), + 'IsModuleAlias': ('sm', 'is_module_alias'), + 'ResolvedModule': ('sm', 'resolved_module'), + 'DefineValue': ('sm', 'define_value'), + + # --- _kind_flags(独立 bool,存储在 SymbolMeta._kind_flags)--- + 'IsStruct': ('kf', 'IsStruct'), + 'IsEnum': ('kf', 'IsEnum'), + 'IsUnion': ('kf', 'IsUnion'), + 'IsTypedef': ('kf', 'IsTypedef'), + 'IsVariable': ('kf', 'IsVariable'), + 'IsFunction': ('kf', 'IsFunction'), + 'IsDefine': ('kf', 'IsDefine'), + 'IsEnumMember': ('kf', 'IsEnumMember'), + 'IsRenum': ('kf', 'IsRenum'), + 'IsExceptionClass': ('kf', 'IsExceptionClass'), + + # --- _extra(CTypeInfo 旧 _extra 字典,迁移到 SymbolMeta)--- + '_extra': ('sm', '_extra'), +} + + +class TypeSpec: + """纯类型描述 — 不包含符号表元数据 + + 职责:描述一个 C 类型的结构(基础类型、指针层数、限定符、数组维度等) + 不包含:名称、行号、文件路径、符号种类等元数据(这些归 SymbolMeta) + + 注意:当前阶段保持与 CTypeInfo 旧字段的兼容性, + PtrCount/VarConst/DataConst 等仍然使用扁平字段。 + 未来 Phase 2 会将指针改为嵌套 PointerLayer 表示。 + """ + + __slots__ = ( + '_base_type', 'ptr_count', + 'var_const', 'var_volatile', 'data_const', 'data_volatile', + 'array_dims', 'storage', + 'is_func_ptr', 'func_ptr_params', 'func_param_names', 'func_ptr_return', + 'is_variadic', + 'is_bitfield', 'bit_width', + 'byte_order', + 'is_array_ptr', 'array_ptr', + 'is_state', + 'original_type', + ) + + def __init__(self): + self._base_type: Any = None # t.CType 实例或 tuple + self.ptr_count: int = 0 + self.var_const: bool = False + self.var_volatile: bool = False + self.data_const: bool = False + self.data_volatile: bool = False + self.array_dims: List[str] = [] + self.storage: Any = None # t.CType (CStatic/CExtern/CExport 等) + self.is_func_ptr: bool = False + self.func_ptr_params: List[Tuple[str, Any]] = [] # (参数名, CTypeInfo) + self.func_param_names: List[str] = [] + self.func_ptr_return: Any = None # CTypeInfo + self.is_variadic: bool = False + self.is_bitfield: bool = False + self.bit_width: int = 0 + self.byte_order: str = "" # "big", "little", or "" + self.is_array_ptr: bool = False + self.array_ptr: Any = None # CTypeInfo + self.is_state: bool = False + self.original_type: Any = None # CTypeInfo | str | None (typedef 原始类型) + + @property + def base_type(self) -> Any: + return self._base_type + + @base_type.setter + def base_type(self, value: Any): + """设置 BaseType,与 CTypeInfo.BaseType setter 逻辑一致(不含 kind 副作用)""" + from lib.includes import t + + if value is None: + self._base_type = None + return + + if isinstance(value, (tuple, list)): + self._base_type = tuple(value) + return + + if isinstance(value, type) and issubclass(value, t.CType): + self._base_type = value() + return + + if isinstance(value, t.CType): + self._base_type = value + return + + raise TypeError( + f"base_type must be t.CType instance, type subclass, or tuple of t.CType, got {type(value)}" + ) + + def copy(self) -> TypeSpec: + """深拷贝""" + new = TypeSpec() + new._base_type = self._base_type + new.ptr_count = self.ptr_count + new.var_const = self.var_const + new.var_volatile = self.var_volatile + new.data_const = self.data_const + new.data_volatile = self.data_volatile + new.array_dims = list(self.array_dims) + new.storage = self.storage + new.is_func_ptr = self.is_func_ptr + new.func_ptr_params = list(self.func_ptr_params) + new.func_param_names = list(self.func_param_names) + new.func_ptr_return = self.func_ptr_return + new.is_variadic = self.is_variadic + new.is_bitfield = self.is_bitfield + new.bit_width = self.bit_width + new.byte_order = self.byte_order + new.is_array_ptr = self.is_array_ptr + new.array_ptr = self.array_ptr + new.is_state = self.is_state + new.original_type = self.original_type + return new + + +class SymbolMeta: + """符号表条目的元数据 — 与类型描述无关 + + 职责:记录符号的名称、位置、种类、成员等元数据 + 不包含:类型结构(BaseType、指针、限定符等,这些归 TypeSpec) + + _kind_flags: 独立 bool 字典,存储 IsStruct/IsEnum/IsTypedef 等。 + 这些 flag 不是互斥的(IsTypedef 和 IsStruct 可以同时为 True)。 + SymbolKind 从 _kind_flags 派生,供新代码使用。 + """ + + __slots__ = ( + 'name', 'lineno', 'file', 'module_name', + 'members', + 'is_cpython_object', 'is_packed', + 'define_value', + 'is_inline', 'inline_body', 'inline_params', + 'is_anonymous', + 'renum_variants', + 'declared_type', 'creturn_types', + 'meta_list', + 'is_module_alias', 'resolved_module', + '_kind_flags', + '_extra', + ) + + def __init__(self): + self.name: str = "" + self.lineno: int = 0 + self.file: str = "" + self.module_name: str = "" + self.members: Dict[str, Any] = {} # 成员名 -> CTypeInfo + self.is_cpython_object: bool = False + self.is_packed: bool = False + self.define_value: Any = None + self.is_inline: bool = False + self.inline_body: list | None = None + self.inline_params: list | None = None + self.is_anonymous: bool = False + self.renum_variants: list = [] + self.declared_type: str = "" + self.creturn_types: list = [] + self.meta_list: Any = None # FuncMeta + self.is_module_alias: bool = False + self.resolved_module: str | None = None + self._kind_flags: Dict[str, bool] = {} # IsStruct/IsEnum/IsTypedef 等 + self._extra: dict = {} + + @property + def kind(self) -> SymbolKind: + """从 _kind_flags 派生主类型种类""" + kf = self._kind_flags + if kf.get('IsStruct') or self.is_cpython_object: + return SymbolKind.STRUCT if not self.is_cpython_object else SymbolKind.CPYTHON_OBJECT + if kf.get('IsEnum'): + return SymbolKind.RENUM if kf.get('IsRenum') else SymbolKind.ENUM + if kf.get('IsUnion'): + return SymbolKind.UNION + if kf.get('IsFunction'): + return SymbolKind.FUNCTION + if kf.get('IsVariable'): + return SymbolKind.VARIABLE + if kf.get('IsDefine'): + return SymbolKind.DEFINE + if kf.get('IsEnumMember'): + return SymbolKind.ENUM_MEMBER + if kf.get('IsExceptionClass'): + return SymbolKind.EXCEPTION + return SymbolKind.UNKNOWN + + def copy(self) -> SymbolMeta: + """深拷贝""" + new = SymbolMeta() + new.name = self.name + new.lineno = self.lineno + new.file = self.file + new.module_name = self.module_name + new.members = dict(self.members) + new.is_cpython_object = self.is_cpython_object + new.is_packed = self.is_packed + new.define_value = self.define_value + new.is_inline = self.is_inline + new.inline_body = self.inline_body + new.inline_params = list(self.inline_params) if self.inline_params else None + new.is_anonymous = self.is_anonymous + new.renum_variants = list(self.renum_variants) + new.declared_type = self.declared_type + new.creturn_types = list(self.creturn_types) + new.meta_list = self.meta_list + new.is_module_alias = self.is_module_alias + new.resolved_module = self.resolved_module + new._kind_flags = dict(self._kind_flags) + new._extra = dict(self._extra) + return new