Skip to content

Commit 4e9cc31

Browse files
HyeockJinKimyouknowone
authored andcommitted
implement async for function in compiler
1 parent dff916d commit 4e9cc31

File tree

3 files changed

+45
-20
lines changed

3 files changed

+45
-20
lines changed

bytecode/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1037,7 +1037,7 @@ impl Instruction {
10371037
}
10381038
GetAIter => 0,
10391039
GetANext => 1,
1040-
EndAsyncFor => -2,
1040+
EndAsyncFor => -1,
10411041
}
10421042
}
10431043

compiler/src/compile.rs

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2460,37 +2460,48 @@ impl Compiler {
24602460
}
24612461

24622462
let mut loop_labels = vec![];
2463+
let mut is_async = false;
24632464
for generator in generators {
2464-
if generator.is_async {
2465-
unimplemented!("async for comprehensions");
2466-
}
2467-
24682465
let loop_block = self.new_block();
24692466
let after_block = self.new_block();
24702467

24712468
// Setup for loop:
2472-
self.emit(Instruction::SetupLoop {
2473-
break_target: after_block,
2474-
});
2469+
if !generator.is_async {
2470+
self.emit(Instruction::SetupLoop {
2471+
break_target: after_block,
2472+
});
2473+
}
24752474

24762475
if loop_labels.is_empty() {
24772476
// Load iterator onto stack (passed as first argument):
24782477
self.emit(Instruction::LoadFast(arg0));
24792478
} else {
24802479
// Evaluate iterated item:
24812480
self.compile_expression(&generator.iter)?;
2482-
2483-
// Get iterator / turn item into an iterator
2484-
self.emit(Instruction::GetIter);
2481+
if generator.is_async {
2482+
self.emit(Instruction::GetAIter);
2483+
} else {
2484+
// Get iterator / turn item into an iterator
2485+
self.emit(Instruction::GetIter);
2486+
}
24852487
}
24862488

24872489
loop_labels.push((loop_block, after_block));
2488-
24892490
self.switch_to_block(loop_block);
2490-
self.emit(Instruction::ForIter {
2491-
target: after_block,
2492-
});
2493-
2491+
if generator.is_async {
2492+
is_async = true;
2493+
self.emit(Instruction::SetupFinally {
2494+
handler: after_block,
2495+
});
2496+
self.emit(Instruction::GetANext);
2497+
self.emit_constant(ConstantData::None);
2498+
self.emit(Instruction::YieldFrom);
2499+
self.emit(Instruction::PopBlock);
2500+
} else {
2501+
self.emit(Instruction::ForIter {
2502+
target: after_block,
2503+
});
2504+
}
24942505
self.compile_store(&generator.target)?;
24952506

24962507
// Now evaluate the ifs:
@@ -2507,7 +2518,11 @@ impl Compiler {
25072518

25082519
// End of for loop:
25092520
self.switch_to_block(after_block);
2510-
self.emit(Instruction::PopBlock);
2521+
if is_async {
2522+
self.emit(Instruction::EndAsyncFor);
2523+
} else {
2524+
self.emit(Instruction::PopBlock);
2525+
}
25112526
}
25122527

25132528
if return_none {
@@ -2544,10 +2559,19 @@ impl Compiler {
25442559
self.compile_expression(&generators[0].iter)?;
25452560

25462561
// Get iterator / turn item into an iterator
2547-
self.emit(Instruction::GetIter);
2562+
if is_async {
2563+
self.emit(Instruction::GetAIter);
2564+
} else {
2565+
self.emit(Instruction::GetIter);
2566+
}
25482567

25492568
// Call just created <listcomp> function:
25502569
self.emit(Instruction::CallFunctionPositional { nargs: 1 });
2570+
if is_async {
2571+
self.emit(Instruction::GetAwaitable);
2572+
self.emit_constant(ConstantData::None);
2573+
self.emit(Instruction::YieldFrom);
2574+
}
25512575
Ok(())
25522576
}
25532577

@@ -2563,7 +2587,9 @@ impl Compiler {
25632587
// "generator_stop" => {}
25642588
"annotations" => self.future_annotations = true,
25652589
other => {
2566-
return Err(self.error(CompileErrorType::InvalidFutureFeature(other.to_owned())))
2590+
return Err(
2591+
self.error(CompileErrorType::InvalidFutureFeature(other.to_owned()))
2592+
);
25672593
}
25682594
}
25692595
}

vm/src/frame.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,6 @@ impl ExecutingFrame<'_> {
893893
}
894894
bytecode::Instruction::EndAsyncFor => {
895895
let exc = self.pop_value();
896-
self.pop_value(); // async iterator we were calling __anext__ on
897896
if exc.fast_isinstance(vm.ctx.exceptions.stop_async_iteration) {
898897
vm.take_exception().expect("Should have exception in stack");
899898
Ok(None)

0 commit comments

Comments
 (0)