fix(classgen): 方法预扫描补 pre_scan_scope_decls,修复 global 名被当局部

方法(method)预扫描只调 pre_scan_allocas,漏调 pre_scan_scope_decls(模块级
函数路径 FuncGenDef 是先 scope_decls 再 allocas)。导致 global BootInfo 未
注册时 prescan 把 BootInfo 当局部创建 alloca(define_var 注册局部),后续翻译
is_global_name 为真又写全局 → 局部 alloca 永不写入 → 读全 0(main.vp __init__
BootInfo memmap 全 0 根因)。

修复:方法预扫描先 pre_scan_scope_decls 注册 global/nonlocal,再 pre_scan_allocas,
与 FuncGenDef/FuncGenMixin 路径对齐。
This commit is contained in:
TermiNexus committed 2026-08-26 19:30:31 +08:00
1 parent 53c72ff57a
commit 9f19673072
1 file changed
+13 -5
+13 -5
View File
@@ -719,9 +719,9 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
ret_ty: llvmlite.LLVMType | t.CPtr = None
if fd.returns is not None:
ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, fd.returns, imported_modules, from_imports, trans)
pool, fd.returns, imported_modules, from_imports, trans, 0)
if ret_ty is None and fd.returns is not None:
if self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State") != 0:
if self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0) != 0:
ret_ty = llvmlite.Void(pool)
if ret_ty is None:
# __init__ 和 __before_init__ 返回 void
@@ -800,7 +800,7 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
param_ty: llvmlite.LLVMType | t.CPtr = i32_ty
if arg.annotation is not None:
resolved: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, arg.annotation, imported_modules, from_imports, trans)
pool, arg.annotation, imported_modules, from_imports, trans, 0)
if resolved is not None:
# 裸类形参 → Ptr(struct):按"对象即指针"引用传参。
# 若按 struct 值传参,self.Head = node 会取局部拷贝地址
@@ -944,7 +944,7 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
param_ty2: llvmlite.LLVMType | t.CPtr = i32_ty
if arg2.annotation is not None:
resolved2: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, arg2.annotation, imported_modules, from_imports, trans)
pool, arg2.annotation, imported_modules, from_imports, trans, 0)
if resolved2 is None:
# fail-fast:参数有注解但类型解析失败,不再静默保持 i32
self.Gen.TypeGenErr.fatal_error(
@@ -1009,9 +1009,17 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
HT.clear_scope_names(trans)
# 预扫描方法体:为局部变量提前创建 alloca
# 必须先预扫描 Global/Nonlocal 声明(对齐 FuncGenDef 模块级函数路径),
# 否则 `global BootInfo` 未注册时 prescan 把 BootInfo 当局部创建 alloca,
# 后续翻译 is_global_name 为真又写全局 → 局部 alloca 永不写入 → 读全 0
# (main.vp __init__ BootInfo memmap 全 0 根因)。
body: list[ast.AST | t.CPtr] | t.CPtr = fd.children
if body is not None:
bn: t.CSizeT = len(body)
for bi in range(bn):
stmt: ast.AST | t.CPtr = body.get(bi)
if stmt is not None:
self.Gen.StmtGenDecl.pre_scan_scope_decls(trans, stmt)
for bi in range(bn):
stmt: ast.AST | t.CPtr = body.get(bi)
if stmt is not None:
@@ -1261,7 +1269,7 @@ class ClassGenVTable(ClassGenBase.ClassGenBase):
# 静态数组字段 + 列表字面量默认值 → 整体置零 + 逐元素 GEP+store
# (与局部 AnnAssign 数组初始化一致;translate_value 会把列表字面量
# 误译成动态 list 对象指针,coerce 到 [N x elem] 会失败)。
# 单参 CArray 字段(如 t.CArray[str] = ["py", ...])经类体字段收集
# 单参 CArray 字段(如 t.CArray[str] = [...])经类体字段收集
# 推断为静态数组,此处保证 __before_init__ 填充真实字符串指针。
if fe.Ty is not None and self.Gen.ExprGenBase.is_array_type(fe.Ty) != 0 \
and fe.DefaultVal.kind() == ast.ASTKind.List: