阶段 2 完成
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user