3
3
*/
4
4
5
5
use super :: super :: pyobject:: {
6
- AttributeProtocol , PyContext , PyFuncArgs , PyObject , PyObjectKind , PyObjectRef ,
7
- PyResult , TypeProtocol ,
6
+ AttributeProtocol , PyContext , PyFuncArgs , PyObject , PyObjectKind , PyObjectRef , PyResult ,
7
+ TypeProtocol ,
8
8
} ;
9
9
use super :: super :: vm:: VirtualMachine ;
10
10
use super :: objstr;
11
11
use super :: objtype; // Required for arg_check! to use isinstance
12
12
13
+ /*
14
+ * This helper function is called at multiple places. First, it is called
15
+ * in the vm when a for loop is entered. Next, it is used when the builtin
16
+ * function 'iter' is called.
17
+ */
13
18
pub fn get_iter ( vm : & mut VirtualMachine , iter_target : & PyObjectRef ) -> PyResult {
14
19
// Check what we are going to iterate over:
15
20
let iterated_obj = if objtype:: isinstance ( iter_target, vm. ctx . iter_type ( ) ) {
16
21
// If object is already an iterator, return that one.
17
- return Ok ( iter_target. clone ( ) )
22
+ return Ok ( iter_target. clone ( ) ) ;
18
23
} else if objtype:: isinstance ( iter_target, vm. ctx . list_type ( ) ) {
19
24
iter_target. clone ( )
20
25
} else {
@@ -37,46 +42,45 @@ pub fn get_iter(vm: &mut VirtualMachine, iter_target: &PyObjectRef) -> PyResult
37
42
38
43
// Sequence iterator:
39
44
fn iter_new ( vm : & mut VirtualMachine , args : PyFuncArgs ) -> PyResult {
40
- arg_check ! (
41
- vm,
42
- args,
43
- required = [ ( iter_target, None ) ]
44
- ) ;
45
+ arg_check ! ( vm, args, required = [ ( iter_target, None ) ] ) ;
45
46
46
47
get_iter ( vm, iter_target)
47
48
}
48
49
49
50
fn iter_iter ( vm : & mut VirtualMachine , args : PyFuncArgs ) -> PyResult {
50
- arg_check ! (
51
- vm,
52
- args,
53
- required = [ ( iter, Some ( vm. ctx. iter_type( ) ) ) ]
54
- ) ;
51
+ arg_check ! ( vm, args, required = [ ( iter, Some ( vm. ctx. iter_type( ) ) ) ] ) ;
55
52
// Return self:
56
53
Ok ( iter. clone ( ) )
57
54
}
58
55
59
56
fn iter_next ( vm : & mut VirtualMachine , args : PyFuncArgs ) -> PyResult {
60
- arg_check ! (
61
- vm,
62
- args,
63
- required = [ ( iter, Some ( vm. ctx. iter_type( ) ) ) ]
64
- ) ;
57
+ arg_check ! ( vm, args, required = [ ( iter, Some ( vm. ctx. iter_type( ) ) ) ] ) ;
65
58
66
- let next_obj: Option < PyObjectRef > = {
67
- // We require a mutable pyobject here to update the iterator:
68
- let mut iterator: & mut PyObject = & mut iter. borrow_mut ( ) ;
69
- iterator. nxt ( )
70
- } ;
71
-
72
- // Return next item, or StopIteration
73
- match next_obj {
74
- Some ( value) => Ok ( value) ,
75
- None => {
76
- let stop_iteration_type = vm. ctx . exceptions . stop_iteration . clone ( ) ;
77
- let stop_iteration = vm. new_exception ( stop_iteration_type, "End of iterator" . to_string ( ) ) ;
78
- Err ( stop_iteration)
59
+ if let PyObjectKind :: Iterator {
60
+ ref mut position,
61
+ iterated_obj : ref iterated_obj_ref,
62
+ } = iter. borrow_mut ( ) . kind
63
+ {
64
+ let iterated_obj = & * iterated_obj_ref. borrow_mut ( ) ;
65
+ match iterated_obj. kind {
66
+ PyObjectKind :: List { ref elements } => {
67
+ if * position < elements. len ( ) {
68
+ let obj_ref = elements[ * position] . clone ( ) ;
69
+ * position += 1 ;
70
+ Ok ( obj_ref)
71
+ } else {
72
+ let stop_iteration_type = vm. ctx . exceptions . stop_iteration . clone ( ) ;
73
+ let stop_iteration =
74
+ vm. new_exception ( stop_iteration_type, "End of iterator" . to_string ( ) ) ;
75
+ Err ( stop_iteration)
76
+ }
77
+ }
78
+ _ => {
79
+ panic ! ( "NOT IMPL" ) ;
80
+ }
79
81
}
82
+ } else {
83
+ panic ! ( "NOT IMPL" ) ;
80
84
}
81
85
}
82
86
@@ -86,4 +90,3 @@ pub fn init(context: &PyContext) {
86
90
iter_type. set_attr ( "__iter__" , context. new_rustfunc ( iter_iter) ) ;
87
91
iter_type. set_attr ( "__next__" , context. new_rustfunc ( iter_next) ) ;
88
92
}
89
-
0 commit comments