|
|
|
|
@@ -11,21 +11,26 @@ 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,
|
|
|
|
|
get_item, seq_equal, seq_ge, seq_gt, seq_le, seq_lt, seq_mul, 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::PySequenceContainer;
|
|
|
|
|
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 {
|
|
|
|
|
@@ -49,6 +54,19 @@ impl PyValue for PyList {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// impl PySequenceContainer for PyList {
|
|
|
|
|
// fn as_slice<'a>(&'a self) -> &'a [PyObjectRef] {
|
|
|
|
|
// let b = self.elements.borrow();
|
|
|
|
|
// &b
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
impl PyList {
|
|
|
|
|
pub fn elements<'a>(&'a self) -> impl std::ops::Deref<Target = Vec<PyObjectRef>> + 'a {
|
|
|
|
|
self.elements.borrow()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PyList {
|
|
|
|
|
pub fn get_len(&self) -> usize {
|
|
|
|
|
self.elements.borrow().len()
|
|
|
|
|
@@ -130,18 +148,22 @@ struct SortOptions {
|
|
|
|
|
|
|
|
|
|
pub type PyListRef = PyRef<PyList>;
|
|
|
|
|
|
|
|
|
|
impl PyListRef {
|
|
|
|
|
pub fn append(self, x: PyObjectRef, _vm: &VirtualMachine) {
|
|
|
|
|
#[pyimpl]
|
|
|
|
|
impl PyList {
|
|
|
|
|
#[pymethod]
|
|
|
|
|
pub 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 +177,88 @@ 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.elements();
|
|
|
|
|
let e2 = other.elements();
|
|
|
|
|
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 {
|
|
|
|
|
get_item(
|
|
|
|
|
vm,
|
|
|
|
|
self.as_object(),
|
|
|
|
|
&self.elements.borrow(),
|
|
|
|
|
needle.clone(),
|
|
|
|
|
)
|
|
|
|
|
#[pymethod(name = "__getitem__")]
|
|
|
|
|
fn getitem(zelf: PyRef<Self>, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
|
|
|
|
get_item(vm, zelf.as_object(), &zelf.elements(), 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 +274,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 +283,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 +337,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 +350,7 @@ impl PyListRef {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn _set_stepped_slice(
|
|
|
|
|
self,
|
|
|
|
|
&self,
|
|
|
|
|
range: Range<usize>,
|
|
|
|
|
step: usize,
|
|
|
|
|
sec: PyIterable,
|
|
|
|
|
@@ -358,7 +392,7 @@ impl PyListRef {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn _set_stepped_slice_reverse(
|
|
|
|
|
self,
|
|
|
|
|
&self,
|
|
|
|
|
range: Range<usize>,
|
|
|
|
|
step: usize,
|
|
|
|
|
sec: PyIterable,
|
|
|
|
|
@@ -400,7 +434,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 +446,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 +461,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 = seq_mul(&self.elements().as_slice(), 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 = seq_mul(&zelf.elements().as_slice(), 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 +499,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 +510,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 +521,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 +537,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 +556,100 @@ 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)?)
|
|
|
|
|
#[pymethod(name = "__eq__")]
|
|
|
|
|
fn eq(
|
|
|
|
|
zelf: PyRef<Self>,
|
|
|
|
|
other: PyObjectRef,
|
|
|
|
|
vm: &VirtualMachine,
|
|
|
|
|
) -> PyResult<PyComparisonValue> {
|
|
|
|
|
let value = if zelf.as_object().is(&other) {
|
|
|
|
|
Implemented(true)
|
|
|
|
|
} else if let Some(other) = other.payload_if_subclass::<PyList>(vm) {
|
|
|
|
|
Implemented(seq_equal(
|
|
|
|
|
vm,
|
|
|
|
|
&zelf.elements().as_slice(),
|
|
|
|
|
&other.elements().as_slice(),
|
|
|
|
|
)?)
|
|
|
|
|
} else {
|
|
|
|
|
vm.ctx.not_implemented()
|
|
|
|
|
NotImplemented
|
|
|
|
|
};
|
|
|
|
|
Ok(value)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)?)
|
|
|
|
|
} else {
|
|
|
|
|
vm.ctx.not_implemented()
|
|
|
|
|
};
|
|
|
|
|
Ok(value)
|
|
|
|
|
#[pymethod(name = "__ne__")]
|
|
|
|
|
fn ne(
|
|
|
|
|
zelf: PyRef<Self>,
|
|
|
|
|
other: PyObjectRef,
|
|
|
|
|
vm: &VirtualMachine,
|
|
|
|
|
) -> PyResult<PyComparisonValue> {
|
|
|
|
|
Ok(PyList::eq(zelf, other, vm)?.map(|v| !v))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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())?;
|
|
|
|
|
#[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.elements().as_slice(),
|
|
|
|
|
&other.elements().as_slice(),
|
|
|
|
|
)?;
|
|
|
|
|
Ok(vm.new_bool(res))
|
|
|
|
|
} else {
|
|
|
|
|
Ok(vm.ctx.not_implemented())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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())?;
|
|
|
|
|
#[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.elements().as_slice(),
|
|
|
|
|
&other.elements().as_slice(),
|
|
|
|
|
)?;
|
|
|
|
|
Ok(vm.new_bool(res))
|
|
|
|
|
} else {
|
|
|
|
|
Ok(vm.ctx.not_implemented())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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())?;
|
|
|
|
|
#[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.elements().as_slice(),
|
|
|
|
|
&other.elements().as_slice(),
|
|
|
|
|
)?;
|
|
|
|
|
Ok(vm.new_bool(res))
|
|
|
|
|
} else {
|
|
|
|
|
Ok(vm.ctx.not_implemented())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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())?;
|
|
|
|
|
#[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.elements().as_slice(),
|
|
|
|
|
&other.elements().as_slice(),
|
|
|
|
|
)?;
|
|
|
|
|
Ok(vm.new_bool(res))
|
|
|
|
|
} else {
|
|
|
|
|
Ok(vm.ctx.not_implemented())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn delitem(self, subscript: SequenceIndex, vm: &VirtualMachine) -> PyResult<()> {
|
|
|
|
|
#[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 +658,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 +727,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 +752,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 +773,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 +788,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 +935,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);
|
|
|
|
|
|