From af445058b4b3db7b5021c83ef477b447535e00fc Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 24 Oct 2026 19:34:22 +0800 Subject: [PATCH] =?UTF-8?q?fix(overload):=20=5Ftranslate=5Fmethod=20?= =?UTF-8?q?=E8=A1=A5=E4=BC=A0=20ClassDef=EF=BC=8C=E4=BF=AE=E5=A4=8D=20unde?= =?UTF-8?q?fined=20name=20cd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 方法重载需要在类体内统计同名 def 才能决定是否追加 _v{hash},但 _translate_method 之前没有 ClassDef 参数。改为从 _translate_oop_methods 把 cd 传下去(两处调用点:sig_only 预扫描与正式翻译),未传时 _method_slot_name 退回原方法名,保持非重载路径行为不变。 --- App/lib/core/Gen/Class/ClassGenVTable.vp | 88 ++++++++++++------------ 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/App/lib/core/Gen/Class/ClassGenVTable.vp b/App/lib/core/Gen/Class/ClassGenVTable.vp index f5637ee..97351c8 100644 --- a/App/lib/core/Gen/Class/ClassGenVTable.vp +++ b/App/lib/core/Gen/Class/ClassGenVTable.vp @@ -54,34 +54,34 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): for i in name: if i == '.': return 1 return 0 - # _method_slot_name - 方法在函数表 / vtable 里的短名。 - # 类内同名方法 >=2 构成重载组时追加 "_v{参数签名hash}"(跳过 self);三者必须一致: - # 函数表键 "Class.m_v{hash}"、LLVM 符号 "{sha1}.Class.m_v{hash}"、vtable 槽名 "m_v{hash}"。 - def _method_slot_name(self, pool: memhub.MemBuddy*, trans: HT.Translator*, cd: ast.ClassDef*, fd: ast.FunctionDef*) -> str: - """方法短名(重载组带签名后缀);失败返回 None(已报错)""" - if fd is None or fd.name is None: return None - if cd is None or cd.children is None: return fd.name - if self.Gen.FuncGenDef._overload_name_count(cd.children, fd.name) < 2: return fd.name - if fd.type_params is not None: - self.Gen.TypeGenErr.fatal_error(fd, f"generic method '{fd.name}' cannot be overloaded (generic overloads are not supported)", "TypeError") - return None - # @staticmethod 没有 self;实例方法 / 类方法的第 0 个形参是 self,不参与签名 - skip_self: int = 1 - fm_s: int = self.Gen.ClassGenBase._extract_func_meta(fd.decorator_list) - if fm_s & GenTypes.META_STATIC != 0: skip_self = 0 - sig: str = self.Gen.FuncGenDef._overload_sig_text(pool, fd, trans, skip_self) - if sig is None: return None - h: str = TSpec.SpecSigHash16(sig) - stdlib.free(sig) - if h is None: return None - base_len: sizet = string.strlen(fd.name) - out: str = pool.alloc(base_len + 24) - if out is None: return None - viperlib.snprintf(out, base_len + 24, "%s_v%s", fd.name, h) - return out - - # _collect_vtable_methods - collect virtual methods (inherited first, then own) into the - # Vt* buffers and entry.VTableMethods/VTableMethodCount; returns 1 if any, else 0. + # _method_slot_name - 方法在函数表 / vtable 里的短名。 + # 类内同名方法 >=2 构成重载组时追加 "_v{参数签名hash}"(跳过 self);三者必须一致: + # 函数表键 "Class.m_v{hash}"、LLVM 符号 "{sha1}.Class.m_v{hash}"、vtable 槽名 "m_v{hash}"。 + def _method_slot_name(self, pool: memhub.MemBuddy*, trans: HT.Translator*, cd: ast.ClassDef*, fd: ast.FunctionDef*) -> str: + """方法短名(重载组带签名后缀);失败返回 None(已报错)""" + if fd is None or fd.name is None: return None + if cd is None or cd.children is None: return fd.name + if self.Gen.FuncGenDef._overload_name_count(cd.children, fd.name) < 2: return fd.name + if fd.type_params is not None: + self.Gen.TypeGenErr.fatal_error(fd, f"generic method '{fd.name}' cannot be overloaded (generic overloads are not supported)", "TypeError") + return None + # @staticmethod 没有 self;实例方法 / 类方法的第 0 个形参是 self,不参与签名 + skip_self: int = 1 + fm_s: int = self.Gen.ClassGenBase._extract_func_meta(fd.decorator_list) + if fm_s & GenTypes.META_STATIC != 0: skip_self = 0 + sig: str = self.Gen.FuncGenDef._overload_sig_text(pool, fd, trans, skip_self) + if sig is None: return None + h: str = TSpec.SpecSigHash16(sig) + stdlib.free(sig) + if h is None: return None + base_len: sizet = string.strlen(fd.name) + out: str = pool.alloc(base_len + 24) + if out is None: return None + viperlib.snprintf(out, base_len + 24, "%s_v%s", fd.name, h) + return out + + # _collect_vtable_methods - collect virtual methods (inherited first, then own) into the + # Vt* buffers and entry.VTableMethods/VTableMethodCount; returns 1 if any, else 0. def _collect_vtable_methods(self, trans: HT.Translator*, cd: ast.ClassDef*, class_name: str) -> int: """Collect virtual methods into entry.VTableMethods/VTableMethodCount.""" if trans is None or cd is None or class_name is None: return 0 @@ -237,12 +237,12 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): # stay loud rather than writing past the PermPool array. self.Gen.TypeGenErr.fatal_error(cd, f"internal error: vtable of '{class_name}' exceeded its computed capacity {vt_cap}", "InternalCompilerError") - mname: str = rawptr(slot_names[ci]) - if mname is None: mname = fd.name - # Skip constructors and special methods (they must not enter the vtable). - # 用 fd.name 判断:重载组的槽名带后缀,用槽名会漏判把 __init__ 塞进 vtable。 - if string.strcmp(fd.name, "__init__") == 0: continue - if string.strcmp(fd.name, "__before_init__") == 0: continue + mname: str = rawptr(slot_names[ci]) + if mname is None: mname = fd.name + # Skip constructors and special methods (they must not enter the vtable). + # 用 fd.name 判断:重载组的槽名带后缀,用槽名会漏判把 __init__ 塞进 vtable。 + if string.strcmp(fd.name, "__init__") == 0: continue + if string.strcmp(fd.name, "__before_init__") == 0: continue if string.strcmp(fd.name, "__new__") == 0: continue # Function-level decorator filter: decide whether the method belongs in the vtable. if self.Gen.ClassGenBase._should_method_be_virtual(cd, fd, trans) == 0: continue @@ -503,7 +503,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): if stmt_pd is None: continue if stmt_pd.kind() == ast.ASTKind.FunctionDef: fd_pd: ast.FunctionDef* = ast.FunctionDef*(stmt_pd) - if fd_pd is not None and fd_pd.name is not None: self._translate_method(trans, fd_pd, struct_ty, class_name, 1) + if fd_pd is not None and fd_pd.name is not None: self._translate_method(trans, fd_pd, struct_ty, class_name, 1, cd) for ci in range(int(cn)): stmt: ast.AST* = children.get(ci) @@ -517,7 +517,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): prev_nf: ast.AST* = self.Gen.StructGen.NllCurFunc self.Gen.StructGen.NllCurFunc = fd self.Gen.TypeGenBase.push_trace(tr_mf, fd.lineno) - self._translate_method(trans, fd, struct_ty, class_name) + self._translate_method(trans, fd, struct_ty, class_name, 0, cd) self.Gen.TypeGenBase.pop_trace() self.Gen.StructGen.NllCurFunc = prev_nf @@ -560,7 +560,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): return 0 # _translate_method - emit define @SHA1.ClassName.method_name(Ptr(StructTy) %self, ...). # self is registered as an SSA Ptr(struct_ty) value (no alloca) so self.field can GEP directly. - def _translate_method(self, trans: HT.Translator*, fd: ast.FunctionDef*, struct_ty: mlirlite.LLVMType*, class_name: str, sig_only: int = 0) -> int: + def _translate_method(self, trans: HT.Translator*, fd: ast.FunctionDef*, struct_ty: mlirlite.LLVMType*, class_name: str, sig_only: int = 0, cd: ast.ClassDef* = None) -> int: """Translate a single method; sig_only emits a forward declaration only.""" if trans is None or fd is None or struct_ty is None or class_name is None: return 0 @@ -594,13 +594,13 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): elif func_meta & GenTypes.META_PROP_DELETER != 0: mn_len2: sizet = string.strlen(method_name_buf) if mn_len2 + 5 < 128: string.strcat(method_name_buf, "$del") - method_name = method_name_buf - - # 重载:类内同名方法 >=2 时短名追加 "_v{签名hash}",使符号、函数表键与 vtable 槽名一致。 - # 属性 setter/deleter 已带 $set/$del 后缀,不参与重载。 - if func_meta & GenTypes.META_PROP_SETTER == 0 and func_meta & GenTypes.META_PROP_DELETER == 0: - slot_nm_m: str = self._method_slot_name(pool, trans, cd, fd) - if slot_nm_m is None: return 0 + method_name = method_name_buf + + # 重载:类内同名方法 >=2 时短名追加 "_v{签名hash}",使符号、函数表键与 vtable 槽名一致。 + # 属性 setter/deleter 已带 $set/$del 后缀,不参与重载。 + if func_meta & GenTypes.META_PROP_SETTER == 0 and func_meta & GenTypes.META_PROP_DELETER == 0: + slot_nm_m: str = self._method_slot_name(pool, trans, cd, fd) + if slot_nm_m is None: return 0 method_name = slot_nm_m is_static_m: int = 0