From cca468e910befce2109f23f2b409aad5d10dc6cc Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 10 Aug 2026 21:48:42 +0800 Subject: [PATCH] =?UTF-8?q?feat(gen):=20=E5=AE=9E=E7=8E=B0=20super()=20?= =?UTF-8?q?=E8=AF=AD=E4=B9=89=EF=BC=88super().=5F=5Finit=5F=5F=20/=20super?= =?UTF-8?q?().method=20=E9=9D=99=E6=80=81=E7=BB=91=E5=AE=9A=E7=88=B6?= =?UTF-8?q?=E7=B1=BB=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 _translate_super_call:当前类取 self 变量注解类名(Mixin 字段 跨类偏移不一致的替代方案),沿 MRO 跳过自身找父类方法,静态调用 父类实现(不虚分派),this_adjust 字节偏移 + 参数 coerce - translate_call 拦截 super().method 形态 --- App/lib/core/Gen/CallGenMixin.vp | 206 +++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) diff --git a/App/lib/core/Gen/CallGenMixin.vp b/App/lib/core/Gen/CallGenMixin.vp index 3d20933..3645570 100644 --- a/App/lib/core/Gen/CallGenMixin.vp +++ b/App/lib/core/Gen/CallGenMixin.vp @@ -3728,6 +3728,199 @@ class CallGenMixin: is_variadic_3441: int = HandlesExprCall._check_and_promote_variadic_call(pool, builder, mod, call_name, head, total_count) return llvmlite.build_call(builder, call_name, head, total_count, call_ret_ty, is_variadic_3441) + # ============================================================ + # _translate_super_call — super().method(args) → 静态调用父类方法 + # + # Python super 语义(2026-08-10 实现): + # - 当前类来自 self.CurClassName(_translate_method 翻译方法体时设置) + # - 父类查找:沿 get_mro_chain(CurClassName) 跳过自身,找第一个定义 method 的祖先 + # - self 指针:符号表 self 变量 alloca load(对象头,复用 c.Addr(self) 模式) + # - this_adjust:父类字段区在子类中字节偏移 delta>0 时 GEP i8* + delta + # (复用 _field_byte_offset 字节偏移法,与 _translate_method_call 一致) + # - 静态调用父类实现:不虚分派(super() 不触发子类 override) + # ============================================================ + def _translate_super_call(self, pool: memhub.MemBuddy | t.CPtr, + builder: llvmlite.IRBuilder | t.CPtr, + mod: llvmlite.LLVMModule | t.CPtr, + cl: ast.Call | t.CPtr, + method_name: str, + trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr: + """super().method(args) → 父类方法静态调用,返回 call 结果 Value""" + if pool is None or builder is None or cl is None or method_name is None: + return None + if trans is None: + return None + # 1. 当前方法所属类:从 self 变量的注解类名获取(_translate_method + # 注册 self 时 set_var_annot_class_name(SymTab, "self", class_name))。 + # 不用 Mixin 字段:TPV Mixin 字段按声明类独立布局(Generator 多继承 + # 去重只保留首个声明),ClassGenMixin 写的 CurClassName 与 CallGenMixin + # 读的位置偏移不一致 → 运行时读到空 → super() 误报"只能在类方法内使用"。 + self_entry: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry( + trans.SymTab, "self") + if self_entry is None: + self_entry = HandlesVar.lookup_var_entry(trans.SymTab, "cls") + if self_entry is None: + HandlesType.fatal_error(cl, "super(): 当前作用域无 self 变量(静态方法内不可用)", "TypeError") + return None + cur_class: str = self_entry.AnnotClassName + if cur_class is None: + HandlesType.fatal_error(cl, "super() 只能在类方法内使用(self 无注解类名)") + return None + # 2. 沿 MRO 跳过自身,找第一个定义 method 的祖先类 + anc: str = None + mro_sp: t.CSizeT | t.CPtr = HandlesStruct.get_mro_chain(pool, cur_class) + mi_sp: int = 1 + while mro_sp is not None and mro_sp[mi_sp] != 0: + anc_sp: str = (str | t.CPtr)(t.CVoid(mro_sp[mi_sp], t.CPtr)) + if anc_sp is not None: + probe_sp: t.CChar | t.CPtr = pool.alloc(160) + if probe_sp is not None: + viperlib.snprintf(probe_sp, 160, "%s.%s", anc_sp, method_name) + if HandlesExprCall.find_func_global(probe_sp) is not None: + anc = anc_sp + break + mi_sp += 1 + if anc is None: + err_sp: t.CChar | t.CPtr = pool.alloc(256) + if err_sp is not None: + viperlib.snprintf(err_sp, 256, "super(): 当前类 %s 的父类链未定义方法 %s", + cur_class, method_name) + HandlesType.fatal_error(cl, err_sp, "TypeError") + HandlesType.fatal_error(cl, "super(): 父类链未定义方法", "TypeError") + return None + # 3. self 指针(self 变量 alloca load,复用 c.Addr(self) 模式) + if self_entry.Alloca is None or self_entry.Alloca.Ty is None: + HandlesType.fatal_error(cl, "super(): 当前作用域无 self 变量(静态方法内不可用)", "TypeError") + return None + self_ptr: llvmlite.Value | t.CPtr = None + match self_entry.Alloca.Ty: + case llvmlite.LLVMType.Ptr(inner1): + match inner1: + case llvmlite.LLVMType.Ptr(inner2): + obj_ty_sp: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, inner2) + self_ptr = llvmlite.build_load(builder, obj_ty_sp, self_entry.Alloca) + case _: + self_ptr = llvmlite.build_load(builder, self_entry.Alloca.Ty, self_entry.Alloca) + case _: + self_ptr = self_entry.Alloca + if self_ptr is None: + return None + # 3. this_adjust(字节偏移法:父类字段区在子类中的偏移差) + self_arg: llvmlite.Value | t.CPtr = self_ptr + if string.strcmp(anc, cur_class) != 0: + anc_entry_sp: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(anc) + if anc_entry_sp is not None and anc_entry_sp.FieldCount > 0: + first_name_sp: str = None + afi_sp: int = 0 + while afi_sp < anc_entry_sp.FieldCount: + afe_sp: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry( + anc_entry_sp, afi_sp) + if afe_sp is not None: + afn_sp: str = HandlesStruct.get_field_name_ptr(afe_sp) + if afn_sp is not None and string.strcmp(afn_sp, "__vtable__") != 0: + first_name_sp = afn_sp + break + afi_sp += 1 + if first_name_sp is not None: + sub_entry_sp: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct( + cur_class) + if sub_entry_sp is not None: + anc_field_sp: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct.lookup_field( + anc_entry_sp.Ty, first_name_sp) + sub_field_sp: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct.lookup_field( + sub_entry_sp.Ty, first_name_sp) + if anc_field_sp is not None and sub_field_sp is not None: + anc_off_sp: int = self._field_byte_offset( + pool, anc_entry_sp, anc_field_sp.Index) + sub_off_sp: int = self._field_byte_offset( + pool, sub_entry_sp, sub_field_sp.Index) + delta_sp: int = sub_off_sp - anc_off_sp + if delta_sp > 0: + i8_ty_sp: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) + i8_ptr_sp: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_sp) + obj_i8_sp: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( + builder, self_ptr, i8_ptr_sp) + dval_sp: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, delta_sp) + adj_sp: llvmlite.Value | t.CPtr = llvmlite.build_gep( + builder, i8_ty_sp, obj_i8_sp, dval_sp) + if adj_sp is not None: + anc_ptr_sp: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, anc_entry_sp.Ty) + self_arg = llvmlite.build_bitcast(builder, adj_sp, anc_ptr_sp) + # 4. 查找父类方法函数 + 构造调用名(SHA1 mangled) + anc_lookup: t.CChar | t.CPtr = pool.alloc(160) + if anc_lookup is None: + return None + viperlib.snprintf(anc_lookup, 160, "%s.%s", anc, method_name) + found_func: llvmlite.Function | t.CPtr = self.find_func_in_module(mod, anc_lookup) + call_name: str = anc_lookup + anc_sha1_sp: str = HandlesStruct.get_struct_sha1(anc) + if anc_sha1_sp is None: + anc_sha1_sp = trans.ModuleSha1 + if found_func is not None: + fname_sp: t.CChar | t.CPtr = llvmlite.function_get_name(found_func) + if fname_sp is not None: + call_name = fname_sp + else: + if anc_sha1_sp is not None: + mangled_sp: str = HandlesFunctions._mangle_name_with_sha1(anc_sha1_sp, anc_lookup) + if mangled_sp is not None: + call_name = mangled_sp + # 5. 翻译参数 + 按形参 coerce(self 是形参 0,第 ai 个实参对应形参 ai+1) + cargs_sp: list[ast.AST | t.CPtr] | t.CPtr = cl.args + can_sp: t.CSizeT = 0 + if cargs_sp is not None: + can_sp = cargs_sp.__len__() + llvmlite.value_set_next(self_arg, None) + head: llvmlite.Value | t.CPtr = self_arg + tail: llvmlite.Value | t.CPtr = self_arg + arg_count_sp: int = 1 + for ai_sp in range(can_sp): + arg_node_sp: ast.AST | t.CPtr = cargs_sp.get(ai_sp) + if arg_node_sp is None: + continue + arg_val_sp: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( + builder, pool, mod, arg_node_sp, None, 0, trans) + if arg_val_sp is None: + continue + if found_func is not None: + pp_sp: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func) + pi_sp: int = 0 + while pp_sp is not None and pi_sp < ai_sp + 1: + if pi_sp == ai_sp + 1: + break + pp_sp = llvmlite.param_get_next(pp_sp) + pi_sp += 1 + if pp_sp is not None: + pty_sp: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(pp_sp) + if pty_sp is not None: + arg_val_sp = HandlesExpr.coerce_to_type( + builder, arg_val_sp, pty_sp, arg_node_sp) + llvmlite.value_set_next(arg_val_sp, None) + llvmlite.value_set_next(tail, arg_val_sp) + tail = arg_val_sp + arg_count_sp += 1 + # 6. 返回类型:found_func → 特殊方法 → text.ll/vpi + ret_ty_sp: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) + if found_func is not None: + frt_sp: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(found_func) + if frt_sp is not None: + ret_ty_sp = frt_sp + else: + sp_ty_sp: llvmlite.LLVMType | t.CPtr = self._special_method_ret_ty(pool, anc, method_name) + if sp_ty_sp is not None: + ret_ty_sp = sp_ty_sp + else: + looked_sp: llvmlite.LLVMType | t.CPtr = self._LookupMethodRetTyFromTextLL( + pool, anc_sha1_sp, anc, method_name) + if looked_sp is not None: + ret_ty_sp = looked_sp + # 7. 跨模块:创建 declare;生成 call + if found_func is None: + self._ensure_method_declare(pool, mod, call_name, ret_ty_sp, head, arg_count_sp) + is_variadic_sp: int = HandlesExprCall._check_and_promote_variadic_call( + pool, builder, mod, call_name, head, arg_count_sp) + return llvmlite.build_call(builder, call_name, head, arg_count_sp, ret_ty_sp, is_variadic_sp) + # ============================================================ # _field_byte_offset — 计算字段在结构体布局中的字节偏移 # @@ -4392,6 +4585,19 @@ class CallGenMixin: return None func_name: str = HandlesExpr.get_func_name(cl.func) + # super() 语义(2026-08-10):super().method(args) → 静态调用父类方法 + # 形态: Call(func=Attribute(value=Call(func=Name('super')), attr=method)) + # 必须在 Attribute 分派前拦截——否则 value 的 Call(super) 被 translate_value + # 当作普通函数调用报错,且走普通属性调用会命中自身/虚分派而非父类实现。 + if func_name is not None and cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: + sup_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) + if sup_at.value is not None and sup_at.value.kind() == ast.ASTKind.Call: + sup_cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(sup_at.value) + if sup_cl.func is not None and sup_cl.func.kind() == ast.ASTKind.Name: + sup_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sup_cl.func) + if sup_nm.id is not None and string.strcmp(sup_nm.id, "super") == 0: + return self._translate_super_call( + pool, builder, mod, cl, func_name, trans) if func_name is None: # 检查是否是 list[int](pool) 形式的泛型实例化调用 # Subscript 节点作为 Call func: 泛型类构造函数