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