mirror of
https://github.com/RustPython/Parser.git
synced 2025-07-15 00:55:22 +00:00
Add async with, reorganize how with blocks work
This commit is contained in:
parent
3638591cde
commit
ae825125a5
1 changed files with 62 additions and 17 deletions
|
@ -386,27 +386,72 @@ impl<O: OutputStream> Compiler<O> {
|
||||||
body,
|
body,
|
||||||
} => {
|
} => {
|
||||||
if *is_async {
|
if *is_async {
|
||||||
unimplemented!("async with");
|
let end_labels = items
|
||||||
} else {
|
.iter()
|
||||||
let end_label = self.new_label();
|
.map(|item| {
|
||||||
for item in items {
|
let end_label = self.new_label();
|
||||||
self.compile_expression(&item.context_expr)?;
|
self.compile_expression(&item.context_expr)?;
|
||||||
self.emit(Instruction::SetupWith { end: end_label });
|
self.emit(Instruction::BeforeAsyncWith);
|
||||||
match &item.optional_vars {
|
self.emit(Instruction::GetAwaitable);
|
||||||
Some(var) => {
|
self.emit(Instruction::LoadConst {
|
||||||
self.compile_store(var)?;
|
value: bytecode::Constant::None,
|
||||||
|
});
|
||||||
|
self.emit(Instruction::YieldFrom);
|
||||||
|
self.emit(Instruction::SetupAsyncWith { end: end_label });
|
||||||
|
match &item.optional_vars {
|
||||||
|
Some(var) => {
|
||||||
|
self.compile_store(var)?;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.emit(Instruction::Pop);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => {
|
Ok(end_label)
|
||||||
self.emit(Instruction::Pop);
|
})
|
||||||
}
|
.collect::<Result<Vec<_>, CompileError>>()?;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.compile_statements(body)?;
|
self.compile_statements(body)?;
|
||||||
for _ in 0..items.len() {
|
|
||||||
self.emit(Instruction::CleanupWith { end: end_label });
|
for end_label in end_labels {
|
||||||
|
self.emit(Instruction::PopBlock);
|
||||||
|
self.emit(Instruction::EnterFinally);
|
||||||
|
self.set_label(end_label);
|
||||||
|
self.emit(Instruction::WithCleanupStart);
|
||||||
|
self.emit(Instruction::GetAwaitable);
|
||||||
|
self.emit(Instruction::LoadConst {
|
||||||
|
value: bytecode::Constant::None,
|
||||||
|
});
|
||||||
|
self.emit(Instruction::YieldFrom);
|
||||||
|
self.emit(Instruction::WithCleanupFinish);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let end_labels = items
|
||||||
|
.iter()
|
||||||
|
.map(|item| {
|
||||||
|
let end_label = self.new_label();
|
||||||
|
self.compile_expression(&item.context_expr)?;
|
||||||
|
self.emit(Instruction::SetupWith { end: end_label });
|
||||||
|
match &item.optional_vars {
|
||||||
|
Some(var) => {
|
||||||
|
self.compile_store(var)?;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.emit(Instruction::Pop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(end_label)
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, CompileError>>()?;
|
||||||
|
|
||||||
|
self.compile_statements(body)?;
|
||||||
|
|
||||||
|
for end_label in end_labels {
|
||||||
|
self.emit(Instruction::PopBlock);
|
||||||
|
self.emit(Instruction::EnterFinally);
|
||||||
|
self.set_label(end_label);
|
||||||
|
self.emit(Instruction::WithCleanupStart);
|
||||||
|
self.emit(Instruction::WithCleanupFinish);
|
||||||
}
|
}
|
||||||
self.set_label(end_label);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
For {
|
For {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue