Files
ViperC/App/lib/core/Gen/GenApi.vp
T
TermiNexus c1a22411ca fix(TypeGenResolve): 规则 5.5 增「本文件顶层类名」证据,模块级早于类定义的窗口不再留裸名
类别:a 编译器缺陷(TPV 侧;补齐"第二个裸类名窗口")

现象(与上一轮 e1bb42f 同一现场、不同窗口):编译 includes/ast/base.vp 时 :359
`_append_child(self.children, node, self.pool)` 报"指针隐式转指针已禁止(被指类型是
非基本类型…)",源 list[rawptr[AST]]* 与目标 list[rawptr<定义模块SHA1>.AST]* 差在实参的
SHA1 前缀。

判据(第二个窗口 = 模块级语句早于类定义):
· Translator.translate 的 prologue 先跑模块级 AnnAssign/Assign(Translator.vp:592-599)
  与 forward_declare_functions(:601),**之后**才 translate_children(:602) 逐个翻译类;
  而"正在定义类"窗口(CurDefModuleSha1/CurDefClassName)只在类定义入口
  (ClassGenDef.vp:50)或 .vpi 注入(VpiReader.vp:2659)才建立 ⇒ 前者解析注解时窗口为
  None ⇒ `_norm_type_arg_name` 规则 5.5 的 ①②③④ 全落空 ⇒ 注解里的裸类名(base.vp:148
  `_append_child(..., lst: list[rawptr[AST]])` 的形参即此窗口)以**裸名**形式被首次注册,
  并被后续复用(首写者胜:StructGenMixin 按 Ty 去重、ClassGenDef existing 早退不重算)
  ⇒ 与同一特化在类定义期解析出的带 SHA1 形式分裂。

修法(正向事实,不猜;与窗口/类定义顺序无关):
1. `StructGenMixin` 增文件级登记:字段 `FileClassNames`(本文件顶层 ClassDef 类名表,
   表与键同池、每文件随 `reset_visible_structs` 重建)+ `FileModuleSha1`(本文件模块
   SHA1),以及 `register_file_classes` / `is_file_class` / `get_file_module_sha1`。
   键从 AST 的 name **复制到 pool** 后再登记(AST name 零拷贝指向 src_buf,跨阶段可能
   失效,直接当表的键会 strcmp 到悬空内存)。
2. `Translator.translate` prologue:在模块级变量/前向声明**之前**调用
   `GenApi.register_file_classes(pool, self.ModuleSha1, tree)`(GenApi 增同名委托)。
3. `TypeGenResolve._norm_type_arg_name` 规则 5.5 增**第五类证据**:①②③④ 全落空时,
   若 `is_file_class(name)`(该裸名确由本文件声明)且本文件模块 SHA1 已知 ⇒ 归属本文件。

验证:TPV 侧改动需重新自举 TransPyV.exe 后生效;本轮以代码级证据链
(Translator.vp:592-602 / ClassGenDef.vp:50 / TypeGenResolve.vp 规则 5.5 闸门)自证。
TransPyV 仓另有他人未提交文件,本次只提交本改动的 4 个文件。
2026-09-30 00:23:43 +08:00

751 lines
35 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdlib
import lib.core.Gen.GenTypes as GenTypes
import lib.core.Gen.Generator as Generator
import lib.core.Gen.Translator as HT
import lib.core.Gen.Generator as Generator
# ============================================================
# GenApi - 管线/保留文件访问 Gen 的模块级委托入口(去除 Handles 层)
#
# 由脚本从 Gen 子对象同名方法自动生成:签名取真源方法(含参数类型注解),
# 函数体经 _g_gen 单例调用 gen 子对象。main/BuildPipeline 注入 _g_gen。
# ============================================================
# 全局 gen 单例(main/BuildPipeline 创建 gen 后注入)
_g_gen: Generator.Generator* = None
# ---------------- set_temp_dir(委托 TypeGenBase.set_temp_dir) ----------------
def set_temp_dir(temp_dir: str) -> None:
"""委托到 gen.set_temp_dir(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TypeGenBase.set_temp_dir(temp_dir)
# ---------------- set_current_file_imports(委托 ImportsGenMixin.set_current_file) ----------------
def set_current_file_imports(file_path: str) -> None:
"""委托到 gen.set_current_file(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.ImportsGen.set_current_file(file_path)
# ---------------- set_current_file_type(委托 TypeGenResolve.set_current_file) ----------------
def set_current_file_type(file_path: str) -> None:
"""委托到 gen.set_current_file —— 报错归因的"当前文件"写入通道(原 Handles 壳)
与 fatal_error 同因同解:Converter 的 vpi 生成(Phase 1)、Phase A-pre-vpi
跑在 BuildPipeline 注入 GenApi._g_gen 之前(BuildPipeline.vp 的
_GeneratePyiFromAst 调用点早于 GenApi._g_gen 赋值),此时 _g_gen 为空;
写侧若缺兜底会静默 no-op → fatal_error 的 get_current_file 读到的仍是
上一个文件(归因错位)。故回退读 Generator 模块单例(main.vp 启动即注入)。
"""
if _g_gen is not None:
_g_gen.TypeGenResolve.set_current_file(file_path)
return
gg: Generator.Generator* = Generator._g_gen
if gg is not None:
gg.TypeGenResolve.set_current_file(file_path)
# ---------------- set_current_module_sha1(委托 TypeGenBase.set_current_module_sha1) ----------------
def set_current_module_sha1(sha1: str) -> None:
"""委托到 gen.set_current_module_sha1(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TypeGenBase.set_current_module_sha1(sha1)
# ---------------- clear_trace(委托 TypeGenBase.clear_trace) ----------------
def clear_trace() -> None:
"""委托到 gen.clear_trace(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TypeGenBase.clear_trace()
# ---------------- clear_cdefine_constants(委托 TypeGenCDef.clear_cdefine_constants) ----------------
def clear_cdefine_constants() -> None:
"""委托到 gen.clear_cdefine_constants(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TypeGenCDef.clear_cdefine_constants()
# ---------------- clear_ctypedefs(委托 TypeGenCType.clear_ctypedefs) ----------------
def clear_ctypedefs() -> None:
"""委托到 gen.clear_ctypedefs(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TypeGenCType.clear_ctypedefs()
# ---------------- RegisterCTypedefFromSource(委托 TypeGenCType.register_ctypedef_from_source) ----------------
def RegisterCTypedefFromSource(pool: memhub.MemBuddy*, src: str) -> int:
"""委托到 gen.register_ctypedef_from_source(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TypeGenCType.register_ctypedef_from_source(pool, src)
return 0
# ---------------- dump_parse_traceback(委托 TypeGenErr.dump_parse_traceback) ----------------
def dump_parse_traceback(file_path: str) -> None:
"""委托到 gen.dump_parse_traceback(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TypeGenErr.dump_parse_traceback(file_path)
# ---------------- fatal_error(委托 TypeGenErr.fatal_error) ----------------
def fatal_error(node: ast.AST*, msg: str,
err_type: str = "SyntaxError") -> None:
"""委托到 gen.TypeGenErr.fatal_error —— 模块级函数的报错通道
VpiReader / Converter 等模块级函数没有 self.Gen,无法直接调用
fatal_error(模块级函数也不应为了报错而持有 gen),统一经此入口。
Converter 的 vpi 生成(Phase 1)跑在 BuildPipeline 注入 GenApi._g_gen
之前(BuildPipeline.vp 的 _GeneratePyiFromAst 调用点早于 GenApi._g_gen
赋值),故 GenApi._g_gen 为空时回退读 Generator 模块单例(main.vp 启动
即注入),避免报错静默 no-op。
"""
if _g_gen is not None:
_g_gen.TypeGenErr.fatal_error(node, msg, err_type)
return
gg: Generator.Generator* = Generator._g_gen
if gg is not None:
gg.TypeGenErr.fatal_error(node, msg, err_type)
# ---------------- map_t_type(委托 TypeGenResolve.map_t_type) ----------------
def map_t_type(pool: memhub.MemBuddy*, type_name: str) -> llvmlite.LLVMType*:
"""委托到 gen.map_t_type(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TypeGenResolve.map_t_type(pool, type_name)
return None
# ---------------- resolve_typedef_or_map(委托 TypeGenResolve.resolve_typedef_or_map) ----------------
def resolve_typedef_or_map(pool: memhub.MemBuddy*,
name: str,
imported_modules: str,
from_imports: str,
trans: HT.Translator* = None) -> llvmlite.LLVMType*:
"""委托到 gen.resolve_typedef_or_map(CTypedef 动态表优先,miss 回退 map_t_type)"""
if _g_gen is not None:
return _g_gen.TypeGenResolve.resolve_typedef_or_map(pool, name, imported_modules, from_imports, trans)
return None
# ---------------- infer_external_func_ret_ty(委托 CallGenLib._infer_external_func_ret_ty) ----------------
def infer_external_func_ret_ty(pool: memhub.MemBuddy*,
func_name: str) -> llvmlite.LLVMType*:
"""委托到 gen.CallGenLib._infer_external_func_ret_ty(外部函数返回类型白名单)
vpi 注入 extern declare 时返回类型解析 miss 的兜底:FindFirstFileA/
GetStdHandle 等 Win32 HANDLE 返回函数 → i8*,避免默认 i32/void 导致
声明签名错误(运行期 FindFirstFileA 句柄丢失 → 文件存在性判断失效根因)。
fatal_if_unknown=0:白名单未命中返回默认 i32(不 fail-fast,注入上下文
无法收敛判断交给调用侧)。
"""
if _g_gen is not None:
return _g_gen.CallGenLib._infer_external_func_ret_ty(pool, func_name, None, 0)
return None
# ---------------- get_current_file(委托 TypeGenResolve.get_current_file) ----------------
def get_current_file() -> str:
"""委托到 gen.get_current_file(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TypeGenResolve.get_current_file()
return None
# ---------------- _is_ctypedef_annotation(委托 TypeGenCType._is_ctypedef_annotation) ----------------
def _is_ctypedef_annotation(annotation: ast.AST*) -> int:
"""委托到 gen._is_ctypedef_annotation(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TypeGenCType._is_ctypedef_annotation(annotation)
return 0
# ---------------- resolve_annotation_type(委托 TypeGenResolve.resolve_annotation_type) ----------------
def resolve_annotation_type(pool: memhub.MemBuddy*, node: ast.AST*, imported_modules: str, from_imports: str, trans: HT.Translator* = None, depth: int = 0) -> llvmlite.LLVMType*:
"""委托到 gen.resolve_annotation_type(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TypeGenResolve.resolve_annotation_type(pool, node, imported_modules, from_imports, trans, depth)
return None
# ---------------- has_decorator_marker(委托 TypeGenErr.has_decorator_marker) ----------------
def has_decorator_marker(node: ast.AST*, marker_name: str,
depth: int = 0) -> int:
"""委托到 gen.has_decorator_marker(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TypeGenErr.has_decorator_marker(node, marker_name, depth)
return 0
# ---------------- _get_type_name_from_annotation(委托 TypeGenResolve._get_type_name_from_annotation) ----------------
def _get_type_name_from_annotation(pool: memhub.MemBuddy*, node: ast.AST*) -> str:
"""委托到 gen._get_type_name_from_annotation(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TypeGenResolve._get_type_name_from_annotation(pool, node)
return None
# ---------------- register_ctypedef(委托 TypeGenCType.register_ctypedef) ----------------
def register_ctypedef(pool: memhub.MemBuddy*, name: str, type_str: str):
"""委托到 gen.register_ctypedef(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TypeGenCType.register_ctypedef(pool, name, type_str)
# ---------------- lookup_cdefine_constant(委托 TypeGenCDef.lookup_cdefine_constant) ----------------
def lookup_cdefine_constant(name: str) -> int64:
"""委托到 gen.lookup_cdefine_constant(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TypeGenCDef.lookup_cdefine_constant(name)
return 0
# ---------------- is_cdefine_found(委托 TypeGenCDef.is_cdefine_found) ----------------
def is_cdefine_found() -> int:
"""委托到 gen.is_cdefine_found(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TypeGenCDef.is_cdefine_found()
return 0
# ---------------- register_cdefine_constant(委托 TypeGenCDef.register_cdefine_constant) ----------------
def register_cdefine_constant(pool: memhub.MemBuddy*,
name: str, value: int64):
"""委托到 gen.register_cdefine_constant(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TypeGenCDef.register_cdefine_constant(pool, name, value)
# ---------------- register_cdefine_double(委托 TypeGenCDef.register_cdefine_double) ----------------
def register_cdefine_double(pool: memhub.MemBuddy*,
name: str, value: double):
"""委托到 gen.register_cdefine_double(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TypeGenCDef.register_cdefine_double(pool, name, value)
# ---------------- is_cdefine_annotation(委托 AssignGenMixin.is_cdefine_annotation) ----------------
def is_cdefine_annotation(annot: ast.AST*) -> int:
"""委托到 gen.is_cdefine_annotation(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.AssignGen.is_cdefine_annotation(annot)
return 0
# ---------------- extract_cdefine_int_value(委托 AssignGenMixin.extract_cdefine_int_value) ----------------
def extract_cdefine_int_value(val_node: ast.AST*) -> int64:
"""委托到 gen.extract_cdefine_int_value(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.AssignGen.extract_cdefine_int_value(val_node)
return 0
# ---------------- push_trace(委托 TypeGenBase.push_trace) ----------------
def push_trace(file_name: str, lineno: int, col_start: int = 0, col_end: int = 0):
"""委托到 gen.push_trace(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TypeGenBase.push_trace(file_name, lineno, col_start, col_end)
# ---------------- pop_trace(委托 TypeGenBase.pop_trace) ----------------
def pop_trace():
"""委托到 gen.pop_trace(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TypeGenBase.pop_trace()
# ---------------- get_temp_dir(委托 TypeGenBase.get_temp_dir) ----------------
def get_temp_dir() -> str:
"""委托到 gen.get_temp_dir(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TypeGenBase.get_temp_dir()
return None
# ---------------- reset_visible_structs(委托 StructGenMixin.reset_visible_structs) ----------------
def reset_visible_structs(pool: memhub.MemBuddy*, strict: int):
"""委托到 gen.reset_visible_structs(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.StructGen.reset_visible_structs(pool, strict)
# ---------------- set_stdlib_alloc(委托 StructGenMixin.set_stdlib_alloc) ----------------
def set_stdlib_alloc(flag: int):
"""委托到 gen.set_stdlib_alloc(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.StructGen.set_stdlib_alloc(flag)
# ---------------- get_struct_count(委托 StructGenMixin.get_struct_count) ----------------
def get_struct_count() -> int:
"""委托到 gen.get_struct_count(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.StructGen.get_struct_count()
return 0
# ---------------- reset_module_methods_emitted(委托 StructGenMixin.reset_module_methods_emitted) ----------------
def reset_module_methods_emitted(sha1: str) -> int:
"""委托到 gen.reset_module_methods_emitted(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.StructGen.reset_module_methods_emitted(sha1)
return 0
# ---------------- get_struct_type(委托 StructGenMixin.get_struct_type) ----------------
def get_struct_type(class_name: str) -> llvmlite.LLVMType*:
"""委托到 gen.get_struct_type(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.StructGen.get_struct_type(class_name)
return None
# ---------------- get_enum_base_type(委托 StmtGenDeclMixin.get_enum_base_type) ----------------
def get_enum_base_type(enum_name: str) -> llvmlite.LLVMType*:
"""委托到 gen.get_enum_base_type(原 Handles 壳)
枚举(t.CEnum)注册在独立的 EnumTable(EnumEntry),不进 StructTable,
get_struct_type 查不到。vpi 返回注解如 "types.FRESULT" 解析时 struct
落空必须回退枚举表取 BaseTy(通常 i32),否则跨模块函数返回类型
无法精确获取 → text.ll 缺失(依赖环)时永久 pending(Phase A 死锁根因)。
"""
if _g_gen is not None:
return _g_gen.StmtGenDecl.get_enum_base_type(enum_name)
return None
# ---------------- add_visible_struct(委托 StructGenMixin.add_visible_struct) ----------------
def add_visible_struct(pool: memhub.MemBuddy*, name: str):
"""委托到 gen.add_visible_struct(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.StructGen.add_visible_struct(pool, name)
# ---------------- find_struct_by_module(委托 StructGenMixin.find_struct_by_module) ----------------
def find_struct_by_module(name: str, sha1: str) -> GenTypes.StructEntry*:
"""委托到 gen.find_struct_by_module(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.StructGen.find_struct_by_module(name, sha1)
return None
# ---------------- mark_module_class(委托 StructGenMixin.mark_module_class) ----------------
def mark_module_class(pool: memhub.MemBuddy*, sha1: str, name: str) -> None:
"""登记"{sha1}.{类名}"(= 该模块声明了这个类),并把 CurDefModuleSha1/CurDefClassName
指向它。注入期(VpiReader)没有"类定义窗口",必须靠这一步让
`_norm_type_arg_name` 规则 5.5 的证据链能被查询(否则裸类名实参取不到定义模块
SHA1 ⇒ 特化名冻结成裸名版本,与该类自身翻译期的带前缀形式分裂)。"""
if _g_gen is not None:
_g_gen.StructGen.mark_module_class(pool, sha1, name)
# ---------------- register_file_classes(委托 StructGenMixin.register_file_classes) ----------------
def register_file_classes(pool: memhub.MemBuddy*, sha1: str, tree: ast.AST*) -> None:
"""文件级预登记本文件顶层 ClassDef 的类名 + 本文件模块 SHA1(规则 5.5 第五类证据)。
由 Translator.translate 的 prologue 调用(在翻译模块级变量/前向声明**之前**),
使"模块级语句早于类定义"这一窗口里裸类名也能判出归属。"""
if _g_gen is not None:
_g_gen.StructGen.register_file_classes(pool, sha1, tree)
# ---------------- find_struct_by_type(委托 StructGenMixin.find_struct_by_type) ----------------
def find_struct_by_type(struct_ty: llvmlite.LLVMType*) -> GenTypes.StructEntry*:
"""委托到 gen.find_struct_by_type(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.StructGen.find_struct_by_type(struct_ty)
return None
# ---------------- register_struct(委托 StructGenMixin.register_struct) ----------------
def register_struct(pool: memhub.MemBuddy*,
name: str,
struct_ty: llvmlite.LLVMType*,
sha1: str = None) -> GenTypes.StructEntry*:
"""委托到 gen.register_struct(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.StructGen.register_struct(pool, name, struct_ty, sha1)
return None
# ---------------- add_field(委托 StructGenMixin.add_field) ----------------
def add_field(pool: memhub.MemBuddy*,
struct_entry: GenTypes.StructEntry*,
field_name: str,
field_ty: llvmlite.LLVMType*) -> int:
"""委托到 gen.add_field(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.StructGen.add_field(pool, struct_entry, field_name, field_ty)
return -1
# ---------------- register_struct_alias(委托 StructGenMixin.register_struct_alias) ----------------
def register_struct_alias(pool: memhub.MemBuddy*,
name: str,
sha1: str,
src_entry: GenTypes.StructEntry*) -> GenTypes.StructEntry*:
"""委托到 gen.StructGen.register_struct_alias(包重导出类别名注册,原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.StructGen.register_struct_alias(pool, name, sha1, src_entry)
return None
# ---------------- get_stdlib_alloc(委托 StructGenMixin.get_stdlib_alloc) ----------------
def get_stdlib_alloc() -> int:
"""委托到 gen.get_stdlib_alloc(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.StructGen.get_stdlib_alloc()
return 0
# ---------------- compute_package_from_relpath(委托 ImportsGenMixin.compute_package_from_relpath) ----------------
def compute_package_from_relpath(pool: memhub.MemBuddy*, rel_path: str) -> str:
"""委托到 gen.compute_package_from_relpath(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.ImportsGen.compute_package_from_relpath(pool, rel_path)
return None
# ---------------- is_module_imported(委托 ImportsGenMixin.is_module_imported) ----------------
def is_module_imported(imported_modules: str, name: str) -> int:
"""委托到 gen.is_module_imported(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.ImportsGen.is_module_imported(imported_modules, name)
return 0
# ============================================================
# SHA1 前缀识别的**唯一真源**:两种书写形态各给一个判定。
#
# sha1_prefix_len(name) → 完整名 "{16位小写hex}.Class" ⇒ 返回 17(前缀字节数),否则 0。
# 判据三条缺一不可:长度 >= 17、第 17 字节是 '.'、前 16 字节全为小写 hex。
# is_sha1_hex16(seg) → 单独的模块段("16位小写hex")⇒ 1/0;用于已切成两段后判 mod 段。
#
# 必须唯一:多处同义拷贝若口径不同(省略 hex 校验 / 允许大写 / 只要 len >= 16 就盲取前 16 字节),
# 同一名字在不同路径会被判成"是/不是 SHA1 前缀",产生「重复加前缀 / 把 SHA1 当模块名再查 /
# 该跳过 store 查询的没跳过」等隐蔽不一致(跨模块同名类归属错乱、泛型实参解析退化)。
# ============================================================
def sha1_prefix_len(name: str) -> int:
"""名字若是 "{16位小写hex}." 形态返回 17(前缀字节数),否则返回 0"""
if name is None:
return 0
if string.strlen(name) < 17:
return 0
if name[16] != '.':
return 0
i: sizet
for i in range(16):
c: int = name[i]
# 48-57 = '0'-'9',97-102 = 'a'-'f'
if not ((c >= 48 and c <= 57) or (c >= 97 and c <= 102)):
return 0
return 17
def is_sha1_hex16(seg: str) -> int:
"""seg 是否恰为 16 位小写 hex(SHA1 模块段),1=是 / 0=否"""
if seg is None:
return 0
if string.strlen(seg) != 16:
return 0
i: sizet
for i in range(16):
c: int = seg[i]
if not ((c >= 48 and c <= 57) or (c >= 97 and c <= 102)):
return 0
return 1
# ---------------- add_imported_module(委托 ImportsGenMixin.add_imported_module) ----------------
def add_imported_module(pool: memhub.MemBuddy*, imported_modules: str, name: str) -> str:
"""委托到 gen.add_imported_module(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.ImportsGen.add_imported_module(pool, imported_modules, name)
return None
# ---------------- translate_import(委托 ImportsGenMixin.translate_import) ----------------
def translate_import(trans: HT.Translator*, node: ast.AST*) -> int:
"""委托到 gen.translate_import(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.ImportsGen.translate_import(trans, node)
return 0
# ---------------- translate_import_from_module(委托 ImportsGenMixin.translate_import_from_module) ----------------
def translate_import_from_module(trans: HT.Translator*, node: ast.AST*) -> int:
"""委托到 gen.translate_import_from_module(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.ImportsGen.translate_import_from_module(trans, node)
return 0
# ---------------- translate_import_from_names(委托 ImportsGenMixin.translate_import_from_names) ----------------
def translate_import_from_names(trans: HT.Translator*, node: ast.AST*) -> int:
"""委托到 gen.translate_import_from_names(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.ImportsGen.translate_import_from_names(trans, node)
return 0
# ---------------- _get_parent_class(委托 ClassGenBase._get_parent_class) ----------------
def _get_parent_class(cd: ast.ClassDef*, trans: HT.Translator* = None) -> str:
"""委托到 gen._get_parent_class(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.ClassGenBase._get_parent_class(cd, trans)
return None
# ---------------- _register_generic_template(委托 ClassGenGeneric._register_generic_template) ----------------
def _register_generic_template(pool: memhub.MemBuddy*, cd: ast.ClassDef*, module_sha1: str):
"""委托到 gen._register_generic_template(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.ClassGenGeneric._register_generic_template(pool, cd, 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 壳)"""
if _g_gen is not None:
return _g_gen.FuncGenBase._mangle_name_with_sha1(sha1, name)
return None
# ---------------- forward_declare_functions(委托 FuncGenDef.forward_declare_functions) ----------------
def forward_declare_functions(trans: HT.Translator*, tree: ast.AST*) -> int:
"""委托到 gen.forward_declare_functions(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.FuncGenDef.forward_declare_functions(trans, tree)
# ============================================================
# f-string 逃逸规则(判据 + 拷贝出口,本文件为唯一实现)
#
# f-string 的结果指针指向**当前函数的栈缓冲**(见 ExprGenFstr._fstr_finalize):
# · 栈缓冲 ⇒ 线程安全(每线程各自栈帧)+ 零运行时依赖(内核无 C-ABI 分配器);
# · 函数返回即失效 ⇒ 把该指针带出函数的写法都是悬空读。历史事故:调用方
# `return f"..."` 后由上层当 %s 喂 snprintf ⇒ ASan stack-buffer-underflow
# in vsnprintf(READ size 1,地址落在栈左红区)。
#
# 因此:逃逸位置一律 fail-fast;确需逃逸时用 escape_fstring_copy 显式拷贝。
#
# 覆盖范围与残留(诚实记录):本判据覆盖 return / 赋值到字段、元素、全局这类
# **直接逃逸**;把 f-string 传进"会保存它"的函数、或放进容器后带走容器,属于
# 间接逃逸,静态判不出,仍靠规则约束(用 escape_fstring_copy 显式拷贝)。
# ============================================================
def fail_if_fstring_escape(node: ast.AST*, where: str) -> int:
"""value 位置是 f-string(JoinedStr / 裸 FormattedValue,含元组元素)却处于逃逸位置 → fail-fast
where: 逃逸位置描述(如 "函数返回值" / "字段赋值" / "全局变量初始化")。
恒返回 0(命中即终止编译,不返回非 0 值)。
"""
if node is None:
return 0
hit: int = 0
k: int = node.kind()
if k == ast.ASTKind.JoinedStr or k == ast.ASTKind.FormattedValue:
hit = 1
elif k == ast.ASTKind.Tuple:
tp: ast.Tuple* = ast.Tuple*(node)
if tp.elts is not None:
i: sizet = 0
en: sizet = len(tp.elts)
while i < en:
e: ast.AST* = tp.elts.get(i)
if e is not None:
ek: int = e.kind()
if ek == ast.ASTKind.JoinedStr or ek == ast.ASTKind.FormattedValue:
hit = 1
break
i += 1
if hit == 0:
return 0
if _g_gen is not None:
_g_gen.TypeGenErr.fatal_error(node,
f"f-string 结果不能用于{where}(逃逸):f-string 指向**当前函数的栈缓冲**,"
f"函数返回即失效,把这个指针带出函数会读到已弹栈的帧"
f"(历史事故:ASan stack-buffer-underflow in vsnprintf)。"
f"需要带出函数时显式分配后拷贝:"
f"tmp: str = f\"...\";out: str = GenApi.escape_fstring_copy(tmp);return out。",
"TypeError")
return 0
def escape_fstring_copy(src: str) -> str:
"""把 f-string 结果拷贝到 stdlib 堆并返回(f-string 逃逸的**唯一**出口)。
f-string 本身是函数内临时值(栈缓冲);要把它带出函数(return / 存字段 /
存全局 / 放进长期容器)必须显式拷贝。分配用 stdlib.malloc(CRT),
生命周期由调用方决定——编译器自身的报文构造只在错误路径使用,允许不回收。
"""
if src is None:
return None
n: sizet = string.strlen(src)
out: str = stdlib.malloc(n + 1)
if out is None:
return None
string.strcpy(out, src)
return out
# ---------------- create_wrapper_main(委托 TranslatorGenMixin.create_wrapper_main) ----------------
def create_wrapper_main(trans: HT.Translator*, tree: ast.AST*, i32_ty: llvmlite.LLVMType*) -> int:
"""委托到 gen.create_wrapper_main(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TranslatorGen.create_wrapper_main(trans, tree, i32_ty)
return 0
# ---------------- handle_module_level_var(委托 TranslatorGenMixin.handle_module_level_var) ----------------
def handle_module_level_var(trans: HT.Translator*, node: ast.AST*) -> int:
"""委托到 gen.handle_module_level_var(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TranslatorGen.handle_module_level_var(trans, node)
return 0
# ---------------- translate_children(委托 TranslatorGenMixin.translate_children) ----------------
def translate_children(trans: HT.Translator*, tree: ast.AST*) -> int:
"""委托到 gen.translate_children(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TranslatorGen.translate_children(trans, tree)
return 0
# ---------------- init_symbol_table(委托 VarGenMixin.init_symbol_table) ----------------
def init_symbol_table(pool: memhub.MemBuddy*) -> rawptr[GenTypes.SymbolTable]:
"""委托到 gen.init_symbol_table(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.VarGen.init_symbol_table(pool)
return None
# ---------------- SetTempDir(委托 CallGenBase.SetTempDir) ----------------
def SetTempDir(temp_dir: str):
"""委托到 gen.SetTempDir(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.CallGenBase.SetTempDir(temp_dir)
# ---------------- find_func_in_module(委托 CallGenBase.find_func_in_module) ----------------
def find_func_in_module(mod: llvmlite.LLVMModule*, name: str) -> llvmlite.Function*:
"""委托到 gen.find_func_in_module(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.CallGenBase.find_func_in_module(mod, name)
return None
# ---------------- add_func_to_table(委托 CallGenLeafKit.add_func_to_table) ----------------
def add_func_to_table(funcs: GenTypes.FuncEntry*, func_count: int, name: str, func: llvmlite.Function*, max_count: int, defaults: t.CPtr = None, default_count: int = 0, param_count: int = 0, pool: memhub.MemBuddy* = None, def_sha1: str = None) -> int:
"""委托到 gen.add_func_to_table(原 Handles 壳)
def_sha1:定义该函数的模块 SHA1(依赖注入路径必须传,避免默认值被挂到导入方名下)
"""
if _g_gen is not None:
return _g_gen.CallGenLeafKit.add_func_to_table(funcs, func_count, name, func, max_count, defaults, default_count, param_count, pool, def_sha1)
return 0
# ---------------- init_func_table(委托 CallGenLeafKit.init_func_table) ----------------
def init_func_table(pool: memhub.MemBuddy*, max_count: int) -> GenTypes.FuncEntry*:
"""委托到 gen.init_func_table(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.CallGenLeafKit.init_func_table(pool, max_count)
return None
# ---------------- translate_call(委托 CallGenMixin.translate_call) ----------------
def translate_call(pool: memhub.MemBuddy*, builder: llvmlite.IRBuilder*, mod: llvmlite.LLVMModule*, node: ast.AST*, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator* = None) -> llvmlite.Value*:
"""委托到 gen.translate_call(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.CallGen.translate_call(pool, builder, mod, node, funcs_ptr, func_count, trans)
return None
# ---------------- translate_printf_call(委托 CallGenLeafKit.translate_printf_call) ----------------
def translate_printf_call(pool: memhub.MemBuddy*, builder: llvmlite.IRBuilder*, mod: llvmlite.LLVMModule*, cl: ast.Call*, trans: HT.Translator* = None):
"""委托到 gen.translate_printf_call(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.CallGenLeafKit.translate_printf_call(pool, builder, mod, cl, trans)
# ---------------- translate_print_call(委托 CallGenLeafKit.translate_print_call) ----------------
def translate_print_call(pool: memhub.MemBuddy*, builder: llvmlite.IRBuilder*, mod: llvmlite.LLVMModule*, cl: ast.Call*, trans: HT.Translator* = None):
"""委托到 gen.translate_print_call(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.CallGenLeafKit.translate_print_call(pool, builder, mod, cl, trans)
# ---------------- add_global_name(委托 TranslatorGenMixin.add_global_name) ----------------
def add_global_name(trans: HT.Translator*, name: str):
"""委托到 gen.TranslatorGen.add_global_name(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TranslatorGen.add_global_name(trans, name)
# ---------------- is_global_name(委托 TranslatorGenMixin.is_global_name) ----------------
def is_global_name(trans: HT.Translator*, name: str) -> int:
"""委托到 gen.TranslatorGen.is_global_name(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TranslatorGen.is_global_name(trans, name)
return 0
# ---------------- add_nonlocal_name(委托 TranslatorGenMixin.add_nonlocal_name) ----------------
def add_nonlocal_name(trans: HT.Translator*, name: str,
var_ty: llvmlite.LLVMType* = None):
"""委托到 gen.TranslatorGen.add_nonlocal_name(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TranslatorGen.add_nonlocal_name(trans, name, var_ty)
# ---------------- get_nonlocal_type(委托 TranslatorGenMixin.get_nonlocal_type) ----------------
def get_nonlocal_type(trans: HT.Translator*,
name: str) -> llvmlite.LLVMType*:
"""委托到 gen.TranslatorGen.get_nonlocal_type(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TranslatorGen.get_nonlocal_type(trans, name)
return None
# ---------------- is_nonlocal_name(委托 TranslatorGenMixin.is_nonlocal_name) ----------------
def is_nonlocal_name(trans: HT.Translator*, name: str) -> int:
"""委托到 gen.TranslatorGen.is_nonlocal_name(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TranslatorGen.is_nonlocal_name(trans, name)
return 0
# ---------------- get_nonlocal_index(委托 TranslatorGenMixin.get_nonlocal_index) ----------------
def get_nonlocal_index(trans: HT.Translator*, name: str) -> int:
"""委托到 gen.TranslatorGen.get_nonlocal_index(原 Handles 壳)"""
if _g_gen is not None:
return _g_gen.TranslatorGen.get_nonlocal_index(trans, name)
return 0
# ---------------- clear_scope_names(委托 TranslatorGenMixin.clear_scope_names) ----------------
def clear_scope_names(trans: HT.Translator*):
"""委托到 gen.TranslatorGen.clear_scope_names(原 Handles 壳)"""
if _g_gen is not None:
_g_gen.TranslatorGen.clear_scope_names(trans)
# ---------------- update_global_func_spec(委托 CallGenLeafKit.update_global_func_spec) ----------------
def update_global_func_spec(name: str,
func: llvmlite.Function*) -> int:
"""委托到 gen.CallGenLeafKit.update_global_func_spec(原 ExprCallTable 壳)"""
if _g_gen is not None:
return _g_gen.CallGenLeafKit.update_global_func_spec(name, func)
return 0