102 lines
7.3 KiB
Python
102 lines
7.3 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: 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__") |