阶段 2 完成
This commit is contained in:
1
TODO
1
TODO
@@ -4,3 +4,4 @@ main 收集
|
|||||||
元类型
|
元类型
|
||||||
@p.set
|
@p.set
|
||||||
函数的描述符用装饰器而不是返回值
|
函数的描述符用装饰器而不是返回值
|
||||||
|
崩溃/返回作用域 回调
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
1
Test/test_out.txt
Normal file
1
Test/test_out.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
UnicodeEncodeError: 'gbk' codec can't encode character '\ufffd' in position 3: illegal multibyte sequence
|
||||||
1
Test/test_output.txt
Normal file
1
Test/test_output.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
======================================================================
|
||||||
@@ -8,6 +8,7 @@ from lib.includes import t
|
|||||||
import ast
|
import ast
|
||||||
from typing import List, Dict
|
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 = {
|
EXCEPTION_CODE_MAP = {
|
||||||
@@ -66,57 +67,72 @@ class CTypeInfo:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._BaseType: t.CType = None
|
object.__setattr__(self, '_ts', TypeSpec())
|
||||||
self.PtrCount: int = 0
|
sm = SymbolMeta()
|
||||||
self.VarConst: bool = False
|
sm.meta_list = FuncMeta.NONE
|
||||||
self.VarVolatile: bool = False
|
object.__setattr__(self, '_sm', sm)
|
||||||
self.DataConst: bool = False
|
|
||||||
self.DataVolatile: bool = False
|
# --- 新公共 API:供新代码直接访问 TypeSpec / SymbolMeta / SymbolKind ---
|
||||||
self.ArrayDims: List[str] = []
|
@property
|
||||||
self.Storage: t.CType = None
|
def ts(self) -> TypeSpec:
|
||||||
self.IsFuncPtr: bool = False
|
"""TypeSpec — 纯类型描述(只读)"""
|
||||||
self.FuncPtrParams: List[Tuple[str, 'CTypeInfo']] = [] # 函数指针参数列表:(参数名, 参数类型)
|
return self._ts
|
||||||
self.FuncParamNames: List[str] = [] # 函数参数名列表
|
|
||||||
self.FuncPtrReturn: "CTypeInfo" = None
|
@property
|
||||||
self.IsBitField: bool = False
|
def sm(self) -> SymbolMeta:
|
||||||
self.BitWidth: int = 0
|
"""SymbolMeta — 符号表元数据(只读)"""
|
||||||
self.ByteOrder: str = "" # "big", "little", or ""
|
return self._sm
|
||||||
self.IsTypedef: bool = False
|
|
||||||
self.IsStruct: bool = False
|
@property
|
||||||
self.IsEnum: bool = False
|
def kind(self) -> 'SymbolKind':
|
||||||
self.IsUnion: bool = False
|
"""SymbolKind — 符号类型种类枚举"""
|
||||||
self.IsRenum: bool = False
|
return self._sm.kind
|
||||||
self.RenumVariants: list = []
|
|
||||||
self.Name: str = ""
|
def __setattr__(self, name, value):
|
||||||
self.Members: Dict[str, 'CTypeInfo'] = {}
|
"""属性设置路由 — 将旧字段名委托到 _ts/_sm/_kind_flags"""
|
||||||
self.OriginalType: "CTypeInfo" = None
|
if name == 'BaseType':
|
||||||
self.DeclaredType: str = ""
|
# BaseType 有复杂的 property setter(自动设置 IsStruct/IsEnum/IsUnion)
|
||||||
self.CreturnTypes: list = []
|
CTypeInfo.BaseType.fset(self, value)
|
||||||
self.Lineno: int = 0
|
return
|
||||||
self.file: str = ""
|
if name in ('_ts', '_sm', 'ts', 'sm', 'kind'):
|
||||||
self.IsAnonymous: bool = False
|
# _ts/_sm 内部字段直接设置;ts/sm/kind 是只读 property,禁止设置
|
||||||
self.IsCpythonObject: bool = False
|
if name in ('ts', 'sm', 'kind'):
|
||||||
self.IsEnumMember: bool = False
|
raise AttributeError(f"'CTypeInfo' attribute '{name}' is read-only")
|
||||||
self.IsVariadic: bool = False
|
object.__setattr__(self, name, value)
|
||||||
self.IsVariable: bool = False
|
return
|
||||||
self.IsFunction: bool = False
|
if name in FIELD_ROUTES:
|
||||||
self.MetaList: FuncMeta = FuncMeta.NONE
|
target, field = FIELD_ROUTES[name]
|
||||||
self.IsArrayPtr: bool = False
|
if target == 'ts':
|
||||||
self.ArrayPtr: 'CTypeInfo' = None
|
setattr(self._ts, field, value)
|
||||||
self.IsState: bool = False
|
elif target == 'sm':
|
||||||
self.IsDefine: bool = False
|
setattr(self._sm, field, value)
|
||||||
self.DefineValue = None
|
elif target == 'kf':
|
||||||
self.IsInline: bool = False
|
self._sm._kind_flags[field] = value
|
||||||
self.InlineBody: list = None
|
return
|
||||||
self.InlineParams: list = None
|
object.__setattr__(self, name, value)
|
||||||
self.ModuleName: str = ""
|
|
||||||
self._extra: dict = {}
|
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
|
@property
|
||||||
def BaseType(self) -> t.CType | tuple:
|
def BaseType(self) -> t.CType | tuple:
|
||||||
return self._BaseType
|
return self._ts._base_type
|
||||||
|
|
||||||
@BaseType.setter
|
@BaseType.setter
|
||||||
def BaseType(self, value: t.CType | type | tuple | List):
|
def BaseType(self, value: t.CType | type | tuple | List):
|
||||||
@@ -127,54 +143,57 @@ class CTypeInfo:
|
|||||||
- type (CType 子类): 如 t.CStruct,自动实例化
|
- type (CType 子类): 如 t.CStruct,自动实例化
|
||||||
- tuple/list of t.CType: 多个组合类型
|
- tuple/list of t.CType: 多个组合类型
|
||||||
"""
|
"""
|
||||||
|
ts = self._ts
|
||||||
|
kf = self._sm._kind_flags
|
||||||
|
|
||||||
if value is None:
|
if value is None:
|
||||||
self._BaseType = None
|
ts._base_type = None
|
||||||
self.IsStruct = False
|
kf['IsStruct'] = False
|
||||||
self.IsEnum = False
|
kf['IsEnum'] = False
|
||||||
self.IsUnion = False
|
kf['IsUnion'] = False
|
||||||
self.IsRenum = False
|
kf['IsRenum'] = False
|
||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(value, (tuple, list)):
|
if isinstance(value, (tuple, list)):
|
||||||
self._BaseType = tuple(value)
|
ts._base_type = tuple(value)
|
||||||
for v in value:
|
for v in value:
|
||||||
if isinstance(v, t.CStruct):
|
if isinstance(v, t.CStruct):
|
||||||
self.IsStruct = True
|
kf['IsStruct'] = True
|
||||||
elif isinstance(v, t.CEnum):
|
elif isinstance(v, t.CEnum):
|
||||||
self.IsEnum = True
|
kf['IsEnum'] = True
|
||||||
elif isinstance(v, t.CUnion):
|
elif isinstance(v, t.CUnion):
|
||||||
self.IsUnion = True
|
kf['IsUnion'] = True
|
||||||
elif isinstance(v, t.REnum):
|
elif isinstance(v, t.REnum):
|
||||||
self.IsRenum = True
|
kf['IsRenum'] = True
|
||||||
self.IsEnum = True
|
kf['IsEnum'] = True
|
||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(value, type) and issubclass(value, t.CType):
|
if isinstance(value, type) and issubclass(value, t.CType):
|
||||||
self._BaseType = value()
|
ts._base_type = value()
|
||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(value, t.CType):
|
if isinstance(value, t.CType):
|
||||||
self._BaseType = value
|
ts._base_type = value
|
||||||
if isinstance(value, t.CStruct):
|
if isinstance(value, t.CStruct):
|
||||||
self.IsStruct = True
|
kf['IsStruct'] = True
|
||||||
self.IsEnum = False
|
kf['IsEnum'] = False
|
||||||
self.IsUnion = False
|
kf['IsUnion'] = False
|
||||||
self.IsRenum = False
|
kf['IsRenum'] = False
|
||||||
elif isinstance(value, t.REnum):
|
elif isinstance(value, t.REnum):
|
||||||
self.IsRenum = True
|
kf['IsRenum'] = True
|
||||||
self.IsEnum = True
|
kf['IsEnum'] = True
|
||||||
self.IsStruct = False
|
kf['IsStruct'] = False
|
||||||
self.IsUnion = False
|
kf['IsUnion'] = False
|
||||||
elif isinstance(value, t.CEnum):
|
elif isinstance(value, t.CEnum):
|
||||||
self.IsEnum = True
|
kf['IsEnum'] = True
|
||||||
self.IsStruct = False
|
kf['IsStruct'] = False
|
||||||
self.IsUnion = False
|
kf['IsUnion'] = False
|
||||||
self.IsRenum = False
|
kf['IsRenum'] = False
|
||||||
elif isinstance(value, t.CUnion):
|
elif isinstance(value, t.CUnion):
|
||||||
self.IsUnion = True
|
kf['IsUnion'] = True
|
||||||
self.IsStruct = False
|
kf['IsStruct'] = False
|
||||||
self.IsEnum = False
|
kf['IsEnum'] = False
|
||||||
self.IsRenum = False
|
kf['IsRenum'] = False
|
||||||
return
|
return
|
||||||
|
|
||||||
raise TypeError(f"BaseType must be t.CType instance, type subclass, or tuple of t.CType, got {type(value)}")
|
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
|
@property
|
||||||
def TypeCls(self):
|
def TypeCls(self):
|
||||||
"""获取 CType 类(从 BaseType 推断)"""
|
"""获取 CType 类(从 BaseType 推断)"""
|
||||||
if self.BaseType:
|
bt = self._ts._base_type
|
||||||
return type(self.BaseType)
|
if bt:
|
||||||
if self.IsStruct:
|
return type(bt)
|
||||||
|
kf = self._sm._kind_flags
|
||||||
|
if kf.get('IsStruct'):
|
||||||
return t.CStruct
|
return t.CStruct
|
||||||
if self.IsEnum:
|
if kf.get('IsEnum'):
|
||||||
return t.CEnum
|
return t.CEnum
|
||||||
if self.IsUnion:
|
if kf.get('IsUnion'):
|
||||||
return t.CUnion
|
return t.CUnion
|
||||||
if self.IsTypedef:
|
if kf.get('IsTypedef'):
|
||||||
return t._CTypedef
|
return t._CTypedef
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def IsPtr(self) -> bool:
|
def IsPtr(self) -> bool:
|
||||||
return self.PtrCount > 0
|
return self._ts.ptr_count > 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def IsVoid(self) -> bool:
|
def IsVoid(self) -> bool:
|
||||||
return isinstance(self.BaseType, t.CVoid)
|
return isinstance(self._ts._base_type, t.CVoid)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def IsStr(self) -> bool:
|
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
|
@property
|
||||||
def IsInt(self) -> bool:
|
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
|
@property
|
||||||
def IsUInt(self) -> bool:
|
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
|
@property
|
||||||
def IsFloat(self) -> bool:
|
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)
|
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
|
@property
|
||||||
def IsDouble(self) -> bool:
|
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
|
@property
|
||||||
def IsPointerToChar(self) -> bool:
|
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:
|
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'
|
return 'Callable'
|
||||||
parts = []
|
parts = []
|
||||||
|
|
||||||
if self.Storage and not isinstance(self.Storage, t.CExport):
|
if ts.storage and not isinstance(ts.storage, t.CExport):
|
||||||
parts.append(self.Storage.CName)
|
parts.append(ts.storage.CName)
|
||||||
|
|
||||||
if self.DataConst or self.DataVolatile:
|
if ts.data_const or ts.data_volatile:
|
||||||
qualifiers = []
|
qualifiers = []
|
||||||
if self.DataConst:
|
if ts.data_const:
|
||||||
qualifiers.append("const")
|
qualifiers.append("const")
|
||||||
if self.DataVolatile:
|
if ts.data_volatile:
|
||||||
qualifiers.append("volatile")
|
qualifiers.append("volatile")
|
||||||
parts.append("_".join(qualifiers))
|
parts.append("_".join(qualifiers))
|
||||||
|
|
||||||
if self.IsTypedef and self.Name:
|
if kf.get('IsTypedef') and sm.name:
|
||||||
return self.Name
|
return sm.name
|
||||||
elif self.IsRenum and self.Name:
|
elif kf.get('IsRenum') and sm.name:
|
||||||
base_name = self.Name
|
base_name = sm.name
|
||||||
elif self.BaseType:
|
elif bt:
|
||||||
base_name = getattr(self.BaseType, 'CName', None) or (self.BaseType if isinstance(self.BaseType, str) else str(self.BaseType))
|
base_name = getattr(bt, 'CName', None) or (bt if isinstance(bt, str) else str(bt))
|
||||||
else:
|
else:
|
||||||
base_name = "void"
|
base_name = "void"
|
||||||
|
|
||||||
if self.IsArrayPtr:
|
if ts.is_array_ptr:
|
||||||
ptr_str = ""
|
ptr_str = ""
|
||||||
if self.PtrCount > 0:
|
if ts.ptr_count > 0:
|
||||||
ptr_str = "*" * self.PtrCount
|
ptr_str = "*" * ts.ptr_count
|
||||||
if self.ArrayPtr:
|
if ts.array_ptr:
|
||||||
inner = self.ArrayPtr.ToString()
|
inner = ts.array_ptr.ToString()
|
||||||
if ptr_str:
|
if ptr_str:
|
||||||
parts.append(f"{base_name} {ptr_str}({inner})")
|
parts.append(f"{base_name} {ptr_str}({inner})")
|
||||||
else:
|
else:
|
||||||
@@ -267,22 +296,22 @@ class CTypeInfo:
|
|||||||
parts.append(f"{base_name} {ptr_str}()")
|
parts.append(f"{base_name} {ptr_str}()")
|
||||||
else:
|
else:
|
||||||
parts.append(f"{base_name} ()")
|
parts.append(f"{base_name} ()")
|
||||||
elif self.ArrayPtr:
|
elif ts.array_ptr:
|
||||||
inner = self.ArrayPtr.ToString()
|
inner = ts.array_ptr.ToString()
|
||||||
if self.PtrCount > 0:
|
if ts.ptr_count > 0:
|
||||||
parts.append(f"{base_name} {'*' * self.PtrCount}({inner})")
|
parts.append(f"{base_name} {'*' * ts.ptr_count}({inner})")
|
||||||
else:
|
else:
|
||||||
parts.append(f"{base_name} ({inner})")
|
parts.append(f"{base_name} ({inner})")
|
||||||
else:
|
else:
|
||||||
parts.append(base_name)
|
parts.append(base_name)
|
||||||
if self.PtrCount > 0:
|
if ts.ptr_count > 0:
|
||||||
parts.append("*" * self.PtrCount)
|
parts.append("*" * ts.ptr_count)
|
||||||
if self.VarConst:
|
if ts.var_const:
|
||||||
parts.append("const")
|
parts.append("const")
|
||||||
if self.VarVolatile:
|
if ts.var_volatile:
|
||||||
parts.append("volatile")
|
parts.append("volatile")
|
||||||
|
|
||||||
for dim in self.ArrayDims:
|
for dim in ts.array_dims:
|
||||||
if dim:
|
if dim:
|
||||||
parts.append(f"[{dim}]")
|
parts.append(f"[{dim}]")
|
||||||
else:
|
else:
|
||||||
@@ -1098,58 +1127,28 @@ class CTypeInfo:
|
|||||||
|
|
||||||
def Copy(self) -> "CTypeInfo":
|
def Copy(self) -> "CTypeInfo":
|
||||||
NewInfo = CTypeInfo()
|
NewInfo = CTypeInfo()
|
||||||
NewInfo.BaseType = self.BaseType
|
NewInfo._ts = self._ts.copy()
|
||||||
NewInfo.PtrCount = self.PtrCount
|
NewInfo._sm = self._sm.copy()
|
||||||
NewInfo.VarConst = self.VarConst
|
# CTypeInfo 引用字段需要深拷贝
|
||||||
NewInfo.VarVolatile = self.VarVolatile
|
if isinstance(NewInfo._ts.func_ptr_return, CTypeInfo):
|
||||||
NewInfo.DataConst = self.DataConst
|
NewInfo._ts.func_ptr_return = NewInfo._ts.func_ptr_return.Copy()
|
||||||
NewInfo.DataVolatile = self.DataVolatile
|
if isinstance(NewInfo._ts.original_type, CTypeInfo):
|
||||||
NewInfo.ArrayDims = list(self.ArrayDims)
|
NewInfo._ts.original_type = NewInfo._ts.original_type.Copy()
|
||||||
NewInfo.Storage = self.Storage
|
if NewInfo._ts.array_ptr:
|
||||||
NewInfo.IsFuncPtr = self.IsFuncPtr
|
NewInfo._ts.array_ptr = NewInfo._ts.array_ptr.Copy()
|
||||||
NewInfo.FuncPtrParams = list(self.FuncPtrParams)
|
# 实例上的动态属性也需要拷贝(如 IsSigned 等)
|
||||||
NewInfo.FuncParamNames = list(self.FuncParamNames)
|
for key, val in self.__dict__.items():
|
||||||
NewInfo.FuncPtrReturn = self.FuncPtrReturn.Copy() if isinstance(self.FuncPtrReturn, CTypeInfo) else self.FuncPtrReturn
|
if key not in ('_ts', '_sm'):
|
||||||
NewInfo.IsBitField = self.IsBitField
|
object.__setattr__(NewInfo, key, val)
|
||||||
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)
|
|
||||||
return NewInfo
|
return NewInfo
|
||||||
|
|
||||||
def get(self, key, default=None):
|
def get(self, key, default=None):
|
||||||
"""获取额外属性"""
|
"""获取额外属性"""
|
||||||
return self._extra.get(key, default)
|
return self._sm._extra.get(key, default)
|
||||||
|
|
||||||
def set(self, key, value):
|
def set(self, key, value):
|
||||||
"""设置额外属性"""
|
"""设置额外属性"""
|
||||||
self._extra[key] = value
|
self._sm._extra[key] = value
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def VoidTypeInfo() -> "CTypeInfo":
|
def VoidTypeInfo() -> "CTypeInfo":
|
||||||
@@ -1173,7 +1172,9 @@ class CTypeInfo:
|
|||||||
return self.ToString()
|
return self.ToString()
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
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:
|
class CTypeHelper:
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from typing import TYPE_CHECKING
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from lib.core.translator import Translator
|
from lib.core.translator import Translator
|
||||||
from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta
|
from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta
|
||||||
from lib.core.SymbolNode import SymbolNode
|
|
||||||
from lib.includes import t
|
from lib.includes import t
|
||||||
import ast
|
import ast
|
||||||
import llvmlite.ir as ir
|
import llvmlite.ir as ir
|
||||||
@@ -658,13 +657,10 @@ class ClassHandle(BaseHandle):
|
|||||||
union_type = ir.IdentifiedStructType(Gen.module, ClassName)
|
union_type = ir.IdentifiedStructType(Gen.module, ClassName)
|
||||||
union_type.set_body(ir.ArrayType(ir.IntType(8), max_size))
|
union_type.set_body(ir.ArrayType(ir.IntType(8), max_size))
|
||||||
Gen.structs[ClassName] = union_type
|
Gen.structs[ClassName] = union_type
|
||||||
UnionNode = SymbolNode.CreateClass(
|
UnionNode = CTypeInfo()
|
||||||
name=ClassName,
|
UnionNode.Name = ClassName
|
||||||
TypeKind='union',
|
UnionNode.IsUnion = True
|
||||||
lineno=Node.lineno,
|
self.Trans.SymbolTable[ClassName] = UnionNode
|
||||||
file='<stdin>'
|
|
||||||
)
|
|
||||||
self.Trans.SymbolTable[ClassName] = UnionNode.attributes
|
|
||||||
|
|
||||||
def _EmitREnumLlvm(self, Node, Gen):
|
def _EmitREnumLlvm(self, Node, Gen):
|
||||||
ClassName = Node.name
|
ClassName = Node.name
|
||||||
|
|||||||
@@ -567,10 +567,18 @@ class ExprCallHandle(BaseHandle):
|
|||||||
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 声明
|
||||||
|
_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/类构造器
|
# 优先检查 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)
|
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)
|
result = self._HandleClassNewLlvm(Node, FuncAttr)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
return result
|
return result
|
||||||
@@ -639,6 +647,10 @@ 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
|
||||||
|
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:
|
if class_name in Gen.structs:
|
||||||
existing = Gen.structs[class_name]
|
existing = Gen.structs[class_name]
|
||||||
if isinstance(existing, ir.IdentifiedStructType) and (existing.elements is None or len(existing.elements) == 0):
|
if isinstance(existing, ir.IdentifiedStructType) and (existing.elements is None or len(existing.elements) == 0):
|
||||||
|
|||||||
@@ -190,6 +190,10 @@ class BaseGenMixin:
|
|||||||
return ir.IntType(32)
|
return ir.IntType(32)
|
||||||
if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass:
|
if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass:
|
||||||
return ir.IntType(32)
|
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'):
|
if hasattr(Entry, 'BaseType'):
|
||||||
from lib.includes import t as _t
|
from lib.includes import t as _t
|
||||||
if isinstance(Entry.BaseType, type) and issubclass(Entry.BaseType, _t.CEnum):
|
if isinstance(Entry.BaseType, type) and issubclass(Entry.BaseType, _t.CEnum):
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|||||||
import ast
|
import ast
|
||||||
import os
|
import os
|
||||||
import llvmlite.ir as ir
|
import llvmlite.ir as ir
|
||||||
|
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||||
|
|
||||||
|
|
||||||
class FuncGenMixin:
|
class FuncGenMixin:
|
||||||
@@ -9,6 +10,9 @@ class FuncGenMixin:
|
|||||||
def setup_from_symbol_table(self, SymbolTable):
|
def setup_from_symbol_table(self, SymbolTable):
|
||||||
self.SymbolTable = SymbolTable
|
self.SymbolTable = SymbolTable
|
||||||
for name, info in SymbolTable.items():
|
for name, info in SymbolTable.items():
|
||||||
|
if isinstance(info, CTypeInfo):
|
||||||
|
# CTypeInfo 对象:struct/union 由 StructGen 处理,此处只处理 dict 格式
|
||||||
|
continue
|
||||||
if not isinstance(info, dict):
|
if not isinstance(info, dict):
|
||||||
if hasattr(info, 'get'):
|
if hasattr(info, 'get'):
|
||||||
info = dict(info) if hasattr(info, '__iter__') else {}
|
info = dict(info) if hasattr(info, '__iter__') else {}
|
||||||
@@ -25,7 +29,7 @@ class FuncGenMixin:
|
|||||||
if isinstance(MemberInfo, dict):
|
if isinstance(MemberInfo, dict):
|
||||||
MemberType = self._type_str_to_llvm(MemberInfo.get('type', 'int'), MemberInfo.get('IsPtr', False))
|
MemberType = self._type_str_to_llvm(MemberInfo.get('type', 'int'), MemberInfo.get('IsPtr', False))
|
||||||
self.class_members[ClassName].append((MemberName, MemberType))
|
self.class_members[ClassName].append((MemberName, MemberType))
|
||||||
elif isinstance(MemberInfo, _CTypeInfo):
|
elif isinstance(MemberInfo, CTypeInfo):
|
||||||
MemberType = self._ctype_to_llvm(MemberInfo)
|
MemberType = self._ctype_to_llvm(MemberInfo)
|
||||||
if MemberType is None:
|
if MemberType is None:
|
||||||
MemberType = self._type_str_to_llvm(MemberInfo.ToString(), MemberInfo.IsPtr)
|
MemberType = self._type_str_to_llvm(MemberInfo.ToString(), MemberInfo.IsPtr)
|
||||||
|
|||||||
@@ -79,8 +79,31 @@ class SymbolNode:
|
|||||||
'type': self.type,
|
'type': self.type,
|
||||||
'lineno': self.lineno,
|
'lineno': self.lineno,
|
||||||
'file': self.file,
|
'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:
|
if self.children:
|
||||||
result['children'] = {name: child.ToDict() for name, child in self.children.items()}
|
result['children'] = {name: child.ToDict() for name, child in self.children.items()}
|
||||||
@@ -118,7 +141,7 @@ class SymbolNode:
|
|||||||
node.attributes.Lineno = lineno
|
node.attributes.Lineno = lineno
|
||||||
else:
|
else:
|
||||||
if TypeName is not None:
|
if TypeName is not None:
|
||||||
node.attributes.BaseType = CTypeInfo.create_FromTypeName(TypeName)
|
node.attributes.BaseType = CTypeInfo.CreateFromTypeName(TypeName)
|
||||||
if IsPtr:
|
if IsPtr:
|
||||||
node.attributes.PtrCount = 1
|
node.attributes.PtrCount = 1
|
||||||
if dims:
|
if dims:
|
||||||
@@ -158,7 +181,7 @@ class SymbolNode:
|
|||||||
CTypeMember.PtrCount = max(CTypeMember.PtrCount, 1)
|
CTypeMember.PtrCount = max(CTypeMember.PtrCount, 1)
|
||||||
node.attributes.Members[MemberName] = CTypeMember
|
node.attributes.Members[MemberName] = CTypeMember
|
||||||
if TypeKind == 'struct':
|
if TypeKind == 'struct':
|
||||||
node.attributes.is_struct = True
|
node.attributes.IsStruct = True
|
||||||
elif TypeKind == 'enum':
|
elif TypeKind == 'enum':
|
||||||
node.attributes.IsEnum = True
|
node.attributes.IsEnum = True
|
||||||
elif TypeKind == 'union':
|
elif TypeKind == 'union':
|
||||||
@@ -198,7 +221,7 @@ class SymbolNode:
|
|||||||
if IsUnion:
|
if IsUnion:
|
||||||
node.attributes.IsUnion = True
|
node.attributes.IsUnion = True
|
||||||
else:
|
else:
|
||||||
node.attributes.is_struct = True
|
node.attributes.IsStruct = True
|
||||||
return node
|
return node
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from lib.core.translator import Translator
|
from lib.core.translator import Translator
|
||||||
from lib.core.SymbolNode import SymbolNode
|
|
||||||
from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper
|
from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper
|
||||||
from lib.includes import t
|
from lib.includes import t
|
||||||
from typing import Any, Dict, Iterator
|
from typing import Any, Dict, Iterator
|
||||||
@@ -48,78 +47,164 @@ def _AnnotationContainsTType(node, TypeName: str) -> bool:
|
|||||||
class SymbolTable:
|
class SymbolTable:
|
||||||
def __init__(self, translator: "Translator"):
|
def __init__(self, translator: "Translator"):
|
||||||
self.translator = translator
|
self.translator = translator
|
||||||
self._root = SymbolNode(name='root', NodeType='root')
|
self._symbols: Dict[str, CTypeInfo] = {}
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
self._root = SymbolNode(name='root', NodeType='root')
|
self._symbols.clear()
|
||||||
|
|
||||||
def get(self, name: str, default=None) -> CTypeInfo:
|
def get(self, name: str, default=None) -> CTypeInfo:
|
||||||
node = self._FindNode(name)
|
return self._symbols.get(name, default)
|
||||||
if node:
|
|
||||||
return node.attributes
|
|
||||||
return default
|
|
||||||
|
|
||||||
def set(self, name: str, value: Any):
|
def set(self, name: str, value: Any):
|
||||||
self._InsertNode(name, value)
|
if isinstance(value, CTypeInfo):
|
||||||
self._cached_len = -1
|
self._symbols[name] = value
|
||||||
|
else:
|
||||||
|
# 兼容旧代码传入 dict 的情况
|
||||||
|
info = self._CTypeInfoFromDict(name, value)
|
||||||
|
self._symbols[name] = info
|
||||||
|
|
||||||
def update(self, symbols: Dict[str, Any]):
|
def update(self, symbols: Dict[str, Any]):
|
||||||
for name, value in symbols.items():
|
for name, value in symbols.items():
|
||||||
self.set(name, value)
|
self.set(name, value)
|
||||||
|
|
||||||
def keys(self) -> Iterator[str]:
|
def keys(self) -> Iterator[str]:
|
||||||
return self._CollectKeys(self._root)
|
return iter(self._symbols.keys())
|
||||||
|
|
||||||
def values(self) -> Iterator[CTypeInfo]:
|
def values(self) -> Iterator[CTypeInfo]:
|
||||||
for node in self._CollectNodes(self._root):
|
return iter(self._symbols.values())
|
||||||
yield node.attributes
|
|
||||||
|
|
||||||
def items(self) -> Iterator[tuple[str, CTypeInfo]]:
|
def items(self) -> Iterator[tuple[str, CTypeInfo]]:
|
||||||
for node in self._CollectNodes(self._root):
|
return iter(self._symbols.items())
|
||||||
yield node.name, node.attributes
|
|
||||||
|
|
||||||
def pop(self, name: str, *args) -> CTypeInfo:
|
def pop(self, name: str, *args) -> CTypeInfo:
|
||||||
node = self._FindNode(name)
|
return self._symbols.pop(name, *args)
|
||||||
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:
|
def __getitem__(self, name: str) -> CTypeInfo:
|
||||||
node = self._FindNode(name)
|
if name in self._symbols:
|
||||||
if node:
|
return self._symbols[name]
|
||||||
return node.attributes
|
|
||||||
raise KeyError(name)
|
raise KeyError(name)
|
||||||
|
|
||||||
def __setitem__(self, name: str, value: Any):
|
def __setitem__(self, name: str, value: Any):
|
||||||
self.set(name, value)
|
self.set(name, value)
|
||||||
|
|
||||||
def __delitem__(self, name: str):
|
def __delitem__(self, name: str):
|
||||||
node = self._FindNode(name)
|
del self._symbols[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:
|
def __contains__(self, name: str) -> bool:
|
||||||
return self._FindNode(name) is not None
|
return name in self._symbols
|
||||||
|
|
||||||
def __len__(self) -> int:
|
def __len__(self) -> int:
|
||||||
if not hasattr(self, '_cached_len') or self._cached_len < 0:
|
return len(self._symbols)
|
||||||
self._cached_len = sum(1 for _ in self._CollectNodes(self._root))
|
|
||||||
return self._cached_len
|
|
||||||
|
|
||||||
def __iter__(self) -> Iterator[str]:
|
def __iter__(self) -> Iterator[str]:
|
||||||
return self.keys()
|
return iter(self._symbols)
|
||||||
|
|
||||||
def ToDict(self) -> Dict[str, Any]:
|
def ToDict(self) -> Dict[str, Any]:
|
||||||
return self._root.ToDict()
|
"""序列化为字典格式"""
|
||||||
|
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]):
|
def FromDict(self, symbols: Dict[str, Any]):
|
||||||
self._root = SymbolNode.FromDict('root', symbols)
|
"""从字典格式反序列化"""
|
||||||
|
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]:
|
def LoadModuleSymbols(self, FullModulePath: str, asname: str, lineno: int = 0) -> list[str]:
|
||||||
return self._LoadSymbolsFromFile(FullModulePath, asname, lineno)
|
return self._LoadSymbolsFromFile(FullModulePath, asname, lineno)
|
||||||
@@ -693,102 +778,70 @@ class SymbolTable:
|
|||||||
return ''
|
return ''
|
||||||
|
|
||||||
def _InsertClassSymbol(self, FullName: str, TypeKind: str, lineno: int, FilePath: str, members: dict, IsCpythonObject: bool, IsPacked: bool = False):
|
def _InsertClassSymbol(self, FullName: str, TypeKind: str, lineno: int, FilePath: str, members: dict, IsCpythonObject: bool, IsPacked: bool = False):
|
||||||
parts = FullName.split('.')
|
info = CTypeInfo()
|
||||||
current = self._root
|
info.Lineno = lineno
|
||||||
|
info.file = FilePath
|
||||||
|
info.Members = members if members else {}
|
||||||
|
|
||||||
for i, part in enumerate(parts[:-1]):
|
if TypeKind == 'struct':
|
||||||
if not current.HasChild(part):
|
info.IsStruct = True
|
||||||
node = SymbolNode(name=part, NodeType='namespace')
|
elif TypeKind == 'union':
|
||||||
current.AddChild(node)
|
info.IsUnion = True
|
||||||
current = current.GetChild(part)
|
elif TypeKind == 'enum':
|
||||||
|
info.IsEnum = True
|
||||||
|
elif TypeKind == 'exception':
|
||||||
|
info.IsStruct = True
|
||||||
|
info.IsExceptionClass = True
|
||||||
|
|
||||||
LastPart = parts[-1]
|
if IsCpythonObject:
|
||||||
node = SymbolNode.CreateClass(
|
info.IsCpythonObject = True
|
||||||
name=LastPart,
|
if IsPacked:
|
||||||
TypeKind=TypeKind,
|
info.IsPacked = True
|
||||||
members=members,
|
|
||||||
lineno=lineno,
|
self._symbols[FullName] = info
|
||||||
file=FilePath,
|
|
||||||
IsCpythonObject=IsCpythonObject,
|
|
||||||
IsPacked=IsPacked
|
|
||||||
)
|
|
||||||
current.AddChild(node)
|
|
||||||
|
|
||||||
def _InsertEnumMemberSymbol(self, FullName: str, EnumName: str, lineno: int, FilePath: str):
|
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 = CTypeInfo()
|
||||||
info.IsEnumMember = True
|
info.IsEnumMember = True
|
||||||
info.EnumName = EnumName
|
info.EnumName = EnumName
|
||||||
info.Lineno = lineno
|
info.Lineno = lineno
|
||||||
info.file = FilePath
|
info.file = FilePath
|
||||||
node = SymbolNode(name=LastPart, NodeType='enum_member')
|
self._symbols[FullName] = info
|
||||||
node.attributes = info
|
|
||||||
current.AddChild(node)
|
|
||||||
|
|
||||||
def _InsertTypedefSymbol(self, FullName: str, OriginalType_kind: str | None, OriginalClass, lineno: int, FilePath: str, members: dict | None = None):
|
def _InsertTypedefSymbol(self, FullName: str, OriginalType_kind: str | None, OriginalClass, lineno: int, FilePath: str, members: dict | None = None):
|
||||||
parts = FullName.split('.')
|
info = CTypeInfo()
|
||||||
current = self._root
|
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):
|
if isinstance(OriginalClass, CTypeInfo):
|
||||||
OriginalType = OriginalClass
|
info.OriginalType = OriginalClass
|
||||||
elif OriginalType_kind == 'typedef' and OriginalClass and isinstance(OriginalClass, str) and ('*' in OriginalClass):
|
elif OriginalType_kind == 'typedef' and OriginalClass and isinstance(OriginalClass, str) and ('*' in OriginalClass):
|
||||||
OriginalType = OriginalClass
|
OriginalType = OriginalClass
|
||||||
if OriginalType == 'CVoid *':
|
if OriginalType == 'CVoid *':
|
||||||
OriginalType = 'void *'
|
OriginalType = 'void *'
|
||||||
|
info.OriginalType = OriginalType
|
||||||
elif OriginalType_kind == 'typedef' and OriginalClass == 'void':
|
elif OriginalType_kind == 'typedef' and OriginalClass == 'void':
|
||||||
OriginalType = 'void *'
|
info.OriginalType = 'void *'
|
||||||
elif OriginalType_kind == 'typedef' and OriginalClass:
|
elif OriginalType_kind == 'typedef' and OriginalClass:
|
||||||
OriginalType = OriginalClass
|
info.OriginalType = OriginalClass
|
||||||
elif OriginalType_kind and OriginalClass and isinstance(OriginalClass, str):
|
elif OriginalType_kind and OriginalClass and isinstance(OriginalClass, str):
|
||||||
OriginalType = f'{OriginalType_kind} {OriginalClass}'
|
info.OriginalType = f'{OriginalType_kind} {OriginalClass}'
|
||||||
else:
|
else:
|
||||||
OriginalType = OriginalClass
|
info.OriginalType = OriginalClass
|
||||||
node = SymbolNode.CreateTypedef(
|
|
||||||
name=LastPart,
|
self._symbols[FullName] = info
|
||||||
OriginalType=OriginalType,
|
|
||||||
members=members,
|
|
||||||
lineno=lineno,
|
|
||||||
file=FilePath
|
|
||||||
)
|
|
||||||
current.AddChild(node)
|
|
||||||
|
|
||||||
def _InsertModuleSymbol(self, name: str, lineno: int, FilePath: str):
|
def _InsertModuleSymbol(self, name: str, lineno: int, FilePath: str):
|
||||||
node = SymbolNode.CreateModule(
|
info = CTypeInfo()
|
||||||
name=name,
|
info.IsModuleAlias = True
|
||||||
lineno=lineno,
|
info.Lineno = lineno
|
||||||
file=FilePath
|
info.file = FilePath
|
||||||
)
|
self._symbols[name] = info
|
||||||
self._root.AddChild(node)
|
|
||||||
|
|
||||||
def _InsertFuncSymbol(self, FullName: str, RetType, ParamTypes: list, lineno: int, FilePath: str, IsVariadic: bool = False, IsInline: bool = False):
|
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 = CTypeInfo()
|
||||||
info.IsFunction = True
|
info.IsFunction = True
|
||||||
if isinstance(RetType, str):
|
if isinstance(RetType, str):
|
||||||
@@ -804,30 +857,15 @@ class SymbolTable:
|
|||||||
info.Storage = t.CInline()
|
info.Storage = t.CInline()
|
||||||
info.Lineno = lineno
|
info.Lineno = lineno
|
||||||
info.file = FilePath
|
info.file = FilePath
|
||||||
node = SymbolNode(name=LastPart, NodeType='function')
|
self._symbols[FullName] = info
|
||||||
node.attributes = info
|
|
||||||
current.AddChild(node)
|
|
||||||
|
|
||||||
def _InsertDefineSymbol(self, FullName: str, DefineValue, lineno: int, FilePath: str):
|
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 = CTypeInfo()
|
||||||
info.IsDefine = True
|
info.IsDefine = True
|
||||||
info.DefineValue = DefineValue
|
info.DefineValue = DefineValue
|
||||||
info.Lineno = lineno
|
info.Lineno = lineno
|
||||||
info.file = FilePath
|
info.file = FilePath
|
||||||
node = SymbolNode(name=LastPart, NodeType='define')
|
self._symbols[FullName] = info
|
||||||
node.attributes = info
|
|
||||||
current.AddChild(node)
|
|
||||||
|
|
||||||
def _eval_const_expr(self, node):
|
def _eval_const_expr(self, node):
|
||||||
"""计算常量表达式的值"""
|
"""计算常量表达式的值"""
|
||||||
@@ -882,117 +920,15 @@ class SymbolTable:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def _InsertAnonymousSymbol(self, FullName: str, IsUnion: bool, members: dict, lineno: int, FilePath: str):
|
def _InsertAnonymousSymbol(self, FullName: str, IsUnion: bool, members: dict, lineno: int, FilePath: str):
|
||||||
parts = FullName.split('.')
|
info = CTypeInfo()
|
||||||
current = self._root
|
if IsUnion:
|
||||||
|
info.IsUnion = True
|
||||||
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:
|
else:
|
||||||
return None
|
info.IsStruct = True
|
||||||
|
info.IsAnonymous = True
|
||||||
|
info.Members = members if members else {}
|
||||||
|
info.Lineno = lineno
|
||||||
|
info.file = FilePath
|
||||||
|
self._symbols[FullName] = info
|
||||||
|
|
||||||
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', '')
|
|
||||||
)
|
|
||||||
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)
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import ast
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from lib.core.SymbolNode import SymbolNode
|
|
||||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||||
from lib.includes import t
|
from lib.includes import t
|
||||||
|
|
||||||
@@ -48,28 +47,25 @@ class AnnotationLoaderMixin:
|
|||||||
# 优先检查是否是 CEnum 子类(枚举)
|
# 优先检查是否是 CEnum 子类(枚举)
|
||||||
if isinstance(attr, type) and issubclass(attr, CEnum) and attr is not CEnum:
|
if isinstance(attr, type) and issubclass(attr, CEnum) and attr is not CEnum:
|
||||||
# 注册枚举类型
|
# 注册枚举类型
|
||||||
EnumNode = SymbolNode.CreateClass(
|
EnumNode = CTypeInfo()
|
||||||
name=AttrName,
|
EnumNode.Name = AttrName
|
||||||
TypeKind='enum',
|
EnumNode.BaseType = t.CEnum()
|
||||||
lineno=0
|
EnumNode.IsEnum = True
|
||||||
)
|
|
||||||
EnumNode.set('enum_class', attr)
|
EnumNode.set('enum_class', attr)
|
||||||
EnumNode.set('source', 'annotation_module')
|
EnumNode.set('source', 'annotation_module')
|
||||||
EnumNode.set('library_name', lib_name)
|
EnumNode.library_name = lib_name
|
||||||
EnumNode.set('file', source_file)
|
EnumNode.file = source_file
|
||||||
self.SymbolTable[AttrName] = EnumNode.attributes
|
self.SymbolTable[AttrName] = EnumNode
|
||||||
if lib_name:
|
if lib_name:
|
||||||
FullName = f'{lib_name}.{AttrName}'
|
FullName = f'{lib_name}.{AttrName}'
|
||||||
full_EnumNode = SymbolNode.CreateClass(
|
full_EnumNode = CTypeInfo()
|
||||||
name=FullName,
|
full_EnumNode.Name = FullName
|
||||||
TypeKind='enum',
|
full_EnumNode.IsEnum = True
|
||||||
lineno=0
|
|
||||||
)
|
|
||||||
full_EnumNode.set('enum_class', attr)
|
full_EnumNode.set('enum_class', attr)
|
||||||
full_EnumNode.set('source', 'annotation_module')
|
full_EnumNode.set('source', 'annotation_module')
|
||||||
full_EnumNode.set('library_name', lib_name)
|
full_EnumNode.library_name = lib_name
|
||||||
full_EnumNode.set('file', source_file)
|
full_EnumNode.file = source_file
|
||||||
self.SymbolTable[FullName] = full_EnumNode.attributes
|
self.SymbolTable[FullName] = full_EnumNode
|
||||||
# 枚举成员也需要注册
|
# 枚举成员也需要注册
|
||||||
for MemberName in dir(attr):
|
for MemberName in dir(attr):
|
||||||
if not MemberName.startswith('_'):
|
if not MemberName.startswith('_'):
|
||||||
@@ -98,27 +94,23 @@ class AnnotationLoaderMixin:
|
|||||||
else:
|
else:
|
||||||
FullName = AttrName
|
FullName = AttrName
|
||||||
# 同时注册带前缀和不带前缀的名称(都是 typedef 别名)
|
# 同时注册带前缀和不带前缀的名称(都是 typedef 别名)
|
||||||
TypedefNode = SymbolNode.CreateClass(
|
TypedefNode = CTypeInfo()
|
||||||
name=AttrName,
|
TypedefNode.Name = AttrName
|
||||||
TypeKind='typedef',
|
TypedefNode.IsTypedef = True
|
||||||
lineno=0
|
TypedefNode.OriginalType = attr().CName
|
||||||
)
|
|
||||||
TypedefNode.set('OriginalType', attr().CName)
|
|
||||||
TypedefNode.set('source', 'annotation_module')
|
TypedefNode.set('source', 'annotation_module')
|
||||||
TypedefNode.set('library_name', lib_name)
|
TypedefNode.library_name = lib_name
|
||||||
TypedefNode.set('file', source_file)
|
TypedefNode.file = source_file
|
||||||
self.SymbolTable[AttrName] = TypedefNode.attributes
|
self.SymbolTable[AttrName] = TypedefNode
|
||||||
if lib_name and FullName != AttrName:
|
if lib_name and FullName != AttrName:
|
||||||
FullTypedef_node = SymbolNode.CreateClass(
|
FullTypedef_node = CTypeInfo()
|
||||||
name=FullName,
|
FullTypedef_node.Name = FullName
|
||||||
TypeKind='typedef',
|
FullTypedef_node.IsTypedef = True
|
||||||
lineno=0
|
FullTypedef_node.OriginalType = attr().CName
|
||||||
)
|
|
||||||
FullTypedef_node.set('OriginalType', attr().CName)
|
|
||||||
FullTypedef_node.set('source', 'annotation_module')
|
FullTypedef_node.set('source', 'annotation_module')
|
||||||
FullTypedef_node.set('library_name', lib_name)
|
FullTypedef_node.library_name = lib_name
|
||||||
FullTypedef_node.set('file', source_file)
|
FullTypedef_node.file = source_file
|
||||||
self.SymbolTable[FullName] = FullTypedef_node.attributes
|
self.SymbolTable[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:
|
||||||
@@ -132,27 +124,23 @@ class AnnotationLoaderMixin:
|
|||||||
FullName = f'{lib_name}.{PublicName}'
|
FullName = f'{lib_name}.{PublicName}'
|
||||||
else:
|
else:
|
||||||
FullName = PublicName
|
FullName = PublicName
|
||||||
TypedefNode = SymbolNode.CreateClass(
|
TypedefNode = CTypeInfo()
|
||||||
name=PublicName,
|
TypedefNode.Name = PublicName
|
||||||
TypeKind='typedef',
|
TypedefNode.IsTypedef = True
|
||||||
lineno=0
|
TypedefNode.OriginalType = attr().CName
|
||||||
)
|
|
||||||
TypedefNode.set('OriginalType', attr().CName)
|
|
||||||
TypedefNode.set('source', 'annotation_module')
|
TypedefNode.set('source', 'annotation_module')
|
||||||
TypedefNode.set('library_name', lib_name)
|
TypedefNode.library_name = lib_name
|
||||||
TypedefNode.set('file', source_file)
|
TypedefNode.file = source_file
|
||||||
self.SymbolTable[PublicName] = TypedefNode.attributes
|
self.SymbolTable[PublicName] = TypedefNode
|
||||||
if lib_name and FullName != PublicName:
|
if lib_name and FullName != PublicName:
|
||||||
FullTypedef_node = SymbolNode.CreateClass(
|
FullTypedef_node = CTypeInfo()
|
||||||
name=FullName,
|
FullTypedef_node.Name = FullName
|
||||||
TypeKind='typedef',
|
FullTypedef_node.IsTypedef = True
|
||||||
lineno=0
|
FullTypedef_node.OriginalType = attr().CName
|
||||||
)
|
|
||||||
FullTypedef_node.set('OriginalType', attr().CName)
|
|
||||||
FullTypedef_node.set('source', 'annotation_module')
|
FullTypedef_node.set('source', 'annotation_module')
|
||||||
FullTypedef_node.set('library_name', lib_name)
|
FullTypedef_node.library_name = lib_name
|
||||||
FullTypedef_node.set('file', source_file)
|
FullTypedef_node.file = source_file
|
||||||
self.SymbolTable[FullName] = FullTypedef_node.attributes
|
self.SymbolTable[FullName] = FullTypedef_node
|
||||||
count += 1
|
count += 1
|
||||||
return count
|
return count
|
||||||
|
|
||||||
@@ -221,15 +209,13 @@ class AnnotationLoaderMixin:
|
|||||||
# 这个类继承自 CType,是 typedef 别名
|
# 这个类继承自 CType,是 typedef 别名
|
||||||
# 更新符号表中的类型为 typedef
|
# 更新符号表中的类型为 typedef
|
||||||
if ClassName in self.SymbolTable:
|
if ClassName in self.SymbolTable:
|
||||||
TypedefNode = SymbolNode.CreateClass(
|
TypedefNode = CTypeInfo()
|
||||||
name=ClassName,
|
TypedefNode.Name = ClassName
|
||||||
TypeKind='typedef',
|
TypedefNode.IsTypedef = True
|
||||||
lineno=0
|
TypedefNode.OriginalType = self.SymbolTable[ClassName].get('OriginalType', f'struct {ClassName}')
|
||||||
)
|
|
||||||
TypedefNode.set('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.attributes
|
self.SymbolTable[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
|
||||||
@@ -332,11 +318,9 @@ class AnnotationLoaderMixin:
|
|||||||
if orig_with_prefix in self.SymbolTable:
|
if orig_with_prefix in self.SymbolTable:
|
||||||
# 添加带前缀的 typedef 别名
|
# 添加带前缀的 typedef 别名
|
||||||
FullTypedef_name = f'{TypePrefix}.{TargetName}'
|
FullTypedef_name = f'{TypePrefix}.{TargetName}'
|
||||||
TypedefNode = SymbolNode.CreateClass(
|
TypedefNode = CTypeInfo()
|
||||||
name=FullTypedef_name,
|
TypedefNode.Name = FullTypedef_name
|
||||||
TypeKind='typedef',
|
TypedefNode.IsTypedef = True
|
||||||
lineno=0
|
|
||||||
)
|
|
||||||
orig_entry = self.SymbolTable.get(orig_with_prefix, {})
|
orig_entry = self.SymbolTable.get(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):
|
||||||
@@ -348,10 +332,10 @@ class AnnotationLoaderMixin:
|
|||||||
orig_type_str = getattr(orig_entry, 'OriginalType', f'struct {original_name}')
|
orig_type_str = getattr(orig_entry, 'OriginalType', f'struct {original_name}')
|
||||||
elif hasattr(orig_entry, 'IsEnum') and orig_entry.IsEnum:
|
elif hasattr(orig_entry, 'IsEnum') and orig_entry.IsEnum:
|
||||||
orig_type_str = f'enum {original_name}'
|
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('source', 'annotation_module')
|
||||||
TypedefNode.set('original_name', TargetName)
|
TypedefNode.set('original_name', TargetName)
|
||||||
self.SymbolTable[FullTypedef_name] = TypedefNode.attributes
|
self.SymbolTable[FullTypedef_name] = TypedefNode
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
self.AnnotationModules.add(lib_name)
|
self.AnnotationModules.add(lib_name)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import re
|
|||||||
import llvmlite.ir as ir
|
import llvmlite.ir as ir
|
||||||
|
|
||||||
from lib.core.LlvmCodeGenerator import LlvmCodeGenerator
|
from lib.core.LlvmCodeGenerator import LlvmCodeGenerator
|
||||||
from lib.core.SymbolNode import SymbolNode
|
|
||||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||||
from lib.includes import t
|
from lib.includes import t
|
||||||
from lib.constants.config import mode as _config_mode
|
from lib.constants.config import mode as _config_mode
|
||||||
@@ -368,15 +367,13 @@ class LlvmGeneratorMixin:
|
|||||||
|
|
||||||
if IsTypedef:
|
if IsTypedef:
|
||||||
TypedefKey = TypedefName if TypedefName else ClassName
|
TypedefKey = TypedefName if TypedefName else ClassName
|
||||||
TypedefNode = SymbolNode.CreateClass(
|
TypedefNode = CTypeInfo()
|
||||||
name=TypedefKey,
|
TypedefNode.Name = TypedefKey
|
||||||
TypeKind='typedef',
|
TypedefNode.IsTypedef = True
|
||||||
lineno=0
|
TypedefNode.OriginalType = f'struct {ClassName}'
|
||||||
)
|
|
||||||
TypedefNode.set('OriginalType', f'struct {ClassName}')
|
|
||||||
TypedefNode.set('IsComplete', True)
|
TypedefNode.set('IsComplete', True)
|
||||||
TypedefNode.set('file', '<stdin>')
|
TypedefNode.file = '<stdin>'
|
||||||
self.SymbolTable[TypedefKey] = TypedefNode.attributes
|
self.SymbolTable[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):
|
||||||
@@ -412,27 +409,23 @@ class LlvmGeneratorMixin:
|
|||||||
self.LogWarning(f"异常被忽略: {_e}")
|
self.LogWarning(f"异常被忽略: {_e}")
|
||||||
|
|
||||||
if not IsTypedef:
|
if not IsTypedef:
|
||||||
StructNode = SymbolNode.CreateClass(
|
StructNode = CTypeInfo()
|
||||||
name=ClassName,
|
StructNode.Name = ClassName
|
||||||
TypeKind='struct',
|
StructNode.IsStruct = True
|
||||||
members=members,
|
StructNode.Members = members or {}
|
||||||
lineno=0
|
StructNode.file = '<stdin>'
|
||||||
)
|
|
||||||
StructNode.set('file', '<stdin>')
|
|
||||||
if ClassName in self.SymbolTable:
|
if ClassName in self.SymbolTable:
|
||||||
existing = self.SymbolTable[ClassName]
|
existing = self.SymbolTable[ClassName]
|
||||||
if hasattr(existing, 'IsCpythonObject') and existing.IsCpythonObject:
|
if hasattr(existing, 'IsCpythonObject') and existing.IsCpythonObject:
|
||||||
StructNode.set('IsCpythonObject', True)
|
StructNode.IsCpythonObject = True
|
||||||
self.SymbolTable[ClassName] = StructNode.attributes
|
self.SymbolTable[ClassName] = StructNode
|
||||||
elif isinstance(Node, ast.FunctionDef):
|
elif isinstance(Node, ast.FunctionDef):
|
||||||
FuncName = Node.name
|
FuncName = Node.name
|
||||||
FuncNode = SymbolNode.CreateClass(
|
FuncNode = CTypeInfo()
|
||||||
name=FuncName,
|
FuncNode.Name = FuncName
|
||||||
TypeKind='function',
|
FuncNode.IsFunction = True
|
||||||
lineno=0
|
FuncNode.file = '<stdin>'
|
||||||
)
|
self.SymbolTable[FuncName] = FuncNode
|
||||||
FuncNode.set('file', '<stdin>')
|
|
||||||
self.SymbolTable[FuncName] = FuncNode.attributes
|
|
||||||
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
|
||||||
@@ -470,39 +463,33 @@ class LlvmGeneratorMixin:
|
|||||||
else:
|
else:
|
||||||
actual_type = 'struct'
|
actual_type = 'struct'
|
||||||
if actual_type == 'enum':
|
if actual_type == 'enum':
|
||||||
TypedefNode = SymbolNode.CreateClass(
|
TypedefNode = CTypeInfo()
|
||||||
name=VarName,
|
TypedefNode.Name = VarName
|
||||||
TypeKind='typedef',
|
TypedefNode.IsTypedef = True
|
||||||
lineno=0
|
TypedefNode.OriginalType = f'enum {OriginalType}'
|
||||||
)
|
TypedefNode.file = '<stdin>'
|
||||||
TypedefNode.set('OriginalType', f'enum {OriginalType}')
|
self.SymbolTable[VarName] = TypedefNode
|
||||||
TypedefNode.set('file', '<stdin>')
|
|
||||||
self.SymbolTable[VarName] = TypedefNode.attributes
|
|
||||||
elif actual_type == 'typedef':
|
elif actual_type == 'typedef':
|
||||||
TypedefNode = SymbolNode.CreateClass(
|
TypedefNode = CTypeInfo()
|
||||||
name=VarName,
|
TypedefNode.Name = VarName
|
||||||
TypeKind='typedef',
|
TypedefNode.IsTypedef = True
|
||||||
lineno=0
|
|
||||||
)
|
|
||||||
if isinstance(OriginalInfo, dict):
|
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:
|
elif isinstance(OriginalInfo, CTypeInfo) and OriginalInfo.OriginalType:
|
||||||
TypedefNode.set('OriginalType', OriginalInfo.OriginalType)
|
TypedefNode.OriginalType = OriginalInfo.OriginalType
|
||||||
else:
|
else:
|
||||||
TypedefNode.set('OriginalType', f'struct {OriginalType}')
|
TypedefNode.OriginalType = f'struct {OriginalType}'
|
||||||
TypedefNode.set('PendingTypedef', True)
|
TypedefNode.set('PendingTypedef', True)
|
||||||
TypedefNode.set('file', '<stdin>')
|
TypedefNode.file = '<stdin>'
|
||||||
self.SymbolTable[VarName] = TypedefNode.attributes
|
self.SymbolTable[VarName] = TypedefNode
|
||||||
else:
|
else:
|
||||||
TypedefNode = SymbolNode.CreateClass(
|
TypedefNode = CTypeInfo()
|
||||||
name=VarName,
|
TypedefNode.Name = VarName
|
||||||
TypeKind='typedef',
|
TypedefNode.IsTypedef = True
|
||||||
lineno=0
|
TypedefNode.OriginalType = f'struct {OriginalType}'
|
||||||
)
|
|
||||||
TypedefNode.set('OriginalType', f'struct {OriginalType}')
|
|
||||||
TypedefNode.set('PendingTypedef', True)
|
TypedefNode.set('PendingTypedef', True)
|
||||||
TypedefNode.set('file', '<stdin>')
|
TypedefNode.file = '<stdin>'
|
||||||
self.SymbolTable[VarName] = TypedefNode.attributes
|
self.SymbolTable[VarName] = TypedefNode
|
||||||
self.GeneratedTypes.add(VarName)
|
self.GeneratedTypes.add(VarName)
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
@@ -522,48 +509,42 @@ class LlvmGeneratorMixin:
|
|||||||
else:
|
else:
|
||||||
actual_type = 'struct'
|
actual_type = 'struct'
|
||||||
if actual_type == 'typedef':
|
if actual_type == 'typedef':
|
||||||
TypedefNode = SymbolNode.CreateClass(
|
TypedefNode = CTypeInfo()
|
||||||
name=VarName,
|
TypedefNode.Name = VarName
|
||||||
TypeKind='typedef',
|
TypedefNode.IsTypedef = True
|
||||||
lineno=0
|
|
||||||
)
|
|
||||||
if isinstance(OriginalInfo, dict):
|
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:
|
elif isinstance(OriginalInfo, CTypeInfo) and OriginalInfo.OriginalType:
|
||||||
TypedefNode.set('OriginalType', OriginalInfo.OriginalType)
|
TypedefNode.OriginalType = OriginalInfo.OriginalType
|
||||||
else:
|
else:
|
||||||
TypedefNode.set('OriginalType', f'struct {OriginalType}')
|
TypedefNode.OriginalType = f'struct {OriginalType}'
|
||||||
TypedefNode.set('PendingTypedef', True)
|
TypedefNode.set('PendingTypedef', True)
|
||||||
TypedefNode.set('file', '<stdin>')
|
TypedefNode.file = '<stdin>'
|
||||||
self.SymbolTable[VarName] = TypedefNode.attributes
|
self.SymbolTable[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
|
||||||
continue
|
continue
|
||||||
elif actual_type == 'struct':
|
elif actual_type == 'struct':
|
||||||
TypedefNode = SymbolNode.CreateClass(
|
TypedefNode = CTypeInfo()
|
||||||
name=VarName,
|
TypedefNode.Name = VarName
|
||||||
TypeKind='typedef',
|
TypedefNode.IsTypedef = True
|
||||||
lineno=0
|
TypedefNode.OriginalType = f'struct {OriginalType}'
|
||||||
)
|
|
||||||
TypedefNode.set('OriginalType', f'struct {OriginalType}')
|
|
||||||
TypedefNode.set('PendingTypedef', True)
|
TypedefNode.set('PendingTypedef', True)
|
||||||
TypedefNode.set('file', '<stdin>')
|
TypedefNode.file = '<stdin>'
|
||||||
self.SymbolTable[VarName] = TypedefNode.attributes
|
self.SymbolTable[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
|
||||||
continue
|
continue
|
||||||
elif actual_type == 'enum':
|
elif actual_type == 'enum':
|
||||||
TypedefNode = SymbolNode.CreateClass(
|
TypedefNode = CTypeInfo()
|
||||||
name=VarName,
|
TypedefNode.Name = VarName
|
||||||
TypeKind='typedef',
|
TypedefNode.IsTypedef = True
|
||||||
lineno=0
|
TypedefNode.OriginalType = f'enum {OriginalType}'
|
||||||
)
|
|
||||||
TypedefNode.set('OriginalType', f'enum {OriginalType}')
|
|
||||||
TypedefNode.set('PendingTypedef', True)
|
TypedefNode.set('PendingTypedef', True)
|
||||||
TypedefNode.set('file', '<stdin>')
|
TypedefNode.file = '<stdin>'
|
||||||
self.SymbolTable[VarName] = TypedefNode.attributes
|
self.SymbolTable[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
|
||||||
@@ -572,14 +553,12 @@ class LlvmGeneratorMixin:
|
|||||||
from lib.core.Handles.HandlesBase import CTypeHelper
|
from lib.core.Handles.HandlesBase import CTypeHelper
|
||||||
CName = CTypeHelper.GetCName(Node.value.attr)
|
CName = CTypeHelper.GetCName(Node.value.attr)
|
||||||
if CName:
|
if CName:
|
||||||
TypedefNode = SymbolNode.CreateClass(
|
TypedefNode = CTypeInfo()
|
||||||
name=VarName,
|
TypedefNode.Name = VarName
|
||||||
TypeKind='typedef',
|
TypedefNode.IsTypedef = True
|
||||||
lineno=0
|
TypedefNode.OriginalType = CName
|
||||||
)
|
TypedefNode.file = '<stdin>'
|
||||||
TypedefNode.set('OriginalType', CName)
|
self.SymbolTable[VarName] = TypedefNode
|
||||||
TypedefNode.set('file', '<stdin>')
|
|
||||||
self.SymbolTable[VarName] = TypedefNode.attributes
|
|
||||||
self.GeneratedTypes.add(VarName)
|
self.GeneratedTypes.add(VarName)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -590,14 +569,12 @@ class LlvmGeneratorMixin:
|
|||||||
except Exception as _e:
|
except Exception as _e:
|
||||||
if __import__('lib.constants.config', fromlist=['mode']).mode == "strict":
|
if __import__('lib.constants.config', fromlist=['mode']).mode == "strict":
|
||||||
self.LogWarning(f"异常被忽略: {_e}")
|
self.LogWarning(f"异常被忽略: {_e}")
|
||||||
var_node = SymbolNode.CreateClass(
|
var_node = CTypeInfo()
|
||||||
name=VarName,
|
var_node.Name = VarName
|
||||||
TypeKind='variable',
|
var_node.IsVariable = True
|
||||||
lineno=0
|
var_node.PtrCount = 1 if IsPtr else 0
|
||||||
)
|
var_node.file = '<stdin>'
|
||||||
var_node.set('IsPtr', IsPtr)
|
self.SymbolTable[VarName] = var_node
|
||||||
var_node.set('file', '<stdin>')
|
|
||||||
self.SymbolTable[VarName] = var_node.attributes
|
|
||||||
|
|
||||||
self.LlvmGen = LlvmCodeGenerator(
|
self.LlvmGen = LlvmCodeGenerator(
|
||||||
triple=getattr(self, 'triple', None),
|
triple=getattr(self, 'triple', None),
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import json
|
|||||||
import struct
|
import struct
|
||||||
|
|
||||||
from lib.utils.helpers import DetectFileType
|
from lib.utils.helpers import DetectFileType
|
||||||
from lib.core.SymbolNode import SymbolNode
|
|
||||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||||
from lib.includes import t
|
from lib.includes import t
|
||||||
from lib.constants.config import mode as _ConfigMode
|
from lib.constants.config import mode as _ConfigMode
|
||||||
@@ -325,13 +324,11 @@ class PythonParserMixin:
|
|||||||
|
|
||||||
if IsCenum:
|
if IsCenum:
|
||||||
# 注册为 enum 类型
|
# 注册为 enum 类型
|
||||||
EnumNode = SymbolNode.CreateClass(
|
EnumNode = CTypeInfo()
|
||||||
name=ClassName,
|
EnumNode.Name = ClassName
|
||||||
TypeKind='enum',
|
EnumNode.IsEnum = True
|
||||||
lineno=0
|
|
||||||
)
|
|
||||||
EnumNode.set('file', '<stdin>')
|
EnumNode.set('file', '<stdin>')
|
||||||
self.SymbolTable[ClassName] = EnumNode.attributes
|
self.SymbolTable[ClassName] = EnumNode
|
||||||
|
|
||||||
# 注册 enum 成员
|
# 注册 enum 成员
|
||||||
for item in node.body:
|
for item in node.body:
|
||||||
@@ -393,25 +390,21 @@ class PythonParserMixin:
|
|||||||
if _ConfigMode == "strict":
|
if _ConfigMode == "strict":
|
||||||
raise
|
raise
|
||||||
_vlog().warning(f"解析结构体成员失败: {_e}", "Exception")
|
_vlog().warning(f"解析结构体成员失败: {_e}", "Exception")
|
||||||
StructNode = SymbolNode.CreateClass(
|
StructNode = CTypeInfo()
|
||||||
name=ClassName,
|
StructNode.Name = ClassName
|
||||||
TypeKind='struct',
|
StructNode.IsStruct = True
|
||||||
members=members,
|
StructNode.Members = members or {}
|
||||||
lineno=0,
|
|
||||||
IsCpythonObject=IsCpythonObject
|
|
||||||
)
|
|
||||||
StructNode.set('file', '<stdin>')
|
StructNode.set('file', '<stdin>')
|
||||||
StructNode.set('IsAnonymous', IsAnonymous)
|
StructNode.set('IsAnonymous', IsAnonymous)
|
||||||
self.SymbolTable[ClassName] = StructNode.attributes
|
StructNode.set('IsCpythonObject', IsCpythonObject)
|
||||||
|
self.SymbolTable[ClassName] = StructNode
|
||||||
elif isinstance(node, ast.FunctionDef):
|
elif isinstance(node, ast.FunctionDef):
|
||||||
FuncName = node.name
|
FuncName = node.name
|
||||||
FuncNode = SymbolNode.CreateClass(
|
FuncNode = CTypeInfo()
|
||||||
name=FuncName,
|
FuncNode.Name = FuncName
|
||||||
TypeKind='function',
|
FuncNode.IsFunction = True
|
||||||
lineno=0
|
|
||||||
)
|
|
||||||
FuncNode.set('file', '<stdin>')
|
FuncNode.set('file', '<stdin>')
|
||||||
self.SymbolTable[FuncName] = FuncNode.attributes
|
self.SymbolTable[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
|
||||||
@@ -445,14 +438,12 @@ class PythonParserMixin:
|
|||||||
if _ConfigMode == "strict":
|
if _ConfigMode == "strict":
|
||||||
raise
|
raise
|
||||||
_vlog().warning(f"获取类型信息失败(ParsePythonFile): {_e}", "Exception")
|
_vlog().warning(f"获取类型信息失败(ParsePythonFile): {_e}", "Exception")
|
||||||
var_node = SymbolNode.CreateClass(
|
var_node = CTypeInfo()
|
||||||
name=VarName,
|
var_node.Name = VarName
|
||||||
TypeKind='variable',
|
var_node.IsVariable = True
|
||||||
lineno=0
|
|
||||||
)
|
|
||||||
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.attributes
|
self.SymbolTable[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}')
|
||||||
|
|
||||||
|
|||||||
302
lib/core/TypeSpec.py
Normal file
302
lib/core/TypeSpec.py
Normal file
@@ -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
|
||||||
Reference in New Issue
Block a user