Add async for

This commit is contained in:
coolreader18 2019-10-17 23:34:43 -05:00
parent 19f62b97a3
commit c39e0baab7

View file

@ -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(())
} }