类别:a(编译器缺陷 —— 特化名生成点不止一处,实参在"裸名/带前缀"两态并存)
背景(命名源审计,两个独立检索子代理收敛到同一清单):`_norm_type_arg_name`
是唯一规范化器,但"拼 Class[a0,a1]"的构造点有 20+ 处,其中 6 处绕过它。
本轮把规范化**下沉到唯一生成器**,让所有调用方自动同源 —— 该函数对已规范化的串
是幂等的(规则 2/3/6 原样返回,嵌套 rawptr[X] 递归同形)。
改动:
1. ClassGenGeneric._mangle_generic_class_name 增 from_imports 参数:逐实参经
TypeGenResolve._norm_type_arg_name 归一后再拼串(长度计算与拼接同用归一后列表)。
唯一调用点 _specialize_generic_class 传 trans._from_imports。
2. ClassGenBase._get_base_name 增 from_imports 参数:Subscript 分支的类型实参
(原为裸 Name.id)同样归一 —— 该函数产出的父类特化名要拿去 find_struct_by_module
查、并写入 entry.ParentName,而注册名由生成器产出,不归一必然对不上
(父类 GSListNode[Value] vs 注册的 GSListNode[{sha1}.Value])。
三处调用点(_get_parent_class / _collect_parents / _trigger_base_specialization)
传 trans._from_imports;递归调用透传。
3. _trigger_base_specialization 本身无需改:它的裸实参进入 _specialize_generic_class,
已由第 1 条统一归一。
收敛效果(连带):_specialize_generic_class 的 spec_name 与
TypeGenResolve._resolve_generic_subscript_ty 自拼的 gen_mangled 现已同形(后者本就
归一),源码注释里"gen_mangled 与特化名可能不一致 ⇒ 用 spec_name_chk 重查"那条
隐性双名自然不再触发。
遗留(未动,见审计清单):ExprGenConst.translate_list_literal /
CallGenCtor._infer_generic_ctor_type_arg 传的内建名不受影响(规则 6 原样保留),
但其"类名"实参现由生成器统一归一;CallGenCall/CallGenDispatch 从已注册名回拆
"[...]" 时用 strchr 按首个逗号切分(深度不敏感)另计。
影响面:ABI 可见(结构体名 / 方法符号后缀段);需 TPV 自举重建 + 回归验证,
重点观察 VpiReader 的泛型键匹配(其键以 T 占位符,初判不受影响)。
1262 lines
62 KiB
Plaintext
1262 lines
62 KiB
Plaintext
import t, c
|
||
from stdint import *
|
||
import ast
|
||
import memhub
|
||
import string
|
||
import stdlib
|
||
import viperlib
|
||
import lib.core.Gen.Translator as HT
|
||
import lib.core.CompilerFactory as CompilerFactory
|
||
import lib.core.Gen.GenTypes as GenTypes
|
||
import lib.core.Gen.Generator as Generator
|
||
|
||
|
||
# ============================================================
|
||
# 本地常量(阶段 D 拆分时从 ClassGenMixin 顶层遗漏,补回:
|
||
# 方法元数据/类元数据/装饰器/异常表容量与编码;本地副本避免跨模块 CDefine 查找)
|
||
# ============================================================
|
||
# 方法元数据 flag 位(对齐 TPC HandlesBase _METHOD_META_*)
|
||
define META_TLS = 32
|
||
# 类编译期元数据表容量上限(__provides__/__requires__/__require_must__)
|
||
define CLASS_META_MAX = 256
|
||
# 自定义装饰器 wrapper 表容量上限(带 @decor 的函数数)
|
||
define DECOR_FUNC_MAX = 64
|
||
# 装饰器表槽内函数名/wrapper 名长度(含 NUL)
|
||
define DECOR_NAME_LEN = 128
|
||
# 异常类注册表容量上限(class X(Exception) 自定义异常类)
|
||
define EXCEPTION_MAX = 64
|
||
# 异常类表槽内类名/父类名长度(含 NUL)
|
||
define EXCEPTION_NAME_LEN = 128
|
||
# 内置异常编码(对齐 TPC HandlesBase.py EXCEPTION_CODE_MAP);
|
||
# KeyError=6 IOError=7 OSError=8 AssertionError=9 Exception=99;用户类从 100 起
|
||
define BUILTIN_EH_VALUE_ERROR = 1
|
||
define BUILTIN_EH_RUNTIME_ERROR = 3
|
||
define BUILTIN_EH_EXCEPTION = 99
|
||
define EH_USER_CODE_START = 100
|
||
# 方法元数据表容量(原 HandlesClassDef.META_MAX/META_KEY_LEN,阶段 D 拆分遗漏)
|
||
define META_MAX = 512
|
||
define META_KEY_LEN = 128
|
||
|
||
|
||
# ============================================================
|
||
# ClassGenBase - ClassGenMixin 拆分(阶段 D):字段 + 方法元数据/异常/继承检测/装饰器(Meta)
|
||
# ============================================================
|
||
novirtual class ClassGenBase:
|
||
"""字段 + 方法元数据/异常/继承检测/装饰器(Meta)"""
|
||
|
||
# --- 方法元数据表(原 _g_method_meta_keys/_g_method_meta_flags/_g_method_meta_count) ---
|
||
Gen: Generator.Generator*
|
||
MethodMetaKeys: bytes
|
||
MethodMetaFlags: bytes
|
||
MethodMetaCount: int
|
||
|
||
# --- REnum 变体表(原 _renum_class_names/_renum_class_variant_counts/
|
||
# _renum_variant_names/_renum_variant_tags/_renum_class_count) ---
|
||
RenumClassNames: sizet*
|
||
RenumClassVariantCounts: sizet*
|
||
RenumVariantNames: sizet*
|
||
RenumVariantTags: sizet*
|
||
RenumClassCount: int
|
||
|
||
# --- REnum 字段别名表(原 _renum_alias_class/_renum_alias_field/
|
||
# _renum_alias_index/_renum_alias_count) ---
|
||
RenumAliasClass: sizet*
|
||
RenumAliasField: sizet*
|
||
RenumAliasIndex: sizet*
|
||
# 变体成员实际 LLVM 类型(对齐 TPC class_members):注册时按注解解析,
|
||
# perm_pool 深拷贝持久化。match 绑定用真实成员类型 bitcast 槽位地址
|
||
# (Struct.Name: i8*,否则按槽位 i64 读 → is/subscript/strlen 失败)。
|
||
RenumAliasTy: sizet*
|
||
# 别名所属变体名(perm_pool 拷贝):同一 payload 位置跨变体类型不同
|
||
# (Int.Bits=i32 vs Struct.Fields=Ptr),match 绑定按 (class, 变体, 位置)
|
||
# 唯一定位成员类型。
|
||
RenumAliasVariant: sizet*
|
||
RenumAliasCount: int
|
||
|
||
# --- 泛型特化缓存(原 _spec_keys/_spec_names/_spec_count) ---
|
||
SpecKeys: sizet*
|
||
SpecNames: sizet*
|
||
SpecCount: int
|
||
|
||
# --- 类编译期元数据表(__provides__/__requires__/__require_must__) ---
|
||
# perm_pool 分配(跨 mark/reset 存活):每槽 kind(4B) + cls(64B) + field(64B)
|
||
# FakeDuck:_str.__requires__=['__mbuddy__'] 等(FakeDuck 移植点 1)
|
||
ClassMetaKinds: int | t.CPtr
|
||
ClassMetaClss: bytes
|
||
ClassMetaFields: bytes
|
||
ClassMetaCount: int
|
||
|
||
# --- 自定义装饰器 wrapper 表(@log/@skip/@repeat 等 → __decor_wrap_{name}) ---
|
||
# perm_pool 分配(跨 mark/reset 存活):每槽函数名(128B) + wrapper 名(128B)
|
||
# 对齐 TPC HandlesFunctions.py L1621-1631 的 _decorated_funcs +
|
||
# DecoratorPass.py 的 wrapper 生成。调用点重写经
|
||
# lookup_decor_wrapper(translate_call 拦截原函数名 → wrapper 名)。
|
||
DecoratorFuncCount: int
|
||
DecoratorFuncNames: bytes
|
||
DecoratorWrapNames: bytes
|
||
# 装饰器首个常量参数(@repeat(3) 的 3),无参数为 0(每槽 8B,i64)
|
||
DecoratorArgs: int64*
|
||
|
||
# --- 异常类注册表(try-except,对齐 TPC HandlesClassDef.py L47-61) ---
|
||
# perm_pool 分配(跨 mark/reset 存活):每槽类名(128B) + 父类名(128B) + 编码(4B)
|
||
# 用户异常类编码从 100 递增;内置编码(ValueError=1 等)不在此表
|
||
# (_lookup_exception_code 走内置硬编码)。异常类不生成 struct。
|
||
ExceptionCount: int
|
||
ExceptionNames: bytes
|
||
ExceptionParents: bytes
|
||
ExceptionCodes: int*
|
||
# 下一个待分配的异常编码(用户类,从 100 起)
|
||
NextExceptionCode: int
|
||
# 递归收集子孙编码用的临时计数(collect_descendant_codes 返回后无效)。
|
||
# 必须与其它字段一起声明在类顶:方法中间的字段注解可能被编译器
|
||
# 当作局部声明处理,破坏 Mixin 布局/this_adjust 对齐。
|
||
_exception_codes_tmp_count: int
|
||
|
||
# --- 泛型特化递归深度(泛型循环套用防护) ---
|
||
# _specialize_generic_class 进入时 +1、退出时 -1;超过上限立即报错终止
|
||
# (防止 F-bounded 等循环特化把编译变成死循环)
|
||
GenericSpecDepth: int
|
||
|
||
# --- 泛型模板表(原 HandlesClassDef._generic_class_names/
|
||
# _generic_class_nodes/_generic_class_sha1s) ---
|
||
GenericClassNames: list[str]*
|
||
GenericClassNodes: list[ast.ClassDef*]*
|
||
GenericClassSha1s: list[str]*
|
||
# 泛型模板来源文件路径(与上面三表同序)。特化翻译模板方法体时 node.lineno 是模板
|
||
# 文件行号,若 CurrentFile 仍是调用方文件,fatal_error 会把模板行号套到调用方文件上
|
||
# 显示错位。此表用于特化期间临时切换 CurrentFile 到模板文件,翻译完恢复。
|
||
GenericClassFiles: list[str]*
|
||
# 泛型模板类型参数名表(与 GenericClassNames 同序,stdlib 深拷贝)。
|
||
# 模板节点 type_params 是 Phase 1 pool 分配的 list,跨 Phase 引用时内容
|
||
# 可能失效(VectorGenericTest 特化 Vector[int].__init__ 的 T.__sizeof__()
|
||
# NameError 根因方向);注册时展平深拷贝到 stdlib,特化时从本表恢复。
|
||
# 每槽指向一个空格分隔、NUL 结尾的 stdlib 缓冲区(如 "T" 或 "T K")。
|
||
GenericClassTpParams: sizet*
|
||
|
||
# --- vtable 方法收集表(原 _g_vt_full_names/_g_vt_method_names/
|
||
# _g_vt_parent_sha1s/_g_vt_method_count) ---
|
||
VtFullNames: sizet*
|
||
VtMethodNames: sizet*
|
||
VtParentSha1s: sizet*
|
||
VtMethodCount: int
|
||
# ============================================================
|
||
# 以下方法由 P5-2 分簇迁移填充(函数体来自 HandlesClassDef.vp,
|
||
# 本模块函数调用改 self.,外部模块调用保留模块前缀)
|
||
# ============================================================
|
||
|
||
def _is_cenum_base(self, base_node: ast.AST*,
|
||
trans: HT.Translator* = None) -> int:
|
||
"""检查 base 节点是否为 t.CEnum,返回 1=是 / 0=否"""
|
||
if base_node is None:
|
||
return 0
|
||
k: int = base_node.kind()
|
||
# Name('CEnum') 形式(from t import CEnum)
|
||
if k == ast.ASTKind.Name:
|
||
nm: ast.Name* = ast.Name*(base_node)
|
||
if nm.id is None:
|
||
return 0
|
||
if string.strcmp(nm.id, "CEnum") == 0:
|
||
return 1
|
||
# 别名形式: from t import CEnum as en; class Color(en)
|
||
# 解析别名原始名(en → CEnum)再比较
|
||
if trans is not None and trans._from_imports is not None:
|
||
alias_orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, nm.id)
|
||
if alias_orig is not None:
|
||
og_len_ce: sizet = 0
|
||
while alias_orig[og_len_ce] != ' ' and alias_orig[og_len_ce] != '\0':
|
||
og_len_ce += 1
|
||
if og_len_ce == 5 and string.strncmp(alias_orig, "CEnum", 5) == 0:
|
||
return 1
|
||
return 0
|
||
# Attribute(t.CEnum) 形式
|
||
if k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute* = ast.Attribute*(base_node)
|
||
if at.attr is not None and string.strcmp(at.attr, "CEnum") == 0:
|
||
return 1
|
||
return 0
|
||
return 0
|
||
def _is_enum_class(self, cd: ast.ClassDef*,
|
||
trans: HT.Translator* = None) -> int:
|
||
"""检查 ClassDef 是否为 CEnum:继承自 t.CEnum 或 @t.CEnum 装饰器形式"""
|
||
if cd is None:
|
||
return 0
|
||
# 装饰器形式: @t.CEnum class Color:(无基类,等价 class Color(t.CEnum):)
|
||
if cd.decorator_list is not None:
|
||
if self._has_decorator(cd.decorator_list, "CEnum") == 1:
|
||
return 1
|
||
if cd.bases is None:
|
||
return 0
|
||
bases: list[ast.AST*]* = cd.bases
|
||
bn: sizet = len(bases)
|
||
if bn == 0:
|
||
return 0
|
||
for bi in range(bn):
|
||
base_node: ast.AST* = bases.get(bi)
|
||
if base_node is None:
|
||
continue
|
||
if self._is_cenum_base(base_node, trans) == 1:
|
||
return 1
|
||
return 0
|
||
def _is_cunion_base(self, base_node: ast.AST*,
|
||
trans: HT.Translator* = None) -> int:
|
||
"""检查 base 节点是否为 t.CUnion,返回 1=是 / 0=否"""
|
||
if base_node is None:
|
||
return 0
|
||
k: int = base_node.kind()
|
||
# Name('CUnion') 形式(from t import CUnion)
|
||
if k == ast.ASTKind.Name:
|
||
nm: ast.Name* = ast.Name*(base_node)
|
||
if nm.id is None:
|
||
return 0
|
||
if string.strcmp(nm.id, "CUnion") == 0:
|
||
return 1
|
||
# 别名形式: from t import CUnion as un; class Data(un)
|
||
if trans is not None and trans._from_imports is not None:
|
||
alias_orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, nm.id)
|
||
if alias_orig is not None:
|
||
og_len_cu: sizet = 0
|
||
while alias_orig[og_len_cu] != ' ' and alias_orig[og_len_cu] != '\0':
|
||
og_len_cu += 1
|
||
if og_len_cu == 6 and string.strncmp(alias_orig, "CUnion", 6) == 0:
|
||
return 1
|
||
return 0
|
||
# Attribute(t.CUnion) 形式
|
||
if k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute* = ast.Attribute*(base_node)
|
||
if at.attr is not None and string.strcmp(at.attr, "CUnion") == 0:
|
||
return 1
|
||
return 0
|
||
return 0
|
||
def _is_union_class(self, cd: ast.ClassDef*,
|
||
trans: HT.Translator* = None) -> int:
|
||
"""检查 ClassDef 是否为 CUnion:继承自 t.CUnion 或 @t.CUnion 装饰器形式"""
|
||
if cd is None:
|
||
return 0
|
||
# 装饰器形式: @t.CUnion class Data:
|
||
if cd.decorator_list is not None:
|
||
if self._has_decorator(cd.decorator_list, "CUnion") == 1:
|
||
return 1
|
||
if cd.bases is None:
|
||
return 0
|
||
bases: list[ast.AST*]* = cd.bases
|
||
bn: sizet = len(bases)
|
||
if bn == 0:
|
||
return 0
|
||
for bi in range(bn):
|
||
base_node: ast.AST* = bases.get(bi)
|
||
if base_node is None:
|
||
continue
|
||
if self._is_cunion_base(base_node, trans) == 1:
|
||
return 1
|
||
return 0
|
||
def _is_crenum_base(self, base_node: ast.AST*,
|
||
trans: HT.Translator* = None) -> int:
|
||
"""检查 base 节点是否为 t.REnum,返回 1=是 / 0=否"""
|
||
if base_node is None:
|
||
return 0
|
||
k: int = base_node.kind()
|
||
# Name('REnum') 形式(from t import REnum)
|
||
if k == ast.ASTKind.Name:
|
||
nm: ast.Name* = ast.Name*(base_node)
|
||
if nm.id is None:
|
||
return 0
|
||
if string.strcmp(nm.id, "REnum") == 0:
|
||
return 1
|
||
# 别名形式: from t import REnum as ren; class Opt(ren)
|
||
if trans is not None and trans._from_imports is not None:
|
||
alias_orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, nm.id)
|
||
if alias_orig is not None:
|
||
og_len_cr: sizet = 0
|
||
while alias_orig[og_len_cr] != ' ' and alias_orig[og_len_cr] != '\0':
|
||
og_len_cr += 1
|
||
if og_len_cr == 5 and string.strncmp(alias_orig, "REnum", 5) == 0:
|
||
return 1
|
||
return 0
|
||
# Attribute(t.REnum) 形式
|
||
if k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute* = ast.Attribute*(base_node)
|
||
if at.attr is not None and string.strcmp(at.attr, "REnum") == 0:
|
||
return 1
|
||
return 0
|
||
return 0
|
||
def _is_renum_class(self, cd: ast.ClassDef*,
|
||
trans: HT.Translator* = None) -> int:
|
||
"""检查 ClassDef 是否为 REnum:继承自 t.REnum 或 @t.REnum 装饰器形式"""
|
||
if cd is None:
|
||
return 0
|
||
# 装饰器形式: @t.REnum class X:
|
||
if cd.decorator_list is not None:
|
||
if self._has_decorator(cd.decorator_list, "REnum") == 1:
|
||
return 1
|
||
if cd.bases is None:
|
||
return 0
|
||
bases: list[ast.AST*]* = cd.bases
|
||
bn: sizet = len(bases)
|
||
if bn == 0:
|
||
return 0
|
||
for bi in range(bn):
|
||
base_node: ast.AST* = bases.get(bi)
|
||
if base_node is None:
|
||
continue
|
||
if self._is_crenum_base(base_node, trans) == 1:
|
||
return 1
|
||
return 0
|
||
def _has_decorator(self, decorator_list: list[ast.AST*]*,
|
||
deco_name: str) -> int:
|
||
"""检查 decorator_list 中是否有指定装饰器名"""
|
||
if decorator_list is None:
|
||
return 0
|
||
dn: sizet = len(decorator_list)
|
||
if dn == 0:
|
||
return 0
|
||
for di in range(dn):
|
||
deco: ast.AST* = decorator_list.get(di)
|
||
if deco is None:
|
||
continue
|
||
k: int = deco.kind()
|
||
# @t.NoVTable 形式(Attribute)
|
||
if k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute* = ast.Attribute*(deco)
|
||
if at.attr is not None and string.strcmp(at.attr, deco_name) == 0:
|
||
# 检查 value 是 Name('t')
|
||
if at.value is not None and at.value.kind() == ast.ASTKind.Name:
|
||
vn: ast.Name* = ast.Name*(at.value)
|
||
if vn.id is not None and string.strcmp(vn.id, "t") == 0:
|
||
return 1
|
||
return 0
|
||
# @NoVTable 形式(Name,from t import NoVTable)
|
||
if k == ast.ASTKind.Name:
|
||
nm: ast.Name* = ast.Name*(deco)
|
||
if nm.id is not None and string.strcmp(nm.id, deco_name) == 0:
|
||
return 1
|
||
return 0
|
||
def _tattr_name(self, node: ast.AST*, attr_name: str) -> int:
|
||
"""从 t.attr.<name> / t.attr.<name>(args) 节点提取最外层属性名并比较。
|
||
|
||
Call(t.attr.aligned(16))→ 递归取 func;Attribute(t.attr.packed)→ 取 attr。
|
||
"""
|
||
if node is None:
|
||
return 0
|
||
if node.kind() == ast.ASTKind.Call:
|
||
cl2: ast.Call* = ast.Call*(node)
|
||
if cl2.func is None:
|
||
return 0
|
||
return self._tattr_name(cl2.func, attr_name)
|
||
if node.kind() == ast.ASTKind.Attribute:
|
||
at2: ast.Attribute* = ast.Attribute*(node)
|
||
if at2.attr is None:
|
||
return 0
|
||
return 1 if string.strcmp(at2.attr, attr_name) == 0 else 0
|
||
return 0
|
||
def _class_has_tattr(self, decorator_list: list[ast.AST*]*,
|
||
attr_name: str) -> int:
|
||
"""检查装饰器列表是否含 t.attr.<attr_name>(@c.Attribute(t.attr.xxx) 或 @t.attr.xxx)。
|
||
|
||
覆盖 packed/aligned/naked/section 等所有 t.attr 属性(B5)。
|
||
"""
|
||
if decorator_list is None:
|
||
return 0
|
||
dn: sizet = len(decorator_list)
|
||
if dn == 0:
|
||
return 0
|
||
for di in range(dn):
|
||
deco: ast.AST* = decorator_list.get(di)
|
||
if deco is None:
|
||
continue
|
||
k: int = deco.kind()
|
||
if k == ast.ASTKind.Call:
|
||
cl: ast.Call* = ast.Call*(deco)
|
||
# @c.Attribute(t.attr.xxx) 形式:func 是 Attribute(c, "Attribute")
|
||
if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute:
|
||
continue
|
||
at0: ast.Attribute* = ast.Attribute*(cl.func)
|
||
if at0.attr is None or string.strcmp(at0.attr, "Attribute") != 0:
|
||
continue
|
||
if cl.args is None:
|
||
continue
|
||
an: sizet = len(cl.args)
|
||
for ai in range(an):
|
||
ag: ast.AST* = cl.args.get(ai)
|
||
if ag is not None and self._tattr_name(ag, attr_name) != 0:
|
||
return 1
|
||
else:
|
||
# @t.attr.xxx 直接形式
|
||
if self._tattr_name(deco, attr_name) != 0:
|
||
return 1
|
||
return 0
|
||
def _tattr_aligned_int(self, node: ast.AST*) -> int:
|
||
"""t.attr.aligned(N) → N(整数参数),非 aligned 或无参返回 0"""
|
||
if node is None:
|
||
return 0
|
||
if node.kind() == ast.ASTKind.Call:
|
||
cl2: ast.Call* = ast.Call*(node)
|
||
if cl2.func is None or cl2.func.kind() != ast.ASTKind.Attribute:
|
||
return 0
|
||
at2: ast.Attribute* = ast.Attribute*(cl2.func)
|
||
if at2.attr is None or string.strcmp(at2.attr, "aligned") != 0:
|
||
return 0
|
||
if cl2.args is None or len(cl2.args) == 0:
|
||
return 0
|
||
a0: ast.AST* = cl2.args.get(0)
|
||
if a0 is None or a0.kind() != ast.ASTKind.Constant:
|
||
return 0
|
||
cn: ast.Constant* = ast.Constant*(a0)
|
||
if cn.const_kind != ast.CONST_INT:
|
||
return 0
|
||
return int(cn.int_val)
|
||
return 0
|
||
def _class_aligned_value(self, decorator_list: list[ast.AST*]*) -> int:
|
||
"""取 @c.Attribute(t.attr.aligned(N)) 的对齐字节数,无 aligned 返回 0"""
|
||
if decorator_list is None:
|
||
return 0
|
||
dn: sizet = len(decorator_list)
|
||
if dn == 0:
|
||
return 0
|
||
for di in range(dn):
|
||
deco: ast.AST* = decorator_list.get(di)
|
||
if deco is None:
|
||
continue
|
||
if deco.kind() == ast.ASTKind.Call:
|
||
cl: ast.Call* = ast.Call*(deco)
|
||
if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute:
|
||
continue
|
||
at0: ast.Attribute* = ast.Attribute*(cl.func)
|
||
if at0.attr is None or string.strcmp(at0.attr, "Attribute") != 0:
|
||
continue
|
||
if cl.args is None:
|
||
continue
|
||
an: sizet = len(cl.args)
|
||
for ai in range(an):
|
||
ag: ast.AST* = cl.args.get(ai)
|
||
if ag is not None:
|
||
av: int = self._tattr_aligned_int(ag)
|
||
if av > 0:
|
||
return av
|
||
else:
|
||
av2: int = self._tattr_aligned_int(deco)
|
||
if av2 > 0:
|
||
return av2
|
||
return 0
|
||
def _extract_func_meta(self, decorator_list: list[ast.AST*]*) -> int:
|
||
"""从装饰器列表提取元数据位掩码,返回 0=无装饰器元数据"""
|
||
meta: int = 0
|
||
if decorator_list is None:
|
||
return meta
|
||
dn: sizet = len(decorator_list)
|
||
if dn == 0:
|
||
return meta
|
||
for di in range(dn):
|
||
deco: ast.AST* = decorator_list.get(di)
|
||
if deco is None:
|
||
continue
|
||
k: int = deco.kind()
|
||
if k == ast.ASTKind.Name:
|
||
nm: ast.Name* = ast.Name*(deco)
|
||
if nm.id is not None:
|
||
if string.strcmp(nm.id, "staticmethod") == 0:
|
||
meta |= GenTypes.META_STATIC
|
||
elif string.strcmp(nm.id, "property") == 0:
|
||
meta |= GenTypes.META_PROP_GETTER
|
||
elif string.strcmp(nm.id, "classmethod") == 0:
|
||
meta |= GenTypes.META_CLASS
|
||
elif string.strcmp(nm.id, "TLS") == 0:
|
||
meta |= META_TLS
|
||
elif k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute* = ast.Attribute*(deco)
|
||
if at.attr is not None and at.value is not None:
|
||
if at.value.kind() == ast.ASTKind.Name:
|
||
vn: ast.Name* = ast.Name*(at.value)
|
||
is_prop_name: int = 0
|
||
if vn.id is not None and string.strcmp(vn.id, "property") == 0:
|
||
is_prop_name = 1
|
||
# @t.TLS 一次性初始化标记(对齐 TPC HandlesFunctions.py
|
||
# L1223-1231:value 必须为 Name('t');@TLS 裸名走上面 Name 分支)
|
||
if vn.id is not None and string.strcmp(vn.id, "t") == 0 \
|
||
and string.strcmp(at.attr, "TLS") == 0:
|
||
meta |= META_TLS
|
||
# @property.setter 或 @x.setter/getter/deleter 都识别
|
||
if is_prop_name != 0 or string.strcmp(at.attr, "setter") == 0 \
|
||
or string.strcmp(at.attr, "getter") == 0 or string.strcmp(at.attr, "deleter") == 0:
|
||
if string.strcmp(at.attr, "setter") == 0:
|
||
meta |= GenTypes.META_PROP_SETTER
|
||
elif string.strcmp(at.attr, "getter") == 0:
|
||
meta |= GenTypes.META_PROP_GETTER
|
||
elif string.strcmp(at.attr, "deleter") == 0:
|
||
meta |= GenTypes.META_PROP_DELETER
|
||
return meta
|
||
def register_class_meta(self, pool: memhub.MemBuddy*,
|
||
kind: int, cls: str, field: str) -> int:
|
||
"""注册类编译期元数据字段(__provides__/__requires__/__require_must__,幂等)"""
|
||
if pool is None or cls is None or field is None:
|
||
return -1
|
||
if self.ClassMetaKinds is None:
|
||
self.ClassMetaKinds = CompilerFactory.factory.PermPool.alloc(CLASS_META_MAX * 4)
|
||
self.ClassMetaClss = CompilerFactory.factory.PermPool.alloc(CLASS_META_MAX * 64)
|
||
self.ClassMetaFields = CompilerFactory.factory.PermPool.alloc(CLASS_META_MAX * 64)
|
||
if self.ClassMetaKinds is None or self.ClassMetaClss is None or self.ClassMetaFields is None:
|
||
return -1
|
||
string.memset(self.ClassMetaKinds, 0, CLASS_META_MAX * 4)
|
||
string.memset(self.ClassMetaClss, 0, CLASS_META_MAX * 64)
|
||
string.memset(self.ClassMetaFields, 0, CLASS_META_MAX * 64)
|
||
self.ClassMetaCount = 0
|
||
if self.ClassMetaCount >= CLASS_META_MAX:
|
||
return -1
|
||
# 幂等:同 (kind, cls, field) 跳过
|
||
for i in range(self.ClassMetaCount):
|
||
if self.ClassMetaKinds[i] == kind:
|
||
if string.strcmp(self.ClassMetaClss + i * 64, cls) == 0:
|
||
if string.strcmp(self.ClassMetaFields + i * 64, field) == 0:
|
||
return 0
|
||
idx_cm: sizet = sizet(self.ClassMetaCount) * 64
|
||
self.ClassMetaKinds[self.ClassMetaCount] = kind
|
||
string.strncpy(self.ClassMetaClss + idx_cm, cls, 63)
|
||
self.ClassMetaClss[idx_cm + 63] = '\0'
|
||
string.strncpy(self.ClassMetaFields + idx_cm, field, 63)
|
||
self.ClassMetaFields[idx_cm + 63] = '\0'
|
||
self.ClassMetaCount += 1
|
||
return 0
|
||
def class_meta_count(self, kind: int, cls: str) -> int:
|
||
"""返回某类某元数据类型的字段数"""
|
||
if self.ClassMetaKinds is None or cls is None:
|
||
return 0
|
||
n_cm: int = 0
|
||
for i in range(self.ClassMetaCount):
|
||
if self.ClassMetaKinds[i] == kind:
|
||
if string.strcmp(self.ClassMetaClss + i * 64, cls) == 0:
|
||
n_cm += 1
|
||
return n_cm
|
||
def class_meta_field_at(self, kind: int, cls: str, idx: int) -> str:
|
||
"""返回某类某元数据类型的第 idx 个字段名"""
|
||
if self.ClassMetaKinds is None or cls is None:
|
||
return None
|
||
n_cm2: int = 0
|
||
for i in range(self.ClassMetaCount):
|
||
if self.ClassMetaKinds[i] == kind:
|
||
if string.strcmp(self.ClassMetaClss + i * 64, cls) == 0:
|
||
if n_cm2 == idx:
|
||
return self.ClassMetaFields + i * 64
|
||
n_cm2 += 1
|
||
return None
|
||
def register_decorator(self, pool: memhub.MemBuddy*,
|
||
func_name: str, wrapper_name: str,
|
||
arg0: int64) -> int:
|
||
"""注册自定义装饰器函数(@log/@skip/@repeat(3) → __decor_wrap_{name})
|
||
|
||
对齐 TPC HandlesFunctions.py L1621-1631 的 _decorated_funcs 注册。
|
||
arg0 为装饰器首个常量参数(@repeat(3) 的 3),无参数为 0。
|
||
"""
|
||
if pool is None or func_name is None or wrapper_name is None:
|
||
return -1
|
||
if self.DecoratorFuncNames is None:
|
||
self.DecoratorFuncNames = CompilerFactory.factory.PermPool.alloc(DECOR_FUNC_MAX * DECOR_NAME_LEN)
|
||
self.DecoratorWrapNames = CompilerFactory.factory.PermPool.alloc(DECOR_FUNC_MAX * DECOR_NAME_LEN)
|
||
self.DecoratorArgs = CompilerFactory.factory.PermPool.alloc(DECOR_FUNC_MAX * 8)
|
||
if self.DecoratorFuncNames is None or self.DecoratorWrapNames is None or self.DecoratorArgs is None:
|
||
return -1
|
||
string.memset(self.DecoratorFuncNames, 0, DECOR_FUNC_MAX * DECOR_NAME_LEN)
|
||
string.memset(self.DecoratorWrapNames, 0, DECOR_FUNC_MAX * DECOR_NAME_LEN)
|
||
string.memset(self.DecoratorArgs, 0, DECOR_FUNC_MAX * 8)
|
||
self.DecoratorFuncCount = 0
|
||
if self.DecoratorFuncCount >= DECOR_FUNC_MAX:
|
||
return -1
|
||
# 幂等:同名函数已注册则跳过(多遍扫描)
|
||
for i in range(self.DecoratorFuncCount):
|
||
if string.strcmp(self.DecoratorFuncNames + i * DECOR_NAME_LEN, func_name) == 0:
|
||
return 0
|
||
idx_dc: sizet = sizet(self.DecoratorFuncCount) * DECOR_NAME_LEN
|
||
string.strncpy(self.DecoratorFuncNames + idx_dc, func_name, DECOR_NAME_LEN - 1)
|
||
self.DecoratorFuncNames[idx_dc + DECOR_NAME_LEN - 1] = '\0'
|
||
string.strncpy(self.DecoratorWrapNames + idx_dc, wrapper_name, DECOR_NAME_LEN - 1)
|
||
self.DecoratorWrapNames[idx_dc + DECOR_NAME_LEN - 1] = '\0'
|
||
self.DecoratorArgs[self.DecoratorFuncCount] = arg0
|
||
self.DecoratorFuncCount += 1
|
||
return 0
|
||
def lookup_decor_wrapper(self, func_name: str) -> str:
|
||
"""按原函数名查 wrapper 名,未注册返回 None"""
|
||
if self.DecoratorFuncNames is None or func_name is None:
|
||
return None
|
||
for i in range(self.DecoratorFuncCount):
|
||
if string.strcmp(self.DecoratorFuncNames + i * DECOR_NAME_LEN, func_name) == 0:
|
||
return self.DecoratorWrapNames + i * DECOR_NAME_LEN
|
||
return None
|
||
def lookup_decor_arg0(self, func_name: str) -> int64:
|
||
"""按原函数名查装饰器首个常量参数(无参数为 0)"""
|
||
if self.DecoratorFuncNames is None or func_name is None:
|
||
return 0
|
||
for i in range(self.DecoratorFuncCount):
|
||
if string.strcmp(self.DecoratorFuncNames + i * DECOR_NAME_LEN, func_name) == 0:
|
||
return self.DecoratorArgs[i]
|
||
return 0
|
||
# ============================================================
|
||
# 异常类注册表(try-except,对齐 TPC HandlesClassDef.py L47-61)
|
||
# ============================================================
|
||
def _ensure_exception_tables(self) -> int:
|
||
"""懒初始化异常表(perm_pool),返回 0 成功"""
|
||
if self.ExceptionNames is not None:
|
||
return 0
|
||
pp_e: memhub.MemBuddy* = CompilerFactory.factory.PermPool
|
||
if pp_e is None:
|
||
return -1
|
||
self.ExceptionNames = pp_e.alloc(EXCEPTION_MAX * EXCEPTION_NAME_LEN)
|
||
self.ExceptionParents = pp_e.alloc(EXCEPTION_MAX * EXCEPTION_NAME_LEN)
|
||
self.ExceptionCodes = pp_e.alloc(EXCEPTION_MAX * 4)
|
||
if self.ExceptionNames is None or self.ExceptionParents is None \
|
||
or self.ExceptionCodes is None:
|
||
return -1
|
||
string.memset(self.ExceptionNames, 0, EXCEPTION_MAX * EXCEPTION_NAME_LEN)
|
||
string.memset(self.ExceptionParents, 0, EXCEPTION_MAX * EXCEPTION_NAME_LEN)
|
||
string.memset(self.ExceptionCodes, 0, EXCEPTION_MAX * 4)
|
||
self.ExceptionCount = 0
|
||
self.NextExceptionCode = EH_USER_CODE_START
|
||
return 0
|
||
def register_exception(self, class_name: str, parent_name: str) -> int:
|
||
"""注册用户异常类并分配编码(幂等:同名跳过)。返回编码或 -1"""
|
||
if class_name is None:
|
||
return -1
|
||
if self._ensure_exception_tables() != 0:
|
||
return -1
|
||
# 幂等:已注册则返回既有编码(多遍扫描)
|
||
for i in range(self.ExceptionCount):
|
||
if string.strcmp(self.ExceptionNames + i * EXCEPTION_NAME_LEN, class_name) == 0:
|
||
return self.ExceptionCodes[i]
|
||
if self.ExceptionCount >= EXCEPTION_MAX:
|
||
return -1
|
||
idx_e: sizet = sizet(self.ExceptionCount) * EXCEPTION_NAME_LEN
|
||
string.strncpy(self.ExceptionNames + idx_e, class_name, EXCEPTION_NAME_LEN - 1)
|
||
self.ExceptionNames[idx_e + EXCEPTION_NAME_LEN - 1] = '\0'
|
||
if parent_name is not None:
|
||
string.strncpy(self.ExceptionParents + idx_e, parent_name, EXCEPTION_NAME_LEN - 1)
|
||
self.ExceptionParents[idx_e + EXCEPTION_NAME_LEN - 1] = '\0'
|
||
code_e: int = self.NextExceptionCode
|
||
self.NextExceptionCode += 1
|
||
self.ExceptionCodes[self.ExceptionCount] = code_e
|
||
self.ExceptionCount += 1
|
||
return code_e
|
||
def _builtin_exception_code(self, name: str) -> int:
|
||
"""内置异常编码(对齐 TPC HandlesBase.py EXCEPTION_CODE_MAP),非内置返回 0"""
|
||
if name is None:
|
||
return 0
|
||
if string.strcmp(name, "ValueError") == 0: return 1
|
||
if string.strcmp(name, "TypeError") == 0: return 2
|
||
if string.strcmp(name, "RuntimeError") == 0: return 3
|
||
if string.strcmp(name, "ZeroDivisionError") == 0: return 4
|
||
if string.strcmp(name, "IndexError") == 0: return 5
|
||
if string.strcmp(name, "KeyError") == 0: return 6
|
||
if string.strcmp(name, "IOError") == 0: return 7
|
||
if string.strcmp(name, "OSError") == 0: return 8
|
||
if string.strcmp(name, "AssertionError") == 0: return 9
|
||
if string.strcmp(name, "Exception") == 0: return 99
|
||
return 0
|
||
def lookup_exception_code(self, name: str) -> int:
|
||
"""查异常编码:内置表优先,其次用户异常表,都未命中返回 0"""
|
||
if name is None:
|
||
return 0
|
||
bi: int = self._builtin_exception_code(name)
|
||
if bi != 0:
|
||
return bi
|
||
if self.ExceptionNames is None:
|
||
return 0
|
||
for i in range(self.ExceptionCount):
|
||
if string.strcmp(self.ExceptionNames + i * EXCEPTION_NAME_LEN, name) == 0:
|
||
return self.ExceptionCodes[i]
|
||
return 0
|
||
def lookup_exception_parent(self, name: str) -> str:
|
||
"""查用户异常类的父类名,非用户异常返回 None"""
|
||
if name is None or self.ExceptionNames is None:
|
||
return None
|
||
for i in range(self.ExceptionCount):
|
||
if string.strcmp(self.ExceptionNames + i * EXCEPTION_NAME_LEN, name) == 0:
|
||
p_e: str = self.ExceptionParents + i * EXCEPTION_NAME_LEN
|
||
if p_e is not None and p_e[0] != '\0':
|
||
return p_e
|
||
return None
|
||
return None
|
||
def is_exception_name(self, name: str) -> int:
|
||
"""name 是否是内置或用户异常类名(1=是 / 0=否)"""
|
||
if name is None:
|
||
return 0
|
||
if self._builtin_exception_code(name) != 0:
|
||
return 1
|
||
if self.ExceptionNames is None:
|
||
return 0
|
||
for i in range(self.ExceptionCount):
|
||
if string.strcmp(self.ExceptionNames + i * EXCEPTION_NAME_LEN, name) == 0:
|
||
return 1
|
||
return 0
|
||
def collect_descendant_codes(self, name: str, out_codes: int | t.CPtr,
|
||
max_codes: int) -> int:
|
||
"""把 name 及其所有子孙异常类的编码收集到 out_codes,返回数量
|
||
(对齐 TPC HandlesTry.py _get_all_match_codes/_collect_descendant_codes:
|
||
编译期静态展开继承树,except X 匹配 X 及全部子孙)。"""
|
||
if name is None or out_codes is None:
|
||
return 0
|
||
self._exception_codes_tmp_count = 0
|
||
self._collect_desc_codes_rec(name, out_codes, max_codes, 0)
|
||
return self._exception_codes_tmp_count
|
||
def _collect_desc_codes_rec(self, name: str, out_codes: int | t.CPtr,
|
||
max_codes: int, depth: int) -> None:
|
||
"""递归收集 name 编码 + 全部子孙编码(BFS 语义对齐 TPC)"""
|
||
if depth > 32:
|
||
return
|
||
code_e: int = self.lookup_exception_code(name)
|
||
if code_e != 0 and self._exception_codes_tmp_count < max_codes:
|
||
# 去重(继承环防护)
|
||
dup: int = 0
|
||
for i in range(self._exception_codes_tmp_count):
|
||
if out_codes[i] == code_e:
|
||
dup = 1
|
||
break
|
||
if dup == 0:
|
||
out_codes[self._exception_codes_tmp_count] = code_e
|
||
self._exception_codes_tmp_count += 1
|
||
# 遍历全部用户异常,找以 name 为父类的子类递归收集
|
||
if self.ExceptionNames is None:
|
||
return
|
||
for i in range(self.ExceptionCount):
|
||
cname_e: str = self.ExceptionNames + i * EXCEPTION_NAME_LEN
|
||
pname_e: str = self.ExceptionParents + i * EXCEPTION_NAME_LEN
|
||
if pname_e is not None and pname_e[0] != '\0':
|
||
if string.strcmp(pname_e, name) == 0:
|
||
self._collect_desc_codes_rec(cname_e, out_codes, max_codes, depth + 1)
|
||
def _is_exception_class_def(self, cd: ast.ClassDef*) -> int:
|
||
"""类定义是否是异常类:基类是 Exception 或已注册异常类(1=是)"""
|
||
if cd is None or cd.bases is None:
|
||
return 0
|
||
bases_e: list[ast.AST*]* = cd.bases
|
||
bn_e: sizet = len(bases_e)
|
||
for bi_e in range(bn_e):
|
||
base_e: ast.AST* = bases_e.get(bi_e)
|
||
if base_e is None:
|
||
continue
|
||
base_name_e: str = None
|
||
if base_e.kind() == ast.ASTKind.Name:
|
||
base_name_e = (ast.Name*(base_e)).id
|
||
elif base_e.kind() == ast.ASTKind.Attribute:
|
||
base_at_e: ast.Attribute* = ast.Attribute*(base_e)
|
||
if base_at_e.attr is not None:
|
||
base_name_e = base_at_e.attr
|
||
if base_name_e is None:
|
||
continue
|
||
if string.strcmp(base_name_e, "Exception") == 0:
|
||
return 1
|
||
if self.is_exception_name(base_name_e) != 0:
|
||
return 1
|
||
return 0
|
||
def _get_exception_parent_name(self, cd: ast.ClassDef*) -> str:
|
||
"""返回异常类定义的真实父类名(第一个非 Exception 的已注册异常类),无则 None"""
|
||
if cd is None or cd.bases is None:
|
||
return None
|
||
bases_e2: list[ast.AST*]* = cd.bases
|
||
bn_e2: sizet = len(bases_e2)
|
||
for bi_e2 in range(bn_e2):
|
||
base_e2: ast.AST* = bases_e2.get(bi_e2)
|
||
if base_e2 is None:
|
||
continue
|
||
base_name_e2: str = None
|
||
if base_e2.kind() == ast.ASTKind.Name:
|
||
base_name_e2 = (ast.Name*(base_e2)).id
|
||
elif base_e2.kind() == ast.ASTKind.Attribute:
|
||
base_at_e2: ast.Attribute* = ast.Attribute*(base_e2)
|
||
if base_at_e2.attr is not None:
|
||
base_name_e2 = base_at_e2.attr
|
||
if base_name_e2 is None:
|
||
continue
|
||
if string.strcmp(base_name_e2, "Exception") != 0 \
|
||
and self.is_exception_name(base_name_e2) != 0:
|
||
return base_name_e2
|
||
return None
|
||
def _register_exception_class_def(self, trans: HT.Translator*,
|
||
cd: ast.ClassDef*) -> int:
|
||
"""注册异常类(分配编码 + 记录父类),不生成 struct,返回 0"""
|
||
if cd is None or cd.name is None:
|
||
return 0
|
||
parent_e: str = self._get_exception_parent_name(cd)
|
||
self.register_exception(cd.name, parent_e)
|
||
return 0
|
||
def _register_class_meta_list(self, pool: memhub.MemBuddy*,
|
||
kind: int, cls: str, value_node: ast.AST*) -> None:
|
||
"""解析类体 __provides__/__requires__ 的 list[str] 字面量并注册"""
|
||
if value_node is None or cls is None:
|
||
return
|
||
if value_node.kind() != ast.ASTKind.List:
|
||
return
|
||
lst_rcm: ast.List* = ast.List*(value_node)
|
||
if lst_rcm.elts is None:
|
||
return
|
||
elts_rcm: list[ast.AST*]* = lst_rcm.elts
|
||
en_rcm: sizet = len(elts_rcm)
|
||
for ei_rcm in range(en_rcm):
|
||
el_rcm: ast.AST* = elts_rcm.get(ei_rcm)
|
||
if el_rcm is None or el_rcm.kind() != ast.ASTKind.Constant:
|
||
continue
|
||
ec_rcm: ast.Constant* = ast.Constant*(el_rcm)
|
||
if ec_rcm.str_val is not None:
|
||
self.register_class_meta(pool, kind, cls, ec_rcm.str_val)
|
||
def register_method_meta(self, class_name: str, method_name: str,
|
||
meta: int) -> None:
|
||
"""注册方法元数据(幂等)"""
|
||
if class_name is None or method_name is None or meta == 0:
|
||
return
|
||
# 懒初始化
|
||
if self.MethodMetaKeys is None:
|
||
self.MethodMetaKeys = CompilerFactory.factory.PermPool.alloc(META_MAX * META_KEY_LEN)
|
||
self.MethodMetaFlags = CompilerFactory.factory.PermPool.alloc(META_MAX * 4)
|
||
if self.MethodMetaKeys is None or self.MethodMetaFlags is None:
|
||
return
|
||
string.memset(self.MethodMetaKeys, 0, META_MAX * META_KEY_LEN)
|
||
string.memset(self.MethodMetaFlags, 0, META_MAX * 4)
|
||
# 构造 key "ClassName.method"
|
||
cl_len: sizet = string.strlen(class_name)
|
||
mn_len: sizet = string.strlen(method_name)
|
||
key_buf: bytes = stdlib.malloc(cl_len + mn_len + 2)
|
||
if key_buf is None:
|
||
return
|
||
viperlib.snprintf(key_buf, cl_len + mn_len + 2, "%s.%s", class_name, method_name)
|
||
# 去重更新
|
||
i: int
|
||
for i in range(self.MethodMetaCount):
|
||
if string.strcmp(self.MethodMetaKeys + i * META_KEY_LEN, key_buf) == 0:
|
||
flags_ptr: t.CPtr = (int | t.CPtr)(uint64(self.MethodMetaFlags) + i * 4)
|
||
# 按位或合并:同一属性名先 @property(getter=4) 再 @x.setter(8)/
|
||
# @x.deleter(16) 会多次注册(如 Config.value / Counter.value)。
|
||
# 若整值替换,后注册的位会覆盖 GETTER 位 → _try_property_getter_attr
|
||
# 不再拦截 obj.prop → 落入字段查找失败返回 None → 上游 llvmlite
|
||
# 收到 NULL Value → 编译器进程段错误(BuiltinDecoratorTest Phase A 崩溃)。
|
||
flags_ptr[0] = flags_ptr[0] | meta
|
||
stdlib.free(key_buf)
|
||
return
|
||
if self.MethodMetaCount < META_MAX:
|
||
# 槽位定长 META_KEY_LEN=128 字节,key 超长时 strncpy 钳制防越界写相邻槽
|
||
string.strncpy(self.MethodMetaKeys + self.MethodMetaCount * META_KEY_LEN,
|
||
key_buf, META_KEY_LEN - 1)
|
||
flags_ptr2: t.CPtr = (int | t.CPtr)(uint64(self.MethodMetaFlags) + self.MethodMetaCount * 4)
|
||
flags_ptr2[0] = meta
|
||
self.MethodMetaCount += 1
|
||
stdlib.free(key_buf)
|
||
def lookup_method_meta(self, class_name: str, method_name: str) -> int:
|
||
"""查找方法元数据位掩码,返回 0=未注册或非装饰器方法"""
|
||
if class_name is None or method_name is None:
|
||
return 0
|
||
if self.MethodMetaKeys is None or self.MethodMetaCount <= 0:
|
||
return 0
|
||
cl_len: sizet = string.strlen(class_name)
|
||
mn_len: sizet = string.strlen(method_name)
|
||
key_buf: bytes = stdlib.malloc(cl_len + mn_len + 2)
|
||
if key_buf is None:
|
||
return 0
|
||
viperlib.snprintf(key_buf, cl_len + mn_len + 2, "%s.%s", class_name, method_name)
|
||
found: int = 0
|
||
i: int
|
||
for i in range(self.MethodMetaCount):
|
||
if string.strcmp(self.MethodMetaKeys + i * META_KEY_LEN, key_buf) == 0:
|
||
flags_ptr: t.CPtr = (int | t.CPtr)(uint64(self.MethodMetaFlags) + i * 4)
|
||
found = flags_ptr[0]
|
||
break
|
||
stdlib.free(key_buf)
|
||
return found
|
||
def _is_marker_base(self, base_name: str) -> int:
|
||
"""检查基类名是否为标记基类,返回 1=是 / 0=否
|
||
|
||
含 t.Struct:t.py 未定义 Struct 类(不被编译),`class X(t.Struct)`
|
||
的 Struct 只是"普通结构体"标记。若不当成标记基类,会被误判为真实父类:
|
||
- 自动启用虚表 → 结构体多出 i8* 槽位(与 TPC 的 {i32,i32} 布局不符)
|
||
- Phase A-pre(declare_only=1)父类延迟检查找不到 "Struct" → 类被延迟注册
|
||
→ forward_declare 时类型未注册 → 裸类形参退化为 i32 → 函数签名与
|
||
函数体 alloca(Ptr(struct))不一致 → llc 报 "'%p' defined with type
|
||
'i32' but expected 'ptr'"。
|
||
与 TPC(_resolve_base_kind 对 t.Struct 返回 None → 无父类)保持一致。
|
||
"""
|
||
if base_name is None:
|
||
return 0
|
||
if string.strcmp(base_name, "Object") == 0:
|
||
return 1
|
||
if string.strcmp(base_name, "CVTable") == 0:
|
||
return 1
|
||
if string.strcmp(base_name, "Exception") == 0:
|
||
return 1
|
||
if string.strcmp(base_name, "CEnum") == 0:
|
||
return 1
|
||
if string.strcmp(base_name, "Enum") == 0:
|
||
return 1
|
||
if string.strcmp(base_name, "CStruct") == 0:
|
||
return 1
|
||
if string.strcmp(base_name, "Struct") == 0:
|
||
return 1
|
||
if string.strcmp(base_name, "CUnion") == 0:
|
||
return 1
|
||
if string.strcmp(base_name, "REnum") == 0:
|
||
return 1
|
||
return 0
|
||
def _get_base_name(self, base_node: ast.AST*,
|
||
pool: memhub.MemBuddy* = None,
|
||
from_imports: str = None) -> str:
|
||
"""从 base AST 节点提取基类名,返回 None=失败
|
||
|
||
对于 Subscript 节点,需要 pool 分配内存拼接特化名;
|
||
pool=None 时降级返回基类名(不含类型实参)
|
||
|
||
类型实参必须与**唯一生成器**(ClassGenGeneric._mangle_generic_class_name)
|
||
同口径:本函数产出的父类特化名要拿去 find_struct_by_module 查、并写入
|
||
`entry.ParentName`,而注册名由生成器(内部经 _norm_type_arg_name 归一)
|
||
产出 ⇒ 这里同样归一,否则父类 `GSListNode[Value]` 与注册的
|
||
`GSListNode[{sha1}.Value]` 不同名 ⇒ 父类查找落空/继承链断裂。
|
||
"""
|
||
if base_node is None:
|
||
return None
|
||
k: int = base_node.kind()
|
||
# Name(id) 形式
|
||
if k == ast.ASTKind.Name:
|
||
nm: ast.Name* = ast.Name*(base_node)
|
||
return nm.id
|
||
# Attribute(attr) 形式
|
||
if k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute* = ast.Attribute*(base_node)
|
||
return at.attr
|
||
# Subscript(value, slice) 形式 — 如 GSListNode[Value]
|
||
if k == ast.ASTKind.Subscript:
|
||
sub: ast.Subscript* = ast.Subscript*(base_node)
|
||
if sub is None or sub.value is None or sub.slice is None:
|
||
return None
|
||
# 提取基类名(如 "GSListNode")
|
||
base_nm: str = self._get_base_name(sub.value, pool, from_imports)
|
||
if base_nm is None:
|
||
return None
|
||
# 提取类型实参名(如 "Value"),并与唯一生成器同口径归一
|
||
slice_k: int = sub.slice.kind()
|
||
arg_nm: str = None
|
||
if slice_k == ast.ASTKind.Name:
|
||
sl_nm: ast.Name* = ast.Name*(sub.slice)
|
||
arg_nm = sl_nm.id
|
||
# 如果无法提取类型实参,返回基类名(降级)
|
||
if arg_nm is None:
|
||
return base_nm
|
||
# 无 pool 时返回基类名(降级,无法拼接特化名)
|
||
if pool is None:
|
||
return base_nm
|
||
arg_norm: str = self.Gen.TypeGenResolve._norm_type_arg_name(pool, arg_nm, from_imports)
|
||
if arg_norm is not None:
|
||
arg_nm = arg_norm
|
||
# 拼接特化名 "GSListNode[Value]"
|
||
base_len: sizet = string.strlen(base_nm)
|
||
arg_len: sizet = string.strlen(arg_nm)
|
||
total_len: sizet = base_len + arg_len + 3 # "[" + arg + "]" + NUL
|
||
mangled: str = pool.alloc(total_len)
|
||
if mangled is None:
|
||
return base_nm # 降级
|
||
mangled[0] = '\0'
|
||
string.strcat(mangled, base_nm)
|
||
string.strcat(mangled, "[")
|
||
string.strcat(mangled, arg_nm)
|
||
string.strcat(mangled, "]")
|
||
return mangled
|
||
return None
|
||
def _get_parent_class(self, cd: ast.ClassDef*,
|
||
trans: HT.Translator* = None) -> str:
|
||
"""获取 ClassDef 的真实父类名,返回 None=无真实父类"""
|
||
if cd is None or cd.bases is None:
|
||
return None
|
||
pool: memhub.MemBuddy* = None
|
||
if trans is not None:
|
||
pool = trans.Pool
|
||
bases: list[ast.AST*]* = cd.bases
|
||
bn: sizet = len(bases)
|
||
if bn == 0:
|
||
return None
|
||
for bi in range(bn):
|
||
base_node: ast.AST* = bases.get(bi)
|
||
if base_node is None:
|
||
continue
|
||
_fi_pc: str = None
|
||
if trans is not None:
|
||
_fi_pc = trans._from_imports
|
||
bname: str = self._get_base_name(base_node, pool, _fi_pc)
|
||
if bname is not None:
|
||
# 基类别名解析(from t import CStruct as cs → cs 实际是 CStruct)。
|
||
# 不解析会把别名当真实父类 → find_struct("cs") 失败 → 类 defer 永不注册。
|
||
bname = self._resolve_base_alias(bname, trans)
|
||
if self._is_marker_base(bname) == 0:
|
||
return bname
|
||
return None
|
||
def _resolve_base_alias(self, base_name: str,
|
||
trans: HT.Translator* = None) -> str:
|
||
"""解析基类别名:from t import CStruct as cs → 基类 cs 实际是 CStruct。
|
||
|
||
别名不解析时 "cs" 会被当作真实父类名 → find_struct("cs") 失败 →
|
||
PhaseA 预注册把整类 defer(永不注册)→ 变量注解 X 解析失败
|
||
(EdgeCaseTest Test12 class CsPoint(cs): 根因)。
|
||
"""
|
||
if base_name is None or trans is None or trans._from_imports is None:
|
||
return base_name
|
||
orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, base_name)
|
||
if orig is not None:
|
||
# lookup_from_import_original 返回 from_imports 内部指针且未 NUL 结尾
|
||
# (如 "CStruct myint:t:CInt CChar:t CPtr:t" 整串直到真正的 NUL)。
|
||
# 复制到独立缓冲并按空格截断出干净原始名——否则 _is_marker_base 的
|
||
# strcmp 对整串比较失败 → 别名基类(CStruct as cs)被当真实父类 →
|
||
# find_struct 失败 → 整类 defer 永不注册 → 变量注解解析失败。
|
||
og_len: sizet = 0
|
||
while orig[og_len] != ' ' and orig[og_len] != '\0':
|
||
og_len += 1
|
||
if og_len > 0:
|
||
og_buf: str = CompilerFactory.factory.PermPool.alloc(og_len + 1)
|
||
if og_buf is not None:
|
||
string.strncpy(og_buf, orig, og_len)
|
||
og_buf[og_len] = '\0'
|
||
return og_buf
|
||
return base_name
|
||
def _collect_parents(self, pool: memhub.MemBuddy*,
|
||
cd: ast.ClassDef*,
|
||
parents_buf: sizet*,
|
||
max_parents: int,
|
||
trans: HT.Translator* = None) -> int:
|
||
"""收集所有非 marker 父类名到 parents_buf,返回数量"""
|
||
if pool is None or cd is None or cd.bases is None or parents_buf is None:
|
||
return 0
|
||
bases: list[ast.AST*]* = cd.bases
|
||
bn: sizet = len(bases)
|
||
count: int = 0
|
||
for bi in range(bn):
|
||
if count >= max_parents:
|
||
break
|
||
base_node: ast.AST* = bases.get(bi)
|
||
if base_node is None:
|
||
continue
|
||
_fi_cp: str = None
|
||
if trans is not None:
|
||
_fi_cp = trans._from_imports
|
||
bname: str = self._get_base_name(base_node, pool, _fi_cp)
|
||
if bname is not None:
|
||
# 基类别名解析(同 _get_parent_class,见 _resolve_base_alias)
|
||
bname = self._resolve_base_alias(bname, trans)
|
||
if self._is_marker_base(bname) == 0:
|
||
parents_buf[count] = sizet(bname)
|
||
count += 1
|
||
return count
|
||
def _field_name_exists(self, names_buf: sizet*,
|
||
count: int, name: str) -> int:
|
||
"""检查字段名是否已在 names_buf 中(先声明父类优先,重复跳过)"""
|
||
if names_buf is None or name is None:
|
||
return 0
|
||
for fi in range(count):
|
||
addr: sizet = names_buf[fi]
|
||
if addr != 0:
|
||
existing: str = rawptr(addr)
|
||
if existing is not None and string.strcmp(existing, name) == 0:
|
||
return 1
|
||
return 0
|
||
def _class_body_has_field(self, cd: ast.ClassDef*) -> int:
|
||
"""检查类体是否声明了字段(AnnAssign),0=纯方法/无字段类"""
|
||
if cd is None or cd.children is None:
|
||
return 0
|
||
cn: sizet = len(cd.children)
|
||
for ci in range(cn):
|
||
stmt: ast.AST* = cd.children.get(ci)
|
||
if stmt is None:
|
||
continue
|
||
if stmt.kind() == ast.ASTKind.AnnAssign:
|
||
return 1
|
||
return 0
|
||
def _trigger_base_specialization(self, trans: HT.Translator*,
|
||
cd: ast.ClassDef*):
|
||
"""触发 base 中 Subscript 的泛型特化(如 GSListNode[Value])"""
|
||
if trans is None or cd is None or cd.bases is None:
|
||
return
|
||
pool: memhub.MemBuddy* = trans.Pool
|
||
bases: list[ast.AST*]* = cd.bases
|
||
bn: sizet = len(bases)
|
||
if bn == 0:
|
||
return
|
||
for bi in range(bn):
|
||
base_node: ast.AST* = bases.get(bi)
|
||
if base_node is None:
|
||
continue
|
||
bk: int = base_node.kind()
|
||
if bk != ast.ASTKind.Subscript:
|
||
continue
|
||
sub: ast.Subscript* = ast.Subscript*(base_node)
|
||
if sub is None or sub.value is None or sub.slice is None:
|
||
continue
|
||
# 提取泛型类名(如 "GSListNode")
|
||
gen_class_name: str = self._get_base_name(sub.value, pool)
|
||
if gen_class_name is None:
|
||
continue
|
||
# 跳过标记基类
|
||
if self._is_marker_base(gen_class_name) == 1:
|
||
continue
|
||
# 提取类型实参名(如 "Value")
|
||
slice_k: int = sub.slice.kind()
|
||
arg_nm: str = None
|
||
if slice_k == ast.ASTKind.Name:
|
||
sl_nm: ast.Name* = ast.Name*(sub.slice)
|
||
arg_nm = sl_nm.id
|
||
if arg_nm is None:
|
||
continue
|
||
# 构建 type_args 列表(elem_size=8:str 是指针,1 会导致双元素重叠损坏)
|
||
type_args: list[str]* = list[str](pool, 8)
|
||
if type_args is None:
|
||
continue
|
||
type_args.append(arg_nm)
|
||
# 触发特化(_specialize_generic_class 有缓存,重复调用安全)
|
||
self.Gen.ClassGenGeneric._specialize_generic_class(trans, gen_class_name, type_args)
|
||
def _has_any_func_cvtable(self, cd: ast.ClassDef*) -> int:
|
||
"""检查类中是否有任何函数标记了 @t.CVTable,返回 1=有 / 0=无"""
|
||
if cd is None or cd.children is None:
|
||
return 0
|
||
children: list[ast.AST*]* = cd.children
|
||
cn: sizet = len(children)
|
||
for ci in range(cn):
|
||
stmt: ast.AST* = children.get(ci)
|
||
if stmt is None:
|
||
continue
|
||
if stmt.kind() != ast.ASTKind.FunctionDef:
|
||
continue
|
||
fd: ast.FunctionDef* = ast.FunctionDef*(stmt)
|
||
if fd is None or fd.name is None:
|
||
continue
|
||
# 跳过构造函数
|
||
if string.strcmp(fd.name, "__init__") == 0:
|
||
continue
|
||
if string.strcmp(fd.name, "__before_init__") == 0:
|
||
continue
|
||
if string.strcmp(fd.name, "__new__") == 0:
|
||
continue
|
||
if fd.decorator_list is not None:
|
||
if self._has_decorator(fd.decorator_list, "CVTable") == 1:
|
||
return 1
|
||
return 0
|
||
def _should_method_be_virtual(self, cd: ast.ClassDef*,
|
||
fd: ast.FunctionDef*,
|
||
trans: HT.Translator* = None) -> int:
|
||
"""判断方法是否应该进入虚表,返回 1=包含 / 0=排除"""
|
||
if fd is None:
|
||
return 0
|
||
# 1. 检查函数级 @t.NoVTable(最高优先级,排除)
|
||
if fd.decorator_list is not None:
|
||
if self._has_decorator(fd.decorator_list, "NoVTable") == 1:
|
||
return 0
|
||
# 2. 检查函数级 @t.CVTable(明确包含)
|
||
if self._has_decorator(fd.decorator_list, "CVTable") == 1:
|
||
return 1
|
||
|
||
# 3. 检查类级别 @t.CVTable
|
||
if cd is not None and cd.decorator_list is not None:
|
||
if self._has_decorator(cd.decorator_list, "CVTable") == 1:
|
||
return 1
|
||
|
||
# 4. 检查继承关系
|
||
parent_name: str = self._get_parent_class(cd, trans)
|
||
if parent_name is not None:
|
||
# 用 SHA1 感知查找父类,规避跨模块同名找错
|
||
is_nvt: int = 0
|
||
if trans is not None:
|
||
p_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(parent_name, trans.ModuleSha1)
|
||
if p_entry is None:
|
||
# 跨模块父类回退全局查找(父类注册在父模块 SHA1 下,如 linkedlist.LinkedNode),
|
||
# 与字段展平(1.5 节)的回退保持一致,否则父类 NoVTable 被误判为有虚表 → 子类插 vptr
|
||
# 导致子类布局比父类多一个指针,父类方法按无 vptr 布局操作错位
|
||
p_entry = self.Gen.StructGen.find_struct(parent_name)
|
||
if p_entry is not None:
|
||
is_nvt = p_entry.IsNoVTable
|
||
else:
|
||
is_nvt = self.Gen.StructGen.is_novtable_by_name(parent_name)
|
||
if is_nvt != 1:
|
||
# 继承链统一虚表:父类有虚表 → 方法进虚表;父类无虚表 → 静态方法。
|
||
# 与 _detect_vtable_status 规则一致,避免父类无 vptr 布局/子类有 vptr 的错位。
|
||
if p_entry is None:
|
||
return 1 # 父类信息未知,保守进虚表
|
||
if p_entry.HasVTable == 1:
|
||
return 1
|
||
return 0
|
||
|
||
# 5. 默认排除
|
||
return 0
|
||
def _detect_vtable_status(self, cd: ast.ClassDef*,
|
||
trans: HT.Translator* = None) -> int:
|
||
"""检测类是否应该启用虚表"""
|
||
if cd is None: return 0
|
||
|
||
# 检查类装饰器
|
||
if cd.decorator_list is not None:
|
||
# @t.CVTable 优先级最高,直接启用
|
||
if self._has_decorator(cd.decorator_list, "CVTable") == 1:
|
||
return 1
|
||
# @t.NoVTable:类级别禁用,但检查函数级 @t.CVTable
|
||
if self._has_decorator(cd.decorator_list, "NoVTable") == 1:
|
||
return self._has_any_func_cvtable(cd)
|
||
|
||
# 检查是否有真实父类(继承自动启用 CVTable)
|
||
parent_name: str = self._get_parent_class(cd, trans)
|
||
if parent_name is not None:
|
||
# 用 SHA1 感知查找父类,规避跨模块同名找错
|
||
is_nvt: int = 0
|
||
if trans is not None:
|
||
p_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(parent_name, trans.ModuleSha1)
|
||
if p_entry is None:
|
||
# 跨模块父类回退全局查找(同 _detect_vtable_status 的回退)
|
||
p_entry = self.Gen.StructGen.find_struct(parent_name)
|
||
if p_entry is not None:
|
||
is_nvt = p_entry.IsNoVTable
|
||
else:
|
||
is_nvt = self.Gen.StructGen.is_novtable_by_name(parent_name)
|
||
if is_nvt == 1:
|
||
# 父类是 NoVTable,检查函数级 @t.CVTable
|
||
return self._has_any_func_cvtable(cd)
|
||
# 继承链统一虚表:父类有虚表 → 子类启用;父类无虚表 → 子类静态。
|
||
# 若父类无 vtable 而子类有,父类方法按无 vptr 布局(self.field@0)操作
|
||
# 子类实例(有 vptr@0)会字段错位 → 运行时错误(父类方法读 vptr 当字段)。
|
||
if p_entry is None: return 1 # 父类信息未知(跨模块/未注册),保守启用虚表
|
||
if p_entry.HasVTable == 1: return 1
|
||
return 0
|
||
|
||
# 默认(无装饰器无继承),检查函数级 @t.CVTable
|
||
return self._has_any_func_cvtable(cd)
|
||
def InitClassGen(self) -> int:
|
||
"""初始化 ClassGen 族字段(构造时由 Generator 调用)"""
|
||
if self is None:
|
||
return 1
|
||
self.MethodMetaKeys = None
|
||
self.MethodMetaFlags = None
|
||
self.MethodMetaCount = 0
|
||
# [D30 根治] REnum 变体注册表挂在编译期单例 factory 上(perm_pool 后端),
|
||
# 与 struct entry 同寿命:此处**恢复**而非清零。清零会让新 Generator
|
||
# 丢掉前序已注册的 REnum 变体(`bits` NameError 根因),见 CompilerFactory。
|
||
self.RenumClassNames = CompilerFactory.factory.RenumClassNames
|
||
self.RenumClassVariantCounts = CompilerFactory.factory.RenumClassVariantCounts
|
||
self.RenumVariantNames = CompilerFactory.factory.RenumVariantNames
|
||
self.RenumVariantTags = CompilerFactory.factory.RenumVariantTags
|
||
self.RenumClassCount = CompilerFactory.factory.RenumClassCount
|
||
self.RenumAliasClass = CompilerFactory.factory.RenumAliasClass
|
||
self.RenumAliasField = CompilerFactory.factory.RenumAliasField
|
||
self.RenumAliasIndex = CompilerFactory.factory.RenumAliasIndex
|
||
self.RenumAliasCount = CompilerFactory.factory.RenumAliasCount
|
||
self.SpecKeys = None
|
||
self.SpecNames = None
|
||
self.SpecCount = 0
|
||
self.GenericClassNames = None
|
||
self.GenericClassNodes = None
|
||
self.GenericClassSha1s = None
|
||
self.GenericClassFiles = None
|
||
self.GenericClassTpParams = None
|
||
self.VtFullNames = None
|
||
self.VtMethodNames = None
|
||
self.VtParentSha1s = None
|
||
self.VtMethodCount = 0
|
||
self.RenumAliasTy = CompilerFactory.factory.RenumAliasTy
|
||
self.RenumAliasVariant = CompilerFactory.factory.RenumAliasVariant
|
||
self.ClassMetaKinds = None
|
||
self.ClassMetaClss = None
|
||
self.ClassMetaFields = None
|
||
self.ClassMetaCount = 0
|
||
self.DecoratorFuncCount = 0
|
||
self.DecoratorFuncNames = None
|
||
self.DecoratorWrapNames = None
|
||
self.DecoratorArgs = None
|
||
self.ExceptionCount = 0
|
||
self.ExceptionNames = None
|
||
self.ExceptionParents = None
|
||
self.ExceptionCodes = None
|
||
self.NextExceptionCode = 0
|
||
self._exception_codes_tmp_count = 0
|
||
self.GenericSpecDepth = 0
|
||
return 0
|