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:
TermiNexus committed 2026-10-03 11:59:26 +08:00
1 parent 1fbebb2a62
commit 692998820c
10 files changed
+886 -57

No files matched your search

+72 -14
View File
@@ -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
+24 -12
View File
@@ -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