forked from RustPython/RustPython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathobjenumerate.rs
More file actions
71 lines (64 loc) · 1.86 KB
/
objenumerate.rs
File metadata and controls
71 lines (64 loc) · 1.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use std::cell::RefCell;
use std::ops::AddAssign;
use super::objint;
use super::objiter;
use crate::pyobject::{PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
use num_bigint::BigInt;
use num_traits::Zero;
fn enumerate_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(cls, Some(vm.ctx.type_type())), (iterable, None)],
optional = [(start, Some(vm.ctx.int_type()))]
);
let counter = if let Some(x) = start {
objint::get_value(x)
} else {
BigInt::zero()
};
let iterator = objiter::get_iter(vm, iterable)?;
Ok(PyObject::new(
PyObjectPayload::EnumerateIterator {
counter: RefCell::new(counter),
iterator,
},
cls.clone(),
))
}
fn enumerate_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(enumerate, Some(vm.ctx.enumerate_type()))]
);
if let PyObjectPayload::EnumerateIterator {
ref counter,
ref iterator,
} = enumerate.payload
{
let next_obj = objiter::call_next(vm, iterator)?;
let result = vm
.ctx
.new_tuple(vec![vm.ctx.new_int(counter.borrow().clone()), next_obj]);
AddAssign::add_assign(&mut counter.borrow_mut() as &mut BigInt, 1);
Ok(result)
} else {
panic!("enumerate doesn't have correct payload");
}
}
pub fn init(context: &PyContext) {
let enumerate_type = &context.enumerate_type;
objiter::iter_type_init(context, enumerate_type);
context.set_attr(
enumerate_type,
"__new__",
context.new_rustfunc(enumerate_new),
);
context.set_attr(
enumerate_type,
"__next__",
context.new_rustfunc(enumerate_next),
);
}