Skip to content

Commit

Permalink
Merge pull request #22 from noir-lang/jz/noir-by-example
Browse files Browse the repository at this point in the history
Add Noir/Rust syntax example section
  • Loading branch information
jzaki authored Oct 2, 2024
2 parents ab532bf + fde991e commit 2b9a230
Show file tree
Hide file tree
Showing 16 changed files with 294 additions and 0 deletions.
3 changes: 3 additions & 0 deletions noir_by_example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
target
Prover.toml
Verifier.toml
11 changes: 11 additions & 0 deletions noir_by_example/Cargo.lock

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

6 changes: 6 additions & 0 deletions noir_by_example/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[workspace]
members = [
"simple_macros/rust",
"loops/rust"
]
resolver = "1"
5 changes: 5 additions & 0 deletions noir_by_example/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[workspace]
members = [
"simple_macros/noir",
"loops/noir"
]
66 changes: 66 additions & 0 deletions noir_by_example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Examples showcasing syntax, libraries, and data structures

## General

These will show Noir side-by-side against [Rust by example](https://doc.rust-lang.org/rust-by-example/).

The goal is to highlight the similarities and differences in the language and design patterns.

### Tooling

You will need:

- `nargo` installed [via noirup](https://noir-lang.org/docs/getting_started/installation/). Uses 0.34.0 (`noirup -v 0.34.0`)
- `cargo` installed [via rustup](https://www.rust-lang.org/tools/install) (optional: to see Rust output)

### What is not covered

The surrounding build artifacts (and additional proving/verifying artifacts for Noir) are not explored in this example.

## Usage

The following commands can be run at the top level `noir_by_example`, or within the specific topic directory.
Eg: `cd simple_macros`

### Compiling

- `nargo compile`
- `cargo build`

### Running main

- Noir:
- `nargo check` # May need to populate values in Prover.toml for topics that need it
- `nargo execute`
- Rust:
- `cargo run` # topic-level only

### Running tests

Simply run:

- `nargo test`
- `cargo test`

To see output from `println`:

- `nargo test --show-output`
- `cargo test -- --nocapture`

To test specific functions, a substring of its name can be added to the end.
Eg, `nargo test macro`, to run tests who's name contains the string `macro`.

## Adding to this repository - GOOD FIRST ISSUES

The Noir documentation has many good pages explaining the syntax with examples, similarly with Rust.

For instance for macro function example:

- Noir example in [(Quasi) Quote](https://noir-lang.org/docs/dev/noir/concepts/comptime#lowering)
- Rust example in [macros](https://doc.rust-lang.org/rust-by-example/macros.html)

To add a new section:

- Go to the directory: `cd noir_by_example`
- Use the script: `./new_topic.sh topic_name`
- Then equivalent functionality to the `noir` and `rust` projects.
7 changes: 7 additions & 0 deletions noir_by_example/loops/noir/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "loops"
type = "bin"
authors = [""]
compiler_version = ">=0.34.0"

[dependencies]
35 changes: 35 additions & 0 deletions noir_by_example/loops/noir/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
fn fixed_loop() {
let len = 10;

// Loop from 1 to l (inclusive)
for i in 1..len + 1 {
print("Loop iteration: ");
println(i);
}
}

fn variable_loop(len: u32) {
let MAX_LEN = 20;
assert(len <= MAX_LEN);
// Loop from 1 to MAX_LEN
for i in 1..MAX_LEN as u32 + 1 {
// only print when beneath len (inclusive)
if (i <= len) {
print("Variable loop iteration: ");
println(i);
}
}
}

// Parameters read from Prover.toml file
fn main(loop_length: u32) {
println("\nLOOPS START");
fixed_loop();
variable_loop(loop_length);
println("LOOPS END\n");
}

#[test]
fn test_loops() {
main(5);
}
7 changes: 7 additions & 0 deletions noir_by_example/loops/rust/Cargo.lock

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

6 changes: 6 additions & 0 deletions noir_by_example/loops/rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "loops"
version = "0.1.0"
edition = "2021"

[dependencies]
39 changes: 39 additions & 0 deletions noir_by_example/loops/rust/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Need standard environment lib for command line arguments
use std::env;

fn fixed_loop() {
let l = 10;

// Loop from 1 to l (inclusive)
for i in 1..=l {
println!("Loop iteration: {}", i);
}
}

fn variable_loop(len: u32) {
// Loop from 1 to len (inclusive)
for i in 1..=len {
println!("Variable loop iteration: {}", i);
}
}

fn main() {
println!("\nLOOPS START");
const DEFAULT: u32 = 5;
// Read first command line argument
let args: Vec<String> = env::args().collect();
let loop_length = if args.len() > 1 {
args[1].parse().unwrap_or(DEFAULT)
} else {
DEFAULT // Default value if no argument is provided
};

fixed_loop();
variable_loop(loop_length); // variable
println!("\nLOOPS END");
}

#[test]
fn test_loops() {
main();
}
45 changes: 45 additions & 0 deletions noir_by_example/new_topic.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/bash
echo "This command is for creating a subdirectory for a new topic."

# Only run from location of script
script_dir="$(cd "$(dirname "$0")" && pwd)"
current_dir="$(pwd)"

if [ "$script_dir" != "$current_dir" ]; then
echo "Error: Script intended to be run from its directory (noir_by_example)"
exit 1
fi

if [ $# -eq 0 ]; then
echo "Error: Please provide a topic_name as an argument."
exit 1
fi

# Create topic dir from command line argument
dir_name="$1"
mkdir -p "$dir_name"

if [ $? -eq 0 ]; then
echo "Directory '$dir_name' created (or already exists)."
cd "$dir_name"

echo "Creating Noir project..."
nargo new noir
if [ $? -ne 0 ]; then
echo "Error: Failed to create new Noir project."
exit 1
fi

echo "Creating Rust ..."
cargo new rust
if [ $? -ne 0 ]; then
echo "Error: Failed to create new Rust project."
exit 1
fi

else
echo "Error: Failed to create directory '$dir_name'."
exit 1
fi

cd ..
7 changes: 7 additions & 0 deletions noir_by_example/simple_macros/noir/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "simple_macros"
type = "bin"
authors = [""]
compiler_version = ">=0.34.0"

[dependencies]
22 changes: 22 additions & 0 deletions noir_by_example/simple_macros/noir/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// https://noir-lang.org/docs/dev/noir/concepts/comptime#lowering
// a compile-time function that returns a `Quoted` type
comptime fn say_hello() -> Quoted {
quote {
// the macro will expand into the contents of this quote
// this single quote isn't divided to take arguments
println("Hello!")
}
}

fn main() {
println("\nSIMPLE_MACRO START");
// This call will unquote into `println!("Hello!")`
let res = say_hello!();
println("SIMPLE_MACRO END\n");
res
}

#[test]
fn test_macros() {
main()
}
7 changes: 7 additions & 0 deletions noir_by_example/simple_macros/rust/Cargo.lock

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

6 changes: 6 additions & 0 deletions noir_by_example/simple_macros/rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "simple_macros"
version = "0.1.0"
edition = "2021"

[dependencies]
22 changes: 22 additions & 0 deletions noir_by_example/simple_macros/rust/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// https://doc.rust-lang.org/rust-by-example/macros.html
// This is a simple macro named `say_hello`.
macro_rules! say_hello {
// `()` indicates that the macro takes no argument.
() => {
// The macro will expand into the contents of this block.
println!("Hello!")
};
}

fn main() {
println!("\nSIMPLE_MACRO START");
// This call will expand into `println!("Hello!")`
let res = say_hello!();
println!("SIMPLE_MACRO END\n");
res
}

#[test]
fn test_macros() {
main()
}

0 comments on commit 2b9a230

Please sign in to comment.