From b22698a6f14dc5e4e32745e3b960008f8cd5dfaf Mon Sep 17 00:00:00 2001 From: Windel Bouwman Date: Wed, 7 Aug 2019 15:31:24 +0200 Subject: [PATCH 1/3] Add variable annotation syntax. Simplify grammar for comprehensions. Add capital J suffix for complex numbers. --- src/compile.rs | 14 ++++++++++++++ src/symboltable.rs | 11 +++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/compile.rs b/src/compile.rs index 3fa6bdb..8d5c4c4 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -553,6 +553,20 @@ impl Compiler { self.compile_op(op, true); self.compile_store(target)?; } + AnnAssign { + target, + annotation, + value, + } => { + // Throw away annotation: + self.compile_expression(annotation)?; + self.emit(Instruction::Pop); + + if let Some(value) = value { + self.compile_expression(value)?; + self.compile_store(target)?; + } + } Delete { targets } => { for target in targets { self.compile_delete(target)?; diff --git a/src/symboltable.rs b/src/symboltable.rs index b12e0f9..c1db24b 100644 --- a/src/symboltable.rs +++ b/src/symboltable.rs @@ -335,6 +335,17 @@ impl SymbolTableBuilder { self.scan_expression(target)?; self.scan_expression(value)?; } + AnnAssign { + target, + annotation, + value, + } => { + self.scan_expression(target)?; + self.scan_expression(annotation)?; + if let Some(value) = value { + self.scan_expression(value)?; + } + } With { items, body, .. } => { for item in items { self.scan_expression(&item.context_expr)?; From b6dd92daf61eac069ebfe68ae5c7cb8d9e4b727e Mon Sep 17 00:00:00 2001 From: Windel Bouwman Date: Wed, 7 Aug 2019 16:13:12 +0200 Subject: [PATCH 2/3] Properly fill the __annotations__ dictionary. --- src/compile.rs | 108 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 71 insertions(+), 37 deletions(-) diff --git a/src/compile.rs b/src/compile.rs index 8d5c4c4..f7ac924 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -358,33 +358,7 @@ impl Compiler { } self.set_label(end_label); } - While { test, body, orelse } => { - let start_label = self.new_label(); - let else_label = self.new_label(); - let end_label = self.new_label(); - self.emit(Instruction::SetupLoop { - start: start_label, - end: end_label, - }); - - self.set_label(start_label); - - self.compile_test(test, None, Some(else_label), EvalContext::Statement)?; - - 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 { - target: start_label, - }); - self.set_label(else_label); - self.emit(Instruction::PopBlock); - if let Some(orelse) = orelse { - self.compile_statements(orelse)?; - } - self.set_label(end_label); - } + While { test, body, orelse } => self.compile_while(test, body, orelse)?, With { is_async, items, @@ -557,16 +531,7 @@ impl Compiler { target, annotation, value, - } => { - // Throw away annotation: - self.compile_expression(annotation)?; - self.emit(Instruction::Pop); - - if let Some(value) = value { - self.compile_expression(value)?; - self.compile_store(target)?; - } - } + } => self.compile_annotated_assign(target, annotation, value)?, Delete { targets } => { for target in targets { self.compile_delete(target)?; @@ -1015,6 +980,40 @@ impl Compiler { } } + fn compile_while( + &mut self, + test: &ast::Expression, + body: &[ast::Statement], + orelse: &Option>, + ) -> Result<(), CompileError> { + let start_label = self.new_label(); + let else_label = self.new_label(); + let end_label = self.new_label(); + self.emit(Instruction::SetupLoop { + start: start_label, + end: end_label, + }); + + self.set_label(start_label); + + self.compile_test(test, None, Some(else_label), EvalContext::Statement)?; + + 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 { + target: start_label, + }); + self.set_label(else_label); + self.emit(Instruction::PopBlock); + if let Some(orelse) = orelse { + self.compile_statements(orelse)?; + } + self.set_label(end_label); + Ok(()) + } + fn compile_for( &mut self, target: &ast::Expression, @@ -1133,6 +1132,39 @@ impl Compiler { Ok(()) } + fn compile_annotated_assign( + &mut self, + target: &ast::Expression, + annotation: &ast::Expression, + value: &Option, + ) -> Result<(), CompileError> { + if let Some(value) = value { + self.compile_expression(value)?; + self.compile_store(target)?; + } + + // Compile annotation: + self.compile_expression(annotation)?; + + if let ast::ExpressionType::Identifier { name } = &target.node { + // Store as dict entry in __annotations__ dict: + self.emit(Instruction::LoadName { + name: String::from("__annotations__"), + scope: bytecode::NameScope::Local, + }); + self.emit(Instruction::LoadConst { + value: bytecode::Constant::String { + value: name.to_string(), + }, + }); + self.emit(Instruction::StoreSubscript); + } else { + // Drop annotation if not assigned to simple identifier. + self.emit(Instruction::Pop); + } + Ok(()) + } + fn compile_store(&mut self, target: &ast::Expression) -> Result<(), CompileError> { match &target.node { ast::ExpressionType::Identifier { name } => { @@ -1276,6 +1308,8 @@ impl Compiler { fn compile_expression(&mut self, expression: &ast::Expression) -> Result<(), CompileError> { trace!("Compiling {:?}", expression); + self.set_source_location(&expression.location); + use ast::ExpressionType::*; match &expression.node { Call { From 69b709e2b147679d24d1dde0f642a7c6ff5ca57d Mon Sep 17 00:00:00 2001 From: Windel Bouwman Date: Wed, 7 Aug 2019 20:11:27 +0200 Subject: [PATCH 3/3] Add parser support for async for loop. Add yield expression inside parentheses. --- src/compile.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/compile.rs b/src/compile.rs index f7ac924..c3870a3 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -1702,6 +1702,10 @@ impl Compiler { let mut loop_labels = vec![]; for generator in generators { + if generator.is_async { + unimplemented!("async for comprehensions"); + } + if loop_labels.is_empty() { // Load iterator onto stack (passed as first argument): self.emit(Instruction::LoadName {