重置上传,新增了多个标准库,开始 TransPyV 自举实验
This commit is contained in:
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user