Skip to content
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
2 changes: 2 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
Expand Up @@ -196,6 +196,7 @@ tracing-web = "0.1.3"
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "json"] }
rust-embed = "6.6.0"
petgraph = "0.6"
insta = "1.42.2"

[profile.dev]
# This is required to be able to run `cargo test` in acvm_js due to the `locals exceeds maximum` error.
Expand Down
2 changes: 1 addition & 1 deletion acvm-repo/acir/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ fxhash.workspace = true
criterion.workspace = true
pprof.workspace = true
num-bigint.workspace = true
insta = "1.42.2"
insta.workspace = true

acir = { path = ".", features = ["arb"] } # Self to turn on `arb`.

Expand Down
1 change: 1 addition & 0 deletions compiler/noirc_frontend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ base64.workspace = true
function_name = "0.3.0"
proptest.workspace = true
proptest-derive.workspace = true
insta.workspace = true

[features]
bn254 = []
Expand Down
11 changes: 2 additions & 9 deletions compiler/noirc_frontend/src/monomorphization/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,20 +443,13 @@ impl std::ops::IndexMut<FuncId> for Program {

impl std::fmt::Display for Program {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut printer = super::printer::AstPrinter::default();
for (id, global) in &self.globals {
printer.print_global(id, global, f)?;
}
for function in &self.functions {
printer.print_function(function, f)?;
}
Ok(())
super::printer::AstPrinter::default().print_program(self, f)
}
}

impl std::fmt::Display for Function {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
super::printer::AstPrinter::default().print_function(self, f)
super::printer::AstPrinter::default().print_function(self, None, f)
}
}

Expand Down
81 changes: 65 additions & 16 deletions compiler/noirc_frontend/src/monomorphization/printer.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,93 @@
//! This module implements printing of the monomorphized AST, for debugging purposes.

use crate::ast::UnaryOp;
use crate::{ast::UnaryOp, shared::Visibility};

use super::ast::{Definition, Expression, Function, GlobalId, LValue, Type, While};
use super::ast::{
Definition, Expression, FuncId, Function, GlobalId, LValue, LocalId, Program, Type, While,
};
use iter_extended::vecmap;
use std::fmt::{Display, Formatter};

#[derive(Default)]
#[derive(Debug)]
pub struct AstPrinter {
indent_level: u32,
pub show_id: bool,
}

impl Default for AstPrinter {
fn default() -> Self {
Self { indent_level: 0, show_id: true }
}
}

impl AstPrinter {
fn fmt_ident(&self, name: &str, definition: &Definition) -> String {
if self.show_id { format!("{}${}", name, definition) } else { name.to_string() }
}

fn fmt_local(&self, name: &str, id: LocalId) -> String {
self.fmt_ident(name, &Definition::Local(id))
}

fn fmt_global(&self, name: &str, id: GlobalId) -> String {
self.fmt_ident(name, &Definition::Global(id))
}

fn fmt_func(&self, name: &str, id: FuncId) -> String {
self.fmt_ident(name, &Definition::Function(id))
}

pub fn print_program(&mut self, program: &Program, f: &mut Formatter) -> std::fmt::Result {
for (id, global) in &program.globals {
self.print_global(id, global, f)?;
}
for function in &program.functions {
let vis = (function.id == Program::main_id()).then_some(program.return_visibility);
self.print_function(function, vis, f)?;
}
Ok(())
}

pub fn print_global(
&mut self,
id: &GlobalId,
(name, typ, expr): &(String, Type, Expression),
f: &mut Formatter,
) -> std::fmt::Result {
write!(f, "global {}$g{}: {} = ", name, id.0, typ)?;
write!(f, "global {}: {} = ", self.fmt_global(name, *id), typ)?;
self.print_expr(expr, f)?;
write!(f, ";")?;
self.next_line(f)
}

pub fn print_function(&mut self, function: &Function, f: &mut Formatter) -> std::fmt::Result {
pub fn print_function(
&mut self,
function: &Function,
return_visibility: Option<Visibility>,
f: &mut Formatter,
) -> std::fmt::Result {
let params = vecmap(&function.parameters, |(id, mutable, name, typ)| {
format!("{}{}$l{}: {}", if *mutable { "mut " } else { "" }, name, id.0, typ)
format!("{}{}: {}", if *mutable { "mut " } else { "" }, self.fmt_local(name, *id), typ)
})
.join(", ");

let vis = return_visibility
.map(|vis| match vis {
Visibility::Private => "".to_string(),
Visibility::Public => "pub ".to_string(),
Visibility::ReturnData => "return_data ".to_string(),
Visibility::CallData(i) => format!("call_data({i}) "),
})
.unwrap_or_default();

write!(
f,
"{}fn {}$f{}({}) -> {} {{",
"{}fn {}({}) -> {}{} {{",
if function.unconstrained { "unconstrained " } else { "" },
function.name,
function.id,
self.fmt_func(&function.name, function.id),
params,
function.return_type
vis,
function.return_type,
)?;
self.indent_level += 1;
self.print_expr_expect_block(&function.body, f)?;
Expand All @@ -49,7 +99,7 @@ impl AstPrinter {
pub fn print_expr(&mut self, expr: &Expression, f: &mut Formatter) -> std::fmt::Result {
match expr {
Expression::Ident(ident) => {
write!(f, "{}${}", ident.name, ident.definition)
write!(f, "{}", self.fmt_ident(&ident.name, &ident.definition))
}
Expression::Literal(literal) => self.print_literal(literal, f),
Expression::Block(exprs) => self.print_block(exprs, f),
Expand Down Expand Up @@ -80,10 +130,9 @@ impl AstPrinter {
Expression::Let(let_expr) => {
write!(
f,
"let {}{}${} = ",
"let {}{} = ",
if let_expr.mutable { "mut " } else { "" },
let_expr.name,
let_expr.id.0
self.fmt_local(&let_expr.name, let_expr.id),
)?;
self.print_expr(&let_expr.expression, f)
}
Expand Down Expand Up @@ -234,7 +283,7 @@ impl AstPrinter {
for_expr: &super::ast::For,
f: &mut Formatter,
) -> Result<(), std::fmt::Error> {
write!(f, "for {}${} in ", for_expr.index_name, for_expr.index_variable.0)?;
write!(f, "for {} in ", self.fmt_local(&for_expr.index_name, for_expr.index_variable))?;
self.print_expr(&for_expr.start_range, f)?;
write!(f, " .. ")?;
self.print_expr(&for_expr.end_range, f)?;
Expand Down Expand Up @@ -366,7 +415,7 @@ impl AstPrinter {

fn print_lvalue(&mut self, lvalue: &LValue, f: &mut Formatter) -> std::fmt::Result {
match lvalue {
LValue::Ident(ident) => write!(f, "{}${}", ident.name, ident.definition),
LValue::Ident(ident) => write!(f, "{}", self.fmt_ident(&ident.name, &ident.definition)),
LValue::Index { array, index, .. } => {
self.print_lvalue(array, f)?;
write!(f, "[")?;
Expand Down
44 changes: 19 additions & 25 deletions compiler/noirc_frontend/src/monomorphization/tests.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
#![cfg(test)]
use crate::{
check_monomorphization_error_using_features,
elaborator::UnstableFeature,
test_utils::{Expect, get_monomorphized},
check_monomorphization_error_using_features, elaborator::UnstableFeature, test_utils::Expect,
};

pub(crate) fn check_rewrite(src: &str, expected: &str, test_path: &str) {
let program = get_monomorphized(src, test_path, Expect::Success).unwrap();
assert!(format!("{}", program) == expected);
}

// NOTE: this will fail in CI when called twice within one test: test names must be unique
#[macro_export]
macro_rules! get_monomorphized {
Expand Down Expand Up @@ -98,12 +91,12 @@
Zero,
^^^^ Type `Odd` is recursive
~~~~ All types in Noir must have a known size at compile-time
Succ(Odd),

Check warning on line 94 in compiler/noirc_frontend/src/monomorphization/tests.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (Succ)
}

enum Odd {
One,
Succ(Even),

Check warning on line 99 in compiler/noirc_frontend/src/monomorphization/tests.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (Succ)
}
";
let features = vec![UnstableFeature::Enums];
Expand All @@ -121,23 +114,24 @@
}
"#;

let expected_rewrite = r#"fn main$f0() -> Field {
let x$0 = 1;
let closure$3 = {
let closure_variable$2 = {
let env$1 = (x$l0);
(env$l1, lambda$f1)
let program = get_monomorphized!(src, Expect::Success).unwrap();
insta::assert_snapshot!(program, @r"
fn main$f0() -> pub Field {
let x$l0 = 1;
let closure$l3 = {
let closure_variable$l2 = {
let env$l1 = (x$l0);
(env$l1, lambda$f1)
};
closure_variable$l2
};
closure_variable$l2
};
{
let tmp$4 = closure$l3;
tmp$l4.1(tmp$l4.0)
{
let tmp$l4 = closure$l3;
tmp$l4.1(tmp$l4.0)
}
}
}
fn lambda$f1(mut env$l1: (Field)) -> Field {
env$l1.0
}
"#;
check_rewrite!(src, expected_rewrite);
fn lambda$f1(mut env$l1: (Field)) -> Field {
env$l1.0
}
");
}
4 changes: 2 additions & 2 deletions tooling/ast_fuzzer/examples/sample.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//! cargo run -p noir_ast_fuzzer --example sample
//! ```
use arbitrary::Unstructured;
use noir_ast_fuzzer::{Config, arb_program};
use noir_ast_fuzzer::{Config, DisplayAstAsNoir, arb_program};
use rand::RngCore;

fn main() {
Expand All @@ -18,5 +18,5 @@ fn main() {

let program = arb_program(&mut u, Config::default()).expect("arb_program");

println!("{program}");
println!("{}", DisplayAstAsNoir(&program));
}
1 change: 1 addition & 0 deletions tooling/ast_fuzzer/fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ color-eyre.workspace = true
libfuzzer-sys.workspace = true

acir.workspace = true
noirc_abi.workspace = true
noirc_evaluator.workspace = true
noirc_frontend.workspace = true

Expand Down
17 changes: 12 additions & 5 deletions tooling/ast_fuzzer/fuzz/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use acir::circuit::ExpressionWidth;
use color_eyre::eyre;
use noir_ast_fuzzer::DisplayAstAsNoir;
use noir_ast_fuzzer::compare::{CompareResult, CompareSsa};
use noirc_abi::input_parser::Format;
use noirc_evaluator::{
brillig::BrilligOptions,
ssa::{self, SsaEvaluatorOptions, SsaProgramArtifact},
Expand Down Expand Up @@ -44,7 +46,7 @@ pub fn create_ssa_or_die(
// and print the AST, then resume the panic, because
// `Program` has a `RefCell` in it, which is not unwind safe.
if show_ast() {
eprintln!("---\n{program}\n---");
eprintln!("---\n{}\n---", DisplayAstAsNoir(&program));
}

ssa::create_program(program, options).unwrap_or_else(|e| {
Expand All @@ -69,11 +71,16 @@ where

if res.is_err() {
for (i, ast) in asts(inputs).into_iter().enumerate() {
eprintln!("AST {}:\n{}", i + 1, ast);
eprintln!("---\nAST {}:\n{}", i + 1, DisplayAstAsNoir(ast));
}
eprintln!("Inputs:\n{:?}", inputs.input_map);
eprintln!("Program 1:\n{}", inputs.ssa1.program);
eprintln!("Program 2:\n{}", inputs.ssa2.program);
eprintln!(
"---\nInputs:\n{}",
Format::Toml
.serialize(&inputs.input_map, &inputs.abi)
.unwrap_or_else(|e| format!("failed to serialize inputs: {e}"))
);
eprintln!("---\nProgram 1:\n{}", inputs.ssa1.program);
eprintln!("---\nProgram 2:\n{}", inputs.ssa2.program);
}

res.map(|_| ())
Expand Down
2 changes: 1 addition & 1 deletion tooling/ast_fuzzer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ mod program;

pub use abi::program_abi;
pub use input::arb_inputs;
pub use program::arb_program;
use program::freq::Freqs;
pub use program::{DisplayAstAsNoir, arb_program};

/// AST generation configuration.
#[derive(Debug, Clone)]
Expand Down
Loading
Loading