From 1afa68a66e9293370c96721919bc5cb9a5977c7d Mon Sep 17 00:00:00 2001 From: Pranav Gaddamadugu <23022326+d0cd@users.noreply.github.com> Date: Wed, 22 Nov 2023 17:33:42 -0800 Subject: [PATCH 1/5] Remove is_main --- compiler/ast/src/functions/mod.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/compiler/ast/src/functions/mod.rs b/compiler/ast/src/functions/mod.rs index e305838a9f..a122ac480f 100644 --- a/compiler/ast/src/functions/mod.rs +++ b/compiler/ast/src/functions/mod.rs @@ -39,7 +39,7 @@ pub mod mode; pub use mode::*; use crate::{Block, Identifier, Node, NodeID, TupleType, Type}; -use leo_span::{sym, Span, Symbol}; +use leo_span::{Span, Symbol}; use serde::{Deserialize, Serialize}; use std::fmt; @@ -111,11 +111,6 @@ impl Function { self.identifier.name } - /// Returns `true` if the function name is `main`. - pub fn is_main(&self) -> bool { - self.name() == sym::main - } - /// /// Private formatting method used for optimizing [fmt::Debug] and [fmt::Display] implementations. /// From afc953cd0bb745999bac7aef1e77bc94236c261b Mon Sep 17 00:00:00 2001 From: Pranav Gaddamadugu <23022326+d0cd@users.noreply.github.com> Date: Wed, 22 Nov 2023 17:34:20 -0800 Subject: [PATCH 2/5] Clippy + fmt --- compiler/ast/src/common/imported_modules.rs | 19 +- compiler/ast/src/passes/reconstructor.rs | 9 +- compiler/compiler/src/compiler.rs | 9 +- compiler/compiler/tests/compile.rs | 6 +- compiler/compiler/tests/execute.rs | 20 +- compiler/parser/src/parser/expression.rs | 61 +++-- compiler/parser/src/parser/file.rs | 92 ++++---- compiler/parser/src/parser/statement.rs | 84 ++++--- .../src/code_generation/visit_expressions.rs | 18 +- .../src/code_generation/visit_statements.rs | 140 ++++++------ .../common/symbol_table/function_symbol.rs | 7 +- .../eliminate_statement.rs | 30 +-- .../destructuring/destructure_statement.rs | 49 ++-- .../src/flattening/flatten_statement.rs | 51 ++--- compiler/passes/src/flattening/flattener.rs | 212 +++++++++--------- .../passes/src/loop_unrolling/unroller.rs | 71 +++--- .../rename_expression.rs | 35 ++- .../rename_statement.rs | 41 ++-- .../src/type_checking/check_expressions.rs | 15 +- .../passes/src/type_checking/check_program.rs | 25 ++- .../src/type_checking/check_statements.rs | 45 ++-- compiler/passes/src/type_checking/checker.rs | 15 +- compiler/span/src/source_map.rs | 18 +- docs/grammar/src/main.rs | 9 +- leo/cli/commands/execute.rs | 15 +- leo/cli/commands/run.rs | 15 +- leo/package/src/inputs/input.rs | 4 +- tests/test-framework/src/runner.rs | 22 +- 28 files changed, 564 insertions(+), 573 deletions(-) diff --git a/compiler/ast/src/common/imported_modules.rs b/compiler/ast/src/common/imported_modules.rs index 16fc81547e..8dab723cf1 100644 --- a/compiler/ast/src/common/imported_modules.rs +++ b/compiler/ast/src/common/imported_modules.rs @@ -26,15 +26,16 @@ pub fn serialize( imported_modules: &IndexMap, Program>, serializer: S, ) -> Result { - let joined: IndexMap = with_session_globals(|s| { - imported_modules - .into_iter() - .map(|(package, program)| { - let package = package.iter().map(|x| x.as_str(s, |s| s.to_owned())).collect::>(); - (package.join("."), program.clone()) - }) - .collect() - }); + let joined: IndexMap = + with_session_globals(|s| { + imported_modules + .into_iter() + .map(|(package, program)| { + let package = package.iter().map(|x| x.as_str(s, |s| s.to_owned())).collect::>(); + (package.join("."), program.clone()) + }) + .collect() + }); joined.serialize(serializer) } diff --git a/compiler/ast/src/passes/reconstructor.rs b/compiler/ast/src/passes/reconstructor.rs index 793df279b9..86ce52192b 100644 --- a/compiler/ast/src/passes/reconstructor.rs +++ b/compiler/ast/src/passes/reconstructor.rs @@ -66,12 +66,9 @@ pub trait ExpressionReconstructor { fn reconstruct_associated_constant(&mut self, input: AssociatedConstant) -> (Expression, Self::AdditionalOutput) { ( - Expression::Access(AccessExpression::AssociatedConstant(AssociatedConstant { - ty: input.ty, - name: input.name, - span: input.span, - id: input.id, - })), + Expression::Access(AccessExpression::AssociatedConstant( + AssociatedConstant { ty: input.ty, name: input.name, span: input.span, id: input.id } + )), Default::default(), ) } diff --git a/compiler/compiler/src/compiler.rs b/compiler/compiler/src/compiler.rs index 02e9d287a0..d185741a7d 100644 --- a/compiler/compiler/src/compiler.rs +++ b/compiler/compiler/src/compiler.rs @@ -244,12 +244,9 @@ impl<'a> Compiler<'a> { /// Runs the destructuring pass. pub fn destructuring_pass(&mut self) -> Result<()> { - self.ast = Destructurer::do_pass(( - std::mem::take(&mut self.ast), - &self.type_table, - &self.node_builder, - &self.assigner, - ))?; + self.ast = Destructurer::do_pass( + (std::mem::take(&mut self.ast), &self.type_table, &self.node_builder, &self.assigner) + )?; if self.compiler_options.output.destructured_ast { self.write_ast_to_json("destructured_ast.json")?; diff --git a/compiler/compiler/tests/compile.rs b/compiler/compiler/tests/compile.rs index 6f9c573e24..f96c0cb5e6 100644 --- a/compiler/compiler/tests/compile.rs +++ b/compiler/compiler/tests/compile.rs @@ -51,9 +51,9 @@ impl Namespace for CompileNamespace { fn run_test(&self, test: Test) -> Result { let buf = BufferEmitter(Rc::default(), Rc::default()); let handler = Handler::new(Box::new(buf.clone())); - create_session_if_not_set_then(|_| { - run_test(test, &handler, &buf).map_err(|()| buf.0.take().to_string() + &buf.1.take().to_string()) - }) + create_session_if_not_set_then( + |_| run_test(test, &handler, &buf).map_err(|()| buf.0.take().to_string() + &buf.1.take().to_string()) + ) } } diff --git a/compiler/compiler/tests/execute.rs b/compiler/compiler/tests/execute.rs index b5d2d30ce1..5785d18716 100644 --- a/compiler/compiler/tests/execute.rs +++ b/compiler/compiler/tests/execute.rs @@ -58,9 +58,9 @@ impl Namespace for ExecuteNamespace { fn run_test(&self, test: Test) -> Result { let buf = BufferEmitter(Rc::default(), Rc::default()); let handler = Handler::new(Box::new(buf.clone())); - create_session_if_not_set_then(|_| { - run_test(test, &handler, &buf).map_err(|()| buf.0.take().to_string() + &buf.1.take().to_string()) - }) + create_session_if_not_set_then( + |_| run_test(test, &handler, &buf).map_err(|()| buf.0.take().to_string() + &buf.1.take().to_string()) + ) } } @@ -125,13 +125,13 @@ fn run_test(test: Test, handler: &Handler, err_buf: &BufferEmitter) -> Result { if self.eat(&Token::As) { let (type_, end_span) = self.parse_primitive_type()?; let span = expr.span() + end_span; - expr = Expression::Cast(CastExpression { - expression: Box::new(expr), - type_, - span, - id: self.node_builder.next_id(), - }); + expr = Expression::Cast( + CastExpression { expression: Box::new(expr), type_, span, id: self.node_builder.next_id() } + ); } Ok(expr) @@ -328,12 +325,9 @@ impl ParserContext<'_> { if let (true, Some(op)) = (args.is_empty(), UnaryOperation::from_symbol(method.name)) { // Found an unary operator and the argument list is empty. - Ok(Expression::Unary(UnaryExpression { - span, - op, - receiver: Box::new(receiver), - id: self.node_builder.next_id(), - })) + Ok(Expression::Unary( + UnaryExpression { span, op, receiver: Box::new(receiver), id: self.node_builder.next_id() } + )) } else if let (1, Some(op)) = (args.len(), BinaryOperation::from_symbol(method.name)) { // Found a binary operator and the argument list contains a single argument. Ok(Expression::Binary(BinaryExpression { @@ -443,12 +437,10 @@ impl ParserContext<'_> { if self.check_int() { // Eat a tuple member access. let (index, span) = self.eat_whole_number()?; - expr = Expression::Access(AccessExpression::Tuple(TupleAccess { - tuple: Box::new(expr), - index, - span, - id: self.node_builder.next_id(), - })) + expr = + Expression::Access(AccessExpression::Tuple( + TupleAccess { tuple: Box::new(expr), index, span, id: self.node_builder.next_id() } + )) } else if self.eat(&Token::Leo) { // Eat an external function call. self.eat(&Token::Div); // todo: Make `/` a more general token. @@ -627,14 +619,15 @@ impl ParserContext<'_> { self.expect_identifier()? }; - let (expression, span) = if self.eat(&Token::Colon) { - // Parse individual struct variable declarations. - let expression = self.parse_expression()?; - let span = identifier.span + expression.span(); - (Some(expression), span) - } else { - (None, identifier.span) - }; + let (expression, span) = + if self.eat(&Token::Colon) { + // Parse individual struct variable declarations. + let expression = self.parse_expression()?; + let span = identifier.span + expression.span(); + (Some(expression), span) + } else { + (None, identifier.span) + }; Ok(StructVariableInitializer { identifier, expression, id: self.node_builder.next_id(), span }) } @@ -685,11 +678,9 @@ impl ParserContext<'_> { // Literal followed by `group`, e.g., `42group`. Some(Token::Group) => { assert_no_whitespace("group")?; - Expression::Literal(Literal::Group(Box::new(GroupLiteral::Single( - value, - full_span, - self.node_builder.next_id(), - )))) + Expression::Literal(Literal::Group(Box::new( + GroupLiteral::Single(value, full_span, self.node_builder.next_id()) + ))) } // Literal followed by `scalar` e.g., `42scalar`. Some(Token::Scalar) => { @@ -732,11 +723,9 @@ impl ParserContext<'_> { Token::Block => { Expression::Identifier(Identifier { name: sym::block, span, id: self.node_builder.next_id() }) } - t if crate::type_::TYPE_TOKENS.contains(&t) => Expression::Identifier(Identifier { - name: t.keyword_to_symbol().unwrap(), - span, - id: self.node_builder.next_id(), - }), + t if crate::type_::TYPE_TOKENS.contains(&t) => Expression::Identifier( + Identifier { name: t.keyword_to_symbol().unwrap(), span, id: self.node_builder.next_id() } + ), token => { return Err(ParserError::unexpected_str(token, "expression", span).into()); } diff --git a/compiler/parser/src/parser/file.rs b/compiler/parser/src/parser/file.rs index 5c3c9c31b8..b2a7aa3522 100644 --- a/compiler/parser/src/parser/file.rs +++ b/compiler/parser/src/parser/file.rs @@ -325,13 +325,9 @@ impl ParserContext<'_> { } else { let type_ = self.parse_type()?.0; - Ok(functions::Input::Internal(FunctionInput { - identifier: name, - mode, - type_, - span: name.span, - id: self.node_builder.next_id(), - })) + Ok(functions::Input::Internal( + FunctionInput { identifier: name, mode, type_, span: name.span, id: self.node_builder.next_id() } + )) } } @@ -420,56 +416,58 @@ impl ParserContext<'_> { let (inputs, ..) = self.parse_paren_comma_list(|p| p.parse_input().map(Some))?; // Parse return type. - let output = match self.eat(&Token::Arrow) { - false => vec![], - true => { - self.disallow_struct_construction = true; - let output = match self.peek_is_left_par() { - true => self.parse_paren_comma_list(|p| p.parse_output().map(Some))?.0, - false => vec![self.parse_output()?], - }; - self.disallow_struct_construction = false; - output - } - }; + let output = + match self.eat(&Token::Arrow) { + false => vec![], + true => { + self.disallow_struct_construction = true; + let output = match self.peek_is_left_par() { + true => self.parse_paren_comma_list(|p| p.parse_output().map(Some))?.0, + false => vec![self.parse_output()?], + }; + self.disallow_struct_construction = false; + output + } + }; // Parse the function body. let block = self.parse_block()?; // Parse the `finalize` block if it exists. - let finalize = match self.eat(&Token::Finalize) { - false => None, - true => { - // Get starting span. - let start = self.prev_token.span; + let finalize = + match self.eat(&Token::Finalize) { + false => None, + true => { + // Get starting span. + let start = self.prev_token.span; - // Parse the identifier. - let identifier = self.expect_identifier()?; + // Parse the identifier. + let identifier = self.expect_identifier()?; - // Parse parameters. - let (input, ..) = self.parse_paren_comma_list(|p| p.parse_input().map(Some))?; + // Parse parameters. + let (input, ..) = self.parse_paren_comma_list(|p| p.parse_input().map(Some))?; - // Parse return type. - let output = match self.eat(&Token::Arrow) { - false => vec![], - true => { - self.disallow_struct_construction = true; - let output = match self.peek_is_left_par() { - true => self.parse_paren_comma_list(|p| p.parse_output().map(Some))?.0, - false => vec![self.parse_output()?], - }; - self.disallow_struct_construction = false; - output - } - }; + // Parse return type. + let output = match self.eat(&Token::Arrow) { + false => vec![], + true => { + self.disallow_struct_construction = true; + let output = match self.peek_is_left_par() { + true => self.parse_paren_comma_list(|p| p.parse_output().map(Some))?.0, + false => vec![self.parse_output()?], + }; + self.disallow_struct_construction = false; + output + } + }; - // Parse the finalize body. - let block = self.parse_block()?; - let span = start + block.span; + // Parse the finalize body. + let block = self.parse_block()?; + let span = start + block.span; - Some(Finalize::new(identifier, input, output, block, span, self.node_builder.next_id())) - } - }; + Some(Finalize::new(identifier, input, output, block, span, self.node_builder.next_id())) + } + }; let span = start + block.span; Ok(( diff --git a/compiler/parser/src/parser/statement.rs b/compiler/parser/src/parser/statement.rs index c79d75c14d..ae8e61d852 100644 --- a/compiler/parser/src/parser/statement.rs +++ b/compiler/parser/src/parser/statement.rs @@ -158,11 +158,9 @@ impl ParserContext<'_> { // Parse the expression as a statement. let end = self.expect(&Token::Semicolon)?; - Ok(Statement::Expression(ExpressionStatement { - span: place.span() + end, - expression: place, - id: self.node_builder.next_id(), - })) + Ok(Statement::Expression( + ExpressionStatement { span: place.span() + end, expression: place, id: self.node_builder.next_id() } + )) } } @@ -271,45 +269,43 @@ impl ParserContext<'_> { let keyword = self.expect(&Token::Console)?; self.expect(&Token::Dot)?; let identifier = self.expect_identifier()?; - let (span, function) = match identifier.name { - sym::assert => { - self.expect(&Token::LeftParen)?; - let expr = self.parse_expression()?; - self.expect(&Token::RightParen)?; - (keyword + expr.span(), ConsoleFunction::Assert(expr)) - } - sym::assert_eq => { - self.expect(&Token::LeftParen)?; - let left = self.parse_expression()?; - self.expect(&Token::Comma)?; - let right = self.parse_expression()?; - self.expect(&Token::RightParen)?; - (left.span() + right.span(), ConsoleFunction::AssertEq(left, right)) - } - sym::assert_neq => { - self.expect(&Token::LeftParen)?; - let left = self.parse_expression()?; - self.expect(&Token::Comma)?; - let right = self.parse_expression()?; - self.expect(&Token::RightParen)?; - (left.span() + right.span(), ConsoleFunction::AssertNeq(left, right)) - } - symbol => { - // Not sure what it is, assume it's `log`. - self.emit_err(ParserError::unexpected_ident( - symbol, - &["assert", "assert_eq", "assert_neq"], - identifier.span, - )); - ( - Default::default(), - ConsoleFunction::Assert(Expression::Err(ErrExpression { - span: Default::default(), - id: self.node_builder.next_id(), - })), - ) - } - }; + let (span, function) = + match identifier.name { + sym::assert => { + self.expect(&Token::LeftParen)?; + let expr = self.parse_expression()?; + self.expect(&Token::RightParen)?; + (keyword + expr.span(), ConsoleFunction::Assert(expr)) + } + sym::assert_eq => { + self.expect(&Token::LeftParen)?; + let left = self.parse_expression()?; + self.expect(&Token::Comma)?; + let right = self.parse_expression()?; + self.expect(&Token::RightParen)?; + (left.span() + right.span(), ConsoleFunction::AssertEq(left, right)) + } + sym::assert_neq => { + self.expect(&Token::LeftParen)?; + let left = self.parse_expression()?; + self.expect(&Token::Comma)?; + let right = self.parse_expression()?; + self.expect(&Token::RightParen)?; + (left.span() + right.span(), ConsoleFunction::AssertNeq(left, right)) + } + symbol => { + // Not sure what it is, assume it's `log`. + self.emit_err( + ParserError::unexpected_ident(symbol, &["assert", "assert_eq", "assert_neq"], identifier.span) + ); + ( + Default::default(), + ConsoleFunction::Assert(Expression::Err( + ErrExpression { span: Default::default(), id: self.node_builder.next_id() } + )), + ) + } + }; self.expect(&Token::Semicolon)?; Ok(ConsoleStatement { span: keyword + span, function, id: self.node_builder.next_id() }) diff --git a/compiler/passes/src/code_generation/visit_expressions.rs b/compiler/passes/src/code_generation/visit_expressions.rs index bccd21f1d3..922d6ef5f5 100644 --- a/compiler/passes/src/code_generation/visit_expressions.rs +++ b/compiler/passes/src/code_generation/visit_expressions.rs @@ -572,16 +572,18 @@ impl<'a> CodeGenerator<'a> { let return_type = &self.symbol_table.lookup_fn_symbol(function_name).unwrap().output_type; match return_type { Type::Unit => {} // Do nothing - Type::Tuple(tuple) => match tuple.length() { - 0 | 1 => unreachable!("Parsing guarantees that a tuple type has at least two elements"), - len => { - for _ in 0..len { - let destination_register = format!("r{}", self.next_register); - destinations.push(destination_register); - self.next_register += 1; + Type::Tuple(tuple) => { + match tuple.length() { + 0 | 1 => unreachable!("Parsing guarantees that a tuple type has at least two elements"), + len => { + for _ in 0..len { + let destination_register = format!("r{}", self.next_register); + destinations.push(destination_register); + self.next_register += 1; + } } } - }, + } _ => { let destination_register = format!("r{}", self.next_register); destinations.push(destination_register); diff --git a/compiler/passes/src/code_generation/visit_statements.rs b/compiler/passes/src/code_generation/visit_statements.rs index 8aa446dfe3..a304f1ffe3 100644 --- a/compiler/passes/src/code_generation/visit_statements.rs +++ b/compiler/passes/src/code_generation/visit_statements.rs @@ -55,18 +55,19 @@ impl<'a> CodeGenerator<'a> { } fn visit_assert(&mut self, input: &'a AssertStatement) -> String { - let mut generate_assert_instruction = |name: &str, left: &'a Expression, right: &'a Expression| { - let (left_operand, left_instructions) = self.visit_expression(left); - let (right_operand, right_instructions) = self.visit_expression(right); - let assert_instruction = format!(" {name} {left_operand} {right_operand};\n"); + let mut generate_assert_instruction = + |name: &str, left: &'a Expression, right: &'a Expression| { + let (left_operand, left_instructions) = self.visit_expression(left); + let (right_operand, right_instructions) = self.visit_expression(right); + let assert_instruction = format!(" {name} {left_operand} {right_operand};\n"); - // Concatenate the instructions. - let mut instructions = left_instructions; - instructions.push_str(&right_instructions); - instructions.push_str(&assert_instruction); + // Concatenate the instructions. + let mut instructions = left_instructions; + instructions.push_str(&right_instructions); + instructions.push_str(&assert_instruction); - instructions - }; + instructions + }; match &input.variant { AssertVariant::Assert(expr) => { let (operand, mut instructions) = self.visit_expression(expr); @@ -81,68 +82,69 @@ impl<'a> CodeGenerator<'a> { } fn visit_return(&mut self, input: &'a ReturnStatement) -> String { - let mut outputs = match input.expression { - // Skip empty return statements. - Expression::Unit(_) => String::new(), - _ => { - let (operand, mut expression_instructions) = self.visit_expression(&input.expression); - // Get the output type of the function. - let output = if self.in_finalize { - // Note that the first unwrap is safe, since `current_function` is set in `visit_function`. - self.current_function.unwrap().finalize.as_ref().unwrap().output.iter() - } else { - // Note that this unwrap is safe, since `current_function` is set in `visit_function`. - self.current_function.unwrap().output.iter() - }; - // If the operand string is empty, initialize an empty vector. - let operand_strings = match operand.is_empty() { - true => vec![], - false => operand.split(' ').collect_vec(), - }; - let instructions = operand_strings - .iter() - .zip_eq(output) - .map(|(operand, output)| { - match output { - Output::Internal(output) => { - let visibility = if self.is_transition_function { - match self.in_finalize { - // If in finalize block, the default visibility is public. - true => match output.mode { - Mode::None => Mode::Public, - mode => mode, - }, - // If not in finalize block, the default visibility is private. - false => match output.mode { - Mode::None => Mode::Private, - mode => mode, - }, - } - } else { - // Only program functions have visibilities associated with their outputs. - Mode::None - }; - format!( - " output {} as {};\n", - operand, - self.visit_type_with_visibility(&output.type_, visibility) - ) + let mut outputs = + match input.expression { + // Skip empty return statements. + Expression::Unit(_) => String::new(), + _ => { + let (operand, mut expression_instructions) = self.visit_expression(&input.expression); + // Get the output type of the function. + let output = if self.in_finalize { + // Note that the first unwrap is safe, since `current_function` is set in `visit_function`. + self.current_function.unwrap().finalize.as_ref().unwrap().output.iter() + } else { + // Note that this unwrap is safe, since `current_function` is set in `visit_function`. + self.current_function.unwrap().output.iter() + }; + // If the operand string is empty, initialize an empty vector. + let operand_strings = match operand.is_empty() { + true => vec![], + false => operand.split(' ').collect_vec(), + }; + let instructions = operand_strings + .iter() + .zip_eq(output) + .map(|(operand, output)| { + match output { + Output::Internal(output) => { + let visibility = if self.is_transition_function { + match self.in_finalize { + // If in finalize block, the default visibility is public. + true => match output.mode { + Mode::None => Mode::Public, + mode => mode, + }, + // If not in finalize block, the default visibility is private. + false => match output.mode { + Mode::None => Mode::Private, + mode => mode, + }, + } + } else { + // Only program functions have visibilities associated with their outputs. + Mode::None + }; + format!( + " output {} as {};\n", + operand, + self.visit_type_with_visibility(&output.type_, visibility) + ) + } + Output::External(output) => { + format!( + " output {} as {}.aleo/{}.record;\n", + operand, output.program_name, output.record, + ) + } } - Output::External(output) => { - format!( - " output {} as {}.aleo/{}.record;\n", - operand, output.program_name, output.record, - ) - } - } - }) - .join(""); + }) + .join(""); - expression_instructions.push_str(&instructions); + expression_instructions.push_str(&instructions); - expression_instructions - } - }; + expression_instructions + } + }; // Initialize storage for the instructions. let mut instructions = String::new(); diff --git a/compiler/passes/src/common/symbol_table/function_symbol.rs b/compiler/passes/src/common/symbol_table/function_symbol.rs index 1d3c7307f7..f52906f5c4 100644 --- a/compiler/passes/src/common/symbol_table/function_symbol.rs +++ b/compiler/passes/src/common/symbol_table/function_symbol.rs @@ -55,10 +55,9 @@ impl SymbolTable { variant: func.variant, _span: func.span, input: func.input.clone(), - finalize: func.finalize.as_ref().map(|finalize| FinalizeData { - input: finalize.input.clone(), - output_type: finalize.output_type.clone(), - }), + finalize: func.finalize.as_ref().map( + |finalize| FinalizeData { input: finalize.input.clone(), output_type: finalize.output_type.clone() } + ), } } } diff --git a/compiler/passes/src/dead_code_elimination/eliminate_statement.rs b/compiler/passes/src/dead_code_elimination/eliminate_statement.rs index 4eeaf0d244..063bf9c58f 100644 --- a/compiler/passes/src/dead_code_elimination/eliminate_statement.rs +++ b/compiler/passes/src/dead_code_elimination/eliminate_statement.rs @@ -87,12 +87,13 @@ impl StatementReconstructor for DeadCodeEliminator<'_> { self.is_necessary = true; // Visit the statement. - let statement = Statement::Assign(Box::new(AssignStatement { - place: input.place, - value: self.reconstruct_expression(input.value).0, - span: input.span, - id: input.id, - })); + let statement = + Statement::Assign(Box::new(AssignStatement { + place: input.place, + value: self.reconstruct_expression(input.value).0, + span: input.span, + id: input.id, + })); // Unset the `is_necessary` flag. self.is_necessary = false; @@ -181,14 +182,15 @@ impl StatementReconstructor for DeadCodeEliminator<'_> { self.is_necessary = true; // Visit the statement. - let statement = Statement::Return(ReturnStatement { - expression: self.reconstruct_expression(input.expression).0, - finalize_arguments: input.finalize_arguments.map(|arguments| { - arguments.into_iter().map(|argument| self.reconstruct_expression(argument).0).collect() - }), - span: input.span, - id: input.id, - }); + let statement = + Statement::Return(ReturnStatement { + expression: self.reconstruct_expression(input.expression).0, + finalize_arguments: input.finalize_arguments.map(|arguments| { + arguments.into_iter().map(|argument| self.reconstruct_expression(argument).0).collect() + }), + span: input.span, + id: input.id, + }); // Unset the `is_necessary` flag. self.is_necessary = false; diff --git a/compiler/passes/src/destructuring/destructure_statement.rs b/compiler/passes/src/destructuring/destructure_statement.rs index 8d7189ce74..97e3654cef 100644 --- a/compiler/passes/src/destructuring/destructure_statement.rs +++ b/compiler/passes/src/destructuring/destructure_statement.rs @@ -137,29 +137,32 @@ impl StatementReconstructor for Destructurer<'_> { ), // If the lhs is a tuple and the rhs is a tuple, create a new assign statement for each tuple element. (Expression::Tuple(lhs_tuple), Expression::Tuple(rhs_tuple)) => { - let statements = lhs_tuple - .elements - .into_iter() - .zip_eq(rhs_tuple.elements) - .map(|(lhs, rhs)| { - // Get the type of the rhs. - let type_ = match self.type_table.get(&lhs.id()) { - Some(type_) => type_.clone(), - None => { - unreachable!("Type checking guarantees that the type of the lhs is in the type table.") - } - }; - // Set the type of the lhs. - self.type_table.insert(rhs.id(), type_); - // Return the assign statement. - Statement::Assign(Box::new(AssignStatement { - place: lhs, - value: rhs, - span: Default::default(), - id: self.node_builder.next_id(), - })) - }) - .collect(); + let statements = + lhs_tuple + .elements + .into_iter() + .zip_eq(rhs_tuple.elements) + .map(|(lhs, rhs)| { + // Get the type of the rhs. + let type_ = match self.type_table.get(&lhs.id()) { + Some(type_) => type_.clone(), + None => { + unreachable!( + "Type checking guarantees that the type of the lhs is in the type table." + ) + } + }; + // Set the type of the lhs. + self.type_table.insert(rhs.id(), type_); + // Return the assign statement. + Statement::Assign(Box::new(AssignStatement { + place: lhs, + value: rhs, + span: Default::default(), + id: self.node_builder.next_id(), + })) + }) + .collect(); (Statement::dummy(Default::default(), self.node_builder.next_id()), statements) } // If the lhs is a tuple and the rhs is an identifier that is a tuple, create a new assign statement for each tuple element. diff --git a/compiler/passes/src/flattening/flatten_statement.rs b/compiler/passes/src/flattening/flatten_statement.rs index 9a47421112..b991b4ada2 100644 --- a/compiler/passes/src/flattening/flatten_statement.rs +++ b/compiler/passes/src/flattening/flatten_statement.rs @@ -62,31 +62,32 @@ impl StatementReconstructor for Flattener<'_> { let mut statements = Vec::new(); // Flatten the arguments of the assert statement. - let assert = AssertStatement { - span: input.span, - id: input.id, - variant: match input.variant { - AssertVariant::Assert(expression) => { - let (expression, additional_statements) = self.reconstruct_expression(expression); - statements.extend(additional_statements); - AssertVariant::Assert(expression) - } - AssertVariant::AssertEq(left, right) => { - let (left, additional_statements) = self.reconstruct_expression(left); - statements.extend(additional_statements); - let (right, additional_statements) = self.reconstruct_expression(right); - statements.extend(additional_statements); - AssertVariant::AssertEq(left, right) - } - AssertVariant::AssertNeq(left, right) => { - let (left, additional_statements) = self.reconstruct_expression(left); - statements.extend(additional_statements); - let (right, additional_statements) = self.reconstruct_expression(right); - statements.extend(additional_statements); - AssertVariant::AssertNeq(left, right) - } - }, - }; + let assert = + AssertStatement { + span: input.span, + id: input.id, + variant: match input.variant { + AssertVariant::Assert(expression) => { + let (expression, additional_statements) = self.reconstruct_expression(expression); + statements.extend(additional_statements); + AssertVariant::Assert(expression) + } + AssertVariant::AssertEq(left, right) => { + let (left, additional_statements) = self.reconstruct_expression(left); + statements.extend(additional_statements); + let (right, additional_statements) = self.reconstruct_expression(right); + statements.extend(additional_statements); + AssertVariant::AssertEq(left, right) + } + AssertVariant::AssertNeq(left, right) => { + let (left, additional_statements) = self.reconstruct_expression(left); + statements.extend(additional_statements); + let (right, additional_statements) = self.reconstruct_expression(right); + statements.extend(additional_statements); + AssertVariant::AssertNeq(left, right) + } + }, + }; // Add the appropriate guards. match self.construct_guard() { diff --git a/compiler/passes/src/flattening/flattener.rs b/compiler/passes/src/flattening/flattener.rs index 1cf6ae2193..9b210d56e2 100644 --- a/compiler/passes/src/flattening/flattener.rs +++ b/compiler/passes/src/flattening/flattener.rs @@ -392,68 +392,71 @@ impl<'a> Flattener<'a> { // Initialize a vector to accumulate any statements generated. let mut statements = Vec::new(); // For each struct member, construct a new ternary expression. - let members = struct_ - .members - .iter() - .map(|Member { identifier, type_, .. }| { - // Create an assignment statement for the first access expression. - let (first, stmt) = - self.unique_simple_assign_statement(Expression::Access(AccessExpression::Member(MemberAccess { - inner: Box::new(Expression::Identifier(*first)), - name: *identifier, + let members = + struct_ + .members + .iter() + .map(|Member { identifier, type_, .. }| { + // Create an assignment statement for the first access expression. + let (first, stmt) = self.unique_simple_assign_statement(Expression::Access( + AccessExpression::Member(MemberAccess { + inner: Box::new(Expression::Identifier(*first)), + name: *identifier, + span: Default::default(), + id: { + // Create a new node ID for the access expression. + let id = self.node_builder.next_id(); + // Set the type of the node ID. + self.type_table.insert(id, type_.clone()); + id + }, + }), + )); + statements.push(stmt); + // Create an assignment statement for the second access expression. + let (second, stmt) = self.unique_simple_assign_statement(Expression::Access( + AccessExpression::Member(MemberAccess { + inner: Box::new(Expression::Identifier(*second)), + name: *identifier, + span: Default::default(), + id: { + // Create a new node ID for the access expression. + let id = self.node_builder.next_id(); + // Set the type of the node ID. + self.type_table.insert(id, type_.clone()); + id + }, + }), + )); + statements.push(stmt); + // Recursively reconstruct the ternary expression. + let (expression, stmts) = self.reconstruct_ternary(TernaryExpression { + condition: Box::new(condition.clone()), + // Access the member of the first expression. + if_true: Box::new(Expression::Identifier(first)), + // Access the member of the second expression. + if_false: Box::new(Expression::Identifier(second)), span: Default::default(), id: { - // Create a new node ID for the access expression. + // Create a new node ID for the ternary expression. let id = self.node_builder.next_id(); // Set the type of the node ID. self.type_table.insert(id, type_.clone()); id }, - }))); - statements.push(stmt); - // Create an assignment statement for the second access expression. - let (second, stmt) = - self.unique_simple_assign_statement(Expression::Access(AccessExpression::Member(MemberAccess { - inner: Box::new(Expression::Identifier(*second)), - name: *identifier, + }); + + // Accumulate any statements generated. + statements.extend(stmts); + + StructVariableInitializer { + identifier: *identifier, + expression: Some(expression), span: Default::default(), - id: { - // Create a new node ID for the access expression. - let id = self.node_builder.next_id(); - // Set the type of the node ID. - self.type_table.insert(id, type_.clone()); - id - }, - }))); - statements.push(stmt); - // Recursively reconstruct the ternary expression. - let (expression, stmts) = self.reconstruct_ternary(TernaryExpression { - condition: Box::new(condition.clone()), - // Access the member of the first expression. - if_true: Box::new(Expression::Identifier(first)), - // Access the member of the second expression. - if_false: Box::new(Expression::Identifier(second)), - span: Default::default(), - id: { - // Create a new node ID for the ternary expression. - let id = self.node_builder.next_id(); - // Set the type of the node ID. - self.type_table.insert(id, type_.clone()); - id - }, - }); - - // Accumulate any statements generated. - statements.extend(stmts); - - StructVariableInitializer { - identifier: *identifier, - expression: Some(expression), - span: Default::default(), - id: self.node_builder.next_id(), - } - }) - .collect(); + id: self.node_builder.next_id(), + } + }) + .collect(); let (expr, stmts) = self.reconstruct_struct_init(StructExpression { name: struct_.identifier, @@ -489,65 +492,66 @@ impl<'a> Flattener<'a> { // Initialize a vector to accumulate any statements generated. let mut statements = Vec::new(); // For each tuple element, construct a new ternary expression. - let elements = tuple_type - .elements() - .iter() - .enumerate() - .map(|(i, type_)| { - // Create an assignment statement for the first access expression. - let (first, stmt) = - self.unique_simple_assign_statement(Expression::Access(AccessExpression::Tuple(TupleAccess { - tuple: Box::new(Expression::Identifier(*first)), - index: NonNegativeNumber::from(i), + let elements = + tuple_type + .elements() + .iter() + .enumerate() + .map(|(i, type_)| { + // Create an assignment statement for the first access expression. + let (first, stmt) = + self.unique_simple_assign_statement(Expression::Access(AccessExpression::Tuple(TupleAccess { + tuple: Box::new(Expression::Identifier(*first)), + index: NonNegativeNumber::from(i), + span: Default::default(), + id: { + // Create a new node ID for the access expression. + let id = self.node_builder.next_id(); + // Set the type of the node ID. + self.type_table.insert(id, type_.clone()); + id + }, + }))); + statements.push(stmt); + // Create an assignment statement for the second access expression. + let (second, stmt) = + self.unique_simple_assign_statement(Expression::Access(AccessExpression::Tuple(TupleAccess { + tuple: Box::new(Expression::Identifier(*second)), + index: NonNegativeNumber::from(i), + span: Default::default(), + id: { + // Create a new node ID for the access expression. + let id = self.node_builder.next_id(); + // Set the type of the node ID. + self.type_table.insert(id, type_.clone()); + id + }, + }))); + statements.push(stmt); + + // Recursively reconstruct the ternary expression. + let (expression, stmts) = self.reconstruct_ternary(TernaryExpression { + condition: Box::new(condition.clone()), + // Access the member of the first expression. + if_true: Box::new(Expression::Identifier(first)), + // Access the member of the second expression. + if_false: Box::new(Expression::Identifier(second)), span: Default::default(), id: { - // Create a new node ID for the access expression. + // Create a new node ID for the ternary expression. let id = self.node_builder.next_id(); // Set the type of the node ID. self.type_table.insert(id, type_.clone()); id }, - }))); - statements.push(stmt); - // Create an assignment statement for the second access expression. - let (second, stmt) = - self.unique_simple_assign_statement(Expression::Access(AccessExpression::Tuple(TupleAccess { - tuple: Box::new(Expression::Identifier(*second)), - index: NonNegativeNumber::from(i), - span: Default::default(), - id: { - // Create a new node ID for the access expression. - let id = self.node_builder.next_id(); - // Set the type of the node ID. - self.type_table.insert(id, type_.clone()); - id - }, - }))); - statements.push(stmt); + }); - // Recursively reconstruct the ternary expression. - let (expression, stmts) = self.reconstruct_ternary(TernaryExpression { - condition: Box::new(condition.clone()), - // Access the member of the first expression. - if_true: Box::new(Expression::Identifier(first)), - // Access the member of the second expression. - if_false: Box::new(Expression::Identifier(second)), - span: Default::default(), - id: { - // Create a new node ID for the ternary expression. - let id = self.node_builder.next_id(); - // Set the type of the node ID. - self.type_table.insert(id, type_.clone()); - id - }, - }); + // Accumulate any statements generated. + statements.extend(stmts); - // Accumulate any statements generated. - statements.extend(stmts); - - expression - }) - .collect(); + expression + }) + .collect(); // Construct the tuple expression. let tuple = TupleExpression { diff --git a/compiler/passes/src/loop_unrolling/unroller.rs b/compiler/passes/src/loop_unrolling/unroller.rs index c95f03843c..e902b6a551 100644 --- a/compiler/passes/src/loop_unrolling/unroller.rs +++ b/compiler/passes/src/loop_unrolling/unroller.rs @@ -192,41 +192,42 @@ impl<'a> Unroller<'a> { self.type_table.insert(id, input.type_.clone()); // Reconstruct `iteration_count` as a `Literal`. - let value = match input.type_ { - Type::Integer(IntegerType::I8) => { - Literal::Integer(IntegerType::I8, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::I16) => { - Literal::Integer(IntegerType::I16, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::I32) => { - Literal::Integer(IntegerType::I32, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::I64) => { - Literal::Integer(IntegerType::I64, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::I128) => { - Literal::Integer(IntegerType::I128, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::U8) => { - Literal::Integer(IntegerType::U8, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::U16) => { - Literal::Integer(IntegerType::U16, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::U32) => { - Literal::Integer(IntegerType::U32, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::U64) => { - Literal::Integer(IntegerType::U64, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::U128) => { - Literal::Integer(IntegerType::U128, iteration_count.to_string(), Default::default(), id) - } - _ => unreachable!( - "The iteration variable must be an integer type. This should be enforced by type checking." - ), - }; + let value = + match input.type_ { + Type::Integer(IntegerType::I8) => { + Literal::Integer(IntegerType::I8, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::I16) => { + Literal::Integer(IntegerType::I16, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::I32) => { + Literal::Integer(IntegerType::I32, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::I64) => { + Literal::Integer(IntegerType::I64, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::I128) => { + Literal::Integer(IntegerType::I128, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::U8) => { + Literal::Integer(IntegerType::U8, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::U16) => { + Literal::Integer(IntegerType::U16, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::U32) => { + Literal::Integer(IntegerType::U32, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::U64) => { + Literal::Integer(IntegerType::U64, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::U128) => { + Literal::Integer(IntegerType::U128, iteration_count.to_string(), Default::default(), id) + } + _ => unreachable!( + "The iteration variable must be an integer type. This should be enforced by type checking." + ), + }; // Add the loop variable as a constant for the current scope self.constant_propagation_table diff --git a/compiler/passes/src/static_single_assignment/rename_expression.rs b/compiler/passes/src/static_single_assignment/rename_expression.rs index ef0ac09492..3ead92c9a8 100644 --- a/compiler/passes/src/static_single_assignment/rename_expression.rs +++ b/compiler/passes/src/static_single_assignment/rename_expression.rs @@ -207,12 +207,13 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> { let (expression, mut statements) = self.consume_expression(*input.expression); // Construct and accumulate a unique assignment statement storing the result of the cast expression. - let (place, statement) = self.unique_simple_assign_statement(Expression::Cast(CastExpression { - expression: Box::new(expression), - type_: input.type_, - span: input.span, - id: input.id, - })); + let (place, statement) = + self.unique_simple_assign_statement(Expression::Cast(CastExpression { + expression: Box::new(expression), + type_: input.type_, + span: input.span, + id: input.id, + })); statements.push(statement); (Expression::Identifier(place), statements) @@ -280,12 +281,13 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> { } // Construct and accumulate a new assignment statement for the struct expression. - let (place, statement) = self.unique_simple_assign_statement(Expression::Struct(StructExpression { - name: input.name, - span: input.span, - members: reordered_members, - id: input.id, - })); + let (place, statement) = + self.unique_simple_assign_statement(Expression::Struct(StructExpression { + name: input.name, + span: input.span, + members: reordered_members, + id: input.id, + })); statements.push(statement); (Expression::Identifier(place), statements) @@ -375,12 +377,9 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> { let (receiver, mut statements) = self.consume_expression(*input.receiver); // Construct and accumulate a new assignment statement for the unary expression. - let (place, statement) = self.unique_simple_assign_statement(Expression::Unary(UnaryExpression { - op: input.op, - receiver: Box::new(receiver), - span: input.span, - id: input.id, - })); + let (place, statement) = self.unique_simple_assign_statement(Expression::Unary( + UnaryExpression { op: input.op, receiver: Box::new(receiver), span: input.span, id: input.id } + )); statements.push(statement); (Expression::Identifier(place), statements) diff --git a/compiler/passes/src/static_single_assignment/rename_statement.rs b/compiler/passes/src/static_single_assignment/rename_statement.rs index 576e59bc30..59d7479660 100644 --- a/compiler/passes/src/static_single_assignment/rename_statement.rs +++ b/compiler/passes/src/static_single_assignment/rename_statement.rs @@ -198,13 +198,14 @@ impl StatementConsumer for StaticSingleAssigner<'_> { self.type_table.insert(id, type_); // Construct a ternary expression for the phi function. - let (value, stmts) = self.consume_ternary(TernaryExpression { - condition: Box::new(condition.clone()), - if_true, - if_false, - span: Default::default(), - id, - }); + let (value, stmts) = + self.consume_ternary(TernaryExpression { + condition: Box::new(condition.clone()), + if_true, + if_false, + span: Default::default(), + id, + }); statements.extend(stmts); @@ -290,22 +291,17 @@ impl StatementConsumer for StaticSingleAssigner<'_> { } // Construct the lhs of the assignment. - let place = Expression::Tuple(TupleExpression { - elements, - span: Default::default(), - id: self.node_builder.next_id(), - }); + let place = Expression::Tuple( + TupleExpression { elements, span: Default::default(), id: self.node_builder.next_id() } + ); // Update the type of the lhs. self.type_table.insert(place.id(), Type::Tuple(tuple_type_)); // Create the assignment statement. - let assignment = Statement::Assign(Box::new(AssignStatement { - place, - value, - span: definition.span, - id: definition.id, - })); + let assignment = Statement::Assign( + Box::new(AssignStatement { place, value, span: definition.span, id: definition.id }) + ); statements.push(assignment); } @@ -401,12 +397,9 @@ impl StatementConsumer for StaticSingleAssigner<'_> { }); // Add the simplified return statement to the list of produced statements. - statements.push(Statement::Return(ReturnStatement { - expression, - finalize_arguments: finalize_args, - span: input.span, - id: input.id, - })); + statements.push(Statement::Return( + ReturnStatement { expression, finalize_arguments: finalize_args, span: input.span, id: input.id } + )); statements } diff --git a/compiler/passes/src/type_checking/check_expressions.rs b/compiler/passes/src/type_checking/check_expressions.rs index 1f406513cf..5560563d42 100644 --- a/compiler/passes/src/type_checking/check_expressions.rs +++ b/compiler/passes/src/type_checking/check_expressions.rs @@ -235,10 +235,9 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> { self.emit_err(TypeCheckerError::type_should_be(type_, "struct", access.inner.span())); } None => { - self.emit_err(TypeCheckerError::could_not_determine_type( - &access.inner, - access.inner.span(), - )); + self.emit_err( + TypeCheckerError::could_not_determine_type(&access.inner, access.inner.span()) + ); } } } @@ -288,11 +287,9 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> { } // The array cannot have more than `MAX_ARRAY_ELEMENTS` elements. num_elements => { - self.emit_err(TypeCheckerError::array_too_large( - num_elements, - Testnet3::MAX_ARRAY_ELEMENTS, - input.span(), - )); + self.emit_err( + TypeCheckerError::array_too_large(num_elements, Testnet3::MAX_ARRAY_ELEMENTS, input.span()) + ); None } }; diff --git a/compiler/passes/src/type_checking/check_program.rs b/compiler/passes/src/type_checking/check_program.rs index 3590d50b3d..4fdf83a9ae 100644 --- a/compiler/passes/src/type_checking/check_program.rs +++ b/compiler/passes/src/type_checking/check_program.rs @@ -121,18 +121,19 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> { // For records, enforce presence of the `owner: Address` member. if input.is_record { - let check_has_field = - |need, expected_ty: Type| match input.members.iter().find_map(|Member { identifier, type_, .. }| { - (identifier.name == need).then_some((identifier, type_)) - }) { - Some((_, actual_ty)) if expected_ty.eq_flat(actual_ty) => {} // All good, found + right type! - Some((field, _)) => { - self.emit_err(TypeCheckerError::record_var_wrong_type(field, expected_ty, input.span())); - } - None => { - self.emit_err(TypeCheckerError::required_record_variable(need, expected_ty, input.span())); - } - }; + let check_has_field = |need, expected_ty: Type| match input + .members + .iter() + .find_map(|Member { identifier, type_, .. }| (identifier.name == need).then_some((identifier, type_))) + { + Some((_, actual_ty)) if expected_ty.eq_flat(actual_ty) => {} // All good, found + right type! + Some((field, _)) => { + self.emit_err(TypeCheckerError::record_var_wrong_type(field, expected_ty, input.span())); + } + None => { + self.emit_err(TypeCheckerError::required_record_variable(need, expected_ty, input.span())); + } + }; check_has_field(sym::owner, Type::Address); } diff --git a/compiler/passes/src/type_checking/check_statements.rs b/compiler/passes/src/type_checking/check_statements.rs index 1bd4e0a1ab..7559999235 100644 --- a/compiler/passes/src/type_checking/check_statements.rs +++ b/compiler/passes/src/type_checking/check_statements.rs @@ -68,21 +68,24 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> { } }; - let var_type = if let Some(var) = self.symbol_table.borrow_mut().lookup_variable(var_name.name) { - match &var.declaration { - VariableType::Const => self.emit_err(TypeCheckerError::cannot_assign_to_const_var(var_name, var.span)), - VariableType::Input(Mode::Constant) => { - self.emit_err(TypeCheckerError::cannot_assign_to_const_input(var_name, var.span)) + let var_type = + if let Some(var) = self.symbol_table.borrow_mut().lookup_variable(var_name.name) { + match &var.declaration { + VariableType::Const => { + self.emit_err(TypeCheckerError::cannot_assign_to_const_var(var_name, var.span)) + } + VariableType::Input(Mode::Constant) => { + self.emit_err(TypeCheckerError::cannot_assign_to_const_input(var_name, var.span)) + } + _ => {} } - _ => {} - } - Some(var.type_.clone()) - } else { - self.emit_err(TypeCheckerError::unknown_sym("variable", var_name.name, var_name.span)); + Some(var.type_.clone()) + } else { + self.emit_err(TypeCheckerError::unknown_sym("variable", var_name.name, var_name.span)); - None - }; + None + }; if var_type.is_some() { self.visit_expression(&input.value, &var_type); @@ -175,16 +178,18 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> { // Enforce that Constant variables have literal expressions on right-hand side match &input.value { Expression::Literal(_) => (), - Expression::Tuple(tuple_expression) => match tuple_expression.elements.len() { - 0 | 1 => unreachable!("Parsing guarantees that tuple types have at least two elements."), - _ => { - if tuple_expression.elements.iter().any(|expr| !matches!(expr, Expression::Literal(_))) { - self.emit_err(TypeCheckerError::const_declaration_must_be_literal_or_tuple_of_literals( - input.span, - )) + Expression::Tuple(tuple_expression) => { + match tuple_expression.elements.len() { + 0 | 1 => unreachable!("Parsing guarantees that tuple types have at least two elements."), + _ => { + if tuple_expression.elements.iter().any(|expr| !matches!(expr, Expression::Literal(_))) { + self.emit_err(TypeCheckerError::const_declaration_must_be_literal_or_tuple_of_literals( + input.span, + )) + } } } - }, + } _ => self.emit_err(TypeCheckerError::const_declaration_must_be_literal_or_tuple_of_literals(input.span())), } diff --git a/compiler/passes/src/type_checking/checker.rs b/compiler/passes/src/type_checking/checker.rs index 0cc3f86229..7c6bfc2f4e 100644 --- a/compiler/passes/src/type_checking/checker.rs +++ b/compiler/passes/src/type_checking/checker.rs @@ -387,11 +387,9 @@ impl<'a> TypeChecker<'a> { ) -> Option { // Check that the number of arguments is correct. if arguments.len() != core_function.num_args() { - self.emit_err(TypeCheckerError::incorrect_num_args_to_call( - core_function.num_args(), - arguments.len(), - function_span, - )); + self.emit_err( + TypeCheckerError::incorrect_num_args_to_call(core_function.num_args(), arguments.len(), function_span) + ); return None; } @@ -982,10 +980,9 @@ impl<'a> TypeChecker<'a> { CoreFunction::MappingContains => { // Check that the operation is invoked in a `finalize` block. if !self.is_finalize { - self.handler.emit_err(TypeCheckerError::invalid_operation_outside_finalize( - "Mapping::contains", - function_span, - )) + self.handler.emit_err( + TypeCheckerError::invalid_operation_outside_finalize("Mapping::contains", function_span) + ) } // Check that the first argument is a mapping. if let Some(mapping_type) = self.assert_mapping_type(&arguments[0].0, arguments[0].1) { diff --git a/compiler/span/src/source_map.rs b/compiler/span/src/source_map.rs index 3a66e4aa05..495f8e256f 100644 --- a/compiler/span/src/source_map.rs +++ b/compiler/span/src/source_map.rs @@ -99,10 +99,11 @@ impl SourceMap { /// Returns a displayable representation of the `span` as a string. pub fn span_to_string(&self, span: Span) -> String { - let loc = match self.span_to_location(span) { - None => return "no-location".to_string(), - Some(l) => l, - }; + let loc = + match self.span_to_location(span) { + None => return "no-location".to_string(), + Some(l) => l, + }; if loc.line_start == loc.line_stop { format!("{}:{}-{}", loc.line_start, loc.col_start, loc.col_stop) @@ -339,10 +340,11 @@ fn normalize_newlines(src: &mut String) { let mut gap_len = 0; let mut tail = buf.as_mut_slice(); loop { - let idx = match find_crlf(&tail[gap_len..]) { - None => tail.len(), - Some(idx) => idx + gap_len, - }; + let idx = + match find_crlf(&tail[gap_len..]) { + None => tail.len(), + Some(idx) => idx + gap_len, + }; tail.copy_within(gap_len..idx, 0); tail = &mut tail[idx - gap_len..]; if tail.len() == gap_len { diff --git a/docs/grammar/src/main.rs b/docs/grammar/src/main.rs index 8eff45acbe..7fd363494b 100644 --- a/docs/grammar/src/main.rs +++ b/docs/grammar/src/main.rs @@ -205,10 +205,11 @@ fn main() -> Result<()> { // Parse ABNF to get list of all definitions. // Rust ABNF does not provide support for `%s` (case sensitive strings, part of // the standard); so we need to remove all occurrences before parsing. - let parsed = abnf::rulelist(&str::replace(&grammar, "%s", "")).map_err(|e| { - eprintln!("{}", &e); - anyhow::anyhow!(e) - })?; + let parsed = + abnf::rulelist(&str::replace(&grammar, "%s", "")).map_err(|e| { + eprintln!("{}", &e); + anyhow::anyhow!(e) + })?; // Init parser and run it. That's it. let mut parser = Processor::new(&grammar, parsed); diff --git a/leo/cli/commands/execute.rs b/leo/cli/commands/execute.rs index 2df5b01510..a2fb45064d 100644 --- a/leo/cli/commands/execute.rs +++ b/leo/cli/commands/execute.rs @@ -54,13 +54,14 @@ impl Command for Execute { fn apply(self, context: Context, input: Self::Input) -> Result { // If input values are provided, then run the program with those inputs. // Otherwise, use the input file. - let mut inputs = match self.inputs.is_empty() { - true => match input { - (Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits), - _ => Vec::new(), - }, - false => self.inputs, - }; + let mut inputs = + match self.inputs.is_empty() { + true => match input { + (Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits), + _ => Vec::new(), + }, + false => self.inputs, + }; // Compose the `execute` command. let mut arguments = vec![SNARKVM_COMMAND.to_string(), self.name]; diff --git a/leo/cli/commands/run.rs b/leo/cli/commands/run.rs index ec27f4d812..b80c76f88f 100644 --- a/leo/cli/commands/run.rs +++ b/leo/cli/commands/run.rs @@ -46,13 +46,14 @@ impl Command for Run { fn apply(self, context: Context, input: Self::Input) -> Result { // If input values are provided, then run the program with those inputs. // Otherwise, use the input file. - let mut inputs = match self.inputs.is_empty() { - true => match input { - (Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits), - _ => Vec::new(), - }, - false => self.inputs, - }; + let mut inputs = + match self.inputs.is_empty() { + true => match input { + (Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits), + _ => Vec::new(), + }, + false => self.inputs, + }; // Compose the `run` command. let mut arguments = vec![SNARKVM_COMMAND.to_string(), self.name]; diff --git a/leo/package/src/inputs/input.rs b/leo/package/src/inputs/input.rs index e7e47e0098..9ca47d7eee 100644 --- a/leo/package/src/inputs/input.rs +++ b/leo/package/src/inputs/input.rs @@ -56,8 +56,8 @@ impl InputFile { pub fn read_from<'a>(&self, path: &'a Path) -> Result<(String, Cow<'a, Path>)> { let path = self.setup_file_path(path); - let input = fs::read_to_string(&path) - .map_err(|_| PackageError::failed_to_read_input_file(path.clone().into_owned()))?; + let input = + fs::read_to_string(&path).map_err(|_| PackageError::failed_to_read_input_file(path.clone().into_owned()))?; Ok((input, path)) } diff --git a/tests/test-framework/src/runner.rs b/tests/test-framework/src/runner.rs index 1fb9e0f78d..3f9be72ddd 100644 --- a/tests/test-framework/src/runner.rs +++ b/tests/test-framework/src/runner.rs @@ -93,12 +93,13 @@ impl TestCases { let mut path_prefix = PathBuf::from(env!("CARGO_MANIFEST_DIR")); path_prefix.push("../../tests"); - let mut new = Self { - tests: Vec::new(), - path_prefix, - expectation_category: expectation_category.to_string(), - fail_categories: Vec::new(), - }; + let mut new = + Self { + tests: Vec::new(), + path_prefix, + expectation_category: expectation_category.to_string(), + fail_categories: Vec::new(), + }; let tests = new.load_tests(additional_check); (new, tests) } @@ -188,10 +189,11 @@ pub fn run_tests(runner: &T, expectation_category: &str) { let mut outputs = vec![]; cases.process_tests(configs, |cases, (path, content, test_name, config)| { - let namespace = match runner.resolve_namespace(&config.namespace) { - Some(ns) => ns, - None => return, - }; + let namespace = + match runner.resolve_namespace(&config.namespace) { + Some(ns) => ns, + None => return, + }; let (expectation_path, expectations) = cases.load_expectations(path); From 4a0228bcac9b3895ff3ceebfdf49ce67172729c2 Mon Sep 17 00:00:00 2001 From: Pranav Gaddamadugu <23022326+d0cd@users.noreply.github.com> Date: Mon, 27 Nov 2023 17:18:48 -0800 Subject: [PATCH 3/5] Update CI rust version --- .circleci/config.yml | 14 +- compiler/ast/src/common/imported_modules.rs | 19 +- compiler/ast/src/passes/reconstructor.rs | 9 +- compiler/compiler/src/compiler.rs | 9 +- compiler/compiler/tests/compile.rs | 6 +- compiler/compiler/tests/execute.rs | 20 +- compiler/parser/src/parser/expression.rs | 61 ++--- compiler/parser/src/parser/file.rs | 92 ++++---- compiler/parser/src/parser/statement.rs | 84 +++---- .../src/code_generation/visit_expressions.rs | 18 +- .../src/code_generation/visit_statements.rs | 140 ++++++------ .../common/symbol_table/function_symbol.rs | 7 +- .../eliminate_statement.rs | 30 ++- .../destructuring/destructure_statement.rs | 49 ++-- .../src/flattening/flatten_statement.rs | 51 +++-- compiler/passes/src/flattening/flattener.rs | 212 +++++++++--------- .../passes/src/loop_unrolling/unroller.rs | 71 +++--- .../rename_expression.rs | 35 +-- .../rename_statement.rs | 41 ++-- .../src/type_checking/check_expressions.rs | 15 +- .../passes/src/type_checking/check_program.rs | 25 +-- .../src/type_checking/check_statements.rs | 45 ++-- compiler/passes/src/type_checking/checker.rs | 15 +- compiler/span/src/source_map.rs | 18 +- docs/grammar/src/main.rs | 9 +- leo/cli/commands/execute.rs | 15 +- leo/cli/commands/run.rs | 15 +- leo/package/src/inputs/input.rs | 4 +- tests/test-framework/src/runner.rs | 22 +- 29 files changed, 580 insertions(+), 571 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8b41b60fc5..9c1dda12aa 100755 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -50,7 +50,7 @@ commands: jobs: check-style: docker: - - image: cimg/rust:1.71 + - image: cimg/rust:1.74 resource_class: xlarge steps: - checkout @@ -66,7 +66,7 @@ jobs: clippy: docker: - - image: cimg/rust:1.71 + - image: cimg/rust:1.74 resource_class: xlarge steps: - checkout @@ -83,7 +83,7 @@ jobs: leo-executable: docker: - - image: cimg/rust:1.71 + - image: cimg/rust:1.74 resource_class: xlarge steps: - checkout @@ -102,7 +102,7 @@ jobs: leo-new: docker: - - image: cimg/rust:1.71 + - image: cimg/rust:1.74 resource_class: xlarge steps: - attach_workspace: @@ -115,7 +115,7 @@ jobs: leo-clean: docker: - - image: cimg/rust:1.71 + - image: cimg/rust:1.74 resource_class: xlarge steps: - attach_workspace: @@ -128,7 +128,7 @@ jobs: leo-example: docker: - - image: cimg/rust:1.71 + - image: cimg/rust:1.74 resource_class: xlarge steps: - attach_workspace: @@ -141,7 +141,7 @@ jobs: test-examples: docker: - - image: cimg/rust:1.71 + - image: cimg/rust:1.74 resource_class: xlarge steps: - attach_workspace: diff --git a/compiler/ast/src/common/imported_modules.rs b/compiler/ast/src/common/imported_modules.rs index 8dab723cf1..16fc81547e 100644 --- a/compiler/ast/src/common/imported_modules.rs +++ b/compiler/ast/src/common/imported_modules.rs @@ -26,16 +26,15 @@ pub fn serialize( imported_modules: &IndexMap, Program>, serializer: S, ) -> Result { - let joined: IndexMap = - with_session_globals(|s| { - imported_modules - .into_iter() - .map(|(package, program)| { - let package = package.iter().map(|x| x.as_str(s, |s| s.to_owned())).collect::>(); - (package.join("."), program.clone()) - }) - .collect() - }); + let joined: IndexMap = with_session_globals(|s| { + imported_modules + .into_iter() + .map(|(package, program)| { + let package = package.iter().map(|x| x.as_str(s, |s| s.to_owned())).collect::>(); + (package.join("."), program.clone()) + }) + .collect() + }); joined.serialize(serializer) } diff --git a/compiler/ast/src/passes/reconstructor.rs b/compiler/ast/src/passes/reconstructor.rs index 86ce52192b..793df279b9 100644 --- a/compiler/ast/src/passes/reconstructor.rs +++ b/compiler/ast/src/passes/reconstructor.rs @@ -66,9 +66,12 @@ pub trait ExpressionReconstructor { fn reconstruct_associated_constant(&mut self, input: AssociatedConstant) -> (Expression, Self::AdditionalOutput) { ( - Expression::Access(AccessExpression::AssociatedConstant( - AssociatedConstant { ty: input.ty, name: input.name, span: input.span, id: input.id } - )), + Expression::Access(AccessExpression::AssociatedConstant(AssociatedConstant { + ty: input.ty, + name: input.name, + span: input.span, + id: input.id, + })), Default::default(), ) } diff --git a/compiler/compiler/src/compiler.rs b/compiler/compiler/src/compiler.rs index d185741a7d..02e9d287a0 100644 --- a/compiler/compiler/src/compiler.rs +++ b/compiler/compiler/src/compiler.rs @@ -244,9 +244,12 @@ impl<'a> Compiler<'a> { /// Runs the destructuring pass. pub fn destructuring_pass(&mut self) -> Result<()> { - self.ast = Destructurer::do_pass( - (std::mem::take(&mut self.ast), &self.type_table, &self.node_builder, &self.assigner) - )?; + self.ast = Destructurer::do_pass(( + std::mem::take(&mut self.ast), + &self.type_table, + &self.node_builder, + &self.assigner, + ))?; if self.compiler_options.output.destructured_ast { self.write_ast_to_json("destructured_ast.json")?; diff --git a/compiler/compiler/tests/compile.rs b/compiler/compiler/tests/compile.rs index f96c0cb5e6..6f9c573e24 100644 --- a/compiler/compiler/tests/compile.rs +++ b/compiler/compiler/tests/compile.rs @@ -51,9 +51,9 @@ impl Namespace for CompileNamespace { fn run_test(&self, test: Test) -> Result { let buf = BufferEmitter(Rc::default(), Rc::default()); let handler = Handler::new(Box::new(buf.clone())); - create_session_if_not_set_then( - |_| run_test(test, &handler, &buf).map_err(|()| buf.0.take().to_string() + &buf.1.take().to_string()) - ) + create_session_if_not_set_then(|_| { + run_test(test, &handler, &buf).map_err(|()| buf.0.take().to_string() + &buf.1.take().to_string()) + }) } } diff --git a/compiler/compiler/tests/execute.rs b/compiler/compiler/tests/execute.rs index 5785d18716..b5d2d30ce1 100644 --- a/compiler/compiler/tests/execute.rs +++ b/compiler/compiler/tests/execute.rs @@ -58,9 +58,9 @@ impl Namespace for ExecuteNamespace { fn run_test(&self, test: Test) -> Result { let buf = BufferEmitter(Rc::default(), Rc::default()); let handler = Handler::new(Box::new(buf.clone())); - create_session_if_not_set_then( - |_| run_test(test, &handler, &buf).map_err(|()| buf.0.take().to_string() + &buf.1.take().to_string()) - ) + create_session_if_not_set_then(|_| { + run_test(test, &handler, &buf).map_err(|()| buf.0.take().to_string() + &buf.1.take().to_string()) + }) } } @@ -125,13 +125,13 @@ fn run_test(test: Test, handler: &Handler, err_buf: &BufferEmitter) -> Result { if self.eat(&Token::As) { let (type_, end_span) = self.parse_primitive_type()?; let span = expr.span() + end_span; - expr = Expression::Cast( - CastExpression { expression: Box::new(expr), type_, span, id: self.node_builder.next_id() } - ); + expr = Expression::Cast(CastExpression { + expression: Box::new(expr), + type_, + span, + id: self.node_builder.next_id(), + }); } Ok(expr) @@ -325,9 +328,12 @@ impl ParserContext<'_> { if let (true, Some(op)) = (args.is_empty(), UnaryOperation::from_symbol(method.name)) { // Found an unary operator and the argument list is empty. - Ok(Expression::Unary( - UnaryExpression { span, op, receiver: Box::new(receiver), id: self.node_builder.next_id() } - )) + Ok(Expression::Unary(UnaryExpression { + span, + op, + receiver: Box::new(receiver), + id: self.node_builder.next_id(), + })) } else if let (1, Some(op)) = (args.len(), BinaryOperation::from_symbol(method.name)) { // Found a binary operator and the argument list contains a single argument. Ok(Expression::Binary(BinaryExpression { @@ -437,10 +443,12 @@ impl ParserContext<'_> { if self.check_int() { // Eat a tuple member access. let (index, span) = self.eat_whole_number()?; - expr = - Expression::Access(AccessExpression::Tuple( - TupleAccess { tuple: Box::new(expr), index, span, id: self.node_builder.next_id() } - )) + expr = Expression::Access(AccessExpression::Tuple(TupleAccess { + tuple: Box::new(expr), + index, + span, + id: self.node_builder.next_id(), + })) } else if self.eat(&Token::Leo) { // Eat an external function call. self.eat(&Token::Div); // todo: Make `/` a more general token. @@ -619,15 +627,14 @@ impl ParserContext<'_> { self.expect_identifier()? }; - let (expression, span) = - if self.eat(&Token::Colon) { - // Parse individual struct variable declarations. - let expression = self.parse_expression()?; - let span = identifier.span + expression.span(); - (Some(expression), span) - } else { - (None, identifier.span) - }; + let (expression, span) = if self.eat(&Token::Colon) { + // Parse individual struct variable declarations. + let expression = self.parse_expression()?; + let span = identifier.span + expression.span(); + (Some(expression), span) + } else { + (None, identifier.span) + }; Ok(StructVariableInitializer { identifier, expression, id: self.node_builder.next_id(), span }) } @@ -678,9 +685,11 @@ impl ParserContext<'_> { // Literal followed by `group`, e.g., `42group`. Some(Token::Group) => { assert_no_whitespace("group")?; - Expression::Literal(Literal::Group(Box::new( - GroupLiteral::Single(value, full_span, self.node_builder.next_id()) - ))) + Expression::Literal(Literal::Group(Box::new(GroupLiteral::Single( + value, + full_span, + self.node_builder.next_id(), + )))) } // Literal followed by `scalar` e.g., `42scalar`. Some(Token::Scalar) => { @@ -723,9 +732,11 @@ impl ParserContext<'_> { Token::Block => { Expression::Identifier(Identifier { name: sym::block, span, id: self.node_builder.next_id() }) } - t if crate::type_::TYPE_TOKENS.contains(&t) => Expression::Identifier( - Identifier { name: t.keyword_to_symbol().unwrap(), span, id: self.node_builder.next_id() } - ), + t if crate::type_::TYPE_TOKENS.contains(&t) => Expression::Identifier(Identifier { + name: t.keyword_to_symbol().unwrap(), + span, + id: self.node_builder.next_id(), + }), token => { return Err(ParserError::unexpected_str(token, "expression", span).into()); } diff --git a/compiler/parser/src/parser/file.rs b/compiler/parser/src/parser/file.rs index b2a7aa3522..5c3c9c31b8 100644 --- a/compiler/parser/src/parser/file.rs +++ b/compiler/parser/src/parser/file.rs @@ -325,9 +325,13 @@ impl ParserContext<'_> { } else { let type_ = self.parse_type()?.0; - Ok(functions::Input::Internal( - FunctionInput { identifier: name, mode, type_, span: name.span, id: self.node_builder.next_id() } - )) + Ok(functions::Input::Internal(FunctionInput { + identifier: name, + mode, + type_, + span: name.span, + id: self.node_builder.next_id(), + })) } } @@ -416,58 +420,56 @@ impl ParserContext<'_> { let (inputs, ..) = self.parse_paren_comma_list(|p| p.parse_input().map(Some))?; // Parse return type. - let output = - match self.eat(&Token::Arrow) { - false => vec![], - true => { - self.disallow_struct_construction = true; - let output = match self.peek_is_left_par() { - true => self.parse_paren_comma_list(|p| p.parse_output().map(Some))?.0, - false => vec![self.parse_output()?], - }; - self.disallow_struct_construction = false; - output - } - }; + let output = match self.eat(&Token::Arrow) { + false => vec![], + true => { + self.disallow_struct_construction = true; + let output = match self.peek_is_left_par() { + true => self.parse_paren_comma_list(|p| p.parse_output().map(Some))?.0, + false => vec![self.parse_output()?], + }; + self.disallow_struct_construction = false; + output + } + }; // Parse the function body. let block = self.parse_block()?; // Parse the `finalize` block if it exists. - let finalize = - match self.eat(&Token::Finalize) { - false => None, - true => { - // Get starting span. - let start = self.prev_token.span; + let finalize = match self.eat(&Token::Finalize) { + false => None, + true => { + // Get starting span. + let start = self.prev_token.span; - // Parse the identifier. - let identifier = self.expect_identifier()?; + // Parse the identifier. + let identifier = self.expect_identifier()?; - // Parse parameters. - let (input, ..) = self.parse_paren_comma_list(|p| p.parse_input().map(Some))?; + // Parse parameters. + let (input, ..) = self.parse_paren_comma_list(|p| p.parse_input().map(Some))?; - // Parse return type. - let output = match self.eat(&Token::Arrow) { - false => vec![], - true => { - self.disallow_struct_construction = true; - let output = match self.peek_is_left_par() { - true => self.parse_paren_comma_list(|p| p.parse_output().map(Some))?.0, - false => vec![self.parse_output()?], - }; - self.disallow_struct_construction = false; - output - } - }; + // Parse return type. + let output = match self.eat(&Token::Arrow) { + false => vec![], + true => { + self.disallow_struct_construction = true; + let output = match self.peek_is_left_par() { + true => self.parse_paren_comma_list(|p| p.parse_output().map(Some))?.0, + false => vec![self.parse_output()?], + }; + self.disallow_struct_construction = false; + output + } + }; - // Parse the finalize body. - let block = self.parse_block()?; - let span = start + block.span; + // Parse the finalize body. + let block = self.parse_block()?; + let span = start + block.span; - Some(Finalize::new(identifier, input, output, block, span, self.node_builder.next_id())) - } - }; + Some(Finalize::new(identifier, input, output, block, span, self.node_builder.next_id())) + } + }; let span = start + block.span; Ok(( diff --git a/compiler/parser/src/parser/statement.rs b/compiler/parser/src/parser/statement.rs index ae8e61d852..c79d75c14d 100644 --- a/compiler/parser/src/parser/statement.rs +++ b/compiler/parser/src/parser/statement.rs @@ -158,9 +158,11 @@ impl ParserContext<'_> { // Parse the expression as a statement. let end = self.expect(&Token::Semicolon)?; - Ok(Statement::Expression( - ExpressionStatement { span: place.span() + end, expression: place, id: self.node_builder.next_id() } - )) + Ok(Statement::Expression(ExpressionStatement { + span: place.span() + end, + expression: place, + id: self.node_builder.next_id(), + })) } } @@ -269,43 +271,45 @@ impl ParserContext<'_> { let keyword = self.expect(&Token::Console)?; self.expect(&Token::Dot)?; let identifier = self.expect_identifier()?; - let (span, function) = - match identifier.name { - sym::assert => { - self.expect(&Token::LeftParen)?; - let expr = self.parse_expression()?; - self.expect(&Token::RightParen)?; - (keyword + expr.span(), ConsoleFunction::Assert(expr)) - } - sym::assert_eq => { - self.expect(&Token::LeftParen)?; - let left = self.parse_expression()?; - self.expect(&Token::Comma)?; - let right = self.parse_expression()?; - self.expect(&Token::RightParen)?; - (left.span() + right.span(), ConsoleFunction::AssertEq(left, right)) - } - sym::assert_neq => { - self.expect(&Token::LeftParen)?; - let left = self.parse_expression()?; - self.expect(&Token::Comma)?; - let right = self.parse_expression()?; - self.expect(&Token::RightParen)?; - (left.span() + right.span(), ConsoleFunction::AssertNeq(left, right)) - } - symbol => { - // Not sure what it is, assume it's `log`. - self.emit_err( - ParserError::unexpected_ident(symbol, &["assert", "assert_eq", "assert_neq"], identifier.span) - ); - ( - Default::default(), - ConsoleFunction::Assert(Expression::Err( - ErrExpression { span: Default::default(), id: self.node_builder.next_id() } - )), - ) - } - }; + let (span, function) = match identifier.name { + sym::assert => { + self.expect(&Token::LeftParen)?; + let expr = self.parse_expression()?; + self.expect(&Token::RightParen)?; + (keyword + expr.span(), ConsoleFunction::Assert(expr)) + } + sym::assert_eq => { + self.expect(&Token::LeftParen)?; + let left = self.parse_expression()?; + self.expect(&Token::Comma)?; + let right = self.parse_expression()?; + self.expect(&Token::RightParen)?; + (left.span() + right.span(), ConsoleFunction::AssertEq(left, right)) + } + sym::assert_neq => { + self.expect(&Token::LeftParen)?; + let left = self.parse_expression()?; + self.expect(&Token::Comma)?; + let right = self.parse_expression()?; + self.expect(&Token::RightParen)?; + (left.span() + right.span(), ConsoleFunction::AssertNeq(left, right)) + } + symbol => { + // Not sure what it is, assume it's `log`. + self.emit_err(ParserError::unexpected_ident( + symbol, + &["assert", "assert_eq", "assert_neq"], + identifier.span, + )); + ( + Default::default(), + ConsoleFunction::Assert(Expression::Err(ErrExpression { + span: Default::default(), + id: self.node_builder.next_id(), + })), + ) + } + }; self.expect(&Token::Semicolon)?; Ok(ConsoleStatement { span: keyword + span, function, id: self.node_builder.next_id() }) diff --git a/compiler/passes/src/code_generation/visit_expressions.rs b/compiler/passes/src/code_generation/visit_expressions.rs index 922d6ef5f5..bccd21f1d3 100644 --- a/compiler/passes/src/code_generation/visit_expressions.rs +++ b/compiler/passes/src/code_generation/visit_expressions.rs @@ -572,18 +572,16 @@ impl<'a> CodeGenerator<'a> { let return_type = &self.symbol_table.lookup_fn_symbol(function_name).unwrap().output_type; match return_type { Type::Unit => {} // Do nothing - Type::Tuple(tuple) => { - match tuple.length() { - 0 | 1 => unreachable!("Parsing guarantees that a tuple type has at least two elements"), - len => { - for _ in 0..len { - let destination_register = format!("r{}", self.next_register); - destinations.push(destination_register); - self.next_register += 1; - } + Type::Tuple(tuple) => match tuple.length() { + 0 | 1 => unreachable!("Parsing guarantees that a tuple type has at least two elements"), + len => { + for _ in 0..len { + let destination_register = format!("r{}", self.next_register); + destinations.push(destination_register); + self.next_register += 1; } } - } + }, _ => { let destination_register = format!("r{}", self.next_register); destinations.push(destination_register); diff --git a/compiler/passes/src/code_generation/visit_statements.rs b/compiler/passes/src/code_generation/visit_statements.rs index a304f1ffe3..8aa446dfe3 100644 --- a/compiler/passes/src/code_generation/visit_statements.rs +++ b/compiler/passes/src/code_generation/visit_statements.rs @@ -55,19 +55,18 @@ impl<'a> CodeGenerator<'a> { } fn visit_assert(&mut self, input: &'a AssertStatement) -> String { - let mut generate_assert_instruction = - |name: &str, left: &'a Expression, right: &'a Expression| { - let (left_operand, left_instructions) = self.visit_expression(left); - let (right_operand, right_instructions) = self.visit_expression(right); - let assert_instruction = format!(" {name} {left_operand} {right_operand};\n"); + let mut generate_assert_instruction = |name: &str, left: &'a Expression, right: &'a Expression| { + let (left_operand, left_instructions) = self.visit_expression(left); + let (right_operand, right_instructions) = self.visit_expression(right); + let assert_instruction = format!(" {name} {left_operand} {right_operand};\n"); - // Concatenate the instructions. - let mut instructions = left_instructions; - instructions.push_str(&right_instructions); - instructions.push_str(&assert_instruction); + // Concatenate the instructions. + let mut instructions = left_instructions; + instructions.push_str(&right_instructions); + instructions.push_str(&assert_instruction); - instructions - }; + instructions + }; match &input.variant { AssertVariant::Assert(expr) => { let (operand, mut instructions) = self.visit_expression(expr); @@ -82,69 +81,68 @@ impl<'a> CodeGenerator<'a> { } fn visit_return(&mut self, input: &'a ReturnStatement) -> String { - let mut outputs = - match input.expression { - // Skip empty return statements. - Expression::Unit(_) => String::new(), - _ => { - let (operand, mut expression_instructions) = self.visit_expression(&input.expression); - // Get the output type of the function. - let output = if self.in_finalize { - // Note that the first unwrap is safe, since `current_function` is set in `visit_function`. - self.current_function.unwrap().finalize.as_ref().unwrap().output.iter() - } else { - // Note that this unwrap is safe, since `current_function` is set in `visit_function`. - self.current_function.unwrap().output.iter() - }; - // If the operand string is empty, initialize an empty vector. - let operand_strings = match operand.is_empty() { - true => vec![], - false => operand.split(' ').collect_vec(), - }; - let instructions = operand_strings - .iter() - .zip_eq(output) - .map(|(operand, output)| { - match output { - Output::Internal(output) => { - let visibility = if self.is_transition_function { - match self.in_finalize { - // If in finalize block, the default visibility is public. - true => match output.mode { - Mode::None => Mode::Public, - mode => mode, - }, - // If not in finalize block, the default visibility is private. - false => match output.mode { - Mode::None => Mode::Private, - mode => mode, - }, - } - } else { - // Only program functions have visibilities associated with their outputs. - Mode::None - }; - format!( - " output {} as {};\n", - operand, - self.visit_type_with_visibility(&output.type_, visibility) - ) - } - Output::External(output) => { - format!( - " output {} as {}.aleo/{}.record;\n", - operand, output.program_name, output.record, - ) - } + let mut outputs = match input.expression { + // Skip empty return statements. + Expression::Unit(_) => String::new(), + _ => { + let (operand, mut expression_instructions) = self.visit_expression(&input.expression); + // Get the output type of the function. + let output = if self.in_finalize { + // Note that the first unwrap is safe, since `current_function` is set in `visit_function`. + self.current_function.unwrap().finalize.as_ref().unwrap().output.iter() + } else { + // Note that this unwrap is safe, since `current_function` is set in `visit_function`. + self.current_function.unwrap().output.iter() + }; + // If the operand string is empty, initialize an empty vector. + let operand_strings = match operand.is_empty() { + true => vec![], + false => operand.split(' ').collect_vec(), + }; + let instructions = operand_strings + .iter() + .zip_eq(output) + .map(|(operand, output)| { + match output { + Output::Internal(output) => { + let visibility = if self.is_transition_function { + match self.in_finalize { + // If in finalize block, the default visibility is public. + true => match output.mode { + Mode::None => Mode::Public, + mode => mode, + }, + // If not in finalize block, the default visibility is private. + false => match output.mode { + Mode::None => Mode::Private, + mode => mode, + }, + } + } else { + // Only program functions have visibilities associated with their outputs. + Mode::None + }; + format!( + " output {} as {};\n", + operand, + self.visit_type_with_visibility(&output.type_, visibility) + ) } - }) - .join(""); + Output::External(output) => { + format!( + " output {} as {}.aleo/{}.record;\n", + operand, output.program_name, output.record, + ) + } + } + }) + .join(""); - expression_instructions.push_str(&instructions); + expression_instructions.push_str(&instructions); - expression_instructions - } - }; + expression_instructions + } + }; // Initialize storage for the instructions. let mut instructions = String::new(); diff --git a/compiler/passes/src/common/symbol_table/function_symbol.rs b/compiler/passes/src/common/symbol_table/function_symbol.rs index f52906f5c4..1d3c7307f7 100644 --- a/compiler/passes/src/common/symbol_table/function_symbol.rs +++ b/compiler/passes/src/common/symbol_table/function_symbol.rs @@ -55,9 +55,10 @@ impl SymbolTable { variant: func.variant, _span: func.span, input: func.input.clone(), - finalize: func.finalize.as_ref().map( - |finalize| FinalizeData { input: finalize.input.clone(), output_type: finalize.output_type.clone() } - ), + finalize: func.finalize.as_ref().map(|finalize| FinalizeData { + input: finalize.input.clone(), + output_type: finalize.output_type.clone(), + }), } } } diff --git a/compiler/passes/src/dead_code_elimination/eliminate_statement.rs b/compiler/passes/src/dead_code_elimination/eliminate_statement.rs index 063bf9c58f..4eeaf0d244 100644 --- a/compiler/passes/src/dead_code_elimination/eliminate_statement.rs +++ b/compiler/passes/src/dead_code_elimination/eliminate_statement.rs @@ -87,13 +87,12 @@ impl StatementReconstructor for DeadCodeEliminator<'_> { self.is_necessary = true; // Visit the statement. - let statement = - Statement::Assign(Box::new(AssignStatement { - place: input.place, - value: self.reconstruct_expression(input.value).0, - span: input.span, - id: input.id, - })); + let statement = Statement::Assign(Box::new(AssignStatement { + place: input.place, + value: self.reconstruct_expression(input.value).0, + span: input.span, + id: input.id, + })); // Unset the `is_necessary` flag. self.is_necessary = false; @@ -182,15 +181,14 @@ impl StatementReconstructor for DeadCodeEliminator<'_> { self.is_necessary = true; // Visit the statement. - let statement = - Statement::Return(ReturnStatement { - expression: self.reconstruct_expression(input.expression).0, - finalize_arguments: input.finalize_arguments.map(|arguments| { - arguments.into_iter().map(|argument| self.reconstruct_expression(argument).0).collect() - }), - span: input.span, - id: input.id, - }); + let statement = Statement::Return(ReturnStatement { + expression: self.reconstruct_expression(input.expression).0, + finalize_arguments: input.finalize_arguments.map(|arguments| { + arguments.into_iter().map(|argument| self.reconstruct_expression(argument).0).collect() + }), + span: input.span, + id: input.id, + }); // Unset the `is_necessary` flag. self.is_necessary = false; diff --git a/compiler/passes/src/destructuring/destructure_statement.rs b/compiler/passes/src/destructuring/destructure_statement.rs index 97e3654cef..8d7189ce74 100644 --- a/compiler/passes/src/destructuring/destructure_statement.rs +++ b/compiler/passes/src/destructuring/destructure_statement.rs @@ -137,32 +137,29 @@ impl StatementReconstructor for Destructurer<'_> { ), // If the lhs is a tuple and the rhs is a tuple, create a new assign statement for each tuple element. (Expression::Tuple(lhs_tuple), Expression::Tuple(rhs_tuple)) => { - let statements = - lhs_tuple - .elements - .into_iter() - .zip_eq(rhs_tuple.elements) - .map(|(lhs, rhs)| { - // Get the type of the rhs. - let type_ = match self.type_table.get(&lhs.id()) { - Some(type_) => type_.clone(), - None => { - unreachable!( - "Type checking guarantees that the type of the lhs is in the type table." - ) - } - }; - // Set the type of the lhs. - self.type_table.insert(rhs.id(), type_); - // Return the assign statement. - Statement::Assign(Box::new(AssignStatement { - place: lhs, - value: rhs, - span: Default::default(), - id: self.node_builder.next_id(), - })) - }) - .collect(); + let statements = lhs_tuple + .elements + .into_iter() + .zip_eq(rhs_tuple.elements) + .map(|(lhs, rhs)| { + // Get the type of the rhs. + let type_ = match self.type_table.get(&lhs.id()) { + Some(type_) => type_.clone(), + None => { + unreachable!("Type checking guarantees that the type of the lhs is in the type table.") + } + }; + // Set the type of the lhs. + self.type_table.insert(rhs.id(), type_); + // Return the assign statement. + Statement::Assign(Box::new(AssignStatement { + place: lhs, + value: rhs, + span: Default::default(), + id: self.node_builder.next_id(), + })) + }) + .collect(); (Statement::dummy(Default::default(), self.node_builder.next_id()), statements) } // If the lhs is a tuple and the rhs is an identifier that is a tuple, create a new assign statement for each tuple element. diff --git a/compiler/passes/src/flattening/flatten_statement.rs b/compiler/passes/src/flattening/flatten_statement.rs index b991b4ada2..9a47421112 100644 --- a/compiler/passes/src/flattening/flatten_statement.rs +++ b/compiler/passes/src/flattening/flatten_statement.rs @@ -62,32 +62,31 @@ impl StatementReconstructor for Flattener<'_> { let mut statements = Vec::new(); // Flatten the arguments of the assert statement. - let assert = - AssertStatement { - span: input.span, - id: input.id, - variant: match input.variant { - AssertVariant::Assert(expression) => { - let (expression, additional_statements) = self.reconstruct_expression(expression); - statements.extend(additional_statements); - AssertVariant::Assert(expression) - } - AssertVariant::AssertEq(left, right) => { - let (left, additional_statements) = self.reconstruct_expression(left); - statements.extend(additional_statements); - let (right, additional_statements) = self.reconstruct_expression(right); - statements.extend(additional_statements); - AssertVariant::AssertEq(left, right) - } - AssertVariant::AssertNeq(left, right) => { - let (left, additional_statements) = self.reconstruct_expression(left); - statements.extend(additional_statements); - let (right, additional_statements) = self.reconstruct_expression(right); - statements.extend(additional_statements); - AssertVariant::AssertNeq(left, right) - } - }, - }; + let assert = AssertStatement { + span: input.span, + id: input.id, + variant: match input.variant { + AssertVariant::Assert(expression) => { + let (expression, additional_statements) = self.reconstruct_expression(expression); + statements.extend(additional_statements); + AssertVariant::Assert(expression) + } + AssertVariant::AssertEq(left, right) => { + let (left, additional_statements) = self.reconstruct_expression(left); + statements.extend(additional_statements); + let (right, additional_statements) = self.reconstruct_expression(right); + statements.extend(additional_statements); + AssertVariant::AssertEq(left, right) + } + AssertVariant::AssertNeq(left, right) => { + let (left, additional_statements) = self.reconstruct_expression(left); + statements.extend(additional_statements); + let (right, additional_statements) = self.reconstruct_expression(right); + statements.extend(additional_statements); + AssertVariant::AssertNeq(left, right) + } + }, + }; // Add the appropriate guards. match self.construct_guard() { diff --git a/compiler/passes/src/flattening/flattener.rs b/compiler/passes/src/flattening/flattener.rs index 9b210d56e2..1cf6ae2193 100644 --- a/compiler/passes/src/flattening/flattener.rs +++ b/compiler/passes/src/flattening/flattener.rs @@ -392,71 +392,68 @@ impl<'a> Flattener<'a> { // Initialize a vector to accumulate any statements generated. let mut statements = Vec::new(); // For each struct member, construct a new ternary expression. - let members = - struct_ - .members - .iter() - .map(|Member { identifier, type_, .. }| { - // Create an assignment statement for the first access expression. - let (first, stmt) = self.unique_simple_assign_statement(Expression::Access( - AccessExpression::Member(MemberAccess { - inner: Box::new(Expression::Identifier(*first)), - name: *identifier, - span: Default::default(), - id: { - // Create a new node ID for the access expression. - let id = self.node_builder.next_id(); - // Set the type of the node ID. - self.type_table.insert(id, type_.clone()); - id - }, - }), - )); - statements.push(stmt); - // Create an assignment statement for the second access expression. - let (second, stmt) = self.unique_simple_assign_statement(Expression::Access( - AccessExpression::Member(MemberAccess { - inner: Box::new(Expression::Identifier(*second)), - name: *identifier, - span: Default::default(), - id: { - // Create a new node ID for the access expression. - let id = self.node_builder.next_id(); - // Set the type of the node ID. - self.type_table.insert(id, type_.clone()); - id - }, - }), - )); - statements.push(stmt); - // Recursively reconstruct the ternary expression. - let (expression, stmts) = self.reconstruct_ternary(TernaryExpression { - condition: Box::new(condition.clone()), - // Access the member of the first expression. - if_true: Box::new(Expression::Identifier(first)), - // Access the member of the second expression. - if_false: Box::new(Expression::Identifier(second)), + let members = struct_ + .members + .iter() + .map(|Member { identifier, type_, .. }| { + // Create an assignment statement for the first access expression. + let (first, stmt) = + self.unique_simple_assign_statement(Expression::Access(AccessExpression::Member(MemberAccess { + inner: Box::new(Expression::Identifier(*first)), + name: *identifier, span: Default::default(), id: { - // Create a new node ID for the ternary expression. + // Create a new node ID for the access expression. let id = self.node_builder.next_id(); // Set the type of the node ID. self.type_table.insert(id, type_.clone()); id }, - }); - - // Accumulate any statements generated. - statements.extend(stmts); - - StructVariableInitializer { - identifier: *identifier, - expression: Some(expression), + }))); + statements.push(stmt); + // Create an assignment statement for the second access expression. + let (second, stmt) = + self.unique_simple_assign_statement(Expression::Access(AccessExpression::Member(MemberAccess { + inner: Box::new(Expression::Identifier(*second)), + name: *identifier, span: Default::default(), - id: self.node_builder.next_id(), - } - }) - .collect(); + id: { + // Create a new node ID for the access expression. + let id = self.node_builder.next_id(); + // Set the type of the node ID. + self.type_table.insert(id, type_.clone()); + id + }, + }))); + statements.push(stmt); + // Recursively reconstruct the ternary expression. + let (expression, stmts) = self.reconstruct_ternary(TernaryExpression { + condition: Box::new(condition.clone()), + // Access the member of the first expression. + if_true: Box::new(Expression::Identifier(first)), + // Access the member of the second expression. + if_false: Box::new(Expression::Identifier(second)), + span: Default::default(), + id: { + // Create a new node ID for the ternary expression. + let id = self.node_builder.next_id(); + // Set the type of the node ID. + self.type_table.insert(id, type_.clone()); + id + }, + }); + + // Accumulate any statements generated. + statements.extend(stmts); + + StructVariableInitializer { + identifier: *identifier, + expression: Some(expression), + span: Default::default(), + id: self.node_builder.next_id(), + } + }) + .collect(); let (expr, stmts) = self.reconstruct_struct_init(StructExpression { name: struct_.identifier, @@ -492,66 +489,65 @@ impl<'a> Flattener<'a> { // Initialize a vector to accumulate any statements generated. let mut statements = Vec::new(); // For each tuple element, construct a new ternary expression. - let elements = - tuple_type - .elements() - .iter() - .enumerate() - .map(|(i, type_)| { - // Create an assignment statement for the first access expression. - let (first, stmt) = - self.unique_simple_assign_statement(Expression::Access(AccessExpression::Tuple(TupleAccess { - tuple: Box::new(Expression::Identifier(*first)), - index: NonNegativeNumber::from(i), - span: Default::default(), - id: { - // Create a new node ID for the access expression. - let id = self.node_builder.next_id(); - // Set the type of the node ID. - self.type_table.insert(id, type_.clone()); - id - }, - }))); - statements.push(stmt); - // Create an assignment statement for the second access expression. - let (second, stmt) = - self.unique_simple_assign_statement(Expression::Access(AccessExpression::Tuple(TupleAccess { - tuple: Box::new(Expression::Identifier(*second)), - index: NonNegativeNumber::from(i), - span: Default::default(), - id: { - // Create a new node ID for the access expression. - let id = self.node_builder.next_id(); - // Set the type of the node ID. - self.type_table.insert(id, type_.clone()); - id - }, - }))); - statements.push(stmt); - - // Recursively reconstruct the ternary expression. - let (expression, stmts) = self.reconstruct_ternary(TernaryExpression { - condition: Box::new(condition.clone()), - // Access the member of the first expression. - if_true: Box::new(Expression::Identifier(first)), - // Access the member of the second expression. - if_false: Box::new(Expression::Identifier(second)), + let elements = tuple_type + .elements() + .iter() + .enumerate() + .map(|(i, type_)| { + // Create an assignment statement for the first access expression. + let (first, stmt) = + self.unique_simple_assign_statement(Expression::Access(AccessExpression::Tuple(TupleAccess { + tuple: Box::new(Expression::Identifier(*first)), + index: NonNegativeNumber::from(i), span: Default::default(), id: { - // Create a new node ID for the ternary expression. + // Create a new node ID for the access expression. let id = self.node_builder.next_id(); // Set the type of the node ID. self.type_table.insert(id, type_.clone()); id }, - }); + }))); + statements.push(stmt); + // Create an assignment statement for the second access expression. + let (second, stmt) = + self.unique_simple_assign_statement(Expression::Access(AccessExpression::Tuple(TupleAccess { + tuple: Box::new(Expression::Identifier(*second)), + index: NonNegativeNumber::from(i), + span: Default::default(), + id: { + // Create a new node ID for the access expression. + let id = self.node_builder.next_id(); + // Set the type of the node ID. + self.type_table.insert(id, type_.clone()); + id + }, + }))); + statements.push(stmt); - // Accumulate any statements generated. - statements.extend(stmts); + // Recursively reconstruct the ternary expression. + let (expression, stmts) = self.reconstruct_ternary(TernaryExpression { + condition: Box::new(condition.clone()), + // Access the member of the first expression. + if_true: Box::new(Expression::Identifier(first)), + // Access the member of the second expression. + if_false: Box::new(Expression::Identifier(second)), + span: Default::default(), + id: { + // Create a new node ID for the ternary expression. + let id = self.node_builder.next_id(); + // Set the type of the node ID. + self.type_table.insert(id, type_.clone()); + id + }, + }); - expression - }) - .collect(); + // Accumulate any statements generated. + statements.extend(stmts); + + expression + }) + .collect(); // Construct the tuple expression. let tuple = TupleExpression { diff --git a/compiler/passes/src/loop_unrolling/unroller.rs b/compiler/passes/src/loop_unrolling/unroller.rs index e902b6a551..c95f03843c 100644 --- a/compiler/passes/src/loop_unrolling/unroller.rs +++ b/compiler/passes/src/loop_unrolling/unroller.rs @@ -192,42 +192,41 @@ impl<'a> Unroller<'a> { self.type_table.insert(id, input.type_.clone()); // Reconstruct `iteration_count` as a `Literal`. - let value = - match input.type_ { - Type::Integer(IntegerType::I8) => { - Literal::Integer(IntegerType::I8, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::I16) => { - Literal::Integer(IntegerType::I16, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::I32) => { - Literal::Integer(IntegerType::I32, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::I64) => { - Literal::Integer(IntegerType::I64, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::I128) => { - Literal::Integer(IntegerType::I128, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::U8) => { - Literal::Integer(IntegerType::U8, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::U16) => { - Literal::Integer(IntegerType::U16, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::U32) => { - Literal::Integer(IntegerType::U32, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::U64) => { - Literal::Integer(IntegerType::U64, iteration_count.to_string(), Default::default(), id) - } - Type::Integer(IntegerType::U128) => { - Literal::Integer(IntegerType::U128, iteration_count.to_string(), Default::default(), id) - } - _ => unreachable!( - "The iteration variable must be an integer type. This should be enforced by type checking." - ), - }; + let value = match input.type_ { + Type::Integer(IntegerType::I8) => { + Literal::Integer(IntegerType::I8, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::I16) => { + Literal::Integer(IntegerType::I16, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::I32) => { + Literal::Integer(IntegerType::I32, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::I64) => { + Literal::Integer(IntegerType::I64, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::I128) => { + Literal::Integer(IntegerType::I128, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::U8) => { + Literal::Integer(IntegerType::U8, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::U16) => { + Literal::Integer(IntegerType::U16, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::U32) => { + Literal::Integer(IntegerType::U32, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::U64) => { + Literal::Integer(IntegerType::U64, iteration_count.to_string(), Default::default(), id) + } + Type::Integer(IntegerType::U128) => { + Literal::Integer(IntegerType::U128, iteration_count.to_string(), Default::default(), id) + } + _ => unreachable!( + "The iteration variable must be an integer type. This should be enforced by type checking." + ), + }; // Add the loop variable as a constant for the current scope self.constant_propagation_table diff --git a/compiler/passes/src/static_single_assignment/rename_expression.rs b/compiler/passes/src/static_single_assignment/rename_expression.rs index 3ead92c9a8..ef0ac09492 100644 --- a/compiler/passes/src/static_single_assignment/rename_expression.rs +++ b/compiler/passes/src/static_single_assignment/rename_expression.rs @@ -207,13 +207,12 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> { let (expression, mut statements) = self.consume_expression(*input.expression); // Construct and accumulate a unique assignment statement storing the result of the cast expression. - let (place, statement) = - self.unique_simple_assign_statement(Expression::Cast(CastExpression { - expression: Box::new(expression), - type_: input.type_, - span: input.span, - id: input.id, - })); + let (place, statement) = self.unique_simple_assign_statement(Expression::Cast(CastExpression { + expression: Box::new(expression), + type_: input.type_, + span: input.span, + id: input.id, + })); statements.push(statement); (Expression::Identifier(place), statements) @@ -281,13 +280,12 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> { } // Construct and accumulate a new assignment statement for the struct expression. - let (place, statement) = - self.unique_simple_assign_statement(Expression::Struct(StructExpression { - name: input.name, - span: input.span, - members: reordered_members, - id: input.id, - })); + let (place, statement) = self.unique_simple_assign_statement(Expression::Struct(StructExpression { + name: input.name, + span: input.span, + members: reordered_members, + id: input.id, + })); statements.push(statement); (Expression::Identifier(place), statements) @@ -377,9 +375,12 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> { let (receiver, mut statements) = self.consume_expression(*input.receiver); // Construct and accumulate a new assignment statement for the unary expression. - let (place, statement) = self.unique_simple_assign_statement(Expression::Unary( - UnaryExpression { op: input.op, receiver: Box::new(receiver), span: input.span, id: input.id } - )); + let (place, statement) = self.unique_simple_assign_statement(Expression::Unary(UnaryExpression { + op: input.op, + receiver: Box::new(receiver), + span: input.span, + id: input.id, + })); statements.push(statement); (Expression::Identifier(place), statements) diff --git a/compiler/passes/src/static_single_assignment/rename_statement.rs b/compiler/passes/src/static_single_assignment/rename_statement.rs index 59d7479660..576e59bc30 100644 --- a/compiler/passes/src/static_single_assignment/rename_statement.rs +++ b/compiler/passes/src/static_single_assignment/rename_statement.rs @@ -198,14 +198,13 @@ impl StatementConsumer for StaticSingleAssigner<'_> { self.type_table.insert(id, type_); // Construct a ternary expression for the phi function. - let (value, stmts) = - self.consume_ternary(TernaryExpression { - condition: Box::new(condition.clone()), - if_true, - if_false, - span: Default::default(), - id, - }); + let (value, stmts) = self.consume_ternary(TernaryExpression { + condition: Box::new(condition.clone()), + if_true, + if_false, + span: Default::default(), + id, + }); statements.extend(stmts); @@ -291,17 +290,22 @@ impl StatementConsumer for StaticSingleAssigner<'_> { } // Construct the lhs of the assignment. - let place = Expression::Tuple( - TupleExpression { elements, span: Default::default(), id: self.node_builder.next_id() } - ); + let place = Expression::Tuple(TupleExpression { + elements, + span: Default::default(), + id: self.node_builder.next_id(), + }); // Update the type of the lhs. self.type_table.insert(place.id(), Type::Tuple(tuple_type_)); // Create the assignment statement. - let assignment = Statement::Assign( - Box::new(AssignStatement { place, value, span: definition.span, id: definition.id }) - ); + let assignment = Statement::Assign(Box::new(AssignStatement { + place, + value, + span: definition.span, + id: definition.id, + })); statements.push(assignment); } @@ -397,9 +401,12 @@ impl StatementConsumer for StaticSingleAssigner<'_> { }); // Add the simplified return statement to the list of produced statements. - statements.push(Statement::Return( - ReturnStatement { expression, finalize_arguments: finalize_args, span: input.span, id: input.id } - )); + statements.push(Statement::Return(ReturnStatement { + expression, + finalize_arguments: finalize_args, + span: input.span, + id: input.id, + })); statements } diff --git a/compiler/passes/src/type_checking/check_expressions.rs b/compiler/passes/src/type_checking/check_expressions.rs index 5560563d42..1f406513cf 100644 --- a/compiler/passes/src/type_checking/check_expressions.rs +++ b/compiler/passes/src/type_checking/check_expressions.rs @@ -235,9 +235,10 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> { self.emit_err(TypeCheckerError::type_should_be(type_, "struct", access.inner.span())); } None => { - self.emit_err( - TypeCheckerError::could_not_determine_type(&access.inner, access.inner.span()) - ); + self.emit_err(TypeCheckerError::could_not_determine_type( + &access.inner, + access.inner.span(), + )); } } } @@ -287,9 +288,11 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> { } // The array cannot have more than `MAX_ARRAY_ELEMENTS` elements. num_elements => { - self.emit_err( - TypeCheckerError::array_too_large(num_elements, Testnet3::MAX_ARRAY_ELEMENTS, input.span()) - ); + self.emit_err(TypeCheckerError::array_too_large( + num_elements, + Testnet3::MAX_ARRAY_ELEMENTS, + input.span(), + )); None } }; diff --git a/compiler/passes/src/type_checking/check_program.rs b/compiler/passes/src/type_checking/check_program.rs index 4fdf83a9ae..3590d50b3d 100644 --- a/compiler/passes/src/type_checking/check_program.rs +++ b/compiler/passes/src/type_checking/check_program.rs @@ -121,19 +121,18 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> { // For records, enforce presence of the `owner: Address` member. if input.is_record { - let check_has_field = |need, expected_ty: Type| match input - .members - .iter() - .find_map(|Member { identifier, type_, .. }| (identifier.name == need).then_some((identifier, type_))) - { - Some((_, actual_ty)) if expected_ty.eq_flat(actual_ty) => {} // All good, found + right type! - Some((field, _)) => { - self.emit_err(TypeCheckerError::record_var_wrong_type(field, expected_ty, input.span())); - } - None => { - self.emit_err(TypeCheckerError::required_record_variable(need, expected_ty, input.span())); - } - }; + let check_has_field = + |need, expected_ty: Type| match input.members.iter().find_map(|Member { identifier, type_, .. }| { + (identifier.name == need).then_some((identifier, type_)) + }) { + Some((_, actual_ty)) if expected_ty.eq_flat(actual_ty) => {} // All good, found + right type! + Some((field, _)) => { + self.emit_err(TypeCheckerError::record_var_wrong_type(field, expected_ty, input.span())); + } + None => { + self.emit_err(TypeCheckerError::required_record_variable(need, expected_ty, input.span())); + } + }; check_has_field(sym::owner, Type::Address); } diff --git a/compiler/passes/src/type_checking/check_statements.rs b/compiler/passes/src/type_checking/check_statements.rs index 7559999235..1bd4e0a1ab 100644 --- a/compiler/passes/src/type_checking/check_statements.rs +++ b/compiler/passes/src/type_checking/check_statements.rs @@ -68,24 +68,21 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> { } }; - let var_type = - if let Some(var) = self.symbol_table.borrow_mut().lookup_variable(var_name.name) { - match &var.declaration { - VariableType::Const => { - self.emit_err(TypeCheckerError::cannot_assign_to_const_var(var_name, var.span)) - } - VariableType::Input(Mode::Constant) => { - self.emit_err(TypeCheckerError::cannot_assign_to_const_input(var_name, var.span)) - } - _ => {} + let var_type = if let Some(var) = self.symbol_table.borrow_mut().lookup_variable(var_name.name) { + match &var.declaration { + VariableType::Const => self.emit_err(TypeCheckerError::cannot_assign_to_const_var(var_name, var.span)), + VariableType::Input(Mode::Constant) => { + self.emit_err(TypeCheckerError::cannot_assign_to_const_input(var_name, var.span)) } + _ => {} + } - Some(var.type_.clone()) - } else { - self.emit_err(TypeCheckerError::unknown_sym("variable", var_name.name, var_name.span)); + Some(var.type_.clone()) + } else { + self.emit_err(TypeCheckerError::unknown_sym("variable", var_name.name, var_name.span)); - None - }; + None + }; if var_type.is_some() { self.visit_expression(&input.value, &var_type); @@ -178,18 +175,16 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> { // Enforce that Constant variables have literal expressions on right-hand side match &input.value { Expression::Literal(_) => (), - Expression::Tuple(tuple_expression) => { - match tuple_expression.elements.len() { - 0 | 1 => unreachable!("Parsing guarantees that tuple types have at least two elements."), - _ => { - if tuple_expression.elements.iter().any(|expr| !matches!(expr, Expression::Literal(_))) { - self.emit_err(TypeCheckerError::const_declaration_must_be_literal_or_tuple_of_literals( - input.span, - )) - } + Expression::Tuple(tuple_expression) => match tuple_expression.elements.len() { + 0 | 1 => unreachable!("Parsing guarantees that tuple types have at least two elements."), + _ => { + if tuple_expression.elements.iter().any(|expr| !matches!(expr, Expression::Literal(_))) { + self.emit_err(TypeCheckerError::const_declaration_must_be_literal_or_tuple_of_literals( + input.span, + )) } } - } + }, _ => self.emit_err(TypeCheckerError::const_declaration_must_be_literal_or_tuple_of_literals(input.span())), } diff --git a/compiler/passes/src/type_checking/checker.rs b/compiler/passes/src/type_checking/checker.rs index 7c6bfc2f4e..0cc3f86229 100644 --- a/compiler/passes/src/type_checking/checker.rs +++ b/compiler/passes/src/type_checking/checker.rs @@ -387,9 +387,11 @@ impl<'a> TypeChecker<'a> { ) -> Option { // Check that the number of arguments is correct. if arguments.len() != core_function.num_args() { - self.emit_err( - TypeCheckerError::incorrect_num_args_to_call(core_function.num_args(), arguments.len(), function_span) - ); + self.emit_err(TypeCheckerError::incorrect_num_args_to_call( + core_function.num_args(), + arguments.len(), + function_span, + )); return None; } @@ -980,9 +982,10 @@ impl<'a> TypeChecker<'a> { CoreFunction::MappingContains => { // Check that the operation is invoked in a `finalize` block. if !self.is_finalize { - self.handler.emit_err( - TypeCheckerError::invalid_operation_outside_finalize("Mapping::contains", function_span) - ) + self.handler.emit_err(TypeCheckerError::invalid_operation_outside_finalize( + "Mapping::contains", + function_span, + )) } // Check that the first argument is a mapping. if let Some(mapping_type) = self.assert_mapping_type(&arguments[0].0, arguments[0].1) { diff --git a/compiler/span/src/source_map.rs b/compiler/span/src/source_map.rs index 495f8e256f..3a66e4aa05 100644 --- a/compiler/span/src/source_map.rs +++ b/compiler/span/src/source_map.rs @@ -99,11 +99,10 @@ impl SourceMap { /// Returns a displayable representation of the `span` as a string. pub fn span_to_string(&self, span: Span) -> String { - let loc = - match self.span_to_location(span) { - None => return "no-location".to_string(), - Some(l) => l, - }; + let loc = match self.span_to_location(span) { + None => return "no-location".to_string(), + Some(l) => l, + }; if loc.line_start == loc.line_stop { format!("{}:{}-{}", loc.line_start, loc.col_start, loc.col_stop) @@ -340,11 +339,10 @@ fn normalize_newlines(src: &mut String) { let mut gap_len = 0; let mut tail = buf.as_mut_slice(); loop { - let idx = - match find_crlf(&tail[gap_len..]) { - None => tail.len(), - Some(idx) => idx + gap_len, - }; + let idx = match find_crlf(&tail[gap_len..]) { + None => tail.len(), + Some(idx) => idx + gap_len, + }; tail.copy_within(gap_len..idx, 0); tail = &mut tail[idx - gap_len..]; if tail.len() == gap_len { diff --git a/docs/grammar/src/main.rs b/docs/grammar/src/main.rs index 7fd363494b..8eff45acbe 100644 --- a/docs/grammar/src/main.rs +++ b/docs/grammar/src/main.rs @@ -205,11 +205,10 @@ fn main() -> Result<()> { // Parse ABNF to get list of all definitions. // Rust ABNF does not provide support for `%s` (case sensitive strings, part of // the standard); so we need to remove all occurrences before parsing. - let parsed = - abnf::rulelist(&str::replace(&grammar, "%s", "")).map_err(|e| { - eprintln!("{}", &e); - anyhow::anyhow!(e) - })?; + let parsed = abnf::rulelist(&str::replace(&grammar, "%s", "")).map_err(|e| { + eprintln!("{}", &e); + anyhow::anyhow!(e) + })?; // Init parser and run it. That's it. let mut parser = Processor::new(&grammar, parsed); diff --git a/leo/cli/commands/execute.rs b/leo/cli/commands/execute.rs index a2fb45064d..2df5b01510 100644 --- a/leo/cli/commands/execute.rs +++ b/leo/cli/commands/execute.rs @@ -54,14 +54,13 @@ impl Command for Execute { fn apply(self, context: Context, input: Self::Input) -> Result { // If input values are provided, then run the program with those inputs. // Otherwise, use the input file. - let mut inputs = - match self.inputs.is_empty() { - true => match input { - (Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits), - _ => Vec::new(), - }, - false => self.inputs, - }; + let mut inputs = match self.inputs.is_empty() { + true => match input { + (Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits), + _ => Vec::new(), + }, + false => self.inputs, + }; // Compose the `execute` command. let mut arguments = vec![SNARKVM_COMMAND.to_string(), self.name]; diff --git a/leo/cli/commands/run.rs b/leo/cli/commands/run.rs index b80c76f88f..ec27f4d812 100644 --- a/leo/cli/commands/run.rs +++ b/leo/cli/commands/run.rs @@ -46,14 +46,13 @@ impl Command for Run { fn apply(self, context: Context, input: Self::Input) -> Result { // If input values are provided, then run the program with those inputs. // Otherwise, use the input file. - let mut inputs = - match self.inputs.is_empty() { - true => match input { - (Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits), - _ => Vec::new(), - }, - false => self.inputs, - }; + let mut inputs = match self.inputs.is_empty() { + true => match input { + (Some(input_ast), circuits) => input_ast.program_inputs(&self.name, circuits), + _ => Vec::new(), + }, + false => self.inputs, + }; // Compose the `run` command. let mut arguments = vec![SNARKVM_COMMAND.to_string(), self.name]; diff --git a/leo/package/src/inputs/input.rs b/leo/package/src/inputs/input.rs index 9ca47d7eee..e7e47e0098 100644 --- a/leo/package/src/inputs/input.rs +++ b/leo/package/src/inputs/input.rs @@ -56,8 +56,8 @@ impl InputFile { pub fn read_from<'a>(&self, path: &'a Path) -> Result<(String, Cow<'a, Path>)> { let path = self.setup_file_path(path); - let input = - fs::read_to_string(&path).map_err(|_| PackageError::failed_to_read_input_file(path.clone().into_owned()))?; + let input = fs::read_to_string(&path) + .map_err(|_| PackageError::failed_to_read_input_file(path.clone().into_owned()))?; Ok((input, path)) } diff --git a/tests/test-framework/src/runner.rs b/tests/test-framework/src/runner.rs index 3f9be72ddd..1fb9e0f78d 100644 --- a/tests/test-framework/src/runner.rs +++ b/tests/test-framework/src/runner.rs @@ -93,13 +93,12 @@ impl TestCases { let mut path_prefix = PathBuf::from(env!("CARGO_MANIFEST_DIR")); path_prefix.push("../../tests"); - let mut new = - Self { - tests: Vec::new(), - path_prefix, - expectation_category: expectation_category.to_string(), - fail_categories: Vec::new(), - }; + let mut new = Self { + tests: Vec::new(), + path_prefix, + expectation_category: expectation_category.to_string(), + fail_categories: Vec::new(), + }; let tests = new.load_tests(additional_check); (new, tests) } @@ -189,11 +188,10 @@ pub fn run_tests(runner: &T, expectation_category: &str) { let mut outputs = vec![]; cases.process_tests(configs, |cases, (path, content, test_name, config)| { - let namespace = - match runner.resolve_namespace(&config.namespace) { - Some(ns) => ns, - None => return, - }; + let namespace = match runner.resolve_namespace(&config.namespace) { + Some(ns) => ns, + None => return, + }; let (expectation_path, expectations) = cases.load_expectations(path); From 220eef35de9658e6db254fc81ab4f5092405a627 Mon Sep 17 00:00:00 2001 From: Pranav Gaddamadugu <23022326+d0cd@users.noreply.github.com> Date: Mon, 4 Dec 2023 18:29:31 -0800 Subject: [PATCH 4/5] Add timeout to CI --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9c1dda12aa..b50225e32a 100755 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -111,7 +111,7 @@ jobs: name: leo new command: | export LEO=/home/circleci/project/project/bin/leo - ./project/.circleci/leo-new.sh + timeout 30m ./project/.circleci/leo-new.sh leo-clean: docker: From 4730bb0fb4a5134ea77a17bcdddc415f551ed5e5 Mon Sep 17 00:00:00 2001 From: Pranav Gaddamadugu <23022326+d0cd@users.noreply.github.com> Date: Mon, 4 Dec 2023 18:44:03 -0800 Subject: [PATCH 5/5] Clippy --- compiler/ast/src/value/mod.rs | 2 ++ compiler/passes/src/destructuring/destructure_statement.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/ast/src/value/mod.rs b/compiler/ast/src/value/mod.rs index 8dcab4f5d0..428f963c16 100644 --- a/compiler/ast/src/value/mod.rs +++ b/compiler/ast/src/value/mod.rs @@ -73,6 +73,7 @@ macro_rules! implement_const_unary { ) => { // TODO: This is temporary since the currently unused code is used in constant folding. #[allow(dead_code)] + #[allow(clippy::redundant_closure_call)] pub(crate) fn $name(self, span: Span) -> Result { use Value::*; @@ -159,6 +160,7 @@ macro_rules! implement_const_binary { ) => { // This is temporary since the currently unused code is used in constant folding. #[allow(dead_code)] + #[allow(clippy::redundant_closure_call)] pub(crate) fn $name(self, other: Self, span: Span) -> Result { use Value::*; diff --git a/compiler/passes/src/destructuring/destructure_statement.rs b/compiler/passes/src/destructuring/destructure_statement.rs index 8d7189ce74..c5cd99cd92 100644 --- a/compiler/passes/src/destructuring/destructure_statement.rs +++ b/compiler/passes/src/destructuring/destructure_statement.rs @@ -173,7 +173,7 @@ impl StatementReconstructor for Destructurer<'_> { let statements = lhs_tuple .elements .into_iter() - .zip_eq(rhs_tuple.elements.into_iter()) + .zip_eq(rhs_tuple.elements) .map(|(lhs, rhs)| { // Get the type of the rhs. let type_ = match self.type_table.get(&lhs.id()) {