From b4a263b0bed2ef6764a03364428216be2d2f4d81 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Mon, 17 Jun 2024 17:58:49 +0000 Subject: [PATCH 1/2] [1 changes] feat: Sync from aztec-packages (https://github.com/noir-lang/noir/pull/5242) chore: replace `is_bn254` implementation to not rely on truncation of literals (https://github.com/noir-lang/noir/pull/5247) chore: add no-predicate to hash implementations (https://github.com/noir-lang/noir/pull/5253) feat(experimental): Implement macro calls & splicing into `Expr` values (https://github.com/noir-lang/noir/pull/5203) feat: add BoundedVec::map (https://github.com/noir-lang/noir/pull/5250) chore: add no predicate to poseidon2 (https://github.com/noir-lang/noir/pull/5252) feat: add `set` and `set_unchecked` methods to `Vec` and `BoundedVec` (https://github.com/noir-lang/noir/pull/5241) fix: Disable `if` optimization (https://github.com/noir-lang/noir/pull/5240) chore: redo typo PR by dropbigfish (https://github.com/noir-lang/noir/pull/5234) chore: add property tests for ABI encoding (https://github.com/noir-lang/noir/pull/5216) chore: thread generics through ACIR/brillig gen (https://github.com/noir-lang/noir/pull/5120) chore: copy across typo PR script from aztec-packages (https://github.com/noir-lang/noir/pull/5235) chore(docs): fixing trailing slash issue (https://github.com/noir-lang/noir/pull/5233) fix: add support for nested arrays returned by oracles (https://github.com/noir-lang/noir/pull/5132) chore: Parse macros (https://github.com/noir-lang/noir/pull/5229) chore: Optimize the elaborator (https://github.com/noir-lang/noir/pull/5230) fix(elaborator): Fix regression introduced by lazy-global changes (https://github.com/noir-lang/noir/pull/5223) fix(elaborator): Fix duplicate methods error (https://github.com/noir-lang/noir/pull/5225) chore: fixing all relative paths (https://github.com/noir-lang/noir/pull/5220) chore: push code related to ABI gen into `noirc_driver` (https://github.com/noir-lang/noir/pull/5218) --- .noir-sync-commit | 2 +- noir/noir-repo/Cargo.lock | 26 +- noir/noir-repo/Cargo.toml | 2 + noir/noir-repo/acvm-repo/acvm_js/build.sh | 2 +- .../noir-repo/acvm-repo/brillig_vm/src/lib.rs | 154 ++++++--- .../aztec_macros/src/utils/ast_utils.rs | 7 +- .../compiler/noirc_driver/src/abi_gen.rs | 106 +++++- .../compiler/noirc_driver/src/lib.rs | 4 +- .../src/brillig/brillig_gen.rs | 7 +- .../brillig/brillig_gen/brillig_black_box.rs | 19 +- .../src/brillig/brillig_gen/brillig_block.rs | 46 ++- .../brillig_gen/brillig_block_variables.rs | 13 +- .../brillig/brillig_gen/brillig_directive.rs | 15 +- .../src/brillig/brillig_gen/brillig_fn.rs | 2 +- .../brillig/brillig_gen/brillig_slice_ops.rs | 4 +- .../noirc_evaluator/src/brillig/brillig_ir.rs | 24 +- .../src/brillig/brillig_ir/artifact.rs | 26 +- .../src/brillig/brillig_ir/codegen_binary.rs | 8 +- .../src/brillig/brillig_ir/codegen_calls.rs | 7 +- .../brillig_ir/codegen_control_flow.rs | 27 +- .../brillig/brillig_ir/codegen_intrinsic.rs | 12 +- .../src/brillig/brillig_ir/codegen_memory.rs | 5 +- .../src/brillig/brillig_ir/codegen_stack.rs | 6 +- .../src/brillig/brillig_ir/debug_show.rs | 4 +- .../src/brillig/brillig_ir/entry_point.rs | 45 ++- .../src/brillig/brillig_ir/instructions.rs | 38 +-- .../src/brillig/brillig_ir/registers.rs | 2 +- .../noirc_evaluator/src/brillig/mod.rs | 11 +- .../compiler/noirc_evaluator/src/ssa.rs | 4 +- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 195 +++++------ .../src/ssa/acir_gen/acir_ir/big_int.rs | 16 +- .../ssa/acir_gen/acir_ir/generated_acir.rs | 68 ++-- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 35 +- .../src/ssa/opt/flatten_cfg.rs | 27 +- .../src/ssa/opt/flatten_cfg/value_merger.rs | 2 +- .../noirc_frontend/src/ast/expression.rs | 52 ++- .../compiler/noirc_frontend/src/ast/mod.rs | 16 +- .../noirc_frontend/src/ast/statement.rs | 7 +- .../compiler/noirc_frontend/src/debug/mod.rs | 4 + .../src/elaborator/expressions.rs | 106 +++++- .../noirc_frontend/src/elaborator/mod.rs | 66 ++-- .../noirc_frontend/src/elaborator/types.rs | 4 +- .../noirc_frontend/src/elaborator/unquote.rs | 306 +++++++++++++++++ .../src/hir/comptime/interpreter.rs | 25 +- .../src/hir/comptime/interpreter/unquote.rs | 287 ++++++++++++++++ .../noirc_frontend/src/hir/comptime/scan.rs | 2 - .../noirc_frontend/src/hir/comptime/value.rs | 2 +- .../src/hir/def_collector/dc_crate.rs | 2 +- .../src/hir/resolution/errors.rs | 29 +- .../src/hir/resolution/resolver.rs | 18 +- .../src/hir/resolution/traits.rs | 1 + .../src/hir/type_check/errors.rs | 7 + .../noirc_frontend/src/hir/type_check/expr.rs | 2 +- .../noirc_frontend/src/hir_def/expr.rs | 12 +- .../noirc_frontend/src/hir_def/types.rs | 22 +- .../noirc_frontend/src/lexer/lexer.rs | 1 + .../noirc_frontend/src/lexer/token.rs | 11 +- .../src/monomorphization/mod.rs | 2 +- .../noirc_frontend/src/node_interner.rs | 10 +- .../noirc_frontend/src/parser/parser.rs | 317 ++++-------------- .../src/parser/parser/literals.rs | 12 +- .../noirc_frontend/src/parser/parser/types.rs | 139 +++++--- .../compiler/noirc_frontend/src/tests.rs | 2 +- noir/noir-repo/cspell.json | 1 + .../docs/docs/how_to/how-to-oracles.md | 4 + .../docs/noir/concepts/data_types/arrays.md | 4 +- .../docs/noir/concepts/data_types/booleans.md | 4 +- .../docs/noir/concepts/data_types/strings.md | 2 +- .../docs/docs/noir/concepts/generics.md | 4 +- .../docs/docs/noir/concepts/unconstrained.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 2 +- .../standard_library/containers/boundedvec.md | 52 ++- .../noir/standard_library/containers/vec.mdx | 19 ++ .../docs/noir/standard_library/recursion.md | 8 +- noir/noir-repo/docs/docs/tooling/debugger.md | 2 +- noir/noir-repo/docs/docusaurus.config.ts | 1 + .../docs/src/components/Notes/_blackbox.mdx | 4 +- .../getting_started/01_hello_world.md | 4 +- .../getting_started/02_breakdown.md | 4 +- .../versioned_docs/version-v0.17.0/index.md | 4 +- .../data_types/02_booleans.md | 4 +- .../data_types/03_strings.md | 2 +- .../language_concepts/data_types/04_arrays.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../version-v0.17.0/nargo/01_commands.md | 2 +- .../standard_library/black_box_fns.md | 20 +- .../standard_library/recursion.md | 2 +- .../getting_started/01_hello_world.md | 4 +- .../getting_started/02_breakdown.md | 4 +- .../versioned_docs/version-v0.19.0/index.md | 4 +- .../data_types/02_booleans.md | 4 +- .../data_types/03_strings.md | 2 +- .../language_concepts/data_types/04_arrays.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../version-v0.19.0/nargo/01_commands.md | 2 +- .../standard_library/black_box_fns.md | 22 +- .../standard_library/recursion.md | 2 +- .../getting_started/01_hello_world.md | 4 +- .../getting_started/02_breakdown.md | 4 +- .../versioned_docs/version-v0.19.1/index.md | 4 +- .../data_types/02_booleans.md | 4 +- .../data_types/03_strings.md | 2 +- .../language_concepts/data_types/04_arrays.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../version-v0.19.1/nargo/01_commands.md | 2 +- .../standard_library/black_box_fns.md | 22 +- .../standard_library/recursion.md | 2 +- .../getting_started/01_hello_world.md | 4 +- .../getting_started/02_breakdown.md | 4 +- .../versioned_docs/version-v0.19.2/index.md | 4 +- .../data_types/02_booleans.md | 4 +- .../data_types/03_strings.md | 2 +- .../language_concepts/data_types/04_arrays.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../version-v0.19.2/nargo/01_commands.md | 2 +- .../standard_library/black_box_fns.md | 22 +- .../standard_library/recursion.md | 2 +- .../getting_started/01_hello_world.md | 4 +- .../getting_started/02_breakdown.md | 4 +- .../versioned_docs/version-v0.19.3/index.md | 4 +- .../data_types/02_booleans.md | 4 +- .../data_types/03_strings.md | 2 +- .../language_concepts/data_types/04_arrays.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../version-v0.19.3/nargo/01_commands.md | 2 +- .../standard_library/black_box_fns.md | 22 +- .../standard_library/recursion.md | 2 +- .../getting_started/01_hello_world.md | 4 +- .../getting_started/02_breakdown.md | 4 +- .../versioned_docs/version-v0.19.4/index.md | 4 +- .../data_types/02_booleans.md | 4 +- .../data_types/03_strings.md | 2 +- .../language_concepts/data_types/04_arrays.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../version-v0.19.4/nargo/01_commands.md | 2 +- .../standard_library/black_box_fns.md | 22 +- .../standard_library/recursion.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 22 +- .../noir/standard_library/recursion.md | 2 +- .../noir/syntax/data_types/arrays.md | 2 +- .../noir/syntax/data_types/booleans.md | 4 +- .../noir/syntax/data_types/strings.md | 2 +- .../noir/concepts/data_types/arrays.md | 4 +- .../noir/concepts/data_types/booleans.md | 4 +- .../noir/concepts/data_types/strings.md | 2 +- .../version-v0.23.0/noir/concepts/generics.md | 4 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 20 +- .../noir/standard_library/recursion.md | 2 +- .../noir/concepts/data_types/arrays.md | 4 +- .../noir/concepts/data_types/booleans.md | 4 +- .../noir/concepts/data_types/strings.md | 2 +- .../version-v0.24.0/noir/concepts/generics.md | 4 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 2 +- .../noir/standard_library/recursion.md | 2 +- .../noir/concepts/data_types/arrays.md | 4 +- .../noir/concepts/data_types/booleans.md | 4 +- .../noir/concepts/data_types/strings.md | 2 +- .../version-v0.25.0/noir/concepts/generics.md | 4 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 2 +- .../noir/standard_library/recursion.md | 2 +- .../noir/concepts/data_types/arrays.md | 4 +- .../noir/concepts/data_types/booleans.md | 4 +- .../noir/concepts/data_types/strings.md | 2 +- .../version-v0.26.0/noir/concepts/generics.md | 4 +- .../noir/concepts/unconstrained.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 2 +- .../noir/standard_library/recursion.md | 2 +- .../noir/concepts/data_types/arrays.md | 4 +- .../noir/concepts/data_types/booleans.md | 4 +- .../noir/concepts/data_types/strings.md | 2 +- .../version-v0.27.0/noir/concepts/generics.md | 4 +- .../noir/concepts/unconstrained.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 2 +- .../noir/standard_library/recursion.md | 2 +- .../noir/concepts/data_types/arrays.md | 4 +- .../noir/concepts/data_types/booleans.md | 4 +- .../noir/concepts/data_types/strings.md | 2 +- .../version-v0.28.0/noir/concepts/generics.md | 4 +- .../noir/concepts/unconstrained.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 2 +- .../noir/standard_library/recursion.md | 2 +- .../version-v0.28.0/tooling/debugger.md | 2 +- .../version-v0.28.0/tutorials/noirjs_app.md | 2 +- .../noir/concepts/data_types/arrays.md | 4 +- .../noir/concepts/data_types/booleans.md | 4 +- .../noir/concepts/data_types/strings.md | 2 +- .../version-v0.29.0/noir/concepts/generics.md | 4 +- .../noir/concepts/unconstrained.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 2 +- .../noir/standard_library/recursion.md | 2 +- .../version-v0.29.0/tooling/debugger.md | 2 +- .../version-v0.29.0/tutorials/noirjs_app.md | 2 +- .../noir/concepts/data_types/arrays.md | 4 +- .../noir/concepts/data_types/booleans.md | 4 +- .../noir/concepts/data_types/strings.md | 2 +- .../version-v0.30.0/noir/concepts/generics.md | 4 +- .../noir/concepts/unconstrained.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 2 +- .../noir/standard_library/recursion.md | 2 +- .../version-v0.30.0/tooling/debugger.md | 2 +- .../src/collections/bounded_vec.nr | 104 +++++- .../noir_stdlib/src/collections/vec.nr | 39 +++ noir/noir-repo/noir_stdlib/src/compat.nr | 18 +- noir/noir-repo/noir_stdlib/src/hash/mimc.nr | 1 + .../noir_stdlib/src/hash/poseidon/bn254.nr | 17 + .../noir_stdlib/src/hash/poseidon2.nr | 2 +- noir/noir-repo/noir_stdlib/src/sha256.nr | 1 + noir/noir-repo/noir_stdlib/src/sha512.nr | 1 + noir/noir-repo/scripts/redo-typo-pr.sh | 32 ++ .../macros}/Nargo.toml | 2 +- .../compile_success_empty/macros/src/main.nr | 15 + .../no_duplicate_methods/Nargo.toml | 6 + .../no_duplicate_methods/Prover.toml | 0 .../no_duplicate_methods/src/main.nr | 26 ++ .../regression_5202/Nargo.toml | 8 + .../regression_5202/fraction/LICENSE | 21 ++ .../regression_5202/fraction/Nargo.toml | 6 + .../regression_5202/fraction/README.md | 10 + .../regression_5202/fraction/src/lib.nr | 201 +++++++++++ .../regression_5202/src/main.nr | 23 ++ .../regression_5252/Nargo.toml | 7 + .../regression_5252/Prover.toml | 6 + .../regression_5252/src/main.nr | 23 ++ .../verify_honk_proof/Prover.toml | 4 - .../verify_honk_proof/src/main.nr | 21 -- .../noir_test_success/bounded_vec/src/main.nr | 27 ++ .../regression_4561/Nargo.toml | 6 + .../regression_4561/src/main.nr | 44 +++ .../tooling/debugger/ignored-tests.txt | 3 +- noir/noir-repo/tooling/nargo_cli/build.rs | 32 +- .../tooling/nargo_cli/tests/stdlib-tests.rs | 85 ++++- .../tooling/nargo_fmt/src/rewrite/expr.rs | 18 +- .../tooling/nargo_fmt/src/rewrite/typ.rs | 2 +- .../tooling/nargo_fmt/tests/expected/let.nr | 4 +- .../tooling/nargo_fmt/tests/input/let.nr | 4 +- .../noir_js_backend_barretenberg/package.json | 2 +- .../src/backend.ts | 5 +- noir/noir-repo/tooling/noirc_abi/Cargo.toml | 14 +- .../tooling/noirc_abi/src/arbitrary.rs | 154 +++++++++ noir/noir-repo/tooling/noirc_abi/src/lib.rs | 169 ++-------- noir/noir-repo/yarn.lock | 13 +- 251 files changed, 2976 insertions(+), 1296 deletions(-) create mode 100644 noir/noir-repo/compiler/noirc_frontend/src/elaborator/unquote.rs create mode 100644 noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/unquote.rs create mode 100755 noir/noir-repo/scripts/redo-typo-pr.sh rename noir/noir-repo/test_programs/{execution_success/verify_honk_proof => compile_success_empty/macros}/Nargo.toml (75%) create mode 100644 noir/noir-repo/test_programs/compile_success_empty/macros/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/Prover.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr create mode 100644 noir/noir-repo/test_programs/execution_success/regression_5202/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/regression_5202/fraction/LICENSE create mode 100644 noir/noir-repo/test_programs/execution_success/regression_5202/fraction/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/regression_5202/fraction/README.md create mode 100644 noir/noir-repo/test_programs/execution_success/regression_5202/fraction/src/lib.nr create mode 100644 noir/noir-repo/test_programs/execution_success/regression_5202/src/main.nr create mode 100644 noir/noir-repo/test_programs/execution_success/regression_5252/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/regression_5252/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/regression_5252/src/main.nr delete mode 100644 noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr create mode 100644 noir/noir-repo/test_programs/noir_test_success/regression_4561/Nargo.toml create mode 100644 noir/noir-repo/test_programs/noir_test_success/regression_4561/src/main.nr create mode 100644 noir/noir-repo/tooling/noirc_abi/src/arbitrary.rs diff --git a/.noir-sync-commit b/.noir-sync-commit index 34ef64dcc09..dc900c989b1 100644 --- a/.noir-sync-commit +++ b/.noir-sync-commit @@ -1 +1 @@ -2e543b40eb83ef2080e4d8f870f525fadd631099 +7de19f5856591203271836f07154abae13f5102b diff --git a/noir/noir-repo/Cargo.lock b/noir/noir-repo/Cargo.lock index bd575d0dca2..7b96737f241 100644 --- a/noir/noir-repo/Cargo.lock +++ b/noir/noir-repo/Cargo.lock @@ -2727,10 +2727,11 @@ version = "0.30.0" dependencies = [ "acvm", "iter-extended", - "noirc_frontend", "noirc_printable_type", "num-bigint", "num-traits", + "proptest", + "proptest-derive", "serde", "serde_json", "strum", @@ -3330,9 +3331,9 @@ dependencies = [ [[package]] name = "proptest" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c003ac8c77cb07bb74f5f198bce836a689bcd5a42574612bf14d17bfd08c20e" +checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", "bit-vec", @@ -3342,12 +3343,23 @@ dependencies = [ "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax 0.7.4", + "regex-syntax 0.8.2", "rusty-fork", "tempfile", "unarray", ] +[[package]] +name = "proptest-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf16337405ca084e9c78985114633b6827711d22b9e6ef6c6c0d665eb3f0b6e" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -3579,12 +3591,6 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" -[[package]] -name = "regex-syntax" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" - [[package]] name = "regex-syntax" version = "0.8.2" diff --git a/noir/noir-repo/Cargo.toml b/noir/noir-repo/Cargo.toml index c08e9f9f38b..639807819ab 100644 --- a/noir/noir-repo/Cargo.toml +++ b/noir/noir-repo/Cargo.toml @@ -141,6 +141,8 @@ jsonrpc = { version = "0.16.0", features = ["minreq_http"] } flate2 = "1.0.24" rand = "0.8.5" proptest = "1.2.0" +proptest-derive = "0.4.0" + im = { version = "15.1", features = ["serde"] } tracing = "0.1.40" diff --git a/noir/noir-repo/acvm-repo/acvm_js/build.sh b/noir/noir-repo/acvm-repo/acvm_js/build.sh index c07d2d8a4c1..16fb26e55db 100755 --- a/noir/noir-repo/acvm-repo/acvm_js/build.sh +++ b/noir/noir-repo/acvm-repo/acvm_js/build.sh @@ -25,7 +25,7 @@ function run_if_available { require_command jq require_command cargo require_command wasm-bindgen -#require_command wasm-opt +require_command wasm-opt self_path=$(dirname "$(readlink -f "$0")") pname=$(cargo read-manifest | jq -r '.name') diff --git a/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs b/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs index da9a34f1044..862162ddccf 100644 --- a/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs +++ b/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs @@ -482,60 +482,64 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { destinations.iter().zip(destination_value_types).zip(&values) { match (destination, value_type) { - (ValueOrArray::MemoryAddress(value_index), HeapValueType::Simple(bit_size)) => { - match output { - ForeignCallParam::Single(value) => { - self.write_value_to_memory(*value_index, value, *bit_size)?; - } - _ => return Err(format!( - "Function result size does not match brillig bytecode. Expected 1 result but got {output:?}") - ), + (ValueOrArray::MemoryAddress(value_index), HeapValueType::Simple(bit_size)) => { + match output { + ForeignCallParam::Single(value) => { + self.write_value_to_memory(*value_index, value, *bit_size)?; } + _ => return Err(format!( + "Function result size does not match brillig bytecode. Expected 1 result but got {output:?}") + ), } - ( - ValueOrArray::HeapArray(HeapArray { pointer: pointer_index, size }), - HeapValueType::Array { value_types, size: type_size }, - ) if size == type_size => { - if HeapValueType::all_simple(value_types) { - match output { - ForeignCallParam::Array(values) => { - if values.len() != *size { - return Err("Foreign call result array doesn't match expected size".to_string()); - } - self.write_values_to_memory_slice(*pointer_index, values, value_types)?; - } - _ => { - return Err("Function result size does not match brillig bytecode size".to_string()); + } + ( + ValueOrArray::HeapArray(HeapArray { pointer: pointer_index, size }), + HeapValueType::Array { value_types, size: type_size }, + ) if size == type_size => { + if HeapValueType::all_simple(value_types) { + match output { + ForeignCallParam::Array(values) => { + if values.len() != *size { + return Err("Foreign call result array doesn't match expected size".to_string()); } + self.write_values_to_memory_slice(*pointer_index, values, value_types)?; + } + _ => { + return Err("Function result size does not match brillig bytecode size".to_string()); } - } else { - unimplemented!("deflattening heap arrays from foreign calls"); } - } - ( - ValueOrArray::HeapVector(HeapVector {pointer: pointer_index, size: size_index }), - HeapValueType::Vector { value_types }, - ) => { - if HeapValueType::all_simple(value_types) { - match output { - ForeignCallParam::Array(values) => { - // Set our size in the size address - self.memory.write(*size_index, values.len().into()); - - self.write_values_to_memory_slice(*pointer_index, values, value_types)?; - } - _ => { - return Err("Function result size does not match brillig bytecode size".to_string()); - } + } else { + // foreign call returning flattened values into a nested type, so the sizes do not match + let destination = self.memory.read_ref(*pointer_index); + let return_type = value_type; + let mut flatten_values_idx = 0; //index of values read from flatten_values + self.write_slice_of_values_to_memory(destination, &output.fields(), &mut flatten_values_idx, return_type)?; + } + } + ( + ValueOrArray::HeapVector(HeapVector {pointer: pointer_index, size: size_index }), + HeapValueType::Vector { value_types }, + ) => { + if HeapValueType::all_simple(value_types) { + match output { + ForeignCallParam::Array(values) => { + // Set our size in the size address + self.memory.write(*size_index, values.len().into()); + self.write_values_to_memory_slice(*pointer_index, values, value_types)?; + + } + _ => { + return Err("Function result size does not match brillig bytecode size".to_string()); } - } else { - unimplemented!("deflattening heap vectors from foreign calls"); } - } - _ => { - return Err(format!("Unexpected value type {value_type:?} for destination {destination:?}")); + } else { + unimplemented!("deflattening heap vectors from foreign calls"); } } + _ => { + return Err(format!("Unexpected value type {value_type:?} for destination {destination:?}")); + } + } } let _ = @@ -596,6 +600,66 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { Ok(()) } + /// Writes flattened values to memory, using the provided type + /// Function calls itself recursively in order to work with recursive types (nested arrays) + /// values_idx is the current index in the values vector and is incremented every time + /// a value is written to memory + /// The function returns the address of the next value to be written + fn write_slice_of_values_to_memory( + &mut self, + destination: MemoryAddress, + values: &Vec, + values_idx: &mut usize, + value_type: &HeapValueType, + ) -> Result { + let mut current_pointer = destination; + match value_type { + HeapValueType::Simple(bit_size) => { + self.write_value_to_memory(destination, &values[*values_idx], *bit_size)?; + *values_idx += 1; + Ok(MemoryAddress(destination.to_usize() + 1)) + } + HeapValueType::Array { value_types, size } => { + for _ in 0..*size { + for typ in value_types { + match typ { + HeapValueType::Simple(len) => { + self.write_value_to_memory( + current_pointer, + &values[*values_idx], + *len, + )?; + *values_idx += 1; + current_pointer = MemoryAddress(current_pointer.to_usize() + 1); + } + HeapValueType::Array { .. } => { + let destination = self.memory.read_ref(current_pointer); + let destination = self.memory.read_ref(destination); + self.write_slice_of_values_to_memory( + destination, + values, + values_idx, + typ, + )?; + current_pointer = MemoryAddress(current_pointer.to_usize() + 1); + } + HeapValueType::Vector { .. } => { + return Err(format!( + "Unsupported returned type in foreign calls {:?}", + typ + )); + } + } + } + } + Ok(current_pointer) + } + HeapValueType::Vector { .. } => { + Err(format!("Unsupported returned type in foreign calls {:?}", value_type)) + } + } + } + /// Process a binary operation. /// This method will not modify the program counter. fn process_binary_field_op( diff --git a/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs b/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs index 4706be2df25..48b3b25747b 100644 --- a/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs +++ b/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs @@ -47,12 +47,17 @@ pub fn method_call( object, method_name: ident(method_name), arguments, + is_macro_call: false, generics: None, }))) } pub fn call(func: Expression, arguments: Vec) -> Expression { - expression(ExpressionKind::Call(Box::new(CallExpression { func: Box::new(func), arguments }))) + expression(ExpressionKind::Call(Box::new(CallExpression { + func: Box::new(func), + is_macro_call: false, + arguments, + }))) } pub fn pattern(name: &str) -> Pattern { diff --git a/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs b/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs index 71dd1b18761..c71474d7731 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs @@ -2,14 +2,17 @@ use std::collections::BTreeMap; use acvm::acir::circuit::ErrorSelector; use iter_extended::vecmap; -use noirc_abi::{Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue}; -use noirc_frontend::ast::Visibility; +use noirc_abi::{ + Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue, AbiVisibility, Sign, +}; +use noirc_frontend::ast::{Signedness, Visibility}; use noirc_frontend::{ hir::Context, hir_def::{expr::HirArrayLiteral, function::Param, stmt::HirPattern, types::Type}, macros_api::{HirExpression, HirLiteral}, node_interner::{FuncId, NodeInterner}, }; +use noirc_frontend::{TypeBinding, TypeVariableKind}; /// Arranges a function signature and a generated circuit's return witnesses into a /// `noirc_abi::Abi`. @@ -20,15 +23,102 @@ pub(super) fn gen_abi( error_types: BTreeMap, ) -> Abi { let (parameters, return_type) = compute_function_abi(context, func_id); - let return_type = return_type - .map(|typ| AbiReturnType { abi_type: typ, visibility: return_visibility.into() }); + let return_type = return_type.map(|typ| AbiReturnType { + abi_type: typ, + visibility: to_abi_visibility(return_visibility), + }); let error_types = error_types .into_iter() - .map(|(selector, typ)| (selector, AbiErrorType::from_type(context, &typ))) + .map(|(selector, typ)| (selector, build_abi_error_type(context, &typ))) .collect(); Abi { parameters, return_type, error_types } } +fn build_abi_error_type(context: &Context, typ: &Type) -> AbiErrorType { + match typ { + Type::FmtString(len, item_types) => { + let length = len.evaluate_to_u32().expect("Cannot evaluate fmt length"); + let Type::Tuple(item_types) = item_types.as_ref() else { + unreachable!("FmtString items must be a tuple") + }; + let item_types = + item_types.iter().map(|typ| abi_type_from_hir_type(context, typ)).collect(); + AbiErrorType::FmtString { length, item_types } + } + _ => AbiErrorType::Custom(abi_type_from_hir_type(context, typ)), + } +} + +pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType { + match typ { + Type::FieldElement => AbiType::Field, + Type::Array(size, typ) => { + let length = size + .evaluate_to_u32() + .expect("Cannot have variable sized arrays as a parameter to main"); + let typ = typ.as_ref(); + AbiType::Array { length, typ: Box::new(abi_type_from_hir_type(context, typ)) } + } + Type::Integer(sign, bit_width) => { + let sign = match sign { + Signedness::Unsigned => Sign::Unsigned, + Signedness::Signed => Sign::Signed, + }; + + AbiType::Integer { sign, width: (*bit_width).into() } + } + Type::TypeVariable(binding, TypeVariableKind::IntegerOrField) + | Type::TypeVariable(binding, TypeVariableKind::Integer) => match &*binding.borrow() { + TypeBinding::Bound(typ) => abi_type_from_hir_type(context, typ), + TypeBinding::Unbound(_) => { + abi_type_from_hir_type(context, &Type::default_int_or_field_type()) + } + }, + Type::Bool => AbiType::Boolean, + Type::String(size) => { + let size = size + .evaluate_to_u32() + .expect("Cannot have variable sized strings as a parameter to main"); + AbiType::String { length: size } + } + + Type::Struct(def, args) => { + let struct_type = def.borrow(); + let fields = struct_type.get_fields(args); + let fields = + vecmap(fields, |(name, typ)| (name, abi_type_from_hir_type(context, &typ))); + // For the ABI, we always want to resolve the struct paths from the root crate + let path = context.fully_qualified_struct_path(context.root_crate_id(), struct_type.id); + AbiType::Struct { fields, path } + } + Type::Alias(def, args) => abi_type_from_hir_type(context, &def.borrow().get_type(args)), + Type::Tuple(fields) => { + let fields = vecmap(fields, |typ| abi_type_from_hir_type(context, typ)); + AbiType::Tuple { fields } + } + Type::Error + | Type::Unit + | Type::Constant(_) + | Type::TraitAsType(..) + | Type::TypeVariable(_, _) + | Type::NamedGeneric(..) + | Type::Forall(..) + | Type::Expr + | Type::Slice(_) + | Type::Function(_, _, _) => unreachable!("{typ} cannot be used in the abi"), + Type::FmtString(_, _) => unreachable!("format strings cannot be used in the abi"), + Type::MutableReference(_) => unreachable!("&mut cannot be used in the abi"), + } +} + +fn to_abi_visibility(value: Visibility) -> AbiVisibility { + match value { + Visibility::Public => AbiVisibility::Public, + Visibility::Private => AbiVisibility::Private, + Visibility::DataBus => AbiVisibility::DataBus, + } +} + pub(super) fn compute_function_abi( context: &Context, func_id: &FuncId, @@ -37,7 +127,7 @@ pub(super) fn compute_function_abi( let (parameters, return_type) = func_meta.function_signature(); let parameters = into_abi_params(context, parameters); - let return_type = return_type.map(|typ| AbiType::from_type(context, &typ)); + let return_type = return_type.map(|typ| abi_type_from_hir_type(context, &typ)); (parameters, return_type) } @@ -57,8 +147,8 @@ fn into_abi_params(context: &Context, params: Vec) -> Vec { let param_name = get_param_name(&pattern, &context.def_interner) .expect("Abi for tuple and struct parameters is unimplemented") .to_owned(); - let as_abi = AbiType::from_type(context, &typ); - AbiParameter { name: param_name, typ: as_abi, visibility: vis.into() } + let as_abi = abi_type_from_hir_type(context, &typ); + AbiParameter { name: param_name, typ: as_abi, visibility: to_abi_visibility(vis) } }) } diff --git a/noir/noir-repo/compiler/noirc_driver/src/lib.rs b/noir/noir-repo/compiler/noirc_driver/src/lib.rs index f8043a60f8c..2c8679eaa95 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/lib.rs @@ -3,7 +3,7 @@ #![warn(unreachable_pub)] #![warn(clippy::semicolon_if_nothing_returned)] -use abi_gen::value_from_hir_expression; +use abi_gen::{abi_type_from_hir_type, value_from_hir_expression}; use acvm::acir::circuit::ExpressionWidth; use clap::Args; use fm::{FileId, FileManager}; @@ -468,7 +468,7 @@ fn compile_contract_inner( let typ = context.def_interner.get_struct(struct_id); let typ = typ.borrow(); let fields = vecmap(typ.get_fields(&[]), |(name, typ)| { - (name, AbiType::from_type(context, &typ)) + (name, abi_type_from_hir_type(context, &typ)) }); let path = context.fully_qualified_struct_path(context.root_crate_id(), typ.id); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen.rs index 5576d673f1d..ee61a9d13d3 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen.rs @@ -6,12 +6,17 @@ pub(crate) mod brillig_fn; pub(crate) mod brillig_slice_ops; mod variable_liveness; +use acvm::FieldElement; + use self::{brillig_block::BrilligBlock, brillig_fn::FunctionContext}; use super::brillig_ir::{artifact::BrilligArtifact, BrilligContext}; use crate::ssa::ir::function::Function; /// Converting an SSA function into Brillig bytecode. -pub(crate) fn convert_ssa_function(func: &Function, enable_debug_trace: bool) -> BrilligArtifact { +pub(crate) fn convert_ssa_function( + func: &Function, + enable_debug_trace: bool, +) -> BrilligArtifact { let mut brillig_context = BrilligContext::new(enable_debug_trace); let mut function_context = FunctionContext::new(func); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs index f56c5daf315..367cdbe4973 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs @@ -1,18 +1,19 @@ use acvm::{ acir::{brillig::BlackBoxOp, BlackBoxFunc}, - FieldElement, + AcirField, }; use crate::brillig::brillig_ir::{ brillig_variable::{BrilligVariable, BrilligVector, SingleAddrVariable}, + debug_show::DebugToString, BrilligBinaryOp, BrilligContext, }; /// Transforms SSA's black box function calls into the corresponding brillig instructions /// Extracting arguments and results from the SSA function call /// And making any necessary type conversions to adapt noir's blackbox calls to brillig's -pub(crate) fn convert_black_box_call( - brillig_context: &mut BrilligContext, +pub(crate) fn convert_black_box_call( + brillig_context: &mut BrilligContext, bb_func: &BlackBoxFunc, function_arguments: &[BrilligVariable], function_results: &[BrilligVariable], @@ -341,7 +342,7 @@ pub(crate) fn convert_black_box_call( let inputs_vector = convert_array_or_vector(brillig_context, inputs, bb_func); let modulus_vector = convert_array_or_vector(brillig_context, modulus, bb_func); let output_id = brillig_context.get_new_bigint_id(); - brillig_context.const_instruction(*output, FieldElement::from(output_id as u128)); + brillig_context.const_instruction(*output, F::from(output_id as u128)); brillig_context.black_box_op_instruction(BlackBoxOp::BigIntFromLeBytes { inputs: inputs_vector.to_heap_vector(), modulus: modulus_vector.to_heap_vector(), @@ -426,8 +427,8 @@ pub(crate) fn convert_black_box_call( } } -fn convert_array_or_vector( - brillig_context: &mut BrilligContext, +fn convert_array_or_vector( + brillig_context: &mut BrilligContext, array_or_vector: &BrilligVariable, bb_func: &BlackBoxFunc, ) -> BrilligVector { @@ -442,8 +443,8 @@ fn convert_array_or_vector( } } -fn prepare_bigint_output( - brillig_context: &mut BrilligContext, +fn prepare_bigint_output( + brillig_context: &mut BrilligContext, lhs_modulus: &SingleAddrVariable, rhs_modulus: &SingleAddrVariable, output: &SingleAddrVariable, @@ -465,6 +466,6 @@ fn prepare_bigint_output( brillig_context.deallocate_register(condition); // Set output id let output_id = brillig_context.get_new_bigint_id(); - brillig_context.const_instruction(*output, FieldElement::from(output_id as u128)); + brillig_context.const_instruction(*output, F::from(output_id as u128)); brillig_context.mov_instruction(modulus_id.address, lhs_modulus.address); } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index 1fa4f41b29c..b441e8be3eb 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -33,7 +33,7 @@ pub(crate) struct BrilligBlock<'block> { /// The basic block that is being converted pub(crate) block_id: BasicBlockId, /// Context for creating brillig opcodes - pub(crate) brillig_context: &'block mut BrilligContext, + pub(crate) brillig_context: &'block mut BrilligContext, /// Tracks the available variable during the codegen of the block pub(crate) variables: BlockVariables, /// For each instruction, the set of values that are not used anymore after it. @@ -44,7 +44,7 @@ impl<'block> BrilligBlock<'block> { /// Converts an SSA Basic block into a sequence of Brillig opcodes pub(crate) fn compile( function_context: &'block mut FunctionContext, - brillig_context: &'block mut BrilligContext, + brillig_context: &'block mut BrilligContext, block_id: BasicBlockId, dfg: &DataFlowGraph, ) { @@ -944,7 +944,7 @@ impl<'block> BrilligBlock<'block> { } pub(crate) fn store_variable_in_array_with_ctx( - ctx: &mut BrilligContext, + ctx: &mut BrilligContext, destination_pointer: MemoryAddress, index_register: SingleAddrVariable, value_variable: BrilligVariable, @@ -1737,8 +1737,7 @@ impl<'block> BrilligBlock<'block> { dfg, ); let array = variable.extract_array(); - self.brillig_context.codegen_allocate_fixed_length_array(array.pointer, array.size); - self.brillig_context.usize_const_instruction(array.rc, 1_usize.into()); + self.allocate_nested_array(typ, Some(array)); variable } @@ -1765,6 +1764,43 @@ impl<'block> BrilligBlock<'block> { } } + fn allocate_nested_array( + &mut self, + typ: &Type, + array: Option, + ) -> BrilligVariable { + match typ { + Type::Array(types, size) => { + let array = array.unwrap_or(BrilligArray { + pointer: self.brillig_context.allocate_register(), + size: *size, + rc: self.brillig_context.allocate_register(), + }); + self.brillig_context.codegen_allocate_fixed_length_array(array.pointer, array.size); + self.brillig_context.usize_const_instruction(array.rc, 1_usize.into()); + + let mut index = 0_usize; + for _ in 0..*size { + for element_type in types.iter() { + match element_type { + Type::Array(_, _) => { + let inner_array = self.allocate_nested_array(element_type, None); + let idx = + self.brillig_context.make_usize_constant_instruction(index.into()); + self.store_variable_in_array(array.pointer, idx, inner_array); + } + Type::Slice(_) => unreachable!("ICE: unsupported slice type in allocate_nested_array(), expects an array or a numeric type"), + _ => (), + } + index += 1; + } + } + BrilligVariable::BrilligArray(array) + } + _ => unreachable!("ICE: allocate_nested_array() expects an array, got {typ:?}"), + } + } + /// Gets the "user-facing" length of an array. /// An array of structs with two fields would be stored as an 2 * array.len() array/vector. /// So we divide the length by the number of subitems in an item to get the user-facing length. diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs index fb9a8577d94..ffbca256d28 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs @@ -1,3 +1,4 @@ +use acvm::FieldElement; use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; use crate::{ @@ -50,7 +51,7 @@ impl BlockVariables { pub(crate) fn define_variable( &mut self, function_context: &mut FunctionContext, - brillig_context: &mut BrilligContext, + brillig_context: &mut BrilligContext, value_id: ValueId, dfg: &DataFlowGraph, ) -> BrilligVariable { @@ -70,7 +71,7 @@ impl BlockVariables { pub(crate) fn define_single_addr_variable( &mut self, function_context: &mut FunctionContext, - brillig_context: &mut BrilligContext, + brillig_context: &mut BrilligContext, value: ValueId, dfg: &DataFlowGraph, ) -> SingleAddrVariable { @@ -83,7 +84,7 @@ impl BlockVariables { &mut self, value_id: &ValueId, function_context: &mut FunctionContext, - brillig_context: &mut BrilligContext, + brillig_context: &mut BrilligContext, ) { assert!(self.available_variables.remove(value_id), "ICE: Variable is not available"); let variable = function_context @@ -122,7 +123,7 @@ impl BlockVariables { /// We keep constants block-local. pub(crate) fn allocate_constant( &mut self, - brillig_context: &mut BrilligContext, + brillig_context: &mut BrilligContext, value_id: ValueId, dfg: &DataFlowGraph, ) -> BrilligVariable { @@ -154,9 +155,9 @@ pub(crate) fn compute_array_length(item_typ: &CompositeType, elem_count: usize) } /// For a given value_id, allocates the necessary registers to hold it. -pub(crate) fn allocate_value( +pub(crate) fn allocate_value( value_id: ValueId, - brillig_context: &mut BrilligContext, + brillig_context: &mut BrilligContext, dfg: &DataFlowGraph, ) -> BrilligVariable { let typ = dfg.type_of_value(value_id); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs index 74319595795..ae159f2c45c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs @@ -1,13 +1,12 @@ use acvm::{ acir::brillig::{BinaryFieldOp, BinaryIntOp, MemoryAddress, Opcode as BrilligOpcode}, acir::AcirField, - FieldElement, }; use crate::brillig::brillig_ir::artifact::GeneratedBrillig; /// Generates brillig bytecode which computes the inverse of its input if not null, and zero else. -pub(crate) fn directive_invert() -> GeneratedBrillig { +pub(crate) fn directive_invert() -> GeneratedBrillig { // We generate the following code: // fn invert(x : Field) -> Field { // 1/ x @@ -28,8 +27,8 @@ pub(crate) fn directive_invert() -> GeneratedBrillig { // Put value zero in register (2) BrilligOpcode::Const { destination: zero_const, - value: FieldElement::from(0_usize), - bit_size: FieldElement::max_num_bits(), + value: F::from(0_usize), + bit_size: F::max_num_bits(), }, BrilligOpcode::BinaryFieldOp { op: BinaryFieldOp::Equals, @@ -42,8 +41,8 @@ pub(crate) fn directive_invert() -> GeneratedBrillig { // Put value one in register (1) BrilligOpcode::Const { destination: one_const, - value: FieldElement::from(1_usize), - bit_size: FieldElement::max_num_bits(), + value: F::one(), + bit_size: F::max_num_bits(), }, // Divide 1 by the input, and set the result of the division into register (0) BrilligOpcode::BinaryFieldOp { @@ -68,13 +67,13 @@ pub(crate) fn directive_invert() -> GeneratedBrillig { /// (a/b, a-a/b*b) /// } /// ``` -pub(crate) fn directive_quotient(bit_size: u32) -> GeneratedBrillig { +pub(crate) fn directive_quotient(bit_size: u32) -> GeneratedBrillig { // `a` is (0) (i.e register index 0) // `b` is (1) // TODO: The only difference between these implementations is the integer version will truncate the input to the `bit_size` via cast. // Once we deduplicate brillig functions then we can modify this so that fields and integers share the same quotient function. - if bit_size >= FieldElement::max_num_bits() { + if bit_size >= F::max_num_bits() { // Field version GeneratedBrillig { byte_code: vec![ diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs index 000d1230ece..f0752c80c46 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs @@ -28,7 +28,7 @@ pub(crate) struct FunctionContext { } impl FunctionContext { - /// Creates a new function context. It will compute the liveness of every variable. + /// Creates a new function context. It will allocate parameters for all blocks and compute the liveness of every variable. pub(crate) fn new(function: &Function) -> Self { let id = function.id(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs index 491086e8c0f..d17b15a13b5 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs @@ -372,7 +372,7 @@ mod tests { use crate::ssa::ir::map::Id; use crate::ssa::ssa_gen::Ssa; - fn create_test_environment() -> (Ssa, FunctionContext, BrilligContext) { + fn create_test_environment() -> (Ssa, FunctionContext, BrilligContext) { let mut builder = FunctionBuilder::new("main".to_string(), Id::test_new(0)); builder.set_runtime(RuntimeType::Brillig); @@ -385,7 +385,7 @@ mod tests { fn create_brillig_block<'a>( function_context: &'a mut FunctionContext, - brillig_context: &'a mut BrilligContext, + brillig_context: &'a mut BrilligContext, ) -> BrilligBlock<'a> { let variables = BlockVariables::default(); BrilligBlock { diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs index ebccf7a0bf1..9785e073be9 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs @@ -25,11 +25,13 @@ mod instructions; pub(crate) use instructions::BrilligBinaryOp; -use self::{artifact::BrilligArtifact, registers::BrilligRegistersContext}; +use self::{ + artifact::BrilligArtifact, debug_show::DebugToString, registers::BrilligRegistersContext, +}; use crate::ssa::ir::dfg::CallStack; use acvm::{ acir::brillig::{MemoryAddress, Opcode as BrilligOpcode}, - FieldElement, + AcirField, }; use debug_show::DebugShow; @@ -76,8 +78,8 @@ impl ReservedRegisters { /// Brillig context object that is used while constructing the /// Brillig bytecode. -pub(crate) struct BrilligContext { - obj: BrilligArtifact, +pub(crate) struct BrilligContext { + obj: BrilligArtifact, /// Tracks register allocations registers: BrilligRegistersContext, /// Context label, must be unique with respect to the function @@ -93,9 +95,9 @@ pub(crate) struct BrilligContext { bigint_new_id: u32, } -impl BrilligContext { +impl BrilligContext { /// Initial context state - pub(crate) fn new(enable_debug_trace: bool) -> BrilligContext { + pub(crate) fn new(enable_debug_trace: bool) -> BrilligContext { BrilligContext { obj: BrilligArtifact::default(), registers: BrilligRegistersContext::new(), @@ -113,12 +115,12 @@ impl BrilligContext { result } /// Adds a brillig instruction to the brillig byte code - fn push_opcode(&mut self, opcode: BrilligOpcode) { + fn push_opcode(&mut self, opcode: BrilligOpcode) { self.obj.push_opcode(opcode); } /// Returns the artifact - pub(crate) fn artifact(self) -> BrilligArtifact { + pub(crate) fn artifact(self) -> BrilligArtifact { self.obj } @@ -200,17 +202,17 @@ pub(crate) mod tests { } } - pub(crate) fn create_context() -> BrilligContext { + pub(crate) fn create_context() -> BrilligContext { let mut context = BrilligContext::new(true); context.enter_context("test"); context } pub(crate) fn create_entry_point_bytecode( - context: BrilligContext, + context: BrilligContext, arguments: Vec, returns: Vec, - ) -> GeneratedBrillig { + ) -> GeneratedBrillig { let artifact = context.artifact(); let mut entry_point_artifact = BrilligContext::new_entry_point_artifact(arguments, returns, "test".to_string()); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs index 99e922c1580..2d0bdb5955c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs @@ -1,4 +1,4 @@ -use acvm::{acir::brillig::Opcode as BrilligOpcode, FieldElement}; +use acvm::acir::brillig::Opcode as BrilligOpcode; use std::collections::{BTreeMap, HashMap}; use crate::ssa::ir::dfg::CallStack; @@ -18,8 +18,8 @@ pub(crate) enum BrilligParameter { /// The result of compiling and linking brillig artifacts. /// This is ready to run bytecode with attached metadata. #[derive(Debug, Default)] -pub(crate) struct GeneratedBrillig { - pub(crate) byte_code: Vec>, +pub(crate) struct GeneratedBrillig { + pub(crate) byte_code: Vec>, pub(crate) locations: BTreeMap, pub(crate) assert_messages: BTreeMap, } @@ -27,8 +27,8 @@ pub(crate) struct GeneratedBrillig { #[derive(Default, Debug, Clone)] /// Artifacts resulting from the compilation of a function into brillig byte code. /// It includes the bytecode of the function and all the metadata that allows linking with other functions. -pub(crate) struct BrilligArtifact { - pub(crate) byte_code: Vec>, +pub(crate) struct BrilligArtifact { + pub(crate) byte_code: Vec>, /// A map of bytecode positions to assertion messages. /// Some error messages (compiler intrinsics) are not emitted via revert data, /// instead, they are handled externally so they don't add size to user programs. @@ -73,9 +73,9 @@ pub(crate) type JumpInstructionPosition = OpcodeLocation; /// to their position in the bytecode. pub(crate) type UnresolvedJumpLocation = Label; -impl BrilligArtifact { +impl BrilligArtifact { /// Resolves all jumps and generates the final bytecode - pub(crate) fn finish(mut self) -> GeneratedBrillig { + pub(crate) fn finish(mut self) -> GeneratedBrillig { self.resolve_jumps(); GeneratedBrillig { byte_code: self.byte_code, @@ -94,7 +94,7 @@ impl BrilligArtifact { /// This method will offset the positions in the Brillig artifact to /// account for the fact that it is being appended to the end of this /// Brillig artifact (self). - pub(crate) fn link_with(&mut self, obj: &BrilligArtifact) { + pub(crate) fn link_with(&mut self, obj: &BrilligArtifact) { // Add the unresolved jumps of the linked function to this artifact. self.add_unresolved_jumps_and_calls(obj); @@ -128,7 +128,7 @@ impl BrilligArtifact { } /// Adds unresolved jumps & function calls from another artifact offset by the current opcode count in the artifact. - fn add_unresolved_jumps_and_calls(&mut self, obj: &BrilligArtifact) { + fn add_unresolved_jumps_and_calls(&mut self, obj: &BrilligArtifact) { let offset = self.index_of_next_opcode(); for (jump_label, jump_location) in &obj.unresolved_jumps { self.unresolved_jumps.push((jump_label + offset, jump_location.clone())); @@ -154,7 +154,7 @@ impl BrilligArtifact { } /// Adds a brillig instruction to the brillig byte code - pub(crate) fn push_opcode(&mut self, opcode: BrilligOpcode) { + pub(crate) fn push_opcode(&mut self, opcode: BrilligOpcode) { if !self.call_stack.is_empty() { self.locations.insert(self.index_of_next_opcode(), self.call_stack.clone()); } @@ -164,7 +164,7 @@ impl BrilligArtifact { /// Adds a unresolved jump to be fixed at the end of bytecode processing. pub(crate) fn add_unresolved_jump( &mut self, - jmp_instruction: BrilligOpcode, + jmp_instruction: BrilligOpcode, destination: UnresolvedJumpLocation, ) { assert!( @@ -178,7 +178,7 @@ impl BrilligArtifact { /// Adds a unresolved external call that will be fixed once linking has been done. pub(crate) fn add_unresolved_external_call( &mut self, - call_instruction: BrilligOpcode, + call_instruction: BrilligOpcode, destination: UnresolvedJumpLocation, ) { // TODO: Add a check to ensure that the opcode is a call instruction @@ -188,7 +188,7 @@ impl BrilligArtifact { } /// Returns true if the opcode is a jump instruction - fn is_jmp_instruction(instruction: &BrilligOpcode) -> bool { + fn is_jmp_instruction(instruction: &BrilligOpcode) -> bool { matches!( instruction, BrilligOpcode::JumpIfNot { .. } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_binary.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_binary.rs index 4ef279bd532..a9c4f238491 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_binary.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_binary.rs @@ -1,8 +1,8 @@ -use acvm::{acir::brillig::MemoryAddress, FieldElement}; +use acvm::{acir::brillig::MemoryAddress, AcirField}; -use super::{instructions::BrilligBinaryOp, BrilligContext}; +use super::{debug_show::DebugToString, instructions::BrilligBinaryOp, BrilligContext}; -impl BrilligContext { +impl BrilligContext { /// Utility method to perform a binary instruction with a constant value in place pub(crate) fn codegen_usize_op_in_place( &mut self, @@ -21,7 +21,7 @@ impl BrilligContext { op: BrilligBinaryOp, constant: usize, ) { - let const_register = self.make_usize_constant_instruction(FieldElement::from(constant)); + let const_register = self.make_usize_constant_instruction(F::from(constant)); self.memory_op_instruction(operand, const_register.address, destination, op); // Mark as no longer used for this purpose, frees for reuse self.deallocate_single_addr(const_register); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs index db65849a6b8..2d93cf70181 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs @@ -1,10 +1,11 @@ -use acvm::acir::brillig::MemoryAddress; +use acvm::{acir::brillig::MemoryAddress, AcirField}; use super::{ - brillig_variable::BrilligVariable, BrilligBinaryOp, BrilligContext, ReservedRegisters, + brillig_variable::BrilligVariable, debug_show::DebugToString, BrilligBinaryOp, BrilligContext, + ReservedRegisters, }; -impl BrilligContext { +impl BrilligContext { /// Saves all of the registers that have been used up until this point. fn codegen_save_registers_of_vars(&mut self, vars: &[BrilligVariable]) -> Vec { // Save all of the used registers at this point in memory diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs index fee3a450119..10badcd7308 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs @@ -1,12 +1,16 @@ -use acvm::acir::brillig::{HeapArray, MemoryAddress}; +use acvm::{ + acir::brillig::{HeapArray, MemoryAddress}, + AcirField, +}; use super::{ artifact::BrilligParameter, brillig_variable::{BrilligVariable, SingleAddrVariable}, + debug_show::DebugToString, BrilligBinaryOp, BrilligContext, ReservedRegisters, }; -impl BrilligContext { +impl BrilligContext { /// Codegens a return from the current function. /// /// For Brillig, the return is implicit, since there is no explicit return instruction. @@ -36,10 +40,11 @@ impl BrilligContext { /// This codegen will issue a loop that will iterate iteration_count times /// The body of the loop should be issued by the caller in the on_iteration closure. - pub(crate) fn codegen_loop(&mut self, iteration_count: MemoryAddress, on_iteration: F) - where - F: FnOnce(&mut BrilligContext, SingleAddrVariable), - { + pub(crate) fn codegen_loop( + &mut self, + iteration_count: MemoryAddress, + on_iteration: impl FnOnce(&mut BrilligContext, SingleAddrVariable), + ) { let iterator_register = self.make_usize_constant_instruction(0_u128.into()); let (loop_section, loop_label) = self.reserve_next_section_label(); @@ -87,7 +92,7 @@ impl BrilligContext { pub(crate) fn codegen_branch( &mut self, condition: MemoryAddress, - mut f: impl FnMut(&mut BrilligContext, bool), + mut f: impl FnMut(&mut BrilligContext, bool), ) { // Reserve 3 sections let (then_section, then_label) = self.reserve_next_section_label(); @@ -112,7 +117,7 @@ impl BrilligContext { pub(crate) fn codegen_if( &mut self, condition: MemoryAddress, - f: impl FnOnce(&mut BrilligContext), + f: impl FnOnce(&mut BrilligContext), ) { let (end_section, end_label) = self.reserve_next_section_label(); let (then_section, then_label) = self.reserve_next_section_label(); @@ -130,7 +135,7 @@ impl BrilligContext { pub(crate) fn codegen_if_not( &mut self, condition: MemoryAddress, - f: impl FnOnce(&mut BrilligContext), + f: impl FnOnce(&mut BrilligContext), ) { let (end_section, end_label) = self.reserve_next_section_label(); @@ -156,7 +161,7 @@ impl BrilligContext { let revert_data = HeapArray { pointer: ctx.allocate_register(), // + 1 due to the revert data id being the first item returned - size: BrilligContext::flattened_tuple_size(&revert_data_types) + 1, + size: Self::flattened_tuple_size(&revert_data_types) + 1, }; ctx.codegen_allocate_fixed_length_array(revert_data.pointer, revert_data.size); @@ -169,7 +174,7 @@ impl BrilligContext { for (revert_variable, revert_param) in revert_data_items.into_iter().zip(revert_data_types.into_iter()) { - let flattened_size = BrilligContext::flattened_size(&revert_param); + let flattened_size = Self::flattened_size(&revert_param); match revert_param { BrilligParameter::SingleAddr(_) => { ctx.store_instruction( diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs index 42f3b34aea0..b1cb2b19764 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs @@ -1,15 +1,15 @@ use acvm::{ acir::brillig::{BlackBoxOp, HeapArray}, acir::AcirField, - FieldElement, }; use super::{ brillig_variable::{BrilligVector, SingleAddrVariable}, + debug_show::DebugToString, BrilligContext, }; -impl BrilligContext { +impl BrilligContext { /// Codegens a truncation of a value to the given bit size pub(crate) fn codegen_truncate( &mut self, @@ -43,7 +43,7 @@ impl BrilligContext { big_endian: bool, limb_bit_size: u32, ) { - assert!(source_field.bit_size == FieldElement::max_num_bits()); + assert!(source_field.bit_size == F::max_num_bits()); self.usize_const_instruction(target_vector.size, limb_count.into()); self.usize_const_instruction(target_vector.rc, 1_usize.into()); @@ -55,12 +55,10 @@ impl BrilligContext { output: HeapArray { pointer: target_vector.pointer, size: limb_count }, }); - let limb_field = - SingleAddrVariable::new(self.allocate_register(), FieldElement::max_num_bits()); - + let limb_field = SingleAddrVariable::new(self.allocate_register(), F::max_num_bits()); let limb_casted = SingleAddrVariable::new(self.allocate_register(), limb_bit_size); - if limb_bit_size != FieldElement::max_num_bits() { + if limb_bit_size != F::max_num_bits() { self.codegen_loop(target_vector.size, |ctx, iterator_register| { // Read the limb ctx.codegen_array_get(target_vector.pointer, iterator_register, limb_field.address); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs index 15761113f51..81c1c3847b1 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs @@ -1,13 +1,14 @@ -use acvm::acir::brillig::MemoryAddress; +use acvm::{acir::brillig::MemoryAddress, AcirField}; use crate::brillig::brillig_ir::BrilligBinaryOp; use super::{ brillig_variable::{BrilligArray, BrilligVariable, BrilligVector, SingleAddrVariable}, + debug_show::DebugToString, BrilligContext, ReservedRegisters, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, }; -impl BrilligContext { +impl BrilligContext { /// Allocates an array of size `size` and stores the pointer to the array /// in `pointer_register` pub(crate) fn codegen_allocate_fixed_length_array( diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs index 1c30f0f848f..943b0b9d7a3 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs @@ -1,8 +1,8 @@ -use acvm::acir::brillig::MemoryAddress; +use acvm::{acir::brillig::MemoryAddress, AcirField}; -use super::BrilligContext; +use super::{debug_show::DebugToString, BrilligContext}; -impl BrilligContext { +impl BrilligContext { /// This function moves values from a set of registers to another set of registers. /// It first moves all sources to new allocated registers to avoid overwriting. pub(crate) fn codegen_mov_registers_to_registers( diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs index def91f82bfd..075a776572e 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs @@ -8,7 +8,7 @@ use acvm::{ }; /// Trait for converting values into debug-friendly strings. -trait DebugToString { +pub(crate) trait DebugToString { fn debug_to_string(&self) -> String; } @@ -169,7 +169,7 @@ impl DebugShow { } /// Stores the value of `constant` in the `result` register - pub(crate) fn const_instruction(&self, result: MemoryAddress, constant: FieldElement) { + pub(crate) fn const_instruction(&self, result: MemoryAddress, constant: F) { debug_println!(self.enable_debug_trace, " CONST {} = {}", result, constant); } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs index 9023183eb36..dc06c2fa0d7 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs @@ -1,21 +1,21 @@ use super::{ artifact::{BrilligArtifact, BrilligParameter}, brillig_variable::{BrilligArray, BrilligVariable, BrilligVector, SingleAddrVariable}, - debug_show::DebugShow, + debug_show::{DebugShow, DebugToString}, registers::BrilligRegistersContext, BrilligBinaryOp, BrilligContext, ReservedRegisters, }; -use acvm::{acir::brillig::MemoryAddress, acir::AcirField, FieldElement}; +use acvm::{acir::brillig::MemoryAddress, acir::AcirField}; pub(crate) const MAX_STACK_SIZE: usize = 2048; -impl BrilligContext { +impl BrilligContext { /// Creates an entry point artifact that will jump to the function label provided. pub(crate) fn new_entry_point_artifact( arguments: Vec, return_parameters: Vec, target_function: T, - ) -> BrilligArtifact { + ) -> BrilligArtifact { let mut context = BrilligContext { obj: BrilligArtifact::default(), registers: BrilligRegistersContext::new(), @@ -42,8 +42,8 @@ impl BrilligContext { arguments: &[BrilligParameter], return_parameters: &[BrilligParameter], ) { - let calldata_size = BrilligContext::flattened_tuple_size(arguments); - let return_data_size = BrilligContext::flattened_tuple_size(return_parameters); + let calldata_size = Self::flattened_tuple_size(arguments); + let return_data_size = Self::flattened_tuple_size(return_parameters); // Set initial value of stack pointer: MAX_STACK_SIZE + calldata_size + return_data_size self.const_instruction( @@ -74,7 +74,7 @@ impl BrilligContext { let pointer_to_the_array_in_calldata = self.make_usize_constant_instruction(current_calldata_pointer.into()); let rc_register = self.make_usize_constant_instruction(1_usize.into()); - let flattened_size = BrilligContext::flattened_size(argument); + let flattened_size = Self::flattened_size(argument); let var = BrilligVariable::BrilligArray(BrilligArray { pointer: pointer_to_the_array_in_calldata.address, size: flattened_size, @@ -88,7 +88,7 @@ impl BrilligContext { let pointer_to_the_array_in_calldata = self.make_usize_constant_instruction(current_calldata_pointer.into()); - let flattened_size = BrilligContext::flattened_size(argument); + let flattened_size = Self::flattened_size(argument); let size_register = self.make_usize_constant_instruction(flattened_size.into()); let rc_register = self.make_usize_constant_instruction(1_usize.into()); @@ -121,7 +121,7 @@ impl BrilligContext { BrilligVariable::BrilligVector(vector), BrilligParameter::Slice(item_type, item_count), ) => { - let flattened_size = BrilligContext::flattened_size(argument); + let flattened_size = Self::flattened_size(argument); let deflattened_address = self.deflatten_array(item_type, flattened_size, vector.pointer); @@ -139,7 +139,7 @@ impl BrilligContext { } fn copy_and_cast_calldata(&mut self, arguments: &[BrilligParameter]) { - let calldata_size = BrilligContext::flattened_tuple_size(arguments); + let calldata_size = Self::flattened_tuple_size(arguments); self.calldata_copy_instruction(MemoryAddress(MAX_STACK_SIZE), calldata_size, 0); fn flat_bit_sizes(param: &BrilligParameter) -> Box + '_> { @@ -154,7 +154,7 @@ impl BrilligContext { for (i, bit_size) in arguments.iter().flat_map(flat_bit_sizes).enumerate() { // Calldatacopy tags everything with field type, so when downcast when necessary - if bit_size < FieldElement::max_num_bits() { + if bit_size < F::max_num_bits() { self.cast_instruction( SingleAddrVariable::new(MemoryAddress(MAX_STACK_SIZE + i), bit_size), SingleAddrVariable::new_field(MemoryAddress(MAX_STACK_SIZE + i)), @@ -169,7 +169,7 @@ impl BrilligContext { BrilligParameter::SingleAddr(_) => 1, BrilligParameter::Array(item_types, item_count) | BrilligParameter::Slice(item_types, item_count) => { - let item_size: usize = item_types.iter().map(BrilligContext::flattened_size).sum(); + let item_size: usize = item_types.iter().map(Self::flattened_size).sum(); item_count * item_size } } @@ -177,7 +177,7 @@ impl BrilligContext { /// Computes the size of a parameter if it was flattened pub(super) fn flattened_tuple_size(tuple: &[BrilligParameter]) -> usize { - tuple.iter().map(BrilligContext::flattened_size).sum() + tuple.iter().map(Self::flattened_size).sum() } /// Computes the size of a parameter if it was flattened @@ -193,12 +193,12 @@ impl BrilligContext { item_count: usize, flattened_array_pointer: MemoryAddress, ) -> MemoryAddress { - if BrilligContext::has_nested_arrays(item_type) { + if Self::has_nested_arrays(item_type) { let movement_register = self.allocate_register(); let deflattened_array_pointer = self.allocate_register(); let target_item_size = item_type.len(); - let source_item_size = BrilligContext::flattened_tuple_size(item_type); + let source_item_size = Self::flattened_tuple_size(item_type); self.codegen_allocate_fixed_length_array( deflattened_array_pointer, @@ -276,7 +276,7 @@ impl BrilligContext { .into_iter() .for_each(|register| self.deallocate_register(register)); - source_offset += BrilligContext::flattened_size(subitem); + source_offset += Self::flattened_size(subitem); } BrilligParameter::Slice(..) => unreachable!("ICE: Cannot deflatten slices"), } @@ -328,8 +328,8 @@ impl BrilligContext { .collect(); // Now, we deflatten the return data - let calldata_size = BrilligContext::flattened_tuple_size(arguments); - let return_data_size = BrilligContext::flattened_tuple_size(return_parameters); + let calldata_size = Self::flattened_tuple_size(arguments); + let return_data_size = Self::flattened_tuple_size(return_parameters); // Return data has a reserved space after calldata let return_data_offset = MAX_STACK_SIZE + calldata_size; @@ -357,7 +357,7 @@ impl BrilligContext { ); self.deallocate_single_addr(pointer_to_return_data); - return_data_index += BrilligContext::flattened_size(return_param); + return_data_index += Self::flattened_size(return_param); } BrilligParameter::Slice(..) => { unreachable!("ICE: Cannot return slices from brillig entrypoints") @@ -376,12 +376,11 @@ impl BrilligContext { flattened_array_pointer: MemoryAddress, deflattened_array_pointer: MemoryAddress, ) { - if BrilligContext::has_nested_arrays(item_type) { + if Self::has_nested_arrays(item_type) { let movement_register = self.allocate_register(); let source_item_size = item_type.len(); - let target_item_size: usize = - item_type.iter().map(BrilligContext::flattened_size).sum(); + let target_item_size: usize = item_type.iter().map(Self::flattened_size).sum(); for item_index in 0..item_count { let source_item_base_index = item_index * source_item_size; @@ -462,7 +461,7 @@ impl BrilligContext { .into_iter() .for_each(|register| self.deallocate_register(register)); - target_offset += BrilligContext::flattened_size(subitem); + target_offset += Self::flattened_size(subitem); } BrilligParameter::Slice(..) => unreachable!("ICE: Cannot flatten slices"), } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs index 03a9216b73a..a614f93fa30 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs @@ -10,12 +10,13 @@ use acvm::{ use super::{ artifact::UnresolvedJumpLocation, brillig_variable::{BrilligArray, BrilligVector, SingleAddrVariable}, + debug_show::DebugToString, BrilligContext, ReservedRegisters, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, }; /// Low level instructions of the brillig IR, used by the brillig ir codegens and brillig_gen /// Printed using debug_slow -impl BrilligContext { +impl BrilligContext { /// Processes a binary instruction according `operation`. /// /// This method will compute lhs rhs @@ -42,8 +43,7 @@ impl BrilligContext { ) { self.debug_show.not_instruction(input.address, input.bit_size, result.address); // Compile !x as ((-1) - x) - let u_max = FieldElement::from(2_i128).pow(&FieldElement::from(input.bit_size as i128)) - - FieldElement::one(); + let u_max = F::from(2_u128).pow(&F::from(input.bit_size as u128)) - F::one(); let max = self.make_constant(u_max, input.bit_size); self.binary(max, input, result, BrilligBinaryOp::Sub); @@ -63,7 +63,7 @@ impl BrilligContext { SingleAddrVariable::new_usize(rhs), SingleAddrVariable::new( destination, - BrilligContext::binary_result_bit_size(op, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), + Self::binary_result_bit_size(op, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ), op, ); @@ -77,8 +77,7 @@ impl BrilligContext { operation: BrilligBinaryOp, ) { let is_field_op = lhs.bit_size == FieldElement::max_num_bits(); - let expected_result_bit_size = - BrilligContext::binary_result_bit_size(operation, lhs.bit_size); + let expected_result_bit_size = Self::binary_result_bit_size(operation, lhs.bit_size); assert!( result.bit_size == expected_result_bit_size, "Expected result bit size to be {}, got {} for operation {:?}", @@ -213,7 +212,7 @@ impl BrilligContext { /// Adds a unresolved `Jump` to the bytecode. fn add_unresolved_jump( &mut self, - jmp_instruction: BrilligOpcode, + jmp_instruction: BrilligOpcode, destination: UnresolvedJumpLocation, ) { self.obj.add_unresolved_jump(jmp_instruction, destination); @@ -369,12 +368,12 @@ impl BrilligContext { } /// Stores the value of `constant` in the `result` register - pub(crate) fn const_instruction(&mut self, result: SingleAddrVariable, constant: FieldElement) { + pub(crate) fn const_instruction(&mut self, result: SingleAddrVariable, constant: F) { self.debug_show.const_instruction(result.address, constant); self.constant(result, constant); } - fn constant(&mut self, result: SingleAddrVariable, constant: FieldElement) { + fn constant(&mut self, result: SingleAddrVariable, constant: F) { assert!( result.bit_size >= constant.num_bits(), "Constant {} does not fit in bit size {}", @@ -382,10 +381,10 @@ impl BrilligContext { result.bit_size ); if result.bit_size > 128 && constant.num_bits() > 128 { - let high = FieldElement::from_be_bytes_reduce( + let high = F::from_be_bytes_reduce( constant.to_be_bytes().get(0..16).expect("FieldElement::to_be_bytes() too short!"), ); - let low = FieldElement::from(constant.to_u128()); + let low = F::from(constant.to_u128()); let high_register = SingleAddrVariable::new(self.allocate_register(), 254); let low_register = SingleAddrVariable::new(self.allocate_register(), 254); let intermediate_register = SingleAddrVariable::new(self.allocate_register(), 254); @@ -393,7 +392,7 @@ impl BrilligContext { self.constant(low_register, low); // I want to multiply high by 2^128, but I can't get that big constant in. // So I'll multiply by 2^64 twice. - self.constant(intermediate_register, FieldElement::from(1_u128 << 64)); + self.constant(intermediate_register, F::from(1_u128 << 64)); self.binary(high_register, intermediate_register, high_register, BrilligBinaryOp::Mul); self.binary(high_register, intermediate_register, high_register, BrilligBinaryOp::Mul); // Now we can add. @@ -411,18 +410,14 @@ impl BrilligContext { } } - pub(crate) fn usize_const_instruction( - &mut self, - result: MemoryAddress, - constant: FieldElement, - ) { + pub(crate) fn usize_const_instruction(&mut self, result: MemoryAddress, constant: F) { self.const_instruction(SingleAddrVariable::new_usize(result), constant); } /// Returns a register which holds the value of a constant pub(crate) fn make_constant_instruction( &mut self, - constant: FieldElement, + constant: F, bit_size: u32, ) -> SingleAddrVariable { let var = SingleAddrVariable::new(self.allocate_register(), bit_size); @@ -430,17 +425,14 @@ impl BrilligContext { var } - fn make_constant(&mut self, constant: FieldElement, bit_size: u32) -> SingleAddrVariable { + fn make_constant(&mut self, constant: F, bit_size: u32) -> SingleAddrVariable { let var = SingleAddrVariable::new(self.allocate_register(), bit_size); self.constant(var, constant); var } /// Returns a register which holds the value of an usize constant - pub(crate) fn make_usize_constant_instruction( - &mut self, - constant: FieldElement, - ) -> SingleAddrVariable { + pub(crate) fn make_usize_constant_instruction(&mut self, constant: F) -> SingleAddrVariable { let register = self.allocate_register(); self.usize_const_instruction(register, constant); SingleAddrVariable::new_usize(register) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/registers.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/registers.rs index f756f06aa69..ae506462b25 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/registers.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/registers.rs @@ -82,7 +82,7 @@ impl BrilligRegistersContext { } } -impl BrilligContext { +impl BrilligContext { /// Returns the i'th register after the reserved ones pub(crate) fn register(&self, i: usize) -> MemoryAddress { MemoryAddress::from(ReservedRegisters::NUM_RESERVED_REGISTERS + i) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/mod.rs index eda1ac97c1e..70c0959517b 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/mod.rs @@ -1,6 +1,8 @@ pub(crate) mod brillig_gen; pub(crate) mod brillig_ir; +use acvm::FieldElement; + use self::{ brillig_gen::{brillig_fn::FunctionContext, convert_ssa_function}, brillig_ir::artifact::{BrilligArtifact, Label}, @@ -16,7 +18,7 @@ use std::collections::{BTreeSet, HashMap}; #[derive(Default)] pub struct Brillig { /// Maps SSA function labels to their brillig artifact - ssa_function_to_brillig: HashMap, + ssa_function_to_brillig: HashMap>, } impl Brillig { @@ -27,7 +29,10 @@ impl Brillig { } /// Finds a brillig function artifact by its function label - pub(crate) fn find_by_function_label(&self, function_label: Label) -> Option<&BrilligArtifact> { + pub(crate) fn find_by_function_label( + &self, + function_label: Label, + ) -> Option<&BrilligArtifact> { self.ssa_function_to_brillig.iter().find_map(|(function_id, obj)| { if FunctionContext::function_id_to_function_label(*function_id) == function_label { Some(obj) @@ -39,7 +44,7 @@ impl Brillig { } impl std::ops::Index for Brillig { - type Output = BrilligArtifact; + type Output = BrilligArtifact; fn index(&self, id: FunctionId) -> &Self::Output { &self.ssa_function_to_brillig[&id] } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index 80a63f223e7..7e362599fb5 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -146,7 +146,7 @@ impl SsaProgramArtifact { /// Compiles the [`Program`] into [`ACIR``][acvm::acir::circuit::Program]. /// -/// The output ACIR is is backend-agnostic and so must go through a transformation pass before usage in proof generation. +/// The output ACIR is backend-agnostic and so must go through a transformation pass before usage in proof generation. #[allow(clippy::type_complexity)] #[tracing::instrument(level = "trace", skip_all)] pub fn create_program( @@ -206,7 +206,7 @@ pub struct SsaCircuitArtifact { } fn convert_generated_acir_into_circuit( - mut generated_acir: GeneratedAcir, + mut generated_acir: GeneratedAcir, func_sig: FunctionSignature, recursive: bool, debug_variables: DebugVariables, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index ac7f2c09687..56b869fbf6b 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -20,7 +20,6 @@ use acvm::{ native_types::{Expression, Witness}, BlackBoxFunc, }, - FieldElement, }; use fxhash::FxHashMap as HashMap; use iter_extended::{try_vecmap, vecmap}; @@ -48,12 +47,12 @@ impl AcirType { } /// Returns the bit size of the underlying type - pub(crate) fn bit_size(&self) -> u32 { + pub(crate) fn bit_size(&self) -> u32 { match self { AcirType::NumericType(numeric_type) => match numeric_type { NumericType::Signed { bit_size } => *bit_size, NumericType::Unsigned { bit_size } => *bit_size, - NumericType::NativeField => FieldElement::max_num_bits(), + NumericType::NativeField => F::max_num_bits(), }, AcirType::Array(_, _) => unreachable!("cannot fetch bit size of array type"), } @@ -106,13 +105,13 @@ impl From for AcirType { /// Context object which holds the relationship between /// `Variables`(AcirVar) and types such as `Expression` and `Witness` /// which are placed into ACIR. -pub(crate) struct AcirContext { +pub(crate) struct AcirContext { /// Two-way map that links `AcirVar` to `AcirVarData`. /// /// The vars object is an instance of the `TwoWayMap`, which provides a bidirectional mapping between `AcirVar` and `AcirVarData`. - vars: HashMap, + vars: HashMap>, - constant_witnesses: HashMap, + constant_witnesses: HashMap, /// An in-memory representation of ACIR. /// @@ -121,13 +120,13 @@ pub(crate) struct AcirContext { /// For example, If one was to add two Variables together, /// then the `acir_ir` will be populated to assert this /// addition. - acir_ir: GeneratedAcir, + acir_ir: GeneratedAcir, /// The BigIntContext, used to generate identifiers for BigIntegers big_int_ctx: BigIntContext, } -impl AcirContext { +impl AcirContext { pub(crate) fn current_witness_index(&self) -> Witness { self.acir_ir.current_witness_index() } @@ -148,7 +147,7 @@ impl AcirContext { } /// Adds a constant to the context and assigns a Variable to represent it - pub(crate) fn add_constant(&mut self, constant: impl Into) -> AcirVar { + pub(crate) fn add_constant(&mut self, constant: impl Into) -> AcirVar { let constant_data = AcirVarData::Const(constant.into()); self.add_data(constant_data) } @@ -156,7 +155,7 @@ impl AcirContext { /// Returns the constant represented by the given variable. /// /// Panics: if the variable does not represent a constant. - pub(crate) fn constant(&self, var: AcirVar) -> FieldElement { + pub(crate) fn constant(&self, var: AcirVar) -> &F { self.vars[&var].as_constant().expect("ICE - expected the variable to be a constant value") } @@ -270,10 +269,7 @@ impl AcirContext { } /// Converts an [`AcirVar`] to an [`Expression`] - pub(crate) fn var_to_expression( - &self, - var: AcirVar, - ) -> Result, InternalError> { + pub(crate) fn var_to_expression(&self, var: AcirVar) -> Result, InternalError> { let var_data = match self.vars.get(&var) { Some(var_data) => var_data, None => { @@ -408,7 +404,7 @@ impl AcirContext { if lhs_expr == rhs_expr { // x ^ x == 0 - let zero = self.add_constant(FieldElement::zero()); + let zero = self.add_constant(F::zero()); return Ok(zero); } else if lhs_expr.is_zero() { // 0 ^ x == x @@ -418,14 +414,14 @@ impl AcirContext { return Ok(lhs); } - let bit_size = typ.bit_size(); + let bit_size = typ.bit_size::(); if bit_size == 1 { // Operands are booleans. // // a ^ b == a + b - 2*a*b let prod = self.mul_var(lhs, rhs)?; let sum = self.add_var(lhs, rhs)?; - self.add_mul_var(sum, -FieldElement::from(2_i128), prod) + self.add_mul_var(sum, -F::from(2_u128), prod) } else { let inputs = vec![AcirValue::Var(lhs, typ.clone()), AcirValue::Var(rhs, typ)]; let outputs = self.black_box_function(BlackBoxFunc::XOR, inputs, 1)?; @@ -448,11 +444,11 @@ impl AcirContext { return Ok(lhs); } else if lhs_expr.is_zero() || rhs_expr.is_zero() { // x & 0 == 0 and 0 & x == 0 - let zero = self.add_constant(FieldElement::zero()); + let zero = self.add_constant(F::zero()); return Ok(zero); } - let bit_size = typ.bit_size(); + let bit_size = typ.bit_size::(); if bit_size == 1 { // Operands are booleans. self.mul_var(lhs, rhs) @@ -480,7 +476,7 @@ impl AcirContext { return Ok(lhs); } - let bit_size = typ.bit_size(); + let bit_size = typ.bit_size::(); if bit_size == 1 { // Operands are booleans // a + b - ab @@ -502,7 +498,7 @@ impl AcirContext { &mut self, lhs: AcirVar, rhs: AcirVar, - assert_message: Option>, + assert_message: Option>, ) -> Result<(), RuntimeError> { let lhs_expr = self.var_to_expression(lhs)?; let rhs_expr = self.var_to_expression(rhs)?; @@ -531,7 +527,7 @@ impl AcirContext { pub(crate) fn vars_to_expressions_or_memory( &self, values: &[AcirValue], - ) -> Result>, RuntimeError> { + ) -> Result>, RuntimeError> { let mut result = Vec::with_capacity(values.len()); for value in values { match value { @@ -597,7 +593,7 @@ impl AcirContext { (AcirVarData::Const(constant), _) | (_, AcirVarData::Const(constant)) if constant.is_zero() => { - self.add_constant(FieldElement::zero()) + self.add_constant(F::zero()) } (AcirVarData::Const(lhs_constant), AcirVarData::Const(rhs_constant)) => { @@ -615,7 +611,7 @@ impl AcirContext { } (AcirVarData::Witness(lhs_witness), AcirVarData::Witness(rhs_witness)) => { let mut expr = Expression::default(); - expr.push_multiplication_term(FieldElement::one(), lhs_witness, rhs_witness); + expr.push_multiplication_term(F::one(), lhs_witness, rhs_witness); self.add_data(AcirVarData::Expr(expr)) } (AcirVarData::Expr(expression), AcirVarData::Witness(witness)) @@ -681,12 +677,7 @@ impl AcirContext { /// Adds a new Variable to context whose value will /// be constrained to be the expression `lhs + k * rhs` - fn add_mul_var( - &mut self, - lhs: AcirVar, - k: FieldElement, - rhs: AcirVar, - ) -> Result { + fn add_mul_var(&mut self, lhs: AcirVar, k: F, rhs: AcirVar) -> Result { let k_var = self.add_constant(k); let intermediate = self.mul_var(k_var, rhs)?; @@ -695,7 +686,7 @@ impl AcirContext { /// Adds a new variable that is constrained to be the logical NOT of `x`. pub(crate) fn not_var(&mut self, x: AcirVar, typ: AcirType) -> Result { - let bit_size = typ.bit_size(); + let bit_size = typ.bit_size::(); // Subtracting from max flips the bits let max = self.add_constant((1_u128 << bit_size) - 1); self.sub_var(max, x) @@ -709,8 +700,8 @@ impl AcirContext { bit_size: u32, predicate: AcirVar, ) -> Result<(AcirVar, AcirVar), RuntimeError> { - let zero = self.add_constant(FieldElement::zero()); - let one = self.add_constant(FieldElement::one()); + let zero = self.add_constant(F::zero()); + let one = self.add_constant(F::one()); let lhs_expr = self.var_to_expression(lhs)?; let rhs_expr = self.var_to_expression(rhs)?; @@ -829,7 +820,7 @@ impl AcirContext { // Avoids overflow: 'q*b+r < 2^max_q_bits*2^max_rhs_bits' let mut avoid_overflow = false; - if max_q_bits + max_rhs_bits >= FieldElement::max_num_bits() - 1 { + if max_q_bits + max_rhs_bits >= F::max_num_bits() - 1 { // q*b+r can overflow; we avoid this when b is constant if rhs_expr.is_const() { avoid_overflow = true; @@ -843,16 +834,16 @@ impl AcirContext { if avoid_overflow { // we compute q0 = p/rhs let rhs_big = BigUint::from_bytes_be(&rhs_const.to_be_bytes()); - let q0_big = FieldElement::modulus() / &rhs_big; - let q0 = FieldElement::from_be_bytes_reduce(&q0_big.to_bytes_be()); + let q0_big = F::modulus() / &rhs_big; + let q0 = F::from_be_bytes_reduce(&q0_big.to_bytes_be()); let q0_var = self.add_constant(q0); // when q == q0, b*q+r can overflow so we need to bound r to avoid the overflow. let size_predicate = self.eq_var(q0_var, quotient_var)?; let predicate = self.mul_var(size_predicate, predicate)?; // Ensure that there is no overflow, under q == q0 predicate - let max_r_big = FieldElement::modulus() - q0_big * rhs_big; - let max_r = FieldElement::from_be_bytes_reduce(&max_r_big.to_bytes_be()); + let max_r_big = F::modulus() - q0_big * rhs_big; + let max_r = F::from_be_bytes_reduce(&max_r_big.to_bytes_be()); let max_r_var = self.add_constant(max_r); let max_r_predicate = self.mul_var(predicate, max_r_var)?; @@ -897,7 +888,7 @@ impl AcirContext { } assert!( - bits < FieldElement::max_num_bits(), + bits < F::max_num_bits(), "range check with bit size of the prime field is not implemented yet" ); @@ -921,7 +912,7 @@ impl AcirContext { // however, since it is a constant, we can compute it's actual bit size let r_bit_size = bit_size_u128(r); // witness = lhs_offset + r - assert!(bits + r_bit_size < FieldElement::max_num_bits()); //we need to ensure lhs_offset + r does not overflow + assert!(bits + r_bit_size < F::max_num_bits()); //we need to ensure lhs_offset + r does not overflow let r_var = self.add_constant(r); let aor = self.add_var(lhs_offset, r_var)?; @@ -945,14 +936,13 @@ impl AcirContext { leading: AcirVar, max_bit_size: u32, ) -> Result { - let max_power_of_two = self.add_constant( - FieldElement::from(2_i128).pow(&FieldElement::from(max_bit_size as i128 - 1)), - ); + let max_power_of_two = + self.add_constant(F::from(2_u128).pow(&F::from(max_bit_size as u128 - 1))); let intermediate = self.sub_var(max_power_of_two, lhs)?; let intermediate = self.mul_var(intermediate, leading)?; - self.add_mul_var(lhs, FieldElement::from(2_i128), intermediate) + self.add_mul_var(lhs, F::from(2_u128), intermediate) } /// Returns the quotient and remainder such that lhs = rhs * quotient + remainder @@ -976,11 +966,10 @@ impl AcirContext { assert_ne!(bit_size, 0, "signed integer should have at least one bit"); // 2^{max_bit size-1} - let max_power_of_two = self.add_constant( - FieldElement::from(2_i128).pow(&FieldElement::from(bit_size as i128 - 1)), - ); - let zero = self.add_constant(FieldElement::zero()); - let one = self.add_constant(FieldElement::one()); + let max_power_of_two = + self.add_constant(F::from(2_u128).pow(&F::from(bit_size as u128 - 1))); + let zero = self.add_constant(F::zero()); + let one = self.add_constant(F::one()); // Get the sign bit of rhs by computing rhs / max_power_of_two let (rhs_leading, _) = self.euclidean_division_var(rhs, max_power_of_two, bit_size, one)?; @@ -1071,9 +1060,8 @@ impl AcirContext { max_bit_size: u32, ) -> Result { // 2^{rhs} - let divisor = - self.add_constant(FieldElement::from(2_u128).pow(&FieldElement::from(rhs as u128))); - let one = self.add_constant(FieldElement::one()); + let divisor = self.add_constant(F::from(2_u128).pow(&F::from(rhs as u128))); + let one = self.add_constant(F::one()); // Computes lhs = 2^{rhs} * q + r let (_, remainder) = self.euclidean_division_var(lhs, divisor, max_bit_size, one)?; @@ -1093,8 +1081,8 @@ impl AcirContext { rhs: AcirVar, bit_count: u32, ) -> Result { - let pow_last = self.add_constant(FieldElement::from(1_u128 << (bit_count - 1))); - let pow = self.add_constant(FieldElement::from(1_u128 << (bit_count))); + let pow_last = self.add_constant(F::from(1_u128 << (bit_count - 1))); + let pow = self.add_constant(F::from(1_u128 << (bit_count))); // We check whether the inputs have same sign or not by computing the XOR of their bit sign @@ -1163,10 +1151,9 @@ impl AcirContext { // Ensure that 2^{max_bits + 1} is less than the field size // // TODO: perhaps this should be a user error, instead of an assert - assert!(max_bits + 1 < FieldElement::max_num_bits()); + assert!(max_bits + 1 < F::max_num_bits()); - let two_max_bits = self - .add_constant(FieldElement::from(2_i128).pow(&FieldElement::from(max_bits as i128))); + let two_max_bits = self.add_constant(F::from(2_u128).pow(&F::from(max_bits as u128))); let diff = self.sub_var(lhs, rhs)?; let comparison_evaluation = self.add_var(diff, two_max_bits)?; @@ -1214,7 +1201,7 @@ impl AcirContext { // compute less than. let comparison = self.more_than_eq_var(lhs, rhs, bit_size)?; - let one = self.add_constant(FieldElement::one()); + let one = self.add_constant(F::one()); self.sub_var(one, comparison) // comparison_negated } @@ -1251,7 +1238,7 @@ impl AcirContext { } }; - (vec![domain_constant], Vec::new()) + (vec![*domain_constant], Vec::new()) } BlackBoxFunc::Poseidon2Permutation => { // The last argument is the state length, which must be a constant @@ -1276,7 +1263,7 @@ impl AcirContext { } }; - (vec![state_len], Vec::new()) + (vec![*state_len], Vec::new()) } BlackBoxFunc::BigIntAdd | BlackBoxFunc::BigIntSub @@ -1297,7 +1284,7 @@ impl AcirContext { output_count = 0; let mut field_inputs = Vec::new(); for i in const_inputs { - field_inputs.push(i?); + field_inputs.push(*i?); } if field_inputs[1] != field_inputs[3] { return Err(RuntimeError::BigIntModulus { call_stack: self.get_call_stack() }); @@ -1306,7 +1293,7 @@ impl AcirContext { let result_id = self.big_int_ctx.new_big_int(field_inputs[1]); ( vec![field_inputs[0], field_inputs[2]], - vec![result_id.bigint_id(), result_id.modulus_id()], + vec![result_id.bigint_id::(), result_id.modulus_id::()], ) } BlackBoxFunc::BigIntToLeBytes => { @@ -1323,10 +1310,10 @@ impl AcirContext { inputs = Vec::new(); let mut field_inputs = Vec::new(); for i in const_inputs { - field_inputs.push(i?); + field_inputs.push(*i?); } let bigint = self.big_int_ctx.get(field_inputs[0]); - let modulus = self.big_int_ctx.modulus(bigint.modulus_id()); + let modulus = self.big_int_ctx.modulus(bigint.modulus_id::()); let bytes_len = ((modulus - BigUint::from(1_u32)).bits() - 1) / 8 + 1; output_count = bytes_len as usize; assert!(bytes_len == 32); @@ -1339,7 +1326,7 @@ impl AcirContext { match inputs.pop().expect(invalid_input) { AcirValue::Array(values) => { for value in values { - modulus.push(self.vars[&value.into_var()?].as_constant().ok_or( + modulus.push(*self.vars[&value.into_var()?].as_constant().ok_or( RuntimeError::InternalError(InternalError::NotAConstant { name: "big integer".to_string(), call_stack: self.get_call_stack(), @@ -1359,9 +1346,8 @@ impl AcirContext { output_count = 0; let modulus_id = self.big_int_ctx.get_or_insert_modulus(big_modulus); - let result_id = - self.big_int_ctx.new_big_int(FieldElement::from(modulus_id as u128)); - (modulus, vec![result_id.bigint_id(), result_id.modulus_id()]) + let result_id = self.big_int_ctx.new_big_int(F::from(modulus_id as u128)); + (modulus, vec![result_id.bigint_id::(), result_id.modulus_id::()]) } BlackBoxFunc::AES128Encrypt => { let invalid_input = "aes128_encrypt - operation requires a plaintext to encrypt"; @@ -1376,7 +1362,7 @@ impl AcirContext { } }?; output_count = input_size + (16 - input_size % 16); - (vec![], vec![FieldElement::from(output_count as u128)]) + (vec![], vec![F::from(output_count as u128)]) } _ => (vec![], vec![]), }; @@ -1420,7 +1406,7 @@ impl AcirContext { // constants too. let witness_var = self.get_or_create_witness_var(input)?; let witness = self.var_to_witness(witness_var)?; - let num_bits = typ.bit_size(); + let num_bits = typ.bit_size::(); single_val_witnesses.push(FunctionInput { witness, num_bits }); } witnesses.push(single_val_witnesses); @@ -1531,7 +1517,7 @@ impl AcirContext { inputs: Vec, return_values: Vec, warnings: Vec, - ) -> GeneratedAcir { + ) -> GeneratedAcir { self.acir_ir.input_witnesses = inputs; self.acir_ir.return_witnesses = return_values; self.acir_ir.warnings = warnings; @@ -1543,7 +1529,7 @@ impl AcirContext { /// Variable can be seen as an index into the context. /// We use a two-way map so that it is efficient to lookup /// either the key or the value. - fn add_data(&mut self, data: AcirVarData) -> AcirVar { + fn add_data(&mut self, data: AcirVarData) -> AcirVar { let id = AcirVar(self.vars.len()); self.vars.insert(id, data); id @@ -1553,7 +1539,7 @@ impl AcirContext { pub(crate) fn brillig_call( &mut self, predicate: AcirVar, - generated_brillig: &GeneratedBrillig, + generated_brillig: &GeneratedBrillig, inputs: Vec, outputs: Vec, attempt_execution: bool, @@ -1561,14 +1547,14 @@ impl AcirContext { brillig_function_index: u32, brillig_stdlib_func: Option, ) -> Result, RuntimeError> { - let brillig_inputs: Vec> = + let brillig_inputs: Vec> = try_vecmap(inputs, |i| -> Result<_, InternalError> { match i { AcirValue::Var(var, _) => { Ok(BrilligInputs::Single(self.var_to_expression(var)?)) } AcirValue::Array(vars) => { - let mut var_expressions: Vec> = Vec::new(); + let mut var_expressions: Vec> = Vec::new(); for var in vars { self.brillig_array_input(&mut var_expressions, var)?; } @@ -1619,8 +1605,8 @@ impl AcirContext { brillig_stdlib_func, ); - fn range_constraint_value( - context: &mut AcirContext, + fn range_constraint_value( + context: &mut AcirContext, value: &AcirValue, ) -> Result<(), RuntimeError> { match value { @@ -1655,7 +1641,7 @@ impl AcirContext { fn brillig_array_input( &mut self, - var_expressions: &mut Vec>, + var_expressions: &mut Vec>, input: AcirValue, ) -> Result<(), InternalError> { match input { @@ -1714,8 +1700,8 @@ impl AcirContext { fn execute_brillig( &mut self, - code: &[BrilligOpcode], - inputs: &[BrilligInputs], + code: &[BrilligOpcode], + inputs: &[BrilligInputs], outputs_types: &[AcirType], ) -> Option> { let mut memory = (execute_brillig(code, inputs)?).into_iter(); @@ -1740,7 +1726,7 @@ impl AcirContext { &mut self, element_types: &[AcirType], size: usize, - memory_iter: &mut impl Iterator>, + memory_iter: &mut impl Iterator>, ) -> AcirValue { let mut array_values = im::Vector::new(); for _ in 0..size { @@ -1821,7 +1807,7 @@ impl AcirContext { ) -> Result<(), InternalError> { let initialized_values = match optional_value { None => { - let zero = self.add_constant(FieldElement::zero()); + let zero = self.add_constant(F::zero()); let zero_witness = self.var_to_witness(zero)?; vec![zero_witness; len] } @@ -1893,13 +1879,13 @@ impl AcirContext { /// Enum representing the possible values that a /// Variable can be given. #[derive(Debug, Eq, Clone)] -enum AcirVarData { +enum AcirVarData { Witness(Witness), - Expr(Expression), - Const(FieldElement), + Expr(Expression), + Const(F), } -impl PartialEq for AcirVarData { +impl PartialEq for AcirVarData { fn eq(&self, other: &Self) -> bool { match (self, other) { (Self::Witness(l0), Self::Witness(r0)) => l0 == r0, @@ -1911,23 +1897,26 @@ impl PartialEq for AcirVarData { } // TODO: check/test this hash impl -impl std::hash::Hash for AcirVarData { +impl std::hash::Hash for AcirVarData { fn hash(&self, state: &mut H) { core::mem::discriminant(self).hash(state); } } -impl AcirVarData { +impl AcirVarData { /// Returns a FieldElement, if the underlying `AcirVarData` /// represents a constant. - pub(crate) fn as_constant(&self) -> Option { + pub(crate) fn as_constant(&self) -> Option<&F> { if let AcirVarData::Const(field) = self { - return Some(*field); + return Some(field); } None } +} + +impl AcirVarData { /// Converts all enum variants to an Expression. - pub(crate) fn to_expression(&self) -> Cow> { + pub(crate) fn to_expression(&self) -> Cow> { match self { AcirVarData::Witness(witness) => Cow::Owned(Expression::from(*witness)), AcirVarData::Expr(expr) => Cow::Borrowed(expr), @@ -1936,23 +1925,17 @@ impl AcirVarData { } } -impl From for AcirVarData { - fn from(constant: FieldElement) -> Self { - AcirVarData::Const(constant) - } -} - -impl From for AcirVarData { +impl From for AcirVarData { fn from(witness: Witness) -> Self { AcirVarData::Witness(witness) } } -impl From> for AcirVarData { - fn from(expr: Expression) -> Self { +impl From> for AcirVarData { + fn from(expr: Expression) -> Self { // Prefer simpler variants if possible. if let Some(constant) = expr.to_const() { - AcirVarData::from(*constant) + AcirVarData::Const(*constant) } else if let Some(witness) = expr.to_witness() { AcirVarData::from(witness) } else { @@ -1970,12 +1953,12 @@ pub(crate) struct AcirVar(usize); /// Returns the finished state of the Brillig VM if execution can complete. /// /// Returns `None` if complete execution of the Brillig bytecode is not possible. -fn execute_brillig( - code: &[BrilligOpcode], - inputs: &[BrilligInputs], -) -> Option>> { +fn execute_brillig( + code: &[BrilligOpcode], + inputs: &[BrilligInputs], +) -> Option>> { // Set input values - let mut calldata: Vec = Vec::new(); + let mut calldata: Vec = Vec::new(); // Each input represents a constant or array of constants. // Iterate over each input and push it into registers and/or memory. diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs index b9c596d80c7..30297b42ecf 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs @@ -1,4 +1,4 @@ -use acvm::{acir::AcirField, FieldElement}; +use acvm::acir::AcirField; use num_bigint::BigUint; /// Represents a bigint value in the form (id, modulus) where @@ -11,12 +11,12 @@ pub(crate) struct BigIntId { } impl BigIntId { - pub(crate) fn bigint_id(&self) -> FieldElement { - FieldElement::from(self.bigint_id as u128) + pub(crate) fn bigint_id>(&self) -> F { + F::from(self.bigint_id as u128) } - pub(crate) fn modulus_id(&self) -> FieldElement { - FieldElement::from(self.modulus_id as u128) + pub(crate) fn modulus_id>(&self) -> F { + F::from(self.modulus_id as u128) } } @@ -29,7 +29,7 @@ pub(crate) struct BigIntContext { impl BigIntContext { /// Creates a new BigIntId for the given modulus identifier and returns it. - pub(crate) fn new_big_int(&mut self, modulus_id: FieldElement) -> BigIntId { + pub(crate) fn new_big_int(&mut self, modulus_id: F) -> BigIntId { let id = self.big_integers.len() as u32; let result = BigIntId { bigint_id: id, modulus_id: modulus_id.to_u128() as u32 }; self.big_integers.push(result); @@ -37,12 +37,12 @@ impl BigIntContext { } /// Returns the modulus corresponding to the given modulus index - pub(crate) fn modulus(&self, idx: FieldElement) -> BigUint { + pub(crate) fn modulus(&self, idx: F) -> BigUint { self.modulus[idx.to_u128() as usize].clone() } /// Returns the BigIntId corresponding to the given identifier - pub(crate) fn get(&self, id: FieldElement) -> BigIntId { + pub(crate) fn get(&self, id: F) -> BigIntId { self.big_integers[id.to_u128() as usize] } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index 9a09e7c06ee..9d271f7cd9c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -19,7 +19,6 @@ use acvm::acir::{ use acvm::{ acir::AcirField, acir::{circuit::directives::Directive, native_types::Expression}, - FieldElement, }; use iter_extended::vecmap; use num_bigint::BigUint; @@ -32,7 +31,7 @@ pub(crate) const PLACEHOLDER_BRILLIG_INDEX: u32 = 0; #[derive(Debug, Default)] /// The output of the Acir-gen pass, which should only be produced for entry point Acir functions -pub(crate) struct GeneratedAcir { +pub(crate) struct GeneratedAcir { /// The next witness index that may be declared. /// If witness index is `None` then we have not yet created a witness /// and thus next witness index that be declared is zero. @@ -42,7 +41,7 @@ pub(crate) struct GeneratedAcir { current_witness_index: Option, /// The opcodes of which the compiled ACIR will comprise. - opcodes: Vec>, + opcodes: Vec>, /// All witness indices that comprise the final return value of the program pub(crate) return_witnesses: Vec, @@ -58,7 +57,7 @@ pub(crate) struct GeneratedAcir { pub(crate) call_stack: CallStack, /// Correspondence between an opcode index and the error message associated with it. - pub(crate) assertion_payloads: BTreeMap>, + pub(crate) assertion_payloads: BTreeMap>, pub(crate) warnings: Vec, @@ -80,7 +79,7 @@ pub(crate) enum BrilligStdlibFunc { } impl BrilligStdlibFunc { - pub(crate) fn get_generated_brillig(&self) -> GeneratedBrillig { + pub(crate) fn get_generated_brillig(&self) -> GeneratedBrillig { match self { BrilligStdlibFunc::Inverse => brillig_directive::directive_invert(), BrilligStdlibFunc::Quotient(bit_size) => { @@ -90,25 +89,25 @@ impl BrilligStdlibFunc { } } -impl GeneratedAcir { +impl GeneratedAcir { /// Returns the current witness index. pub(crate) fn current_witness_index(&self) -> Witness { Witness(self.current_witness_index.unwrap_or(0)) } /// Adds a new opcode into ACIR. - pub(crate) fn push_opcode(&mut self, opcode: AcirOpcode) { + pub(crate) fn push_opcode(&mut self, opcode: AcirOpcode) { self.opcodes.push(opcode); if !self.call_stack.is_empty() { self.locations.insert(self.last_acir_opcode_location(), self.call_stack.clone()); } } - pub(crate) fn opcodes(&self) -> &[AcirOpcode] { + pub(crate) fn opcodes(&self) -> &[AcirOpcode] { &self.opcodes } - pub(crate) fn take_opcodes(&mut self) -> Vec> { + pub(crate) fn take_opcodes(&mut self) -> Vec> { std::mem::take(&mut self.opcodes) } @@ -127,7 +126,7 @@ impl GeneratedAcir { /// /// If `expr` can be represented as a `Witness` then this function will return it, /// else a new opcode will be added to create a `Witness` that is equal to `expr`. - pub(crate) fn get_or_create_witness(&mut self, expr: &Expression) -> Witness { + pub(crate) fn get_or_create_witness(&mut self, expr: &Expression) -> Witness { match expr.to_witness() { Some(witness) => witness, None => self.create_witness_for_expression(expr), @@ -140,10 +139,7 @@ impl GeneratedAcir { /// This means you cannot multiply an infinite amount of `Expression`s together. /// Once the `Expression` goes over degree-2, then it needs to be reduced to a `Witness` /// which has degree-1 in order to be able to continue the multiplication chain. - pub(crate) fn create_witness_for_expression( - &mut self, - expression: &Expression, - ) -> Witness { + pub(crate) fn create_witness_for_expression(&mut self, expression: &Expression) -> Witness { let fresh_witness = self.next_witness_index(); // Create a constraint that sets them to be equal to each other @@ -163,15 +159,15 @@ impl GeneratedAcir { } } -impl GeneratedAcir { +impl GeneratedAcir { /// Calls a black box function and returns the output /// of said blackbox function. pub(crate) fn call_black_box( &mut self, func_name: BlackBoxFunc, inputs: &[Vec], - constant_inputs: Vec, - constant_outputs: Vec, + constant_inputs: Vec, + constant_outputs: Vec, output_count: usize, ) -> Result, InternalError> { let input_count = inputs.iter().fold(0usize, |sum, val| sum + val.len()); @@ -388,7 +384,7 @@ impl GeneratedAcir { /// Only radix that are a power of two are supported pub(crate) fn radix_le_decompose( &mut self, - input_expr: &Expression, + input_expr: &Expression, radix: u32, limb_count: u32, bit_size: u32, @@ -414,7 +410,7 @@ impl GeneratedAcir { self.range_constraint(*limb_witness, bit_size)?; composed_limbs = composed_limbs.add_mul( - FieldElement::from_be_bytes_reduce(&radix_pow.to_bytes_be()), + F::from_be_bytes_reduce(&radix_pow.to_bytes_be()), &Expression::from(*limb_witness), ); @@ -434,7 +430,7 @@ impl GeneratedAcir { /// /// Safety: It is the callers responsibility to ensure that the /// resulting `Witness` is constrained to be the inverse. - pub(crate) fn brillig_inverse(&mut self, expr: Expression) -> Witness { + pub(crate) fn brillig_inverse(&mut self, expr: Expression) -> Witness { // Create the witness for the result let inverted_witness = self.next_witness_index(); @@ -458,18 +454,14 @@ impl GeneratedAcir { /// /// If `expr` is not zero, then the constraint system will /// fail upon verification. - pub(crate) fn assert_is_zero(&mut self, expr: Expression) { + pub(crate) fn assert_is_zero(&mut self, expr: Expression) { self.push_opcode(AcirOpcode::AssertZero(expr)); } /// Returns a `Witness` that is constrained to be: /// - `1` if `lhs == rhs` /// - `0` otherwise - pub(crate) fn is_equal( - &mut self, - lhs: &Expression, - rhs: &Expression, - ) -> Witness { + pub(crate) fn is_equal(&mut self, lhs: &Expression, rhs: &Expression) -> Witness { let t = lhs - rhs; self.is_zero(&t) @@ -527,13 +519,13 @@ impl GeneratedAcir { /// By setting `z` to be `0`, we can make `y` equal to `1`. /// This is easily observed: `y = 1 - t * 0` /// Now since `y` is one, this means that `t` needs to be zero, or else `y * t == 0` will fail. - fn is_zero(&mut self, t_expr: &Expression) -> Witness { + fn is_zero(&mut self, t_expr: &Expression) -> Witness { // We're checking for equality with zero so we can negate the expression without changing the result. // This is useful as it will sometimes allow us to simplify an expression down to a witness. let t_witness = if let Some(witness) = t_expr.to_witness() { witness } else { - let negated_expr = t_expr * -FieldElement::one(); + let negated_expr = t_expr * -F::one(); self.get_or_create_witness(&negated_expr) }; @@ -545,17 +537,17 @@ impl GeneratedAcir { // Add constraint y == 1 - tz => y + tz - 1 == 0 let y_is_boolean_constraint = Expression { - mul_terms: vec![(FieldElement::one(), t_witness, z)], - linear_combinations: vec![(FieldElement::one(), y)], - q_c: -FieldElement::one(), + mul_terms: vec![(F::one(), t_witness, z)], + linear_combinations: vec![(F::one(), y)], + q_c: -F::one(), }; self.assert_is_zero(y_is_boolean_constraint); // Add constraint that y * t == 0; let ty_zero_constraint = Expression { - mul_terms: vec![(FieldElement::one(), t_witness, y)], + mul_terms: vec![(F::one(), t_witness, y)], linear_combinations: vec![], - q_c: FieldElement::zero(), + q_c: F::zero(), }; self.assert_is_zero(ty_zero_constraint); @@ -571,9 +563,9 @@ impl GeneratedAcir { ) -> Result<(), RuntimeError> { // We class this as an error because users should instead // do `as Field`. - if num_bits >= FieldElement::max_num_bits() { + if num_bits >= F::max_num_bits() { return Err(RuntimeError::InvalidRangeConstraint { - num_bits: FieldElement::max_num_bits(), + num_bits: F::max_num_bits(), call_stack: self.call_stack.clone(), }); }; @@ -588,9 +580,9 @@ impl GeneratedAcir { pub(crate) fn brillig_call( &mut self, - predicate: Option>, - generated_brillig: &GeneratedBrillig, - inputs: Vec>, + predicate: Option>, + generated_brillig: &GeneratedBrillig, + inputs: Vec>, outputs: Vec, brillig_function_index: u32, stdlib_func: Option, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 40170e58a30..aaa483b91c9 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -42,11 +42,11 @@ use im::Vector; use iter_extended::{try_vecmap, vecmap}; #[derive(Default)] -struct SharedContext { +struct SharedContext { /// Final list of Brillig functions which will be part of the final program /// This is shared across `Context` structs as we want one list of Brillig /// functions across all ACIR artifacts - generated_brillig: Vec, + generated_brillig: Vec>, /// Maps SSA function index -> Final generated Brillig artifact index. /// There can be Brillig functions specified in SSA which do not act as @@ -65,7 +65,7 @@ struct SharedContext { brillig_stdlib_calls_to_resolve: HashMap>, } -impl SharedContext { +impl SharedContext { fn generated_brillig_pointer( &self, func_id: FunctionId, @@ -74,7 +74,7 @@ impl SharedContext { self.brillig_generated_func_pointers.get(&(func_id, arguments)) } - fn generated_brillig(&self, func_pointer: usize) -> &GeneratedBrillig { + fn generated_brillig(&self, func_pointer: usize) -> &GeneratedBrillig { &self.generated_brillig[func_pointer] } @@ -83,7 +83,7 @@ impl SharedContext { func_id: FunctionId, arguments: Vec, generated_pointer: u32, - code: GeneratedBrillig, + code: GeneratedBrillig, ) { self.brillig_generated_func_pointers.insert((func_id, arguments), generated_pointer); self.generated_brillig.push(code); @@ -123,7 +123,7 @@ impl SharedContext { generated_pointer: u32, func_id: FunctionId, opcode_location: OpcodeLocation, - code: GeneratedBrillig, + code: GeneratedBrillig, ) { self.brillig_stdlib_func_pointer.insert(brillig_stdlib_func, generated_pointer); self.add_call_to_resolve(func_id, (opcode_location, generated_pointer)); @@ -151,7 +151,7 @@ struct Context<'a> { current_side_effects_enabled_var: AcirVar, /// Manages and builds the `AcirVar`s to which the converted SSA values refer. - acir_context: AcirContext, + acir_context: AcirContext, /// Track initialized acir dynamic arrays /// @@ -189,7 +189,7 @@ struct Context<'a> { data_bus: DataBus, /// Contains state that is generated and also used across ACIR functions - shared_context: &'a mut SharedContext, + shared_context: &'a mut SharedContext, } #[derive(Clone)] @@ -274,8 +274,11 @@ impl AcirValue { } } -pub(crate) type Artifacts = - (Vec, Vec>, BTreeMap); +pub(crate) type Artifacts = ( + Vec>, + Vec>, + BTreeMap, +); impl Ssa { #[tracing::instrument(level = "trace", skip_all)] @@ -331,7 +334,7 @@ impl Ssa { } impl<'a> Context<'a> { - fn new(shared_context: &'a mut SharedContext) -> Context<'a> { + fn new(shared_context: &'a mut SharedContext) -> Context<'a> { let mut acir_context = AcirContext::default(); let current_side_effects_enabled_var = acir_context.add_constant(FieldElement::one()); @@ -354,7 +357,7 @@ impl<'a> Context<'a> { ssa: &Ssa, function: &Function, brillig: &Brillig, - ) -> Result, RuntimeError> { + ) -> Result>, RuntimeError> { match function.runtime() { RuntimeType::Acir(inline_type) => { match inline_type { @@ -386,7 +389,7 @@ impl<'a> Context<'a> { main_func: &Function, ssa: &Ssa, brillig: &Brillig, - ) -> Result { + ) -> Result, RuntimeError> { let dfg = &main_func.dfg; let entry_block = &dfg[main_func.entry_block()]; let input_witness = self.convert_ssa_block_params(entry_block.parameters(), dfg)?; @@ -435,7 +438,7 @@ impl<'a> Context<'a> { mut self, main_func: &Function, brillig: &Brillig, - ) -> Result { + ) -> Result, RuntimeError> { let dfg = &main_func.dfg; let inputs = try_vecmap(dfg[main_func.entry_block()].parameters(), |param_id| { @@ -919,7 +922,7 @@ impl<'a> Context<'a> { func: &Function, arguments: Vec, brillig: &Brillig, - ) -> Result { + ) -> Result, InternalError> { // Create the entry point artifact let mut entry_point = BrilligContext::new_entry_point_artifact( arguments, @@ -1897,7 +1900,7 @@ impl<'a> Context<'a> { } let binary_type = AcirType::from(binary_type); - let bit_count = binary_type.bit_size(); + let bit_count = binary_type.bit_size::(); let num_type = binary_type.to_numeric_type(); let result = match binary.operator { BinaryOp::Add => self.acir_context.add_var(lhs, rhs), diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index e07f947db8d..58f70ba9192 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -375,7 +375,6 @@ impl<'f> Context<'f> { let old_condition = *condition; let then_condition = self.inserter.resolve(old_condition); - let one = FieldElement::one(); let old_stores = std::mem::take(&mut self.store_values); let old_allocations = std::mem::take(&mut self.local_allocations); let branch = ConditionalBranch { @@ -393,15 +392,6 @@ impl<'f> Context<'f> { }; self.condition_stack.push(cond_context); self.insert_current_side_effects_enabled(); - // Optimization: within the then branch we know the condition to be true, so replace - // any references of it within this branch with true. Likewise, do the same with false - // with the else branch. We must be careful not to replace the condition if it is a - // known constant, otherwise we can end up setting 1 = 0 or vice-versa. - if self.inserter.function.dfg.get_numeric_constant(old_condition).is_none() { - let known_value = self.inserter.function.dfg.make_constant(one, Type::bool()); - - self.inserter.map_value(old_condition, known_value); - } vec![self.branch_ends[if_entry], *else_destination, *then_destination] } @@ -414,7 +404,6 @@ impl<'f> Context<'f> { self.insert_instruction(Instruction::Not(cond_context.condition), CallStack::new()); let else_condition = self.link_condition(else_condition); - let zero = FieldElement::zero(); // Make sure the else branch sees the previous values of each store // rather than any values created in the 'then' branch. let old_stores = std::mem::take(&mut cond_context.then_branch.store_values); @@ -429,21 +418,12 @@ impl<'f> Context<'f> { local_allocations: old_allocations, last_block: *block, }; - let old_condition = else_branch.old_condition; cond_context.then_branch.local_allocations.clear(); cond_context.else_branch = Some(else_branch); self.condition_stack.push(cond_context); self.insert_current_side_effects_enabled(); - // Optimization: within the then branch we know the condition to be true, so replace - // any references of it within this branch with true. Likewise, do the same with false - // with the else branch. We must be careful not to replace the condition if it is a - // known constant, otherwise we can end up setting 1 = 0 or vice-versa. - if self.inserter.function.dfg.get_numeric_constant(old_condition).is_none() { - let known_value = self.inserter.function.dfg.make_constant(zero, Type::bool()); - - self.inserter.map_value(old_condition, known_value); - } + assert_eq!(self.cfg.successors(*block).len(), 1); vec![self.cfg.successors(*block).next().unwrap()] } @@ -471,11 +451,6 @@ impl<'f> Context<'f> { // known to be true/false within the then/else branch respectively. self.insert_current_side_effects_enabled(); - // We must map back to `then_condition` here. Mapping `old_condition` to itself would - // lose any previous mappings. - self.inserter - .map_value(cond_context.then_branch.old_condition, cond_context.then_branch.condition); - // While there is a condition on the stack we don't compile outside the condition // until it is popped. This ensures we inline the full then and else branches // before continuing from the end of the conditional here where they can be merged properly. diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs index c59134e4ecc..de75d34565e 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs @@ -304,7 +304,7 @@ impl<'a> ValueMerger<'a> { let mut current_then = then_value; let mut current_else = else_value; - // Arbitrarily limit this to looking at at most 10 past ArraySet operations. + // Arbitrarily limit this to looking at most 10 past ArraySet operations. // If there are more than that, we assume 2 completely separate arrays are being merged. let max_iters = 2; let mut seen_then = Vec::with_capacity(max_iters); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs index 50836add8de..075df4ee4e3 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs @@ -33,9 +33,18 @@ pub enum ExpressionKind { Tuple(Vec), Lambda(Box), Parenthesized(Box), - Quote(BlockExpression), + Quote(BlockExpression, Span), + Unquote(Box), Comptime(BlockExpression, Span), + /// Unquote expressions are replaced with UnquoteMarkers when Quoted + /// expressions are resolved. Since the expression being quoted remains an + /// ExpressionKind (rather than a resolved ExprId), the UnquoteMarker must be + /// here in the AST even though it is technically HIR-only. + /// Each usize in an UnquoteMarker is an index which corresponds to the index of the + /// expression in the Hir::Quote expression list to replace it with. + UnquoteMarker(usize), + // This variant is only emitted when inlining the result of comptime // code. It is used to translate function values back into the AST while // guaranteeing they have the same instantiated type and definition id without resolving again. @@ -179,19 +188,21 @@ impl Expression { pub fn member_access_or_method_call( lhs: Expression, - (rhs, args): UnaryRhsMemberAccess, + rhs: UnaryRhsMemberAccess, span: Span, ) -> Expression { - let kind = match args { - None => ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { lhs, rhs })), - Some((generics, arguments)) => { - ExpressionKind::MethodCall(Box::new(MethodCallExpression { - object: lhs, - method_name: rhs, - generics, - arguments, - })) + let kind = match rhs.method_call { + None => { + let rhs = rhs.method_or_field; + ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { lhs, rhs })) } + Some(method_call) => ExpressionKind::MethodCall(Box::new(MethodCallExpression { + object: lhs, + method_name: rhs.method_or_field, + generics: method_call.turbofish, + arguments: method_call.args, + is_macro_call: method_call.macro_call, + })), }; Expression::new(kind, span) } @@ -206,7 +217,12 @@ impl Expression { Expression::new(kind, span) } - pub fn call(lhs: Expression, arguments: Vec, span: Span) -> Expression { + pub fn call( + lhs: Expression, + is_macro_call: bool, + arguments: Vec, + span: Span, + ) -> Expression { // Need to check if lhs is an if expression since users can sequence if expressions // with tuples without calling them. E.g. `if c { t } else { e }(a, b)` is interpreted // as a sequence of { if, tuple } rather than a function call. This behavior matches rust. @@ -224,7 +240,11 @@ impl Expression { ], }) } else { - ExpressionKind::Call(Box::new(CallExpression { func: Box::new(lhs), arguments })) + ExpressionKind::Call(Box::new(CallExpression { + func: Box::new(lhs), + is_macro_call, + arguments, + })) }; Expression::new(kind, span) } @@ -447,6 +467,7 @@ pub enum ArrayLiteral { pub struct CallExpression { pub func: Box, pub arguments: Vec, + pub is_macro_call: bool, } #[derive(Debug, PartialEq, Eq, Clone)] @@ -456,6 +477,7 @@ pub struct MethodCallExpression { /// Method calls have an optional list of generics if the turbofish operator was used pub generics: Option>, pub arguments: Vec, + pub is_macro_call: bool, } #[derive(Debug, PartialEq, Eq, Clone)] @@ -535,10 +557,12 @@ impl Display for ExpressionKind { } Lambda(lambda) => lambda.fmt(f), Parenthesized(sub_expr) => write!(f, "({sub_expr})"), - Quote(block) => write!(f, "quote {block}"), + Quote(block, _) => write!(f, "quote {block}"), Comptime(block, _) => write!(f, "comptime {block}"), Error => write!(f, "Error"), Resolved(_) => write!(f, "?Resolved"), + Unquote(expr) => write!(f, "$({expr})"), + UnquoteMarker(index) => write!(f, "${index}"), } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs index bd2b45d9c48..3492df73103 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs @@ -117,7 +117,7 @@ pub enum UnresolvedTypeData { ), // The type of quoted code for metaprogramming - Code, + Expr, Unspecified, // This is for when the user declares a variable without specifying it's type Error, @@ -134,8 +134,16 @@ pub struct UnresolvedType { } /// Type wrapper for a member access -pub(crate) type UnaryRhsMemberAccess = - (Ident, Option<(Option>, Vec)>); +pub struct UnaryRhsMemberAccess { + pub method_or_field: Ident, + pub method_call: Option, +} + +pub struct UnaryRhsMethodCall { + pub turbofish: Option>, + pub macro_call: bool, + pub args: Vec, +} /// The precursor to TypeExpression, this is the type that the parser allows /// to be used in the length position of an array type. Only constants, variables, @@ -208,7 +216,7 @@ impl std::fmt::Display for UnresolvedTypeData { } } MutableReference(element) => write!(f, "&mut {element}"), - Code => write!(f, "Code"), + Expr => write!(f, "Expr"), Unit => write!(f, "()"), Error => write!(f, "error"), Unspecified => write!(f, "unspecified"), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs index 9b2c0fbfee8..48e34ad7fc9 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs @@ -608,6 +608,7 @@ impl ForRange { object: Expression::new(array_ident.clone(), array_span), method_name: Ident::new("len".to_string(), array_span), generics: None, + is_macro_call: false, arguments: vec![], })); let end_range = Expression::new(end_range, array_span); @@ -727,7 +728,11 @@ impl Display for LValue { impl Display for Path { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let segments = vecmap(&self.segments, ToString::to_string); - write!(f, "{}::{}", self.kind, segments.join("::")) + if self.kind == PathKind::Plain { + write!(f, "{}", segments.join("::")) + } else { + write!(f, "{}::{}", self.kind, segments.join("::")) + } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/debug/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/debug/mod.rs index c222e08e77a..f5866f5b756 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/debug/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/debug/mod.rs @@ -581,6 +581,7 @@ fn build_assign_var_stmt(var_id: SourceVarId, expr: ast::Expression) -> ast::Sta ), span, }), + is_macro_call: false, arguments: vec![uint_expr(var_id.0 as u128, span), expr], })); ast::Statement { kind: ast::StatementKind::Semi(ast::Expression { kind, span }), span } @@ -599,6 +600,7 @@ fn build_drop_var_stmt(var_id: SourceVarId, span: Span) -> ast::Statement { ), span, }), + is_macro_call: false, arguments: vec![uint_expr(var_id.0 as u128, span)], })); ast::Statement { kind: ast::StatementKind::Semi(ast::Expression { kind, span }), span } @@ -626,6 +628,7 @@ fn build_assign_member_stmt( ), span, }), + is_macro_call: false, arguments: [ vec![uint_expr(var_id.0 as u128, span)], vec![expr.clone()], @@ -649,6 +652,7 @@ fn build_debug_call_stmt(fname: &str, fn_id: DebugFnId, span: Span) -> ast::Stat ), span, }), + is_macro_call: false, arguments: vec![uint_expr(fn_id.0 as u128, span)], })); ast::Statement { kind: ast::StatementKind::Semi(ast::Expression { kind, span }), span } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs index a922f552c4b..a57690878dc 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs @@ -18,7 +18,7 @@ use crate::{ HirArrayLiteral, HirBinaryOp, HirBlockExpression, HirCallExpression, HirCastExpression, HirConstructorExpression, HirIfExpression, HirIndexExpression, HirInfixExpression, HirLambda, HirMemberAccess, HirMethodCallExpression, HirMethodReference, - HirPrefixExpression, + HirPrefixExpression, HirQuoted, }, traits::TraitConstraint, }, @@ -58,12 +58,19 @@ impl<'context> Elaborator<'context> { ExpressionKind::Tuple(tuple) => self.elaborate_tuple(tuple), ExpressionKind::Lambda(lambda) => self.elaborate_lambda(*lambda), ExpressionKind::Parenthesized(expr) => return self.elaborate_expression(*expr), - ExpressionKind::Quote(quote) => self.elaborate_quote(quote), + ExpressionKind::Quote(quote, _) => self.elaborate_quote(quote), ExpressionKind::Comptime(comptime, _) => { return self.elaborate_comptime_block(comptime, expr.span) } ExpressionKind::Resolved(id) => return (id, self.interner.id_type(id)), ExpressionKind::Error => (HirExpression::Error, Type::Error), + ExpressionKind::Unquote(_) => { + self.push_err(ResolverError::UnquoteUsedOutsideQuote { span: expr.span }); + (HirExpression::Error, Type::Error) + } + ExpressionKind::UnquoteMarker(index) => { + unreachable!("UnquoteMarker({index}) remaining in runtime code") + } }; let id = self.interner.push_expr(hir_expr); self.interner.push_expr_location(id, expr.span, self.file); @@ -280,10 +287,22 @@ impl<'context> Elaborator<'context> { (typ, arg, span) }); + // Avoid cloning arguments unless this is a macro call + let mut comptime_args = Vec::new(); + if call.is_macro_call { + comptime_args = arguments.clone(); + } + let location = Location::new(span, self.file); - let call = HirCallExpression { func, arguments, location }; - let typ = self.type_check_call(&call, func_type, args, span); - (HirExpression::Call(call), typ) + let hir_call = HirCallExpression { func, arguments, location }; + let typ = self.type_check_call(&hir_call, func_type, args, span); + + if call.is_macro_call { + self.call_macro(func, comptime_args, location, typ) + .unwrap_or_else(|| (HirExpression::Error, Type::Error)) + } else { + (HirExpression::Call(hir_call), typ) + } } fn elaborate_method_call( @@ -627,8 +646,11 @@ impl<'context> Elaborator<'context> { (expr, Type::Function(arg_types, Box::new(body_type), Box::new(env_type))) } - fn elaborate_quote(&mut self, block: BlockExpression) -> (HirExpression, Type) { - (HirExpression::Quote(block), Type::Code) + fn elaborate_quote(&mut self, mut block: BlockExpression) -> (HirExpression, Type) { + let mut unquoted_exprs = Vec::new(); + self.find_unquoted_exprs_in_block(&mut block, &mut unquoted_exprs); + let quoted = HirQuoted { quoted_block: block, unquoted_exprs }; + (HirExpression::Quote(quoted), Type::Expr) } fn elaborate_comptime_block(&mut self, block: BlockExpression, span: Span) -> (ExprId, Type) { @@ -661,4 +683,74 @@ impl<'context> Elaborator<'context> { Err(error) => make_error(self, error), } } + + fn try_get_comptime_function( + &mut self, + func: ExprId, + location: Location, + ) -> Result { + match self.interner.expression(&func) { + HirExpression::Ident(ident, _generics) => { + let definition = self.interner.definition(ident.id); + if let DefinitionKind::Function(function) = definition.kind { + let meta = self.interner.function_modifiers(&function); + if meta.is_comptime { + Ok(function) + } else { + Err(ResolverError::MacroIsNotComptime { span: location.span }) + } + } else { + Err(ResolverError::InvalidSyntaxInMacroCall { span: location.span }) + } + } + _ => Err(ResolverError::InvalidSyntaxInMacroCall { span: location.span }), + } + } + + /// Call a macro function and inlines its code at the call site. + /// This will also perform a type check to ensure that the return type is an `Expr` value. + fn call_macro( + &mut self, + func: ExprId, + arguments: Vec, + location: Location, + return_type: Type, + ) -> Option<(HirExpression, Type)> { + self.unify(&return_type, &Type::Expr, || TypeCheckError::MacroReturningNonExpr { + typ: return_type.clone(), + span: location.span, + }); + + let function = match self.try_get_comptime_function(func, location) { + Ok(function) => function, + Err(error) => { + self.push_err(error); + return None; + } + }; + + let mut interpreter = Interpreter::new(self.interner, &mut self.comptime_scopes); + + let mut comptime_args = Vec::new(); + let mut errors = Vec::new(); + + for argument in arguments { + match interpreter.evaluate(argument) { + Ok(arg) => { + let location = interpreter.interner.expr_location(&argument); + comptime_args.push((arg, location)); + } + Err(error) => errors.push((error.into(), self.file)), + } + } + + if !errors.is_empty() { + self.errors.append(&mut errors); + return None; + } + + let result = interpreter.call_function(function, comptime_args, location); + let (expr_id, typ) = self.inline_comptime_value(result, location.span); + Some((self.interner.expression(&expr_id), typ)) + } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs index 37ad74b78b0..93e8b36f4e0 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs @@ -62,6 +62,7 @@ mod scope; mod statements; mod traits; mod types; +mod unquote; use fm::FileId; use iter_extended::vecmap; @@ -232,25 +233,22 @@ impl<'context> Elaborator<'context> { // Must resolve structs before we resolve globals. this.collect_struct_definitions(items.types); - // Bind trait impls to their trait. Collect trait functions, that have a - // default implementation, which hasn't been overridden. - for trait_impl in &mut items.trait_impls { - this.collect_trait_impl(trait_impl); - } - // Before we resolve any function symbols we must go through our impls and // re-collect the methods within into their proper module. This cannot be // done during def collection since we need to be able to resolve the type of // the impl since that determines the module we should collect into. - // - // These are resolved after trait impls so that struct methods are chosen - // over trait methods if there are name conflicts. for ((_self_type, module), impls) in &mut items.impls { this.collect_impls(*module, impls); } + // Bind trait impls to their trait. Collect trait functions, that have a + // default implementation, which hasn't been overridden. + for trait_impl in &mut items.trait_impls { + this.collect_trait_impl(trait_impl); + } + // We must wait to resolve non-literal globals until after we resolve structs since struct - // globals will need to reference the struct type they're initialized to to ensure they are valid. + // globals will need to reference the struct type they're initialized to ensure they are valid. while let Some((_, global)) = this.unresolved_globals.pop_first() { this.elaborate_global(global); } @@ -311,6 +309,7 @@ impl<'context> Elaborator<'context> { let old_function = std::mem::replace(&mut self.current_function, Some(id)); // Without this, impl methods can accidentally be placed in contracts. See #3254 + let was_in_contract = self.in_contract; if self.self_type.is_some() { self.in_contract = false; } @@ -404,8 +403,10 @@ impl<'context> Elaborator<'context> { meta.function_body = FunctionBody::Resolved; self.trait_bounds.clear(); + self.type_variables.clear(); self.in_unconstrained_fn = false; self.interner.update_fn(id, hir_func); + self.in_contract = was_in_contract; self.current_function = old_function; self.current_item = old_item; } @@ -547,6 +548,7 @@ impl<'context> Elaborator<'context> { self.current_function = Some(func_id); // Without this, impl methods can accidentally be placed in contracts. See #3254 + let was_in_contract = self.in_contract; if self.self_type.is_some() { self.in_contract = false; } @@ -662,6 +664,7 @@ impl<'context> Elaborator<'context> { }; self.interner.push_fn_meta(meta, func_id); + self.in_contract = was_in_contract; self.current_function = None; self.scopes.end_function(); self.current_item = None; @@ -860,9 +863,12 @@ impl<'context> Elaborator<'context> { self.self_type = None; } - fn get_module_mut(&mut self, module: ModuleId) -> &mut ModuleData { + fn get_module_mut( + def_maps: &mut BTreeMap, + module: ModuleId, + ) -> &mut ModuleData { let message = "A crate should always be present for a given crate id"; - &mut self.def_maps.get_mut(&module.krate).expect(message).modules[module.local_id.0] + &mut def_maps.get_mut(&module.krate).expect(message).modules[module.local_id.0] } fn declare_methods_on_struct( @@ -890,7 +896,7 @@ impl<'context> Elaborator<'context> { // Grab the module defined by the struct type. Note that impls are a case // where the module the methods are added to is not the same as the module // they are resolved in. - let module = self.get_module_mut(struct_ref.id.module_id()); + let module = Self::get_module_mut(self.def_maps, struct_ref.id.module_id()); for (_, method_id, method) in &functions.functions { // If this method was already declared, remove it from the module so it cannot @@ -899,22 +905,37 @@ impl<'context> Elaborator<'context> { // If not, that is specialization which is allowed. let name = method.name_ident().clone(); if module.declare_function(name, ItemVisibility::Public, *method_id).is_err() { - module.remove_function(method.name_ident()); + let existing = module.find_func_with_name(method.name_ident()).expect( + "declare_function should only error if there is an existing function", + ); + + // Only remove the existing function from scope if it is from a trait impl as + // well. If it is from a non-trait impl that should override trait impl methods + // anyway so that Foo::bar always resolves to the non-trait impl version. + if self.interner.function_meta(&existing).trait_impl.is_some() { + module.remove_function(method.name_ident()); + } } } - self.declare_struct_methods(self_type, &function_ids); + // Trait impl methods are already declared in NodeInterner::add_trait_implementation + if !is_trait_impl { + self.declare_methods(self_type, &function_ids); + } // We can define methods on primitive types only if we're in the stdlib } else if !is_trait_impl && *self_type != Type::Error { if self.crate_id.is_stdlib() { - self.declare_struct_methods(self_type, &function_ids); + // Trait impl methods are already declared in NodeInterner::add_trait_implementation + if !is_trait_impl { + self.declare_methods(self_type, &function_ids); + } } else { self.push_err(DefCollectorErrorKind::NonStructTypeInImpl { span }); } } } - fn declare_struct_methods(&mut self, self_type: &Type, function_ids: &[FuncId]) { + fn declare_methods(&mut self, self_type: &Type, function_ids: &[FuncId]) { for method_id in function_ids { let method_name = self.interner.function_name(method_id).to_owned(); @@ -1080,6 +1101,7 @@ impl<'context> Elaborator<'context> { // make sure every struct's fields is accurately set. for id in struct_ids { let struct_type = self.interner.get_struct(id); + // Only handle structs without generics as any generics args will be checked // after monomorphization when performing SSA codegen if struct_type.borrow().generics.is_empty() { @@ -1114,8 +1136,8 @@ impl<'context> Elaborator<'context> { } fn elaborate_global(&mut self, global: UnresolvedGlobal) { - self.local_module = global.module_id; - self.file = global.file_id; + let old_module = std::mem::replace(&mut self.local_module, global.module_id); + let old_file = std::mem::replace(&mut self.file, global.file_id); let global_id = global.global_id; self.current_item = Some(DependencyId::Global(global_id)); @@ -1147,6 +1169,8 @@ impl<'context> Elaborator<'context> { // Otherwise we may prematurely default to a Field inside the next function if this // global was unused there, even if it is consistently used as a u8 everywhere else. self.type_variables.clear(); + self.local_module = old_module; + self.file = old_file; } fn elaborate_comptime_global(&mut self, global_id: GlobalId) { @@ -1186,11 +1210,13 @@ impl<'context> Elaborator<'context> { self.local_module = *local_module; for (generics, _, function_set) in function_sets { + self.file = function_set.file_id; self.add_generics(generics); let self_type = self.resolve_type(self_type.clone()); function_set.self_type = Some(self_type.clone()); self.self_type = Some(self_type); self.define_function_metas_for_functions(function_set); + self.self_type = None; self.generics.clear(); } } @@ -1205,10 +1231,10 @@ impl<'context> Elaborator<'context> { let trait_generics = vecmap(&trait_impl.trait_generics, |generic| self.resolve_type(generic.clone())); + trait_impl.resolved_trait_generics = trait_generics; let self_type = self.resolve_type(unresolved_type.clone()); - self.self_type = Some(self_type.clone()); trait_impl.methods.self_type = Some(self_type); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs index 3baa7054fc5..a9571a6669d 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs @@ -72,7 +72,7 @@ impl<'context> Elaborator<'context> { let fields = self.resolve_type_inner(*fields); Type::FmtString(Box::new(resolved_size), Box::new(fields)) } - Code => Type::Code, + Expr => Type::Expr, Unit => Type::Unit, Unspecified => Type::Error, Error => Type::Error, @@ -1396,7 +1396,7 @@ impl<'context> Elaborator<'context> { | Type::TypeVariable(_, _) | Type::Constant(_) | Type::NamedGeneric(_, _) - | Type::Code + | Type::Expr | Type::Forall(_, _) => (), Type::TraitAsType(_, _, args) => { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/unquote.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/unquote.rs new file mode 100644 index 00000000000..6767f471f16 --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/unquote.rs @@ -0,0 +1,306 @@ +use crate::{ + ast::{ + ArrayLiteral, AssignStatement, ConstrainStatement, ConstructorExpression, IfExpression, + InfixExpression, Lambda, + }, + macros_api::{ + BlockExpression, CallExpression, CastExpression, Expression, ExpressionKind, + ForLoopStatement, ForRange, IndexExpression, LetStatement, Literal, MemberAccessExpression, + MethodCallExpression, PrefixExpression, Statement, StatementKind, + }, + node_interner::ExprId, +}; + +use super::Elaborator; + +impl<'a> Elaborator<'a> { + pub fn find_unquoted_exprs_in_block( + &mut self, + block: &mut BlockExpression, + unquoted_exprs: &mut Vec, + ) { + for statement in &mut block.statements { + self.find_unquoted_exprs_in_statement(statement, unquoted_exprs); + } + } + + fn find_unquoted_exprs_in_statement( + &mut self, + statement: &mut Statement, + unquoted_exprs: &mut Vec, + ) { + match &mut statement.kind { + StatementKind::Let(let_) => self.find_unquoted_exprs_in_let(let_, unquoted_exprs), + StatementKind::Constrain(constrain) => { + self.find_unquoted_exprs_in_constrain(constrain, unquoted_exprs); + } + StatementKind::Expression(expr) => { + self.find_unquoted_exprs_in_expr(expr, unquoted_exprs); + } + StatementKind::Assign(assign) => { + self.find_unquoted_exprs_in_assign(assign, unquoted_exprs); + } + StatementKind::For(for_) => self.find_unquoted_exprs_in_for(for_, unquoted_exprs), + StatementKind::Break => (), + StatementKind::Continue => (), + StatementKind::Comptime(comptime) => { + self.find_unquoted_exprs_in_statement(comptime, unquoted_exprs); + } + StatementKind::Semi(expr) => self.find_unquoted_exprs_in_expr(expr, unquoted_exprs), + StatementKind::Error => (), + } + } + + fn find_unquoted_exprs_in_constrain( + &mut self, + constrain: &mut ConstrainStatement, + unquoted_exprs: &mut Vec, + ) { + self.find_unquoted_exprs_in_expr(&mut constrain.0, unquoted_exprs); + if let Some(msg) = constrain.1.as_mut() { + self.find_unquoted_exprs_in_expr(msg, unquoted_exprs); + } + } + + fn find_unquoted_exprs_in_let( + &mut self, + let_: &mut LetStatement, + unquoted_exprs: &mut Vec, + ) { + self.find_unquoted_exprs_in_expr(&mut let_.expression, unquoted_exprs); + } + + fn find_unquoted_exprs_in_assign( + &mut self, + assign: &mut AssignStatement, + unquoted_exprs: &mut Vec, + ) { + self.find_unquoted_exprs_in_expr(&mut assign.expression, unquoted_exprs); + } + + fn find_unquoted_exprs_in_for( + &mut self, + for_: &mut ForLoopStatement, + unquoted_exprs: &mut Vec, + ) { + match &mut for_.range { + ForRange::Range(start, end) => { + self.find_unquoted_exprs_in_expr(start, unquoted_exprs); + self.find_unquoted_exprs_in_expr(end, unquoted_exprs); + } + ForRange::Array(array) => { + self.find_unquoted_exprs_in_expr(array, unquoted_exprs); + } + }; + self.find_unquoted_exprs_in_expr(&mut for_.block, unquoted_exprs); + } + + fn find_unquoted_exprs_in_expr( + &mut self, + expr: &mut Expression, + unquoted_exprs: &mut Vec, + ) { + match &mut expr.kind { + ExpressionKind::Literal(literal) => { + self.find_unquoted_exprs_in_literal(literal, unquoted_exprs); + } + ExpressionKind::Block(block) => { + self.find_unquoted_exprs_in_block(block, unquoted_exprs); + } + ExpressionKind::Prefix(prefix) => { + self.find_unquoted_exprs_in_prefix(prefix, unquoted_exprs); + } + ExpressionKind::Index(index) => { + self.find_unquoted_exprs_in_index(index, unquoted_exprs); + } + ExpressionKind::Call(call) => self.find_unquoted_exprs_in_call(call, unquoted_exprs), + ExpressionKind::MethodCall(call) => { + self.find_unquoted_exprs_in_method_call(call, unquoted_exprs); + } + ExpressionKind::Constructor(constructor) => { + self.find_unquoted_exprs_in_constructor(constructor, unquoted_exprs); + } + ExpressionKind::MemberAccess(access) => { + self.find_unquoted_exprs_in_access(access, unquoted_exprs); + } + ExpressionKind::Cast(cast) => self.find_unquoted_exprs_in_cast(cast, unquoted_exprs), + ExpressionKind::Infix(infix) => { + self.find_unquoted_exprs_in_infix(infix, unquoted_exprs); + } + ExpressionKind::If(if_) => self.find_unquoted_exprs_in_if(if_, unquoted_exprs), + ExpressionKind::Variable(_, _) => (), + ExpressionKind::Tuple(tuple) => { + self.find_unquoted_exprs_in_tuple(tuple, unquoted_exprs); + } + ExpressionKind::Lambda(lambda) => { + self.find_unquoted_exprs_in_lambda(lambda, unquoted_exprs); + } + ExpressionKind::Parenthesized(expr) => { + self.find_unquoted_exprs_in_expr(expr, unquoted_exprs); + } + ExpressionKind::Quote(quote, _) => { + self.find_unquoted_exprs_in_block(quote, unquoted_exprs); + } + ExpressionKind::Comptime(block, _) => { + self.find_unquoted_exprs_in_block(block, unquoted_exprs); + } + ExpressionKind::Resolved(_) => (), + ExpressionKind::Error => (), + ExpressionKind::UnquoteMarker(_) => (), + ExpressionKind::Unquote(unquoted) => { + // Avoid an expensive clone for unquoted + let empty_expr = Expression::new(ExpressionKind::Error, unquoted.span); + let unquote = std::mem::replace(unquoted.as_mut(), empty_expr); + self.replace_unquote(expr, unquote, unquoted_exprs); + } + } + } + + fn find_unquoted_exprs_in_literal( + &mut self, + literal: &mut Literal, + unquoted_exprs: &mut Vec, + ) { + match literal { + Literal::Array(array) | Literal::Slice(array) => match array { + ArrayLiteral::Standard(elements) => { + for element in elements { + self.find_unquoted_exprs_in_expr(element, unquoted_exprs); + } + } + ArrayLiteral::Repeated { repeated_element, length } => { + self.find_unquoted_exprs_in_expr(repeated_element, unquoted_exprs); + self.find_unquoted_exprs_in_expr(length, unquoted_exprs); + } + }, + Literal::Bool(_) + | Literal::Integer(_, _) + | Literal::Str(_) + | Literal::RawStr(_, _) + | Literal::FmtStr(_) + | Literal::Unit => (), + } + } + + fn find_unquoted_exprs_in_prefix( + &mut self, + prefix: &mut PrefixExpression, + unquoted_exprs: &mut Vec, + ) { + self.find_unquoted_exprs_in_expr(&mut prefix.rhs, unquoted_exprs); + } + + fn find_unquoted_exprs_in_index( + &mut self, + index: &mut IndexExpression, + unquoted_exprs: &mut Vec, + ) { + self.find_unquoted_exprs_in_expr(&mut index.collection, unquoted_exprs); + self.find_unquoted_exprs_in_expr(&mut index.index, unquoted_exprs); + } + + fn find_unquoted_exprs_in_call( + &mut self, + call: &mut CallExpression, + unquoted_exprs: &mut Vec, + ) { + self.find_unquoted_exprs_in_expr(&mut call.func, unquoted_exprs); + + for arg in &mut call.arguments { + self.find_unquoted_exprs_in_expr(arg, unquoted_exprs); + } + } + + fn find_unquoted_exprs_in_method_call( + &mut self, + call: &mut MethodCallExpression, + unquoted_exprs: &mut Vec, + ) { + self.find_unquoted_exprs_in_expr(&mut call.object, unquoted_exprs); + + for arg in &mut call.arguments { + self.find_unquoted_exprs_in_expr(arg, unquoted_exprs); + } + } + + fn find_unquoted_exprs_in_constructor( + &mut self, + constructor: &mut ConstructorExpression, + unquoted_exprs: &mut Vec, + ) { + for (_, field) in &mut constructor.fields { + self.find_unquoted_exprs_in_expr(field, unquoted_exprs); + } + } + + fn find_unquoted_exprs_in_access( + &mut self, + member_access: &mut MemberAccessExpression, + unquoted_exprs: &mut Vec, + ) { + self.find_unquoted_exprs_in_expr(&mut member_access.lhs, unquoted_exprs); + } + + fn find_unquoted_exprs_in_cast( + &mut self, + cast: &mut CastExpression, + unquoted_exprs: &mut Vec, + ) { + self.find_unquoted_exprs_in_expr(&mut cast.lhs, unquoted_exprs); + } + + fn find_unquoted_exprs_in_infix( + &mut self, + infix: &mut InfixExpression, + unquoted_exprs: &mut Vec, + ) { + self.find_unquoted_exprs_in_expr(&mut infix.lhs, unquoted_exprs); + self.find_unquoted_exprs_in_expr(&mut infix.rhs, unquoted_exprs); + } + + fn find_unquoted_exprs_in_if( + &mut self, + if_: &mut IfExpression, + unquoted_exprs: &mut Vec, + ) { + self.find_unquoted_exprs_in_expr(&mut if_.condition, unquoted_exprs); + self.find_unquoted_exprs_in_expr(&mut if_.consequence, unquoted_exprs); + + if let Some(alternate) = if_.alternative.as_mut() { + self.find_unquoted_exprs_in_expr(alternate, unquoted_exprs); + } + } + + fn find_unquoted_exprs_in_tuple( + &mut self, + tuple: &mut [Expression], + unquoted_exprs: &mut Vec, + ) { + for field in tuple { + self.find_unquoted_exprs_in_expr(field, unquoted_exprs); + } + } + + fn find_unquoted_exprs_in_lambda( + &mut self, + lambda: &mut Lambda, + unquoted_exprs: &mut Vec, + ) { + self.find_unquoted_exprs_in_expr(&mut lambda.body, unquoted_exprs); + } + + /// Elaborate and store the unquoted expression in the given vector, then + /// replace it with an unquote expression with an UnquoteMarker expression to mark the position + /// to replace it with later. + fn replace_unquote( + &mut self, + expr: &mut Expression, + unquoted: Expression, + unquoted_exprs: &mut Vec, + ) { + let (expr_id, _) = self.elaborate_expression(unquoted); + let unquote_marker_id = unquoted_exprs.len(); + unquoted_exprs.push(expr_id); + expr.kind = ExpressionKind::UnquoteMarker(unquote_marker_id); + } +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs index 186eaa58c14..3648881e501 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs @@ -7,6 +7,7 @@ use noirc_errors::Location; use rustc_hash::FxHashMap as HashMap; use crate::ast::{BinaryOpKind, FunctionKind, IntegerBitSize, Signedness}; +use crate::hir_def::expr::HirQuoted; use crate::{ hir_def::{ expr::{ @@ -25,13 +26,17 @@ use crate::{ Shared, Type, TypeBinding, TypeBindings, TypeVariableKind, }; +use self::unquote::UnquoteArgs; + use super::errors::{IResult, InterpreterError}; use super::value::Value; +mod unquote; + #[allow(unused)] pub struct Interpreter<'interner> { /// To expand macros the Interpreter may mutate hir nodes within the NodeInterner - pub(super) interner: &'interner mut NodeInterner, + pub interner: &'interner mut NodeInterner, /// Each value currently in scope in the interpreter. /// Each element of the Vec represents a scope with every scope together making @@ -315,14 +320,11 @@ impl<'a> Interpreter<'a> { } /// Evaluate an expression and return the result - pub(super) fn evaluate(&mut self, id: ExprId) -> IResult { + pub fn evaluate(&mut self, id: ExprId) -> IResult { match self.interner.expression(&id) { HirExpression::Ident(ident, _) => self.evaluate_ident(ident, id), HirExpression::Literal(literal) => self.evaluate_literal(literal, id), - HirExpression::Block(block) => { - dbg!("going to evaluate a block"); - self.evaluate_block(block) - } + HirExpression::Block(block) => self.evaluate_block(block), HirExpression::Prefix(prefix) => self.evaluate_prefix(prefix, id), HirExpression::Infix(infix) => self.evaluate_infix(infix, id), HirExpression::Index(index) => self.evaluate_index(index, id), @@ -334,7 +336,7 @@ impl<'a> Interpreter<'a> { HirExpression::If(if_) => self.evaluate_if(if_, id), HirExpression::Tuple(tuple) => self.evaluate_tuple(tuple), HirExpression::Lambda(lambda) => self.evaluate_lambda(lambda, id), - HirExpression::Quote(block) => Ok(Value::Code(Rc::new(block))), + HirExpression::Quote(block) => self.evaluate_quote(block, id), HirExpression::Comptime(block) => self.evaluate_block(block), HirExpression::Unquote(block) => { // An Unquote expression being found is indicative of a macro being @@ -1127,6 +1129,15 @@ impl<'a> Interpreter<'a> { Ok(Value::Closure(lambda, environment, typ)) } + fn evaluate_quote(&mut self, mut quoted: HirQuoted, expr_id: ExprId) -> IResult { + let file = self.interner.expr_location(&expr_id).file; + let values = try_vecmap(quoted.unquoted_exprs, |value| self.evaluate(value))?; + let args = UnquoteArgs { values, file }; + + self.substitute_unquoted_values_into_block(&mut quoted.quoted_block, &args); + Ok(Value::Code(Rc::new(quoted.quoted_block))) + } + pub fn evaluate_statement(&mut self, statement: StmtId) -> IResult { match self.interner.statement(&statement) { HirStatement::Let(let_) => self.evaluate_let(let_), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/unquote.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/unquote.rs new file mode 100644 index 00000000000..58ca345ca90 --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/unquote.rs @@ -0,0 +1,287 @@ +use fm::FileId; +use noirc_errors::Location; + +use crate::{ + ast::{ + ArrayLiteral, AssignStatement, ConstrainStatement, ConstructorExpression, IfExpression, + InfixExpression, Lambda, + }, + hir::comptime::{errors::IResult, Value}, + macros_api::{ + BlockExpression, CallExpression, CastExpression, Expression, ExpressionKind, + ForLoopStatement, ForRange, IndexExpression, LetStatement, Literal, MemberAccessExpression, + MethodCallExpression, PrefixExpression, Statement, StatementKind, + }, +}; + +use super::Interpreter; + +pub(super) struct UnquoteArgs { + pub(super) values: Vec, + pub(super) file: FileId, +} + +impl<'a> Interpreter<'a> { + pub(super) fn substitute_unquoted_values_into_block( + &mut self, + block: &mut BlockExpression, + args: &UnquoteArgs, + ) -> IResult<()> { + for statement in &mut block.statements { + self.substitute_unquoted_into_statement(statement, args)?; + } + Ok(()) + } + + fn substitute_unquoted_into_statement( + &mut self, + statement: &mut Statement, + args: &UnquoteArgs, + ) -> IResult<()> { + match &mut statement.kind { + StatementKind::Let(let_) => self.substitute_unquoted_into_let(let_, args), + StatementKind::Constrain(constrain) => { + self.substitute_unquoted_into_constrain(constrain, args) + } + StatementKind::Expression(expr) => self.substitute_unquoted_into_expr(expr, args), + StatementKind::Assign(assign) => self.substitute_unquoted_into_assign(assign, args), + StatementKind::For(for_) => self.substitute_unquoted_into_for(for_, args), + StatementKind::Break => Ok(()), + StatementKind::Continue => Ok(()), + StatementKind::Comptime(comptime) => { + self.substitute_unquoted_into_statement(comptime, args) + } + StatementKind::Semi(expr) => self.substitute_unquoted_into_expr(expr, args), + StatementKind::Error => Ok(()), + } + } + + fn substitute_unquoted_into_constrain( + &mut self, + constrain: &mut ConstrainStatement, + args: &UnquoteArgs, + ) -> IResult<()> { + self.substitute_unquoted_into_expr(&mut constrain.0, args)?; + if let Some(msg) = constrain.1.as_mut() { + self.substitute_unquoted_into_expr(msg, args)?; + } + Ok(()) + } + + fn substitute_unquoted_into_let( + &mut self, + let_: &mut LetStatement, + args: &UnquoteArgs, + ) -> IResult<()> { + self.substitute_unquoted_into_expr(&mut let_.expression, args) + } + + fn substitute_unquoted_into_assign( + &mut self, + assign: &mut AssignStatement, + args: &UnquoteArgs, + ) -> IResult<()> { + self.substitute_unquoted_into_expr(&mut assign.expression, args) + } + + fn substitute_unquoted_into_for( + &mut self, + for_: &mut ForLoopStatement, + args: &UnquoteArgs, + ) -> IResult<()> { + match &mut for_.range { + ForRange::Range(start, end) => { + self.substitute_unquoted_into_expr(start, args)?; + self.substitute_unquoted_into_expr(end, args)?; + } + ForRange::Array(array) => { + self.substitute_unquoted_into_expr(array, args)?; + } + }; + self.substitute_unquoted_into_expr(&mut for_.block, args) + } + + fn substitute_unquoted_into_expr( + &mut self, + expr: &mut Expression, + args: &UnquoteArgs, + ) -> IResult<()> { + match &mut expr.kind { + ExpressionKind::Literal(literal) => { + self.substitute_unquoted_into_literal(literal, args) + } + ExpressionKind::Block(block) => self.substitute_unquoted_values_into_block(block, args), + ExpressionKind::Prefix(prefix) => self.substitute_unquoted_into_prefix(prefix, args), + ExpressionKind::Index(index) => self.substitute_unquoted_into_index(index, args), + ExpressionKind::Call(call) => self.substitute_unquoted_into_call(call, args), + ExpressionKind::MethodCall(call) => { + self.substitute_unquoted_into_method_call(call, args) + } + ExpressionKind::Constructor(constructor) => { + self.substitute_unquoted_into_constructor(constructor, args) + } + ExpressionKind::MemberAccess(access) => { + self.substitute_unquoted_into_access(access, args) + } + ExpressionKind::Cast(cast) => self.substitute_unquoted_into_cast(cast, args), + ExpressionKind::Infix(infix) => self.substitute_unquoted_into_infix(infix, args), + ExpressionKind::If(if_) => self.substitute_unquoted_into_if(if_, args), + ExpressionKind::Variable(_, _) => Ok(()), + ExpressionKind::Tuple(tuple) => self.substitute_unquoted_into_tuple(tuple, args), + ExpressionKind::Lambda(lambda) => self.substitute_unquoted_into_lambda(lambda, args), + ExpressionKind::Parenthesized(expr) => self.substitute_unquoted_into_expr(expr, args), + ExpressionKind::Quote(quote, _) => { + self.substitute_unquoted_values_into_block(quote, args) + } + ExpressionKind::Unquote(unquote) => self.substitute_unquoted_into_expr(unquote, args), + ExpressionKind::Comptime(comptime, _) => { + self.substitute_unquoted_values_into_block(comptime, args) + } + ExpressionKind::Resolved(_) => Ok(()), + ExpressionKind::Error => Ok(()), + ExpressionKind::UnquoteMarker(index) => { + let location = Location::new(expr.span, args.file); + *expr = args.values[*index].clone().into_expression(self.interner, location)?; + Ok(()) + } + } + } + + fn substitute_unquoted_into_literal( + &mut self, + literal: &mut Literal, + args: &UnquoteArgs, + ) -> IResult<()> { + match literal { + Literal::Array(array) | Literal::Slice(array) => match array { + ArrayLiteral::Standard(elements) => { + for element in elements { + self.substitute_unquoted_into_expr(element, args)?; + } + Ok(()) + } + ArrayLiteral::Repeated { repeated_element, length } => { + self.substitute_unquoted_into_expr(repeated_element, args)?; + self.substitute_unquoted_into_expr(length, args)?; + Ok(()) + } + }, + Literal::Bool(_) + | Literal::Integer(_, _) + | Literal::Str(_) + | Literal::RawStr(_, _) + | Literal::FmtStr(_) + | Literal::Unit => Ok(()), + } + } + + fn substitute_unquoted_into_prefix( + &mut self, + prefix: &mut PrefixExpression, + args: &UnquoteArgs, + ) -> IResult<()> { + self.substitute_unquoted_into_expr(&mut prefix.rhs, args) + } + + fn substitute_unquoted_into_index( + &mut self, + index: &mut IndexExpression, + args: &UnquoteArgs, + ) -> IResult<()> { + self.substitute_unquoted_into_expr(&mut index.collection, args)?; + self.substitute_unquoted_into_expr(&mut index.index, args) + } + + fn substitute_unquoted_into_call( + &mut self, + call: &mut CallExpression, + args: &UnquoteArgs, + ) -> IResult<()> { + self.substitute_unquoted_into_expr(&mut call.func, args)?; + for arg in &mut call.arguments { + self.substitute_unquoted_into_expr(arg, args)?; + } + Ok(()) + } + + fn substitute_unquoted_into_method_call( + &mut self, + call: &mut MethodCallExpression, + args: &UnquoteArgs, + ) -> IResult<()> { + self.substitute_unquoted_into_expr(&mut call.object, args)?; + for arg in &mut call.arguments { + self.substitute_unquoted_into_expr(arg, args)?; + } + Ok(()) + } + + fn substitute_unquoted_into_constructor( + &mut self, + constructor: &mut ConstructorExpression, + args: &UnquoteArgs, + ) -> IResult<()> { + for (_, field) in &mut constructor.fields { + self.substitute_unquoted_into_expr(field, args)?; + } + Ok(()) + } + + fn substitute_unquoted_into_access( + &mut self, + access: &mut MemberAccessExpression, + args: &UnquoteArgs, + ) -> IResult<()> { + self.substitute_unquoted_into_expr(&mut access.lhs, args) + } + + fn substitute_unquoted_into_cast( + &mut self, + cast: &mut CastExpression, + args: &UnquoteArgs, + ) -> IResult<()> { + self.substitute_unquoted_into_expr(&mut cast.lhs, args) + } + + fn substitute_unquoted_into_infix( + &mut self, + infix: &mut InfixExpression, + args: &UnquoteArgs, + ) -> IResult<()> { + self.substitute_unquoted_into_expr(&mut infix.lhs, args)?; + self.substitute_unquoted_into_expr(&mut infix.rhs, args) + } + + fn substitute_unquoted_into_if( + &mut self, + if_: &mut IfExpression, + args: &UnquoteArgs, + ) -> IResult<()> { + self.substitute_unquoted_into_expr(&mut if_.condition, args)?; + self.substitute_unquoted_into_expr(&mut if_.consequence, args)?; + + if let Some(alternative) = if_.alternative.as_mut() { + self.substitute_unquoted_into_expr(alternative, args)?; + } + Ok(()) + } + + fn substitute_unquoted_into_tuple( + &mut self, + tuple: &mut [Expression], + args: &UnquoteArgs, + ) -> IResult<()> { + for field in tuple { + self.substitute_unquoted_into_expr(field, args)?; + } + Ok(()) + } + + fn substitute_unquoted_into_lambda( + &mut self, + lambda: &mut Lambda, + args: &UnquoteArgs, + ) -> IResult<()> { + self.substitute_unquoted_into_expr(&mut lambda.body, args) + } +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/scan.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/scan.rs index 9e3b03ef525..f2e21e608ea 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/scan.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/scan.rs @@ -53,9 +53,7 @@ impl<'interner> Interpreter<'interner> { /// Otherwise, scan through its expression for any comptime blocks to evaluate. pub fn scan_global(&mut self, global: GlobalId) -> IResult<()> { if let Some(let_) = self.interner.get_global_let_statement(global) { - // dbg!(let_.clone()); if let_.comptime { - dbg!("got here"); self.evaluate_let(let_)?; } else { self.scan_expression(let_.expression)?; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/value.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/value.rs index 11bbbc7484d..5d91b151218 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/value.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/value.rs @@ -70,7 +70,7 @@ impl Value { Value::Struct(_, typ) => return Cow::Borrowed(typ), Value::Array(_, typ) => return Cow::Borrowed(typ), Value::Slice(_, typ) => return Cow::Borrowed(typ), - Value::Code(_) => Type::Code, + Value::Code(_) => Type::Expr, Value::Pointer(element) => { let element = element.borrow().get_type().into_owned(); Type::MutableReference(Box::new(element)) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 9b47a104a40..4511537a1cc 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -404,7 +404,7 @@ impl DefCollector { resolved_module.errors.extend(collect_impls(context, crate_id, &def_collector.items.impls)); // We must wait to resolve non-integer globals until after we resolve structs since struct - // globals will need to reference the struct type they're initialized to to ensure they are valid. + // globals will need to reference the struct type they're initialized to ensure they are valid. resolved_module.resolve_globals(context, other_globals, crate_id); // Resolve each function in the crate. This is now possible since imports have been resolved diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs index 06f6dda7142..2c6461cb77c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs @@ -100,6 +100,12 @@ pub enum ResolverError { FoldAttributeOnUnconstrained { ident: Ident }, #[error("Invalid array length construction")] ArrayLengthInterpreter { error: InterpreterError }, + #[error("The unquote operator '$' can only be used within a quote expression")] + UnquoteUsedOutsideQuote { span: Span }, + #[error("Invalid syntax in macro call")] + InvalidSyntaxInMacroCall { span: Span }, + #[error("Macros must be comptime functions")] + MacroIsNotComptime { span: Span }, } impl ResolverError { @@ -319,7 +325,7 @@ impl<'a> From<&'a ResolverError> for Diagnostic { "Usage of the `#[foreign]` or `#[builtin]` function attributes are not allowed outside of the Noir standard library".into(), ident.span(), ), - ResolverError::OracleMarkedAsConstrained { ident } => Diagnostic::simple_error( + ResolverError::OracleMarkedAsConstrained { ident } => Diagnostic::simple_warning( error.to_string(), "Oracle functions must have the `unconstrained` keyword applied".into(), ident.span(), @@ -391,6 +397,27 @@ impl<'a> From<&'a ResolverError> for Diagnostic { diag } ResolverError::ArrayLengthInterpreter { error } => Diagnostic::from(error), + ResolverError::UnquoteUsedOutsideQuote { span } => { + Diagnostic::simple_error( + "The unquote operator '$' can only be used within a quote expression".into(), + "".into(), + *span, + ) + }, + ResolverError::InvalidSyntaxInMacroCall { span } => { + Diagnostic::simple_error( + "Invalid syntax in macro call".into(), + "Macro calls must call a comptime function directly, they cannot use higher-order functions".into(), + *span, + ) + }, + ResolverError::MacroIsNotComptime{ span } => { + Diagnostic::simple_error( + "This macro call is to a non-comptime function".into(), + "Macro calls must be to comptime functions".into(), + *span, + ) + }, } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 01f58ba4c27..4583125d2a2 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -17,7 +17,7 @@ use crate::hir_def::expr::{ HirArrayLiteral, HirBinaryOp, HirBlockExpression, HirCallExpression, HirCapturedVar, HirCastExpression, HirConstructorExpression, HirExpression, HirIdent, HirIfExpression, HirIndexExpression, HirInfixExpression, HirLambda, HirLiteral, HirMemberAccess, - HirMethodCallExpression, HirPrefixExpression, ImplKind, + HirMethodCallExpression, HirPrefixExpression, HirQuoted, ImplKind, }; use crate::hir_def::function::FunctionBody; @@ -569,7 +569,7 @@ impl<'a> Resolver<'a> { let fields = self.resolve_type_inner(*fields); Type::FmtString(Box::new(resolved_size), Box::new(fields)) } - Code => Type::Code, + Expr => Type::Expr, Unit => Type::Unit, Unspecified => Type::Error, Error => Type::Error, @@ -1158,7 +1158,7 @@ impl<'a> Resolver<'a> { | Type::TypeVariable(_, _) | Type::Constant(_) | Type::NamedGeneric(_, _) - | Type::Code + | Type::Expr | Type::Forall(_, _) => (), Type::TraitAsType(_, _, args) => { @@ -1641,13 +1641,23 @@ impl<'a> Resolver<'a> { ExpressionKind::Parenthesized(sub_expr) => return self.resolve_expression(*sub_expr), // The quoted expression isn't resolved since we don't want errors if variables aren't defined - ExpressionKind::Quote(block) => HirExpression::Quote(block), + ExpressionKind::Quote(block, _) => { + let quoted = HirQuoted { quoted_block: block, unquoted_exprs: Vec::new() }; + HirExpression::Quote(quoted) + } ExpressionKind::Comptime(block, _) => { HirExpression::Comptime(self.resolve_block(block)) } ExpressionKind::Resolved(_) => unreachable!( "ExpressionKind::Resolved should only be emitted by the comptime interpreter" ), + ExpressionKind::Unquote(_) => { + self.push_err(ResolverError::UnquoteUsedOutsideQuote { span: expr.span }); + HirExpression::Literal(HirLiteral::Unit) + } + ExpressionKind::UnquoteMarker(index) => { + unreachable!("UnquoteMarker({index}) remaining in runtime code") + } }; // If these lines are ever changed, make sure to change the early return diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs index 3d355fd4447..4c360731711 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs @@ -300,6 +300,7 @@ fn collect_trait_impl( let file = def_maps[&crate_id].file_id(trait_impl.module_id); let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file); resolver.add_generics(&trait_impl.generics); + let typ = resolver.resolve_type(unresolved_type); errors.extend(take_errors(trait_impl.file_id, resolver)); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs index 0d8a9f3e717..bd32ba2fce5 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -143,6 +143,8 @@ pub enum TypeCheckError { }, #[error("Strings do not support indexed assignment")] StringIndexAssign { span: Span }, + #[error("Macro calls may only return Expr values")] + MacroReturningNonExpr { typ: Type, span: Span }, } impl TypeCheckError { @@ -335,6 +337,11 @@ impl<'a> From<&'a TypeCheckError> for Diagnostic { let msg = format!("Expected {expected_count} generic{expected_plural} from this function, but {actual_count} {actual_plural} provided"); Diagnostic::simple_error(msg, "".into(), *span) }, + TypeCheckError::MacroReturningNonExpr { typ, span } => Diagnostic::simple_error( + format!("Expected macro call to return an `Expr` but found a(n) {typ}"), + "Macro calls must return quoted expressions, otherwise there is no code to insert".into(), + *span, + ), } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs index 50af9dbf34e..503bbbf79be 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -307,7 +307,7 @@ impl<'interner> TypeChecker<'interner> { Type::Function(params, Box::new(lambda.return_type), Box::new(env_type)) } - HirExpression::Quote(_) => Type::Code, + HirExpression::Quote(_) => Type::Expr, HirExpression::Comptime(block) => self.check_block(block), // Unquote should be inserted & removed by the comptime interpreter. diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs index 163ea10ee02..9547aef866b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs @@ -33,7 +33,7 @@ pub enum HirExpression { If(HirIfExpression), Tuple(Vec), Lambda(HirLambda), - Quote(crate::ast::BlockExpression), + Quote(HirQuoted), Unquote(crate::ast::BlockExpression), Comptime(HirBlockExpression), Error, @@ -291,3 +291,13 @@ pub struct HirLambda { pub body: ExprId, pub captures: Vec, } + +#[derive(Debug, Clone)] +pub struct HirQuoted { + pub quoted_block: crate::ast::BlockExpression, + + /// Each expression here corresponds to a `ExpressionKind::UnquoteMarker(index)` in `quoted_block`. + /// The values of these expressions after evaluation will be inlined into the position + /// indicated by their corresponding UnquoteMarker with that index. + pub unquoted_exprs: Vec, +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs index 1357ea09f94..a90bd931496 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs @@ -105,7 +105,7 @@ pub enum Type { Constant(u32), /// The type of quoted code in macros. This is always a comptime-only type - Code, + Expr, /// The result of some type error. Remembering type errors as their own type variant lets /// us avoid issuing repeat type errors for the same item. For example, a lambda with @@ -147,7 +147,7 @@ impl Type { | Type::MutableReference(_) | Type::Forall(_, _) | Type::Constant(_) - | Type::Code + | Type::Expr | Type::Slice(_) | Type::Error => unreachable!("This type cannot exist as a parameter to main"), } @@ -644,7 +644,7 @@ impl Type { | Type::Constant(_) | Type::NamedGeneric(_, _) | Type::Forall(_, _) - | Type::Code => false, + | Type::Expr => false, Type::TraitAsType(_, _, args) => { args.iter().any(|generic| generic.contains_numeric_typevar(target_id)) @@ -710,7 +710,7 @@ impl Type { | Type::Function(_, _, _) | Type::MutableReference(_) | Type::Forall(_, _) - | Type::Code + | Type::Expr | Type::Slice(_) | Type::TraitAsType(..) => false, @@ -759,7 +759,7 @@ impl Type { | Type::MutableReference(_) | Type::Forall(_, _) // TODO: probably can allow code as it is all compile time - | Type::Code + | Type::Expr | Type::TraitAsType(..) => false, Type::Alias(alias, generics) => { @@ -922,7 +922,7 @@ impl std::fmt::Display for Type { Type::MutableReference(element) => { write!(f, "&mut {element}") } - Type::Code => write!(f, "Code"), + Type::Expr => write!(f, "Expr"), } } } @@ -1643,7 +1643,7 @@ impl Type { | Type::Bool | Type::Constant(_) | Type::Error - | Type::Code + | Type::Expr | Type::Unit => self.clone(), } } @@ -1686,7 +1686,7 @@ impl Type { | Type::Bool | Type::Constant(_) | Type::Error - | Type::Code + | Type::Expr | Type::Unit => false, } } @@ -1743,7 +1743,7 @@ impl Type { // Expect that this function should only be called on instantiated types Forall(..) => unreachable!(), - FieldElement | Integer(_, _) | Bool | Constant(_) | Unit | Code | Error => self.clone(), + FieldElement | Integer(_, _) | Bool | Constant(_) | Unit | Expr | Error => self.clone(), } } @@ -1878,7 +1878,7 @@ impl From<&Type> for PrintableType { Type::MutableReference(typ) => { PrintableType::MutableReference { typ: Box::new(typ.as_ref().into()) } } - Type::Code => unreachable!(), + Type::Expr => unreachable!(), } } } @@ -1963,7 +1963,7 @@ impl std::fmt::Debug for Type { Type::MutableReference(element) => { write!(f, "&mut {element:?}") } - Type::Code => write!(f, "Code"), + Type::Expr => write!(f, "Expr"), } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs b/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs index 2d1ebf530e3..3d052e22e36 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs @@ -141,6 +141,7 @@ impl<'a> Lexer<'a> { Some('}') => self.single_char_token(Token::RightBrace), Some('[') => self.single_char_token(Token::LeftBracket), Some(']') => self.single_char_token(Token::RightBracket), + Some('$') => self.single_char_token(Token::DollarSign), Some('"') => self.eat_string_literal(), Some('f') => self.eat_format_string_or_alpha_numeric(), Some('r') => self.eat_raw_string_or_alpha_numeric(), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs index d8555b4fbf7..d204191796c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs @@ -85,6 +85,8 @@ pub enum BorrowedToken<'input> { Semicolon, /// ! Bang, + /// $ + DollarSign, /// = Assign, #[allow(clippy::upper_case_acronyms)] @@ -179,6 +181,8 @@ pub enum Token { Bang, /// = Assign, + /// $ + DollarSign, #[allow(clippy::upper_case_acronyms)] EOF, @@ -238,6 +242,7 @@ pub fn token_to_borrowed_token(token: &Token) -> BorrowedToken<'_> { Token::Semicolon => BorrowedToken::Semicolon, Token::Assign => BorrowedToken::Assign, Token::Bang => BorrowedToken::Bang, + Token::DollarSign => BorrowedToken::DollarSign, Token::EOF => BorrowedToken::EOF, Token::Invalid(c) => BorrowedToken::Invalid(*c), Token::Whitespace(ref s) => BorrowedToken::Whitespace(s), @@ -349,6 +354,7 @@ impl fmt::Display for Token { Token::Semicolon => write!(f, ";"), Token::Assign => write!(f, "="), Token::Bang => write!(f, "!"), + Token::DollarSign => write!(f, "$"), Token::EOF => write!(f, "end of input"), Token::Invalid(c) => write!(f, "{c}"), Token::Whitespace(ref s) => write!(f, "{s}"), @@ -454,7 +460,7 @@ impl fmt::Display for IntType { impl IntType { // XXX: Result - // Is not the best API. We could split this into two functions. One that checks if the the + // Is not the best API. We could split this into two functions. One that checks if the // word is a integer, which only returns an Option pub(crate) fn lookup_int_type(word: &str) -> Result, LexerErrorKind> { // Check if the first string is a 'u' or 'i' @@ -840,6 +846,7 @@ pub enum Keyword { Crate, Dep, Else, + Expr, Field, Fn, For, @@ -884,6 +891,7 @@ impl fmt::Display for Keyword { Keyword::Crate => write!(f, "crate"), Keyword::Dep => write!(f, "dep"), Keyword::Else => write!(f, "else"), + Keyword::Expr => write!(f, "Expr"), Keyword::Field => write!(f, "Field"), Keyword::Fn => write!(f, "fn"), Keyword::For => write!(f, "for"), @@ -931,6 +939,7 @@ impl Keyword { "crate" => Keyword::Crate, "dep" => Keyword::Dep, "else" => Keyword::Else, + "Expr" => Keyword::Expr, "Field" => Keyword::Field, "fn" => Keyword::Fn, "for" => Keyword::For, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs index 7ecea5c9eac..c6cc1344aae 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -1012,7 +1012,7 @@ impl<'interner> Monomorphizer<'interner> { HirType::Forall(_, _) | HirType::Constant(_) | HirType::Error => { unreachable!("Unexpected type {} found", typ) } - HirType::Code => unreachable!("Tried to translate Code type into runtime code"), + HirType::Expr => unreachable!("Tried to translate Code type into runtime code"), }) } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs index cef49332b00..5fdce80087a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs @@ -1411,6 +1411,13 @@ impl NodeInterner { ) -> Result<(), (Span, FileId)> { self.trait_implementations.insert(impl_id, trait_impl.clone()); + // Avoid adding error types to impls since they'll conflict with every other type. + // We don't need to return an error since we expect an error to already be issued when + // the error type is created. + if object_type == Type::Error { + return Ok(()); + } + // Replace each generic with a fresh type variable let substitutions = impl_generics .into_iter() @@ -1466,6 +1473,7 @@ impl NodeInterner { force_type_check: bool, ) -> Option { let methods = self.struct_methods.get(&(id, method_name.to_owned())); + // If there is only one method, just return it immediately. // It will still be typechecked later. if !force_type_check { @@ -1817,7 +1825,7 @@ fn get_type_method_key(typ: &Type) -> Option { Type::Tuple(_) => Some(Tuple), Type::Function(_, _, _) => Some(Function), Type::NamedGeneric(_, _) => Some(Generic), - Type::Code => Some(Code), + Type::Expr => Some(Code), Type::MutableReference(element) => get_type_method_key(element), Type::Alias(alias, _) => get_type_method_key(&alias.borrow().typ), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs index cabc788e07d..0d8215f2ea4 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs @@ -24,6 +24,7 @@ //! be limited to cases like the above `fn` example where it is clear we shouldn't back out of the //! current parser to try alternative parsers in a `choice` expression. use self::primitives::{keyword, mutable_reference, variable}; +use self::types::{generic_type_args, maybe_comp_time, parse_type}; use super::{ foldl_with_span, labels::ParsingRuleLabel, parameter_name_recovery, parameter_recovery, @@ -35,8 +36,8 @@ use super::{spanned, Item, ItemKind}; use crate::ast::{ BinaryOp, BinaryOpKind, BlockExpression, ForLoopStatement, ForRange, Ident, IfExpression, InfixExpression, LValue, Literal, ModuleDeclaration, NoirTypeAlias, Param, Path, Pattern, - Recoverable, Statement, TraitBound, TypeImpl, UnaryRhsMemberAccess, UnresolvedTraitConstraint, - UnresolvedTypeExpression, UseTree, UseTreeKind, Visibility, + Recoverable, Statement, TraitBound, TypeImpl, UnaryRhsMemberAccess, UnaryRhsMethodCall, + UnresolvedTraitConstraint, UseTree, UseTreeKind, Visibility, }; use crate::ast::{ Expression, ExpressionKind, LetStatement, StatementKind, UnresolvedType, UnresolvedTypeData, @@ -59,6 +60,7 @@ mod path; mod primitives; mod structs; mod traits; +mod types; // synthesized by LALRPOP lalrpop_mod!(pub noir_parser); @@ -674,41 +676,6 @@ where }) } -fn parse_type<'a>() -> impl NoirParser + 'a { - recursive(parse_type_inner) -} - -fn parse_type_inner<'a>( - recursive_type_parser: impl NoirParser + 'a, -) -> impl NoirParser + 'a { - choice(( - field_type(), - int_type(), - bool_type(), - string_type(), - format_string_type(recursive_type_parser.clone()), - named_type(recursive_type_parser.clone()), - named_trait(recursive_type_parser.clone()), - slice_type(recursive_type_parser.clone()), - array_type(recursive_type_parser.clone()), - parenthesized_type(recursive_type_parser.clone()), - tuple_type(recursive_type_parser.clone()), - function_type(recursive_type_parser.clone()), - mutable_reference_type(recursive_type_parser), - )) -} - -fn parenthesized_type( - recursive_type_parser: impl NoirParser, -) -> impl NoirParser { - recursive_type_parser - .delimited_by(just(Token::LeftParen), just(Token::RightParen)) - .map_with_span(|typ, span| UnresolvedType { - typ: UnresolvedTypeData::Parenthesized(Box::new(typ)), - span: span.into(), - }) -} - fn optional_visibility() -> impl NoirParser { keyword(Keyword::Pub) .or(keyword(Keyword::CallData)) @@ -724,187 +691,6 @@ fn optional_visibility() -> impl NoirParser { }) } -fn maybe_comp_time() -> impl NoirParser { - keyword(Keyword::Comptime).or_not().validate(|opt, span, emit| { - if opt.is_some() { - emit(ParserError::with_reason( - ParserErrorReason::ExperimentalFeature("Comptime values"), - span, - )); - } - opt.is_some() - }) -} - -fn field_type() -> impl NoirParser { - keyword(Keyword::Field) - .map_with_span(|_, span| UnresolvedTypeData::FieldElement.with_span(span)) -} - -fn bool_type() -> impl NoirParser { - keyword(Keyword::Bool).map_with_span(|_, span| UnresolvedTypeData::Bool.with_span(span)) -} - -fn string_type() -> impl NoirParser { - keyword(Keyword::String) - .ignore_then(type_expression().delimited_by(just(Token::Less), just(Token::Greater))) - .map_with_span(|expr, span| UnresolvedTypeData::String(expr).with_span(span)) -} - -fn format_string_type<'a>( - type_parser: impl NoirParser + 'a, -) -> impl NoirParser + 'a { - keyword(Keyword::FormatString) - .ignore_then( - type_expression() - .then_ignore(just(Token::Comma)) - .then(type_parser) - .delimited_by(just(Token::Less), just(Token::Greater)), - ) - .map_with_span(|(size, fields), span| { - UnresolvedTypeData::FormatString(size, Box::new(fields)).with_span(span) - }) -} - -fn int_type() -> impl NoirParser { - filter_map(|span, token: Token| match token { - Token::IntType(int_type) => Ok(int_type), - unexpected => { - Err(ParserError::expected_label(ParsingRuleLabel::IntegerType, unexpected, span)) - } - }) - .validate(|token, span, emit| { - UnresolvedTypeData::from_int_token(token).map(|data| data.with_span(span)).unwrap_or_else( - |err| { - emit(ParserError::with_reason(ParserErrorReason::InvalidBitSize(err.0), span)); - UnresolvedType::error(span) - }, - ) - }) -} - -fn named_type<'a>( - type_parser: impl NoirParser + 'a, -) -> impl NoirParser + 'a { - path().then(generic_type_args(type_parser)).map_with_span(|(path, args), span| { - UnresolvedTypeData::Named(path, args, false).with_span(span) - }) -} - -fn named_trait<'a>( - type_parser: impl NoirParser + 'a, -) -> impl NoirParser + 'a { - keyword(Keyword::Impl).ignore_then(path()).then(generic_type_args(type_parser)).map_with_span( - |(path, args), span| UnresolvedTypeData::TraitAsType(path, args).with_span(span), - ) -} - -fn generic_type_args<'a>( - type_parser: impl NoirParser + 'a, -) -> impl NoirParser> + 'a { - type_parser - .clone() - // Without checking for a terminating ',' or '>' here we may incorrectly - // parse a generic `N * 2` as just the type `N` then fail when there is no - // separator afterward. Failing early here ensures we try the `type_expression` - // parser afterward. - .then_ignore(one_of([Token::Comma, Token::Greater]).rewind()) - .or(type_expression() - .map_with_span(|expr, span| UnresolvedTypeData::Expression(expr).with_span(span))) - .separated_by(just(Token::Comma)) - .allow_trailing() - .at_least(1) - .delimited_by(just(Token::Less), just(Token::Greater)) - .or_not() - .map(Option::unwrap_or_default) -} - -fn array_type<'a>( - type_parser: impl NoirParser + 'a, -) -> impl NoirParser + 'a { - just(Token::LeftBracket) - .ignore_then(type_parser) - .then(just(Token::Semicolon).ignore_then(type_expression())) - .then_ignore(just(Token::RightBracket)) - .map_with_span(|(element_type, size), span| { - UnresolvedTypeData::Array(size, Box::new(element_type)).with_span(span) - }) -} - -fn slice_type(type_parser: impl NoirParser) -> impl NoirParser { - just(Token::LeftBracket) - .ignore_then(type_parser) - .then_ignore(just(Token::RightBracket)) - .map_with_span(|element_type, span| { - UnresolvedTypeData::Slice(Box::new(element_type)).with_span(span) - }) -} - -fn type_expression() -> impl NoirParser { - recursive(|expr| { - expression_with_precedence( - Precedence::lowest_type_precedence(), - expr, - nothing(), - nothing(), - true, - false, - ) - }) - .labelled(ParsingRuleLabel::TypeExpression) - .try_map(UnresolvedTypeExpression::from_expr) -} - -fn tuple_type(type_parser: T) -> impl NoirParser -where - T: NoirParser, -{ - let fields = type_parser.separated_by(just(Token::Comma)).allow_trailing(); - parenthesized(fields).map_with_span(|fields, span| { - if fields.is_empty() { - UnresolvedTypeData::Unit.with_span(span) - } else { - UnresolvedTypeData::Tuple(fields).with_span(span) - } - }) -} - -fn function_type(type_parser: T) -> impl NoirParser -where - T: NoirParser, -{ - let args = parenthesized(type_parser.clone().separated_by(just(Token::Comma)).allow_trailing()); - - let env = just(Token::LeftBracket) - .ignore_then(type_parser.clone()) - .then_ignore(just(Token::RightBracket)) - .or_not() - .map_with_span(|t, span| { - t.unwrap_or_else(|| UnresolvedTypeData::Unit.with_span(Span::empty(span.end()))) - }); - - keyword(Keyword::Fn) - .ignore_then(env) - .then(args) - .then_ignore(just(Token::Arrow)) - .then(type_parser) - .map_with_span(|((env, args), ret), span| { - UnresolvedTypeData::Function(args, Box::new(ret), Box::new(env)).with_span(span) - }) -} - -fn mutable_reference_type(type_parser: T) -> impl NoirParser -where - T: NoirParser, -{ - just(Token::Ampersand) - .ignore_then(keyword(Keyword::Mut)) - .ignore_then(type_parser) - .map_with_span(|element, span| { - UnresolvedTypeData::MutableReference(Box::new(element)).with_span(span) - }) -} - fn expression() -> impl ExprParser { recursive(|expr| { expression_with_precedence( @@ -1073,14 +859,18 @@ where S: NoirParser + 'a, { enum UnaryRhs { - Call(Vec), + Call((Option, Vec)), ArrayIndex(Expression), Cast(UnresolvedType), MemberAccess(UnaryRhsMemberAccess), } // `(arg1, ..., argN)` in `my_func(arg1, ..., argN)` - let call_rhs = parenthesized(expression_list(expr_parser.clone())).map(UnaryRhs::Call); + // Optionally accepts a leading `!` for macro calls. + let call_rhs = just(Token::Bang) + .or_not() + .then(parenthesized(expression_list(expr_parser.clone()))) + .map(UnaryRhs::Call); // `[expr]` in `arr[expr]` let array_rhs = expr_parser @@ -1097,11 +887,23 @@ where // A turbofish operator is optional in a method call to specify generic types let turbofish = primitives::turbofish(type_parser); + // `::!(arg1, .., argN)` with the turbofish and macro portions being optional. + let method_call_rhs = turbofish + .then(just(Token::Bang).or_not()) + .then(parenthesized(expression_list(expr_parser.clone()))) + .map(|((turbofish, macro_call), args)| UnaryRhsMethodCall { + turbofish, + macro_call: macro_call.is_some(), + args, + }); + // `.foo` or `.foo(args)` in `atom.foo` or `atom.foo(args)` let member_rhs = just(Token::Dot) .ignore_then(field_name()) - .then(turbofish.then(parenthesized(expression_list(expr_parser.clone()))).or_not()) - .map(UnaryRhs::MemberAccess) + .then(method_call_rhs.or_not()) + .map(|(method_or_field, method_call)| { + UnaryRhs::MemberAccess(UnaryRhsMemberAccess { method_or_field, method_call }) + }) .labelled(ParsingRuleLabel::FieldAccess); let rhs = choice((call_rhs, array_rhs, cast_rhs, member_rhs)); @@ -1110,7 +912,9 @@ where atom(expr_parser, expr_no_constructors, statement, allow_constructors), rhs, |lhs, rhs, span| match rhs { - UnaryRhs::Call(args) => Expression::call(lhs, args, span), + UnaryRhs::Call((is_macro, args)) => { + Expression::call(lhs, is_macro.is_some(), args, span) + } UnaryRhs::ArrayIndex(index) => Expression::index(lhs, index, span), UnaryRhs::Cast(r#type) => Expression::cast(lhs, r#type, span), UnaryRhs::MemberAccess(field) => { @@ -1272,6 +1076,7 @@ where block(statement.clone()).map(ExpressionKind::Block), comptime_expr(statement.clone()), quote(statement), + unquote(expr_parser.clone()), variable(), literal(), )) @@ -1300,13 +1105,25 @@ fn quote<'a, P>(statement: P) -> impl NoirParser + 'a where P: NoirParser + 'a, { - keyword(Keyword::Quote).ignore_then(block(statement)).validate(|block, span, emit| { - emit(ParserError::with_reason( - ParserErrorReason::ExperimentalFeature("quoted expressions"), - span, - )); - ExpressionKind::Quote(block) - }) + keyword(Keyword::Quote).ignore_then(spanned(block(statement))).validate( + |(block, block_span), span, emit| { + emit(ParserError::with_reason( + ParserErrorReason::ExperimentalFeature("quoted expressions"), + span, + )); + ExpressionKind::Quote(block, block_span) + }, + ) +} + +/// unquote: '$' variable +/// | '$' '(' expression ')' +fn unquote<'a, P>(expr_parser: P) -> impl NoirParser + 'a +where + P: ExprParser + 'a, +{ + let unquote = variable().map_with_span(Expression::new).or(parenthesized(expr_parser)); + just(Token::DollarSign).ignore_then(unquote).map(|expr| ExpressionKind::Unquote(Box::new(expr))) } fn tuple

(expr_parser: P) -> impl NoirParser @@ -1452,11 +1269,6 @@ mod test { ); } - #[test] - fn parse_type_expression() { - parse_all(type_expression(), vec!["(123)", "123", "(1 + 1)", "(1 + (1))"]); - } - #[test] fn parse_array_sugar() { let valid = vec!["[0;7]", "[(1, 2); 4]", "[0;Four]", "[2;1+3-a]"]; @@ -1735,27 +1547,19 @@ mod test { Case { source: "let = 4 + 3", expect: "let $error: unspecified = (4 + 3)", errors: 1 }, Case { source: "let = ", expect: "let $error: unspecified = Error", errors: 2 }, Case { source: "let", expect: "let $error: unspecified = Error", errors: 3 }, - Case { source: "foo = one two three", expect: "foo = plain::one", errors: 1 }, + Case { source: "foo = one two three", expect: "foo = one", errors: 1 }, Case { source: "constrain", expect: "constrain Error", errors: 2 }, Case { source: "assert", expect: "constrain Error", errors: 1 }, - Case { source: "constrain x ==", expect: "constrain (plain::x == Error)", errors: 2 }, - Case { source: "assert(x ==)", expect: "constrain (plain::x == Error)", errors: 1 }, - Case { - source: "assert(x == x, x)", - expect: "constrain (plain::x == plain::x)", - errors: 0, - }, + Case { source: "constrain x ==", expect: "constrain (x == Error)", errors: 2 }, + Case { source: "assert(x ==)", expect: "constrain (x == Error)", errors: 1 }, + Case { source: "assert(x == x, x)", expect: "constrain (x == x)", errors: 0 }, Case { source: "assert_eq(x,)", expect: "constrain (Error == Error)", errors: 1 }, Case { source: "assert_eq(x, x, x, x)", expect: "constrain (Error == Error)", errors: 1, }, - Case { - source: "assert_eq(x, x, x)", - expect: "constrain (plain::x == plain::x)", - errors: 0, - }, + Case { source: "assert_eq(x, x, x)", expect: "constrain (x == x)", errors: 0 }, ]; check_cases_with_errors(&cases[..], fresh_statement()); @@ -1797,7 +1601,7 @@ mod test { source: "{ if structure { a: 1 } {} }", expect: concat!( "{\n", - " if plain::structure {\n", + " if structure {\n", " Error\n", " }\n", " {\n", @@ -1808,22 +1612,17 @@ mod test { }, Case { source: "{ if ( structure { a: 1 } ) {} }", - expect: concat!("{\n", " if ((plain::structure { a: 1 })) {\n", " }\n", "}",), + expect: concat!("{\n", " if ((structure { a: 1 })) {\n", " }\n", "}",), errors: 0, }, Case { source: "{ if ( structure {} ) {} }", - expect: concat!("{\n", " if ((plain::structure { })) {\n", " }\n", "}"), + expect: concat!("{\n", " if ((structure { })) {\n", " }\n", "}"), errors: 0, }, Case { source: "{ if (a { x: 1 }, b { y: 2 }) {} }", - expect: concat!( - "{\n", - " if ((plain::a { x: 1 }), (plain::b { y: 2 })) {\n", - " }\n", - "}", - ), + expect: concat!("{\n", " if ((a { x: 1 }), (b { y: 2 })) {\n", " }\n", "}",), errors: 0, }, Case { @@ -1831,8 +1630,8 @@ mod test { expect: concat!( "{\n", " if ({\n", - " let foo: unspecified = (plain::bar { baz: 42 })\n", - " (plain::foo == (plain::bar { baz: 42 }))\n", + " let foo: unspecified = (bar { baz: 42 })\n", + " (foo == (bar { baz: 42 }))\n", " }) {\n", " }\n", "}", diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/literals.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/literals.rs index 584224fda46..b25b6acc9e2 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/literals.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/literals.rs @@ -108,18 +108,18 @@ mod test { #[allow(clippy::needless_raw_string_hashes)] Case { source: r####"r###""###"####, expect: r####"r###""###"####, errors: 0 }, // miscellaneous - Case { source: r##" r#\"foo\"# "##, expect: "plain::r", errors: 2 }, - Case { source: r#" r\"foo\" "#, expect: "plain::r", errors: 1 }, + Case { source: r##" r#\"foo\"# "##, expect: "r", errors: 2 }, + Case { source: r#" r\"foo\" "#, expect: "r", errors: 1 }, Case { source: r##" r##"foo"# "##, expect: "(none)", errors: 2 }, // missing 'r' letter Case { source: r##" ##"foo"# "##, expect: r#""foo""#, errors: 2 }, - Case { source: r#" #"foo" "#, expect: "plain::foo", errors: 2 }, + Case { source: r#" #"foo" "#, expect: "foo", errors: 2 }, // whitespace - Case { source: r##" r #"foo"# "##, expect: "plain::r", errors: 2 }, - Case { source: r##" r# "foo"# "##, expect: "plain::r", errors: 3 }, + Case { source: r##" r #"foo"# "##, expect: "r", errors: 2 }, + Case { source: r##" r# "foo"# "##, expect: "r", errors: 3 }, Case { source: r#" r#"foo" # "#, expect: "(none)", errors: 2 }, // after identifier - Case { source: r##" bar#"foo"# "##, expect: "plain::bar", errors: 2 }, + Case { source: r##" bar#"foo"# "##, expect: "bar", errors: 2 }, // nested Case { source: r###"r##"foo r#"bar"# r"baz" ### bye"##"###, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/types.rs index 82dd3dad681..40edc9936d1 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/types.rs @@ -1,22 +1,38 @@ use super::{ - expression_with_precedence, keyword, nothing, parenthesized, NoirParser, ParserError, + expression_with_precedence, keyword, nothing, parenthesized, path, NoirParser, ParserError, ParserErrorReason, Precedence, }; -use crate::ast::{UnresolvedType, UnresolvedTypeData}; +use crate::ast::{Recoverable, UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression}; use crate::parser::labels::ParsingRuleLabel; use crate::token::{Keyword, Token}; -use crate::{Recoverable, UnresolvedTypeExpression}; use chumsky::prelude::*; use noirc_errors::Span; -fn maybe_comp_time() -> impl NoirParser<()> { - keyword(Keyword::Comptime).or_not().validate(|opt, span, emit| { - if opt.is_some() { - emit(ParserError::with_reason(ParserErrorReason::ComptimeDeprecated, span)); - } - }) +pub(super) fn parse_type<'a>() -> impl NoirParser + 'a { + recursive(parse_type_inner) +} + +pub(super) fn parse_type_inner<'a>( + recursive_type_parser: impl NoirParser + 'a, +) -> impl NoirParser + 'a { + choice(( + field_type(), + int_type(), + bool_type(), + string_type(), + expr_type(), + format_string_type(recursive_type_parser.clone()), + named_type(recursive_type_parser.clone()), + named_trait(recursive_type_parser.clone()), + slice_type(recursive_type_parser.clone()), + array_type(recursive_type_parser.clone()), + parenthesized_type(recursive_type_parser.clone()), + tuple_type(recursive_type_parser.clone()), + function_type(recursive_type_parser.clone()), + mutable_reference_type(recursive_type_parser), + )) } pub(super) fn parenthesized_type( @@ -30,29 +46,41 @@ pub(super) fn parenthesized_type( }) } +pub(super) fn maybe_comp_time() -> impl NoirParser { + keyword(Keyword::Comptime).or_not().validate(|opt, span, emit| { + if opt.is_some() { + emit(ParserError::with_reason( + ParserErrorReason::ExperimentalFeature("Comptime values"), + span, + )); + } + opt.is_some() + }) +} + pub(super) fn field_type() -> impl NoirParser { - maybe_comp_time() - .then_ignore(keyword(Keyword::Field)) + keyword(Keyword::Field) .map_with_span(|_, span| UnresolvedTypeData::FieldElement.with_span(span)) } pub(super) fn bool_type() -> impl NoirParser { - maybe_comp_time() - .then_ignore(keyword(Keyword::Bool)) - .map_with_span(|_, span| UnresolvedTypeData::Bool.with_span(span)) + keyword(Keyword::Bool).map_with_span(|_, span| UnresolvedTypeData::Bool.with_span(span)) +} + +/// This is the type `Expr` - the type of a quoted, untyped expression object used for macros +pub(super) fn expr_type() -> impl NoirParser { + keyword(Keyword::Expr).map_with_span(|_, span| UnresolvedTypeData::Expr.with_span(span)) } pub(super) fn string_type() -> impl NoirParser { keyword(Keyword::String) - .ignore_then( - type_expression().delimited_by(just(Token::Less), just(Token::Greater)).or_not(), - ) + .ignore_then(type_expression().delimited_by(just(Token::Less), just(Token::Greater))) .map_with_span(|expr, span| UnresolvedTypeData::String(expr).with_span(span)) } -pub(super) fn format_string_type( - type_parser: impl NoirParser, -) -> impl NoirParser { +pub(super) fn format_string_type<'a>( + type_parser: impl NoirParser + 'a, +) -> impl NoirParser + 'a { keyword(Keyword::FormatString) .ignore_then( type_expression() @@ -66,26 +94,61 @@ pub(super) fn format_string_type( } pub(super) fn int_type() -> impl NoirParser { - maybe_comp_time() - .then(filter_map(|span, token: Token| match token { - Token::IntType(int_type) => Ok(int_type), - unexpected => { - Err(ParserError::expected_label(ParsingRuleLabel::IntegerType, unexpected, span)) - } - })) - .validate(|(_, token), span, emit| { - UnresolvedTypeData::from_int_token(token) - .map(|data| data.with_span(span)) - .unwrap_or_else(|err| { - emit(ParserError::with_reason(ParserErrorReason::InvalidBitSize(err.0), span)); - UnresolvedType::error(span) - }) - }) + filter_map(|span, token: Token| match token { + Token::IntType(int_type) => Ok(int_type), + unexpected => { + Err(ParserError::expected_label(ParsingRuleLabel::IntegerType, unexpected, span)) + } + }) + .validate(|token, span, emit| { + UnresolvedTypeData::from_int_token(token).map(|data| data.with_span(span)).unwrap_or_else( + |err| { + emit(ParserError::with_reason(ParserErrorReason::InvalidBitSize(err.0), span)); + UnresolvedType::error(span) + }, + ) + }) } -pub(super) fn array_type( - type_parser: impl NoirParser, -) -> impl NoirParser { +pub(super) fn named_type<'a>( + type_parser: impl NoirParser + 'a, +) -> impl NoirParser + 'a { + path().then(generic_type_args(type_parser)).map_with_span(|(path, args), span| { + UnresolvedTypeData::Named(path, args, false).with_span(span) + }) +} + +pub(super) fn named_trait<'a>( + type_parser: impl NoirParser + 'a, +) -> impl NoirParser + 'a { + keyword(Keyword::Impl).ignore_then(path()).then(generic_type_args(type_parser)).map_with_span( + |(path, args), span| UnresolvedTypeData::TraitAsType(path, args).with_span(span), + ) +} + +pub(super) fn generic_type_args<'a>( + type_parser: impl NoirParser + 'a, +) -> impl NoirParser> + 'a { + type_parser + .clone() + // Without checking for a terminating ',' or '>' here we may incorrectly + // parse a generic `N * 2` as just the type `N` then fail when there is no + // separator afterward. Failing early here ensures we try the `type_expression` + // parser afterward. + .then_ignore(one_of([Token::Comma, Token::Greater]).rewind()) + .or(type_expression() + .map_with_span(|expr, span| UnresolvedTypeData::Expression(expr).with_span(span))) + .separated_by(just(Token::Comma)) + .allow_trailing() + .at_least(1) + .delimited_by(just(Token::Less), just(Token::Greater)) + .or_not() + .map(Option::unwrap_or_default) +} + +pub(super) fn array_type<'a>( + type_parser: impl NoirParser + 'a, +) -> impl NoirParser + 'a { just(Token::LeftBracket) .ignore_then(type_parser) .then(just(Token::Semicolon).ignore_then(type_expression())) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs index 99215c8f173..1acf1fbf3f2 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs @@ -619,7 +619,7 @@ fn check_impl_struct_not_trait() { CompilationError::DefinitionError(DefCollectorErrorKind::NotATrait { not_a_trait_name, }) => { - assert_eq!(not_a_trait_name.to_string(), "plain::Default"); + assert_eq!(not_a_trait_name.to_string(), "Default"); } _ => { panic!("No other errors are expected! Found = {:?}", err); diff --git a/noir/noir-repo/cspell.json b/noir/noir-repo/cspell.json index 9eb6e6f9239..2fb20ae2ba4 100644 --- a/noir/noir-repo/cspell.json +++ b/noir/noir-repo/cspell.json @@ -166,6 +166,7 @@ "rfind", "rustc", "rustup", + "sboxed", "schnorr", "sdiv", "secp256k1", diff --git a/noir/noir-repo/docs/docs/how_to/how-to-oracles.md b/noir/noir-repo/docs/docs/how_to/how-to-oracles.md index 62ead1f534f..2d2ed5c94b9 100644 --- a/noir/noir-repo/docs/docs/how_to/how-to-oracles.md +++ b/noir/noir-repo/docs/docs/how_to/how-to-oracles.md @@ -166,6 +166,10 @@ interface ForeignCallResult { } ``` +::: Multidimensional Arrays + +If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in json as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. + ::: ## Step 3 - Usage with Nargo diff --git a/noir/noir-repo/docs/docs/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/docs/noir/concepts/data_types/arrays.md index efce3e95d32..95d749053e2 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/docs/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = &[]; ``` diff --git a/noir/noir-repo/docs/docs/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/docs/noir/concepts/data_types/booleans.md index 3dcfa836814..2507af710e7 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/docs/noir/concepts/data_types/booleans.md @@ -24,5 +24,5 @@ fn main() { ``` The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/docs/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/docs/noir/concepts/data_types/strings.md index 311dfd64416..8ab5825a4c4 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/docs/noir/concepts/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/docs/noir/concepts/generics.md b/noir/noir-repo/docs/docs/noir/concepts/generics.md index ddd42bf1f9b..0c1c27a2221 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/generics.md +++ b/noir/noir-repo/docs/docs/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/docs/noir/concepts/unconstrained.md b/noir/noir-repo/docs/docs/noir/concepts/unconstrained.md index b8e71fe65f0..96f824c5e42 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/unconstrained.md +++ b/noir/noir-repo/docs/docs/noir/concepts/unconstrained.md @@ -96,4 +96,4 @@ Generally we want to use brillig whenever there's something that's easy to verif ## Break and Continue -In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/docs/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/docs/noir/modules_packages_crates/dependencies.md index 04c1703d929..2c028d85853 100644 --- a/noir/noir-repo/docs/docs/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/docs/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/docs/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/docs/noir/standard_library/black_box_fns.md index eeead580969..d5694250f05 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/docs/noir/standard_library/black_box_fns.md @@ -25,7 +25,7 @@ Here is a list of the current black box functions: - XOR - RANGE - [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/docs/noir/standard_library/containers/boundedvec.md b/noir/noir-repo/docs/docs/noir/standard_library/containers/boundedvec.md index ccce62562f8..98b7d584033 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/containers/boundedvec.md +++ b/noir/noir-repo/docs/docs/noir/standard_library/containers/boundedvec.md @@ -59,7 +59,7 @@ but for now make sure to use type annotations when using bounded vectors. Otherw ### get ```rust -pub fn get(mut self: Self, index: u64) -> T { +pub fn get(self, index: u64) -> T { ``` Retrieves an element from the vector at the given index, starting from zero. @@ -80,7 +80,7 @@ fn foo(v: BoundedVec) { ### get_unchecked ```rust -pub fn get_unchecked(mut self: Self, index: u64) -> T { +pub fn get_unchecked(self, index: u64) -> T { ``` Retrieves an element from the vector at the given index, starting from zero, without @@ -93,6 +93,42 @@ Example: #include_code get_unchecked_example test_programs/noir_test_success/bounded_vec/src/main.nr rust +### set + +```rust +pub fn set(&mut self: Self, index: u64, value: T) { +``` + +Writes an element to the vector at the given index, starting from zero. + +If the given index is equal to or greater than the length of the vector, this will issue a constraint failure. + +Example: + +```rust +fn foo(v: BoundedVec) { + let first = v.get(0); + assert(first != 42); + v.set(0, 42); + let new_first = v.get(0); + assert(new_first == 42); +} +``` + +### set_unchecked + +```rust +pub fn set_unchecked(&mut self: Self, index: u64, value: T) -> T { +``` + +Writes an element to the vector at the given index, starting from zero, without performing a bounds check. + +Since this function does not perform a bounds check on length before accessing the element, it is unsafe! Use at your own risk! + +Example: + +#include_code set_unchecked_example test_programs/noir_test_success/bounded_vec/src/main.nr rust + ### push @@ -210,6 +246,18 @@ Example: let bounded_vec: BoundedVec = BoundedVec::from_array([1, 2, 3]) ``` +### map + +```rust +pub fn map(self, f: fn[Env](T) -> U) -> BoundedVec +``` + +Creates a new vector of equal size by calling a closure on each element in this vector. + +Example: + +#include_code bounded-vec-map-example noir_stdlib/src/collections/bounded_vec.nr rust + ### any ```rust diff --git a/noir/noir-repo/docs/docs/noir/standard_library/containers/vec.mdx b/noir/noir-repo/docs/docs/noir/standard_library/containers/vec.mdx index fcfd7e07aa0..475011922f8 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/containers/vec.mdx +++ b/noir/noir-repo/docs/docs/noir/standard_library/containers/vec.mdx @@ -84,6 +84,25 @@ let vector: Vec = Vec::from_slice(&[10, 20, 30]); assert(vector.get(1) == 20); ``` +### set + +```rust +pub fn set(&mut self: Self, index: u64, value: T) { +``` + +Writes an element to the vector at the given index, starting from zero. + +Panics if the index points beyond the vector's end. + +Example: + +```rust +let vector: Vec = Vec::from_slice(&[10, 20, 30]); +assert(vector.get(1) == 20); +vector.set(1, 42); +assert(vector.get(1) == 42); +``` + ### push Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. diff --git a/noir/noir-repo/docs/docs/noir/standard_library/recursion.md b/noir/noir-repo/docs/docs/noir/standard_library/recursion.md index a93894043dc..cb3e7a9fcdf 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/docs/noir/standard_library/recursion.md @@ -4,6 +4,8 @@ description: Learn about how to write recursive proofs in Noir. keywords: [recursion, recursive proofs, verification_key, verify_proof] --- +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) @@ -33,11 +35,7 @@ By incorporating this attribute directly in the circuit's definition, tooling li pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} ``` -:::info - -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. - -::: + ## Example usage diff --git a/noir/noir-repo/docs/docs/tooling/debugger.md b/noir/noir-repo/docs/docs/tooling/debugger.md index 7c158d949d1..9b7565ba9ff 100644 --- a/noir/noir-repo/docs/docs/tooling/debugger.md +++ b/noir/noir-repo/docs/docs/tooling/debugger.md @@ -12,7 +12,7 @@ There are currently two ways of debugging Noir programs: 1. From VS Code, via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). 2. Via the REPL debugger, which ships with Nargo. -In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation) and vscode-noir: +In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation/index.md) and vscode-noir: - Noir & Nargo ≥0.28.0 - Noir's VS Code extension ≥0.0.11 diff --git a/noir/noir-repo/docs/docusaurus.config.ts b/noir/noir-repo/docs/docusaurus.config.ts index 29f612b0109..f0c986f1c28 100644 --- a/noir/noir-repo/docs/docusaurus.config.ts +++ b/noir/noir-repo/docs/docusaurus.config.ts @@ -14,6 +14,7 @@ export default { favicon: 'img/favicon.ico', url: 'https://noir-lang.org', baseUrl: '/', + trailingSlash: true, onBrokenLinks: 'throw', onBrokenMarkdownLinks: 'throw', i18n: { diff --git a/noir/noir-repo/docs/src/components/Notes/_blackbox.mdx b/noir/noir-repo/docs/src/components/Notes/_blackbox.mdx index 9fe9b48fbff..226017072c8 100644 --- a/noir/noir-repo/docs/src/components/Notes/_blackbox.mdx +++ b/noir/noir-repo/docs/src/components/Notes/_blackbox.mdx @@ -1,5 +1,5 @@ :::info -This is a black box function. Read [this section](../black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](../../black_box_fns) to learn more about black box functions in Noir. -::: \ No newline at end of file +::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/01_hello_world.md index d4daae605a2..34f8cd96fcd 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/01_hello_world.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/01_hello_world.md @@ -74,7 +74,7 @@ x : Field, y : pub Field Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. +[Data Types](../language_concepts/data_types.md) section. The next line of the program specifies its body: @@ -84,7 +84,7 @@ assert(x != y); The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments.md) chapter. ## Build In/Output Files diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md index e7b1f33b339..8616feee917 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md @@ -51,7 +51,7 @@ license = "MIT" ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} ``` -Nargo.toml for a [workspace](../modules_packages_crates/workspaces) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: ```toml [workspace] @@ -74,7 +74,7 @@ The package section requires a number of fields including: #### Dependencies section -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/index.md index 2d5e6f4454f..c88aabf0ac1 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/index.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands.md#nargo-codegen-verifier) command to create a verifier contract. ### Protocol Developers @@ -96,4 +96,4 @@ Some libraries that are available today include: - [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir - [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/02_booleans.md index 885db167d83..d353606210a 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/02_booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/02_booleans.md @@ -26,5 +26,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/03_strings.md index c42f34ec3ad..4360893e9a2 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/03_strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/03_strings.md @@ -16,7 +16,7 @@ keywords: The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging). +`std::println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/04_arrays.md index bdbd1798bef..1424ca2df14 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/04_arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/04_arrays.md @@ -56,7 +56,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md index e91e73a4c4f..87a09293ea8 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md @@ -81,14 +81,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/01_commands.md index 65e2bdb44e3..e2b0af522f4 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/01_commands.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/01_commands.md @@ -213,7 +213,7 @@ you run `nargo test`. To print `println` statements in tests, use the `--show-ou Takes an optional `--exact` flag which allows you to select tests based on an exact name. -See an example on the [testing page](./testing). +See an example on the [testing page](./testing.md). ### Options diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md index a412de19d06..b4dedefe4c9 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md @@ -26,19 +26,19 @@ fn sha256(_input : [u8; N]) -> [u8; 32] {} Here is a list of the current black box functions that are supported by UltraPlonk: - AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen](./cryptographic_primitives/hashes#pedersen) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Pedersen](./cryptographic_primitives/hashes.mdx#pedersen) +- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- [Compute merkle root](./merkle_trees.md#compute_merkle_root) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) +- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/recursion.md index ff4c63acaa7..5e592a2fd89 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/recursion.md @@ -15,7 +15,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/01_hello_world.md index d4daae605a2..34f8cd96fcd 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/01_hello_world.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/01_hello_world.md @@ -74,7 +74,7 @@ x : Field, y : pub Field Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. +[Data Types](../language_concepts/data_types.md) section. The next line of the program specifies its body: @@ -84,7 +84,7 @@ assert(x != y); The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments.md) chapter. ## Build In/Output Files diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md index d28a54a1600..f928370b2e8 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md @@ -51,7 +51,7 @@ license = "MIT" ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} ``` -Nargo.toml for a [workspace](../modules_packages_crates/workspaces) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: ```toml [workspace] @@ -74,7 +74,7 @@ The package section requires a number of fields including: #### Dependencies section -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/index.md index 380368db036..e8d86020a20 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/index.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier.md) command to create a verifier contract. ### Protocol Developers @@ -97,4 +97,4 @@ Some libraries that are available today include: - [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir - [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/02_booleans.md index 885db167d83..d353606210a 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/02_booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/02_booleans.md @@ -26,5 +26,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/03_strings.md index c42f34ec3ad..4360893e9a2 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/03_strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/03_strings.md @@ -16,7 +16,7 @@ keywords: The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging). +`std::println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/04_arrays.md index bdbd1798bef..1424ca2df14 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/04_arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/04_arrays.md @@ -56,7 +56,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md index e91e73a4c4f..87a09293ea8 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md @@ -81,14 +81,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/01_commands.md index 65e2bdb44e3..e2b0af522f4 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/01_commands.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/01_commands.md @@ -213,7 +213,7 @@ you run `nargo test`. To print `println` statements in tests, use the `--show-ou Takes an optional `--exact` flag which allows you to select tests based on an exact name. -See an example on the [testing page](./testing). +See an example on the [testing page](./testing.md). ### Options diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md index e0c6d475c1f..985bb7c879d 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md @@ -26,20 +26,20 @@ fn sha256(_input : [u8; N]) -> [u8; 32] {} Here is a list of the current black box functions that are supported by UltraPlonk: - AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- [Compute merkle root](./merkle_trees.md#compute_merkle_root) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) +- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/recursion.md index ff4c63acaa7..5e592a2fd89 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/recursion.md @@ -15,7 +15,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/01_hello_world.md index d4daae605a2..34f8cd96fcd 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/01_hello_world.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/01_hello_world.md @@ -74,7 +74,7 @@ x : Field, y : pub Field Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. +[Data Types](../language_concepts/data_types.md) section. The next line of the program specifies its body: @@ -84,7 +84,7 @@ assert(x != y); The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments.md) chapter. ## Build In/Output Files diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md index d28a54a1600..f928370b2e8 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md @@ -51,7 +51,7 @@ license = "MIT" ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} ``` -Nargo.toml for a [workspace](../modules_packages_crates/workspaces) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: ```toml [workspace] @@ -74,7 +74,7 @@ The package section requires a number of fields including: #### Dependencies section -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/index.md index 380368db036..e8d86020a20 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/index.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier.md) command to create a verifier contract. ### Protocol Developers @@ -97,4 +97,4 @@ Some libraries that are available today include: - [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir - [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/02_booleans.md index 885db167d83..d353606210a 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/02_booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/02_booleans.md @@ -26,5 +26,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/03_strings.md index c42f34ec3ad..4360893e9a2 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/03_strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/03_strings.md @@ -16,7 +16,7 @@ keywords: The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging). +`std::println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/04_arrays.md index bdbd1798bef..1424ca2df14 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/04_arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/04_arrays.md @@ -56,7 +56,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md index e91e73a4c4f..87a09293ea8 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md @@ -81,14 +81,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/01_commands.md index 65e2bdb44e3..e2b0af522f4 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/01_commands.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/01_commands.md @@ -213,7 +213,7 @@ you run `nargo test`. To print `println` statements in tests, use the `--show-ou Takes an optional `--exact` flag which allows you to select tests based on an exact name. -See an example on the [testing page](./testing). +See an example on the [testing page](./testing.md). ### Options diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md index e0c6d475c1f..985bb7c879d 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md @@ -26,20 +26,20 @@ fn sha256(_input : [u8; N]) -> [u8; 32] {} Here is a list of the current black box functions that are supported by UltraPlonk: - AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- [Compute merkle root](./merkle_trees.md#compute_merkle_root) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) +- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/recursion.md index ff4c63acaa7..5e592a2fd89 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/recursion.md @@ -15,7 +15,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/01_hello_world.md index d4daae605a2..34f8cd96fcd 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/01_hello_world.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/01_hello_world.md @@ -74,7 +74,7 @@ x : Field, y : pub Field Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. +[Data Types](../language_concepts/data_types.md) section. The next line of the program specifies its body: @@ -84,7 +84,7 @@ assert(x != y); The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments.md) chapter. ## Build In/Output Files diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md index d28a54a1600..f928370b2e8 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md @@ -51,7 +51,7 @@ license = "MIT" ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} ``` -Nargo.toml for a [workspace](../modules_packages_crates/workspaces) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: ```toml [workspace] @@ -74,7 +74,7 @@ The package section requires a number of fields including: #### Dependencies section -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/index.md index 380368db036..e8d86020a20 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/index.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier.md) command to create a verifier contract. ### Protocol Developers @@ -97,4 +97,4 @@ Some libraries that are available today include: - [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir - [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/02_booleans.md index 885db167d83..d353606210a 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/02_booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/02_booleans.md @@ -26,5 +26,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/03_strings.md index c42f34ec3ad..4360893e9a2 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/03_strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/03_strings.md @@ -16,7 +16,7 @@ keywords: The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging). +`std::println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/04_arrays.md index bdbd1798bef..1424ca2df14 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/04_arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/04_arrays.md @@ -56,7 +56,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md index e91e73a4c4f..87a09293ea8 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md @@ -81,14 +81,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/01_commands.md index 65e2bdb44e3..e2b0af522f4 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/01_commands.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/01_commands.md @@ -213,7 +213,7 @@ you run `nargo test`. To print `println` statements in tests, use the `--show-ou Takes an optional `--exact` flag which allows you to select tests based on an exact name. -See an example on the [testing page](./testing). +See an example on the [testing page](./testing.md). ### Options diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md index e0c6d475c1f..985bb7c879d 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md @@ -26,20 +26,20 @@ fn sha256(_input : [u8; N]) -> [u8; 32] {} Here is a list of the current black box functions that are supported by UltraPlonk: - AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- [Compute merkle root](./merkle_trees.md#compute_merkle_root) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) +- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/recursion.md index ff4c63acaa7..5e592a2fd89 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/recursion.md @@ -15,7 +15,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/01_hello_world.md index d4daae605a2..34f8cd96fcd 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/01_hello_world.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/01_hello_world.md @@ -74,7 +74,7 @@ x : Field, y : pub Field Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. +[Data Types](../language_concepts/data_types.md) section. The next line of the program specifies its body: @@ -84,7 +84,7 @@ assert(x != y); The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments.md) chapter. ## Build In/Output Files diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md index 7a7fb876c35..10422029661 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md @@ -51,7 +51,7 @@ license = "MIT" ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} ``` -Nargo.toml for a [workspace](../modules_packages_crates/workspaces) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: ```toml [workspace] @@ -74,7 +74,7 @@ The package section requires a number of fields including: #### Dependencies section -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/index.md index 380368db036..e8d86020a20 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/index.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier.md) command to create a verifier contract. ### Protocol Developers @@ -97,4 +97,4 @@ Some libraries that are available today include: - [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir - [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/02_booleans.md index 885db167d83..d353606210a 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/02_booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/02_booleans.md @@ -26,5 +26,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md index c42f34ec3ad..4360893e9a2 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md @@ -16,7 +16,7 @@ keywords: The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging). +`std::println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md index bdbd1798bef..1424ca2df14 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md @@ -56,7 +56,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md index e91e73a4c4f..87a09293ea8 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md @@ -81,14 +81,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/01_commands.md index 65e2bdb44e3..e2b0af522f4 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/01_commands.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/01_commands.md @@ -213,7 +213,7 @@ you run `nargo test`. To print `println` statements in tests, use the `--show-ou Takes an optional `--exact` flag which allows you to select tests based on an exact name. -See an example on the [testing page](./testing). +See an example on the [testing page](./testing.md). ### Options diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md index e0c6d475c1f..985bb7c879d 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md @@ -26,20 +26,20 @@ fn sha256(_input : [u8; N]) -> [u8; 32] {} Here is a list of the current black box functions that are supported by UltraPlonk: - AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- [Compute merkle root](./merkle_trees.md#compute_merkle_root) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) +- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md index ff4c63acaa7..5e592a2fd89 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md @@ -15,7 +15,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md index d4daae605a2..34f8cd96fcd 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md @@ -74,7 +74,7 @@ x : Field, y : pub Field Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. +[Data Types](../language_concepts/data_types.md) section. The next line of the program specifies its body: @@ -84,7 +84,7 @@ assert(x != y); The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments.md) chapter. ## Build In/Output Files diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md index d28a54a1600..f928370b2e8 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md @@ -51,7 +51,7 @@ license = "MIT" ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} ``` -Nargo.toml for a [workspace](../modules_packages_crates/workspaces) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: ```toml [workspace] @@ -74,7 +74,7 @@ The package section requires a number of fields including: #### Dependencies section -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/index.md index 380368db036..e8d86020a20 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/index.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier.md) command to create a verifier contract. ### Protocol Developers @@ -97,4 +97,4 @@ Some libraries that are available today include: - [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir - [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md index 885db167d83..d353606210a 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md @@ -26,5 +26,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md index b4c75942bb8..baa3f205094 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md @@ -15,7 +15,7 @@ keywords: The string type is a fixed length value defined with `str`. -You can use strings in `assert()` functions or print them with `std::println()`. See more about [Logging](../../standard_library/logging). +You can use strings in `assert()` functions or print them with `std::println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md index bdbd1798bef..1424ca2df14 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md @@ -56,7 +56,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md index e91e73a4c4f..87a09293ea8 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md @@ -81,14 +81,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/01_commands.md index 65e2bdb44e3..e2b0af522f4 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/01_commands.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/01_commands.md @@ -213,7 +213,7 @@ you run `nargo test`. To print `println` statements in tests, use the `--show-ou Takes an optional `--exact` flag which allows you to select tests based on an exact name. -See an example on the [testing page](./testing). +See an example on the [testing page](./testing.md). ### Options diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md index e0c6d475c1f..985bb7c879d 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md @@ -26,20 +26,20 @@ fn sha256(_input : [u8; N]) -> [u8; 32] {} Here is a list of the current black box functions that are supported by UltraPlonk: - AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- [Compute merkle root](./merkle_trees.md#compute_merkle_root) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) +- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md index ff4c63acaa7..5e592a2fd89 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md @@ -15,7 +15,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md index a37dc401b7d..d9d21ef0485 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md index e0c6d475c1f..985bb7c879d 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md @@ -26,20 +26,20 @@ fn sha256(_input : [u8; N]) -> [u8; 32] {} Here is a list of the current black box functions that are supported by UltraPlonk: - AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- [Compute merkle root](./merkle_trees.md#compute_merkle_root) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) +- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/recursion.md index 67962082a8f..4a004fd3664 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/recursion.md @@ -15,7 +15,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/arrays.md index 075d39dadd4..4c80d50ed01 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/booleans.md index 69826fcd724..7211716f63e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/strings.md index 8d76d4ca654..dd6c844f6ae 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging). +`std::println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/arrays.md index 7f275a2d771..d95346454a9 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = []; ``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/booleans.md index 69826fcd724..7211716f63e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/strings.md index 311dfd64416..8ab5825a4c4 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/generics.md index ddd42bf1f9b..0c1c27a2221 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/generics.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/dependencies.md index a37dc401b7d..d9d21ef0485 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/black_box_fns.md index eae8744abf0..e8b62f21d4e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/black_box_fns.md @@ -12,19 +12,19 @@ The ACVM spec defines a set of blackbox functions which backends will be expecte Here is a list of the current black box functions: -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Blake3](./cryptographic_primitives/hashes#blake3) -- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) +- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/recursion.md index f252150c8b5..4390bda4a26 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/recursion.md @@ -15,7 +15,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/arrays.md index a8bd338e736..ca54d82b26b 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = []; ``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/booleans.md index 69826fcd724..7211716f63e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/strings.md index 311dfd64416..8ab5825a4c4 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/generics.md index ddd42bf1f9b..0c1c27a2221 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/generics.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/dependencies.md index a37dc401b7d..d9d21ef0485 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md index be8c65679c3..e8b62f21d4e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md @@ -24,7 +24,7 @@ Here is a list of the current black box functions: - XOR - RANGE - [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/recursion.md index 9337499dac8..ed2ed01fceb 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/recursion.md @@ -35,7 +35,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md index a8bd338e736..ca54d82b26b 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = []; ``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md index 69826fcd724..7211716f63e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md index 311dfd64416..8ab5825a4c4 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md index ddd42bf1f9b..0c1c27a2221 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md index 04c1703d929..2c028d85853 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md index be8c65679c3..e8b62f21d4e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md @@ -24,7 +24,7 @@ Here is a list of the current black box functions: - XOR - RANGE - [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md index 9337499dac8..ed2ed01fceb 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md @@ -35,7 +35,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/arrays.md index efce3e95d32..95d749053e2 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = &[]; ``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/booleans.md index 69826fcd724..7211716f63e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md index 311dfd64416..8ab5825a4c4 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md index ddd42bf1f9b..0c1c27a2221 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/unconstrained.md index b8e71fe65f0..96f824c5e42 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/unconstrained.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/unconstrained.md @@ -96,4 +96,4 @@ Generally we want to use brillig whenever there's something that's easy to verif ## Break and Continue -In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/dependencies.md index 04c1703d929..2c028d85853 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/black_box_fns.md index be8c65679c3..e8b62f21d4e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/black_box_fns.md @@ -24,7 +24,7 @@ Here is a list of the current black box functions: - XOR - RANGE - [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/recursion.md index a93894043dc..f33c285cf4e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/recursion.md @@ -35,7 +35,7 @@ pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md index efce3e95d32..95d749053e2 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = &[]; ``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/booleans.md index 69826fcd724..7211716f63e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md index 311dfd64416..8ab5825a4c4 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md index ddd42bf1f9b..0c1c27a2221 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md index b8e71fe65f0..96f824c5e42 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md @@ -96,4 +96,4 @@ Generally we want to use brillig whenever there's something that's easy to verif ## Break and Continue -In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/dependencies.md index 04c1703d929..2c028d85853 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/black_box_fns.md index be8c65679c3..e8b62f21d4e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/black_box_fns.md @@ -24,7 +24,7 @@ Here is a list of the current black box functions: - XOR - RANGE - [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/recursion.md index a93894043dc..f33c285cf4e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/recursion.md @@ -35,7 +35,7 @@ pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md index efce3e95d32..95d749053e2 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = &[]; ``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/booleans.md index 69826fcd724..7211716f63e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md index 311dfd64416..8ab5825a4c4 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md index ddd42bf1f9b..0c1c27a2221 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md index b8e71fe65f0..96f824c5e42 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md @@ -96,4 +96,4 @@ Generally we want to use brillig whenever there's something that's easy to verif ## Break and Continue -In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/dependencies.md index 04c1703d929..2c028d85853 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/black_box_fns.md index be8c65679c3..e8b62f21d4e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/black_box_fns.md @@ -24,7 +24,7 @@ Here is a list of the current black box functions: - XOR - RANGE - [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/recursion.md index a93894043dc..f33c285cf4e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/recursion.md @@ -35,7 +35,7 @@ pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/debugger.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/debugger.md index 7c158d949d1..9b7565ba9ff 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/debugger.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/debugger.md @@ -12,7 +12,7 @@ There are currently two ways of debugging Noir programs: 1. From VS Code, via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). 2. Via the REPL debugger, which ships with Nargo. -In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation) and vscode-noir: +In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation/index.md) and vscode-noir: - Noir & Nargo ≥0.28.0 - Noir's VS Code extension ≥0.0.11 diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tutorials/noirjs_app.md index 6446e0b2a76..3dd9fe7d2b0 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tutorials/noirjs_app.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tutorials/noirjs_app.md @@ -24,7 +24,7 @@ Before we start, we want to make sure we have Node and Nargo installed. We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). -As for `Nargo`, we can follow the the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: +As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: ```sh curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md index efce3e95d32..95d749053e2 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = &[]; ``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/booleans.md index 69826fcd724..7211716f63e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md index 311dfd64416..8ab5825a4c4 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md index ddd42bf1f9b..0c1c27a2221 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md index b8e71fe65f0..96f824c5e42 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md @@ -96,4 +96,4 @@ Generally we want to use brillig whenever there's something that's easy to verif ## Break and Continue -In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/dependencies.md index 04c1703d929..2c028d85853 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/black_box_fns.md index be8c65679c3..e8b62f21d4e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/black_box_fns.md @@ -24,7 +24,7 @@ Here is a list of the current black box functions: - XOR - RANGE - [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/recursion.md index a93894043dc..f33c285cf4e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/recursion.md @@ -35,7 +35,7 @@ pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/debugger.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/debugger.md index 7c158d949d1..9b7565ba9ff 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/debugger.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/debugger.md @@ -12,7 +12,7 @@ There are currently two ways of debugging Noir programs: 1. From VS Code, via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). 2. Via the REPL debugger, which ships with Nargo. -In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation) and vscode-noir: +In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation/index.md) and vscode-noir: - Noir & Nargo ≥0.28.0 - Noir's VS Code extension ≥0.0.11 diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tutorials/noirjs_app.md index 6446e0b2a76..3dd9fe7d2b0 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tutorials/noirjs_app.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tutorials/noirjs_app.md @@ -24,7 +24,7 @@ Before we start, we want to make sure we have Node and Nargo installed. We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). -As for `Nargo`, we can follow the the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: +As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: ```sh curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md index efce3e95d32..95d749053e2 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = &[]; ``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/booleans.md index 69826fcd724..7211716f63e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md index 311dfd64416..8ab5825a4c4 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md index ddd42bf1f9b..0c1c27a2221 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md index b8e71fe65f0..96f824c5e42 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md @@ -96,4 +96,4 @@ Generally we want to use brillig whenever there's something that's easy to verif ## Break and Continue -In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/dependencies.md index 04c1703d929..2c028d85853 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/black_box_fns.md index eeead580969..d5694250f05 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/black_box_fns.md @@ -25,7 +25,7 @@ Here is a list of the current black box functions: - XOR - RANGE - [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/recursion.md index a93894043dc..f33c285cf4e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/recursion.md @@ -35,7 +35,7 @@ pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/debugger.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/debugger.md index 7c158d949d1..9b7565ba9ff 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/debugger.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/debugger.md @@ -12,7 +12,7 @@ There are currently two ways of debugging Noir programs: 1. From VS Code, via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). 2. Via the REPL debugger, which ships with Nargo. -In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation) and vscode-noir: +In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation/index.md) and vscode-noir: - Noir & Nargo ≥0.28.0 - Noir's VS Code extension ≥0.0.11 diff --git a/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr b/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr index aae96e5943d..6fde9e70f4d 100644 --- a/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr +++ b/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr @@ -11,15 +11,35 @@ impl BoundedVec { BoundedVec { storage: [zeroed; MaxLen], len: 0 } } - pub fn get(mut self: Self, index: u32) -> T { + /// Get an element from the vector at the given index. + /// Panics if the given index points beyond the end of the vector (`self.len()`). + pub fn get(self, index: u32) -> T { assert(index < self.len); - self.storage[index] + self.get_unchecked(index) } - pub fn get_unchecked(mut self: Self, index: u32) -> T { + /// Get an element from the vector at the given index. + /// Responds with undefined data for `index` where `self.len < index < self.max_len()`. + pub fn get_unchecked(self, index: u32) -> T { self.storage[index] } + /// Write an element to the vector at the given index. + /// Panics if the given index points beyond the end of the vector (`self.len()`). + pub fn set(&mut self, index: u32, value: T) { + assert(index < self.len, "Attempted to write past end of BoundedVec"); + self.set_unchecked(index, value) + } + + /// Write an element to the vector at the given index. + /// Does not check whether the passed `index` is a valid index within the vector. + /// + /// Silently writes past the end of the vector for `index` where `self.len < index < self.max_len()` + /// Panics if the given index points beyond the maximum length of the vector (`self.max_len()`). + pub fn set_unchecked(&mut self, index: u32, value: T) { + self.storage[index] = value; + } + pub fn push(&mut self, elem: T) { assert(self.len < MaxLen, "push out of bounds"); @@ -101,6 +121,17 @@ impl BoundedVec { } ret } + + pub fn map(self, f: fn[Env](T) -> U) -> BoundedVec { + let mut ret = BoundedVec::new(); + ret.len = self.len(); + for i in 0..MaxLen { + if i < self.len() { + ret.storage[i] = f(self.get_unchecked(i)); + } + } + ret + } } impl Eq for BoundedVec where T: Eq { @@ -142,6 +173,73 @@ mod bounded_vec_tests { assert(bounded_vec1 != bounded_vec2); } + mod set { + use crate::collections::bounded_vec::BoundedVec; + + #[test] + fn set_updates_values_properly() { + let mut vec = BoundedVec::from_array([0, 0, 0, 0, 0]); + + vec.set(0, 42); + assert_eq(vec.storage, [42, 0, 0, 0, 0]); + + vec.set(1, 43); + assert_eq(vec.storage, [42, 43, 0, 0, 0]); + + vec.set(2, 44); + assert_eq(vec.storage, [42, 43, 44, 0, 0]); + + vec.set(1, 10); + assert_eq(vec.storage, [42, 10, 44, 0, 0]); + + vec.set(0, 0); + assert_eq(vec.storage, [0, 10, 44, 0, 0]); + } + + #[test(should_fail_with = "Attempted to write past end of BoundedVec")] + fn panics_when_writing_elements_past_end_of_vec() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.set(0, 42); + + // Need to use println to avoid DIE removing the write operation. + crate::println(vec.get(0)); + } + } + + mod map { + use crate::collections::bounded_vec::BoundedVec; + + #[test] + fn applies_function_correctly() { + // docs:start:bounded-vec-map-example + let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]); + let result = vec.map(|value| value * 2); + // docs:end:bounded-vec-map-example + let expected = BoundedVec::from_array([2, 4, 6, 8]); + + assert_eq(result, expected); + } + + #[test] + fn applies_function_that_changes_return_type() { + let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]); + let result = vec.map(|value| (value * 2) as Field); + let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]); + + assert_eq(result, expected); + } + + #[test] + fn does_not_apply_function_past_len() { + let vec: BoundedVec = BoundedVec::from_array([0, 1]); + let result = vec.map(|value| if value == 0 { 5 } else { value }); + let expected = BoundedVec::from_array([5, 1]); + + assert_eq(result, expected); + assert_eq(result.storage()[2], 0); + } + } + mod from_array { use crate::collections::bounded_vec::BoundedVec; diff --git a/noir/noir-repo/noir_stdlib/src/collections/vec.nr b/noir/noir-repo/noir_stdlib/src/collections/vec.nr index 18aaa8b9b3b..cedae7f5ce1 100644 --- a/noir/noir-repo/noir_stdlib/src/collections/vec.nr +++ b/noir/noir-repo/noir_stdlib/src/collections/vec.nr @@ -21,6 +21,12 @@ impl Vec { self.slice[index] } + /// Write an element to the vector at the given index. + /// Panics if the given index points beyond the end of the vector (`self.len()`). + pub fn set(&mut self, index: u32, value: T) { + self.slice[index] = value; + } + /// Push a new element to the end of the vector, returning a /// new vector with a length one greater than the /// original unmodified vector. @@ -57,3 +63,36 @@ impl Vec { self.slice.len() } } + +mod tests { + use crate::collections::vec::Vec; + + #[test] + fn set_updates_values_properly() { + let mut vec = Vec { slice: &[0, 0, 0, 0, 0] }; + + vec.set(0, 42); + assert_eq(vec.slice, &[42, 0, 0, 0, 0]); + + vec.set(1, 43); + assert_eq(vec.slice, &[42, 43, 0, 0, 0]); + + vec.set(2, 44); + assert_eq(vec.slice, &[42, 43, 44, 0, 0]); + + vec.set(1, 10); + assert_eq(vec.slice, &[42, 10, 44, 0, 0]); + + vec.set(0, 0); + assert_eq(vec.slice, &[0, 10, 44, 0, 0]); + } + + #[test(should_fail)] + fn panics_when_writing_elements_past_end_of_vec() { + let mut vec = Vec::new(); + vec.set(0, 42); + + // Need to use println to avoid DIE removing the write operation. + crate::println(vec.get(0)); + } +} diff --git a/noir/noir-repo/noir_stdlib/src/compat.nr b/noir/noir-repo/noir_stdlib/src/compat.nr index 5d80c422c33..30b7f73f130 100644 --- a/noir/noir-repo/noir_stdlib/src/compat.nr +++ b/noir/noir-repo/noir_stdlib/src/compat.nr @@ -1,4 +1,18 @@ +global BN254_MODULUS_BE_BYTES: [u8; 32] = [ + 48, 100, 78, 114, 225, 49, 160, 41, 184, 80, 69, 182, 129, 129, 88, 93, 40, 51, 232, 72, 121, 185, 112, 145, 67, 225, 245, 147, 240, 0, 0, 1 +]; + pub fn is_bn254() -> bool { - // bn254 truncates its curve order to 0 - 21888242871839275222246405745257275088548364400416034343698204186575808495617 == 0 + // TODO: refactor this once https://github.com/noir-lang/noir/issues/5245 is resolved. + let modulus_bytes = crate::field::modulus_be_bytes(); + if modulus_bytes.len() == 32 { + let mut modulus_bytes_array: [u8; 32] = [0; 32]; + for i in 0..32 { + modulus_bytes_array[i] = modulus_bytes[i]; + } + + modulus_bytes_array == BN254_MODULUS_BE_BYTES + } else { + false + } } diff --git a/noir/noir-repo/noir_stdlib/src/hash/mimc.nr b/noir/noir-repo/noir_stdlib/src/hash/mimc.nr index 6c5502c2fbf..e90bacb75c2 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/mimc.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/mimc.nr @@ -116,6 +116,7 @@ global MIMC_BN254_CONSTANTS: [Field; MIMC_BN254_ROUNDS] = [ //mimc implementation with hardcoded parameters for BN254 curve. #[field(bn254)] +#[no_predicates] pub fn mimc_bn254(array: [Field; N]) -> Field { let exponent = 7; let mut r = 0; diff --git a/noir/noir-repo/noir_stdlib/src/hash/poseidon/bn254.nr b/noir/noir-repo/noir_stdlib/src/hash/poseidon/bn254.nr index 54f22884e29..9d3accb1ebd 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/poseidon/bn254.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/poseidon/bn254.nr @@ -6,12 +6,14 @@ use crate::hash::poseidon::{PoseidonConfig, absorb}; // Variable-length Poseidon-128 sponge as suggested in second bullet point of §3 of https://eprint.iacr.org/2019/458.pdf #[field(bn254)] +#[no_predicates] pub fn sponge(msg: [Field; N]) -> Field { absorb(consts::x5_5_config(), [0; 5], 4, 1, msg)[1] } // Various instances of the Poseidon hash function // Consistent with Circom's implementation +#[no_predicates] pub fn hash_1(input: [Field; 1]) -> Field { let mut state = [0; 2]; for i in 0..input.len() { @@ -21,6 +23,7 @@ pub fn hash_1(input: [Field; 1]) -> Field { perm::x5_2(state)[0] } +#[no_predicates] pub fn hash_2(input: [Field; 2]) -> Field { let mut state = [0; 3]; for i in 0..input.len() { @@ -30,6 +33,7 @@ pub fn hash_2(input: [Field; 2]) -> Field { perm::x5_3(state)[0] } +#[no_predicates] pub fn hash_3(input: [Field; 3]) -> Field { let mut state = [0; 4]; for i in 0..input.len() { @@ -39,6 +43,7 @@ pub fn hash_3(input: [Field; 3]) -> Field { perm::x5_4(state)[0] } +#[no_predicates] pub fn hash_4(input: [Field; 4]) -> Field { let mut state = [0; 5]; for i in 0..input.len() { @@ -48,6 +53,7 @@ pub fn hash_4(input: [Field; 4]) -> Field { perm::x5_5(state)[0] } +#[no_predicates] pub fn hash_5(input: [Field; 5]) -> Field { let mut state = [0; 6]; for i in 0..input.len() { @@ -57,6 +63,7 @@ pub fn hash_5(input: [Field; 5]) -> Field { perm::x5_6(state)[0] } +#[no_predicates] pub fn hash_6(input: [Field; 6]) -> Field { let mut state = [0; 7]; for i in 0..input.len() { @@ -66,6 +73,7 @@ pub fn hash_6(input: [Field; 6]) -> Field { perm::x5_7(state)[0] } +#[no_predicates] pub fn hash_7(input: [Field; 7]) -> Field { let mut state = [0; 8]; for i in 0..input.len() { @@ -75,6 +83,7 @@ pub fn hash_7(input: [Field; 7]) -> Field { perm::x5_8(state)[0] } +#[no_predicates] pub fn hash_8(input: [Field; 8]) -> Field { let mut state = [0; 9]; for i in 0..input.len() { @@ -84,6 +93,7 @@ pub fn hash_8(input: [Field; 8]) -> Field { perm::x5_9(state)[0] } +#[no_predicates] pub fn hash_9(input: [Field; 9]) -> Field { let mut state = [0; 10]; for i in 0..input.len() { @@ -93,6 +103,7 @@ pub fn hash_9(input: [Field; 9]) -> Field { perm::x5_10(state)[0] } +#[no_predicates] pub fn hash_10(input: [Field; 10]) -> Field { let mut state = [0; 11]; for i in 0..input.len() { @@ -102,6 +113,7 @@ pub fn hash_10(input: [Field; 10]) -> Field { perm::x5_11(state)[0] } +#[no_predicates] pub fn hash_11(input: [Field; 11]) -> Field { let mut state = [0; 12]; for i in 0..input.len() { @@ -111,6 +123,7 @@ pub fn hash_11(input: [Field; 11]) -> Field { perm::x5_12(state)[0] } +#[no_predicates] pub fn hash_12(input: [Field; 12]) -> Field { let mut state = [0; 13]; for i in 0..input.len() { @@ -120,6 +133,7 @@ pub fn hash_12(input: [Field; 12]) -> Field { perm::x5_13(state)[0] } +#[no_predicates] pub fn hash_13(input: [Field; 13]) -> Field { let mut state = [0; 14]; for i in 0..input.len() { @@ -129,6 +143,7 @@ pub fn hash_13(input: [Field; 13]) -> Field { perm::x5_14(state)[0] } +#[no_predicates] pub fn hash_14(input: [Field; 14]) -> Field { let mut state = [0; 15]; for i in 0..input.len() { @@ -138,6 +153,7 @@ pub fn hash_14(input: [Field; 14]) -> Field { perm::x5_15(state)[0] } +#[no_predicates] pub fn hash_15(input: [Field; 15]) -> Field { let mut state = [0; 16]; for i in 0..input.len() { @@ -147,6 +163,7 @@ pub fn hash_15(input: [Field; 15]) -> Field { perm::x5_16(state)[0] } +#[no_predicates] pub fn hash_16(input: [Field; 16]) -> Field { let mut state = [0; 17]; for i in 0..input.len() { diff --git a/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr b/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr index 04d922b581d..4a68925255a 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr @@ -11,7 +11,7 @@ struct Poseidon2 { } impl Poseidon2 { - + #[no_predicates] pub fn hash(input: [Field; N], message_size: u32) -> Field { if message_size == N { Poseidon2::hash_internal(input, N, false) diff --git a/noir/noir-repo/noir_stdlib/src/sha256.nr b/noir/noir-repo/noir_stdlib/src/sha256.nr index d856043fcfa..6057876951d 100644 --- a/noir/noir-repo/noir_stdlib/src/sha256.nr +++ b/noir/noir-repo/noir_stdlib/src/sha256.nr @@ -38,6 +38,7 @@ fn hash_final_block(msg_block: [u8; 64], mut state: [u32; 8]) -> [u8; 32] { } // Variable size SHA-256 hash +#[no_predicates] pub fn sha256_var(msg: [u8; N], message_size: u64) -> [u8; 32] { let mut msg_block: [u8; 64] = [0; 64]; let mut h: [u32; 8] = [1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225]; // Intermediate hash, starting with the canonical initial value diff --git a/noir/noir-repo/noir_stdlib/src/sha512.nr b/noir/noir-repo/noir_stdlib/src/sha512.nr index 0f8ffcfcb1c..4e46840ebb7 100644 --- a/noir/noir-repo/noir_stdlib/src/sha512.nr +++ b/noir/noir-repo/noir_stdlib/src/sha512.nr @@ -87,6 +87,7 @@ fn msg_u8_to_u64(msg: [u8; 128]) -> [u64; 16] { msg64 } // SHA-512 hash function +#[no_predicates] pub fn digest(msg: [u8; N]) -> [u8; 64] { let mut msg_block: [u8; 128] = [0; 128]; // noir-fmt:ignore diff --git a/noir/noir-repo/scripts/redo-typo-pr.sh b/noir/noir-repo/scripts/redo-typo-pr.sh new file mode 100755 index 00000000000..416be65a449 --- /dev/null +++ b/noir/noir-repo/scripts/redo-typo-pr.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -eux + +# Configuration +ORIGINAL_PR_NUMBER=$1 +REPO='noir-lang/noir' +NEW_BRANCH="chore/typo-redo-$ORIGINAL_PR_NUMBER" +AUTHOR=`gh pr view $ORIGINAL_PR_NUMBER --json author --jq '.author.login'` + +# Step 1: Checkout the PR locally +echo "Checking out PR #$ORIGINAL_PR_NUMBER" +gh pr checkout $ORIGINAL_PR_NUMBER + +# Step 2: Create a new local branch +echo "Creating new local branch $NEW_BRANCH" +git checkout -b $NEW_BRANCH + +# Step 3: Push the new branch to GitHub +echo "Pushing new branch $NEW_BRANCH to GitHub" +git commit --amend --no-edit +git push origin $NEW_BRANCH + +# Step 4: create a new pull request +echo "Creating a new pull request for $NEW_BRANCH" +gh pr create --base master --head $NEW_BRANCH --title "chore: redo typo PR by $AUTHOR" --body "Thanks $AUTHOR for https://github.com/$REPO/pull/$ORIGINAL_PR_NUMBER. Our policy is to redo typo changes to dissuade metric farming. This is an automated script." + +# Step 5: Close the original PR +echo "Closing original PR #$ORIGINAL_PR_NUMBER" +gh pr close $ORIGINAL_PR_NUMBER + +echo "Script completed." diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/macros/Nargo.toml similarity index 75% rename from noir/noir-repo/test_programs/execution_success/verify_honk_proof/Nargo.toml rename to noir/noir-repo/test_programs/compile_success_empty/macros/Nargo.toml index d298dabb560..e4408e2ee17 100644 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Nargo.toml +++ b/noir/noir-repo/test_programs/compile_success_empty/macros/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "verify_honk_proof" +name = "macros" type = "bin" authors = [""] compiler_version = ">=0.30.0" diff --git a/noir/noir-repo/test_programs/compile_success_empty/macros/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/macros/src/main.nr new file mode 100644 index 00000000000..f466226d575 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/macros/src/main.nr @@ -0,0 +1,15 @@ +comptime fn my_macro(x: Field, y: Field) -> Expr { + // Current version of macros in Noir are not hygienic + // so we can quote a and b here and expect them to resolve + // to the a and b in main at the callsite of my_macro. + quote { + $x + $y + a + b + } +} + +fn main() { + let a = 100; + let b = 200; + let result = my_macro!(1, 2); + assert_eq(result, 1 + 2 + a + b); +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/Nargo.toml new file mode 100644 index 00000000000..2125d475530 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "no_duplicate_methods" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/Prover.toml b/noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/Prover.toml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr new file mode 100644 index 00000000000..2be1d3fa11e --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr @@ -0,0 +1,26 @@ +// Test that declaring several methods & trait methods with the same name +// does not trigger a duplicate method error +trait ToField { + fn to_field(self) -> Field; +} +trait ToField2 { + fn to_field(self) -> Field; +} + +struct Foo { x: Field } + +impl ToField for Foo { + fn to_field(self) -> Field { self.x } +} + +impl ToField2 for Foo { + fn to_field(self) -> Field { self.x } +} + +impl Foo { + fn to_field(self) -> Field { + self.x + } +} + +fn main() {} diff --git a/noir/noir-repo/test_programs/execution_success/regression_5202/Nargo.toml b/noir/noir-repo/test_programs/execution_success/regression_5202/Nargo.toml new file mode 100644 index 00000000000..da3da06a306 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_5202/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "regression_5202" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] +fraction = { path = "fraction" } diff --git a/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/LICENSE b/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/LICENSE new file mode 100644 index 00000000000..929af4807ca --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Resurgence Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/Nargo.toml b/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/Nargo.toml new file mode 100644 index 00000000000..82e929d0bc7 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "fraction" +type = "lib" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/README.md b/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/README.md new file mode 100644 index 00000000000..17c81e5555a --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/README.md @@ -0,0 +1,10 @@ +# fraction +The Noir repository for accessing Fractions by Resurgence Labs + +# usage +To Use as a Dependency, add the following line to your project's Nargo.toml under [dependencies]: +fraction = { tag = "v1.2.2", git = "https://github.com/resurgencelabs/fraction" } + +Note: This is a highly dynamic repository. The code will change as more features are added, both at the repository level by Resurgence Labs, as well as at the language level itself by the Noir team. + + diff --git a/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/src/lib.nr b/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/src/lib.nr new file mode 100644 index 00000000000..4b20eb6b76c --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/src/lib.nr @@ -0,0 +1,201 @@ +use dep::std; + +global MAX: Fraction = Fraction { sign: true, num: 3050913689, den: 1 }; +global MIN: Fraction = Fraction { sign: false, num: 3050913689, den: 1 }; +global ZERO: Fraction = Fraction { sign: true, num: 0, den: 1 }; +global ONE: Fraction = Fraction { sign: true, num: 1, den: 1 }; +global NEGATIVE_ONE: Fraction = Fraction { sign: false, num: 1, den: 1 }; + +struct Fraction { + sign: bool, + num: u32, + den: u32, +} + +// Create a Fraction type variable without lenghtier code +pub fn toFraction(s: bool, n: u32, d: u32) -> Fraction { + assert(d != 0); + Fraction { sign: s, num: n, den: d } +} + +// Swaps the numerator and denominator +fn invertFraction(f: Fraction) -> Fraction { + assert(f.num != 0); + Fraction { sign: f.sign, num: f.den, den: f.num } +} + +// Changes the Sign of the Fraction +fn signChangeFraction(f: Fraction) -> Fraction { + Fraction { sign: !f.sign, num: f.num, den: f.den } +} + +// this method will only work till numerator and denominator values are under 100 +// this has been set for efficiency reasons, and will be modified once the Noir team +// can implement dynamic limit for loops +fn reduceFraction(f: Fraction) -> Fraction { + let mut a = f.num; + let mut b = f.den; + let mut j = 1; + let mut gcd = 1; + + let min = if a > b { b } else { a }; + + for i in 2..100 { + j = i as u32; + if (j <= min) { + if (a % j == 0) & (b % j == 0) { + gcd = j; + } + } + } + + Fraction { sign: f.sign, num: f.num / gcd, den: f.den / gcd } +} + +// Adds two fractions +pub fn addFraction(f1: Fraction, f2: Fraction) -> Fraction { + let mut an = U128::from_integer(f1.num); + let mut ad = U128::from_integer(f1.den); + let mut bn = U128::from_integer(f2.num); + let mut bd = U128::from_integer(f2.den); + let mut m = f1; + let mut n = f2; + + if f1.sign == f2.sign { + if ((ad * bd > U128::from_integer(2000000000)) + | ((an * bd + ad * bn) > U128::from_integer(2000000000)) + | ((an * bd) > U128::from_integer(2000000000)) + | ((ad * bn) > U128::from_integer(2000000000))) { + m = reduceFraction(m); + n = reduceFraction(n); + } + an = U128::from_integer(m.num); + ad = U128::from_integer(m.den); + bn = U128::from_integer(n.num); + bd = U128::from_integer(n.den); + if ((ad * bd > U128::from_integer(2000000000)) + | ((an * bd + ad * bn) > U128::from_integer(2000000000)) + | ((an * bd) > U128::from_integer(2000000000)) + | ((ad * bn) > U128::from_integer(2000000000))) { + let mut ddd = (an * bd + ad * bn) / (ad * bd); + let mut factor = U128::from_integer(1); + for _ in 1..5 { + if ddd * U128::from_integer(10) < U128::from_integer(2000000000) { + ddd *= U128::from_integer(10); + factor *= U128::from_integer(10); + } + } + let np: u32 = U128::to_integer(((an * bd + ad * bn) * factor) / (ad * bd)); + let fx: u32 = U128::to_integer(factor); + Fraction { sign: f1.sign, num: np, den: fx } + } else { + Fraction { sign: f1.sign, num: (m.num * n.den + n.num * m.den), den: m.den * n.den } + } + } else if ((an * bd) > (bn * ad)) { + if ((ad * bd > U128::from_integer(2000000000)) + | ((an * bd - ad * bn) > U128::from_integer(2000000000)) + | ((an * bd) > U128::from_integer(2000000000))) { + m = reduceFraction(m); + n = reduceFraction(n); + } + an = U128::from_integer(m.num); + ad = U128::from_integer(m.den); + bn = U128::from_integer(n.num); + bd = U128::from_integer(n.den); + + if ((ad * bd > U128::from_integer(2000000000)) + | ((an * bd - ad * bn) > U128::from_integer(2000000000)) + | ((an * bd) > U128::from_integer(2000000000))) { + let mut ddd = (an * bd - ad * bn) / (ad * bd); + let mut factor = U128::from_integer(1); + for _ in 1..5 { + if ddd * U128::from_integer(10) < U128::from_integer(2000000000) { + ddd *= U128::from_integer(10); + factor *= U128::from_integer(10); + } + } + let np: u32 = U128::to_integer(((an * bd - ad * bn) * factor) / (ad * bd)); + let fx: u32 = U128::to_integer(factor); + Fraction { sign: f1.sign, num: np, den: fx } + } else { + Fraction { sign: f1.sign, num: (m.num * n.den - n.num * m.den), den: m.den * n.den } + } + } else { + if ((ad * bd > U128::from_integer(2000000000)) + | ((bn * ad - bd * an) > U128::from_integer(2000000000)) + | ((bn * ad) > U128::from_integer(2000000000))) { + m = reduceFraction(m); + n = reduceFraction(n); + } + an = U128::from_integer(m.num); + ad = U128::from_integer(m.den); + bn = U128::from_integer(n.num); + bd = U128::from_integer(n.den); + if ((ad * bd > U128::from_integer(2000000000)) + | ((bn * ad - bd * an) > U128::from_integer(2000000000)) + | ((bn * ad) > U128::from_integer(2000000000))) { + let mut ddd = (bn * ad - bd * an) / (ad * bd); + let mut factor = U128::from_integer(1); + for _ in 1..5 { + if ddd * U128::from_integer(10) < U128::from_integer(2000000000) { + ddd *= U128::from_integer(10); + factor *= U128::from_integer(10); + } + } + let np: u32 = U128::to_integer(((bn * ad - bd * an) * factor) / (ad * bd)); + let fx: u32 = U128::to_integer(factor); + Fraction { sign: f2.sign, num: np, den: fx } + } else { + Fraction { sign: f2.sign, num: (n.num * m.den - m.num * n.den), den: m.den * n.den } + } + } +} + +// Returns the closest but smaller Integer to the Given Fraction, but typecast to Fraction for convenience +pub fn floor(f: Fraction) -> Fraction { + let q = f.num / f.den; + if q * f.den == f.num { + Fraction { sign: f.sign, num: f.num, den: f.den } + } else if f.sign { + Fraction { sign: f.sign, num: q, den: 1 } + } else { + Fraction { sign: f.sign, num: q + 1, den: 1 } + } +} + +#[test] +fn test_sum() { + let f1 = toFraction(true, 3, 5); + let f2 = toFraction(true, 2, 5); + let f = addFraction(f1, f2); + assert(f.num == f.den); +} + +#[test] +fn test_reduce() { + let f1 = toFraction(true, 2, 10); + let f2 = reduceFraction(f1); + assert(f2.num == 1); +} + +#[test] +fn test_floor() { + let f = toFraction(true, 7, 5); + let fl = floor(f); + assert(fl.num == 1); + assert(fl.den == 1); +} + +#[test] +fn test_floor2() { + let f = toFraction(false, 12, 5); + let fl = floor(f); + assert(fl.num == 3); + assert(fl.den == 1); +} + +#[test] +fn test_globals() { + let a = addFraction(ONE, NEGATIVE_ONE); + assert(a.num == ZERO.num); +} diff --git a/noir/noir-repo/test_programs/execution_success/regression_5202/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_5202/src/main.nr new file mode 100644 index 00000000000..e41b760b83e --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_5202/src/main.nr @@ -0,0 +1,23 @@ +use dep::fraction::{Fraction, MAX, floor, toFraction, addFraction}; + +fn main() { + let g1 = toFraction(true, 33333333, 5); + let g2 = toFraction(true, 500000, 33333333); + let a = addFraction(g1, g2); + + let f1 = floor(a); + let f2 = MAX; + assert(f1.sign); + assert(f2.sign); + + if f1.sign != f2.sign { + if (f1.sign) { () } else { () } + } else { + // Test fails here before the fix to #5202. + // An optimization which assumes an if condition to be true/false + // within the then/else branch respectively wasn't being set properly + // causing f1.sign to be assumed to be false in this else branch. + assert(f1.sign); + assert(f2.sign); + } +} diff --git a/noir/noir-repo/test_programs/execution_success/regression_5252/Nargo.toml b/noir/noir-repo/test_programs/execution_success/regression_5252/Nargo.toml new file mode 100644 index 00000000000..855507dfaf3 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_5252/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_5252" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/regression_5252/Prover.toml b/noir/noir-repo/test_programs/execution_success/regression_5252/Prover.toml new file mode 100644 index 00000000000..82776b4463d --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_5252/Prover.toml @@ -0,0 +1,6 @@ +to_hash = [[1,5,9,2,24,563,3545,5,52,4244,43,2,7373567,2,286762,7,2457,24,2456,2456], +[2234,2,26,27,24566,132452,3452456344567,657,45674657,4567467,45674,4567456,4567,23454,2345,2345345245,25252345,2435234524366,8678678,67867567], +[9887575467567,5367367243617,46244567783,64673425,67456573456,4673457,46735,745674,6574,567456,7456,84,683,683,8368,38,32,16,7,98], +#[465656,234324,4353,5245246,2567345674567,5634563456,7676474,4747,4567456746,56,4657456,4657,4567,46,7,8,98,87,76,57] +] +enable = [1,1,0] diff --git a/noir/noir-repo/test_programs/execution_success/regression_5252/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_5252/src/main.nr new file mode 100644 index 00000000000..315807c3396 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_5252/src/main.nr @@ -0,0 +1,23 @@ +use dep::std::hash::{mimc, poseidon, poseidon2::Poseidon2}; + +global NUM_HASHES = 3; +global HASH_LENGTH = 20; + +pub fn poseidon_hash(inputs: [Field; N]) -> Field { + Poseidon2::hash(inputs, inputs.len()) +} + +fn main( + to_hash: [[Field; HASH_LENGTH]; NUM_HASHES], + enable: [bool; NUM_HASHES] +) -> pub [Field; NUM_HASHES] { + let mut result = [0; NUM_HASHES]; + for i in 0..NUM_HASHES { + let enable = enable[i]; + let to_hash = to_hash[i]; + if enable { + result[i] = poseidon_hash(to_hash) + poseidon::bn254::sponge(to_hash) + mimc::mimc_bn254(to_hash); + } + } + result +} diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml deleted file mode 100644 index 1ebc77c5a5f..00000000000 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml +++ /dev/null @@ -1,4 +0,0 @@ -key_hash = "0x096129b1c6e108252fc5c829c4cc9b7e8f0d1fd9f29c2532b563d6396645e08f" -proof = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf","0x00000000000000000000000000000000000000000000000b75c020998797da78","0x0000000000000000000000000000000000000000000000005a107acb64952eca","0x000000000000000000000000000000000000000000000000000031e97a575e9d","0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4","0x00000000000000000000000000000000000000000000000c410db10a01750aeb","0x00000000000000000000000000000000000000000000000d722669117f9758a4","0x000000000000000000000000000000000000000000000000000178cbf4206471","0x000000000000000000000000000000000000000000000000e91b8a11e7842c38","0x000000000000000000000000000000000000000000000007fd51009034b3357f","0x000000000000000000000000000000000000000000000009889939f81e9c7402","0x0000000000000000000000000000000000000000000000000000f94656a2ca48","0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f","0x0000000000000000000000000000000000000000000000093fe27776f50224bd","0x000000000000000000000000000000000000000000000004a0c80c0da527a081","0x0000000000000000000000000000000000000000000000000001b52c2020d746","0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632","0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc","0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62","0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c","0x000000000000000000000000000000b0804efd6573805f991458295f510a2004","0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e","0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47","0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15","0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd","0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383","0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4","0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98","0x00000000000000000000000000000044d7ca77b464f03aa44f6f8d49a0d3ada5","0x00000000000000000000000000000000002a36959f550517d82d0af666bcd7dc","0x0000000000000000000000000000000566b28c19f0b1732b95e0381bc5d6dbdd","0x00000000000000000000000000000000002511360b7a8c6a823559f0ac9eb02b","0x000000000000000000000000000000f968b227a358a305607f3efc933823d288","0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08","0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f","0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1","0x00000000000000000000000000000058035b1ed115023f42bf4ee93d2dc29dcb","0x00000000000000000000000000000000002de4b004225be4e68938b0db546287","0x0000000000000000000000000000003d18d72585ef033ab3663d1944abb2054a","0x0000000000000000000000000000000000149a1974c0c2b5f0639970cda1af83","0x000000000000000000000000000000bb1eb2b1fc10b55295ed6c1ae54e8a40da","0x000000000000000000000000000000000026da80059472ac8c64e437d6fe6134","0x000000000000000000000000000000d1f101b72ee710423ca44548910676a4fe","0x00000000000000000000000000000000000323378ad6b5aec67af99e522095a0","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x2622384e4b4688a3ad115007c1c09de1a141aeca06c31925898cf746038a5897","0x2f743e893a3880004db1ff3492279d89c025b9815f16e129d15f7a3687b6f833","0x03e05487307f18e3afb90cc524e56809e478039d317a3757433bfc8e06a32b73","0x099ba7011747dd2d8b5ac03ed02b93c9803d51899677409931d5b1571c3041b5","0x189ef108e334c5173619eac1067b99526a5cc6e47cbffaa3c117f0c3eb8bebd4","0x0b5f77b69ac2955ecc44a73e18b2ea8403224cf769657d53acc9a5d302d0b86e","0x1b81353a160e985e8a1fb09d3a3827fe68d03585757530dcec1b8038ac829a21","0x175e75cef1b974011de38e6e631f42bffd4dcb6fad6680930388cffaa60d940e","0x1631945a2aa39032cfa8cf379d18a983d4b5a487adab67252c6514b35bc88095","0x181b639e465a6f9842c5d75f6f5b855a065f498595146df3bd2b9c0ef66042a1","0x0c6e5af7add3e12f610c13d8066896d08882a7c50cfe33676fda8a75e250e9b9","0x28f94cd060c45a2e6b423831302deb456d0964879db5008a2be0957a2c749e2a","0x1c81fb20cea508580aa962e5b4736a43382816e7abac7e478e6c080cf896798d","0x23dea53784aa14dcf7e1cce5ee480796e67b2dd69a8e20c5c09558001640edfa","0x149c2548f8b0d96fefecab53e31aa3902341c903fa0ef863ef64610315de993b","0x16ad81b3129ccebe1682d14b726bc9b86acd0f0be8c304594ce5a87e756add27","0x2c1ef938516edccc0cd1d4d812644d72b6ead3c85e1c8500fc54e77e5652b23f","0x0eecb7fba3395b21197cb24bb9b733b1985d81f35a1ee944714ffd781a7bd136","0x06e2a96ecf1e8419198eca10133954f3560102467f40a234cf071d23c6cf411a","0x1e6bfa2adcbdc50313408ef28a77b76dd915fa372c093c4484ba662695a3eadc","0x28ccaf4d4759c1f4bb49429b961a59cdefbc445017ffa807e90c54b27e1ee657","0x22803d537311e757a146ae7a2fc396d42d67f27e73efca82e3e324dc493da4de","0x196255f687cede05f326204bfaead7a54f8d48b67ce8522cb8af6a7fffaffcb6","0x147ea42988386b944f006be242ccc6b099fadd7f450955d252768667bbaee4f9","0x1f9ccb05e508b1d08c79c11acbc0677fdc18d5d40827e2e1eaae60fee51b940f","0x28ea76870d22eea72821da25f9b7a89341347afcd6c077387986a82dc8afa833","0x0e6ef82d3e5a318a9c6233dffbb00d130599f4ac979a89b034ce9d930b11165a","0x2e97fa9299a218c982504199ada3278270b9cb566bf46fe1ecc1d151e06b8745","0x1a41ac9b1032ac24c11720407c253a866e9c75a4ec233f15f968b206ea1e5d0e","0x0b31b541bb044c1bc2428c2a57ba29438f620050d1628389ff1fa90c494d7c58","0x050fec8d69f182768a9b34eca8c3f4695dad8bc20a10904090cfe18777d44d25","0x069283ac40daaafff76c3679f54a0aa773c8d71152fbb9c3219906113fc4f683","0x25c3ec4e8b90214aafe3b5416abf11a98bd34b8acb449df8424f159ddf858bc1","0x1a3884f3a922d0da758cb7ed9a5ddc3c3c2132dde8d913753fa3e6b766be5697","0x222d05a0fce0565bf9cc490f97bd4eff53858f2ca6afe9d91c5c8d7de8076f39","0x054698b045b439467a3067a8dc2b4d020b2bb44df3d98a19f9cfb04c9ee5ffd1","0x0e39d66cded0f3df40e04124e36c827bcaf15fbe9fb6e9bbc3af889f8bd1ebf0","0x145aea47dc97ec35ac67f135aac37f8bc6eaf149551a2f48901529d10e25c860","0x1894877b2769ae2c288738f8aa33acfc7ca9a7d1e26a76908ca2909bf25aa59a","0x27e8c702be67be467f052abd180464a468b7d5d5d8a4961e56e8561f7863c91a","0x0326d3e4607d54a30c7fa99d1609f386aeb8c8094cabd7397246074f634dcec8","0x17eb8f62b5ba2dad391e3f81d3a6b9d03ff723a7d6a4d77b98b18ddd0debf4fd","0x1a5d3e8a27c1f69d6e4558b3c89cd9347c62182ce90fb6e34392bc4e7b7c178c","0x2293034bed3d33d5ad0d150f64d493c9be554f640103621f9ae56034a7323d84","0x13d75ffbb9d2ceb2daa6d42f3618d4ea9775befa1cf5f9df141dfebf794abc35","0x2ec339c42fbb2d50221ec907779e72be3eab2960d110a90d36cc6c0afcf5857e","0x15e9c913fa84a2657571831d5d7a90f6534ca67a1617b4063fa5bf09f46cd7a2","0x10f56fbe9fefd59d2acd49fa641fedcfb65d96d54cf47207e2c8ab34f22bbabe","0x117fa3859a400040ebe8dee4a60ddcb04484ff5cfb5294c6530354c3c8cb35f3","0x123260b824df2f8bbe6a351ba2fa94c61aa754741eb198b768a699b2d1cc2b6f","0x1e51d9a653adc6b67287d35bb60584261f57363177c6b54a56dbd39834d851ba","0x18a9b2e2fce77bdb5e41215e2caeb7e77e946dbb2f381c8e7974709e03a6c216","0x2b2640870195a40e374cfa834e37ad9a5e17cb687bd2119a63ac02c3769b0f1e","0x2da73263fef362dfc79dd1066fd7ec294b765e2533f3ac4320e8d1540f2639a8","0x0cc9f299e5291bb1bc0951ce510a634c418af9f9802a291fe6d951768c0a1b2d","0x02a940acb788df42cc9219531776d45465be19087fc3f523fe92df771e5efc10","0x2d5976cc5540e761824bdacf69a2dddabe104fdbb235985ae9080b488f642fa9","0x284c18d1574d2cb7b4ee45b3ff30176eff2ab9c7b7f60cd8a87cef599379244d","0x12a38d659bf38da09af8f445505baa16bcb036d83173f6f45a7e46cac511e5a1","0x0852ef710b2396ba5b7fd69a95b336908d3a368262ec41e0d972564f784201a4","0x240c467a31ed3bb7c4cef09407750d2d89b3750e6cebb4aaa9d0f1f92be77249","0x04edf7595087745abc11fe7780afd4754c5013725653a4cec31f039b77e7b3c7","0x080d04b50ae3acd787f33f8f4a639a58677b5c04ef8a352fd4dd9236883f0e81","0x0cd745e7540fe230038f024ab1269177599ad94e8d8099a010eb7eebd3e41ec8","0x25e2394f90f5b3e3046b8876a6b3ef19a03ef9e9aeae4813fcb14907decc0393","0x03df12a6e39c606d70d3d470aff710d9daa86dece773a6f6f057725b57d6d115","0x0f744082aecf54f55db19dfbe56a81c17b3eb48417305c129beb6c97a22c705b","0x244a80d6d82e82fc416e8e4694deb4e08b81c32bb90cb2f96ff3f687298322d1","0x251eb4d8692f49523e3972096264ee770b295fb62a970fbfdd8aa1fff661ef50","0x0c4d9200120430618493a9151d632faa95c9ae842b7d97103a4afb3330cafbed","0x09e970a55dd7335db16a3823b6489c77cb7785f674cb7c924994ee121122e514","0x19e5bd1113959463be673ee72103bfe7559f423c632fbf9701ff099e165c429b","0x071eb2916ba30652a328c98353f69f239c41a4913c34931f18e91e5414b3270a","0x2a0cd2ebac904b7ebd82b6509dfcaf9ecf32175758c691d01f4fb32dad6371c4","0x1aa43a3009417d95904ebecd4189545e52ca7e9c7dfa3bde5f255ddefed5c754","0x29fd7a93212d60af81b810dad13a240bbbe16966a4977408b1d64c5d692b50b4","0x000000000000000000000000000000bef7cad70fa62891e6329cb7c17d0c5459","0x0000000000000000000000000000000000209177f2a04609421c1f23c04b454e","0x00000000000000000000000000000060dec389686170618e2490100f3fcf39e2","0x0000000000000000000000000000000000213368873145aad5f93798c31730af","0x000000000000000000000000000000c0f21a470488d9cbe53650d941c25cd569","0x000000000000000000000000000000000016d6f88e6b319553f5948886a6bd5e","0x000000000000000000000000000000d6dbb8a54a071e01c46d648c8c555ec352","0x0000000000000000000000000000000000130a7ce06ad74eb6c83f5565e2f821","0x00000000000000000000000000000058ca3aa788bd6ff37a5da3ecefdc896601","0x00000000000000000000000000000000001381bddcf8fb976cc52fee0d920598","0x00000000000000000000000000000082bdd94acd10edf22e09b1a42be500f8f8","0x00000000000000000000000000000000002f27815e28b2bc0699336893abdc0f","0x000000000000000000000000000000eb1d6973a54f8848f4c0630370d6181e49","0x000000000000000000000000000000000000129c1889d64ab66303bf17bfc864","0x000000000000000000000000000000155918aa9f6d352b847bf860a261266282","0x0000000000000000000000000000000000216e687d2f85a811f67573cbf311ba","0x0000000000000000000000000000002d2662f79a7ba21a95f44e67ed0b5abf3b","0x00000000000000000000000000000000001351870a81dc6edff235df110fe798","0x000000000000000000000000000000b113a55b86f59b21fe419ed8518dfddfc6","0x00000000000000000000000000000000002f26cd920f79b0d72a49897acc521c","0x0000000000000000000000000000002a4e1689c65dcae73ed1a33b03c611a7fe","0x00000000000000000000000000000000001c5093a8ae791c00fdd763c95800c5","0x0000000000000000000000000000006231d049ec3683c06ec6b00348e0669c61","0x0000000000000000000000000000000000237bfd7ec06c28f22ce84db9bb17ed","0x0000000000000000000000000000008afa7fa0842467bded20491950c3c1cde0","0x00000000000000000000000000000000000194ab5c71154605b8483cb40d00b8","0x00000000000000000000000000000066709af193591e93e8be3b833f63cb8597","0x000000000000000000000000000000000008ab9091bb9225b00ca0c011dff12f"] -public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] -verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84","0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae","0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16","0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1","0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c","0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7","0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8","0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c","0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5","0x00000000000000000000000000000000002002681bb417184b2df070a16a3858","0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511","0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223","0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7","0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c","0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130","0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f","0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3","0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592","0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3","0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1","0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0","0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c","0x0000000000000000000000000000009f825dde88092070747180d581c342444a","0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01","0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff","0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9","0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1","0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b","0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2","0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f","0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0","0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349","0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8","0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2","0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556","0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d","0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb","0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d","0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8","0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862","0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e","0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830","0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f","0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe","0x000000000000000000000000000000231147211b3c75e1f47d150e4bbd2fb22e","0x00000000000000000000000000000000000d19ee104a10d3c701cfd87473cbbe","0x0000000000000000000000000000006705f3f382637d00f698e2c5c94ed05ae9","0x00000000000000000000000000000000000b9c792da28bb60601dd7ce4b74e68","0x000000000000000000000000000000ac5acc8cc21e4ddb225c510670f80c80b3","0x00000000000000000000000000000000002da9d3fa57343e6998aba19429b9fa","0x0000000000000000000000000000004bacbf54b7c17a560df0af18b6d0d527be","0x00000000000000000000000000000000000faea33aeca2025b22c288964b21eb","0x000000000000000000000000000000492e756298d68d6e95de096055cc0336c3","0x00000000000000000000000000000000001a12a12f004859e5a3675c7315121b","0x000000000000000000000000000000893d521d512f30e6d32afbbc0cecd8ee00","0x00000000000000000000000000000000001674b3c1ef12c6da690631e0d86c04","0x000000000000000000000000000000aa6cb02a52e7a613873d4ac9b411349945","0x00000000000000000000000000000000001ecb1fe9c493add46751f9940f73e1","0x00000000000000000000000000000045b3d362ca82cba69fb2b9c733a5b8c351","0x000000000000000000000000000000000019a683586af466e331945b732d2f8c","0x000000000000000000000000000000fc79b052dfdfe67c0ecfc06b4267ffd694","0x00000000000000000000000000000000001336a70c396393038d5e9913744ac2","0x0000000000000000000000000000005450d29af1e9438e91cd33ddeb2548226e","0x000000000000000000000000000000000000993a602891cfd0e6f6ecf7404933","0x000000000000000000000000000000498efddab90a32e9b2db729ed6e9b40192","0x00000000000000000000000000000000002425efebe9628c63ca6fc28bdb5901","0x000000000000000000000000000000d8488157f875a21ab5f93f1c2b641f3de9","0x0000000000000000000000000000000000290f95ada3936604dc4b14df7504e3","0x0000000000000000000000000000005d6902187f3ed60dcce06fca211b40329a","0x00000000000000000000000000000000002b5870a6ba0b20aaa0178e5adfbc36","0x000000000000000000000000000000e5c2519171fa0e548fc3c4966ffc1ce570","0x00000000000000000000000000000000001cb8d8f4793b7debbdc429389dbf2d","0x000000000000000000000000000000a3ee22dd60456277b86c32a18982dcb185","0x00000000000000000000000000000000002493c99a3d068b03f8f2b8d28b57ce","0x000000000000000000000000000000f6c3731486320082c20ec71bbdc92196c1","0x00000000000000000000000000000000001ded39c4c8366469843cd63f09ecac","0x000000000000000000000000000000494997477ab161763e46601d95844837ef","0x00000000000000000000000000000000002e0cddbc5712d79b59cb3b41ebbcdd","0x000000000000000000000000000000426db4c64531d350750df62dbbc41a1bd9","0x0000000000000000000000000000000000303126892f664d8d505964d14315ec","0x00000000000000000000000000000076a6b2c6040c0c62bd59acfe3e3e125672","0x000000000000000000000000000000000000874a5ad262eecc6b565e0b085074","0x000000000000000000000000000000ef082fb517183c9c6841c2b8ef2ca1df04","0x0000000000000000000000000000000000127b2a745a1b74968c3edc18982b9b","0x000000000000000000000000000000c9efd4f8c3d56e1eb23d789a8f710d5be6","0x000000000000000000000000000000000015a18748490ff4c2b1871081954e86","0x000000000000000000000000000000a0011ef987dc016ab110eacd554a1d8bbf","0x00000000000000000000000000000000002097c84955059442a95df075833071","0x000000000000000000000000000000d38e9426ad3085b68b00a93c17897c2877","0x00000000000000000000000000000000002aecd48089890ea0798eb952c66824","0x00000000000000000000000000000078d8a9ce405ce559f441f2e71477ff3ddb","0x00000000000000000000000000000000001216bdb2f0d961bb8a7a23331d2150","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb","0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56","0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc","0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4"] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr deleted file mode 100644 index d25fd804ce4..00000000000 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr +++ /dev/null @@ -1,21 +0,0 @@ -use dep::std; - -// This circuit aggregates a single Honk proof from `assert_statement_recursive`. -fn main( - verification_key: [Field; 103], - // This is the proof without public inputs attached. - // - // This means: the size of this does not change with the number of public inputs. - proof: [Field; 153], - public_inputs: pub [Field; 1], - // This is currently not public. It is fine given that the vk is a part of the circuit definition. - // I believe we want to eventually make it public too though. - key_hash: Field -) { - std::verify_proof( - verification_key.as_slice(), - proof.as_slice(), - public_inputs.as_slice(), - key_hash - ); -} diff --git a/noir/noir-repo/test_programs/noir_test_success/bounded_vec/src/main.nr b/noir/noir-repo/test_programs/noir_test_success/bounded_vec/src/main.nr index 22ec291f9d6..e5aa5f88a94 100644 --- a/noir/noir-repo/test_programs/noir_test_success/bounded_vec/src/main.nr +++ b/noir/noir-repo/test_programs/noir_test_success/bounded_vec/src/main.nr @@ -63,6 +63,33 @@ fn sum_of_first_three(v: BoundedVec) -> u32 { } // docs:end:get_unchecked_example +#[test(should_fail)] +// docs:start:set_unchecked_example +fn set_unchecked_example() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([1, 2]); + + // Here we're safely writing within the valid range of `vec` + // `vec` now has the value [42, 2] + vec.set_unchecked(0, 42); + + // We can then safely read this value back out of `vec`. + // Notice that we use the checked version of `get` which would prevent reading unsafe values. + assert_eq(vec.get(0), 42); + + // We've now written past the end of `vec`. + // As this index is still within the maximum potential length of `v`, + // it won't cause a constraint failure. + vec.set_unchecked(2, 42); + println(vec); + + // This will write past the end of the maximum potential length of `vec`, + // it will then trigger a constraint failure. + vec.set_unchecked(5, 42); + println(vec); +} +// docs:end:set_unchecked_example + #[test(should_fail_with = "push out of bounds")] fn push_docs_example() { // docs:start:bounded-vec-push-example diff --git a/noir/noir-repo/test_programs/noir_test_success/regression_4561/Nargo.toml b/noir/noir-repo/test_programs/noir_test_success/regression_4561/Nargo.toml new file mode 100644 index 00000000000..90deee74640 --- /dev/null +++ b/noir/noir-repo/test_programs/noir_test_success/regression_4561/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression_4561" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/test_programs/noir_test_success/regression_4561/src/main.nr b/noir/noir-repo/test_programs/noir_test_success/regression_4561/src/main.nr new file mode 100644 index 00000000000..138f7e805b3 --- /dev/null +++ b/noir/noir-repo/test_programs/noir_test_success/regression_4561/src/main.nr @@ -0,0 +1,44 @@ +// Regression test for issue #4561 +use dep::std::test::OracleMock; + +type TReturnElem = [Field; 3]; +type TReturn = [TReturnElem; 2]; + +#[oracle(simple_nested_return)] +unconstrained fn simple_nested_return_oracle() -> TReturn {} + +unconstrained fn simple_nested_return_unconstrained() -> TReturn { + simple_nested_return_oracle() +} + +#[test] +fn test_simple_nested_return() { + OracleMock::mock("simple_nested_return").returns([1, 2, 3, 4, 5, 6]); + assert_eq(simple_nested_return_unconstrained(), [[1, 2, 3], [4, 5, 6]]); +} + +#[oracle(nested_with_fields_return)] +unconstrained fn nested_with_fields_return_oracle() -> (Field, TReturn, Field) {} + +unconstrained fn nested_with_fields_return_unconstrained() -> (Field, TReturn, Field) { + nested_with_fields_return_oracle() +} + +#[test] +fn test_nested_with_fields_return() { + OracleMock::mock("nested_with_fields_return").returns((0, [1, 2, 3, 4, 5, 6], 7)); + assert_eq(nested_with_fields_return_unconstrained(), (0, [[1, 2, 3], [4, 5, 6]], 7)); +} + +#[oracle(two_nested_return)] +unconstrained fn two_nested_return_oracle() -> (Field, TReturn, Field, TReturn) {} + +unconstrained fn two_nested_return_unconstrained() -> (Field, TReturn, Field, TReturn) { + two_nested_return_oracle() +} + +#[test] +fn two_nested_return() { + OracleMock::mock("two_nested_return").returns((0, [1, 2, 3, 4, 5, 6], 7, [1, 2, 3, 4, 5, 6])); + assert_eq(two_nested_return_unconstrained(), (0, [[1, 2, 3], [4, 5, 6]], 7, [[1, 2, 3], [4, 5, 6]])); +} \ No newline at end of file diff --git a/noir/noir-repo/tooling/debugger/ignored-tests.txt b/noir/noir-repo/tooling/debugger/ignored-tests.txt index a9193896589..a3971d437fb 100644 --- a/noir/noir-repo/tooling/debugger/ignored-tests.txt +++ b/noir/noir-repo/tooling/debugger/ignored-tests.txt @@ -11,7 +11,8 @@ fold_distinct_return fold_fibonacci fold_numeric_generic_poseidon is_unconstrained +macros modulus references regression_4709 -to_bytes_integration \ No newline at end of file +to_bytes_integration diff --git a/noir/noir-repo/tooling/nargo_cli/build.rs b/noir/noir-repo/tooling/nargo_cli/build.rs index fcc09653c7d..846160320cf 100644 --- a/noir/noir-repo/tooling/nargo_cli/build.rs +++ b/noir/noir-repo/tooling/nargo_cli/build.rs @@ -42,22 +42,27 @@ fn main() { /// These should be fixed and removed from this list. const IGNORED_BRILLIG_TESTS: [&str; 11] = [ // Takes a very long time to execute as large loops do not get simplified. - &"regression_4709", + "regression_4709", // bit sizes for bigint operation doesn't match up. - &"bigint", + "bigint", // ICE due to looking for function which doesn't exist. - &"fold_after_inlined_calls", - &"fold_basic", - &"fold_basic_nested_call", - &"fold_call_witness_condition", - &"fold_complex_outputs", - &"fold_distinct_return", - &"fold_fibonacci", - &"fold_numeric_generic_poseidon", + "fold_after_inlined_calls", + "fold_basic", + "fold_basic_nested_call", + "fold_call_witness_condition", + "fold_complex_outputs", + "fold_distinct_return", + "fold_fibonacci", + "fold_numeric_generic_poseidon", // Expected to fail as test asserts on which runtime it is in. - &"is_unconstrained", + "is_unconstrained", ]; +/// Certain comptime features are only available in the elaborator. +/// We skip these tests for non-elaborator code since they are not +/// expected to work there. This can be removed once the old code is removed. +const IGNORED_COMPTIME_TESTS: [&str; 1] = ["macros"]; + fn generate_execution_success_tests(test_file: &mut File, test_data_dir: &Path) { let test_sub_dir = "execution_success"; let test_data_dir = test_data_dir.join(test_sub_dir); @@ -281,10 +286,13 @@ fn generate_compile_success_empty_tests(test_file: &mut File, test_data_dir: &Pa }; let test_dir = &test_dir.path(); + let comptime_ignored = + if IGNORED_COMPTIME_TESTS.contains(&test_name.as_str()) { "\n#[ignore]" } else { "" }; + write!( test_file, r#" -#[test] +#[test]{comptime_ignored} fn compile_success_empty_{test_name}() {{ let test_program_dir = PathBuf::from("{test_dir}"); diff --git a/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs b/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs index 0bb967e7502..70857b4b65e 100644 --- a/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs +++ b/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs @@ -1,6 +1,8 @@ +use std::io::Write; use std::{collections::BTreeMap, path::PathBuf}; use acvm::blackbox_solver::StubbedBlackBoxSolver; +use fm::FileManager; use noirc_driver::{check_crate, file_manager_with_stdlib, CompileOptions}; use noirc_frontend::hir::FunctionNameMatch; @@ -9,6 +11,7 @@ use nargo::{ package::{Package, PackageType}, parse_all, prepare_package, }; +use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; #[test] fn run_stdlib_tests() { @@ -23,7 +26,7 @@ fn run_stdlib_tests() { root_dir: PathBuf::from("."), package_type: PackageType::Binary, entry_path: PathBuf::from("main.nr"), - name: "dummy".parse().unwrap(), + name: "stdlib".parse().unwrap(), dependencies: BTreeMap::new(), }; @@ -58,5 +61,85 @@ fn run_stdlib_tests() { .collect(); assert!(!test_report.is_empty(), "Could not find any tests within the stdlib"); + display_test_report(&file_manager, &dummy_package, &CompileOptions::default(), &test_report); assert!(test_report.iter().all(|(_, status)| !status.failed())); } + +// This code is copied from `src/cli/test_cmd.rs`. +// This should be abstracted into a proper test runner at some point. +fn display_test_report( + file_manager: &FileManager, + package: &Package, + compile_options: &CompileOptions, + test_report: &[(String, TestStatus)], +) { + let writer = StandardStream::stderr(ColorChoice::Always); + let mut writer = writer.lock(); + + for (test_name, test_status) in test_report { + write!(writer, "[{}] Testing {test_name}... ", package.name) + .expect("Failed to write to stderr"); + writer.flush().expect("Failed to flush writer"); + + match &test_status { + TestStatus::Pass { .. } => { + writer + .set_color(ColorSpec::new().set_fg(Some(Color::Green))) + .expect("Failed to set color"); + writeln!(writer, "ok").expect("Failed to write to stderr"); + } + TestStatus::Fail { message, error_diagnostic } => { + writer + .set_color(ColorSpec::new().set_fg(Some(Color::Red))) + .expect("Failed to set color"); + writeln!(writer, "FAIL\n{message}\n").expect("Failed to write to stderr"); + if let Some(diag) = error_diagnostic { + noirc_errors::reporter::report_all( + file_manager.as_file_map(), + &[diag.clone()], + compile_options.deny_warnings, + compile_options.silence_warnings, + ); + } + } + TestStatus::CompileError(err) => { + noirc_errors::reporter::report_all( + file_manager.as_file_map(), + &[err.clone()], + compile_options.deny_warnings, + compile_options.silence_warnings, + ); + } + } + writer.reset().expect("Failed to reset writer"); + } + + write!(writer, "[{}] ", package.name).expect("Failed to write to stderr"); + + let count_all = test_report.len(); + let count_failed = test_report.iter().filter(|(_, status)| status.failed()).count(); + let plural = if count_all == 1 { "" } else { "s" }; + if count_failed == 0 { + writer.set_color(ColorSpec::new().set_fg(Some(Color::Green))).expect("Failed to set color"); + write!(writer, "{count_all} test{plural} passed").expect("Failed to write to stderr"); + writer.reset().expect("Failed to reset writer"); + writeln!(writer).expect("Failed to write to stderr"); + } else { + let count_passed = count_all - count_failed; + let plural_failed = if count_failed == 1 { "" } else { "s" }; + let plural_passed = if count_passed == 1 { "" } else { "s" }; + + if count_passed != 0 { + writer + .set_color(ColorSpec::new().set_fg(Some(Color::Green))) + .expect("Failed to set color"); + write!(writer, "{count_passed} test{plural_passed} passed, ",) + .expect("Failed to write to stderr"); + } + + writer.set_color(ColorSpec::new().set_fg(Some(Color::Red))).expect("Failed to set color"); + writeln!(writer, "{count_failed} test{plural_failed} failed") + .expect("Failed to write to stderr"); + writer.reset().expect("Failed to reset writer"); + } +} diff --git a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/expr.rs b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/expr.rs index 7ff943aea62..ec8ac4abec7 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/expr.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/expr.rs @@ -63,7 +63,8 @@ pub(crate) fn rewrite( NewlineMode::IfContainsNewLineAndWidth, ); - format!("{callee}{args}") + let bang = if call_expr.is_macro_call { "!" } else { "" }; + format!("{callee}{bang}{args}") } ExpressionKind::MethodCall(method_call_expr) => { let args_span = visitor.span_before( @@ -85,7 +86,8 @@ pub(crate) fn rewrite( NewlineMode::IfContainsNewLineAndWidth, ); - format!("{object}.{method}{turbofish}{args}") + let bang = if method_call_expr.is_macro_call { "!" } else { "" }; + format!("{object}.{method}{turbofish}{bang}{args}") } ExpressionKind::MemberAccess(member_access_expr) => { let lhs_str = rewrite_sub_expr(visitor, shape, member_access_expr.lhs); @@ -166,7 +168,9 @@ pub(crate) fn rewrite( format!("{path_string}{turbofish}") } ExpressionKind::Lambda(_) => visitor.slice(span).to_string(), - ExpressionKind::Quote(block) => format!("quote {}", rewrite_block(visitor, block, span)), + ExpressionKind::Quote(block, block_span) => { + format!("quote {}", rewrite_block(visitor, block, block_span)) + } ExpressionKind::Comptime(block, block_span) => { format!("comptime {}", rewrite_block(visitor, block, block_span)) } @@ -174,6 +178,14 @@ pub(crate) fn rewrite( ExpressionKind::Resolved(_) => { unreachable!("ExpressionKind::Resolved should only emitted by the comptime interpreter") } + ExpressionKind::Unquote(expr) => { + if matches!(&expr.kind, ExpressionKind::Variable(..)) { + format!("${expr}") + } else { + format!("$({})", rewrite_sub_expr(visitor, shape, *expr)) + } + } + ExpressionKind::UnquoteMarker(_) => unreachable!("UnquoteMarker in runtime code"), } } diff --git a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/typ.rs b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/typ.rs index 278457f82d1..3ad1d9302be 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/typ.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/typ.rs @@ -64,7 +64,7 @@ pub(crate) fn rewrite(visitor: &FmtVisitor, _shape: Shape, typ: UnresolvedType) | UnresolvedTypeData::Expression(_) | UnresolvedTypeData::String(_) | UnresolvedTypeData::FormatString(_, _) - | UnresolvedTypeData::Code + | UnresolvedTypeData::Expr | UnresolvedTypeData::TraitAsType(_, _) => visitor.slice(typ.span.unwrap()).into(), UnresolvedTypeData::Error => unreachable!(), } diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/expected/let.nr b/noir/noir-repo/tooling/nargo_fmt/tests/expected/let.nr index c57801155a0..7ff69e74306 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/expected/let.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/expected/let.nr @@ -44,12 +44,12 @@ fn let_() { } }; - let expr = Expr { + let expr = MyExpr { // A boolean literal (true, false). kind: ExprKind::Bool(true) }; - let expr = Expr { /*A boolean literal (true, false).*/ kind: ExprKind::Bool(true) }; + let expr = MyExpr { /*A boolean literal (true, false).*/ kind: ExprKind::Bool(true) }; let mut V = dep::crate2::MyStruct { Q: x }; let mut V = dep::crate2::MyStruct {}; diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/input/let.nr b/noir/noir-repo/tooling/nargo_fmt/tests/input/let.nr index 67c4ab8bd52..37cdc6655c7 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/input/let.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/input/let.nr @@ -20,11 +20,11 @@ fn let_() { let person = Person { first_name: "John", last_name: "Doe", home_address: Address { street: "123 Main St", city: "Exampleville", zip_code: "12345", master: Person { first_name: "John", last_name: "Doe", home_address: Address { street: "123 Main St", city: "Exampleville", zip_code: "12345" } } } }; - let expr = Expr {// A boolean literal (true, false). + let expr = MyExpr {// A boolean literal (true, false). kind: ExprKind::Bool(true), }; - let expr = Expr {/*A boolean literal (true, false).*/kind: ExprKind::Bool(true),}; + let expr = MyExpr {/*A boolean literal (true, false).*/kind: ExprKind::Bool(true),}; let mut V = dep::crate2::MyStruct { Q: x }; let mut V = dep::crate2::MyStruct {}; diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json index 35fbd6f438b..af3011068bf 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json @@ -41,7 +41,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "portal:../../../../barretenberg/ts", + "@aztec/bb.js": "0.41.0", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/backend.ts b/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/backend.ts index ce2c2712491..d07681dd8c1 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/backend.ts +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/backend.ts @@ -45,10 +45,7 @@ export class BarretenbergVerifierBackend implements VerifierBackend { const { Barretenberg, RawBuffer, Crs } = await import('@aztec/bb.js'); const api = await Barretenberg.new(this.options); - const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes( - this.acirUncompressedBytecode, - /*honkRecursion=*/ false, // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): Remove this flag - ); + const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes(this.acirUncompressedBytecode); const crs = await Crs.new(subgroupSize + 1); await api.commonInitSlabAllocator(subgroupSize); await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data())); diff --git a/noir/noir-repo/tooling/noirc_abi/Cargo.toml b/noir/noir-repo/tooling/noirc_abi/Cargo.toml index baae2dfa35e..e8f57060367 100644 --- a/noir/noir-repo/tooling/noirc_abi/Cargo.toml +++ b/noir/noir-repo/tooling/noirc_abi/Cargo.toml @@ -11,7 +11,6 @@ license.workspace = true [dependencies] acvm.workspace = true iter-extended.workspace = true -noirc_frontend.workspace = true noirc_printable_type.workspace = true toml.workspace = true serde_json = "1.0" @@ -23,13 +22,10 @@ num-traits = "0.2" [dev-dependencies] strum = "0.24" strum_macros = "0.24" +proptest.workspace = true +proptest-derive.workspace = true + [features] -bn254 = [ - "acvm/bn254", - "noirc_frontend/bn254", -] -bls12_381 = [ - "acvm/bls12_381", - "noirc_frontend/bls12_381", -] \ No newline at end of file +bn254 = ["acvm/bn254"] +bls12_381 = ["acvm/bls12_381"] \ No newline at end of file diff --git a/noir/noir-repo/tooling/noirc_abi/src/arbitrary.rs b/noir/noir-repo/tooling/noirc_abi/src/arbitrary.rs new file mode 100644 index 00000000000..aecb620b79d --- /dev/null +++ b/noir/noir-repo/tooling/noirc_abi/src/arbitrary.rs @@ -0,0 +1,154 @@ +use iter_extended::{btree_map, vecmap}; +use prop::collection::vec; +use proptest::prelude::*; + +use acvm::{AcirField, FieldElement}; + +use crate::{ + input_parser::InputValue, Abi, AbiParameter, AbiReturnType, AbiType, AbiVisibility, InputMap, + Sign, +}; +use std::collections::{BTreeMap, HashSet}; + +pub(super) use proptest_derive::Arbitrary; + +/// Mutates an iterator of mutable references to [`String`]s to ensure that all values are unique. +fn ensure_unique_strings<'a>(iter: impl Iterator) { + let mut seen_values: HashSet = HashSet::default(); + for value in iter { + while seen_values.contains(value.as_str()) { + value.push('1'); + } + seen_values.insert(value.clone()); + } +} + +proptest::prop_compose! { + pub(super) fn arb_field_from_integer(bit_size: u32)(value: u128)-> FieldElement { + let width = (bit_size % 128).clamp(1, 127); + let max_value = 2u128.pow(width) - 1; + FieldElement::from(value.clamp(0, max_value)) + } +} + +fn arb_value_from_abi_type(abi_type: &AbiType) -> SBoxedStrategy { + match abi_type { + AbiType::Field => vec(any::(), 32) + .prop_map(|bytes| InputValue::Field(FieldElement::from_be_bytes_reduce(&bytes))) + .sboxed(), + AbiType::Integer { width, .. } => { + arb_field_from_integer(*width).prop_map(InputValue::Field).sboxed() + } + + AbiType::Boolean => { + any::().prop_map(|val| InputValue::Field(FieldElement::from(val))).sboxed() + } + + AbiType::String { length } => { + // Strings only allow ASCII characters as each character must be able to be represented by a single byte. + let string_regex = format!("[[:ascii:]]{{{length}}}"); + proptest::string::string_regex(&string_regex) + .expect("parsing of regex should always succeed") + .prop_map(InputValue::String) + .sboxed() + } + AbiType::Array { length, typ } => { + let length = *length as usize; + let elements = vec(arb_value_from_abi_type(typ), length..=length); + + elements.prop_map(InputValue::Vec).sboxed() + } + + AbiType::Struct { fields, .. } => { + let fields: Vec> = fields + .iter() + .map(|(name, typ)| (Just(name.clone()), arb_value_from_abi_type(typ)).sboxed()) + .collect(); + + fields + .prop_map(|fields| { + let fields: BTreeMap<_, _> = fields.into_iter().collect(); + InputValue::Struct(fields) + }) + .sboxed() + } + + AbiType::Tuple { fields } => { + let fields: Vec<_> = fields.iter().map(arb_value_from_abi_type).collect(); + fields.prop_map(InputValue::Vec).sboxed() + } + } +} + +fn arb_primitive_abi_type() -> SBoxedStrategy { + const MAX_STRING_LEN: u32 = 1000; + proptest::prop_oneof![ + Just(AbiType::Field), + Just(AbiType::Boolean), + any::<(Sign, u32)>().prop_map(|(sign, width)| { + let width = (width % 128).clamp(1, 127); + AbiType::Integer { sign, width } + }), + // restrict length of strings to avoid running out of memory + (1..MAX_STRING_LEN).prop_map(|length| AbiType::String { length }), + ] + .sboxed() +} + +pub(super) fn arb_abi_type() -> BoxedStrategy { + let leaf = arb_primitive_abi_type(); + + leaf.prop_recursive( + 8, // up to 8 levels deep + 256, // Shoot for maximum size of 256 nodes + 10, // We put up to 10 items per collection + |inner| { + prop_oneof![ + (1..10u32, inner.clone()) + .prop_map(|(length, typ)| { AbiType::Array { length, typ: Box::new(typ) } }) + .boxed(), + prop::collection::vec(inner.clone(), 1..10) + .prop_map(|fields| { AbiType::Tuple { fields } }) + .boxed(), + (".*", prop::collection::vec((".+", inner), 1..10)) + .prop_map(|(path, mut fields)| { + // Require that all field names are unique. + ensure_unique_strings(fields.iter_mut().map(|(field_name, _)| field_name)); + AbiType::Struct { path, fields } + }) + .boxed(), + ] + }, + ) + .boxed() +} + +fn arb_abi_param_and_value() -> BoxedStrategy<(AbiParameter, InputValue)> { + arb_abi_type() + .prop_flat_map(|typ| { + let value = arb_value_from_abi_type(&typ); + let param = arb_abi_param(typ); + (param, value) + }) + .boxed() +} + +fn arb_abi_param(typ: AbiType) -> SBoxedStrategy { + (".+", any::()) + .prop_map(move |(name, visibility)| AbiParameter { name, typ: typ.clone(), visibility }) + .sboxed() +} + +prop_compose! { + pub(super) fn arb_abi_and_input_map() + (mut parameters_with_values in proptest::collection::vec(arb_abi_param_and_value(), 0..100), return_type: Option) + -> (Abi, InputMap) { + // Require that all parameter names are unique. + ensure_unique_strings(parameters_with_values.iter_mut().map(|(param_name,_)| &mut param_name.name)); + + let parameters = vecmap(¶meters_with_values, |(param, _)| param.clone()); + let input_map = btree_map(parameters_with_values, |(param, value)| (param.name, value)); + + (Abi { parameters, return_type, error_types: BTreeMap::default() }, input_map) + } +} diff --git a/noir/noir-repo/tooling/noirc_abi/src/lib.rs b/noir/noir-repo/tooling/noirc_abi/src/lib.rs index 514fac2e73d..b3d80099137 100644 --- a/noir/noir-repo/tooling/noirc_abi/src/lib.rs +++ b/noir/noir-repo/tooling/noirc_abi/src/lib.rs @@ -13,8 +13,6 @@ use acvm::{ use errors::AbiError; use input_parser::InputValue; use iter_extended::{try_btree_map, try_vecmap, vecmap}; -use noirc_frontend::ast::{Signedness, Visibility}; -use noirc_frontend::{hir::Context, Type, TypeBinding, TypeVariableKind}; use noirc_printable_type::{ decode_value as printable_type_decode_value, PrintableType, PrintableValue, PrintableValueDisplay, @@ -27,6 +25,9 @@ use std::{collections::BTreeMap, str}; // // This ABI has nothing to do with ACVM or ACIR. Although they implicitly have a relationship +#[cfg(test)] +mod arbitrary; + pub mod errors; pub mod input_parser; mod serialization; @@ -77,6 +78,7 @@ pub enum AbiType { } #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] #[serde(rename_all = "lowercase")] /// Represents whether the parameter is public or known only to the prover. pub enum AbiVisibility { @@ -87,27 +89,8 @@ pub enum AbiVisibility { DataBus, } -impl From for AbiVisibility { - fn from(value: Visibility) -> Self { - match value { - Visibility::Public => AbiVisibility::Public, - Visibility::Private => AbiVisibility::Private, - Visibility::DataBus => AbiVisibility::DataBus, - } - } -} - -impl From<&Visibility> for AbiVisibility { - fn from(value: &Visibility) -> Self { - match value { - Visibility::Public => AbiVisibility::Public, - Visibility::Private => AbiVisibility::Private, - Visibility::DataBus => AbiVisibility::DataBus, - } - } -} - #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] #[serde(rename_all = "lowercase")] pub enum Sign { Unsigned, @@ -115,70 +98,6 @@ pub enum Sign { } impl AbiType { - pub fn from_type(context: &Context, typ: &Type) -> Self { - // Note; use strict_eq instead of partial_eq when comparing field types - // in this method, you most likely want to distinguish between public and private - match typ { - Type::FieldElement => Self::Field, - Type::Array(size, typ) => { - let length = size - .evaluate_to_u32() - .expect("Cannot have variable sized arrays as a parameter to main"); - let typ = typ.as_ref(); - Self::Array { length, typ: Box::new(Self::from_type(context, typ)) } - } - Type::Integer(sign, bit_width) => { - let sign = match sign { - Signedness::Unsigned => Sign::Unsigned, - Signedness::Signed => Sign::Signed, - }; - - Self::Integer { sign, width: (*bit_width).into() } - } - Type::TypeVariable(binding, TypeVariableKind::IntegerOrField) - | Type::TypeVariable(binding, TypeVariableKind::Integer) => match &*binding.borrow() { - TypeBinding::Bound(typ) => Self::from_type(context, typ), - TypeBinding::Unbound(_) => { - Self::from_type(context, &Type::default_int_or_field_type()) - } - }, - Type::Bool => Self::Boolean, - Type::String(size) => { - let size = size - .evaluate_to_u32() - .expect("Cannot have variable sized strings as a parameter to main"); - Self::String { length: size } - } - - Type::Struct(def, args) => { - let struct_type = def.borrow(); - let fields = struct_type.get_fields(args); - let fields = vecmap(fields, |(name, typ)| (name, Self::from_type(context, &typ))); - // For the ABI, we always want to resolve the struct paths from the root crate - let path = - context.fully_qualified_struct_path(context.root_crate_id(), struct_type.id); - Self::Struct { fields, path } - } - Type::Alias(def, args) => Self::from_type(context, &def.borrow().get_type(args)), - Type::Tuple(fields) => { - let fields = vecmap(fields, |typ| Self::from_type(context, typ)); - Self::Tuple { fields } - } - Type::Error - | Type::Unit - | Type::Constant(_) - | Type::TraitAsType(..) - | Type::TypeVariable(_, _) - | Type::NamedGeneric(..) - | Type::Forall(..) - | Type::Code - | Type::Slice(_) - | Type::Function(_, _, _) => unreachable!("{typ} cannot be used in the abi"), - Type::FmtString(_, _) => unreachable!("format strings cannot be used in the abi"), - Type::MutableReference(_) => unreachable!("&mut cannot be used in the abi"), - } - } - /// Returns the number of field elements required to represent the type once encoded. pub fn field_count(&self) -> u32 { match self { @@ -228,10 +147,12 @@ impl From<&AbiType> for PrintableType { } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] /// An argument or return value of the circuit's `main` function. pub struct AbiParameter { pub name: String, #[serde(rename = "type")] + #[cfg_attr(test, proptest(strategy = "arbitrary::arb_abi_type()"))] pub typ: AbiType, pub visibility: AbiVisibility, } @@ -243,16 +164,20 @@ impl AbiParameter { } #[derive(Clone, Debug, Serialize, Deserialize)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] pub struct AbiReturnType { + #[cfg_attr(test, proptest(strategy = "arbitrary::arb_abi_type()"))] pub abi_type: AbiType, pub visibility: AbiVisibility, } #[derive(Clone, Debug, Serialize, Deserialize)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] pub struct Abi { /// An ordered list of the arguments to the program's `main` function, specifying their types and visibility. pub parameters: Vec, pub return_type: Option, + #[cfg_attr(test, proptest(strategy = "proptest::prelude::Just(BTreeMap::from([]))"))] pub error_types: BTreeMap, } @@ -543,22 +468,6 @@ pub enum AbiErrorType { FmtString { length: u32, item_types: Vec }, Custom(AbiType), } -impl AbiErrorType { - pub fn from_type(context: &Context, typ: &Type) -> Self { - match typ { - Type::FmtString(len, item_types) => { - let length = len.evaluate_to_u32().expect("Cannot evaluate fmt length"); - let Type::Tuple(item_types) = item_types.as_ref() else { - unreachable!("FmtString items must be a tuple") - }; - let item_types = - item_types.iter().map(|typ| AbiType::from_type(context, typ)).collect(); - Self::FmtString { length, item_types } - } - _ => Self::Custom(AbiType::from_type(context, typ)), - } - } -} pub fn display_abi_error( fields: &[F], @@ -590,56 +499,18 @@ pub fn display_abi_error( #[cfg(test)] mod test { - use std::collections::BTreeMap; + use proptest::prelude::*; - use acvm::{AcirField, FieldElement}; + use crate::arbitrary::arb_abi_and_input_map; - use crate::{ - input_parser::InputValue, Abi, AbiParameter, AbiReturnType, AbiType, AbiVisibility, - InputMap, - }; + proptest! { + #[test] + fn encoding_and_decoding_returns_original_witness_map((abi, input_map) in arb_abi_and_input_map()) { + let witness_map = abi.encode(&input_map, None).unwrap(); + let (decoded_inputs, return_value) = abi.decode(&witness_map).unwrap(); - #[test] - fn witness_encoding_roundtrip() { - let abi = Abi { - parameters: vec![ - AbiParameter { - name: "thing1".to_string(), - typ: AbiType::Array { length: 2, typ: Box::new(AbiType::Field) }, - visibility: AbiVisibility::Public, - }, - AbiParameter { - name: "thing2".to_string(), - typ: AbiType::Field, - visibility: AbiVisibility::Public, - }, - ], - return_type: Some(AbiReturnType { - abi_type: AbiType::Field, - visibility: AbiVisibility::Public, - }), - error_types: BTreeMap::default(), - }; - - // Note we omit return value from inputs - let inputs: InputMap = BTreeMap::from([ - ( - "thing1".to_string(), - InputValue::Vec(vec![ - InputValue::Field(FieldElement::one()), - InputValue::Field(FieldElement::one()), - ]), - ), - ("thing2".to_string(), InputValue::Field(FieldElement::zero())), - ]); - - let witness_map = abi.encode(&inputs, None).unwrap(); - let (reconstructed_inputs, return_value) = abi.decode(&witness_map).unwrap(); - - for (key, expected_value) in inputs { - assert_eq!(reconstructed_inputs[&key], expected_value); + prop_assert_eq!(decoded_inputs, input_map); + prop_assert_eq!(return_value, None); } - - assert!(return_value.is_none()); } } diff --git a/noir/noir-repo/yarn.lock b/noir/noir-repo/yarn.lock index 181b6b3b206..a947ec56aba 100644 --- a/noir/noir-repo/yarn.lock +++ b/noir/noir-repo/yarn.lock @@ -221,18 +221,19 @@ __metadata: languageName: node linkType: hard -"@aztec/bb.js@portal:../../../../barretenberg/ts::locator=%40noir-lang%2Fbackend_barretenberg%40workspace%3Atooling%2Fnoir_js_backend_barretenberg": - version: 0.0.0-use.local - resolution: "@aztec/bb.js@portal:../../../../barretenberg/ts::locator=%40noir-lang%2Fbackend_barretenberg%40workspace%3Atooling%2Fnoir_js_backend_barretenberg" +"@aztec/bb.js@npm:0.41.0": + version: 0.41.0 + resolution: "@aztec/bb.js@npm:0.41.0" dependencies: comlink: ^4.4.1 commander: ^10.0.1 debug: ^4.3.4 tslib: ^2.4.0 bin: - bb.js: ./dest/node/main.js + bb.js: dest/node/main.js + checksum: e5e0095eaff3de45726366726337b131bb6ff7cf2cb53be705572c7d6715dae4c948bf86a03cfad68bc98c0c2d83e64cbe3723cc72260c8dbfa262af8cb81f9b languageName: node - linkType: soft + linkType: hard "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.11, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.8.3": version: 7.23.5 @@ -4395,7 +4396,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg" dependencies: - "@aztec/bb.js": "portal:../../../../barretenberg/ts" + "@aztec/bb.js": 0.41.0 "@noir-lang/types": "workspace:*" "@types/node": ^20.6.2 "@types/prettier": ^3 From 2f50ae41847d8f23341ef58cc080dde5424d8407 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Mon, 17 Jun 2024 17:59:37 +0000 Subject: [PATCH 2/2] chore: apply sync fixes --- noir/noir-repo/acvm-repo/acvm_js/build.sh | 2 +- .../noir_js_backend_barretenberg/package.json | 2 +- noir/noir-repo/yarn.lock | 13 ++++++------- noir/scripts/sync-in-fixup.sh | 18 ++++++++++++++++++ 4 files changed, 26 insertions(+), 9 deletions(-) create mode 100755 noir/scripts/sync-in-fixup.sh diff --git a/noir/noir-repo/acvm-repo/acvm_js/build.sh b/noir/noir-repo/acvm-repo/acvm_js/build.sh index 16fb26e55db..c07d2d8a4c1 100755 --- a/noir/noir-repo/acvm-repo/acvm_js/build.sh +++ b/noir/noir-repo/acvm-repo/acvm_js/build.sh @@ -25,7 +25,7 @@ function run_if_available { require_command jq require_command cargo require_command wasm-bindgen -require_command wasm-opt +#require_command wasm-opt self_path=$(dirname "$(readlink -f "$0")") pname=$(cargo read-manifest | jq -r '.name') diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json index af3011068bf..35fbd6f438b 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json @@ -41,7 +41,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "0.41.0", + "@aztec/bb.js": "portal:../../../../barretenberg/ts", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, diff --git a/noir/noir-repo/yarn.lock b/noir/noir-repo/yarn.lock index a947ec56aba..181b6b3b206 100644 --- a/noir/noir-repo/yarn.lock +++ b/noir/noir-repo/yarn.lock @@ -221,19 +221,18 @@ __metadata: languageName: node linkType: hard -"@aztec/bb.js@npm:0.41.0": - version: 0.41.0 - resolution: "@aztec/bb.js@npm:0.41.0" +"@aztec/bb.js@portal:../../../../barretenberg/ts::locator=%40noir-lang%2Fbackend_barretenberg%40workspace%3Atooling%2Fnoir_js_backend_barretenberg": + version: 0.0.0-use.local + resolution: "@aztec/bb.js@portal:../../../../barretenberg/ts::locator=%40noir-lang%2Fbackend_barretenberg%40workspace%3Atooling%2Fnoir_js_backend_barretenberg" dependencies: comlink: ^4.4.1 commander: ^10.0.1 debug: ^4.3.4 tslib: ^2.4.0 bin: - bb.js: dest/node/main.js - checksum: e5e0095eaff3de45726366726337b131bb6ff7cf2cb53be705572c7d6715dae4c948bf86a03cfad68bc98c0c2d83e64cbe3723cc72260c8dbfa262af8cb81f9b + bb.js: ./dest/node/main.js languageName: node - linkType: hard + linkType: soft "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.11, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.8.3": version: 7.23.5 @@ -4396,7 +4395,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg" dependencies: - "@aztec/bb.js": 0.41.0 + "@aztec/bb.js": "portal:../../../../barretenberg/ts" "@noir-lang/types": "workspace:*" "@types/node": ^20.6.2 "@types/prettier": ^3 diff --git a/noir/scripts/sync-in-fixup.sh b/noir/scripts/sync-in-fixup.sh new file mode 100755 index 00000000000..ba3c591eac4 --- /dev/null +++ b/noir/scripts/sync-in-fixup.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -eu + +cd $(dirname $0)/../noir-repo + +tmp=$(mktemp) +BACKEND_BARRETENBERG_PACKAGE_JSON=./tooling/noir_js_backend_barretenberg/package.json + +jq -r '.dependencies."@aztec/bb.js"' $BACKEND_BARRETENBERG_PACKAGE_JSON > ../bb-version +jq '.dependencies."@aztec/bb.js" = "portal:../../../../barretenberg/ts"' $BACKEND_BARRETENBERG_PACKAGE_JSON > $tmp && mv $tmp $BACKEND_BARRETENBERG_PACKAGE_JSON + +# This script runs in CI which enforces immutable installs by default, +# we then must turn this off in order to update yarn.lock. +YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install + +# Remove requirement for `wasm-opt` to be installed +sed -i "s/^require_command wasm-opt/#require_command wasm-opt/" ./tooling/noirc_abi_wasm/build.sh +sed -i "s/^require_command wasm-opt/#require_command wasm-opt/" ./acvm-repo/acvm_js/build.sh