from __future__ import annotations from typing import TYPE_CHECKING if TYPE_CHECKING: from lib.core.translator import Translator from lib.core.Handles.HandlesBase import BaseHandle, FuncMeta import ast import llvmlite.ir as ir class DeleteHandle(BaseHandle): def _HandleDeleteLlvm(self, Node: ast.Delete) -> None: Gen: "Translator.LlvmGen" = self.Trans.LlvmGen for target in Node.targets: if isinstance(target, ast.Subscript): ClassName: str | None = self.Trans.ExprHandler._get_var_class(target.value, Gen) if ClassName and Gen._has_function(f'{ClassName}.__delitem__'): obj_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(target.value) idx_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(target.slice) if obj_val and idx_val: # 处理 obj_val 为 i8(整数)的情况:联合类型 | t.CPtr 降级后可能被 load 为 i8 if isinstance(obj_val.type, ir.IntType) and obj_val.type.width == 8: obj_val = Gen.builder.inttoptr(obj_val, ir.PointerType(ir.IntType(8)), name=f"i8_to_ptr_{ClassName}") if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") Gen.builder.call(Gen._get_function(f'{ClassName}.__delitem__'), [obj_val, idx_val], name=f"call_{ClassName}.__delitem__") elif isinstance(target, ast.Name): ClassName: str | None = Gen.var_struct_class.get(target.id) if ClassName and Gen._has_function(f'{ClassName}.__delete__'): obj_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(target) if obj_val: # 处理 obj_val 为 i8(整数)的情况:联合类型 | t.CPtr 降级后可能被 load 为 i8 if isinstance(obj_val.type, ir.IntType) and obj_val.type.width == 8: obj_val = Gen.builder.inttoptr(obj_val, ir.PointerType(ir.IntType(8)), name=f"i8_to_ptr_{ClassName}") if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") Gen.builder.call(Gen._get_function(f'{ClassName}.__delete__'), [obj_val], name=f"call_{ClassName}.__delete__") elif isinstance(target, ast.Attribute): # 检查 property deleter AttrName: str = target.attr ClassName: str | None = None obj_val_for_prop: ir.Value | None = None if isinstance(target.value, ast.Name) and target.value.id == 'self': # del self.attr — 检查当前类的 property deleter ClassName = self.Trans._CurrentCpythonObjectClass if ClassName: PropKey: str = f'{ClassName}.{AttrName}' PropInfo: "SymbolTable.SymbolInfo | None" = self.Trans.SymbolTable.lookup(PropKey) if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList: SelfVar: ir.Value | None = Gen._get_var_ptr('self') if SelfVar: SelfPtr: ir.Value = Gen._load(SelfVar, name="self") DeleterFunc: ir.Function | None = Gen._get_function(PropKey + '$del') if DeleterFunc and SelfPtr: Gen.builder.call(DeleterFunc, [SelfPtr], name=f"prop_del_{PropKey}") continue else: # del obj.attr — 检查 obj 类的 property deleter ClassName = self.Trans.ExprHandler._get_var_class(target.value, Gen) if ClassName: PropKey: str = f'{ClassName}.{AttrName}' PropInfo: "SymbolTable.SymbolInfo | None" = self.Trans.SymbolTable.lookup(PropKey) if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList: obj_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(target.value) if obj_val: DeleterFunc: ir.Function | None = Gen._get_function(PropKey + '$del') if DeleterFunc: Gen.builder.call(DeleterFunc, [obj_val], name=f"prop_del_{PropKey}") continue # 原有的 __del__ 处理逻辑 obj_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(target) if obj_val: if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.PointerType): obj_val = Gen._load(obj_val, name="Load_del_ptr") ClassName = None if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): for CN, ST in Gen.structs.items(): if obj_val.type.pointee == ST: ClassName = CN break elif isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: if isinstance(target.value, ast.Name) and target.value.id == 'self': AttrName = target.attr SelfClassName: str | None = self.Trans._CurrentCpythonObjectClass if SelfClassName and SelfClassName in Gen.class_members: for member_name, member_type in Gen.class_members[SelfClassName]: if member_name == AttrName: for CN in Gen.structs: if CN == AttrName or Gen._has_function(f'{CN}.__del__'): ClassName = CN break break if not ClassName: for CN, ST in Gen.structs.items(): if Gen._has_function(f'{CN}.__del__'): ClassName = CN break if ClassName and Gen._has_function(f'{ClassName}.__del__'): if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") Gen.builder.call(Gen._get_function(f'{ClassName}.__del__'), [obj_val], name=f"call_{ClassName}.__del__")