282 lines
12 KiB
Python
282 lines
12 KiB
Python
import t, c
|
||
from stdint import *
|
||
import ast
|
||
import llvmlite
|
||
import memhub
|
||
import string
|
||
import lib.core.Handles.HandlesBase as HandlesBase
|
||
import lib.core.Handles.HandlesTranslator as HT
|
||
import lib.core.Handles.HandlesVar as HandlesVar
|
||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||
import lib.core.Handles.HandlesType as HandlesType
|
||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||
|
||
|
||
# ============================================================
|
||
# HandlesAnnAssign - AnnAssign 语句处理(Mixin 继承模式)
|
||
# ============================================================
|
||
|
||
|
||
# ============================================================
|
||
# is_cdefine_annotation - 检测注解是否为 t.CDefine(模块级函数)
|
||
#
|
||
# 支持两种形式:
|
||
# 1. Attribute(Name('t'), 'CDefine')
|
||
# 2. BinOp(... | Attribute(Name('t'), 'CDefine'))(联合注解)
|
||
# ============================================================
|
||
def is_cdefine_annotation(annot: ast.AST | t.CPtr) -> int:
|
||
"""检测注解是否为 t.CDefine,返回 1 表示是,0 表示否"""
|
||
if annot is None:
|
||
return 0
|
||
k: int = annot.kind()
|
||
if k == ast.ASTKind.Attribute:
|
||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annot)
|
||
if at.attr is not None and string.strcmp(at.attr, "CDefine") == 0:
|
||
return 1
|
||
return 0
|
||
if k == ast.ASTKind.BinOp:
|
||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(annot)
|
||
if is_cdefine_annotation(bop.left) != 0:
|
||
return 1
|
||
if is_cdefine_annotation(bop.right) != 0:
|
||
return 1
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# extract_cdefine_int_value - 从 AnnAssign.value 提取整数常量(模块级函数)
|
||
#
|
||
# 仅支持 ast.Constant(INT),其他形式返回 0
|
||
# ============================================================
|
||
def extract_cdefine_int_value(val_node: ast.AST | t.CPtr) -> int:
|
||
"""从值节点提取整数常量(仅支持 Constant INT)"""
|
||
if val_node is None:
|
||
return 0
|
||
if val_node.kind() != ast.ASTKind.Constant:
|
||
return 0
|
||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(val_node)
|
||
if cn.const_kind != ast.CONST_INT:
|
||
return 0
|
||
return cn.int_val
|
||
|
||
|
||
@t.NoVTable
|
||
class AnnAssignHandle(HandlesBase.Mixin):
|
||
"""AnnAssign 语句处理器:继承 Mixin 获得 Trans 回指针"""
|
||
|
||
def __init__(self, trans: HT.Translator | t.CPtr):
|
||
self.Trans = trans
|
||
|
||
# ============================================================
|
||
# PreScan - 预扫描 AnnAssign,为有类型注解的变量提前创建 alloca
|
||
#
|
||
# 返回新增的变量数
|
||
# ============================================================
|
||
def PreScan(self, node: ast.AST | t.CPtr) -> int:
|
||
"""预扫描 AnnAssign,提前创建 alloca 到 entry block 顶部"""
|
||
if node is None:
|
||
return 0
|
||
k: int = node.kind()
|
||
if k != ast.ASTKind.AnnAssign:
|
||
return 0
|
||
|
||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
|
||
if aa is None or aa.target is None:
|
||
return 0
|
||
target: ast.AST | t.CPtr = aa.target
|
||
if target.kind() != ast.ASTKind.Name:
|
||
return 0
|
||
|
||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(target)
|
||
if nm.id is None:
|
||
return 0
|
||
|
||
# CDefine 注解: 不创建 alloca,但注册常量到全局表
|
||
# 供后续 t.CArray[elem_ty, NAME] 编译期解析使用
|
||
if is_cdefine_annotation(aa.annotation) != 0:
|
||
pool_ps: memhub.MemBuddy | t.CPtr = self.Trans.Pool
|
||
val_ps: int = extract_cdefine_int_value(aa.value)
|
||
HandlesType.register_cdefine_constant(pool_ps, nm.id, val_ps)
|
||
return 0
|
||
|
||
# global/nonlocal 变量不需要局部 alloca
|
||
if HT.is_global_name(self.Trans, nm.id) != 0:
|
||
return 0
|
||
if HT.is_nonlocal_name(self.Trans, nm.id) != 0:
|
||
return 0
|
||
|
||
# 检查是否已存在
|
||
existing: llvmlite.Value | t.CPtr = HandlesVar.lookup_current(
|
||
self.Trans.SymTab, nm.id)
|
||
if existing is not None:
|
||
return 0
|
||
|
||
pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool
|
||
builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder
|
||
|
||
# 从 annotation 推断类型(修复:原硬编码 i32 导致 str 等类型错误)
|
||
var_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
annot: ast.AST | t.CPtr = aa.annotation
|
||
if annot is not None:
|
||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||
pool, annot, self.Trans._imported_modules, self.Trans._from_imports)
|
||
if resolved is None:
|
||
# 尝试特化泛型类注解(如 list[str])
|
||
# resolve_annotation_type 返回 None 可能是因为泛型类未特化
|
||
if annot.kind() == ast.ASTKind.Subscript:
|
||
sub_annot: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(annot)
|
||
if sub_annot.value is not None and sub_annot.value.kind() == ast.ASTKind.Name:
|
||
sub_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub_annot.value)
|
||
if sub_nm.id is not None:
|
||
template_cd: ast.ClassDef | t.CPtr = HandlesClassDef._find_generic_template(sub_nm.id)
|
||
if template_cd is not None:
|
||
type_args_ps: list[str] | t.CPtr = HandlesExprCall._extract_type_args_from_slice(pool, sub_annot.slice)
|
||
if type_args_ps is not None and type_args_ps.__len__() > 0:
|
||
spec_name_ps: str = HandlesClassDef._specialize_generic_class(
|
||
self.Trans, sub_nm.id, type_args_ps)
|
||
if spec_name_ps is not None:
|
||
resolved = HandlesType.resolve_annotation_type(
|
||
pool, annot, self.Trans._imported_modules, self.Trans._from_imports)
|
||
if resolved is not None:
|
||
var_ty = resolved
|
||
|
||
alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, var_ty)
|
||
if alloca is not None:
|
||
if HandlesVar.define_var(
|
||
self.Trans.SymTab, nm.id, alloca) == 0:
|
||
# 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体)
|
||
if annot is not None:
|
||
cls_nm_ps: str = HandlesType.extract_class_name_from_annotation(
|
||
annot, self.Trans._imported_modules)
|
||
if cls_nm_ps is not None:
|
||
HandlesVar.set_var_annot_class_name(
|
||
self.Trans.SymTab, nm.id, cls_nm_ps)
|
||
return 0
|
||
return 0
|
||
|
||
# ============================================================
|
||
# Handle - 翻译 AnnAssign 语句
|
||
#
|
||
# 返回新增的变量数
|
||
# ============================================================
|
||
def Handle(self, node: ast.AST | t.CPtr) -> int:
|
||
"""翻译 AnnAssign(target=Name, annotation=..., value=expr)"""
|
||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
|
||
if aa is None:
|
||
return 0
|
||
|
||
target: ast.AST | t.CPtr = aa.target
|
||
if target is None or target.kind() != ast.ASTKind.Name:
|
||
return 0
|
||
|
||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(target)
|
||
if nm.id is None:
|
||
return 0
|
||
|
||
# CDefine 注解: 编译期常量,不生成运行时代码
|
||
# 注册到全局 CDefine 表供 t.CArray[elem_ty, NAME] 解析
|
||
# 注: PreScan 已注册过,此处保证即使跳过 PreScan 也能正确注册
|
||
if is_cdefine_annotation(aa.annotation) != 0:
|
||
pool_cd: memhub.MemBuddy | t.CPtr = self.Trans.Pool
|
||
val_cd: int = extract_cdefine_int_value(aa.value)
|
||
HandlesType.register_cdefine_constant(pool_cd, nm.id, val_cd)
|
||
return 0
|
||
|
||
pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool
|
||
builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder
|
||
mod: llvmlite.LLVMModule | t.CPtr = self.Trans.Module
|
||
|
||
# 确定类型(从 annotation 推断)
|
||
var_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
annot: ast.AST | t.CPtr = aa.annotation
|
||
if annot is not None:
|
||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||
pool, annot, self.Trans._imported_modules, self.Trans._from_imports)
|
||
if resolved is not None:
|
||
var_ty = resolved
|
||
|
||
# global 变量:写入模块作用域中的全局变量
|
||
if HT.is_global_name(self.Trans, nm.id) != 0:
|
||
mod_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var(
|
||
self.Trans.SymTab, nm.id)
|
||
if mod_alloca is not None and aa.value is not None:
|
||
rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, mod, aa.value,
|
||
None, 0, self.Trans)
|
||
if rhs_val is not None:
|
||
target_ty: llvmlite.LLVMType | t.CPtr = None
|
||
if mod_alloca.Ty is not None:
|
||
target_ty = mod_alloca.Ty.Pointee
|
||
if target_ty is not None:
|
||
rhs_val = HandlesExpr.coerce_to_type(builder, rhs_val, target_ty)
|
||
llvmlite.build_store(builder, rhs_val, mod_alloca)
|
||
return 0
|
||
|
||
# nonlocal 变量:通过闭包 env 写入
|
||
if HT.is_nonlocal_name(self.Trans, nm.id) != 0:
|
||
if aa.value is not None:
|
||
rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, mod, aa.value,
|
||
None, 0, self.Trans)
|
||
if rhs_val is not None:
|
||
nl_ptr: llvmlite.Value | t.CPtr = HandlesNonlocal.get_nonlocal_var_ptr(
|
||
self.Trans, nm.id)
|
||
if nl_ptr is not None:
|
||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
rhs_coerced: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type(
|
||
builder, rhs_val, i32_ty)
|
||
llvmlite.build_store(builder, rhs_coerced, nl_ptr)
|
||
return 0
|
||
|
||
# 普通局部变量
|
||
# 创建 alloca
|
||
alloca: llvmlite.Value | t.CPtr = HandlesVar.get_or_create_sym(
|
||
self.Trans.SymTab, pool, builder, nm.id, var_ty)
|
||
if alloca is None:
|
||
return 0
|
||
# 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体)
|
||
if annot is not None:
|
||
cls_nm_hd: str = HandlesType.extract_class_name_from_annotation(
|
||
annot, self.Trans._imported_modules)
|
||
if cls_nm_hd is not None:
|
||
HandlesVar.set_var_annot_class_name(
|
||
self.Trans.SymTab, nm.id, cls_nm_hd)
|
||
|
||
new_vars: int = 0
|
||
existing: llvmlite.Value | t.CPtr = HandlesVar.lookup_current(
|
||
self.Trans.SymTab, nm.id)
|
||
if existing is None:
|
||
new_vars = 1
|
||
|
||
# 如果有初始值,store
|
||
if aa.value is not None:
|
||
rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, mod, aa.value,
|
||
None, 0, self.Trans)
|
||
if rhs_val is not None:
|
||
# 类型转换:将 rhs_val 转换为 alloca 的 pointee 类型
|
||
# 修复:整数字面量是 i32,但变量可能是 i8/i16/i64,需 trunc/sext
|
||
target_ty: llvmlite.LLVMType | t.CPtr = None
|
||
if alloca.Ty is not None:
|
||
target_ty = alloca.Ty.Pointee
|
||
if target_ty is not None:
|
||
rhs_val = HandlesExpr.coerce_to_type(builder, rhs_val, target_ty)
|
||
llvmlite.build_store(builder, rhs_val, alloca)
|
||
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# NewAnnAssignHandle - 工厂函数
|
||
# ============================================================
|
||
def NewAnnAssignHandle(pool: memhub.MemBuddy | t.CPtr,
|
||
trans: HT.Translator | t.CPtr) -> AnnAssignHandle | t.CPtr:
|
||
h: AnnAssignHandle | t.CPtr = pool.alloc(AnnAssignHandle.__sizeof__())
|
||
if h is None:
|
||
return None
|
||
string.memset(h, 0, AnnAssignHandle.__sizeof__())
|
||
h.Trans = trans
|
||
return h
|