From beb636b4d30c99c0b6e64bbfe9647c36cddba324 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Sat, 16 Sep 2023 23:40:37 +0000 Subject: [PATCH 1/7] feat: add support for attributes on structs --- compiler/noirc_frontend/src/ast/structure.rs | 6 ++- compiler/noirc_frontend/src/parser/errors.rs | 4 +- compiler/noirc_frontend/src/parser/parser.rs | 40 +++++++++++++++++--- 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/compiler/noirc_frontend/src/ast/structure.rs b/compiler/noirc_frontend/src/ast/structure.rs index 9b4c0153f52..6a32fa717f3 100644 --- a/compiler/noirc_frontend/src/ast/structure.rs +++ b/compiler/noirc_frontend/src/ast/structure.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -use crate::{Ident, UnresolvedGenerics, UnresolvedType}; +use crate::{token::SecondaryAttribute, Ident, UnresolvedGenerics, UnresolvedType}; use iter_extended::vecmap; use noirc_errors::Span; @@ -8,6 +8,7 @@ use noirc_errors::Span; #[derive(Clone, Debug, PartialEq, Eq)] pub struct NoirStruct { pub name: Ident, + pub attributes: Vec, pub generics: UnresolvedGenerics, pub fields: Vec<(Ident, UnresolvedType)>, pub span: Span, @@ -16,11 +17,12 @@ pub struct NoirStruct { impl NoirStruct { pub fn new( name: Ident, + attributes: Vec, generics: Vec, fields: Vec<(Ident, UnresolvedType)>, span: Span, ) -> NoirStruct { - NoirStruct { name, generics, fields, span } + NoirStruct { name, attributes, generics, fields, span } } } diff --git a/compiler/noirc_frontend/src/parser/errors.rs b/compiler/noirc_frontend/src/parser/errors.rs index 45832ce39db..424f777f227 100644 --- a/compiler/noirc_frontend/src/parser/errors.rs +++ b/compiler/noirc_frontend/src/parser/errors.rs @@ -32,9 +32,11 @@ pub enum ParserErrorReason { #[error("Where clauses are allowed only on functions with generic parameters")] WhereClauseOnNonGenericFunction, #[error( - "Multiple primary attributes found. Only one primary attribute is allowed per function." + "Multiple primary attributes found. Only one primary attribute is allowed per function" )] MultiplePrimaryAttributesFound, + #[error("A primary attribute cannot be placed on a struct")] + NoPrimaryAttributesAllowedOnStruct, #[error("Assert statements can only accept string literals")] AssertMessageNotString, } diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 34aa0ccb072..eca20035e6c 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -35,7 +35,7 @@ use crate::ast::{ }; use crate::lexer::Lexer; use crate::parser::{force, ignore_then_commit, statement_recovery}; -use crate::token::{Attribute, Attributes, Keyword, Token, TokenKind}; +use crate::token::{Attribute, Attributes, Keyword, SecondaryAttribute, Token, TokenKind}; use crate::{ BinaryOp, BinaryOpKind, BlockExpression, ConstrainStatement, Distinctness, FunctionDefinition, FunctionReturnType, Ident, IfExpression, InfixExpression, LValue, Lambda, Literal, @@ -237,11 +237,16 @@ fn struct_definition() -> impl NoirParser { ), ); - keyword(Struct).ignore_then(ident()).then(generics()).then(fields).map_with_span( - |((name, generics), fields), span| { - TopLevelStatement::Struct(NoirStruct { name, generics, fields, span }) - }, - ) + attributes() + .or_not() + .then_ignore(keyword(Struct)) + .then(ident()) + .then(generics()) + .then(fields) + .validate(|(((raw_attributes, name), generics), fields), span, emit| { + let attributes = validate_struct_attributes(raw_attributes, span, emit); + TopLevelStatement::Struct(NoirStruct { name, attributes, generics, fields, span }) + }) } fn type_alias_definition() -> impl NoirParser { @@ -457,6 +462,29 @@ fn validate_attributes( Attributes { primary, secondary } } +fn validate_struct_attributes( + attributes: Option>, + span: Span, + emit: &mut dyn FnMut(ParserError), +) -> Vec { + let attrs = attributes.unwrap_or(vec![]); + let mut struct_attributes = vec![]; + + for attribute in attrs { + match attribute { + Attribute::Primary(..) => { + emit(ParserError::with_reason( + ParserErrorReason::NoPrimaryAttributesAllowedOnStruct, + span, + )); + } + Attribute::Secondary(attr) => struct_attributes.push(attr), + } + } + + struct_attributes +} + fn validate_where_clause( generics: &Vec, where_clause: &Vec, From e0f9a08c7967e797970257ae04160ac5d0e4f87a Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Mon, 18 Sep 2023 09:44:58 +0000 Subject: [PATCH 2/7] test: include test cases --- compiler/noirc_frontend/src/parser/parser.rs | 8 +++++++- .../compile_success_empty/attributes_struct/Nargo.toml | 7 +++++++ .../compile_success_empty/attributes_struct/src/main.nr | 8 ++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 tooling/nargo_cli/tests/compile_success_empty/attributes_struct/Nargo.toml create mode 100644 tooling/nargo_cli/tests/compile_success_empty/attributes_struct/src/main.nr diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index eca20035e6c..ebebdc923ef 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -2246,10 +2246,16 @@ mod test { "struct Foo { }", "struct Bar { ident: Field, }", "struct Baz { ident: Field, other: Field }", + "#[attribute] struct Baz { ident: Field, other: Field }", ]; parse_all(struct_definition(), cases); - let failing = vec!["struct { }", "struct Foo { bar: pub Field }"]; + let failing = vec![ + "struct { }", + "struct Foo { bar: pub Field }", + "struct Foo { bar: pub Field }", + "#[oracle(some)] struct Foo { bar: Field }", + ]; parse_all_failing(struct_definition(), failing); } diff --git a/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/Nargo.toml new file mode 100644 index 00000000000..0f00e7d9c73 --- /dev/null +++ b/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "attributes_struct" +type = "bin" +authors = [""] +compiler_version = "0.11.1" + +[dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/src/main.nr new file mode 100644 index 00000000000..0bad42aee57 --- /dev/null +++ b/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/src/main.nr @@ -0,0 +1,8 @@ +#[some_attribute] +#[another_attribute] +struct SomeStruct { + a: Field, + b: Field +} + +fn main() {} From 9d1f4671fb2d63f25cb7b6cb2784566fc9a55a2d Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Mon, 18 Sep 2023 09:50:25 +0000 Subject: [PATCH 3/7] test: primary attirbute failure case --- .../compile_failure/primary_attribute_struct/Nargo.toml | 8 ++++++++ .../compile_failure/primary_attribute_struct/src/main.nr | 8 ++++++++ 2 files changed, 16 insertions(+) create mode 100644 tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/Nargo.toml create mode 100644 tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/Nargo.toml new file mode 100644 index 00000000000..872c8f2030d --- /dev/null +++ b/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/Nargo.toml @@ -0,0 +1,8 @@ + +[package] +name = "primary_attribute_struct" +type = "bin" +authors = [""] +compiler_version = "0.11.1" + +[dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/src/main.nr b/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/src/main.nr new file mode 100644 index 00000000000..8922ef60091 --- /dev/null +++ b/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/src/main.nr @@ -0,0 +1,8 @@ +// An primary attribute should not be able to be added to a struct defintion +#[oracle(some_oracle)] +struct SomeStruct{ + x: Field, + y: Field +} + +fn main() {} From 74eba330e77745b2f7706d6bef57607bbf9b45c0 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Mon, 18 Sep 2023 09:56:13 +0000 Subject: [PATCH 4/7] chore: fmt --- compiler/noirc_frontend/src/parser/parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index ebebdc923ef..483add39aff 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -467,7 +467,7 @@ fn validate_struct_attributes( span: Span, emit: &mut dyn FnMut(ParserError), ) -> Vec { - let attrs = attributes.unwrap_or(vec![]); + let attrs = attributes.unwrap_or_default(vec![]); let mut struct_attributes = vec![]; for attribute in attrs { From 36771752f2f432f3ee34f5899501c955adfaff79 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Mon, 18 Sep 2023 09:58:46 +0000 Subject: [PATCH 5/7] fix --- compiler/noirc_frontend/src/parser/parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 483add39aff..1007fcc8840 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -467,7 +467,7 @@ fn validate_struct_attributes( span: Span, emit: &mut dyn FnMut(ParserError), ) -> Vec { - let attrs = attributes.unwrap_or_default(vec![]); + let attrs = attributes.unwrap_or_default(); let mut struct_attributes = vec![]; for attribute in attrs { From 1364a38a7dc76f4492a441f9b26a1eaf93aefe34 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 19 Sep 2023 09:36:24 +0000 Subject: [PATCH 6/7] fix: rename primary attribute to function attribute --- compiler/noirc_frontend/src/ast/function.rs | 24 ++++---- .../noirc_frontend/src/hir/def_map/mod.rs | 6 +- .../src/hir/resolution/resolver.rs | 4 +- .../noirc_frontend/src/hir_def/function.rs | 2 +- compiler/noirc_frontend/src/lexer/lexer.rs | 20 ++++--- compiler/noirc_frontend/src/lexer/token.rs | 56 +++++++++---------- .../src/monomorphization/mod.rs | 10 ++-- compiler/noirc_frontend/src/parser/errors.rs | 8 +-- compiler/noirc_frontend/src/parser/parser.rs | 12 ++-- 9 files changed, 73 insertions(+), 69 deletions(-) diff --git a/compiler/noirc_frontend/src/ast/function.rs b/compiler/noirc_frontend/src/ast/function.rs index 72ed1db6e3b..9b192c722a0 100644 --- a/compiler/noirc_frontend/src/ast/function.rs +++ b/compiler/noirc_frontend/src/ast/function.rs @@ -3,7 +3,7 @@ use std::fmt::Display; use noirc_errors::Span; use crate::{ - token::{Attributes, PrimaryAttribute, SecondaryAttribute}, + token::{Attributes, FunctionAttribute, SecondaryAttribute}, FunctionReturnType, Ident, Pattern, Visibility, }; @@ -65,11 +65,11 @@ impl NoirFunction { pub fn attributes(&self) -> &Attributes { &self.def.attributes } - pub fn primary_attribute(&self) -> Option<&PrimaryAttribute> { - self.def.attributes.primary.as_ref() + pub fn function_attribute(&self) -> Option<&FunctionAttribute> { + self.def.attributes.function_attribute.as_ref() } - pub fn secondary_attributes(&self) -> &Vec { - self.def.attributes.secondary.as_ref() + pub fn other_attributes(&self) -> &Vec { + self.def.attributes.secondary_attributes.as_ref() } pub fn def(&self) -> &FunctionDefinition { &self.def @@ -89,19 +89,19 @@ impl NoirFunction { FunctionKind::LowLevel => {} _ => return None, } - assert!(self.primary_attribute().unwrap().is_foreign()); + assert!(self.function_attribute().unwrap().is_foreign()); Some(&self.def) } } impl From for NoirFunction { fn from(fd: FunctionDefinition) -> Self { - // The function type is determined by the existence of a primary attribute - let kind = match fd.attributes.primary { - Some(PrimaryAttribute::Builtin(_)) => FunctionKind::Builtin, - Some(PrimaryAttribute::Foreign(_)) => FunctionKind::LowLevel, - Some(PrimaryAttribute::Test { .. }) => FunctionKind::Normal, - Some(PrimaryAttribute::Oracle(_)) => FunctionKind::Oracle, + // The function type is determined by the existence of a function attribute + let kind = match fd.attributes.function_attribute { + Some(FunctionAttribute::Builtin(_)) => FunctionKind::Builtin, + Some(FunctionAttribute::Foreign(_)) => FunctionKind::LowLevel, + Some(FunctionAttribute::Test { .. }) => FunctionKind::Normal, + Some(FunctionAttribute::Oracle(_)) => FunctionKind::Oracle, None => FunctionKind::Normal, }; diff --git a/compiler/noirc_frontend/src/hir/def_map/mod.rs b/compiler/noirc_frontend/src/hir/def_map/mod.rs index 1a7c6674e01..06028224004 100644 --- a/compiler/noirc_frontend/src/hir/def_map/mod.rs +++ b/compiler/noirc_frontend/src/hir/def_map/mod.rs @@ -3,7 +3,7 @@ use crate::hir::def_collector::dc_crate::DefCollector; use crate::hir::Context; use crate::node_interner::{FuncId, NodeInterner}; use crate::parser::{parse_program, ParsedModule}; -use crate::token::{PrimaryAttribute, TestScope}; +use crate::token::{FunctionAttribute, TestScope}; use arena::{Arena, Index}; use fm::{FileId, FileManager}; use noirc_errors::{FileDiagnostic, Location}; @@ -140,8 +140,8 @@ impl CrateDefMap { module.value_definitions().filter_map(|id| { if let Some(func_id) = id.as_function() { let func_meta = interner.function_meta(&func_id); - match func_meta.attributes.primary { - Some(PrimaryAttribute::Test(scope)) => { + match func_meta.attributes.function_attribute { + Some(FunctionAttribute::Test(scope)) => { Some(TestFunction::new(func_id, scope, func_meta.name.location)) } _ => None, diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 411e91f2cf4..ea9a9f6487f 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -17,7 +17,7 @@ use crate::hir_def::expr::{ HirIfExpression, HirIndexExpression, HirInfixExpression, HirLambda, HirLiteral, HirMemberAccess, HirMethodCallExpression, HirPrefixExpression, }; -use crate::token::PrimaryAttribute; +use crate::token::FunctionAttribute; use regex::Regex; use std::collections::{BTreeMap, HashSet}; use std::rc::Rc; @@ -731,7 +731,7 @@ impl<'a> Resolver<'a> { self.push_err(ResolverError::DistinctNotAllowed { ident: func.name_ident().clone() }); } - if matches!(attributes.primary, Some(PrimaryAttribute::Test { .. })) + if matches!(attributes.function_attribute, Some(FunctionAttribute::Test { .. })) && !parameters.is_empty() { self.push_err(ResolverError::TestFunctionHasParameters { diff --git a/compiler/noirc_frontend/src/hir_def/function.rs b/compiler/noirc_frontend/src/hir_def/function.rs index c552100c919..92287de1110 100644 --- a/compiler/noirc_frontend/src/hir_def/function.rs +++ b/compiler/noirc_frontend/src/hir_def/function.rs @@ -100,7 +100,7 @@ pub struct FuncMeta { /// A function's attributes are the `#[...]` items above the function /// definition. - /// Primary Attributes will alter the function kind, secondary attributes do not + /// Function Attributes will alter the function kind, secondary attributes do not pub attributes: Attributes, /// This function's type in its contract. diff --git a/compiler/noirc_frontend/src/lexer/lexer.rs b/compiler/noirc_frontend/src/lexer/lexer.rs index 5b6e010cc77..c32b956b716 100644 --- a/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/compiler/noirc_frontend/src/lexer/lexer.rs @@ -1,6 +1,8 @@ +use crate::token::Attribute; + use super::{ errors::LexerErrorKind, - token::{Attribute, IntType, Keyword, SpannedToken, Token, Tokens}, + token::{IntType, Keyword, SpannedToken, Token, Tokens}, }; use acvm::FieldElement; use noirc_errors::{Position, Span}; @@ -411,7 +413,7 @@ impl<'a> Iterator for Lexer<'a> { #[cfg(test)] mod tests { use super::*; - use crate::token::{Attribute, PrimaryAttribute, SecondaryAttribute, TestScope}; + use crate::token::{FunctionAttribute, SecondaryAttribute, TestScope}; #[test] fn test_single_double_char() { let input = "! != + ( ) { } [ ] | , ; : :: < <= > >= & - -> . .. % / * = == << >>"; @@ -499,9 +501,11 @@ mod tests { let input = "#[foreign(sha256)]#[foreign(blake2s)]#[builtin(sum)]"; let expected = vec![ - Token::Attribute(Attribute::Primary(PrimaryAttribute::Foreign("sha256".to_string()))), - Token::Attribute(Attribute::Primary(PrimaryAttribute::Foreign("blake2s".to_string()))), - Token::Attribute(Attribute::Primary(PrimaryAttribute::Builtin("sum".to_string()))), + Token::Attribute(Attribute::Function(FunctionAttribute::Foreign("sha256".to_string()))), + Token::Attribute(Attribute::Function(FunctionAttribute::Foreign( + "blake2s".to_string(), + ))), + Token::Attribute(Attribute::Function(FunctionAttribute::Builtin("sum".to_string()))), ]; let mut lexer = Lexer::new(input); @@ -533,7 +537,7 @@ mod tests { let token = lexer.next().unwrap().unwrap(); assert_eq!( token.token(), - &Token::Attribute(Attribute::Primary(PrimaryAttribute::Test(TestScope::None))) + &Token::Attribute(Attribute::Function(FunctionAttribute::Test(TestScope::None))) ); } @@ -557,7 +561,7 @@ mod tests { let token = lexer.next().unwrap().unwrap(); assert_eq!( token.token(), - &Token::Attribute(Attribute::Primary(PrimaryAttribute::Test( + &Token::Attribute(Attribute::Function(FunctionAttribute::Test( TestScope::ShouldFailWith { reason: None } ))) ); @@ -571,7 +575,7 @@ mod tests { let token = lexer.next().unwrap().unwrap(); assert_eq!( token.token(), - &Token::Attribute(Attribute::Primary(PrimaryAttribute::Test( + &Token::Attribute(Attribute::Function(FunctionAttribute::Test( TestScope::ShouldFailWith { reason: Some("hello".to_owned()) } ))) ); diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index e99dcb72fb6..868d3a13a69 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -364,14 +364,14 @@ impl fmt::Display for TestScope { // Calls to functions which have the foreign attribute are executed in the host language pub struct Attributes { // Each function can have a single Primary Attribute - pub primary: Option, + pub function_attribute: Option, // Each function can have many Secondary Attributes - pub secondary: Vec, + pub secondary_attributes: Vec, } impl Attributes { pub fn empty() -> Self { - Self { primary: None, secondary: Vec::new() } + Self { function_attribute: None, secondary_attributes: Vec::new() } } /// Returns true if one of the secondary attributes is `contract_library_method` @@ -379,14 +379,14 @@ impl Attributes { /// This is useful for finding out if we should compile a contract method /// as an entry point or not. pub fn has_contract_library_method(&self) -> bool { - self.secondary + self.secondary_attributes .iter() .any(|attribute| attribute == &SecondaryAttribute::ContractLibraryMethod) } /// Returns note if a deprecated secondary attribute is found pub fn get_deprecated_note(&self) -> Option> { - self.secondary.iter().find_map(|attr| match attr { + self.secondary_attributes.iter().find_map(|attr| match attr { SecondaryAttribute::Deprecated(note) => Some(note.clone()), _ => None, }) @@ -398,14 +398,14 @@ impl Attributes { /// A secondary attribute has no effect and is either consumed by a library or used as a notice for the developer #[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] pub enum Attribute { - Primary(PrimaryAttribute), + Function(FunctionAttribute), Secondary(SecondaryAttribute), } impl fmt::Display for Attribute { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Attribute::Primary(attribute) => write!(f, "{}", attribute), + Attribute::Function(attribute) => write!(f, "{}", attribute), Attribute::Secondary(attribute) => write!(f, "{}", attribute), } } @@ -442,23 +442,23 @@ impl Attribute { // Primary Attributes ["foreign", name] => { validate(name)?; - Attribute::Primary(PrimaryAttribute::Foreign(name.to_string())) + Attribute::Function(FunctionAttribute::Foreign(name.to_string())) } ["builtin", name] => { validate(name)?; - Attribute::Primary(PrimaryAttribute::Builtin(name.to_string())) + Attribute::Function(FunctionAttribute::Builtin(name.to_string())) } ["oracle", name] => { validate(name)?; - Attribute::Primary(PrimaryAttribute::Oracle(name.to_string())) + Attribute::Function(FunctionAttribute::Oracle(name.to_string())) } - ["test"] => Attribute::Primary(PrimaryAttribute::Test(TestScope::None)), + ["test"] => Attribute::Function(FunctionAttribute::Test(TestScope::None)), ["test", name] => { validate(name)?; let malformed_scope = LexerErrorKind::MalformedFuncAttribute { span, found: word.to_owned() }; match TestScope::lookup_str(name) { - Some(scope) => Attribute::Primary(PrimaryAttribute::Test(scope)), + Some(scope) => Attribute::Function(FunctionAttribute::Test(scope)), None => return Err(malformed_scope), } } @@ -492,44 +492,44 @@ impl Attribute { /// Primary Attributes are those which a function can only have one of. /// They change the FunctionKind and thus have direct impact on the IR output #[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] -pub enum PrimaryAttribute { +pub enum FunctionAttribute { Foreign(String), Builtin(String), Oracle(String), Test(TestScope), } -impl PrimaryAttribute { +impl FunctionAttribute { pub fn builtin(self) -> Option { match self { - PrimaryAttribute::Builtin(name) => Some(name), + FunctionAttribute::Builtin(name) => Some(name), _ => None, } } pub fn foreign(self) -> Option { match self { - PrimaryAttribute::Foreign(name) => Some(name), + FunctionAttribute::Foreign(name) => Some(name), _ => None, } } pub fn is_foreign(&self) -> bool { - matches!(self, PrimaryAttribute::Foreign(_)) + matches!(self, FunctionAttribute::Foreign(_)) } pub fn is_low_level(&self) -> bool { - matches!(self, PrimaryAttribute::Foreign(_) | PrimaryAttribute::Builtin(_)) + matches!(self, FunctionAttribute::Foreign(_) | FunctionAttribute::Builtin(_)) } } -impl fmt::Display for PrimaryAttribute { +impl fmt::Display for FunctionAttribute { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - PrimaryAttribute::Test(scope) => write!(f, "#[test{}]", scope), - PrimaryAttribute::Foreign(ref k) => write!(f, "#[foreign({k})]"), - PrimaryAttribute::Builtin(ref k) => write!(f, "#[builtin({k})]"), - PrimaryAttribute::Oracle(ref k) => write!(f, "#[oracle({k})]"), + FunctionAttribute::Test(scope) => write!(f, "#[test{}]", scope), + FunctionAttribute::Foreign(ref k) => write!(f, "#[foreign({k})]"), + FunctionAttribute::Builtin(ref k) => write!(f, "#[builtin({k})]"), + FunctionAttribute::Oracle(ref k) => write!(f, "#[oracle({k})]"), } } } @@ -560,13 +560,13 @@ impl fmt::Display for SecondaryAttribute { } } -impl AsRef for PrimaryAttribute { +impl AsRef for FunctionAttribute { fn as_ref(&self) -> &str { match self { - PrimaryAttribute::Foreign(string) => string, - PrimaryAttribute::Builtin(string) => string, - PrimaryAttribute::Oracle(string) => string, - PrimaryAttribute::Test { .. } => "", + FunctionAttribute::Foreign(string) => string, + FunctionAttribute::Builtin(string) => string, + FunctionAttribute::Oracle(string) => string, + FunctionAttribute::Test { .. } => "", } } } diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index 2a7687731b9..c1dcd25794e 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -21,7 +21,7 @@ use crate::{ types, }, node_interner::{self, DefinitionKind, NodeInterner, StmtId}, - token::PrimaryAttribute, + token::FunctionAttribute, ContractFunctionType, FunctionKind, Type, TypeBinding, TypeBindings, TypeVariableKind, Visibility, }; @@ -145,14 +145,14 @@ impl<'interner> Monomorphizer<'interner> { let meta = self.interner.function_meta(&id); match meta.kind { FunctionKind::LowLevel => { - let attribute = meta.attributes.primary.expect("all low level functions must contain a primary attribute which contains the opcode which it links to"); + let attribute = meta.attributes.function_attribute.expect("all low level functions must contain a function attribute which contains the opcode which it links to"); let opcode = attribute.foreign().expect( "ice: function marked as foreign, but attribute kind does not match this", ); Definition::LowLevel(opcode) } FunctionKind::Builtin => { - let attribute = meta.attributes.primary.expect("all low level functions must contain a primary attribute which contains the opcode which it links to"); + let attribute = meta.attributes.function_attribute.expect("all low level functions must contain a primary attribute which contains the opcode which it links to"); let opcode = attribute.builtin().expect( "ice: function marked as builtin, but attribute kind does not match this", ); @@ -165,11 +165,11 @@ impl<'interner> Monomorphizer<'interner> { FunctionKind::Oracle => { let attr = meta .attributes - .primary + .function_attribute .expect("Oracle function must have an oracle attribute"); match attr { - PrimaryAttribute::Oracle(name) => Definition::Oracle(name), + FunctionAttribute::Oracle(name) => Definition::Oracle(name), _ => unreachable!("Oracle function must have an oracle attribute"), } } diff --git a/compiler/noirc_frontend/src/parser/errors.rs b/compiler/noirc_frontend/src/parser/errors.rs index 424f777f227..90eaf18c3d7 100644 --- a/compiler/noirc_frontend/src/parser/errors.rs +++ b/compiler/noirc_frontend/src/parser/errors.rs @@ -32,11 +32,11 @@ pub enum ParserErrorReason { #[error("Where clauses are allowed only on functions with generic parameters")] WhereClauseOnNonGenericFunction, #[error( - "Multiple primary attributes found. Only one primary attribute is allowed per function" + "Multiple primary attributes found. Only one function attribute is allowed per function" )] - MultiplePrimaryAttributesFound, - #[error("A primary attribute cannot be placed on a struct")] - NoPrimaryAttributesAllowedOnStruct, + MultipleFunctionAttributesFound, + #[error("A function attribute cannot be placed on a struct")] + NoFunctionAttributesAllowedOnStruct, #[error("Assert statements can only accept string literals")] AssertMessageNotString, } diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 1007fcc8840..d2f6dabb0d7 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -174,7 +174,7 @@ fn function_definition(allow_self: bool) -> impl NoirParser { .validate(|(((args, ret), where_clause), (body, body_span)), span, emit| { let ((((attributes, modifiers), name), generics), parameters) = args; - // Validate collected attributes, filtering them into primary and secondary variants + // Validate collected attributes, filtering them into function and secondary variants let attrs = validate_attributes(attributes, span, emit); validate_where_clause(&generics, &where_clause, span, emit); FunctionDefinition { @@ -446,10 +446,10 @@ fn validate_attributes( for attribute in attrs { match attribute { - Attribute::Primary(attr) => { + Attribute::Function(attr) => { if primary.is_some() { emit(ParserError::with_reason( - ParserErrorReason::MultiplePrimaryAttributesFound, + ParserErrorReason::MultipleFunctionAttributesFound, span, )); } @@ -459,7 +459,7 @@ fn validate_attributes( } } - Attributes { primary, secondary } + Attributes { function_attribute: primary, secondary_attributes: secondary } } fn validate_struct_attributes( @@ -472,9 +472,9 @@ fn validate_struct_attributes( for attribute in attrs { match attribute { - Attribute::Primary(..) => { + Attribute::Function(..) => { emit(ParserError::with_reason( - ParserErrorReason::NoPrimaryAttributesAllowedOnStruct, + ParserErrorReason::NoFunctionAttributesAllowedOnStruct, span, )); } From 970cab19209e2091122a24dcb453cc9ec78e86e4 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 19 Sep 2023 09:40:45 +0000 Subject: [PATCH 7/7] clean --- compiler/noirc_frontend/src/ast/function.rs | 8 ++++---- compiler/noirc_frontend/src/hir/def_map/mod.rs | 2 +- compiler/noirc_frontend/src/hir/resolution/resolver.rs | 2 +- compiler/noirc_frontend/src/lexer/token.rs | 10 +++++----- compiler/noirc_frontend/src/monomorphization/mod.rs | 6 +++--- compiler/noirc_frontend/src/parser/parser.rs | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/compiler/noirc_frontend/src/ast/function.rs b/compiler/noirc_frontend/src/ast/function.rs index 9b192c722a0..e16c0fcba15 100644 --- a/compiler/noirc_frontend/src/ast/function.rs +++ b/compiler/noirc_frontend/src/ast/function.rs @@ -66,10 +66,10 @@ impl NoirFunction { &self.def.attributes } pub fn function_attribute(&self) -> Option<&FunctionAttribute> { - self.def.attributes.function_attribute.as_ref() + self.def.attributes.function.as_ref() } - pub fn other_attributes(&self) -> &Vec { - self.def.attributes.secondary_attributes.as_ref() + pub fn secondary_attributes(&self) -> &Vec { + self.def.attributes.secondary.as_ref() } pub fn def(&self) -> &FunctionDefinition { &self.def @@ -97,7 +97,7 @@ impl NoirFunction { impl From for NoirFunction { fn from(fd: FunctionDefinition) -> Self { // The function type is determined by the existence of a function attribute - let kind = match fd.attributes.function_attribute { + let kind = match fd.attributes.function { Some(FunctionAttribute::Builtin(_)) => FunctionKind::Builtin, Some(FunctionAttribute::Foreign(_)) => FunctionKind::LowLevel, Some(FunctionAttribute::Test { .. }) => FunctionKind::Normal, diff --git a/compiler/noirc_frontend/src/hir/def_map/mod.rs b/compiler/noirc_frontend/src/hir/def_map/mod.rs index 06028224004..911ec1ed743 100644 --- a/compiler/noirc_frontend/src/hir/def_map/mod.rs +++ b/compiler/noirc_frontend/src/hir/def_map/mod.rs @@ -140,7 +140,7 @@ impl CrateDefMap { module.value_definitions().filter_map(|id| { if let Some(func_id) = id.as_function() { let func_meta = interner.function_meta(&func_id); - match func_meta.attributes.function_attribute { + match func_meta.attributes.function { Some(FunctionAttribute::Test(scope)) => { Some(TestFunction::new(func_id, scope, func_meta.name.location)) } diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index ea9a9f6487f..d2fb3eb9017 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -731,7 +731,7 @@ impl<'a> Resolver<'a> { self.push_err(ResolverError::DistinctNotAllowed { ident: func.name_ident().clone() }); } - if matches!(attributes.function_attribute, Some(FunctionAttribute::Test { .. })) + if matches!(attributes.function, Some(FunctionAttribute::Test { .. })) && !parameters.is_empty() { self.push_err(ResolverError::TestFunctionHasParameters { diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index 868d3a13a69..fb5ab220b2c 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -364,14 +364,14 @@ impl fmt::Display for TestScope { // Calls to functions which have the foreign attribute are executed in the host language pub struct Attributes { // Each function can have a single Primary Attribute - pub function_attribute: Option, + pub function: Option, // Each function can have many Secondary Attributes - pub secondary_attributes: Vec, + pub secondary: Vec, } impl Attributes { pub fn empty() -> Self { - Self { function_attribute: None, secondary_attributes: Vec::new() } + Self { function: None, secondary: Vec::new() } } /// Returns true if one of the secondary attributes is `contract_library_method` @@ -379,14 +379,14 @@ impl Attributes { /// This is useful for finding out if we should compile a contract method /// as an entry point or not. pub fn has_contract_library_method(&self) -> bool { - self.secondary_attributes + self.secondary .iter() .any(|attribute| attribute == &SecondaryAttribute::ContractLibraryMethod) } /// Returns note if a deprecated secondary attribute is found pub fn get_deprecated_note(&self) -> Option> { - self.secondary_attributes.iter().find_map(|attr| match attr { + self.secondary.iter().find_map(|attr| match attr { SecondaryAttribute::Deprecated(note) => Some(note.clone()), _ => None, }) diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index c1dcd25794e..d90d47645ea 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -145,14 +145,14 @@ impl<'interner> Monomorphizer<'interner> { let meta = self.interner.function_meta(&id); match meta.kind { FunctionKind::LowLevel => { - let attribute = meta.attributes.function_attribute.expect("all low level functions must contain a function attribute which contains the opcode which it links to"); + let attribute = meta.attributes.function.expect("all low level functions must contain a function attribute which contains the opcode which it links to"); let opcode = attribute.foreign().expect( "ice: function marked as foreign, but attribute kind does not match this", ); Definition::LowLevel(opcode) } FunctionKind::Builtin => { - let attribute = meta.attributes.function_attribute.expect("all low level functions must contain a primary attribute which contains the opcode which it links to"); + let attribute = meta.attributes.function.expect("all low level functions must contain a primary attribute which contains the opcode which it links to"); let opcode = attribute.builtin().expect( "ice: function marked as builtin, but attribute kind does not match this", ); @@ -165,7 +165,7 @@ impl<'interner> Monomorphizer<'interner> { FunctionKind::Oracle => { let attr = meta .attributes - .function_attribute + .function .expect("Oracle function must have an oracle attribute"); match attr { diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index d2f6dabb0d7..d07cb27d9f1 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -459,7 +459,7 @@ fn validate_attributes( } } - Attributes { function_attribute: primary, secondary_attributes: secondary } + Attributes { function: primary, secondary } } fn validate_struct_attributes(