diff --git a/vm/src/protocol/callable.rs b/vm/src/protocol/callable.rs new file mode 100644 index 000000000..9e002bc44 --- /dev/null +++ b/vm/src/protocol/callable.rs @@ -0,0 +1,33 @@ +use crate::{ + function::IntoFuncArgs, + types::GenericMethod, + {PyObject, PyResult, VirtualMachine} +}; + +impl PyObject { + #[inline] + pub fn to_callable(&self) -> Option> { + PyCallable::new(self) + } + + #[inline] + pub fn is_callable(&self) -> bool { + self.to_callable().is_some() + } +} + +pub struct PyCallable<'a> { + pub obj: &'a PyObject, + pub call: GenericMethod, +} + +impl<'a> PyCallable<'a> { + pub fn new(obj: &'a PyObject) -> Option { + let call = obj.class().mro_find_map(|cls| cls.slots.call.load())?; + Some(PyCallable { obj, call }) + } + + pub fn invoke(&self, args: impl IntoFuncArgs, vm: &VirtualMachine) -> PyResult { + (self.call)(self.obj, args.into_args(vm), vm) + } +} diff --git a/vm/src/protocol/mod.rs b/vm/src/protocol/mod.rs index dae492628..4170c20df 100644 --- a/vm/src/protocol/mod.rs +++ b/vm/src/protocol/mod.rs @@ -1,4 +1,5 @@ mod buffer; +mod callable; mod iter; mod mapping; mod number; @@ -6,6 +7,7 @@ mod object; mod sequence; pub use buffer::{BufferDescriptor, BufferMethods, BufferResizeGuard, PyBuffer, VecBuffer}; +pub use callable::PyCallable; pub use iter::{PyIter, PyIterIter, PyIterReturn}; pub use mapping::{PyMapping, PyMappingMethods}; pub use number::{PyNumber, PyNumberMethods}; diff --git a/vm/src/signal.rs b/vm/src/signal.rs index bca796342..7489282de 100644 --- a/vm/src/signal.rs +++ b/vm/src/signal.rs @@ -37,8 +37,8 @@ fn trigger_signals(vm: &VirtualMachine) -> PyResult<()> { let triggered = trigger.swap(false, Ordering::Relaxed); if triggered { if let Some(handler) = &signal_handlers[signum] { - if vm.is_callable(handler) { - vm.invoke(handler, (signum, vm.ctx.none()))?; + if let Some(callable) = handler.to_callable() { + callable.invoke((signum, vm.ctx.none()), vm)?; } } }