Files
TransPyV/App/lib/core/Handles/HandlesAugAssign.py
2026-07-19 13:18:46 +08:00

255 lines
9.9 KiB
Python
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 ast
import llvmlite
import memhub
import stdio
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.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:
stdio.printf("[AUGASGN] attribute ptr is None\n")
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:
stdio.printf("[AUGASGN] cannot load attribute\n")
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:
stdio.printf("[AUGASGN] rhs is None\n")
return 0
# 4. 应用二元运算
result: llvmlite.Value | t.CPtr = _apply_aug_op(
pool, builder, aug.op, cur_val, rhs_val)
if result is None:
stdio.printf("[AUGASGN] binop failed for attr op=%d\n", aug.op)
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
if tk != ast.ASTKind.Name:
stdio.printf("[AUGASGN] only Name/Attribute target supported\n")
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:
stdio.printf("[AUGASGN] cannot load target %s\n", nm.id)
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:
stdio.printf("[AUGASGN] rhs is None\n")
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:
stdio.printf("[AUGASGN] binop failed for op=%d\n", aug.op)
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.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