316 lines
13 KiB
Python
316 lines
13 KiB
Python
import t, c
|
||
from stdint import *
|
||
import ast
|
||
import llvmlite
|
||
import memhub
|
||
import stdio
|
||
import string
|
||
import viperlib
|
||
import lib.core.VLogger as VLogger
|
||
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.HandlesNonlocal as HandlesNonlocal
|
||
|
||
|
||
# ============================================================
|
||
# HandlesAugAssign - 增强赋值语句处理(Mixin 继承模式)
|
||
#
|
||
# 处理 += -= *= /= %= &= |= ^= <<= >>=
|
||
# 流程: load target → apply binop → store result
|
||
#
|
||
# 支持 local/global/nonlocal 三种变量作用域
|
||
# ============================================================
|
||
|
||
|
||
@t.NoVTable
|
||
class AugAssignHandle(HandlesBase.Mixin):
|
||
"""增强赋值处理器 (+=, -=, *=, etc.):继承 Mixin 获得 Trans 回指针"""
|
||
|
||
def __init__(self, trans: HT.Translator | t.CPtr):
|
||
self.Trans = trans
|
||
|
||
# ============================================================
|
||
# Handle - 处理 AugAssign 语句,返回新增变量数(始终为 0)
|
||
# ============================================================
|
||
def Handle(self, node: ast.AST | t.CPtr) -> int:
|
||
"""翻译增强赋值语句 (x += 1, y -= 2, etc.)"""
|
||
if node is None:
|
||
return 0
|
||
|
||
aug: ast.AugAssign | t.CPtr = (ast.AugAssign | t.CPtr)(node)
|
||
if aug is None:
|
||
return 0
|
||
|
||
target: ast.AST | t.CPtr = aug.target
|
||
if target is None:
|
||
return 0
|
||
|
||
tk: int = target.kind()
|
||
|
||
# Attribute 目标: self.field += 1
|
||
# 流程: get_attribute_ptr → load → binop → store
|
||
if tk == ast.ASTKind.Attribute:
|
||
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
|
||
|
||
# 1. 获取字段指针
|
||
field_ptr: llvmlite.Value | t.CPtr = HandlesExpr.get_attribute_ptr(
|
||
builder, pool, mod, target, self.Trans)
|
||
if field_ptr is None:
|
||
VLogger.error("attribute ptr is None", "AUGASGN")
|
||
return 0
|
||
|
||
# 2. 确定字段类型并加载当前值
|
||
target_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
if field_ptr.Ty is not None:
|
||
target_ty = field_ptr.Ty.Pointee
|
||
cur_val: llvmlite.Value | t.CPtr = llvmlite.build_load(
|
||
builder, target_ty, field_ptr)
|
||
if cur_val is None:
|
||
VLogger.error("cannot load attribute", "AUGASGN")
|
||
return 0
|
||
|
||
# 3. 翻译 RHS 值
|
||
rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, mod, aug.value, None, 0, self.Trans)
|
||
if rhs_val is None:
|
||
VLogger.error("rhs is None", "AUGASGN")
|
||
return 0
|
||
|
||
# 4. 应用二元运算
|
||
result: llvmlite.Value | t.CPtr = _apply_aug_op(
|
||
pool, builder, aug.op, cur_val, rhs_val)
|
||
if result is None:
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "binop failed for attr op=%d", aug.op)
|
||
VLogger.error(fb, "AUGASGN")
|
||
return 0
|
||
|
||
# 5. 类型对齐并存储
|
||
result = HandlesExpr.coerce_to_type(builder, result, target_ty)
|
||
if result is None:
|
||
return 0
|
||
llvmlite.build_store(builder, result, field_ptr)
|
||
return 0
|
||
|
||
# Subscript 目标: self.state[i] += x / arr[i] += x
|
||
# 流程: get_subscript_ptr → load → binop → store
|
||
if tk == ast.ASTKind.Subscript:
|
||
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
|
||
|
||
# 1. 获取元素指针
|
||
elem_ptr: llvmlite.Value | t.CPtr = HandlesExpr.get_subscript_ptr(
|
||
builder, pool, mod, target, self.Trans)
|
||
if elem_ptr is None:
|
||
VLogger.error("subscript ptr is None", "AUGASGN")
|
||
return 0
|
||
|
||
# 2. 确定元素类型并加载当前值
|
||
target_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
if elem_ptr.Ty is not None and elem_ptr.Ty.Pointee is not None:
|
||
target_ty = elem_ptr.Ty.Pointee
|
||
cur_val: llvmlite.Value | t.CPtr = llvmlite.build_load(
|
||
builder, target_ty, elem_ptr)
|
||
if cur_val is None:
|
||
VLogger.error("cannot load subscript element", "AUGASGN")
|
||
return 0
|
||
|
||
# 3. 翻译 RHS 值
|
||
rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, mod, aug.value, None, 0, self.Trans)
|
||
if rhs_val is None:
|
||
VLogger.error("rhs is None", "AUGASGN")
|
||
return 0
|
||
|
||
# 4. 应用二元运算
|
||
result: llvmlite.Value | t.CPtr = _apply_aug_op(
|
||
pool, builder, aug.op, cur_val, rhs_val)
|
||
if result is None:
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "binop failed for sub op=%d", aug.op)
|
||
VLogger.error(fb, "AUGASGN")
|
||
return 0
|
||
|
||
# 5. 类型对齐并存储
|
||
result = HandlesExpr.coerce_to_type(builder, result, target_ty)
|
||
if result is None:
|
||
return 0
|
||
llvmlite.build_store(builder, result, elem_ptr)
|
||
return 0
|
||
|
||
if tk != ast.ASTKind.Name:
|
||
VLogger.error("only Name/Attribute/Subscript target supported", "AUGASGN")
|
||
return 0
|
||
|
||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(target)
|
||
if nm is None or nm.id is None:
|
||
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
|
||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||
|
||
# 1. 确定变量作用域类型: 0=local, 1=global, 2=nonlocal
|
||
scope_type: int = 0
|
||
if HT.is_global_name(self.Trans, nm.id) != 0:
|
||
scope_type = 1
|
||
elif HT.is_nonlocal_name(self.Trans, nm.id) != 0:
|
||
scope_type = 2
|
||
|
||
# 2. 加载当前值
|
||
cur_val: llvmlite.Value | t.CPtr = None
|
||
target_alloca: llvmlite.Value | t.CPtr = None
|
||
target_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||
|
||
if scope_type == 1:
|
||
# global 变量
|
||
target_alloca = HandlesVar.lookup_module_var(
|
||
self.Trans.SymTab, nm.id)
|
||
if target_alloca is not None:
|
||
if target_alloca.Ty is not None:
|
||
target_ty = target_alloca.Ty.Pointee
|
||
cur_val = llvmlite.build_load(builder, target_ty, target_alloca)
|
||
elif scope_type == 2:
|
||
# nonlocal 变量(通过闭包 env)
|
||
cur_val = HandlesNonlocal.load_nonlocal_var(self.Trans, nm.id)
|
||
if cur_val is not None:
|
||
target_ty = cur_val.Ty
|
||
else:
|
||
# 普通局部变量
|
||
target_alloca = HandlesVar.lookup_var(self.Trans.SymTab, nm.id)
|
||
if target_alloca is not None:
|
||
if target_alloca.Ty is not None:
|
||
target_ty = target_alloca.Ty.Pointee
|
||
cur_val = llvmlite.build_load(builder, target_ty, target_alloca)
|
||
|
||
if cur_val is None:
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "cannot load target %s", nm.id)
|
||
VLogger.error(fb, "AUGASGN")
|
||
return 0
|
||
|
||
# 3. 翻译 RHS 值
|
||
rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||
builder, pool, mod, aug.value, None, 0, self.Trans)
|
||
if rhs_val is None:
|
||
VLogger.error("rhs is None", "AUGASGN")
|
||
return 0
|
||
|
||
# 4. 类型对齐 + 应用二元运算
|
||
# 注意: AugAssign 不走运算符重载(语义上需要 __iadd__ 而非 __add__)
|
||
result: llvmlite.Value | t.CPtr = _apply_aug_op(
|
||
pool, builder, aug.op, cur_val, rhs_val)
|
||
if result is None:
|
||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||
if fb is not None:
|
||
viperlib.snprintf(fb, 1024, "binop failed for op=%d", aug.op)
|
||
VLogger.error(fb, "AUGASGN")
|
||
return 0
|
||
|
||
# 5. 存储结果
|
||
result = HandlesExpr.coerce_to_type(builder, result, target_ty)
|
||
if result is None:
|
||
return 0
|
||
|
||
if scope_type == 1:
|
||
# global 变量
|
||
if target_alloca is not None:
|
||
llvmlite.build_store(builder, result, target_alloca)
|
||
elif scope_type == 2:
|
||
# nonlocal 变量
|
||
nl_ptr: llvmlite.Value | t.CPtr = HandlesNonlocal.get_nonlocal_var_ptr(
|
||
self.Trans, nm.id)
|
||
if nl_ptr is not None:
|
||
llvmlite.build_store(builder, result, nl_ptr)
|
||
else:
|
||
# 普通局部变量
|
||
if target_alloca is not None:
|
||
llvmlite.build_store(builder, result, target_alloca)
|
||
|
||
return 0
|
||
|
||
|
||
# ============================================================
|
||
# _apply_aug_op - 应用增强赋值的二元运算
|
||
#
|
||
# 支持指针算术: ptr += int / ptr -= int
|
||
# 整数运算自动类型提升
|
||
# ============================================================
|
||
def _apply_aug_op(pool: memhub.MemBuddy | t.CPtr,
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
op: int,
|
||
lhs: llvmlite.Value | t.CPtr,
|
||
rhs: llvmlite.Value | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||
"""应用增强赋值的二元运算(指针算术 + 整数运算)"""
|
||
lhs_bits: int = HandlesExpr.get_llvm_type_bits(lhs.Ty)
|
||
rhs_bits: int = HandlesExpr.get_llvm_type_bits(rhs.Ty)
|
||
|
||
# 指针算术: ptr += int / ptr -= int
|
||
if lhs_bits == 0 and rhs_bits != 0:
|
||
if op == ast.OpKind.Add or op == ast.OpKind.Sub:
|
||
i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool)
|
||
ptr_as_int: llvmlite.Value | t.CPtr = llvmlite.build_ptrtoint(builder, lhs, i64_ty)
|
||
int_val: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type(builder, rhs, i64_ty)
|
||
if ptr_as_int is None or int_val is None:
|
||
return None
|
||
if op == ast.OpKind.Add:
|
||
result: llvmlite.Value | t.CPtr = llvmlite.build_add(builder, ptr_as_int, int_val)
|
||
else:
|
||
result = llvmlite.build_sub(builder, ptr_as_int, int_val)
|
||
if result is None:
|
||
return None
|
||
return llvmlite.build_inttoptr(builder, result, lhs.Ty)
|
||
return None
|
||
|
||
# 整数运算:类型提升
|
||
if lhs_bits > rhs_bits and rhs_bits > 0:
|
||
rhs = HandlesExpr.coerce_to_type(builder, rhs, lhs.Ty)
|
||
elif rhs_bits > lhs_bits and lhs_bits > 0:
|
||
lhs = HandlesExpr.coerce_to_type(builder, lhs, rhs.Ty)
|
||
|
||
if op == ast.OpKind.Add:
|
||
return llvmlite.build_add(builder, lhs, rhs)
|
||
elif op == ast.OpKind.Sub:
|
||
return llvmlite.build_sub(builder, lhs, rhs)
|
||
elif op == ast.OpKind.Mult:
|
||
return llvmlite.build_mul(builder, lhs, rhs)
|
||
elif op == ast.OpKind.Div:
|
||
return llvmlite.build_sdiv(builder, lhs, rhs)
|
||
elif op == ast.OpKind.FloorDiv:
|
||
return llvmlite.build_sdiv(builder, lhs, rhs)
|
||
elif op == ast.OpKind.Mod:
|
||
return llvmlite.build_srem(builder, lhs, rhs)
|
||
elif op == ast.OpKind.BitAnd:
|
||
return llvmlite.build_and(builder, lhs, rhs)
|
||
elif op == ast.OpKind.BitOr:
|
||
return llvmlite.build_or(builder, lhs, rhs)
|
||
elif op == ast.OpKind.BitXor:
|
||
return llvmlite.build_xor(builder, lhs, rhs)
|
||
elif op == ast.OpKind.LShift:
|
||
return llvmlite.build_shl(builder, lhs, rhs)
|
||
elif op == ast.OpKind.RShift:
|
||
return llvmlite.build_ashr(builder, lhs, rhs)
|
||
return None
|
||
|
||
|
||
# ============================================================
|
||
# NewAugAssignHandle - 工厂函数
|
||
# ============================================================
|
||
def NewAugAssignHandle(pool: memhub.MemBuddy | t.CPtr,
|
||
trans: HT.Translator | t.CPtr) -> AugAssignHandle | t.CPtr:
|
||
h: AugAssignHandle | t.CPtr = pool.alloc(AugAssignHandle.__sizeof__())
|
||
if h is None:
|
||
return None
|
||
string.memset(h, 0, AugAssignHandle.__sizeof__())
|
||
h.Trans = trans
|
||
return h
|