修复了一些问题

This commit is contained in:
TermiNexus committed 2026-09-17 14:52:37 +08:00
1 parent 43e7cdd2cc
commit 6af2dea917
16 files changed
+387 -288

No files matched your search

+138 -138
View File
@@ -18,7 +18,7 @@ from lib.core.SymbolUtils import ParseListAnnotation, ExtractTypeNameFromBinOp,
# 注解里的存储类 / 限定符标记:这些名字**不是类名**(联合注解里与指针类混写,
# 如 `t.CExtern | rowptr[CompilerFactory]`),提取"指针指向的类"时必须滤掉。
# 如 `t.CExtern | rawptr[CompilerFactory]`),提取"指针指向的类"时必须滤掉。
_MARKER_ANNOT_NAMES: frozenset[str] = frozenset({
'CExtern', 'CExport', 'CStatic', 'CInline', 'CConst', 'CVolatile', 'CRegister',
'CAuto', 'CDefine', 'CTypedef', 'CPostdefinition', 'CPtr', 'CArrayPtr', 'CVoid',
@@ -590,9 +590,9 @@ class ImportHandle(BaseHandle):
HandlesFile = os.path.abspath(inspect.getfile(self.__class__))
TransPyCRoot = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(HandlesFile))))
FullModulePath = None
# includes 只认项目(project.vpj includes → LibraryPaths)目录,禁止回退仓库硬编码
# TransPyCRoot/includes:仓库副本缺失时回退会造成声明解析时序错乱(memhub 未注册→i32)。
FullModulePath = None
# includes 只认项目(project.vpj includes → LibraryPaths)目录,禁止回退仓库硬编码
# TransPyCRoot/includes:仓库副本缺失时回退会造成声明解析时序错乱(memhub 未注册→i32)。
SearchDirs = list(self.Trans.LibraryPaths)
for LibPath in SearchDirs:
@@ -857,51 +857,51 @@ class ImportHandle(BaseHandle):
if module_name:
self._LoadDeclarationsFromStubLlvm(module_name, Gen)
def _AnnotationStructName(self, annotation: ast.AST) -> str | None:
"""从注解里提取「指针指向的类」短名(递归,0 判定返回 None)
覆盖形态:`X` / `mod.X` / `rowptr[X]` / `t.CPtr[X]` / 联合 `A | B`(两翼都试)。
存储类与限定符标记(`t.CExtern` / `t.CExport` / `t.CPtr` 等)不算类名,
由 `_MARKER_ANNOT_NAMES` 过滤;返回的是**短名**,调用方再解析成
`Gen.structs` 真实键。
"""
if annotation is None:
return None
if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr):
_left: str | None = self._AnnotationStructName(annotation.left)
if _left:
return _left
return self._AnnotationStructName(annotation.right)
if isinstance(annotation, ast.Subscript):
_base: ast.AST = annotation.value
_bn: str = ''
if isinstance(_base, ast.Name):
_bn = _base.id
elif isinstance(_base, ast.Attribute):
_bn = _base.attr
if _bn in ('rowptr', 'CPtr', 'CArrayPtr'):
_sl: ast.AST = annotation.slice
if hasattr(ast, 'Index') and isinstance(_sl, ast.Index):
_sl = _sl.value
return self._AnnotationStructName(_sl)
return None
if isinstance(annotation, ast.Name):
if annotation.id in _MARKER_ANNOT_NAMES:
return None
return annotation.id
if isinstance(annotation, ast.Attribute):
# `mod.Class`:mod 为 t/c 时是内建标记/内建类型名,不作为类的键
if isinstance(annotation.value, ast.Name) and annotation.value.id in ('t', 'c'):
return None
if annotation.attr in _MARKER_ANNOT_NAMES:
return None
return annotation.attr
return None
def _AnnotationStructName(self, annotation: ast.AST) -> str | None:
"""从注解里提取「指针指向的类」短名(递归,0 判定返回 None)
覆盖形态:`X` / `mod.X` / `rawptr[X]` / `t.CPtr[X]` / 联合 `A | B`(两翼都试)。
存储类与限定符标记(`t.CExtern` / `t.CExport` / `t.CPtr` 等)不算类名,
由 `_MARKER_ANNOT_NAMES` 过滤;返回的是**短名**,调用方再解析成
`Gen.structs` 真实键。
"""
if annotation is None:
return None
if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr):
_left: str | None = self._AnnotationStructName(annotation.left)
if _left:
return _left
return self._AnnotationStructName(annotation.right)
if isinstance(annotation, ast.Subscript):
_base: ast.AST = annotation.value
_bn: str = ''
if isinstance(_base, ast.Name):
_bn = _base.id
elif isinstance(_base, ast.Attribute):
_bn = _base.attr
if _bn in ('rawptr', 'CPtr', 'CArrayPtr'):
_sl: ast.AST = annotation.slice
if hasattr(ast, 'Index') and isinstance(_sl, ast.Index):
_sl = _sl.value
return self._AnnotationStructName(_sl)
return None
if isinstance(annotation, ast.Name):
if annotation.id in _MARKER_ANNOT_NAMES:
return None
return annotation.id
if isinstance(annotation, ast.Attribute):
# `mod.Class`:mod 为 t/c 时是内建标记/内建类型名,不作为类的键
if isinstance(annotation.value, ast.Name) and annotation.value.id in ('t', 'c'):
return None
if annotation.attr in _MARKER_ANNOT_NAMES:
return None
return annotation.attr
return None
def _ResolveAnnotationStructKey(self, Gen: LlvmGeneratorMixin, name: str) -> str | None:
"""把注解里的类短名解析为 `Gen.structs` 的真实键(0 命中返回 None)
三条路径与类字段侧的 `rowptr[裸结构]` 登记保持一致:裸名直查 /
三条路径与类字段侧的 `rawptr[裸结构]` 登记保持一致:裸名直查 /
`class_sha1_map` 加前缀 / 全量短名模糊扫描(跨模块类在
`class_sha1_map` 尚未登记该短名时靠这条兜住)。
"""
@@ -928,7 +928,7 @@ class ImportHandle(BaseHandle):
is_string_val = False
TypeInfo = None
# 【跨模块模块级变量的**类登记**】`CTypeInfo.FromNode` 对
# `X | t.CPtr` / `rowptr[X]` 注解只给出指针占位(rowptr[X] 折叠成 i8*),
# `X | t.CPtr` / `rawptr[X]` 注解只给出指针占位(rawptr[X] 折叠成 i8*),
# 且本函数**只算类型、不登记变量类** → 消费侧 `Mod.Var.Field` 链在
# `_get_var_class` 里解析为空:StructGenMixin.vp:139 "属性访问未能解析出
# 目标类型/成员"、CallGenLeafKit.vp:589 / ClassGenVTable.vp:99 误报
@@ -942,8 +942,8 @@ class ImportHandle(BaseHandle):
_eg_tk: str | None = self._ResolveAnnotationStructKey(Gen, _eg_tn)
if _eg_tk:
_eg_cur: str | None = Gen.var_struct_class.get(VarName)
if (not _eg_cur or _eg_cur == 'rowptr' or _eg_cur.endswith('.rowptr')
or _eg_cur.startswith('rowptr[')):
if (not _eg_cur or _eg_cur == 'rawptr' or _eg_cur.endswith('.rawptr')
or _eg_cur.startswith('rawptr[')):
Gen.var_struct_class[VarName] = _eg_tk
if getattr(Gen, 'global_struct_class', None) is not None:
Gen.global_struct_class[VarName] = _eg_tk
@@ -1521,85 +1521,85 @@ class ImportHandle(BaseHandle):
if ReexportName2 not in Gen.functions:
Gen.functions[ReexportName2] = func
def _ClassifyExternalClass(self, Node: ast.ClassDef) -> tuple:
"""遍历 Node.bases/decorator_list 做类别判断(纯函数、与 Gen 无关)。
结果由 _EmitExternalClassDeclLlvm 按 (source_sha1, class_name) 类级缓存,
同一 worker 进程内多个任务对同一跨模块类重复调用时跳过本遍历。
返回 (IsGenericClass, IsCenum, IsRenum, IsCpythonObject, IsCVTable,
IsNoVTable, IsPacked)。
PEP 695 泛型类(如 GSListNode[T])特殊:跨模块继承展平需要从泛型基类
获取字段(如 Next),否则子类(如 Value(GSListNode[Value]))的
class_members 会缺少继承字段;但泛型类的方法声明必须跳过(方法参数
类型 T 会被解析为 opaque struct,LLVM 不允许 opaque struct 作为值参数)。
"""
IsGenericClass: bool = hasattr(Node, 'type_params') and bool(Node.type_params)
IsCenum = False
IsRenum = False
IsCpythonObject = False
IsCVTable = False
IsNoVTable = False
if Node.bases:
for base in Node.bases:
if getattr(base, 'attr', None):
if base.attr == 'REnum':
IsRenum = True
break
elif base.attr == 'CEnum' or base.attr == 'Enum':
IsCenum = True
break
elif getattr(base, 'id', None):
if base.id == 'REnum':
IsRenum = True
break
elif base.id == 'CEnum' or base.id == 'Enum':
IsCenum = True
break
if not IsCenum and not IsRenum and getattr(Node, 'decorator_list', None):
for decorator in Node.decorator_list:
if isinstance(decorator, ast.Attribute):
if getattr(decorator.value, 'id', None) == 't':
if decorator.attr == 'Object':
IsCpythonObject = True
elif decorator.attr == 'CVTable':
IsCVTable = True
elif decorator.attr == 'NoVTable':
IsNoVTable = True
elif decorator.attr == 'REnum':
IsRenum = True
elif decorator.attr == 'CEnum' or decorator.attr == 'Enum':
IsCenum = True
elif isinstance(decorator, ast.Call):
if isinstance(decorator.func, ast.Attribute):
if getattr(decorator.func.value, 'id', None) == 't':
if decorator.func.attr == 'Object':
IsCpythonObject = True
elif decorator.func.attr == 'CVTable':
IsCVTable = True
elif decorator.func.attr == 'NoVTable':
IsNoVTable = True
elif isinstance(decorator.func, ast.Name):
if decorator.func.id == 'Object':
IsCpythonObject = True
elif decorator.func.id == 'CVTable':
IsCVTable = True
elif decorator.func.id == 'NoVTable':
IsNoVTable = True
IsPacked = False
if getattr(Node, 'decorator_list', None):
for decorator in Node.decorator_list:
if isinstance(decorator, ast.Call):
if isinstance(decorator.func, ast.Attribute):
if getattr(decorator.func.value, 'id', None) == 'c' and decorator.func.attr == 'Attribute':
for arg in decorator.args:
if isinstance(arg, ast.Attribute):
if isinstance(arg.value, ast.Attribute):
if getattr(arg.value.value, 'id', None) == 't' and arg.value.attr == 'attr' and arg.attr == 'packed':
IsPacked = True
return (IsGenericClass, IsCenum, IsRenum, IsCpythonObject,
IsCVTable, IsNoVTable, IsPacked)
def _ClassifyExternalClass(self, Node: ast.ClassDef) -> tuple:
"""遍历 Node.bases/decorator_list 做类别判断(纯函数、与 Gen 无关)。
结果由 _EmitExternalClassDeclLlvm 按 (source_sha1, class_name) 类级缓存,
同一 worker 进程内多个任务对同一跨模块类重复调用时跳过本遍历。
返回 (IsGenericClass, IsCenum, IsRenum, IsCpythonObject, IsCVTable,
IsNoVTable, IsPacked)。
PEP 695 泛型类(如 GSListNode[T])特殊:跨模块继承展平需要从泛型基类
获取字段(如 Next),否则子类(如 Value(GSListNode[Value]))的
class_members 会缺少继承字段;但泛型类的方法声明必须跳过(方法参数
类型 T 会被解析为 opaque struct,LLVM 不允许 opaque struct 作为值参数)。
"""
IsGenericClass: bool = hasattr(Node, 'type_params') and bool(Node.type_params)
IsCenum = False
IsRenum = False
IsCpythonObject = False
IsCVTable = False
IsNoVTable = False
if Node.bases:
for base in Node.bases:
if getattr(base, 'attr', None):
if base.attr == 'REnum':
IsRenum = True
break
elif base.attr == 'CEnum' or base.attr == 'Enum':
IsCenum = True
break
elif getattr(base, 'id', None):
if base.id == 'REnum':
IsRenum = True
break
elif base.id == 'CEnum' or base.id == 'Enum':
IsCenum = True
break
if not IsCenum and not IsRenum and getattr(Node, 'decorator_list', None):
for decorator in Node.decorator_list:
if isinstance(decorator, ast.Attribute):
if getattr(decorator.value, 'id', None) == 't':
if decorator.attr == 'Object':
IsCpythonObject = True
elif decorator.attr == 'CVTable':
IsCVTable = True
elif decorator.attr == 'NoVTable':
IsNoVTable = True
elif decorator.attr == 'REnum':
IsRenum = True
elif decorator.attr == 'CEnum' or decorator.attr == 'Enum':
IsCenum = True
elif isinstance(decorator, ast.Call):
if isinstance(decorator.func, ast.Attribute):
if getattr(decorator.func.value, 'id', None) == 't':
if decorator.func.attr == 'Object':
IsCpythonObject = True
elif decorator.func.attr == 'CVTable':
IsCVTable = True
elif decorator.func.attr == 'NoVTable':
IsNoVTable = True
elif isinstance(decorator.func, ast.Name):
if decorator.func.id == 'Object':
IsCpythonObject = True
elif decorator.func.id == 'CVTable':
IsCVTable = True
elif decorator.func.id == 'NoVTable':
IsNoVTable = True
IsPacked = False
if getattr(Node, 'decorator_list', None):
for decorator in Node.decorator_list:
if isinstance(decorator, ast.Call):
if isinstance(decorator.func, ast.Attribute):
if getattr(decorator.func.value, 'id', None) == 'c' and decorator.func.attr == 'Attribute':
for arg in decorator.args:
if isinstance(arg, ast.Attribute):
if isinstance(arg.value, ast.Attribute):
if getattr(arg.value.value, 'id', None) == 't' and arg.value.attr == 'attr' and arg.attr == 'packed':
IsPacked = True
return (IsGenericClass, IsCenum, IsRenum, IsCpythonObject,
IsCVTable, IsNoVTable, IsPacked)
def _EmitExternalClassDeclLlvm(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin, module_name: str | None = None, actual_module_name: str | None = None, source_sha1: str | None = None) -> None:
ClassName = Node.name
# Compute source_sha1 up front (moved from mid-function) so it can serve as
@@ -1900,10 +1900,10 @@ class ImportHandle(BaseHandle):
if ClassName not in Gen.class_member_element_class:
Gen.class_member_element_class[ClassName] = {}
Gen.class_member_element_class[ClassName][VarName] = spec_in_anno
# Subscript 容器字段(list[X] / rowptr[list[X]],如 includes/ast
# 的 Call.args / Import.names: rowptr[list[rowptr[AST]]]):非 BinOp
# Subscript 容器字段(list[X] / rawptr[list[X]],如 includes/ast
# 的 Call.args / Import.names: rawptr[list[rawptr[AST]]]):非 BinOp
# 联合,上面两分支不命中 → 容器身份丢失 → 字段方法调用(get/len…)
# 分派失败报 "Undefined method 'get' in class 'rowptr'"(Converter.vp)。
# 分派失败报 "Undefined method 'get' in class 'rawptr'"(Converter.vp)。
# 用与特化生成端同源的 _resolve_type_arg_str 构造 element_class,
# 键名与 Gen.structs 中 list 特化名保持一致。
if isinstance(item.annotation, ast.Subscript):
@@ -1913,13 +1913,13 @@ class ImportHandle(BaseHandle):
_elem_slice_s: ast.AST | None = None
if _subname_s == 'list':
_elem_slice_s = _ann_sub_s.slice
elif _subname_s == 'rowptr':
elif _subname_s == 'rawptr':
_slice_s: ast.AST = _ann_sub_s.slice
if isinstance(_slice_s, ast.Subscript):
# rowptr[泛型容器](rowptr[list[X]] / rowptr[GSList[Param]]):
# rawptr[泛型容器](rawptr[list[X]] / rawptr[GSList[Param]]):
# 容器身份 = 泛型特化名。list 继续走 _elem_slice_s 统一登记;
# 其余泛型容器直接登记 element_class(阻塞 B 根因链一环:
# 原实现只认内层 list,rowptr[GSList[Param]] 在此空转并跳过
# 原实现只认内层 list,rawptr[GSList[Param]] 在此空转并跳过
# 裸结构分支 → element_class 缺失 → 字段/局部变量方法分派
# 丢失容器身份,FakeDuck 错绑 LinkedNode.append 写穿)。
_inner_sub_s: ast.Subscript = _slice_s
@@ -1938,11 +1938,11 @@ class ImportHandle(BaseHandle):
Gen.class_member_element_class[ClassName] = {}
Gen.class_member_element_class[ClassName][VarName] = _ec_gs
else:
# rowptr[裸结构](如 rowptr[Token]):跨模块 stub 会把自引用/类内
# rawptr[裸结构](如 rawptr[Token]):跨模块 stub 会把自引用/类内
# 指针字段退化为 i8*,链式成员访问(a.b.c)需 element_class 恢复
# struct 身份走 char*→struct cast。HEAD 态 `Token | t.CPtr` 联合
# 由上方 BinOp 分支登记;rowptr 重构后此分支补齐(阻塞 A 根因)。
# 与 HandlesClassDef 的 rowptr 分支对称。
# 由上方 BinOp 分支登记;rawptr 重构后此分支补齐(阻塞 A 根因)。
# 与 HandlesClassDef 的 rawptr 分支对称。
_slc_name_s: str | None = None
if isinstance(_slice_s, ast.Name):
_slc_name_s = _slice_s.id
@@ -1959,7 +1959,7 @@ class ImportHandle(BaseHandle):
else:
# 短名模糊扫描(对齐 HandlesAnnAssign 变量侧
# 补偿 L597-602):跨模块 `mod.Class` 形态的
# rowptr[Class] 字段在 class_sha1_map 尚无该短名
# rawptr[Class] 字段在 class_sha1_map 尚无该短名
# 时上面两路全 miss → element_class 静默缺失 →
# 字段方法调用(factory.PermPool.alloc)链尾类名
# 丢失 → TPC 调用分派返回 i32 0 哨兵 → 误报