(
&mut self,
target: &ast::Expr,
iter: &ast::Expr,
body: &[ast::Stmt],
orelse: &[ast::Stmt],
is_async: bool,
)
| 5780 | } |
| 5781 | |
| 5782 | fn compile_for( |
| 5783 | &mut self, |
| 5784 | target: &ast::Expr, |
| 5785 | iter: &ast::Expr, |
| 5786 | body: &[ast::Stmt], |
| 5787 | orelse: &[ast::Stmt], |
| 5788 | is_async: bool, |
| 5789 | ) -> CompileResult<()> { |
| 5790 | self.enter_conditional_block(); |
| 5791 | |
| 5792 | // Start loop |
| 5793 | let for_block = self.new_block(); |
| 5794 | let else_block = self.new_block(); |
| 5795 | let after_block = self.new_block(); |
| 5796 | let mut end_async_for_target = BlockIdx::NULL; |
| 5797 | |
| 5798 | // The thing iterated: |
| 5799 | // Optimize: `for x in [a, b, c]` → use tuple instead of list |
| 5800 | // Skip for async-for (GET_AITER expects the original type) |
| 5801 | if !is_async |
| 5802 | && let ast::Expr::List(ast::ExprList { elts, .. }) = iter |
| 5803 | && !elts.iter().any(|e| matches!(e, ast::Expr::Starred(_))) |
| 5804 | { |
| 5805 | for elt in elts { |
| 5806 | self.compile_expression(elt)?; |
| 5807 | } |
| 5808 | emit!( |
| 5809 | self, |
| 5810 | Instruction::BuildTuple { |
| 5811 | count: u32::try_from(elts.len()).expect("too many elements"), |
| 5812 | } |
| 5813 | ); |
| 5814 | } else { |
| 5815 | self.compile_expression(iter)?; |
| 5816 | } |
| 5817 | |
| 5818 | if is_async { |
| 5819 | if self.ctx.func != FunctionContext::AsyncFunction { |
| 5820 | return Err(self.error(CodegenErrorType::InvalidAsyncFor)); |
| 5821 | } |
| 5822 | emit!(self, Instruction::GetAIter); |
| 5823 | |
| 5824 | self.switch_to_block(for_block); |
| 5825 | |
| 5826 | // codegen_async_for: push fblock BEFORE SETUP_FINALLY |
| 5827 | self.push_fblock(FBlockType::ForLoop, for_block, after_block)?; |
| 5828 | |
| 5829 | // SETUP_FINALLY to guard the __anext__ call |
| 5830 | emit!(self, PseudoInstruction::SetupFinally { delta: else_block }); |
| 5831 | emit!(self, Instruction::GetANext); |
| 5832 | self.emit_load_const(ConstantData::None); |
| 5833 | end_async_for_target = self.compile_yield_from_sequence(true)?; |
| 5834 | // POP_BLOCK for SETUP_FINALLY - only GetANext/yield_from are protected |
| 5835 | emit!(self, PseudoInstruction::PopBlock); |
| 5836 | emit!(self, Instruction::NotTaken); |
| 5837 | |
| 5838 | // Success block for __anext__ |
| 5839 | self.compile_store(target)?; |
no test coverage detected