Merge pull request #2690 from DimitrisJim/clean_up_unary

Refactor unary ops.
This commit is contained in:
Noah
2021-06-07 19:39:33 -05:00
committed by GitHub
3 changed files with 32 additions and 31 deletions

View File

@@ -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]

View File

@@ -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)

View File

@@ -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<PyObjectRef> {
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