diff --git a/App/lib/core/Gen/Type/TypeGenErr.vp b/App/lib/core/Gen/Type/TypeGenErr.vp index 0295472..0efe4e7 100644 --- a/App/lib/core/Gen/Type/TypeGenErr.vp +++ b/App/lib/core/Gen/Type/TypeGenErr.vp @@ -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: diff --git a/App/lib/core/Gen/Type/TypeGenResolve.vp b/App/lib/core/Gen/Type/TypeGenResolve.vp index 4df8bd2..6a86d62 100644 --- a/App/lib/core/Gen/Type/TypeGenResolve.vp +++ b/App/lib/core/Gen/Type/TypeGenResolve.vp @@ -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)