Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: module attributes #5888

Merged
merged 22 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions aztec_macros/src/utils/parse_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ fn empty_item(item: &mut Item) {
ItemKind::Import(use_tree, _) => empty_use_tree(use_tree),
ItemKind::Struct(noir_struct) => empty_noir_struct(noir_struct),
ItemKind::TypeAlias(noir_type_alias) => empty_noir_type_alias(noir_type_alias),
ItemKind::InnerAttribute(_) => (),
}
}

Expand Down
1 change: 1 addition & 0 deletions compiler/noirc_frontend/src/ast/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ pub trait Recoverable {
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ModuleDeclaration {
pub ident: Ident,
pub outer_attributes: Vec<SecondaryAttribute>,
}

impl std::fmt::Display for ModuleDeclaration {
Expand Down
13 changes: 12 additions & 1 deletion compiler/noirc_frontend/src/ast/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
QuotedTypeId,
},
parser::{Item, ItemKind, ParsedSubModule},
token::Tokens,
token::{SecondaryAttribute, Tokens},
ParsedModule, QuotedType,
};

Expand Down Expand Up @@ -432,6 +432,8 @@
fn visit_struct_pattern(&mut self, _: &Path, _: &[(Ident, Pattern)], _: Span) -> bool {
true
}

fn visit_secondary_attribute(&mut self, _: &SecondaryAttribute, _: Span) {}
}

impl ParsedModule {
Expand Down Expand Up @@ -481,6 +483,9 @@
ItemKind::ModuleDecl(module_declaration) => {
module_declaration.accept(self.span, visitor);
}
ItemKind::InnerAttribute(attribute) => {
attribute.accept(self.span, visitor);
}
}
}
}
Expand Down Expand Up @@ -1205,8 +1210,8 @@
UnresolvedTypeData::Unspecified => visitor.visit_unspecified_type(self.span),
UnresolvedTypeData::Quoted(typ) => visitor.visit_quoted_type(typ, self.span),
UnresolvedTypeData::FieldElement => visitor.visit_field_element_type(self.span),
UnresolvedTypeData::Integer(signdness, size) => {

Check warning on line 1213 in compiler/noirc_frontend/src/ast/visitor.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (signdness)
visitor.visit_integer_type(*signdness, *size, self.span);

Check warning on line 1214 in compiler/noirc_frontend/src/ast/visitor.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (signdness)
}
UnresolvedTypeData::Bool => visitor.visit_bool_type(self.span),
UnresolvedTypeData::Unit => visitor.visit_unit_type(self.span),
Expand Down Expand Up @@ -1289,6 +1294,12 @@
}
}

impl SecondaryAttribute {
pub fn accept(&self, span: Span, visitor: &mut impl Visitor) {
visitor.visit_secondary_attribute(self, span);
}
}

fn visit_expressions(expressions: &[Expression], visitor: &mut impl Visitor) {
for expression in expressions {
expression.accept(visitor);
Expand Down
63 changes: 49 additions & 14 deletions compiler/noirc_frontend/src/elaborator/comptime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ use crate::{
comptime::{Interpreter, InterpreterError, Value},
def_collector::{
dc_crate::{
CollectedItems, CompilationError, UnresolvedFunctions, UnresolvedStruct,
UnresolvedTrait, UnresolvedTraitImpl,
CollectedItems, CompilationError, ModuleAttribute, UnresolvedFunctions,
UnresolvedStruct, UnresolvedTrait, UnresolvedTraitImpl,
},
dc_mod,
},
def_map::ModuleId,
resolution::errors::ResolverError,
},
hir_def::expr::HirIdent,
Expand Down Expand Up @@ -96,21 +97,31 @@ impl<'context> Elaborator<'context> {
generated_items: &mut CollectedItems,
) {
for attribute in attributes {
if let SecondaryAttribute::Custom(attribute) = attribute {
if let Err(error) = self.run_comptime_attribute_on_item(
&attribute.contents,
item.clone(),
span,
attribute.contents_span,
generated_items,
) {
self.errors.push(error);
}
}
self.run_comptime_attribute_on_item(attribute, &item, span, generated_items);
}
}

fn run_comptime_attribute_on_item(
&mut self,
attribute: &SecondaryAttribute,
item: &Value,
span: Span,
generated_items: &mut CollectedItems,
) {
if let SecondaryAttribute::Custom(attribute) = attribute {
if let Err(error) = self.run_comptime_attribute_name_on_item(
&attribute.contents,
item.clone(),
span,
attribute.contents_span,
generated_items,
) {
self.errors.push(error);
}
}
}

fn run_comptime_attribute_name_on_item(
&mut self,
attribute: &str,
item: Value,
Expand Down Expand Up @@ -383,7 +394,8 @@ impl<'context> Elaborator<'context> {
| TopLevelStatement::Trait(_)
| TopLevelStatement::Impl(_)
| TopLevelStatement::TypeAlias(_)
| TopLevelStatement::SubModule(_) => {
| TopLevelStatement::SubModule(_)
| TopLevelStatement::InnerAttribute(_) => {
let item = item.to_string();
let error = InterpreterError::UnsupportedTopLevelItemUnquote { item, location };
self.errors.push(error.into_compilation_error_pair());
Expand Down Expand Up @@ -422,6 +434,7 @@ impl<'context> Elaborator<'context> {
traits: &BTreeMap<TraitId, UnresolvedTrait>,
types: &BTreeMap<StructId, UnresolvedStruct>,
functions: &[UnresolvedFunctions],
module_attributes: &[ModuleAttribute],
) -> CollectedItems {
let mut generated_items = CollectedItems::default();

Expand All @@ -444,9 +457,31 @@ impl<'context> Elaborator<'context> {
}

self.run_attributes_on_functions(functions, &mut generated_items);

self.run_attributes_on_modules(module_attributes, &mut generated_items);

generated_items
}

fn run_attributes_on_modules(
&mut self,
module_attributes: &[ModuleAttribute],
generated_items: &mut CollectedItems,
) {
for module_attribute in module_attributes {
let local_id = module_attribute.module_id;
let module_id = ModuleId { krate: self.crate_id, local_id };
let item = Value::ModuleDefinition(module_id);
let attribute = &module_attribute.attribute;
let span = Span::default();

self.local_module = module_attribute.attribute_module_id;
self.file = module_attribute.attribute_file_id;

self.run_comptime_attribute_on_item(attribute, &item, span, generated_items);
}
}

fn run_attributes_on_functions(
&mut self,
function_sets: &[UnresolvedFunctions],
Expand Down
7 changes: 6 additions & 1 deletion compiler/noirc_frontend/src/elaborator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
node_interner::{
DefinitionKind, DependencyId, ExprId, FuncId, GlobalId, ReferenceId, TraitId, TypeAliasId,
},
token::CustomAtrribute,

Check warning on line 31 in compiler/noirc_frontend/src/elaborator/mod.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (Atrribute)
Shared, Type, TypeVariable,
};
use crate::{
Expand Down Expand Up @@ -321,7 +321,12 @@

// We have to run any comptime attributes on functions before the function is elaborated
// since the generated items are checked beforehand as well.
let generated_items = self.run_attributes(&items.traits, &items.types, &items.functions);
let generated_items = self.run_attributes(
&items.traits,
&items.types,
&items.functions,
&items.module_attributes,
);

// After everything is collected, we can elaborate our generated items.
// It may be better to inline these within `items` entirely since elaborating them
Expand Down Expand Up @@ -820,7 +825,7 @@
let attributes = func.secondary_attributes().iter();
let attributes =
attributes.filter_map(|secondary_attribute| secondary_attribute.as_custom());
let attributes: Vec<CustomAtrribute> = attributes.cloned().collect();

Check warning on line 828 in compiler/noirc_frontend/src/elaborator/mod.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (Atrribute)

let meta = FuncMeta {
name: name_ident,
Expand Down
33 changes: 33 additions & 0 deletions compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ impl<'local, 'context> Interpreter<'local, 'context> {
function_def_set_return_type(self, arguments, location)
}
"module_functions" => module_functions(self, arguments, location),
"module_has_named_attribute" => module_has_named_attribute(self, arguments, location),
"module_is_contract" => module_is_contract(self, arguments, location),
"module_name" => module_name(interner, arguments, location),
"modulus_be_bits" => modulus_be_bits(interner, arguments, location),
Expand Down Expand Up @@ -1816,6 +1817,38 @@ fn module_functions(
Ok(Value::Slice(func_ids, slice_type))
}

// fn has_named_attribute(self, name: Quoted) -> bool
fn module_has_named_attribute(
interpreter: &Interpreter,
arguments: Vec<(Value, Location)>,
location: Location,
) -> IResult<Value> {
let (self_argument, name) = check_two_arguments(arguments, location)?;
let module_id = get_module(self_argument)?;
let module_data = interpreter.elaborator.get_module(module_id);
let name = get_quoted(name)?;

let name = name.iter().map(|token| token.to_string()).collect::<Vec<_>>().join("");

let attributes = module_data.outer_attributes.iter().chain(&module_data.inner_attributes);
for attribute in attributes {
let parse_result = Elaborator::parse_attribute(attribute, location);
let Ok(Some((function, _arguments))) = parse_result else {
continue;
};

let ExpressionKind::Variable(path) = function.kind else {
continue;
};

if path.last_name() == name {
return Ok(Value::Bool(true));
}
}

Ok(Value::Bool(false))
}

// fn is_contract(self) -> bool
fn module_is_contract(
interpreter: &Interpreter,
Expand Down
8 changes: 7 additions & 1 deletion compiler/noirc_frontend/src/hir/comptime/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,13 @@ fn interpret_helper(src: &str) -> Result<Value, InterpreterError> {
let module_id = LocalModuleId(Index::unsafe_zeroed());
let mut modules = noirc_arena::Arena::default();
let location = Location::new(Default::default(), file);
let root = LocalModuleId(modules.insert(ModuleData::new(None, location, false)));
let root = LocalModuleId(modules.insert(ModuleData::new(
None,
location,
Vec::new(),
Vec::new(),
false,
)));
assert_eq!(root, module_id);

let file_manager = FileManager::new(&PathBuf::new());
Expand Down
18 changes: 18 additions & 0 deletions compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleId};
use crate::hir::resolution::errors::ResolverError;
use crate::hir::resolution::path_resolver;
use crate::hir::type_check::TypeCheckError;
use crate::token::SecondaryAttribute;
use crate::{Generics, Type};

use crate::hir::resolution::import::{resolve_import, ImportDirective, PathResolution};
Expand Down Expand Up @@ -111,6 +112,21 @@ pub struct UnresolvedGlobal {
pub stmt_def: LetStatement,
}

pub struct ModuleAttribute {
// The file in which the module is defined
pub file_id: FileId,
// The module this attribute is attached to
pub module_id: LocalModuleId,
// The file where the attribute exists (it could be the same as `file_id`
// or a different one if it's an inner attribute in a different file)
pub attribute_file_id: FileId,
// The module where the attribute is defined (similar to `attribute_file_id`,
// it could be different than `module_id` for inner attributes)
pub attribute_module_id: LocalModuleId,
pub attribute: SecondaryAttribute,
pub is_inner: bool,
}

/// Given a Crate root, collect all definitions in that crate
pub struct DefCollector {
pub(crate) def_map: CrateDefMap,
Expand All @@ -127,6 +143,7 @@ pub struct CollectedItems {
pub globals: Vec<UnresolvedGlobal>,
pub(crate) impls: ImplMap,
pub(crate) trait_impls: Vec<UnresolvedTraitImpl>,
pub(crate) module_attributes: Vec<ModuleAttribute>,
}

impl CollectedItems {
Expand Down Expand Up @@ -238,6 +255,7 @@ impl DefCollector {
impls: HashMap::default(),
globals: vec![],
trait_impls: vec![],
module_attributes: vec![],
},
}
}
Expand Down
Loading
Loading