feat(gen,type): callable[] / callable[[]] / callable[[A,B],R] 与 t.Callable 逐点等价

- 判据单一真源:_SubscriptAttrIsCallable 扩为 _IsCallableSubscriptValue,同时认 Attribute(attr=Callable) 与裸名 Name(callable | Callable)。

- Subscript 分支在 Name 路径(泛型特化 / CArray / builtins typedef 兜底)之前拦截裸名 callable/Callable → i8*;否则 callable[] 会先撞 slice=None 的 fail-fast、callable[[]] 会被当泛型类名查空。

- TypeGenErr.try_extract_callable_ret 改用同一判据:callable[[A, B], R] 现在也会注册返回类型 R(可间接调用),无签名形态([]、[[]])仍返回 None。
This commit is contained in:
TermiNexus committed 2026-09-27 12:30:47 +08:00
1 parent a76cf55a2d
commit 9455db0eec
2 files changed
+37 -16

No files matched your search

+5 -5
View File
@@ -184,14 +184,14 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase):
imported_modules: str,
from_imports: str,
trans: HT.Translator*) -> llvmlite.LLVMType*:
"""提取 t.Callable 注解的返回类型 LLVMType;非 Callable 注解返回 None"""
"""提取函数指针注解(t.Callable[[A,B], R] / callable[[A,B], R])的返回类型
LLVMType;非 Callable 注解或无签名形态([]、[[]])返回 None"""
if annot is None or annot.kind() != ast.ASTKind.Subscript:
return None
sub_cr: ast.Subscript* = ast.Subscript*(annot)
if sub_cr.value is None or sub_cr.value.kind() != ast.ASTKind.Attribute:
return None
at_cr: ast.Attribute* = ast.Attribute*(sub_cr.value)
if at_cr.attr is None or string.strcmp(at_cr.attr, "Callable") != 0:
# 构造子判据走 TypeGenResolve 单一真源(Attribute 形态 t.Callable 与
# 裸名形态 callable / Callable 等价)
if self.Gen.TypeGenResolve._IsCallableSubscriptValue(sub_cr.value) == 0:
return None
# slice 必须是 Tuple(elts=[args_list, ret_node])
if sub_cr.slice is None or sub_cr.slice.kind() != ast.ASTKind.Tuple:
+32 -11
View File
@@ -1366,20 +1366,33 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
return llvmlite.Int32(pool)
return llvmlite.Int64(pool)
# ============================================================
# _SubscriptAttrIsCallable - Subscript 的 value 是否为 t.Callable / c.Callable
# _IsCallableSubscriptValue - Subscript 的 value 是否为函数指针类型构造子
#
# 用于放行"空下标/空参数表"的无签名函数指针注解:
# t.Callable[](slice=None)/ t.Callable[[]](slice=空 List)
# 与 t.Callable[[A, B], Ret]、裸 t.Callable 同为 i8*。
# 两种书写形态逐点等价(同 i8*):
# t.Callable[...] / c.Callable[...] → Attribute(attr="Callable")
# callable[...] / Callable[...] → Name(内建别名,注解位置生效)
# 用于放行"空下标/空参数表"的无签名形态(slice=None / 空 List):
# t.Callable[] / t.Callable[[]] / callable[] / callable[[]]
# ============================================================
def _SubscriptAttrIsCallable(self, value_node: ast.AST*) -> int:
if value_node is None or value_node.kind() != ast.ASTKind.Attribute:
def _IsCallableSubscriptValue(self, value_node: ast.AST*) -> int:
if value_node is None:
return 0
at: ast.Attribute* = ast.Attribute*(value_node)
if at.attr is None:
vk: int = value_node.kind()
if vk == ast.ASTKind.Attribute:
at: ast.Attribute* = ast.Attribute*(value_node)
if at.attr is None:
return 0
if string.strcmp(at.attr, "Callable") == 0:
return 1
return 0
if string.strcmp(at.attr, "Callable") == 0:
return 1
if vk == ast.ASTKind.Name:
nm: ast.Name* = ast.Name*(value_node)
if nm.id is None:
return 0
if string.strcmp(nm.id, "callable") == 0:
return 1
if string.strcmp(nm.id, "Callable") == 0:
return 1
return 0
def map_t_type(self, pool: memhub.MemBuddy*,
@@ -2774,8 +2787,16 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
self.Gen.TypeGenErr.fatal_type_error(node, "Subscript 节点缺少 value")
# 空下标形态(t.Callable[])的 slice 为 None:只有无签名函数指针允许,
# 落到下方 Callable 分支按 i8* 处理;其它类型仍要求 slice 存在。
if sub.slice is None and self._SubscriptAttrIsCallable(sub.value) == 0:
if sub.slice is None and self._IsCallableSubscriptValue(sub.value) == 0:
self.Gen.TypeGenErr.fatal_type_error(node, "Subscript 节点缺少 value 或 slice")
# 函数指针(裸名形态 callable / Callable):与 t.Callable 逐点等价,
# 无签名(callable[] / callable[[]])或有签名(callable[[A, B], R])
# 统一 i8*。必须在本分支的 Name 路径(泛型特化 / CArray / builtins
# typedef 兜底)之前判定,否则裸名 callable 会被当泛型类名查空。
# 完整签名的返回类型注册见 TypeGenErr.try_extract_callable_ret。
if sub.value.kind() == ast.ASTKind.Name \
and self._IsCallableSubscriptValue(sub.value) != 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
# 泛型类类型注解: list[int] → 查找已特化的 struct(value 是 Name 泛型类名)
if sub.value.kind() == ast.ASTKind.Name:
gen_nm: ast.Name* = ast.Name*(sub.value)