From d9b1ae296b8952fdee9f163ff0ef69dd4e8bdeb7 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Sun, 20 Sep 2020 10:43:31 +0900 Subject: [PATCH] tp_del --- vm/src/macros.rs | 7 +++++-- vm/src/obj/objtype.rs | 7 +++++++ vm/src/pyobjectrc.rs | 5 +++-- vm/src/slots.rs | 21 +++++++++++++++++++++ vm/src/stdlib/io.rs | 9 +++++++-- 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/vm/src/macros.rs b/vm/src/macros.rs index 292dc674c..515ce12ad 100644 --- a/vm/src/macros.rs +++ b/vm/src/macros.rs @@ -47,11 +47,14 @@ macro_rules! py_class { py_class } }; - (@extract_slots($ctx:expr, $slots:expr, (slot $slot_name:ident), $value:expr)) => { - $slots.$slot_name = Some( + (@extract_slots($ctx:expr, $slots:expr, (slot new), $value:expr)) => { + $slots.new = Some( $crate::function::IntoPyNativeFunc::into_func($value) ); }; + (@extract_slots($ctx:expr, $slots:expr, (slot $slot_name:ident), $value:expr)) => { + $slots.$slot_name.store(Some($value)); + }; (@extract_slots($ctx:expr, $class:expr, $name:expr, $value:expr)) => {}; (@extract_attrs($ctx:expr, $slots:expr, (slot $slot_name:ident), $value:expr)) => {}; (@extract_attrs($ctx:expr, $class:expr, $name:expr, $value:expr)) => { diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index 0bd01e89b..5607bfcd9 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -150,6 +150,13 @@ impl PyClassRef { } as _; self.slots.hash.store(Some(func)); } + "__del__" => { + let func: slots::DelFunc = |zelf, vm| { + let magic = get_class_magic(&zelf, "__del__"); + vm.invoke(&magic, vec![zelf.clone()]).map(|_| ()) + } as _; + self.slots.del.store(Some(func)); + } _ => (), } } diff --git a/vm/src/pyobjectrc.rs b/vm/src/pyobjectrc.rs index 0e58b50cf..432dd90b0 100644 --- a/vm/src/pyobjectrc.rs +++ b/vm/src/pyobjectrc.rs @@ -146,11 +146,12 @@ where // CPython-compatible drop implementation let zelf = Self::into_ref(self.clone()); - if let Some(del_method) = zelf.inner.get_class_attr("__del__") { + if let Some(del_slot) = zelf.class().first_in_mro(|cls| cls.slots.del.load()) { crate::vm::thread::with_vm(&zelf, |vm| { - if let Err(e) = vm.invoke(&del_method, vec![zelf.clone()]) { + if let Err(e) = del_slot(&zelf, vm) { // exception in del will be ignored but printed print!("Exception ignored in: ",); + let del_method = zelf.get_class_attr("__del__").unwrap(); let repr = vm.to_repr(&del_method); match repr { Ok(v) => println!("{}", v.to_string()), diff --git a/vm/src/slots.rs b/vm/src/slots.rs index 68eb46829..10ec75137 100644 --- a/vm/src/slots.rs +++ b/vm/src/slots.rs @@ -41,6 +41,7 @@ impl Default for PyTpFlags { } pub(crate) type GenericMethod = fn(PyObjectRef, PyFuncArgs, &VirtualMachine) -> PyResult; +pub(crate) type DelFunc = fn(&PyObjectRef, &VirtualMachine) -> PyResult<()>; pub(crate) type DescrGetFunc = fn(PyObjectRef, Option, Option, &VirtualMachine) -> PyResult; pub(crate) type HashFunc = fn(&PyObjectRef, &VirtualMachine) -> PyResult; @@ -50,6 +51,7 @@ pub struct PyClassSlots { pub flags: PyTpFlags, pub name: PyRwLock>, // tp_name, not class name pub new: Option, + pub del: AtomicCell>, pub call: AtomicCell>, pub descr_get: AtomicCell>, pub hash: AtomicCell>, @@ -82,6 +84,25 @@ impl std::fmt::Debug for PyClassSlots { } } +#[pyimpl] +pub trait SlotDesctuctor: PyValue { + #[pyslot] + fn tp_del(zelf: &PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { + if let Some(zelf) = zelf.downcast_ref() { + Self::del(zelf, vm) + } else { + Err(vm.new_type_error("unexpected payload for __del__".to_owned())) + } + } + + #[pymethod(magic)] + fn __del__(zelf: PyRef, vm: &VirtualMachine) -> PyResult<()> { + Self::del(&zelf, vm) + } + + fn del(zelf: &PyRef, vm: &VirtualMachine) -> PyResult<()>; +} + #[pyimpl] pub trait SlotCall: PyValue { #[pymethod(magic)] diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index 170f1bb35..121d6cefe 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -416,11 +416,15 @@ fn io_base_cm_enter(instance: PyObjectRef) -> PyObjectRef { instance } -fn io_base_cm_del(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { - vm.call_method(&instance, "close", vec![])?; +fn io_base_cm_del_slot(instance: &PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { + vm.call_method(instance, "close", vec![])?; Ok(()) } +fn io_base_cm_del(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { + io_base_cm_del_slot(&instance, vm) +} + fn io_base_cm_exit(instance: PyObjectRef, _args: PyFuncArgs, vm: &VirtualMachine) -> PyResult<()> { vm.call_method(&instance, "close", vec![])?; Ok(()) @@ -1271,6 +1275,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let io_base = py_class!(ctx, "_IOBase", &ctx.types.object_type, { "__enter__" => ctx.new_method(io_base_cm_enter), "__del__" => ctx.new_method(io_base_cm_del), + (slot del) => io_base_cm_del_slot, "__exit__" => ctx.new_method(io_base_cm_exit), "seekable" => ctx.new_method(io_base_seekable), "readable" => ctx.new_method(io_base_readable),