Files
ViperC/App/lib/core/Handles/HandlesVar.vp
T
TermiNexus e07ea491a5 chore(gen): 全量备份——Handles 委托壳瘦身与单例注入统一
- 删除 Handles 各模块已迁移至 Gen 的旧函数体,保留一行委托壳(25 文件 -798 行)
- main.vp / BuildPipeline.vp 全局单例注入改为 _g_gen 直接赋值
- 机械化迁移测试前的基线备份
2026-08-20 05:33:59 +08:00

372 lines
16 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 llvmlite
import memhub
import string
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesVar - 嵌套作用域符号表 + 变量管理(P6 对象化后的委托层)
#
# 使用 Scope 链(Parent 指针)管理嵌套作用域,
# 每个作用域包含一个 VarEntry 数组(扁平化,已验证可工作)。
#
# 作用域类型:
# SCOPE_MODULE — 模块级(根作用域)
# SCOPE_FUNCTION — 函数级
# SCOPE_BLOCK — 块级(if/for/while,当前未使用块作用域)
#
# P6 对象化重构(wiki/14-oo-refactor.md):
# 全部模块级函数已迁移为 lib.core.Gen.VarGenMixin 的方法(方法化迁移,
# 无全局状态),本模块保留同名模块级函数作为"一行委托":延迟 import
# Gen 取全局单例(BuildPipeline/main 创建后 set_global_gen 注册),
# 再调用 gen 的对应方法。签名与旧函数完全一致,调用方零改动。
#
# VarEntry/Scope/SymbolTable 类型与常量保留在本模块(gen 方法签名引用)。
# ============================================================
# 作用域类型常量
SCOPE_MODULE: t.CDefine = 0
SCOPE_FUNCTION: t.CDefine = 1
SCOPE_BLOCK: t.CDefine = 2
# 每个作用域最大变量数
# 256 太小:NewAstTest main() 有 289 个局部变量,add_var 超限静默失败
# 导致变量未注册,后续使用报"未定义名称"(与 Gen/VarGenMixin 保持一致)。
MAX_VARS: t.CDefine = 1024
# ============================================================
# VarEntry - 变量表条目
# ============================================================
@t.NoVTable
class VarEntry:
"""变量表条目"""
Name: str
Alloca: llvmlite.Value | t.CPtr
Used: t.CInt
AnnotClassName: str # 原始类型注解的类名(str 别名在结构体字段中触发编译器 bug,改用显式联合类型)
IsPtrElement: t.CInt # 标志: 1=注解为 bytes|t.CPtr 或 str|t.CPtr, 下标按 8 字节步长
# ============================================================
# Scope - 作用域节点
#
# Parent 指向父作用域(None 表示根),
# Vars 是 VarEntry 数组,VarCount 是当前变量数。
# ============================================================
@t.NoVTable
class Scope:
"""作用域节点"""
Parent: Scope | t.CPtr
Vars: VarEntry | t.CPtr
VarCount: t.CInt
Kind: t.CInt
# ============================================================
# SymbolTable - 嵌套作用域符号表
#
# Root 是模块级根作用域,Current 是当前作用域。
# enter_scope/exit_scope 管理作用域栈。
# ============================================================
@t.NoVTable
class SymbolTable:
"""嵌套作用域符号表"""
Pool: memhub.MemBuddy | t.CPtr
Root: Scope | t.CPtr
Current: Scope | t.CPtr
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
#
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
# P6 委托函数用本地 _g_gen(cast 成 Generator 类型)调
# VarGenMixin 方法,避免函数体 import 包模块与 Generator
# 类/模块名歧义。
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# 委托函数:延迟 import Gen 取全局单例 → 调 gen 方法
# (gen 未注册时正常流程不会发生;有返回值函数返回默认值)
# ============================================================
# ============================================================
# init_vars — 分配并清零 VarEntry 数组
# ============================================================
def init_vars(pool: memhub.MemBuddy | t.CPtr) -> VarEntry | t.CPtr:
"""分配并清零变量表数组(委托到 gen.init_vars)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.init_vars(pool)
return None
# ============================================================
# find_var — 在变量表中按名称查找
# ============================================================
def find_var(vars_ptr: VarEntry | t.CPtr,
var_count: int,
name: str) -> llvmlite.Value | t.CPtr:
"""在变量表中按名称查找(委托到 gen.find_var)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.find_var(vars_ptr, var_count, name)
return None
# ============================================================
# find_var_entry — 在变量表中按名称查找,返回 VarEntry(含 AnnotTy)
# ============================================================
def find_var_entry(vars_ptr: VarEntry | t.CPtr,
var_count: int,
name: str) -> VarEntry | t.CPtr:
"""在变量表中按名称查找,返回 VarEntry 或 None(委托到 gen.find_var_entry)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.find_var_entry(vars_ptr, var_count, name)
return None
# ============================================================
# lookup_var_entry — 从当前作用域逐级向上查找变量,返回 VarEntry
# ============================================================
def lookup_var_entry(symtab: SymbolTable | t.CPtr,
name: str) -> VarEntry | t.CPtr:
"""从当前作用域逐级向上查找变量,返回 VarEntry 或 None(委托到 gen.lookup_var_entry)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.lookup_var_entry(symtab, name)
return None
# ============================================================
# set_var_annot_class_name — 设置变量的原始类型注解类名
#
# 在函数参数定义后调用,存储原始类型注解的类名。
# 方法调用检测时,当 alloca 类型是 Ptr(i8)(联合类型简化),
# 通过 AnnotClassName 查找实际结构体类型。
# ============================================================
def set_var_annot_class_name(symtab: SymbolTable | t.CPtr,
name: str,
class_name: str) -> int:
"""设置变量的原始类型注解类名,返回 0=成功 / 1=失败(委托到 gen.set_var_annot_class_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.set_var_annot_class_name(symtab, name, class_name)
return 0
# ============================================================
# set_var_ptr_element — 标记变量为"指针到 str/bytes"类型
#
# 注解为 bytes|t.CPtr 或 str|t.CPtr 的变量,其 alloca 类型是 i8*,
# 但下标访问应按 8 字节步长(i8** 语义),而非 1 字节步长(i8* 语义)。
# 此标志在 HandlesAnnAssign 中根据注解形式设置。
# ============================================================
def set_var_ptr_element(symtab: SymbolTable | t.CPtr,
name: str) -> int:
"""标记变量为 ptr_element 类型,返回 0=成功 / 1=失败(委托到 gen.set_var_ptr_element)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.set_var_ptr_element(symtab, name)
return 0
# ============================================================
# add_var — 添加变量到变量表
# ============================================================
def add_var(vars_ptr: VarEntry | t.CPtr,
var_count: int,
name: str,
alloca: llvmlite.Value | t.CPtr) -> int:
"""添加变量到变量表(委托到 gen.add_var)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.add_var(vars_ptr, var_count, name, alloca)
return 0
# ============================================================
# _alloca_at_entry - 在函数入口块生成 alloca(确保支配性)
#
# LLVM IR 要求指令支配所有使用点。如果 alloca 在条件分支内生成,
# 但在其他分支使用,会违反支配性(Instruction does not dominate all uses)。
# 标准做法:所有 alloca 在函数入口块生成。
#
# 临时切换 builder.CurBlock 到入口块,生成 alloca,然后恢复。
# ============================================================
def _alloca_at_entry(builder: llvmlite.IRBuilder | t.CPtr,
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
"""在函数入口块生成 alloca,返回 alloca 值(委托到 gen._alloca_at_entry)
使用 llvmlite.build_alloca_at_entry 在入口块终止指令之前插入 alloca,
确保所有 alloca 在入口块,避免支配性违规。
"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._alloca_at_entry(builder, ty)
return None
# ============================================================
# get_or_create_var — 查找或创建变量 alloca(旧版兼容)
# ============================================================
def get_or_create_var(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
vars_ptr: VarEntry | t.CPtr,
var_count: int,
name: str,
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
"""查找或创建变量 alloca(委托到 gen.get_or_create_var)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_or_create_var(pool, builder, vars_ptr, var_count, name, ty)
return None
# ============================================================
# _create_scope — 创建新作用域节点(内部辅助函数)
# ============================================================
def _create_scope(pool: memhub.MemBuddy | t.CPtr,
parent: Scope | t.CPtr,
kind: int) -> Scope | t.CPtr:
"""创建并初始化作用域节点(委托到 gen._create_scope)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._create_scope(pool, parent, kind)
return None
# ============================================================
# init_symbol_table — 创建符号表(含模块级根作用域)
# ============================================================
def init_symbol_table(pool: memhub.MemBuddy | t.CPtr) -> SymbolTable | t.CPtr:
"""创建并初始化符号表,包含模块级根作用域(委托到 gen.init_symbol_table)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.init_symbol_table(pool)
return None
# ============================================================
# enter_scope — 进入新作用域
# ============================================================
def enter_scope(symtab: SymbolTable | t.CPtr,
kind: int) -> Scope | t.CPtr:
"""进入新作用域,返回新创建的作用域(委托到 gen.enter_scope)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.enter_scope(symtab, kind)
return None
# ============================================================
# exit_scope — 退出当前作用域
# ============================================================
def exit_scope(symtab: SymbolTable | t.CPtr):
"""退出当前作用域,恢复到父作用域(委托到 gen.exit_scope)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.exit_scope(symtab)
# ============================================================
# define_var — 在当前作用域定义变量
# ============================================================
def define_var(symtab: SymbolTable | t.CPtr,
name: str,
alloca: llvmlite.Value | t.CPtr) -> int:
"""在当前作用域定义变量,返回 0 成功(委托到 gen.define_var)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.define_var(symtab, name, alloca)
return 0
# ============================================================
# define_module_var — 在模块作用域定义变量
# ============================================================
def define_module_var(symtab: SymbolTable | t.CPtr,
name: str,
alloca: llvmlite.Value | t.CPtr) -> int:
"""在模块作用域定义变量,返回 0 成功(委托到 gen.define_module_var)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.define_module_var(symtab, name, alloca)
return 0
# ============================================================
# lookup_var — 从当前作用域逐级向上查找变量
# ============================================================
def lookup_var(symtab: SymbolTable | t.CPtr,
name: str) -> llvmlite.Value | t.CPtr:
"""从当前作用域逐级向上查找变量,返回 alloca 或 None(委托到 gen.lookup_var)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.lookup_var(symtab, name)
return None
# ============================================================
# lookup_current — 仅在当前作用域查找变量
# ============================================================
def lookup_current(symtab: SymbolTable | t.CPtr,
name: str) -> llvmlite.Value | t.CPtr:
"""仅在当前作用域查找变量(委托到 gen.lookup_current)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.lookup_current(symtab, name)
return None
# ============================================================
# lookup_module_var — 在模块作用域查找变量
# ============================================================
def lookup_module_var(symtab: SymbolTable | t.CPtr,
name: str) -> llvmlite.Value | t.CPtr:
"""在模块作用域查找变量(委托到 gen.lookup_module_var)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.lookup_module_var(symtab, name)
return None
# ============================================================
# is_module_scope - 判断当前是否在模块级作用域
#
# 用于区分模块级代码和函数内代码:
# - 模块级代码:AnnAssign 应修改模块级变量(Python 语义)
# - 函数内代码:无 global 声明时 AnnAssign 应创建局部变量(Python 语义)
# ============================================================
def is_module_scope(symtab: SymbolTable | t.CPtr) -> int:
"""判断当前作用域是否为模块级作用域(Current == Root,委托到 gen.is_module_scope)
Returns: 1=模块级作用域, 0=函数内作用域
"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.is_module_scope(symtab)
return 0
# ============================================================
# get_or_create_sym — 查找或创建变量(在当前作用域)
# ============================================================
def get_or_create_sym(symtab: SymbolTable | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
name: str,
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
"""查找或创建变量 alloca(在当前作用域,委托到 gen.get_or_create_sym)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_or_create_sym(symtab, pool, builder, name, ty)
return None