Skip to content

Commit

Permalink
feat(attributes): Split attributes into Primary and Secondary
Browse files Browse the repository at this point in the history
  • Loading branch information
Maddiaa0 committed Sep 2, 2023
1 parent 9fe4cfd commit 53be3f1
Show file tree
Hide file tree
Showing 11 changed files with 216 additions and 80 deletions.
14 changes: 7 additions & 7 deletions crates/noirc_frontend/src/ast/expression.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::fmt::Display;

use crate::token::{Attribute, Token};
use crate::token::{Attributes, Token};
use crate::{
Distinctness, Ident, Path, Pattern, Recoverable, Statement, TraitConstraint, UnresolvedType,
UnresolvedTypeData, Visibility,
Expand Down Expand Up @@ -351,8 +351,9 @@ pub struct Lambda {
pub struct FunctionDefinition {
pub name: Ident,

// XXX: Currently we only have one attribute defined. If more attributes are needed per function, we can make this a vector and make attribute definition more expressive
pub attribute: Option<Attribute>,
// The `Attributes` container holds both `primary` (ones that change the function kind)
// and `secondary` attributes (ones that do not change the function kind)
pub attributes: Attributes,

/// True if this function was defined with the 'open' keyword
pub is_open: bool,
Expand Down Expand Up @@ -643,7 +644,8 @@ impl FunctionDefinition {
.collect();
FunctionDefinition {
name: name.clone(),
attribute: None,
// TODO(MD): is this the best way to do this? -> It was previously just None
attributes: Attributes::empty(),
is_open: false,
is_internal: false,
is_unconstrained: false,
Expand All @@ -661,9 +663,7 @@ impl FunctionDefinition {

impl Display for FunctionDefinition {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(attribute) = &self.attribute {
writeln!(f, "{attribute}")?;
}
writeln!(f, "{:?}", self.attributes)?;

let parameters = vecmap(&self.parameters, |(name, r#type, visibility)| {
format!("{name}: {visibility} {type}")
Expand Down
31 changes: 20 additions & 11 deletions crates/noirc_frontend/src/ast/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use std::fmt::Display;

use noirc_errors::Span;

use crate::{token::Attribute, FunctionReturnType, Ident, Pattern, Visibility};
use crate::{
token::{Attributes, PrimaryAttribute, SecondaryAttribute},
FunctionReturnType, Ident, Pattern, Visibility,
};

use super::{FunctionDefinition, UnresolvedType, UnresolvedTypeData};

Expand Down Expand Up @@ -59,8 +62,14 @@ impl NoirFunction {
pub fn parameters(&self) -> &Vec<(Pattern, UnresolvedType, Visibility)> {
&self.def.parameters
}
pub fn attribute(&self) -> Option<&Attribute> {
self.def.attribute.as_ref()
pub fn attributes(&self) -> &Attributes {
&self.def.attributes
}
pub fn primary_attribute(&self) -> Option<&PrimaryAttribute> {
self.def.attributes.primary.as_ref()
}
pub fn secondary_attributes(&self) -> &Vec<SecondaryAttribute> {
self.def.attributes.secondary.as_ref()
}
pub fn def(&self) -> &FunctionDefinition {
&self.def
Expand All @@ -80,20 +89,20 @@ impl NoirFunction {
FunctionKind::LowLevel => {}
_ => return None,
}
assert!(self.attribute().unwrap().is_foreign());
assert!(self.primary_attribute().unwrap().is_foreign());
Some(&self.def)
}
}

impl From<FunctionDefinition> for NoirFunction {
fn from(fd: FunctionDefinition) -> Self {
let kind = match fd.attribute {
Some(Attribute::Builtin(_)) => FunctionKind::Builtin,
Some(Attribute::Foreign(_)) => FunctionKind::LowLevel,
Some(Attribute::Test { .. }) => FunctionKind::Normal,
Some(Attribute::Oracle(_)) => FunctionKind::Oracle,
Some(Attribute::Deprecated(_)) | None => FunctionKind::Normal,
Some(Attribute::Custom(_)) => FunctionKind::Normal,
// 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,
None => FunctionKind::Normal,
};

NoirFunction { def: fd, kind }
Expand Down
1 change: 1 addition & 0 deletions crates/noirc_frontend/src/hir/def_collector/dc_mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ impl<'a> ModCollector<'a> {
}

for item in &trait_def.items {
// TODO(Maddiaa): Should traits have a notion of attributes? -> I have a feeling they should
if let TraitItem::Function {
name,
generics,
Expand Down
8 changes: 5 additions & 3 deletions crates/noirc_frontend/src/hir/def_map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{Attribute, TestScope};
use crate::token::{PrimaryAttribute, TestScope};
use arena::{Arena, Index};
use fm::{FileId, FileManager};
use noirc_errors::{FileDiagnostic, Location};
Expand Down Expand Up @@ -139,8 +139,10 @@ impl CrateDefMap {
self.modules.iter().flat_map(|(_, module)| {
module.value_definitions().filter_map(|id| {
if let Some(func_id) = id.as_function() {
match interner.function_meta(&func_id).attributes {
Some(Attribute::Test(scope)) => Some(TestFunction::new(func_id, scope)),
match interner.function_meta(&func_id).attributes.primary {
Some(PrimaryAttribute::Test(scope)) => {
Some(TestFunction::new(func_id, scope))
}
_ => None,
}
} else {
Expand Down
8 changes: 5 additions & 3 deletions crates/noirc_frontend/src/hir/resolution/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::hir_def::expr::{
HirIfExpression, HirIndexExpression, HirInfixExpression, HirLambda, HirLiteral,
HirMemberAccess, HirMethodCallExpression, HirPrefixExpression,
};
use crate::token::Attribute;
use crate::token::PrimaryAttribute;
use regex::Regex;
use std::collections::{HashMap, HashSet};
use std::rc::Rc;
Expand Down Expand Up @@ -669,7 +669,7 @@ impl<'a> Resolver<'a> {
let id = self.interner.function_definition_id(func_id);
let name_ident = HirIdent { id, location };

let attributes = func.attribute().cloned();
let attributes = func.attributes().clone();

let mut generics =
vecmap(self.generics.clone(), |(name, typevar, _)| match &*typevar.borrow() {
Expand Down Expand Up @@ -722,7 +722,9 @@ impl<'a> Resolver<'a> {
self.push_err(ResolverError::DistinctNotAllowed { ident: func.name_ident().clone() });
}

if matches!(attributes, Some(Attribute::Test { .. })) && !parameters.is_empty() {
if matches!(attributes.primary, Some(PrimaryAttribute::Test { .. }))
&& !parameters.is_empty()
{
self.push_err(ResolverError::TestFunctionHasParameters {
span: func.name_ident().span(),
});
Expand Down
6 changes: 3 additions & 3 deletions crates/noirc_frontend/src/hir/type_check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
types::Type,
},
node_interner::{DefinitionKind, ExprId, FuncId},
token::Attribute::Deprecated,
token::SecondaryAttribute::Deprecated,
Shared, Signedness, TypeBinding, TypeVariableKind, UnaryOp,
};

Expand All @@ -26,10 +26,10 @@ impl<'interner> TypeChecker<'interner> {
self.interner.try_definition(id).map(|def| &def.kind)
{
let meta = self.interner.function_meta(func_id);
if let Some(Deprecated(note)) = meta.attributes {
if let note = meta.attributes.get_deprecated_note() {
self.errors.push(TypeCheckError::CallDeprecated {
name: self.interner.definition_name(id).to_string(),
note,
note, // TODO(MD): remove clone
span: location.span,
});
}
Expand Down
5 changes: 3 additions & 2 deletions crates/noirc_frontend/src/hir_def/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use super::expr::{HirBlockExpression, HirExpression, HirIdent};
use super::stmt::HirPattern;
use crate::hir::def_map::ModuleId;
use crate::node_interner::{ExprId, NodeInterner};
use crate::{token::Attribute, FunctionKind};
use crate::{token::Attributes, FunctionKind};
use crate::{ContractFunctionType, Distinctness, FunctionReturnType, Type, Visibility};

/// A Hir function is a block expression
Expand Down Expand Up @@ -101,7 +101,8 @@ pub struct FuncMeta {
/// A function's attributes are the `#[...]` items above the function
/// definition, if any. Currently, this is limited to a maximum of only one
/// Attribute per function.
pub attributes: Option<Attribute>,
/// TODO: edit the above
pub attributes: Attributes,

/// This function's type in its contract.
/// If this function is not in a contract, this is always 'Secret'.
Expand Down
Loading

0 comments on commit 53be3f1

Please sign in to comment.