fix(compiler): 支持模块限定泛型类类型注解 numpy.ndarray[t.CDouble]
Subscript value 为 Attribute 时仅支持 t.CArray/t.Callable,模块限定 泛型类(numpy.ndarray[T])触发 fail-fast。提取 _resolve_generic_subscript_ty 辅助函数,Name 泛型类与 Attribute 泛型类共用(收集实参→mangled→特化)。
This commit is contained in:
1 parent
16d0302b08
commit
aa6eee54e9
1 file changed
+105
-78
@@ -1526,6 +1526,100 @@ def extract_class_name_from_annotation(node: ast.AST | t.CPtr,
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# _resolve_generic_subscript_ty - 解析泛型类类型注解
|
||||||
|
# (list[int] / numpy.ndarray[t.CDouble])
|
||||||
|
#
|
||||||
|
# 收集 slice 类型实参,构造 mangled name("list[int]"),查找已特化结构体;
|
||||||
|
# 未特化时检查是否泛型模板并主动触发特化。Name 泛型类与模块限定泛型类
|
||||||
|
# (Attribute value,如 numpy.ndarray[t.CDouble])共用此逻辑。
|
||||||
|
# ============================================================
|
||||||
|
def _resolve_generic_subscript_ty(pool: memhub.MemBuddy | t.CPtr,
|
||||||
|
sub: ast.Subscript | t.CPtr,
|
||||||
|
gen_cls_name: str,
|
||||||
|
trans: HT.Translator | t.CPtr,
|
||||||
|
imported_modules: str,
|
||||||
|
from_imports: str) -> llvmlite.LLVMType | t.CPtr:
|
||||||
|
"""解析泛型类类型注解(特化或查找已注册结构体),失败返回 None"""
|
||||||
|
if pool is None or sub is None or gen_cls_name is None:
|
||||||
|
return None
|
||||||
|
# tuple[...] 类型注解:TransPyV 暂不支持 tuple 返回类型,返回 None 让上层默认处理
|
||||||
|
# 避免走到 list[str](pool, 4) 构造路径崩溃(tuple 未定义为泛型类)
|
||||||
|
if string.strcmp(gen_cls_name, "tuple") == 0:
|
||||||
|
return None
|
||||||
|
# 先收集类型实参名,再分配缓冲区拼接 mangled name(elem_size=8:str 是指针)
|
||||||
|
gen_arg_names: list[str] | t.CPtr = list[str](pool, 8)
|
||||||
|
if sub.slice.kind() == ast.ASTKind.Tuple:
|
||||||
|
gen_tp: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(sub.slice)
|
||||||
|
gen_elts: list[ast.AST | t.CPtr] | t.CPtr = gen_tp.elts
|
||||||
|
if gen_elts is not None:
|
||||||
|
gen_en: t.CSizeT = gen_elts.__len__()
|
||||||
|
gen_ei: t.CSizeT
|
||||||
|
for gen_ei in range(gen_en):
|
||||||
|
gen_elt: ast.AST | t.CPtr = gen_elts.get(gen_ei)
|
||||||
|
gen_tn: str = _get_type_name_from_annotation(pool, gen_elt)
|
||||||
|
gen_arg_names.append(gen_tn)
|
||||||
|
else:
|
||||||
|
gen_tn_single: str = _get_type_name_from_annotation(pool, sub.slice)
|
||||||
|
gen_arg_names.append(gen_tn_single)
|
||||||
|
# 计算总长度并分配缓冲区
|
||||||
|
gen_total: t.CSizeT = string.strlen(gen_cls_name) + 2 # "[" 和 "]"
|
||||||
|
gen_an: t.CSizeT = gen_arg_names.__len__()
|
||||||
|
gen_ai: t.CSizeT
|
||||||
|
for gen_ai in range(gen_an):
|
||||||
|
if gen_ai > 0:
|
||||||
|
gen_total += 1 # ","
|
||||||
|
gen_atn: str = gen_arg_names.get(gen_ai)
|
||||||
|
if gen_atn is not None:
|
||||||
|
gen_total += string.strlen(gen_atn)
|
||||||
|
gen_total += 1 # NUL
|
||||||
|
gen_mangled: str = pool.alloc(gen_total)
|
||||||
|
if gen_mangled is None:
|
||||||
|
return None
|
||||||
|
gen_mangled[0] = '\0'
|
||||||
|
string.strcat(gen_mangled, gen_cls_name)
|
||||||
|
string.strcat(gen_mangled, "[")
|
||||||
|
for gen_ai in range(gen_an):
|
||||||
|
if gen_ai > 0:
|
||||||
|
string.strcat(gen_mangled, ",")
|
||||||
|
gen_atn: str = gen_arg_names.get(gen_ai)
|
||||||
|
if gen_atn is not None:
|
||||||
|
string.strcat(gen_mangled, gen_atn)
|
||||||
|
string.strcat(gen_mangled, "]")
|
||||||
|
# 查找已特化的 struct(特化由实例化调用 list[int](pool) 触发)
|
||||||
|
gen_spec_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(gen_mangled)
|
||||||
|
if gen_spec_ty is not None:
|
||||||
|
# 治本修复:Phase B 补译泛型特化类方法体
|
||||||
|
# Phase 1a(declare_only==1)特化时只注册结构体不译方法体(MethodsEmitted==0),
|
||||||
|
# Phase B(declare_only==0)解析字段类型命中已注册结构体时本会早返回,
|
||||||
|
# 导致方法体永远不生成 → GSList[Line].append 等符号只有 declare 无 define → 链接失败。
|
||||||
|
# 此处 Phase B 且方法体未译时,调用 _specialize_generic_class 走其已注册分支补译方法体。
|
||||||
|
if trans is not None and trans._declare_only == 0:
|
||||||
|
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||||
|
gen_spec_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(gen_mangled)
|
||||||
|
if gen_spec_entry is not None and gen_spec_entry.MethodsEmitted == 0:
|
||||||
|
HandlesClassDef._specialize_generic_class(trans, gen_cls_name, gen_arg_names)
|
||||||
|
return gen_spec_ty
|
||||||
|
# 未特化:尝试主动触发泛型特化(与 TPC _HandleSubscript 对齐)
|
||||||
|
# 当 trans 可用时,检查是否是泛型模板并触发特化
|
||||||
|
if trans is not None:
|
||||||
|
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||||
|
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||||
|
template_cd_chk: ast.ClassDef | t.CPtr = HandlesClassDef._find_generic_template(gen_cls_name)
|
||||||
|
if template_cd_chk is not None:
|
||||||
|
type_args_chk: list[str] | t.CPtr = HandlesExprCall._extract_type_args_from_slice(
|
||||||
|
pool, sub.slice)
|
||||||
|
if type_args_chk is not None and type_args_chk.__len__() > 0:
|
||||||
|
spec_name_chk: str = HandlesClassDef._specialize_generic_class(
|
||||||
|
trans, gen_cls_name, type_args_chk)
|
||||||
|
if spec_name_chk is not None:
|
||||||
|
gen_spec_ty = HandlesStruct.get_struct_type(gen_mangled)
|
||||||
|
if gen_spec_ty is not None:
|
||||||
|
return gen_spec_ty
|
||||||
|
# 未特化:返回 None(不报错,让后续流程处理)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# 解析类型注解节点为 LLVMType
|
# 解析类型注解节点为 LLVMType
|
||||||
#
|
#
|
||||||
@@ -1771,92 +1865,25 @@ def resolve_annotation_type(pool: memhub.MemBuddy | t.CPtr,
|
|||||||
sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node)
|
sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node)
|
||||||
if sub.value is None or sub.slice is None:
|
if sub.value is None or sub.slice is None:
|
||||||
fatal_type_error(node, "Subscript 节点缺少 value 或 slice")
|
fatal_type_error(node, "Subscript 节点缺少 value 或 slice")
|
||||||
# 泛型类类型注解: list[int] → 查找已特化的 struct
|
# 泛型类类型注解: list[int] → 查找已特化的 struct(value 是 Name 泛型类名)
|
||||||
# value 是 Name(泛型类名),slice 是类型实参
|
|
||||||
if sub.value.kind() == ast.ASTKind.Name:
|
if sub.value.kind() == ast.ASTKind.Name:
|
||||||
gen_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value)
|
gen_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value)
|
||||||
# tuple[...] 类型注解:TransPyV 暂不支持 tuple 返回类型,返回 None 让上层默认处理
|
|
||||||
# 避免走到 list[str](pool, 4) 构造路径崩溃(tuple 未定义为泛型类)
|
|
||||||
if gen_nm.id is not None:
|
if gen_nm.id is not None:
|
||||||
if string.strcmp(gen_nm.id, "tuple") == 0:
|
return _resolve_generic_subscript_ty(pool, sub, gen_nm.id, trans,
|
||||||
return None
|
imported_modules, from_imports)
|
||||||
# 先收集类型实参名,再分配缓冲区拼接 mangled name(elem_size=8:str 是指针)
|
# 检查 value 是否是 Attribute(t.CArray / t.Callable / 模块限定泛型类如 numpy.ndarray[T])
|
||||||
gen_arg_names: list[str] | t.CPtr = list[str](pool, 8)
|
|
||||||
if sub.slice.kind() == ast.ASTKind.Tuple:
|
|
||||||
gen_tp: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(sub.slice)
|
|
||||||
gen_elts: list[ast.AST | t.CPtr] | t.CPtr = gen_tp.elts
|
|
||||||
if gen_elts is not None:
|
|
||||||
gen_en: t.CSizeT = gen_elts.__len__()
|
|
||||||
gen_ei: t.CSizeT
|
|
||||||
for gen_ei in range(gen_en):
|
|
||||||
gen_elt: ast.AST | t.CPtr = gen_elts.get(gen_ei)
|
|
||||||
gen_tn: str = _get_type_name_from_annotation(pool, gen_elt)
|
|
||||||
gen_arg_names.append(gen_tn)
|
|
||||||
else:
|
|
||||||
gen_tn_single: str = _get_type_name_from_annotation(pool, sub.slice)
|
|
||||||
gen_arg_names.append(gen_tn_single)
|
|
||||||
# 计算总长度并分配缓冲区
|
|
||||||
gen_total: t.CSizeT = string.strlen(gen_nm.id) + 2 # "[" 和 "]"
|
|
||||||
gen_an: t.CSizeT = gen_arg_names.__len__()
|
|
||||||
gen_ai: t.CSizeT
|
|
||||||
for gen_ai in range(gen_an):
|
|
||||||
if gen_ai > 0:
|
|
||||||
gen_total += 1 # ","
|
|
||||||
gen_atn: str = gen_arg_names.get(gen_ai)
|
|
||||||
if gen_atn is not None:
|
|
||||||
gen_total += string.strlen(gen_atn)
|
|
||||||
gen_total += 1 # NUL
|
|
||||||
gen_mangled: str = pool.alloc(gen_total)
|
|
||||||
if gen_mangled is None:
|
|
||||||
return None
|
|
||||||
gen_mangled[0] = '\0'
|
|
||||||
string.strcat(gen_mangled, gen_nm.id)
|
|
||||||
string.strcat(gen_mangled, "[")
|
|
||||||
for gen_ai in range(gen_an):
|
|
||||||
if gen_ai > 0:
|
|
||||||
string.strcat(gen_mangled, ",")
|
|
||||||
gen_atn: str = gen_arg_names.get(gen_ai)
|
|
||||||
if gen_atn is not None:
|
|
||||||
string.strcat(gen_mangled, gen_atn)
|
|
||||||
string.strcat(gen_mangled, "]")
|
|
||||||
# 查找已特化的 struct(特化由实例化调用 list[int](pool) 触发)
|
|
||||||
gen_spec_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(gen_mangled)
|
|
||||||
if gen_spec_ty is not None:
|
|
||||||
# 治本修复:Phase B 补译泛型特化类方法体
|
|
||||||
# Phase 1a(declare_only==1)特化时只注册结构体不译方法体(MethodsEmitted==0),
|
|
||||||
# Phase B(declare_only==0)解析字段类型命中已注册结构体时本会早返回,
|
|
||||||
# 导致方法体永远不生成 → GSList[Line].append 等符号只有 declare 无 define → 链接失败。
|
|
||||||
# 此处 Phase B 且方法体未译时,调用 _specialize_generic_class 走其已注册分支补译方法体。
|
|
||||||
if trans is not None and trans._declare_only == 0:
|
|
||||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
|
||||||
gen_spec_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(gen_mangled)
|
|
||||||
if gen_spec_entry is not None and gen_spec_entry.MethodsEmitted == 0:
|
|
||||||
HandlesClassDef._specialize_generic_class(trans, gen_nm.id, gen_arg_names)
|
|
||||||
return gen_spec_ty
|
|
||||||
# 未特化:尝试主动触发泛型特化(与 TPC _HandleSubscript 对齐)
|
|
||||||
# 当 trans 可用时,检查是否是泛型模板并触发特化
|
|
||||||
if trans is not None:
|
|
||||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
|
||||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
|
||||||
template_cd_chk: ast.ClassDef | t.CPtr = HandlesClassDef._find_generic_template(gen_nm.id)
|
|
||||||
if template_cd_chk is not None:
|
|
||||||
type_args_chk: list[str] | t.CPtr = HandlesExprCall._extract_type_args_from_slice(
|
|
||||||
pool, sub.slice)
|
|
||||||
if type_args_chk is not None and type_args_chk.__len__() > 0:
|
|
||||||
spec_name_chk: str = HandlesClassDef._specialize_generic_class(
|
|
||||||
trans, gen_nm.id, type_args_chk)
|
|
||||||
if spec_name_chk is not None:
|
|
||||||
gen_spec_ty = HandlesStruct.get_struct_type(gen_mangled)
|
|
||||||
if gen_spec_ty is not None:
|
|
||||||
return gen_spec_ty
|
|
||||||
# 未特化:返回 None(不报错,让后续流程处理)
|
|
||||||
return None
|
|
||||||
# 检查 value 是否是 Attribute(Name('t'), 'CArray'/'Callable')
|
|
||||||
if sub.value.kind() != ast.ASTKind.Attribute:
|
if sub.value.kind() != ast.ASTKind.Attribute:
|
||||||
fatal_type_error(node, "不支持的 Subscript 类型注解(仅支持 t.CArray / t.Callable)")
|
fatal_type_error(node, "不支持的 Subscript 类型注解(仅支持 t.CArray / t.Callable)")
|
||||||
arr_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(sub.value)
|
arr_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(sub.value)
|
||||||
if arr_at.attr is None:
|
if arr_at.attr is None:
|
||||||
fatal_type_error(node, "Subscript Attribute 缺少 attr")
|
fatal_type_error(node, "Subscript Attribute 缺少 attr")
|
||||||
|
# 模块限定泛型类: numpy.ndarray[t.CDouble] → 裸类名 ndarray 走泛型特化
|
||||||
|
# (在 t.CArray / t.Callable 检查之前;模板已注册即视为泛型类)
|
||||||
|
if trans is not None:
|
||||||
|
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||||
|
if HandlesClassDef._find_generic_template(arr_at.attr) is not None:
|
||||||
|
return _resolve_generic_subscript_ty(pool, sub, arr_at.attr, trans,
|
||||||
|
imported_modules, from_imports)
|
||||||
if arr_at.value is None or arr_at.value.kind() != ast.ASTKind.Name:
|
if arr_at.value is None or arr_at.value.kind() != ast.ASTKind.Name:
|
||||||
fatal_type_error(node, "t.CArray / t.Callable 必须通过模块名限定")
|
fatal_type_error(node, "t.CArray / t.Callable 必须通过模块名限定")
|
||||||
arr_val_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arr_at.value)
|
arr_val_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arr_at.value)
|
||||||
|
|||||||
Reference in new issue
Block a user