forked from RustPython/RustPython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathobjiter.rs
More file actions
136 lines (124 loc) · 4.32 KB
/
objiter.rs
File metadata and controls
136 lines (124 loc) · 4.32 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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
* Various types to support iteration.
*/
use super::super::pyobject::{
AttributeProtocol, PyContext, PyFuncArgs, PyObjectKind, PyObjectRef, PyResult, TypeProtocol,
};
use super::super::vm::VirtualMachine;
use super::objbool;
// use super::objstr;
use super::objtype; // Required for arg_check! to use isinstance
/*
* This helper function is called at multiple places. First, it is called
* in the vm when a for loop is entered. Next, it is used when the builtin
* function 'iter' is called.
*/
pub fn get_iter(vm: &mut VirtualMachine, iter_target: &PyObjectRef) -> PyResult {
vm.call_method(iter_target, "__iter__", vec![])
// let type_str = objstr::get_value(&vm.to_str(iter_target.typ()).unwrap());
// let type_error = vm.new_type_error(format!("Cannot iterate over {}", type_str));
// return Err(type_error);
}
/*
* Helper function to retrieve the next object (or none) from an iterator.
*/
pub fn get_next_object(
vm: &mut VirtualMachine,
iter_obj: &PyObjectRef,
) -> Result<Option<PyObjectRef>, PyObjectRef> {
let next_obj: PyResult = vm.call_method(iter_obj, "__next__", vec![]);
match next_obj {
Ok(value) => Ok(Some(value)),
Err(next_error) => {
// Check if we have stopiteration, or something else:
if objtype::isinstance(&next_error, &vm.ctx.exceptions.stop_iteration) {
Ok(None)
} else {
Err(next_error)
}
}
}
}
/* Retrieve all elements from an iterator */
pub fn get_all(
vm: &mut VirtualMachine,
iter_obj: &PyObjectRef,
) -> Result<Vec<PyObjectRef>, PyObjectRef> {
let mut elements = vec![];
loop {
let element = get_next_object(vm, iter_obj)?;
match element {
Some(v) => elements.push(v),
None => break,
}
}
Ok(elements)
}
// Sequence iterator:
fn iter_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(iter_target, None)]);
get_iter(vm, iter_target)
}
fn iter_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(iter, Some(vm.ctx.iter_type()))]);
// Return self:
Ok(iter.clone())
}
fn iter_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(iter, Some(vm.ctx.iter_type())), (needle, None)]
);
loop {
match vm.call_method(&iter, "__next__", vec![]) {
Ok(element) => match vm.call_method(needle, "__eq__", vec![element.clone()]) {
Ok(value) => {
if objbool::get_value(&value) {
return Ok(vm.new_bool(true));
} else {
continue;
}
}
Err(_) => return Err(vm.new_type_error("".to_string())),
},
Err(_) => return Ok(vm.new_bool(false)),
}
}
}
fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(iter, Some(vm.ctx.iter_type()))]);
if let PyObjectKind::Iterator {
ref mut position,
iterated_obj: ref iterated_obj_ref,
} = iter.borrow_mut().kind
{
let iterated_obj = &*iterated_obj_ref.borrow_mut();
match iterated_obj.kind {
PyObjectKind::Sequence { ref elements } => {
if *position < elements.len() {
let obj_ref = elements[*position].clone();
*position += 1;
Ok(obj_ref)
} else {
let stop_iteration_type = vm.ctx.exceptions.stop_iteration.clone();
let stop_iteration =
vm.new_exception(stop_iteration_type, "End of iterator".to_string());
Err(stop_iteration)
}
}
_ => {
panic!("NOT IMPL");
}
}
} else {
panic!("NOT IMPL");
}
}
pub fn init(context: &PyContext) {
let ref iter_type = context.iter_type;
iter_type.set_attr("__contains__", context.new_rustfunc(iter_contains));
iter_type.set_attr("__iter__", context.new_rustfunc(iter_iter));
iter_type.set_attr("__new__", context.new_rustfunc(iter_new));
iter_type.set_attr("__next__", context.new_rustfunc(iter_next));
}