Skip to content

Commit ce514d2

Browse files
committed
Add itertools.count
1 parent 7490724 commit ce514d2

File tree

2 files changed

+121
-1
lines changed

2 files changed

+121
-1
lines changed

tests/snippets/stdlib_itertools.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,55 @@
11
import itertools
2+
3+
# count
4+
5+
# default arguments
6+
c = itertools.count()
7+
assert next(c) == 0
8+
assert next(c) == 1
9+
assert next(c) == 2
10+
11+
# positional
12+
c = itertools.count(2, 3)
13+
assert next(c) == 2
14+
assert next(c) == 5
15+
assert next(c) == 8
16+
17+
# backwards
18+
c = itertools.count(1, -10)
19+
assert next(c) == 1
20+
assert next(c) == -9
21+
assert next(c) == -19
22+
23+
# step = 0
24+
c = itertools.count(5, 0)
25+
assert next(c) == 5
26+
assert next(c) == 5
27+
28+
# itertools.count TODOs: kwargs and floats
29+
30+
# step kwarg
31+
# c = itertools.count(step=5)
32+
# assert next(c) == 0
33+
# assert next(c) == 5
34+
35+
# start kwarg
36+
# c = itertools.count(start=10)
37+
# assert next(c) == 10
38+
39+
# float start
40+
# c = itertools.count(0.5)
41+
# assert next(c) == 0.5
42+
# assert next(c) == 1.5
43+
# assert next(c) == 2.5
44+
45+
# float step
46+
# c = itertools.count(1, 0.5)
47+
# assert next(c) == 1
48+
# assert next(c) == 1.5
49+
# assert next(c) == 2
50+
51+
# float start + step
52+
# c = itertools.count(0.5, 0.5)
53+
# assert next(c) == 0.5
54+
# assert next(c) == 1
55+
# assert next(c) == 1.5

vm/src/stdlib/itertools.rs

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,73 @@
1-
use crate::pyobject::PyObjectRef;
1+
use std::cell::RefCell;
2+
use std::ops::AddAssign;
3+
4+
use num_bigint::BigInt;
5+
6+
use crate::function::OptionalArg;
7+
use crate::obj::objint::{PyInt, PyIntRef};
8+
use crate::obj::objtype::PyClassRef;
9+
use crate::pyobject::{PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue};
210
use crate::vm::VirtualMachine;
311

12+
#[pyclass]
13+
#[derive(Debug)]
14+
struct PyItertoolsCount {
15+
cur: RefCell<BigInt>,
16+
step: BigInt,
17+
}
18+
19+
impl PyValue for PyItertoolsCount {
20+
fn class(vm: &VirtualMachine) -> PyClassRef {
21+
vm.class("itertools", "count")
22+
}
23+
}
24+
25+
#[pyimpl]
26+
impl PyItertoolsCount {
27+
#[pymethod(name = "__new__")]
28+
fn new(
29+
_cls: PyClassRef,
30+
start: OptionalArg<PyIntRef>,
31+
step: OptionalArg<PyIntRef>,
32+
vm: &VirtualMachine,
33+
) -> PyResult {
34+
let start = match start.into_option() {
35+
Some(int) => int.as_bigint().clone(),
36+
None => BigInt::from(0),
37+
};
38+
let step = match step.into_option() {
39+
Some(int) => int.as_bigint().clone(),
40+
None => BigInt::from(1),
41+
};
42+
43+
Ok(PyItertoolsCount {
44+
cur: RefCell::new(start),
45+
step: step,
46+
}
47+
.into_ref(vm)
48+
.into_object())
49+
}
50+
51+
#[pymethod(name = "__next__")]
52+
fn next(&self, _vm: &VirtualMachine) -> PyResult<PyInt> {
53+
let result = self.cur.borrow().clone();
54+
AddAssign::add_assign(&mut self.cur.borrow_mut() as &mut BigInt, &self.step);
55+
Ok(PyInt::new(result))
56+
}
57+
58+
#[pymethod(name = "__iter__")]
59+
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
60+
zelf
61+
}
62+
}
63+
464
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
65+
let ctx = &vm.ctx;
66+
67+
let count = ctx.new_class("count", ctx.object());
68+
PyItertoolsCount::extend_class(ctx, &count);
69+
570
py_module!(vm, "itertools", {
71+
"count" => count,
672
})
773
}

0 commit comments

Comments
 (0)