fix(overload): _translate_method 补传 ClassDef,修复 undefined name cd
方法重载需要在类体内统计同名 def 才能决定是否追加 _v{hash},但 _translate_method 之前没有 ClassDef 参数。改为从 _translate_oop_methods 把 cd 传下去(两处调用点:sig_only 预扫描与正式翻译),未传时 _method_slot_name 退回原方法名,保持非重载路径行为不变。
This commit is contained in:
1 parent
51b30d3413
commit
af445058b4
1 file changed
+44
-44
@@ -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 <ret_ty> @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
|
||||
|
||||
Reference in new issue
Block a user