implement async for function in compiler

This commit is contained in:
HyeockJinKim
2021-08-25 18:58:48 +09:00
committed by Jeong YunWon
parent 2856aff757
commit 61f37b10e2

View File

@@ -2656,11 +2656,8 @@ impl Compiler {
}
let mut loop_labels = vec![];
let mut is_async = false;
for generator in generators {
if generator.is_async {
unimplemented!("async for comprehensions");
}
let loop_block = self.new_block();
let after_block = self.new_block();
@@ -2672,35 +2669,31 @@ impl Compiler {
self.compile_expression(&generator.iter)?;
// Get iterator / turn item into an iterator
emit!(self, Instruction::GetIter);
if generator.is_async {
emit!(self, Instruction::GetAIter);
} else {
emit!(self, Instruction::GetIter);
}
}
loop_labels.push((loop_block, after_block));
self.switch_to_block(loop_block);
if generator.is_async {
let check_asynciter_block = self.new_block();
self.emit(Instruction::GetAIter);
self.switch_to_block(loop_block);
self.emit(Instruction::SetupExcept {
handler: check_asynciter_block,
is_async = true;
emit!(self, Instruction::SetupExcept {
handler: after_block,
});
self.emit(Instruction::GetANext);
emit!(self, Instruction::GetANext);
self.emit_constant(ConstantData::None);
self.emit(Instruction::YieldFrom);
self.compile_store(&generator.target)?;
self.emit(Instruction::PopBlock);
emit!(self, Instruction::YieldFrom);
emit!(self, Instruction::PopBlock);
} else {
// Get iterator / turn item into an iterator
self.emit(Instruction::GetIter);
self.switch_to_block(loop_block);
self.emit(Instruction::ForIter {
target: after_block,
});
self.compile_store(&generator.target)?;
emit!(
self,
Instruction::ForIter {
target: after_block,
}
);
}
self.compile_store(&generator.target)?;
@@ -2719,6 +2712,9 @@ impl Compiler {
// End of for loop:
self.switch_to_block(after_block);
if is_async {
emit!(self, Instruction::EndAsyncFor);
}
}
if return_none {
@@ -2755,10 +2751,19 @@ impl Compiler {
self.compile_expression(&generators[0].iter)?;
// Get iterator / turn item into an iterator
emit!(self, Instruction::GetIter);
if is_async {
emit!(self, Instruction::GetAIter);
} else {
emit!(self, Instruction::GetIter);
};
// Call just created <listcomp> function:
emit!(self, Instruction::CallFunctionPositional { nargs: 1 });
if is_async {
emit!(self, Instruction::GetAwaitable);
self.emit_constant(ConstantData::None);
emit!(self, Instruction::YieldFrom);
}
Ok(())
}