diff --git a/vm/src/builtins/make_module.rs b/vm/src/builtins/make_module.rs index 9a02d6366..b69849378 100644 --- a/vm/src/builtins/make_module.rs +++ b/vm/src/builtins/make_module.rs @@ -42,10 +42,7 @@ mod decl { #[pyfunction] fn abs(x: PyObjectRef, vm: &VirtualMachine) -> PyResult { - let method = vm.get_method_or_type_error(x.clone(), "__abs__", || { - format!("bad operand type for abs(): '{}'", x.class().name) - })?; - vm.invoke(&method, ()) + vm._abs(&x) } #[pyfunction] diff --git a/vm/src/frame.rs b/vm/src/frame.rs index aad993592..ab828d829 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -1666,33 +1666,9 @@ impl ExecutingFrame<'_> { fn execute_unop(&mut self, vm: &VirtualMachine, op: &bytecode::UnaryOperator) -> FrameResult { let a = self.pop_value(); let value = match *op { - bytecode::UnaryOperator::Minus => vm - .get_special_method(a, "__neg__")? - .map_err(|a| { - vm.new_type_error(format!( - "bad operand type for unary -: '{}'", - a.class().name - )) - })? - .invoke((), vm)?, - bytecode::UnaryOperator::Plus => vm - .get_special_method(a, "__pos__")? - .map_err(|a| { - vm.new_type_error(format!( - "bad operand type for unary +: '{}'", - a.class().name - )) - })? - .invoke((), vm)?, - bytecode::UnaryOperator::Invert => vm - .get_special_method(a, "__invert__")? - .map_err(|a| { - vm.new_type_error(format!( - "bad operand type for unary ~: '{}'", - a.class().name - )) - })? - .invoke((), vm)?, + bytecode::UnaryOperator::Minus => vm._neg(&a)?, + bytecode::UnaryOperator::Plus => vm._pos(&a)?, + bytecode::UnaryOperator::Invert => vm._invert(&a)?, bytecode::UnaryOperator::Not => { let value = pybool::boolval(vm, a)?; vm.ctx.new_bool(!value) diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 1bd18fbb1..1fa1e2e46 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -642,6 +642,10 @@ impl VirtualMachine { self.new_exception_msg(name_error, msg) } + pub fn new_unsupported_unary_error(&self, a: &PyObjectRef, op: &str) -> PyBaseExceptionRef { + self.new_type_error(format!("bad operand type for {}: '{}'", op, a.class().name)) + } + pub fn new_unsupported_binop_error( &self, a: &PyObjectRef, @@ -1611,6 +1615,30 @@ impl VirtualMachine { }) } + pub fn _abs(&self, a: &PyObjectRef) -> PyResult { + self.get_special_method(a.clone(), "__abs__")? + .map_err(|_| self.new_unsupported_unary_error(a, "abs()"))? + .invoke((), self) + } + + pub fn _pos(&self, a: &PyObjectRef) -> PyResult { + self.get_special_method(a.clone(), "__pos__")? + .map_err(|_| self.new_unsupported_unary_error(a, "unary +"))? + .invoke((), self) + } + + pub fn _neg(&self, a: &PyObjectRef) -> PyResult { + self.get_special_method(a.clone(), "__neg__")? + .map_err(|_| self.new_unsupported_unary_error(a, "unary -"))? + .invoke((), self) + } + + pub fn _invert(&self, a: &PyObjectRef) -> PyResult { + self.get_special_method(a.clone(), "__invert__")? + .map_err(|_| self.new_unsupported_unary_error(a, "unary ~"))? + .invoke((), self) + } + // Perform a comparison, raising TypeError when the requested comparison // operator is not supported. // see: CPython PyObject_RichCompare