Files
TransPyC/lib/core/Handles/HandlesDelete.py
2026-07-18 19:25:40 +08:00

102 lines
7.3 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.
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__")