From 2918c2314e828fa26f1478ac3a61c5e956ddfc89 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 26 Jun 2024 14:31:24 +0000 Subject: [PATCH] chore: apply sync fixes --- .aztec-sync-commit | 2 +- Cargo.lock | 83 ++- Cargo.toml | 9 +- acvm-repo/brillig_vm/src/lib.rs | 154 ++---- aztec_macros/Cargo.toml | 2 +- aztec_macros/src/lib.rs | 33 +- .../src/transforms/contract_interface.rs | 230 ++++++--- aztec_macros/src/transforms/events.rs | 488 ++++++++++++------ aztec_macros/src/transforms/note_interface.rs | 94 ++-- aztec_macros/src/transforms/storage.rs | 20 +- aztec_macros/src/utils/ast_utils.rs | 7 +- aztec_macros/src/utils/constants.rs | 1 - aztec_macros/src/utils/errors.rs | 6 + compiler/noirc_driver/src/abi_gen.rs | 111 +--- compiler/noirc_driver/src/lib.rs | 4 +- compiler/noirc_errors/src/reporter.rs | 6 +- .../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 +- compiler/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 +- compiler/noirc_frontend/src/ast/expression.rs | 52 +- compiler/noirc_frontend/src/ast/mod.rs | 16 +- compiler/noirc_frontend/src/ast/statement.rs | 7 +- compiler/noirc_frontend/src/debug/mod.rs | 4 - .../src/elaborator/expressions.rs | 106 +--- compiler/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/import.rs | 43 +- .../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 +- compiler/noirc_frontend/src/hir_def/expr.rs | 12 +- compiler/noirc_frontend/src/hir_def/types.rs | 22 +- compiler/noirc_frontend/src/lexer/lexer.rs | 1 - compiler/noirc_frontend/src/lexer/token.rs | 11 +- .../src/monomorphization/mod.rs | 6 +- compiler/noirc_frontend/src/node_interner.rs | 19 +- compiler/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 +- cspell.json | 1 - docs/docs/how_to/how-to-oracles.md | 12 +- docs/docs/noir/concepts/data_types/arrays.md | 4 +- .../docs/noir/concepts/data_types/booleans.md | 4 +- docs/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/docs/noir/standard_library/recursion.md | 8 +- docs/docs/tooling/debugger.md | 2 +- 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 +- docs/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 +- docs/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 +- docs/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 +- docs/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 +- docs/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 +- docs/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 +- noir_stdlib/src/collections/bounded_vec.nr | 104 +--- noir_stdlib/src/collections/vec.nr | 39 -- noir_stdlib/src/compat.nr | 18 +- noir_stdlib/src/hash/mimc.nr | 1 - noir_stdlib/src/hash/poseidon/bn254.nr | 17 - noir_stdlib/src/hash/poseidon2.nr | 2 +- noir_stdlib/src/sha256.nr | 1 - noir_stdlib/src/sha512.nr | 1 - scripts/redo-typo-pr.sh | 32 -- .../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}/Nargo.toml | 2 +- .../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/acvm_cli/Cargo.toml | 2 +- tooling/debugger/ignored-tests.txt | 3 +- tooling/nargo_cli/Cargo.toml | 9 +- 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 +- .../src/backend.ts | 5 +- tooling/noirc_abi/Cargo.toml | 14 +- tooling/noirc_abi/src/arbitrary.rs | 154 ------ tooling/noirc_abi/src/lib.rs | 171 +++++- tooling/noirc_abi_wasm/build.sh | 2 +- tooling/profiler/Cargo.toml | 42 ++ .../profiler/src/cli/gates_flamegraph_cmd.rs | 486 +++++++++++++++++ tooling/profiler/src/cli/mod.rs | 33 ++ tooling/profiler/src/main.rs | 35 ++ 265 files changed, 2544 insertions(+), 3335 deletions(-) delete mode 100644 compiler/noirc_frontend/src/elaborator/unquote.rs delete mode 100644 compiler/noirc_frontend/src/hir/comptime/interpreter/unquote.rs delete mode 100755 scripts/redo-typo-pr.sh delete mode 100644 test_programs/compile_success_empty/macros/src/main.nr delete mode 100644 test_programs/compile_success_empty/no_duplicate_methods/Nargo.toml delete mode 100644 test_programs/compile_success_empty/no_duplicate_methods/Prover.toml delete mode 100644 test_programs/compile_success_empty/no_duplicate_methods/src/main.nr delete mode 100644 test_programs/execution_success/regression_5202/Nargo.toml delete mode 100644 test_programs/execution_success/regression_5202/fraction/LICENSE delete mode 100644 test_programs/execution_success/regression_5202/fraction/Nargo.toml delete mode 100644 test_programs/execution_success/regression_5202/fraction/README.md delete mode 100644 test_programs/execution_success/regression_5202/fraction/src/lib.nr delete mode 100644 test_programs/execution_success/regression_5202/src/main.nr delete mode 100644 test_programs/execution_success/regression_5252/Nargo.toml delete mode 100644 test_programs/execution_success/regression_5252/Prover.toml delete mode 100644 test_programs/execution_success/regression_5252/src/main.nr rename test_programs/{compile_success_empty/macros => execution_success/verify_honk_proof}/Nargo.toml (75%) create mode 100644 test_programs/execution_success/verify_honk_proof/Prover.toml create mode 100644 test_programs/execution_success/verify_honk_proof/src/main.nr delete mode 100644 test_programs/noir_test_success/regression_4561/Nargo.toml delete mode 100644 test_programs/noir_test_success/regression_4561/src/main.nr delete mode 100644 tooling/noirc_abi/src/arbitrary.rs create mode 100644 tooling/profiler/Cargo.toml create mode 100644 tooling/profiler/src/cli/gates_flamegraph_cmd.rs create mode 100644 tooling/profiler/src/cli/mod.rs create mode 100644 tooling/profiler/src/main.rs diff --git a/.aztec-sync-commit b/.aztec-sync-commit index bdaabc69727..d1e571cab5c 100644 --- a/.aztec-sync-commit +++ b/.aztec-sync-commit @@ -1 +1 @@ -12af650f0d27c37dca06bb329bf76a5574534d78 +9be0ad6b41a69c35ad9737d60da7a16300b87642 diff --git a/Cargo.lock b/Cargo.lock index 7b96737f241..50b65919f1e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -451,6 +451,7 @@ dependencies = [ "noirc_errors", "noirc_frontend", "regex", + "tiny-keccak", ] [[package]] @@ -1186,6 +1187,19 @@ dependencies = [ "syn 2.0.64", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if 1.0.0", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core 0.9.8", +] + [[package]] name = "debugid" version = "0.8.0" @@ -1382,6 +1396,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "log", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -2017,12 +2040,17 @@ dependencies = [ [[package]] name = "inferno" -version = "0.11.15" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fb7c1b80a1dfa604bb4a649a5c5aeef3d913f7c520cb42b40e534e8a61bcdfc" +checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9" dependencies = [ "ahash 0.8.11", - "indexmap 1.9.3", + "clap", + "crossbeam-channel", + "crossbeam-utils", + "dashmap", + "env_logger", + "indexmap 2.2.6", "is-terminal", "itoa", "log", @@ -2698,6 +2726,29 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "noir_profiler" +version = "0.30.0" +dependencies = [ + "acir", + "clap", + "codespan-reporting", + "color-eyre", + "const_format", + "fm", + "im", + "inferno", + "nargo", + "noirc_abi", + "noirc_driver", + "noirc_errors", + "serde", + "serde_json", + "tempfile", + "tracing-appender", + "tracing-subscriber", +] + [[package]] name = "noir_wasm" version = "0.30.0" @@ -2727,11 +2778,10 @@ version = "0.30.0" dependencies = [ "acvm", "iter-extended", + "noirc_frontend", "noirc_printable_type", "num-bigint", "num-traits", - "proptest", - "proptest-derive", "serde", "serde_json", "strum", @@ -3331,9 +3381,9 @@ dependencies = [ [[package]] name = "proptest" -version = "1.4.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +checksum = "7c003ac8c77cb07bb74f5f198bce836a689bcd5a42574612bf14d17bfd08c20e" dependencies = [ "bit-set", "bit-vec", @@ -3343,23 +3393,12 @@ dependencies = [ "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax 0.8.2", + "regex-syntax 0.7.4", "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" @@ -3591,6 +3630,12 @@ 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/Cargo.toml b/Cargo.toml index 639807819ab..be4cd81ab58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ members = [ "tooling/noirc_abi", "tooling/noirc_abi_wasm", "tooling/acvm_cli", + "tooling/profiler", # ACVM "acvm-repo/acir_field", "acvm-repo/acir", @@ -34,7 +35,7 @@ members = [ # Utility crates "utils/iter-extended", ] -default-members = ["tooling/nargo_cli", "tooling/acvm_cli"] +default-members = ["tooling/nargo_cli", "tooling/acvm_cli", "tooling/profiler"] resolver = "2" [workspace.package] @@ -80,7 +81,7 @@ acvm_cli = { path = "tooling/acvm_cli" } # Arkworks ark-bn254 = { version = "^0.4.0", default-features = false, features = ["curve"] } ark-bls12-381 = { version = "^0.4.0", default-features = false, features = ["curve"] } -grumpkin = { version = "0.1.0", package = "noir_grumpkin", features = ["std"] } +grumpkin = { version = "0.1.0", package = "noir_grumpkin", features = ["std"] } ark-ec = { version = "^0.4.0", default-features = false } ark-ff = { version = "^0.4.0", default-features = false } ark-std = { version = "^0.4.0", default-features = false } @@ -139,11 +140,9 @@ similar-asserts = "1.5.0" tempfile = "3.6.0" jsonrpc = { version = "0.16.0", features = ["minreq_http"] } flate2 = "1.0.24" +color-eyre = "0.6.2" rand = "0.8.5" proptest = "1.2.0" -proptest-derive = "0.4.0" - - im = { version = "15.1", features = ["serde"] } tracing = "0.1.40" tracing-web = "0.1.3" diff --git a/acvm-repo/brillig_vm/src/lib.rs b/acvm-repo/brillig_vm/src/lib.rs index 862162ddccf..da9a34f1044 100644 --- a/acvm-repo/brillig_vm/src/lib.rs +++ b/acvm-repo/brillig_vm/src/lib.rs @@ -482,64 +482,60 @@ 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)?; + (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:?}") + ), } - _ => 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()); + ( + 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()); } - 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"); } - } 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()); + } + ( + 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"); } - } else { - unimplemented!("deflattening heap vectors from foreign calls"); + } + _ => { + return Err(format!("Unexpected value type {value_type:?} for destination {destination:?}")); } } - _ => { - return Err(format!("Unexpected value type {value_type:?} for destination {destination:?}")); - } - } } let _ = @@ -600,66 +596,6 @@ 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/aztec_macros/Cargo.toml b/aztec_macros/Cargo.toml index ed70066af22..a99a654aeed 100644 --- a/aztec_macros/Cargo.toml +++ b/aztec_macros/Cargo.toml @@ -16,4 +16,4 @@ noirc_errors.workspace = true iter-extended.workspace = true convert_case = "0.6.0" regex = "1.10" - +tiny-keccak = { version = "2.0.0", features = ["keccak"] } diff --git a/aztec_macros/src/lib.rs b/aztec_macros/src/lib.rs index a36b7b17d09..580a132aa5a 100644 --- a/aztec_macros/src/lib.rs +++ b/aztec_macros/src/lib.rs @@ -7,7 +7,7 @@ use transforms::{ contract_interface::{ generate_contract_interface, stub_function, update_fn_signatures_in_contract_interface, }, - events::{generate_selector_impl, transform_events}, + events::{generate_event_impls, transform_event_abi}, functions::{ check_for_public_args, export_fn_abi, transform_function, transform_unconstrained, }, @@ -65,19 +65,14 @@ fn transform( // Usage -> mut ast -> aztec_library::transform(&mut ast) // Covers all functions in the ast for submodule in ast.submodules.iter_mut().filter(|submodule| submodule.is_contract) { - if transform_module( - crate_id, - &file_id, - context, - &mut submodule.contents, - submodule.name.0.contents.as_str(), - ) - .map_err(|err| (err.into(), file_id))? + if transform_module(&file_id, &mut submodule.contents, submodule.name.0.contents.as_str()) + .map_err(|err| (err.into(), file_id))? { check_for_aztec_dependency(crate_id, context)?; } } + generate_event_impls(&mut ast).map_err(|err| (err.into(), file_id))?; generate_note_interface_impl(&mut ast).map_err(|err| (err.into(), file_id))?; Ok(ast) @@ -87,9 +82,7 @@ fn transform( /// For annotated functions it calls the `transform` function which will perform the required transformations. /// Returns true if an annotated node is found, false otherwise fn transform_module( - crate_id: &CrateId, file_id: &FileId, - context: &HirContext, module: &mut SortedModule, module_name: &str, ) -> Result { @@ -106,19 +99,7 @@ fn transform_module( if !check_for_storage_implementation(module, storage_struct_name) { generate_storage_implementation(module, storage_struct_name)?; } - // Make sure we're only generating the storage layout for the root crate - // In case we got a contract importing other contracts for their interface, we - // don't want to generate the storage layout for them - if crate_id == context.root_crate_id() { - generate_storage_layout(module, storage_struct_name.clone())?; - } - } - - for structure in module.types.iter_mut() { - if structure.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(event)")) { - module.impls.push(generate_selector_impl(structure)); - has_transformed_module = true; - } + generate_storage_layout(module, storage_struct_name.clone(), module_name)?; } let has_initializer = module.functions.iter().any(|func| { @@ -219,7 +200,7 @@ fn transform_module( }); } - generate_contract_interface(module, module_name, &stubs)?; + generate_contract_interface(module, module_name, &stubs, storage_defined)?; } Ok(has_transformed_module) @@ -235,7 +216,7 @@ fn transform_hir( context: &mut HirContext, ) -> Result<(), (AztecMacroError, FileId)> { if has_aztec_dependency(crate_id, context) { - transform_events(crate_id, context)?; + transform_event_abi(crate_id, context)?; inject_compute_note_hash_and_optionally_a_nullifier(crate_id, context)?; assign_storage_slots(crate_id, context)?; inject_note_exports(crate_id, context)?; diff --git a/aztec_macros/src/transforms/contract_interface.rs b/aztec_macros/src/transforms/contract_interface.rs index 90f9ce6164a..8b763dfcc57 100644 --- a/aztec_macros/src/transforms/contract_interface.rs +++ b/aztec_macros/src/transforms/contract_interface.rs @@ -61,11 +61,7 @@ pub fn stub_function(aztec_visibility: &str, func: &NoirFunction, is_static_call let parameters = func.parameters(); let is_void = if matches!(fn_return_type.typ, UnresolvedTypeData::Unit) { "Void" } else { "" }; let is_static = if is_static_call { "Static" } else { "" }; - let return_type_hint = if is_void == "Void" { - "".to_string() - } else { - format!("<{}>", fn_return_type.typ.to_string().replace("plain::", "")) - }; + let return_type_hint = fn_return_type.typ.to_string().replace("plain::", ""); let call_args = parameters .iter() .map(|arg| { @@ -73,22 +69,67 @@ pub fn stub_function(aztec_visibility: &str, func: &NoirFunction, is_static_call match &arg.typ.typ { UnresolvedTypeData::Array(_, typ) => { format!( - "let hash_{0} = {0}.map(|x: {1}| x.serialize()); - for i in 0..{0}.len() {{ - args_acc = args_acc.append(hash_{0}[i].as_slice()); - }}\n", + "let serialized_{0} = {0}.map(|x: {1}| x.serialize()); + for i in 0..{0}.len() {{ + args_acc = args_acc.append(serialized_{0}[i].as_slice()); + }}\n", param_name, typ.typ.to_string().replace("plain::", "") ) } - _ => { + UnresolvedTypeData::Named(_, _, _) | UnresolvedTypeData::String(_) => { format!("args_acc = args_acc.append({}.serialize().as_slice());\n", param_name) } + _ => { + format!("args_acc = args_acc.append(&[{}.to_field()]);\n", param_name) + } } }) .collect::>() .join(""); - if aztec_visibility != "Public" { + + let param_types = if !parameters.is_empty() { + parameters + .iter() + .map(|param| param.pattern.name_ident().0.contents.clone()) + .collect::>() + .join(", ") + } else { + "".to_string() + }; + + let original = format!( + "| inputs: dep::aztec::context::inputs::{}ContextInputs | -> {} {{ + {}(inputs{}) + }}", + aztec_visibility, + if aztec_visibility == "Private" { + "dep::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs".to_string() + } else { + return_type_hint.clone() + }, + fn_name, + if param_types.is_empty() { "".to_string() } else { format!(" ,{} ", param_types) } + ); + let arg_types = format!( + "({}{})", + parameters + .iter() + .map(|param| param.typ.typ.to_string().replace("plain::", "")) + .collect::>() + .join(","), + // In order to distinguish between a single element Tuple (Type,) and a single type with unnecessary parenthesis around it (Type), + // The latter gets simplified to Type, that is NOT a valid env + if parameters.len() == 1 { "," } else { "" } + ); + + let generics = if is_void == "Void" { + format!("{}>", arg_types) + } else { + format!("{}, {}>", return_type_hint, arg_types) + }; + + let fn_body = if aztec_visibility != "Public" { let args_hash = if !parameters.is_empty() { format!( "let mut args_acc: [Field] = &[]; @@ -98,23 +139,33 @@ pub fn stub_function(aztec_visibility: &str, func: &NoirFunction, is_static_call call_args ) } else { - "let args_hash = 0;".to_string() + " + let mut args_acc: [Field] = &[]; + let args_hash = 0; + " + .to_string() }; - let fn_body = format!( - "{} - dep::aztec::context::{}{}{}CallInterface {{ - target_contract: self.target_contract, - selector: {}, - args_hash, - }}", - args_hash, aztec_visibility, is_static, is_void, fn_selector, - ); format!( - "pub fn {}(self, {}) -> dep::aztec::context::{}{}{}CallInterface{} {{ - {} - }}", - fn_name, fn_parameters, aztec_visibility, is_static, is_void, return_type_hint, fn_body + "{} + let selector = {}; + dep::aztec::context::{}{}{}CallInterface {{ + target_contract: self.target_contract, + selector, + name: \"{}\", + args_hash, + args: args_acc, + original: {}, + is_static: {} + }}", + args_hash, + fn_selector, + aztec_visibility, + is_static, + is_void, + fn_name, + original, + is_static_call ) } else { let args = format!( @@ -123,23 +174,42 @@ pub fn stub_function(aztec_visibility: &str, func: &NoirFunction, is_static_call ", call_args ); - let fn_body = format!( + format!( "{} - dep::aztec::context::Public{}{}CallInterface {{ + let selector = {}; + dep::aztec::context::{}{}{}CallInterface {{ target_contract: self.target_contract, - selector: {}, + selector, + name: \"{}\", args: args_acc, gas_opts: dep::aztec::context::gas::GasOpts::default(), + original: {}, + is_static: {} }}", - args, is_static, is_void, fn_selector, - ); - format!( - "pub fn {}(self, {}) -> dep::aztec::context::Public{}{}CallInterface{} {{ - {} - }}", - fn_name, fn_parameters, is_static, is_void, return_type_hint, fn_body + args, + fn_selector, + aztec_visibility, + is_static, + is_void, + fn_name, + original, + is_static_call ) - } + }; + + format!( + "pub fn {}(self, {}) -> dep::aztec::context::{}{}{}CallInterface<{},{} {{ + {} + }}", + fn_name, + fn_parameters, + aztec_visibility, + is_static, + is_void, + fn_name.len(), + generics, + fn_body + ) } // Generates the contract interface as a struct with an `at` function that holds the stubbed functions and provides @@ -149,7 +219,15 @@ pub fn generate_contract_interface( module: &mut SortedModule, module_name: &str, stubs: &[(String, Location)], + has_storage_layout: bool, ) -> Result<(), AztecMacroError> { + let storage_layout_getter = format!( + "#[contract_library_method] + pub fn storage() -> StorageLayout {{ + {}_STORAGE_LAYOUT + }}", + module_name, + ); let contract_interface = format!( " struct {0} {{ @@ -164,6 +242,12 @@ pub fn generate_contract_interface( ) -> Self {{ Self {{ target_contract }} }} + + pub fn interface() -> Self {{ + Self {{ target_contract: dep::aztec::protocol_types::address::AztecAddress::zero() }} + }} + + {2} }} #[contract_library_method] @@ -172,9 +256,18 @@ pub fn generate_contract_interface( ) -> {0} {{ {0} {{ target_contract }} }} + + #[contract_library_method] + pub fn interface() -> {0} {{ + {0} {{ target_contract: dep::aztec::protocol_types::address::AztecAddress::zero() }} + }} + + {3} ", module_name, stubs.iter().map(|(src, _)| src.to_owned()).collect::>().join("\n"), + if has_storage_layout { storage_layout_getter.clone() } else { "".to_string() }, + if has_storage_layout { format!("#[contract_library_method]\n{}", storage_layout_getter) } else { "".to_string() } ); let (contract_interface_ast, errors) = parse_program(&contract_interface); @@ -191,7 +284,7 @@ pub fn generate_contract_interface( .iter() .enumerate() .map(|(i, (method, orig_span))| { - if method.name() == "at" { + if method.name() == "at" || method.name() == "interface" || method.name() == "storage" { (method.clone(), *orig_span) } else { let (_, new_location) = stubs[i]; @@ -205,7 +298,9 @@ pub fn generate_contract_interface( module.types.push(contract_interface_ast.types.pop().unwrap()); module.impls.push(impl_with_locations); - module.functions.push(contract_interface_ast.functions.pop().unwrap()); + for function in contract_interface_ast.functions { + module.functions.push(function); + } Ok(()) } @@ -244,7 +339,7 @@ pub fn update_fn_signatures_in_contract_interface( let name = context.def_interner.function_name(func_id); let fn_parameters = &context.def_interner.function_meta(func_id).parameters.clone(); - if name == "at" { + if name == "at" || name == "interface" || name == "storage" { continue; } @@ -257,42 +352,29 @@ pub fn update_fn_signatures_in_contract_interface( .collect::>(), ); let hir_func = context.def_interner.function(func_id).block(&context.def_interner); - let call_interface_constructor_statement = context.def_interner.statement( - hir_func - .statements() - .last() - .ok_or((AztecMacroError::AztecDepNotFound, file_id))?, + + let function_selector_statement = context.def_interner.statement( + hir_func.statements().get(hir_func.statements().len() - 2).ok_or(( + AztecMacroError::CouldNotGenerateContractInterface { + secondary_message: Some( + "Function signature statement not found, invalid body length" + .to_string(), + ), + }, + file_id, + ))?, ); - let call_interface_constructor_expression = - match call_interface_constructor_statement { - HirStatement::Expression(expression_id) => { - match context.def_interner.expression(&expression_id) { - HirExpression::Constructor(hir_constructor_expression) => { - Ok(hir_constructor_expression) - } - _ => Err(( - AztecMacroError::CouldNotGenerateContractInterface { - secondary_message: Some( - "CallInterface constructor statement must be a constructor expression" - .to_string(), - ), - }, - file_id, - )), - } - } - _ => Err(( - AztecMacroError::CouldNotGenerateContractInterface { - secondary_message: Some( - "CallInterface constructor statement must be an expression" - .to_string(), - ), - }, - file_id, - )), - }?; - let (_, function_selector_expression_id) = - call_interface_constructor_expression.fields[1]; + let function_selector_expression_id = match function_selector_statement { + HirStatement::Let(let_statement) => Ok(let_statement.expression), + _ => Err(( + AztecMacroError::CouldNotGenerateContractInterface { + secondary_message: Some( + "Function selector statement must be an expression".to_string(), + ), + }, + file_id, + )), + }?; let function_selector_expression = context.def_interner.expression(&function_selector_expression_id); diff --git a/aztec_macros/src/transforms/events.rs b/aztec_macros/src/transforms/events.rs index 69cb6ddafc3..05861b96eb4 100644 --- a/aztec_macros/src/transforms/events.rs +++ b/aztec_macros/src/transforms/events.rs @@ -1,178 +1,333 @@ -use iter_extended::vecmap; -use noirc_errors::Span; -use noirc_frontend::ast::{ - ExpressionKind, FunctionDefinition, FunctionReturnType, ItemVisibility, Literal, NoirFunction, - Visibility, -}; +use noirc_frontend::ast::{ItemVisibility, NoirFunction, NoirTraitImpl, TraitImplItem}; +use noirc_frontend::macros_api::{NodeInterner, StructId}; +use noirc_frontend::token::SecondaryAttribute; use noirc_frontend::{ graph::CrateId, - macros_api::{ - BlockExpression, FileId, HirContext, HirExpression, HirLiteral, HirStatement, NodeInterner, - NoirStruct, PathKind, StatementKind, StructId, StructType, Type, TypeImpl, - UnresolvedTypeData, - }, - token::SecondaryAttribute, + macros_api::{FileId, HirContext}, + parse_program, + parser::SortedModule, }; -use crate::{ - chained_dep, - utils::{ - ast_utils::{ - call, expression, ident, ident_path, is_custom_attribute, make_statement, make_type, - path, variable_path, - }, - constants::SIGNATURE_PLACEHOLDER, - errors::AztecMacroError, - hir_utils::{collect_crate_structs, signature_of_type}, - }, -}; +use crate::utils::hir_utils::collect_crate_structs; +use crate::utils::{ast_utils::is_custom_attribute, errors::AztecMacroError}; + +// Automatic implementation of most of the methods in the EventInterface trait, guiding the user with meaningful error messages in case some +// methods must be implemented manually. +pub fn generate_event_impls(module: &mut SortedModule) -> Result<(), AztecMacroError> { + // Find structs annotated with #[aztec(event)] + // Why doesn't this work ? Events are not tagged and do not appear, it seems only going through the submodule works + // let annotated_event_structs = module + // .types + // .iter_mut() + // .filter(|typ| typ.attributes.iter().any(|attr: &SecondaryAttribute| is_custom_attribute(attr, "aztec(event)"))); + // This did not work because I needed the submodule itself to add the trait impl back in to, but it would be nice if it was tagged on the module level + // let mut annotated_event_structs = module.submodules.iter_mut() + // .flat_map(|submodule| submodule.contents.types.iter_mut()) + // .filter(|typ| typ.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(event)"))); + + // To diagnose + // let test = module.types.iter_mut(); + // for event_struct in test { + // print!("\ngenerate_event_interface_impl COUNT: {}\n", event_struct.name.0.contents); + // } + + for submodule in module.submodules.iter_mut() { + let annotated_event_structs = submodule.contents.types.iter_mut().filter(|typ| { + typ.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(event)")) + }); + + for event_struct in annotated_event_structs { + // event_struct.attributes.push(SecondaryAttribute::Abi("events".to_string())); + // If one impl is pushed, this doesn't throw the "#[abi(tag)] attributes can only be used in contracts" error + // But if more than one impl is pushed, we get an increasing amount of "#[abi(tag)] attributes can only be used in contracts" errors + // We work around this by doing this addition in the HIR pass via transform_event_abi below. + + let event_type = event_struct.name.0.contents.to_string(); + let event_len = event_struct.fields.len() as u32; + // event_byte_len = event fields * 32 + randomness (32) + event_type_id (32) + let event_byte_len = event_len * 32 + 64; + + let mut event_fields = vec![]; + + for (field_ident, field_type) in event_struct.fields.iter() { + event_fields.push(( + field_ident.0.contents.to_string(), + field_type.typ.to_string().replace("plain::", ""), + )); + } -/// Generates the impl for an event selector -/// -/// Inserts the following code: -/// ```noir -/// impl SomeStruct { -/// fn selector() -> FunctionSelector { -/// aztec::protocol_types::abis::function_selector::FunctionSelector::from_signature("SIGNATURE_PLACEHOLDER") -/// } -/// } -/// ``` -/// -/// This allows developers to emit events without having to write the signature of the event every time they emit it. -/// The signature cannot be known at this point since types are not resolved yet, so we use a signature placeholder. -/// It'll get resolved after by transforming the HIR. -pub fn generate_selector_impl(structure: &mut NoirStruct) -> TypeImpl { - structure.attributes.push(SecondaryAttribute::Abi("events".to_string())); - let struct_type = - make_type(UnresolvedTypeData::Named(path(structure.name.clone()), vec![], true)); - - let selector_path = - chained_dep!("aztec", "protocol_types", "abis", "function_selector", "FunctionSelector"); - let mut from_signature_path = selector_path.clone(); - from_signature_path.segments.push(ident("from_signature")); - - let selector_fun_body = BlockExpression { - statements: vec![make_statement(StatementKind::Expression(call( - variable_path(from_signature_path), - vec![expression(ExpressionKind::Literal(Literal::Str( - SIGNATURE_PLACEHOLDER.to_string(), - )))], - )))], - }; - - // Define `FunctionSelector` return type - let return_type = - FunctionReturnType::Ty(make_type(UnresolvedTypeData::Named(selector_path, vec![], true))); - - let mut selector_fn_def = FunctionDefinition::normal( - &ident("selector"), - &vec![], - &[], - &selector_fun_body, - &[], - &return_type, - ); - - selector_fn_def.visibility = ItemVisibility::Public; - - // Seems to be necessary on contract modules - selector_fn_def.return_visibility = Visibility::Public; - - TypeImpl { - object_type: struct_type, - type_span: structure.span, - generics: vec![], - methods: vec![(NoirFunction::normal(selector_fn_def), Span::default())], + let mut event_interface_trait_impl = + generate_trait_impl_stub_event_interface(event_type.as_str(), event_byte_len)?; + event_interface_trait_impl.items.push(TraitImplItem::Function( + generate_fn_get_event_type_id(event_type.as_str(), event_len)?, + )); + event_interface_trait_impl.items.push(TraitImplItem::Function( + generate_fn_private_to_be_bytes(event_type.as_str(), event_byte_len)?, + )); + event_interface_trait_impl.items.push(TraitImplItem::Function( + generate_fn_to_be_bytes(event_type.as_str(), event_byte_len)?, + )); + event_interface_trait_impl + .items + .push(TraitImplItem::Function(generate_fn_emit(event_type.as_str())?)); + submodule.contents.trait_impls.push(event_interface_trait_impl); + + let serialize_trait_impl = + generate_trait_impl_serialize(event_type.as_str(), event_len, &event_fields)?; + submodule.contents.trait_impls.push(serialize_trait_impl); + + let deserialize_trait_impl = + generate_trait_impl_deserialize(event_type.as_str(), event_len, &event_fields)?; + submodule.contents.trait_impls.push(deserialize_trait_impl); + } } + + Ok(()) } -/// Computes the signature for a resolved event type. -/// It has the form 'EventName(Field,(Field),[u8;2])' -fn event_signature(event: &StructType) -> String { - let fields = vecmap(event.get_fields(&[]), |(_, typ)| signature_of_type(&typ)); - format!("{}({})", event.name.0.contents, fields.join(",")) +fn generate_trait_impl_stub_event_interface( + event_type: &str, + byte_length: u32, +) -> Result { + let byte_length_without_randomness = byte_length - 32; + let trait_impl_source = format!( + " +impl dep::aztec::event::event_interface::EventInterface<{byte_length}, {byte_length_without_randomness}> for {event_type} {{ + }} + " + ) + .to_string(); + + let (parsed_ast, errors) = parse_program(&trait_impl_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementEventInterface { + secondary_message: Some(format!("Failed to parse Noir macro code (trait impl of {event_type} for EventInterface). This is either a bug in the compiler or the Noir macro code")), + }); + } + + let mut sorted_ast = parsed_ast.into_sorted(); + let event_interface_impl = sorted_ast.trait_impls.remove(0); + + Ok(event_interface_impl) } -/// Substitutes the signature literal that was introduced in the selector method previously with the actual signature. -fn transform_event( - struct_id: StructId, - interner: &mut NodeInterner, -) -> Result<(), (AztecMacroError, FileId)> { - let struct_type = interner.get_struct(struct_id); - let selector_id = interner - .lookup_method(&Type::Struct(struct_type.clone(), vec![]), struct_id, "selector", false) - .ok_or_else(|| { - let error = AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Selector method not found".to_owned(), - }; - (error, struct_type.borrow().location.file) - })?; - let selector_function = interner.function(&selector_id); - - let compute_selector_statement = interner.statement( - selector_function.block(interner).statements().first().ok_or_else(|| { - let error = AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Compute selector statement not found".to_owned(), - }; - (error, struct_type.borrow().location.file) - })?, - ); - - let compute_selector_expression = match compute_selector_statement { - HirStatement::Expression(expression_id) => match interner.expression(&expression_id) { - HirExpression::Call(hir_call_expression) => Some(hir_call_expression), - _ => None, - }, - _ => None, +fn generate_trait_impl_serialize( + event_type: &str, + event_len: u32, + event_fields: &[(String, String)], +) -> Result { + let field_names = + event_fields.iter().map(|field| format!("self.{}", field.0)).collect::>(); + let field_input = field_names.join(","); + + let trait_impl_source = format!( + " + impl dep::aztec::protocol_types::traits::Serialize<{event_len}> for {event_type} {{ + fn serialize(self: {event_type}) -> [Field; {event_len}] {{ + [{field_input}] + }} + }} + " + ) + .to_string(); + + let (parsed_ast, errors) = parse_program(&trait_impl_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementEventInterface { + secondary_message: Some(format!("Failed to parse Noir macro code (trait impl of Serialize for {event_type}). This is either a bug in the compiler or the Noir macro code")), + }); } - .ok_or_else(|| { - let error = AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Compute selector statement is not a call expression".to_owned(), - }; - (error, struct_type.borrow().location.file) - })?; - - let first_arg_id = compute_selector_expression.arguments.first().ok_or_else(|| { - let error = AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Compute selector statement is not a call expression".to_owned(), - }; - (error, struct_type.borrow().location.file) - })?; - - match interner.expression(first_arg_id) { - HirExpression::Literal(HirLiteral::Str(signature)) - if signature == SIGNATURE_PLACEHOLDER => - { - let selector_literal_id = *first_arg_id; - - let structure = interner.get_struct(struct_id); - let signature = event_signature(&structure.borrow()); - interner.update_expression(selector_literal_id, |expr| { - *expr = HirExpression::Literal(HirLiteral::Str(signature.clone())); - }); - - // Also update the type! It might have a different length now than the placeholder. - interner.push_expr_type( - selector_literal_id, - Type::String(Box::new(Type::Constant(signature.len() as u32))), - ); - Ok(()) - } - _ => Err(( - AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Signature placeholder literal does not match".to_owned(), - }, - struct_type.borrow().location.file, - )), + + let mut sorted_ast = parsed_ast.into_sorted(); + let serialize_impl = sorted_ast.trait_impls.remove(0); + + Ok(serialize_impl) +} + +fn generate_trait_impl_deserialize( + event_type: &str, + event_len: u32, + event_fields: &[(String, String)], +) -> Result { + let field_names: Vec = event_fields + .iter() + .enumerate() + .map(|(index, field)| format!("{}: fields[{}]", field.0, index)) + .collect::>(); + let field_input = field_names.join(","); + + let trait_impl_source = format!( + " + impl dep::aztec::protocol_types::traits::Deserialize<{event_len}> for {event_type} {{ + fn deserialize(fields: [Field; {event_len}]) -> {event_type} {{ + {event_type} {{ {field_input} }} + }} + }} + " + ) + .to_string(); + + let (parsed_ast, errors) = parse_program(&trait_impl_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementEventInterface { + secondary_message: Some(format!("Failed to parse Noir macro code (trait impl of Deserialize for {event_type}). This is either a bug in the compiler or the Noir macro code")), + }); } + + let mut sorted_ast = parsed_ast.into_sorted(); + let deserialize_impl = sorted_ast.trait_impls.remove(0); + + Ok(deserialize_impl) } -pub fn transform_events( +fn generate_fn_get_event_type_id( + event_type: &str, + field_length: u32, +) -> Result { + let from_signature_input = + std::iter::repeat("Field").take(field_length as usize).collect::>().join(","); + let function_source = format!( + " + fn get_event_type_id() -> dep::aztec::protocol_types::abis::event_selector::EventSelector {{ + dep::aztec::protocol_types::abis::event_selector::EventSelector::from_signature(\"{event_type}({from_signature_input})\") + }} + ", + ) + .to_string(); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementEventInterface { + secondary_message: Some(format!("Failed to parse Noir macro code (fn get_event_type_id, implemented for EventInterface of {event_type}). This is either a bug in the compiler or the Noir macro code")), + }); + } + + let mut function_ast = function_ast.into_sorted(); + let mut noir_fn = function_ast.functions.remove(0); + noir_fn.def.visibility = ItemVisibility::Public; + Ok(noir_fn) +} + +fn generate_fn_private_to_be_bytes( + event_type: &str, + byte_length: u32, +) -> Result { + let function_source = format!( + " + fn private_to_be_bytes(self: {event_type}, randomness: Field) -> [u8; {byte_length}] {{ + let mut buffer: [u8; {byte_length}] = [0; {byte_length}]; + + let randomness_bytes = randomness.to_be_bytes(32); + let event_type_id_bytes = {event_type}::get_event_type_id().to_field().to_be_bytes(32); + + for i in 0..32 {{ + buffer[i] = randomness_bytes[i]; + buffer[32 + i] = event_type_id_bytes[i]; + }} + + let serialized_event = self.serialize(); + + for i in 0..serialized_event.len() {{ + let bytes = serialized_event[i].to_be_bytes(32); + for j in 0..32 {{ + buffer[64 + i * 32 + j] = bytes[j]; + }} + }} + + buffer + }} + " + ) + .to_string(); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementEventInterface { + secondary_message: Some(format!("Failed to parse Noir macro code (fn private_to_be_bytes, implemented for EventInterface of {event_type}). This is either a bug in the compiler or the Noir macro code")), + }); + } + + let mut function_ast = function_ast.into_sorted(); + let mut noir_fn = function_ast.functions.remove(0); + noir_fn.def.visibility = ItemVisibility::Public; + Ok(noir_fn) +} + +fn generate_fn_to_be_bytes( + event_type: &str, + byte_length: u32, +) -> Result { + let byte_length_without_randomness = byte_length - 32; + let function_source = format!( + " + fn to_be_bytes(self: {event_type}) -> [u8; {byte_length_without_randomness}] {{ + let mut buffer: [u8; {byte_length_without_randomness}] = [0; {byte_length_without_randomness}]; + + let event_type_id_bytes = {event_type}::get_event_type_id().to_field().to_be_bytes(32); + + for i in 0..32 {{ + buffer[i] = event_type_id_bytes[i]; + }} + + let serialized_event = self.serialize(); + + for i in 0..serialized_event.len() {{ + let bytes = serialized_event[i].to_be_bytes(32); + for j in 0..32 {{ + buffer[32 + i * 32 + j] = bytes[j]; + }} + }} + + buffer + }} + ") + .to_string(); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementEventInterface { + secondary_message: Some(format!("Failed to parse Noir macro code (fn to_be_bytes, implemented for EventInterface of {event_type}). This is either a bug in the compiler or the Noir macro code")), + }); + } + + let mut function_ast = function_ast.into_sorted(); + let mut noir_fn = function_ast.functions.remove(0); + noir_fn.def.visibility = ItemVisibility::Public; + Ok(noir_fn) +} + +fn generate_fn_emit(event_type: &str) -> Result { + let function_source = format!( + " + fn emit(self: {event_type}, _emit: fn[Env](Self) -> ()) {{ + _emit(self); + }} + " + ) + .to_string(); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementEventInterface { + secondary_message: Some(format!("Failed to parse Noir macro code (fn emit, implemented for EventInterface of {event_type}). This is either a bug in the compiler or the Noir macro code")), + }); + } + + let mut function_ast = function_ast.into_sorted(); + let mut noir_fn = function_ast.functions.remove(0); + noir_fn.def.visibility = ItemVisibility::Public; + Ok(noir_fn) +} + +// We do this pass in the HIR to work around the "#[abi(tag)] attributes can only be used in contracts" error +pub fn transform_event_abi( crate_id: &CrateId, context: &mut HirContext, ) -> Result<(), (AztecMacroError, FileId)> { @@ -184,3 +339,14 @@ pub fn transform_events( } Ok(()) } + +fn transform_event( + struct_id: StructId, + interner: &mut NodeInterner, +) -> Result<(), (AztecMacroError, FileId)> { + interner.update_struct_attributes(struct_id, |struct_attributes| { + struct_attributes.push(SecondaryAttribute::Abi("events".to_string())); + }); + + Ok(()) +} diff --git a/aztec_macros/src/transforms/note_interface.rs b/aztec_macros/src/transforms/note_interface.rs index fdce8b81db2..3ace22a89c3 100644 --- a/aztec_macros/src/transforms/note_interface.rs +++ b/aztec_macros/src/transforms/note_interface.rs @@ -11,7 +11,10 @@ use noirc_frontend::{ Type, }; +use acvm::AcirField; use regex::Regex; +// TODO(#7165): nuke the following dependency from here and Cargo.toml +use tiny_keccak::{Hasher, Keccak}; use crate::{ chained_dep, @@ -97,7 +100,6 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt .collect::, _>>()?; let [note_serialized_len, note_bytes_len]: [_; 2] = note_interface_generics.try_into().unwrap(); - let note_type_id = note_type_id(¬e_type); // Automatically inject the header field if it's not present let (header_field_name, _) = if let Some(existing_header) = @@ -184,25 +186,26 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt } if !check_trait_method_implemented(trait_impl, "get_note_type_id") { + let note_type_id = compute_note_type_id(¬e_type); let get_note_type_id_fn = - generate_note_get_type_id(¬e_type_id, note_interface_impl_span)?; + generate_get_note_type_id(note_type_id, note_interface_impl_span)?; trait_impl.items.push(TraitImplItem::Function(get_note_type_id_fn)); } if !check_trait_method_implemented(trait_impl, "compute_note_content_hash") { - let get_header_fn = + let compute_note_content_hash_fn = generate_compute_note_content_hash(¬e_type, note_interface_impl_span)?; - trait_impl.items.push(TraitImplItem::Function(get_header_fn)); + trait_impl.items.push(TraitImplItem::Function(compute_note_content_hash_fn)); } if !check_trait_method_implemented(trait_impl, "to_be_bytes") { - let get_header_fn = generate_note_to_be_bytes( + let to_be_bytes_fn = generate_note_to_be_bytes( ¬e_type, note_bytes_len.as_str(), note_serialized_len.as_str(), note_interface_impl_span, )?; - trait_impl.items.push(TraitImplItem::Function(get_header_fn)); + trait_impl.items.push(TraitImplItem::Function(to_be_bytes_fn)); } } @@ -324,16 +327,17 @@ fn generate_note_set_header( // Automatically generate the note type id getter method. The id itself its calculated as the concatenation // of the conversion of the characters in the note's struct name to unsigned integers. -fn generate_note_get_type_id( - note_type_id: &str, +fn generate_get_note_type_id( + note_type_id: u32, impl_span: Option, ) -> Result { + // TODO(#7165): replace {} with dep::aztec::protocol_types::abis::note_selector::compute_note_selector(\"{}\") in the function source below let function_source = format!( " - fn get_note_type_id() -> Field {{ - {} - }} - ", + fn get_note_type_id() -> Field {{ + {} + }} + ", note_type_id ) .to_string(); @@ -387,7 +391,7 @@ fn generate_note_properties_struct( // Generate the deserialize_content method as // -// fn deserialize_content(serialized_note: [Field; NOTE_SERILIZED_LEN]) -> Self { +// fn deserialize_content(serialized_note: [Field; NOTE_SERIALIZED_LEN]) -> Self { // NoteType { // note_field1: serialized_note[0] as Field, // note_field2: NoteFieldType2::from_field(serialized_note[1])... @@ -525,10 +529,10 @@ fn generate_note_exports_global( let struct_source = format!( " #[abi(notes)] - global {0}_EXPORTS: (Field, str<{1}>) = ({2},\"{0}\"); + global {0}_EXPORTS: (Field, str<{1}>) = (0x{2},\"{0}\"); ", note_type, - note_type_id.len(), + note_type.len(), note_type_id ) .to_string(); @@ -685,10 +689,18 @@ fn generate_note_deserialize_content_source( .to_string() } +// TODO(#7165): nuke this function // Utility function to generate the note type id as a Field -fn note_type_id(note_type: &str) -> String { +fn compute_note_type_id(note_type: &str) -> u32 { // TODO(#4519) Improve automatic note id generation and assignment - note_type.chars().map(|c| (c as u32).to_string()).collect::>().join("") + let mut keccak = Keccak::v256(); + let mut result = [0u8; 32]; + keccak.update(note_type.as_bytes()); + keccak.finalize(&mut result); + // Take the first 4 bytes of the hash and convert them to an integer + // If you change the following value you have to change NUM_BYTES_PER_NOTE_TYPE_ID in l1_note_payload.ts as well + let num_bytes_per_note_type_id = 4; + u32::from_be_bytes(result[0..num_bytes_per_note_type_id].try_into().unwrap()) } pub fn inject_note_exports( @@ -717,29 +729,42 @@ pub fn inject_note_exports( }, file_id, ))?; - let init_function = + let get_note_type_id_function = context.def_interner.function(&func_id).block(&context.def_interner); - let init_function_statement_id = init_function.statements().first().ok_or(( - AztecMacroError::CouldNotExportStorageLayout { - span: None, - secondary_message: Some(format!( - "Could not retrieve note id statement from function for note {}", - note.borrow().name.0.contents - )), - }, - file_id, - ))?; - let note_id_statement = context.def_interner.statement(init_function_statement_id); + let get_note_type_id_statement_id = + get_note_type_id_function.statements().first().ok_or(( + AztecMacroError::CouldNotExportStorageLayout { + span: None, + secondary_message: Some(format!( + "Could not retrieve note id statement from function for note {}", + note.borrow().name.0.contents + )), + }, + file_id, + ))?; + let note_type_id_statement = + context.def_interner.statement(get_note_type_id_statement_id); - let note_id_value = match note_id_statement { + let note_type_id = match note_type_id_statement { HirStatement::Expression(expression_id) => { match context.def_interner.expression(&expression_id) { HirExpression::Literal(HirLiteral::Integer(value, _)) => Ok(value), + HirExpression::Literal(_) => Err(( + AztecMacroError::CouldNotExportStorageLayout { + span: None, + secondary_message: Some( + "note_type_id statement must be a literal integer expression" + .to_string(), + ), + }, + file_id, + )), _ => Err(( AztecMacroError::CouldNotExportStorageLayout { span: None, secondary_message: Some( - "note_id statement must be a literal expression".to_string(), + "note_type_id statement must be a literal expression" + .to_string(), ), }, file_id, @@ -747,9 +772,10 @@ pub fn inject_note_exports( } } _ => Err(( - AztecMacroError::CouldNotAssignStorageSlots { + AztecMacroError::CouldNotExportStorageLayout { + span: None, secondary_message: Some( - "note_id statement must be an expression".to_string(), + "note_type_id statement must be an expression".to_string(), ), }, file_id, @@ -757,7 +783,7 @@ pub fn inject_note_exports( }?; let global = generate_note_exports_global( ¬e.borrow().name.0.contents, - ¬e_id_value.to_string(), + ¬e_type_id.to_hex(), ) .map_err(|err| (err, file_id))?; diff --git a/aztec_macros/src/transforms/storage.rs b/aztec_macros/src/transforms/storage.rs index a1c21c7efcf..bac87502c7d 100644 --- a/aztec_macros/src/transforms/storage.rs +++ b/aztec_macros/src/transforms/storage.rs @@ -497,6 +497,7 @@ pub fn assign_storage_slots( pub fn generate_storage_layout( module: &mut SortedModule, storage_struct_name: String, + module_name: &str, ) -> Result<(), AztecMacroError> { let definition = module .types @@ -504,33 +505,28 @@ pub fn generate_storage_layout( .find(|r#struct| r#struct.name.0.contents == *storage_struct_name) .unwrap(); - let mut generic_args = vec![]; let mut storable_fields = vec![]; let mut storable_fields_impl = vec![]; - definition.fields.iter().enumerate().for_each(|(index, (field_ident, field_type))| { - storable_fields.push(format!("{}: dep::aztec::prelude::Storable", field_ident, index)); - generic_args.push(format!("N{}", index)); - storable_fields_impl.push(format!( - "{}: dep::aztec::prelude::Storable {{ slot: 0, typ: \"{}\" }}", - field_ident, - field_type.to_string().replace("plain::", "") - )); + definition.fields.iter().for_each(|(field_ident, _)| { + storable_fields.push(format!("{}: dep::aztec::prelude::Storable", field_ident)); + storable_fields_impl + .push(format!("{}: dep::aztec::prelude::Storable {{ slot: 0 }}", field_ident,)); }); let storage_fields_source = format!( " - struct StorageLayout<{}> {{ + struct StorageLayout {{ {} }} #[abi(storage)] - global STORAGE_LAYOUT = StorageLayout {{ + global {}_STORAGE_LAYOUT = StorageLayout {{ {} }}; ", - generic_args.join(", "), storable_fields.join(",\n"), + module_name, storable_fields_impl.join(",\n") ); diff --git a/aztec_macros/src/utils/ast_utils.rs b/aztec_macros/src/utils/ast_utils.rs index 48b3b25747b..4706be2df25 100644 --- a/aztec_macros/src/utils/ast_utils.rs +++ b/aztec_macros/src/utils/ast_utils.rs @@ -47,17 +47,12 @@ 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), - is_macro_call: false, - arguments, - }))) + expression(ExpressionKind::Call(Box::new(CallExpression { func: Box::new(func), arguments }))) } pub fn pattern(name: &str) -> Pattern { diff --git a/aztec_macros/src/utils/constants.rs b/aztec_macros/src/utils/constants.rs index 848cca0477d..2178f7a2526 100644 --- a/aztec_macros/src/utils/constants.rs +++ b/aztec_macros/src/utils/constants.rs @@ -1,4 +1,3 @@ pub const FUNCTION_TREE_HEIGHT: u32 = 5; pub const MAX_CONTRACT_PRIVATE_FUNCTIONS: usize = 2_usize.pow(FUNCTION_TREE_HEIGHT); -pub const SIGNATURE_PLACEHOLDER: &str = "SIGNATURE_PLACEHOLDER"; pub const SELECTOR_PLACEHOLDER: &str = "SELECTOR_PLACEHOLDER"; diff --git a/aztec_macros/src/utils/errors.rs b/aztec_macros/src/utils/errors.rs index 852b5f1e57a..557d065cb25 100644 --- a/aztec_macros/src/utils/errors.rs +++ b/aztec_macros/src/utils/errors.rs @@ -14,6 +14,7 @@ pub enum AztecMacroError { CouldNotAssignStorageSlots { secondary_message: Option }, CouldNotImplementComputeNoteHashAndOptionallyANullifier { secondary_message: Option }, CouldNotImplementNoteInterface { span: Option, secondary_message: Option }, + CouldNotImplementEventInterface { secondary_message: Option }, MultipleStorageDefinitions { span: Option }, CouldNotExportStorageLayout { span: Option, secondary_message: Option }, CouldNotInjectContextGenericInStorage { secondary_message: Option }, @@ -67,6 +68,11 @@ impl From for MacroError { secondary_message, span }, + AztecMacroError::CouldNotImplementEventInterface { secondary_message } => MacroError { + primary_message: "Could not implement automatic methods for event, please provide an implementation of the EventInterface trait".to_string(), + secondary_message, + span: None, + }, AztecMacroError::MultipleStorageDefinitions { span } => MacroError { primary_message: "Only one struct can be tagged as #[aztec(storage)]".to_string(), secondary_message: None, diff --git a/compiler/noirc_driver/src/abi_gen.rs b/compiler/noirc_driver/src/abi_gen.rs index c71474d7731..e959c61732a 100644 --- a/compiler/noirc_driver/src/abi_gen.rs +++ b/compiler/noirc_driver/src/abi_gen.rs @@ -1,18 +1,16 @@ use std::collections::BTreeMap; use acvm::acir::circuit::ErrorSelector; +use acvm::AcirField; use iter_extended::vecmap; -use noirc_abi::{ - Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue, AbiVisibility, Sign, -}; -use noirc_frontend::ast::{Signedness, Visibility}; +use noirc_abi::{Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue}; +use noirc_frontend::ast::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`. @@ -23,102 +21,15 @@ 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: to_abi_visibility(return_visibility), - }); + let return_type = return_type + .map(|typ| AbiReturnType { abi_type: typ, visibility: return_visibility.into() }); let error_types = error_types .into_iter() - .map(|(selector, typ)| (selector, build_abi_error_type(context, &typ))) + .map(|(selector, typ)| (selector, AbiErrorType::from_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, @@ -127,7 +38,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| abi_type_from_hir_type(context, &typ)); + let return_type = return_type.map(|typ| AbiType::from_type(context, &typ)); (parameters, return_type) } @@ -147,8 +58,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 = abi_type_from_hir_type(context, &typ); - AbiParameter { name: param_name, typ: as_abi, visibility: to_abi_visibility(vis) } + let as_abi = AbiType::from_type(context, &typ); + AbiParameter { name: param_name, typ: as_abi, visibility: vis.into() } }) } @@ -197,9 +108,7 @@ pub(super) fn value_from_hir_expression(context: &Context, expression: HirExpres }, HirLiteral::Bool(value) => AbiValue::Boolean { value }, HirLiteral::Str(value) => AbiValue::String { value }, - HirLiteral::Integer(field, sign) => { - AbiValue::Integer { value: field.to_string(), sign } - } + HirLiteral::Integer(field, sign) => AbiValue::Integer { value: field.to_hex(), sign }, _ => unreachable!("Literal cannot be used in the abi"), }, _ => unreachable!("Type cannot be used in the abi {:?}", expression), diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index 2c8679eaa95..f8043a60f8c 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -3,7 +3,7 @@ #![warn(unreachable_pub)] #![warn(clippy::semicolon_if_nothing_returned)] -use abi_gen::{abi_type_from_hir_type, value_from_hir_expression}; +use abi_gen::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, abi_type_from_hir_type(context, &typ)) + (name, AbiType::from_type(context, &typ)) }); let path = context.fully_qualified_struct_path(context.root_crate_id(), typ.id); diff --git a/compiler/noirc_errors/src/reporter.rs b/compiler/noirc_errors/src/reporter.rs index cb5abbe2079..42cab72345d 100644 --- a/compiler/noirc_errors/src/reporter.rs +++ b/compiler/noirc_errors/src/reporter.rs @@ -202,14 +202,14 @@ fn stack_trace<'files>( let path = files.name(call_item.file).expect("should get file path"); let source = files.source(call_item.file).expect("should get file source"); - let (line, column) = location(source.as_ref(), call_item.span.start()); + let (line, column) = line_and_column_from_span(source.as_ref(), &call_item.span); result += &format!("{}. {}:{}:{}\n", i + 1, path, line, column); } result } -fn location(source: &str, span_start: u32) -> (u32, u32) { +pub fn line_and_column_from_span(source: &str, span: &Span) -> (u32, u32) { let mut line = 1; let mut column = 0; @@ -221,7 +221,7 @@ fn location(source: &str, span_start: u32) -> (u32, u32) { column = 0; } - if span_start <= i as u32 { + if span.start() <= i as u32 { break; } } diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen.rs index ee61a9d13d3..5576d673f1d 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen.rs @@ -6,17 +6,12 @@ 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/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs index 367cdbe4973..f56c5daf315 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs @@ -1,19 +1,18 @@ use acvm::{ acir::{brillig::BlackBoxOp, BlackBoxFunc}, - AcirField, + FieldElement, }; 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], @@ -342,7 +341,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, F::from(output_id as u128)); + brillig_context.const_instruction(*output, FieldElement::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(), @@ -427,8 +426,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 { @@ -443,8 +442,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, @@ -466,6 +465,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, F::from(output_id as u128)); + brillig_context.const_instruction(*output, FieldElement::from(output_id as u128)); brillig_context.mov_instruction(modulus_id.address, lhs_modulus.address); } diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index b441e8be3eb..1fa4f41b29c 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/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,7 +1737,8 @@ impl<'block> BrilligBlock<'block> { dfg, ); let array = variable.extract_array(); - self.allocate_nested_array(typ, Some(array)); + self.brillig_context.codegen_allocate_fixed_length_array(array.pointer, array.size); + self.brillig_context.usize_const_instruction(array.rc, 1_usize.into()); variable } @@ -1764,43 +1765,6 @@ 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/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs index ffbca256d28..fb9a8577d94 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs @@ -1,4 +1,3 @@ -use acvm::FieldElement; use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; use crate::{ @@ -51,7 +50,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 { @@ -71,7 +70,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 { @@ -84,7 +83,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 @@ -123,7 +122,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 { @@ -155,9 +154,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/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs index ae159f2c45c..74319595795 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs @@ -1,12 +1,13 @@ 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 @@ -27,8 +28,8 @@ pub(crate) fn directive_invert() -> GeneratedBrillig { // Put value zero in register (2) BrilligOpcode::Const { destination: zero_const, - value: F::from(0_usize), - bit_size: F::max_num_bits(), + value: FieldElement::from(0_usize), + bit_size: FieldElement::max_num_bits(), }, BrilligOpcode::BinaryFieldOp { op: BinaryFieldOp::Equals, @@ -41,8 +42,8 @@ pub(crate) fn directive_invert() -> GeneratedBrillig { // Put value one in register (1) BrilligOpcode::Const { destination: one_const, - value: F::one(), - bit_size: F::max_num_bits(), + value: FieldElement::from(1_usize), + bit_size: FieldElement::max_num_bits(), }, // Divide 1 by the input, and set the result of the division into register (0) BrilligOpcode::BinaryFieldOp { @@ -67,13 +68,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 >= F::max_num_bits() { + if bit_size >= FieldElement::max_num_bits() { // Field version GeneratedBrillig { byte_code: vec![ diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs index f0752c80c46..000d1230ece 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs +++ b/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 allocate parameters for all blocks and compute the liveness of every variable. + /// Creates a new function context. It will compute the liveness of every variable. pub(crate) fn new(function: &Function) -> Self { let id = function.id(); diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs index d17b15a13b5..491086e8c0f 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs +++ b/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/compiler/noirc_evaluator/src/brillig/brillig_ir.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs index 9785e073be9..ebccf7a0bf1 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs @@ -25,13 +25,11 @@ mod instructions; pub(crate) use instructions::BrilligBinaryOp; -use self::{ - artifact::BrilligArtifact, debug_show::DebugToString, registers::BrilligRegistersContext, -}; +use self::{artifact::BrilligArtifact, registers::BrilligRegistersContext}; use crate::ssa::ir::dfg::CallStack; use acvm::{ acir::brillig::{MemoryAddress, Opcode as BrilligOpcode}, - AcirField, + FieldElement, }; use debug_show::DebugShow; @@ -78,8 +76,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 @@ -95,9 +93,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(), @@ -115,12 +113,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 } @@ -202,17 +200,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/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs index 2d0bdb5955c..99e922c1580 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs @@ -1,4 +1,4 @@ -use acvm::acir::brillig::Opcode as BrilligOpcode; +use acvm::{acir::brillig::Opcode as BrilligOpcode, FieldElement}; 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/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_binary.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_binary.rs index a9c4f238491..4ef279bd532 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_binary.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_binary.rs @@ -1,8 +1,8 @@ -use acvm::{acir::brillig::MemoryAddress, AcirField}; +use acvm::{acir::brillig::MemoryAddress, FieldElement}; -use super::{debug_show::DebugToString, instructions::BrilligBinaryOp, BrilligContext}; +use super::{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(F::from(constant)); + let const_register = self.make_usize_constant_instruction(FieldElement::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/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs index 2d93cf70181..db65849a6b8 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs @@ -1,11 +1,10 @@ -use acvm::{acir::brillig::MemoryAddress, AcirField}; +use acvm::acir::brillig::MemoryAddress; use super::{ - brillig_variable::BrilligVariable, debug_show::DebugToString, BrilligBinaryOp, BrilligContext, - ReservedRegisters, + brillig_variable::BrilligVariable, 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/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs index 10badcd7308..fee3a450119 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs @@ -1,16 +1,12 @@ -use acvm::{ - acir::brillig::{HeapArray, MemoryAddress}, - AcirField, -}; +use acvm::acir::brillig::{HeapArray, MemoryAddress}; 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. @@ -40,11 +36,10 @@ 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: impl FnOnce(&mut BrilligContext, SingleAddrVariable), - ) { + pub(crate) fn codegen_loop(&mut self, iteration_count: MemoryAddress, on_iteration: F) + where + F: 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(); @@ -92,7 +87,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(); @@ -117,7 +112,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(); @@ -135,7 +130,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(); @@ -161,7 +156,7 @@ impl BrilligContext { let revert_data = HeapArray { pointer: ctx.allocate_register(), // + 1 due to the revert data id being the first item returned - size: Self::flattened_tuple_size(&revert_data_types) + 1, + size: BrilligContext::flattened_tuple_size(&revert_data_types) + 1, }; ctx.codegen_allocate_fixed_length_array(revert_data.pointer, revert_data.size); @@ -174,7 +169,7 @@ impl BrilligContext { for (revert_variable, revert_param) in revert_data_items.into_iter().zip(revert_data_types.into_iter()) { - let flattened_size = Self::flattened_size(&revert_param); + let flattened_size = BrilligContext::flattened_size(&revert_param); match revert_param { BrilligParameter::SingleAddr(_) => { ctx.store_instruction( diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs index b1cb2b19764..42f3b34aea0 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs +++ b/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 == F::max_num_bits()); + assert!(source_field.bit_size == FieldElement::max_num_bits()); self.usize_const_instruction(target_vector.size, limb_count.into()); self.usize_const_instruction(target_vector.rc, 1_usize.into()); @@ -55,10 +55,12 @@ impl BrilligContext { output: HeapArray { pointer: target_vector.pointer, size: limb_count }, }); - let limb_field = SingleAddrVariable::new(self.allocate_register(), F::max_num_bits()); + let limb_field = + SingleAddrVariable::new(self.allocate_register(), FieldElement::max_num_bits()); + let limb_casted = SingleAddrVariable::new(self.allocate_register(), limb_bit_size); - if limb_bit_size != F::max_num_bits() { + if limb_bit_size != FieldElement::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/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs index 81c1c3847b1..15761113f51 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs @@ -1,14 +1,13 @@ -use acvm::{acir::brillig::MemoryAddress, AcirField}; +use acvm::acir::brillig::MemoryAddress; 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/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs index 943b0b9d7a3..1c30f0f848f 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs @@ -1,8 +1,8 @@ -use acvm::{acir::brillig::MemoryAddress, AcirField}; +use acvm::acir::brillig::MemoryAddress; -use super::{debug_show::DebugToString, BrilligContext}; +use super::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/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs index 075a776572e..def91f82bfd 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs @@ -8,7 +8,7 @@ use acvm::{ }; /// Trait for converting values into debug-friendly strings. -pub(crate) trait DebugToString { +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: F) { + pub(crate) fn const_instruction(&self, result: MemoryAddress, constant: FieldElement) { debug_println!(self.enable_debug_trace, " CONST {} = {}", result, constant); } diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs index dc06c2fa0d7..9023183eb36 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs +++ b/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, DebugToString}, + debug_show::DebugShow, registers::BrilligRegistersContext, BrilligBinaryOp, BrilligContext, ReservedRegisters, }; -use acvm::{acir::brillig::MemoryAddress, acir::AcirField}; +use acvm::{acir::brillig::MemoryAddress, acir::AcirField, FieldElement}; 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 = Self::flattened_tuple_size(arguments); - let return_data_size = Self::flattened_tuple_size(return_parameters); + let calldata_size = BrilligContext::flattened_tuple_size(arguments); + let return_data_size = BrilligContext::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 = Self::flattened_size(argument); + let flattened_size = BrilligContext::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 = Self::flattened_size(argument); + let flattened_size = BrilligContext::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 = Self::flattened_size(argument); + let flattened_size = BrilligContext::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 = Self::flattened_tuple_size(arguments); + let calldata_size = BrilligContext::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 < F::max_num_bits() { + if bit_size < FieldElement::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(Self::flattened_size).sum(); + let item_size: usize = item_types.iter().map(BrilligContext::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(Self::flattened_size).sum() + tuple.iter().map(BrilligContext::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 Self::has_nested_arrays(item_type) { + if BrilligContext::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 = Self::flattened_tuple_size(item_type); + let source_item_size = BrilligContext::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 += Self::flattened_size(subitem); + source_offset += BrilligContext::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 = Self::flattened_tuple_size(arguments); - let return_data_size = Self::flattened_tuple_size(return_parameters); + let calldata_size = BrilligContext::flattened_tuple_size(arguments); + let return_data_size = BrilligContext::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 += Self::flattened_size(return_param); + return_data_index += BrilligContext::flattened_size(return_param); } BrilligParameter::Slice(..) => { unreachable!("ICE: Cannot return slices from brillig entrypoints") @@ -376,11 +376,12 @@ impl BrilligContext { flattened_array_pointer: MemoryAddress, deflattened_array_pointer: MemoryAddress, ) { - if Self::has_nested_arrays(item_type) { + if BrilligContext::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(Self::flattened_size).sum(); + let target_item_size: usize = + item_type.iter().map(BrilligContext::flattened_size).sum(); for item_index in 0..item_count { let source_item_base_index = item_index * source_item_size; @@ -461,7 +462,7 @@ impl BrilligContext { .into_iter() .for_each(|register| self.deallocate_register(register)); - target_offset += Self::flattened_size(subitem); + target_offset += BrilligContext::flattened_size(subitem); } BrilligParameter::Slice(..) => unreachable!("ICE: Cannot flatten slices"), } diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs index a614f93fa30..03a9216b73a 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs @@ -10,13 +10,12 @@ 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 @@ -43,7 +42,8 @@ impl BrilligContext { ) { self.debug_show.not_instruction(input.address, input.bit_size, result.address); // Compile !x as ((-1) - x) - let u_max = F::from(2_u128).pow(&F::from(input.bit_size as u128)) - F::one(); + let u_max = FieldElement::from(2_i128).pow(&FieldElement::from(input.bit_size as i128)) + - FieldElement::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, - Self::binary_result_bit_size(op, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), + BrilligContext::binary_result_bit_size(op, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ), op, ); @@ -77,7 +77,8 @@ impl BrilligContext { operation: BrilligBinaryOp, ) { let is_field_op = lhs.bit_size == FieldElement::max_num_bits(); - let expected_result_bit_size = Self::binary_result_bit_size(operation, lhs.bit_size); + let expected_result_bit_size = + BrilligContext::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 {:?}", @@ -212,7 +213,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); @@ -368,12 +369,12 @@ impl BrilligContext { } /// Stores the value of `constant` in the `result` register - pub(crate) fn const_instruction(&mut self, result: SingleAddrVariable, constant: F) { + pub(crate) fn const_instruction(&mut self, result: SingleAddrVariable, constant: FieldElement) { self.debug_show.const_instruction(result.address, constant); self.constant(result, constant); } - fn constant(&mut self, result: SingleAddrVariable, constant: F) { + fn constant(&mut self, result: SingleAddrVariable, constant: FieldElement) { assert!( result.bit_size >= constant.num_bits(), "Constant {} does not fit in bit size {}", @@ -381,10 +382,10 @@ impl BrilligContext { result.bit_size ); if result.bit_size > 128 && constant.num_bits() > 128 { - let high = F::from_be_bytes_reduce( + let high = FieldElement::from_be_bytes_reduce( constant.to_be_bytes().get(0..16).expect("FieldElement::to_be_bytes() too short!"), ); - let low = F::from(constant.to_u128()); + let low = FieldElement::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); @@ -392,7 +393,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, F::from(1_u128 << 64)); + self.constant(intermediate_register, FieldElement::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. @@ -410,14 +411,18 @@ impl BrilligContext { } } - pub(crate) fn usize_const_instruction(&mut self, result: MemoryAddress, constant: F) { + pub(crate) fn usize_const_instruction( + &mut self, + result: MemoryAddress, + constant: FieldElement, + ) { 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: F, + constant: FieldElement, bit_size: u32, ) -> SingleAddrVariable { let var = SingleAddrVariable::new(self.allocate_register(), bit_size); @@ -425,14 +430,17 @@ impl BrilligContext { var } - fn make_constant(&mut self, constant: F, bit_size: u32) -> SingleAddrVariable { + fn make_constant(&mut self, constant: FieldElement, 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: F) -> SingleAddrVariable { + pub(crate) fn make_usize_constant_instruction( + &mut self, + constant: FieldElement, + ) -> SingleAddrVariable { let register = self.allocate_register(); self.usize_const_instruction(register, constant); SingleAddrVariable::new_usize(register) diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/registers.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/registers.rs index ae506462b25..f756f06aa69 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/registers.rs +++ b/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/compiler/noirc_evaluator/src/brillig/mod.rs b/compiler/noirc_evaluator/src/brillig/mod.rs index 70c0959517b..eda1ac97c1e 100644 --- a/compiler/noirc_evaluator/src/brillig/mod.rs +++ b/compiler/noirc_evaluator/src/brillig/mod.rs @@ -1,8 +1,6 @@ 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}, @@ -18,7 +16,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 { @@ -29,10 +27,7 @@ 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) @@ -44,7 +39,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/compiler/noirc_evaluator/src/ssa.rs b/compiler/noirc_evaluator/src/ssa.rs index 7e362599fb5..80a63f223e7 100644 --- a/compiler/noirc_evaluator/src/ssa.rs +++ b/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 backend-agnostic and so must go through a transformation pass before usage in proof generation. +/// The output ACIR is 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/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 56b869fbf6b..ac7f2c09687 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -20,6 +20,7 @@ use acvm::{ native_types::{Expression, Witness}, BlackBoxFunc, }, + FieldElement, }; use fxhash::FxHashMap as HashMap; use iter_extended::{try_vecmap, vecmap}; @@ -47,12 +48,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 => F::max_num_bits(), + NumericType::NativeField => FieldElement::max_num_bits(), }, AcirType::Array(_, _) => unreachable!("cannot fetch bit size of array type"), } @@ -105,13 +106,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. /// @@ -120,13 +121,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() } @@ -147,7 +148,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) } @@ -155,7 +156,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) -> &F { + pub(crate) fn constant(&self, var: AcirVar) -> FieldElement { self.vars[&var].as_constant().expect("ICE - expected the variable to be a constant value") } @@ -269,7 +270,10 @@ 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 => { @@ -404,7 +408,7 @@ impl AcirContext { if lhs_expr == rhs_expr { // x ^ x == 0 - let zero = self.add_constant(F::zero()); + let zero = self.add_constant(FieldElement::zero()); return Ok(zero); } else if lhs_expr.is_zero() { // 0 ^ x == x @@ -414,14 +418,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, -F::from(2_u128), prod) + self.add_mul_var(sum, -FieldElement::from(2_i128), prod) } else { let inputs = vec![AcirValue::Var(lhs, typ.clone()), AcirValue::Var(rhs, typ)]; let outputs = self.black_box_function(BlackBoxFunc::XOR, inputs, 1)?; @@ -444,11 +448,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(F::zero()); + let zero = self.add_constant(FieldElement::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) @@ -476,7 +480,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 @@ -498,7 +502,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)?; @@ -527,7 +531,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 { @@ -593,7 +597,7 @@ impl AcirContext { (AcirVarData::Const(constant), _) | (_, AcirVarData::Const(constant)) if constant.is_zero() => { - self.add_constant(F::zero()) + self.add_constant(FieldElement::zero()) } (AcirVarData::Const(lhs_constant), AcirVarData::Const(rhs_constant)) => { @@ -611,7 +615,7 @@ impl AcirContext { } (AcirVarData::Witness(lhs_witness), AcirVarData::Witness(rhs_witness)) => { let mut expr = Expression::default(); - expr.push_multiplication_term(F::one(), lhs_witness, rhs_witness); + expr.push_multiplication_term(FieldElement::one(), lhs_witness, rhs_witness); self.add_data(AcirVarData::Expr(expr)) } (AcirVarData::Expr(expression), AcirVarData::Witness(witness)) @@ -677,7 +681,12 @@ 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: F, rhs: AcirVar) -> Result { + fn add_mul_var( + &mut self, + lhs: AcirVar, + k: FieldElement, + rhs: AcirVar, + ) -> Result { let k_var = self.add_constant(k); let intermediate = self.mul_var(k_var, rhs)?; @@ -686,7 +695,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) @@ -700,8 +709,8 @@ impl AcirContext { bit_size: u32, predicate: AcirVar, ) -> Result<(AcirVar, AcirVar), RuntimeError> { - let zero = self.add_constant(F::zero()); - let one = self.add_constant(F::one()); + let zero = self.add_constant(FieldElement::zero()); + let one = self.add_constant(FieldElement::one()); let lhs_expr = self.var_to_expression(lhs)?; let rhs_expr = self.var_to_expression(rhs)?; @@ -820,7 +829,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 >= F::max_num_bits() - 1 { + if max_q_bits + max_rhs_bits >= FieldElement::max_num_bits() - 1 { // q*b+r can overflow; we avoid this when b is constant if rhs_expr.is_const() { avoid_overflow = true; @@ -834,16 +843,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 = F::modulus() / &rhs_big; - let q0 = F::from_be_bytes_reduce(&q0_big.to_bytes_be()); + let q0_big = FieldElement::modulus() / &rhs_big; + let q0 = FieldElement::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 = F::modulus() - q0_big * rhs_big; - let max_r = F::from_be_bytes_reduce(&max_r_big.to_bytes_be()); + 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_var = self.add_constant(max_r); let max_r_predicate = self.mul_var(predicate, max_r_var)?; @@ -888,7 +897,7 @@ impl AcirContext { } assert!( - bits < F::max_num_bits(), + bits < FieldElement::max_num_bits(), "range check with bit size of the prime field is not implemented yet" ); @@ -912,7 +921,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 < F::max_num_bits()); //we need to ensure lhs_offset + r does not overflow + assert!(bits + r_bit_size < FieldElement::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)?; @@ -936,13 +945,14 @@ impl AcirContext { leading: AcirVar, max_bit_size: u32, ) -> Result { - let max_power_of_two = - self.add_constant(F::from(2_u128).pow(&F::from(max_bit_size as u128 - 1))); + let max_power_of_two = self.add_constant( + FieldElement::from(2_i128).pow(&FieldElement::from(max_bit_size as i128 - 1)), + ); let intermediate = self.sub_var(max_power_of_two, lhs)?; let intermediate = self.mul_var(intermediate, leading)?; - self.add_mul_var(lhs, F::from(2_u128), intermediate) + self.add_mul_var(lhs, FieldElement::from(2_i128), intermediate) } /// Returns the quotient and remainder such that lhs = rhs * quotient + remainder @@ -966,10 +976,11 @@ 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(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()); + 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()); // 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)?; @@ -1060,8 +1071,9 @@ impl AcirContext { max_bit_size: u32, ) -> Result { // 2^{rhs} - let divisor = self.add_constant(F::from(2_u128).pow(&F::from(rhs as u128))); - let one = self.add_constant(F::one()); + let divisor = + self.add_constant(FieldElement::from(2_u128).pow(&FieldElement::from(rhs as u128))); + let one = self.add_constant(FieldElement::one()); // Computes lhs = 2^{rhs} * q + r let (_, remainder) = self.euclidean_division_var(lhs, divisor, max_bit_size, one)?; @@ -1081,8 +1093,8 @@ impl AcirContext { rhs: AcirVar, bit_count: u32, ) -> Result { - let pow_last = self.add_constant(F::from(1_u128 << (bit_count - 1))); - let pow = self.add_constant(F::from(1_u128 << (bit_count))); + let pow_last = self.add_constant(FieldElement::from(1_u128 << (bit_count - 1))); + let pow = self.add_constant(FieldElement::from(1_u128 << (bit_count))); // We check whether the inputs have same sign or not by computing the XOR of their bit sign @@ -1151,9 +1163,10 @@ 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 < F::max_num_bits()); + assert!(max_bits + 1 < FieldElement::max_num_bits()); - let two_max_bits = self.add_constant(F::from(2_u128).pow(&F::from(max_bits as u128))); + let two_max_bits = self + .add_constant(FieldElement::from(2_i128).pow(&FieldElement::from(max_bits as i128))); let diff = self.sub_var(lhs, rhs)?; let comparison_evaluation = self.add_var(diff, two_max_bits)?; @@ -1201,7 +1214,7 @@ impl AcirContext { // compute less than. let comparison = self.more_than_eq_var(lhs, rhs, bit_size)?; - let one = self.add_constant(F::one()); + let one = self.add_constant(FieldElement::one()); self.sub_var(one, comparison) // comparison_negated } @@ -1238,7 +1251,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 @@ -1263,7 +1276,7 @@ impl AcirContext { } }; - (vec![*state_len], Vec::new()) + (vec![state_len], Vec::new()) } BlackBoxFunc::BigIntAdd | BlackBoxFunc::BigIntSub @@ -1284,7 +1297,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() }); @@ -1293,7 +1306,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 => { @@ -1310,10 +1323,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); @@ -1326,7 +1339,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(), @@ -1346,8 +1359,9 @@ 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(F::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(FieldElement::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"; @@ -1362,7 +1376,7 @@ impl AcirContext { } }?; output_count = input_size + (16 - input_size % 16); - (vec![], vec![F::from(output_count as u128)]) + (vec![], vec![FieldElement::from(output_count as u128)]) } _ => (vec![], vec![]), }; @@ -1406,7 +1420,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); @@ -1517,7 +1531,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; @@ -1529,7 +1543,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 @@ -1539,7 +1553,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, @@ -1547,14 +1561,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)?; } @@ -1605,8 +1619,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 { @@ -1641,7 +1655,7 @@ impl AcirContext { fn brillig_array_input( &mut self, - var_expressions: &mut Vec>, + var_expressions: &mut Vec>, input: AcirValue, ) -> Result<(), InternalError> { match input { @@ -1700,8 +1714,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(); @@ -1726,7 +1740,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 { @@ -1807,7 +1821,7 @@ impl AcirContext { ) -> Result<(), InternalError> { let initialized_values = match optional_value { None => { - let zero = self.add_constant(F::zero()); + let zero = self.add_constant(FieldElement::zero()); let zero_witness = self.var_to_witness(zero)?; vec![zero_witness; len] } @@ -1879,13 +1893,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(F), + Expr(Expression), + Const(FieldElement), } -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, @@ -1897,26 +1911,23 @@ 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<&F> { + pub(crate) fn as_constant(&self) -> Option { 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), @@ -1925,17 +1936,23 @@ impl AcirVarData { } } -impl From for AcirVarData { +impl From for AcirVarData { + fn from(constant: FieldElement) -> Self { + AcirVarData::Const(constant) + } +} + +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::Const(*constant) + AcirVarData::from(*constant) } else if let Some(witness) = expr.to_witness() { AcirVarData::from(witness) } else { @@ -1953,12 +1970,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/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs index 30297b42ecf..b9c596d80c7 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs @@ -1,4 +1,4 @@ -use acvm::acir::AcirField; +use acvm::{acir::AcirField, FieldElement}; 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) -> F { - F::from(self.bigint_id as u128) + pub(crate) fn bigint_id(&self) -> FieldElement { + FieldElement::from(self.bigint_id as u128) } - pub(crate) fn modulus_id>(&self) -> F { - F::from(self.modulus_id as u128) + pub(crate) fn modulus_id(&self) -> FieldElement { + FieldElement::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: F) -> BigIntId { + pub(crate) fn new_big_int(&mut self, modulus_id: FieldElement) -> 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: F) -> BigUint { + pub(crate) fn modulus(&self, idx: FieldElement) -> BigUint { self.modulus[idx.to_u128() as usize].clone() } /// Returns the BigIntId corresponding to the given identifier - pub(crate) fn get(&self, id: F) -> BigIntId { + pub(crate) fn get(&self, id: FieldElement) -> BigIntId { self.big_integers[id.to_u128() as usize] } diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index 9d271f7cd9c..9a09e7c06ee 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -19,6 +19,7 @@ use acvm::acir::{ use acvm::{ acir::AcirField, acir::{circuit::directives::Directive, native_types::Expression}, + FieldElement, }; use iter_extended::vecmap; use num_bigint::BigUint; @@ -31,7 +32,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. @@ -41,7 +42,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, @@ -57,7 +58,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, @@ -79,7 +80,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) => { @@ -89,25 +90,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) } @@ -126,7 +127,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), @@ -139,7 +140,10 @@ 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 @@ -159,15 +163,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()); @@ -384,7 +388,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, @@ -410,7 +414,7 @@ impl GeneratedAcir { self.range_constraint(*limb_witness, bit_size)?; composed_limbs = composed_limbs.add_mul( - F::from_be_bytes_reduce(&radix_pow.to_bytes_be()), + FieldElement::from_be_bytes_reduce(&radix_pow.to_bytes_be()), &Expression::from(*limb_witness), ); @@ -430,7 +434,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(); @@ -454,14 +458,18 @@ 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) @@ -519,13 +527,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 * -F::one(); + let negated_expr = t_expr * -FieldElement::one(); self.get_or_create_witness(&negated_expr) }; @@ -537,17 +545,17 @@ impl GeneratedAcir { // Add constraint y == 1 - tz => y + tz - 1 == 0 let y_is_boolean_constraint = Expression { - mul_terms: vec![(F::one(), t_witness, z)], - linear_combinations: vec![(F::one(), y)], - q_c: -F::one(), + mul_terms: vec![(FieldElement::one(), t_witness, z)], + linear_combinations: vec![(FieldElement::one(), y)], + q_c: -FieldElement::one(), }; self.assert_is_zero(y_is_boolean_constraint); // Add constraint that y * t == 0; let ty_zero_constraint = Expression { - mul_terms: vec![(F::one(), t_witness, y)], + mul_terms: vec![(FieldElement::one(), t_witness, y)], linear_combinations: vec![], - q_c: F::zero(), + q_c: FieldElement::zero(), }; self.assert_is_zero(ty_zero_constraint); @@ -563,9 +571,9 @@ impl GeneratedAcir { ) -> Result<(), RuntimeError> { // We class this as an error because users should instead // do `as Field`. - if num_bits >= F::max_num_bits() { + if num_bits >= FieldElement::max_num_bits() { return Err(RuntimeError::InvalidRangeConstraint { - num_bits: F::max_num_bits(), + num_bits: FieldElement::max_num_bits(), call_stack: self.call_stack.clone(), }); }; @@ -580,9 +588,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/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index aaa483b91c9..40170e58a30 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/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,11 +274,8 @@ impl AcirValue { } } -pub(crate) type Artifacts = ( - Vec>, - Vec>, - BTreeMap, -); +pub(crate) type Artifacts = + (Vec, Vec>, BTreeMap); impl Ssa { #[tracing::instrument(level = "trace", skip_all)] @@ -334,7 +331,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()); @@ -357,7 +354,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 { @@ -389,7 +386,7 @@ impl<'a> Context<'a> { main_func: &Function, ssa: &Ssa, brillig: &Brillig, - ) -> Result, RuntimeError> { + ) -> Result { 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)?; @@ -438,7 +435,7 @@ impl<'a> Context<'a> { mut self, main_func: &Function, brillig: &Brillig, - ) -> Result, RuntimeError> { + ) -> Result { let dfg = &main_func.dfg; let inputs = try_vecmap(dfg[main_func.entry_block()].parameters(), |param_id| { @@ -922,7 +919,7 @@ impl<'a> Context<'a> { func: &Function, arguments: Vec, brillig: &Brillig, - ) -> Result, InternalError> { + ) -> Result { // Create the entry point artifact let mut entry_point = BrilligContext::new_entry_point_artifact( arguments, @@ -1900,7 +1897,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/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index 58f70ba9192..e07f947db8d 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -375,6 +375,7 @@ 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 { @@ -392,6 +393,15 @@ 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] } @@ -404,6 +414,7 @@ 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); @@ -418,12 +429,21 @@ 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()] } @@ -451,6 +471,11 @@ 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/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs index de75d34565e..c59134e4ecc 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs +++ b/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 most 10 past ArraySet operations. + // Arbitrarily limit this to looking at 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/compiler/noirc_frontend/src/ast/expression.rs b/compiler/noirc_frontend/src/ast/expression.rs index 075df4ee4e3..50836add8de 100644 --- a/compiler/noirc_frontend/src/ast/expression.rs +++ b/compiler/noirc_frontend/src/ast/expression.rs @@ -33,18 +33,9 @@ pub enum ExpressionKind { Tuple(Vec), Lambda(Box), Parenthesized(Box), - Quote(BlockExpression, Span), - Unquote(Box), + Quote(BlockExpression), 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. @@ -188,21 +179,19 @@ impl Expression { pub fn member_access_or_method_call( lhs: Expression, - rhs: UnaryRhsMemberAccess, + (rhs, args): UnaryRhsMemberAccess, span: Span, ) -> Expression { - let kind = match rhs.method_call { - None => { - let rhs = rhs.method_or_field; - ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { lhs, rhs })) + 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, + })) } - 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) } @@ -217,12 +206,7 @@ impl Expression { Expression::new(kind, span) } - pub fn call( - lhs: Expression, - is_macro_call: bool, - arguments: Vec, - span: Span, - ) -> Expression { + pub fn call(lhs: Expression, 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. @@ -240,11 +224,7 @@ impl Expression { ], }) } else { - ExpressionKind::Call(Box::new(CallExpression { - func: Box::new(lhs), - is_macro_call, - arguments, - })) + ExpressionKind::Call(Box::new(CallExpression { func: Box::new(lhs), arguments })) }; Expression::new(kind, span) } @@ -467,7 +447,6 @@ pub enum ArrayLiteral { pub struct CallExpression { pub func: Box, pub arguments: Vec, - pub is_macro_call: bool, } #[derive(Debug, PartialEq, Eq, Clone)] @@ -477,7 +456,6 @@ 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)] @@ -557,12 +535,10 @@ 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/compiler/noirc_frontend/src/ast/mod.rs b/compiler/noirc_frontend/src/ast/mod.rs index 3492df73103..bd2b45d9c48 100644 --- a/compiler/noirc_frontend/src/ast/mod.rs +++ b/compiler/noirc_frontend/src/ast/mod.rs @@ -117,7 +117,7 @@ pub enum UnresolvedTypeData { ), // The type of quoted code for metaprogramming - Expr, + Code, Unspecified, // This is for when the user declares a variable without specifying it's type Error, @@ -134,16 +134,8 @@ pub struct UnresolvedType { } /// Type wrapper for a member access -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, -} +pub(crate) type UnaryRhsMemberAccess = + (Ident, Option<(Option>, 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, @@ -216,7 +208,7 @@ impl std::fmt::Display for UnresolvedTypeData { } } MutableReference(element) => write!(f, "&mut {element}"), - Expr => write!(f, "Expr"), + Code => write!(f, "Code"), Unit => write!(f, "()"), Error => write!(f, "error"), Unspecified => write!(f, "unspecified"), diff --git a/compiler/noirc_frontend/src/ast/statement.rs b/compiler/noirc_frontend/src/ast/statement.rs index 48e34ad7fc9..9b2c0fbfee8 100644 --- a/compiler/noirc_frontend/src/ast/statement.rs +++ b/compiler/noirc_frontend/src/ast/statement.rs @@ -608,7 +608,6 @@ 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); @@ -728,11 +727,7 @@ 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); - if self.kind == PathKind::Plain { - write!(f, "{}", segments.join("::")) - } else { - write!(f, "{}::{}", self.kind, segments.join("::")) - } + write!(f, "{}::{}", self.kind, segments.join("::")) } } diff --git a/compiler/noirc_frontend/src/debug/mod.rs b/compiler/noirc_frontend/src/debug/mod.rs index f5866f5b756..c222e08e77a 100644 --- a/compiler/noirc_frontend/src/debug/mod.rs +++ b/compiler/noirc_frontend/src/debug/mod.rs @@ -581,7 +581,6 @@ 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 } @@ -600,7 +599,6 @@ 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 } @@ -628,7 +626,6 @@ fn build_assign_member_stmt( ), span, }), - is_macro_call: false, arguments: [ vec![uint_expr(var_id.0 as u128, span)], vec![expr.clone()], @@ -652,7 +649,6 @@ 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/compiler/noirc_frontend/src/elaborator/expressions.rs b/compiler/noirc_frontend/src/elaborator/expressions.rs index a57690878dc..a922f552c4b 100644 --- a/compiler/noirc_frontend/src/elaborator/expressions.rs +++ b/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, HirQuoted, + HirPrefixExpression, }, traits::TraitConstraint, }, @@ -58,19 +58,12 @@ 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); @@ -287,22 +280,10 @@ 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 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) - } + let call = HirCallExpression { func, arguments, location }; + let typ = self.type_check_call(&call, func_type, args, span); + (HirExpression::Call(call), typ) } fn elaborate_method_call( @@ -646,11 +627,8 @@ impl<'context> Elaborator<'context> { (expr, Type::Function(arg_types, Box::new(body_type), Box::new(env_type))) } - 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_quote(&mut self, block: BlockExpression) -> (HirExpression, Type) { + (HirExpression::Quote(block), Type::Code) } fn elaborate_comptime_block(&mut self, block: BlockExpression, span: Span) -> (ExprId, Type) { @@ -683,74 +661,4 @@ 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/compiler/noirc_frontend/src/elaborator/mod.rs b/compiler/noirc_frontend/src/elaborator/mod.rs index 93e8b36f4e0..37ad74b78b0 100644 --- a/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/compiler/noirc_frontend/src/elaborator/mod.rs @@ -62,7 +62,6 @@ mod scope; mod statements; mod traits; mod types; -mod unquote; use fm::FileId; use iter_extended::vecmap; @@ -233,22 +232,25 @@ 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 ensure they are valid. + // globals will need to reference the struct type they're initialized to to ensure they are valid. while let Some((_, global)) = this.unresolved_globals.pop_first() { this.elaborate_global(global); } @@ -309,7 +311,6 @@ 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; } @@ -403,10 +404,8 @@ 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; } @@ -548,7 +547,6 @@ 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; } @@ -664,7 +662,6 @@ 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; @@ -863,12 +860,9 @@ impl<'context> Elaborator<'context> { self.self_type = None; } - fn get_module_mut( - def_maps: &mut BTreeMap, - module: ModuleId, - ) -> &mut ModuleData { + fn get_module_mut(&mut self, module: ModuleId) -> &mut ModuleData { let message = "A crate should always be present for a given crate id"; - &mut def_maps.get_mut(&module.krate).expect(message).modules[module.local_id.0] + &mut self.def_maps.get_mut(&module.krate).expect(message).modules[module.local_id.0] } fn declare_methods_on_struct( @@ -896,7 +890,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(self.def_maps, struct_ref.id.module_id()); + let module = self.get_module_mut(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 @@ -905,37 +899,22 @@ 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() { - 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()); - } + module.remove_function(method.name_ident()); } } - // Trait impl methods are already declared in NodeInterner::add_trait_implementation - if !is_trait_impl { - self.declare_methods(self_type, &function_ids); - } + self.declare_struct_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() { - // Trait impl methods are already declared in NodeInterner::add_trait_implementation - if !is_trait_impl { - self.declare_methods(self_type, &function_ids); - } + self.declare_struct_methods(self_type, &function_ids); } else { self.push_err(DefCollectorErrorKind::NonStructTypeInImpl { span }); } } } - fn declare_methods(&mut self, self_type: &Type, function_ids: &[FuncId]) { + fn declare_struct_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(); @@ -1101,7 +1080,6 @@ 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() { @@ -1136,8 +1114,8 @@ impl<'context> Elaborator<'context> { } fn elaborate_global(&mut self, global: UnresolvedGlobal) { - 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); + self.local_module = global.module_id; + self.file = global.file_id; let global_id = global.global_id; self.current_item = Some(DependencyId::Global(global_id)); @@ -1169,8 +1147,6 @@ 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) { @@ -1210,13 +1186,11 @@ 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(); } } @@ -1231,10 +1205,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/compiler/noirc_frontend/src/elaborator/types.rs b/compiler/noirc_frontend/src/elaborator/types.rs index a9571a6669d..3baa7054fc5 100644 --- a/compiler/noirc_frontend/src/elaborator/types.rs +++ b/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)) } - Expr => Type::Expr, + Code => Type::Code, Unit => Type::Unit, Unspecified => Type::Error, Error => Type::Error, @@ -1396,7 +1396,7 @@ impl<'context> Elaborator<'context> { | Type::TypeVariable(_, _) | Type::Constant(_) | Type::NamedGeneric(_, _) - | Type::Expr + | Type::Code | Type::Forall(_, _) => (), Type::TraitAsType(_, _, args) => { diff --git a/compiler/noirc_frontend/src/elaborator/unquote.rs b/compiler/noirc_frontend/src/elaborator/unquote.rs deleted file mode 100644 index 6767f471f16..00000000000 --- a/compiler/noirc_frontend/src/elaborator/unquote.rs +++ /dev/null @@ -1,306 +0,0 @@ -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/compiler/noirc_frontend/src/hir/comptime/interpreter.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs index 3648881e501..186eaa58c14 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs @@ -7,7 +7,6 @@ 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::{ @@ -26,17 +25,13 @@ 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 interner: &'interner mut NodeInterner, + pub(super) 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 @@ -320,11 +315,14 @@ impl<'a> Interpreter<'a> { } /// Evaluate an expression and return the result - pub fn evaluate(&mut self, id: ExprId) -> IResult { + pub(super) 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) => self.evaluate_block(block), + HirExpression::Block(block) => { + dbg!("going to evaluate a 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), @@ -336,7 +334,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) => self.evaluate_quote(block, id), + HirExpression::Quote(block) => Ok(Value::Code(Rc::new(block))), HirExpression::Comptime(block) => self.evaluate_block(block), HirExpression::Unquote(block) => { // An Unquote expression being found is indicative of a macro being @@ -1129,15 +1127,6 @@ 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/compiler/noirc_frontend/src/hir/comptime/interpreter/unquote.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter/unquote.rs deleted file mode 100644 index 58ca345ca90..00000000000 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter/unquote.rs +++ /dev/null @@ -1,287 +0,0 @@ -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/compiler/noirc_frontend/src/hir/comptime/scan.rs b/compiler/noirc_frontend/src/hir/comptime/scan.rs index f2e21e608ea..9e3b03ef525 100644 --- a/compiler/noirc_frontend/src/hir/comptime/scan.rs +++ b/compiler/noirc_frontend/src/hir/comptime/scan.rs @@ -53,7 +53,9 @@ 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/compiler/noirc_frontend/src/hir/comptime/value.rs b/compiler/noirc_frontend/src/hir/comptime/value.rs index 5d91b151218..11bbbc7484d 100644 --- a/compiler/noirc_frontend/src/hir/comptime/value.rs +++ b/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::Expr, + Value::Code(_) => Type::Code, Value::Pointer(element) => { let element = element.borrow().get_type().into_owned(); Type::MutableReference(Box::new(element)) diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 4511537a1cc..9b47a104a40 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/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 ensure they are valid. + // globals will need to reference the struct type they're initialized to 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/compiler/noirc_frontend/src/hir/resolution/errors.rs b/compiler/noirc_frontend/src/hir/resolution/errors.rs index 2c6461cb77c..06f6dda7142 100644 --- a/compiler/noirc_frontend/src/hir/resolution/errors.rs +++ b/compiler/noirc_frontend/src/hir/resolution/errors.rs @@ -100,12 +100,6 @@ 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 { @@ -325,7 +319,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_warning( + ResolverError::OracleMarkedAsConstrained { ident } => Diagnostic::simple_error( error.to_string(), "Oracle functions must have the `unconstrained` keyword applied".into(), ident.span(), @@ -397,27 +391,6 @@ 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/compiler/noirc_frontend/src/hir/resolution/import.rs b/compiler/noirc_frontend/src/hir/resolution/import.rs index 343113836ed..9a0be775c30 100644 --- a/compiler/noirc_frontend/src/hir/resolution/import.rs +++ b/compiler/noirc_frontend/src/hir/resolution/import.rs @@ -88,15 +88,12 @@ pub fn resolve_import( import_directive: &ImportDirective, def_maps: &BTreeMap, ) -> Result { - let allow_contracts = - allow_referencing_contracts(def_maps, crate_id, import_directive.module_id); - let module_scope = import_directive.module_id; let NamespaceResolution { module_id: resolved_module, namespace: resolved_namespace, mut error, - } = resolve_path_to_ns(import_directive, crate_id, crate_id, def_maps, allow_contracts)?; + } = resolve_path_to_ns(import_directive, crate_id, crate_id, def_maps)?; let name = resolve_path_name(import_directive); @@ -129,20 +126,11 @@ pub fn resolve_import( }) } -fn allow_referencing_contracts( - def_maps: &BTreeMap, - krate: CrateId, - local_id: LocalModuleId, -) -> bool { - ModuleId { krate, local_id }.module(def_maps).is_contract -} - fn resolve_path_to_ns( import_directive: &ImportDirective, crate_id: CrateId, importing_crate: CrateId, def_maps: &BTreeMap, - allow_contracts: bool, ) -> NamespaceResolutionResult { let import_path = &import_directive.path.segments; let def_map = &def_maps[&crate_id]; @@ -150,21 +138,11 @@ fn resolve_path_to_ns( match import_directive.path.kind { crate::ast::PathKind::Crate => { // Resolve from the root of the crate - resolve_path_from_crate_root( - crate_id, - importing_crate, - import_path, - def_maps, - allow_contracts, - ) + resolve_path_from_crate_root(crate_id, importing_crate, import_path, def_maps) + } + crate::ast::PathKind::Dep => { + resolve_external_dep(def_map, import_directive, def_maps, importing_crate) } - crate::ast::PathKind::Dep => resolve_external_dep( - def_map, - import_directive, - def_maps, - allow_contracts, - importing_crate, - ), crate::ast::PathKind::Plain => { // Plain paths are only used to import children modules. It's possible to allow import of external deps, but maybe this distinction is better? // In Rust they can also point to external Dependencies, if no children can be found with the specified name @@ -174,7 +152,6 @@ fn resolve_path_to_ns( import_path, import_directive.module_id, def_maps, - allow_contracts, ) } } @@ -186,7 +163,6 @@ fn resolve_path_from_crate_root( import_path: &[Ident], def_maps: &BTreeMap, - allow_contracts: bool, ) -> NamespaceResolutionResult { resolve_name_in_module( crate_id, @@ -194,7 +170,6 @@ fn resolve_path_from_crate_root( import_path, def_maps[&crate_id].root, def_maps, - allow_contracts, ) } @@ -204,7 +179,6 @@ fn resolve_name_in_module( import_path: &[Ident], starting_mod: LocalModuleId, def_maps: &BTreeMap, - allow_contracts: bool, ) -> NamespaceResolutionResult { let def_map = &def_maps[&krate]; let mut current_mod_id = ModuleId { krate, local_id: starting_mod }; @@ -267,10 +241,6 @@ fn resolve_name_in_module( return Err(PathResolutionError::Unresolved(current_segment.clone())); } - // Check if it is a contract and we're calling from a non-contract context - if current_mod.is_contract && !allow_contracts { - return Err(PathResolutionError::ExternalContractUsed(current_segment.clone())); - } current_ns = found_ns; } @@ -288,7 +258,6 @@ fn resolve_external_dep( current_def_map: &CrateDefMap, directive: &ImportDirective, def_maps: &BTreeMap, - allow_contracts: bool, importing_crate: CrateId, ) -> NamespaceResolutionResult { // Use extern_prelude to get the dep @@ -316,7 +285,7 @@ fn resolve_external_dep( is_prelude: false, }; - resolve_path_to_ns(&dep_directive, dep_module.krate, importing_crate, def_maps, allow_contracts) + resolve_path_to_ns(&dep_directive, dep_module.krate, importing_crate, def_maps) } // Issue an error if the given private function is being called from a non-child module, or diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 4583125d2a2..01f58ba4c27 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/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, HirQuoted, ImplKind, + HirMethodCallExpression, HirPrefixExpression, 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)) } - Expr => Type::Expr, + Code => Type::Code, Unit => Type::Unit, Unspecified => Type::Error, Error => Type::Error, @@ -1158,7 +1158,7 @@ impl<'a> Resolver<'a> { | Type::TypeVariable(_, _) | Type::Constant(_) | Type::NamedGeneric(_, _) - | Type::Expr + | Type::Code | Type::Forall(_, _) => (), Type::TraitAsType(_, _, args) => { @@ -1641,23 +1641,13 @@ 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, _) => { - let quoted = HirQuoted { quoted_block: block, unquoted_exprs: Vec::new() }; - HirExpression::Quote(quoted) - } + ExpressionKind::Quote(block) => HirExpression::Quote(block), 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/compiler/noirc_frontend/src/hir/resolution/traits.rs b/compiler/noirc_frontend/src/hir/resolution/traits.rs index 4c360731711..3d355fd4447 100644 --- a/compiler/noirc_frontend/src/hir/resolution/traits.rs +++ b/compiler/noirc_frontend/src/hir/resolution/traits.rs @@ -300,7 +300,6 @@ 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/compiler/noirc_frontend/src/hir/type_check/errors.rs b/compiler/noirc_frontend/src/hir/type_check/errors.rs index bd32ba2fce5..0d8a9f3e717 100644 --- a/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -143,8 +143,6 @@ 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 { @@ -337,11 +335,6 @@ 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/compiler/noirc_frontend/src/hir/type_check/expr.rs b/compiler/noirc_frontend/src/hir/type_check/expr.rs index 503bbbf79be..50af9dbf34e 100644 --- a/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/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::Expr, + HirExpression::Quote(_) => Type::Code, HirExpression::Comptime(block) => self.check_block(block), // Unquote should be inserted & removed by the comptime interpreter. diff --git a/compiler/noirc_frontend/src/hir_def/expr.rs b/compiler/noirc_frontend/src/hir_def/expr.rs index 9547aef866b..163ea10ee02 100644 --- a/compiler/noirc_frontend/src/hir_def/expr.rs +++ b/compiler/noirc_frontend/src/hir_def/expr.rs @@ -33,7 +33,7 @@ pub enum HirExpression { If(HirIfExpression), Tuple(Vec), Lambda(HirLambda), - Quote(HirQuoted), + Quote(crate::ast::BlockExpression), Unquote(crate::ast::BlockExpression), Comptime(HirBlockExpression), Error, @@ -291,13 +291,3 @@ 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/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index a90bd931496..1357ea09f94 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/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 - Expr, + Code, /// 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::Expr + | Type::Code | 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::Expr => false, + | Type::Code => 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::Expr + | Type::Code | 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::Expr + | Type::Code | 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::Expr => write!(f, "Expr"), + Type::Code => write!(f, "Code"), } } } @@ -1643,7 +1643,7 @@ impl Type { | Type::Bool | Type::Constant(_) | Type::Error - | Type::Expr + | Type::Code | Type::Unit => self.clone(), } } @@ -1686,7 +1686,7 @@ impl Type { | Type::Bool | Type::Constant(_) | Type::Error - | Type::Expr + | Type::Code | 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 | Expr | Error => self.clone(), + FieldElement | Integer(_, _) | Bool | Constant(_) | Unit | Code | 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::Expr => unreachable!(), + Type::Code => unreachable!(), } } } @@ -1963,7 +1963,7 @@ impl std::fmt::Debug for Type { Type::MutableReference(element) => { write!(f, "&mut {element:?}") } - Type::Expr => write!(f, "Expr"), + Type::Code => write!(f, "Code"), } } } diff --git a/compiler/noirc_frontend/src/lexer/lexer.rs b/compiler/noirc_frontend/src/lexer/lexer.rs index 3d052e22e36..2d1ebf530e3 100644 --- a/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/compiler/noirc_frontend/src/lexer/lexer.rs @@ -141,7 +141,6 @@ 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/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index d204191796c..d8555b4fbf7 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -85,8 +85,6 @@ pub enum BorrowedToken<'input> { Semicolon, /// ! Bang, - /// $ - DollarSign, /// = Assign, #[allow(clippy::upper_case_acronyms)] @@ -181,8 +179,6 @@ pub enum Token { Bang, /// = Assign, - /// $ - DollarSign, #[allow(clippy::upper_case_acronyms)] EOF, @@ -242,7 +238,6 @@ 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), @@ -354,7 +349,6 @@ 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}"), @@ -460,7 +454,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 + // Is not the best API. We could split this into two functions. One that checks if the 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' @@ -846,7 +840,6 @@ pub enum Keyword { Crate, Dep, Else, - Expr, Field, Fn, For, @@ -891,7 +884,6 @@ 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"), @@ -939,7 +931,6 @@ 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/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index c6cc1344aae..6dfd575d2b2 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -241,7 +241,9 @@ impl<'interner> Monomorphizer<'interner> { Definition::Oracle(opcode.to_string()) } FunctionKind::Recursive => { - unreachable!("Only main can be specified as recursive, which should already be checked"); + let id = + self.queue_function(id, expr_id, typ, turbofish_generics, trait_method); + Definition::Function(id) } } } @@ -1012,7 +1014,7 @@ impl<'interner> Monomorphizer<'interner> { HirType::Forall(_, _) | HirType::Constant(_) | HirType::Error => { unreachable!("Unexpected type {} found", typ) } - HirType::Expr => unreachable!("Tried to translate Code type into runtime code"), + HirType::Code => unreachable!("Tried to translate Code type into runtime code"), }) } diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 5fdce80087a..cd82685c31e 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -623,6 +623,15 @@ impl NodeInterner { f(&mut value); } + pub fn update_struct_attributes( + &mut self, + type_id: StructId, + f: impl FnOnce(&mut StructAttributes), + ) { + let value = self.struct_attributes.get_mut(&type_id).unwrap(); + f(value); + } + pub fn update_trait(&mut self, trait_id: TraitId, f: impl FnOnce(&mut Trait)) { let value = self.traits.get_mut(&trait_id).unwrap(); f(value); @@ -1411,13 +1420,6 @@ 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() @@ -1473,7 +1475,6 @@ 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 { @@ -1825,7 +1826,7 @@ fn get_type_method_key(typ: &Type) -> Option { Type::Tuple(_) => Some(Tuple), Type::Function(_, _, _) => Some(Function), Type::NamedGeneric(_, _) => Some(Generic), - Type::Expr => Some(Code), + Type::Code => Some(Code), Type::MutableReference(element) => get_type_method_key(element), Type::Alias(alias, _) => get_type_method_key(&alias.borrow().typ), diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 0d8215f2ea4..cabc788e07d 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -24,7 +24,6 @@ //! 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, @@ -36,8 +35,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, UnaryRhsMethodCall, - UnresolvedTraitConstraint, UseTree, UseTreeKind, Visibility, + Recoverable, Statement, TraitBound, TypeImpl, UnaryRhsMemberAccess, UnresolvedTraitConstraint, + UnresolvedTypeExpression, UseTree, UseTreeKind, Visibility, }; use crate::ast::{ Expression, ExpressionKind, LetStatement, StatementKind, UnresolvedType, UnresolvedTypeData, @@ -60,7 +59,6 @@ mod path; mod primitives; mod structs; mod traits; -mod types; // synthesized by LALRPOP lalrpop_mod!(pub noir_parser); @@ -676,6 +674,41 @@ 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)) @@ -691,6 +724,187 @@ 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( @@ -859,18 +1073,14 @@ where S: NoirParser + 'a, { enum UnaryRhs { - Call((Option, Vec)), + Call(Vec), ArrayIndex(Expression), Cast(UnresolvedType), MemberAccess(UnaryRhsMemberAccess), } // `(arg1, ..., argN)` in `my_func(arg1, ..., argN)` - // 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); + let call_rhs = parenthesized(expression_list(expr_parser.clone())).map(UnaryRhs::Call); // `[expr]` in `arr[expr]` let array_rhs = expr_parser @@ -887,23 +1097,11 @@ 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(method_call_rhs.or_not()) - .map(|(method_or_field, method_call)| { - UnaryRhs::MemberAccess(UnaryRhsMemberAccess { method_or_field, method_call }) - }) + .then(turbofish.then(parenthesized(expression_list(expr_parser.clone()))).or_not()) + .map(UnaryRhs::MemberAccess) .labelled(ParsingRuleLabel::FieldAccess); let rhs = choice((call_rhs, array_rhs, cast_rhs, member_rhs)); @@ -912,9 +1110,7 @@ where atom(expr_parser, expr_no_constructors, statement, allow_constructors), rhs, |lhs, rhs, span| match rhs { - UnaryRhs::Call((is_macro, args)) => { - Expression::call(lhs, is_macro.is_some(), args, span) - } + UnaryRhs::Call(args) => Expression::call(lhs, args, span), UnaryRhs::ArrayIndex(index) => Expression::index(lhs, index, span), UnaryRhs::Cast(r#type) => Expression::cast(lhs, r#type, span), UnaryRhs::MemberAccess(field) => { @@ -1076,7 +1272,6 @@ where block(statement.clone()).map(ExpressionKind::Block), comptime_expr(statement.clone()), quote(statement), - unquote(expr_parser.clone()), variable(), literal(), )) @@ -1105,25 +1300,13 @@ fn quote<'a, P>(statement: P) -> impl NoirParser + 'a where P: NoirParser + 'a, { - 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))) + keyword(Keyword::Quote).ignore_then(block(statement)).validate(|block, span, emit| { + emit(ParserError::with_reason( + ParserErrorReason::ExperimentalFeature("quoted expressions"), + span, + )); + ExpressionKind::Quote(block) + }) } fn tuple

(expr_parser: P) -> impl NoirParser @@ -1269,6 +1452,11 @@ 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]"]; @@ -1547,19 +1735,27 @@ 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 = one", errors: 1 }, + Case { source: "foo = one two three", expect: "foo = plain::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 (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: "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: "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 (x == x)", errors: 0 }, + Case { + source: "assert_eq(x, x, x)", + expect: "constrain (plain::x == plain::x)", + errors: 0, + }, ]; check_cases_with_errors(&cases[..], fresh_statement()); @@ -1601,7 +1797,7 @@ mod test { source: "{ if structure { a: 1 } {} }", expect: concat!( "{\n", - " if structure {\n", + " if plain::structure {\n", " Error\n", " }\n", " {\n", @@ -1612,17 +1808,22 @@ mod test { }, Case { source: "{ if ( structure { a: 1 } ) {} }", - expect: concat!("{\n", " if ((structure { a: 1 })) {\n", " }\n", "}",), + expect: concat!("{\n", " if ((plain::structure { a: 1 })) {\n", " }\n", "}",), errors: 0, }, Case { source: "{ if ( structure {} ) {} }", - expect: concat!("{\n", " if ((structure { })) {\n", " }\n", "}"), + expect: concat!("{\n", " if ((plain::structure { })) {\n", " }\n", "}"), errors: 0, }, Case { source: "{ if (a { x: 1 }, b { y: 2 }) {} }", - expect: concat!("{\n", " if ((a { x: 1 }), (b { y: 2 })) {\n", " }\n", "}",), + expect: concat!( + "{\n", + " if ((plain::a { x: 1 }), (plain::b { y: 2 })) {\n", + " }\n", + "}", + ), errors: 0, }, Case { @@ -1630,8 +1831,8 @@ mod test { expect: concat!( "{\n", " if ({\n", - " let foo: unspecified = (bar { baz: 42 })\n", - " (foo == (bar { baz: 42 }))\n", + " let foo: unspecified = (plain::bar { baz: 42 })\n", + " (plain::foo == (plain::bar { baz: 42 }))\n", " }) {\n", " }\n", "}", diff --git a/compiler/noirc_frontend/src/parser/parser/literals.rs b/compiler/noirc_frontend/src/parser/parser/literals.rs index b25b6acc9e2..584224fda46 100644 --- a/compiler/noirc_frontend/src/parser/parser/literals.rs +++ b/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: "r", errors: 2 }, - Case { source: r#" r\"foo\" "#, expect: "r", errors: 1 }, + 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: "(none)", errors: 2 }, // missing 'r' letter Case { source: r##" ##"foo"# "##, expect: r#""foo""#, errors: 2 }, - Case { source: r#" #"foo" "#, expect: "foo", errors: 2 }, + Case { source: r#" #"foo" "#, expect: "plain::foo", errors: 2 }, // whitespace - Case { source: r##" r #"foo"# "##, expect: "r", errors: 2 }, - Case { source: r##" r# "foo"# "##, expect: "r", errors: 3 }, + 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: "(none)", errors: 2 }, // after identifier - Case { source: r##" bar#"foo"# "##, expect: "bar", errors: 2 }, + Case { source: r##" bar#"foo"# "##, expect: "plain::bar", errors: 2 }, // nested Case { source: r###"r##"foo r#"bar"# r"baz" ### bye"##"###, diff --git a/compiler/noirc_frontend/src/parser/parser/types.rs b/compiler/noirc_frontend/src/parser/parser/types.rs index 40edc9936d1..82dd3dad681 100644 --- a/compiler/noirc_frontend/src/parser/parser/types.rs +++ b/compiler/noirc_frontend/src/parser/parser/types.rs @@ -1,38 +1,22 @@ use super::{ - expression_with_precedence, keyword, nothing, parenthesized, path, NoirParser, ParserError, + expression_with_precedence, keyword, nothing, parenthesized, NoirParser, ParserError, ParserErrorReason, Precedence, }; -use crate::ast::{Recoverable, UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression}; +use crate::ast::{UnresolvedType, UnresolvedTypeData}; use crate::parser::labels::ParsingRuleLabel; use crate::token::{Keyword, Token}; +use crate::{Recoverable, UnresolvedTypeExpression}; use chumsky::prelude::*; use noirc_errors::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), - )) +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 parenthesized_type( @@ -46,41 +30,29 @@ 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 { - keyword(Keyword::Field) + maybe_comp_time() + .then_ignore(keyword(Keyword::Field)) .map_with_span(|_, span| UnresolvedTypeData::FieldElement.with_span(span)) } pub(super) fn bool_type() -> impl NoirParser { - 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)) + maybe_comp_time() + .then_ignore(keyword(Keyword::Bool)) + .map_with_span(|_, span| UnresolvedTypeData::Bool.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))) + .ignore_then( + type_expression().delimited_by(just(Token::Less), just(Token::Greater)).or_not(), + ) .map_with_span(|expr, span| UnresolvedTypeData::String(expr).with_span(span)) } -pub(super) fn format_string_type<'a>( - type_parser: impl NoirParser + 'a, -) -> impl NoirParser + 'a { +pub(super) fn format_string_type( + type_parser: impl NoirParser, +) -> impl NoirParser { keyword(Keyword::FormatString) .ignore_then( type_expression() @@ -94,61 +66,26 @@ pub(super) fn format_string_type<'a>( } pub(super) 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) - }, - ) - }) -} - -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) + 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) + }) + }) } -pub(super) fn array_type<'a>( - type_parser: impl NoirParser + 'a, -) -> impl NoirParser + 'a { +pub(super) fn array_type( + type_parser: impl NoirParser, +) -> impl NoirParser { just(Token::LeftBracket) .ignore_then(type_parser) .then(just(Token::Semicolon).ignore_then(type_expression())) diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index 1acf1fbf3f2..99215c8f173 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/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(), "Default"); + assert_eq!(not_a_trait_name.to_string(), "plain::Default"); } _ => { panic!("No other errors are expected! Found = {:?}", err); diff --git a/cspell.json b/cspell.json index 2fb20ae2ba4..9eb6e6f9239 100644 --- a/cspell.json +++ b/cspell.json @@ -166,7 +166,6 @@ "rfind", "rustc", "rustup", - "sboxed", "schnorr", "sdiv", "secp256k1", diff --git a/docs/docs/how_to/how-to-oracles.md b/docs/docs/how_to/how-to-oracles.md index 2d2ed5c94b9..64d984c8cf9 100644 --- a/docs/docs/how_to/how-to-oracles.md +++ b/docs/docs/how_to/how-to-oracles.md @@ -141,10 +141,10 @@ server.addMethod("resolve_function_call", async (params) => { if params.function !== "getSqrt" { throw Error("Unexpected foreign call") }; - const values = params.inputs[0].Array.map((field) => { + const values = params.inputs[0].map((field) => { return `${Math.sqrt(parseInt(field, 16))}`; }); - return { values: [{ Array: values }] }; + return { values }; }); ``` @@ -166,10 +166,6 @@ 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 @@ -236,9 +232,9 @@ const foreignCallHandler = async (name, input) => { // notice that the "inputs" parameter contains *all* the inputs // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] const oracleReturn = await client.request(name, [ - { Array: input[0].map((i) => i.toString("hex")) }, + input[0].map((i) => i.toString("hex")), ]); - return [oracleReturn.values[0].Array]; + return { values: oracleReturn }; }; // the rest of your NoirJS code diff --git a/docs/docs/noir/concepts/data_types/arrays.md b/docs/docs/noir/concepts/data_types/arrays.md index 95d749053e2..efce3e95d32 100644 --- a/docs/docs/noir/concepts/data_types/arrays.md +++ b/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.mdx), 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), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,9 +70,7 @@ 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/docs/docs/noir/concepts/data_types/booleans.md b/docs/docs/noir/concepts/data_types/booleans.md index 2507af710e7..3dcfa836814 100644 --- a/docs/docs/noir/concepts/data_types/booleans.md +++ b/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.md) and -[Assert Function](../assert.md) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/docs/noir/concepts/data_types/strings.md b/docs/docs/noir/concepts/data_types/strings.md index 8ab5825a4c4..311dfd64416 100644 --- a/docs/docs/noir/concepts/data_types/strings.md +++ b/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.md). +`println()`. See more about [Logging](../../standard_library/logging). ```rust use dep::std; diff --git a/docs/docs/noir/concepts/generics.md b/docs/docs/noir/concepts/generics.md index 0c1c27a2221..ddd42bf1f9b 100644 --- a/docs/docs/noir/concepts/generics.md +++ b/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.md) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits) 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.md). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits). diff --git a/docs/docs/noir/concepts/unconstrained.md b/docs/docs/noir/concepts/unconstrained.md index 96f824c5e42..b8e71fe65f0 100644 --- a/docs/docs/noir/concepts/unconstrained.md +++ b/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.md#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) diff --git a/docs/docs/noir/modules_packages_crates/dependencies.md b/docs/docs/noir/modules_packages_crates/dependencies.md index 2c028d85853..04c1703d929 100644 --- a/docs/docs/noir/modules_packages_crates/dependencies.md +++ b/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.md#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#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.md) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/docs/noir/standard_library/black_box_fns.md b/docs/docs/noir/standard_library/black_box_fns.md index d5694250f05..eeead580969 100644 --- a/docs/docs/noir/standard_library/black_box_fns.md +++ b/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.md) +- [Recursive proof verification](./recursion) 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/docs/docs/noir/standard_library/containers/boundedvec.md b/docs/docs/noir/standard_library/containers/boundedvec.md index 98b7d584033..ccce62562f8 100644 --- a/docs/docs/noir/standard_library/containers/boundedvec.md +++ b/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(self, index: u64) -> T { +pub fn get(mut self: 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(self, index: u64) -> T { +pub fn get_unchecked(mut self: Self, index: u64) -> T { ``` Retrieves an element from the vector at the given index, starting from zero, without @@ -93,42 +93,6 @@ 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 @@ -246,18 +210,6 @@ 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/docs/docs/noir/standard_library/containers/vec.mdx b/docs/docs/noir/standard_library/containers/vec.mdx index 475011922f8..fcfd7e07aa0 100644 --- a/docs/docs/noir/standard_library/containers/vec.mdx +++ b/docs/docs/noir/standard_library/containers/vec.mdx @@ -84,25 +84,6 @@ 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/docs/docs/noir/standard_library/recursion.md b/docs/docs/noir/standard_library/recursion.md index cb3e7a9fcdf..a93894043dc 100644 --- a/docs/docs/noir/standard_library/recursion.md +++ b/docs/docs/noir/standard_library/recursion.md @@ -4,8 +4,6 @@ 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) @@ -35,7 +33,11 @@ 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/docs/docs/tooling/debugger.md b/docs/docs/tooling/debugger.md index 9b7565ba9ff..7c158d949d1 100644 --- a/docs/docs/tooling/debugger.md +++ b/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/index.md) 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) and vscode-noir: - Noir & Nargo ≥0.28.0 - Noir's VS Code extension ≥0.0.11 diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts index f0c986f1c28..29f612b0109 100644 --- a/docs/docusaurus.config.ts +++ b/docs/docusaurus.config.ts @@ -14,7 +14,6 @@ export default { favicon: 'img/favicon.ico', url: 'https://noir-lang.org', baseUrl: '/', - trailingSlash: true, onBrokenLinks: 'throw', onBrokenMarkdownLinks: 'throw', i18n: { diff --git a/docs/src/components/Notes/_blackbox.mdx b/docs/src/components/Notes/_blackbox.mdx index 226017072c8..9fe9b48fbff 100644 --- a/docs/src/components/Notes/_blackbox.mdx +++ b/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/docs/versioned_docs/version-v0.17.0/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.17.0/getting_started/01_hello_world.md index 34f8cd96fcd..d4daae605a2 100644 --- a/docs/versioned_docs/version-v0.17.0/getting_started/01_hello_world.md +++ b/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.md) section. +[Data Types](../language_concepts/data_types) 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.md) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. ## Build In/Output Files diff --git a/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md index 8616feee917..e7b1f33b339 100644 --- a/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md +++ b/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.md) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces) 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.md)for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/docs/versioned_docs/version-v0.17.0/index.md b/docs/versioned_docs/version-v0.17.0/index.md index c88aabf0ac1..2d5e6f4454f 100644 --- a/docs/versioned_docs/version-v0.17.0/index.md +++ b/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.md#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) 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.md) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies) for more information. diff --git a/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/02_booleans.md b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/02_booleans.md index d353606210a..885db167d83 100644 --- a/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/02_booleans.md +++ b/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.md) and -[Assert Function](../assert.md) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/03_strings.md b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/03_strings.md index 4360893e9a2..c42f34ec3ad 100644 --- a/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/03_strings.md +++ b/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.md). +`std::println()`. See more about [Logging](../../standard_library/logging). ```rust use dep::std; diff --git a/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/04_arrays.md b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/04_arrays.md index 1424ca2df14..bdbd1798bef 100644 --- a/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/04_arrays.md +++ b/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.mdx), 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), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md index 87a09293ea8..e91e73a4c4f 100644 --- a/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md +++ b/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.md#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#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.md) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.17.0/nargo/01_commands.md b/docs/versioned_docs/version-v0.17.0/nargo/01_commands.md index e2b0af522f4..65e2bdb44e3 100644 --- a/docs/versioned_docs/version-v0.17.0/nargo/01_commands.md +++ b/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.md). +See an example on the [testing page](./testing). ### Options diff --git a/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md index b4dedefe4c9..a412de19d06 100644 --- a/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md +++ b/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.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) +- [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) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) +- [Keccak256](./cryptographic_primitives/hashes#keccak256) +- [Recursive proof verification](./recursion) 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/docs/versioned_docs/version-v0.17.0/standard_library/recursion.md b/docs/versioned_docs/version-v0.17.0/standard_library/recursion.md index 5e592a2fd89..ff4c63acaa7 100644 --- a/docs/versioned_docs/version-v0.17.0/standard_library/recursion.md +++ b/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.md) 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. ::: diff --git a/docs/versioned_docs/version-v0.19.0/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.19.0/getting_started/01_hello_world.md index 34f8cd96fcd..d4daae605a2 100644 --- a/docs/versioned_docs/version-v0.19.0/getting_started/01_hello_world.md +++ b/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.md) section. +[Data Types](../language_concepts/data_types) 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.md) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. ## Build In/Output Files diff --git a/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md index f928370b2e8..d28a54a1600 100644 --- a/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md +++ b/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.md) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces) 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.md)for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/docs/versioned_docs/version-v0.19.0/index.md b/docs/versioned_docs/version-v0.19.0/index.md index e8d86020a20..380368db036 100644 --- a/docs/versioned_docs/version-v0.19.0/index.md +++ b/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.md) 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) 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.md) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies) for more information. diff --git a/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/02_booleans.md b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/02_booleans.md index d353606210a..885db167d83 100644 --- a/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/02_booleans.md +++ b/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.md) and -[Assert Function](../assert.md) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/03_strings.md b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/03_strings.md index 4360893e9a2..c42f34ec3ad 100644 --- a/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/03_strings.md +++ b/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.md). +`std::println()`. See more about [Logging](../../standard_library/logging). ```rust use dep::std; diff --git a/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/04_arrays.md b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/04_arrays.md index 1424ca2df14..bdbd1798bef 100644 --- a/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/04_arrays.md +++ b/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.mdx), 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), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md index 87a09293ea8..e91e73a4c4f 100644 --- a/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md +++ b/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.md#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#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.md) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.19.0/nargo/01_commands.md b/docs/versioned_docs/version-v0.19.0/nargo/01_commands.md index e2b0af522f4..65e2bdb44e3 100644 --- a/docs/versioned_docs/version-v0.19.0/nargo/01_commands.md +++ b/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.md). +See an example on the [testing page](./testing). ### Options diff --git a/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md index 985bb7c879d..e0c6d475c1f 100644 --- a/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md +++ b/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.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) +- [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) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) +- [Keccak256](./cryptographic_primitives/hashes#keccak256) +- [Recursive proof verification](./recursion) 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/docs/versioned_docs/version-v0.19.0/standard_library/recursion.md b/docs/versioned_docs/version-v0.19.0/standard_library/recursion.md index 5e592a2fd89..ff4c63acaa7 100644 --- a/docs/versioned_docs/version-v0.19.0/standard_library/recursion.md +++ b/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.md) 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. ::: diff --git a/docs/versioned_docs/version-v0.19.1/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.19.1/getting_started/01_hello_world.md index 34f8cd96fcd..d4daae605a2 100644 --- a/docs/versioned_docs/version-v0.19.1/getting_started/01_hello_world.md +++ b/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.md) section. +[Data Types](../language_concepts/data_types) 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.md) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. ## Build In/Output Files diff --git a/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md index f928370b2e8..d28a54a1600 100644 --- a/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md +++ b/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.md) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces) 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.md)for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/docs/versioned_docs/version-v0.19.1/index.md b/docs/versioned_docs/version-v0.19.1/index.md index e8d86020a20..380368db036 100644 --- a/docs/versioned_docs/version-v0.19.1/index.md +++ b/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.md) 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) 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.md) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies) for more information. diff --git a/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/02_booleans.md b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/02_booleans.md index d353606210a..885db167d83 100644 --- a/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/02_booleans.md +++ b/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.md) and -[Assert Function](../assert.md) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/03_strings.md b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/03_strings.md index 4360893e9a2..c42f34ec3ad 100644 --- a/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/03_strings.md +++ b/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.md). +`std::println()`. See more about [Logging](../../standard_library/logging). ```rust use dep::std; diff --git a/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/04_arrays.md b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/04_arrays.md index 1424ca2df14..bdbd1798bef 100644 --- a/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/04_arrays.md +++ b/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.mdx), 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), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md index 87a09293ea8..e91e73a4c4f 100644 --- a/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md +++ b/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.md#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#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.md) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.19.1/nargo/01_commands.md b/docs/versioned_docs/version-v0.19.1/nargo/01_commands.md index e2b0af522f4..65e2bdb44e3 100644 --- a/docs/versioned_docs/version-v0.19.1/nargo/01_commands.md +++ b/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.md). +See an example on the [testing page](./testing). ### Options diff --git a/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md index 985bb7c879d..e0c6d475c1f 100644 --- a/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md +++ b/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.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) +- [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) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) +- [Keccak256](./cryptographic_primitives/hashes#keccak256) +- [Recursive proof verification](./recursion) 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/docs/versioned_docs/version-v0.19.1/standard_library/recursion.md b/docs/versioned_docs/version-v0.19.1/standard_library/recursion.md index 5e592a2fd89..ff4c63acaa7 100644 --- a/docs/versioned_docs/version-v0.19.1/standard_library/recursion.md +++ b/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.md) 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. ::: diff --git a/docs/versioned_docs/version-v0.19.2/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.19.2/getting_started/01_hello_world.md index 34f8cd96fcd..d4daae605a2 100644 --- a/docs/versioned_docs/version-v0.19.2/getting_started/01_hello_world.md +++ b/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.md) section. +[Data Types](../language_concepts/data_types) 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.md) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. ## Build In/Output Files diff --git a/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md index f928370b2e8..d28a54a1600 100644 --- a/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md +++ b/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.md) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces) 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.md)for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/docs/versioned_docs/version-v0.19.2/index.md b/docs/versioned_docs/version-v0.19.2/index.md index e8d86020a20..380368db036 100644 --- a/docs/versioned_docs/version-v0.19.2/index.md +++ b/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.md) 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) 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.md) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies) for more information. diff --git a/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/02_booleans.md b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/02_booleans.md index d353606210a..885db167d83 100644 --- a/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/02_booleans.md +++ b/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.md) and -[Assert Function](../assert.md) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/03_strings.md b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/03_strings.md index 4360893e9a2..c42f34ec3ad 100644 --- a/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/03_strings.md +++ b/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.md). +`std::println()`. See more about [Logging](../../standard_library/logging). ```rust use dep::std; diff --git a/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/04_arrays.md b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/04_arrays.md index 1424ca2df14..bdbd1798bef 100644 --- a/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/04_arrays.md +++ b/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.mdx), 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), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md index 87a09293ea8..e91e73a4c4f 100644 --- a/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md +++ b/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.md#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#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.md) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.19.2/nargo/01_commands.md b/docs/versioned_docs/version-v0.19.2/nargo/01_commands.md index e2b0af522f4..65e2bdb44e3 100644 --- a/docs/versioned_docs/version-v0.19.2/nargo/01_commands.md +++ b/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.md). +See an example on the [testing page](./testing). ### Options diff --git a/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md index 985bb7c879d..e0c6d475c1f 100644 --- a/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md +++ b/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.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) +- [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) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) +- [Keccak256](./cryptographic_primitives/hashes#keccak256) +- [Recursive proof verification](./recursion) 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/docs/versioned_docs/version-v0.19.2/standard_library/recursion.md b/docs/versioned_docs/version-v0.19.2/standard_library/recursion.md index 5e592a2fd89..ff4c63acaa7 100644 --- a/docs/versioned_docs/version-v0.19.2/standard_library/recursion.md +++ b/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.md) 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. ::: diff --git a/docs/versioned_docs/version-v0.19.3/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.19.3/getting_started/01_hello_world.md index 34f8cd96fcd..d4daae605a2 100644 --- a/docs/versioned_docs/version-v0.19.3/getting_started/01_hello_world.md +++ b/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.md) section. +[Data Types](../language_concepts/data_types) 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.md) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. ## Build In/Output Files diff --git a/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md index 10422029661..7a7fb876c35 100644 --- a/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md +++ b/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.md) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces) 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.md)for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/docs/versioned_docs/version-v0.19.3/index.md b/docs/versioned_docs/version-v0.19.3/index.md index e8d86020a20..380368db036 100644 --- a/docs/versioned_docs/version-v0.19.3/index.md +++ b/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.md) 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) 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.md) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies) for more information. diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/02_booleans.md b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/02_booleans.md index d353606210a..885db167d83 100644 --- a/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/02_booleans.md +++ b/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.md) and -[Assert Function](../assert.md) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md index 4360893e9a2..c42f34ec3ad 100644 --- a/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md +++ b/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.md). +`std::println()`. See more about [Logging](../../standard_library/logging). ```rust use dep::std; diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md index 1424ca2df14..bdbd1798bef 100644 --- a/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md +++ b/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.mdx), 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), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md index 87a09293ea8..e91e73a4c4f 100644 --- a/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md +++ b/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.md#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#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.md) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.19.3/nargo/01_commands.md b/docs/versioned_docs/version-v0.19.3/nargo/01_commands.md index e2b0af522f4..65e2bdb44e3 100644 --- a/docs/versioned_docs/version-v0.19.3/nargo/01_commands.md +++ b/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.md). +See an example on the [testing page](./testing). ### Options diff --git a/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md index 985bb7c879d..e0c6d475c1f 100644 --- a/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md +++ b/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.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) +- [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) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) +- [Keccak256](./cryptographic_primitives/hashes#keccak256) +- [Recursive proof verification](./recursion) 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/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md b/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md index 5e592a2fd89..ff4c63acaa7 100644 --- a/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md +++ b/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.md) 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. ::: diff --git a/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md index 34f8cd96fcd..d4daae605a2 100644 --- a/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md +++ b/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.md) section. +[Data Types](../language_concepts/data_types) 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.md) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. ## Build In/Output Files diff --git a/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md index f928370b2e8..d28a54a1600 100644 --- a/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md +++ b/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.md) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces) 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.md)for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/docs/versioned_docs/version-v0.19.4/index.md b/docs/versioned_docs/version-v0.19.4/index.md index e8d86020a20..380368db036 100644 --- a/docs/versioned_docs/version-v0.19.4/index.md +++ b/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.md) 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) 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.md) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies) for more information. diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md index d353606210a..885db167d83 100644 --- a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md +++ b/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.md) and -[Assert Function](../assert.md) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md index baa3f205094..b4c75942bb8 100644 --- a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md +++ b/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.md). +You can use strings in `assert()` functions or print them with `std::println()`. See more about [Logging](../../standard_library/logging). ```rust use dep::std; diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md index 1424ca2df14..bdbd1798bef 100644 --- a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md +++ b/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.mdx), 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), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md index 87a09293ea8..e91e73a4c4f 100644 --- a/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md +++ b/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.md#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#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.md) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.19.4/nargo/01_commands.md b/docs/versioned_docs/version-v0.19.4/nargo/01_commands.md index e2b0af522f4..65e2bdb44e3 100644 --- a/docs/versioned_docs/version-v0.19.4/nargo/01_commands.md +++ b/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.md). +See an example on the [testing page](./testing). ### Options diff --git a/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md index 985bb7c879d..e0c6d475c1f 100644 --- a/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md +++ b/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.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) +- [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) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) +- [Keccak256](./cryptographic_primitives/hashes#keccak256) +- [Recursive proof verification](./recursion) 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/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md b/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md index 5e592a2fd89..ff4c63acaa7 100644 --- a/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md +++ b/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.md) 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. ::: diff --git a/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md index d9d21ef0485..a37dc401b7d 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md +++ b/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.md#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#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.md) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md index 985bb7c879d..e0c6d475c1f 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md +++ b/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.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) +- [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) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) +- [Keccak256](./cryptographic_primitives/hashes#keccak256) +- [Recursive proof verification](./recursion) 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/docs/versioned_docs/version-v0.22.0/noir/standard_library/recursion.md b/docs/versioned_docs/version-v0.22.0/noir/standard_library/recursion.md index 4a004fd3664..67962082a8f 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/standard_library/recursion.md +++ b/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.md) 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. ::: diff --git a/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/arrays.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/arrays.md index 4c80d50ed01..075d39dadd4 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/arrays.md +++ b/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.mdx), 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), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/booleans.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/booleans.md index 7211716f63e..69826fcd724 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/booleans.md +++ b/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.md) and -[Assert Function](../assert.md) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/strings.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/strings.md index dd6c844f6ae..8d76d4ca654 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/strings.md +++ b/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.md). +`std::println()`. See more about [Logging](../../standard_library/logging). ```rust use dep::std; diff --git a/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/arrays.md b/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/arrays.md index d95346454a9..7f275a2d771 100644 --- a/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/arrays.md +++ b/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.mdx), 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), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,9 +70,7 @@ 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/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/booleans.md b/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/booleans.md index 7211716f63e..69826fcd724 100644 --- a/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/booleans.md +++ b/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.md) and -[Assert Function](../assert.md) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/strings.md b/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/strings.md index 8ab5825a4c4..311dfd64416 100644 --- a/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/strings.md +++ b/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.md). +`println()`. See more about [Logging](../../standard_library/logging). ```rust use dep::std; diff --git a/docs/versioned_docs/version-v0.23.0/noir/concepts/generics.md b/docs/versioned_docs/version-v0.23.0/noir/concepts/generics.md index 0c1c27a2221..ddd42bf1f9b 100644 --- a/docs/versioned_docs/version-v0.23.0/noir/concepts/generics.md +++ b/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.md) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits) 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.md). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits). diff --git a/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/dependencies.md index d9d21ef0485..a37dc401b7d 100644 --- a/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/dependencies.md +++ b/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.md#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#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.md) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.23.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.23.0/noir/standard_library/black_box_fns.md index e8b62f21d4e..eae8744abf0 100644 --- a/docs/versioned_docs/version-v0.23.0/noir/standard_library/black_box_fns.md +++ b/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.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) +- [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) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion.md) +- [Keccak256](./cryptographic_primitives/hashes#keccak256) +- [Recursive proof verification](./recursion) 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/docs/versioned_docs/version-v0.23.0/noir/standard_library/recursion.md b/docs/versioned_docs/version-v0.23.0/noir/standard_library/recursion.md index 4390bda4a26..f252150c8b5 100644 --- a/docs/versioned_docs/version-v0.23.0/noir/standard_library/recursion.md +++ b/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.md) 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. ::: diff --git a/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/arrays.md b/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/arrays.md index ca54d82b26b..a8bd338e736 100644 --- a/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/arrays.md +++ b/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.mdx), 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), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,9 +70,7 @@ 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/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/booleans.md b/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/booleans.md index 7211716f63e..69826fcd724 100644 --- a/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/booleans.md +++ b/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.md) and -[Assert Function](../assert.md) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/strings.md b/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/strings.md index 8ab5825a4c4..311dfd64416 100644 --- a/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/strings.md +++ b/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.md). +`println()`. See more about [Logging](../../standard_library/logging). ```rust use dep::std; diff --git a/docs/versioned_docs/version-v0.24.0/noir/concepts/generics.md b/docs/versioned_docs/version-v0.24.0/noir/concepts/generics.md index 0c1c27a2221..ddd42bf1f9b 100644 --- a/docs/versioned_docs/version-v0.24.0/noir/concepts/generics.md +++ b/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.md) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits) 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.md). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits). diff --git a/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/dependencies.md index d9d21ef0485..a37dc401b7d 100644 --- a/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/dependencies.md +++ b/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.md#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#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.md) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md index e8b62f21d4e..be8c65679c3 100644 --- a/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md +++ b/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.md) +- [Recursive proof verification](./recursion) 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/docs/versioned_docs/version-v0.24.0/noir/standard_library/recursion.md b/docs/versioned_docs/version-v0.24.0/noir/standard_library/recursion.md index ed2ed01fceb..9337499dac8 100644 --- a/docs/versioned_docs/version-v0.24.0/noir/standard_library/recursion.md +++ b/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.md) 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. ::: diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md index ca54d82b26b..a8bd338e736 100644 --- a/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md +++ b/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.mdx), 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), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,9 +70,7 @@ 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/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md index 7211716f63e..69826fcd724 100644 --- a/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md +++ b/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.md) and -[Assert Function](../assert.md) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md index 8ab5825a4c4..311dfd64416 100644 --- a/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md +++ b/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.md). +`println()`. See more about [Logging](../../standard_library/logging). ```rust use dep::std; diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md index 0c1c27a2221..ddd42bf1f9b 100644 --- a/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md +++ b/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.md) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits) 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.md). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits). diff --git a/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md index 2c028d85853..04c1703d929 100644 --- a/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md +++ b/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.md#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#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.md) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md index e8b62f21d4e..be8c65679c3 100644 --- a/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md +++ b/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.md) +- [Recursive proof verification](./recursion) 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/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md b/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md index ed2ed01fceb..9337499dac8 100644 --- a/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md +++ b/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.md) 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. ::: diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/arrays.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/arrays.md index 95d749053e2..efce3e95d32 100644 --- a/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/arrays.md +++ b/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.mdx), 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), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,9 +70,7 @@ 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/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/booleans.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/booleans.md index 7211716f63e..69826fcd724 100644 --- a/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/booleans.md +++ b/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.md) and -[Assert Function](../assert.md) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md index 8ab5825a4c4..311dfd64416 100644 --- a/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md +++ b/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.md). +`println()`. See more about [Logging](../../standard_library/logging). ```rust use dep::std; diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md index 0c1c27a2221..ddd42bf1f9b 100644 --- a/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md +++ b/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.md) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits) 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.md). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits). diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/unconstrained.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/unconstrained.md index 96f824c5e42..b8e71fe65f0 100644 --- a/docs/versioned_docs/version-v0.26.0/noir/concepts/unconstrained.md +++ b/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.md#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) diff --git a/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/dependencies.md index 2c028d85853..04c1703d929 100644 --- a/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/dependencies.md +++ b/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.md#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#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.md) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.26.0/noir/standard_library/black_box_fns.md index e8b62f21d4e..be8c65679c3 100644 --- a/docs/versioned_docs/version-v0.26.0/noir/standard_library/black_box_fns.md +++ b/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.md) +- [Recursive proof verification](./recursion) 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/docs/versioned_docs/version-v0.26.0/noir/standard_library/recursion.md b/docs/versioned_docs/version-v0.26.0/noir/standard_library/recursion.md index f33c285cf4e..a93894043dc 100644 --- a/docs/versioned_docs/version-v0.26.0/noir/standard_library/recursion.md +++ b/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.md) 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. ::: diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md index 95d749053e2..efce3e95d32 100644 --- a/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md +++ b/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.mdx), 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), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,9 +70,7 @@ 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/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/booleans.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/booleans.md index 7211716f63e..69826fcd724 100644 --- a/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/booleans.md +++ b/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.md) and -[Assert Function](../assert.md) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md index 8ab5825a4c4..311dfd64416 100644 --- a/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md +++ b/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.md). +`println()`. See more about [Logging](../../standard_library/logging). ```rust use dep::std; diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md index 0c1c27a2221..ddd42bf1f9b 100644 --- a/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md +++ b/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.md) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits) 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.md). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits). diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md index 96f824c5e42..b8e71fe65f0 100644 --- a/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md +++ b/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.md#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) diff --git a/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/dependencies.md index 2c028d85853..04c1703d929 100644 --- a/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/dependencies.md +++ b/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.md#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#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.md) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.27.0/noir/standard_library/black_box_fns.md index e8b62f21d4e..be8c65679c3 100644 --- a/docs/versioned_docs/version-v0.27.0/noir/standard_library/black_box_fns.md +++ b/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.md) +- [Recursive proof verification](./recursion) 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/docs/versioned_docs/version-v0.27.0/noir/standard_library/recursion.md b/docs/versioned_docs/version-v0.27.0/noir/standard_library/recursion.md index f33c285cf4e..a93894043dc 100644 --- a/docs/versioned_docs/version-v0.27.0/noir/standard_library/recursion.md +++ b/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.md) 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. ::: diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md index 95d749053e2..efce3e95d32 100644 --- a/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md +++ b/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.mdx), 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), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,9 +70,7 @@ 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/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/booleans.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/booleans.md index 7211716f63e..69826fcd724 100644 --- a/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/booleans.md +++ b/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.md) and -[Assert Function](../assert.md) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md index 8ab5825a4c4..311dfd64416 100644 --- a/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md +++ b/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.md). +`println()`. See more about [Logging](../../standard_library/logging). ```rust use dep::std; diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md index 0c1c27a2221..ddd42bf1f9b 100644 --- a/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md +++ b/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.md) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits) 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.md). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits). diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md index 96f824c5e42..b8e71fe65f0 100644 --- a/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md +++ b/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.md#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) diff --git a/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/dependencies.md index 2c028d85853..04c1703d929 100644 --- a/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/dependencies.md +++ b/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.md#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#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.md) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.28.0/noir/standard_library/black_box_fns.md index e8b62f21d4e..be8c65679c3 100644 --- a/docs/versioned_docs/version-v0.28.0/noir/standard_library/black_box_fns.md +++ b/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.md) +- [Recursive proof verification](./recursion) 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/docs/versioned_docs/version-v0.28.0/noir/standard_library/recursion.md b/docs/versioned_docs/version-v0.28.0/noir/standard_library/recursion.md index f33c285cf4e..a93894043dc 100644 --- a/docs/versioned_docs/version-v0.28.0/noir/standard_library/recursion.md +++ b/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.md) 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. ::: diff --git a/docs/versioned_docs/version-v0.28.0/tooling/debugger.md b/docs/versioned_docs/version-v0.28.0/tooling/debugger.md index 9b7565ba9ff..7c158d949d1 100644 --- a/docs/versioned_docs/version-v0.28.0/tooling/debugger.md +++ b/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/index.md) 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) and vscode-noir: - Noir & Nargo ≥0.28.0 - Noir's VS Code extension ≥0.0.11 diff --git a/docs/versioned_docs/version-v0.28.0/tutorials/noirjs_app.md b/docs/versioned_docs/version-v0.28.0/tutorials/noirjs_app.md index 3dd9fe7d2b0..6446e0b2a76 100644 --- a/docs/versioned_docs/version-v0.28.0/tutorials/noirjs_app.md +++ b/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 [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 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/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md index 95d749053e2..efce3e95d32 100644 --- a/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md +++ b/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.mdx), 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), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,9 +70,7 @@ 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/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/booleans.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/booleans.md index 7211716f63e..69826fcd724 100644 --- a/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/booleans.md +++ b/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.md) and -[Assert Function](../assert.md) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md index 8ab5825a4c4..311dfd64416 100644 --- a/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md +++ b/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.md). +`println()`. See more about [Logging](../../standard_library/logging). ```rust use dep::std; diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md index 0c1c27a2221..ddd42bf1f9b 100644 --- a/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md +++ b/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.md) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits) 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.md). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits). diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md index 96f824c5e42..b8e71fe65f0 100644 --- a/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md +++ b/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.md#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) diff --git a/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/dependencies.md index 2c028d85853..04c1703d929 100644 --- a/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/dependencies.md +++ b/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.md#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#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.md) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.29.0/noir/standard_library/black_box_fns.md index e8b62f21d4e..be8c65679c3 100644 --- a/docs/versioned_docs/version-v0.29.0/noir/standard_library/black_box_fns.md +++ b/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.md) +- [Recursive proof verification](./recursion) 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/docs/versioned_docs/version-v0.29.0/noir/standard_library/recursion.md b/docs/versioned_docs/version-v0.29.0/noir/standard_library/recursion.md index f33c285cf4e..a93894043dc 100644 --- a/docs/versioned_docs/version-v0.29.0/noir/standard_library/recursion.md +++ b/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.md) 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. ::: diff --git a/docs/versioned_docs/version-v0.29.0/tooling/debugger.md b/docs/versioned_docs/version-v0.29.0/tooling/debugger.md index 9b7565ba9ff..7c158d949d1 100644 --- a/docs/versioned_docs/version-v0.29.0/tooling/debugger.md +++ b/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/index.md) 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) and vscode-noir: - Noir & Nargo ≥0.28.0 - Noir's VS Code extension ≥0.0.11 diff --git a/docs/versioned_docs/version-v0.29.0/tutorials/noirjs_app.md b/docs/versioned_docs/version-v0.29.0/tutorials/noirjs_app.md index 3dd9fe7d2b0..6446e0b2a76 100644 --- a/docs/versioned_docs/version-v0.29.0/tutorials/noirjs_app.md +++ b/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 [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 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/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md index 95d749053e2..efce3e95d32 100644 --- a/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md +++ b/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.mdx), 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), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,9 +70,7 @@ 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/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/booleans.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/booleans.md index 7211716f63e..69826fcd724 100644 --- a/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/booleans.md +++ b/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.md) and -[Assert Function](../assert.md) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md index 8ab5825a4c4..311dfd64416 100644 --- a/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md +++ b/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.md). +`println()`. See more about [Logging](../../standard_library/logging). ```rust use dep::std; diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md index 0c1c27a2221..ddd42bf1f9b 100644 --- a/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md +++ b/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.md) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits) 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.md). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits). diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md index 96f824c5e42..b8e71fe65f0 100644 --- a/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md +++ b/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.md#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) diff --git a/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/dependencies.md index 2c028d85853..04c1703d929 100644 --- a/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/dependencies.md +++ b/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.md#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#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.md) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.30.0/noir/standard_library/black_box_fns.md index d5694250f05..eeead580969 100644 --- a/docs/versioned_docs/version-v0.30.0/noir/standard_library/black_box_fns.md +++ b/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.md) +- [Recursive proof verification](./recursion) 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/docs/versioned_docs/version-v0.30.0/noir/standard_library/recursion.md b/docs/versioned_docs/version-v0.30.0/noir/standard_library/recursion.md index f33c285cf4e..a93894043dc 100644 --- a/docs/versioned_docs/version-v0.30.0/noir/standard_library/recursion.md +++ b/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.md) 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. ::: diff --git a/docs/versioned_docs/version-v0.30.0/tooling/debugger.md b/docs/versioned_docs/version-v0.30.0/tooling/debugger.md index 9b7565ba9ff..7c158d949d1 100644 --- a/docs/versioned_docs/version-v0.30.0/tooling/debugger.md +++ b/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/index.md) 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) and vscode-noir: - Noir & Nargo ≥0.28.0 - Noir's VS Code extension ≥0.0.11 diff --git a/noir_stdlib/src/collections/bounded_vec.nr b/noir_stdlib/src/collections/bounded_vec.nr index 6fde9e70f4d..aae96e5943d 100644 --- a/noir_stdlib/src/collections/bounded_vec.nr +++ b/noir_stdlib/src/collections/bounded_vec.nr @@ -11,33 +11,13 @@ impl BoundedVec { BoundedVec { storage: [zeroed; MaxLen], len: 0 } } - /// 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 { + pub fn get(mut self: Self, index: u32) -> T { assert(index < self.len); - self.get_unchecked(index) - } - - /// 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 get_unchecked(mut self: Self, index: u32) -> T { + self.storage[index] } pub fn push(&mut self, elem: T) { @@ -121,17 +101,6 @@ 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 { @@ -173,73 +142,6 @@ 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_stdlib/src/collections/vec.nr b/noir_stdlib/src/collections/vec.nr index cedae7f5ce1..18aaa8b9b3b 100644 --- a/noir_stdlib/src/collections/vec.nr +++ b/noir_stdlib/src/collections/vec.nr @@ -21,12 +21,6 @@ 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. @@ -63,36 +57,3 @@ 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_stdlib/src/compat.nr b/noir_stdlib/src/compat.nr index 30b7f73f130..5d80c422c33 100644 --- a/noir_stdlib/src/compat.nr +++ b/noir_stdlib/src/compat.nr @@ -1,18 +1,4 @@ -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 { - // 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 - } + // bn254 truncates its curve order to 0 + 21888242871839275222246405745257275088548364400416034343698204186575808495617 == 0 } diff --git a/noir_stdlib/src/hash/mimc.nr b/noir_stdlib/src/hash/mimc.nr index e90bacb75c2..6c5502c2fbf 100644 --- a/noir_stdlib/src/hash/mimc.nr +++ b/noir_stdlib/src/hash/mimc.nr @@ -116,7 +116,6 @@ 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_stdlib/src/hash/poseidon/bn254.nr b/noir_stdlib/src/hash/poseidon/bn254.nr index 9d3accb1ebd..54f22884e29 100644 --- a/noir_stdlib/src/hash/poseidon/bn254.nr +++ b/noir_stdlib/src/hash/poseidon/bn254.nr @@ -6,14 +6,12 @@ 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() { @@ -23,7 +21,6 @@ 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() { @@ -33,7 +30,6 @@ 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() { @@ -43,7 +39,6 @@ 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() { @@ -53,7 +48,6 @@ 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() { @@ -63,7 +57,6 @@ 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() { @@ -73,7 +66,6 @@ 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() { @@ -83,7 +75,6 @@ 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() { @@ -93,7 +84,6 @@ 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() { @@ -103,7 +93,6 @@ 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() { @@ -113,7 +102,6 @@ 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() { @@ -123,7 +111,6 @@ 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() { @@ -133,7 +120,6 @@ 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() { @@ -143,7 +129,6 @@ 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() { @@ -153,7 +138,6 @@ 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() { @@ -163,7 +147,6 @@ 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_stdlib/src/hash/poseidon2.nr b/noir_stdlib/src/hash/poseidon2.nr index 4a68925255a..04d922b581d 100644 --- a/noir_stdlib/src/hash/poseidon2.nr +++ b/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_stdlib/src/sha256.nr b/noir_stdlib/src/sha256.nr index 6057876951d..d856043fcfa 100644 --- a/noir_stdlib/src/sha256.nr +++ b/noir_stdlib/src/sha256.nr @@ -38,7 +38,6 @@ 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_stdlib/src/sha512.nr b/noir_stdlib/src/sha512.nr index 4e46840ebb7..0f8ffcfcb1c 100644 --- a/noir_stdlib/src/sha512.nr +++ b/noir_stdlib/src/sha512.nr @@ -87,7 +87,6 @@ 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/scripts/redo-typo-pr.sh b/scripts/redo-typo-pr.sh deleted file mode 100755 index 416be65a449..00000000000 --- a/scripts/redo-typo-pr.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/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/test_programs/compile_success_empty/macros/src/main.nr b/test_programs/compile_success_empty/macros/src/main.nr deleted file mode 100644 index f466226d575..00000000000 --- a/test_programs/compile_success_empty/macros/src/main.nr +++ /dev/null @@ -1,15 +0,0 @@ -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/test_programs/compile_success_empty/no_duplicate_methods/Nargo.toml b/test_programs/compile_success_empty/no_duplicate_methods/Nargo.toml deleted file mode 100644 index 2125d475530..00000000000 --- a/test_programs/compile_success_empty/no_duplicate_methods/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "no_duplicate_methods" -type = "bin" -authors = [""] - -[dependencies] diff --git a/test_programs/compile_success_empty/no_duplicate_methods/Prover.toml b/test_programs/compile_success_empty/no_duplicate_methods/Prover.toml deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr b/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr deleted file mode 100644 index 2be1d3fa11e..00000000000 --- a/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr +++ /dev/null @@ -1,26 +0,0 @@ -// 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/test_programs/execution_success/regression_5202/Nargo.toml b/test_programs/execution_success/regression_5202/Nargo.toml deleted file mode 100644 index da3da06a306..00000000000 --- a/test_programs/execution_success/regression_5202/Nargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "regression_5202" -type = "bin" -authors = [""] -compiler_version = ">=0.30.0" - -[dependencies] -fraction = { path = "fraction" } diff --git a/test_programs/execution_success/regression_5202/fraction/LICENSE b/test_programs/execution_success/regression_5202/fraction/LICENSE deleted file mode 100644 index 929af4807ca..00000000000 --- a/test_programs/execution_success/regression_5202/fraction/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -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/test_programs/execution_success/regression_5202/fraction/Nargo.toml b/test_programs/execution_success/regression_5202/fraction/Nargo.toml deleted file mode 100644 index 82e929d0bc7..00000000000 --- a/test_programs/execution_success/regression_5202/fraction/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "fraction" -type = "lib" -authors = [""] - -[dependencies] diff --git a/test_programs/execution_success/regression_5202/fraction/README.md b/test_programs/execution_success/regression_5202/fraction/README.md deleted file mode 100644 index 17c81e5555a..00000000000 --- a/test_programs/execution_success/regression_5202/fraction/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# 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/test_programs/execution_success/regression_5202/fraction/src/lib.nr b/test_programs/execution_success/regression_5202/fraction/src/lib.nr deleted file mode 100644 index 4b20eb6b76c..00000000000 --- a/test_programs/execution_success/regression_5202/fraction/src/lib.nr +++ /dev/null @@ -1,201 +0,0 @@ -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/test_programs/execution_success/regression_5202/src/main.nr b/test_programs/execution_success/regression_5202/src/main.nr deleted file mode 100644 index e41b760b83e..00000000000 --- a/test_programs/execution_success/regression_5202/src/main.nr +++ /dev/null @@ -1,23 +0,0 @@ -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/test_programs/execution_success/regression_5252/Nargo.toml b/test_programs/execution_success/regression_5252/Nargo.toml deleted file mode 100644 index 855507dfaf3..00000000000 --- a/test_programs/execution_success/regression_5252/Nargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "regression_5252" -version = "0.1.0" -type = "bin" -authors = [""] - -[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/regression_5252/Prover.toml b/test_programs/execution_success/regression_5252/Prover.toml deleted file mode 100644 index 82776b4463d..00000000000 --- a/test_programs/execution_success/regression_5252/Prover.toml +++ /dev/null @@ -1,6 +0,0 @@ -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/test_programs/execution_success/regression_5252/src/main.nr b/test_programs/execution_success/regression_5252/src/main.nr deleted file mode 100644 index 315807c3396..00000000000 --- a/test_programs/execution_success/regression_5252/src/main.nr +++ /dev/null @@ -1,23 +0,0 @@ -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/test_programs/compile_success_empty/macros/Nargo.toml b/test_programs/execution_success/verify_honk_proof/Nargo.toml similarity index 75% rename from test_programs/compile_success_empty/macros/Nargo.toml rename to test_programs/execution_success/verify_honk_proof/Nargo.toml index e4408e2ee17..d298dabb560 100644 --- a/test_programs/compile_success_empty/macros/Nargo.toml +++ b/test_programs/execution_success/verify_honk_proof/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "macros" +name = "verify_honk_proof" type = "bin" authors = [""] compiler_version = ">=0.30.0" diff --git a/test_programs/execution_success/verify_honk_proof/Prover.toml b/test_programs/execution_success/verify_honk_proof/Prover.toml new file mode 100644 index 00000000000..4619fd298dd --- /dev/null +++ b/test_programs/execution_success/verify_honk_proof/Prover.toml @@ -0,0 +1,4 @@ +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","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x000000000000000000000000000000f968b227a358a305607f3efc933823d288","0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08","0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f","0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1","0x0000000000000000000000000000005b739ed2075f2b046062b8fc6a2d1e9863","0x00000000000000000000000000000000001285cd1030d338c0e1603b4da2c838","0x00000000000000000000000000000027447d6c281eb38b2b937af4a516d60c04","0x000000000000000000000000000000000019bc3d980465fbb4a656a74296fc58","0x000000000000000000000000000000b484788ace8f7df86dd5e325d2e9b12599","0x00000000000000000000000000000000000a2ca0d10eb7b767114ae230b728d3","0x000000000000000000000000000000c6dfc7092f16f95795e437664498b88d53","0x0000000000000000000000000000000000131067b4e4d95a4f6f8cf5c9b5450a","0x0f413f22eec51f2a02800e0cafaeec1d92d744fbbaef213c687b9edabd6985f5","0x21230f4ff26c80ffb5d037a9d1d26c3f955ca34cbeca4f54db6656b932967a0c","0x0521f877fe35535767f99597cc50effbd283dcae6812ee0a7620d796ccbfd642","0x202b01350a9cc5c20ec0f3eaada338c0a3b793811bd539418ffa3cc4302615e2","0x2d1214d9b0d41058ad4a172d9c0aecc5bdabe95e687c3465050c6b5396509be4","0x1113b344a151b0af091cb28d728b752ebb4865da6cd7ee68471b961ca5cf69b9","0x2aa66d0954bb83e17bd5c9928d3aa7a7df75d741d409f7c15ba596804ba643fb","0x2e26bc7a530771ef7a95d5360d537e41cf94d8a0942764ff09881c107f91a106","0x0f14f32b921bb63ad1df00adab7c82af58ea8aa7f353f14b281208d8c5fab504","0x13429515c0c53b6502bbcdf545defb3cb69a986c9263e070fcbb397391aae1a3","0x1f21cac5e2f262afc1006a21454cc6bcb018c44e53ad8ab61cebbac99e539176","0x2a9886a6ddc8a61b097c668cd362fc8acdee8dde74f7b1af192c3e060bb2948f","0x2d718181e408ead2e9bcd30a84ad1fccbaf8d48ab6d1820bad4933d284b503c4","0x2634c1aafc902f14508f34d3d7e9d485f42d1a4c95b5a1ef73711ed0d3c68d77","0x092ede9777e6472ce5ffd8c963d466006189e960e2c591d338dc8d4af1a057fb","0x1cba45b17fd24f1cb1b4ab7b83eee741f6c77ba70a497dc4de259eceb7d5ea26","0x246e887c7bf2e17f919b2393b6e9b00b33e8822d862544a775aac05cb7bff710","0x04c3f539fe8689971948afcb437f1ecbd444a5bddaca1c8a450348dcd8480047","0x20c6a423ae4fd58e8951aa378d02d77baf90508ceb48856db2319d70938b186e","0x1bcf8786b554b3316d8ebdbc9d006a4e5d4865aad512ffd404b7f83550d3d030","0x09ab038260518f0970564afcd6bf22e2abf6b1fa5e12a327bbf195b6ca5edd78","0x1024e32554746f89c195286ba6ccfc9765e5d14bbe8064bc6fdf22d16ec6b495","0x17706656f8dbd7e47bb257a6428f0cb7278ea02fa9e6ce431d7bcc9133fba9c7","0x25a3e8a33c15ef2a4dd16313a6049bf1d468b4cdc141f238f2d51a1e8e1c22b3","0x1198863f08006edb27aee23164fb117a4ddec1bf1ed89807aa907e5cd24bf068","0x1862b4856b5b4d4a064f873e221703e4e2cd1ebfca1337dedca56485c38ed5a0","0x062214af1ea6dd6bf8895b92d394571c43970b6f967e1c794624d96071b25ad3","0x1e5be9428ddcf1f9b0cbafc28101e792ec5cf73852b0cd0b84fbff71b4490e09","0x2d4189bea5b1e30f63c64bd26df82f18bcaf885ec8887b54634b2557869ce87f","0x0f2e5d9a908850e9d44925e17d8b12d1adb1ed029799c9b5858598504242bbc0","0x3050dc85746a57931d99f3f35e77c2ba561fba0baa018b79ff1fd544026833ae","0x2a591a32437e5e0b875a137fd868bd1b6dbc003ff1b661f26e00627cc7c5cf47","0x27946841e1670ad9c65717016d0cedf524724217236e81b9fd0a264a36ebfb0e","0x0fc396e9d19d6e68e289602e292ee345542d0d28bf6de34fa62cc577cbdfb1df","0x08e7433a07a44c0c9c4dd4b273a2685bbd1a91fd5cf2b43409458fab42a23e1b","0x12bd9bfb029c3503a5c6deea87b0a0f11bb9f7ea584af2d48f3e48d7e09247ae","0x2ccc4810748c0a82dfc0f063d0b8c7999ffe9474653080e6ef92b3cb7a428784","0x08eb574d7fecadadb508c8bd35fdad06b99110609d679763c2e3645229b1b95a","0x0f1a65e747c8021ed7c454a4be1e89b1bce66ead9ed980fa98a7a050eafe98a1","0x1c8ff9e36684ec71614dee4c17859b06c742089f6029d3694a16e00dac9b57f1","0x0303101a8ba712aeca4da85b767ab8d3ecf489ec7d746f8ee20041717cc000e9","0x0aaf64c65e7088e5596108c9601467911fea809ca6540d79af77e6e66e36cd99","0x17caf164ce74ea7edfb1390e07763d2197797ec26661b92cde18a98d61d2fddc","0x18cb055c7ad6d01437725bb457681d81f3ecadc4f35d838a3c13daf25a44456a","0x2d78602b8bbcd32b36a99a6e2d248e7fe044ef1b50813133370412f9ef5299f0","0x2b139276ea86d426a115479e4154f72a6bd83a6253bf13e9670dc6b4664378f0","0x127c7837b384902c39a104036c09546728571c46c8166b1b9b13b3a615ebb781","0x05faa4816f83cf0189a482ad943c94b9ec6474002f2b327f8698763ad0ea0985","0x2f90359cc30ee693fb3aced96523cf7aebd152c22329eee56a398d9a4ac0628e","0x0a71beaf17a59c5a238f04c1f203848d87502c5057a78c13f0cfb0f9876e7714","0x2696c1e6d089556adaeb95c8a5e3065b00a393a38c2d69e9bd6ce8cdc49d87da","0x1f3d165a7dc6564a036e451eb9cb7f1e1cb1e6d29daa75e3f135ea3e58a79ccd","0x1473a660819bdd838d56122b72b32b267211e9f1103239480ec50fa85c9e1035","0x0a8ccaeb22451f391b3fc3467c8e6e900270a7afb7b510e8acf5a4f06f1c0888","0x03b3080afc0658cc87e307758cebc171921f43eca159b9dedf7f72aa8dd926bd","0x2dd7d6663fa0e1755dfafac352c361fcd64c7f4d53627e3646870ac169cc4a07","0x1ec54b883f5f35ccad0e75695af20790d9860104095bab34c9bf01628dd40cb9","0x193dff50f83c241f7a9e087a29ce72ecf3f6d8563593f786dcd04c32bcfd4ced","0x135122c0dae26cda8ca1c09de8225064ad86d10423ab0aaa53b481aa4626e1d6","0x08d5a56cbfab5aeed56d3cdd7fb6b30fc26b0c1a5b63fccd7fa44c53ba6fd35a","0x0d12f126dfa2daad3726d00ca339284cc22e36c6d81bb7a4b95c6f9598b60e7c","0x2e8b24bbdf2fd839d3c7cae1f0eeb96bfcfaeef30b27476f2fafcb17da78cd5e","0x2364acfe0cea39b7f749c5f303b99504977357925f810f684c60f35d16315211","0x06ca062eb70b8c51cfac35345e7b6b51f33a8ec9ebe204fb9b4911200bf508b7","0x266c0aa1ccb97186815bf69084f600d06ddd934e59a38dfe602ee5d6b9487f22","0x1d817537a49c6d0e3b4b65c6665334b91d7593142e60065048be9e55ceb5e7ab","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x25b77026673a1e613e50df0e88fb510973739d5f9064bd364079a9f884209632","0x25c9bc7a3f6aae3d43ff68b5614b34b5eaceff37157b37347995d231784ac1fd","0x085f69baef22680ae15f4801ef4361ebe9c7fc24a94b5bc2527dce8fb705439e","0x0d7c6b9ce31bfc32238a205455baf5ffe99cd30eb0f7bb5b504e1d4501e01382","0x1001a8cc4bc1221c814fba0eddcf3c40619b133373640c600de5bed0a0a05b10","0x20f5894be90e52977cb70f4f4cbd5101693db0360848939750db7e91109d54b6","0x22c09cb26db43f0599408b4daed0f4f496c66424e6affa41c14387d8e0af851b","0x24e5f41357798432426a9549d71e8cc681eaebacbe87f6e3bf38e85de5aa2f3d","0x06eb90100c736fbf2b87432d7821ecdc0b365024739bc36363d48b905973f5b9","0x0000000000000000000000000000007f36e0b4f59927ebbb2302e76cbe8bd44e","0x00000000000000000000000000000000001b95777c6c98640c80638c195909ca","0x0000000000000000000000000000006d4b1ad71244248cb2070fbbbb0ac9df88","0x00000000000000000000000000000000001abada4d5d816a67b6fc75746cb723","0x000000000000000000000000000000465811089df032ceb5269254547a101e57","0x000000000000000000000000000000000011a4a909c59776a6df9c7615e8e87d","0x000000000000000000000000000000311f6f724e7199351c9774225f15c25f20","0x00000000000000000000000000000000001ddba8eb0ab208ad3d96c70941fcbc","0x0000000000000000000000000000000dfa80bdf5be151b21ad89466b7201b63d","0x000000000000000000000000000000000015ca7dc258adab8ea406d94e00c56d","0x000000000000000000000000000000507ea3454165f92295b6e435c7d30d14f0","0x00000000000000000000000000000000002f522608db7b7d389d1df67eab104d","0x000000000000000000000000000000950102cce743fadb23965fc72e31efd36c","0x000000000000000000000000000000000018b4a7ec90df68dfe97d3c5367d1bf","0x000000000000000000000000000000118d90258b25dba8bc0f99d9f7547c6a62","0x000000000000000000000000000000000012d78638701da6322abbf325693b0f","0x000000000000000000000000000000144743e0d082f35295b51561af65f94c6b","0x00000000000000000000000000000000002322a615615e5405836374bb3c5336","0x000000000000000000000000000000e6f08dd5904ee42f826cde680919b41a96","0x00000000000000000000000000000000002d3f823ea255b68465e4b5360bf864","0x00000000000000000000000000000076d4db93683b6363ae92a5a20d8bb9922e","0x00000000000000000000000000000000002f8a7009cac72c9599b81cb9054308","0x00000000000000000000000000000085c12dd2be9f2b29e54c1a4bc3cbf9b6ce","0x000000000000000000000000000000000024e3688a1f4f50b0c6bd6c068f32b2","0x00000000000000000000000000000023a2015e7ea351e444c9405adfbd81e84d","0x00000000000000000000000000000000001fb3e4228c15dc4380db796925ec49","0x000000000000000000000000000000834ad9406b8ded7208b872373be7445e47","0x0000000000000000000000000000000000267544d6a9f5cc46d10555f2617c65"] +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/test_programs/execution_success/verify_honk_proof/src/main.nr b/test_programs/execution_success/verify_honk_proof/src/main.nr new file mode 100644 index 00000000000..c534b07fc77 --- /dev/null +++ b/test_programs/execution_success/verify_honk_proof/src/main.nr @@ -0,0 +1,21 @@ +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; 156], + 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/test_programs/noir_test_success/bounded_vec/src/main.nr b/test_programs/noir_test_success/bounded_vec/src/main.nr index e5aa5f88a94..22ec291f9d6 100644 --- a/test_programs/noir_test_success/bounded_vec/src/main.nr +++ b/test_programs/noir_test_success/bounded_vec/src/main.nr @@ -63,33 +63,6 @@ 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/test_programs/noir_test_success/regression_4561/Nargo.toml b/test_programs/noir_test_success/regression_4561/Nargo.toml deleted file mode 100644 index 90deee74640..00000000000 --- a/test_programs/noir_test_success/regression_4561/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "regression_4561" -type = "bin" -authors = [""] - -[dependencies] diff --git a/test_programs/noir_test_success/regression_4561/src/main.nr b/test_programs/noir_test_success/regression_4561/src/main.nr deleted file mode 100644 index 138f7e805b3..00000000000 --- a/test_programs/noir_test_success/regression_4561/src/main.nr +++ /dev/null @@ -1,44 +0,0 @@ -// 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/tooling/acvm_cli/Cargo.toml b/tooling/acvm_cli/Cargo.toml index 1cfd1f3b270..a592f2d65f3 100644 --- a/tooling/acvm_cli/Cargo.toml +++ b/tooling/acvm_cli/Cargo.toml @@ -20,7 +20,7 @@ path = "src/main.rs" [dependencies] thiserror.workspace = true toml.workspace = true -color-eyre = "0.6.2" +color-eyre.workspace = true clap.workspace = true acvm.workspace = true nargo.workspace = true diff --git a/tooling/debugger/ignored-tests.txt b/tooling/debugger/ignored-tests.txt index a3971d437fb..a9193896589 100644 --- a/tooling/debugger/ignored-tests.txt +++ b/tooling/debugger/ignored-tests.txt @@ -11,8 +11,7 @@ fold_distinct_return fold_fibonacci fold_numeric_generic_poseidon is_unconstrained -macros modulus references regression_4709 -to_bytes_integration +to_bytes_integration \ No newline at end of file diff --git a/tooling/nargo_cli/Cargo.toml b/tooling/nargo_cli/Cargo.toml index a9946c8700c..7c7e7b9d5ca 100644 --- a/tooling/nargo_cli/Cargo.toml +++ b/tooling/nargo_cli/Cargo.toml @@ -41,11 +41,16 @@ prettytable-rs = "0.10" rayon = "1.8.0" thiserror.workspace = true tower.workspace = true -async-lsp = { workspace = true, features = ["client-monitor", "stdio", "tracing", "tokio"] } +async-lsp = { workspace = true, features = [ + "client-monitor", + "stdio", + "tracing", + "tokio", +] } const_format.workspace = true similar-asserts.workspace = true termcolor = "1.1.2" -color-eyre = "0.6.2" +color-eyre.workspace = true tokio = { version = "1.0", features = ["io-std", "rt"] } dap.workspace = true clap-markdown = { git = "https://github.com/noir-lang/clap-markdown", rev = "450d759532c88f0dba70891ceecdbc9ff8f25d2b", optional = true } diff --git a/tooling/nargo_cli/build.rs b/tooling/nargo_cli/build.rs index 846160320cf..fcc09653c7d 100644 --- a/tooling/nargo_cli/build.rs +++ b/tooling/nargo_cli/build.rs @@ -42,27 +42,22 @@ 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); @@ -286,13 +281,10 @@ 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]{comptime_ignored} +#[test] fn compile_success_empty_{test_name}() {{ let test_program_dir = PathBuf::from("{test_dir}"); diff --git a/tooling/nargo_cli/tests/stdlib-tests.rs b/tooling/nargo_cli/tests/stdlib-tests.rs index 70857b4b65e..0bb967e7502 100644 --- a/tooling/nargo_cli/tests/stdlib-tests.rs +++ b/tooling/nargo_cli/tests/stdlib-tests.rs @@ -1,8 +1,6 @@ -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; @@ -11,7 +9,6 @@ use nargo::{ package::{Package, PackageType}, parse_all, prepare_package, }; -use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; #[test] fn run_stdlib_tests() { @@ -26,7 +23,7 @@ fn run_stdlib_tests() { root_dir: PathBuf::from("."), package_type: PackageType::Binary, entry_path: PathBuf::from("main.nr"), - name: "stdlib".parse().unwrap(), + name: "dummy".parse().unwrap(), dependencies: BTreeMap::new(), }; @@ -61,85 +58,5 @@ 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/tooling/nargo_fmt/src/rewrite/expr.rs b/tooling/nargo_fmt/src/rewrite/expr.rs index ec8ac4abec7..7ff943aea62 100644 --- a/tooling/nargo_fmt/src/rewrite/expr.rs +++ b/tooling/nargo_fmt/src/rewrite/expr.rs @@ -63,8 +63,7 @@ pub(crate) fn rewrite( NewlineMode::IfContainsNewLineAndWidth, ); - let bang = if call_expr.is_macro_call { "!" } else { "" }; - format!("{callee}{bang}{args}") + format!("{callee}{args}") } ExpressionKind::MethodCall(method_call_expr) => { let args_span = visitor.span_before( @@ -86,8 +85,7 @@ pub(crate) fn rewrite( NewlineMode::IfContainsNewLineAndWidth, ); - let bang = if method_call_expr.is_macro_call { "!" } else { "" }; - format!("{object}.{method}{turbofish}{bang}{args}") + format!("{object}.{method}{turbofish}{args}") } ExpressionKind::MemberAccess(member_access_expr) => { let lhs_str = rewrite_sub_expr(visitor, shape, member_access_expr.lhs); @@ -168,9 +166,7 @@ pub(crate) fn rewrite( format!("{path_string}{turbofish}") } ExpressionKind::Lambda(_) => visitor.slice(span).to_string(), - ExpressionKind::Quote(block, block_span) => { - format!("quote {}", rewrite_block(visitor, block, block_span)) - } + ExpressionKind::Quote(block) => format!("quote {}", rewrite_block(visitor, block, span)), ExpressionKind::Comptime(block, block_span) => { format!("comptime {}", rewrite_block(visitor, block, block_span)) } @@ -178,14 +174,6 @@ 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/tooling/nargo_fmt/src/rewrite/typ.rs b/tooling/nargo_fmt/src/rewrite/typ.rs index 3ad1d9302be..278457f82d1 100644 --- a/tooling/nargo_fmt/src/rewrite/typ.rs +++ b/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::Expr + | UnresolvedTypeData::Code | UnresolvedTypeData::TraitAsType(_, _) => visitor.slice(typ.span.unwrap()).into(), UnresolvedTypeData::Error => unreachable!(), } diff --git a/tooling/nargo_fmt/tests/expected/let.nr b/tooling/nargo_fmt/tests/expected/let.nr index 7ff69e74306..c57801155a0 100644 --- a/tooling/nargo_fmt/tests/expected/let.nr +++ b/tooling/nargo_fmt/tests/expected/let.nr @@ -44,12 +44,12 @@ fn let_() { } }; - let expr = MyExpr { + 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 expr = Expr { /*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/tooling/nargo_fmt/tests/input/let.nr b/tooling/nargo_fmt/tests/input/let.nr index 37cdc6655c7..67c4ab8bd52 100644 --- a/tooling/nargo_fmt/tests/input/let.nr +++ b/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 = MyExpr {// A boolean literal (true, false). + 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 expr = Expr {/*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/tooling/noir_js_backend_barretenberg/src/backend.ts b/tooling/noir_js_backend_barretenberg/src/backend.ts index d07681dd8c1..ce2c2712491 100644 --- a/tooling/noir_js_backend_barretenberg/src/backend.ts +++ b/tooling/noir_js_backend_barretenberg/src/backend.ts @@ -45,7 +45,10 @@ 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); + const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes( + this.acirUncompressedBytecode, + /*honkRecursion=*/ false, // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): Remove this flag + ); 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/tooling/noirc_abi/Cargo.toml b/tooling/noirc_abi/Cargo.toml index e8f57060367..baae2dfa35e 100644 --- a/tooling/noirc_abi/Cargo.toml +++ b/tooling/noirc_abi/Cargo.toml @@ -11,6 +11,7 @@ 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" @@ -22,10 +23,13 @@ num-traits = "0.2" [dev-dependencies] strum = "0.24" strum_macros = "0.24" -proptest.workspace = true -proptest-derive.workspace = true - [features] -bn254 = ["acvm/bn254"] -bls12_381 = ["acvm/bls12_381"] \ No newline at end of file +bn254 = [ + "acvm/bn254", + "noirc_frontend/bn254", +] +bls12_381 = [ + "acvm/bls12_381", + "noirc_frontend/bls12_381", +] \ No newline at end of file diff --git a/tooling/noirc_abi/src/arbitrary.rs b/tooling/noirc_abi/src/arbitrary.rs deleted file mode 100644 index aecb620b79d..00000000000 --- a/tooling/noirc_abi/src/arbitrary.rs +++ /dev/null @@ -1,154 +0,0 @@ -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/tooling/noirc_abi/src/lib.rs b/tooling/noirc_abi/src/lib.rs index b3d80099137..86c982b5b0d 100644 --- a/tooling/noirc_abi/src/lib.rs +++ b/tooling/noirc_abi/src/lib.rs @@ -13,6 +13,8 @@ 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, @@ -25,9 +27,6 @@ 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; @@ -78,7 +77,6 @@ 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 { @@ -89,8 +87,27 @@ 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, @@ -98,6 +115,70 @@ 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 { @@ -147,12 +228,10 @@ 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, } @@ -164,20 +243,16 @@ 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))] +#[derive(Clone, Debug, Default, Serialize, Deserialize)] 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, } @@ -468,6 +543,22 @@ 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], @@ -499,18 +590,56 @@ pub fn display_abi_error( #[cfg(test)] mod test { - use proptest::prelude::*; + use std::collections::BTreeMap; - use crate::arbitrary::arb_abi_and_input_map; + use acvm::{AcirField, FieldElement}; - 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(); + use crate::{ + input_parser::InputValue, Abi, AbiParameter, AbiReturnType, AbiType, AbiVisibility, + InputMap, + }; + + #[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(), + }; - prop_assert_eq!(decoded_inputs, input_map); - prop_assert_eq!(return_value, None); + // 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); } + + assert!(return_value.is_none()); } } diff --git a/tooling/noirc_abi_wasm/build.sh b/tooling/noirc_abi_wasm/build.sh index c07d2d8a4c1..16fb26e55db 100755 --- a/tooling/noirc_abi_wasm/build.sh +++ b/tooling/noirc_abi_wasm/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/tooling/profiler/Cargo.toml b/tooling/profiler/Cargo.toml new file mode 100644 index 00000000000..baebe9292e6 --- /dev/null +++ b/tooling/profiler/Cargo.toml @@ -0,0 +1,42 @@ +[package] +name = "noir_profiler" +description = "Profiler for noir circuits" +version.workspace = true +authors.workspace = true +edition.workspace = true +license.workspace = true +rust-version.workspace = true +repository.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[[bin]] +name = "noir-profiler" +path = "src/main.rs" + +[dependencies] +color-eyre.workspace = true +clap.workspace = true +nargo.workspace = true +const_format.workspace = true +serde.workspace = true +serde_json.workspace = true +fm.workspace = true +codespan-reporting.workspace = true +inferno = "0.11.19" +im.workspace = true +acir.workspace = true +noirc_errors.workspace = true + +# Logs +tracing-subscriber.workspace = true +tracing-appender = "0.2.3" + +[dev-dependencies] +noirc_abi.workspace = true +noirc_driver.workspace = true +tempfile.workspace = true + +[features] +default = ["bn254"] +bn254 = ["acir/bn254"] diff --git a/tooling/profiler/src/cli/gates_flamegraph_cmd.rs b/tooling/profiler/src/cli/gates_flamegraph_cmd.rs new file mode 100644 index 00000000000..4f51eed4ba3 --- /dev/null +++ b/tooling/profiler/src/cli/gates_flamegraph_cmd.rs @@ -0,0 +1,486 @@ +use std::collections::BTreeMap; +use std::io::BufWriter; +use std::path::{Path, PathBuf}; +use std::process::Command; + +use clap::Args; +use codespan_reporting::files::Files; +use color_eyre::eyre::{self, Context}; +use inferno::flamegraph::{from_lines, Options}; +use nargo::artifacts::debug::DebugArtifact; +use serde::{Deserialize, Serialize}; + +use acir::circuit::OpcodeLocation; +use nargo::artifacts::program::ProgramArtifact; +use nargo::errors::Location; +use noirc_errors::reporter::line_and_column_from_span; + +#[derive(Debug, Clone, Args)] +pub(crate) struct GatesFlamegraphCommand { + /// The path to the artifact JSON file + #[clap(long, short)] + artifact_path: String, + + /// Path to the noir backend binary + #[clap(long, short)] + backend_path: String, + + /// The output folder for the flamegraph svg files + #[clap(long, short)] + output: String, +} + +trait GatesProvider { + fn get_gates(&self, artifact_path: &Path) -> eyre::Result; +} + +struct BackendGatesProvider { + backend_path: PathBuf, +} + +impl GatesProvider for BackendGatesProvider { + fn get_gates(&self, artifact_path: &Path) -> eyre::Result { + let backend_gates_response = + Command::new(&self.backend_path).arg("gates").arg("-b").arg(artifact_path).output()?; + + // Parse the backend gates command stdout as json + let backend_gates_response: BackendGatesResponse = + serde_json::from_slice(&backend_gates_response.stdout)?; + Ok(backend_gates_response) + } +} + +trait FlamegraphGenerator { + fn generate_flamegraph<'lines, I: IntoIterator>( + &self, + folded_lines: I, + artifact_name: &str, + function_name: &str, + output_path: &Path, + ) -> eyre::Result<()>; +} + +struct InfernoFlamegraphGenerator {} + +impl FlamegraphGenerator for InfernoFlamegraphGenerator { + fn generate_flamegraph<'lines, I: IntoIterator>( + &self, + folded_lines: I, + artifact_name: &str, + function_name: &str, + output_path: &Path, + ) -> eyre::Result<()> { + let flamegraph_file = std::fs::File::create(output_path)?; + let flamegraph_writer = BufWriter::new(flamegraph_file); + + let mut options = Options::default(); + options.hash = true; + options.deterministic = true; + options.title = format!("{}-{}", artifact_name, function_name); + options.subtitle = Some("Sample = Gate".to_string()); + options.frame_height = 24; + options.color_diffusion = true; + + from_lines(&mut options, folded_lines, flamegraph_writer)?; + + Ok(()) + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +struct BackendGatesReport { + acir_opcodes: usize, + circuit_size: usize, + gates_per_opcode: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +struct BackendGatesResponse { + functions: Vec, +} + +struct FoldedStackItem { + total_gates: usize, + nested_items: BTreeMap, +} + +pub(crate) fn run(args: GatesFlamegraphCommand) -> eyre::Result<()> { + run_with_provider( + &PathBuf::from(args.artifact_path), + &BackendGatesProvider { backend_path: PathBuf::from(args.backend_path) }, + &InfernoFlamegraphGenerator {}, + &PathBuf::from(args.output), + ) +} + +fn run_with_provider( + artifact_path: &Path, + gates_provider: &Provider, + flamegraph_generator: &Generator, + output_path: &Path, +) -> eyre::Result<()> { + let program = + read_program_from_file(artifact_path).context("Error reading program from file")?; + + let backend_gates_response = + gates_provider.get_gates(artifact_path).context("Error querying backend for gates")?; + + let function_names = program.names.clone(); + + let debug_artifact: DebugArtifact = program.into(); + + for (func_idx, (func_gates, func_name)) in + backend_gates_response.functions.into_iter().zip(function_names).enumerate() + { + println!( + "Opcode count: {}, Total gates by opcodes: {}, Circuit size: {}", + func_gates.acir_opcodes, + func_gates.gates_per_opcode.iter().sum::(), + func_gates.circuit_size + ); + + // Create a nested hashmap with the stack items, folding the gates for all the callsites that are equal + let mut folded_stack_items = BTreeMap::new(); + + func_gates.gates_per_opcode.into_iter().enumerate().for_each(|(opcode_index, gates)| { + let call_stack = &debug_artifact.debug_symbols[func_idx] + .locations + .get(&OpcodeLocation::Acir(opcode_index)); + let location_names = if let Some(call_stack) = call_stack { + call_stack + .iter() + .map(|location| location_to_callsite_label(*location, &debug_artifact)) + .collect::>() + } else { + vec!["unknown".to_string()] + }; + + add_locations_to_folded_stack_items(&mut folded_stack_items, location_names, gates); + }); + let folded_lines = to_folded_sorted_lines(&folded_stack_items, Default::default()); + + flamegraph_generator.generate_flamegraph( + folded_lines.iter().map(|as_string| as_string.as_str()), + artifact_path.to_str().unwrap(), + &func_name, + &Path::new(&output_path).join(Path::new(&format!("{}.svg", &func_name))), + )?; + } + + Ok(()) +} + +pub(crate) fn read_program_from_file>( + circuit_path: P, +) -> eyre::Result { + let file_path = circuit_path.as_ref().with_extension("json"); + + let input_string = std::fs::read(file_path)?; + let program = serde_json::from_slice(&input_string)?; + + Ok(program) +} + +fn location_to_callsite_label<'files>( + location: Location, + files: &'files impl Files<'files, FileId = fm::FileId>, +) -> String { + let filename = + Path::new(&files.name(location.file).expect("should have a file path").to_string()) + .file_name() + .map(|os_str| os_str.to_string_lossy().to_string()) + .unwrap_or("invalid_path".to_string()); + let source = files.source(location.file).expect("should have a file source"); + + let code_slice = source + .as_ref() + .chars() + .skip(location.span.start() as usize) + .take(location.span.end() as usize - location.span.start() as usize) + .collect::(); + + // ";" is used for frame separation, and is not allowed by inferno + // Check code slice for ";" and replace it with 'GREEK QUESTION MARK' (U+037E) + let code_slice = code_slice.replace(';', "\u{037E}"); + + let (line, column) = line_and_column_from_span(source.as_ref(), &location.span); + + format!("{}:{}:{}::{}", filename, line, column, code_slice) +} + +fn add_locations_to_folded_stack_items( + stack_items: &mut BTreeMap, + locations: Vec, + gates: usize, +) { + let mut child_map = stack_items; + for (index, location) in locations.iter().enumerate() { + let current_item = child_map + .entry(location.clone()) + .or_insert(FoldedStackItem { total_gates: 0, nested_items: BTreeMap::new() }); + + child_map = &mut current_item.nested_items; + + if index == locations.len() - 1 { + current_item.total_gates += gates; + } + } +} + +/// Creates a vector of lines in the format that inferno expects from a nested hashmap of stack items +/// The lines have to be sorted in the following way, exploring the graph in a depth-first manner: +/// main 100 +/// main::foo 0 +/// main::foo::bar 200 +/// main::baz 27 +/// main::baz::qux 800 +fn to_folded_sorted_lines( + folded_stack_items: &BTreeMap, + parent_stacks: im::Vector, +) -> Vec { + folded_stack_items + .iter() + .flat_map(move |(location, folded_stack_item)| { + let frame_list: Vec = + parent_stacks.iter().cloned().chain(std::iter::once(location.clone())).collect(); + let line: String = + format!("{} {}", frame_list.join(";"), folded_stack_item.total_gates); + + let mut new_parent_stacks = parent_stacks.clone(); + new_parent_stacks.push_back(location.clone()); + + let child_lines: Vec = + to_folded_sorted_lines(&folded_stack_item.nested_items, new_parent_stacks); + + std::iter::once(line).chain(child_lines) + }) + .collect() +} + +#[cfg(test)] +mod tests { + use acir::circuit::{OpcodeLocation, Program}; + use color_eyre::eyre::{self}; + use fm::{FileId, FileManager}; + use nargo::artifacts::program::ProgramArtifact; + use noirc_driver::DebugFile; + use noirc_errors::{ + debug_info::{DebugInfo, ProgramDebugInfo}, + Location, Span, + }; + use std::{ + cell::RefCell, + collections::{BTreeMap, HashMap}, + path::{Path, PathBuf}, + }; + use tempfile::TempDir; + + use super::{BackendGatesReport, BackendGatesResponse, GatesProvider}; + + struct TestGateProvider { + mock_responses: HashMap, + } + + impl GatesProvider for TestGateProvider { + fn get_gates(&self, artifact_path: &std::path::Path) -> eyre::Result { + let response = self + .mock_responses + .get(artifact_path) + .expect("should have a mock response for the artifact path"); + + Ok(response.clone()) + } + } + + #[derive(Default)] + struct TestFlamegraphGenerator { + lines_received: RefCell>>, + } + + impl super::FlamegraphGenerator for TestFlamegraphGenerator { + fn generate_flamegraph<'lines, I: IntoIterator>( + &self, + folded_lines: I, + _artifact_name: &str, + _function_name: &str, + _output_path: &std::path::Path, + ) -> eyre::Result<()> { + let lines = folded_lines.into_iter().map(|line| line.to_string()).collect(); + self.lines_received.borrow_mut().push(lines); + Ok(()) + } + } + + fn find_spans_for(source: &str, needle: &str) -> Vec { + let mut spans = Vec::new(); + let mut start = 0; + while let Some(start_idx) = source[start..].find(needle) { + let start_idx = start + start_idx; + let end_idx = start_idx + needle.len(); + spans.push(Span::inclusive(start_idx as u32, end_idx as u32 - 1)); + start = end_idx; + } + spans + } + + struct TestCase { + expected_folded_sorted_lines: Vec>, + debug_symbols: ProgramDebugInfo, + file_map: BTreeMap, + gates_report: BackendGatesResponse, + } + + fn simple_test_case(temp_dir: &TempDir) -> TestCase { + let source_code = r##" + fn main() { + foo(); + bar(); + whatever(); + } + fn foo() { + baz(); + } + fn bar () { + whatever() + } + fn baz () { + whatever() + } + "##; + + let source_file_name = Path::new("main.nr"); + let mut fm = FileManager::new(temp_dir.path()); + let file_id = fm.add_file_with_source(source_file_name, source_code.to_string()).unwrap(); + + let main_declaration_location = + Location::new(find_spans_for(source_code, "fn main()")[0], file_id); + let main_foo_call_location = + Location::new(find_spans_for(source_code, "foo()")[0], file_id); + let main_bar_call_location = + Location::new(find_spans_for(source_code, "bar()")[0], file_id); + let main_whatever_call_location = + Location::new(find_spans_for(source_code, "whatever()")[0], file_id); + let foo_baz_call_location = Location::new(find_spans_for(source_code, "baz()")[0], file_id); + let bar_whatever_call_location = + Location::new(find_spans_for(source_code, "whatever()")[1], file_id); + let baz_whatever_call_location = + Location::new(find_spans_for(source_code, "whatever()")[2], file_id); + + let mut opcode_locations = BTreeMap::>::new(); + // main::foo::baz::whatever + opcode_locations.insert( + OpcodeLocation::Acir(0), + vec![ + main_declaration_location, + main_foo_call_location, + foo_baz_call_location, + baz_whatever_call_location, + ], + ); + + // main::bar::whatever + opcode_locations.insert( + OpcodeLocation::Acir(1), + vec![main_declaration_location, main_bar_call_location, bar_whatever_call_location], + ); + // main::whatever + opcode_locations.insert( + OpcodeLocation::Acir(2), + vec![main_declaration_location, main_whatever_call_location], + ); + + let file_map = BTreeMap::from_iter(vec![( + file_id, + DebugFile { source: source_code.to_string(), path: source_file_name.to_path_buf() }, + )]); + + let debug_symbols = ProgramDebugInfo { + debug_infos: vec![DebugInfo::new( + opcode_locations, + BTreeMap::default(), + BTreeMap::default(), + BTreeMap::default(), + )], + }; + + let backend_gates_response = BackendGatesResponse { + functions: vec![BackendGatesReport { + acir_opcodes: 3, + circuit_size: 100, + gates_per_opcode: vec![10, 20, 30], + }], + }; + + let expected_folded_sorted_lines = vec![ + "main.nr:2:9::fn main() 0".to_string(), + "main.nr:2:9::fn main();main.nr:3:13::foo() 0".to_string(), + "main.nr:2:9::fn main();main.nr:3:13::foo();main.nr:8:13::baz() 0".to_string(), + "main.nr:2:9::fn main();main.nr:3:13::foo();main.nr:8:13::baz();main.nr:14:13::whatever() 10".to_string(), + "main.nr:2:9::fn main();main.nr:4:13::bar() 0".to_string(), + "main.nr:2:9::fn main();main.nr:4:13::bar();main.nr:11:13::whatever() 20".to_string(), + "main.nr:2:9::fn main();main.nr:5:13::whatever() 30".to_string(), + ]; + + TestCase { + expected_folded_sorted_lines: vec![expected_folded_sorted_lines], + debug_symbols, + file_map, + gates_report: backend_gates_response, + } + } + + #[test] + fn test_flamegraph() { + let temp_dir = tempfile::tempdir().unwrap(); + + let test_cases = vec![simple_test_case(&temp_dir)]; + let artifact_names: Vec<_> = + test_cases.iter().enumerate().map(|(idx, _)| format!("test{}.json", idx)).collect(); + + let test_cases_with_names: Vec<_> = test_cases.into_iter().zip(artifact_names).collect(); + + let mut mock_responses: HashMap = HashMap::new(); + // Collect mock responses + for (test_case, artifact_name) in test_cases_with_names.iter() { + mock_responses.insert( + temp_dir.path().join(artifact_name.clone()), + test_case.gates_report.clone(), + ); + } + + let provider = TestGateProvider { mock_responses }; + + for (test_case, artifact_name) in test_cases_with_names.iter() { + let artifact_path = temp_dir.path().join(artifact_name.clone()); + + let artifact = ProgramArtifact { + noir_version: "0.0.0".to_string(), + hash: 27, + abi: noirc_abi::Abi::default(), + bytecode: Program::default(), + debug_symbols: test_case.debug_symbols.clone(), + file_map: test_case.file_map.clone(), + names: vec!["main".to_string()], + }; + + // Write the artifact to a file + let artifact_file = std::fs::File::create(&artifact_path).unwrap(); + serde_json::to_writer(artifact_file, &artifact).unwrap(); + + let flamegraph_generator = TestFlamegraphGenerator::default(); + + super::run_with_provider( + &artifact_path, + &provider, + &flamegraph_generator, + temp_dir.path(), + ) + .expect("should run without errors"); + + // Check that the flamegraph generator was called with the correct folded sorted lines + let calls_received = flamegraph_generator.lines_received.borrow().clone(); + + assert_eq!(calls_received, test_case.expected_folded_sorted_lines); + } + } +} diff --git a/tooling/profiler/src/cli/mod.rs b/tooling/profiler/src/cli/mod.rs new file mode 100644 index 00000000000..d54a3f6167c --- /dev/null +++ b/tooling/profiler/src/cli/mod.rs @@ -0,0 +1,33 @@ +use clap::{Parser, Subcommand}; +use color_eyre::eyre; +use const_format::formatcp; + +mod gates_flamegraph_cmd; + +const PROFILER_VERSION: &str = env!("CARGO_PKG_VERSION"); + +static VERSION_STRING: &str = formatcp!("version = {}\n", PROFILER_VERSION,); + +#[derive(Parser, Debug)] +#[command(name="Noir profiler", author, version=VERSION_STRING, about, long_about = None)] +struct ProfilerCli { + #[command(subcommand)] + command: GatesFlamegraphCommand, +} + +#[non_exhaustive] +#[derive(Subcommand, Clone, Debug)] +enum GatesFlamegraphCommand { + GatesFlamegraph(gates_flamegraph_cmd::GatesFlamegraphCommand), +} + +pub(crate) fn start_cli() -> eyre::Result<()> { + let ProfilerCli { command } = ProfilerCli::parse(); + + match command { + GatesFlamegraphCommand::GatesFlamegraph(args) => gates_flamegraph_cmd::run(args), + } + .map_err(|err| eyre::eyre!("{}", err))?; + + Ok(()) +} diff --git a/tooling/profiler/src/main.rs b/tooling/profiler/src/main.rs new file mode 100644 index 00000000000..8e08644de23 --- /dev/null +++ b/tooling/profiler/src/main.rs @@ -0,0 +1,35 @@ +#![forbid(unsafe_code)] +#![warn(unreachable_pub)] +#![warn(clippy::semicolon_if_nothing_returned)] +#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] + +mod cli; + +use std::env; + +use tracing_appender::rolling; +use tracing_subscriber::{fmt::format::FmtSpan, EnvFilter}; + +fn main() { + // Setup tracing + if let Ok(log_dir) = env::var("PROFILER_LOG_DIR") { + let debug_file = rolling::daily(log_dir, "profiler-log"); + tracing_subscriber::fmt() + .with_span_events(FmtSpan::ACTIVE) + .with_writer(debug_file) + .with_ansi(false) + .with_env_filter(EnvFilter::from_default_env()) + .init(); + } else { + tracing_subscriber::fmt() + .with_span_events(FmtSpan::ACTIVE) + .with_ansi(true) + .with_env_filter(EnvFilter::from_env("NOIR_LOG")) + .init(); + } + + if let Err(report) = cli::start_cli() { + eprintln!("{report}"); + std::process::exit(1); + } +}