From f78c262228768b9cb0037dfc221ea69f61887527 Mon Sep 17 00:00:00 2001 From: Jake Fecher Date: Tue, 19 Mar 2024 14:40:02 -0500 Subject: [PATCH 1/2] Add 'quote' to parser --- compiler/noirc_frontend/src/ast/expression.rs | 2 ++ .../src/hir/resolution/resolver.rs | 4 ++++ .../noirc_frontend/src/hir/type_check/expr.rs | 1 + compiler/noirc_frontend/src/hir_def/expr.rs | 1 + compiler/noirc_frontend/src/hir_def/types.rs | 14 ++++++++++++++ compiler/noirc_frontend/src/lexer/token.rs | 3 +++ .../noirc_frontend/src/monomorphization/mod.rs | 2 ++ compiler/noirc_frontend/src/node_interner.rs | 2 ++ compiler/noirc_frontend/src/parser/parser.rs | 16 +++++++++++++++- tooling/nargo_fmt/src/rewrite/expr.rs | 18 ++++++++++++------ tooling/noirc_abi/src/lib.rs | 3 ++- 11 files changed, 58 insertions(+), 8 deletions(-) diff --git a/compiler/noirc_frontend/src/ast/expression.rs b/compiler/noirc_frontend/src/ast/expression.rs index a9ecc1a53e5..4bf9c58e25e 100644 --- a/compiler/noirc_frontend/src/ast/expression.rs +++ b/compiler/noirc_frontend/src/ast/expression.rs @@ -27,6 +27,7 @@ pub enum ExpressionKind { Tuple(Vec), Lambda(Box), Parenthesized(Box), + Quote(BlockExpression), Error, } @@ -483,6 +484,7 @@ impl Display for ExpressionKind { } Lambda(lambda) => lambda.fmt(f), Parenthesized(sub_expr) => write!(f, "({sub_expr})"), + Quote(block) => write!(f, "quote {block}"), Error => write!(f, "Error"), } } diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 90716bb958d..994318c4837 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -1086,6 +1086,7 @@ impl<'a> Resolver<'a> { | Type::NamedGeneric(_, _) | Type::NotConstant | Type::TraitAsType(..) + | Type::Code | Type::Forall(_, _) => (), Type::Array(length, element_type) => { @@ -1607,6 +1608,9 @@ impl<'a> Resolver<'a> { }) }), ExpressionKind::Parenthesized(sub_expr) => return self.resolve_expression(*sub_expr), + + // The quoted expression isn't resolved since we don't want errors if variables aren't defined + ExpressionKind::Quote(block) => HirExpression::Quote(block), }; // If these lines are ever changed, make sure to change the early return diff --git a/compiler/noirc_frontend/src/hir/type_check/expr.rs b/compiler/noirc_frontend/src/hir/type_check/expr.rs index 0b3dd022209..64369b2d45f 100644 --- a/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -311,6 +311,7 @@ impl<'interner> TypeChecker<'interner> { Type::Function(params, Box::new(lambda.return_type), Box::new(env_type)) } + HirExpression::Quote(_) => Type::Code, }; self.interner.push_expr_type(*expr_id, typ.clone()); diff --git a/compiler/noirc_frontend/src/hir_def/expr.rs b/compiler/noirc_frontend/src/hir_def/expr.rs index b4c590de491..bb91cb418b1 100644 --- a/compiler/noirc_frontend/src/hir_def/expr.rs +++ b/compiler/noirc_frontend/src/hir_def/expr.rs @@ -31,6 +31,7 @@ pub enum HirExpression { Tuple(Vec), Lambda(HirLambda), Error, + Quote(crate::BlockExpression), } impl HirExpression { diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index 60bc5b2470f..4ce1dea81a7 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -103,6 +103,9 @@ pub enum Type { /// involving slices. NotConstant, + /// The type of quoted code in macros. This is always a comptime-only type + Code, + /// The result of some type error. Remembering type errors as their own type variant lets /// us avoid issuing repeat type errors for the same item. For example, a lambda with /// an invalid type would otherwise issue a new error each time it is called @@ -147,6 +150,7 @@ impl Type { | Type::Forall(_, _) | Type::Constant(_) | Type::NotConstant + | Type::Code | Type::Error => unreachable!("This type cannot exist as a parameter to main"), } } @@ -633,6 +637,7 @@ impl Type { | Type::NamedGeneric(_, _) | Type::NotConstant | Type::Forall(_, _) + | Type::Code | Type::TraitAsType(..) => false, Type::Array(length, elem) => { @@ -697,6 +702,7 @@ impl Type { | Type::MutableReference(_) | Type::Forall(_, _) | Type::TraitAsType(..) + | Type::Code | Type::NotConstant => false, Type::Alias(alias, generics) => { @@ -861,6 +867,7 @@ impl std::fmt::Display for Type { write!(f, "&mut {element}") } Type::NotConstant => write!(f, "_"), + Type::Code => write!(f, "Code"), } } } @@ -1549,6 +1556,7 @@ impl Type { | Type::TraitAsType(..) | Type::Error | Type::NotConstant + | Type::Code | Type::Unit => self.clone(), } } @@ -1590,6 +1598,7 @@ impl Type { | Type::TraitAsType(..) | Type::Error | Type::NotConstant + | Type::Code | Type::Unit => false, } } @@ -1647,6 +1656,7 @@ impl Type { | Constant(_) | Unit | Error + | Code | NotConstant => self.clone(), } } @@ -1773,6 +1783,9 @@ impl From<&Type> for PrintableType { PrintableType::MutableReference { typ: Box::new(typ.as_ref().into()) } } Type::NotConstant => unreachable!(), + + // Is this actually unreachable? + Type::Code => unreachable!(), } } } @@ -1859,6 +1872,7 @@ impl std::fmt::Debug for Type { write!(f, "&mut {element:?}") } Type::NotConstant => write!(f, "NotConstant"), + Type::Code => write!(f, "Code"), } } } diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index 1e341d34510..4432a3f9e07 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -667,6 +667,7 @@ pub enum Keyword { Mod, Mut, Pub, + Quote, Return, ReturnData, String, @@ -710,6 +711,7 @@ impl fmt::Display for Keyword { Keyword::Mod => write!(f, "mod"), Keyword::Mut => write!(f, "mut"), Keyword::Pub => write!(f, "pub"), + Keyword::Quote => write!(f, "quote"), Keyword::Return => write!(f, "return"), Keyword::ReturnData => write!(f, "return_data"), Keyword::String => write!(f, "str"), @@ -756,6 +758,7 @@ impl Keyword { "mod" => Keyword::Mod, "mut" => Keyword::Mut, "pub" => Keyword::Pub, + "quote" => Keyword::Quote, "return" => Keyword::Return, "return_data" => Keyword::ReturnData, "str" => Keyword::String, diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index a99a4e61d4d..56680c13e65 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -510,6 +510,7 @@ impl<'interner> Monomorphizer<'interner> { unreachable!("Encountered HirExpression::MethodCall during monomorphization {hir_method_call:?}") } HirExpression::Error => unreachable!("Encountered Error node during monomorphization"), + HirExpression::Quote(_) => unreachable!("quote expression remaining in runtime code"), }; Ok(expr) @@ -940,6 +941,7 @@ impl<'interner> Monomorphizer<'interner> { | HirType::Error => { unreachable!("Unexpected type {} found", typ) } + HirType::Code => unreachable!("Tried to translate Code type into runtime code"), } } diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index b83d2008530..2bf4f5dac06 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -1671,6 +1671,7 @@ enum TypeMethodKey { Tuple, Function, Generic, + Code, } fn get_type_method_key(typ: &Type) -> Option { @@ -1689,6 +1690,7 @@ fn get_type_method_key(typ: &Type) -> Option { Type::Tuple(_) => Some(Tuple), Type::Function(_, _, _) => Some(Function), Type::NamedGeneric(_, _) => Some(Generic), + Type::Code => Some(Code), Type::MutableReference(element) => get_type_method_key(element), Type::Alias(alias, _) => get_type_method_key(&alias.borrow().typ), diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index b2d9d7e6802..1698b8eea17 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -1109,7 +1109,8 @@ where nothing().boxed() }, lambdas::lambda(expr_parser.clone()), - block(statement).map(ExpressionKind::Block), + block(statement.clone()).map(ExpressionKind::Block), + quote(statement), variable(), literal(), )) @@ -1134,6 +1135,19 @@ where .labelled(ParsingRuleLabel::Atom) } +fn quote<'a, P>(statement: P) -> impl NoirParser + 'a +where + P: NoirParser + 'a, +{ + keyword(Keyword::Quote).ignore_then(block(statement)).validate(|block, span, emit| { + emit(ParserError::with_reason( + ParserErrorReason::ExperimentalFeature("quoted expressions"), + span, + )); + ExpressionKind::Quote(block) + }) +} + fn tuple

(expr_parser: P) -> impl NoirParser where P: ExprParser, diff --git a/tooling/nargo_fmt/src/rewrite/expr.rs b/tooling/nargo_fmt/src/rewrite/expr.rs index 32d104f559b..d0d3235a983 100644 --- a/tooling/nargo_fmt/src/rewrite/expr.rs +++ b/tooling/nargo_fmt/src/rewrite/expr.rs @@ -1,4 +1,7 @@ -use noirc_frontend::{token::Token, ArrayLiteral, Expression, ExpressionKind, Literal, UnaryOp}; +use noirc_frontend::{ + macros_api::Span, token::Token, ArrayLiteral, BlockExpression, Expression, ExpressionKind, + Literal, UnaryOp, +}; use crate::visitor::{ expr::{format_brackets, format_parens, NewlineMode}, @@ -20,11 +23,7 @@ pub(crate) fn rewrite( shape: Shape, ) -> String { match kind { - ExpressionKind::Block(block) => { - let mut visitor = visitor.fork(); - visitor.visit_block(block, span); - visitor.finish() - } + ExpressionKind::Block(block) => rewrite_block(visitor, block, span), ExpressionKind::Prefix(prefix) => { let op = match prefix.operator { UnaryOp::Minus => "-", @@ -150,6 +149,13 @@ pub(crate) fn rewrite( visitor.format_if(*if_expr) } ExpressionKind::Lambda(_) | ExpressionKind::Variable(_) => visitor.slice(span).to_string(), + ExpressionKind::Quote(block) => format!("quote {}", rewrite_block(visitor, block, span)), ExpressionKind::Error => unreachable!(), } } + +fn rewrite_block(visitor: &FmtVisitor, block: BlockExpression, span: Span) -> String { + let mut visitor = visitor.fork(); + visitor.visit_block(block, span); + visitor.finish() +} diff --git a/tooling/noirc_abi/src/lib.rs b/tooling/noirc_abi/src/lib.rs index 26feab65d83..6aed45d1846 100644 --- a/tooling/noirc_abi/src/lib.rs +++ b/tooling/noirc_abi/src/lib.rs @@ -179,7 +179,8 @@ impl AbiType { | Type::NamedGeneric(..) | Type::Forall(..) | Type::NotConstant - | Type::Function(_, _, _) => unreachable!("Type cannot be used in the abi"), + | Type::Code + | Type::Function(_, _, _) => unreachable!("{typ} cannot be used in the abi"), Type::FmtString(_, _) => unreachable!("format strings cannot be used in the abi"), Type::MutableReference(_) => unreachable!("&mut cannot be used in the abi"), } From 707c4b30767a5f0dd5b782df3bf7cd1f3dc1a65a Mon Sep 17 00:00:00 2001 From: Jake Fecher Date: Wed, 20 Mar 2024 10:37:16 -0500 Subject: [PATCH 2/2] fmt --- compiler/noirc_frontend/src/hir_def/types.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index fe0c7ed8a61..3c5627f739b 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -1630,9 +1630,14 @@ impl Type { // Expect that this function should only be called on instantiated types Forall(..) => unreachable!(), - TraitAsType(..) | FieldElement | Integer(_, _) | Bool | Constant(_) | Unit | Code | Error => { - self.clone() - } + TraitAsType(..) + | FieldElement + | Integer(_, _) + | Bool + | Constant(_) + | Unit + | Code + | Error => self.clone(), } } @@ -1761,7 +1766,6 @@ impl From<&Type> for PrintableType { Type::MutableReference(typ) => { PrintableType::MutableReference { typ: Box::new(typ.as_ref().into()) } } - // Is this actually unreachable? Type::Code => unreachable!(), } }