diff --git a/src/compile.rs b/src/compile.rs index 034e0f9..f4d088c 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -39,7 +39,7 @@ struct CompileContext { func: FunctionContext, } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialEq)] enum FunctionContext { NoFunction, Function, @@ -562,6 +562,17 @@ impl Compiler { } match value { 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)?; } None => { @@ -1543,6 +1554,8 @@ impl Compiler { self.set_source_location(expression.location); use ast::ExpressionType::*; + #[allow(unused_imports)] // not unused, overrides ast::ExpressionType::None + use Option::None; match &expression.node { Call { function, @@ -1637,13 +1650,25 @@ impl Compiler { self.mark_generator(); match value { Some(expression) => self.compile_expression(expression)?, - Option::None => self.emit(Instruction::LoadConst { + None => self.emit(Instruction::LoadConst { value: bytecode::Constant::None, }), }; self.emit(Instruction::YieldValue); } 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.emit(Instruction::GetAwaitable); self.emit(Instruction::LoadConst { @@ -1652,6 +1677,32 @@ impl Compiler { self.emit(Instruction::YieldFrom); } 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.compile_expression(value)?; self.emit(Instruction::GetIter); @@ -1670,7 +1721,7 @@ impl Compiler { value: bytecode::Constant::Boolean { value: false }, }); } - None => { + ast::ExpressionType::None => { self.emit(Instruction::LoadConst { value: bytecode::Constant::None, }); diff --git a/src/error.rs b/src/error.rs index 836e479..2c82501 100644 --- a/src/error.rs +++ b/src/error.rs @@ -54,6 +54,9 @@ pub enum CompileErrorType { InvalidContinue, InvalidReturn, InvalidYield, + InvalidYieldFrom, + InvalidAwait, + AsyncYieldFrom, } impl CompileError { @@ -96,6 +99,9 @@ impl fmt::Display for CompileError { CompileErrorType::InvalidContinue => "'continue' outside loop".to_owned(), CompileErrorType::InvalidReturn => "'return' 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 {