diff --git a/App/lib/Phase/Phase1/Phase1Scan.vp b/App/lib/Phase/Phase1/Phase1Scan.vp index 9675e18..2e1fe02 100644 --- a/App/lib/Phase/Phase1/Phase1Scan.vp +++ b/App/lib/Phase/Phase1/Phase1Scan.vp @@ -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 diff --git a/App/lib/Phase/Phase2/__init__.vp b/App/lib/Phase/Phase2/__init__.vp index e2baca7..2b726ff 100644 --- a/App/lib/Phase/Phase2/__init__.vp +++ b/App/lib/Phase/Phase2/__init__.vp @@ -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 diff --git a/App/lib/Stub/StubGen/Converter.vp b/App/lib/Stub/StubGen/Converter.vp index 7e7e815..745cc74 100644 --- a/App/lib/Stub/StubGen/Converter.vp +++ b/App/lib/Stub/StubGen/Converter.vp @@ -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, "") # 类定义 diff --git a/App/lib/core/Gen/Call/CallGenDispatch.vp b/App/lib/core/Gen/Call/CallGenDispatch.vp index 6454b3e..b2e09fb 100644 --- a/App/lib/core/Gen/Call/CallGenDispatch.vp +++ b/App/lib/core/Gen/Call/CallGenDispatch.vp @@ -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*, diff --git a/App/lib/core/Gen/Call/CallGenMixin.vp b/App/lib/core/Gen/Call/CallGenMixin.vp index b2d82dd..e5b469c 100644 --- a/App/lib/core/Gen/Call/CallGenMixin.vp +++ b/App/lib/core/Gen/Call/CallGenMixin.vp @@ -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) 当裸名 diff --git a/App/lib/core/Gen/Class/ClassGenBase.vp b/App/lib/core/Gen/Class/ClassGenBase.vp index 8ad60ee..c7f771d 100644 --- a/App/lib/core/Gen/Class/ClassGenBase.vp +++ b/App/lib/core/Gen/Class/ClassGenBase.vp @@ -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 diff --git a/App/lib/core/Gen/Class/ClassGenGeneric.vp b/App/lib/core/Gen/Class/ClassGenGeneric.vp index f79db9b..63e6c12 100644 --- a/App/lib/core/Gen/Class/ClassGenGeneric.vp +++ b/App/lib/core/Gen/Class/ClassGenGeneric.vp @@ -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 diff --git a/App/lib/core/Gen/Func/FuncGenDef.vp b/App/lib/core/Gen/Func/FuncGenDef.vp index 7016fa0..c0eb3b4 100644 --- a/App/lib/core/Gen/Func/FuncGenDef.vp +++ b/App/lib/core/Gen/Func/FuncGenDef.vp @@ -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_/resume_), @@ -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 diff --git a/App/lib/core/Gen/GenApi.vp b/App/lib/core/Gen/GenApi.vp index af6aaf8..c78f46f 100644 --- a/App/lib/core/Gen/GenApi.vp +++ b/App/lib/core/Gen/GenApi.vp @@ -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 壳)""" diff --git a/App/lib/core/Gen/TranslatorGenMixin.vp b/App/lib/core/Gen/TranslatorGenMixin.vp index 35b6e5c..d94c5de 100644 --- a/App/lib/core/Gen/TranslatorGenMixin.vp +++ b/App/lib/core/Gen/TranslatorGenMixin.vp @@ -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: