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 规避循环依赖)。
393 lines
18 KiB
Plaintext
393 lines
18 KiB
Plaintext
import t, c
|
||
from stdint import *
|
||
import llvmlite
|
||
import memhub
|
||
import string
|
||
import lib.core.Handles.HandlesVar as HandlesVar
|
||
|
||
|
||
# ============================================================
|
||
# VarGenMixin - 变量/作用域符号表 Mixin(P6 对象化,wiki/14-oo-refactor.md)
|
||
#
|
||
# 从 HandlesVar.vp 迁移:模块级函数(init_vars/find_var/find_var_entry/
|
||
# lookup_var_entry/set_var_annot_class_name/set_var_ptr_element/add_var/
|
||
# _alloca_at_entry/get_or_create_var/_create_scope/init_symbol_table/
|
||
# enter_scope/exit_scope/define_var/define_module_var/lookup_var/
|
||
# lookup_current/lookup_module_var/is_module_scope/get_or_create_sym)
|
||
# → 本类方法。
|
||
#
|
||
# 迁移原则(与 P1-P5 一致,行为零变化):
|
||
# 1. 方法保留原函数签名(含 symtab/vars_ptr 等指针首参——self 是宿主
|
||
# Generator,这些函数操作数据结构指针,self 可能少用,但为风格
|
||
# 统一仍方法化)
|
||
# 2. 函数体原样搬入,本模块内部函数调用改为 self.xxx(...);
|
||
# 跨模块调用保留模块前缀(本模块无跨模块调用)
|
||
# 3. HandlesVar.vp 原函数保留为"一行委托":本地模块级单例 _g_gen
|
||
# (BuildPipeline/main 注入)cast 成 Generator 类型后调本类方法
|
||
# 4. VarEntry/Scope/SymbolTable 数据结构类保留在 HandlesVar.vp
|
||
# (本类方法签名/函数体经 HandlesVar 前缀引用)
|
||
#
|
||
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整,无 vtable 开销)。
|
||
# ============================================================
|
||
|
||
|
||
# ============================================================
|
||
# 常量(与 HandlesVar 保持一致)
|
||
# ============================================================
|
||
# 作用域类型常量
|
||
SCOPE_MODULE: t.CDefine = 0
|
||
SCOPE_FUNCTION: t.CDefine = 1
|
||
SCOPE_BLOCK: t.CDefine = 2
|
||
|
||
# 每个作用域最大变量数
|
||
MAX_VARS: t.CDefine = 256
|
||
|
||
|
||
# ============================================================
|
||
# VarGenMixin - 变量/作用域符号表 Mixin
|
||
# ============================================================
|
||
@t.NoVTable
|
||
class VarGenMixin:
|
||
"""变量/作用域 Mixin(P6 方法化)"""
|
||
# 迁移自 HandlesVar 的模块级函数
|
||
|
||
# ============================================================
|
||
# init_vars — 分配并清零 VarEntry 数组
|
||
# ============================================================
|
||
def init_vars(self, pool: memhub.MemBuddy | t.CPtr) -> HandlesVar.VarEntry | t.CPtr:
|
||
"""分配并清零变量表数组"""
|
||
size: t.CSizeT = MAX_VARS * HandlesVar.VarEntry.__sizeof__()
|
||
vars_ptr: HandlesVar.VarEntry | t.CPtr = pool.alloc(size)
|
||
if vars_ptr is not None:
|
||
string.memset(vars_ptr, 0, size)
|
||
return vars_ptr
|
||
|
||
# ============================================================
|
||
# find_var — 在变量表中按名称查找
|
||
# ============================================================
|
||
def find_var(self, vars_ptr: HandlesVar.VarEntry | t.CPtr,
|
||
var_count: int,
|
||
name: str) -> llvmlite.Value | t.CPtr:
|
||
"""在变量表中按名称查找"""
|
||
if name is None or vars_ptr is None:
|
||
return None
|
||
entry_size: t.CSizeT = HandlesVar.VarEntry.__sizeof__()
|
||
for i in range(var_count):
|
||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + i * entry_size
|
||
entry: HandlesVar.VarEntry | t.CPtr = (HandlesVar.VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||
if entry.Name is not None and entry.Used != 0:
|
||
if string.strcmp(entry.Name, name) == 0:
|
||
return entry.Alloca
|
||
return None
|
||
|
||
# ============================================================
|
||
# find_var_entry — 在变量表中按名称查找,返回 VarEntry(含 AnnotTy)
|
||
# ============================================================
|
||
def find_var_entry(self, vars_ptr: HandlesVar.VarEntry | t.CPtr,
|
||
var_count: int,
|
||
name: str) -> HandlesVar.VarEntry | t.CPtr:
|
||
"""在变量表中按名称查找,返回 VarEntry 或 None"""
|
||
if name is None or vars_ptr is None:
|
||
return None
|
||
entry_size: t.CSizeT = HandlesVar.VarEntry.__sizeof__()
|
||
for i in range(var_count):
|
||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + i * entry_size
|
||
entry: HandlesVar.VarEntry | t.CPtr = (HandlesVar.VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||
if entry.Name is not None and entry.Used != 0:
|
||
if string.strcmp(entry.Name, name) == 0:
|
||
return entry
|
||
return None
|
||
|
||
# ============================================================
|
||
# lookup_var_entry — 从当前作用域逐级向上查找变量,返回 VarEntry
|
||
# ============================================================
|
||
def lookup_var_entry(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||
name: str) -> HandlesVar.VarEntry | t.CPtr:
|
||
"""从当前作用域逐级向上查找变量,返回 VarEntry 或 None"""
|
||
if symtab is None or name is None:
|
||
return None
|
||
scope: HandlesVar.Scope | t.CPtr = symtab.Current
|
||
while scope is not None:
|
||
result: HandlesVar.VarEntry | t.CPtr = self.find_var_entry(scope.Vars, scope.VarCount, name)
|
||
if result is not None:
|
||
return result
|
||
scope = scope.Parent
|
||
return None
|
||
|
||
# ============================================================
|
||
# set_var_annot_class_name — 设置变量的原始类型注解类名
|
||
#
|
||
# 在函数参数定义后调用,存储原始类型注解的类名。
|
||
# 方法调用检测时,当 alloca 类型是 Ptr(i8)(联合类型简化),
|
||
# 通过 AnnotClassName 查找实际结构体类型。
|
||
# ============================================================
|
||
def set_var_annot_class_name(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||
name: str,
|
||
class_name: str) -> int:
|
||
"""设置变量的原始类型注解类名,返回 0=成功 / 1=失败"""
|
||
if symtab is None or name is None:
|
||
return 1
|
||
entry: HandlesVar.VarEntry | t.CPtr = self.lookup_var_entry(symtab, name)
|
||
if entry is None:
|
||
return 1
|
||
entry.AnnotClassName = 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(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||
name: str) -> int:
|
||
"""标记变量为 ptr_element 类型,返回 0=成功 / 1=失败"""
|
||
if symtab is None or name is None:
|
||
return 1
|
||
entry: HandlesVar.VarEntry | t.CPtr = self.lookup_var_entry(symtab, name)
|
||
if entry is None:
|
||
return 1
|
||
entry.IsPtrElement = 1
|
||
return 0
|
||
|
||
# ============================================================
|
||
# add_var — 添加变量到变量表
|
||
# ============================================================
|
||
def add_var(self, vars_ptr: HandlesVar.VarEntry | t.CPtr,
|
||
var_count: int,
|
||
name: str,
|
||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||
"""添加变量到变量表"""
|
||
if name is None or alloca is None or vars_ptr is None:
|
||
return 1
|
||
if var_count >= MAX_VARS:
|
||
return 1
|
||
entry_size: t.CSizeT = HandlesVar.VarEntry.__sizeof__()
|
||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + var_count * entry_size
|
||
entry: HandlesVar.VarEntry | t.CPtr = (HandlesVar.VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||
entry.Name = name
|
||
entry.Alloca = alloca
|
||
entry.Used = 1
|
||
return 0
|
||
|
||
# ============================================================
|
||
# _alloca_at_entry - 在函数入口块生成 alloca(确保支配性)
|
||
#
|
||
# LLVM IR 要求指令支配所有使用点。如果 alloca 在条件分支内生成,
|
||
# 但在其他分支使用,会违反支配性(Instruction does not dominate all uses)。
|
||
# 标准做法:所有 alloca 在函数入口块生成。
|
||
#
|
||
# 临时切换 builder.CurBlock 到入口块,生成 alloca,然后恢复。
|
||
# ============================================================
|
||
def _alloca_at_entry(self, builder: llvmlite.IRBuilder | t.CPtr,
|
||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||
"""在函数入口块生成 alloca,返回 alloca 值
|
||
|
||
使用 llvmlite.build_alloca_at_entry 在入口块终止指令之前插入 alloca,
|
||
确保所有 alloca 在入口块,避免支配性违规。
|
||
"""
|
||
if builder is None or ty is None:
|
||
return None
|
||
return llvmlite.build_alloca_at_entry(builder, ty)
|
||
|
||
# ============================================================
|
||
# get_or_create_var — 查找或创建变量 alloca(旧版兼容)
|
||
# ============================================================
|
||
def get_or_create_var(self, pool: memhub.MemBuddy | t.CPtr,
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
vars_ptr: HandlesVar.VarEntry | t.CPtr,
|
||
var_count: int,
|
||
name: str,
|
||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||
"""查找或创建变量 alloca"""
|
||
existing: llvmlite.Value | t.CPtr = self.find_var(vars_ptr, var_count, name)
|
||
if existing is not None:
|
||
return existing
|
||
alloca: llvmlite.Value | t.CPtr = self._alloca_at_entry(builder, ty)
|
||
if alloca is None:
|
||
return None
|
||
if self.add_var(vars_ptr, var_count, name, alloca) != 0:
|
||
return None
|
||
return alloca
|
||
|
||
# ============================================================
|
||
# _create_scope — 创建新作用域节点(内部辅助函数)
|
||
# ============================================================
|
||
def _create_scope(self, pool: memhub.MemBuddy | t.CPtr,
|
||
parent: HandlesVar.Scope | t.CPtr,
|
||
kind: int) -> HandlesVar.Scope | t.CPtr:
|
||
"""创建并初始化作用域节点"""
|
||
scope: HandlesVar.Scope | t.CPtr = pool.alloc(HandlesVar.Scope.__sizeof__())
|
||
if scope is None:
|
||
return None
|
||
string.memset(scope, 0, HandlesVar.Scope.__sizeof__())
|
||
scope.Parent = parent
|
||
scope.Vars = self.init_vars(pool)
|
||
scope.VarCount = 0
|
||
scope.Kind = kind
|
||
if scope.Vars is None:
|
||
return None
|
||
return scope
|
||
|
||
# ============================================================
|
||
# init_symbol_table — 创建符号表(含模块级根作用域)
|
||
# ============================================================
|
||
def init_symbol_table(self, pool: memhub.MemBuddy | t.CPtr) -> HandlesVar.SymbolTable | t.CPtr:
|
||
"""创建并初始化符号表,包含模块级根作用域"""
|
||
if pool is None:
|
||
return None
|
||
symtab: HandlesVar.SymbolTable | t.CPtr = pool.alloc(HandlesVar.SymbolTable.__sizeof__())
|
||
if symtab is None:
|
||
return None
|
||
string.memset(symtab, 0, HandlesVar.SymbolTable.__sizeof__())
|
||
symtab.Pool = pool
|
||
|
||
# 创建根作用域(模块级)
|
||
root: HandlesVar.Scope | t.CPtr = self._create_scope(pool, None, SCOPE_MODULE)
|
||
if root is None:
|
||
return None
|
||
|
||
symtab.Root = root
|
||
symtab.Current = root
|
||
return symtab
|
||
|
||
# ============================================================
|
||
# enter_scope — 进入新作用域
|
||
# ============================================================
|
||
def enter_scope(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||
kind: int) -> HandlesVar.Scope | t.CPtr:
|
||
"""进入新作用域,返回新创建的作用域"""
|
||
if symtab is None:
|
||
return None
|
||
pool: memhub.MemBuddy | t.CPtr = symtab.Pool
|
||
scope: HandlesVar.Scope | t.CPtr = self._create_scope(pool, symtab.Current, kind)
|
||
if scope is None:
|
||
return None
|
||
symtab.Current = scope
|
||
return scope
|
||
|
||
# ============================================================
|
||
# exit_scope — 退出当前作用域
|
||
# ============================================================
|
||
def exit_scope(self, symtab: HandlesVar.SymbolTable | t.CPtr):
|
||
"""退出当前作用域,恢复到父作用域"""
|
||
if symtab is not None and symtab.Current is not None:
|
||
symtab.Current = symtab.Current.Parent
|
||
|
||
# ============================================================
|
||
# define_var — 在当前作用域定义变量
|
||
# ============================================================
|
||
def define_var(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||
name: str,
|
||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||
"""在当前作用域定义变量,返回 0 成功"""
|
||
if symtab is None or name is None or alloca is None:
|
||
return 1
|
||
scope: HandlesVar.Scope | t.CPtr = symtab.Current
|
||
if scope is None:
|
||
return 1
|
||
ret: int = self.add_var(scope.Vars, scope.VarCount, name, alloca)
|
||
if ret == 0:
|
||
scope.VarCount = scope.VarCount + 1
|
||
return ret
|
||
|
||
# ============================================================
|
||
# define_module_var — 在模块作用域定义变量
|
||
# ============================================================
|
||
def define_module_var(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||
name: str,
|
||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||
"""在模块作用域定义变量,返回 0 成功"""
|
||
if symtab is None or name is None or alloca is None:
|
||
return 1
|
||
scope: HandlesVar.Scope | t.CPtr = symtab.Root
|
||
if scope is None:
|
||
return 1
|
||
ret: int = self.add_var(scope.Vars, scope.VarCount, name, alloca)
|
||
if ret == 0:
|
||
scope.VarCount = scope.VarCount + 1
|
||
return ret
|
||
|
||
# ============================================================
|
||
# lookup_var — 从当前作用域逐级向上查找变量
|
||
# ============================================================
|
||
def lookup_var(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||
name: str) -> llvmlite.Value | t.CPtr:
|
||
"""从当前作用域逐级向上查找变量,返回 alloca 或 None"""
|
||
if symtab is None or name is None:
|
||
return None
|
||
scope: HandlesVar.Scope | t.CPtr = symtab.Current
|
||
while scope is not None:
|
||
result: llvmlite.Value | t.CPtr = self.find_var(
|
||
scope.Vars, scope.VarCount, name)
|
||
if result is not None:
|
||
return result
|
||
scope = scope.Parent
|
||
return None
|
||
|
||
# ============================================================
|
||
# lookup_current — 仅在当前作用域查找变量
|
||
# ============================================================
|
||
def lookup_current(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||
name: str) -> llvmlite.Value | t.CPtr:
|
||
"""仅在当前作用域查找变量"""
|
||
if symtab is None or name is None:
|
||
return None
|
||
scope: HandlesVar.Scope | t.CPtr = symtab.Current
|
||
if scope is None:
|
||
return None
|
||
return self.find_var(scope.Vars, scope.VarCount, name)
|
||
|
||
# ============================================================
|
||
# lookup_module_var — 在模块作用域查找变量
|
||
# ============================================================
|
||
def lookup_module_var(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||
name: str) -> llvmlite.Value | t.CPtr:
|
||
"""在模块作用域查找变量"""
|
||
if symtab is None or name is None:
|
||
return None
|
||
scope: HandlesVar.Scope | t.CPtr = symtab.Root
|
||
if scope is None:
|
||
return None
|
||
return self.find_var(scope.Vars, scope.VarCount, name)
|
||
|
||
# ============================================================
|
||
# is_module_scope - 判断当前是否在模块级作用域
|
||
#
|
||
# 用于区分模块级代码和函数内代码:
|
||
# - 模块级代码:AnnAssign 应修改模块级变量(Python 语义)
|
||
# - 函数内代码:无 global 声明时 AnnAssign 应创建局部变量(Python 语义)
|
||
# ============================================================
|
||
def is_module_scope(self, symtab: HandlesVar.SymbolTable | t.CPtr) -> int:
|
||
"""判断当前作用域是否为模块级作用域(Current == Root)
|
||
|
||
Returns: 1=模块级作用域, 0=函数内作用域
|
||
"""
|
||
if symtab is None:
|
||
return 0
|
||
if symtab.Root is None or symtab.Current is None:
|
||
return 0
|
||
# 比较指针:Current 与 Root 相同则为模块级
|
||
if t.CUInt64T(symtab.Current) == t.CUInt64T(symtab.Root):
|
||
return 1
|
||
return 0
|
||
|
||
# ============================================================
|
||
# get_or_create_sym — 查找或创建变量(在当前作用域)
|
||
# ============================================================
|
||
def get_or_create_sym(self, symtab: HandlesVar.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(在当前作用域)"""
|
||
existing: llvmlite.Value | t.CPtr = self.lookup_current(symtab, name)
|
||
if existing is not None:
|
||
return existing
|
||
alloca: llvmlite.Value | t.CPtr = self._alloca_at_entry(builder, ty)
|
||
if alloca is None:
|
||
return None
|
||
self.define_var(symtab, name, alloca)
|
||
return alloca
|