Files
TransPyC/lib/core/Handles/HandlesDelete.py

96 lines
6.4 KiB
Python

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):
Gen = self.Trans.LlvmGen
for target in Node.targets:
if isinstance(target, ast.Subscript):
ClassName = self.Trans.ExprHandler._get_var_class(target.value, Gen)
if ClassName and Gen._has_function(f'{ClassName}.__delitem__'):
obj_val = self.Trans.ExprHandler.HandleExprLlvm(target.value)
idx_val = self.Trans.ExprHandler.HandleExprLlvm(target.slice)
if obj_val and idx_val:
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 = Gen.var_struct_class.get(target.id)
if ClassName and Gen._has_function(f'{ClassName}.__delete__'):
obj_val = self.Trans.ExprHandler.HandleExprLlvm(target)
if obj_val:
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 = target.attr
ClassName = None
obj_val_for_prop = None
if isinstance(target.value, ast.Name) and target.value.id == 'self':
# del self.attr — 检查当前类的 property deleter
ClassName = self.Trans._CurrentCpythonObjectClass
if ClassName:
PropKey = f'{ClassName}.{AttrName}'
PropInfo = self.Trans.SymbolTable.get(PropKey)
if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList:
SelfVar = Gen._get_var_ptr('self')
if SelfVar:
SelfPtr = Gen._load(SelfVar, name="self")
DeleterFunc = 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 = f'{ClassName}.{AttrName}'
PropInfo = self.Trans.SymbolTable.get(PropKey)
if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList:
obj_val = self.Trans.ExprHandler.HandleExprLlvm(target.value)
if obj_val:
DeleterFunc = Gen._get_function(PropKey + '$del')
if DeleterFunc:
Gen.builder.call(DeleterFunc, [obj_val], name=f"prop_del_{PropKey}")
continue
# 原有的 __del__ 处理逻辑
obj_val = 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 = 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__")