diff --git a/compiler/noirc_frontend/src/ast/statement.rs b/compiler/noirc_frontend/src/ast/statement.rs index 6b120ada5b9..af45dc1fde1 100644 --- a/compiler/noirc_frontend/src/ast/statement.rs +++ b/compiler/noirc_frontend/src/ast/statement.rs @@ -44,7 +44,7 @@ pub enum StatementKind { Expression(Expression), Assign(AssignStatement), For(ForLoopStatement), - Loop(Expression, Location /* loop keyword location */), + Loop(LoopStatement), While(WhileStatement), Break, Continue, @@ -904,6 +904,12 @@ pub struct WhileStatement { pub while_keyword_location: Location, } +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct LoopStatement { + pub body: Expression, + pub loop_keyword_location: Location, +} + impl Display for StatementKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -911,7 +917,7 @@ impl Display for StatementKind { StatementKind::Expression(expression) => expression.fmt(f), StatementKind::Assign(assign) => assign.fmt(f), StatementKind::For(for_loop) => for_loop.fmt(f), - StatementKind::Loop(block, _) => write!(f, "loop {block}"), + StatementKind::Loop(loop_) => write!(f, "loop {}", loop_.body), StatementKind::While(while_) => { write!(f, "while {} {}", while_.condition, while_.body) } diff --git a/compiler/noirc_frontend/src/ast/visitor.rs b/compiler/noirc_frontend/src/ast/visitor.rs index 6602d145968..eae64d7c4e2 100644 --- a/compiler/noirc_frontend/src/ast/visitor.rs +++ b/compiler/noirc_frontend/src/ast/visitor.rs @@ -1219,9 +1219,9 @@ impl Statement { StatementKind::For(for_loop_statement) => { for_loop_statement.accept(visitor); } - StatementKind::Loop(block, _) => { - if visitor.visit_loop_statement(block) { - block.accept(visitor); + StatementKind::Loop(loop_) => { + if visitor.visit_loop_statement(&loop_.body) { + loop_.body.accept(visitor); } } StatementKind::While(while_) => { diff --git a/compiler/noirc_frontend/src/elaborator/statements.rs b/compiler/noirc_frontend/src/elaborator/statements.rs index 550f71fd115..fee91807654 100644 --- a/compiler/noirc_frontend/src/elaborator/statements.rs +++ b/compiler/noirc_frontend/src/elaborator/statements.rs @@ -5,8 +5,8 @@ use noirc_errors::Location; use crate::{ Type, ast::{ - AssignStatement, Expression, ForLoopStatement, ForRange, IntegerBitSize, LValue, - LetStatement, Statement, StatementKind, WhileStatement, + AssignStatement, ForLoopStatement, ForRange, IntegerBitSize, LValue, LetStatement, + LoopStatement, Statement, StatementKind, WhileStatement, }, elaborator::PathResolutionTarget, hir::{ @@ -41,7 +41,7 @@ impl Elaborator<'_> { StatementKind::Let(let_stmt) => self.elaborate_local_let(let_stmt), StatementKind::Assign(assign) => self.elaborate_assign(assign), StatementKind::For(for_stmt) => self.elaborate_for(for_stmt), - StatementKind::Loop(block, location) => self.elaborate_loop(block, location), + StatementKind::Loop(loop_) => self.elaborate_loop(loop_), StatementKind::While(while_) => self.elaborate_while(while_), StatementKind::Break => self.elaborate_jump(true, statement.location), StatementKind::Continue => self.elaborate_jump(false, statement.location), @@ -255,11 +255,8 @@ impl Elaborator<'_> { (statement, Type::Unit) } - pub(super) fn elaborate_loop( - &mut self, - block: Expression, - location: Location, - ) -> (HirStatement, Type) { + pub(super) fn elaborate_loop(&mut self, loop_: LoopStatement) -> (HirStatement, Type) { + let LoopStatement { body: block, loop_keyword_location: location } = loop_; let in_constrained_function = self.in_constrained_function(); if in_constrained_function { self.push_err(ResolverError::LoopInConstrainedFn { location }); diff --git a/compiler/noirc_frontend/src/hir/comptime/display.rs b/compiler/noirc_frontend/src/hir/comptime/display.rs index 76142a0c22a..29efb7f0781 100644 --- a/compiler/noirc_frontend/src/hir/comptime/display.rs +++ b/compiler/noirc_frontend/src/hir/comptime/display.rs @@ -10,7 +10,7 @@ use crate::{ ArrayLiteral, AsTraitPath, AssignStatement, BlockExpression, CallExpression, CastExpression, ConstrainExpression, ConstructorExpression, Expression, ExpressionKind, ForBounds, ForLoopStatement, ForRange, GenericTypeArgs, IfExpression, IndexExpression, - InfixExpression, LValue, Lambda, LetStatement, Literal, MatchExpression, + InfixExpression, LValue, Lambda, LetStatement, Literal, LoopStatement, MatchExpression, MemberAccessExpression, MethodCallExpression, Pattern, PrefixExpression, Statement, StatementKind, UnresolvedType, UnresolvedTypeData, UnsafeExpression, WhileStatement, }, @@ -831,9 +831,10 @@ fn remove_interned_in_statement_kind( block: remove_interned_in_expression(interner, for_loop.block), ..for_loop }), - StatementKind::Loop(block, span) => { - StatementKind::Loop(remove_interned_in_expression(interner, block), span) - } + StatementKind::Loop(loop_) => StatementKind::Loop(LoopStatement { + body: remove_interned_in_expression(interner, loop_.body), + loop_keyword_location: loop_.loop_keyword_location, + }), StatementKind::While(while_) => StatementKind::While(WhileStatement { condition: remove_interned_in_expression(interner, while_.condition), body: remove_interned_in_expression(interner, while_.body), diff --git a/compiler/noirc_frontend/src/hir/comptime/hir_to_display_ast.rs b/compiler/noirc_frontend/src/hir/comptime/hir_to_display_ast.rs index fcec476c28f..dfb8165e22c 100644 --- a/compiler/noirc_frontend/src/hir/comptime/hir_to_display_ast.rs +++ b/compiler/noirc_frontend/src/hir/comptime/hir_to_display_ast.rs @@ -6,9 +6,9 @@ use crate::NamedGeneric; use crate::ast::{ ArrayLiteral, AssignStatement, BlockExpression, CallExpression, CastExpression, ConstrainKind, ConstructorExpression, ExpressionKind, ForLoopStatement, ForRange, GenericTypeArgs, Ident, - IfExpression, IndexExpression, InfixExpression, LValue, Lambda, Literal, MatchExpression, - MemberAccessExpression, Path, PathSegment, Pattern, PrefixExpression, UnresolvedType, - UnresolvedTypeData, UnresolvedTypeExpression, UnsafeExpression, WhileStatement, + IfExpression, IndexExpression, InfixExpression, LValue, Lambda, Literal, LoopStatement, + MatchExpression, MemberAccessExpression, Path, PathSegment, Pattern, PrefixExpression, + UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, UnsafeExpression, WhileStatement, }; use crate::ast::{ConstrainExpression, Expression, Statement, StatementKind}; use crate::hir_def::expr::{ @@ -47,9 +47,10 @@ impl HirStatement { block: for_stmt.block.to_display_ast(interner), location, }), - HirStatement::Loop(block) => { - StatementKind::Loop(block.to_display_ast(interner), location) - } + HirStatement::Loop(block) => StatementKind::Loop(LoopStatement { + body: block.to_display_ast(interner), + loop_keyword_location: location, + }), HirStatement::While(condition, block) => StatementKind::While(WhileStatement { condition: condition.to_display_ast(interner), body: block.to_display_ast(interner), diff --git a/compiler/noirc_frontend/src/parser/parser/statement.rs b/compiler/noirc_frontend/src/parser/parser/statement.rs index e512cc7df67..28643a5ee15 100644 --- a/compiler/noirc_frontend/src/parser/parser/statement.rs +++ b/compiler/noirc_frontend/src/parser/parser/statement.rs @@ -3,8 +3,8 @@ use noirc_errors::{Located, Location}; use crate::{ ast::{ AssignStatement, BinaryOp, BinaryOpKind, Expression, ExpressionKind, ForBounds, - ForLoopStatement, ForRange, Ident, InfixExpression, LValue, LetStatement, Statement, - StatementKind, WhileStatement, + ForLoopStatement, ForRange, Ident, InfixExpression, LValue, LetStatement, LoopStatement, + Statement, StatementKind, WhileStatement, }, parser::{ParserErrorReason, labels::ParsingRuleLabel}, token::{Attribute, Keyword, Token, TokenKind}, @@ -138,8 +138,8 @@ impl Parser<'_> { return Some(StatementKind::For(for_loop)); } - if let Some((block, span)) = self.parse_loop() { - return Some(StatementKind::Loop(block, span)); + if let Some(loop_) = self.parse_loop() { + return Some(StatementKind::Loop(loop_)); } if let Some(while_) = self.parse_while() { @@ -298,7 +298,7 @@ impl Parser<'_> { } /// LoopStatement = 'loop' Block - fn parse_loop(&mut self) -> Option<(Expression, Location)> { + fn parse_loop(&mut self) -> Option { let start_location = self.current_token_location; if !self.eat_keyword(Keyword::Loop) { return None; @@ -318,7 +318,7 @@ impl Parser<'_> { } }; - Some((block, start_location)) + Some(LoopStatement { body: block, loop_keyword_location: start_location }) } /// WhileStatement = 'while' ExpressionExceptConstructor Block @@ -469,7 +469,10 @@ mod tests { use insta::assert_snapshot; use crate::{ - ast::{ExpressionKind, ForRange, LValue, Statement, StatementKind, UnresolvedTypeData}, + ast::{ + ExpressionKind, ForRange, LValue, LoopStatement, Statement, StatementKind, + UnresolvedTypeData, + }, parser::{ Parser, ParserErrorReason, parser::tests::{ @@ -678,7 +681,7 @@ mod tests { #[test] fn parses_assignment_with_unsafe() { - let src = "// Safety: test + let src = "// Safety: test x = unsafe { 1 }"; let statement = parse_statement_no_errors(src); let StatementKind::Assign(assign) = statement.kind else { @@ -814,7 +817,9 @@ mod tests { let src = "loop { }"; let mut parser = Parser::for_str_with_dummy_file(src); let statement = parser.parse_statement_or_error(); - let StatementKind::Loop(block, location) = statement.kind else { + let StatementKind::Loop(LoopStatement { body: block, loop_keyword_location: location }) = + statement.kind + else { panic!("Expected loop"); }; let ExpressionKind::Block(block) = block.kind else { @@ -830,7 +835,7 @@ mod tests { let src = "loop { 1; 2 }"; let mut parser = Parser::for_str_with_dummy_file(src); let statement = parser.parse_statement_or_error(); - let StatementKind::Loop(block, _) = statement.kind else { + let StatementKind::Loop(LoopStatement { body: block, .. }) = statement.kind else { panic!("Expected loop"); }; let ExpressionKind::Block(block) = block.kind else { diff --git a/tooling/lsp/src/with_file.rs b/tooling/lsp/src/with_file.rs index 9a362b69ced..1b08ae51258 100644 --- a/tooling/lsp/src/with_file.rs +++ b/tooling/lsp/src/with_file.rs @@ -8,13 +8,13 @@ use noirc_frontend::{ CastExpression, ConstrainExpression, ConstructorExpression, Documented, EnumVariant, Expression, ExpressionKind, ForBounds, ForLoopStatement, ForRange, FunctionDefinition, FunctionReturnType, GenericTypeArgs, Ident, IdentOrQuotedType, IfExpression, - IndexExpression, InfixExpression, LValue, Lambda, LetStatement, Literal, MatchExpression, - MemberAccessExpression, MethodCallExpression, ModuleDeclaration, NoirEnumeration, - NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, Param, Path, PathSegment, Pattern, - PrefixExpression, Statement, StatementKind, StructField, TraitBound, TraitImplItem, - TraitImplItemKind, TraitItem, TypeAlias, TypeImpl, TypePath, UnresolvedGeneric, - UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, - UnsafeExpression, UseTree, UseTreeKind, WhileStatement, + IndexExpression, InfixExpression, LValue, Lambda, LetStatement, Literal, LoopStatement, + MatchExpression, MemberAccessExpression, MethodCallExpression, ModuleDeclaration, + NoirEnumeration, NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, Param, Path, + PathSegment, Pattern, PrefixExpression, Statement, StatementKind, StructField, TraitBound, + TraitImplItem, TraitImplItemKind, TraitItem, TypeAlias, TypeImpl, TypePath, + UnresolvedGeneric, UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, + UnresolvedTypeExpression, UnsafeExpression, UseTree, UseTreeKind, WhileStatement, }, parser::{Item, ItemKind, ParsedSubModule}, token::{ @@ -901,10 +901,10 @@ fn statement_kind_with_file(kind: StatementKind, file: FileId) -> StatementKind body: expression_with_file(while_.body, file), while_keyword_location: while_.while_keyword_location, }), - StatementKind::Loop(expression, location) => StatementKind::Loop( - expression_with_file(expression, file), - location_with_file(location, file), - ), + StatementKind::Loop(loop_) => StatementKind::Loop(LoopStatement { + body: expression_with_file(loop_.body, file), + loop_keyword_location: location_with_file(loop_.loop_keyword_location, file), + }), StatementKind::Comptime(statement) => { StatementKind::Comptime(Box::new(statement_with_file(*statement, file))) } diff --git a/tooling/nargo_fmt/src/formatter/statement.rs b/tooling/nargo_fmt/src/formatter/statement.rs index 9ab273329d6..580d34b3c9d 100644 --- a/tooling/nargo_fmt/src/formatter/statement.rs +++ b/tooling/nargo_fmt/src/formatter/statement.rs @@ -1,7 +1,8 @@ use noirc_frontend::{ ast::{ AssignStatement, Expression, ExpressionKind, ForLoopStatement, ForRange, LetStatement, - Pattern, Statement, StatementKind, UnresolvedType, UnresolvedTypeData, WhileStatement, + LoopStatement, Pattern, Statement, StatementKind, UnresolvedType, UnresolvedTypeData, + WhileStatement, }, token::{Keyword, SecondaryAttribute, Token, TokenKind}, }; @@ -72,8 +73,8 @@ impl ChunkFormatter<'_, '_> { StatementKind::For(for_loop_statement) => { group.group(self.format_for_loop(for_loop_statement)); } - StatementKind::Loop(block, _) => { - group.group(self.format_loop(block)); + StatementKind::Loop(loop_) => { + group.group(self.format_loop(loop_)); } StatementKind::While(while_) => { group.group(self.format_while(while_)); @@ -281,7 +282,7 @@ impl ChunkFormatter<'_, '_> { group } - fn format_loop(&mut self, block: Expression) -> ChunkGroup { + fn format_loop(&mut self, loop_: LoopStatement) -> ChunkGroup { let mut group = ChunkGroup::new(); group.text(self.chunk(|formatter| { @@ -290,6 +291,8 @@ impl ChunkFormatter<'_, '_> { group.space(self); + let block = loop_.body; + let ExpressionKind::Block(block) = block.kind else { panic!("Expected a block expression for loop body"); }; @@ -448,7 +451,7 @@ mod tests { #[test] fn format_let_statement_with_unsafe_comment() { - let src = " fn foo() { + let src = " fn foo() { // Safety: some comment let x = unsafe { 1 } ; } "; let expected = "fn foo() { @@ -461,7 +464,7 @@ mod tests { #[test] fn format_let_statement_with_unsafe_doc_comment() { - let src = " fn foo() { + let src = " fn foo() { /// Safety: some comment let x = unsafe { 1 } ; } "; let expected = "fn foo() { @@ -474,8 +477,8 @@ mod tests { #[test] fn format_let_statement_with_unsafe_comment_right_before_unsafe() { - let src = " fn foo() { - + let src = " fn foo() { + let x = // Safety: some comment unsafe { 1 } ; } "; let expected = "fn foo() { @@ -489,7 +492,7 @@ mod tests { #[test] fn format_let_statement_with_long_type() { - let src = " fn foo() { + let src = " fn foo() { let some_variable: ThisIsAReallyLongType = 123; foo(); }