重置上传,新增了多个标准库,开始 TransPyV 自举实验

This commit is contained in:
2026-07-19 11:38:15 +08:00
parent 796222a300
commit 4e66207ba1
1041 changed files with 6597 additions and 27814 deletions

View File

@@ -476,6 +476,7 @@ class DeclarationGenerator:
seen_member_names: set[str] = set()
for base in node.bases:
base_name: str | None = None
type_args: list[str] = []
if isinstance(base, ast.Attribute):
base_name = base.attr
elif isinstance(base, ast.Name):
@@ -485,10 +486,19 @@ class DeclarationGenerator:
base_name = base.value.attr
elif isinstance(base.value, ast.Name):
base_name = base.value.id
slice_node: ast.AST = base.slice
if isinstance(slice_node, ast.Name):
type_args.append(slice_node.id)
elif isinstance(slice_node, ast.Tuple):
for elt in slice_node.elts:
if isinstance(elt, ast.Name):
type_args.append(elt.id)
if base_name and not self._is_marker_base(base_name):
base_member_types: list[str]
base_seen: set[str]
base_member_types, base_seen = self._get_inherited_members(base_name)
if type_args:
base_member_types = self._specialize_member_types(base_member_types, type_args)
for mt in base_member_types:
member_types.append(mt)
seen_member_names.update(base_seen)
@@ -632,8 +642,124 @@ class DeclarationGenerator:
decls.append(f'declare {ret_type} @"{method_name}"({param_str})')
else:
decls.append(f'declare {ret_type} @{method_name}({param_str})')
# 为继承但未覆写的方法生成包装声明
# 这些声明让跨模块调用能正确解析子类包装函数的签名,
# 避免 stub 缺失导致默认 i32 返回类型 → 64 位指针截断
decls.extend(self._generate_inherited_method_decls(node, class_name, struct_type_name))
return decls
def _generate_inherited_method_decls(self, node: ast.ClassDef, child_class_name: str, child_struct_type: str) -> list[str]:
"""为继承但未覆写的方法生成包装声明
在 Phase 1 stub 中声明子类继承方法的签名(与父类相同,但 self 参数为子类类型)。
这样测试模块翻译时能从 temp stub 中获取正确的返回类型,
避免 Phase 2 includes 翻译滞后导致跨模块调用使用默认 i32 返回类型。
"""
decls: list[str] = []
# 收集子类自身定义的方法名(这些不需要生成包装,子类有自己的实现)
seen_method_names: set[str] = set()
for item in node.body:
if isinstance(item, ast.FunctionDef):
seen_method_names.add(item.name)
# 沿继承链收集父类方法,近祖先优先
for base in node.bases:
base_name: str | None = None
if isinstance(base, ast.Attribute):
base_name = base.attr
elif isinstance(base, ast.Name):
base_name = base.id
elif isinstance(base, ast.Subscript):
if isinstance(base.value, ast.Attribute):
base_name = base.value.attr
elif isinstance(base.value, ast.Name):
base_name = base.value.id
if not base_name or self._is_marker_base(base_name):
continue
self._CollectInheritedWrapperDecls(
base_name, child_class_name, child_struct_type,
seen_method_names, decls)
return decls
def _CollectInheritedWrapperDecls(
self, parent_name: str, child_class_name: str, child_struct_type: str,
seen_method_names: set[str], decls: list[str]) -> None:
"""递归收集父类及其祖先的方法,为未覆写的方法生成包装声明"""
# 查找父类节点:先在当前 .pyi 中查找,找不到则查跨模块类定义映射
parent_node: ast.ClassDef | None = None
for n in ast.iter_child_nodes(self._pyi_tree):
if isinstance(n, ast.ClassDef) and n.name == parent_name:
parent_node = n
break
if parent_node is None:
parent_node = self._cross_module_class_defs.get(parent_name)
if parent_node is None:
return
# 为父类的每个方法生成包装声明
for item in parent_node.body:
if isinstance(item, ast.FunctionDef):
if hasattr(item, 'type_params') and item.type_params:
continue
method_name: str = item.name
# __before_init__ 只在自身类生成,不生成继承包装
if method_name == '__before_init__':
continue
# 跳过子类已覆写的方法,以及已处理的祖先方法
if method_name in seen_method_names:
continue
seen_method_names.add(method_name)
# 构建包装方法名:{module_sha1}.{child_class}.{method_name}
wrapper_name: str = f'{child_class_name}.{method_name}'
if self.module_sha1:
wrapper_name = f"{self.module_sha1}.{wrapper_name}"
# 解析返回类型(与父类方法相同)
ret_type: str = self._get_type_str(item.returns) if item.returns else 'void'
if not ret_type:
ret_type = 'void'
elif ret_type == 'i8*':
if item.returns is None:
ret_type = 'void'
# 构建参数列表第一个参数self替换为子类类型其余与父类相同
params: list[str] = []
for arg_idx, arg in enumerate(item.args.args):
arg_type: str
if arg_idx == 0 and arg.arg == 'self':
arg_type = f'{child_struct_type}*'
else:
if arg.annotation:
arg_type = self._get_type_str(arg.annotation)
else:
arg_type = 'i8*'
arg_type = self._decay_array_to_ptr(arg_type)
params.append(arg_type)
param_str: str = ', '.join(params) if params else ''
if wrapper_name[0].isdigit():
decls.append(f'declare {ret_type} @"{wrapper_name}"({param_str})')
else:
decls.append(f'declare {ret_type} @{wrapper_name}({param_str})')
# 递归处理祖先类
for base in parent_node.bases:
base_name: str | None = None
if isinstance(base, ast.Attribute):
base_name = base.attr
elif isinstance(base, ast.Name):
base_name = base.id
elif isinstance(base, ast.Subscript):
if isinstance(base.value, ast.Attribute):
base_name = base.value.attr
elif isinstance(base.value, ast.Name):
base_name = base.value.id
if base_name and not self._is_marker_base(base_name):
self._CollectInheritedWrapperDecls(
base_name, child_class_name, child_struct_type,
seen_method_names, decls)
def _get_inherited_members(self, base_name: str) -> tuple[list[str], set[str]]:
member_types: list[str] = []
seen_names: set[str] = set()
@@ -675,6 +801,36 @@ class DeclarationGenerator:
seen_names.add(stmt.targets[0].attr)
return member_types, seen_names
def _specialize_member_types(self, member_types: list[str], type_args: list[str]) -> list[str]:
"""将基类成员类型中的泛型参数 T 替换为具体类型参数
处理泛型基类继承(如 GSListNode[BasicBlock])时,基类 _get_inherited_members
返回的成员类型中会包含未特化的 T 引用(形式为 %"SHA1.T"*)。
替换策略:使用 i8*(不透明指针)代替 T*,而非具体类型指针。
原因:跨模块场景中,具体类型指针的 SHA1 前缀可能与导入模块不一致,
导致 TransPyC 类型转换失败。i8* 作为通用指针类型,可安全赋值给
任何 Class | t.CPtr 注解的变量,运行时行为与 T* 相同(都是指针)。
Args:
member_types: 基类成员类型字符串列表
type_args: 类型参数名列表(如 ['BasicBlock']
Returns:
特化后的成员类型字符串列表
"""
if not type_args:
return member_types
result: list[str] = []
for mt in member_types:
new_mt: str = mt
# 将 %"SHA1.T"* 替换为 i8*(不透明指针)
new_mt = re.sub(r'%"[a-f0-9]+\.T"\*', 'i8*', new_mt)
# 将 %"SHA1.T"(非指针,如 embedded struct替换为 i8*
new_mt = re.sub(r'%"[a-f0-9]+\.T"', 'i8*', new_mt)
result.append(new_mt)
return result
def _llvm_type_size_str(self, type_str: str) -> int:
"""估算 LLVM 类型字符串的大小(字节),用于 REnum 变体大小比较
@@ -839,6 +995,18 @@ class DeclarationGenerator:
base: str = self._get_type_str(annotation.value)
if base == 'i8*' and isinstance(annotation.slice, ast.Constant):
return f'[{self._get_const_int(annotation.slice)} x i8]'
# 处理 t.CPtr[Type] 语法(指向 Type 的指针)
# 例如: t.CPtr[t.CPtr] -> i8** (void**), t.CPtr[t.CInt] -> i32* (int*)
# t.CPtr[t.CPtr[t.CInt]] -> i32** (int**)
ValueIsCPtr: bool = (
(isinstance(annotation.value, ast.Attribute) and annotation.value.attr == 'CPtr')
or (isinstance(annotation.value, ast.Name) and annotation.value.id == 'CPtr')
)
if ValueIsCPtr and isinstance(annotation.slice, (ast.Attribute, ast.Name, ast.Subscript)):
slice_type: str = self._get_type_str(annotation.slice, embedded=True)
if slice_type and slice_type != 'void':
return f'{slice_type}*'
return 'i8*'
if isinstance(annotation.slice, ast.Constant) and isinstance(annotation.slice.value, int):
return f'[{annotation.slice.value} x {base}]'
# 处理 t.CArray[elem_type, count] 注解 → [count x elem_type]