Skip to content

Commit

Permalink
Unquote multiple items from annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
jfecher committed Jul 8, 2024
1 parent b58a034 commit 81c322f
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 74 deletions.
140 changes: 71 additions & 69 deletions compiler/noirc_frontend/src/elaborator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1288,11 +1288,11 @@ impl<'context> Elaborator<'context> {
.map_err(|error| error.into_compilation_error_pair())?;

if value != Value::Unit {
let item = value
.into_top_level_item(location)
let items = value
.into_top_level_items(location)
.map_err(|error| error.into_compilation_error_pair())?;

self.add_item(item, generated_items, location);
self.add_items(items, generated_items, location);
}

Ok(())
Expand Down Expand Up @@ -1544,79 +1544,81 @@ impl<'context> Elaborator<'context> {
(comptime, items)
}

fn add_item(
fn add_items(
&mut self,
item: TopLevelStatement,
items: Vec<TopLevelStatement>,
generated_items: &mut CollectedItems,
location: Location,
) {
match item {
TopLevelStatement::Function(function) => {
let id = self.interner.push_empty_fn();
let module = self.module_id();
self.interner.push_function(id, &function.def, module, location);
let functions = vec![(self.local_module, id, function)];
generated_items.functions.push(UnresolvedFunctions {
file_id: self.file,
functions,
trait_id: None,
self_type: None,
});
}
TopLevelStatement::TraitImpl(mut trait_impl) => {
let methods = dc_mod::collect_trait_impl_functions(
self.interner,
&mut trait_impl,
self.crate_id,
self.file,
self.local_module,
);
for item in items {
match item {
TopLevelStatement::Function(function) => {
let id = self.interner.push_empty_fn();
let module = self.module_id();
self.interner.push_function(id, &function.def, module, location);
let functions = vec![(self.local_module, id, function)];
generated_items.functions.push(UnresolvedFunctions {
file_id: self.file,
functions,
trait_id: None,
self_type: None,
});
}
TopLevelStatement::TraitImpl(mut trait_impl) => {
let methods = dc_mod::collect_trait_impl_functions(
self.interner,
&mut trait_impl,
self.crate_id,
self.file,
self.local_module,
);

generated_items.trait_impls.push(UnresolvedTraitImpl {
file_id: self.file,
module_id: self.local_module,
trait_generics: trait_impl.trait_generics,
trait_path: trait_impl.trait_name,
object_type: trait_impl.object_type,
methods,
generics: trait_impl.impl_generics,
where_clause: trait_impl.where_clause,

// These last fields are filled in later
trait_id: None,
impl_id: None,
resolved_object_type: None,
resolved_generics: Vec::new(),
resolved_trait_generics: Vec::new(),
});
}
TopLevelStatement::Global(global) => {
let (global, error) = dc_mod::collect_global(
self.interner,
self.def_maps.get_mut(&self.crate_id).unwrap(),
global,
self.file,
self.local_module,
);
generated_items.trait_impls.push(UnresolvedTraitImpl {
file_id: self.file,
module_id: self.local_module,
trait_generics: trait_impl.trait_generics,
trait_path: trait_impl.trait_name,
object_type: trait_impl.object_type,
methods,
generics: trait_impl.impl_generics,
where_clause: trait_impl.where_clause,

// These last fields are filled in later
trait_id: None,
impl_id: None,
resolved_object_type: None,
resolved_generics: Vec::new(),
resolved_trait_generics: Vec::new(),
});
}
TopLevelStatement::Global(global) => {
let (global, error) = dc_mod::collect_global(
self.interner,
self.def_maps.get_mut(&self.crate_id).unwrap(),
global,
self.file,
self.local_module,
);

generated_items.globals.push(global);
if let Some(error) = error {
self.errors.push(error);
generated_items.globals.push(global);
if let Some(error) = error {
self.errors.push(error);
}
}
// Assume that an error has already been issued
TopLevelStatement::Error => (),

TopLevelStatement::Module(_)
| TopLevelStatement::Import(_)
| TopLevelStatement::Struct(_)
| TopLevelStatement::Trait(_)
| TopLevelStatement::Impl(_)
| TopLevelStatement::TypeAlias(_)
| TopLevelStatement::SubModule(_) => {
let item = item.to_string();
let error = InterpreterError::UnsupportedTopLevelItemUnquote { item, location };
self.errors.push(error.into_compilation_error_pair());
}
}
// Assume that an error has already been issued
TopLevelStatement::Error => (),

TopLevelStatement::Module(_)
| TopLevelStatement::Import(_)
| TopLevelStatement::Struct(_)
| TopLevelStatement::Trait(_)
| TopLevelStatement::Impl(_)
| TopLevelStatement::TypeAlias(_)
| TopLevelStatement::SubModule(_) => {
let item = item.to_string();
let error = InterpreterError::UnsupportedTopLevelItemUnquote { item, location };
self.errors.push(error.into_compilation_error_pair());
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions compiler/noirc_frontend/src/hir/comptime/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,9 +326,12 @@ impl Value {
}
}

pub(crate) fn into_top_level_item(self, location: Location) -> IResult<TopLevelStatement> {
pub(crate) fn into_top_level_items(
self,
location: Location,
) -> IResult<Vec<TopLevelStatement>> {
match self {
Value::Code(tokens) => parse_tokens(tokens, parser::top_level_item(), location.file),
Value::Code(tokens) => parse_tokens(tokens, parser::top_level_items(), location.file),
value => Err(InterpreterError::CannotInlineMacro { value, location }),
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use chumsky::primitive::Container;
pub use errors::ParserError;
pub use errors::ParserErrorReason;
use noirc_errors::Span;
pub use parser::{expression, parse_program, top_level_item};
pub use parser::{expression, parse_program, top_level_items};

#[derive(Debug, Clone)]
pub enum TopLevelStatement {
Expand Down
4 changes: 2 additions & 2 deletions compiler/noirc_frontend/src/parser/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ fn module() -> impl NoirParser<ParsedModule> {
}

/// This parser is used for parsing top level statements in macros
pub fn top_level_item() -> impl NoirParser<TopLevelStatement> {
top_level_statement(module())
pub fn top_level_items() -> impl NoirParser<Vec<TopLevelStatement>> {
top_level_statement(module()).repeated()
}

/// top_level_statement: function_definition
Expand Down
7 changes: 7 additions & 0 deletions test_programs/compile_success_empty/short/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "unquote_multiple_items_from_annotation"
type = "bin"
authors = [""]
compiler_version = ">=0.31.0"

[dependencies]
14 changes: 14 additions & 0 deletions test_programs/compile_success_empty/short/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#[foo]
struct Foo {}

fn main() {
assert_eq(ONE, 1);
assert_eq(TWO, 2);
}

comptime fn foo(_: StructDefinition) -> Quoted {
quote {
global ONE = 1;
global TWO = 2;
}
}

0 comments on commit 81c322f

Please sign in to comment.