mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Merge pull request #1655 from youknowone/refactor-tuple
Refactor list, tuple and collections.deque
This commit is contained in:
17 files changed
+520
-513
No files matched your search
+2
-2
@@ -52,9 +52,9 @@ fn main() {
|
||||
if let Err(err) = res {
|
||||
if objtype::isinstance(&err, &vm.ctx.exceptions.system_exit) {
|
||||
let args = err.args();
|
||||
match args.elements.len() {
|
||||
match args.as_slice().len() {
|
||||
0 => return,
|
||||
1 => match_class!(match args.elements[0].clone() {
|
||||
1 => match_class!(match args.as_slice()[0].clone() {
|
||||
i @ PyInt => {
|
||||
use num_traits::cast::ToPrimitive;
|
||||
process::exit(i.as_bigint().to_i32().unwrap());
|
||||
|
||||
@@ -37,3 +37,10 @@ assert deque(maxlen=3) == deque()
|
||||
assert deque([1, 2, 3, 4], maxlen=2) == deque([3, 4])
|
||||
|
||||
assert len(deque([1, 2, 3, 4])) == 4
|
||||
|
||||
assert d >= d
|
||||
assert not (d > d)
|
||||
assert d <= d
|
||||
assert not (d < d)
|
||||
assert d == d
|
||||
assert not (d != d)
|
||||
@@ -275,20 +275,20 @@ fn exception_args_as_string(
|
||||
varargs: PyTupleRef,
|
||||
str_single: bool,
|
||||
) -> Vec<PyStringRef> {
|
||||
match varargs.elements.len() {
|
||||
let varargs = varargs.as_slice();
|
||||
match varargs.len() {
|
||||
0 => vec![],
|
||||
1 => {
|
||||
let args0_repr = if str_single {
|
||||
vm.to_str(&varargs.elements[0])
|
||||
vm.to_str(&varargs[0])
|
||||
.unwrap_or_else(|_| PyString::from("<element str() failed>").into_ref(vm))
|
||||
} else {
|
||||
vm.to_repr(&varargs.elements[0])
|
||||
vm.to_repr(&varargs[0])
|
||||
.unwrap_or_else(|_| PyString::from("<element repr() failed>").into_ref(vm))
|
||||
};
|
||||
vec![args0_repr]
|
||||
}
|
||||
_ => varargs
|
||||
.elements
|
||||
.iter()
|
||||
.map(|vararg| {
|
||||
vm.to_repr(vararg)
|
||||
@@ -362,8 +362,8 @@ impl ExceptionCtor {
|
||||
(Self::Class(cls), _) => {
|
||||
let args = match_class!(match value {
|
||||
PyNone => vec![],
|
||||
tup @ PyTuple => tup.elements.clone(),
|
||||
exc @ PyBaseException => exc.args().elements.clone(),
|
||||
tup @ PyTuple => tup.as_slice().to_vec(),
|
||||
exc @ PyBaseException => exc.args().as_slice().to_vec(),
|
||||
obj => vec![obj],
|
||||
});
|
||||
invoke(cls, args, vm)
|
||||
@@ -609,7 +609,7 @@ fn make_arg_getter(idx: usize) -> impl Fn(PyBaseExceptionRef, &VirtualMachine) -
|
||||
move |exc, vm| {
|
||||
exc.args
|
||||
.borrow()
|
||||
.elements
|
||||
.as_slice()
|
||||
.get(idx)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| vm.get_none())
|
||||
|
||||
+1
-1
@@ -583,7 +583,7 @@ pub fn single_or_tuple_any<T: PyValue, F: Fn(PyRef<T>) -> PyResult<bool>>(
|
||||
match_class!(match obj {
|
||||
obj @ T => (self.predicate)(obj),
|
||||
tuple @ PyTuple => {
|
||||
for obj in tuple.elements.iter() {
|
||||
for obj in tuple.as_slice().iter() {
|
||||
if self.check(obj.clone())? {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ pub mod py_serde;
|
||||
mod pyhash;
|
||||
pub mod pyobject;
|
||||
pub mod scope;
|
||||
mod sequence;
|
||||
pub mod stdlib;
|
||||
mod sysmodule;
|
||||
pub mod types;
|
||||
|
||||
@@ -11,7 +11,7 @@ use super::objint::{self, PyInt, PyIntRef};
|
||||
use super::objlist::PyList;
|
||||
use super::objmemory::PyMemoryView;
|
||||
use super::objnone::PyNoneRef;
|
||||
use super::objsequence::{self, is_valid_slice_arg, PySliceableSequence};
|
||||
use super::objsequence::{is_valid_slice_arg, PySliceableSequence};
|
||||
use super::objslice::PySliceRef;
|
||||
use super::objstr::{self, PyString, PyStringRef};
|
||||
use super::objtuple::PyTupleRef;
|
||||
@@ -859,8 +859,8 @@ impl PyByteInner {
|
||||
Either::A(byte) => byte.elements,
|
||||
Either::B(tuple) => {
|
||||
let mut flatten = vec![];
|
||||
for v in objsequence::get_elements_tuple(tuple.as_object()).to_vec() {
|
||||
flatten.extend(PyByteInner::try_from_object(vm, v)?.elements)
|
||||
for v in tuple.as_slice() {
|
||||
flatten.extend(PyByteInner::try_from_object(vm, v.clone())?.elements)
|
||||
}
|
||||
flatten
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ pub fn new_stop_iteration(vm: &VirtualMachine) -> PyBaseExceptionRef {
|
||||
pub fn stop_iter_value(vm: &VirtualMachine, exc: &PyBaseExceptionRef) -> PyResult {
|
||||
let args = exc.args();
|
||||
let val = args
|
||||
.elements
|
||||
.as_slice()
|
||||
.first()
|
||||
.cloned()
|
||||
.unwrap_or_else(|| vm.get_none());
|
||||
|
||||
+174
-183
@@ -10,22 +10,25 @@ use super::objbool;
|
||||
use super::objbyteinner;
|
||||
use super::objint::PyIntRef;
|
||||
use super::objiter;
|
||||
use super::objsequence::{
|
||||
get_elements_list, get_item, seq_equal, seq_ge, seq_gt, seq_le, seq_lt, seq_mul, SequenceIndex,
|
||||
};
|
||||
use super::objsequence::{get_item, SequenceIndex};
|
||||
use super::objslice::PySliceRef;
|
||||
use super::objtype::{self, PyClassRef};
|
||||
use super::objtype::PyClassRef;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::pyobject::{
|
||||
IdProtocol, PyClassImpl, PyContext, PyIterable, PyObjectRef, PyRef, PyResult, PyValue,
|
||||
TryFromObject, TypeProtocol,
|
||||
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.
|
||||
///
|
||||
/// If no argument is given, the constructor creates a new empty list.
|
||||
/// The argument must be an iterable if specified.
|
||||
#[pyclass]
|
||||
#[derive(Default)]
|
||||
pub struct PyList {
|
||||
// TODO: shouldn't be public
|
||||
pub elements: RefCell<Vec<PyObjectRef>>,
|
||||
elements: RefCell<Vec<PyObjectRef>>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for PyList {
|
||||
@@ -50,11 +53,21 @@ impl PyValue for PyList {
|
||||
}
|
||||
|
||||
impl PyList {
|
||||
pub fn get_len(&self) -> usize {
|
||||
pub fn borrow_sequence<'a>(&'a self) -> impl SimpleSeq + 'a {
|
||||
self.elements.borrow()
|
||||
}
|
||||
|
||||
pub fn borrow_elements<'a>(&'a self) -> impl std::ops::Deref<Target = Vec<PyObjectRef>> + 'a {
|
||||
self.elements.borrow()
|
||||
}
|
||||
}
|
||||
|
||||
impl PyList {
|
||||
fn get_len(&self) -> usize {
|
||||
self.elements.borrow().len()
|
||||
}
|
||||
|
||||
pub fn get_pos(&self, p: i32) -> Option<usize> {
|
||||
fn get_pos(&self, p: i32) -> Option<usize> {
|
||||
// convert a (potentially negative) positon into a real index
|
||||
if p < 0 {
|
||||
if -p as usize > self.get_len() {
|
||||
@@ -69,7 +82,7 @@ impl PyList {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_slice_pos(&self, slice_pos: &BigInt) -> usize {
|
||||
fn get_slice_pos(&self, slice_pos: &BigInt) -> usize {
|
||||
if let Some(pos) = slice_pos.to_i32() {
|
||||
if let Some(index) = self.get_pos(pos) {
|
||||
// within bounds
|
||||
@@ -86,7 +99,7 @@ impl PyList {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_slice_range(&self, start: &Option<BigInt>, stop: &Option<BigInt>) -> Range<usize> {
|
||||
fn get_slice_range(&self, start: &Option<BigInt>, stop: &Option<BigInt>) -> Range<usize> {
|
||||
let start = start.as_ref().map(|x| self.get_slice_pos(x)).unwrap_or(0);
|
||||
let stop = stop
|
||||
.as_ref()
|
||||
@@ -96,7 +109,10 @@ impl PyList {
|
||||
start..stop
|
||||
}
|
||||
|
||||
pub fn get_byte_inner(&self, vm: &VirtualMachine) -> PyResult<objbyteinner::PyByteInner> {
|
||||
pub(crate) fn get_byte_inner(
|
||||
&self,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<objbyteinner::PyByteInner> {
|
||||
let mut elements = Vec::<u8>::with_capacity(self.get_len());
|
||||
for elem in self.elements.borrow().iter() {
|
||||
match PyIntRef::try_from_object(vm, elem.clone()) {
|
||||
@@ -130,18 +146,22 @@ struct SortOptions {
|
||||
|
||||
pub type PyListRef = PyRef<PyList>;
|
||||
|
||||
impl PyListRef {
|
||||
pub fn append(self, x: PyObjectRef, _vm: &VirtualMachine) {
|
||||
#[pyimpl]
|
||||
impl PyList {
|
||||
#[pymethod]
|
||||
pub(crate) fn append(&self, x: PyObjectRef, _vm: &VirtualMachine) {
|
||||
self.elements.borrow_mut().push(x);
|
||||
}
|
||||
|
||||
fn extend(self, x: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
#[pymethod]
|
||||
fn extend(&self, x: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let mut new_elements = vm.extract_elements(&x)?;
|
||||
self.elements.borrow_mut().append(&mut new_elements);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn insert(self, position: isize, element: PyObjectRef, _vm: &VirtualMachine) {
|
||||
#[pymethod]
|
||||
fn insert(&self, position: isize, element: PyObjectRef, _vm: &VirtualMachine) {
|
||||
let mut vec = self.elements.borrow_mut();
|
||||
let vec_len = vec.len().to_isize().unwrap();
|
||||
// This unbounded position can be < 0 or > vec.len()
|
||||
@@ -155,76 +175,93 @@ impl PyListRef {
|
||||
vec.insert(position, element.clone());
|
||||
}
|
||||
|
||||
fn add(self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&other, &vm.ctx.list_type()) {
|
||||
let e1 = self.elements.borrow();
|
||||
let e2 = get_elements_list(&other);
|
||||
#[pymethod(name = "__add__")]
|
||||
fn add(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if let Some(other) = other.payload_if_subclass::<PyList>(vm) {
|
||||
let e1 = self.borrow_sequence();
|
||||
let e2 = other.borrow_sequence();
|
||||
let elements = e1.iter().chain(e2.iter()).cloned().collect();
|
||||
Ok(vm.ctx.new_list(elements))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!("Cannot add {} and {}", self.as_object(), other)))
|
||||
Err(vm.new_type_error(format!(
|
||||
"Cannot add {} and {}",
|
||||
Self::class(vm).name,
|
||||
other.class().name
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
fn iadd(self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
#[pymethod(name = "__iadd__")]
|
||||
fn iadd(zelf: PyRef<Self>, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if let Ok(new_elements) = vm.extract_elements(&other) {
|
||||
let mut e = new_elements;
|
||||
self.elements.borrow_mut().append(&mut e);
|
||||
Ok(self.into_object())
|
||||
zelf.elements.borrow_mut().append(&mut e);
|
||||
Ok(zelf.into_object())
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}
|
||||
|
||||
fn bool(self, _vm: &VirtualMachine) -> bool {
|
||||
#[pymethod(name = "__bool__")]
|
||||
fn bool(&self, _vm: &VirtualMachine) -> bool {
|
||||
!self.elements.borrow().is_empty()
|
||||
}
|
||||
|
||||
fn clear(self, _vm: &VirtualMachine) {
|
||||
#[pymethod]
|
||||
fn clear(&self, _vm: &VirtualMachine) {
|
||||
self.elements.borrow_mut().clear();
|
||||
}
|
||||
|
||||
fn copy(self, vm: &VirtualMachine) -> PyObjectRef {
|
||||
#[pymethod]
|
||||
fn copy(&self, vm: &VirtualMachine) -> PyObjectRef {
|
||||
vm.ctx.new_list(self.elements.borrow().clone())
|
||||
}
|
||||
|
||||
fn len(self, _vm: &VirtualMachine) -> usize {
|
||||
#[pymethod(name = "__len__")]
|
||||
fn len(&self, _vm: &VirtualMachine) -> usize {
|
||||
self.elements.borrow().len()
|
||||
}
|
||||
|
||||
fn sizeof(self, _vm: &VirtualMachine) -> usize {
|
||||
#[pymethod(name = "__sizeof__")]
|
||||
fn sizeof(&self, _vm: &VirtualMachine) -> usize {
|
||||
size_of::<Self>() + self.elements.borrow().capacity() * size_of::<PyObjectRef>()
|
||||
}
|
||||
|
||||
fn reverse(self, _vm: &VirtualMachine) {
|
||||
#[pymethod]
|
||||
fn reverse(&self, _vm: &VirtualMachine) {
|
||||
self.elements.borrow_mut().reverse();
|
||||
}
|
||||
fn reversed(self, _vm: &VirtualMachine) -> PyListReverseIterator {
|
||||
let final_position = self.elements.borrow().len();
|
||||
|
||||
#[pymethod(name = "__reversed__")]
|
||||
fn reversed(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyListReverseIterator {
|
||||
let final_position = zelf.elements.borrow().len();
|
||||
PyListReverseIterator {
|
||||
position: Cell::new(final_position),
|
||||
list: self,
|
||||
list: zelf,
|
||||
}
|
||||
}
|
||||
|
||||
fn getitem(self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
#[pymethod(name = "__getitem__")]
|
||||
fn getitem(zelf: PyRef<Self>, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
get_item(
|
||||
vm,
|
||||
self.as_object(),
|
||||
&self.elements.borrow(),
|
||||
zelf.as_object(),
|
||||
&zelf.elements.borrow(),
|
||||
needle.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
fn iter(self, _vm: &VirtualMachine) -> PyListIterator {
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyListIterator {
|
||||
PyListIterator {
|
||||
position: Cell::new(0),
|
||||
list: self,
|
||||
list: zelf,
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod(name = "__setitem__")]
|
||||
fn setitem(
|
||||
self,
|
||||
&self,
|
||||
subscript: SequenceIndex,
|
||||
value: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
@@ -240,7 +277,7 @@ impl PyListRef {
|
||||
}
|
||||
}
|
||||
|
||||
fn setindex(self, index: i32, value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn setindex(&self, index: i32, value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if let Some(pos_index) = self.get_pos(index) {
|
||||
self.elements.borrow_mut()[pos_index] = value;
|
||||
Ok(vm.get_none())
|
||||
@@ -249,7 +286,7 @@ impl PyListRef {
|
||||
}
|
||||
}
|
||||
|
||||
fn setslice(self, slice: PySliceRef, sec: PyIterable, vm: &VirtualMachine) -> PyResult {
|
||||
fn setslice(&self, slice: PySliceRef, sec: PyIterable, vm: &VirtualMachine) -> PyResult {
|
||||
let step = slice.step_index(vm)?.unwrap_or_else(BigInt::one);
|
||||
|
||||
if step.is_zero() {
|
||||
@@ -303,7 +340,7 @@ impl PyListRef {
|
||||
}
|
||||
}
|
||||
|
||||
fn _set_slice(self, range: Range<usize>, sec: PyIterable, vm: &VirtualMachine) -> PyResult {
|
||||
fn _set_slice(&self, range: Range<usize>, sec: PyIterable, vm: &VirtualMachine) -> PyResult {
|
||||
// consume the iter, we need it's size
|
||||
// and if it's going to fail we want that to happen *before* we start modifing
|
||||
let items: Result<Vec<PyObjectRef>, _> = sec.iter(vm)?.collect();
|
||||
@@ -316,7 +353,7 @@ impl PyListRef {
|
||||
}
|
||||
|
||||
fn _set_stepped_slice(
|
||||
self,
|
||||
&self,
|
||||
range: Range<usize>,
|
||||
step: usize,
|
||||
sec: PyIterable,
|
||||
@@ -358,7 +395,7 @@ impl PyListRef {
|
||||
}
|
||||
|
||||
fn _set_stepped_slice_reverse(
|
||||
self,
|
||||
&self,
|
||||
range: Range<usize>,
|
||||
step: usize,
|
||||
sec: PyIterable,
|
||||
@@ -400,7 +437,7 @@ impl PyListRef {
|
||||
}
|
||||
}
|
||||
|
||||
fn _replace_indexes<I>(self, indexes: I, items: &[PyObjectRef])
|
||||
fn _replace_indexes<I>(&self, indexes: I, items: &[PyObjectRef])
|
||||
where
|
||||
I: Iterator<Item = usize>,
|
||||
{
|
||||
@@ -412,10 +449,11 @@ impl PyListRef {
|
||||
}
|
||||
}
|
||||
|
||||
fn repr(self, vm: &VirtualMachine) -> PyResult<String> {
|
||||
let s = if let Some(_guard) = ReprGuard::enter(self.as_object()) {
|
||||
let mut str_parts = Vec::with_capacity(self.elements.borrow().len());
|
||||
for elem in self.elements.borrow().iter() {
|
||||
#[pymethod(name = "__repr__")]
|
||||
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
|
||||
let s = if let Some(_guard) = ReprGuard::enter(zelf.as_object()) {
|
||||
let mut str_parts = Vec::with_capacity(zelf.elements.borrow().len());
|
||||
for elem in zelf.elements.borrow().iter() {
|
||||
let s = vm.to_repr(elem)?;
|
||||
str_parts.push(s.as_str().to_string());
|
||||
}
|
||||
@@ -426,30 +464,35 @@ impl PyListRef {
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
fn hash(self, vm: &VirtualMachine) -> PyResult<()> {
|
||||
#[pymethod(name = "__hash__")]
|
||||
fn hash(&self, vm: &VirtualMachine) -> PyResult<()> {
|
||||
Err(vm.new_type_error("unhashable type".to_string()))
|
||||
}
|
||||
|
||||
fn mul(self, counter: isize, vm: &VirtualMachine) -> PyObjectRef {
|
||||
let new_elements = seq_mul(&self.elements.borrow().as_slice(), counter)
|
||||
#[pymethod(name = "__mul__")]
|
||||
fn mul(&self, counter: isize, vm: &VirtualMachine) -> PyObjectRef {
|
||||
let new_elements = sequence::seq_mul(&self.borrow_sequence(), counter)
|
||||
.cloned()
|
||||
.collect();
|
||||
vm.ctx.new_list(new_elements)
|
||||
}
|
||||
|
||||
fn rmul(self, counter: isize, vm: &VirtualMachine) -> PyObjectRef {
|
||||
#[pymethod(name = "__rmul__")]
|
||||
fn rmul(&self, counter: isize, vm: &VirtualMachine) -> PyObjectRef {
|
||||
self.mul(counter, &vm)
|
||||
}
|
||||
|
||||
fn imul(self, counter: isize, _vm: &VirtualMachine) -> Self {
|
||||
let new_elements = seq_mul(&self.elements.borrow().as_slice(), counter)
|
||||
#[pymethod(name = "__imul__")]
|
||||
fn imul(zelf: PyRef<Self>, counter: isize, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
let new_elements = sequence::seq_mul(&zelf.borrow_sequence(), counter)
|
||||
.cloned()
|
||||
.collect();
|
||||
self.elements.replace(new_elements);
|
||||
self
|
||||
zelf.elements.replace(new_elements);
|
||||
zelf
|
||||
}
|
||||
|
||||
fn count(self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
#[pymethod]
|
||||
fn count(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
let mut count: usize = 0;
|
||||
for element in self.elements.borrow().iter() {
|
||||
if vm.identical_or_equal(element, &needle)? {
|
||||
@@ -459,7 +502,8 @@ impl PyListRef {
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
fn contains(self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
#[pymethod(name = "__contains__")]
|
||||
fn contains(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
for element in self.elements.borrow().iter() {
|
||||
if vm.identical_or_equal(element, &needle)? {
|
||||
return Ok(true);
|
||||
@@ -469,7 +513,8 @@ impl PyListRef {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn index(self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
#[pymethod]
|
||||
fn index(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
for (index, element) in self.elements.borrow().iter().enumerate() {
|
||||
if vm.identical_or_equal(element, &needle)? {
|
||||
return Ok(index);
|
||||
@@ -479,7 +524,8 @@ impl PyListRef {
|
||||
Err(vm.new_value_error(format!("'{}' is not in list", needle_str.as_str())))
|
||||
}
|
||||
|
||||
fn pop(self, i: OptionalArg<isize>, vm: &VirtualMachine) -> PyResult {
|
||||
#[pymethod]
|
||||
fn pop(&self, i: OptionalArg<isize>, vm: &VirtualMachine) -> PyResult {
|
||||
let mut i = i.into_option().unwrap_or(-1);
|
||||
let mut elements = self.elements.borrow_mut();
|
||||
if i < 0 {
|
||||
@@ -494,7 +540,8 @@ impl PyListRef {
|
||||
}
|
||||
}
|
||||
|
||||
fn remove(self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
#[pymethod]
|
||||
fn remove(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let mut ri: Option<usize> = None;
|
||||
for (index, element) in self.elements.borrow().iter().enumerate() {
|
||||
if vm.identical_or_equal(element, &needle)? {
|
||||
@@ -512,86 +559,70 @@ impl PyListRef {
|
||||
}
|
||||
}
|
||||
|
||||
fn eq(self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let value = if self.as_object().is(&other) {
|
||||
vm.new_bool(true)
|
||||
} else if objtype::isinstance(&other, &vm.ctx.list_type()) {
|
||||
vm.new_bool(self.inner_eq(&other, vm)?)
|
||||
#[inline]
|
||||
fn cmp<F>(&self, other: PyObjectRef, op: F, vm: &VirtualMachine) -> PyResult<PyComparisonValue>
|
||||
where
|
||||
F: Fn(&Vec<PyObjectRef>, &Vec<PyObjectRef>) -> PyResult<bool>,
|
||||
{
|
||||
let r = if let Some(other) = other.payload_if_subclass::<PyList>(vm) {
|
||||
Implemented(op(&*self.borrow_elements(), &*other.borrow_elements())?)
|
||||
} else {
|
||||
vm.ctx.not_implemented()
|
||||
NotImplemented
|
||||
};
|
||||
Ok(value)
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
fn ne(self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let value = if self.as_object().is(&other) {
|
||||
vm.new_bool(false)
|
||||
} else if objtype::isinstance(&other, &vm.ctx.list_type()) {
|
||||
vm.new_bool(!self.inner_eq(&other, vm)?)
|
||||
#[pymethod(name = "__eq__")]
|
||||
fn eq(
|
||||
zelf: PyRef<Self>,
|
||||
other: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyComparisonValue> {
|
||||
if zelf.as_object().is(&other) {
|
||||
Ok(Implemented(true))
|
||||
} else {
|
||||
vm.ctx.not_implemented()
|
||||
};
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn inner_eq(self, other: &PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
let zelf = self.elements.borrow();
|
||||
let other = get_elements_list(other);
|
||||
seq_equal(vm, &zelf.as_slice(), &other.as_slice())
|
||||
}
|
||||
|
||||
fn lt(self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&other, &vm.ctx.list_type()) {
|
||||
let zelf = self.elements.borrow();
|
||||
let other = get_elements_list(&other);
|
||||
let res = seq_lt(vm, &zelf.as_slice(), &other.as_slice())?;
|
||||
Ok(vm.new_bool(res))
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
zelf.cmp(other, |a, b| sequence::eq(vm, a, b), vm)
|
||||
}
|
||||
}
|
||||
|
||||
fn gt(self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&other, &vm.ctx.list_type()) {
|
||||
let zelf = self.elements.borrow();
|
||||
let other = get_elements_list(&other);
|
||||
let res = seq_gt(vm, &zelf.as_slice(), &other.as_slice())?;
|
||||
Ok(vm.new_bool(res))
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
#[pymethod(name = "__ne__")]
|
||||
fn ne(
|
||||
zelf: PyRef<Self>,
|
||||
other: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyComparisonValue> {
|
||||
Ok(PyList::eq(zelf, other, vm)?.map(|v| !v))
|
||||
}
|
||||
|
||||
fn ge(self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&other, &vm.ctx.list_type()) {
|
||||
let zelf = self.elements.borrow();
|
||||
let other = get_elements_list(&other);
|
||||
let res = seq_ge(vm, &zelf.as_slice(), &other.as_slice())?;
|
||||
Ok(vm.new_bool(res))
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
#[pymethod(name = "__lt__")]
|
||||
fn lt(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyComparisonValue> {
|
||||
self.cmp(other, |a, b| sequence::lt(vm, a, b), vm)
|
||||
}
|
||||
|
||||
fn le(self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&other, &vm.ctx.list_type()) {
|
||||
let zelf = self.elements.borrow();
|
||||
let other = get_elements_list(&other);
|
||||
let res = seq_le(vm, &zelf.as_slice(), &other.as_slice())?;
|
||||
Ok(vm.new_bool(res))
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
#[pymethod(name = "__gt__")]
|
||||
fn gt(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyComparisonValue> {
|
||||
self.cmp(other, |a, b| sequence::gt(vm, a, b), vm)
|
||||
}
|
||||
|
||||
fn delitem(self, subscript: SequenceIndex, vm: &VirtualMachine) -> PyResult<()> {
|
||||
#[pymethod(name = "__ge__")]
|
||||
fn ge(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyComparisonValue> {
|
||||
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| sequence::le(vm, a, b), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__delitem__")]
|
||||
fn delitem(&self, subscript: SequenceIndex, vm: &VirtualMachine) -> PyResult<()> {
|
||||
match subscript {
|
||||
SequenceIndex::Int(index) => self.delindex(index, vm),
|
||||
SequenceIndex::Slice(slice) => self.delslice(slice, vm),
|
||||
}
|
||||
}
|
||||
|
||||
fn delindex(self, index: i32, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn delindex(&self, index: i32, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if let Some(pos_index) = self.get_pos(index) {
|
||||
self.elements.borrow_mut().remove(pos_index);
|
||||
Ok(())
|
||||
@@ -600,7 +631,7 @@ impl PyListRef {
|
||||
}
|
||||
}
|
||||
|
||||
fn delslice(self, slice: PySliceRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn delslice(&self, slice: PySliceRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let start = slice.start_index(vm)?;
|
||||
let stop = slice.stop_index(vm)?;
|
||||
let step = slice.step_index(vm)?.unwrap_or_else(BigInt::one);
|
||||
@@ -669,11 +700,11 @@ impl PyListRef {
|
||||
}
|
||||
}
|
||||
|
||||
fn _del_slice(self, range: Range<usize>) {
|
||||
fn _del_slice(&self, range: Range<usize>) {
|
||||
self.elements.borrow_mut().drain(range);
|
||||
}
|
||||
|
||||
fn _del_stepped_slice(self, range: Range<usize>, step: usize) {
|
||||
fn _del_stepped_slice(&self, range: Range<usize>, step: usize) {
|
||||
// no easy way to delete stepped indexes so here is what we'll do
|
||||
let mut deleted = 0;
|
||||
let mut elements = self.elements.borrow_mut();
|
||||
@@ -694,7 +725,7 @@ impl PyListRef {
|
||||
elements.drain((range.end - deleted)..range.end);
|
||||
}
|
||||
|
||||
fn _del_stepped_slice_reverse(self, range: Range<usize>, step: usize) {
|
||||
fn _del_stepped_slice_reverse(&self, range: Range<usize>, step: usize) {
|
||||
// no easy way to delete stepped indexes so here is what we'll do
|
||||
let mut deleted = 0;
|
||||
let mut elements = self.elements.borrow_mut();
|
||||
@@ -715,7 +746,8 @@ impl PyListRef {
|
||||
elements.drain(range.start..(range.start + deleted));
|
||||
}
|
||||
|
||||
fn sort(self, options: SortOptions, vm: &VirtualMachine) -> PyResult<()> {
|
||||
#[pymethod]
|
||||
fn sort(&self, options: SortOptions, vm: &VirtualMachine) -> PyResult<()> {
|
||||
// replace list contents with [] for duration of sort.
|
||||
// this prevents keyfunc from messing with the list and makes it easy to
|
||||
// check if it tries to append elements to it.
|
||||
@@ -729,20 +761,21 @@ impl PyListRef {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn list_new(
|
||||
cls: PyClassRef,
|
||||
iterable: OptionalArg<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyListRef> {
|
||||
let elements = if let OptionalArg::Present(iterable) = iterable {
|
||||
vm.extract_elements(&iterable)?
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
#[pyslot(new)]
|
||||
fn list_new(
|
||||
cls: PyClassRef,
|
||||
iterable: OptionalArg<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyListRef> {
|
||||
let elements = if let OptionalArg::Present(iterable) = iterable {
|
||||
vm.extract_elements(&iterable)?
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
PyList::from(elements).into_ref_with_type(vm, cls)
|
||||
PyList::from(elements).into_ref_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
fn quicksort(
|
||||
@@ -875,51 +908,9 @@ impl PyListReverseIterator {
|
||||
}
|
||||
}
|
||||
|
||||
#[rustfmt::skip] // to avoid line splitting
|
||||
pub fn init(context: &PyContext) {
|
||||
let list_type = &context.types.list_type;
|
||||
|
||||
let list_doc = "Built-in mutable sequence.\n\n\
|
||||
If no argument is given, the constructor creates a new empty list.\n\
|
||||
The argument must be an iterable if specified.";
|
||||
|
||||
extend_class!(context, list_type, {
|
||||
"__sizeof__" => context.new_rustfunc(PyListRef::sizeof),
|
||||
"__add__" => context.new_rustfunc(PyListRef::add),
|
||||
"__iadd__" => context.new_rustfunc(PyListRef::iadd),
|
||||
"__bool__" => context.new_rustfunc(PyListRef::bool),
|
||||
"__contains__" => context.new_rustfunc(PyListRef::contains),
|
||||
"__delitem__" => context.new_rustfunc(PyListRef::delitem),
|
||||
"__eq__" => context.new_rustfunc(PyListRef::eq),
|
||||
"__ne__" => context.new_rustfunc(PyListRef::ne),
|
||||
"__lt__" => context.new_rustfunc(PyListRef::lt),
|
||||
"__gt__" => context.new_rustfunc(PyListRef::gt),
|
||||
"__le__" => context.new_rustfunc(PyListRef::le),
|
||||
"__ge__" => context.new_rustfunc(PyListRef::ge),
|
||||
"__getitem__" => context.new_rustfunc(PyListRef::getitem),
|
||||
"__iter__" => context.new_rustfunc(PyListRef::iter),
|
||||
"__setitem__" => context.new_rustfunc(PyListRef::setitem),
|
||||
"__reversed__" => context.new_rustfunc(PyListRef::reversed),
|
||||
"__mul__" => context.new_rustfunc(PyListRef::mul),
|
||||
"__rmul__" => context.new_rustfunc(PyListRef::rmul),
|
||||
"__imul__" => context.new_rustfunc(PyListRef::imul),
|
||||
"__len__" => context.new_rustfunc(PyListRef::len),
|
||||
(slot new) => list_new,
|
||||
"__repr__" => context.new_rustfunc(PyListRef::repr),
|
||||
"__hash__" => context.new_rustfunc(PyListRef::hash),
|
||||
"__doc__" => context.new_str(list_doc.to_string()),
|
||||
"append" => context.new_rustfunc(PyListRef::append),
|
||||
"clear" => context.new_rustfunc(PyListRef::clear),
|
||||
"copy" => context.new_rustfunc(PyListRef::copy),
|
||||
"count" => context.new_rustfunc(PyListRef::count),
|
||||
"extend" => context.new_rustfunc(PyListRef::extend),
|
||||
"index" => context.new_rustfunc(PyListRef::index),
|
||||
"insert" => context.new_rustfunc(PyListRef::insert),
|
||||
"reverse" => context.new_rustfunc(PyListRef::reverse),
|
||||
"sort" => context.new_rustfunc(PyListRef::sort),
|
||||
"pop" => context.new_rustfunc(PyListRef::pop),
|
||||
"remove" => context.new_rustfunc(PyListRef::remove)
|
||||
});
|
||||
PyList::extend_class(context, list_type);
|
||||
|
||||
PyListIterator::extend_class(context, &context.types.listiterator_type);
|
||||
PyListReverseIterator::extend_class(context, &context.types.listreverseiterator_type);
|
||||
|
||||
+2
-157
@@ -1,6 +1,5 @@
|
||||
use std::cell::RefCell;
|
||||
use std::marker::Sized;
|
||||
use std::ops::{Deref, DerefMut, Range};
|
||||
use std::ops::Range;
|
||||
|
||||
use num_bigint::{BigInt, ToBigInt};
|
||||
use num_traits::{One, Signed, ToPrimitive, Zero};
|
||||
@@ -11,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 {
|
||||
@@ -247,160 +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 std::collections::VecDeque<PyObjectRef> {
|
||||
fn len(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
fn iter(&self) -> DynPyIter {
|
||||
Box::new(self.iter())
|
||||
}
|
||||
}
|
||||
|
||||
// impl<'a, I>
|
||||
|
||||
pub fn seq_equal(
|
||||
vm: &VirtualMachine,
|
||||
zelf: &dyn SimpleSeq,
|
||||
other: &dyn 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: &dyn SimpleSeq, other: &dyn 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: &dyn SimpleSeq, other: &dyn 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: &dyn SimpleSeq, other: &dyn 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: &dyn SimpleSeq, other: &dyn 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(seq: &dyn SimpleSeq, repetitions: isize) -> SeqMul {
|
||||
SeqMul {
|
||||
seq,
|
||||
repetitions: repetitions.max(0) as usize,
|
||||
iter: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_elements_cell<'a>(obj: &'a PyObjectRef) -> &'a RefCell<Vec<PyObjectRef>> {
|
||||
if let Some(list) = obj.payload::<PyList>() {
|
||||
return &list.elements;
|
||||
}
|
||||
panic!("Cannot extract elements from non-sequence");
|
||||
}
|
||||
|
||||
pub fn get_elements_list<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<PyObjectRef>> + 'a {
|
||||
if let Some(list) = obj.payload::<PyList>() {
|
||||
return list.elements.borrow();
|
||||
}
|
||||
panic!("Cannot extract elements from non-sequence");
|
||||
}
|
||||
|
||||
pub fn get_elements_tuple<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<PyObjectRef>> + 'a {
|
||||
if let Some(tuple) = obj.payload::<PyTuple>() {
|
||||
return &tuple.elements;
|
||||
}
|
||||
panic!("Cannot extract elements from non-sequence");
|
||||
}
|
||||
|
||||
pub fn get_mut_elements<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = Vec<PyObjectRef>> + 'a {
|
||||
if let Some(list) = obj.payload::<PyList>() {
|
||||
return list.elements.borrow_mut();
|
||||
}
|
||||
panic!("Cannot extract elements from non-sequence");
|
||||
}
|
||||
|
||||
//Check if given arg could be used with PySliceableSequence.get_slice_range()
|
||||
pub fn is_valid_slice_arg(
|
||||
arg: OptionalArg<PyObjectRef>,
|
||||
|
||||
@@ -1472,8 +1472,10 @@ pub fn do_cformat_string(
|
||||
call_getitem(vm, &values, &vm.ctx.new_str(key.to_string()))?
|
||||
}
|
||||
None => {
|
||||
let mut elements =
|
||||
objtuple::get_value(&values).into_iter().skip(tuple_index);
|
||||
let mut elements = objtuple::get_value(&values)
|
||||
.to_vec()
|
||||
.into_iter()
|
||||
.skip(tuple_index);
|
||||
|
||||
tuple_index = try_update_quantity_from_tuple(
|
||||
vm,
|
||||
@@ -1507,11 +1509,7 @@ pub fn do_cformat_string(
|
||||
}
|
||||
|
||||
// check that all arguments were converted
|
||||
if (!mapping_required
|
||||
&& objtuple::get_value(&values)
|
||||
.into_iter()
|
||||
.nth(tuple_index)
|
||||
.is_some())
|
||||
if (!mapping_required && objtuple::get_value(&values).get(tuple_index).is_some())
|
||||
&& !objtype::isinstance(&values_obj, &vm.ctx.types.dict_type)
|
||||
{
|
||||
return Err(
|
||||
|
||||
+48
-66
@@ -2,15 +2,15 @@ use std::cell::Cell;
|
||||
use std::fmt;
|
||||
|
||||
use super::objiter;
|
||||
use super::objsequence::{
|
||||
get_elements_tuple, get_item, seq_equal, seq_ge, seq_gt, seq_le, seq_lt, seq_mul,
|
||||
};
|
||||
use super::objtype::{self, PyClassRef};
|
||||
use super::objsequence::get_item;
|
||||
use super::objtype::PyClassRef;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::pyhash;
|
||||
use crate::pyobject::{
|
||||
IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue,
|
||||
IntoPyObject, PyArithmaticValue::*, PyClassImpl, PyComparisonValue, PyContext, PyObjectRef,
|
||||
PyRef, PyResult, PyValue,
|
||||
};
|
||||
use crate::sequence::{self, SimpleSeq};
|
||||
use crate::vm::{ReprGuard, VirtualMachine};
|
||||
|
||||
/// tuple() -> empty tuple
|
||||
@@ -19,8 +19,7 @@ use crate::vm::{ReprGuard, VirtualMachine};
|
||||
/// If the argument is a tuple, the return value is the same object.
|
||||
#[pyclass]
|
||||
pub struct PyTuple {
|
||||
// TODO: shouldn't be public
|
||||
pub elements: Vec<PyObjectRef>,
|
||||
elements: Vec<PyObjectRef>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for PyTuple {
|
||||
@@ -61,68 +60,65 @@ impl_intopyobj_tuple!((A, 0), (B, 1), (C, 2), (D, 3), (E, 4), (F, 5));
|
||||
impl_intopyobj_tuple!((A, 0), (B, 1), (C, 2), (D, 3), (E, 4), (F, 5), (G, 6));
|
||||
|
||||
impl PyTuple {
|
||||
pub fn fast_getitem(&self, idx: usize) -> PyObjectRef {
|
||||
pub(crate) fn fast_getitem(&self, idx: usize) -> PyObjectRef {
|
||||
self.elements[idx].clone()
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[PyObjectRef] {
|
||||
&self.elements
|
||||
}
|
||||
}
|
||||
|
||||
pub type PyTupleRef = PyRef<PyTuple>;
|
||||
|
||||
pub fn get_value(obj: &PyObjectRef) -> Vec<PyObjectRef> {
|
||||
obj.payload::<PyTuple>().unwrap().elements.clone()
|
||||
pub(crate) fn get_value(obj: &PyObjectRef) -> &[PyObjectRef] {
|
||||
obj.payload::<PyTuple>().unwrap().as_slice()
|
||||
}
|
||||
|
||||
#[pyimpl]
|
||||
impl PyTuple {
|
||||
#[pymethod(name = "__lt__")]
|
||||
fn lt(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&other, &vm.ctx.tuple_type()) {
|
||||
let other = get_elements_tuple(&other);
|
||||
let res = seq_lt(vm, &self.elements.as_slice(), &other.as_slice())?;
|
||||
Ok(vm.new_bool(res))
|
||||
#[inline]
|
||||
fn cmp<F>(&self, other: PyObjectRef, op: F, vm: &VirtualMachine) -> PyResult<PyComparisonValue>
|
||||
where
|
||||
F: Fn(&Vec<PyObjectRef>, &Vec<PyObjectRef>) -> PyResult<bool>,
|
||||
{
|
||||
let r = if let Some(other) = other.payload_if_subclass::<PyTuple>(vm) {
|
||||
Implemented(op(&self.elements, &other.elements)?)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
NotImplemented
|
||||
};
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__lt__")]
|
||||
fn lt(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyComparisonValue> {
|
||||
self.cmp(other, |a, b| sequence::lt(vm, a, b), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__gt__")]
|
||||
fn gt(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&other, &vm.ctx.tuple_type()) {
|
||||
let other = get_elements_tuple(&other);
|
||||
let res = seq_gt(vm, &self.elements.as_slice(), &other.as_slice())?;
|
||||
Ok(vm.new_bool(res))
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
fn gt(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyComparisonValue> {
|
||||
self.cmp(other, |a, b| sequence::gt(vm, a, b), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__ge__")]
|
||||
fn ge(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&other, &vm.ctx.tuple_type()) {
|
||||
let other = get_elements_tuple(&other);
|
||||
let res = seq_ge(vm, &self.elements.as_slice(), &other.as_slice())?;
|
||||
Ok(vm.new_bool(res))
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
fn ge(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyComparisonValue> {
|
||||
self.cmp(other, |a, b| sequence::ge(vm, a, b), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__le__")]
|
||||
fn le(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&other, &vm.ctx.tuple_type()) {
|
||||
let other = get_elements_tuple(&other);
|
||||
let res = seq_le(vm, &self.elements.as_slice(), &other.as_slice())?;
|
||||
Ok(vm.new_bool(res))
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
fn le(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyComparisonValue> {
|
||||
self.cmp(other, |a, b| sequence::le(vm, a, b), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__add__")]
|
||||
fn add(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&other, &vm.ctx.tuple_type()) {
|
||||
let e2 = get_elements_tuple(&other);
|
||||
let elements = self.elements.iter().chain(e2.iter()).cloned().collect();
|
||||
if let Some(other) = other.payload_if_subclass::<PyTuple>(vm) {
|
||||
let elements = self
|
||||
.elements
|
||||
.iter()
|
||||
.chain(other.as_slice().iter())
|
||||
.cloned()
|
||||
.collect();
|
||||
Ok(vm.ctx.new_tuple(elements))
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
@@ -146,26 +142,13 @@ impl PyTuple {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__eq__")]
|
||||
fn eq(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&other, &vm.ctx.tuple_type()) {
|
||||
Ok(vm.new_bool(self.inner_eq(&other, vm)?))
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
fn eq(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyComparisonValue> {
|
||||
self.cmp(other, |a, b| sequence::eq(vm, a, b), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__ne__")]
|
||||
fn ne(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&other, &vm.ctx.tuple_type()) {
|
||||
Ok(vm.new_bool(!self.inner_eq(&other, vm)?))
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}
|
||||
|
||||
fn inner_eq(&self, other: &PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
let other = get_elements_tuple(other);
|
||||
seq_equal(vm, &self.elements.as_slice(), &other.as_slice())
|
||||
fn ne(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyComparisonValue> {
|
||||
Ok(self.eq(other, vm)?.map(|v| !v))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__hash__")]
|
||||
@@ -208,7 +191,7 @@ impl PyTuple {
|
||||
|
||||
#[pymethod(name = "__mul__")]
|
||||
fn mul(&self, counter: isize, vm: &VirtualMachine) -> PyObjectRef {
|
||||
let new_elements = seq_mul(&self.elements.as_slice(), counter)
|
||||
let new_elements = sequence::seq_mul(&self.elements, counter)
|
||||
.cloned()
|
||||
.collect();
|
||||
vm.ctx.new_tuple(new_elements)
|
||||
@@ -277,8 +260,8 @@ impl PyValue for PyTupleIterator {
|
||||
impl PyTupleIterator {
|
||||
#[pymethod(name = "__next__")]
|
||||
fn next(&self, vm: &VirtualMachine) -> PyResult {
|
||||
if self.position.get() < self.tuple.elements.len() {
|
||||
let ret = self.tuple.elements[self.position.get()].clone();
|
||||
if self.position.get() < self.tuple.as_slice().len() {
|
||||
let ret = self.tuple.as_slice()[self.position.get()].clone();
|
||||
self.position.set(self.position.get() + 1);
|
||||
Ok(ret)
|
||||
} else {
|
||||
@@ -292,7 +275,6 @@ impl PyTupleIterator {
|
||||
}
|
||||
}
|
||||
|
||||
#[rustfmt::skip] // to avoid line splitting
|
||||
pub fn init(context: &PyContext) {
|
||||
let tuple_type = &context.types.tuple_type;
|
||||
PyTuple::extend_class(context, tuple_type);
|
||||
|
||||
+9
-8
@@ -4,7 +4,10 @@ use serde;
|
||||
use serde::de::{DeserializeSeed, Visitor};
|
||||
use serde::ser::{Serialize, SerializeMap, SerializeSeq};
|
||||
|
||||
use crate::obj::{objbool, objdict::PyDictRef, objfloat, objint, objsequence, objstr, objtype};
|
||||
use crate::obj::{
|
||||
objbool, objdict::PyDictRef, objfloat, objint, objlist::PyList, objstr, objtuple::PyTuple,
|
||||
objtype,
|
||||
};
|
||||
use crate::pyobject::{IdProtocol, ItemProtocol, PyObjectRef, TypeProtocol};
|
||||
use crate::VirtualMachine;
|
||||
use num_traits::cast::ToPrimitive;
|
||||
@@ -59,7 +62,7 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> {
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let serialize_seq_elements =
|
||||
|serializer: S, elements: &Vec<PyObjectRef>| -> Result<S::Ok, S::Error> {
|
||||
|serializer: S, elements: &[PyObjectRef]| -> Result<S::Ok, S::Error> {
|
||||
let mut seq = serializer.serialize_seq(Some(elements.len()))?;
|
||||
for e in elements.iter() {
|
||||
seq.serialize_element(&self.clone_with_object(e))?;
|
||||
@@ -84,12 +87,10 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> {
|
||||
} else {
|
||||
serializer.serialize_i64(v.to_i64().ok_or_else(int_too_large)?)
|
||||
}
|
||||
} else if objtype::isinstance(self.pyobject, &self.vm.ctx.list_type()) {
|
||||
let elements = objsequence::get_elements_list(self.pyobject);
|
||||
serialize_seq_elements(serializer, &elements)
|
||||
} else if objtype::isinstance(self.pyobject, &self.vm.ctx.tuple_type()) {
|
||||
let elements = objsequence::get_elements_tuple(self.pyobject);
|
||||
serialize_seq_elements(serializer, &elements)
|
||||
} else if let Some(list) = self.pyobject.payload_if_subclass::<PyList>(self.vm) {
|
||||
serialize_seq_elements(serializer, &list.borrow_elements())
|
||||
} else if let Some(tuple) = self.pyobject.payload_if_subclass::<PyTuple>(self.vm) {
|
||||
serialize_seq_elements(serializer, tuple.as_slice())
|
||||
} else if objtype::isinstance(self.pyobject, &self.vm.ctx.dict_type()) {
|
||||
let dict: PyDictRef = self.pyobject.clone().downcast().unwrap();
|
||||
let pairs: Vec<_> = dict.into_iter().collect();
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
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(crate) 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(crate) 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(crate) 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(crate) 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(crate) 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(crate) struct SeqMul<'a> {
|
||||
seq: &'a dyn SimpleSeq,
|
||||
repetitions: usize,
|
||||
iter: Option<DynPyIter<'a>>,
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for SeqMul<'_> {}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn seq_mul(seq: &impl SimpleSeq, repetitions: isize) -> SeqMul {
|
||||
SeqMul {
|
||||
seq,
|
||||
repetitions: repetitions.max(0) as usize,
|
||||
iter: None,
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
use crate::function::OptionalArg;
|
||||
use crate::obj::{objiter, objsequence, objtype::PyClassRef};
|
||||
use crate::pyobject::{IdProtocol, PyClassImpl, PyIterable, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
use crate::obj::{objiter, objtype::PyClassRef};
|
||||
use crate::pyobject::{
|
||||
IdProtocol, PyArithmaticValue::*, PyClassImpl, PyComparisonValue, PyIterable, PyObjectRef,
|
||||
PyRef, PyResult, PyValue,
|
||||
};
|
||||
use crate::sequence::{self, SimpleSeq};
|
||||
use crate::vm::ReprGuard;
|
||||
use crate::VirtualMachine;
|
||||
use itertools::Itertools;
|
||||
@@ -27,6 +31,12 @@ struct PyDequeOptions {
|
||||
maxlen: Option<usize>,
|
||||
}
|
||||
|
||||
impl PyDeque {
|
||||
fn borrow_deque<'a>(&'a self) -> impl std::ops::Deref<Target = VecDeque<PyObjectRef>> + 'a {
|
||||
self.deque.borrow()
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl]
|
||||
impl PyDeque {
|
||||
#[pyslot(new)]
|
||||
@@ -201,6 +211,7 @@ impl PyDeque {
|
||||
fn maxlen(&self, _vm: &VirtualMachine) -> Option<usize> {
|
||||
self.maxlen.get()
|
||||
}
|
||||
|
||||
#[pyproperty(setter)]
|
||||
fn set_maxlen(&self, maxlen: Option<usize>, _vm: &VirtualMachine) {
|
||||
self.maxlen.set(maxlen);
|
||||
@@ -227,100 +238,97 @@ impl PyDeque {
|
||||
Ok(repr)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn cmp<F>(&self, other: PyObjectRef, op: F, vm: &VirtualMachine) -> PyResult<PyComparisonValue>
|
||||
where
|
||||
F: Fn(&VecDeque<PyObjectRef>, &VecDeque<PyObjectRef>) -> PyResult<bool>,
|
||||
{
|
||||
let r = if let Some(other) = other.payload_if_subclass::<PyDeque>(vm) {
|
||||
Implemented(op(&*self.borrow_deque(), &*other.borrow_deque())?)
|
||||
} else {
|
||||
NotImplemented
|
||||
};
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__eq__")]
|
||||
fn eq(zelf: PyRef<Self>, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn eq(
|
||||
zelf: PyRef<Self>,
|
||||
other: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyComparisonValue> {
|
||||
if zelf.as_object().is(&other) {
|
||||
return Ok(vm.new_bool(true));
|
||||
Ok(Implemented(true))
|
||||
} else {
|
||||
zelf.cmp(other, |a, b| sequence::eq(vm, a, b), vm)
|
||||
}
|
||||
}
|
||||
|
||||
let other = match_class!(match other {
|
||||
other @ Self => other,
|
||||
_ => return Ok(vm.ctx.not_implemented()),
|
||||
});
|
||||
|
||||
let lhs: &VecDeque<_> = &zelf.deque.borrow();
|
||||
let rhs: &VecDeque<_> = &other.deque.borrow();
|
||||
|
||||
let eq = objsequence::seq_equal(vm, lhs, rhs)?;
|
||||
Ok(vm.new_bool(eq))
|
||||
#[pymethod(name = "__ne__")]
|
||||
fn ne(
|
||||
zelf: PyRef<Self>,
|
||||
other: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyComparisonValue> {
|
||||
Ok(PyDeque::eq(zelf, other, vm)?.map(|v| !v))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__lt__")]
|
||||
fn lt(zelf: PyRef<Self>, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn lt(
|
||||
zelf: PyRef<Self>,
|
||||
other: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyComparisonValue> {
|
||||
if zelf.as_object().is(&other) {
|
||||
return Ok(vm.new_bool(true));
|
||||
Ok(Implemented(false))
|
||||
} else {
|
||||
zelf.cmp(other, |a, b| sequence::lt(vm, a, b), vm)
|
||||
}
|
||||
|
||||
let other = match_class!(match other {
|
||||
other @ Self => other,
|
||||
_ => return Ok(vm.ctx.not_implemented()),
|
||||
});
|
||||
|
||||
let lhs: &VecDeque<_> = &zelf.deque.borrow();
|
||||
let rhs: &VecDeque<_> = &other.deque.borrow();
|
||||
|
||||
let eq = objsequence::seq_lt(vm, lhs, rhs)?;
|
||||
Ok(vm.new_bool(eq))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__gt__")]
|
||||
fn gt(zelf: PyRef<Self>, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn gt(
|
||||
zelf: PyRef<Self>,
|
||||
other: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyComparisonValue> {
|
||||
if zelf.as_object().is(&other) {
|
||||
return Ok(vm.new_bool(true));
|
||||
Ok(Implemented(false))
|
||||
} else {
|
||||
zelf.cmp(other, |a, b| sequence::gt(vm, a, b), vm)
|
||||
}
|
||||
|
||||
let other = match_class!(match other {
|
||||
other @ Self => other,
|
||||
_ => return Ok(vm.ctx.not_implemented()),
|
||||
});
|
||||
|
||||
let lhs: &VecDeque<_> = &zelf.deque.borrow();
|
||||
let rhs: &VecDeque<_> = &other.deque.borrow();
|
||||
|
||||
let eq = objsequence::seq_gt(vm, lhs, rhs)?;
|
||||
Ok(vm.new_bool(eq))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__le__")]
|
||||
fn le(zelf: PyRef<Self>, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn le(
|
||||
zelf: PyRef<Self>,
|
||||
other: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyComparisonValue> {
|
||||
if zelf.as_object().is(&other) {
|
||||
return Ok(vm.new_bool(true));
|
||||
Ok(Implemented(true))
|
||||
} else {
|
||||
zelf.cmp(other, |a, b| sequence::le(vm, a, b), vm)
|
||||
}
|
||||
|
||||
let other = match_class!(match other {
|
||||
other @ Self => other,
|
||||
_ => return Ok(vm.ctx.not_implemented()),
|
||||
});
|
||||
|
||||
let lhs: &VecDeque<_> = &zelf.deque.borrow();
|
||||
let rhs: &VecDeque<_> = &other.deque.borrow();
|
||||
|
||||
let eq = objsequence::seq_le(vm, lhs, rhs)?;
|
||||
Ok(vm.new_bool(eq))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__ge__")]
|
||||
fn ge(zelf: PyRef<Self>, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn ge(
|
||||
zelf: PyRef<Self>,
|
||||
other: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyComparisonValue> {
|
||||
if zelf.as_object().is(&other) {
|
||||
return Ok(vm.new_bool(true));
|
||||
Ok(Implemented(true))
|
||||
} else {
|
||||
zelf.cmp(other, |a, b| sequence::ge(vm, a, b), vm)
|
||||
}
|
||||
|
||||
let other = match_class!(match other {
|
||||
other @ Self => other,
|
||||
_ => return Ok(vm.ctx.not_implemented()),
|
||||
});
|
||||
|
||||
let lhs: &VecDeque<_> = &zelf.deque.borrow();
|
||||
let rhs: &VecDeque<_> = &other.deque.borrow();
|
||||
|
||||
let eq = objsequence::seq_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 {
|
||||
|
||||
@@ -389,16 +389,16 @@ impl ToSocketAddrs for Address {
|
||||
impl TryFromObject for Address {
|
||||
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
|
||||
let tuple = PyTupleRef::try_from_object(vm, obj)?;
|
||||
if tuple.elements.len() != 2 {
|
||||
if tuple.as_slice().len() != 2 {
|
||||
Err(vm.new_type_error("Address tuple should have only 2 values".to_string()))
|
||||
} else {
|
||||
let host = PyStringRef::try_from_object(vm, tuple.elements[0].clone())?;
|
||||
let host = PyStringRef::try_from_object(vm, tuple.as_slice()[0].clone())?;
|
||||
let host = if host.as_str().is_empty() {
|
||||
PyString::from("0.0.0.0").into_ref(vm)
|
||||
} else {
|
||||
host
|
||||
};
|
||||
let port = u16::try_from_object(vm, tuple.elements[1].clone())?;
|
||||
let port = u16::try_from_object(vm, tuple.as_slice()[1].clone())?;
|
||||
Ok(Address { host, port })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ use subprocess;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::obj::objbytes::PyBytesRef;
|
||||
use crate::obj::objlist::PyListRef;
|
||||
use crate::obj::objsequence;
|
||||
use crate::obj::objstr::{self, PyStringRef};
|
||||
use crate::obj::objtype::PyClassRef;
|
||||
use crate::pyobject::{Either, IntoPyObject, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
@@ -107,7 +106,8 @@ impl PopenRef {
|
||||
let stderr = convert_redirection(args.stderr, vm)?;
|
||||
let command_list = match &args.args {
|
||||
Either::A(command) => vec![command.as_str().to_string()],
|
||||
Either::B(command_list) => objsequence::get_elements_list(command_list.as_object())
|
||||
Either::B(command_list) => command_list
|
||||
.borrow_elements()
|
||||
.iter()
|
||||
.map(|x| objstr::get_value(x))
|
||||
.collect(),
|
||||
|
||||
+12
-6
@@ -33,10 +33,10 @@ use crate::obj::objfunction::{PyFunction, PyMethod};
|
||||
use crate::obj::objgenerator::PyGenerator;
|
||||
use crate::obj::objint::PyInt;
|
||||
use crate::obj::objiter;
|
||||
use crate::obj::objlist::PyList;
|
||||
use crate::obj::objmodule::{self, PyModule};
|
||||
use crate::obj::objsequence;
|
||||
use crate::obj::objstr::{PyString, PyStringRef};
|
||||
use crate::obj::objtuple::PyTupleRef;
|
||||
use crate::obj::objtuple::{PyTuple, PyTupleRef};
|
||||
use crate::obj::objtype::{self, PyClassRef};
|
||||
use crate::pyhash;
|
||||
use crate::pyobject::{
|
||||
@@ -850,7 +850,7 @@ impl VirtualMachine {
|
||||
// Add missing positional arguments, if we have fewer positional arguments than the
|
||||
// function definition calls for
|
||||
if nargs < nexpected_args {
|
||||
let num_defaults_available = defaults.as_ref().map_or(0, |d| d.elements.len());
|
||||
let num_defaults_available = defaults.as_ref().map_or(0, |d| d.as_slice().len());
|
||||
|
||||
// Given the number of defaults available, check all the arguments for which we
|
||||
// _don't_ have defaults; if any are missing, raise an exception
|
||||
@@ -870,7 +870,7 @@ impl VirtualMachine {
|
||||
)));
|
||||
}
|
||||
if let Some(defaults) = defaults {
|
||||
let defaults = &defaults.elements;
|
||||
let defaults = defaults.as_slice();
|
||||
// We have sufficient defaults, so iterate over the corresponding names and use
|
||||
// the default if we don't already have a value
|
||||
for (default_index, i) in (required_args..nexpected_args).enumerate() {
|
||||
@@ -905,12 +905,18 @@ impl VirtualMachine {
|
||||
// Extract elements from item, if possible:
|
||||
let cls = value.class();
|
||||
if cls.is(&self.ctx.tuple_type()) {
|
||||
objsequence::get_elements_tuple(value)
|
||||
value
|
||||
.payload::<PyTuple>()
|
||||
.unwrap()
|
||||
.as_slice()
|
||||
.iter()
|
||||
.map(|obj| T::try_from_object(self, obj.clone()))
|
||||
.collect()
|
||||
} else if cls.is(&self.ctx.list_type()) {
|
||||
objsequence::get_elements_list(value)
|
||||
value
|
||||
.payload::<PyList>()
|
||||
.unwrap()
|
||||
.borrow_elements()
|
||||
.iter()
|
||||
.map(|obj| T::try_from_object(self, obj.clone()))
|
||||
.collect()
|
||||
|
||||
Reference in new issue
Block a user