修复了一些问题
This commit is contained in:
1 parent
43e7cdd2cc
commit
6af2dea917
16 files changed
+387
-288
No files matched your search
+138
-138
@@ -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 哨兵 → 误报
|
||||
|
||||
Reference in new issue
Block a user