From 9ff5a3a03e686aa8b692a0414b41b488edcc7215 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 8 Oct 2026 21:04:41 +0800 Subject: [PATCH] =?UTF-8?q?fix(gen):=20=E6=B3=9B=E5=9E=8B=E7=B1=BB?= =?UTF-8?q?=E6=9E=84=E9=80=A0=E5=A4=8D=E7=94=A8=20new=20=E6=8F=8F=E8=BF=B0?= =?UTF-8?q?=E7=AC=A6=E5=AD=98=E5=82=A8=EF=BC=8C=E5=B9=B6=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=B3=9B=E5=9E=8B=E4=B8=8B=E6=A0=87=20callee?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - _translate_generic_ctor_call 之前一律 _alloca_at_entry:new memgr(pool) hlife list[int](...) 会忽略描述符给的内存、把对象构造到栈上、返回栈地址(静默悬垂)。改为与 _translate_struct_ctor 同款:tmp = _g_new_storage,为空才回落 alloca。 - _translate_new_expr 支持泛型下标 callee(Box[int]):新增 _specialize_new_generic_class 先特化模板拿具体类名,再走同一条取存储路径。 --- App/lib/core/Gen/Call/CallGenCtor.vp | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/App/lib/core/Gen/Call/CallGenCtor.vp b/App/lib/core/Gen/Call/CallGenCtor.vp index 845bf55..37e2499 100644 --- a/App/lib/core/Gen/Call/CallGenCtor.vp +++ b/App/lib/core/Gen/Call/CallGenCtor.vp @@ -325,6 +325,21 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if new_node.Source == ast.NEW_SRC_HEAP or new_node.Source == ast.NEW_SRC_DEFAULT: return 1 return 0 + # _specialize_new_generic_class - `new` 的 callee 是泛型下标(list[int])时先特化,返回具体类名。 + # §7.2/M4:`list`/`dict`/`hashtable` 从"类内 __new__ 从池取本体"迁到"调用点 new memgr(pool) …" + # 之后,构造点的 callee 就是下标形式,必须先特化才能拿到 struct 布局去取存储。 + def _specialize_new_generic_class(self, pool: memhub.MemBuddy*, func_node: ast.AST*, trans: HT.Translator*) -> str: + """`new … list[int](...)` → 特化模板并返回具体类名;不是已知泛型模板 → None""" + if pool is None or func_node is None or trans is None: return None + sub_node: ast.Subscript* = ast.Subscript*(func_node) + if sub_node.value is None or sub_node.value.kind() != ast.ASTKind.Name: return None + gen_nm: ast.Name* = ast.Name*(sub_node.value) + if gen_nm.id is None: return None + if self.Gen.ClassGenGeneric._find_generic_template(gen_nm.id) is None: return None + gen_type_args: list[str]* = self._extract_type_args_from_slice(pool, sub_node.slice, trans._from_imports) + if gen_type_args is None or len(gen_type_args) == 0: return None + return self.Gen.ClassGenGeneric._specialize_generic_class(trans, gen_nm.id, gen_type_args) + # _translate_new_expr - M2.4 `new [hlife|slife] [stack|heap|memgr(x)] T(args)`。 # 与既有值构造(T(args))唯一差别是"取存储"一步;其余序列(__before_init__ → __init__ / # 字段赋值)用合成 Call 走同一条路径,存储经 _g_new_storage 覆盖。结果恒为 T*。 @@ -351,6 +366,10 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): self.Gen.TypeGenErr.fatal_error(new_node, "`new stack hlife` is contradictory: a stack allocation can never outlive its frame; use `new stack slife` (the default for stack), or `heap`/`memgr(x)` for a longer lifetime", "LifetimeError") return None class_name: str = self.Gen.ExprGenBase.get_func_name(new_node.func) + # §7.2/M4:泛型容器 callee(`new memgr(pool) hlife list[int](...)`)——先特化模板拿具体类名, + # 再按普通类走同一条取存储路径(存储复用见 _translate_generic_ctor_call)。 + if class_name is None and new_node.func is not None and new_node.func.kind() == ast.ASTKind.Subscript: + class_name = self._specialize_new_generic_class(pool, new_node.func, trans) if class_name is None: self.Gen.TypeGenErr.fatal_error(new_node, "`new` requires a class type to construct (expected `new … T(args)`)", "TypeError") return None @@ -901,8 +920,11 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): # ensure the struct definition is available in this module (for alloca) self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, struct_ty) - # alloca tmp (self pointer) - tmp: mlirlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, struct_ty) + # 取存储:`new` 描述符已给出存储(memgr(pool)/heap/stack)就复用它,否则回落到入口块 + # alloca(普通 `T(...)` 构造的既有行为)。**这是 §7.2/M4 迁移的前提件**:没有它, + # `new memgr(pool) hlife list[int](...)` 会忽略描述符存储、构造到栈上并返回栈地址。 + tmp: mlirlite.Value* = _g_new_storage + if tmp is None: tmp = self.Gen.VarGen._alloca_at_entry(builder, struct_ty) if tmp is None: return None # Translate args into a pointer array (extra_args[slot]): positional args -> slots