mirror of
https://github.com/RustPython/Parser.git
synced 2025-07-15 09:05:25 +00:00
Add async for
This commit is contained in:
parent
19f62b97a3
commit
c39e0baab7
1 changed files with 56 additions and 24 deletions
|
@ -442,13 +442,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||||
iter,
|
iter,
|
||||||
body,
|
body,
|
||||||
orelse,
|
orelse,
|
||||||
} => {
|
} => self.compile_for(target, iter, body, orelse, *is_async)?,
|
||||||
if *is_async {
|
|
||||||
unimplemented!("async for");
|
|
||||||
} else {
|
|
||||||
self.compile_for(target, iter, body, orelse)?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Raise { exception, cause } => match exception {
|
Raise { exception, cause } => match exception {
|
||||||
Some(value) => {
|
Some(value) => {
|
||||||
self.compile_expression(value)?;
|
self.compile_expression(value)?;
|
||||||
|
@ -736,14 +730,9 @@ impl<O: OutputStream> Compiler<O> {
|
||||||
self.emit(Instruction::Duplicate);
|
self.emit(Instruction::Duplicate);
|
||||||
|
|
||||||
// Check exception type:
|
// Check exception type:
|
||||||
self.emit(Instruction::LoadName {
|
|
||||||
name: String::from("isinstance"),
|
|
||||||
scope: bytecode::NameScope::Global,
|
|
||||||
});
|
|
||||||
self.emit(Instruction::Rotate { amount: 2 });
|
|
||||||
self.compile_expression(exc_type)?;
|
self.compile_expression(exc_type)?;
|
||||||
self.emit(Instruction::CallFunction {
|
self.emit(Instruction::CompareOperation {
|
||||||
typ: CallType::Positional(2),
|
op: bytecode::ComparisonOperator::ExceptionMatch,
|
||||||
});
|
});
|
||||||
|
|
||||||
// We cannot handle this exception type:
|
// We cannot handle this exception type:
|
||||||
|
@ -1108,11 +1097,13 @@ impl<O: OutputStream> Compiler<O> {
|
||||||
iter: &ast::Expression,
|
iter: &ast::Expression,
|
||||||
body: &[ast::Statement],
|
body: &[ast::Statement],
|
||||||
orelse: &Option<Vec<ast::Statement>>,
|
orelse: &Option<Vec<ast::Statement>>,
|
||||||
|
is_async: bool,
|
||||||
) -> Result<(), CompileError> {
|
) -> Result<(), CompileError> {
|
||||||
// Start loop
|
// Start loop
|
||||||
let start_label = self.new_label();
|
let start_label = self.new_label();
|
||||||
let else_label = self.new_label();
|
let else_label = self.new_label();
|
||||||
let end_label = self.new_label();
|
let end_label = self.new_label();
|
||||||
|
|
||||||
self.emit(Instruction::SetupLoop {
|
self.emit(Instruction::SetupLoop {
|
||||||
start: start_label,
|
start: start_label,
|
||||||
end: end_label,
|
end: end_label,
|
||||||
|
@ -1121,19 +1112,57 @@ impl<O: OutputStream> Compiler<O> {
|
||||||
// The thing iterated:
|
// The thing iterated:
|
||||||
self.compile_expression(iter)?;
|
self.compile_expression(iter)?;
|
||||||
|
|
||||||
// Retrieve Iterator
|
if is_async {
|
||||||
self.emit(Instruction::GetIter);
|
let check_asynciter_label = self.new_label();
|
||||||
|
let body_label = self.new_label();
|
||||||
|
|
||||||
self.set_label(start_label);
|
self.emit(Instruction::GetAIter);
|
||||||
self.emit(Instruction::ForIter { target: else_label });
|
|
||||||
|
|
||||||
// Start of loop iteration, set targets:
|
self.set_label(start_label);
|
||||||
self.compile_store(target)?;
|
self.emit(Instruction::SetupExcept {
|
||||||
|
handler: check_asynciter_label,
|
||||||
|
});
|
||||||
|
self.emit(Instruction::GetANext);
|
||||||
|
self.emit(Instruction::LoadConst {
|
||||||
|
value: bytecode::Constant::None,
|
||||||
|
});
|
||||||
|
self.emit(Instruction::YieldFrom);
|
||||||
|
self.compile_store(target)?;
|
||||||
|
self.emit(Instruction::PopBlock);
|
||||||
|
self.emit(Instruction::Jump { target: body_label });
|
||||||
|
|
||||||
let was_in_loop = self.in_loop;
|
self.set_label(check_asynciter_label);
|
||||||
self.in_loop = true;
|
self.emit(Instruction::Duplicate);
|
||||||
self.compile_statements(body)?;
|
self.emit(Instruction::LoadName {
|
||||||
self.in_loop = was_in_loop;
|
name: "StopAsyncIteration".to_string(),
|
||||||
|
scope: bytecode::NameScope::Global,
|
||||||
|
});
|
||||||
|
self.emit(Instruction::CompareOperation {
|
||||||
|
op: bytecode::ComparisonOperator::ExceptionMatch,
|
||||||
|
});
|
||||||
|
self.emit(Instruction::JumpIfTrue { target: else_label });
|
||||||
|
self.emit(Instruction::Raise { argc: 0 });
|
||||||
|
|
||||||
|
let was_in_loop = self.in_loop;
|
||||||
|
self.in_loop = true;
|
||||||
|
self.set_label(body_label);
|
||||||
|
self.compile_statements(body)?;
|
||||||
|
self.in_loop = was_in_loop;
|
||||||
|
} else {
|
||||||
|
// Retrieve Iterator
|
||||||
|
self.emit(Instruction::GetIter);
|
||||||
|
|
||||||
|
self.set_label(start_label);
|
||||||
|
self.emit(Instruction::ForIter { target: else_label });
|
||||||
|
|
||||||
|
// Start of loop iteration, set targets:
|
||||||
|
self.compile_store(target)?;
|
||||||
|
|
||||||
|
let was_in_loop = self.in_loop;
|
||||||
|
self.in_loop = true;
|
||||||
|
self.compile_statements(body)?;
|
||||||
|
self.in_loop = was_in_loop;
|
||||||
|
}
|
||||||
|
|
||||||
self.emit(Instruction::Jump {
|
self.emit(Instruction::Jump {
|
||||||
target: start_label,
|
target: start_label,
|
||||||
|
@ -1144,6 +1173,9 @@ impl<O: OutputStream> Compiler<O> {
|
||||||
self.compile_statements(orelse)?;
|
self.compile_statements(orelse)?;
|
||||||
}
|
}
|
||||||
self.set_label(end_label);
|
self.set_label(end_label);
|
||||||
|
if is_async {
|
||||||
|
self.emit(Instruction::Pop);
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue