5 个新 Mixin(92 方法)承接 HandlesBody/If/While/For/Return/Nonlocal/Match/Enum/AnnAssign/AugAssign/Var/Imports/Translator/Main 的无状态函数与 _g_ 全局;15 个 Handles 模块改为一行委托(调用方零改动);Generator 组合扩展至 12 Mixin,__init__ 初始化 8 个新字段;BuildPipeline/main 注入 14 个模块 set_global_gen;修复 ImportsGenMixin 与 TypeGenMixin 的 CurrentFile 重复字段冲突(改 HandlesType 委托,延迟 import 规避循环依赖)。
137 lines
6.1 KiB
Plaintext
137 lines
6.1 KiB
Plaintext
import t, c
|
||
from stdint import *
|
||
import ast
|
||
import llvmlite
|
||
import memhub
|
||
import string
|
||
import stdio
|
||
import lib.core.VLogger as VLogger
|
||
import lib.core.Handles.HandlesTranslator as HT
|
||
import lib.core.Handles.HandlesVar as HandlesVar
|
||
|
||
|
||
# ============================================================
|
||
# HandlesNonlocal - nonlocal 变量访问(通过闭包 env)(P6 对象化后的委托层)
|
||
#
|
||
# 全部模块级函数已迁移为 lib.core.Gen.StmtGenMixin 的方法,本模块
|
||
# 保留同名模块级函数作为"一行委托":延迟 import Gen 取全局单例
|
||
# (BuildPipeline/main 创建后 set_global_gen 注册),再调用 gen 的
|
||
# 对应方法。签名与旧函数完全一致,调用方零改动。
|
||
#
|
||
# 闭包 env 结构: {i8* ptr0, i8* ptr1, ...} (每个 nonlocal 变量一个 i8* 指针)
|
||
# 指针指向父函数中变量的 alloca(原始存储位置),父与子共享同一存储,
|
||
# 子函数修改对父函数可见(符合 Python nonlocal 语义)。
|
||
#
|
||
# 在提升的嵌套函数中:
|
||
# 1. 函数签名: define i32 @__closure_{name}(i8* %env)
|
||
# 2. 入口处: %env_alloca = alloca i8*; store i8* %env, i8** %env_alloca
|
||
# 3. 访问 nonlocal var:
|
||
# a. %env_ptr = load i8*, i8** %env_alloca
|
||
# b. %addr = gep i8, i8* %env_ptr, i32 (index * 8)
|
||
# c. %ptr_addr = bitcast i8* %addr to i8**
|
||
# d. %var_ptr_raw = load i8*, i8** %ptr_addr
|
||
# e. %var_ptr = bitcast i8* %var_ptr_raw to <var_ty>*
|
||
# f. read: %val = load <var_ty>, <var_ty>* %var_ptr
|
||
# write: store <var_ty> %new, <var_ty>* %var_ptr
|
||
#
|
||
# 变量类型通过 HT.get_nonlocal_type() 获取(注册 nonlocal 时记录)。
|
||
# ============================================================
|
||
|
||
|
||
# ============================================================
|
||
# 全局 gen 单例(模块级镜像,同 HandlesStruct 模式)
|
||
#
|
||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||
# StmtGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||
# ============================================================
|
||
_g_gen: t.CVoid | t.CPtr = None
|
||
|
||
|
||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||
global _g_gen
|
||
_g_gen = gen
|
||
|
||
|
||
# ============================================================
|
||
# _is_void_type — 判断是否为 Void 类型(非法用作变量类型)
|
||
#
|
||
# 由于某些路径(如 c.DerefAs 设置的 Pointee 字段访问异常)可能导致
|
||
# 类型被设为 Void 而非 None,这里显式检测 Void 类型并视为无效,
|
||
# 回退为 i32,避免生成 "bitcast ... to void*" / "load void, void*" 的非法 IR。
|
||
# ============================================================
|
||
def _is_void_type(ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||
"""判断是否为 Void 类型,是则返回 1,否则 0(委托到 gen._is_void_type)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._is_void_type(ty)
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# 获取或创建 _env_ptr 变量(存储 env 参数的 alloca)
|
||
# ============================================================
|
||
def get_env_ptr_var(trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||
"""获取或创建 _env_ptr 变量(存储闭包 env 指针)(委托到 gen.get_env_ptr_var)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g.get_env_ptr_var(trans)
|
||
return None
|
||
|
||
|
||
# ============================================================
|
||
# 从 env 加载原始变量指针(i8*)→ 调用方 bitcast 为具体类型
|
||
#
|
||
# env 存储指针数组(8 字节/槽),每个指针指向父函数的 alloca。
|
||
# ============================================================
|
||
def _load_raw_var_ptr(trans: HT.Translator | t.CPtr,
|
||
name: str) -> llvmlite.Value | t.CPtr:
|
||
"""从闭包 env 加载 nonlocal 变量的原始指针(i8*)(委托到 gen._load_raw_var_ptr)
|
||
|
||
返回 i8* 类型的 Value,调用方需 bitcast 为具体类型指针后 load/store。
|
||
"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._load_raw_var_ptr(trans, name)
|
||
return None
|
||
|
||
|
||
# ============================================================
|
||
# 加载 nonlocal 变量值 → 返回具体类型的 Value
|
||
#
|
||
# env 存储指向父函数 alloca 的指针,通过类型恢复 load 正确类型的值。
|
||
# ============================================================
|
||
def load_nonlocal_var(trans: HT.Translator | t.CPtr,
|
||
name: str) -> llvmlite.Value | t.CPtr:
|
||
"""从闭包 env 加载 nonlocal 变量值(委托到 gen.load_nonlocal_var)
|
||
|
||
通过 HT.get_nonlocal_type 获取变量类型,bitcast 原始指针后 load。
|
||
"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g.load_nonlocal_var(trans, name)
|
||
return None
|
||
|
||
|
||
# ============================================================
|
||
# 获取 nonlocal 变量指针(用于 store)
|
||
#
|
||
# 返回具体类型指针(var_ty*),用于直接 store。
|
||
# ============================================================
|
||
def get_nonlocal_var_ptr(trans: HT.Translator | t.CPtr,
|
||
name: str) -> llvmlite.Value | t.CPtr:
|
||
"""获取 nonlocal 变量的存储指针(var_ty*),用于 store 操作(委托到 gen.get_nonlocal_var_ptr)
|
||
|
||
返回的指针指向父函数的 alloca,store 操作对父函数可见。
|
||
"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g.get_nonlocal_var_ptr(trans, name)
|
||
return None
|