Skip to content

Commit ec14318

Browse files
HyeockJinKimyouknowone
authored andcommitted
implement async for function in compiler
1 parent e5ca631 commit ec14318

File tree

3 files changed

+37
-15
lines changed

3 files changed

+37
-15
lines changed

compiler/codegen/src/compile.rs

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2654,11 +2654,8 @@ impl Compiler {
26542654
}
26552655

26562656
let mut loop_labels = vec![];
2657+
let mut is_async = false;
26572658
for generator in generators {
2658-
if generator.is_async {
2659-
unimplemented!("async for comprehensions");
2660-
}
2661-
26622659
let loop_block = self.new_block();
26632660
let after_block = self.new_block();
26642661

@@ -2670,18 +2667,32 @@ impl Compiler {
26702667
self.compile_expression(&generator.iter)?;
26712668

26722669
// Get iterator / turn item into an iterator
2673-
emit!(self, Instruction::GetIter);
2670+
if generator.is_async {
2671+
emit!(self, Instruction::GetAIter);
2672+
} else {
2673+
emit!(self, Instruction::GetIter);
2674+
}
26742675
}
26752676

26762677
loop_labels.push((loop_block, after_block));
2677-
26782678
self.switch_to_block(loop_block);
2679-
emit!(
2680-
self,
2681-
Instruction::ForIter {
2682-
target: after_block,
2683-
}
2684-
);
2679+
if generator.is_async {
2680+
is_async = true;
2681+
emit!(self, Instruction::SetupFinally {
2682+
handler: after_block,
2683+
});
2684+
emit!(self, Instruction::GetANext);
2685+
self.emit_constant(ConstantData::None);
2686+
emit!(self, Instruction::YieldFrom);
2687+
emit!(self, Instruction::PopBlock);
2688+
} else {
2689+
emit!(
2690+
self,
2691+
Instruction::ForIter {
2692+
target: after_block,
2693+
}
2694+
);
2695+
}
26852696

26862697
self.compile_store(&generator.target)?;
26872698

@@ -2699,6 +2710,9 @@ impl Compiler {
26992710

27002711
// End of for loop:
27012712
self.switch_to_block(after_block);
2713+
if is_async {
2714+
emit!(self, Instruction::EndAsyncFor);
2715+
}
27022716
}
27032717

27042718
if return_none {
@@ -2735,10 +2749,19 @@ impl Compiler {
27352749
self.compile_expression(&generators[0].iter)?;
27362750

27372751
// Get iterator / turn item into an iterator
2738-
emit!(self, Instruction::GetIter);
2752+
if is_async {
2753+
emit!(self, Instruction::GetAIter);
2754+
} else {
2755+
emit!(self, Instruction::GetIter);
2756+
};
27392757

27402758
// Call just created <listcomp> function:
27412759
emit!(self, Instruction::CallFunctionPositional { nargs: 1 });
2760+
if is_async {
2761+
emit!(self, Instruction::GetAwaitable);
2762+
self.emit_constant(ConstantData::None);
2763+
emit!(self, Instruction::YieldFrom);
2764+
}
27422765
Ok(())
27432766
}
27442767

compiler/core/src/bytecode.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1268,7 +1268,7 @@ impl Instruction {
12681268
}
12691269
GetAIter => 0,
12701270
GetANext => 1,
1271-
EndAsyncFor => -2,
1271+
EndAsyncFor => -1,
12721272
ExtendedArg => 0,
12731273
}
12741274
}

vm/src/frame.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,6 @@ impl ExecutingFrame<'_> {
10001000
}
10011001
bytecode::Instruction::EndAsyncFor => {
10021002
let exc = self.pop_value();
1003-
self.pop_value(); // async iterator we were calling __anext__ on
10041003
if exc.fast_isinstance(vm.ctx.exceptions.stop_async_iteration) {
10051004
vm.take_exception().expect("Should have exception in stack");
10061005
Ok(None)

0 commit comments

Comments
 (0)