- CallGenBase:字段声明处直接给默认值,InitCallGen 不再逐字段赋值 - CallGenFd/CallGenDispatch:@t.NoVTable 改 novirtual,清理过时注释 - VLogger:LogLevel 改 enum、t.CDefine 改 define 关键字、Logger|t.CPtr 改 Logger*、longjmp 用 rawptr - Generator:_g_gen 由 Generator|t.CPtr 改为 Generator* - CallGenProp:合并续行
445 lines
25 KiB
Plaintext
445 lines
25 KiB
Plaintext
import lib.core.Gen.GenTypes as GenTypes
|
||
import lib.core.Gen.GenApi as GenApi
|
||
import t, c
|
||
from stdint import *
|
||
import ast
|
||
import llvmlite
|
||
import memhub
|
||
import string
|
||
import stdio
|
||
import viperlib
|
||
import lib.core.Gen.Translator as HT
|
||
|
||
from . import CallGenBase
|
||
|
||
|
||
# ============================================================
|
||
# CallGenProp - CallGenMixin 拆分(阶段 B):属性访问(getter/setter/deleter / 静态类调用 / list 内置方法)
|
||
# ============================================================
|
||
novirtual class CallGenProp(CallGenBase.CallGenBase):
|
||
"""属性访问(getter/setter/deleter / 静态类调用 / list 内置方法)"""
|
||
|
||
# ============================================================
|
||
# 属性方法(@property/@x.setter/@x.deleter)与静态/类方法调用辅助
|
||
#
|
||
# 元数据表由 HandlesClassDef 在类翻译/预注册阶段填充,
|
||
# 这里负责把 obj.prop / obj.prop=v / del obj.prop / Class.method()
|
||
# 翻译为对应的 {sha1}.ClassName.prop 系列函数调用。
|
||
# ============================================================
|
||
|
||
# ============================================================
|
||
# _translate_property_call — 翻译属性方法调用
|
||
#
|
||
# 与 _translate_method_call 的调用名/返回类型解析逻辑一致:
|
||
# 1. 优先用模块中已有的函数(精确/后缀匹配,来自 stub 注入)
|
||
# 2. 否则用类所属模块的 SHA1 构造 "{sha1}.ClassName.method" 调用名
|
||
# 3. 返回类型:函数实类型 → text.ll 查找 → 按方法名推断(默认 i32)
|
||
#
|
||
# call_head/call_count: 已构建好的参数链表(如 getter 只有 obj 一个参数)
|
||
# ============================================================
|
||
def _translate_property_call(self, pool: memhub.MemBuddy*,
|
||
builder: llvmlite.IRBuilder*,
|
||
mod: llvmlite.LLVMModule*,
|
||
class_name: str,
|
||
method_name: str,
|
||
call_head: llvmlite.Value*,
|
||
call_count: int,
|
||
trans: HT.Translator*) -> llvmlite.Value*:
|
||
"""翻译属性/静态方法调用,返回 call 结果 Value"""
|
||
if pool is None or builder is None or class_name is None or method_name is None: return None
|
||
|
||
# 构造查找名: ClassName.method_name
|
||
lookup_name: str = pool.alloc(128)
|
||
if lookup_name is None: return None
|
||
viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, method_name)
|
||
|
||
# 查找函数(精确/后缀匹配)
|
||
found_func: llvmlite.Function* = self.find_func_in_module(mod, lookup_name)
|
||
|
||
# 确定调用名
|
||
call_name: str = lookup_name
|
||
if found_func is not None:
|
||
found_name: str = llvmlite.function_get_name(found_func)
|
||
if found_name is not None:
|
||
call_name = found_name
|
||
else:
|
||
# 未找到:用类所属模块的 SHA1 构造调用名
|
||
cls_sha1_pc: str = self.Gen.StructGen.get_struct_sha1(class_name)
|
||
if cls_sha1_pc is not None:
|
||
mlen_pc: sizet = string.strlen(cls_sha1_pc) + string.strlen(lookup_name) + 2
|
||
mangled_pc: str = pool.alloc(mlen_pc)
|
||
if mangled_pc is not None:
|
||
viperlib.snprintf(mangled_pc, mlen_pc, "%s.%s", cls_sha1_pc, lookup_name)
|
||
call_name = mangled_pc
|
||
|
||
# 确定返回类型
|
||
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
|
||
call_ret_ty: llvmlite.LLVMType* = i32_ty
|
||
if found_func is not None:
|
||
frt: llvmlite.LLVMType* = llvmlite.function_get_ret_ty(found_func)
|
||
if frt is not None:
|
||
call_ret_ty = frt
|
||
else:
|
||
sp_ty1: llvmlite.LLVMType* = self._special_method_ret_ty(pool, class_name, method_name)
|
||
if sp_ty1 is not None:
|
||
call_ret_ty = sp_ty1
|
||
else:
|
||
cls_sha1_rt: str = self.Gen.StructGen.get_struct_sha1(class_name)
|
||
looked_up_ty: llvmlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, cls_sha1_rt, class_name, method_name)
|
||
if looked_up_ty is not None:
|
||
call_ret_ty = looked_up_ty
|
||
else:
|
||
# 精确查找:vpi stub 返回注解缓存(方法定义处,不硬编码白名单)
|
||
vpi_ret_ty: llvmlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, cls_sha1_rt, class_name, method_name)
|
||
if vpi_ret_ty is not None:
|
||
call_ret_ty = vpi_ret_ty
|
||
else:
|
||
# Phase A 依赖未就绪(cls_sha1_rt None / 定义模块 text.ll 未生成):
|
||
# 保持默认 i32(build_call(Void) 返回 None 会破坏表达式翻译)。
|
||
if cls_sha1_rt is None \
|
||
or self._dep_text_ll_exists(pool, cls_sha1_rt) == 0:
|
||
call_ret_ty = llvmlite.Int32(pool)
|
||
else:
|
||
call_ret_ty = self._fail_method_ret_ty(method_name)
|
||
|
||
# 参数类型对齐:按目标函数声明的参数类型转换实参(与 _translate_method_call
|
||
# 一致)。例如 from_long(10) 的 i32 字面量 → i64 形参(v: t.CLong),
|
||
# 不转换则 call(i32) 与 declare(i64) 不匹配,llc 报参数类型错误。
|
||
# 目标函数优先用已找到的 found_func,否则按 mangled 调用名查模块 declare。
|
||
tgt_func_pc: llvmlite.Function* = found_func
|
||
if tgt_func_pc is None:
|
||
tgt_func_pc = self.find_func_in_module(mod, call_name)
|
||
if tgt_func_pc is not None:
|
||
prev_pc: llvmlite.Value* = None
|
||
cur_arg_pc: llvmlite.Value* = call_head
|
||
cur_param_pc: llvmlite.Param* = llvmlite.function_get_param_head(tgt_func_pc)
|
||
while cur_arg_pc is not None and cur_param_pc is not None:
|
||
param_ty_pc: llvmlite.LLVMType* = llvmlite.param_get_ty(cur_param_pc)
|
||
if param_ty_pc is not None and cur_arg_pc.Ty is not None:
|
||
coerced_pc: llvmlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, cur_arg_pc, param_ty_pc)
|
||
if coerced_pc is not None and coerced_pc != cur_arg_pc:
|
||
# 保持链表完整性:新 Value 继承原节点的 Next,前驱指向新节点
|
||
llvmlite.value_set_next(coerced_pc, cur_arg_pc.Next)
|
||
if prev_pc is None:
|
||
call_head = coerced_pc
|
||
else:
|
||
llvmlite.value_set_next(prev_pc, coerced_pc)
|
||
cur_arg_pc = coerced_pc
|
||
prev_pc = cur_arg_pc
|
||
cur_arg_pc = cur_arg_pc.Next
|
||
cur_param_pc = llvmlite.param_get_next(cur_param_pc)
|
||
|
||
# 确保 declare 存在,然后调用
|
||
self._ensure_method_declare(pool, mod, call_name, call_ret_ty, call_head, call_count)
|
||
return llvmlite.build_call(builder, call_name, call_head, call_count, call_ret_ty, 0)
|
||
# ============================================================
|
||
# _resolve_obj_class_name — 解析对象表达式的类名(短名)
|
||
#
|
||
# 优先从变量注解(AnnotClassName)解析(如 "memhub.MemBuddy" → "MemBuddy"),
|
||
# 失败时从 LLVM 类型解析(Ptr(Struct) → 类名)。
|
||
# 供属性访问/赋值/删除识别 property 时使用。
|
||
# ============================================================
|
||
|
||
# ============================================================
|
||
def _resolve_obj_class_name(self, pool: memhub.MemBuddy*,
|
||
trans: HT.Translator*,
|
||
obj_node: ast.AST*) -> str:
|
||
"""解析对象表达式的类名(短名),失败返回 None"""
|
||
if pool is None or trans is None or obj_node is None:
|
||
return None
|
||
if obj_node.kind() == ast.ASTKind.Name:
|
||
obj_nm: ast.Name* = ast.Name*(obj_node)
|
||
if obj_nm.id is not None:
|
||
var_entry: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, obj_nm.id)
|
||
annot_val: str = self.Gen.VarGen.var_annot_class_name(var_entry)
|
||
if annot_val is not None:
|
||
# [D32] 取「模块限定名」末段时只按**括号外**的 '.' 切分。
|
||
# 此前用 string.strrchr 在整个串上找最后一个 '.':泛型特化名
|
||
# "list[e94ef9e139461915.AST|t.CPtr]" 的 '.' 落在 '[' 内 ⇒
|
||
# 返回 "AST|t.CPtr]" 这种垃圾短名 ⇒ 后续按它查表必落空,
|
||
# 进而可能被兜底成任意特化(.get() 误分派)。
|
||
n_av: sizet = string.strlen(annot_val)
|
||
last_dot_av: sizet = n_av
|
||
depth_av: int = 0
|
||
ai_av: sizet = 0
|
||
while ai_av < n_av:
|
||
ch_av: int = annot_val[ai_av]
|
||
if ch_av == '[':
|
||
depth_av += 1
|
||
elif ch_av == ']':
|
||
depth_av -= 1
|
||
elif ch_av == '.' and depth_av == 0:
|
||
last_dot_av = ai_av
|
||
ai_av += 1
|
||
if last_dot_av < n_av:
|
||
return annot_val + last_dot_av + 1
|
||
return annot_val
|
||
return None
|
||
# ============================================================
|
||
# _try_property_getter_attr — 尝试将 obj.attr 翻译为 property getter 调用
|
||
#
|
||
# 检查 obj 的类是否有 @property/@x.getter 的 attr 方法;
|
||
# 若有则生成 call Class.attr(obj) 并返回调用结果 Value;否则返回 None。
|
||
# ============================================================
|
||
|
||
# ============================================================
|
||
def _try_property_getter_attr(self, pool: memhub.MemBuddy*,
|
||
builder: llvmlite.IRBuilder*,
|
||
mod: llvmlite.LLVMModule*,
|
||
at_node: ast.Attribute*,
|
||
obj_ptr: llvmlite.Value*,
|
||
trans: HT.Translator*,
|
||
fallback_class_name: str = None) -> llvmlite.Value*:
|
||
"""尝试 property getter 属性访问,返回调用结果 Value;非 getter 返回 None
|
||
|
||
fallback_class_name: 对象表达式非 Name 时从 LLVM 类型解析出的类名兜底。
|
||
"""
|
||
if at_node is None or at_node.attr is None or obj_ptr is None or trans is None:
|
||
return None
|
||
class_name: str = self._resolve_obj_class_name(pool, trans, at_node.value)
|
||
if class_name is None:
|
||
class_name = fallback_class_name
|
||
if class_name is None:
|
||
return None
|
||
meta: int = self.Gen.ClassGenBase.lookup_method_meta(class_name, at_node.attr)
|
||
if meta & GenTypes.META_PROP_GETTER == 0:
|
||
return None
|
||
# 单参数调用: obj → getter
|
||
llvmlite.value_set_next(obj_ptr, None)
|
||
return self._translate_property_call(pool, builder, mod, class_name, at_node.attr, obj_ptr, 1, trans)
|
||
# ============================================================
|
||
# _try_property_setter — 尝试将 obj.attr = v 翻译为 property setter 调用
|
||
#
|
||
# 检查 obj 的类是否有 @x.setter 的 attr 方法;
|
||
# 若有则生成 call Class.attr$set(obj, v),返回 1;否则返回 0。
|
||
# ============================================================
|
||
|
||
# ============================================================
|
||
def _try_property_setter(self, pool: memhub.MemBuddy*,
|
||
builder: llvmlite.IRBuilder*,
|
||
mod: llvmlite.LLVMModule*,
|
||
target_attr: ast.Attribute*,
|
||
rhs_val: llvmlite.Value*,
|
||
trans: HT.Translator*) -> int:
|
||
"""尝试 property setter 赋值,返回 1=已处理(生成调用)"""
|
||
if pool is None or builder is None or mod is None or trans is None: return 0
|
||
if target_attr is None or target_attr.attr is None or rhs_val is None: return 0
|
||
class_name: str = self._resolve_obj_class_name(pool, trans, target_attr.value)
|
||
if class_name is None: return 0
|
||
meta: int = self.Gen.ClassGenBase.lookup_method_meta(class_name, target_attr.attr)
|
||
if meta & GenTypes.META_PROP_SETTER == 0: return 0
|
||
# 翻译对象值(self 参数)
|
||
obj_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, target_attr.value, None, 0, trans)
|
||
if obj_val is None: return 0
|
||
# 构建参数链表: obj → rhs
|
||
llvmlite.value_set_next(obj_val, None)
|
||
llvmlite.value_set_next(rhs_val, None)
|
||
llvmlite.value_set_next(obj_val, rhs_val)
|
||
# setter 函数名带 $set 后缀
|
||
setter_name_buf: str = pool.alloc(128)
|
||
if setter_name_buf is None: return 0
|
||
viperlib.snprintf(setter_name_buf, 128, "%s$set", target_attr.attr)
|
||
self._translate_property_call(pool, builder, mod, class_name,
|
||
setter_name_buf, obj_val, 2, trans)
|
||
return 1
|
||
# ============================================================
|
||
# _try_property_deleter — 尝试将 del obj.attr 翻译为 property deleter 调用
|
||
#
|
||
# 检查 obj 的类是否有 @x.deleter 的 attr 方法;
|
||
# 若有则生成 call Class.attr$del(obj),返回 1;否则返回 0。
|
||
# ============================================================
|
||
|
||
# ============================================================
|
||
def _try_property_deleter(self, pool: memhub.MemBuddy*,
|
||
builder: llvmlite.IRBuilder*,
|
||
mod: llvmlite.LLVMModule*,
|
||
target_attr: ast.Attribute*,
|
||
trans: HT.Translator*) -> int:
|
||
"""尝试 property deleter 删除,返回 1=已处理(生成调用)"""
|
||
if pool is None or builder is None or mod is None or trans is None: return 0
|
||
if target_attr is None or target_attr.attr is None: return 0
|
||
class_name: str = self._resolve_obj_class_name(pool, trans, target_attr.value)
|
||
if class_name is None: return 0
|
||
meta: int = self.Gen.ClassGenBase.lookup_method_meta(class_name, target_attr.attr)
|
||
if meta & GenTypes.META_PROP_DELETER == 0: return 0
|
||
# 翻译对象值(self 参数)
|
||
obj_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, target_attr.value, None, 0, trans)
|
||
if obj_val is None: return 0
|
||
llvmlite.value_set_next(obj_val, None)
|
||
# deleter 函数名带 $del 后缀
|
||
del_name_buf: str = pool.alloc(128)
|
||
if del_name_buf is None: return 0
|
||
viperlib.snprintf(del_name_buf, 128, "%s$del", target_attr.attr)
|
||
self._translate_property_call(pool, builder, mod, class_name,
|
||
del_name_buf, obj_val, 1, trans)
|
||
return 1
|
||
# ============================================================
|
||
# _translate_static_class_call — 翻译 ClassName.method(args) 静态/类方法调用
|
||
#
|
||
# @staticmethod: 直接 call Class.method(args...),无 self
|
||
# @classmethod: 在参数前插入栈上分配的类实例指针(与 TPC 一致)
|
||
# ============================================================
|
||
|
||
# ============================================================
|
||
def _translate_static_class_call(self, pool: memhub.MemBuddy*,
|
||
builder: llvmlite.IRBuilder*,
|
||
mod: llvmlite.LLVMModule*,
|
||
class_name: str,
|
||
method_name: str,
|
||
cl: ast.Call*,
|
||
trans: HT.Translator*) -> llvmlite.Value*:
|
||
"""翻译类名静态/类方法调用,返回 call 结果 Value;非静态/类方法返回 None"""
|
||
if pool is None or builder is None or mod is None or trans is None: return None
|
||
if class_name is None or method_name is None or cl is None: return None
|
||
meta: int = self.Gen.ClassGenBase.lookup_method_meta(class_name, method_name)
|
||
is_static: int = 0
|
||
is_class: int = 0
|
||
if meta & GenTypes.META_STATIC != 0: is_static = 1
|
||
if meta & GenTypes.META_CLASS != 0: is_class = 1
|
||
if is_static == 0 and is_class == 0: return None
|
||
|
||
# 构建参数链表
|
||
head: llvmlite.Value* = None
|
||
total_count: int = 0
|
||
|
||
# @classmethod: 插入栈上分配的类实例指针作为 cls 参数
|
||
if is_class != 0:
|
||
struct_ty_cc: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(class_name)
|
||
if struct_ty_cc is None: return None
|
||
cls_ptr: llvmlite.Value* = self.Gen.VarGen._alloca_at_entry(builder, struct_ty_cc)
|
||
if cls_ptr is None: return None
|
||
llvmlite.value_set_next(cls_ptr, None)
|
||
head = cls_ptr
|
||
total_count = 1
|
||
|
||
# 翻译调用参数
|
||
cargs: list[ast.AST*]* = cl.args
|
||
can: sizet = 0
|
||
if cargs is not None:
|
||
can = len(cargs)
|
||
tail: llvmlite.Value* = head
|
||
for ai in range(can):
|
||
arg_node: ast.AST* = cargs.get(ai)
|
||
if arg_node is None: continue
|
||
arg_val: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg_node, None, 0, trans)
|
||
if arg_val is None: continue
|
||
llvmlite.value_set_next(arg_val, None)
|
||
if head is None:
|
||
head = arg_val
|
||
tail = arg_val
|
||
else:
|
||
llvmlite.value_set_next(tail, arg_val)
|
||
tail = arg_val
|
||
total_count += 1
|
||
|
||
# 零参 @staticmethod(如 PyListObj.new()):head 保持 None 是合法的
|
||
# 无参调用,照常走 _translate_property_call(SHA1 前缀名 + 精确返回类型)。
|
||
# 若此处 return None,调用方回退通用路径把方法名当裸函数解析,生成
|
||
# call i32 @new() → 链接 undefined reference(CPythonTest 根因)。
|
||
# @classmethod 恒有 cls_ptr(head 非 None),不受影响。
|
||
return self._translate_property_call(pool, builder, mod, class_name, method_name, head, total_count, trans)
|
||
# ============================================================
|
||
# _is_list_builtin_method - 判断是否是 list 泛型内置容器方法
|
||
#
|
||
# list[T] 是内置泛型容器(_list.vp),其方法(append/get/set/pop/clear/
|
||
# __iter__/__len__/__getitem__/__setitem__)由 translate_call 的 list
|
||
# 内置分支内联 GEP 处理,不注册为方法函数。若 obj.method() 检测把
|
||
# list 特化 struct(如 list[AST | CPtr])误当普通结构体走
|
||
# _translate_method_call,会查不到 append 返回类型 → fail-fast
|
||
# (NewAstTest body.append 根因)。此判断用于跳过 method_call 路径。
|
||
#
|
||
# 返回: 1=list 内置方法(应落到 list 内置分支),0=普通方法
|
||
# ============================================================
|
||
|
||
# ============================================================
|
||
def _is_list_builtin_method(self, class_name: str,
|
||
method_name: str) -> int:
|
||
"""判断 (class_name, method_name) 是否是 list 泛型内置方法"""
|
||
if class_name is None or method_name is None: return 0
|
||
# 类名必须以 "list" 开头(list / list[AST | CPtr] 特化名)
|
||
if string.strncmp(class_name, "list", 4) != 0: return 0
|
||
# 方法名必须是 list 内置方法集合
|
||
if string.strcmp(method_name, "append") == 0: return 1
|
||
if string.strcmp(method_name, "get") == 0: return 1
|
||
if string.strcmp(method_name, "set") == 0: return 1
|
||
if string.strcmp(method_name, "pop") == 0: return 1
|
||
if string.strcmp(method_name, "clear") == 0: return 1
|
||
if string.strcmp(method_name, "__iter__") == 0: return 1
|
||
if string.strcmp(method_name, "__len__") == 0: return 1
|
||
if string.strcmp(method_name, "__getitem__") == 0: return 1
|
||
if string.strcmp(method_name, "__setitem__") == 0: return 1
|
||
return 0
|
||
|
||
# ============================================================
|
||
# _strip_module_sha1_prefix - 去跨模块特化名的 sha1 前缀
|
||
#
|
||
# 接收者实际结构体名常带 "{16位小写hex}." 前缀(如
|
||
# "e94ef9e139461915.list[ast.ASTptr]");判定基名 | 特化名前必须先剥离。
|
||
# 前缀长度判定走唯一真源 GenApi.sha1_prefix_len(C10 收敛)。
|
||
# ============================================================
|
||
def _strip_module_sha1_prefix(self, name: str) -> str:
|
||
"""去除 "{16hex}." 前缀(无前缀则原样返回;返回原串内部子串)"""
|
||
if name is None:
|
||
return None
|
||
pfx: int = GenApi.sha1_prefix_len(name)
|
||
return name + pfx if pfx != 0 else name
|
||
|
||
# _resolve_generic_receiver_name:解析接收者实际泛型特化名(IR 真值)——接收者实际 LLVM 结构体类型名比可能退化的注解/注册名可靠,故泛型判定以此为准:去 sha1 前缀取 '[' 前基名,基名是已注册泛型模板时含类型实参 ⇒ 返回实际特化名,无类型实参 ⇒ fail-fast(D25);基名非泛型模板或实际类型不可得 ⇒ 返回 None(调用方各自回退)。与 CallGenCall._translate_method_call 的 D25 分派修复共用本函数(唯一口径)
|
||
def _resolve_generic_receiver_name(self, pool: memhub.MemBuddy*,
|
||
struct_ty: llvmlite.LLVMType*,
|
||
method_name: str,
|
||
cl: ast.Call*) -> str:
|
||
"""返回实际泛型特化名(去 sha1)或 None;裸泛型基类 fail-fast"""
|
||
if struct_ty is None:
|
||
return None
|
||
ty_nm: str = llvmlite.get_struct_name(struct_ty)
|
||
if ty_nm is None or ty_nm[0] == '\0':
|
||
return None
|
||
short_nm: str = self._strip_module_sha1_prefix(ty_nm)
|
||
lb: str = string.strchr(short_nm, '[')
|
||
bare_len: sizet = 0
|
||
if lb is not None:
|
||
bare_len = sizet(uint64(lb) - uint64(short_nm))
|
||
else:
|
||
bare_len = string.strlen(short_nm)
|
||
if bare_len == 0:
|
||
return None
|
||
base_nm: str = pool.alloc(bare_len + 1)
|
||
if base_nm is None:
|
||
return None
|
||
string.strncpy(base_nm, short_nm, bare_len)
|
||
base_nm[bare_len] = '\0'
|
||
# 基名非已注册泛型模板(普通类接收者)⇒ 非泛型,交由调用方原口径处理
|
||
if self.Gen.ClassGenGeneric._find_generic_template(base_nm) is None:
|
||
return None
|
||
if lb is not None:
|
||
return short_nm
|
||
# 裸泛型基类(无类型实参):接收者元素类型未知 → fail-fast(D25 口径)
|
||
self.Gen.TypeGenErr.fatal_error(
|
||
cl,
|
||
f"方法 '{method_name}' 的接收者实际结构体类型是裸泛型基类 "
|
||
f"'{short_nm}*'(丢失类型实参),元素类型未知;"
|
||
f"禁止静默按默认元素类型处理(元素按 i32 处理会截断指针),"
|
||
f"请让该变量的注解/类型带上实参(如 list[ast.AST*])",
|
||
"TypeError")
|
||
return None
|
||
|
||
# _is_list_builtin_receiver:基于接收者实际类型判定 list 内建方法,判据与 _resolve_generic_receiver_name 同源——优先采用接收者实际 LLVM 结构体类型名(去 sha1 判基名),不可得时回退注解名/注册名判定。返回 1=list 内置方法 / 0=非
|
||
def _is_list_builtin_receiver(self, pool: memhub.MemBuddy*,
|
||
recv_val: llvmlite.Value*,
|
||
fallback_name: str,
|
||
method_name: str,
|
||
cl: ast.Call*) -> int:
|
||
"""基于接收者实际类型判定 list 内建方法(实际类型不可得回退注解名)"""
|
||
sty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(recv_val)
|
||
if sty is not None:
|
||
ty_nm: str = llvmlite.get_struct_name(sty)
|
||
if ty_nm is not None and ty_nm[0] != '\0':
|
||
# 泛型模板接收者:裸基类 fail-fast;含实参用实际特化名
|
||
act_nm: str = self._resolve_generic_receiver_name(pool, sty, method_name, cl)
|
||
if act_nm is not None:
|
||
return self._is_list_builtin_method(act_nm, method_name)
|
||
# 非泛型模板接收者:用去 sha1 后的实际短名判定(不复用退化注解名)
|
||
return self._is_list_builtin_method(self._strip_module_sha1_prefix(ty_nm), method_name)
|
||
# 实际类型不可得 → 回退注解名/注册名判定(信息缺失下的既有行为)
|
||
return self._is_list_builtin_method(fallback_name, method_name) |