diff --git a/vm/src/obj/objbytearray.rs b/vm/src/obj/objbytearray.rs index 16758a438..6f78ecf48 100644 --- a/vm/src/obj/objbytearray.rs +++ b/vm/src/obj/objbytearray.rs @@ -7,7 +7,7 @@ use std::ops::{Deref, DerefMut}; use num_traits::ToPrimitive; use crate::function::OptionalArg; -use crate::pyobject::{PyContext, PyObjectRef, PyRef, PyResult, PyValue}; +use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; use crate::vm::VirtualMachine; use super::objint; @@ -84,11 +84,7 @@ pub fn init(context: &PyContext) { "upper" => context.new_rustfunc(PyByteArrayRef::upper) }); - let bytearrayiterator_type = &context.bytearrayiterator_type; - extend_class!(context, bytearrayiterator_type, { - "__next__" => context.new_rustfunc(PyByteArrayIteratorRef::next), - "__iter__" => context.new_rustfunc(PyByteArrayIteratorRef::iter), - }); + PyByteArrayIterator::extend_class(context, &context.bytearrayiterator_type); } fn bytearray_new( @@ -287,6 +283,7 @@ mod tests { } } +#[pyclass] #[derive(Debug)] pub struct PyByteArrayIterator { position: Cell, @@ -299,10 +296,10 @@ impl PyValue for PyByteArrayIterator { } } -type PyByteArrayIteratorRef = PyRef; - -impl PyByteArrayIteratorRef { - fn next(self, vm: &VirtualMachine) -> PyResult { +#[pyimpl] +impl PyByteArrayIterator { + #[pymethod(name = "__next__")] + fn next(&self, vm: &VirtualMachine) -> PyResult { if self.position.get() < self.bytearray.value.borrow().len() { let ret = self.bytearray.value.borrow()[self.position.get()]; self.position.set(self.position.get() + 1); @@ -312,7 +309,8 @@ impl PyByteArrayIteratorRef { } } - fn iter(self, _vm: &VirtualMachine) -> Self { - self + #[pymethod(name = "__iter__")] + fn iter(zelf: PyRef, _vm: &VirtualMachine) -> PyRef { + zelf } } diff --git a/vm/src/obj/objbytes.rs b/vm/src/obj/objbytes.rs index 0556de053..df9795902 100644 --- a/vm/src/obj/objbytes.rs +++ b/vm/src/obj/objbytes.rs @@ -64,11 +64,7 @@ pub fn init(context: &PyContext) { extend_class!(context, bytes_type, { "fromhex" => context.new_rustfunc(PyBytesRef::fromhex), }); - let bytesiterator_type = &context.bytesiterator_type; - extend_class!(context, bytesiterator_type, { - "__next__" => context.new_rustfunc(PyBytesIteratorRef::next), - "__iter__" => context.new_rustfunc(PyBytesIteratorRef::iter), - }); + PyBytesIterator::extend_class(context, &context.bytesiterator_type); } #[pyimpl] @@ -271,6 +267,7 @@ impl PyBytesRef { } } +#[pyclass] #[derive(Debug)] pub struct PyBytesIterator { position: Cell, @@ -283,10 +280,10 @@ impl PyValue for PyBytesIterator { } } -type PyBytesIteratorRef = PyRef; - -impl PyBytesIteratorRef { - fn next(self, vm: &VirtualMachine) -> PyResult { +#[pyimpl] +impl PyBytesIterator { + #[pymethod(name = "__next__")] + fn next(&self, vm: &VirtualMachine) -> PyResult { if self.position.get() < self.bytes.inner.len() { let ret = self.bytes[self.position.get()]; self.position.set(self.position.get() + 1); @@ -296,7 +293,8 @@ impl PyBytesIteratorRef { } } - fn iter(self, _vm: &VirtualMachine) -> Self { - self + #[pymethod(name = "__iter__")] + fn iter(zelf: PyRef, _vm: &VirtualMachine) -> PyRef { + zelf } } diff --git a/vm/src/obj/objenumerate.rs b/vm/src/obj/objenumerate.rs index c94aeabbd..56d232272 100644 --- a/vm/src/obj/objenumerate.rs +++ b/vm/src/obj/objenumerate.rs @@ -5,13 +5,14 @@ use num_bigint::BigInt; use num_traits::Zero; use crate::function::OptionalArg; -use crate::pyobject::{PyContext, PyObjectRef, PyRef, PyResult, PyValue}; +use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; use crate::vm::VirtualMachine; use super::objint::PyIntRef; use super::objiter; use super::objtype::PyClassRef; +#[pyclass] #[derive(Debug)] pub struct PyEnumerate { counter: RefCell, @@ -44,8 +45,10 @@ fn enumerate_new( .into_ref_with_type(vm, cls) } -impl PyEnumerateRef { - fn next(self, vm: &VirtualMachine) -> PyResult { +#[pyimpl] +impl PyEnumerate { + #[pymethod(name = "__next__")] + fn next(&self, vm: &VirtualMachine) -> PyResult { let iterator = &self.iterator; let counter = &self.counter; let next_obj = objiter::call_next(vm, iterator)?; @@ -58,16 +61,15 @@ impl PyEnumerateRef { Ok(result) } - fn iter(self, _vm: &VirtualMachine) -> Self { - self + #[pymethod(name = "__iter__")] + fn iter(zelf: PyRef, _vm: &VirtualMachine) -> PyRef { + zelf } } pub fn init(context: &PyContext) { - let enumerate_type = &context.enumerate_type; - extend_class!(context, enumerate_type, { + PyEnumerate::extend_class(context, &context.enumerate_type); + extend_class!(context, &context.enumerate_type, { "__new__" => context.new_rustfunc(enumerate_new), - "__next__" => context.new_rustfunc(PyEnumerateRef::next), - "__iter__" => context.new_rustfunc(PyEnumerateRef::iter), }); } diff --git a/vm/src/obj/objfilter.rs b/vm/src/obj/objfilter.rs index 858a0531a..24800d6aa 100644 --- a/vm/src/obj/objfilter.rs +++ b/vm/src/obj/objfilter.rs @@ -1,4 +1,4 @@ -use crate::pyobject::{IdProtocol, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; +use crate::pyobject::{IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; use crate::vm::VirtualMachine; // Required for arg_check! to use isinstance use super::objbool; @@ -7,6 +7,11 @@ use crate::obj::objtype::PyClassRef; pub type PyFilterRef = PyRef; +/// filter(function or None, iterable) --> filter object +/// +/// Return an iterator yielding those items of iterable for which function(item) +/// is true. If function is None, return the items that are true. +#[pyclass] #[derive(Debug)] pub struct PyFilter { predicate: PyObjectRef, @@ -34,8 +39,10 @@ fn filter_new( .into_ref_with_type(vm, cls) } -impl PyFilterRef { - fn next(self, vm: &VirtualMachine) -> PyResult { +#[pyimpl] +impl PyFilter { + #[pymethod(name = "__next__")] + fn next(&self, vm: &VirtualMachine) -> PyResult { let predicate = &self.predicate; let iterator = &self.iterator; loop { @@ -53,23 +60,15 @@ impl PyFilterRef { } } - fn iter(self, _vm: &VirtualMachine) -> Self { - self + #[pymethod(name = "__iter__")] + fn iter(zelf: PyRef, _vm: &VirtualMachine) -> PyRef { + zelf } } pub fn init(context: &PyContext) { - let filter_type = &context.filter_type; - - let filter_doc = - "filter(function or None, iterable) --> filter object\n\n\ - Return an iterator yielding those items of iterable for which function(item)\n\ - is true. If function is None, return the items that are true."; - - extend_class!(context, filter_type, { + PyFilter::extend_class(context, &context.filter_type); + extend_class!(context, &context.filter_type, { "__new__" => context.new_rustfunc(filter_new), - "__doc__" => context.new_str(filter_doc.to_string()), - "__next__" => context.new_rustfunc(PyFilterRef::next), - "__iter__" => context.new_rustfunc(PyFilterRef::iter), }); } diff --git a/vm/src/obj/objiter.rs b/vm/src/obj/objiter.rs index 6e1dc1d06..efe672d62 100644 --- a/vm/src/obj/objiter.rs +++ b/vm/src/obj/objiter.rs @@ -4,7 +4,9 @@ use std::cell::Cell; -use crate::pyobject::{PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol}; +use crate::pyobject::{ + PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol, +}; use crate::vm::VirtualMachine; use super::objtype; @@ -75,6 +77,7 @@ pub fn new_stop_iteration(vm: &VirtualMachine) -> PyObjectRef { vm.new_exception(stop_iteration_type, "End of iterator".to_string()) } +#[pyclass] #[derive(Debug)] pub struct PySequenceIterator { pub position: Cell, @@ -87,10 +90,10 @@ impl PyValue for PySequenceIterator { } } -type PySequenceIteratorRef = PyRef; - -impl PySequenceIteratorRef { - fn next(self, vm: &VirtualMachine) -> PyResult { +#[pyimpl] +impl PySequenceIterator { + #[pymethod(name = "__next__")] + fn next(&self, vm: &VirtualMachine) -> PyResult { let number = vm.ctx.new_int(self.position.get()); match vm.call_method(&self.obj, "__getitem__", vec![number]) { Ok(val) => { @@ -105,16 +108,12 @@ impl PySequenceIteratorRef { } } - fn iter(self, _vm: &VirtualMachine) -> Self { - self + #[pymethod(name = "__iter__")] + fn iter(zelf: PyRef, _vm: &VirtualMachine) -> PyRef { + zelf } } pub fn init(context: &PyContext) { - let iter_type = &context.iter_type; - - extend_class!(context, iter_type, { - "__next__" => context.new_rustfunc(PySequenceIteratorRef::next), - "__iter__" => context.new_rustfunc(PySequenceIteratorRef::iter), - }); + PySequenceIterator::extend_class(context, &context.iter_type); } diff --git a/vm/src/obj/objlist.rs b/vm/src/obj/objlist.rs index 5c1bad5af..6b00b6828 100644 --- a/vm/src/obj/objlist.rs +++ b/vm/src/obj/objlist.rs @@ -8,7 +8,8 @@ use num_traits::{One, Signed, ToPrimitive, Zero}; use crate::function::{OptionalArg, PyFuncArgs}; use crate::pyobject::{ - IdProtocol, PyContext, PyIterable, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, + IdProtocol, PyClassImpl, PyContext, PyIterable, PyObjectRef, PyRef, PyResult, PyValue, + TryFromObject, }; use crate::vm::{ReprGuard, VirtualMachine}; @@ -776,6 +777,7 @@ fn list_sort(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(vm.get_none()) } +#[pyclass] #[derive(Debug)] pub struct PyListIterator { pub position: Cell, @@ -788,10 +790,10 @@ impl PyValue for PyListIterator { } } -type PyListIteratorRef = PyRef; - -impl PyListIteratorRef { - fn next(self, vm: &VirtualMachine) -> PyResult { +#[pyimpl] +impl PyListIterator { + #[pymethod(name = "__next__")] + fn next(&self, vm: &VirtualMachine) -> PyResult { if self.position.get() < self.list.elements.borrow().len() { let ret = self.list.elements.borrow()[self.position.get()].clone(); self.position.set(self.position.get() + 1); @@ -801,8 +803,9 @@ impl PyListIteratorRef { } } - fn iter(self, _vm: &VirtualMachine) -> Self { - self + #[pymethod(name = "__iter__")] + fn iter(zelf: PyRef, _vm: &VirtualMachine) -> PyRef { + zelf } } @@ -848,9 +851,5 @@ pub fn init(context: &PyContext) { "remove" => context.new_rustfunc(PyListRef::remove) }); - let listiterator_type = &context.listiterator_type; - extend_class!(context, listiterator_type, { - "__next__" => context.new_rustfunc(PyListIteratorRef::next), - "__iter__" => context.new_rustfunc(PyListIteratorRef::iter), - }); + PyListIterator::extend_class(context, &context.listiterator_type); } diff --git a/vm/src/obj/objmap.rs b/vm/src/obj/objmap.rs index 061f4179f..61fe67c0d 100644 --- a/vm/src/obj/objmap.rs +++ b/vm/src/obj/objmap.rs @@ -1,10 +1,15 @@ use crate::function::Args; -use crate::pyobject::{PyContext, PyObjectRef, PyRef, PyResult, PyValue}; +use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; use crate::vm::VirtualMachine; use super::objiter; use super::objtype::PyClassRef; +/// map(func, *iterables) --> map object +/// +/// Make an iterator that computes the function using arguments from +/// each of the iterables. Stops when the shortest iterable is exhausted. +#[pyclass] #[derive(Debug)] pub struct PyMap { mapper: PyObjectRef, @@ -35,8 +40,10 @@ fn map_new( .into_ref_with_type(vm, cls.clone()) } -impl PyMapRef { - fn next(self, vm: &VirtualMachine) -> PyResult { +#[pyimpl] +impl PyMap { + #[pymethod(name = "__next__")] + fn next(&self, vm: &VirtualMachine) -> PyResult { let next_objs = self .iterators .iter() @@ -47,22 +54,15 @@ impl PyMapRef { vm.invoke(self.mapper.clone(), next_objs) } - fn iter(self, _vm: &VirtualMachine) -> Self { - self + #[pymethod(name = "__iter__")] + fn iter(zelf: PyRef, _vm: &VirtualMachine) -> PyRef { + zelf } } pub fn init(context: &PyContext) { - let map_type = &context.map_type; - - let map_doc = "map(func, *iterables) --> map object\n\n\ - Make an iterator that computes the function using arguments from\n\ - each of the iterables. Stops when the shortest iterable is exhausted."; - - extend_class!(context, map_type, { + PyMap::extend_class(context, &context.map_type); + extend_class!(context, &context.map_type, { "__new__" => context.new_rustfunc(map_new), - "__next__" => context.new_rustfunc(PyMapRef::next), - "__iter__" => context.new_rustfunc(PyMapRef::iter), - "__doc__" => context.new_str(map_doc.to_string()) }); } diff --git a/vm/src/obj/objrange.rs b/vm/src/obj/objrange.rs index d98e7491f..2a43579c5 100644 --- a/vm/src/obj/objrange.rs +++ b/vm/src/obj/objrange.rs @@ -6,7 +6,7 @@ use num_traits::{One, Signed, Zero}; use crate::function::{OptionalArg, PyFuncArgs}; use crate::pyobject::{ - PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol, + PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -124,11 +124,7 @@ pub fn init(context: &PyContext) { "step" => context.new_property(PyRange::step), }); - let rangeiterator_type = &context.rangeiterator_type; - extend_class!(context, rangeiterator_type, { - "__next__" => context.new_rustfunc(PyRangeIteratorRef::next), - "__iter__" => context.new_rustfunc(PyRangeIteratorRef::iter), - }); + PyRangeIterator::extend_class(context, &context.rangeiterator_type); } type PyRangeRef = PyRef; @@ -341,6 +337,7 @@ fn range_new(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(range.into_object()) } +#[pyclass] #[derive(Debug)] pub struct PyRangeIterator { position: Cell, @@ -353,10 +350,10 @@ impl PyValue for PyRangeIterator { } } -type PyRangeIteratorRef = PyRef; - -impl PyRangeIteratorRef { - fn next(self, vm: &VirtualMachine) -> PyResult { +#[pyimpl] +impl PyRangeIterator { + #[pymethod(name = "__next__")] + fn next(&self, vm: &VirtualMachine) -> PyResult { let position = BigInt::from(self.position.get()); if let Some(int) = self.range.get(&position) { self.position.set(self.position.get() + 1); @@ -366,8 +363,9 @@ impl PyRangeIteratorRef { } } - fn iter(self, _vm: &VirtualMachine) -> Self { - self + #[pymethod(name = "__iter__")] + fn iter(zelf: PyRef, _vm: &VirtualMachine) -> PyRef { + zelf } } diff --git a/vm/src/obj/objtuple.rs b/vm/src/obj/objtuple.rs index 216945284..42999189f 100644 --- a/vm/src/obj/objtuple.rs +++ b/vm/src/obj/objtuple.rs @@ -3,7 +3,7 @@ use std::fmt; use std::hash::{Hash, Hasher}; use crate::function::OptionalArg; -use crate::pyobject::{IdProtocol, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; +use crate::pyobject::{IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; use crate::vm::{ReprGuard, VirtualMachine}; use super::objbool; @@ -224,6 +224,7 @@ fn tuple_new( PyTuple::from(elements).into_ref_with_type(vm, cls) } +#[pyclass] #[derive(Debug)] pub struct PyTupleIterator { position: Cell, @@ -236,10 +237,10 @@ impl PyValue for PyTupleIterator { } } -type PyTupleIteratorRef = PyRef; - -impl PyTupleIteratorRef { - fn next(self, vm: &VirtualMachine) -> PyResult { +#[pyimpl] +impl PyTupleIterator { + #[pymethod(name = "__next__")] + fn next(&self, vm: &VirtualMachine) -> PyResult { if self.position.get() < self.tuple.elements.borrow().len() { let ret = self.tuple.elements.borrow()[self.position.get()].clone(); self.position.set(self.position.get() + 1); @@ -249,8 +250,9 @@ impl PyTupleIteratorRef { } } - fn iter(self, _vm: &VirtualMachine) -> Self { - self + #[pymethod(name = "__iter__")] + fn iter(zelf: PyRef, _vm: &VirtualMachine) -> PyRef { + zelf } } @@ -282,9 +284,5 @@ If the argument is a tuple, the return value is the same object."; "index" => context.new_rustfunc(PyTupleRef::index) }); - let tupleiterator_type = &context.tupleiterator_type; - extend_class!(context, tupleiterator_type, { - "__next__" => context.new_rustfunc(PyTupleIteratorRef::next), - "__iter__" => context.new_rustfunc(PyTupleIteratorRef::iter), - }); + PyTupleIterator::extend_class(context, &context.tupleiterator_type); } diff --git a/vm/src/obj/objzip.rs b/vm/src/obj/objzip.rs index 81640a724..d9c577aa0 100644 --- a/vm/src/obj/objzip.rs +++ b/vm/src/obj/objzip.rs @@ -1,5 +1,5 @@ use crate::function::Args; -use crate::pyobject::{PyContext, PyObjectRef, PyRef, PyResult, PyValue}; +use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; use crate::vm::VirtualMachine; use super::objiter; @@ -7,6 +7,7 @@ use crate::obj::objtype::PyClassRef; pub type PyZipRef = PyRef; +#[pyclass] #[derive(Debug)] pub struct PyZip { iterators: Vec, @@ -26,8 +27,10 @@ fn zip_new(cls: PyClassRef, iterables: Args, vm: &VirtualMachine) -> PyResult PyResult { +#[pyimpl] +impl PyZip { + #[pymethod(name = "__next__")] + fn next(&self, vm: &VirtualMachine) -> PyResult { if self.iterators.is_empty() { Err(objiter::new_stop_iteration(vm)) } else { @@ -41,16 +44,15 @@ impl PyZipRef { } } - fn iter(self, _vm: &VirtualMachine) -> Self { - self + #[pymethod(name = "__iter__")] + fn iter(zelf: PyRef, _vm: &VirtualMachine) -> PyRef { + zelf } } pub fn init(context: &PyContext) { - let zip_type = &context.zip_type; - extend_class!(context, zip_type, { + PyZip::extend_class(context, &context.zip_type); + extend_class!(context, &context.zip_type, { "__new__" => context.new_rustfunc(zip_new), - "__next__" => context.new_rustfunc(PyZipRef::next), - "__iter__" => context.new_rustfunc(PyZipRef::iter), }); } diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index 6d81ca9c1..2b6c859eb 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -15,7 +15,7 @@ use crate::obj::objiter; use crate::obj::objstr; use crate::obj::objstr::PyStringRef; use crate::obj::objtype::PyClassRef; -use crate::pyobject::{ItemProtocol, PyObjectRef, PyRef, PyResult, PyValue}; +use crate::pyobject::{ItemProtocol, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue}; use crate::vm::VirtualMachine; #[cfg(unix)] @@ -232,6 +232,7 @@ impl DirEntryRef { } } +#[pyclass] #[derive(Debug)] struct ScandirIterator { entries: RefCell, @@ -243,10 +244,10 @@ impl PyValue for ScandirIterator { } } -type ScandirIteratorRef = PyRef; - -impl ScandirIteratorRef { - fn next(self, vm: &VirtualMachine) -> PyResult { +#[pyimpl] +impl ScandirIterator { + #[pymethod(name = "__next__")] + fn next(&self, vm: &VirtualMachine) -> PyResult { match self.entries.borrow_mut().next() { Some(entry) => match entry { Ok(entry) => Ok(DirEntry { entry }.into_ref(vm).into_object()), @@ -256,8 +257,9 @@ impl ScandirIteratorRef { } } - fn iter(self, _vm: &VirtualMachine) -> Self { - self + #[pymethod(name = "__iter__")] + fn iter(zelf: PyRef, _vm: &VirtualMachine) -> PyRef { + zelf } } @@ -418,10 +420,8 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let environ = _os_environ(vm); - let scandir_iter = py_class!(ctx, "ScandirIter", ctx.object(), { - "__iter__" => ctx.new_rustfunc(ScandirIteratorRef::iter), - "__next__" => ctx.new_rustfunc(ScandirIteratorRef::next), - }); + let scandir_iter = ctx.new_class("ScandirIter", ctx.object()); + ScandirIterator::extend_class(ctx, &scandir_iter); let dir_entry = py_class!(ctx, "DirEntry", ctx.object(), { "name" => ctx.new_property(DirEntryRef::name),