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

chore: Pull out aztec macros to their own crate and create an API for them in the compiler frontend #3578

Merged
merged 21 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
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];
kevaundray marked this conversation as resolved.
Show resolved Hide resolved

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
Loading