Partially implement async generators

This commit is contained in:
coolreader18 2020-01-05 00:17:45 -06:00 committed by Noah
parent e9ff68c850
commit d5b9e6b93a
2 changed files with 60 additions and 3 deletions

View file

@ -39,7 +39,7 @@ struct CompileContext {
func: FunctionContext, func: FunctionContext,
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy, PartialEq)]
enum FunctionContext { enum FunctionContext {
NoFunction, NoFunction,
Function, Function,
@ -562,6 +562,17 @@ impl<O: OutputStream> Compiler<O> {
} }
match value { match value {
Some(v) => { Some(v) => {
<<<<<<< Updated upstream
=======
if self.ctx.func == FunctionContext::AsyncFunction
&& self.current_output().is_generator()
{
return Err(self.error_loc(
CompileErrorType::AsyncReturnValue,
statement.location.clone(),
));
}
>>>>>>> Stashed changes
self.compile_expression(v)?; self.compile_expression(v)?;
} }
None => { None => {
@ -1543,6 +1554,8 @@ impl<O: OutputStream> Compiler<O> {
self.set_source_location(expression.location); self.set_source_location(expression.location);
use ast::ExpressionType::*; use ast::ExpressionType::*;
#[allow(unused_imports)] // not unused, overrides ast::ExpressionType::None
use Option::None;
match &expression.node { match &expression.node {
Call { Call {
function, function,
@ -1637,13 +1650,25 @@ impl<O: OutputStream> Compiler<O> {
self.mark_generator(); self.mark_generator();
match value { match value {
Some(expression) => self.compile_expression(expression)?, Some(expression) => self.compile_expression(expression)?,
Option::None => self.emit(Instruction::LoadConst { None => self.emit(Instruction::LoadConst {
value: bytecode::Constant::None, value: bytecode::Constant::None,
}), }),
}; };
self.emit(Instruction::YieldValue); self.emit(Instruction::YieldValue);
} }
Await { value } => { Await { value } => {
if self.ctx.func != FunctionContext::AsyncFunction {
<<<<<<< Updated upstream
return Err(CompileError {
statement: None,
error: CompileErrorType::InvalidAwait,
location: self.current_source_location.clone(),
source_path: None,
});
=======
return Err(self.error(CompileErrorType::InvalidAwait));
>>>>>>> Stashed changes
}
self.compile_expression(value)?; self.compile_expression(value)?;
self.emit(Instruction::GetAwaitable); self.emit(Instruction::GetAwaitable);
self.emit(Instruction::LoadConst { self.emit(Instruction::LoadConst {
@ -1652,6 +1677,32 @@ impl<O: OutputStream> Compiler<O> {
self.emit(Instruction::YieldFrom); self.emit(Instruction::YieldFrom);
} }
YieldFrom { value } => { YieldFrom { value } => {
match self.ctx.func {
FunctionContext::NoFunction => {
<<<<<<< Updated upstream
return Err(CompileError {
statement: None,
error: CompileErrorType::InvalidYieldFrom,
location: self.current_source_location.clone(),
source_path: None,
})
}
FunctionContext::AsyncFunction => {
return Err(CompileError {
statement: None,
error: CompileErrorType::AsyncYieldFrom,
location: self.current_source_location.clone(),
source_path: None,
})
=======
return Err(self.error(CompileErrorType::InvalidYieldFrom))
}
FunctionContext::AsyncFunction => {
return Err(self.error(CompileErrorType::AsyncYieldFrom))
>>>>>>> Stashed changes
}
FunctionContext::Function => {}
}
self.mark_generator(); self.mark_generator();
self.compile_expression(value)?; self.compile_expression(value)?;
self.emit(Instruction::GetIter); self.emit(Instruction::GetIter);
@ -1670,7 +1721,7 @@ impl<O: OutputStream> Compiler<O> {
value: bytecode::Constant::Boolean { value: false }, value: bytecode::Constant::Boolean { value: false },
}); });
} }
None => { ast::ExpressionType::None => {
self.emit(Instruction::LoadConst { self.emit(Instruction::LoadConst {
value: bytecode::Constant::None, value: bytecode::Constant::None,
}); });

View file

@ -54,6 +54,9 @@ pub enum CompileErrorType {
InvalidContinue, InvalidContinue,
InvalidReturn, InvalidReturn,
InvalidYield, InvalidYield,
InvalidYieldFrom,
InvalidAwait,
AsyncYieldFrom,
} }
impl CompileError { impl CompileError {
@ -96,6 +99,9 @@ impl fmt::Display for CompileError {
CompileErrorType::InvalidContinue => "'continue' outside loop".to_owned(), CompileErrorType::InvalidContinue => "'continue' outside loop".to_owned(),
CompileErrorType::InvalidReturn => "'return' outside function".to_owned(), CompileErrorType::InvalidReturn => "'return' outside function".to_owned(),
CompileErrorType::InvalidYield => "'yield' outside function".to_owned(), CompileErrorType::InvalidYield => "'yield' outside function".to_owned(),
CompileErrorType::InvalidYieldFrom => "'yield from' outside function".to_owned(),
CompileErrorType::InvalidAwait => "'await' outside async function".to_owned(),
CompileErrorType::AsyncYieldFrom => "'yield from' inside async function".to_owned(),
}; };
if let Some(statement) = &self.statement { if let Some(statement) = &self.statement {