diff --git a/stdlib/src/array.rs b/stdlib/src/array.rs index ee9bef2a8..03ca50d80 100644 --- a/stdlib/src/array.rs +++ b/stdlib/src/array.rs @@ -23,7 +23,7 @@ mod array { BufferDescriptor, BufferMethods, BufferResizeGuard, PyBuffer, PyIterReturn, PyMappingMethods, }, - sequence::{SequenceMutOp, SequenceOp}, + sequence::{SequenceExt, SequenceMutExt}, sliceable::{ SaturatedSlice, SequenceIndex, SliceableSequenceMutOp, SliceableSequenceOp, }, diff --git a/vm/src/builtins/list.rs b/vm/src/builtins/list.rs index 27a22ea28..2fd52b864 100644 --- a/vm/src/builtins/list.rs +++ b/vm/src/builtins/list.rs @@ -7,9 +7,10 @@ use crate::{ class::PyClassImpl, convert::ToPyObject, function::{FuncArgs, OptionalArg, PyComparisonValue}, + iter::PyExactSizeIterator, protocol::{PyIterReturn, PyMappingMethods, PySequence, PySequenceMethods}, recursion::ReprGuard, - sequence::{MutObjectSequenceOp, ObjectSequenceOp, SequenceMutOp, SequenceOp}, + sequence::{MutObjectSequenceOp, SequenceExt, SequenceMutExt}, sliceable::{saturate_index, SequenceIndex, SliceableSequenceMutOp, SliceableSequenceOp}, types::{ AsMapping, AsSequence, Comparable, Constructor, Hashable, Initializer, IterNext, @@ -492,7 +493,9 @@ impl Comparable for PyList { let other = class_or_notimplemented!(Self, other); let a = &*zelf.borrow_vec(); let b = &*other.borrow_vec(); - a.cmp(vm, b, op).map(PyComparisonValue::Implemented) + a.iter() + .richcompare(b.iter(), op, vm) + .map(PyComparisonValue::Implemented) } } diff --git a/vm/src/builtins/str.rs b/vm/src/builtins/str.rs index 1700795d6..20c6b492a 100644 --- a/vm/src/builtins/str.rs +++ b/vm/src/builtins/str.rs @@ -11,7 +11,7 @@ use crate::{ function::{ArgIterable, FuncArgs, OptionalArg, OptionalOption, PyComparisonValue}, intern::PyInterned, protocol::{PyIterReturn, PyMappingMethods, PySequenceMethods}, - sequence::SequenceOp, + sequence::SequenceExt, sliceable::{SequenceIndex, SliceableSequenceOp}, types::{ AsMapping, AsSequence, Comparable, Constructor, Hashable, IterNext, IterNextIterable, diff --git a/vm/src/builtins/tuple.rs b/vm/src/builtins/tuple.rs index 59ea9a644..4721cf0d8 100644 --- a/vm/src/builtins/tuple.rs +++ b/vm/src/builtins/tuple.rs @@ -4,9 +4,10 @@ use crate::{ class::PyClassImpl, convert::{ToPyObject, TransmuteFromObject, TryFromBorrowedObject}, function::{OptionalArg, PyArithmeticValue, PyComparisonValue}, + iter::PyExactSizeIterator, protocol::{PyIterReturn, PyMappingMethods, PySequenceMethods}, recursion::ReprGuard, - sequence::{ObjectSequenceOp, SequenceOp}, + sequence::SequenceExt, sliceable::{SequenceIndex, SliceableSequenceOp}, stdlib::sys, types::{ @@ -400,7 +401,9 @@ impl Comparable for PyTuple { return Ok(res.into()); } let other = class_or_notimplemented!(Self, other); - zelf.cmp(vm, other, op).map(PyComparisonValue::Implemented) + zelf.iter() + .richcompare(other.iter(), op, vm) + .map(PyComparisonValue::Implemented) } } diff --git a/vm/src/bytesinner.rs b/vm/src/bytesinner.rs index 5a332c82e..b3063d3ce 100644 --- a/vm/src/bytesinner.rs +++ b/vm/src/bytesinner.rs @@ -7,7 +7,7 @@ use crate::{ function::{ArgIterable, Either, OptionalArg, OptionalOption, PyComparisonValue}, identifier, protocol::PyBuffer, - sequence::{SequenceMutOp, SequenceOp}, + sequence::{SequenceExt, SequenceMutExt}, types::PyComparisonOp, AsObject, PyObject, PyObjectRef, PyPayload, PyResult, TryFromBorrowedObject, VirtualMachine, }; diff --git a/vm/src/iter.rs b/vm/src/iter.rs new file mode 100644 index 000000000..fc432e9e6 --- /dev/null +++ b/vm/src/iter.rs @@ -0,0 +1,50 @@ +use crate::{types::PyComparisonOp, vm::VirtualMachine, PyObjectRef, PyResult}; +use itertools::Itertools; + +pub trait PyExactSizeIterator<'a>: ExactSizeIterator + Sized { + fn eq(self, other: impl PyExactSizeIterator<'a>, vm: &VirtualMachine) -> PyResult { + let lhs = self; + let rhs = other; + if lhs.len() != rhs.len() { + return Ok(false); + } + for (a, b) in lhs.zip_eq(rhs) { + if !vm.identical_or_equal(a, b)? { + return Ok(false); + } + } + Ok(true) + } + + fn richcompare( + self, + other: impl PyExactSizeIterator<'a>, + op: PyComparisonOp, + vm: &VirtualMachine, + ) -> PyResult { + let less = match op { + PyComparisonOp::Eq => return PyExactSizeIterator::eq(self, other, vm), + PyComparisonOp::Ne => return PyExactSizeIterator::eq(self, other, vm).map(|eq| !eq), + PyComparisonOp::Lt | PyComparisonOp::Le => true, + PyComparisonOp::Gt | PyComparisonOp::Ge => false, + }; + + let lhs = self; + let rhs = other; + let lhs_len = lhs.len(); + let rhs_len = rhs.len(); + for (a, b) in lhs.zip(rhs) { + let ret = if less { + vm.bool_seq_lt(a, b)? + } else { + vm.bool_seq_gt(a, b)? + }; + if let Some(v) = ret { + return Ok(v); + } + } + Ok(op.eval_ord(lhs_len.cmp(&rhs_len))) + } +} + +impl<'a, T> PyExactSizeIterator<'a> for T where T: ExactSizeIterator + Sized {} diff --git a/vm/src/lib.rs b/vm/src/lib.rs index a772e4604..a3b86dd62 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -57,6 +57,7 @@ mod frozen; pub mod function; pub mod import; mod intern; +pub mod iter; pub mod object; pub mod prelude; pub mod protocol; diff --git a/vm/src/sequence.rs b/vm/src/sequence.rs index 798db5833..b7eb01964 100644 --- a/vm/src/sequence.rs +++ b/vm/src/sequence.rs @@ -4,70 +4,8 @@ use crate::{ vm::VirtualMachine, AsObject, PyObject, PyObjectRef, PyResult, }; -use itertools::Itertools; use optional::Optioned; -use std::{collections::VecDeque, ops::Range}; - -pub trait ObjectSequenceOp<'a> { - type Iter: ExactSizeIterator; - - fn iter(&'a self) -> Self::Iter; - - fn eq(&'a self, vm: &VirtualMachine, other: &'a Self) -> PyResult { - let lhs = self.iter(); - let rhs = other.iter(); - if lhs.len() != rhs.len() { - return Ok(false); - } - for (a, b) in lhs.zip_eq(rhs) { - if !vm.identical_or_equal(a, b)? { - return Ok(false); - } - } - Ok(true) - } - - fn cmp(&'a self, vm: &VirtualMachine, other: &'a Self, op: PyComparisonOp) -> PyResult { - let less = match op { - PyComparisonOp::Eq => return self.eq(vm, other), - PyComparisonOp::Ne => return self.eq(vm, other).map(|eq| !eq), - PyComparisonOp::Lt | PyComparisonOp::Le => true, - PyComparisonOp::Gt | PyComparisonOp::Ge => false, - }; - - let lhs = self.iter(); - let rhs = other.iter(); - let lhs_len = lhs.len(); - let rhs_len = rhs.len(); - for (a, b) in lhs.zip(rhs) { - let ret = if less { - vm.bool_seq_lt(a, b)? - } else { - vm.bool_seq_gt(a, b)? - }; - if let Some(v) = ret { - return Ok(v); - } - } - Ok(op.eval_ord(lhs_len.cmp(&rhs_len))) - } -} - -impl<'a> ObjectSequenceOp<'a> for [PyObjectRef] { - type Iter = core::slice::Iter<'a, PyObjectRef>; - - fn iter(&'a self) -> Self::Iter { - self.iter() - } -} - -impl<'a> ObjectSequenceOp<'a> for VecDeque { - type Iter = std::collections::vec_deque::Iter<'a, PyObjectRef>; - - fn iter(&'a self) -> Self::Iter { - self.iter() - } -} +use std::ops::Range; pub trait MutObjectSequenceOp<'a> { type Guard; @@ -242,7 +180,7 @@ pub trait MutObjectSequenceOp<'a> { } } -pub trait SequenceOp +pub trait SequenceExt where Self: AsRef<[T]>, { @@ -256,9 +194,9 @@ where } } -impl SequenceOp for [T] {} +impl SequenceExt for [T] {} -pub trait SequenceMutOp +pub trait SequenceMutExt where Self: AsRef<[T]>, { @@ -282,7 +220,7 @@ where } } -impl SequenceMutOp for Vec { +impl SequenceMutExt for Vec { fn as_vec_mut(&mut self) -> &mut Vec { self } diff --git a/vm/src/stdlib/collections.rs b/vm/src/stdlib/collections.rs index 59efa9a67..da77d399d 100644 --- a/vm/src/stdlib/collections.rs +++ b/vm/src/stdlib/collections.rs @@ -9,9 +9,10 @@ mod _collections { }, common::lock::{PyMutex, PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard}, function::{FuncArgs, KwArgs, OptionalArg, PyComparisonValue}, + iter::PyExactSizeIterator, protocol::{PyIterReturn, PySequenceMethods}, recursion::ReprGuard, - sequence::{MutObjectSequenceOp, ObjectSequenceOp}, + sequence::MutObjectSequenceOp, sliceable, sliceable::saturate_index, types::{ @@ -565,7 +566,9 @@ mod _collections { let other = class_or_notimplemented!(Self, other); let lhs = zelf.borrow_deque(); let rhs = other.borrow_deque(); - lhs.cmp(vm, &rhs, op).map(PyComparisonValue::Implemented) + lhs.iter() + .richcompare(rhs.iter(), op, vm) + .map(PyComparisonValue::Implemented) } }