fix(gen): 泛型类构造复用 new 描述符存储,并支持泛型下标 callee
- _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 先特化模板拿具体类名,再走同一条取存储路径。
This commit is contained in:
1 parent
b6a9b50f93
commit
9ff5a3a03e
1 file changed
+24
-2
@@ -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
|
||||
|
||||
Reference in new issue
Block a user