Files
ViperC/App/lib/core/Handles/HandlesNonlocal.vp
T
TermiNexus 6677da99f7 refactor(gen): P6 方法化 - StmtGen/AssignGen/VarGen/ImportsGen/TranslatorGen Mixin
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 规避循环依赖)。
2026-08-10 18:42:07 +08:00

137 lines
6.1 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 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