vm::sequence for SimpleSeq utilities

This commit is contained in:
Jeong YunWon
2020-01-07 22:24:05 +09:00
parent 18fcd99584
commit 226ebfa0c6
5 changed files with 179 additions and 188 deletions

View File

@@ -10,9 +10,7 @@ use super::objbool;
use super::objbyteinner;
use super::objint::PyIntRef;
use super::objiter;
use super::objsequence::{
get_item, seq_equal, seq_ge, seq_gt, seq_le, seq_lt, seq_mul, SequenceIndex, SimpleSeq,
};
use super::objsequence::{get_item, SequenceIndex};
use super::objslice::PySliceRef;
use super::objtype::PyClassRef;
use crate::function::OptionalArg;
@@ -20,6 +18,7 @@ use crate::pyobject::{
IdProtocol, PyArithmaticValue::*, PyClassImpl, PyComparisonValue, PyContext, PyIterable,
PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol,
};
use crate::sequence::{self, SimpleSeq};
use crate::vm::{ReprGuard, VirtualMachine};
/// Built-in mutable sequence.
@@ -469,7 +468,9 @@ impl PyList {
#[pymethod(name = "__mul__")]
fn mul(&self, counter: isize, vm: &VirtualMachine) -> PyObjectRef {
let new_elements = seq_mul(&self.borrow_sequence(), counter).cloned().collect();
let new_elements = sequence::seq_mul(&self.borrow_sequence(), counter)
.cloned()
.collect();
vm.ctx.new_list(new_elements)
}
@@ -480,7 +481,9 @@ impl PyList {
#[pymethod(name = "__imul__")]
fn imul(zelf: PyRef<Self>, counter: isize, _vm: &VirtualMachine) -> PyRef<Self> {
let new_elements = seq_mul(&zelf.borrow_sequence(), counter).cloned().collect();
let new_elements = sequence::seq_mul(&zelf.borrow_sequence(), counter)
.cloned()
.collect();
zelf.elements.replace(new_elements);
zelf
}
@@ -562,7 +565,7 @@ impl PyList {
let value = if zelf.as_object().is(&other) {
Implemented(true)
} else if let Some(other) = other.payload_if_subclass::<PyList>(vm) {
Implemented(seq_equal(
Implemented(sequence::eq(
vm,
&zelf.borrow_sequence(),
&other.borrow_sequence(),
@@ -585,7 +588,7 @@ impl PyList {
#[pymethod(name = "__lt__")]
fn lt(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
if let Some(other) = other.payload_if_subclass::<PyList>(vm) {
let res = seq_lt(vm, &self.borrow_sequence(), &other.borrow_sequence())?;
let res = sequence::lt(vm, &self.borrow_sequence(), &other.borrow_sequence())?;
Ok(vm.new_bool(res))
} else {
Ok(vm.ctx.not_implemented())
@@ -595,7 +598,7 @@ impl PyList {
#[pymethod(name = "__gt__")]
fn gt(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
if let Some(other) = other.payload_if_subclass::<PyList>(vm) {
let res = seq_gt(vm, &self.borrow_sequence(), &other.borrow_sequence())?;
let res = sequence::gt(vm, &self.borrow_sequence(), &other.borrow_sequence())?;
Ok(vm.new_bool(res))
} else {
Ok(vm.ctx.not_implemented())
@@ -605,7 +608,7 @@ impl PyList {
#[pymethod(name = "__ge__")]
fn ge(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
if let Some(other) = other.payload_if_subclass::<PyList>(vm) {
let res = seq_ge(vm, &self.borrow_sequence(), &other.borrow_sequence())?;
let res = sequence::ge(vm, &self.borrow_sequence(), &other.borrow_sequence())?;
Ok(vm.new_bool(res))
} else {
Ok(vm.ctx.not_implemented())
@@ -615,7 +618,7 @@ impl PyList {
#[pymethod(name = "__le__")]
fn le(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
if let Some(other) = other.payload_if_subclass::<PyList>(vm) {
let res = seq_le(vm, &self.borrow_sequence(), &other.borrow_sequence())?;
let res = sequence::le(vm, &self.borrow_sequence(), &other.borrow_sequence())?;
Ok(vm.new_bool(res))
} else {
Ok(vm.ctx.not_implemented())

View File

@@ -1,5 +1,5 @@
use std::marker::Sized;
use std::ops::{Deref, Range};
use std::ops::Range;
use num_bigint::{BigInt, ToBigInt};
use num_traits::{One, Signed, ToPrimitive, Zero};
@@ -10,7 +10,7 @@ use super::objnone::PyNone;
use super::objslice::{PySlice, PySliceRef};
use super::objtuple::PyTuple;
use crate::function::OptionalArg;
use crate::pyobject::{IdProtocol, PyObject, PyObjectRef, PyResult, TryFromObject, TypeProtocol};
use crate::pyobject::{PyObject, PyObjectRef, PyResult, TryFromObject, TypeProtocol};
use crate::vm::VirtualMachine;
pub trait PySliceableSequence {
@@ -246,166 +246,6 @@ pub fn get_item(
}
}
type DynPyIter<'a> = Box<dyn ExactSizeIterator<Item = &'a PyObjectRef> + 'a>;
#[allow(clippy::len_without_is_empty)]
pub trait SimpleSeq {
fn len(&self) -> usize;
fn iter(&self) -> DynPyIter;
}
// impl SimpleSeq for &[PyObjectRef] {
// fn len(&self) -> usize {
// (&**self).len()
// }
// fn iter(&self) -> DynPyIter {
// Box::new((&**self).iter())
// }
// }
impl SimpleSeq for Vec<PyObjectRef> {
fn len(&self) -> usize {
self.len()
}
fn iter(&self) -> DynPyIter {
Box::new(self.as_slice().iter())
}
}
impl SimpleSeq for std::collections::VecDeque<PyObjectRef> {
fn len(&self) -> usize {
self.len()
}
fn iter(&self) -> DynPyIter {
Box::new(self.iter())
}
}
impl<T> SimpleSeq for std::cell::Ref<'_, T> where T: SimpleSeq {
fn len(&self) -> usize {
self.deref().len()
}
fn iter(&self) -> DynPyIter {
self.deref().iter()
}
}
// impl<'a, I>
pub fn seq_equal(
vm: &VirtualMachine,
zelf: &impl SimpleSeq,
other: &impl SimpleSeq,
) -> PyResult<bool> {
if zelf.len() == other.len() {
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
if a.is(b) {
continue;
}
if !vm.bool_eq(a.clone(), b.clone())? {
return Ok(false);
}
}
Ok(true)
} else {
Ok(false)
}
}
pub fn seq_lt(
vm: &VirtualMachine,
zelf: &impl SimpleSeq,
other: &impl SimpleSeq,
) -> PyResult<bool> {
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
if let Some(v) = vm.bool_seq_lt(a.clone(), b.clone())? {
return Ok(v);
}
}
Ok(zelf.len() < other.len())
}
pub fn seq_gt(
vm: &VirtualMachine,
zelf: &impl SimpleSeq,
other: &impl SimpleSeq,
) -> PyResult<bool> {
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
if let Some(v) = vm.bool_seq_gt(a.clone(), b.clone())? {
return Ok(v);
}
}
Ok(zelf.len() > other.len())
}
pub fn seq_ge(
vm: &VirtualMachine,
zelf: &impl SimpleSeq,
other: &impl SimpleSeq,
) -> PyResult<bool> {
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
if let Some(v) = vm.bool_seq_gt(a.clone(), b.clone())? {
return Ok(v);
}
}
Ok(zelf.len() >= other.len())
}
pub fn seq_le(
vm: &VirtualMachine,
zelf: &impl SimpleSeq,
other: &impl SimpleSeq,
) -> PyResult<bool> {
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
if let Some(v) = vm.bool_seq_lt(a.clone(), b.clone())? {
return Ok(v);
}
}
Ok(zelf.len() <= other.len())
}
pub struct SeqMul<'a> {
seq: &'a dyn SimpleSeq,
repetitions: usize,
iter: Option<DynPyIter<'a>>,
}
impl<'a> Iterator for SeqMul<'a> {
type Item = &'a PyObjectRef;
fn next(&mut self) -> Option<Self::Item> {
if self.seq.len() == 0 {
return None;
}
match self.iter.as_mut().and_then(Iterator::next) {
Some(item) => Some(item),
None => {
if self.repetitions == 0 {
None
} else {
self.repetitions -= 1;
self.iter = Some(self.seq.iter());
self.next()
}
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.iter.as_ref().map_or(0, ExactSizeIterator::len)
+ (self.repetitions * self.seq.len());
(size, Some(size))
}
}
impl ExactSizeIterator for SeqMul<'_> {}
pub fn seq_mul<'a>(seq: &'a impl SimpleSeq, repetitions: isize) -> SeqMul<'a> {
SeqMul {
seq,
repetitions: repetitions.max(0) as usize,
iter: None,
}
}
//Check if given arg could be used with PySliceableSequence.get_slice_range()
pub fn is_valid_slice_arg(
arg: OptionalArg<PyObjectRef>,

View File

@@ -2,7 +2,7 @@ use std::cell::Cell;
use std::fmt;
use super::objiter;
use super::objsequence::{get_item, seq_equal, seq_ge, seq_gt, seq_le, seq_lt, seq_mul, SimpleSeq};
use super::objsequence::get_item;
use super::objtype::PyClassRef;
use crate::function::OptionalArg;
use crate::pyhash;
@@ -10,6 +10,7 @@ use crate::pyobject::{
IntoPyObject, PyArithmaticValue::*, PyClassImpl, PyComparisonValue, PyContext, PyObjectRef,
PyRef, PyResult, PyValue,
};
use crate::sequence::{self, SimpleSeq};
use crate::vm::{ReprGuard, VirtualMachine};
/// tuple() -> empty tuple
@@ -95,22 +96,22 @@ impl PyTuple {
#[pymethod(name = "__lt__")]
fn lt(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyComparisonValue> {
self.cmp(other, |a, b| seq_lt(vm, a, b), vm)
self.cmp(other, |a, b| sequence::lt(vm, a, b), vm)
}
#[pymethod(name = "__gt__")]
fn gt(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyComparisonValue> {
self.cmp(other, |a, b| seq_gt(vm, a, b), vm)
self.cmp(other, |a, b| sequence::gt(vm, a, b), vm)
}
#[pymethod(name = "__ge__")]
fn ge(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyComparisonValue> {
self.cmp(other, |a, b| seq_ge(vm, a, b), vm)
self.cmp(other, |a, b| sequence::ge(vm, a, b), vm)
}
#[pymethod(name = "__le__")]
fn le(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyComparisonValue> {
self.cmp(other, |a, b| seq_le(vm, a, b), vm)
self.cmp(other, |a, b| sequence::le(vm, a, b), vm)
}
#[pymethod(name = "__add__")]
@@ -146,7 +147,7 @@ impl PyTuple {
#[pymethod(name = "__eq__")]
fn eq(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyComparisonValue> {
self.cmp(other, |a, b| seq_equal(vm, a, b), vm)
self.cmp(other, |a, b| sequence::eq(vm, a, b), vm)
}
#[pymethod(name = "__ne__")]
@@ -194,7 +195,9 @@ impl PyTuple {
#[pymethod(name = "__mul__")]
fn mul(&self, counter: isize, vm: &VirtualMachine) -> PyObjectRef {
let new_elements = seq_mul(&self.elements, counter).cloned().collect();
let new_elements = sequence::seq_mul(&self.elements, counter)
.cloned()
.collect();
vm.ctx.new_tuple(new_elements)
}

View File

@@ -1,2 +1,146 @@
use crate::pyobject::{PyObjectRef, PyResult, PyValue};
use crate::pyobject::{IdProtocol, PyObjectRef, PyResult};
use crate::vm::VirtualMachine;
use std::ops::Deref;
type DynPyIter<'a> = Box<dyn ExactSizeIterator<Item = &'a PyObjectRef> + 'a>;
#[allow(clippy::len_without_is_empty)]
pub trait SimpleSeq {
fn len(&self) -> usize;
fn iter(&self) -> DynPyIter;
}
// impl SimpleSeq for &[PyObjectRef] {
// fn len(&self) -> usize {
// (&**self).len()
// }
// fn iter(&self) -> DynPyIter {
// Box::new((&**self).iter())
// }
// }
impl SimpleSeq for Vec<PyObjectRef> {
fn len(&self) -> usize {
self.len()
}
fn iter(&self) -> DynPyIter {
Box::new(self.as_slice().iter())
}
}
impl SimpleSeq for std::collections::VecDeque<PyObjectRef> {
fn len(&self) -> usize {
self.len()
}
fn iter(&self) -> DynPyIter {
Box::new(self.iter())
}
}
impl<T> SimpleSeq for std::cell::Ref<'_, T>
where
T: SimpleSeq,
{
fn len(&self) -> usize {
self.deref().len()
}
fn iter(&self) -> DynPyIter {
self.deref().iter()
}
}
// impl<'a, I>
pub fn eq(vm: &VirtualMachine, zelf: &impl SimpleSeq, other: &impl SimpleSeq) -> PyResult<bool> {
if zelf.len() == other.len() {
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
if a.is(b) {
continue;
}
if !vm.bool_eq(a.clone(), b.clone())? {
return Ok(false);
}
}
Ok(true)
} else {
Ok(false)
}
}
pub fn lt(vm: &VirtualMachine, zelf: &impl SimpleSeq, other: &impl SimpleSeq) -> PyResult<bool> {
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
if let Some(v) = vm.bool_seq_lt(a.clone(), b.clone())? {
return Ok(v);
}
}
Ok(zelf.len() < other.len())
}
pub fn gt(vm: &VirtualMachine, zelf: &impl SimpleSeq, other: &impl SimpleSeq) -> PyResult<bool> {
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
if let Some(v) = vm.bool_seq_gt(a.clone(), b.clone())? {
return Ok(v);
}
}
Ok(zelf.len() > other.len())
}
pub fn ge(vm: &VirtualMachine, zelf: &impl SimpleSeq, other: &impl SimpleSeq) -> PyResult<bool> {
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
if let Some(v) = vm.bool_seq_gt(a.clone(), b.clone())? {
return Ok(v);
}
}
Ok(zelf.len() >= other.len())
}
pub fn le(vm: &VirtualMachine, zelf: &impl SimpleSeq, other: &impl SimpleSeq) -> PyResult<bool> {
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
if let Some(v) = vm.bool_seq_lt(a.clone(), b.clone())? {
return Ok(v);
}
}
Ok(zelf.len() <= other.len())
}
pub struct SeqMul<'a> {
seq: &'a dyn SimpleSeq,
repetitions: usize,
iter: Option<DynPyIter<'a>>,
}
impl<'a> Iterator for SeqMul<'a> {
type Item = &'a PyObjectRef;
fn next(&mut self) -> Option<Self::Item> {
if self.seq.len() == 0 {
return None;
}
match self.iter.as_mut().and_then(Iterator::next) {
Some(item) => Some(item),
None => {
if self.repetitions == 0 {
None
} else {
self.repetitions -= 1;
self.iter = Some(self.seq.iter());
self.next()
}
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.iter.as_ref().map_or(0, ExactSizeIterator::len)
+ (self.repetitions * self.seq.len());
(size, Some(size))
}
}
impl ExactSizeIterator for SeqMul<'_> {}
pub fn seq_mul<'a>(seq: &'a impl SimpleSeq, repetitions: isize) -> SeqMul<'a> {
SeqMul {
seq,
repetitions: repetitions.max(0) as usize,
iter: None,
}
}

View File

@@ -1,6 +1,7 @@
use crate::function::OptionalArg;
use crate::obj::{objiter, objsequence, objtype::PyClassRef};
use crate::obj::{objiter, objtype::PyClassRef};
use crate::pyobject::{IdProtocol, PyClassImpl, PyIterable, PyObjectRef, PyRef, PyResult, PyValue};
use crate::sequence::{self, SimpleSeq};
use crate::vm::ReprGuard;
use crate::VirtualMachine;
use itertools::Itertools;
@@ -28,7 +29,7 @@ struct PyDequeOptions {
}
impl PyDeque {
pub fn borrow_sequence<'a>(&'a self) -> impl objsequence::SimpleSeq + 'a {
pub fn borrow_sequence<'a>(&'a self) -> impl SimpleSeq + 'a {
self.deque.borrow()
}
}
@@ -247,7 +248,7 @@ impl PyDeque {
let lhs = &zelf.borrow_sequence();
let rhs = &other.borrow_sequence();
let eq = objsequence::seq_equal(vm, lhs, rhs)?;
let eq = sequence::eq(vm, lhs, rhs)?;
Ok(vm.new_bool(eq))
}
@@ -265,7 +266,7 @@ impl PyDeque {
let lhs = &zelf.borrow_sequence();
let rhs = &other.borrow_sequence();
let eq = objsequence::seq_lt(vm, lhs, rhs)?;
let eq = sequence::lt(vm, lhs, rhs)?;
Ok(vm.new_bool(eq))
}
@@ -283,7 +284,7 @@ impl PyDeque {
let lhs = &zelf.borrow_sequence();
let rhs = &other.borrow_sequence();
let eq = objsequence::seq_gt(vm, lhs, rhs)?;
let eq = sequence::gt(vm, lhs, rhs)?;
Ok(vm.new_bool(eq))
}
@@ -301,7 +302,7 @@ impl PyDeque {
let lhs = &zelf.borrow_sequence();
let rhs = &other.borrow_sequence();
let eq = objsequence::seq_le(vm, lhs, rhs)?;
let eq = sequence::le(vm, lhs, rhs)?;
Ok(vm.new_bool(eq))
}
@@ -319,14 +320,14 @@ impl PyDeque {
let lhs = &zelf.borrow_sequence();
let rhs = &other.borrow_sequence();
let eq = objsequence::seq_ge(vm, lhs, rhs)?;
let eq = sequence::ge(vm, lhs, rhs)?;
Ok(vm.new_bool(eq))
}
#[pymethod(name = "__mul__")]
fn mul(&self, n: isize, _vm: &VirtualMachine) -> Self {
let deque: &VecDeque<_> = &self.deque.borrow();
let mul = objsequence::seq_mul(deque, n);
let mul = sequence::seq_mul(deque, n);
let skipped = if let Some(maxlen) = self.maxlen.get() {
mul.len() - maxlen
} else {