Skip to content

Commit f624e8e

Browse files
authored
Merge pull request RustPython#3785 from youknowone/exact-size-operator
PyExactSizeIterator
2 parents fafd843 + 4f272ee commit f624e8e

File tree

9 files changed

+74
-76
lines changed

9 files changed

+74
-76
lines changed

stdlib/src/array.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ mod array {
2323
BufferDescriptor, BufferMethods, BufferResizeGuard, PyBuffer, PyIterReturn,
2424
PyMappingMethods,
2525
},
26-
sequence::{SequenceMutOp, SequenceOp},
26+
sequence::{SequenceExt, SequenceMutExt},
2727
sliceable::{
2828
SaturatedSlice, SequenceIndex, SliceableSequenceMutOp, SliceableSequenceOp,
2929
},

vm/src/builtins/list.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ use crate::{
66
class::PyClassImpl,
77
convert::ToPyObject,
88
function::{FuncArgs, OptionalArg, PyComparisonValue},
9+
iter::PyExactSizeIterator,
910
protocol::{PyIterReturn, PyMappingMethods, PySequence, PySequenceMethods},
1011
recursion::ReprGuard,
11-
sequence::{MutObjectSequenceOp, ObjectSequenceOp, SequenceMutOp, SequenceOp},
12+
sequence::{MutObjectSequenceOp, SequenceExt, SequenceMutExt},
1213
sliceable::{saturate_index, SequenceIndex, SliceableSequenceMutOp, SliceableSequenceOp},
1314
types::{
1415
AsMapping, AsSequence, Comparable, Constructor, Hashable, Initializer, IterNext,
@@ -491,7 +492,9 @@ impl Comparable for PyList {
491492
let other = class_or_notimplemented!(Self, other);
492493
let a = &*zelf.borrow_vec();
493494
let b = &*other.borrow_vec();
494-
a.cmp(vm, b, op).map(PyComparisonValue::Implemented)
495+
a.iter()
496+
.richcompare(b.iter(), op, vm)
497+
.map(PyComparisonValue::Implemented)
495498
}
496499
}
497500

vm/src/builtins/str.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{
1111
function::{ArgIterable, FuncArgs, OptionalArg, OptionalOption, PyComparisonValue},
1212
intern::PyInterned,
1313
protocol::{PyIterReturn, PyMappingMethods, PySequenceMethods},
14-
sequence::SequenceOp,
14+
sequence::SequenceExt,
1515
sliceable::{SequenceIndex, SliceableSequenceOp},
1616
types::{
1717
AsMapping, AsSequence, Comparable, Constructor, Hashable, IterNext, IterNextIterable,

vm/src/builtins/tuple.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ use crate::{
44
class::PyClassImpl,
55
convert::{ToPyObject, TransmuteFromObject},
66
function::{OptionalArg, PyArithmeticValue, PyComparisonValue},
7+
iter::PyExactSizeIterator,
78
protocol::{PyIterReturn, PyMappingMethods, PySequenceMethods},
89
recursion::ReprGuard,
9-
sequence::{ObjectSequenceOp, SequenceOp},
10+
sequence::SequenceExt,
1011
sliceable::{SequenceIndex, SliceableSequenceOp},
1112
stdlib::sys,
1213
types::{
@@ -400,7 +401,9 @@ impl Comparable for PyTuple {
400401
return Ok(res.into());
401402
}
402403
let other = class_or_notimplemented!(Self, other);
403-
zelf.cmp(vm, other, op).map(PyComparisonValue::Implemented)
404+
zelf.iter()
405+
.richcompare(other.iter(), op, vm)
406+
.map(PyComparisonValue::Implemented)
404407
}
405408
}
406409

vm/src/bytesinner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
function::{ArgIterable, Either, OptionalArg, OptionalOption, PyComparisonValue},
88
identifier,
99
protocol::PyBuffer,
10-
sequence::{SequenceMutOp, SequenceOp},
10+
sequence::{SequenceExt, SequenceMutExt},
1111
types::PyComparisonOp,
1212
AsObject, PyObject, PyObjectRef, PyPayload, PyResult, TryFromBorrowedObject, VirtualMachine,
1313
};

vm/src/iter.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use crate::{types::PyComparisonOp, vm::VirtualMachine, PyObjectRef, PyResult};
2+
use itertools::Itertools;
3+
4+
pub trait PyExactSizeIterator<'a>: ExactSizeIterator<Item = &'a PyObjectRef> + Sized {
5+
fn eq(self, other: impl PyExactSizeIterator<'a>, vm: &VirtualMachine) -> PyResult<bool> {
6+
let lhs = self;
7+
let rhs = other;
8+
if lhs.len() != rhs.len() {
9+
return Ok(false);
10+
}
11+
for (a, b) in lhs.zip_eq(rhs) {
12+
if !vm.identical_or_equal(a, b)? {
13+
return Ok(false);
14+
}
15+
}
16+
Ok(true)
17+
}
18+
19+
fn richcompare(
20+
self,
21+
other: impl PyExactSizeIterator<'a>,
22+
op: PyComparisonOp,
23+
vm: &VirtualMachine,
24+
) -> PyResult<bool> {
25+
let less = match op {
26+
PyComparisonOp::Eq => return PyExactSizeIterator::eq(self, other, vm),
27+
PyComparisonOp::Ne => return PyExactSizeIterator::eq(self, other, vm).map(|eq| !eq),
28+
PyComparisonOp::Lt | PyComparisonOp::Le => true,
29+
PyComparisonOp::Gt | PyComparisonOp::Ge => false,
30+
};
31+
32+
let lhs = self;
33+
let rhs = other;
34+
let lhs_len = lhs.len();
35+
let rhs_len = rhs.len();
36+
for (a, b) in lhs.zip(rhs) {
37+
let ret = if less {
38+
vm.bool_seq_lt(a, b)?
39+
} else {
40+
vm.bool_seq_gt(a, b)?
41+
};
42+
if let Some(v) = ret {
43+
return Ok(v);
44+
}
45+
}
46+
Ok(op.eval_ord(lhs_len.cmp(&rhs_len)))
47+
}
48+
}
49+
50+
impl<'a, T> PyExactSizeIterator<'a> for T where T: ExactSizeIterator<Item = &'a PyObjectRef> + Sized {}

vm/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ mod frozen;
5757
pub mod function;
5858
pub mod import;
5959
mod intern;
60+
pub mod iter;
6061
pub mod object;
6162
pub mod prelude;
6263
pub mod protocol;

vm/src/sequence.rs

Lines changed: 5 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -4,70 +4,8 @@ use crate::{
44
vm::VirtualMachine,
55
AsObject, PyObject, PyObjectRef, PyResult,
66
};
7-
use itertools::Itertools;
87
use optional::Optioned;
9-
use std::{collections::VecDeque, ops::Range};
10-
11-
pub trait ObjectSequenceOp<'a> {
12-
type Iter: ExactSizeIterator<Item = &'a PyObjectRef>;
13-
14-
fn iter(&'a self) -> Self::Iter;
15-
16-
fn eq(&'a self, vm: &VirtualMachine, other: &'a Self) -> PyResult<bool> {
17-
let lhs = self.iter();
18-
let rhs = other.iter();
19-
if lhs.len() != rhs.len() {
20-
return Ok(false);
21-
}
22-
for (a, b) in lhs.zip_eq(rhs) {
23-
if !vm.identical_or_equal(a, b)? {
24-
return Ok(false);
25-
}
26-
}
27-
Ok(true)
28-
}
29-
30-
fn cmp(&'a self, vm: &VirtualMachine, other: &'a Self, op: PyComparisonOp) -> PyResult<bool> {
31-
let less = match op {
32-
PyComparisonOp::Eq => return self.eq(vm, other),
33-
PyComparisonOp::Ne => return self.eq(vm, other).map(|eq| !eq),
34-
PyComparisonOp::Lt | PyComparisonOp::Le => true,
35-
PyComparisonOp::Gt | PyComparisonOp::Ge => false,
36-
};
37-
38-
let lhs = self.iter();
39-
let rhs = other.iter();
40-
let lhs_len = lhs.len();
41-
let rhs_len = rhs.len();
42-
for (a, b) in lhs.zip(rhs) {
43-
let ret = if less {
44-
vm.bool_seq_lt(a, b)?
45-
} else {
46-
vm.bool_seq_gt(a, b)?
47-
};
48-
if let Some(v) = ret {
49-
return Ok(v);
50-
}
51-
}
52-
Ok(op.eval_ord(lhs_len.cmp(&rhs_len)))
53-
}
54-
}
55-
56-
impl<'a> ObjectSequenceOp<'a> for [PyObjectRef] {
57-
type Iter = core::slice::Iter<'a, PyObjectRef>;
58-
59-
fn iter(&'a self) -> Self::Iter {
60-
self.iter()
61-
}
62-
}
63-
64-
impl<'a> ObjectSequenceOp<'a> for VecDeque<PyObjectRef> {
65-
type Iter = std::collections::vec_deque::Iter<'a, PyObjectRef>;
66-
67-
fn iter(&'a self) -> Self::Iter {
68-
self.iter()
69-
}
70-
}
8+
use std::ops::Range;
719

7210
pub trait MutObjectSequenceOp<'a> {
7311
type Guard;
@@ -242,7 +180,7 @@ pub trait MutObjectSequenceOp<'a> {
242180
}
243181
}
244182

245-
pub trait SequenceOp<T: Clone>
183+
pub trait SequenceExt<T: Clone>
246184
where
247185
Self: AsRef<[T]>,
248186
{
@@ -256,9 +194,9 @@ where
256194
}
257195
}
258196

259-
impl<T: Clone> SequenceOp<T> for [T] {}
197+
impl<T: Clone> SequenceExt<T> for [T] {}
260198

261-
pub trait SequenceMutOp<T: Clone>
199+
pub trait SequenceMutExt<T: Clone>
262200
where
263201
Self: AsRef<[T]>,
264202
{
@@ -282,7 +220,7 @@ where
282220
}
283221
}
284222

285-
impl<T: Clone> SequenceMutOp<T> for Vec<T> {
223+
impl<T: Clone> SequenceMutExt<T> for Vec<T> {
286224
fn as_vec_mut(&mut self) -> &mut Vec<T> {
287225
self
288226
}

vm/src/stdlib/collections.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ mod _collections {
99
},
1010
common::lock::{PyMutex, PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard},
1111
function::{FuncArgs, KwArgs, OptionalArg, PyComparisonValue},
12+
iter::PyExactSizeIterator,
1213
protocol::{PyIterReturn, PySequenceMethods},
1314
recursion::ReprGuard,
14-
sequence::{MutObjectSequenceOp, ObjectSequenceOp},
15+
sequence::MutObjectSequenceOp,
1516
sliceable,
1617
sliceable::saturate_index,
1718
types::{
@@ -565,7 +566,9 @@ mod _collections {
565566
let other = class_or_notimplemented!(Self, other);
566567
let lhs = zelf.borrow_deque();
567568
let rhs = other.borrow_deque();
568-
lhs.cmp(vm, &rhs, op).map(PyComparisonValue::Implemented)
569+
lhs.iter()
570+
.richcompare(rhs.iter(), op, vm)
571+
.map(PyComparisonValue::Implemented)
569572
}
570573
}
571574

0 commit comments

Comments
 (0)