33 */
44
55use super :: super :: pyobject:: {
6- AttributeProtocol , PyContext , PyFuncArgs , PyObject , PyObjectKind , PyObjectRef ,
7- PyResult , TypeProtocol ,
6+ AttributeProtocol , PyContext , PyFuncArgs , PyObject , PyObjectKind , PyObjectRef , PyResult ,
7+ TypeProtocol ,
88} ;
99use super :: super :: vm:: VirtualMachine ;
1010use super :: objstr;
1111use super :: objtype; // Required for arg_check! to use isinstance
1212
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+ */
1318pub fn get_iter ( vm : & mut VirtualMachine , iter_target : & PyObjectRef ) -> PyResult {
1419 // Check what we are going to iterate over:
1520 let iterated_obj = if objtype:: isinstance ( iter_target, vm. ctx . iter_type ( ) ) {
1621 // If object is already an iterator, return that one.
17- return Ok ( iter_target. clone ( ) )
22+ return Ok ( iter_target. clone ( ) ) ;
1823 } else if objtype:: isinstance ( iter_target, vm. ctx . list_type ( ) ) {
1924 iter_target. clone ( )
2025 } else {
@@ -37,46 +42,45 @@ pub fn get_iter(vm: &mut VirtualMachine, iter_target: &PyObjectRef) -> PyResult
3742
3843// Sequence iterator:
3944fn 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 ) ] ) ;
4546
4647 get_iter ( vm, iter_target)
4748}
4849
4950fn 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( ) ) ) ] ) ;
5552 // Return self:
5653 Ok ( iter. clone ( ) )
5754}
5855
5956fn 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( ) ) ) ] ) ;
6558
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+ }
7981 }
82+ } else {
83+ panic ! ( "NOT IMPL" ) ;
8084 }
8185}
8286
@@ -86,4 +90,3 @@ pub fn init(context: &PyContext) {
8690 iter_type. set_attr ( "__iter__" , context. new_rustfunc ( iter_iter) ) ;
8791 iter_type. set_attr ( "__next__" , context. new_rustfunc ( iter_next) ) ;
8892}
89-
0 commit comments