Basic async for comprehension support

This commit is contained in:
Jeong YunWon committed 2024-04-25 20:23:25 +09:00
1 parent 61f37b10e2
commit f3501f44cb
2 files changed
+26 -15

No files matched your search

+24 -15
View File
@@ -2629,24 +2629,30 @@ impl Compiler {
compile_element: &dyn Fn(&mut Self) -> CompileResult<()>,
) -> CompileResult<()> {
let prev_ctx = self.ctx;
let is_async = generators.iter().any(|g| g.is_async);
self.ctx = CompileContext {
loop_data: None,
in_class: prev_ctx.in_class,
func: FunctionContext::Function,
func: if is_async {
FunctionContext::AsyncFunction
} else {
FunctionContext::Function
},
};
// We must have at least one generator:
assert!(!generators.is_empty());
let flags = bytecode::CodeFlags::NEW_LOCALS | bytecode::CodeFlags::IS_OPTIMIZED;
let flags = if is_async {
flags | bytecode::CodeFlags::IS_COROUTINE
} else {
flags
};
// Create magnificent function <listcomp>:
self.push_output(
bytecode::CodeFlags::NEW_LOCALS | bytecode::CodeFlags::IS_OPTIMIZED,
1,
1,
0,
name.to_owned(),
);
self.push_output(flags, 1, 1, 0, name.to_owned());
let arg0 = self.varname(".0")?;
let return_none = init_collection.is_none();
@@ -2656,11 +2662,12 @@ impl Compiler {
}
let mut loop_labels = vec![];
let mut is_async = false;
for generator in generators {
let loop_block = self.new_block();
let after_block = self.new_block();
// emit!(self, Instruction::SetupLoop);
if loop_labels.is_empty() {
// Load iterator onto stack (passed as first argument):
emit!(self, Instruction::LoadFast(arg0));
@@ -2679,13 +2686,16 @@ impl Compiler {
loop_labels.push((loop_block, after_block));
self.switch_to_block(loop_block);
if generator.is_async {
is_async = true;
emit!(self, Instruction::SetupExcept {
handler: after_block,
});
emit!(
self,
Instruction::SetupExcept {
handler: after_block,
}
);
emit!(self, Instruction::GetANext);
self.emit_constant(ConstantData::None);
emit!(self, Instruction::YieldFrom);
self.compile_store(&generator.target)?;
emit!(self, Instruction::PopBlock);
} else {
emit!(
@@ -2694,10 +2704,9 @@ impl Compiler {
target: after_block,
}
);
self.compile_store(&generator.target)?;
}
self.compile_store(&generator.target)?;
// Now evaluate the ifs:
for if_condition in &generator.ifs {
self.compile_jump_if(if_condition, false, loop_block)?
+2
View File
@@ -1944,6 +1944,7 @@ impl ExecutingFrame<'_> {
#[track_caller]
fn pop_block(&mut self) -> Block {
let block = self.state.blocks.pop().expect("No more blocks to pop!");
// eprintln!("popped block: {:?} stack: {} truncate to {}", block.typ, self.state.stack.len(), block.level);
#[cfg(debug_assertions)]
if self.state.stack.len() < block.level {
dbg!(&self);
@@ -2002,6 +2003,7 @@ impl ExecutingFrame<'_> {
}
#[inline]
#[track_caller]
fn nth_value(&self, depth: u32) -> &PyObject {
let stack = &self.state.stack;
&stack[stack.len() - depth as usize - 1]