ClassGenMixin 拆分(47ac2dd)时 _resolve_base_alias 丢失:_get_parent_class
/_collect_parents 不再解析 from-import 别名基类(from t import CStruct as cs
→ class CsPoint(cs)),'cs' 被当真实父类 → find_struct('cs') 失败 → 类 defer
永不注册 → 变量注解解析失败(EdgeCaseTest Test12 回归)。恢复
_resolve_base_alias 并在两处调用;_collect_parents 增 trans 参数透传(别名
解析需 from_imports)。TypeGenResolve 增 [DBG-ANNOT] 插桩待验证后移除。
1119 lines
55 KiB
Plaintext
1119 lines
55 KiB
Plaintext
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
|
||
|
||
|
||
# ============================================================
|
||
# 本地常量(阶段 D 拆分时从 ClassGenMixin 顶层遗漏,补回:
|
||
# 方法元数据/类元数据/装饰器/异常表容量与编码;本地副本避免跨模块 CDefine 查找)
|
||
# ============================================================
|
||
# 方法元数据 flag 位(对齐 TPC HandlesBase _METHOD_META_*)
|
||
META_TLS: t.CDefine = 32
|
||
# 类编译期元数据表容量上限(__provides__/__requires__/__require_must__)
|
||
CLASS_META_MAX: t.CDefine = 256
|
||
# 自定义装饰器 wrapper 表容量上限(带 @decor 的函数数)
|
||
DECOR_FUNC_MAX: t.CDefine = 64
|
||
# 装饰器表槽内函数名/wrapper 名长度(含 NUL)
|
||
DECOR_NAME_LEN: t.CDefine = 128
|
||
# 异常类注册表容量上限(class X(Exception) 自定义异常类)
|
||
EXCEPTION_MAX: t.CDefine = 64
|
||
# 异常类表槽内类名/父类名长度(含 NUL)
|
||
EXCEPTION_NAME_LEN: t.CDefine = 128
|
||
# 内置异常编码(对齐 TPC HandlesBase.py EXCEPTION_CODE_MAP);
|
||
# KeyError=6 IOError=7 OSError=8 AssertionError=9 Exception=99;用户类从 100 起
|
||
BUILTIN_EH_VALUE_ERROR: t.CDefine = 1
|
||
BUILTIN_EH_RUNTIME_ERROR: t.CDefine = 3
|
||
BUILTIN_EH_EXCEPTION: t.CDefine = 99
|
||
EH_USER_CODE_START: t.CDefine = 100
|
||
|
||
|
||
# ============================================================
|
||
# ClassGenBase - ClassGenMixin 拆分(阶段 D):字段 + 方法元数据/异常/继承检测/装饰器(Meta)
|
||
#
|
||
# 继承 ClassGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||
# 跨 Mixin 调用统一走 HandlesClassDef 委托(经 _g_gen)。
|
||
# @t.NoVTable:静态绑定。
|
||
# ============================================================
|
||
@t.NoVTable
|
||
class ClassGenBase:
|
||
"""字段 + 方法元数据/异常/继承检测/装饰器(Meta)"""
|
||
|
||
# --- 方法元数据表(原 _g_method_meta_keys/_g_method_meta_flags/_g_method_meta_count) ---
|
||
MethodMetaKeys: bytes
|
||
MethodMetaFlags: bytes
|
||
MethodMetaCount: int
|
||
|
||
# --- REnum 变体表(原 _renum_class_names/_renum_class_variant_counts/
|
||
# _renum_variant_names/_renum_variant_tags/_renum_class_count) ---
|
||
RenumClassNames: t.CSizeT | t.CPtr
|
||
RenumClassVariantCounts: t.CSizeT | t.CPtr
|
||
RenumVariantNames: t.CSizeT | t.CPtr
|
||
RenumVariantTags: t.CSizeT | t.CPtr
|
||
RenumClassCount: int
|
||
|
||
# --- REnum 字段别名表(原 _renum_alias_class/_renum_alias_field/
|
||
# _renum_alias_index/_renum_alias_count) ---
|
||
RenumAliasClass: t.CSizeT | t.CPtr
|
||
RenumAliasField: t.CSizeT | t.CPtr
|
||
RenumAliasIndex: t.CSizeT | t.CPtr
|
||
# 变体成员实际 LLVM 类型(对齐 TPC class_members):注册时按注解解析,
|
||
# perm_pool 深拷贝持久化。match 绑定用真实成员类型 bitcast 槽位地址
|
||
# (Struct.Name: i8*,否则按槽位 i64 读 → is/subscript/strlen 失败)。
|
||
RenumAliasTy: t.CSizeT | t.CPtr
|
||
# 别名所属变体名(perm_pool 拷贝):同一 payload 位置跨变体类型不同
|
||
# (Int.Bits=i32 vs Struct.Fields=Ptr),match 绑定按 (class, 变体, 位置)
|
||
# 唯一定位成员类型。
|
||
RenumAliasVariant: t.CSizeT | t.CPtr
|
||
RenumAliasCount: int
|
||
|
||
# --- 泛型特化缓存(原 _spec_keys/_spec_names/_spec_count) ---
|
||
SpecKeys: t.CSizeT | t.CPtr
|
||
SpecNames: t.CSizeT | t.CPtr
|
||
SpecCount: int
|
||
|
||
# --- 类编译期元数据表(__provides__/__requires__/__require_must__) ---
|
||
# perm_pool 分配(跨 mark/reset 存活):每槽 kind(4B) + cls(64B) + field(64B)
|
||
# FakeDuck:_str.__requires__=['__mbuddy__'] 等(FakeDuck 移植点 1)
|
||
ClassMetaKinds: t.CInt | 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: t.CInt64T | t.CPtr
|
||
|
||
# --- 异常类注册表(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: t.CInt | t.CPtr
|
||
# 下一个待分配的异常编码(用户类,从 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] | t.CPtr
|
||
GenericClassNodes: list[ast.ClassDef | t.CPtr] | t.CPtr
|
||
GenericClassSha1s: list[str] | t.CPtr
|
||
# 泛型模板来源文件路径(与上面三表同序)。特化翻译模板方法体时
|
||
# node.lineno 是模板文件行号,若 CurrentFile 仍是调用方文件,
|
||
# fatal_error 会把模板行号套到调用方文件上显示错位(如 vector.vp
|
||
# 的 T(...) 错报成 vectortest.vp 的 return 0)。此表用于特化期间
|
||
# 临时切换 CurrentFile 到模板文件,翻译完恢复。
|
||
GenericClassFiles: list[str] | t.CPtr
|
||
# 泛型模板类型参数名表(与 GenericClassNames 同序,stdlib 深拷贝)。
|
||
# 模板节点 type_params 是 Phase 1 pool 分配的 list,跨 Phase 引用时内容
|
||
# 可能失效(VectorGenericTest 特化 Vector[int].__init__ 的 T.__sizeof__()
|
||
# NameError 根因方向);注册时展平深拷贝到 stdlib,特化时从本表恢复。
|
||
# 每槽指向一个空格分隔、NUL 结尾的 stdlib 缓冲区(如 "T" 或 "T K")。
|
||
GenericClassTpParams: t.CSizeT | t.CPtr
|
||
|
||
# --- vtable 方法收集表(原 _g_vt_full_names/_g_vt_method_names/
|
||
# _g_vt_parent_sha1s/_g_vt_method_count) ---
|
||
VtFullNames: t.CSizeT | t.CPtr
|
||
VtMethodNames: t.CSizeT | t.CPtr
|
||
VtParentSha1s: t.CSizeT | t.CPtr
|
||
VtMethodCount: int
|
||
# ============================================================
|
||
# 以下方法由 P5-2 分簇迁移填充(函数体来自 HandlesClassDef.vp,
|
||
# 本模块函数调用改 self.,外部模块调用保留模块前缀)
|
||
# ============================================================
|
||
|
||
def _is_cenum_base(self, base_node: ast.AST | t.CPtr,
|
||
trans: HT.Translator | t.CPtr = 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 | t.CPtr = (ast.Name | t.CPtr)(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 = HandlesImports.lookup_from_import_original(
|
||
trans._from_imports, nm.id)
|
||
if alias_orig is not None:
|
||
og_len_ce: t.CSizeT = 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 | t.CPtr = (ast.Attribute | t.CPtr)(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 | t.CPtr,
|
||
trans: HT.Translator | t.CPtr = 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 | t.CPtr] | t.CPtr = cd.bases
|
||
bn: t.CSizeT = len(bases)
|
||
if bn == 0:
|
||
return 0
|
||
for bi in range(bn):
|
||
base_node: ast.AST | t.CPtr = 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 | t.CPtr,
|
||
trans: HT.Translator | t.CPtr = 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 | t.CPtr = (ast.Name | t.CPtr)(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 = HandlesImports.lookup_from_import_original(
|
||
trans._from_imports, nm.id)
|
||
if alias_orig is not None:
|
||
og_len_cu: t.CSizeT = 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 | t.CPtr = (ast.Attribute | t.CPtr)(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 | t.CPtr,
|
||
trans: HT.Translator | t.CPtr = 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 | t.CPtr] | t.CPtr = cd.bases
|
||
bn: t.CSizeT = len(bases)
|
||
if bn == 0:
|
||
return 0
|
||
for bi in range(bn):
|
||
base_node: ast.AST | t.CPtr = 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 | t.CPtr,
|
||
trans: HT.Translator | t.CPtr = 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 | t.CPtr = (ast.Name | t.CPtr)(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 = HandlesImports.lookup_from_import_original(
|
||
trans._from_imports, nm.id)
|
||
if alias_orig is not None:
|
||
og_len_cr: t.CSizeT = 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 | t.CPtr = (ast.Attribute | t.CPtr)(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 | t.CPtr,
|
||
trans: HT.Translator | t.CPtr = 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 | t.CPtr] | t.CPtr = cd.bases
|
||
bn: t.CSizeT = len(bases)
|
||
if bn == 0:
|
||
return 0
|
||
for bi in range(bn):
|
||
base_node: ast.AST | t.CPtr = 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 | t.CPtr] | t.CPtr,
|
||
deco_name: str) -> int:
|
||
"""检查 decorator_list 中是否有指定装饰器名"""
|
||
if decorator_list is None:
|
||
return 0
|
||
dn: t.CSizeT = len(decorator_list)
|
||
if dn == 0:
|
||
return 0
|
||
for di in range(dn):
|
||
deco: ast.AST | t.CPtr = decorator_list.get(di)
|
||
if deco is None:
|
||
continue
|
||
k: int = deco.kind()
|
||
# @t.NoVTable 形式(Attribute)
|
||
if k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(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 | t.CPtr = (ast.Name | t.CPtr)(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 | t.CPtr = (ast.Name | t.CPtr)(deco)
|
||
if nm.id is not None and string.strcmp(nm.id, deco_name) == 0:
|
||
return 1
|
||
return 0
|
||
def _extract_func_meta(self, decorator_list: list[ast.AST | t.CPtr] | t.CPtr) -> int:
|
||
"""从装饰器列表提取元数据位掩码,返回 0=无装饰器元数据"""
|
||
meta: int = 0
|
||
if decorator_list is None:
|
||
return meta
|
||
dn: t.CSizeT = len(decorator_list)
|
||
if dn == 0:
|
||
return meta
|
||
for di in range(dn):
|
||
deco: ast.AST | t.CPtr = decorator_list.get(di)
|
||
if deco is None:
|
||
continue
|
||
k: int = deco.kind()
|
||
if k == ast.ASTKind.Name:
|
||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(deco)
|
||
if nm.id is not None:
|
||
if string.strcmp(nm.id, "staticmethod") == 0:
|
||
meta |= META_STATIC
|
||
elif string.strcmp(nm.id, "property") == 0:
|
||
meta |= META_PROP_GETTER
|
||
elif string.strcmp(nm.id, "classmethod") == 0:
|
||
meta |= META_CLASS
|
||
elif string.strcmp(nm.id, "TLS") == 0:
|
||
meta |= META_TLS
|
||
elif k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(deco)
|
||
if at.attr is not None and at.value is not None:
|
||
if at.value.kind() == ast.ASTKind.Name:
|
||
vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(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 |= META_PROP_SETTER
|
||
elif string.strcmp(at.attr, "getter") == 0:
|
||
meta |= META_PROP_GETTER
|
||
elif string.strcmp(at.attr, "deleter") == 0:
|
||
meta |= META_PROP_DELETER
|
||
return meta
|
||
def register_class_meta(self, pool: memhub.MemBuddy | t.CPtr,
|
||
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.get_perm_pool().alloc(CLASS_META_MAX * 4)
|
||
self.ClassMetaClss = CompilerFactory.get_perm_pool().alloc(CLASS_META_MAX * 64)
|
||
self.ClassMetaFields = CompilerFactory.get_perm_pool().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: t.CSizeT = t.CSizeT(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 | t.CPtr,
|
||
func_name: str, wrapper_name: str,
|
||
arg0: t.CInt64T) -> 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.get_perm_pool().alloc(
|
||
DECOR_FUNC_MAX * DECOR_NAME_LEN)
|
||
self.DecoratorWrapNames = CompilerFactory.get_perm_pool().alloc(
|
||
DECOR_FUNC_MAX * DECOR_NAME_LEN)
|
||
self.DecoratorArgs = CompilerFactory.get_perm_pool().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: t.CSizeT = t.CSizeT(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) -> t.CInt64T:
|
||
"""按原函数名查装饰器首个常量参数(无参数为 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 | t.CPtr = CompilerFactory.get_perm_pool()
|
||
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: t.CSizeT = t.CSizeT(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: t.CInt | 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: t.CInt | 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 | t.CPtr) -> int:
|
||
"""类定义是否是异常类:基类是 Exception 或已注册异常类(1=是)"""
|
||
if cd is None or cd.bases is None:
|
||
return 0
|
||
bases_e: list[ast.AST | t.CPtr] | t.CPtr = cd.bases
|
||
bn_e: t.CSizeT = len(bases_e)
|
||
for bi_e in range(bn_e):
|
||
base_e: ast.AST | t.CPtr = 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 | t.CPtr)(base_e)).id
|
||
elif base_e.kind() == ast.ASTKind.Attribute:
|
||
base_at_e: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(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 | t.CPtr) -> str:
|
||
"""返回异常类定义的真实父类名(第一个非 Exception 的已注册异常类),无则 None"""
|
||
if cd is None or cd.bases is None:
|
||
return None
|
||
bases_e2: list[ast.AST | t.CPtr] | t.CPtr = cd.bases
|
||
bn_e2: t.CSizeT = len(bases_e2)
|
||
for bi_e2 in range(bn_e2):
|
||
base_e2: ast.AST | t.CPtr = 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 | t.CPtr)(base_e2)).id
|
||
elif base_e2.kind() == ast.ASTKind.Attribute:
|
||
base_at_e2: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(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 | t.CPtr,
|
||
cd: ast.ClassDef | t.CPtr) -> 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 | t.CPtr,
|
||
kind: int, cls: str, value_node: ast.AST | t.CPtr) -> 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 | t.CPtr = (ast.List | t.CPtr)(value_node)
|
||
if lst_rcm.elts is None:
|
||
return
|
||
elts_rcm: list[ast.AST | t.CPtr] | t.CPtr = lst_rcm.elts
|
||
en_rcm: t.CSizeT = len(elts_rcm)
|
||
for ei_rcm in range(en_rcm):
|
||
el_rcm: ast.AST | t.CPtr = elts_rcm.get(ei_rcm)
|
||
if el_rcm is None or el_rcm.kind() != ast.ASTKind.Constant:
|
||
continue
|
||
ec_rcm: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(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.get_perm_pool().alloc(META_MAX * META_KEY_LEN)
|
||
self.MethodMetaFlags = CompilerFactory.get_perm_pool().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: t.CSizeT = string.strlen(class_name)
|
||
mn_len: t.CSizeT = 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 = (t.CInt | t.CPtr)(t.CVoid(
|
||
t.CUInt64T(self.MethodMetaFlags) + i * 4, t.CPtr))
|
||
# 按位或合并:同一属性名先 @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 = (t.CInt | t.CPtr)(t.CVoid(
|
||
t.CUInt64T(self.MethodMetaFlags) + self.MethodMetaCount * 4, t.CPtr))
|
||
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: t.CSizeT = string.strlen(class_name)
|
||
mn_len: t.CSizeT = 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 = (t.CInt | t.CPtr)(t.CVoid(
|
||
t.CUInt64T(self.MethodMetaFlags) + i * 4, t.CPtr))
|
||
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 | t.CPtr,
|
||
pool: memhub.MemBuddy | t.CPtr = None) -> str:
|
||
"""从 base AST 节点提取基类名,返回 None=失败
|
||
|
||
对于 Subscript 节点,需要 pool 分配内存拼接特化名;
|
||
pool=None 时降级返回基类名(不含类型实参)
|
||
"""
|
||
if base_node is None:
|
||
return None
|
||
k: int = base_node.kind()
|
||
# Name(id) 形式
|
||
if k == ast.ASTKind.Name:
|
||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node)
|
||
return nm.id
|
||
# Attribute(attr) 形式
|
||
if k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node)
|
||
return at.attr
|
||
# Subscript(value, slice) 形式 — 如 GSListNode[Value]
|
||
if k == ast.ASTKind.Subscript:
|
||
sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(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)
|
||
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 | t.CPtr = (ast.Name | t.CPtr)(sub.slice)
|
||
arg_nm = sl_nm.id
|
||
# 如果无法提取类型实参,返回基类名(降级)
|
||
if arg_nm is None:
|
||
return base_nm
|
||
# 无 pool 时返回基类名(降级,无法拼接特化名)
|
||
if pool is None:
|
||
return base_nm
|
||
# 拼接特化名 "GSListNode[Value]"
|
||
base_len: t.CSizeT = string.strlen(base_nm)
|
||
arg_len: t.CSizeT = string.strlen(arg_nm)
|
||
total_len: t.CSizeT = 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 | t.CPtr,
|
||
trans: HT.Translator | t.CPtr = None) -> str:
|
||
"""获取 ClassDef 的真实父类名,返回 None=无真实父类"""
|
||
if cd is None or cd.bases is None:
|
||
return None
|
||
pool: memhub.MemBuddy | t.CPtr = None
|
||
if trans is not None:
|
||
pool = trans.Pool
|
||
bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases
|
||
bn: t.CSizeT = len(bases)
|
||
if bn == 0:
|
||
return None
|
||
for bi in range(bn):
|
||
base_node: ast.AST | t.CPtr = bases.get(bi)
|
||
if base_node is None:
|
||
continue
|
||
bname: str = self._get_base_name(base_node, pool)
|
||
if bname is not None:
|
||
# 基类别名解析(from t import CStruct as cs → cs 实际是 CStruct)。
|
||
# ClassGen 拆分(47ac2dd)时丢失,EdgeCaseTest Test12 class
|
||
# CsPoint(cs) 回归根因:'cs' 被当真实父类 → 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 | t.CPtr = 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 = HandlesImports.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: t.CSizeT = 0
|
||
while orig[og_len] != ' ' and orig[og_len] != '\0':
|
||
og_len += 1
|
||
if og_len > 0:
|
||
og_buf: str = CompilerFactory.get_perm_pool().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 | t.CPtr,
|
||
cd: ast.ClassDef | t.CPtr,
|
||
parents_buf: t.CSizeT | t.CPtr,
|
||
max_parents: int,
|
||
trans: HT.Translator | t.CPtr = 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 | t.CPtr] | t.CPtr = cd.bases
|
||
bn: t.CSizeT = len(bases)
|
||
count: int = 0
|
||
for bi in range(bn):
|
||
if count >= max_parents:
|
||
break
|
||
base_node: ast.AST | t.CPtr = bases.get(bi)
|
||
if base_node is None:
|
||
continue
|
||
bname: str = self._get_base_name(base_node, pool)
|
||
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] = t.CSizeT(bname)
|
||
count += 1
|
||
return count
|
||
def _field_name_exists(self, names_buf: t.CSizeT | t.CPtr,
|
||
count: int, name: str) -> int:
|
||
"""检查字段名是否已在 names_buf 中(先声明父类优先,重复跳过)"""
|
||
if names_buf is None or name is None:
|
||
return 0
|
||
for fi in range(count):
|
||
addr: t.CSizeT = names_buf[fi]
|
||
if addr != 0:
|
||
existing: str = (str | t.CPtr)(t.CVoid(addr, t.CPtr))
|
||
if existing is not None and string.strcmp(existing, name) == 0:
|
||
return 1
|
||
return 0
|
||
def _class_body_has_field(self, cd: ast.ClassDef | t.CPtr) -> int:
|
||
"""检查类体是否声明了字段(AnnAssign),0=纯方法/无字段类"""
|
||
if cd is None or cd.children is None:
|
||
return 0
|
||
cn: t.CSizeT = len(cd.children)
|
||
for ci in range(cn):
|
||
stmt: ast.AST | t.CPtr = 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 | t.CPtr,
|
||
cd: ast.ClassDef | t.CPtr):
|
||
"""触发 base 中 Subscript 的泛型特化(如 GSListNode[Value])"""
|
||
if trans is None or cd is None or cd.bases is None:
|
||
return
|
||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||
bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases
|
||
bn: t.CSizeT = len(bases)
|
||
if bn == 0:
|
||
return
|
||
for bi in range(bn):
|
||
base_node: ast.AST | t.CPtr = bases.get(bi)
|
||
if base_node is None:
|
||
continue
|
||
bk: int = base_node.kind()
|
||
if bk != ast.ASTKind.Subscript:
|
||
continue
|
||
sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(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 | t.CPtr = (ast.Name | t.CPtr)(sub.slice)
|
||
arg_nm = sl_nm.id
|
||
if arg_nm is None:
|
||
continue
|
||
# 构建 type_args 列表(elem_size=8:str 是指针,1 会导致双元素重叠损坏)
|
||
type_args: list[str] | t.CPtr = list[str](pool, 8)
|
||
if type_args is None:
|
||
continue
|
||
type_args.append(arg_nm)
|
||
# 触发特化(_specialize_generic_class 有缓存,重复调用安全)
|
||
HandlesClassDef._specialize_generic_class(trans, gen_class_name, type_args)
|
||
def _has_any_func_cvtable(self, cd: ast.ClassDef | t.CPtr) -> int:
|
||
"""检查类中是否有任何函数标记了 @t.CVTable,返回 1=有 / 0=无"""
|
||
if cd is None or cd.children is None:
|
||
return 0
|
||
children: list[ast.AST | t.CPtr] | t.CPtr = cd.children
|
||
cn: t.CSizeT = len(children)
|
||
for ci in range(cn):
|
||
stmt: ast.AST | t.CPtr = children.get(ci)
|
||
if stmt is None:
|
||
continue
|
||
if stmt.kind() != ast.ASTKind.FunctionDef:
|
||
continue
|
||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(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 | t.CPtr,
|
||
fd: ast.FunctionDef | t.CPtr,
|
||
trans: HT.Translator | t.CPtr = 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: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
|
||
parent_name, trans.ModuleSha1)
|
||
if p_entry is None:
|
||
# 跨模块父类回退全局查找(父类注册在父模块 SHA1 下,如 linkedlist.LinkedNode),
|
||
# 与字段展平(1.5 节)的回退保持一致,否则父类 NoVTable 被误判为有虚表 → 子类插 vptr
|
||
# 导致子类布局比父类多一个指针,父类方法按无 vptr 布局操作错位
|
||
p_entry = HandlesStruct.find_struct(parent_name)
|
||
if p_entry is not None:
|
||
is_nvt = p_entry.IsNoVTable
|
||
else:
|
||
is_nvt = HandlesStruct.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 | t.CPtr,
|
||
trans: HT.Translator | t.CPtr = 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: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(
|
||
parent_name, trans.ModuleSha1)
|
||
if p_entry is None:
|
||
# 跨模块父类回退全局查找(同 _detect_vtable_status 的回退)
|
||
p_entry = HandlesStruct.find_struct(parent_name)
|
||
if p_entry is not None:
|
||
is_nvt = p_entry.IsNoVTable
|
||
else:
|
||
is_nvt = HandlesStruct.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) |