From aa805f2747ce6f93d2da9c12cf58754180ab8f05 Mon Sep 17 00:00:00 2001 From: evan-schott <53463459+evan-schott@users.noreply.github.com> Date: Tue, 3 Oct 2023 10:14:37 -0700 Subject: [PATCH] fixes --- compiler/ast/src/passes/consumer.rs | 3 + compiler/ast/src/passes/reconstructor.rs | 18 +++- compiler/ast/src/passes/visitor.rs | 7 +- compiler/ast/src/program/program_scope.rs | 4 +- compiler/ast/src/statement/const_.rs | 46 +++++++++ compiler/ast/src/statement/mod.rs | 10 ++ compiler/parser/src/parser/file.rs | 4 +- compiler/parser/src/parser/statement.rs | 25 +---- .../src/code_generation/visit_statements.rs | 3 + .../common/constant_propagation_table/mod.rs | 10 +- .../src/loop_unrolling/unroll_expression.rs | 4 +- .../src/loop_unrolling/unroll_program.rs | 63 ++---------- .../src/loop_unrolling/unroll_statement.rs | 53 +++++++--- .../passes/src/loop_unrolling/unroller.rs | 19 +++- .../rename_statement.rs | 5 + .../passes/src/type_checking/check_program.rs | 2 +- .../src/type_checking/check_statements.rs | 96 +++++++++++++------ errors/README.md | 6 +- .../loop_unroller/loop_unroller_errors.rs | 4 +- errors/src/errors/mod.rs | 5 +- .../errors/type_checker/type_checker_error.rs | 13 +++ .../constants/const_tuple_declaration.out | 15 +++ .../compiler/constants/constant_finalize.out | 14 +-- .../constants/constant_loop_bound.out | 14 +-- .../decreasing_constant_loop_bound_fail.out | 2 +- .../compiler/constants/loop_unrolling.out | 14 +-- .../compiler/constants/tuple_definition.out | 15 --- .../constants/tuple_definition_fail.out | 2 +- .../compiler/constants/tuple_shadow_fail.out | 2 +- .../statements/loop_decreasing_fail.out | 2 +- tests/expectations/execution/counter.out | 14 +-- .../constants/const_tuple_declaration.leo | 17 ++++ .../compiler/constants/loop_unrolling.leo | 6 +- .../compiler/constants/tuple_definition.leo | 11 --- .../constants/tuple_definition_fail.leo | 2 +- 35 files changed, 324 insertions(+), 206 deletions(-) create mode 100644 compiler/ast/src/statement/const_.rs create mode 100644 tests/expectations/compiler/constants/const_tuple_declaration.out delete mode 100644 tests/expectations/compiler/constants/tuple_definition.out create mode 100644 tests/tests/compiler/constants/const_tuple_declaration.leo delete mode 100644 tests/tests/compiler/constants/tuple_definition.leo diff --git a/compiler/ast/src/passes/consumer.rs b/compiler/ast/src/passes/consumer.rs index db6458ab66..7f0e6adba7 100644 --- a/compiler/ast/src/passes/consumer.rs +++ b/compiler/ast/src/passes/consumer.rs @@ -78,6 +78,7 @@ pub trait StatementConsumer { Statement::Block(stmt) => self.consume_block(stmt), Statement::Conditional(stmt) => self.consume_conditional(stmt), Statement::Console(stmt) => self.consume_console(stmt), + Statement::Const(stmt) => self.consume_const(stmt), Statement::Definition(stmt) => self.consume_definition(stmt), Statement::Expression(stmt) => self.consume_expression_statement(stmt), Statement::Iteration(stmt) => self.consume_iteration(*stmt), @@ -95,6 +96,8 @@ pub trait StatementConsumer { fn consume_console(&mut self, input: ConsoleStatement) -> Self::Output; + fn consume_const(&mut self, input: ConstDeclaration) -> Self::Output; + fn consume_definition(&mut self, input: DefinitionStatement) -> Self::Output; fn consume_expression_statement(&mut self, input: ExpressionStatement) -> Self::Output; diff --git a/compiler/ast/src/passes/reconstructor.rs b/compiler/ast/src/passes/reconstructor.rs index 9a17dc8368..eb04622887 100644 --- a/compiler/ast/src/passes/reconstructor.rs +++ b/compiler/ast/src/passes/reconstructor.rs @@ -202,6 +202,7 @@ pub trait StatementReconstructor: ExpressionReconstructor { } Statement::Conditional(stmt) => self.reconstruct_conditional(stmt), Statement::Console(stmt) => self.reconstruct_console(stmt), + Statement::Const(stmt) => self.reconstruct_const(stmt), Statement::Definition(stmt) => self.reconstruct_definition(stmt), Statement::Expression(stmt) => self.reconstruct_expression_statement(stmt), Statement::Iteration(stmt) => self.reconstruct_iteration(*stmt), @@ -287,6 +288,19 @@ pub trait StatementReconstructor: ExpressionReconstructor { ) } + fn reconstruct_const(&mut self, input: ConstDeclaration) -> (Statement, Self::AdditionalOutput) { + ( + Statement::Const(ConstDeclaration { + place: input.place, + type_: input.type_, + value: self.reconstruct_expression(input.value).0, + span: input.span, + id: input.id, + }), + Default::default(), + ) + } + fn reconstruct_definition(&mut self, input: DefinitionStatement) -> (Statement, Self::AdditionalOutput) { ( Statement::Definition(DefinitionStatement { @@ -368,7 +382,7 @@ pub trait ProgramReconstructor: StatementReconstructor { structs: input.structs.into_iter().map(|(i, c)| (i, self.reconstruct_struct(c))).collect(), mappings: input.mappings.into_iter().map(|(id, mapping)| (id, self.reconstruct_mapping(mapping))).collect(), functions: input.functions.into_iter().map(|(i, f)| (i, self.reconstruct_function(f))).collect(), - consts: input.consts.into_iter().map(|(i, c)| (i, self.reconstruct_const(c))).collect(), + consts: input.consts.into_iter().map(|(i, c)| (i, self.reconstruct_global_const(c))).collect(), span: input.span, } } @@ -396,7 +410,7 @@ pub trait ProgramReconstructor: StatementReconstructor { } } - fn reconstruct_const(&mut self, input: DefinitionStatement) -> DefinitionStatement { + fn reconstruct_global_const(&mut self, input: ConstDeclaration) -> ConstDeclaration { input } diff --git a/compiler/ast/src/passes/visitor.rs b/compiler/ast/src/passes/visitor.rs index 8b4804f9ea..7e66ca6c3c 100644 --- a/compiler/ast/src/passes/visitor.rs +++ b/compiler/ast/src/passes/visitor.rs @@ -128,6 +128,7 @@ pub trait StatementVisitor<'a>: ExpressionVisitor<'a> { Statement::Block(stmt) => self.visit_block(stmt), Statement::Conditional(stmt) => self.visit_conditional(stmt), Statement::Console(stmt) => self.visit_console(stmt), + Statement::Const(stmt) => self.visit_const(stmt), Statement::Definition(stmt) => self.visit_definition(stmt), Statement::Expression(stmt) => self.visit_expression_statement(stmt), Statement::Iteration(stmt) => self.visit_iteration(stmt), @@ -177,6 +178,10 @@ pub trait StatementVisitor<'a>: ExpressionVisitor<'a> { }; } + fn visit_const(&mut self, input: &'a ConstDeclaration) { + self.visit_expression(&input.value, &Default::default()); + } + fn visit_definition(&mut self, input: &'a DefinitionStatement) { self.visit_expression(&input.value, &Default::default()); } @@ -233,6 +238,4 @@ pub trait ProgramVisitor<'a>: StatementVisitor<'a> { self.visit_block(&finalize.block); } } - - fn visit_const(&mut self, _input: &'a DefinitionStatement) {} } diff --git a/compiler/ast/src/program/program_scope.rs b/compiler/ast/src/program/program_scope.rs index c40083c80a..3184e3373f 100644 --- a/compiler/ast/src/program/program_scope.rs +++ b/compiler/ast/src/program/program_scope.rs @@ -16,7 +16,7 @@ //! A Leo program scope consists of struct, function, and mapping definitions. -use crate::{DefinitionStatement, Function, Mapping, ProgramId, Struct}; +use crate::{ConstDeclaration, Function, Mapping, ProgramId, Struct}; use indexmap::IndexMap; use leo_span::{Span, Symbol}; @@ -29,7 +29,7 @@ pub struct ProgramScope { /// The program id of the program scope. pub program_id: ProgramId, /// A map from const names to const definitions. - pub consts: IndexMap, + pub consts: IndexMap, /// A map from struct names to struct definitions. pub structs: IndexMap, /// A map from mapping names to mapping definitions. diff --git a/compiler/ast/src/statement/const_.rs b/compiler/ast/src/statement/const_.rs new file mode 100644 index 0000000000..ab172a6b58 --- /dev/null +++ b/compiler/ast/src/statement/const_.rs @@ -0,0 +1,46 @@ +// Copyright (C) 2019-2023 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{Expression, Identifier, Node, NodeID, Type}; +use leo_span::Span; + +use serde::{Deserialize, Serialize}; +use std::fmt; + +/// A constant declaration statement. +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] +pub struct ConstDeclaration { + /// The place to assign to. As opposed to `DefinitionStatement`, this can only be an identifier + pub place: Identifier, + /// The type of the binding, if specified, or inferred otherwise. + pub type_: Type, + /// An initializer value for the binding. + pub value: Expression, + /// The span excluding the semicolon. + pub span: Span, + /// The ID of the node. + pub id: NodeID, +} + +impl fmt::Display for ConstDeclaration { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.place)?; + write!(f, ": {}", self.type_)?; + write!(f, " = {};", self.value) + } +} + +crate::simple_node_impl!(ConstDeclaration); diff --git a/compiler/ast/src/statement/mod.rs b/compiler/ast/src/statement/mod.rs index 7dae07ef71..b96d0d327b 100644 --- a/compiler/ast/src/statement/mod.rs +++ b/compiler/ast/src/statement/mod.rs @@ -29,6 +29,9 @@ pub use conditional::*; pub mod console; pub use console::*; +pub mod const_; +pub use const_::*; + pub mod definition; pub use definition::*; @@ -61,6 +64,8 @@ pub enum Statement { Conditional(ConditionalStatement), /// A console logging statement. Console(ConsoleStatement), + /// A binding from identifier to constant value. + Const(ConstDeclaration), /// A binding or set of bindings / variables to declare. Definition(DefinitionStatement), /// An expression statement @@ -86,6 +91,7 @@ impl fmt::Display for Statement { Statement::Block(x) => x.fmt(f), Statement::Conditional(x) => x.fmt(f), Statement::Console(x) => x.fmt(f), + Statement::Const(x) => x.fmt(f), Statement::Definition(x) => x.fmt(f), Statement::Expression(x) => x.fmt(f), Statement::Iteration(x) => x.fmt(f), @@ -103,6 +109,7 @@ impl Node for Statement { Block(n) => n.span(), Conditional(n) => n.span(), Console(n) => n.span(), + Const(n) => n.span(), Definition(n) => n.span(), Expression(n) => n.span(), Iteration(n) => n.span(), @@ -118,6 +125,7 @@ impl Node for Statement { Block(n) => n.set_span(span), Conditional(n) => n.set_span(span), Console(n) => n.set_span(span), + Const(n) => n.set_span(span), Definition(n) => n.set_span(span), Expression(n) => n.set_span(span), Iteration(n) => n.set_span(span), @@ -133,6 +141,7 @@ impl Node for Statement { Block(n) => n.id(), Conditional(n) => n.id(), Console(n) => n.id(), + Const(n) => n.id(), Definition(n) => n.id(), Expression(n) => n.id(), Iteration(n) => n.id(), @@ -148,6 +157,7 @@ impl Node for Statement { Block(n) => n.set_id(id), Conditional(n) => n.set_id(id), Console(n) => n.set_id(id), + Const(n) => n.set_id(id), Definition(n) => n.set_id(id), Expression(n) => n.set_id(id), Iteration(n) => n.set_id(id), diff --git a/compiler/parser/src/parser/file.rs b/compiler/parser/src/parser/file.rs index 2d8c64c2b6..27807177f5 100644 --- a/compiler/parser/src/parser/file.rs +++ b/compiler/parser/src/parser/file.rs @@ -146,8 +146,8 @@ impl ParserContext<'_> { while self.has_next() { match &self.token.token { Token::Const => { - let definition = self.parse_const_definition_statement()?; - consts.insert(Symbol::intern(&definition.place.to_string()), definition); + let declaration = self.parse_const_declaration_statement()?; + consts.insert(Symbol::intern(&declaration.place.to_string()), declaration); } Token::Struct | Token::Record => { let (id, struct_) = self.parse_struct()?; diff --git a/compiler/parser/src/parser/statement.rs b/compiler/parser/src/parser/statement.rs index ac460ca97d..c79d75c14d 100644 --- a/compiler/parser/src/parser/statement.rs +++ b/compiler/parser/src/parser/statement.rs @@ -45,7 +45,7 @@ impl ParserContext<'_> { Token::For => Ok(Statement::Iteration(Box::new(self.parse_loop_statement()?))), Token::Assert | Token::AssertEq | Token::AssertNeq => Ok(self.parse_assert_statement()?), Token::Let => Ok(Statement::Definition(self.parse_definition_statement()?)), - Token::Const => Ok(Statement::Definition(self.parse_const_definition_statement()?)), + Token::Const => Ok(Statement::Const(self.parse_const_declaration_statement()?)), Token::LeftCurly => Ok(Statement::Block(self.parse_block()?)), Token::Console => Err(ParserError::console_statements_are_not_yet_supported(self.token.span).into()), Token::Finalize => Err(ParserError::finalize_statements_are_deprecated(self.token.span).into()), @@ -315,34 +315,19 @@ impl ParserContext<'_> { Ok(ConsoleStatement { span: keyword + span, function, id: self.node_builder.next_id() }) } - /// Returns a [`DefinitionStatement`] AST node if the next tokens represent a const definition statement. - pub(super) fn parse_const_definition_statement(&mut self) -> Result { + /// Returns a [`ConstDeclaration`] AST node if the next tokens represent a const declaration statement. + pub(super) fn parse_const_declaration_statement(&mut self) -> Result { self.expect(&Token::Const)?; let decl_span = self.prev_token.span; - let decl_type = match &self.prev_token.token { - Token::Const => DeclarationType::Const, - _ => unreachable!( - "parse_const_definition_statement shouldn't produce this as have already ensured that first token was 'Const'" - ), - }; // Parse variable name and type. - let place = self.parse_expression()?; - self.expect(&Token::Colon)?; - let type_ = self.parse_type()?.0; + let (place, type_, _) = self.parse_typed_ident()?; self.expect(&Token::Assign)?; let value = self.parse_expression()?; self.expect(&Token::Semicolon)?; - Ok(DefinitionStatement { - span: decl_span + value.span(), - declaration_type: decl_type, - place, - type_, - value, - id: self.node_builder.next_id(), - }) + Ok(ConstDeclaration { span: decl_span + value.span(), place, type_, value, id: self.node_builder.next_id() }) } /// Returns a [`DefinitionStatement`] AST node if the next tokens represent a definition statement. diff --git a/compiler/passes/src/code_generation/visit_statements.rs b/compiler/passes/src/code_generation/visit_statements.rs index 2ed9ea3eac..aa2b7dbea7 100644 --- a/compiler/passes/src/code_generation/visit_statements.rs +++ b/compiler/passes/src/code_generation/visit_statements.rs @@ -44,6 +44,9 @@ impl<'a> CodeGenerator<'a> { Statement::Block(stmt) => self.visit_block(stmt), Statement::Conditional(stmt) => self.visit_conditional(stmt), Statement::Console(stmt) => self.visit_console(stmt), + Statement::Const(_) => { + unreachable!("`ConstStatement`s should not be in the AST at this phase of compilation.") + } Statement::Definition(stmt) => self.visit_definition(stmt), Statement::Expression(stmt) => self.visit_expression_statement(stmt), Statement::Iteration(stmt) => self.visit_iteration(stmt), diff --git a/compiler/passes/src/common/constant_propagation_table/mod.rs b/compiler/passes/src/common/constant_propagation_table/mod.rs index 58f1f1da9a..7f623ab7b0 100644 --- a/compiler/passes/src/common/constant_propagation_table/mod.rs +++ b/compiler/passes/src/common/constant_propagation_table/mod.rs @@ -17,7 +17,7 @@ use indexmap::IndexMap; use std::cell::RefCell; -use leo_ast::Literal; +use leo_ast::Expression; use leo_errors::Result; use leo_span::Symbol; @@ -30,7 +30,7 @@ pub struct ConstantPropagationTable { pub(crate) parent: Option>, /// The known constants in the current scope /// This field is populated as necessary. - pub(crate) constants: IndexMap, + pub(crate) constants: IndexMap, /// The index of the current scope. pub(crate) scope_index: usize, /// The sub-scopes of this scope. @@ -47,8 +47,8 @@ impl ConstantPropagationTable { } /// Inserts a constant into the constant propagation table. - pub fn insert_constant(&mut self, symbol: Symbol, literal: Literal) -> Result<()> { - self.constants.insert(symbol, literal); + pub fn insert_constant(&mut self, symbol: Symbol, expr: Expression) -> Result<()> { + self.constants.insert(symbol, expr); Ok(()) } @@ -66,7 +66,7 @@ impl ConstantPropagationTable { } /// Attempts to lookup a constant in the constant propagation table. - pub fn lookup_constant(&self, symbol: Symbol) -> Option<&Literal> { + pub fn lookup_constant(&self, symbol: Symbol) -> Option<&Expression> { if let Some(constant) = self.constants.get(&symbol) { Some(constant) } else if let Some(parent) = self.parent.as_ref() { diff --git a/compiler/passes/src/loop_unrolling/unroll_expression.rs b/compiler/passes/src/loop_unrolling/unroll_expression.rs index 71654f4cd1..b9939ad92e 100644 --- a/compiler/passes/src/loop_unrolling/unroll_expression.rs +++ b/compiler/passes/src/loop_unrolling/unroll_expression.rs @@ -23,8 +23,8 @@ impl ExpressionReconstructor for Unroller<'_> { fn reconstruct_identifier(&mut self, input: Identifier) -> (Expression, Self::AdditionalOutput) { // Substitute the identifier with the constant value if it is a constant. - if let Some(literal) = self.constant_propagation_table.borrow().lookup_constant(input.name) { - return (Expression::Literal(literal.clone()), Default::default()); + if let Some(expr) = self.constant_propagation_table.borrow().lookup_constant(input.name) { + return (expr.clone(), Default::default()); } (Expression::Identifier(input), Default::default()) } diff --git a/compiler/passes/src/loop_unrolling/unroll_program.rs b/compiler/passes/src/loop_unrolling/unroll_program.rs index a80083c2d0..452dcf8730 100644 --- a/compiler/passes/src/loop_unrolling/unroll_program.rs +++ b/compiler/passes/src/loop_unrolling/unroll_program.rs @@ -14,20 +14,23 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_ast::{Expression::Literal, *}; -use leo_span::Symbol; +use indexmap::IndexMap; +use leo_ast::*; use crate::Unroller; impl ProgramReconstructor for Unroller<'_> { fn reconstruct_program_scope(&mut self, input: ProgramScope) -> ProgramScope { - let new_consts = input.consts.into_iter().map(|(i, c)| (i, self.reconstruct_const(c))).collect(); + // Don't need to reconstructed consts, just need to add them to constant propagation table + input.consts.into_iter().for_each(|(_, c)| { + self.reconstruct_const(c); + }); ProgramScope { program_id: input.program_id, structs: input.structs, mappings: input.mappings, functions: input.functions.into_iter().map(|(i, f)| (i, self.reconstruct_function(f))).collect(), - consts: new_consts, + consts: IndexMap::new(), span: input.span, } } @@ -83,56 +86,4 @@ impl ProgramReconstructor for Unroller<'_> { reconstructed_function } - - fn reconstruct_const(&mut self, input: DefinitionStatement) -> DefinitionStatement { - // Reconstruct the RHS expression to allow for constant propagation - let reconstructed_value_expression = self.reconstruct_expression(input.value.clone()).0; - - // Helper function to add global constants to constant variable table - let insert_variable = |symbol: Symbol, value: &Expression| { - if let Literal(literal) = value { - if let Err(err) = self.constant_propagation_table.borrow_mut().insert_constant(symbol, literal.clone()) - { - self.handler.emit_err(err); - } - } else { - unreachable!("Type checking guarantees that the value of a constant is a literal."); - } - }; - - // No matter if doing multiple definitions in one line or not, insert all global constants into the constant propagation table - match &input.place { - Expression::Identifier(identifier) => { - insert_variable(identifier.name, &reconstructed_value_expression); - } - Expression::Tuple(tuple_expression) => { - let tuple_values: &Vec = match &reconstructed_value_expression { - Expression::Tuple(tuple_value_expression) => &tuple_value_expression.elements, - _ => unreachable!( - "Definition statement that defines tuple of variables must be assigned to tuple of values" - ), - }; - - for (i, element) in tuple_expression.elements.iter().enumerate() { - let identifier = match element { - Expression::Identifier(identifier) => identifier, - _ => unreachable!("All elements of a definition tuple must be identifiers"), - }; - insert_variable(identifier.name, &tuple_values[i].clone()); - } - } - _ => unreachable!( - "Type checking guarantees that the lhs of a `DefinitionStatement` is either an identifier or tuple." - ), - } - - DefinitionStatement { - declaration_type: input.declaration_type, - place: input.place, - type_: input.type_, - value: reconstructed_value_expression, - span: input.span, - id: input.id, - } - } } diff --git a/compiler/passes/src/loop_unrolling/unroll_statement.rs b/compiler/passes/src/loop_unrolling/unroll_statement.rs index 96c6274e13..f98250815e 100644 --- a/compiler/passes/src/loop_unrolling/unroll_statement.rs +++ b/compiler/passes/src/loop_unrolling/unroll_statement.rs @@ -50,26 +50,51 @@ impl StatementReconstructor for Unroller<'_> { (block, Default::default()) } + fn reconstruct_const(&mut self, input: ConstDeclaration) -> (Statement, Self::AdditionalOutput) { + // Reconstruct the RHS expression to allow for constant propagation + let reconstructed_value_expression = self.reconstruct_expression(input.value.clone()).0; + + // Add to constant propagation table. Since TC completed we know that the RHS is a literal or tuple of literals. + if let Err(err) = self.constant_propagation_table.borrow_mut().insert_constant(input.place.name, input.value) { + self.handler.emit_err(err); + } + + // Remove from symbol table + if self.symbol_table.borrow().lookup_variable(input.place.name).is_some() { + if let Err(err) = self.symbol_table.borrow_mut().remove_variable_from_current_scope(input.place.name) { + self.handler.emit_err(err); + } + } + + ( + Statement::Const(ConstDeclaration { + place: input.place, + type_: input.type_, + value: reconstructed_value_expression, + span: input.span, + id: input.id, + }), + true, + ) + } + fn reconstruct_definition(&mut self, input: DefinitionStatement) -> (Statement, Self::AdditionalOutput) { // Helper function to add variables to symbol table - let insert_variable = |symbol: Symbol, type_: Type, span: Span, declaration: VariableType| { - if let Err(err) = - self.symbol_table.borrow_mut().insert_variable(symbol, VariableSymbol { type_, span, declaration }) - { + let insert_variable = |symbol: Symbol, type_: Type, span: Span| { + if let Err(err) = self.symbol_table.borrow_mut().insert_variable(symbol, VariableSymbol { + type_, + span, + declaration: VariableType::Mut, + }) { self.handler.emit_err(err); } }; - let declaration = - if input.declaration_type == DeclarationType::Const { VariableType::Const } else { VariableType::Mut }; - // If we are unrolling a loop, then we need to repopulate the symbol table. - // If we are not unrolling a loop, the we need to remove constants from the symbol table. - // We always need to add constant variables to the constant variable table. - if declaration == VariableType::Mut && self.is_unrolling { + if self.is_unrolling { match &input.place { Expression::Identifier(identifier) => { - insert_variable(identifier.name, input.type_.clone(), input.span, declaration); + insert_variable(identifier.name, input.type_.clone(), input.span); } Expression::Tuple(tuple_expression) => { let tuple_type = match input.type_ { @@ -83,15 +108,13 @@ impl StatementReconstructor for Unroller<'_> { Expression::Identifier(identifier) => identifier, _ => unreachable!("Type checking guarantees that if the lhs is a tuple, all of its elements are identifiers.") }; - insert_variable(identifier.name, input.type_.clone(), input.span, declaration); + insert_variable(identifier.name, input.type_.clone(), input.span); }); } _ => unreachable!( "Type checking guarantees that the lhs of a `DefinitionStatement` is either an identifier or tuple." ), } - } else if declaration == VariableType::Const { - return (Statement::Definition(self.reconstruct_const(input.clone())), true); } // Reconstruct the expression and return @@ -104,7 +127,7 @@ impl StatementReconstructor for Unroller<'_> { span: input.span, id: input.id, }), - false, + Default::default(), ) } diff --git a/compiler/passes/src/loop_unrolling/unroller.rs b/compiler/passes/src/loop_unrolling/unroller.rs index d220290f7d..2749a1ce1b 100644 --- a/compiler/passes/src/loop_unrolling/unroller.rs +++ b/compiler/passes/src/loop_unrolling/unroller.rs @@ -16,6 +16,7 @@ use leo_ast::{ Block, + Expression, IntegerType, IterationStatement, Literal, @@ -240,12 +241,24 @@ impl<'a> Unroller<'a> { // Add the loop variable as a constant for the current scope self.constant_propagation_table .borrow_mut() - .insert_constant(input.variable.name, value) + .insert_constant(input.variable.name, Expression::Literal(value.clone())) .expect("Failed to insert constant into CPT"); // Reconstruct the statements in the loop body. - let statements: Vec<_> = - input.block.statements.clone().into_iter().map(|s| self.reconstruct_statement(s).0).collect(); + let statements: Vec<_> = input + .block + .statements + .clone() + .into_iter() + .filter_map(|s| { + let (reconstructed_statement, additional_output) = self.reconstruct_statement(s); + if additional_output { + None // Exclude this statement from the block since it is a constant variable definition + } else { + Some(reconstructed_statement) + } + }) + .collect(); let block = Statement::Block(Block { statements, span: input.block.span, id: input.block.id }); diff --git a/compiler/passes/src/static_single_assignment/rename_statement.rs b/compiler/passes/src/static_single_assignment/rename_statement.rs index fea08fac1e..861c9848c7 100644 --- a/compiler/passes/src/static_single_assignment/rename_statement.rs +++ b/compiler/passes/src/static_single_assignment/rename_statement.rs @@ -26,6 +26,7 @@ use leo_ast::{ CallExpression, ConditionalStatement, ConsoleStatement, + ConstDeclaration, DefinitionStatement, Expression, ExpressionConsumer, @@ -214,6 +215,10 @@ impl StatementConsumer for StaticSingleAssigner<'_> { unreachable!("Parsing guarantees that console statements are not present in the program.") } + fn consume_const(&mut self, _: ConstDeclaration) -> Self::Output { + unreachable!("Loop unrolling pass removes all constant declaration statements in the program.") + } + /// Consumes the `DefinitionStatement` into an `AssignStatement`, renaming the left-hand-side as appropriate. fn consume_definition(&mut self, definition: DefinitionStatement) -> Self::Output { // First consume the right-hand-side of the definition. diff --git a/compiler/passes/src/type_checking/check_program.rs b/compiler/passes/src/type_checking/check_program.rs index 6aba26a16d..06bec954e8 100644 --- a/compiler/passes/src/type_checking/check_program.rs +++ b/compiler/passes/src/type_checking/check_program.rs @@ -54,7 +54,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> { fn visit_program_scope(&mut self, input: &'a ProgramScope) { // Typecheck each const definition, and append to symbol table. - input.consts.values().for_each(|c| self.visit_definition(c)); + input.consts.values().for_each(|c| self.visit_const(c)); // Typecheck each struct definition. input.structs.values().for_each(|function| self.visit_struct(function)); diff --git a/compiler/passes/src/type_checking/check_statements.rs b/compiler/passes/src/type_checking/check_statements.rs index 436de46bfe..8d7c86b8fe 100644 --- a/compiler/passes/src/type_checking/check_statements.rs +++ b/compiler/passes/src/type_checking/check_statements.rs @@ -35,6 +35,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> { Statement::Block(stmt) => self.visit_block(stmt), Statement::Conditional(stmt) => self.visit_conditional(stmt), Statement::Console(stmt) => self.visit_console(stmt), + Statement::Const(stmt) => self.visit_const(stmt), Statement::Definition(stmt) => self.visit_definition(stmt), Statement::Expression(stmt) => self.visit_expression_statement(stmt), Statement::Iteration(stmt) => self.visit_iteration(stmt), @@ -150,10 +151,57 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> { unreachable!("Parsing guarantees that console statements are not present in the AST."); } - fn visit_definition(&mut self, input: &'a DefinitionStatement) { - let declaration = - if input.declaration_type == DeclarationType::Const { VariableType::Const } else { VariableType::Mut }; + fn visit_const(&mut self, input: &'a ConstDeclaration) { + // Check that the type of the definition is not a unit type, singleton tuple type, or nested tuple type. + match &input.type_ { + // If the type is an empty tuple, return an error. + Type::Unit => self.emit_err(TypeCheckerError::lhs_must_be_identifier_or_tuple(input.span)), + // If the type is a singleton tuple, return an error. + Type::Tuple(tuple) => match tuple.len() { + 0 | 1 => unreachable!("Parsing guarantees that tuple types have at least two elements."), + _ => { + if tuple.iter().any(|type_| matches!(type_, Type::Tuple(_))) { + self.emit_err(TypeCheckerError::nested_tuple_type(input.span)) + } + } + }, + Type::Mapping(_) | Type::Err => unreachable!( + "Parsing guarantees that `mapping` and `err` types are not present at this location in the AST." + ), + // Otherwise, the type is valid. + _ => (), // Do nothing + } + // 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, + )) + } + } + }, + _ => self.emit_err(TypeCheckerError::const_declaration_must_be_literal_or_tuple_of_literals(input.span())), + } + + // Check the expression on the right-hand side. + self.visit_expression(&input.value, &Some(input.type_.clone())); + + // Add constants to symbol table so that any references to them in later statements will pass TC + if let Err(err) = self.symbol_table.borrow_mut().insert_variable(input.place.name, VariableSymbol { + type_: input.type_.clone(), + span: input.place.span, + declaration: VariableType::Const, + }) { + self.handler.emit_err(err); + } + } + + fn visit_definition(&mut self, input: &'a DefinitionStatement) { // Check that the type of the definition is defined. self.assert_type_is_defined(&input.type_, input.span); @@ -177,35 +225,17 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> { _ => (), // Do nothing } - // Enforce additional constraint that constant definitions can only be literals or tuples of literals. This will be removed after constant folding. - if input.declaration_type == DeclarationType::Const { - // 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, - )) - } - } - }, - _ => self - .emit_err(TypeCheckerError::const_declaration_must_be_literal_or_tuple_of_literals(input.span())), - } - } - // Check the expression on the right-hand side. self.visit_expression(&input.value, &Some(input.type_.clone())); // TODO: Dedup with unrolling pass. // Helper to insert the variables into the symbol table. - let insert_variable = |symbol: Symbol, type_: Type, span: Span, declaration: VariableType| { - if let Err(err) = - self.symbol_table.borrow_mut().insert_variable(symbol, VariableSymbol { type_, span, declaration }) - { + let insert_variable = |symbol: Symbol, type_: Type, span: Span| { + if let Err(err) = self.symbol_table.borrow_mut().insert_variable(symbol, VariableSymbol { + type_, + span, + declaration: VariableType::Mut, + }) { self.handler.emit_err(err); } }; @@ -213,7 +243,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> { // Insert the variables in the into the symbol table. match &input.place { Expression::Identifier(identifier) => { - insert_variable(identifier.name, input.type_.clone(), identifier.span, declaration) + insert_variable(identifier.name, input.type_.clone(), identifier.span) } Expression::Tuple(tuple_expression) => { let tuple_type = match &input.type_ { @@ -222,6 +252,14 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> { "Type checking guarantees that if the lhs is a tuple, its associated type is also a tuple." ), }; + if tuple_expression.elements.len() != tuple_type.len() { + return self.emit_err(TypeCheckerError::incorrect_num_tuple_elements( + tuple_expression.elements.len(), + tuple_type.len(), + input.place.span(), + )); + } + tuple_expression.elements.iter().zip_eq(tuple_type.0.iter()).for_each(|(expression, type_)| { let identifier = match expression { Expression::Identifier(identifier) => identifier, @@ -231,7 +269,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> { )); } }; - insert_variable(identifier.name, type_.clone(), identifier.span, declaration) + insert_variable(identifier.name, type_.clone(), identifier.span) }); } _ => self.emit_err(TypeCheckerError::lhs_must_be_identifier_or_tuple(input.place.span())), diff --git a/errors/README.md b/errors/README.md index 1e334f0f1d..a3bfcfaf63 100644 --- a/errors/README.md +++ b/errors/README.md @@ -49,10 +49,14 @@ The errors for the `leo-compiler` crate. Its error codes will range from 6_000-6 The errors for the `leo-imports` crate. Its error codes will range from 4_000-4_999 and be prefixed with the characters `IMP`. -## Input +### Input The errors for the `leo-ast` crate. Its error codes will range from 8_000-8_999 and be prefixed with the characters `INP`. +### Loop Unrolling + +The errors for loop unrolling in the `leo-passes` crate. Its error codes will range from 9_000-9_999 and be prefixed with the characters `LUN`. + ### Package The errors for the `leo-package` crate. Its error codes will range from 5_000-5_999 and be prefixed with the characters `PAK`. diff --git a/errors/src/errors/loop_unroller/loop_unroller_errors.rs b/errors/src/errors/loop_unroller/loop_unroller_errors.rs index eacc646af5..937f9cf83f 100644 --- a/errors/src/errors/loop_unroller/loop_unroller_errors.rs +++ b/errors/src/errors/loop_unroller/loop_unroller_errors.rs @@ -18,9 +18,9 @@ use crate::create_messages; use std::fmt::Debug; create_messages!( - /// AstError enum that represents all the errors for the `leo-ast` crate. + /// LoopUnrollerError enum that represents all the errors for the loop unrolling errors in the `leo-loop_unroller` crate. LoopUnrollerError, - code_mask: 8000i32, + code_mask: 9000i32, code_prefix: "LUN", @formatted diff --git a/errors/src/errors/mod.rs b/errors/src/errors/mod.rs index 4b8e4071b4..e890d7761b 100644 --- a/errors/src/errors/mod.rs +++ b/errors/src/errors/mod.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::loop_unroller::LoopUnrollerError; /// Contains the ASG error definitions. use crate::LeoMessageCode; @@ -38,6 +37,9 @@ pub use self::flattener::*; pub mod input; pub use self::input::*; +pub mod loop_unroller; +pub use self::loop_unroller::*; + /// Contains the Package error definitions. pub mod package; pub use self::package::*; @@ -46,7 +48,6 @@ pub use self::package::*; pub mod parser; pub use self::parser::*; -pub mod loop_unroller; /// Contains the Type Checker error definitions. pub mod type_checker; diff --git a/errors/src/errors/type_checker/type_checker_error.rs b/errors/src/errors/type_checker/type_checker_error.rs index 98ccf0b186..d770e24bfe 100644 --- a/errors/src/errors/type_checker/type_checker_error.rs +++ b/errors/src/errors/type_checker/type_checker_error.rs @@ -671,4 +671,17 @@ create_messages!( help: None, } + @formatted + incorrect_num_tuple_elements { + args: (identifiers: impl Display, types: impl Display), + msg: format!("Expected a tuple with {types} elements, found one with {identifiers} elements"), + help: None, + } + + @formatted + const_declaration_can_only_have_one_binding { + args: (), + msg: format!("A constant declaration statement can only bind a single value"), + help: None, + } ); diff --git a/tests/expectations/compiler/constants/const_tuple_declaration.out b/tests/expectations/compiler/constants/const_tuple_declaration.out new file mode 100644 index 0000000000..e34d2f4d52 --- /dev/null +++ b/tests/expectations/compiler/constants/const_tuple_declaration.out @@ -0,0 +1,15 @@ +--- +namespace: Compile +expectation: Pass +outputs: + - - initial_symbol_table: af2effe11f5047f1accaca1df1d8456dbb355969e1e843ba37eda44257570551 + type_checked_symbol_table: 61642b3cd24a2f6303c7abf5dac2821ed2f739f5d009f448b7eef2693fbfb0eb + unrolled_symbol_table: 751fa39b0cb4c55b0bd8ac36ef03aefc90829cb4f06ed664b5915b16dbaaaa70 + initial_ast: 8147cde7c4f4b40f45e67afc32bb4f1c28e994968b52b4d2c7f40fa9b9ef3d0c + unrolled_ast: d0850814c6ead0d76661bf37b45212d2edbb6b47d38a006d43e5cba4fcc779f1 + ssa_ast: b02e95a4c70b6d2fe4b9ba66d742d6001acf85fee058f0f065525265b5ee9c2b + flattened_ast: 7d8d33926bf19f4e5e00d9611b77284ce467483bb35192e7f4f9c7ae295c559b + inlined_ast: 7d8d33926bf19f4e5e00d9611b77284ce467483bb35192e7f4f9c7ae295c559b + dce_ast: 419b58124f548bd498b1cb0dda20f13505372d86cc2d405e9e97cca9327a3bd9 + bytecode: acfb8fc365ba153cf8598a04dad8ff4ac65b9df6c6356cb077fcf9dafbead7e9 + warnings: "" diff --git a/tests/expectations/compiler/constants/constant_finalize.out b/tests/expectations/compiler/constants/constant_finalize.out index ca9e5803c0..6aaf0ffc74 100644 --- a/tests/expectations/compiler/constants/constant_finalize.out +++ b/tests/expectations/compiler/constants/constant_finalize.out @@ -4,12 +4,12 @@ expectation: Pass outputs: - - initial_symbol_table: 77b127880b95652f948bc184d24fb51eb368cc2ccb022093cd27c2fbc03bb70e type_checked_symbol_table: be1bdc9825b662e2070dabbd8e16d24d51ed989e91e385f9ebf27e11dc12b902 - unrolled_symbol_table: be1bdc9825b662e2070dabbd8e16d24d51ed989e91e385f9ebf27e11dc12b902 - initial_ast: 0ab8753999f0db720682d3600df3575fcb8da517f539ee23844406eef6cdf0d0 - unrolled_ast: 3f0b5beb875ff9de3b98978d7136c946f450f32b0c7bab7ac47257a9c8d4a7ea - ssa_ast: 2fd2a759cd7ab2242c9f7b97bc1241ab81bd26d6e1f35a308792edff76226e8f - flattened_ast: f6ea27693b4afa98e03b9201a01ba174c999395159b952bd2057291224a363f2 - inlined_ast: f6ea27693b4afa98e03b9201a01ba174c999395159b952bd2057291224a363f2 - dce_ast: f6ea27693b4afa98e03b9201a01ba174c999395159b952bd2057291224a363f2 + unrolled_symbol_table: 435f5b6da45d68cf00a82aca5b9bd6e326c5d7d2252811db0e96afd1de00a727 + initial_ast: f7f9f8362006d7a5e3659df72b883a2f21bc5ee43381ccbd023b32de23c5f833 + unrolled_ast: 6ec80c2610eb0231078e39c207e6fef0346325d175c821c4e16d8aa96becedec + ssa_ast: bb89e164033dca2cb1b61d21c2e012bf72ce6d832c94de647a94f3a0ddf579e6 + flattened_ast: 40c0e11be11bed1d1214f8b9a1dba9a34a86070eb9ffbc92827185ceaa458f08 + inlined_ast: 40c0e11be11bed1d1214f8b9a1dba9a34a86070eb9ffbc92827185ceaa458f08 + dce_ast: 40c0e11be11bed1d1214f8b9a1dba9a34a86070eb9ffbc92827185ceaa458f08 bytecode: 88de5519495f51852482cfc5ab129cde77b8d2b53fd2eebfd66472c6fe0cdafe warnings: "" diff --git a/tests/expectations/compiler/constants/constant_loop_bound.out b/tests/expectations/compiler/constants/constant_loop_bound.out index 918c672099..5bc6721357 100644 --- a/tests/expectations/compiler/constants/constant_loop_bound.out +++ b/tests/expectations/compiler/constants/constant_loop_bound.out @@ -4,12 +4,12 @@ expectation: Pass outputs: - - initial_symbol_table: d1eed24f01e5256fec3b444fd3a38b7e25756c5fb20010872884a34d54ef888c type_checked_symbol_table: 89c060252a9e229b91f2ac52e5e3823e04400f3e060ead04999aa4911f42c731 - unrolled_symbol_table: 26537147843c8e9daeda6a7af59b2b4bca86c6f067b08a4f4c3a7b7ffe30e59a - initial_ast: 1b2029fc1b5100e84675a87052375b38af1da27315d22daf1ccf49f17c5e5cf9 - unrolled_ast: 6c9e5266587d4b90c0ea7522edcc4c3a6b00f6cfaadb91c59daba698b2da5b91 - ssa_ast: a69548faa4852b092997ff059e4bbeb2161caada00423171ff0c98a167891165 - flattened_ast: c67bdab30e2af4d0130fc11772176f267e1a7144488fab3ae7bcd33136b3ee47 - inlined_ast: c67bdab30e2af4d0130fc11772176f267e1a7144488fab3ae7bcd33136b3ee47 - dce_ast: c67bdab30e2af4d0130fc11772176f267e1a7144488fab3ae7bcd33136b3ee47 + unrolled_symbol_table: c00e0818651bd9e2c068becdf3819b8d46238e0cfad46c87791efa9c97c6f9de + initial_ast: 310ef81cd18a675700a7c5d315978a5aeddfcb5220d7cb3ebb2c22cdefc72c27 + unrolled_ast: 7e5cc7fedc616597a85fa4a5b46cc5432b93cf2d1f76f615f72d0a287f17232a + ssa_ast: a789faf5dde9e018665a22e2aa96674ca424dfdc6abc954c099113d7136e7e02 + flattened_ast: 6d1021575d55836a866f7b99e87fed633869521e08d97f3d25fdfc2e7e60648d + inlined_ast: 6d1021575d55836a866f7b99e87fed633869521e08d97f3d25fdfc2e7e60648d + dce_ast: 6d1021575d55836a866f7b99e87fed633869521e08d97f3d25fdfc2e7e60648d bytecode: a6350aaded46f7047061f7e68a8ae41eb8aa0d29f02560257ecdc582a6c684f9 warnings: "" diff --git a/tests/expectations/compiler/constants/decreasing_constant_loop_bound_fail.out b/tests/expectations/compiler/constants/decreasing_constant_loop_bound_fail.out index 6d099d369c..9aa0d25a2e 100644 --- a/tests/expectations/compiler/constants/decreasing_constant_loop_bound_fail.out +++ b/tests/expectations/compiler/constants/decreasing_constant_loop_bound_fail.out @@ -2,4 +2,4 @@ namespace: Compile expectation: Fail outputs: - - "Error [ELUN0378000]: The loop range must be increasing.\n --> compiler-test:6:26\n |\n 6 | const STOP: u8 = 0u8;\n | ^^^\n" + - "Error [ELUN0379000]: The loop range must be increasing.\n --> compiler-test:6:26\n |\n 6 | const STOP: u8 = 0u8;\n | ^^^\n" diff --git a/tests/expectations/compiler/constants/loop_unrolling.out b/tests/expectations/compiler/constants/loop_unrolling.out index 5cab0e5d49..996eff1208 100644 --- a/tests/expectations/compiler/constants/loop_unrolling.out +++ b/tests/expectations/compiler/constants/loop_unrolling.out @@ -4,12 +4,12 @@ expectation: Pass outputs: - - initial_symbol_table: c6a4e40ae8f466c3ff6bf5d356d6ba89684438f88015e8ea23ff43eadb662b49 type_checked_symbol_table: 0b88104308fe0b9e390a59a4359d6245170347557911b21ba04cd1d9124da14d - unrolled_symbol_table: 0f5bcb03574cbdb2a6a0f335693d8bc0bca4926ce259fa0e0acc09baba07bcdd - initial_ast: 0418d21afa3636a1e9b0c4440bb1b06633c7674a0157ffb2b1b26b478147fee8 - unrolled_ast: e07e1eab58e31a09d2b4464a0644fe3b4189aeb4d4418963ecdb9c0fdb8a25cc - ssa_ast: b5306dfc16a75fa20fa0c8c8c8df27de7c9cc76399f8245e7baa4998e77d4b5a - flattened_ast: 88e816cddb1f37e20dbf4c53e4c12095a8b6374af790d5210b431c0787607f73 - inlined_ast: 88e816cddb1f37e20dbf4c53e4c12095a8b6374af790d5210b431c0787607f73 - dce_ast: e01c208549e62b4372dcbfd2c24fb4c3bba4e7cb20e7e0a47acf67dd9dda5c63 + unrolled_symbol_table: af56532f8dd6c6ca6f5fc8af3667202298898a54fe2f871a7874684a712f141d + initial_ast: 542dc099a401102c60c971fc4c4a97dc5a885e9b949b647ffd12fa418b82ede0 + unrolled_ast: 6cee219515c51e5b250b0e1905eaeeb27b2d6de0690055bc9e2a8fbb50f5330a + ssa_ast: cd15cc9451d67fd9489a4de0ad5debd70f410ca9b8608bacd408948ee1d79e18 + flattened_ast: a9cb531c3f1a8f3ae4d192d5c630fb0e92800ce2b974017835c90658969cda46 + inlined_ast: a9cb531c3f1a8f3ae4d192d5c630fb0e92800ce2b974017835c90658969cda46 + dce_ast: a9cb531c3f1a8f3ae4d192d5c630fb0e92800ce2b974017835c90658969cda46 bytecode: d9595550f8a3d55b350b4f46059fb01bf63308aa4b4416594c2eb20231f6483a warnings: "" diff --git a/tests/expectations/compiler/constants/tuple_definition.out b/tests/expectations/compiler/constants/tuple_definition.out deleted file mode 100644 index f551cb95f9..0000000000 --- a/tests/expectations/compiler/constants/tuple_definition.out +++ /dev/null @@ -1,15 +0,0 @@ ---- -namespace: Compile -expectation: Pass -outputs: - - - initial_symbol_table: d698a6988e2f4caf3321c2a5b0c0228721f13930b072f738e97747b7d3ade0de - type_checked_symbol_table: 88168597bb3de8d73a3ada9b63c026594d716c75f2deb4b7d20abd2758d6b4d3 - unrolled_symbol_table: 88168597bb3de8d73a3ada9b63c026594d716c75f2deb4b7d20abd2758d6b4d3 - initial_ast: f24907cd9e0f0b5f3fce4efb5eeea7945ec22c4780a31df6870816eb9480632f - unrolled_ast: 764e6b1b9204c5d98a6ccb9354fbee08aac7cc83647c5ebcd2e9c2880daa2544 - ssa_ast: 764e6b1b9204c5d98a6ccb9354fbee08aac7cc83647c5ebcd2e9c2880daa2544 - flattened_ast: 96c6bdf5200642b65e8f6e83228dc0a01c493c13d3b4d9686829b2efca7451fb - inlined_ast: 96c6bdf5200642b65e8f6e83228dc0a01c493c13d3b4d9686829b2efca7451fb - dce_ast: 96c6bdf5200642b65e8f6e83228dc0a01c493c13d3b4d9686829b2efca7451fb - bytecode: 91d9f12af3f91ba9332bdf7303424e4369e14db4b713c13f43afc72a55cfcd4a - warnings: "" diff --git a/tests/expectations/compiler/constants/tuple_definition_fail.out b/tests/expectations/compiler/constants/tuple_definition_fail.out index 3c9b3c5eb5..e1d2f2e926 100644 --- a/tests/expectations/compiler/constants/tuple_definition_fail.out +++ b/tests/expectations/compiler/constants/tuple_definition_fail.out @@ -2,4 +2,4 @@ namespace: Compile expectation: Fail outputs: - - "Error [ETYC0372080]: The value of a const declaration must be a literal\n --> compiler-test:4:5\n |\n 4 | const (GOODBYE,HELLO): (u8,u8) = (0u8,(1u8,1u8));\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nError [ETYC0372058]: A tuple expression cannot contain another tuple expression.\n --> compiler-test:4:43\n |\n 4 | const (GOODBYE,HELLO): (u8,u8) = (0u8,(1u8,1u8));\n | ^^^^^^^^^\nError [ETYC0372023]: Tuples must be explicitly typed in Leo\n --> compiler-test:4:43\n |\n 4 | const (GOODBYE,HELLO): (u8,u8) = (0u8,(1u8,1u8));\n | ^^^^^^^^^\n |\n = The function definition must match the function return statement\n" + - "Error [EPAR0370009]: unexpected string: expected 'identifier', found '('\n --> compiler-test:4:11\n |\n 4 | const (HELLO,GOODBYE): (u8,u8) = (1u8, 1u8);\n | ^" diff --git a/tests/expectations/compiler/constants/tuple_shadow_fail.out b/tests/expectations/compiler/constants/tuple_shadow_fail.out index 683cfe3b79..876771fcff 100644 --- a/tests/expectations/compiler/constants/tuple_shadow_fail.out +++ b/tests/expectations/compiler/constants/tuple_shadow_fail.out @@ -2,4 +2,4 @@ namespace: Compile expectation: Fail outputs: - - "Error [EAST0372009]: variable `HELLO` shadowed by\n --> compiler-test:5:11\n |\n 5 | const HELLO: u8 = 0u8;\n | ^^^^^\n" + - "Error [EPAR0370009]: unexpected string: expected 'identifier', found '('\n --> compiler-test:4:11\n |\n 4 | const (HELLO,GOODBYE): (u8,u8) = (0u8,0u8);\n | ^" diff --git a/tests/expectations/compiler/statements/loop_decreasing_fail.out b/tests/expectations/compiler/statements/loop_decreasing_fail.out index 1aa85ddc1d..b43ebd1a53 100644 --- a/tests/expectations/compiler/statements/loop_decreasing_fail.out +++ b/tests/expectations/compiler/statements/loop_decreasing_fail.out @@ -2,4 +2,4 @@ namespace: Compile expectation: Fail outputs: - - "Error [ELUN0378000]: The loop range must be increasing.\n --> compiler-test:7:28\n |\n 7 | for i: i8 in 10i8..5i8 {\n | ^^^\n" + - "Error [ELUN0379000]: The loop range must be increasing.\n --> compiler-test:7:28\n |\n 7 | for i: i8 in 10i8..5i8 {\n | ^^^\n" diff --git a/tests/expectations/execution/counter.out b/tests/expectations/execution/counter.out index dccab0cbfb..8a6e53ed86 100644 --- a/tests/expectations/execution/counter.out +++ b/tests/expectations/execution/counter.out @@ -4,13 +4,13 @@ expectation: Pass outputs: - - initial_symbol_table: 4194c6207c716b52d30529becd081afc9b7313e8e1ce400cc65c33fac50fab31 type_checked_symbol_table: 51dec1877b8da96c81929eabd624019ae50c181362703756b68d94d002cb2f56 - unrolled_symbol_table: f62721c061790b66cf66c0dbac8f85ca582bb420e6b315e081e7894bb81e8cdf - initial_ast: 40297565663ad5f424bb0ac5a571ea56a99043ce11acc018df07cbbcc2df2994 - unrolled_ast: d00d781141ee230a9b6602ed35a264bde7f84cc3ea904e7aa83ea3edd877e723 - ssa_ast: 5455c22f4e05610c0bd8c2a7ac0d15d8aab1f8ae6cc23fcdb3cc75e75e16519d - flattened_ast: 84a675cf8525bd7a82dabe9fb1542926b34e611fcf4a51e82528cd855b18b5c8 - inlined_ast: 84a675cf8525bd7a82dabe9fb1542926b34e611fcf4a51e82528cd855b18b5c8 - dce_ast: 84a675cf8525bd7a82dabe9fb1542926b34e611fcf4a51e82528cd855b18b5c8 + unrolled_symbol_table: 0b6340ef766a4154f31b5fa00d9bebe8478a8e3c81f091b8433e870ad7213b25 + initial_ast: bc84c92328b456b2a88fadd3998ae180078447418a1adacbc9495f3d9177a38a + unrolled_ast: e9972535de2da936d1db8f65497b529ceedc0a691ea34a9e407447c84311332f + ssa_ast: 5a9e0d139821e42ea9cdb3a75c9b9ccdd10e4368490f2c5a1edca0e3d41913d5 + flattened_ast: 99f8c4ca373d413eba9db8b8949bdf493e6a201298578c22608de3bc8f4abcbf + inlined_ast: 99f8c4ca373d413eba9db8b8949bdf493e6a201298578c22608de3bc8f4abcbf + dce_ast: 99f8c4ca373d413eba9db8b8949bdf493e6a201298578c22608de3bc8f4abcbf bytecode: 6f468335c2ba73721aece1b1018fff421437eee9d52956368d33822d46e8c012 warnings: "" results: diff --git a/tests/tests/compiler/constants/const_tuple_declaration.leo b/tests/tests/compiler/constants/const_tuple_declaration.leo new file mode 100644 index 0000000000..cd06b8e5f6 --- /dev/null +++ b/tests/tests/compiler/constants/const_tuple_declaration.leo @@ -0,0 +1,17 @@ +/* +namespace: Compile +expectation: Pass +*/ + +program test.aleo { + + const B: (u8,u32) = (1u8,1u32); + transition foo() -> u32 { + for i: u32 in 0u32..1u32 { + let d:(u8,u32) = B; + const A:u32 = 1u32; + let c:u32 = A; + } + return 1u32; + } +} \ No newline at end of file diff --git a/tests/tests/compiler/constants/loop_unrolling.leo b/tests/tests/compiler/constants/loop_unrolling.leo index f4e8aefcd6..fbfa74474d 100644 --- a/tests/tests/compiler/constants/loop_unrolling.leo +++ b/tests/tests/compiler/constants/loop_unrolling.leo @@ -1,7 +1,7 @@ /* -namespace: Compile -expectation: Pass -*/ + namespace: Compile + expectation: Pass + */ program test.aleo { const START: u32 = 0u32; diff --git a/tests/tests/compiler/constants/tuple_definition.leo b/tests/tests/compiler/constants/tuple_definition.leo deleted file mode 100644 index f215b30947..0000000000 --- a/tests/tests/compiler/constants/tuple_definition.leo +++ /dev/null @@ -1,11 +0,0 @@ -/* -namespace: Compile -expectation: Pass -*/ - -program test.aleo { - const (HELLO,GOODBYE): (u8,u8) = (1u8, 1u8); - transition foo(a: u8, b: u8, flag: bool) -> u8 { - return GOODBYE; - } -} \ No newline at end of file diff --git a/tests/tests/compiler/constants/tuple_definition_fail.leo b/tests/tests/compiler/constants/tuple_definition_fail.leo index b6b5db4727..e8f09ec404 100644 --- a/tests/tests/compiler/constants/tuple_definition_fail.leo +++ b/tests/tests/compiler/constants/tuple_definition_fail.leo @@ -4,7 +4,7 @@ expectation: Fail */ program test.aleo { - const (GOODBYE,HELLO): (u8,u8) = (0u8,(1u8,1u8)); + const (HELLO,GOODBYE): (u8,u8) = (1u8, 1u8); transition foo(a: u8, b: u8, flag: bool) -> u8 { return GOODBYE; }