From 0e583b28294b8fb3afa7fab7ad9bf1fb32ddd2f6 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Tue, 7 Jan 2020 20:42:25 +0900 Subject: [PATCH] Refactor PyList to have elements as private field --- vm/src/obj/objlist.rs | 344 +++++++++++++++++++----------------- vm/src/obj/objsequence.rs | 23 +-- vm/src/obj/objtuple.rs | 1 - vm/src/py_serde.rs | 8 +- vm/src/stdlib/subprocess.rs | 4 +- vm/src/vm.rs | 7 +- 6 files changed, 193 insertions(+), 194 deletions(-) diff --git a/vm/src/obj/objlist.rs b/vm/src/obj/objlist.rs index 5e88d55cb..e85a0e984 100644 --- a/vm/src/obj/objlist.rs +++ b/vm/src/obj/objlist.rs @@ -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>, + elements: RefCell>, } 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> + '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; -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::(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, 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.elements.borrow().capacity() * size_of::() } - 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, _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, 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, _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, sec: PyIterable, vm: &VirtualMachine) -> PyResult { + fn _set_slice(&self, range: Range, 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, _> = sec.iter(vm)?.collect(); @@ -316,7 +350,7 @@ impl PyListRef { } fn _set_stepped_slice( - self, + &self, range: Range, step: usize, sec: PyIterable, @@ -358,7 +392,7 @@ impl PyListRef { } fn _set_stepped_slice_reverse( - self, + &self, range: Range, step: usize, sec: PyIterable, @@ -400,7 +434,7 @@ impl PyListRef { } } - fn _replace_indexes(self, indexes: I, items: &[PyObjectRef]) + fn _replace_indexes(&self, indexes: I, items: &[PyObjectRef]) where I: Iterator, { @@ -412,10 +446,11 @@ impl PyListRef { } } - fn repr(self, vm: &VirtualMachine) -> PyResult { - 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, vm: &VirtualMachine) -> PyResult { + 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, counter: isize, _vm: &VirtualMachine) -> PyRef { + 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 { + #[pymethod] + fn count(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult { 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 { + #[pymethod(name = "__contains__")] + fn contains(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult { 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 { + #[pymethod] + fn index(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult { 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, vm: &VirtualMachine) -> PyResult { + #[pymethod] + fn pop(&self, i: OptionalArg, 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 = 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, + other: PyObjectRef, + vm: &VirtualMachine, + ) -> PyResult { + let value = if zelf.as_object().is(&other) { + Implemented(true) + } else if let Some(other) = other.payload_if_subclass::(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, + other: PyObjectRef, + vm: &VirtualMachine, + ) -> PyResult { + Ok(PyList::eq(zelf, other, vm)?.map(|v| !v)) } - fn inner_eq(self, other: &PyObjectRef, vm: &VirtualMachine) -> PyResult { - 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::(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::(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::(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::(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) { + fn _del_slice(&self, range: Range) { self.elements.borrow_mut().drain(range); } - fn _del_stepped_slice(self, range: Range, step: usize) { + fn _del_stepped_slice(&self, range: Range, 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, step: usize) { + fn _del_stepped_slice_reverse(&self, range: Range, 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, - vm: &VirtualMachine, -) -> PyResult { - let elements = if let OptionalArg::Present(iterable) = iterable { - vm.extract_elements(&iterable)? - } else { - vec![] - }; + #[pyslot(new)] + fn list_new( + cls: PyClassRef, + iterable: OptionalArg, + vm: &VirtualMachine, + ) -> PyResult { + 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); diff --git a/vm/src/obj/objsequence.rs b/vm/src/obj/objsequence.rs index 44100cb55..1f67106ec 100644 --- a/vm/src/obj/objsequence.rs +++ b/vm/src/obj/objsequence.rs @@ -1,6 +1,6 @@ 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}; @@ -389,27 +389,6 @@ pub fn seq_mul(seq: &impl SimpleSeq, repetitions: isize) -> SeqMul { } } -pub fn get_elements_cell<'a>(obj: &'a PyObjectRef) -> &'a RefCell> { - if let Some(list) = obj.payload::() { - return &list.elements; - } - panic!("Cannot extract elements from non-sequence"); -} - -pub fn get_elements_list<'a>(obj: &'a PyObjectRef) -> impl Deref> + 'a { - if let Some(list) = obj.payload::() { - return list.elements.borrow(); - } - panic!("Cannot extract elements from non-sequence"); -} - -pub fn get_mut_elements<'a>(obj: &'a PyObjectRef) -> impl DerefMut> + 'a { - if let Some(list) = obj.payload::() { - 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, diff --git a/vm/src/obj/objtuple.rs b/vm/src/obj/objtuple.rs index 7d6957491..90f969723 100644 --- a/vm/src/obj/objtuple.rs +++ b/vm/src/obj/objtuple.rs @@ -278,7 +278,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); diff --git a/vm/src/py_serde.rs b/vm/src/py_serde.rs index dbcba3060..3c8b05a8c 100644 --- a/vm/src/py_serde.rs +++ b/vm/src/py_serde.rs @@ -5,7 +5,8 @@ use serde::de::{DeserializeSeed, Visitor}; use serde::ser::{Serialize, SerializeMap, SerializeSeq}; use crate::obj::{ - objbool, objdict::PyDictRef, objfloat, objint, objsequence, objstr, objtuple::PyTuple, objtype, + objbool, objdict::PyDictRef, objfloat, objint, objlist::PyList, objstr, objtuple::PyTuple, + objtype, }; use crate::pyobject::{IdProtocol, ItemProtocol, PyObjectRef, TypeProtocol}; use crate::VirtualMachine; @@ -86,9 +87,8 @@ 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 let Some(list) = self.pyobject.payload_if_subclass::(self.vm) { + serialize_seq_elements(serializer, &list.elements()) } else if let Some(tuple) = self.pyobject.payload_if_subclass::(self.vm) { serialize_seq_elements(serializer, tuple.as_slice()) } else if objtype::isinstance(self.pyobject, &self.vm.ctx.dict_type()) { diff --git a/vm/src/stdlib/subprocess.rs b/vm/src/stdlib/subprocess.rs index bf6738694..2f0760eae 100644 --- a/vm/src/stdlib/subprocess.rs +++ b/vm/src/stdlib/subprocess.rs @@ -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 + .elements() .iter() .map(|x| objstr::get_value(x)) .collect(), diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 8abdf94d8..fd2fdf85d 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -33,8 +33,8 @@ 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::{PyTuple, PyTupleRef}; use crate::obj::objtype::{self, PyClassRef}; @@ -913,7 +913,10 @@ impl VirtualMachine { .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::() + .unwrap() + .elements() .iter() .map(|obj| T::try_from_object(self, obj.clone())) .collect()