refactor(gen): ClassGenMixin 拆 5 组(Base/Enum/Generic/VTable/Def,4768→空壳)
This commit is contained in:
1 parent
81d4ff3ac4
commit
47ac2dd57c
8 files changed
+4807
-4745
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,577 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
import lib.core.Gen.ClassGenBase as ClassGenBase
|
||||
|
||||
# ============================================================
|
||||
# ClassGenDef - ClassGenMixin 拆分(阶段 D):translate_class_def 主入口
|
||||
#
|
||||
# 继承 ClassGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesClassDef 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class ClassGenDef(ClassGenBase.ClassGenBase):
|
||||
"""translate_class_def 主入口"""
|
||||
|
||||
# ============================================================
|
||||
# translate_class_def — 翻译 class 定义(簇 D)
|
||||
# ============================================================
|
||||
def translate_class_def(self, trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 class 定义,返回 0"""
|
||||
if node is None or trans is None:
|
||||
return 0
|
||||
|
||||
cd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(node)
|
||||
if cd is None or cd.name is None:
|
||||
return 0
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
class_name: str = cd.name
|
||||
|
||||
if trans.ModuleSha1 is None:
|
||||
# fail-fast:翻译类时模块 SHA1 缺失(命名空间隔离依赖它)——
|
||||
VLogger.error("翻译类时 ModuleSha1 缺失", "CLASS")
|
||||
HandlesType.fatal_error(cd, "翻译类时 ModuleSha1 缺失", "TypeError")
|
||||
|
||||
# 命名空间隔离:标记为当前文件可见(必须在 existing 检查之前,
|
||||
# 因为 Phase B 时结构体已注册会提前 return,否则永远无法标记本地类)
|
||||
HandlesStruct.add_visible_struct(pool, class_name)
|
||||
|
||||
# 枚举类:交给 HandlesEnum 处理
|
||||
if HandlesClassDef._is_enum_class(cd, trans) == 1:
|
||||
return HandlesClassDef._translate_enum_def(trans, cd)
|
||||
|
||||
# 联合体类:交给联合体处理
|
||||
if HandlesClassDef._is_union_class(cd, trans) == 1:
|
||||
return HandlesClassDef._translate_union_def(trans, cd)
|
||||
|
||||
# REnum 类:交给 REnum 处理({i32 tag, max_payload} 布局)
|
||||
if HandlesClassDef._is_renum_class(cd, trans) == 1:
|
||||
return HandlesClassDef._translate_renum_def(trans, cd)
|
||||
|
||||
# 泛型类:存储为模板,不发射 IR(等实例化时特化)
|
||||
# 用局部变量接收 cd.type_params,触发类型推断
|
||||
tp_val: list[str] | t.CPtr = cd.type_params
|
||||
if HandlesClassDef._is_generic_class(tp_val) == 1:
|
||||
HandlesClassDef._register_generic_template(pool, cd, trans.ModuleSha1)
|
||||
return 0
|
||||
|
||||
# 异常类(try-except):注册编码+继承树,不生成 struct
|
||||
# (对齐 TPC HandlesClassDef.py L509-511:_is_exception_class →
|
||||
# _RegisterExceptionClass → return,异常类不编译为结构体)
|
||||
if HandlesClassDef._is_exception_class_def(cd) == 1:
|
||||
return HandlesClassDef._register_exception_class_def(trans, cd)
|
||||
|
||||
# 检查是否已注册(用 SHA1 区分跨模块同名类)
|
||||
existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
|
||||
class_name, trans.ModuleSha1)
|
||||
if existing is not None:
|
||||
# BUG 5 方案1修改点2:existing 时字段完整性检查
|
||||
# 结构体已注册,但需验证字段信息是否完整(防止 i32 回退残留或注册不完整)
|
||||
# 注意:无字段类(接口/标记类,类体无 AnnAssign)合法(空 struct + 方法),
|
||||
# 仅当"类体声明了字段但 FieldCount==0"才算注册不完整(Phase A-pre 漏注册)。
|
||||
if existing.FieldCount == 0 and trans._declare_only == 0:
|
||||
if HandlesClassDef._class_body_has_field(cd) != 0:
|
||||
# Phase B 时字段数为 0 说明注册不完整(Phase A-pre 可能漏注册)
|
||||
HandlesType.fatal_error(
|
||||
node,
|
||||
f"结构体已注册但字段数为0,类: {class_name},可能注册不完整",
|
||||
"InternalCompilerError")
|
||||
# 结构体已注册(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 | t.CPtr = llvmlite.DeepCopyType(
|
||||
CompilerFactory.get_perm_pool(), 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: t.CSizeT = string.strlen(old_name)
|
||||
on_copy: str = CompilerFactory.get_perm_pool().alloc(on_len + 1)
|
||||
if on_copy is not None:
|
||||
string.strcpy(on_copy, old_name)
|
||||
c.DerefAs(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)
|
||||
# Phase A-pre(declare_only=1)多遍扫描时,类已注册但不应翻译方法体
|
||||
# Phase B(declare_only=0)时全量翻译方法体
|
||||
if trans._declare_only == 1:
|
||||
HandlesClassDef._translate_oop_methods(trans, cd, existing.Ty, class_name, 1)
|
||||
else:
|
||||
HandlesClassDef._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
|
||||
# ============================================================
|
||||
HandlesClassDef._trigger_base_specialization(trans, cd)
|
||||
|
||||
# ============================================================
|
||||
# VTable 检测:判断是否启用虚表
|
||||
# ============================================================
|
||||
has_vtable: int = HandlesClassDef._detect_vtable_status(cd, trans)
|
||||
parent_name: str = HandlesClassDef._get_parent_class(cd, trans)
|
||||
# 多继承:收集所有真实父类名(跳过 marker base),供字段展平/vtable/MRO 使用
|
||||
parents_buf: t.CSizeT | t.CPtr = pool.alloc(8 * HandlesStruct.PARENT_MAX)
|
||||
parents_count: int = 0
|
||||
if parents_buf is not None:
|
||||
parents_count = HandlesClassDef._collect_parents(pool, cd, parents_buf, HandlesStruct.PARENT_MAX)
|
||||
is_novtable_deco: int = 0
|
||||
if cd.decorator_list is not None:
|
||||
if HandlesClassDef._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: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
|
||||
parent_name, trans.ModuleSha1)
|
||||
if parent_check is None:
|
||||
parent_check = HandlesStruct.find_struct(parent_name)
|
||||
if parent_check is None:
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# 1. 遍历 class body,收集字段信息
|
||||
# ============================================================
|
||||
# 用 CSizeT 数组存储指针值(64 位系统上 8 字节)
|
||||
field_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * HandlesStruct.FIELD_MAX)
|
||||
field_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * HandlesStruct.FIELD_MAX)
|
||||
field_defaults_buf: t.CSizeT | t.CPtr = pool.alloc(8 * HandlesStruct.FIELD_MAX)
|
||||
field_annot_buf: t.CSizeT | t.CPtr = pool.alloc(8 * HandlesStruct.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:
|
||||
return 0
|
||||
string.memset(field_names_buf, 0, 8 * HandlesStruct.FIELD_MAX)
|
||||
string.memset(field_types_buf, 0, 8 * HandlesStruct.FIELD_MAX)
|
||||
string.memset(field_defaults_buf, 0, 8 * HandlesStruct.FIELD_MAX)
|
||||
string.memset(field_annot_buf, 0, 8 * HandlesStruct.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: t.CSizeT = parents_buf[pi]
|
||||
if pname_addr == 0:
|
||||
continue
|
||||
pname: str = (str | t.CPtr)(t.CVoid(pname_addr, t.CPtr))
|
||||
if pname is None:
|
||||
continue
|
||||
# 用 SHA1 感知查找父类,规避跨模块同名找错
|
||||
parent_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.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 = HandlesStruct.find_struct(pname)
|
||||
if parent_entry is None:
|
||||
# 父类尚未注册(依赖模块未翻译:Phase A 按文件序,子类模块可能
|
||||
# 先于父类模块,如 Generator.vp G < TypeGenMixin.vp T)。此时
|
||||
# **不能**继续注册——StructTable 在 StdlibAlloc=1 时用 perm_pool
|
||||
# 分配(init_struct_table L136-140),残缺条目跨 pass 存活,
|
||||
# 后续 pass 的 existing 早退(L2995-3006)永远无法修复 → 子类
|
||||
# __init__ 写父类字段(self.TraceFrames)每遍永久失败。
|
||||
# 整类 defer(不注册)+ 标记 _deps_pending 下遍重译;模块级
|
||||
# 变量/函数参数解析失败静默降级 i32(handle_module_level_var
|
||||
# L422-426 / FuncGenMixin L482-483),不致命,本遍文件不写盘。
|
||||
if trans is not None:
|
||||
trans._deps_pending = 1
|
||||
return 0
|
||||
pfc: int = parent_entry.FieldCount
|
||||
for pfi in range(pfc):
|
||||
pfe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry(
|
||||
parent_entry, pfi)
|
||||
if pfe is None:
|
||||
continue
|
||||
pfn: str = HandlesStruct.get_field_name_ptr(pfe)
|
||||
if pfn is None:
|
||||
continue
|
||||
# 跳过父类的 vtable 指针字段
|
||||
if string.strcmp(pfn, "__vtable__") == 0:
|
||||
continue
|
||||
# 多继承去重:字段名已存在跳过(先声明父类优先)
|
||||
if HandlesClassDef._field_name_exists(field_names_buf, field_count, pfn) != 0:
|
||||
continue
|
||||
if field_count < HandlesStruct.FIELD_MAX:
|
||||
pft: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_field_type_ptr(pfe)
|
||||
pfd: ast.AST | t.CPtr = HandlesStruct.get_field_default_ptr(pfe)
|
||||
pfa: str = HandlesStruct.get_field_annot_class_name(pfe)
|
||||
field_names_buf[field_count] = t.CSizeT(pfn)
|
||||
field_types_buf[field_count] = t.CSizeT(pft)
|
||||
if pfd is not None:
|
||||
field_defaults_buf[field_count] = t.CSizeT(pfd)
|
||||
else:
|
||||
field_defaults_buf[field_count] = 0
|
||||
if pfa is not None:
|
||||
stored_val: t.CSizeT = t.CSizeT(pfa)
|
||||
field_annot_buf[field_count] = stored_val
|
||||
else:
|
||||
field_annot_buf[field_count] = 0
|
||||
field_count += 1
|
||||
|
||||
children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||||
if children is None:
|
||||
return 0
|
||||
|
||||
cn: t.CSizeT = len(children)
|
||||
for ci in range(cn):
|
||||
stmt: ast.AST | t.CPtr = 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 | t.CPtr = (ast.AnnAssign | t.CPtr)(stmt)
|
||||
if aa is None or aa.target is None:
|
||||
continue
|
||||
|
||||
# 获取字段名
|
||||
if aa.target.kind() != ast.ASTKind.Name:
|
||||
continue
|
||||
tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
|
||||
if tgt.id is None:
|
||||
continue
|
||||
|
||||
# 类体 CDefine 常量(任意位置,2026-08-10):注册到全局 CDefine 表。
|
||||
# 方法内裸名(如 ISINSTANCE_CLASS_MAX)经 translate_name_value 查
|
||||
# CDefine 表解析为常量值;类体开头的常量(MRO_MAX 等)由早期预注册
|
||||
# 路径注册,但方法之后的 AnnAssign 不经过那些路径 → 此处统一兜底注册。
|
||||
if HandlesAnnAssign.is_cdefine_annotation(aa.annotation) != 0:
|
||||
if aa.value is not None:
|
||||
HandlesAnnAssign._register_cdefine_from_value(pool, tgt.id, aa.value)
|
||||
# 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 < HandlesStruct.FIELD_MAX:
|
||||
cdef_ty_l: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
if cdef_ty_l is not None:
|
||||
field_names_buf[field_count] = t.CSizeT(tgt.id)
|
||||
field_types_buf[field_count] = t.CSizeT(cdef_ty_l)
|
||||
if aa.value is not None:
|
||||
field_defaults_buf[field_count] = t.CSizeT(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:
|
||||
HandlesClassDef._register_class_meta_list(pool, HandlesType.CLASS_META_PROVIDES, class_name, aa.value)
|
||||
continue
|
||||
if string.strcmp(tgt.id, "__requires__") == 0:
|
||||
HandlesClassDef._register_class_meta_list(pool, HandlesType.CLASS_META_REQUIRES, class_name, aa.value)
|
||||
continue
|
||||
if string.strcmp(tgt.id, "__require_must__") == 0:
|
||||
HandlesClassDef._register_class_meta_list(pool, HandlesType.CLASS_META_REQUIRE_MUST, class_name, aa.value)
|
||||
continue
|
||||
|
||||
# 解析字段类型
|
||||
field_ty: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||||
pool, aa.annotation, trans._imported_modules, trans._from_imports, trans)
|
||||
# 单参 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 = HandlesAnnAssign._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:
|
||||
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 未注册)→ 标记
|
||||
# _deps_pending 下遍重译,不在本遍以残缺字段注册结构体。
|
||||
# 真正的类型错误由 Phase A 收敛检查暴露("Phase A 无法完成
|
||||
# 翻译: <file>,请检查依赖模块是否已编译/注册"),不静默掩盖。
|
||||
if trans is not None:
|
||||
trans._deps_pending = 1
|
||||
return 0
|
||||
# 旧行为:fast-fail NameError(已移除——Phase A 依赖未就绪时
|
||||
# 误报真实错误,中断多遍收敛;真实错误交给收敛检查兜底)
|
||||
|
||||
# 存储到数组(指针转 CSizeT)
|
||||
if field_count < HandlesStruct.FIELD_MAX:
|
||||
diag_name_val: t.CSizeT = t.CSizeT(tgt.id)
|
||||
field_names_buf[field_count] = diag_name_val
|
||||
field_types_buf[field_count] = t.CSizeT(field_ty)
|
||||
# 存储默认值 AST 指针(None=无默认值)
|
||||
if aa.value is not None:
|
||||
field_defaults_buf[field_count] = t.CSizeT(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 = HandlesType.extract_class_name_from_annotation(
|
||||
aa.annotation, trans._imported_modules, pool)
|
||||
if annot_cn is not None:
|
||||
diag_cn_val: t.CSizeT = t.CSizeT(annot_cn)
|
||||
field_annot_buf[field_count] = diag_cn_val
|
||||
else:
|
||||
field_annot_buf[field_count] = 0
|
||||
else:
|
||||
field_annot_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: llvmlite.ParamNode | t.CPtr = None
|
||||
prev_node: llvmlite.ParamNode | t.CPtr = None
|
||||
total_field_count: int = field_count
|
||||
|
||||
# 如果有虚表,首字段添加 i8* vtable 指针
|
||||
if has_vtable == 1:
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||||
vtable_node: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__())
|
||||
if vtable_node is None:
|
||||
fb_vn: str = VLogger.fmt_buf()
|
||||
if fb_vn is not None:
|
||||
viperlib.snprintf(fb_vn, 1024, "failed to alloc vtable node for %s", class_name)
|
||||
VLogger.error(fb_vn, "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: t.CSizeT = field_types_buf[fi]
|
||||
if fty_addr == 0:
|
||||
continue
|
||||
fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr, t.CPtr))
|
||||
|
||||
# 创建 ParamNode
|
||||
pnode: llvmlite.ParamNode | t.CPtr = 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: t.CSizeT = string.strlen(type_name)
|
||||
tn_copy: str = CompilerFactory.get_perm_pool().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 | t.CPtr = llvmlite.Struct(pool, first_node, total_field_count, type_name)
|
||||
if struct_ty is None:
|
||||
fb_st: str = VLogger.fmt_buf()
|
||||
if fb_st is not None:
|
||||
viperlib.snprintf(fb_st, 1024, "failed to create StructType for %s", class_name)
|
||||
VLogger.error(fb_st, "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 HandlesStruct.get_stdlib_alloc() != 0:
|
||||
st_copy: llvmlite.LLVMType | t.CPtr = llvmlite.DeepCopyType(
|
||||
CompilerFactory.get_perm_pool(), struct_ty)
|
||||
if st_copy is not None:
|
||||
struct_ty = st_copy
|
||||
type_name = llvmlite.get_struct_name(struct_ty)
|
||||
|
||||
# 注册命名结构体到模块(输出 %"name" = type { ... } 定义行)
|
||||
llvmlite.module_add_named_type(trans.Module, pool, struct_ty)
|
||||
|
||||
# 扫描字段类型,为跨模块结构体引用添加 opaque 声明
|
||||
# 例如 list[int].__pool__ 引用 memhub.MemManager,需要在当前模块添加 %"sha1.MemManager" = type opaque
|
||||
for fi in range(field_count):
|
||||
fty_addr_op: t.CSizeT = field_types_buf[fi]
|
||||
if fty_addr_op == 0:
|
||||
continue
|
||||
fty_op: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr_op, t.CPtr))
|
||||
llvmlite.module_ensure_opaque_for_type(trans.Module, pool, fty_op)
|
||||
|
||||
# ============================================================
|
||||
# 3. 注册到 HandlesStruct
|
||||
# ============================================================
|
||||
entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.register_struct(
|
||||
pool, class_name, struct_ty, trans.ModuleSha1)
|
||||
if entry is None:
|
||||
fb_re: str = VLogger.fmt_buf()
|
||||
if fb_re is not None:
|
||||
viperlib.snprintf(fb_re, 1024, "failed to register %s", class_name)
|
||||
VLogger.error(fb_re, "CLASS")
|
||||
return 0
|
||||
|
||||
# 标记 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 字符串(本文件 AST/1a 预存),reset 后悬空;
|
||||
# _translate_oop_methods/_detect_vtable_status 会在后续文件
|
||||
# find_struct(ParentName) strcmp 解引用 → 用 stdlib 拷贝保证跨文件存活
|
||||
if HandlesStruct.get_stdlib_alloc() != 0:
|
||||
pn_len: t.CSizeT = string.strlen(parent_name)
|
||||
pn_buf: str = CompilerFactory.get_perm_pool().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:
|
||||
HandlesStruct.set_parent_names(pool, class_name, parents_buf, parents_count)
|
||||
|
||||
# 添加字段信息
|
||||
# 如果有虚表,先添加 __vtable__ 字段占位(索引 0),用户字段从索引 1 开始
|
||||
if has_vtable == 1:
|
||||
i8_ptr_ty2: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||||
HandlesStruct.add_field(pool, entry, "__vtable__", i8_ptr_ty2, None, None)
|
||||
|
||||
for fi in range(field_count):
|
||||
fname_addr: t.CSizeT = field_names_buf[fi]
|
||||
if fname_addr == 0:
|
||||
continue
|
||||
fname: str = (str | t.CPtr)(t.CVoid(fname_addr, t.CPtr))
|
||||
fty_addr2: t.CSizeT = field_types_buf[fi]
|
||||
if fty_addr2 == 0:
|
||||
continue
|
||||
fty2: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr2, t.CPtr))
|
||||
# 恢复默认值 AST 指针
|
||||
fdef_addr: t.CSizeT = field_defaults_buf[fi]
|
||||
fdef: ast.AST | t.CPtr = None
|
||||
if fdef_addr != 0:
|
||||
fdef = (ast.AST | t.CPtr)(t.CVoid(fdef_addr, t.CPtr))
|
||||
# 恢复注解类名指针
|
||||
fannot_addr: t.CSizeT = field_annot_buf[fi]
|
||||
fannot: str = None
|
||||
if fannot_addr != 0:
|
||||
fannot = (str)(t.CVoid(fannot_addr, t.CPtr))
|
||||
if fname is not None and fty2 is not None:
|
||||
HandlesStruct.add_field(pool, entry, fname, fty2, fdef, fannot)
|
||||
|
||||
# Phase 1a 声明模式:只注册 struct + 设置 OOP 标志,不翻译方法体
|
||||
if trans._declare_only == 1:
|
||||
HandlesClassDef._translate_oop_methods(trans, cd, struct_ty, class_name, 1)
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# 4. OOP 方法处理:扫描 FunctionDef,标记 OOP,翻译方法,生成 __before_init__
|
||||
# ============================================================
|
||||
HandlesClassDef._translate_oop_methods(trans, cd, struct_ty, class_name)
|
||||
|
||||
return 0
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,675 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
import lib.core.Gen.ClassGenBase as ClassGenBase
|
||||
|
||||
# ============================================================
|
||||
# ClassGenGeneric - ClassGenMixin 拆分(阶段 D):泛型模板注册/特化/克隆
|
||||
#
|
||||
# 继承 ClassGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesClassDef 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class ClassGenGeneric(ClassGenBase.ClassGenBase):
|
||||
"""泛型模板注册/特化/克隆"""
|
||||
|
||||
# ============================================================
|
||||
# 簇 C:泛型模板注册/特化(P5-2 第三阶段迁移,函数体来自
|
||||
# HandlesClassDef.vp,逻辑零改动)
|
||||
#
|
||||
# 说明:
|
||||
# - _generic_class_* 全局表已迁入 self.GenericClassNames/
|
||||
# GenericClassNodes/GenericClassSha1s(P5-2 收尾)
|
||||
# - _spec_* 全局缓存迁移为 self.SpecKeys/SpecNames/SpecCount
|
||||
# ============================================================
|
||||
|
||||
def _is_generic_class(self, tp: list[str] | t.CPtr) -> int:
|
||||
"""检查 ClassDef 是否有类型参数(泛型类),返回 1=是 / 0=否
|
||||
|
||||
接收 type_params 而非 cd,避免 cd.type_params 属性访问
|
||||
因跨模块类型推断失败返回 None。
|
||||
"""
|
||||
if tp is None:
|
||||
return 0
|
||||
return 1
|
||||
def _register_generic_template(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
cd: ast.ClassDef | t.CPtr,
|
||||
module_sha1: str):
|
||||
"""注册泛型类模板(类名 + ClassDef 节点 + 来源模块 SHA1)"""
|
||||
if self.GenericClassNames is None:
|
||||
self.GenericClassNames = list[str](pool, 8)
|
||||
self.GenericClassNodes = list[ast.ClassDef | t.CPtr](pool, 8)
|
||||
self.GenericClassSha1s = list[str](pool, 8)
|
||||
self.GenericClassFiles = list[str](pool, 8)
|
||||
if self.GenericClassTpParams is None:
|
||||
self.GenericClassTpParams = CompilerFactory.get_perm_pool().alloc(GENERIC_TEMPLATE_MAX * 8)
|
||||
if self.GenericClassTpParams is None:
|
||||
return
|
||||
string.memset(self.GenericClassTpParams, 0, GENERIC_TEMPLATE_MAX * 8)
|
||||
# 用局部变量接收 list,触发类型推断(避免字段 __len__ 失败)
|
||||
names_local: list[str] | t.CPtr = self.GenericClassNames
|
||||
cn: t.CSizeT = len(names_local)
|
||||
i: t.CSizeT
|
||||
for i in range(cn):
|
||||
nm: str = names_local.get(i)
|
||||
if nm is not None and string.strcmp(nm, cd.name) == 0:
|
||||
return
|
||||
# type_params stdlib 深拷贝:模板节点的 type_params 是 pool 分配的
|
||||
tp_names_buf: str = self._copy_type_params_stdlib(cd.type_params)
|
||||
self.GenericClassNames.append(cd.name)
|
||||
self.GenericClassNodes.append(cd)
|
||||
self.GenericClassSha1s.append(module_sha1)
|
||||
# 同时保存模板来源文件路径(错误定位用,见字段注释)
|
||||
self.GenericClassFiles.append(HandlesType.get_current_file())
|
||||
if tp_names_buf is not None and cn < GENERIC_TEMPLATE_MAX:
|
||||
self.GenericClassTpParams[cn] = t.CSizeT(tp_names_buf)
|
||||
def _copy_type_params_stdlib(self, tp: list[str] | t.CPtr) -> str:
|
||||
"""将模板 type_params 深拷贝为空格分隔、NUL 结尾的 stdlib 缓冲区
|
||||
|
||||
TPC Python 参考实现:type_params = [tp.name for tp in Node.type_params]
|
||||
(Python 字符串不可变天然跨阶段存活);Viper 的 type_params 是 pool
|
||||
分配 list,跨 Phase 内容可能被复用污染,必须注册时拷贝到 stdlib。
|
||||
返回缓冲区指针;tp 为 None(非泛型)或分配失败返回 None。
|
||||
"""
|
||||
if tp is None:
|
||||
return None
|
||||
tp_n: t.CSizeT = len(tp)
|
||||
if tp_n == 0:
|
||||
return None
|
||||
# 计算总长:各名字长度 + (n-1) 个空格 + NUL
|
||||
total: t.CSizeT = 1
|
||||
ti: t.CSizeT
|
||||
for ti in range(tp_n):
|
||||
tp_name: str = tp.get(ti)
|
||||
if tp_name is not None:
|
||||
total += string.strlen(tp_name) + 1
|
||||
buf: str = CompilerFactory.get_perm_pool().alloc(total)
|
||||
if buf is None:
|
||||
return None
|
||||
buf[0] = '\0'
|
||||
for ti in range(tp_n):
|
||||
tp_name = tp.get(ti)
|
||||
if tp_name is None:
|
||||
continue
|
||||
if ti > 0 and buf[0] != '\0':
|
||||
string.strcat(buf, " ")
|
||||
string.strcat(buf, tp_name)
|
||||
return buf
|
||||
def _find_generic_template_tp_params(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
class_name: str) -> list[str] | t.CPtr:
|
||||
"""查找泛型类模板的类型参数名列表,未找到返回 None
|
||||
|
||||
从注册时深拷贝的 stdlib 缓冲区重建当前 pool 的 list[str]
|
||||
(特化期间 pool 有效,方法与体翻译共用)。与 GenericClassNames 同序。
|
||||
"""
|
||||
if self.GenericClassNames is None or class_name is None \
|
||||
or self.GenericClassTpParams is None:
|
||||
return None
|
||||
names_local: list[str] | t.CPtr = self.GenericClassNames
|
||||
cn: t.CSizeT = len(names_local)
|
||||
i: t.CSizeT
|
||||
for i in range(cn):
|
||||
nm: str = names_local.get(i)
|
||||
if nm is not None and string.strcmp(nm, class_name) == 0:
|
||||
if i >= GENERIC_TEMPLATE_MAX:
|
||||
return None
|
||||
buf_addr: t.CSizeT = self.GenericClassTpParams[i]
|
||||
if buf_addr == 0:
|
||||
return None
|
||||
buf_tp: str = (str | t.CPtr)(t.CVoid(buf_addr, t.CPtr))
|
||||
# 空格分隔 → list[str]
|
||||
# 注意:list[str](pool, 8) 第二个参数是 elem_size(指针 8 字节),
|
||||
# 不是容量!传 4 会导致 get(i) 偏移算错、append 相互覆盖
|
||||
# (Pair[T1,T2] 的 seg1 写 data+4 覆盖 seg0 高 4 字节 → strcmp
|
||||
# 收到 0x15B78D5015B78CB0 混合垃圾崩溃,GenericTest 回归根因)
|
||||
tp_list: list[str] | t.CPtr = list[str](pool, 8)
|
||||
if tp_list is None:
|
||||
return None
|
||||
seg_start: t.CSizeT = 0
|
||||
pos: t.CSizeT = 0
|
||||
blen: t.CSizeT = string.strlen(buf_tp)
|
||||
while pos <= blen:
|
||||
if buf_tp[pos] == ' ' or buf_tp[pos] == '\0':
|
||||
seg_len: t.CSizeT = pos - seg_start
|
||||
if seg_len > 0:
|
||||
seg: str = pool.alloc(seg_len + 1)
|
||||
if seg is not None:
|
||||
string.strncpy(seg, buf_tp + seg_start, seg_len)
|
||||
seg[seg_len] = '\0'
|
||||
tp_list.append(seg)
|
||||
seg_start = pos + 1
|
||||
pos += 1
|
||||
return tp_list
|
||||
return None
|
||||
def _find_generic_template(self, class_name: str) -> ast.ClassDef | t.CPtr:
|
||||
"""查找泛型类模板,返回 ClassDef 节点或 None"""
|
||||
if self.GenericClassNames is None or class_name is None:
|
||||
return None
|
||||
# 用局部变量接收 list,触发类型推断(避免字段 __len__ 失败)
|
||||
names_local: list[str] | t.CPtr = self.GenericClassNames
|
||||
nodes_local: list[ast.ClassDef | t.CPtr] | t.CPtr = self.GenericClassNodes
|
||||
cn: t.CSizeT = len(names_local)
|
||||
i: t.CSizeT
|
||||
for i in range(cn):
|
||||
nm: str = names_local.get(i)
|
||||
if nm is not None and string.strcmp(nm, class_name) == 0:
|
||||
node: ast.ClassDef | t.CPtr = nodes_local.get(i)
|
||||
return node
|
||||
return None
|
||||
def _find_generic_template_sha1(self, class_name: str) -> str:
|
||||
"""查找泛型类模板的来源模块 SHA1,未找到返回 None"""
|
||||
if self.GenericClassNames is None or class_name is None:
|
||||
return None
|
||||
# 用局部变量接收 list,触发类型推断
|
||||
names_local: list[str] | t.CPtr = self.GenericClassNames
|
||||
sha1s_local: list[str] | t.CPtr = self.GenericClassSha1s
|
||||
cn: t.CSizeT = len(names_local)
|
||||
i: t.CSizeT
|
||||
for i in range(cn):
|
||||
nm: str = names_local.get(i)
|
||||
if nm is not None and string.strcmp(nm, class_name) == 0:
|
||||
sha1_val: str = sha1s_local.get(i)
|
||||
return sha1_val
|
||||
return None
|
||||
def _find_generic_template_file(self, class_name: str) -> str:
|
||||
"""查找泛型类模板的来源文件路径,未找到返回 None
|
||||
|
||||
与 _find_generic_template_sha1 同表同序;供特化翻译模板方法体时
|
||||
临时切换 CurrentFile(错误定位:模板 node.lineno 需配模板文件路径)。
|
||||
"""
|
||||
if self.GenericClassNames is None or class_name is None:
|
||||
return None
|
||||
names_local: list[str] | t.CPtr = self.GenericClassNames
|
||||
files_local: list[str] | t.CPtr = self.GenericClassFiles
|
||||
cn: t.CSizeT = len(names_local)
|
||||
i: t.CSizeT
|
||||
for i in range(cn):
|
||||
nm: str = names_local.get(i)
|
||||
if nm is not None and string.strcmp(nm, class_name) == 0:
|
||||
f_val: str = files_local.get(i)
|
||||
return f_val
|
||||
return None
|
||||
def _mangle_generic_class_name(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
class_name: str,
|
||||
type_args: list[str] | t.CPtr) -> str:
|
||||
"""生成特化类名: list + [int] -> list[int]
|
||||
|
||||
分配新缓冲区拼接,避免原地 strcat 导致缓冲区溢出
|
||||
"""
|
||||
if class_name is None or type_args is None or pool is None:
|
||||
return class_name
|
||||
n: t.CSizeT = len(type_args)
|
||||
if n == 0:
|
||||
return class_name
|
||||
# 计算总长度: class_name + "[" + arg0 + "," + arg1 + ... + "]" + NUL
|
||||
total_len: t.CSizeT = string.strlen(class_name) + 2 # "[" 和 "]"
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
if i > 0:
|
||||
total_len += 1 # ","
|
||||
ta: str = type_args.get(i)
|
||||
if ta is not None:
|
||||
total_len += string.strlen(ta)
|
||||
total_len += 1 # NUL
|
||||
# 分配新缓冲区
|
||||
mangled: str = pool.alloc(total_len)
|
||||
if mangled is None:
|
||||
return class_name
|
||||
mangled[0] = '\0'
|
||||
string.strcat(mangled, class_name)
|
||||
string.strcat(mangled, "[")
|
||||
for i in range(n):
|
||||
if i > 0:
|
||||
string.strcat(mangled, ",")
|
||||
ta: str = type_args.get(i)
|
||||
if ta is not None:
|
||||
string.strcat(mangled, ta)
|
||||
string.strcat(mangled, "]")
|
||||
return mangled
|
||||
def _clone_annotation(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
tp_names: list[str] | t.CPtr,
|
||||
type_args: list[str] | t.CPtr) -> ast.AST | t.CPtr:
|
||||
"""拷贝类型注解表达式,替换类型参数 T 为具体类型名
|
||||
|
||||
tp_names: 类型参数名列表 ['T']
|
||||
type_args: 类型实参名列表 ['int']
|
||||
"""
|
||||
if node is None:
|
||||
return None
|
||||
k: int = node.kind()
|
||||
|
||||
# Name: 可能是类型参数 T
|
||||
if k == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
|
||||
if nm.id is not None:
|
||||
n: t.CSizeT = len(tp_names) if tp_names is not None else 0
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
tpn: str = tp_names.get(i)
|
||||
if tpn is not None and string.strcmp(nm.id, tpn) == 0:
|
||||
ta: str = type_args.get(i)
|
||||
# 类型实参可能是复合类型(如 "AST|t.CPtr"),用 _parse_type_string 解析
|
||||
parsed_node: ast.AST | t.CPtr = HandlesType._parse_type_string(pool, ta, nm.ctx)
|
||||
return parsed_node
|
||||
return ast.Name(pool, nm.id, nm.ctx)
|
||||
return None
|
||||
|
||||
# Attribute: t.CPtr 等
|
||||
if k == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
|
||||
new_value: ast.AST | t.CPtr = self._clone_annotation(pool, at.value, tp_names, type_args)
|
||||
return ast.Attribute(pool, new_value, at.attr, at.ctx)
|
||||
|
||||
# BinOp: T | t.CPtr 等
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
|
||||
new_left: ast.AST | t.CPtr = self._clone_annotation(pool, bop.left, tp_names, type_args)
|
||||
new_right: ast.AST | t.CPtr = self._clone_annotation(pool, bop.right, tp_names, type_args)
|
||||
return ast.BinOp(pool, new_left, bop.op, new_right)
|
||||
|
||||
# Subscript: list[int] 等
|
||||
if k == ast.ASTKind.Subscript:
|
||||
sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node)
|
||||
new_value2: ast.AST | t.CPtr = self._clone_annotation(pool, sub.value, tp_names, type_args)
|
||||
new_slice: ast.AST | t.CPtr = self._clone_annotation(pool, sub.slice, tp_names, type_args)
|
||||
return ast.Subscript(pool, new_value2, new_slice, sub.ctx)
|
||||
|
||||
# Tuple: (T, int) 等
|
||||
if k == ast.ASTKind.Tuple:
|
||||
tup: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(node)
|
||||
new_elts: list[ast.AST | t.CPtr] | t.CPtr = list[ast.AST | t.CPtr](pool, 8)
|
||||
if tup.elts is not None:
|
||||
tup_elts: list[ast.AST | t.CPtr] | t.CPtr = tup.elts
|
||||
en: t.CSizeT = len(tup_elts)
|
||||
ei: t.CSizeT
|
||||
for ei in range(en):
|
||||
el: ast.AST | t.CPtr = tup_elts.get(ei)
|
||||
new_el: ast.AST | t.CPtr = self._clone_annotation(pool, el, tp_names, type_args)
|
||||
if new_el is not None:
|
||||
new_elts.append(new_el)
|
||||
return ast.Tuple(pool, new_elts, tup.ctx)
|
||||
|
||||
# Constant: 默认值等
|
||||
if k == ast.ASTKind.Constant:
|
||||
cnst: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
|
||||
return ast.Constant(pool, cnst.const_kind, cnst.int_val, cnst.float_val,
|
||||
cnst.str_val, cnst.lineno, cnst.col_offset)
|
||||
|
||||
# 其他: 直接引用(不拷贝)
|
||||
return node
|
||||
def _clone_arguments(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
args: ast.AST | t.CPtr,
|
||||
tp_names: list[str] | t.CPtr,
|
||||
type_args: list[str] | t.CPtr) -> ast.AST | t.CPtr:
|
||||
"""拷贝 Arguments 节点,替换 arg annotation 中的 T"""
|
||||
if args is None:
|
||||
return None
|
||||
if args.kind() != ast.ASTKind.Arguments:
|
||||
return args
|
||||
old_args: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args)
|
||||
# 拷贝 args 列表,替换每个 Arg 的 annotation
|
||||
new_arg_list: list[ast.AST | t.CPtr] | t.CPtr = list[ast.AST | t.CPtr](pool, 8)
|
||||
if old_args.args is not None:
|
||||
old_arg_list: list[ast.AST | t.CPtr] | t.CPtr = old_args.args
|
||||
an: t.CSizeT = len(old_arg_list)
|
||||
ai: t.CSizeT
|
||||
for ai in range(an):
|
||||
arg_node: ast.AST | t.CPtr = old_arg_list.get(ai)
|
||||
if arg_node is None:
|
||||
continue
|
||||
if arg_node.kind() == ast.ASTKind.Arg:
|
||||
ag: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(arg_node)
|
||||
new_anno: ast.AST | t.CPtr = self._clone_annotation(pool, ag.annotation, tp_names, type_args)
|
||||
new_arg: ast.Arg | t.CPtr = ast.Arg(pool, ag.arg, new_anno)
|
||||
new_arg_list.append(new_arg)
|
||||
else:
|
||||
new_arg_list.append(arg_node)
|
||||
return ast.Arguments(pool, new_arg_list, old_args.vararg, old_args.kwarg,
|
||||
old_args.defaults, old_args.kw_defaults)
|
||||
def _clone_classdef_for_spec(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
cd: ast.ClassDef | t.CPtr,
|
||||
spec_name: str,
|
||||
tp_names: list[str] | t.CPtr,
|
||||
type_args: list[str] | t.CPtr) -> ast.ClassDef | t.CPtr:
|
||||
"""拷贝 ClassDef 节点用于泛型特化
|
||||
|
||||
- 替换类名为 spec_name
|
||||
- 清除 type_params(特化后不是泛型类)
|
||||
- 拷贝 children 中的 AnnAssign 和 FunctionDef,替换类型注解中的 T
|
||||
- 方法体直接引用原始节点(通过 type_map 上下文处理 T)
|
||||
"""
|
||||
# 创建新 ClassDef(type_params=None 表示非泛型)
|
||||
new_cd: ast.ClassDef | t.CPtr = ast.ClassDef(pool, spec_name, cd.bases, cd.keywords,
|
||||
cd.decorator_list, None)
|
||||
# 拷贝 children
|
||||
if cd.children is not None:
|
||||
cd_children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||||
cn: t.CSizeT = len(cd_children)
|
||||
ci: t.CSizeT
|
||||
for ci in range(cn):
|
||||
child: ast.AST | t.CPtr = cd_children.get(ci)
|
||||
if child is None:
|
||||
continue
|
||||
ck: int = child.kind()
|
||||
|
||||
if ck == ast.ASTKind.AnnAssign:
|
||||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(child)
|
||||
new_target: ast.AST | t.CPtr = aa.target
|
||||
new_anno2: ast.AST | t.CPtr = self._clone_annotation(pool, aa.annotation, tp_names, type_args)
|
||||
new_value3: ast.AST | t.CPtr = aa.value
|
||||
new_aa: ast.AnnAssign | t.CPtr = ast.AnnAssign(pool, new_target, new_anno2, new_value3, aa.simple)
|
||||
new_cd.append(new_aa)
|
||||
|
||||
elif ck == ast.ASTKind.FunctionDef:
|
||||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child)
|
||||
new_args2: ast.AST | t.CPtr = self._clone_arguments(pool, fd.args, tp_names, type_args)
|
||||
new_returns2: ast.AST | t.CPtr = self._clone_annotation(pool, fd.returns, tp_names, type_args)
|
||||
new_fd: ast.FunctionDef | t.CPtr = ast.FunctionDef(pool, fd.name, new_args2,
|
||||
fd.decorator_list, new_returns2, 0)
|
||||
# 方法体直接引用原始节点
|
||||
if fd.children is not None:
|
||||
fd_children: list[ast.AST | t.CPtr] | t.CPtr = fd.children
|
||||
bcn: t.CSizeT = len(fd_children)
|
||||
bci: t.CSizeT
|
||||
for bci in range(bcn):
|
||||
body_stmt: ast.AST | t.CPtr = fd_children.get(bci)
|
||||
if body_stmt is not None:
|
||||
new_fd.append(body_stmt)
|
||||
new_cd.append(new_fd)
|
||||
|
||||
else:
|
||||
new_cd.append(child)
|
||||
|
||||
return new_cd
|
||||
def _find_cached_spec(self, spec_key: str) -> str:
|
||||
"""查找已缓存的特化名,未找到返回 None"""
|
||||
if self.SpecKeys is None or spec_key is None:
|
||||
return None
|
||||
i: int
|
||||
for i in range(self.SpecCount):
|
||||
key_addr: t.CSizeT = self.SpecKeys[i]
|
||||
if key_addr != 0:
|
||||
k: str = (str | t.CPtr)(t.CVoid(key_addr, t.CPtr))
|
||||
if k is not None and string.strcmp(k, spec_key) == 0:
|
||||
name_addr: t.CSizeT = self.SpecNames[i]
|
||||
if name_addr != 0:
|
||||
return (str | t.CPtr)(t.CVoid(name_addr, t.CPtr))
|
||||
return None
|
||||
def _cache_spec(self, pool: memhub.MemBuddy | t.CPtr, spec_key: str, spec_name: str):
|
||||
"""缓存特化结果(stdlib 深拷贝存储,跨文件安全)"""
|
||||
if spec_key is None or spec_name is None:
|
||||
return
|
||||
if self.SpecKeys is None:
|
||||
self.SpecKeys = CompilerFactory.get_perm_pool().alloc(SPEC_CACHE_MAX * 8)
|
||||
self.SpecNames = CompilerFactory.get_perm_pool().alloc(SPEC_CACHE_MAX * 8)
|
||||
if self.SpecKeys is None or self.SpecNames is None:
|
||||
return
|
||||
string.memset(self.SpecKeys, 0, SPEC_CACHE_MAX * 8)
|
||||
string.memset(self.SpecNames, 0, SPEC_CACHE_MAX * 8)
|
||||
self.SpecCount = 0
|
||||
if self.SpecCount >= SPEC_CACHE_MAX:
|
||||
return
|
||||
# 深拷贝字符串到 stdlib 区
|
||||
key_len: t.CSizeT = string.strlen(spec_key)
|
||||
name_len: t.CSizeT = string.strlen(spec_name)
|
||||
key_copy: str = CompilerFactory.get_perm_pool().alloc(key_len + 1)
|
||||
name_copy: str = CompilerFactory.get_perm_pool().alloc(name_len + 1)
|
||||
if key_copy is None or name_copy is None:
|
||||
return
|
||||
string.strcpy(key_copy, spec_key)
|
||||
string.strcpy(name_copy, spec_name)
|
||||
self.SpecKeys[self.SpecCount] = t.CSizeT(key_copy)
|
||||
self.SpecNames[self.SpecCount] = t.CSizeT(name_copy)
|
||||
self.SpecCount += 1
|
||||
def _merge_template_imports(self, trans: HT.Translator | t.CPtr,
|
||||
template_sha1: str) -> None:
|
||||
"""将模板模块的 imports 并入 trans._imported_modules(空格分隔)"""
|
||||
if trans is None or template_sha1 is None:
|
||||
return
|
||||
tdeps: str = StubMerger.LookupIncludesDeps(template_sha1)
|
||||
if tdeps is None or tdeps[0] == '\0':
|
||||
return
|
||||
cur: str = trans._imported_modules
|
||||
if cur is None or cur[0] == '\0':
|
||||
trans._imported_modules = tdeps
|
||||
return
|
||||
cur_len: t.CSizeT = string.strlen(cur)
|
||||
td_len: t.CSizeT = string.strlen(tdeps)
|
||||
merged: str = trans.Pool.alloc(cur_len + td_len + 2)
|
||||
if merged is None:
|
||||
return
|
||||
string.strcpy(merged, cur)
|
||||
merged[cur_len] = ' '
|
||||
string.strcpy(merged + cur_len + 1, tdeps)
|
||||
trans._imported_modules = merged
|
||||
def _specialize_generic_class(self, trans: HT.Translator | t.CPtr,
|
||||
class_name: str,
|
||||
type_args: list[str] | t.CPtr) -> str:
|
||||
"""特化泛型类,返回特化类名
|
||||
|
||||
1. 查找泛型模板
|
||||
2. 生成特化名
|
||||
3. 检查缓存
|
||||
4. 拷贝 ClassDef 节点(替换类型注解中的 T)
|
||||
5. 设置 type_map 上下文(用于方法体中的 T 替换)
|
||||
6. 调用 translate_class_def 翻译特化类
|
||||
7. 返回特化名
|
||||
"""
|
||||
if trans is None or class_name is None or type_args is None:
|
||||
return None
|
||||
# 泛型循环套用防护:递归深度 +1,超过上限立即报错终止(防 F-bounded
|
||||
# 等循环特化把编译变死循环)。所有返回路径都必须 -1(见各 return 前)。
|
||||
self.GenericSpecDepth += 1
|
||||
if self.GenericSpecDepth > GENERIC_SPEC_MAX_DEPTH:
|
||||
err_spec: str = trans.Pool.alloc(256)
|
||||
if err_spec is not None:
|
||||
viperlib.snprintf(err_spec, 256,
|
||||
"泛型特化递归过深(疑似泛型循环套用),类: %s 深度=%d",
|
||||
class_name, self.GenericSpecDepth)
|
||||
HandlesType.fatal_error(None, err_spec, "InternalCompilerError")
|
||||
HandlesType.fatal_error(None, "泛型特化递归过深(疑似泛型循环套用)", "InternalCompilerError")
|
||||
# 防御:泛型上下文内收集的 type_args 若残留未替换的类型参数名(如 "T"),
|
||||
# 统一替换为具体类型名,避免 ndarray[T] 二次递归特化崩溃。
|
||||
# 调用方传入的 type_args 均为临时新建列表,就地替换无共享副作用。
|
||||
ta_cnt_g: t.CSizeT = len(type_args)
|
||||
ta_i_g: t.CSizeT
|
||||
for ta_i_g in range(ta_cnt_g):
|
||||
ta_raw_g: str = type_args.get(ta_i_g)
|
||||
if ta_raw_g is not None:
|
||||
ta_rsv_g: str = HandlesType.resolve_generic_type_name(ta_raw_g)
|
||||
if ta_rsv_g is not None and string.strcmp(ta_raw_g, ta_rsv_g) != 0:
|
||||
type_args.set(ta_i_g, ta_rsv_g)
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
|
||||
# 1. 查找泛型模板
|
||||
template_cd: ast.ClassDef | t.CPtr = self._find_generic_template(class_name)
|
||||
if template_cd is None:
|
||||
self.GenericSpecDepth -= 1
|
||||
return None
|
||||
|
||||
# 2. 生成特化名
|
||||
spec_name: str = self._mangle_generic_class_name(pool, class_name, type_args)
|
||||
if spec_name is None:
|
||||
self.GenericSpecDepth -= 1
|
||||
return None
|
||||
|
||||
# 治本修复:Phase B 补译泛型特化类方法体(统一入口,在 cache/existing 检查之前)
|
||||
# Phase 1a(declare_only==1)特化时只注册结构体不译方法体(MethodsEmitted==0),
|
||||
# Phase B(declare_only==0)重复进入时若方法体未译,补译方法体生成 define,
|
||||
# 避免 GSList[Line].append 等符号只有 declare 无 define → 链接失败。
|
||||
# 首次 Phase B 特化(Phase 1a 未特化)find_struct 返回 None,不补译,走下方正常全量翻译。
|
||||
if trans._declare_only == 0:
|
||||
pre_existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name)
|
||||
if pre_existing is not None and pre_existing.MethodsEmitted == 0:
|
||||
# 防重入:先标记 MethodsEmitted=1,避免补译过程中方法体/返回类型注解
|
||||
# 再次触发 _specialize_generic_class(如 __iter__ 返回 list[T]|t.CPtr)
|
||||
# 导致无限递归补译 → OOM。补译完成后已设置,无需恢复。
|
||||
# 注意:此处提前置位后调用 _translate_oop_methods 必须传 reemit=1
|
||||
# (补译模式),否则其 MethodsEmitted==1 防重复检查会拦截补译,
|
||||
# 方法体永不发射 → 特化方法只有 call 无 define → 链接 undefined symbol。
|
||||
pre_existing.MethodsEmitted = 1
|
||||
# 从 stdlib 深拷贝表取 type_params(模板节点 pool list 跨 Phase 可能失效)
|
||||
tp_names_pre: list[str] | t.CPtr = self._find_generic_template_tp_params(
|
||||
pool, class_name)
|
||||
if tp_names_pre is None:
|
||||
tp_names_pre = template_cd.type_params
|
||||
spec_cd_pre: ast.ClassDef | t.CPtr = self._clone_classdef_for_spec(
|
||||
pool, template_cd, spec_name, tp_names_pre, type_args)
|
||||
if spec_cd_pre is not None:
|
||||
trans.GenericTypeParamNames = tp_names_pre
|
||||
trans.GenericTypeArgs = type_args
|
||||
HandlesType.set_generic_context(tp_names_pre, type_args)
|
||||
saved_ms_pre: str = trans.ModuleSha1
|
||||
saved_imp_pre: str = trans._imported_modules
|
||||
template_sha1_pre: str = self._find_generic_template_sha1(class_name)
|
||||
if template_sha1_pre is not None:
|
||||
trans.ModuleSha1 = template_sha1_pre
|
||||
self._merge_template_imports(trans, template_sha1_pre)
|
||||
# 错误定位上下文:补译的是模板方法体(spec_cd_pre 克隆自模板,
|
||||
# node.lineno 是模板文件行号)。切换 CurrentFile 到模板文件并压入
|
||||
# trace 帧,使 fatal_error 正确显示模板文件位置(翻译完恢复)。
|
||||
saved_cur_pre: str = HandlesType.get_current_file()
|
||||
tpl_file_pre: str = self._find_generic_template_file(class_name)
|
||||
if tpl_file_pre is not None:
|
||||
HandlesType.set_current_file(tpl_file_pre)
|
||||
HandlesType.push_trace(tpl_file_pre, template_cd.lineno)
|
||||
HandlesClassDef._translate_oop_methods(trans, spec_cd_pre, pre_existing.Ty, spec_name, 0, 1)
|
||||
if tpl_file_pre is not None:
|
||||
HandlesType.pop_trace()
|
||||
HandlesType.set_current_file(saved_cur_pre)
|
||||
trans.ModuleSha1 = saved_ms_pre
|
||||
trans._imported_modules = saved_imp_pre
|
||||
trans.GenericTypeParamNames = None
|
||||
trans.GenericTypeArgs = None
|
||||
HandlesType.clear_generic_context()
|
||||
|
||||
# 3. 检查缓存(spec_key 包含所有类型实参,避免多参数泛型缓存冲突)
|
||||
# 分配新缓冲区避免原地 strcat 溢出
|
||||
sk_n: t.CSizeT = len(type_args)
|
||||
sk_total: t.CSizeT = string.strlen(class_name) + 2 # "<" 和 ">"
|
||||
sk_i: t.CSizeT
|
||||
for sk_i in range(sk_n):
|
||||
if sk_i > 0:
|
||||
sk_total += 1 # ","
|
||||
sk_ta: str = type_args.get(sk_i)
|
||||
if sk_ta is not None:
|
||||
sk_total += string.strlen(sk_ta)
|
||||
sk_total += 1 # NUL
|
||||
spec_key: str = pool.alloc(sk_total)
|
||||
if spec_key is None:
|
||||
self.GenericSpecDepth -= 1
|
||||
return None
|
||||
spec_key[0] = '\0'
|
||||
string.strcat(spec_key, class_name)
|
||||
string.strcat(spec_key, "<")
|
||||
for sk_i in range(sk_n):
|
||||
if sk_i > 0:
|
||||
string.strcat(spec_key, ",")
|
||||
sk_ta: str = type_args.get(sk_i)
|
||||
if sk_ta is not None:
|
||||
string.strcat(spec_key, sk_ta)
|
||||
string.strcat(spec_key, ">")
|
||||
cached: str = self._find_cached_spec(spec_key)
|
||||
if cached is not None:
|
||||
self.GenericSpecDepth -= 1
|
||||
return cached
|
||||
|
||||
# 4. 检查是否已注册(Phase B 重复特化)
|
||||
existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name)
|
||||
if existing is not None:
|
||||
self._cache_spec(pool, spec_key, spec_name)
|
||||
self.GenericSpecDepth -= 1
|
||||
return spec_name
|
||||
|
||||
# 预注册缓存(防止递归)
|
||||
self._cache_spec(pool, spec_key, spec_name)
|
||||
|
||||
# 5. 拷贝 ClassDef 节点
|
||||
# 从 stdlib 深拷贝表取 type_params(模板节点 pool list 跨 Phase 可能失效)
|
||||
tp_names: list[str] | t.CPtr = self._find_generic_template_tp_params(
|
||||
pool, class_name)
|
||||
if tp_names is None:
|
||||
tp_names = template_cd.type_params
|
||||
spec_cd: ast.ClassDef | t.CPtr = self._clone_classdef_for_spec(
|
||||
pool, template_cd, spec_name, tp_names, type_args)
|
||||
if spec_cd is None:
|
||||
self.GenericSpecDepth -= 1
|
||||
return None
|
||||
|
||||
# 6. 设置 type_map 上下文(用于方法体中的 T 替换)
|
||||
trans.GenericTypeParamNames = tp_names
|
||||
trans.GenericTypeArgs = type_args
|
||||
HandlesType.set_generic_context(tp_names, type_args)
|
||||
|
||||
# 7. 翻译特化类
|
||||
# 切换 trans.ModuleSha1 为泛型模板定义模块的 SHA1,
|
||||
# 使结构体类型名和方法定义名都用定义模块的 SHA1 前缀,
|
||||
# 与调用端 get_struct_sha1(class_name) 查到的 SHA1 一致。
|
||||
# 同时并入模板模块的 imports(见 _merge_template_imports 注释),
|
||||
# 避免模板方法体内的跨模块调用被误报"模块未导入"。
|
||||
saved_module_sha1: str = trans.ModuleSha1
|
||||
saved_imported: str = trans._imported_modules
|
||||
template_sha1: str = self._find_generic_template_sha1(class_name)
|
||||
if template_sha1 is not None:
|
||||
trans.ModuleSha1 = template_sha1
|
||||
self._merge_template_imports(trans, template_sha1)
|
||||
# 错误定位上下文:spec_cd 克隆自模板,方法体的 node.lineno 是模板文件
|
||||
# 行号,而 CurrentFile 仍是调用方文件 → 错误显示错位。切换 CurrentFile
|
||||
# 到模板文件并压入 trace 帧(翻译完恢复),使 fatal_error 正确溯源。
|
||||
saved_cur_full: str = HandlesType.get_current_file()
|
||||
tpl_file_full: str = self._find_generic_template_file(class_name)
|
||||
if tpl_file_full is not None:
|
||||
HandlesType.set_current_file(tpl_file_full)
|
||||
HandlesType.push_trace(tpl_file_full, template_cd.lineno)
|
||||
HandlesClassDef.translate_class_def(trans, spec_cd)
|
||||
if tpl_file_full is not None:
|
||||
HandlesType.pop_trace()
|
||||
HandlesType.set_current_file(saved_cur_full)
|
||||
# 恢复原始 ModuleSha1 与 imports
|
||||
trans.ModuleSha1 = saved_module_sha1
|
||||
trans._imported_modules = saved_imported
|
||||
|
||||
# 8. 清除 type_map 上下文
|
||||
trans.GenericTypeParamNames = None
|
||||
trans.GenericTypeArgs = None
|
||||
HandlesType.clear_generic_context()
|
||||
|
||||
# 特化结果字段名完整性检查(fail-fast:字段名缺失 = 字段表损坏,
|
||||
# 静默继续会让后续 GEP 按错索引访问)
|
||||
if string.strcmp(class_name, "GSListNode") == 0:
|
||||
result_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name)
|
||||
if result_entry is not None:
|
||||
ri: int
|
||||
for ri in range(result_entry.FieldCount):
|
||||
rfe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry(
|
||||
result_entry, ri)
|
||||
if rfe is not None:
|
||||
rfn: str = HandlesStruct.get_field_name_ptr(rfe)
|
||||
if rfn is None:
|
||||
VLogger.error("SPEC 字段名缺失(字段表损坏)", "SPEC")
|
||||
HandlesType.fatal_error(None, "SPEC 字段名缺失(字段表损坏)", "TypeError")
|
||||
|
||||
self.GenericSpecDepth -= 1
|
||||
return spec_name
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -27,6 +27,11 @@ import lib.core.Gen.FuncGenBase as FuncGenBase
|
||||
import lib.core.Gen.FuncGenDef as FuncGenDef
|
||||
import lib.core.Gen.FuncGenMixin as FuncGenMixin
|
||||
import lib.core.Gen.ClassGenMixin as ClassGenMixin
|
||||
import lib.core.Gen.ClassGenBase as ClassGenBase
|
||||
import lib.core.Gen.ClassGenEnum as ClassGenEnum
|
||||
import lib.core.Gen.ClassGenGeneric as ClassGenGeneric
|
||||
import lib.core.Gen.ClassGenVTable as ClassGenVTable
|
||||
import lib.core.Gen.ClassGenDef as ClassGenDef
|
||||
import lib.core.Gen.ImportsGenMixin as ImportsGenMixin
|
||||
import lib.core.Gen.StmtGenMixin as StmtGenMixin
|
||||
import lib.core.Gen.AssignGenMixin as AssignGenMixin
|
||||
@@ -62,7 +67,10 @@ class Generator(BaseGenMixin.BaseGenMixin, TypeGenMixin.TypeGenMixin,
|
||||
CallGenLib.CallGenLib, CallGenDispatch.CallGenDispatch,
|
||||
FuncGenBase.FuncGenBase, FuncGenDef.FuncGenDef,
|
||||
FuncGenMixin.FuncGenMixin,
|
||||
ClassGenMixin.ClassGenMixin, ImportsGenMixin.ImportsGenMixin,
|
||||
ClassGenMixin.ClassGenMixin, ClassGenBase.ClassGenBase,
|
||||
ClassGenEnum.ClassGenEnum, ClassGenGeneric.ClassGenGeneric,
|
||||
ClassGenVTable.ClassGenVTable, ClassGenDef.ClassGenDef,
|
||||
ImportsGenMixin.ImportsGenMixin,
|
||||
StmtGenMixin.StmtGenMixin, AssignGenMixin.AssignGenMixin,
|
||||
VarGenMixin.VarGenMixin, TranslatorGenMixin.TranslatorGenMixin):
|
||||
"""生成器:多继承 Mixin 组合(对象化迁移宿主)"""
|
||||
|
||||
@@ -1056,6 +1056,39 @@ def translate_class_def(trans: HT.Translator | t.CPtr,
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ClassGenDef 跨 Mixin 委托(阶段 D:ClassGenMixin 拆 Base/Def 后
|
||||
# translate_class_def 经此调用这些方法。参数与目标方法一致,去 self)
|
||||
# ============================================================
|
||||
def _is_exception_class_def(cd: ast.ClassDef | t.CPtr) -> int:
|
||||
"""类定义是否是异常类(委托到 gen._is_exception_class_def)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._is_exception_class_def(cd)
|
||||
return 0
|
||||
|
||||
|
||||
def _register_exception_class_def(trans: HT.Translator | t.CPtr,
|
||||
cd: ast.ClassDef | t.CPtr) -> int:
|
||||
"""注册异常类(分配编码 + 记录父类)(委托到 gen._register_exception_class_def)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._register_exception_class_def(trans, cd)
|
||||
return 0
|
||||
|
||||
|
||||
def _register_class_meta_list(pool: memhub.MemBuddy | t.CPtr,
|
||||
kind: int, cls: str,
|
||||
value_node: ast.AST | t.CPtr) -> None:
|
||||
"""解析类体 __provides__/__requires__ 的 list[str] 字面量并注册(委托到 gen._register_class_meta_list)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
g._register_class_meta_list(pool, kind, cls, value_node)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# VTable 生成
|
||||
#
|
||||
|
||||
Reference in new issue
Block a user