- StubMergerStore 新增共享导入上下文记账(AppendImportedModule / AppendFromImport / ImportCtx / AllocImportCtx / NotePlainImport),ImportsGenMixin 与 VpiReader 共用同一份 口径;顺带移除 add_from_import 的 256 缓冲静默截断,VpiReader 删除两份私有副本 - 注入窗口按「名字归属」判据解析(is_module_class + CurDefModuleSha1): _forward_declare_ptr_from_node 的 Name 分支、resolve_annotation_type 的 Name/Attribute 分支均补齐,使同一 stub 内先声明/先引用的类产出**具名占位**而不是 Ptr(i8),并新增 _is_tattr_marker 让 t.attr.* 属性标记不参与类型联合竞争 - VpiReader._inject_class_struct_declare:命中前向声明占位时不再早退,改为「占位 Ty 原地写入」(对齐 ClassGenDef.fill_fwd),修 StructTable 爆表(table full, cannot register Translator) - 清除全部一次性探针:[DBG-GEN](VpiReader / StructGenMixin / ClassGenDef)、 [DBG-ATTR](ExprGenAttr)、[MODSHA1](CallGenMixin) 根因记录:vpi 注入期漏记 `import X as Y -> from_imports "Y:X"`,使 GenTypes.VarEntry.Spec (TSpec.TypeSpec | t.CPtr)取不到模块 SHA1、退化为 i8* 并被永久冻结 (CallGenCtor.vp:897 .PtrLevel 属性访问失败)。
753 lines
47 KiB
Plaintext
753 lines
47 KiB
Plaintext
import lib.core.Gen.GenTypes as GenTypes
|
||
import t, c
|
||
from stdint import *
|
||
import ast
|
||
import llvmlite
|
||
import memhub
|
||
import string
|
||
import stdio
|
||
import viperlib
|
||
import lib.core.VLogger as VLogger
|
||
import lib.core.Gen.Translator as HT
|
||
import lib.core.CompilerFactory as CompilerFactory
|
||
|
||
from . import ClassGenBase
|
||
|
||
|
||
# ============================================================
|
||
# ClassGenDef - ClassGenMixin 拆分(阶段 D):translate_class_def 主入口
|
||
# ============================================================
|
||
novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
|
||
"""translate_class_def 主入口"""
|
||
|
||
# ============================================================
|
||
# translate_class_def — 翻译 class 定义(簇 D)
|
||
# ============================================================
|
||
def translate_class_def(self, trans: HT.Translator*,
|
||
node: ast.AST*) -> int:
|
||
"""翻译 class 定义,返回 0"""
|
||
if node is None or trans is None: return 0
|
||
|
||
cd: ast.ClassDef* = ast.ClassDef*(node)
|
||
if cd is None or cd.name is None: return 0
|
||
|
||
pool: memhub.MemBuddy* = trans.Pool
|
||
class_name: str = cd.name
|
||
|
||
if trans.ModuleSha1 is None:
|
||
# fail-fast:翻译类时模块 SHA1 缺失(命名空间隔离依赖它)——
|
||
VLogger.error("翻译类时 ModuleSha1 缺失", "CLASS")
|
||
self.Gen.TypeGenErr.fatal_error(cd, "翻译类时 ModuleSha1 缺失", "TypeError")
|
||
|
||
# 命名空间隔离:标记为当前文件可见(必须在 existing 检查之前,
|
||
# 因为 Phase B 时结构体已注册会提前 return,否则永远无法标记本地类)
|
||
self.Gen.StructGen.add_visible_struct(pool, class_name)
|
||
# 登记"本模块声明了这个类"(键 "{SHA1}.{类名}",与 struct 注册状态无关):
|
||
# 泛型类型实参命名规范化(TypeGenResolve._norm_type_arg_name 规则 5.5)据此
|
||
# 判定裸类名归属 —— 类体里的**自引用**(如 includes/ast/base.vp
|
||
# `AST.children: list[rawptr[AST]]`)解析时本类尚未 register_struct,
|
||
# 只查注册表会留在裸名 ⇒ 与后续带 SHA1 的形式分裂成两个特化名。
|
||
self.Gen.StructGen.mark_module_class(pool, trans.ModuleSha1, class_name)
|
||
|
||
# 枚举类:交给 HandlesEnum 处理
|
||
# 分派歧义检测(fail-fast):REnum 优先于 CEnum/CUnion。若某类同时被判为枚举,
|
||
# 说明被 `_is_enum_class` 抢先截胡 → 走 _translate_enum_def ⇒ 变体表永不注册
|
||
# ⇒ _is_renum_class_name 恒 0、变体构造拿不到 tag。两者语义互斥,禁止静默按枚举处理。
|
||
if self.Gen.ClassGenBase._is_enum_class(cd, trans) == 1:
|
||
if self.Gen.ClassGenBase._is_renum_class(cd, trans) == 1:
|
||
self.Gen.TypeGenErr.fatal_error(
|
||
cd,
|
||
f"类 '{class_name}' 同时被判定为 CEnum 与 REnum(分派歧义),"
|
||
f"REnum 变体表将无法注册",
|
||
"TypeError")
|
||
return self.Gen.ClassGenEnum._translate_enum_def(trans, cd)
|
||
|
||
# 联合体类:交给联合体处理
|
||
if self.Gen.ClassGenBase._is_union_class(cd, trans) == 1:
|
||
return self.Gen.ClassGenEnum._translate_union_def(trans, cd)
|
||
|
||
# REnum 类:交给 REnum 处理({i32 tag, max_payload} 布局)
|
||
if self.Gen.ClassGenBase._is_renum_class(cd, trans) == 1:
|
||
return self.Gen.ClassGenEnum._translate_renum_def(trans, cd)
|
||
|
||
# 泛型类:存储为模板,不发射 IR(等实例化时特化)
|
||
# 用局部变量接收 cd.type_params,触发类型推断
|
||
tp_val: list[str]* = cd.type_params
|
||
if self.Gen.ClassGenGeneric._is_generic_class(tp_val) == 1:
|
||
self.Gen.ClassGenGeneric._register_generic_template(pool, cd, trans.ModuleSha1)
|
||
return 0
|
||
|
||
# 异常类(try-except):注册编码+继承树,不生成 struct
|
||
# (对齐 TPC HandlesClassDef.py L509-511:_is_exception_class →
|
||
# _RegisterExceptionClass → return,异常类不编译为结构体)
|
||
if self.Gen.ClassGenBase._is_exception_class_def(cd) == 1:
|
||
return self.Gen.ClassGenBase._register_exception_class_def(trans, cd)
|
||
|
||
# 嵌套类 / 嵌套 struct:类体里再写 class / struct 此前被**静默丢弃**
|
||
# (字段循环只认 AnnAssign、_translate_oop_methods 只认 FunctionDef),
|
||
# 现按既有扁平命名先例发射为独立结构体 `{外类}_{内类}`(与 TPC 的
|
||
# union/renum 嵌套命名 `{ClassName}_{Nested}` 同源)。
|
||
# 放在此处(enum/union/renum/泛型/异常分派之后、existing 检查之前):
|
||
# 位于**所有提前 return 之前**,故 declare_only=1/0 两条路径都会递归;
|
||
# 而 REnum/union 的嵌套类已由各自分支按"变体"处理并提前 return,不会重复发射。
|
||
self._translate_nested_classdefs(trans, cd)
|
||
|
||
# 检查是否已注册(用 SHA1 区分跨模块同名类)
|
||
existing: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(class_name, trans.ModuleSha1)
|
||
# 空类注册不完整检测:existing FieldCount==0 但源类体声明了字段(vpi 注入/注册缺陷)。
|
||
# 标记 _deps_pending 延迟会让空 entry 持久存在、多遍死锁不收敛 ⇒ 改为中和旧 entry
|
||
# (置空 Name + Ty=None,使 find_struct_by_module 不再命中),走下方完整注册路径重建。
|
||
needs_rereg: int = 0
|
||
# 前向声明占位命中:本类此前被"指向未注册类的指针"注解按名字前向声明过
|
||
# (StructGenMixin.ensure_forward_class 建了 {sha}.Class 不透明占位)。
|
||
# 此处**不早退**,走下方"原位填充"分支——把字段体写进同一个 Ty 对象,
|
||
# 保住指针身份,使所有已发出的 Ptr(占位.Ty) 引用(如 CallGenBase.Gen)
|
||
# 在填充后自动指向完整定义(对齐 TPC 的 opaque 占位 + set_body 填充)。
|
||
fill_fwd: int = 0
|
||
if existing is not None:
|
||
if existing.IsForwardDecl != 0:
|
||
fill_fwd = 1
|
||
elif existing.FieldCount == 0 and trans._declare_only == 0:
|
||
if self.Gen.ClassGenBase._class_body_has_field(cd) != 0:
|
||
if existing.Name is not None:
|
||
existing.Name[0] = '\0'
|
||
existing.Ty = None
|
||
existing.FieldCount = 0
|
||
needs_rereg = 1
|
||
if existing is not None and needs_rereg == 0 and fill_fwd == 0:
|
||
# 结构体已注册(Phase A-pre 多遍扫描或 Phase B 重新翻译),但仍需在当前模块中翻译方法
|
||
if existing.Ty is not None:
|
||
# Phase 1b(declare_only=0):existing.Ty 是 Phase 1a 注册的 struct_ty,
|
||
# 其 Name(如 "sha1.ClassName")指向 Phase 1a 的 pool 内存。虽然 mark1
|
||
# 之前分配不被 reset 回收,但 struct_ty 会被后续文件翻译引用(vtable/
|
||
# self 参数类型打印),部分实现下 pool 块被复用导致 Name 悬空崩溃。
|
||
# 保险起见:深拷贝 Name 到 stdlib,确保跨文件永久存活。
|
||
if trans._declare_only == 0:
|
||
# 深拷贝整个 existing.Ty 到 stdlib:1a pool Ty 跨 1b reset 悬空,
|
||
# _ensure_field_types_in_module 遍历悬空字段 ParamNode 链表
|
||
# 读悬空挂起(G3 LinkedNode.prepend 挂起根因)。DeepCopyType
|
||
# 递归深拷贝字段链表/子类型/Name 到 stdlib(深度上限+链守卫)。
|
||
ty_deep: llvmlite.LLVMType* = llvmlite.DeepCopyType(CompilerFactory.factory.PermPool, existing.Ty)
|
||
if ty_deep is not None:
|
||
existing.Ty = ty_deep
|
||
old_name: str = llvmlite.get_struct_name(existing.Ty)
|
||
if old_name is not None:
|
||
on_len: sizet = string.strlen(old_name)
|
||
on_copy: str = CompilerFactory.factory.PermPool.alloc(on_len + 1)
|
||
if on_copy is not None:
|
||
string.strcpy(on_copy, old_name)
|
||
# in-place 覆盖所指 REnum 值(保留 existing.Ty 的指针同一性:
|
||
# Phase A 已把它登记进 named-type 表,换指针旧条目仍指向悬空
|
||
# Name)。REnum 变体构造返回 **boxed 指针**,`*槽 = <boxed 变体>`
|
||
# 属「构造物化」(boxed 指针 → 值槽的整对象拷贝,语义即
|
||
# load+store),按严格规则③的构造物化例外放行——与
|
||
# c.DerefAs(ptr, <boxed 变体>) 等价,用 * 写法更直白。
|
||
*existing.Ty = llvmlite.LLVMType.Struct(llvmlite.get_struct_fields(existing.Ty), llvmlite.get_struct_fcount(existing.Ty), on_copy)
|
||
# Phase B: 将已存在的命名结构体注册到当前模块(输出类型定义行)
|
||
llvmlite.module_add_named_type(trans.Module, pool, existing.Ty)
|
||
# B5:existing 路径(Phase B 已注册类)同样需设置 packed/aligned——
|
||
# Phase A 注册时虽已设置,但 Phase B 重新 add_named_type 后节点
|
||
# IsPacked=0,打印输出 `{...}`(idt_entry packed 未生效根因)。
|
||
if self.Gen.ClassGenBase._class_has_tattr(cd.decorator_list, "packed") != 0:
|
||
llvmlite.module_set_named_type_packed(trans.Module, pool, existing.Ty, 1)
|
||
# StructTable 每 Phase 可能重建(existing 是 Phase B 新 entry),
|
||
# 必须补设 IsPacked——否则跨模块 stub 注入(ensure_struct_def
|
||
# _in_module)按 entry.IsPacked 判定 packed 时读 0 → stub 非 packed。
|
||
existing.IsPacked = 1
|
||
align_ex: int = self.Gen.ClassGenBase._class_aligned_value(cd.decorator_list)
|
||
if align_ex > 0 and existing.Align == 0:
|
||
existing.Align = align_ex
|
||
# Phase A-pre(declare_only=1)多遍扫描时,类已注册但不应翻译方法体
|
||
# Phase B(declare_only=0)时全量翻译方法体
|
||
if trans._declare_only == 1:
|
||
self.Gen.ClassGenVTable._translate_oop_methods(trans, cd, existing.Ty, class_name, 1)
|
||
else:
|
||
self.Gen.ClassGenVTable._translate_oop_methods(trans, cd, existing.Ty, class_name)
|
||
# SHA1 已在 register_struct 时设置,无需再补
|
||
return 0
|
||
|
||
# ============================================================
|
||
# 触发 base 中 Subscript 的泛型特化(如 GSListNode[Value])
|
||
# 必须在 _detect_vtable_status 和父类字段继承之前调用,
|
||
# 否则 find_struct_by_module("GSListNode[Value]") 返回 None
|
||
# ============================================================
|
||
self.Gen.ClassGenBase._trigger_base_specialization(trans, cd)
|
||
|
||
# ============================================================
|
||
# VTable 检测:判断是否启用虚表
|
||
# ============================================================
|
||
has_vtable: int = self.Gen.ClassGenBase._detect_vtable_status(cd, trans)
|
||
parent_name: str = self.Gen.ClassGenBase._get_parent_class(cd, trans)
|
||
# 多继承:收集所有真实父类名(跳过 marker base),供字段展平/vtable/MRO 使用
|
||
parents_buf: sizet* = pool.alloc(8 * GenTypes.PARENT_MAX)
|
||
parents_count: int = 0
|
||
if parents_buf is not None:
|
||
parents_count = self.Gen.ClassGenBase._collect_parents(pool, cd, parents_buf, GenTypes.PARENT_MAX, trans)
|
||
is_novtable_deco: int = 0
|
||
if cd.decorator_list is not None:
|
||
if self.Gen.ClassGenBase._has_decorator(cd.decorator_list, "NoVTable") == 1:
|
||
is_novtable_deco = 1
|
||
|
||
# ============================================================
|
||
# PhaseA 预注册延迟检查:父类未注册时延迟注册当前类
|
||
#
|
||
# 根因:AssignHandle(HandlesBase.Mixin) 有自己的字段 _CurrentClass,
|
||
# 当 Mixin 未注册时(字母序:HandlesAssign.py 在 HandlesBase.py 之前),
|
||
# field_count=1(不是0),field_count==0 静默返回不触发,
|
||
# AssignHandle 被注册为只有 _CurrentClass 字段(缺 Trans)。
|
||
# 后续遍 existing is not None,不补字段 → attribute ptr is None: self.Trans
|
||
#
|
||
# 修复:declare_only==1 且父类未注册时,延迟注册到下一遍。
|
||
# 多遍 PhaseA-pre 会在后续遍中重试(父类已注册后完整注册)。
|
||
# Phase B(declare_only==0)不延迟,避免死锁。
|
||
# ============================================================
|
||
if trans._declare_only == 1 and parent_name is not None:
|
||
parent_check: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(parent_name, trans.ModuleSha1)
|
||
if parent_check is None:
|
||
parent_check = self.Gen.StructGen.find_struct(parent_name)
|
||
if parent_check is None:
|
||
return 0
|
||
|
||
# ============================================================
|
||
# 1. 遍历 class body,收集字段信息
|
||
# ============================================================
|
||
# 用 CSizeT 数组存储指针值(64 位系统上 8 字节)
|
||
field_names_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX)
|
||
field_types_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX)
|
||
field_defaults_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX)
|
||
field_annot_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX)
|
||
# 字段 volatile 标记缓冲(1=字段注解联合含 t.CVolatile);与 field_annot_buf
|
||
# 并行,取值 0/1(sizet 数组复用,避免另设类型)。
|
||
field_volatile_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX)
|
||
# 字段「所指物 volatile」标记缓冲(1=字段注解为 rawptr[t.CVolatile | T],
|
||
# 等价 C 的 volatile T*);与 field_volatile_buf 并行,取值 0/1。
|
||
field_pointee_volatile_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX)
|
||
# 字段 const 对象标记缓冲(1=字段注解含 t.CConst 且字段类型非指针);
|
||
# 与 field_volatile_buf 并行,取值 0/1。
|
||
field_const_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX)
|
||
if field_names_buf is None or field_types_buf is None or field_defaults_buf is None:
|
||
return 0
|
||
if field_annot_buf is None or field_volatile_buf is None:
|
||
return 0
|
||
if field_pointee_volatile_buf is None or field_const_buf is None:
|
||
return 0
|
||
string.memset(field_names_buf, 0, 8 * GenTypes.FIELD_MAX)
|
||
string.memset(field_types_buf, 0, 8 * GenTypes.FIELD_MAX)
|
||
string.memset(field_defaults_buf, 0, 8 * GenTypes.FIELD_MAX)
|
||
string.memset(field_annot_buf, 0, 8 * GenTypes.FIELD_MAX)
|
||
string.memset(field_volatile_buf, 0, 8 * GenTypes.FIELD_MAX)
|
||
string.memset(field_pointee_volatile_buf, 0, 8 * GenTypes.FIELD_MAX)
|
||
string.memset(field_const_buf, 0, 8 * GenTypes.FIELD_MAX)
|
||
|
||
field_count: int = 0
|
||
|
||
# ============================================================
|
||
# 1.5 继承父类字段(字段展平)
|
||
# ============================================================
|
||
#
|
||
# 父类字段排在子类字段之前,结构体布局:
|
||
# [vtable_ptr?, parent_field1, ..., child_field1, ...]
|
||
# 跳过父类的 __vtable__ 字段(子类会有自己的 vtable 指针)
|
||
# ============================================================
|
||
# 多继承字段展平:遍历所有父类(声明顺序),字段名去重(先声明优先)
|
||
if parents_count > 0 and parents_buf is not None:
|
||
for pi in range(parents_count):
|
||
pname_addr: sizet = parents_buf[pi]
|
||
if pname_addr == 0: continue
|
||
pname: str = rawptr(pname_addr)
|
||
if pname is None: continue
|
||
# 用 SHA1 感知查找父类,规避跨模块同名找错
|
||
parent_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(pname, trans.ModuleSha1)
|
||
if parent_entry is None:
|
||
# 父类可能定义在另一个模块(不同 SHA1,如 HandlesBase.Mixin),
|
||
# find_struct_by_module 不回退全局查找,此处手动回退到 find_struct,
|
||
# 否则子类无法继承父类字段 → field_count==0 → __sizeof__ 失败
|
||
parent_entry = self.Gen.StructGen.find_struct(pname)
|
||
if parent_entry is None:
|
||
# 父类尚未注册(Phase A 按文件序,子类模块可能先于父类模块):此时
|
||
# **不能**继续注册——StructTable 在 StdlibAlloc=1 时用 perm_pool 分配,
|
||
# 残缺条目跨 pass 存活,后续 pass 的 existing 早退永远无法修复 → 子类
|
||
# __init__ 写父类字段每遍永久失败。整类 defer(不注册);模块级变量/函数
|
||
# 参数解析失败静默降级 i32,不致命。
|
||
return 0
|
||
pfc: int = parent_entry.FieldCount
|
||
for pfi in range(pfc):
|
||
pfe: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(parent_entry, pfi)
|
||
if pfe is None: continue
|
||
pfn: str = self.Gen.StructGen.get_field_name_ptr(pfe)
|
||
if pfn is None: continue
|
||
# 跳过父类的 vtable 指针字段
|
||
if string.strcmp(pfn, "__vtable__") == 0: continue
|
||
# 多继承去重:字段名已存在跳过(先声明父类优先)
|
||
if self.Gen.ClassGenBase._field_name_exists(field_names_buf, field_count, pfn) != 0: continue
|
||
if field_count < GenTypes.FIELD_MAX:
|
||
pft: llvmlite.LLVMType* = self.Gen.StructGen.get_field_type_ptr(pfe)
|
||
pfd: ast.AST* = self.Gen.StructGen.get_field_default_ptr(pfe)
|
||
pfa: str = self.Gen.StructGen.get_field_annot_class_name(pfe)
|
||
field_names_buf[field_count] = sizet(pfn)
|
||
field_types_buf[field_count] = sizet(pft)
|
||
if pfd is not None:
|
||
field_defaults_buf[field_count] = sizet(pfd)
|
||
else:
|
||
field_defaults_buf[field_count] = 0
|
||
if pfa is not None:
|
||
stored_val: sizet = sizet(pfa)
|
||
field_annot_buf[field_count] = stored_val
|
||
else:
|
||
field_annot_buf[field_count] = 0
|
||
# 继承父类字段的 volatile 标记(字段展平后语义不变)
|
||
field_volatile_buf[field_count] = sizet(pfe.IsVolatile)
|
||
# 继承父类字段的「所指物 volatile」标记(展平后语义不变)
|
||
field_pointee_volatile_buf[field_count] = sizet(pfe.PointeeVolatile)
|
||
# 继承父类字段的 const 对象标记(展平后语义不变)
|
||
field_const_buf[field_count] = sizet(pfe.IsConst)
|
||
field_count += 1
|
||
|
||
children: list[ast.AST*]* = cd.children
|
||
if children is None:
|
||
return 0
|
||
|
||
cn: sizet = len(children)
|
||
for ci in range(cn):
|
||
stmt: ast.AST* = children.get(ci)
|
||
if stmt is None: continue
|
||
sk: int = stmt.kind()
|
||
|
||
if sk != ast.ASTKind.AnnAssign: continue
|
||
|
||
# AnnAssign(target=Name(id), annotation=type, value=...)
|
||
aa: ast.AnnAssign* = ast.AnnAssign*(stmt)
|
||
if aa is None or aa.target is None: continue
|
||
|
||
# 获取字段名
|
||
if aa.target.kind() != ast.ASTKind.Name: continue
|
||
tgt: ast.Name* = ast.Name*(aa.target)
|
||
if tgt.id is None: continue
|
||
|
||
# 类体 CDefine 常量(任意位置,2026-08-10):注册到全局 CDefine 表。
|
||
# 方法内裸名(如 ISINSTANCE_CLASS_MAX)经 translate_name_value 查
|
||
# CDefine 表解析为常量值;类体开头的常量(MRO_MAX 等)由早期预注册
|
||
# 路径注册,但方法之后的 AnnAssign 不经过那些路径 → 此处统一兜底注册。
|
||
if self.Gen.AssignGen.is_cdefine_annotation(aa.annotation) != 0:
|
||
if aa.value is not None:
|
||
self.Gen.AssignGen._register_cdefine_from_value(pool, tgt.id, aa.value, aa.annotation)
|
||
# CDefine 字段类型固定 i32,直接收集后跳过通用注解解析:
|
||
# resolve_annotation_type 不识别 "CDefine"(map_t_type/CTypedef
|
||
# 表均无此名),类体尾部常量(ISINSTANCE_CLASS_MAX 是首个触发
|
||
# 该路径的实例)Phase B 会 NameError: 't.CDefine' is not defined。
|
||
# 与类头常量(MRO_MAX 等)的 i32 字段语义保持一致。
|
||
if field_count < GenTypes.FIELD_MAX:
|
||
cdef_ty_l: llvmlite.LLVMType* = llvmlite.Int32(pool)
|
||
if cdef_ty_l is not None:
|
||
field_names_buf[field_count] = sizet(tgt.id)
|
||
field_types_buf[field_count] = sizet(cdef_ty_l)
|
||
if aa.value is not None:
|
||
field_defaults_buf[field_count] = sizet(aa.value)
|
||
else:
|
||
field_defaults_buf[field_count] = 0
|
||
field_count += 1
|
||
continue
|
||
|
||
# 跳过编译期元数据字段(__provides__/__requires__/__require_must__)
|
||
# 这些字段只用于 with 上下文的静态可达性检查,不生成运行时代码
|
||
# (FakeDuck:_str.__requires__=['__mbuddy__'])。此处解析 list[str]
|
||
# 字面量注册到持久元数据表,供 requires 注入 / with provider 查询。
|
||
if string.strcmp(tgt.id, "__provides__") == 0:
|
||
self.Gen.ClassGenBase._register_class_meta_list(pool, GenTypes.CLASS_META_PROVIDES, class_name, aa.value)
|
||
continue
|
||
if string.strcmp(tgt.id, "__requires__") == 0:
|
||
self.Gen.ClassGenBase._register_class_meta_list(pool, GenTypes.CLASS_META_REQUIRES, class_name, aa.value)
|
||
continue
|
||
if string.strcmp(tgt.id, "__require_must__") == 0:
|
||
self.Gen.ClassGenBase._register_class_meta_list(pool, GenTypes.CLASS_META_REQUIRE_MUST, class_name, aa.value)
|
||
continue
|
||
|
||
# 解析字段类型
|
||
field_ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, aa.annotation, trans._imported_modules, trans._from_imports, trans, 0)
|
||
# void 不是合法字段类型(用户 2026-10-01:void 只能用于 `void*` 与
|
||
# `typedef 不透明结构体 = void`);`void*` 已在上游归并为 i8*,不会命中。
|
||
# 放任会按 LLVM void 建字段槽 ⇒ 结构体布局非法(拖到 llc 才暴露),
|
||
# 故此处编译期 fail-fast。
|
||
if field_ty is not None and self.Gen.StmtGenDecl._is_void_type(field_ty) != 0:
|
||
self.Gen.TypeGenErr.fatal_error(aa, f"字段 '{tgt.id}' 不能是 void 类型(void 只能用于 void* 与 typedef 别名)", "TypeError")
|
||
# 单参 t.CArray[elem] + 列表字面量 → 静态数组 [N x elem]
|
||
# (与局部 AnnAssign 路径一致,对齐 TPC ParseListAnnotation 语义):
|
||
# 否则字段保持 Ptr(elem)(如 t.CArray[str] → i8**),
|
||
# for x in self.field 会误走指针迭代(元素非整数 → null 终止符
|
||
# 检查失败报错)。推断为静态数组后走数组迭代(按长度 N)。
|
||
if field_ty is not None:
|
||
field_ty = self.Gen.AssignGen._infer_static_array_ty_from_literal(pool, aa.annotation, aa.value, field_ty)
|
||
if field_ty is None:
|
||
# BUG 5 方案1修改点1:消除 i32 静默回退
|
||
# Phase A-pre(declare_only=1):依赖的类可能尚未注册,延迟到下一遍
|
||
# Phase B(declare_only=0):真正的类型解析错误,fast-fail 终止该类翻译
|
||
# 不再用 i32 回退(会导致结构体布局错误 + GEP 索引错乱)
|
||
# 例外:泛型 Subscript(如 list[AST|t.CPtr])未特化时回退为 Ptr(i8),
|
||
# 因为泛型特化可能延迟到构造调用时。AnnotClassName 会携带 mangled name
|
||
# 供 translate_attribute 做后续 bitcast。
|
||
is_generic_sub: int = 0
|
||
if aa.annotation is not None and aa.annotation.kind() == ast.ASTKind.Subscript:
|
||
# t.CArray[elem, N](含裸 CArray[elem, N])是定长值数组,非泛型堆对象——
|
||
# 元素类型未就绪时若回退 Ptr(i8) 会注册成退化字段布局,Phase B 复用该 entry
|
||
# 后 GEP 元素成 i8、字段访问/赋值全部失效。仅真正的泛型类(list[T]/Vector[T]
|
||
# 等堆对象)未特化才回退 Ptr(i8)(AnnotClassName 携带 mangled name 供后续恢复)。
|
||
sub_g: ast.Subscript* = ast.Subscript*(aa.annotation)
|
||
is_carray_sub_g: int = 0
|
||
if sub_g is not None and sub_g.value is not None:
|
||
if sub_g.value.kind() == ast.ASTKind.Attribute:
|
||
svg_at: ast.Attribute* = ast.Attribute*(sub_g.value)
|
||
if svg_at.attr is not None and string.strcmp(svg_at.attr, "CArray") == 0:
|
||
is_carray_sub_g = 1
|
||
elif sub_g.value.kind() == ast.ASTKind.Name:
|
||
svg_nm: ast.Name* = ast.Name*(sub_g.value)
|
||
if svg_nm.id is not None and (string.strcmp(svg_nm.id, "CArray") == 0 or string.strcmp(svg_nm.id, "rawarray") == 0 or string.strcmp(svg_nm.id, "array") == 0):
|
||
is_carray_sub_g = 1
|
||
if is_carray_sub_g == 0:
|
||
is_generic_sub = 1
|
||
if is_generic_sub != 0:
|
||
# 泛型未特化:回退为 Ptr(i8),依赖 AnnotClassName 做后续类型恢复
|
||
field_ty = llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||
else:
|
||
# Phase A-pre(declare_only=1):依赖的类可能尚未注册,
|
||
# 静默 return 0 让多遍收敛机制生效(下一遍依赖类已注册即可成功)
|
||
if trans._declare_only == 1:
|
||
return 0
|
||
# Phase A(declare_only=0,Phase2.vp L573 多遍):依赖模块按
|
||
# 文件序可能晚于本模块翻译(如 TypeGenMixin.vp G < HandlesType.vp
|
||
# H,TraceFrames 注解的 HandlesType.TraceFrame 未注册)→ 不在本遍
|
||
# 以残缺字段注册结构体。
|
||
return 0
|
||
# 旧行为:fast-fail NameError(已移除——Phase A 依赖未就绪时
|
||
# 误报真实错误,中断多遍收敛;真实错误交给收敛检查兜底)
|
||
|
||
# 存储到数组(指针转 CSizeT)
|
||
if field_count < GenTypes.FIELD_MAX:
|
||
diag_name_val: sizet = sizet(tgt.id)
|
||
field_names_buf[field_count] = diag_name_val
|
||
field_types_buf[field_count] = sizet(field_ty)
|
||
# 存储默认值 AST 指针(None=无默认值)
|
||
if aa.value is not None:
|
||
field_defaults_buf[field_count] = sizet(aa.value)
|
||
else:
|
||
field_defaults_buf[field_count] = 0
|
||
# 提取原始类型注解的类名(联合类型简化为 Ptr(i8) 时回退查找结构体)
|
||
# BUG 1 方案3:传 pool 使泛型 Subscript 返回 mangled name(如 "list[ast.AST|t.CPtr]")
|
||
if aa.annotation is not None:
|
||
annot_cn: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(aa.annotation, trans._imported_modules, pool, trans._from_imports)
|
||
if annot_cn is not None:
|
||
diag_cn_val: sizet = sizet(annot_cn)
|
||
field_annot_buf[field_count] = diag_cn_val
|
||
else:
|
||
field_annot_buf[field_count] = 0
|
||
# t.CVolatile 存储类标记 → 该字段经对象访问的 load/store 带
|
||
# volatile(如 Spinlock.locked: t.CVolatile | t.CInt)。
|
||
if self.Gen.TypeGenErr.has_decorator_marker(aa.annotation, "CVolatile", 0) != 0:
|
||
field_volatile_buf[field_count] = 1
|
||
else:
|
||
field_volatile_buf[field_count] = 0
|
||
# rawptr[t.CVolatile | T](volatile 指针指向物,等价 C 的
|
||
# volatile T*)→ 经该字段解引用(self.ptr[i]/self.ptr.field)
|
||
# 的 load/store 带 volatile。
|
||
if self.Gen.TypeGenErr.has_pointee_volatile_marker(aa.annotation) != 0:
|
||
field_pointee_volatile_buf[field_count] = 1
|
||
else:
|
||
field_pointee_volatile_buf[field_count] = 0
|
||
# const 对象字段(注解含 t.CConst 且字段类型非指针)→ 经对象给该
|
||
# 字段赋值 fail-fast。判据与 TPC 的 Gen.field_const_flags 一致。
|
||
if self.Gen.TypeGenErr.is_const_object_marker(aa.annotation, field_ty) != 0:
|
||
field_const_buf[field_count] = 1
|
||
else:
|
||
field_const_buf[field_count] = 0
|
||
else:
|
||
field_annot_buf[field_count] = 0
|
||
field_volatile_buf[field_count] = 0
|
||
field_pointee_volatile_buf[field_count] = 0
|
||
field_const_buf[field_count] = 0
|
||
field_count += 1
|
||
|
||
if field_count == 0:
|
||
# PhaseA 预注册时,父类可能尚未注册(字母序单遍扫描),
|
||
# 导致子类无法继承父类字段 → field_count==0。
|
||
# 静默返回,Phase2.py 的多遍 PhaseA-pre 会在后续遍中重试。
|
||
if trans._declare_only == 1 and parent_name is not None:
|
||
return 0
|
||
# 无字段类(接口/标记类):不能整体跳过——类可能只有方法
|
||
# (如多继承中的 ShapeM/Vec2Extra),需注册类并翻译方法。
|
||
# 空 struct 在 LLVM 中合法({});@t.CVTable 类由下方补 vtable 指针字段。
|
||
|
||
# ============================================================
|
||
# 2. 创建 LLVM StructType
|
||
# ============================================================
|
||
# 构建 ParamNode 链表
|
||
first_node: rawptr[llvmlite.ParamNode] = None
|
||
prev_node: rawptr[llvmlite.ParamNode] = None
|
||
total_field_count: int = field_count
|
||
|
||
# 如果有虚表,首字段添加 i8* vtable 指针
|
||
if has_vtable == 1:
|
||
i8_ptr_ty: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||
vtable_node: rawptr[llvmlite.ParamNode] = pool.alloc(llvmlite.ParamNode.__sizeof__())
|
||
if vtable_node is None:
|
||
VLogger.error(f"failed to alloc vtable node for {class_name}", "CLASS")
|
||
return 0
|
||
string.memset(vtable_node, 0, llvmlite.ParamNode.__sizeof__())
|
||
vtable_node.Ty = i8_ptr_ty
|
||
first_node = vtable_node
|
||
prev_node = vtable_node
|
||
total_field_count = field_count + 1
|
||
|
||
for fi in range(field_count):
|
||
fty_addr: sizet = field_types_buf[fi]
|
||
if fty_addr == 0:
|
||
continue
|
||
fty: llvmlite.LLVMType* = (llvmlite.LLVMType*)(fty_addr)
|
||
|
||
# 创建 ParamNode
|
||
pnode: rawptr[llvmlite.ParamNode] = pool.alloc(llvmlite.ParamNode.__sizeof__())
|
||
if pnode is None:
|
||
continue
|
||
string.memset(pnode, 0, llvmlite.ParamNode.__sizeof__())
|
||
pnode.Ty = fty
|
||
|
||
if first_node is None:
|
||
first_node = pnode
|
||
if prev_node is not None:
|
||
prev_node.Next = pnode
|
||
prev_node = pnode
|
||
|
||
# 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName"
|
||
# 注意: Phase 1b(declare_only=0)时 struct_ty 会注册到全局表并被后续
|
||
# 文件翻译引用(vtable/self 参数类型打印),其 Name 必须跨 1b 每文件
|
||
# reset_to(mark1) 存活 → 用 stdlib 深拷贝;Phase 1a 仍用 pool(无需跨文件)。
|
||
type_name: str = class_name
|
||
if trans.ModuleSha1 is not None:
|
||
name_buf: str = pool.alloc(64)
|
||
if name_buf is not None:
|
||
viperlib.snprintf(name_buf, 64, "%s.%s", trans.ModuleSha1, class_name)
|
||
type_name = name_buf
|
||
if trans._declare_only == 0 and type_name is not None:
|
||
tn_len: sizet = string.strlen(type_name)
|
||
tn_copy: str = CompilerFactory.factory.PermPool.alloc(tn_len + 1)
|
||
if tn_copy is not None:
|
||
string.strcpy(tn_copy, type_name)
|
||
type_name = tn_copy
|
||
|
||
# 创建 StructType(命名结构体)
|
||
struct_ty: llvmlite.LLVMType* = llvmlite.Struct(pool, first_node, total_field_count, type_name)
|
||
if struct_ty is None:
|
||
VLogger.error(f"failed to create StructType for {class_name}", "CLASS")
|
||
return 0
|
||
|
||
# Phase 1b(declare_only=0)新注册的 struct_ty 会被注册到全局表并被后续文件
|
||
# 翻译引用(vtable/self 参数类型打印/find_struct_by_type 指针匹配)。LLVMType
|
||
# 对象和 Fields 链是 pool 分配的,本文件 reset_to(mark1) 后悬空。深拷贝整棵树
|
||
# 到 stdlib,并替换 struct_ty 指针,保证 entry.Ty 与调用方持有的 struct_ty
|
||
# 指向同一个 stdlib 拷贝(指针匹配不失效)且跨文件永久存活。
|
||
# StdlibAlloc=1(Phase2 mark2 后)也必须深拷贝:Phase A-pre-inc(declare_only=1)
|
||
# 预注册 includes 时若仍用 pool struct_ty,reset_to(mark2) 后 entry.Ty 悬空 →
|
||
# 后续文件字段类型引用(resolve → Ptr(entry.Ty))→ opaque 扫描遍历悬空 fields
|
||
# 崩溃(LoopTest _scan_type_for_cross_module_refs 0xFFFF 根因)。
|
||
if trans._declare_only == 0 or self.Gen.StructGen.get_stdlib_alloc() != 0:
|
||
st_copy: llvmlite.LLVMType* = llvmlite.DeepCopyType(CompilerFactory.factory.PermPool, struct_ty)
|
||
if st_copy is not None:
|
||
struct_ty = st_copy
|
||
type_name = llvmlite.get_struct_name(struct_ty)
|
||
|
||
# 前向声明占位命中:**原位填充**——保持 existing.Ty 指针身份不变,仅把刚构建
|
||
# 的字段体写进同一个类型对象(名称沿用占位的 "{sha}.Class")。此后所有已发出的
|
||
# Ptr(占位.Ty) 引用(如 CallGenBase.Gen)自动指向完整定义。这一步必须早于
|
||
# module_add_named_type:避免同一名字先以占位名注册、又以新对象重复注册。
|
||
if fill_fwd != 0 and existing is not None and existing.Ty is not None:
|
||
_fwd_name: str = llvmlite.get_struct_name(existing.Ty)
|
||
_fwd_fields: rawptr[llvmlite.ParamNode] = llvmlite.get_struct_fields(struct_ty)
|
||
_fwd_fc: int = llvmlite.get_struct_fcount(struct_ty)
|
||
*existing.Ty = llvmlite.LLVMType.Struct(_fwd_fields, _fwd_fc, _fwd_name)
|
||
struct_ty = existing.Ty
|
||
type_name = _fwd_name
|
||
existing.IsForwardDecl = 0
|
||
existing.FieldCount = 0
|
||
|
||
# 注册命名结构体到模块(输出 %"name" = type { ... } 定义行)
|
||
llvmlite.module_add_named_type(trans.Module, pool, struct_ty)
|
||
|
||
# B5:@c.Attribute(t.attr.packed) 打包结构体 → 类型定义输出 <{...}>
|
||
# (LLVM packed struct,无字段填充,GEP 按 packed 布局计算偏移)。
|
||
# idt/gdt/elf/fat32 等二进制格式结构体依赖它读写硬件/磁盘布局。
|
||
is_packed_cd: int = self.Gen.ClassGenBase._class_has_tattr(cd.decorator_list, "packed")
|
||
if is_packed_cd != 0:
|
||
llvmlite.module_set_named_type_packed(trans.Module, pool, struct_ty, 1)
|
||
|
||
# 扫描字段类型,为跨模块结构体引用添加 opaque 声明
|
||
# 例如 list[int].__pool__ 引用 memhub.MemManager,需要在当前模块添加 %"sha1.MemManager" = type opaque
|
||
for fi in range(field_count):
|
||
fty_addr_op: sizet = field_types_buf[fi]
|
||
if fty_addr_op == 0:
|
||
continue
|
||
fty_op: llvmlite.LLVMType* = (llvmlite.LLVMType*)(fty_addr_op)
|
||
llvmlite.module_ensure_opaque_for_type(trans.Module, pool, fty_op)
|
||
|
||
# ============================================================
|
||
# 3. 注册到 HandlesStruct
|
||
# ============================================================
|
||
entry: GenTypes.StructEntry* = None
|
||
if fill_fwd != 0 and existing is not None:
|
||
# 前向声明占位:字段体已原位写入 existing.Ty,登记条目沿用 existing
|
||
# (不新建条目/Ty,否则已发出的 Ptr(占位.Ty) 引用会指向旧空对象)。
|
||
entry = existing
|
||
else:
|
||
entry = self.Gen.StructGen.register_struct(pool, class_name, struct_ty, trans.ModuleSha1)
|
||
if entry is None:
|
||
VLogger.error(f"failed to register {class_name}", "CLASS")
|
||
return 0
|
||
|
||
# B5:记录 packed 标记到 StructEntry(供 __sizeof__/字段布局等派生查询)
|
||
if is_packed_cd != 0:
|
||
entry.IsPacked = 1
|
||
# B5:记录 aligned 对齐值(@c.Attribute(t.attr.aligned(N)),如 fpu_context 16 对齐),
|
||
# 供全局变量/局部 alloca 生成时施加对齐。
|
||
align_cd: int = self.Gen.ClassGenBase._class_aligned_value(cd.decorator_list)
|
||
if align_cd > 0:
|
||
entry.Align = align_cd
|
||
|
||
# 标记 VTable 状态(直接用 entry,规避跨模块同名 find_struct 找错)
|
||
if has_vtable == 1:
|
||
entry.HasVTable = 1
|
||
if is_novtable_deco == 1:
|
||
entry.IsNoVTable = 1
|
||
if parent_name is not None:
|
||
# 1b 阶段父类名是 pool 字符串,reset 后悬空;_translate_oop_methods/
|
||
# _detect_vtable_status 会在后续文件 find_struct(ParentName) strcmp 解引用
|
||
# → 用 stdlib 拷贝保证跨文件存活。
|
||
if self.Gen.StructGen.get_stdlib_alloc() != 0:
|
||
pn_len: sizet = string.strlen(parent_name)
|
||
pn_buf: str = CompilerFactory.factory.PermPool.alloc(pn_len + 1)
|
||
if pn_buf is not None:
|
||
string.strcpy(pn_buf, parent_name)
|
||
entry.ParentName = pn_buf
|
||
else:
|
||
entry.ParentName = parent_name
|
||
# 多继承:设置父类数组(供 MRO/字段/vtable 查询,stdlib 深拷贝跨文件存活)
|
||
if parents_count > 0 and parents_buf is not None:
|
||
self.Gen.StructGen.set_parent_names(pool, class_name, parents_buf, parents_count)
|
||
|
||
# 添加字段信息
|
||
# 如果有虚表,先添加 __vtable__ 字段占位(索引 0),用户字段从索引 1 开始
|
||
if has_vtable == 1:
|
||
i8_ptr_ty2: llvmlite.LLVMType* = llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||
self.Gen.StructGen.add_field(pool, entry, "__vtable__", i8_ptr_ty2, None, None)
|
||
|
||
for fi in range(field_count):
|
||
fname_addr: sizet = field_names_buf[fi]
|
||
if fname_addr == 0:
|
||
continue
|
||
fname: str = rawptr(fname_addr)
|
||
fty_addr2: sizet = field_types_buf[fi]
|
||
if fty_addr2 == 0:
|
||
continue
|
||
fty2: llvmlite.LLVMType* = (llvmlite.LLVMType*)(fty_addr2)
|
||
# 恢复默认值 AST 指针
|
||
fdef_addr: sizet = field_defaults_buf[fi]
|
||
fdef: ast.AST* = None
|
||
if fdef_addr != 0:
|
||
fdef = (ast.AST*)(fdef_addr)
|
||
# 恢复注解类名指针
|
||
fannot_addr: sizet = field_annot_buf[fi]
|
||
fannot: str = None
|
||
if fannot_addr != 0:
|
||
fannot = str(fannot_addr)
|
||
if fname is not None and fty2 is not None:
|
||
fidx_add: int = self.Gen.StructGen.add_field(pool, entry, fname, fty2, fdef, fannot)
|
||
# t.CVolatile 字段标记(field_volatile_buf[fi] 与 add_field 顺序一一对应)
|
||
if fidx_add >= 0 and field_volatile_buf[fi] != 0:
|
||
fe_vol: GenTypes.FieldEntry* = \
|
||
self.Gen.StructGen._get_field_entry(entry, fidx_add)
|
||
if fe_vol is not None:
|
||
fe_vol.IsVolatile = 1
|
||
# rawptr[t.CVolatile | T] 字段标记(field_pointee_volatile_buf[fi] 与
|
||
# add_field 顺序一一对应):经该字段解引用时 load/store 带 volatile。
|
||
if fidx_add >= 0 and field_pointee_volatile_buf[fi] != 0:
|
||
fe_pv: GenTypes.FieldEntry* = \
|
||
self.Gen.StructGen._get_field_entry(entry, fidx_add)
|
||
if fe_pv is not None:
|
||
fe_pv.PointeeVolatile = 1
|
||
# const 对象字段标记(field_const_buf[fi] 与 add_field 顺序一一对应)
|
||
if fidx_add >= 0 and field_const_buf[fi] != 0:
|
||
fe_c: GenTypes.FieldEntry* = \
|
||
self.Gen.StructGen._get_field_entry(entry, fidx_add)
|
||
if fe_c is not None:
|
||
fe_c.IsConst = 1
|
||
|
||
# Phase 1a 声明模式:只注册 struct + 设置 OOP 标志,不翻译方法体
|
||
if trans._declare_only == 1:
|
||
self.Gen.ClassGenVTable._translate_oop_methods(trans, cd, struct_ty, class_name, 1)
|
||
return 0
|
||
|
||
# ============================================================
|
||
# 4. OOP 方法处理:扫描 FunctionDef,标记 OOP,翻译方法,生成 __before_init__
|
||
# ============================================================
|
||
self.Gen.ClassGenVTable._translate_oop_methods(trans, cd, struct_ty, class_name)
|
||
|
||
return 0
|
||
|
||
# ============================================================
|
||
# _translate_nested_classdefs - 递归翻译类体内的嵌套 class / struct
|
||
#
|
||
# 命名与引用口径(用户 2026-10-01 定,与 TPC union/renum 嵌套命名同源):
|
||
# · 内层结构体 IR 名 = `{sha1}.{外类}_{内类}`(sha1 = 与外层相同的定义模块);
|
||
# · 引用两种写法都可:限定名 `外类.内类`(Attribute 兜底,见 TypeGenResolve)
|
||
# 与扁平名 `外类_内类`(裸名直查结构体表即可命中);
|
||
# · 多层嵌套自然递归为 `A_B_C`(递归时子节点名已被改写为 A_B)。
|
||
# 实现选择"临时改写子节点 name 再递归"而非另写发射器:本模块所有名字派生点
|
||
# (IR 名 {sha}.{名}、register_struct/add_field、AnnotClassName、方法符号名
|
||
# `{类}.{方法}` 的 mangling、mark_module_class 键)都读 cd.name ⇒ 改名即全链路
|
||
# 一致,且复用继承展平/packed/OOP/vtable 等全部既有逻辑,零新增判据。
|
||
# 两个必须的护栏:
|
||
# ① 扁平名字符串分配在 PermPool —— 它要跨 Phase(1a/1b)存活,trans.Pool 会随
|
||
# mark/reset 回收成悬空串(后续 strcmp 读悬空内存)。
|
||
# ② 递归返回后**还原"正在定义类"窗口**(CurDefModuleSha1/CurDefClassName 会被
|
||
# 内层 mark_module_class 覆盖)——不还原会让外层随后的字段注解解析误判
|
||
# "当前定义类"(规则 5.5 的自引用窗口据此判定,误判会冻结裸名票名)。
|
||
# ============================================================
|
||
def _translate_nested_classdefs(self, trans: HT.Translator*,
|
||
cd: ast.ClassDef*) -> None:
|
||
"""把本类体内的嵌套 ClassDef 逐个按 `{外类}_{内类}` 递归翻译"""
|
||
if trans is None or cd is None or cd.name is None:
|
||
return
|
||
children: list[ast.AST*]* = cd.children
|
||
if children is None:
|
||
return
|
||
cn: sizet = len(children)
|
||
ci: sizet = 0
|
||
while ci < cn:
|
||
child_ast: ast.AST* = children.get(ci)
|
||
ci += 1
|
||
if child_ast is None:
|
||
continue
|
||
if child_ast.kind() != ast.ASTKind.ClassDef:
|
||
continue
|
||
child: ast.ClassDef* = ast.ClassDef*(child_ast)
|
||
if child is None or child.name is None:
|
||
continue
|
||
# 扁平名 `{外类}_{内类}`(优先 PermPool:名字要跨 Phase 存活;
|
||
# PermPool 缺失时退回本遍池,行为与旧路径一致)
|
||
flat_pool: memhub.MemBuddy* = CompilerFactory.factory.PermPool
|
||
if flat_pool is None:
|
||
flat_pool = trans.Pool
|
||
if flat_pool is None:
|
||
continue
|
||
outer_len: sizet = string.strlen(cd.name)
|
||
inner_len: sizet = string.strlen(child.name)
|
||
flat_len: sizet = outer_len + 1 + inner_len
|
||
flat_buf: str = flat_pool.alloc(flat_len + 1)
|
||
if flat_buf is None:
|
||
continue
|
||
viperlib.snprintf(flat_buf, flat_len + 1, "%s_%s", cd.name, child.name)
|
||
# 改写子节点名 → 递归(内部一律以扁平名注册/发射)
|
||
old_name: str = child.name
|
||
child.name = flat_buf
|
||
saved_def_sha1: str = self.Gen.StructGen.CurDefModuleSha1
|
||
saved_def_cls: str = self.Gen.StructGen.CurDefClassName
|
||
self.translate_class_def(trans, child_ast)
|
||
self.Gen.StructGen.CurDefModuleSha1 = saved_def_sha1
|
||
self.Gen.StructGen.CurDefClassName = saved_def_cls
|
||
child.name = old_name |