重置上传,新增了多个标准库,开始 TransPyV 自举实验
This commit is contained in:
@@ -8,6 +8,28 @@ import llvmlite.ir as ir
|
||||
|
||||
|
||||
class WithHandle(BaseHandle):
|
||||
def _ResolveInheritedMethod(self, ClassName: str, MethodName: str, Gen: "Translator.LlvmGen") -> tuple[str | None, "ir.Function | None"]:
|
||||
"""沿继承链查找方法,返回 (定义方法的类名, 函数对象)
|
||||
|
||||
当子类未覆写 __enter__/__exit__ 等方法时,沿 Gen.class_parent 链查找父类实现。
|
||||
_generate_inherited_method_wrappers 只为 class_methods[ClassName] 中的方法生成包装,
|
||||
不包括父类独有方法,因此 with 语句需要单独处理继承查找。
|
||||
"""
|
||||
# 先检查子类自身
|
||||
FullName: str = f'{ClassName}.{MethodName}'
|
||||
func = Gen._find_function(FullName) if hasattr(Gen, '_find_function') else Gen.functions.get(FullName)
|
||||
if func:
|
||||
return (ClassName, func)
|
||||
# 沿继承链查找
|
||||
p: str | None = Gen.class_parent.get(ClassName) if hasattr(Gen, 'class_parent') else None
|
||||
while p:
|
||||
parent_full: str = f'{p}.{MethodName}'
|
||||
parent_func = Gen._find_function(parent_full) if hasattr(Gen, '_find_function') else Gen.functions.get(parent_full)
|
||||
if parent_func:
|
||||
return (p, parent_func)
|
||||
p = Gen.class_parent.get(p)
|
||||
return (None, None)
|
||||
|
||||
def _HandleWithLlvm(self, Node: ast.With) -> None:
|
||||
Gen: "Translator.LlvmGen" = self.Trans.LlvmGen
|
||||
for item in Node.items:
|
||||
@@ -60,10 +82,16 @@ class WithHandle(BaseHandle):
|
||||
ctx_is_var_ref: bool = isinstance(context_expr, ast.Name)
|
||||
enter_result: ir.Value | None = None
|
||||
if ClassName:
|
||||
EnterFuncName: str = f'{ClassName}.__enter__'
|
||||
if EnterFuncName in Gen.functions:
|
||||
# 沿继承链查找 __enter__(子类可能未覆写,使用父类实现)
|
||||
enter_class, enter_func = self._ResolveInheritedMethod(ClassName, '__enter__', Gen)
|
||||
if enter_func is not None:
|
||||
ctx_Loaded: ir.Value = Gen._load(ctx_alloca, name="__with_ctx")
|
||||
enter_call: ir.CallInstr = Gen.builder.call(Gen.functions[EnterFuncName], [ctx_Loaded], name="call_enter")
|
||||
# 父类方法需要 self 为父类指针类型,bitcast 子类指针
|
||||
if enter_class != ClassName and enter_class in Gen.structs:
|
||||
parent_ptr_type = ir.PointerType(Gen.structs[enter_class])
|
||||
if ctx_Loaded.type != parent_ptr_type:
|
||||
ctx_Loaded = Gen.builder.bitcast(ctx_Loaded, parent_ptr_type, name="cast_enter_self")
|
||||
enter_call: ir.CallInstr = Gen.builder.call(enter_func, [ctx_Loaded], name="call_enter")
|
||||
enter_result = enter_call
|
||||
if isinstance(enter_call.type, ir.PointerType):
|
||||
pointee: ir.Type = enter_call.type.pointee
|
||||
@@ -139,10 +167,16 @@ class WithHandle(BaseHandle):
|
||||
if Gen._with_provides_stack:
|
||||
Gen._with_provides_stack.pop()
|
||||
if ClassName:
|
||||
ExitFuncName: str = f'{ClassName}.__exit__'
|
||||
if ExitFuncName in Gen.functions:
|
||||
# 沿继承链查找 __exit__(子类可能未覆写,使用父类实现)
|
||||
exit_class, exit_func = self._ResolveInheritedMethod(ClassName, '__exit__', Gen)
|
||||
if exit_func is not None:
|
||||
ctx_Loaded: ir.Value = Gen._load(ctx_alloca, name="__with_ctx")
|
||||
Gen.builder.call(Gen.functions[ExitFuncName], [ctx_Loaded], name="call_exit")
|
||||
# 父类方法需要 self 为父类指针类型,bitcast 子类指针
|
||||
if exit_class != ClassName and exit_class in Gen.structs:
|
||||
parent_ptr_type = ir.PointerType(Gen.structs[exit_class])
|
||||
if ctx_Loaded.type != parent_ptr_type:
|
||||
ctx_Loaded = Gen.builder.bitcast(ctx_Loaded, parent_ptr_type, name="cast_exit_self")
|
||||
Gen.builder.call(exit_func, [ctx_Loaded], name="call_exit")
|
||||
Gen._unregister_local_heap_ptr(original_ctx_val)
|
||||
if ctx_val is not original_ctx_val:
|
||||
Gen._unregister_local_heap_ptr(ctx_val)
|
||||
|
||||
Reference in New Issue
Block a user