Skip to content

Commit

Permalink
chore: Pull out aztec macros to their own crate and create an API for…
Browse files Browse the repository at this point in the history
… them in the compiler frontend (noir-lang#3578)
  • Loading branch information
kevaundray authored Nov 28, 2023
1 parent 1ef8546 commit ae56683
Show file tree
Hide file tree
Showing 15 changed files with 206 additions and 94 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-aztec-feature-flag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ jobs:
save-if: ${{ github.event_name != 'merge_group' }}

- name: Build with feature flag
run: cargo build --features="noirc_frontend/aztec"
run: cargo build --features="noirc_driver/aztec"
2 changes: 1 addition & 1 deletion .github/workflows/publish-es-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- name: Enable aztec features
if: ${{ inputs.npm-tag == 'aztec' }}
run: |
echo $'\n'"default = [\"aztec\"]"$'\n' >> compiler/noirc_frontend/Cargo.toml
echo $'\n'"default = [\"aztec\"]"$'\n' >> compiler/noirc_driver/Cargo.toml
- name: Build wasm package
run: |
Expand Down
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[workspace]

members = [
"aztec_macros",
"compiler/noirc_evaluator",
"compiler/noirc_frontend",
"compiler/noirc_errors",
Expand Down
14 changes: 14 additions & 0 deletions aztec_macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "aztec_macros"
version.workspace = true
authors.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
noirc_frontend.workspace = true
iter-extended.workspace = true
Original file line number Diff line number Diff line change
@@ -1,28 +1,59 @@
use acvm::FieldElement;
use iter_extended::vecmap;
use noirc_errors::Span;

use crate::graph::CrateId;
use crate::hir::def_collector::errors::DefCollectorErrorKind;
use crate::hir_def::expr::{HirExpression, HirLiteral};
use crate::hir_def::stmt::HirStatement;
use crate::node_interner::{NodeInterner, StructId};
use crate::parser::SortedModule;
use crate::token::SecondaryAttribute;
use crate::{
hir::Context, BlockExpression, CallExpression, CastExpression, Distinctness, Expression,
ExpressionKind, FunctionReturnType, Ident, IndexExpression, LetStatement, Literal,
MemberAccessExpression, MethodCallExpression, NoirFunction, Path, PathKind, Pattern, Statement,
UnresolvedType, UnresolvedTypeData, Visibility,
};
use crate::{
ForLoopStatement, ForRange, FunctionDefinition, FunctionVisibility, ImportStatement,
NoirStruct, Param, PrefixExpression, Signedness, StatementKind, StructType, Type, TypeImpl,
UnaryOp,

use noirc_frontend::macros_api::FieldElement;
use noirc_frontend::macros_api::{
BlockExpression, CallExpression, CastExpression, Distinctness, Expression, ExpressionKind,
ForLoopStatement, ForRange, FunctionDefinition, FunctionReturnType, FunctionVisibility,
HirContext, HirExpression, HirLiteral, HirStatement, Ident, ImportStatement, IndexExpression,
LetStatement, Literal, MemberAccessExpression, MethodCallExpression, NoirFunction, NoirStruct,
Param, Path, PathKind, Pattern, PrefixExpression, SecondaryAttribute, Signedness, Span,
Statement, StatementKind, StructType, Type, TypeImpl, UnaryOp, UnresolvedType,
UnresolvedTypeData, Visibility,
};
use fm::FileId;
use noirc_frontend::macros_api::{CrateId, FileId};
use noirc_frontend::macros_api::{MacroError, MacroProcessor};
use noirc_frontend::macros_api::{ModuleDefId, NodeInterner, SortedModule, StructId};

pub struct AztecMacro;

impl MacroProcessor for AztecMacro {
fn process_untyped_ast(
&self,
ast: SortedModule,
crate_id: &CrateId,
context: &HirContext,
) -> Result<SortedModule, (MacroError, FileId)> {
transform(ast, crate_id, context)
}

fn process_typed_ast(&self, crate_id: &CrateId, context: &mut HirContext) {
transform_hir(crate_id, context)
}
}

#[derive(Debug, Clone)]
pub enum AztecMacroError {
// TODO(benesjan): https://github.com/AztecProtocol/aztec-packages/issues/2905
AztecNotFound,
AztecComputeNoteHashAndNullifierNotFound { span: Span },
}

use super::def_map::ModuleDefId;
impl From<AztecMacroError> for MacroError {
fn from(err: AztecMacroError) -> Self {
match err {
AztecMacroError::AztecNotFound {} => MacroError {
primary_message: "Aztec dependency not found. Please add aztec as a dependency in your Cargo.toml".to_owned(),
secondary_message: None,
span: None,
},
AztecMacroError::AztecComputeNoteHashAndNullifierNotFound { span } => MacroError {
primary_message: "compute_note_hash_and_nullifier function not found. Define it in your contract.".to_owned(),
secondary_message: None,
span: Some(span),
},
}
}
}

//
// Helper macros for creating noir ast nodes
Expand Down Expand Up @@ -162,11 +193,11 @@ fn import(path: Path) -> ImportStatement {

/// Traverses every function in the ast, calling `transform_function` which
/// determines if further processing is required
pub(crate) fn transform(
fn transform(
mut ast: SortedModule,
crate_id: &CrateId,
context: &Context,
) -> Result<SortedModule, (DefCollectorErrorKind, FileId)> {
context: &HirContext,
) -> Result<SortedModule, (MacroError, FileId)> {
// Usage -> mut ast -> aztec_library::transform(&mut ast)

// Covers all functions in the ast
Expand All @@ -184,7 +215,7 @@ pub(crate) fn transform(
//

/// Completes the Hir with data gathered from type resolution
pub(crate) fn transform_hir(crate_id: &CrateId, context: &mut Context) {
fn transform_hir(crate_id: &CrateId, context: &mut HirContext) {
transform_events(crate_id, context);
}

Expand All @@ -206,14 +237,14 @@ fn include_relevant_imports(ast: &mut SortedModule) {
/// Creates an error alerting the user that they have not downloaded the Aztec-noir library
fn check_for_aztec_dependency(
crate_id: &CrateId,
context: &Context,
) -> Result<(), (DefCollectorErrorKind, FileId)> {
context: &HirContext,
) -> Result<(), (MacroError, FileId)> {
let crate_graph = &context.crate_graph[crate_id];
let has_aztec_dependency = crate_graph.dependencies.iter().any(|dep| dep.as_name() == "aztec");
if has_aztec_dependency {
Ok(())
} else {
Err((DefCollectorErrorKind::AztecNotFound {}, crate_graph.root_file_id))
Err((AztecMacroError::AztecNotFound.into(), crate_graph.root_file_id))
}
}

Expand All @@ -234,10 +265,7 @@ fn check_for_compute_note_hash_and_nullifier_definition(module: &SortedModule) -
// Array(Option<UnresolvedTypeExpression>, Box<UnresolvedType>) contains only fields
&& match &func.def.parameters[3].typ.typ {
UnresolvedTypeData::Array(_, inner_type) => {
match inner_type.typ {
UnresolvedTypeData::FieldElement => true,
_ => false,
}
matches!(inner_type.typ, UnresolvedTypeData::FieldElement)
},
_ => false,
}
Expand All @@ -247,10 +275,7 @@ fn check_for_compute_note_hash_and_nullifier_definition(module: &SortedModule) -
FunctionReturnType::Ty(unresolved_type) => {
match &unresolved_type.typ {
UnresolvedTypeData::Array(_, inner_type) => {
match inner_type.typ {
UnresolvedTypeData::FieldElement => true,
_ => false,
}
matches!(inner_type.typ, UnresolvedTypeData::FieldElement)
},
_ => false,
}
Expand All @@ -274,19 +299,18 @@ fn is_custom_attribute(attr: &SecondaryAttribute, attribute_name: &str) -> bool
fn transform_module(
module: &mut SortedModule,
crate_id: &CrateId,
context: &Context,
) -> Result<bool, (DefCollectorErrorKind, FileId)> {
context: &HirContext,
) -> Result<bool, (MacroError, FileId)> {
let mut has_transformed_module = false;

// Check for a user defined storage struct
let storage_defined = check_for_storage_definition(&module);
let storage_defined = check_for_storage_definition(module);

if storage_defined && !check_for_compute_note_hash_and_nullifier_definition(&module) {
if storage_defined && !check_for_compute_note_hash_and_nullifier_definition(module) {
let crate_graph = &context.crate_graph[crate_id];
return Err((
DefCollectorErrorKind::AztecComputeNoteHashAndNullifierNotFound {
span: Span::default(), // Add a default span so we know which contract file the error originates from
},
AztecMacroError::AztecComputeNoteHashAndNullifierNotFound { span: Span::default() }
.into(),
crate_graph.root_file_id,
));
}
Expand Down Expand Up @@ -374,7 +398,7 @@ fn transform_unconstrained(func: &mut NoirFunction) {
func.def.body.0.insert(0, abstract_storage("Unconstrained", true));
}

fn collect_crate_structs(crate_id: &CrateId, context: &Context) -> Vec<StructId> {
fn collect_crate_structs(crate_id: &CrateId, context: &HirContext) -> Vec<StructId> {
context
.def_map(crate_id)
.expect("ICE: Missing crate in def_map")
Expand Down Expand Up @@ -444,7 +468,7 @@ fn transform_event(struct_id: StructId, interner: &mut NodeInterner) {
}
}

fn transform_events(crate_id: &CrateId, context: &mut Context) {
fn transform_events(crate_id: &CrateId, context: &mut HirContext) {
for struct_id in collect_crate_structs(crate_id, context) {
let attributes = context.def_interner.struct_attributes(&struct_id);
if attributes.iter().any(|attr| matches!(attr, SecondaryAttribute::Event)) {
Expand Down Expand Up @@ -514,7 +538,7 @@ fn generate_selector_impl(structure: &NoirStruct) -> TypeImpl {
/// fn foo() {
/// // ...
/// }
pub(crate) fn create_inputs(ty: &str) -> Param {
fn create_inputs(ty: &str) -> Param {
let context_ident = ident("inputs");
let context_pattern = Pattern::Identifier(context_ident);
let type_path = chained_path!("aztec", "abi", ty);
Expand Down Expand Up @@ -574,7 +598,7 @@ fn create_context(ty: &str, params: &[Param]) -> Vec<Statement> {
// `hasher.add_multiple({ident}.serialize())`
UnresolvedTypeData::Named(..) => add_struct_to_hasher(identifier),
UnresolvedTypeData::Array(_, arr_type) => {
add_array_to_hasher(identifier, &arr_type)
add_array_to_hasher(identifier, arr_type)
}
// `hasher.add({ident})`
UnresolvedTypeData::FieldElement => add_field_to_hasher(identifier),
Expand Down Expand Up @@ -819,7 +843,7 @@ fn make_castable_return_type(expression: Expression) -> Statement {
/// fn foo() {
/// // ...
/// }
pub(crate) fn create_return_type(ty: &str) -> FunctionReturnType {
fn create_return_type(ty: &str) -> FunctionReturnType {
let return_path = chained_path!("aztec", "abi", ty);

let ty = make_type(UnresolvedTypeData::Named(return_path, vec![]));
Expand All @@ -844,7 +868,7 @@ pub(crate) fn create_return_type(ty: &str) -> FunctionReturnType {
/// fn foo() {
/// // ...
/// }
pub(crate) fn create_context_finish() -> Statement {
fn create_context_finish() -> Statement {
let method_call = method_call(
variable("context"), // variable
"finish", // method name
Expand Down Expand Up @@ -875,7 +899,7 @@ fn add_struct_to_hasher(identifier: &Ident) -> Statement {
fn create_loop_over(var: Expression, loop_body: Vec<Statement>) -> Statement {
// If this is an array of primitive types (integers / fields) we can add them each to the hasher
// casted to a field
let span = var.span.clone();
let span = var.span;

// `array.len()`
let end_range_expression = method_call(
Expand Down
5 changes: 5 additions & 0 deletions compiler/noirc_driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ iter-extended.workspace = true
fm.workspace = true
serde.workspace = true
fxhash.workspace = true

aztec_macros ={path = "../../aztec_macros", optional = true}

[features]
aztec = ["aztec_macros"]
8 changes: 7 additions & 1 deletion compiler/noirc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use noirc_evaluator::errors::RuntimeError;
use noirc_frontend::graph::{CrateId, CrateName};
use noirc_frontend::hir::def_map::{Contract, CrateDefMap};
use noirc_frontend::hir::Context;
use noirc_frontend::macros_api::MacroProcessor;
use noirc_frontend::monomorphization::monomorphize;
use noirc_frontend::node_interner::FuncId;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -121,8 +122,13 @@ pub fn check_crate(
crate_id: CrateId,
deny_warnings: bool,
) -> CompilationResult<()> {
#[cfg(not(feature = "aztec"))]
let macros: Vec<&dyn MacroProcessor> = Vec::new();
#[cfg(feature = "aztec")]
let macros = vec![&aztec_macros::AztecMacro as &dyn MacroProcessor];

let mut errors = vec![];
let diagnostics = CrateDefMap::collect_defs(crate_id, context);
let diagnostics = CrateDefMap::collect_defs(crate_id, context, macros);
errors.extend(diagnostics.into_iter().map(|(error, file_id)| {
let diagnostic: CustomDiagnostic = error.into();
diagnostic.in_file(file_id)
Expand Down
3 changes: 0 additions & 3 deletions compiler/noirc_frontend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,3 @@ regex = "1.9.1"
[dev-dependencies]
strum = "0.24"
strum_macros = "0.24"

[features]
aztec = []
15 changes: 10 additions & 5 deletions compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::hir::resolution::{
use crate::hir::type_check::{type_check_func, TypeCheckError, TypeChecker};
use crate::hir::Context;
use crate::hir_def::traits::{Trait, TraitConstant, TraitFunction, TraitImpl, TraitType};
use crate::macros_api::MacroProcessor;
use crate::node_interner::{
FuncId, NodeInterner, StmtId, StructId, TraitId, TraitImplId, TypeAliasId,
};
Expand Down Expand Up @@ -199,6 +200,7 @@ impl DefCollector {
context: &mut Context,
ast: SortedModule,
root_file_id: FileId,
macro_processors: Vec<&dyn MacroProcessor>,
) -> Vec<(CompilationError, FileId)> {
let mut errors: Vec<(CompilationError, FileId)> = vec![];
let crate_id = def_map.krate;
Expand All @@ -211,7 +213,11 @@ impl DefCollector {
let crate_graph = &context.crate_graph[crate_id];

for dep in crate_graph.dependencies.clone() {
errors.extend(CrateDefMap::collect_defs(dep.crate_id, context));
errors.extend(CrateDefMap::collect_defs(
dep.crate_id,
context,
macro_processors.clone(),
));

let dep_def_root =
context.def_map(&dep.crate_id).expect("ice: def map was just created").root;
Expand Down Expand Up @@ -341,10 +347,9 @@ impl DefCollector {

errors.extend(resolved_globals.errors);

// We run hir transformations before type checks
#[cfg(feature = "aztec")]
crate::hir::aztec_library::transform_hir(&crate_id, context);

for macro_processor in macro_processors {
macro_processor.process_typed_ast(&crate_id, context);
}
errors.extend(type_check_globals(&mut context.def_interner, resolved_globals.globals));

// Type check all of the functions in the crate
Expand Down
Loading

0 comments on commit ae56683

Please sign in to comment.