mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-29 03:04:38 +08:00
Basic async for comprehension support
This commit is contained in:
1 parent
61f37b10e2
commit
f3501f44cb
2 files changed
+26
-15
No files matched your search
@@ -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)?
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in new issue
Block a user