- 删除 Handles 各模块已迁移至 Gen 的旧函数体,保留一行委托壳(25 文件 -798 行) - main.vp / BuildPipeline.vp 全局单例注入改为 _g_gen 直接赋值 - 机械化迁移测试前的基线备份
372 lines
16 KiB
Plaintext
372 lines
16 KiB
Plaintext
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
|