feat(generic): 泛型函数类型实参推断与单态化
支持 def f[T](x: T) -> T 及 f(x)/f[T](x):模板注册(Phase1Scan/Phase2 顶层 FunctionDef,键 {sha1}.{name})、按形参注解对齐从实参推断类型实参(无来源即 fail-fast,不静默默认 int)、克隆模板并 set_generic_context 后翻译生成特化体(名字 {sha1}.f[int],规范化复用 _mangle_generic_class_name)、同签名去重、跨模块按模板签名补 declare。泛型函数模板不再发 vpi(模板签名含未绑定 T),也不再发射 int 兜底版本。已知限制(未静默):bound [T: bound] 解析期已被丢弃;t.CExport/t.CExtern/t.State 泛型函数、关键字/默认参数调用、mod.f[T](x) 显式下标等暂 fail-fast 或走既有报错。
This commit is contained in:
1 parent
1fbebb2a62
commit
692998820c
10 files changed
+886
-57
No files matched your search
@@ -245,6 +245,50 @@ def _BufHasGenericClassMarker(buf: bytes, blen: sizet) -> int:
|
||||
pos += 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# _BufHasGenericFuncMarker - 文本扫描检测文件是否含泛型函数标记
|
||||
#
|
||||
# 泛型函数(PEP 695)语法: def name[(函数名后紧跟 '[',如 def f[T](...):)。
|
||||
# 与 _BufHasGenericClassMarker 同款逐字节词边界扫描;用于泛型函数模板的
|
||||
# 轻量预筛(避免为无泛型函数的文件 parse AST)。误报无害、漏报有害(模板未
|
||||
# 预注册),故保守只匹配单行形式。
|
||||
# ============================================================
|
||||
def _BufHasGenericFuncMarker(buf: bytes, blen: sizet) -> int:
|
||||
"""文本扫描:buf 中是否有 'def 标识符[' 泛型函数标记,返回 1/0"""
|
||||
if buf is None or blen <= 4:
|
||||
return 0
|
||||
pos: sizet = 0
|
||||
while pos + 3 < blen:
|
||||
if buf[pos] == 'd' and buf[pos + 1] == 'e' and buf[pos + 2] == 'f':
|
||||
# def 前是词边界(行首或非标识符字符)
|
||||
prev_ok: int = 1
|
||||
if pos > 0:
|
||||
pc: char = buf[pos - 1]
|
||||
if(pc >= 'a' and pc <= 'z') or(pc >= 'A' and pc <= 'Z') \
|
||||
or(pc >= '0' and pc <= '9') or pc == '_':
|
||||
prev_ok = 0
|
||||
if prev_ok != 0:
|
||||
p: sizet = pos + 3
|
||||
# 跳过空白
|
||||
while p < blen and(buf[p] == ' ' or buf[p] == '\t'):
|
||||
p += 1
|
||||
# 读函数名标识符
|
||||
if p < blen and((buf[p] >= 'a' and buf[p] <= 'z')
|
||||
or(buf[p] >= 'A' and buf[p] <= 'Z') or buf[p] == '_'):
|
||||
while p < blen and((buf[p] >= 'a' and buf[p] <= 'z')
|
||||
or(buf[p] >= 'A' and buf[p] <= 'Z')
|
||||
or(buf[p] >= '0' and buf[p] <= '9')
|
||||
or buf[p] == '_'):
|
||||
p += 1
|
||||
# 函数名后非空白是 '[' → 泛型函数
|
||||
while p < blen and(buf[p] == ' ' or buf[p] == '\t'):
|
||||
p += 1
|
||||
if p < blen and buf[p] == '[':
|
||||
return 1
|
||||
pos += 1
|
||||
else:
|
||||
pos += 1
|
||||
return 0
|
||||
# ============================================================
|
||||
# _PreRegisterAllGenericTemplates - 预注册 includes 泛型类模板(mark1 前)
|
||||
#
|
||||
# 泛型模板表(GenericClassNames/GenericClassNodes/GenericClassSha1s/GenericClassFiles + 模板节点)是懒分配的跨文件持久表,
|
||||
@@ -289,8 +333,10 @@ def _PreRegisterAllGenericTemplates(mb: memhub.MemBuddy*,
|
||||
continue
|
||||
if bytes_read_pg < Phase1.SRC_BUF_SIZE:
|
||||
src_buf_pg[bytes_read_pg] = 0
|
||||
# 文本扫描筛选:非泛型文件跳过(不 parse、不驻留,防 OOM)
|
||||
if _BufHasGenericClassMarker(src_buf_pg, bytes_read_pg) == 0:
|
||||
# 文本扫描筛选:非泛型文件跳过(不 parse、不驻留,防 OOM)。
|
||||
# 泛型类(class X[)与泛型函数(def f[)任一命中即进入 parse。
|
||||
if _BufHasGenericClassMarker(src_buf_pg, bytes_read_pg) == 0 \
|
||||
and _BufHasGenericFuncMarker(src_buf_pg, bytes_read_pg) == 0:
|
||||
stdlib.free(src_buf_pg)
|
||||
continue
|
||||
# 泛型文件:永久池解析 → 注册模板(节点/表进 perm_pool,跨 reset 存活)
|
||||
@@ -304,26 +350,38 @@ def _PreRegisterAllGenericTemplates(mb: memhub.MemBuddy*,
|
||||
if tree_pg is None:
|
||||
stdlib.free(src_buf_pg)
|
||||
continue
|
||||
# 遍历顶层 ClassDef,注册泛型模板(type_params 非 None)
|
||||
# 遍历顶层 ClassDef/FunctionDef,注册泛型模板(type_params 非 None)
|
||||
ch_pg: list[ast.AST*]* = tree_pg.children
|
||||
if ch_pg is not None:
|
||||
cn_pg: sizet = len(ch_pg)
|
||||
for ci_pg in range(cn_pg):
|
||||
child_pg: ast.AST* = ch_pg.get(ci_pg)
|
||||
if child_pg is None or child_pg.kind() != ast.ASTKind.ClassDef:
|
||||
if child_pg is None:
|
||||
continue
|
||||
cd_pg: ast.ClassDef* = ast.ClassDef*(child_pg)
|
||||
if cd_pg is None or cd_pg.name is None:
|
||||
continue
|
||||
tp_pg: list[str]* = cd_pg.type_params
|
||||
if tp_pg is None:
|
||||
continue
|
||||
GenApi.set_current_file_type(file_path_pg)
|
||||
GenApi._register_generic_template(perm, cd_pg, entry_pg.Sha1)
|
||||
handled_count += 1
|
||||
ck_pg: int = child_pg.kind()
|
||||
if ck_pg == ast.ASTKind.ClassDef:
|
||||
cd_pg: ast.ClassDef* = ast.ClassDef*(child_pg)
|
||||
if cd_pg is None or cd_pg.name is None:
|
||||
continue
|
||||
tp_pg: list[str]* = cd_pg.type_params
|
||||
if tp_pg is None:
|
||||
continue
|
||||
GenApi.set_current_file_type(file_path_pg)
|
||||
GenApi._register_generic_template(perm, cd_pg, entry_pg.Sha1)
|
||||
handled_count += 1
|
||||
elif ck_pg == ast.ASTKind.FunctionDef:
|
||||
fd_pg: ast.FunctionDef* = ast.FunctionDef*(child_pg)
|
||||
if fd_pg is None or fd_pg.name is None:
|
||||
continue
|
||||
tf_pg: list[str]* = fd_pg.type_params
|
||||
if tf_pg is None:
|
||||
continue
|
||||
GenApi.set_current_file_type(file_path_pg)
|
||||
GenApi._register_generic_func_template(perm, fd_pg, entry_pg.Sha1)
|
||||
handled_count += 1
|
||||
stdlib.free(src_buf_pg)
|
||||
if handled_count > 0:
|
||||
VLogger.info(f"mark1 前永久池预注册 {handled_count} 个 includes 泛型类模板", "Phase1")
|
||||
VLogger.info(f"mark1 前永久池预注册 {handled_count} 个 includes 泛型模板(类+函数)", "Phase1")
|
||||
else:
|
||||
VLogger.info(f"mark1 前永久池预注册 0 个泛型模板(扫描 {result.Count} 个文件,可能 marker 未命中或全量扫描失败)", "Phase1")
|
||||
return handled_count
|
||||
|
||||
@@ -303,26 +303,38 @@ def _PreRegisterAppGenericTemplates(mb: memhub.MemBuddy*,
|
||||
if tree_pa is None:
|
||||
stdlib.free(src_buf_pa)
|
||||
continue
|
||||
# 遍历顶层 ClassDef,注册泛型模板(type_params 非 None)
|
||||
# 遍历顶层 ClassDef/FunctionDef,注册泛型模板(type_params 非 None)
|
||||
ch_pa: list[ast.AST*]* = tree_pa.children
|
||||
if ch_pa is not None:
|
||||
cn_pa: sizet = len(ch_pa)
|
||||
for ci_pa in range(cn_pa):
|
||||
child_pa: ast.AST* = ch_pa.get(ci_pa)
|
||||
if child_pa is None or child_pa.kind() != ast.ASTKind.ClassDef:
|
||||
if child_pa is None:
|
||||
continue
|
||||
cd_pa: ast.ClassDef* = ast.ClassDef*(child_pa)
|
||||
if cd_pa is None or cd_pa.name is None:
|
||||
continue
|
||||
tp_pa: list[str]* = cd_pa.type_params
|
||||
if tp_pa is None:
|
||||
continue
|
||||
GenApi.set_current_file_type(ent_pa.Path)
|
||||
GenApi._register_generic_template(perm_pa, cd_pa, ent_pa.Sha1)
|
||||
handled += 1
|
||||
ck_pa: int = child_pa.kind()
|
||||
if ck_pa == ast.ASTKind.ClassDef:
|
||||
cd_pa: ast.ClassDef* = ast.ClassDef*(child_pa)
|
||||
if cd_pa is None or cd_pa.name is None:
|
||||
continue
|
||||
tp_pa: list[str]* = cd_pa.type_params
|
||||
if tp_pa is None:
|
||||
continue
|
||||
GenApi.set_current_file_type(ent_pa.Path)
|
||||
GenApi._register_generic_template(perm_pa, cd_pa, ent_pa.Sha1)
|
||||
handled += 1
|
||||
elif ck_pa == ast.ASTKind.FunctionDef:
|
||||
fd_pa: ast.FunctionDef* = ast.FunctionDef*(child_pa)
|
||||
if fd_pa is None or fd_pa.name is None:
|
||||
continue
|
||||
tf_pa: list[str]* = fd_pa.type_params
|
||||
if tf_pa is None:
|
||||
continue
|
||||
GenApi.set_current_file_type(ent_pa.Path)
|
||||
GenApi._register_generic_func_template(perm_pa, fd_pa, ent_pa.Sha1)
|
||||
handled += 1
|
||||
stdlib.free(src_buf_pa)
|
||||
if handled > 0:
|
||||
VLogger.info(f"mark2 前预注册 {handled} 个 App 泛型类模板", "PhaseA")
|
||||
VLogger.info(f"mark2 前预注册 {handled} 个 App 泛型模板(类+函数)", "PhaseA")
|
||||
return handled
|
||||
|
||||
|
||||
|
||||
@@ -984,6 +984,13 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
|
||||
# 函数定义(_PyiFunction 已以 "\n" 收尾,不再补空行)
|
||||
elif k == ast.ASTKind.FunctionDef:
|
||||
fn: ast.FunctionDef* = ast.FunctionDef*(stmt)
|
||||
# 泛型函数模板(def f[T])不发 vpi:模板签名含未绑定类型形参 T,
|
||||
# 注入侧无法解析(旧行为会写出 `def f(x: T)` 的错误/失败签名)。
|
||||
# 特化体按调用点单态化生成({模板SHA1}.f[args]),其签名由编译器
|
||||
# 内存中的模板表 + 实参跨模块复现(见 ClassGenGeneric.
|
||||
# _ensure_generic_func_declare),不落 vpi。
|
||||
if fn.type_params is not None:
|
||||
continue
|
||||
pos = _PyiFunction(buf, buf_size, pos, fn, 0, "")
|
||||
|
||||
# 类定义
|
||||
|
||||
@@ -27,6 +27,225 @@ import lib.core.Gen.GenApi as GenApi
|
||||
novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
"""translate_call 前置检测 helper(继承 Base)"""
|
||||
|
||||
# ============================================================
|
||||
# _tc_h0_generic_func - 泛型函数调用(隐式/显式类型实参 → 单态化 → 调用)
|
||||
#
|
||||
# 未命中(不是泛型函数调用)返回 None;命中即发射调用并用 hit_box 标记
|
||||
# (返回 None 但 hit_box=1 表示返回 void 的调用,不可再走主路径)。
|
||||
# 必须在普通函数/类构造分派之前拦截:泛型函数模板在定义处不发射普通函数,
|
||||
# 走主路径会"裸名调用未定义"。
|
||||
# ============================================================
|
||||
def _tc_h0_generic_func(self, pool: memhub.MemBuddy*,
|
||||
builder: llvmlite.IRBuilder*,
|
||||
mod: llvmlite.LLVMModule*,
|
||||
cl: ast.Call*,
|
||||
funcs_ptr: t.CPtr,
|
||||
func_count: int,
|
||||
trans: HT.Translator*,
|
||||
func_name: str,
|
||||
cargs: list[ast.AST*]*,
|
||||
can: sizet,
|
||||
hit_box: t.CPtr = None) -> llvmlite.Value*:
|
||||
if cl is None or trans is None: return None
|
||||
if self.Gen.ClassGenGeneric.GenericFuncKeys is None: return None
|
||||
if cl.func is None: return None
|
||||
# ---- 判定泛型函数调用形态 + 模板名/显式类型实参 ----
|
||||
tpl_name: str = None
|
||||
explicit_slice: ast.AST* = None
|
||||
tpl_mod_sha1: str = None
|
||||
is_attr_call: int = 0
|
||||
fk: int = cl.func.kind()
|
||||
if fk == ast.ASTKind.Subscript:
|
||||
sub: ast.Subscript* = ast.Subscript*(cl.func)
|
||||
if sub.value is not None and sub.value.kind() == ast.ASTKind.Name:
|
||||
sn: ast.Name* = ast.Name*(sub.value)
|
||||
tpl_name = sn.id
|
||||
explicit_slice = sub.slice
|
||||
elif fk == ast.ASTKind.Name:
|
||||
tpl_name = func_name
|
||||
elif fk == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute* = ast.Attribute*(cl.func)
|
||||
if at.attr is not None and at.value is not None and at.value.kind() == ast.ASTKind.Name:
|
||||
mn: ast.Name* = ast.Name*(at.value)
|
||||
if mn.id is not None and trans._imported_modules is not None:
|
||||
if self.Gen.ImportsGen.is_module_imported_or_known(trans._imported_modules, mn.id) != 0:
|
||||
tpl_mod_sha1 = self._lookup_module_sha1(mn.id)
|
||||
# 仅当基座是**已导入模块**时才按模块限定泛型函数处理;
|
||||
# 否则 `obj.add(x)` 里 obj 不是模块,绝不能按裸名 local 键
|
||||
# 命中同名模块级泛型函数 add 而劫持方法调用。
|
||||
if tpl_mod_sha1 is not None:
|
||||
is_attr_call = 1
|
||||
tpl_name = at.attr
|
||||
if tpl_name is None: return None
|
||||
# ---- 解析模板键("{sha1}.{fname}"):模块限定 > 本模块 > from_imports ----
|
||||
tpl_key: str = None
|
||||
if is_attr_call != 0:
|
||||
# 模块限定调用:只认该模块 SHA1 的键
|
||||
if tpl_mod_sha1 is not None:
|
||||
cand_q: str = self._generic_func_key(pool, tpl_mod_sha1, tpl_name)
|
||||
if self.Gen.ClassGenGeneric._find_generic_func_template(cand_q) is not None:
|
||||
tpl_key = cand_q
|
||||
else:
|
||||
if trans.ModuleSha1 is not None:
|
||||
cand_l: str = self._generic_func_key(pool, trans.ModuleSha1, tpl_name)
|
||||
if self.Gen.ClassGenGeneric._find_generic_func_template(cand_l) is not None:
|
||||
tpl_key = cand_l
|
||||
if tpl_key is None and trans._from_imports is not None:
|
||||
imp_sha: str = self._lookup_mod_sha1(pool, trans._from_imports, tpl_name, 0)
|
||||
if imp_sha is not None:
|
||||
cand_f: str = self._generic_func_key(pool, imp_sha, tpl_name)
|
||||
if self.Gen.ClassGenGeneric._find_generic_func_template(cand_f) is not None:
|
||||
tpl_key = cand_f
|
||||
if tpl_key is None: return None
|
||||
template_fd: ast.FunctionDef* = self.Gen.ClassGenGeneric._find_generic_func_template(tpl_key)
|
||||
if template_fd is None: return None
|
||||
tp_names: list[str]* = self.Gen.ClassGenGeneric._find_generic_func_tp_params(pool, tpl_key)
|
||||
if tp_names is None: tp_names = template_fd.type_params
|
||||
if tp_names is None: return None
|
||||
tp_count: sizet = len(tp_names)
|
||||
if tp_count == 0: return None
|
||||
# ---- 汇总类型实参 ----
|
||||
type_args: list[str]* = None
|
||||
if explicit_slice is not None:
|
||||
type_args = self.Gen.CallGenCtor._extract_type_args_from_slice(pool, explicit_slice, trans._from_imports)
|
||||
if type_args is None or len(type_args) != tp_count:
|
||||
self.Gen.TypeGenErr.fatal_error(cl,
|
||||
f"泛型函数 '{tpl_name}' 显式类型实参个数不匹配(需要 {tp_count}):请写 {tpl_name}[类型1, 类型2](...)",
|
||||
"TypeError")
|
||||
return None
|
||||
else:
|
||||
# 隐式推断:按模板签名的形参位对齐(形参注解恰为 T 的那一位实参)
|
||||
ctx_args: list[str]* = self.Gen.CallGenCtor._infer_ctor_type_args_from_ctx(pool, trans, tpl_name, int(tp_count), cl)
|
||||
type_args = list[str](pool, 8)
|
||||
if type_args is None: return None
|
||||
tpi: sizet
|
||||
for tpi in range(tp_count):
|
||||
tp_name: str = tp_names.get(tpi)
|
||||
ta: str = None
|
||||
slot: int = self.Gen.ClassGenGeneric._find_generic_func_param_slot(template_fd, tp_name)
|
||||
if slot >= 0 and sizet(slot) < can:
|
||||
ta = self.Gen.ClassGenGeneric._infer_generic_func_type_arg(pool, cargs.get(sizet(slot)), tpl_name, trans)
|
||||
if ta is None and slot >= 0:
|
||||
# 关键字实参:按模板形参名定位(位置优先,槽位已被位置实参占用则 -1)
|
||||
kwi: int = self._generic_func_kw_arg_index(template_fd, slot, cl.keywords, int(can))
|
||||
if kwi >= 0:
|
||||
kwn: rawptr[ast.Keyword] = rawptr[ast.Keyword](cl.keywords.get(sizet(kwi)))
|
||||
if kwn is not None and kwn.value is not None:
|
||||
ta = self.Gen.ClassGenGeneric._infer_generic_func_type_arg(pool, kwn.value, tpl_name, trans)
|
||||
if ta is None and ctx_args is not None and sizet(tpi) < len(ctx_args):
|
||||
ta = ctx_args.get(tpi)
|
||||
if ta is None:
|
||||
self.Gen.TypeGenErr.fatal_error(cl,
|
||||
f"无法从实参推断泛型函数 '{tpl_name}' 的第 {tpi + 1} 个类型实参(类型形参 {tp_name});"
|
||||
f"禁止静默默认 int。请显式标注如 {tpl_name}[类型](...) 或为对应实参标注类型",
|
||||
"TypeError")
|
||||
return None
|
||||
type_args.append(ta)
|
||||
# ---- 单态化 ----
|
||||
spec_name: str = self.Gen.ClassGenGeneric._specialize_generic_function(trans, tpl_key, type_args)
|
||||
if spec_name is None:
|
||||
self.Gen.TypeGenErr.fatal_error(cl, f"泛型函数 '{tpl_name}' 特化失败", "TypeError")
|
||||
return None
|
||||
# ---- 发射调用 ----
|
||||
return self._emit_generic_func_call(pool, builder, mod, trans, cl, spec_name, cargs, can, hit_box)
|
||||
|
||||
def _generic_func_key(self, pool: memhub.MemBuddy*,
|
||||
sha1: str, name: str) -> str:
|
||||
"""构造泛型函数模板键 "{sha1}.{name}"(新缓冲区)"""
|
||||
if sha1 is None or name is None: return None
|
||||
klen: sizet = string.strlen(sha1) + string.strlen(name) + 2
|
||||
kbuf: str = pool.alloc(klen)
|
||||
if kbuf is None: return None
|
||||
viperlib.snprintf(kbuf, klen, "%s.%s", sha1, name)
|
||||
return kbuf
|
||||
|
||||
def _generic_func_kw_arg_index(self, template_fd: ast.FunctionDef*,
|
||||
slot: int, keywords: list[ast.AST*]*,
|
||||
pos_count: int) -> int:
|
||||
"""类型形参对应的形参槽位由关键字实参传入时,返回 keywords 下标;否则 -1
|
||||
|
||||
slot 已被位置实参占用(slot < pos_count)时返回 -1(位置优先)。
|
||||
"""
|
||||
if template_fd is None or keywords is None: return -1
|
||||
if slot < pos_count: return -1
|
||||
if template_fd.args is None or template_fd.args.kind() != ast.ASTKind.Arguments: return -1
|
||||
ags: ast.Arguments* = ast.Arguments*(template_fd.args)
|
||||
if ags.args is None: return -1
|
||||
alist: list[ast.AST*]* = ags.args
|
||||
if sizet(slot) >= len(alist): return -1
|
||||
pa: ast.AST* = alist.get(sizet(slot))
|
||||
if pa is None or pa.kind() != ast.ASTKind.Arg: return -1
|
||||
ag: ast.Arg* = ast.Arg*(pa)
|
||||
if ag.arg is None: return -1
|
||||
kn: sizet = len(keywords)
|
||||
ki: sizet
|
||||
for ki in range(kn):
|
||||
kw: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(ki))
|
||||
if kw is None or kw.arg is None:
|
||||
continue
|
||||
if string.strcmp(kw.arg, ag.arg) == 0:
|
||||
return int(ki)
|
||||
return -1
|
||||
|
||||
def _emit_generic_func_call(self, pool: memhub.MemBuddy*,
|
||||
builder: llvmlite.IRBuilder*,
|
||||
mod: llvmlite.LLVMModule*,
|
||||
trans: HT.Translator*,
|
||||
cl: ast.Call*,
|
||||
spec_name: str,
|
||||
cargs: list[ast.AST*]*,
|
||||
can: sizet,
|
||||
hit_box: t.CPtr = None) -> llvmlite.Value*:
|
||||
"""发射对特化函数的调用(按特化 define/declare 的形参类型 coerce 实参)
|
||||
|
||||
泛型函数调用只支持位置实参(关键字实参/默认参数缺口 fail-fast,不静默)。
|
||||
"""
|
||||
func: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, spec_name)
|
||||
if func is None:
|
||||
self.Gen.TypeGenErr.fatal_error(cl,
|
||||
f"泛型函数特化符号未在当前模块注册: {spec_name}", "InternalCompilerError")
|
||||
return None
|
||||
kw: list[ast.AST*]* = cl.keywords
|
||||
if kw is not None and len(kw) > 0:
|
||||
self.Gen.TypeGenErr.fatal_error(cl, "泛型函数调用暂不支持关键字实参,请改用位置实参", "TypeError")
|
||||
return None
|
||||
if hit_box is not None:
|
||||
hit_box[0] = 1
|
||||
param_count: int = 0
|
||||
pp: llvmlite.Param* = llvmlite.function_get_param_head(func)
|
||||
while pp is not None:
|
||||
param_count += 1
|
||||
pp = llvmlite.param_get_next(pp)
|
||||
if int(can) < param_count:
|
||||
self.Gen.TypeGenErr.fatal_error(cl,
|
||||
"泛型函数调用实参个数少于形参个数(默认参数暂不支持),请补齐实参", "TypeError")
|
||||
return None
|
||||
ret_ty: llvmlite.LLVMType* = llvmlite.function_get_ret_ty(func)
|
||||
head: llvmlite.Value* = None
|
||||
tail: llvmlite.Value* = None
|
||||
fp: llvmlite.Param* = llvmlite.function_get_param_head(func)
|
||||
ai: sizet = 0
|
||||
while ai < can:
|
||||
arg: ast.AST* = cargs.get(ai)
|
||||
fpty: llvmlite.LLVMType* = None
|
||||
if fp is not None:
|
||||
fpty = llvmlite.param_get_ty(fp)
|
||||
if arg is not None:
|
||||
av: llvmlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg, None, 0, trans, fpty, "形参")
|
||||
if av is not None:
|
||||
if fpty is not None:
|
||||
av = self.Gen.ExprGenBase.coerce_to_type(builder, av, fpty, arg, trans)
|
||||
av.Next = None
|
||||
if head is None:
|
||||
head = av
|
||||
else:
|
||||
tail.Next = av
|
||||
tail = av
|
||||
if fp is not None:
|
||||
fp = llvmlite.param_get_next(fp)
|
||||
ai += 1
|
||||
return llvmlite.build_call(builder, func, head, int(can), ret_ty, 0)
|
||||
|
||||
def _tc_h1_super_ctraits(self, pool: memhub.MemBuddy*,
|
||||
builder: llvmlite.IRBuilder*,
|
||||
mod: llvmlite.LLVMModule*,
|
||||
|
||||
@@ -112,6 +112,22 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
can: sizet = 0
|
||||
if cargs is not None:
|
||||
can = len(cargs)
|
||||
# ---- 泛型函数调用(PEP 695 def f[T])优先拦截 ----
|
||||
# 泛型函数模板在定义处不发射普通函数(见 FuncGenDef 守护),必须在此
|
||||
# 之前完成类型实参推断 + 单态化。命中即返回(含 void 返回:hit_box=1
|
||||
# 区分"已处理无返回值"与"未命中")。未命中返回 None 继续既有分派。
|
||||
h0_hit: t.CPtr = stdlib.malloc(4)
|
||||
if h0_hit is not None:
|
||||
h0_hit[0] = 0
|
||||
_tc_h0_generic_func_res: llvmlite.Value* = self.Gen.CallGenDispatch._tc_h0_generic_func(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, h0_hit)
|
||||
h0_hit_val: int = 0
|
||||
if h0_hit is not None:
|
||||
h0_hit_val = h0_hit[0]
|
||||
stdlib.free(h0_hit)
|
||||
if _tc_h0_generic_func_res is not None:
|
||||
return _tc_h0_generic_func_res
|
||||
if h0_hit_val != 0:
|
||||
return None
|
||||
# super()/ctraits 检测:void 方法(如 __init__)命中后 build_call 返回
|
||||
# None 属预期(void call 无 SSA 值),必须用 hit_box 区分"命中已处理"
|
||||
# 与"未命中",否则 None 被误判继续主路径 → 内层 Call(super) 当裸名
|
||||
|
||||
@@ -1237,6 +1237,11 @@ novirtual class ClassGenBase:
|
||||
self.GenericClassSha1s = None
|
||||
self.GenericClassFiles = None
|
||||
self.GenericClassTpParams = None
|
||||
self.GenericFuncKeys = None
|
||||
self.GenericFuncNodes = None
|
||||
self.GenericFuncSha1s = None
|
||||
self.GenericFuncFiles = None
|
||||
self.GenericFuncTpParams = None
|
||||
self.VtFullNames = None
|
||||
self.VtMethodNames = None
|
||||
self.VtParentSha1s = None
|
||||
|
||||
@@ -11,6 +11,7 @@ import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
from . import ClassGenBase
|
||||
import lib.Stub.StubMerger.StubMergerStore as StubMergerStore
|
||||
import lib.core.Gen.Type.TypeSpec as TSpec
|
||||
|
||||
|
||||
# 泛型特化递归深度上限(泛型循环套用防护)
|
||||
@@ -144,6 +145,515 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase):
|
||||
string.strcat(buf, " ")
|
||||
string.strcat(buf, tp_name)
|
||||
return buf
|
||||
|
||||
# ============================================================
|
||||
# 泛型函数模板(PEP 695 def f[T](...) / def pair[T1,T2](...))
|
||||
#
|
||||
# 范式照搬同文件泛型类模板(_register_generic_template / _find_generic_template
|
||||
# / _specialize_generic_class):注册表落永久池、tp 名 stdlib 深拷贝、特化名
|
||||
# 复用 _mangle_generic_class_name 做唯一规范化、去重复用 SpecKeys/SpecNames。
|
||||
# 差异:
|
||||
# 1) 节点是 FunctionDef;表键含定义模块 SHA1("{sha1}.{fname}",避免跨模块
|
||||
# 同名函数串味——函数名重复远多于类名);
|
||||
# 2) 新增调用点推断(显式下标 / 按签名形参位 / 返回值注解上下文);
|
||||
# 3) 特化定位是"发射 define"(translate_function_def);全局缓存命中而当前
|
||||
# 模块无该符号时补 declare(_ensure_generic_func_declare)。
|
||||
# ============================================================
|
||||
def _is_generic_function(self, tp: list[str]*) -> int:
|
||||
"""检查 FunctionDef 是否有类型参数(泛型函数),返回 1=是 / 0=否"""
|
||||
if tp is None: return 0
|
||||
return 1
|
||||
|
||||
def _register_generic_func_template(self, pool: memhub.MemBuddy*,
|
||||
fd: ast.FunctionDef*,
|
||||
module_sha1: str) -> None:
|
||||
"""注册泛型函数模板(键 "{module_sha1}.{函数名}" + 节点 + tp 名)
|
||||
|
||||
表体一律落永久池(同 _register_generic_template 的池归属修复):扫描
|
||||
预注册路径传永久池,但 forward_declare 兜底路径传的是会被 reset 的
|
||||
trans.Pool,故键/SHA1/来源文件串统一深拷贝进永久池,防跨 mark 悬空。
|
||||
"""
|
||||
if fd is None or fd.name is None or module_sha1 is None: return
|
||||
perm: memhub.MemBuddy* = CompilerFactory.factory.PermPool
|
||||
table_pool: memhub.MemBuddy* = perm
|
||||
if table_pool is None:
|
||||
table_pool = pool
|
||||
if self.GenericFuncKeys is None:
|
||||
self.GenericFuncKeys = list[str](table_pool, 8)
|
||||
self.GenericFuncNodes = list[ast.FunctionDef*](table_pool, 8)
|
||||
self.GenericFuncSha1s = list[str](table_pool, 8)
|
||||
self.GenericFuncFiles = list[str](table_pool, 8)
|
||||
if self.GenericFuncTpParams is None:
|
||||
if perm is None: return
|
||||
self.GenericFuncTpParams = perm.alloc(GENERIC_TEMPLATE_MAX * 8)
|
||||
if self.GenericFuncTpParams is None: return
|
||||
string.memset(self.GenericFuncTpParams, 0, GENERIC_TEMPLATE_MAX * 8)
|
||||
# 键 = "{sha1}.{name}"(新缓冲区拼接,避免原地 strcat 溢出)
|
||||
key_len: sizet = string.strlen(module_sha1) + string.strlen(fd.name) + 2
|
||||
key_buf: str = table_pool.alloc(key_len)
|
||||
if key_buf is None: return
|
||||
viperlib.snprintf(key_buf, key_len, "%s.%s", module_sha1, fd.name)
|
||||
keys_local: list[str]* = self.GenericFuncKeys
|
||||
kn: sizet = len(keys_local)
|
||||
ki: sizet
|
||||
for ki in range(kn):
|
||||
knm: str = keys_local.get(ki)
|
||||
if knm is not None and string.strcmp(knm, key_buf) == 0: return
|
||||
tp_names_buf: str = self._copy_type_params_stdlib(fd.type_params)
|
||||
self.GenericFuncKeys.append(self._dup_perm_str(key_buf))
|
||||
self.GenericFuncNodes.append(fd)
|
||||
self.GenericFuncSha1s.append(self._dup_perm_str(module_sha1))
|
||||
self.GenericFuncFiles.append(self._dup_perm_str(self.Gen.TypeGenResolve.get_current_file()))
|
||||
if tp_names_buf is not None and kn < GENERIC_TEMPLATE_MAX:
|
||||
self.GenericFuncTpParams[kn] = sizet(tp_names_buf)
|
||||
|
||||
def _find_generic_func_template(self, key: str) -> ast.FunctionDef*:
|
||||
"""按 "{sha1}.{fname}" 键查找泛型函数模板节点,未找到返回 None"""
|
||||
if self.GenericFuncKeys is None or key is None:
|
||||
return None
|
||||
keys_local: list[str]* = self.GenericFuncKeys
|
||||
nodes_local: list[ast.FunctionDef*]* = self.GenericFuncNodes
|
||||
kn: sizet = len(keys_local)
|
||||
i: sizet
|
||||
for i in range(kn):
|
||||
knm: str = keys_local.get(i)
|
||||
if knm is not None and string.strcmp(knm, key) == 0:
|
||||
return nodes_local.get(i)
|
||||
return None
|
||||
|
||||
def _find_generic_func_template_sha1(self, key: str) -> str:
|
||||
"""按键查找泛型函数模板的来源模块 SHA1,未找到返回 None"""
|
||||
if self.GenericFuncKeys is None or key is None:
|
||||
return None
|
||||
keys_local: list[str]* = self.GenericFuncKeys
|
||||
sha1s_local: list[str]* = self.GenericFuncSha1s
|
||||
kn: sizet = len(keys_local)
|
||||
i: sizet
|
||||
for i in range(kn):
|
||||
knm: str = keys_local.get(i)
|
||||
if knm is not None and string.strcmp(knm, key) == 0:
|
||||
return sha1s_local.get(i)
|
||||
return None
|
||||
|
||||
def _find_generic_func_template_file(self, key: str) -> str:
|
||||
"""按键查找泛型函数模板来源文件路径(错误定位用),未找到返回 None"""
|
||||
if self.GenericFuncKeys is None or key is None:
|
||||
return None
|
||||
keys_local: list[str]* = self.GenericFuncKeys
|
||||
files_local: list[str]* = self.GenericFuncFiles
|
||||
kn: sizet = len(keys_local)
|
||||
i: sizet
|
||||
for i in range(kn):
|
||||
knm: str = keys_local.get(i)
|
||||
if knm is not None and string.strcmp(knm, key) == 0:
|
||||
return files_local.get(i)
|
||||
return None
|
||||
|
||||
def _find_generic_func_tp_params(self, pool: memhub.MemBuddy*,
|
||||
key: str) -> list[str]*:
|
||||
"""查找泛型函数模板的类型参数名列表,未找到返回 None
|
||||
|
||||
从注册时深拷贝的 stdlib 缓冲区重建当前 pool 的 list[str](特化期间
|
||||
pool 有效)。逐字节解析逻辑与 _find_generic_template_tp_params 一致:
|
||||
空格分隔;elem_size 必须传 8(str 指针 8 字节)。
|
||||
"""
|
||||
if self.GenericFuncKeys is None or key is None \
|
||||
or self.GenericFuncTpParams is None:
|
||||
return None
|
||||
keys_local: list[str]* = self.GenericFuncKeys
|
||||
kn: sizet = len(keys_local)
|
||||
i: sizet
|
||||
for i in range(kn):
|
||||
knm: str = keys_local.get(i)
|
||||
if knm is not None and string.strcmp(knm, key) == 0:
|
||||
if i >= GENERIC_TEMPLATE_MAX:
|
||||
return None
|
||||
buf_addr: sizet = self.GenericFuncTpParams[i]
|
||||
if buf_addr == 0:
|
||||
return None
|
||||
buf_tp: str = rawptr(buf_addr)
|
||||
tp_list: list[str]* = list[str](pool, 8)
|
||||
if tp_list is None:
|
||||
return None
|
||||
seg_start: sizet = 0
|
||||
pos: sizet = 0
|
||||
blen: sizet = string.strlen(buf_tp)
|
||||
while pos <= blen:
|
||||
if buf_tp[pos] == ' ' or buf_tp[pos] == '\0':
|
||||
seg_len: sizet = pos - seg_start
|
||||
if seg_len > 0:
|
||||
seg: str = pool.alloc(seg_len + 1)
|
||||
if seg is not None:
|
||||
string.strncpy(seg, buf_tp + seg_start, seg_len)
|
||||
seg[seg_len] = '\0'
|
||||
tp_list.append(seg)
|
||||
seg_start = pos + 1
|
||||
pos += 1
|
||||
return tp_list
|
||||
return None
|
||||
|
||||
def _find_generic_func_param_slot(self, fd: ast.FunctionDef*,
|
||||
tp_name: str) -> int:
|
||||
"""函数模板形参列表中注解恰为类型形参 tp_name 的形参槽位(0 起)
|
||||
|
||||
module 级函数无 self,槽位即位置实参下标;找不到返回 -1。判据复用
|
||||
CallGenCtor._annotation_refers_type_param(只认 T 与 T|X,不认 Subscript
|
||||
—— 实参是容器而非 T 本身,不能作为 T 的推断来源)。
|
||||
"""
|
||||
if fd is None or tp_name is None or fd.args is None: return -1
|
||||
if fd.args.kind() != ast.ASTKind.Arguments: return -1
|
||||
ags: ast.Arguments* = ast.Arguments*(fd.args)
|
||||
if ags.args is None: return -1
|
||||
alist: list[ast.AST*]* = ags.args
|
||||
an: sizet = len(alist)
|
||||
ai: sizet
|
||||
for ai in range(an):
|
||||
pa: ast.AST* = alist.get(ai)
|
||||
if pa is None or pa.kind() != ast.ASTKind.Arg: continue
|
||||
ag: ast.Arg* = ast.Arg*(pa)
|
||||
if self.Gen.CallGenCtor._annotation_refers_type_param(ag.annotation, tp_name) != 0:
|
||||
return int(ai)
|
||||
return -1
|
||||
|
||||
def _infer_generic_func_type_arg(self, pool: memhub.MemBuddy*,
|
||||
arg_node: ast.AST*,
|
||||
func_name: str,
|
||||
trans: HT.Translator*) -> str:
|
||||
"""从调用实参 AST 推断泛型函数的类型实参名(不发射 IR,非 fatal)
|
||||
|
||||
与 CallGenCtor._infer_generic_ctor_type_arg 同源,但函数调用实参可以是
|
||||
任意表达式(普通函数调用/c.Addr 等):推断不出返回 None,由调用方汇总
|
||||
全部来源后统一 fail-fast(不在此 fail-fast,避免"某一实参推不出"就误杀
|
||||
本来可由其它来源确定的类型形参)。
|
||||
"""
|
||||
if arg_node is None: return None
|
||||
k: int = arg_node.kind()
|
||||
if k == ast.ASTKind.Constant:
|
||||
cn: ast.Constant* = ast.Constant*(arg_node)
|
||||
if cn.const_kind == ast.CONST_FLOAT: return "double"
|
||||
if cn.const_kind == ast.CONST_CHAR: return "char"
|
||||
if cn.const_kind == ast.CONST_STR: return "str"
|
||||
return "int"
|
||||
# 一元正负号常量(clamp(-3, ...)):类型由操作数决定
|
||||
if k == ast.ASTKind.UnaryOp:
|
||||
uo: ast.UnaryOp* = ast.UnaryOp*(arg_node)
|
||||
return self._infer_generic_func_type_arg(pool, uo.operand, func_name, trans)
|
||||
if k == ast.ASTKind.Name:
|
||||
nm: ast.Name* = ast.Name*(arg_node)
|
||||
if nm.id is not None and trans is not None:
|
||||
ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id)
|
||||
if ve is not None:
|
||||
cn_nm: str = self.Gen.VarGen.var_annot_class_name(ve)
|
||||
pl: int = 0
|
||||
if ve.Spec is not None:
|
||||
pl = ve.Spec.PtrLevel
|
||||
if cn_nm is not None:
|
||||
return self.Gen.CallGenCtor._ptr_layer_type_arg(pool, cn_nm, pl, trans._from_imports)
|
||||
# 内建标量(str/char/bytes/bool/float/double 被
|
||||
# extract_class_name_from_annotation 跳过 ⇒ SourceName 为 None):
|
||||
# 从 Spec 的 LLVM 形态反推可解析的类型名(double/float/int/char/bool)。
|
||||
return self._infer_scalar_type_name_from_spec(pool, ve.Spec)
|
||||
return None
|
||||
if k == ast.ASTKind.Attribute:
|
||||
cn_at: str = self.Gen.ExprGenAttr._resolve_attr_field_class(pool, trans, arg_node)
|
||||
pl_at: int = 0
|
||||
fe: GenTypes.FieldEntry* = self.Gen.ExprGenAttr._resolve_attr_field_entry(pool, trans, arg_node)
|
||||
if fe is not None and fe.Spec is not None:
|
||||
pl_at = fe.Spec.PtrLevel
|
||||
fi: str = None
|
||||
if trans is not None:
|
||||
fi = trans._from_imports
|
||||
if cn_at is not None:
|
||||
return self.Gen.CallGenCtor._ptr_layer_type_arg(pool, cn_at, pl_at, fi)
|
||||
# 内建标量字段:同 Name 分支的 Spec 反推
|
||||
if fe is not None:
|
||||
return self._infer_scalar_type_name_from_spec(pool, fe.Spec)
|
||||
return None
|
||||
if k == ast.ASTKind.Call:
|
||||
cl_f: ast.Call* = ast.Call*(arg_node)
|
||||
if cl_f.func is not None:
|
||||
fn_id: str = None
|
||||
if cl_f.func.kind() == ast.ASTKind.Name:
|
||||
fn_nm: ast.Name* = ast.Name*(cl_f.func)
|
||||
fn_id = fn_nm.id
|
||||
elif cl_f.func.kind() == ast.ASTKind.Attribute:
|
||||
fn_at: ast.Attribute* = ast.Attribute*(cl_f.func)
|
||||
fn_id = fn_at.attr
|
||||
if fn_id is not None:
|
||||
if string.strcmp(fn_id, "float") == 0 or string.strcmp(fn_id, "double") == 0 \
|
||||
or string.strstr(fn_id, "Float") is not None or string.strstr(fn_id, "Double") is not None:
|
||||
return "double"
|
||||
if string.strcmp(fn_id, "char") == 0 or string.strstr(fn_id, "Char") is not None:
|
||||
return "char"
|
||||
if string.strcmp(fn_id, "int") == 0 or string.strstr(fn_id, "Int") is not None \
|
||||
or string.strstr(fn_id, "UInt") is not None or string.strstr(fn_id, "Short") is not None \
|
||||
or string.strstr(fn_id, "Long") is not None:
|
||||
return "int"
|
||||
return None
|
||||
return None
|
||||
|
||||
def _infer_scalar_type_name_from_spec(self, pool: memhub.MemBuddy*,
|
||||
sp: TSpec.TypeSpec*) -> str:
|
||||
"""从变量的 TypeSpec 反推可解析的内建标量类型名
|
||||
|
||||
仅覆盖 extract_class_name_from_annotation 会跳过的内建标量
|
||||
(str/char/bytes/bool/float/double 的 SourceName 为 None):按 LLVM
|
||||
形态映射为源码可解析名(double/float/int/char/bool)。指针/结构体返回
|
||||
None(交由注解来源名路径处理;此处不做猜测,避免错特化)。
|
||||
"""
|
||||
if pool is None or sp is None: return None
|
||||
buf: str = pool.alloc(32)
|
||||
if buf is None: return None
|
||||
buf[0] = '\0'
|
||||
if TSpec.SpecToLLVMText(sp, buf, 32) == 0:
|
||||
return None
|
||||
if string.strcmp(buf, "double") == 0: return "double"
|
||||
if string.strcmp(buf, "float") == 0: return "float"
|
||||
if string.strcmp(buf, "half") == 0: return "float"
|
||||
if string.strcmp(buf, "i1") == 0: return "bool"
|
||||
if string.strcmp(buf, "i8") == 0: return "char"
|
||||
if string.strcmp(buf, "i16") == 0: return "int"
|
||||
if string.strcmp(buf, "i32") == 0: return "int"
|
||||
if string.strcmp(buf, "i64") == 0: return "int"
|
||||
return None
|
||||
|
||||
def _clone_funcdef_for_spec(self, pool: memhub.MemBuddy*,
|
||||
fd: ast.FunctionDef*,
|
||||
spec_base: str,
|
||||
tp_names: list[str]*,
|
||||
type_args: list[str]*) -> ast.FunctionDef*:
|
||||
"""拷贝 FunctionDef 用于泛型函数特化
|
||||
|
||||
- 函数名替换为 spec_base(如 "f[int,double]")
|
||||
- type_params 清空(特化后非泛型,避免 translate_function_def 再入模板分支)
|
||||
- 形参/返回注解经 _clone_annotation 替换 T 为具体类型
|
||||
- 函数体直接引用原始节点(T 在体内的用法由 generic_context 处理,与
|
||||
_clone_classdef_for_spec 对方法体的处理同口径)
|
||||
"""
|
||||
if fd is None: return None
|
||||
new_args: ast.AST* = self._clone_arguments(pool, fd.args, tp_names, type_args)
|
||||
new_returns: ast.AST* = self._clone_annotation(pool, fd.returns, tp_names, type_args)
|
||||
new_fd: ast.FunctionDef* = ast.FunctionDef(pool, spec_base, new_args,
|
||||
fd.decorator_list, new_returns, 0)
|
||||
if fd.children is not None:
|
||||
body: list[ast.AST*]* = fd.children
|
||||
bn: sizet = len(body)
|
||||
bi: sizet
|
||||
for bi in range(bn):
|
||||
stmt: ast.AST* = body.get(bi)
|
||||
if stmt is not None:
|
||||
new_fd.append(stmt)
|
||||
return new_fd
|
||||
|
||||
def _ensure_generic_func_declare(self, trans: HT.Translator*,
|
||||
pool: memhub.MemBuddy*,
|
||||
spec_name: str,
|
||||
template_key: str,
|
||||
tp_names: list[str]*,
|
||||
type_args: list[str]*) -> llvmlite.Function*:
|
||||
"""确保当前模块存在特化函数的 declare(跨模块缓存命中时用)
|
||||
|
||||
特化 define 全局只发射一份(SpecKeys 去重);命中缓存的调用方模块里没有
|
||||
该符号的 LLVM 声明,按"模板签名 + 实参"在本模块补一条 declare。返回该
|
||||
declare;失败返回 None。
|
||||
"""
|
||||
if trans is None or pool is None or spec_name is None: return None
|
||||
mod: llvmlite.LLVMModule* = trans.Module
|
||||
if mod is None: return None
|
||||
existing: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(mod, spec_name)
|
||||
if existing is not None: return existing
|
||||
template_fd: ast.FunctionDef* = self._find_generic_func_template(template_key)
|
||||
if template_fd is None: return None
|
||||
template_sha1: str = self._find_generic_func_template_sha1(template_key)
|
||||
if template_sha1 is None: return None
|
||||
spec_base: str = self._mangle_generic_class_name(pool, template_fd.name, type_args, trans._from_imports)
|
||||
if spec_base is None: return None
|
||||
spec_fd: ast.FunctionDef* = self._clone_funcdef_for_spec(pool, template_fd, spec_base, tp_names, type_args)
|
||||
if spec_fd is None: return None
|
||||
i32_ty: llvmlite.LLVMType* = llvmlite.Int32(pool)
|
||||
saved_ms: str = trans.ModuleSha1
|
||||
saved_imp: str = trans._imported_modules
|
||||
saved_gtpn: list[str]* = trans.GenericTypeParamNames
|
||||
saved_gta: list[str]* = trans.GenericTypeArgs
|
||||
trans.ModuleSha1 = template_sha1
|
||||
self._merge_template_imports(trans, template_sha1)
|
||||
trans.GenericTypeParamNames = tp_names
|
||||
trans.GenericTypeArgs = type_args
|
||||
self.Gen.TypeGenBase.set_generic_context(tp_names, type_args)
|
||||
saved_cur: str = self.Gen.TypeGenResolve.get_current_file()
|
||||
tpl_file: str = self._find_generic_func_template_file(template_key)
|
||||
if tpl_file is not None:
|
||||
self.Gen.TypeGenResolve.set_current_file(tpl_file)
|
||||
ret_ty: llvmlite.LLVMType* = None
|
||||
if spec_fd.returns is not None:
|
||||
ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, spec_fd.returns, trans._imported_modules, trans._from_imports, trans, 0)
|
||||
if ret_ty is None:
|
||||
ret_ty = i32_ty
|
||||
func: llvmlite.Function* = llvmlite.create_declare(pool, mod, spec_name, ret_ty)
|
||||
if func is not None and spec_fd.args is not None and spec_fd.args.kind() == ast.ASTKind.Arguments:
|
||||
ags: ast.Arguments* = ast.Arguments*(spec_fd.args)
|
||||
if ags.args is not None:
|
||||
alist: list[ast.AST*]* = ags.args
|
||||
an: sizet = len(alist)
|
||||
ai: sizet
|
||||
for ai in range(an):
|
||||
pa: ast.AST* = alist.get(ai)
|
||||
if pa is None or pa.kind() != ast.ASTKind.Arg: continue
|
||||
arg: ast.Arg* = ast.Arg*(pa)
|
||||
if arg.arg is None: continue
|
||||
param_ty: llvmlite.LLVMType* = i32_ty
|
||||
if arg.annotation is not None:
|
||||
resolved: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, trans._imported_modules, trans._from_imports, trans, 0)
|
||||
if resolved is not None:
|
||||
match resolved:
|
||||
case llvmlite.LLVMType.Struct(_, _, _):
|
||||
param_ty = llvmlite.Ptr(pool, resolved)
|
||||
case llvmlite.LLVMType.Array(aelem_ty, _):
|
||||
param_ty = llvmlite.Ptr(pool, aelem_ty)
|
||||
case _:
|
||||
param_ty = resolved
|
||||
pname: str = pool.alloc(32)
|
||||
if pname is not None:
|
||||
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
|
||||
llvmlite.add_param(pool, func, param_ty, pname)
|
||||
if tpl_file is not None:
|
||||
self.Gen.TypeGenResolve.set_current_file(saved_cur)
|
||||
trans.ModuleSha1 = saved_ms
|
||||
trans._imported_modules = saved_imp
|
||||
trans.GenericTypeParamNames = saved_gtpn
|
||||
trans.GenericTypeArgs = saved_gta
|
||||
self.Gen.TypeGenBase.clear_generic_context()
|
||||
return func
|
||||
|
||||
def _specialize_generic_function(self, trans: HT.Translator*,
|
||||
template_key: str,
|
||||
type_args: list[str]*) -> str:
|
||||
"""特化泛型函数,返回特化函数 mangled 名("{模板sha1}.{f}[args]")
|
||||
|
||||
1. 查找模板;2. 逐实参规范化生成特化名;3. SpecKeys 去重
|
||||
(命中且本模块无该符号 → 补 declare);4. 克隆模板 + generic_context
|
||||
翻译发射 define(translate_function_def),命名/签名与调用点一致。
|
||||
"""
|
||||
if trans is None or template_key is None or type_args is None:
|
||||
return None
|
||||
self.GenericSpecDepth += 1
|
||||
if self.GenericSpecDepth > GENERIC_SPEC_MAX_DEPTH:
|
||||
self.Gen.TypeGenErr.fatal_error(None, "泛型函数特化递归过深(疑似泛型循环套用)", "InternalCompilerError")
|
||||
pool: memhub.MemBuddy* = trans.Pool
|
||||
template_fd: ast.FunctionDef* = self._find_generic_func_template(template_key)
|
||||
if template_fd is None:
|
||||
self.GenericSpecDepth -= 1
|
||||
return None
|
||||
template_sha1: str = self._find_generic_func_template_sha1(template_key)
|
||||
if template_sha1 is None:
|
||||
self.GenericSpecDepth -= 1
|
||||
return None
|
||||
# 防御:泛型上下文内收集的实参若残留未替换的类型形参名(如 "T"),
|
||||
# 统一替换为具体类型名(嵌套特化:泛型函数体内再调泛型函数)。
|
||||
ta_cnt_g: sizet = len(type_args)
|
||||
ta_i_g: sizet
|
||||
for ta_i_g in range(ta_cnt_g):
|
||||
ta_raw_g: str = type_args.get(ta_i_g)
|
||||
if ta_raw_g is not None:
|
||||
ta_rsv_g: str = self.Gen.TypeGenBase.resolve_generic_type_name(ta_raw_g)
|
||||
if ta_rsv_g is not None and string.strcmp(ta_raw_g, ta_rsv_g) != 0:
|
||||
type_args.set(ta_i_g, ta_rsv_g)
|
||||
tp_names: list[str]* = self._find_generic_func_tp_params(pool, template_key)
|
||||
if tp_names is None:
|
||||
tp_names = template_fd.type_params
|
||||
if tp_names is None:
|
||||
self.GenericSpecDepth -= 1
|
||||
return None
|
||||
if len(tp_names) != len(type_args):
|
||||
err_tp: str = pool.alloc(256)
|
||||
if err_tp is not None:
|
||||
viperlib.snprintf(err_tp, 256,
|
||||
"泛型函数 '%s' 类型实参个数不匹配(需要 %d,给定 %d)",
|
||||
template_fd.name, len(tp_names), len(type_args))
|
||||
self.Gen.TypeGenErr.fatal_error(None, err_tp, "TypeError")
|
||||
self.GenericSpecDepth -= 1
|
||||
return None
|
||||
# CExport/CExtern/State 存储标记的泛型函数不支持(特化名会绕过裸名导出语义)
|
||||
if template_fd.returns is not None:
|
||||
if self.Gen.TypeGenErr.has_decorator_marker(template_fd.returns, "CExport", 0) != 0 \
|
||||
or self.Gen.TypeGenErr.has_decorator_marker(template_fd.returns, "CExtern", 0) != 0 \
|
||||
or self.Gen.TypeGenErr.has_decorator_marker(template_fd.returns, "State", 0) != 0:
|
||||
self.Gen.TypeGenErr.fatal_error(template_fd, "泛型函数暂不支持 t.CExport/t.CExtern/t.State 存储标记", "TypeError")
|
||||
# 生成特化名(唯一生成器内部逐实参规范化,裸名/带前缀在此收敛为同一名)
|
||||
spec_base: str = self._mangle_generic_class_name(pool, template_fd.name, type_args, trans._from_imports)
|
||||
if spec_base is None:
|
||||
self.GenericSpecDepth -= 1
|
||||
return None
|
||||
spec_name: str = self.Gen.FuncGenBase._mangle_name_with_sha1(template_sha1, spec_base)
|
||||
# spec_key 用「模板键 + 归一化后的特化基名」构造:与 spec_name 一一对应
|
||||
# (都用 spec_base),避免原始实参书写差异(裸名/带前缀)导致同一特化名
|
||||
# 算出两个缓存键 → 重复发射同名 define。含模板键(带 SHA1)故与泛型类
|
||||
# 缓存键(裸类名<...>)不冲突。
|
||||
spec_key: str = pool.alloc(string.strlen(template_key) + string.strlen(spec_base) + 2)
|
||||
if spec_key is None:
|
||||
self.GenericSpecDepth -= 1
|
||||
return None
|
||||
spec_key[0] = '\0'
|
||||
string.strcat(spec_key, template_key)
|
||||
string.strcat(spec_key, "#")
|
||||
string.strcat(spec_key, spec_base)
|
||||
cached: str = self._find_cached_spec(spec_key)
|
||||
if cached is not None:
|
||||
self._ensure_generic_func_declare(trans, pool, spec_name, template_key, tp_names, type_args)
|
||||
self.GenericSpecDepth -= 1
|
||||
return cached
|
||||
# 本模块已存在同名 define(多遍重译/同 pass 重复):直接复用,禁止再克隆
|
||||
# 发射(translate_function_def 对已 define 的同名会新建 → 模块内重复符号)。
|
||||
# 仅 declare(跨模块补的声明)时继续走发射路径(translate_function_def 会
|
||||
# 复用该 declare 并补函数体转 define)。
|
||||
existing_fn: llvmlite.Function* = self.Gen.CallGenBase.find_func_in_module(trans.Module, spec_name)
|
||||
if existing_fn is not None and existing_fn.IsDeclared == 0:
|
||||
self._cache_spec(pool, spec_key, spec_name)
|
||||
self.GenericSpecDepth -= 1
|
||||
return spec_name
|
||||
# 克隆 + 上下文翻译发射 define
|
||||
spec_fd: ast.FunctionDef* = self._clone_funcdef_for_spec(pool, template_fd, spec_base, tp_names, type_args)
|
||||
if spec_fd is None:
|
||||
self.GenericSpecDepth -= 1
|
||||
return None
|
||||
# 预注册缓存(防止递归特化)
|
||||
self._cache_spec(pool, spec_key, spec_name)
|
||||
saved_ms: str = trans.ModuleSha1
|
||||
saved_imp: str = trans._imported_modules
|
||||
saved_gtpn: list[str]* = trans.GenericTypeParamNames
|
||||
saved_gta: list[str]* = trans.GenericTypeArgs
|
||||
# 类定义窗口必须与 ModuleSha1 一起保存/恢复(特化翻译内部会按模板模块
|
||||
# sha1 + 特化名刷新窗口,见 _specialize_generic_class 的"窗口同进同出")
|
||||
saved_def_mod: str = self.Gen.StructGen.CurDefModuleSha1
|
||||
saved_def_cls: str = self.Gen.StructGen.CurDefClassName
|
||||
# 切换 ModuleSha1 为模板定义模块的 SHA1:特化函数符号名 = {模板SHA1}.f[args],
|
||||
# 跨模块一致;同时并入模板模块 imports(模板体内跨模块调用可见)。
|
||||
trans.ModuleSha1 = template_sha1
|
||||
self._merge_template_imports(trans, template_sha1)
|
||||
trans.GenericTypeParamNames = tp_names
|
||||
trans.GenericTypeArgs = type_args
|
||||
self.Gen.TypeGenBase.set_generic_context(tp_names, type_args)
|
||||
# 错误定位:特化体 node.lineno 是模板文件行号,临时切换 CurrentFile 到
|
||||
# 模板文件并压 trace 帧(翻译完恢复)。
|
||||
saved_cur: str = self.Gen.TypeGenResolve.get_current_file()
|
||||
tpl_file: str = self._find_generic_func_template_file(template_key)
|
||||
if tpl_file is not None:
|
||||
self.Gen.TypeGenResolve.set_current_file(tpl_file)
|
||||
self.Gen.TypeGenBase.push_trace(tpl_file, template_fd.lineno)
|
||||
self.Gen.FuncGenDef.translate_function_def(trans, spec_fd)
|
||||
if tpl_file is not None:
|
||||
self.Gen.TypeGenBase.pop_trace()
|
||||
self.Gen.TypeGenResolve.set_current_file(saved_cur)
|
||||
trans.ModuleSha1 = saved_ms
|
||||
trans._imported_modules = saved_imp
|
||||
self.Gen.StructGen.CurDefModuleSha1 = saved_def_mod
|
||||
self.Gen.StructGen.CurDefClassName = saved_def_cls
|
||||
trans.GenericTypeParamNames = saved_gtpn
|
||||
trans.GenericTypeArgs = saved_gta
|
||||
self.Gen.TypeGenBase.clear_generic_context()
|
||||
self.GenericSpecDepth -= 1
|
||||
return spec_name
|
||||
|
||||
def _find_generic_template_tp_params(self, pool: memhub.MemBuddy*,
|
||||
class_name: str) -> list[str]*:
|
||||
"""查找泛型类模板的类型参数名列表,未找到返回 None
|
||||
|
||||
@@ -87,22 +87,16 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
|
||||
fd: ast.FunctionDef* = ast.FunctionDef*(child)
|
||||
if fd is None or fd.name is None: continue
|
||||
|
||||
# PEP 695 泛型函数(def f[T](...) -> T)按普通函数编译(TPV 无泛型
|
||||
# 函数特化机制,与 translate_function_def L678-691 一致):此处先设置
|
||||
# 类型参数上下文(T→"int"),使返回/参数注解中的 T 可解析,否则
|
||||
# forward_declare 阶段 "函数返回类型解析失败:注解不可解析"
|
||||
# (ExpandKeywordsTest fn ident[T] 根因)。所有退出路径(continue /
|
||||
# 循环末尾)必须 clear_generic_context,避免污染后续函数注解解析。
|
||||
tp_names_fd: list[str]* = None
|
||||
# PEP 695 泛型函数(def f[T](...) -> T)**不发射前向声明**:注册为
|
||||
# 泛型函数模板,调用点单态化时经 _specialize_generic_function 克隆
|
||||
# 发射特化 define({模板SHA1}.f[args])。旧行为(T 映射 int 兜底、
|
||||
# 按普通函数编译)已废弃——那会让 f(1.5) 被误编译成 int 版
|
||||
# (违反 D25「禁止静默默认 int」),且与特化路径的符号名冲突。
|
||||
# 与 translate_function_def 顶部同判据(幂等注册)。
|
||||
if fd.type_params is not None:
|
||||
tp_names_fd = fd.type_params
|
||||
tp_args_fd: list[str]* = list[str](pool, 8)
|
||||
if tp_args_fd is not None:
|
||||
tpn_fd: sizet = len(fd.type_params)
|
||||
tpi_fd: sizet = 0
|
||||
for tpi_fd in range(tpn_fd):
|
||||
tp_args_fd.append("int")
|
||||
self.Gen.TypeGenBase.set_generic_context(tp_names_fd, tp_args_fd)
|
||||
self.Gen.ClassGenGeneric._register_generic_func_template(pool, fd, trans.ModuleSha1)
|
||||
continue
|
||||
tp_names_fd: list[str]* = None
|
||||
|
||||
# 推断返回类型
|
||||
ret_ty: llvmlite.LLVMType* = None
|
||||
@@ -303,6 +297,13 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
|
||||
if fd is None or fd.name is None:
|
||||
return 0
|
||||
|
||||
# PEP 695 泛型函数模板不直接发射(与 forward_declare_functions 同口径):
|
||||
# 调用点单态化时由 ClassGenGeneric._specialize_generic_function 克隆发射
|
||||
# (克隆体的 type_params 已清空,不会落到此分支)。此处仅确保模板已注册。
|
||||
if fd.type_params is not None:
|
||||
self.Gen.ClassGenGeneric._register_generic_func_template(trans.Pool, fd, trans.ModuleSha1)
|
||||
return 0
|
||||
|
||||
# async def(TPV-M1 协程):FLAG_IS_ASYNC=1(includes/ast/stmts.vp L342-345,
|
||||
# 解析器把 async def 存为 FunctionDef 且 flags & 1)。
|
||||
# → 走 AsyncGenMixin 状态机翻译(create_<name>/resume_<name>),
|
||||
@@ -739,20 +740,9 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
|
||||
# 进入函数作用域(嵌套符号表)
|
||||
self.Gen.VarGen.enter_scope(trans.SymTab, FuncGenMixin.SCOPE_FUNCTION)
|
||||
|
||||
# PEP 695 泛型函数: def f[T](...) — 设置泛型上下文,类型参数映射到 "int" 兜底。
|
||||
# TPV 无泛型函数特化机制(类泛型走 _specialize_generic_class),泛型函数按普通
|
||||
# 函数编译;设置上下文使参数注解 T / 方法体中的 T(x) 转换可解析为 int。
|
||||
# (注意与类特化的 set_generic_context 一样是全局状态,需在退出作用域前清除。)
|
||||
tp_names_fn: list[str]* = None
|
||||
if fd.type_params is not None:
|
||||
tp_names_fn = fd.type_params
|
||||
tp_args_fn: list[str]* = list[str](pool, 8)
|
||||
if tp_args_fn is not None:
|
||||
tpn_fn: sizet = len(fd.type_params)
|
||||
tpi_fn: sizet = 0
|
||||
for tpi_fn in range(tpn_fn):
|
||||
tp_args_fn.append("int")
|
||||
self.Gen.TypeGenBase.set_generic_context(tp_names_fn, tp_args_fn)
|
||||
# 泛型函数模板在入口处已早返回(见本函数顶部);到此处 fd.type_params 恒为
|
||||
# None(特化克隆清空 type_params),泛型上下文由 _specialize_generic_function
|
||||
# 在调用 translate_function_def 前用具体类型实参设置。
|
||||
|
||||
# 为参数创建 alloca
|
||||
if args_node is not None:
|
||||
@@ -1043,8 +1033,6 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
|
||||
self.Gen.TypeGenErr.fatal_error(node, "函数流程掉出末尾但未显式 return", "TypeError")
|
||||
|
||||
# 恢复模块级作用域(退出函数作用域)
|
||||
if tp_names_fn is not None:
|
||||
self.Gen.TypeGenBase.clear_generic_context()
|
||||
self.Gen.VarGen.exit_scope(trans.SymTab)
|
||||
trans._cur_func = old_func
|
||||
trans._cur_builder = old_builder
|
||||
|
||||
@@ -531,6 +531,13 @@ def _register_generic_template(pool: memhub.MemBuddy*, cd: ast.ClassDef*, module
|
||||
_g_gen.ClassGenGeneric._register_generic_template(pool, cd, module_sha1)
|
||||
|
||||
|
||||
# ---------------- _register_generic_func_template(委托 ClassGenGeneric._register_generic_func_template) ----------------
|
||||
def _register_generic_func_template(pool: memhub.MemBuddy*, fd: ast.FunctionDef*, module_sha1: str):
|
||||
"""委托到 gen.ClassGenGeneric._register_generic_func_template(扫描预注册用)"""
|
||||
if _g_gen is not None:
|
||||
_g_gen.ClassGenGeneric._register_generic_func_template(pool, fd, module_sha1)
|
||||
|
||||
|
||||
# ---------------- _mangle_name_with_sha1(委托 FuncGenBase._mangle_name_with_sha1) ----------------
|
||||
def _mangle_name_with_sha1(sha1: str, name: str) -> str:
|
||||
"""委托到 gen._mangle_name_with_sha1(原 Handles 壳)"""
|
||||
|
||||
@@ -89,6 +89,13 @@ novirtual class TranslatorGenMixin:
|
||||
self.Gen.ImportsGen.translate_import_from_module(trans, child)
|
||||
self.Gen.ImportsGen.translate_import_from_names(trans, child)
|
||||
elif kd == ast.ASTKind.FunctionDef:
|
||||
# PEP 695 泛型函数(def f[T]):定义处不发射(模板已由 Phase1Scan/
|
||||
# Phase2 扫描或 forward_declare_functions 注册),调用点单态化。
|
||||
# 必须在此跳过——否则 1a 的 _prescan_funcdef_signatures 会把未绑定
|
||||
# 类型形参 T 当注解解析(落空/误导)。
|
||||
fd_tc: ast.FunctionDef* = ast.FunctionDef*(child)
|
||||
if fd_tc is not None and fd_tc.type_params is not None:
|
||||
continue
|
||||
# Phase 1a 声明模式:只注册 CExport/State 函数到全局表(解决翻译顺序依赖)
|
||||
# Phase 1b 全量翻译:正常翻译函数体
|
||||
if trans._declare_only == 0:
|
||||
|
||||
Reference in new issue
Block a user