阶段 2 完成
This commit is contained in:
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 @@
|
||||
======================================================================
|
||||
@@ -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:
|
||||
|
||||
@@ -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='<stdin>'
|
||||
)
|
||||
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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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', '<stdin>')
|
||||
self.SymbolTable[TypedefKey] = TypedefNode.attributes
|
||||
TypedefNode.file = '<stdin>'
|
||||
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', '<stdin>')
|
||||
StructNode = CTypeInfo()
|
||||
StructNode.Name = ClassName
|
||||
StructNode.IsStruct = True
|
||||
StructNode.Members = members or {}
|
||||
StructNode.file = '<stdin>'
|
||||
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', '<stdin>')
|
||||
self.SymbolTable[FuncName] = FuncNode.attributes
|
||||
FuncNode = CTypeInfo()
|
||||
FuncNode.Name = FuncName
|
||||
FuncNode.IsFunction = True
|
||||
FuncNode.file = '<stdin>'
|
||||
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', '<stdin>')
|
||||
self.SymbolTable[VarName] = TypedefNode.attributes
|
||||
TypedefNode = CTypeInfo()
|
||||
TypedefNode.Name = VarName
|
||||
TypedefNode.IsTypedef = True
|
||||
TypedefNode.OriginalType = f'enum {OriginalType}'
|
||||
TypedefNode.file = '<stdin>'
|
||||
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', '<stdin>')
|
||||
self.SymbolTable[VarName] = TypedefNode.attributes
|
||||
TypedefNode.file = '<stdin>'
|
||||
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', '<stdin>')
|
||||
self.SymbolTable[VarName] = TypedefNode.attributes
|
||||
TypedefNode.file = '<stdin>'
|
||||
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', '<stdin>')
|
||||
self.SymbolTable[VarName] = TypedefNode.attributes
|
||||
TypedefNode.file = '<stdin>'
|
||||
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', '<stdin>')
|
||||
self.SymbolTable[VarName] = TypedefNode.attributes
|
||||
TypedefNode.file = '<stdin>'
|
||||
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', '<stdin>')
|
||||
self.SymbolTable[VarName] = TypedefNode.attributes
|
||||
TypedefNode.file = '<stdin>'
|
||||
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', '<stdin>')
|
||||
self.SymbolTable[VarName] = TypedefNode.attributes
|
||||
TypedefNode = CTypeInfo()
|
||||
TypedefNode.Name = VarName
|
||||
TypedefNode.IsTypedef = True
|
||||
TypedefNode.OriginalType = CName
|
||||
TypedefNode.file = '<stdin>'
|
||||
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', '<stdin>')
|
||||
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 = '<stdin>'
|
||||
self.SymbolTable[VarName] = var_node
|
||||
|
||||
self.LlvmGen = LlvmCodeGenerator(
|
||||
triple=getattr(self, 'triple', None),
|
||||
|
||||
@@ -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', '<stdin>')
|
||||
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', '<stdin>')
|
||||
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', '<stdin>')
|
||||
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', '<stdin>')
|
||||
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}')
|
||||
|
||||
|
||||
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