Advance the iterator on top of stack. Returns `true` if iteration continued (item pushed), `false` if exhausted (jumped).
(
&mut self,
vm: &VirtualMachine,
target: bytecode::Label,
)
| 6916 | /// Advance the iterator on top of stack. |
| 6917 | /// Returns `true` if iteration continued (item pushed), `false` if exhausted (jumped). |
| 6918 | fn execute_for_iter( |
| 6919 | &mut self, |
| 6920 | vm: &VirtualMachine, |
| 6921 | target: bytecode::Label, |
| 6922 | ) -> Result<bool, PyBaseExceptionRef> { |
| 6923 | let top = self.top_value(); |
| 6924 | |
| 6925 | // FOR_ITER_RANGE: bypass generic iterator protocol for range iterators |
| 6926 | if let Some(range_iter) = top.downcast_ref_if_exact::<PyRangeIterator>(vm) { |
| 6927 | if let Some(value) = range_iter.fast_next() { |
| 6928 | self.push_value(vm.ctx.new_int(value).into()); |
| 6929 | return Ok(true); |
| 6930 | } |
| 6931 | if vm.use_tracing.get() && !vm.is_none(&self.object.trace.lock()) { |
| 6932 | let stop_exc = vm.new_stop_iteration(None); |
| 6933 | self.fire_exception_trace(&stop_exc, vm)?; |
| 6934 | } |
| 6935 | self.jump(self.for_iter_jump_target(target)); |
| 6936 | return Ok(false); |
| 6937 | } |
| 6938 | |
| 6939 | let top_of_stack = PyIter::new(top); |
| 6940 | let next_obj = top_of_stack.next(vm); |
| 6941 | |
| 6942 | match next_obj { |
| 6943 | Ok(PyIterReturn::Return(value)) => { |
| 6944 | self.push_value(value); |
| 6945 | Ok(true) |
| 6946 | } |
| 6947 | Ok(PyIterReturn::StopIteration(value)) => { |
| 6948 | // Fire 'exception' trace event for StopIteration, matching |
| 6949 | // FOR_ITER's inline call to _PyEval_MonitorRaise. |
| 6950 | if vm.use_tracing.get() && !vm.is_none(&self.object.trace.lock()) { |
| 6951 | let stop_exc = vm.new_stop_iteration(value); |
| 6952 | self.fire_exception_trace(&stop_exc, vm)?; |
| 6953 | } |
| 6954 | self.jump(self.for_iter_jump_target(target)); |
| 6955 | Ok(false) |
| 6956 | } |
| 6957 | Err(next_error) => { |
| 6958 | self.pop_value(); |
| 6959 | Err(next_error) |
| 6960 | } |
| 6961 | } |
| 6962 | } |
| 6963 | |
| 6964 | /// Compute the jump target for FOR_ITER exhaustion: skip END_FOR and jump to POP_ITER. |
| 6965 | fn for_iter_jump_target(&self, target: bytecode::Label) -> bytecode::Label { |
no test coverage detected