Skip to content

Commit

Permalink
Add Noir (#6432)
Browse files Browse the repository at this point in the history
* add noir

* Update lib/linguist/languages.yml

Co-authored-by: Colin Seymour <[email protected]>

* add submodule

* remove vscode-noir

* add submodule

* add test

* add license

* fix syntax

* update samples

* fix syntax

* Sort submodules

* Remove noir

* Fix heuristic

* Add tm_scope

This can be changed when the grammar is added

* Fix heuristic test

* Update lib/linguist/heuristics.yml

Co-authored-by: John Gardner <[email protected]>

* Update lib/linguist/languages.yml

Co-authored-by: John Gardner <[email protected]>

* add noir grammar

* add missing updates

* update to latest commit

* update noir submodule

* update noir submodule

* ran bundle exec licensed cache -c vendor/licenses/config.yml

* Update lib/linguist/heuristics.yml

Co-authored-by: John Gardner <[email protected]>

---------

Co-authored-by: Colin Seymour <[email protected]>
Co-authored-by: Colin Seymour <[email protected]>
Co-authored-by: John Gardner <[email protected]>
  • Loading branch information
4 people authored Aug 29, 2024
1 parent d190ad8 commit 34ae2f4
Show file tree
Hide file tree
Showing 12 changed files with 436 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -1314,6 +1314,9 @@
[submodule "vendor/grammars/vscode-move-syntax"]
path = vendor/grammars/vscode-move-syntax
url = https://github.com/damirka/vscode-move-syntax.git
[submodule "vendor/grammars/vscode-noir"]
path = vendor/grammars/vscode-noir
url = https://github.com/noir-lang/vscode-noir.git
[submodule "vendor/grammars/vscode-opa"]
path = vendor/grammars/vscode-opa
url = https://github.com/open-policy-agent/vscode-opa.git
Expand Down
2 changes: 2 additions & 0 deletions grammars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,8 @@ vendor/grammars/vscode-move-syntax:
- markdown.move.codeblock
- mdx.LANGUAGE.codeblock
- source.move
vendor/grammars/vscode-noir:
- source.nr
vendor/grammars/vscode-opa:
- markdown.rego.codeblock
- source.rego
Expand Down
5 changes: 5 additions & 0 deletions lib/linguist/heuristics.yml
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,11 @@ disambiguations:
- language: NL
pattern: '^(b|g)[0-9]+ '
- language: NewLisp
- extensions: ['.nr']
rules:
- language: Roff
pattern: '^\.'
- language: Noir
- extensions: ['.nu']
rules:
- language: Nushell
Expand Down
12 changes: 12 additions & 0 deletions lib/linguist/languages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4693,6 +4693,18 @@ Nix:
tm_scope: source.nix
ace_mode: nix
language_id: 252
Noir:
type: programming
aliases:
- nargo
ace_mode: rust
codemirror_mode: rust
codemirror_mime_type: text/x-rustsrc
extensions:
- ".nr"
color: "#2f1f49"
tm_scope: source.nr
language_id: 813068465
Nu:
type: programming
color: "#c9df40"
Expand Down
74 changes: 74 additions & 0 deletions samples/Noir/array.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@

impl<T, N> [T; N] {
#[builtin(array_len)]
fn len(_array: Self) -> comptime Field {}

#[builtin(arraysort)]
fn sort(_array: Self) -> Self {}

// Sort with a custom sorting function.
fn sort_via(mut a: Self, ordering: fn(T, T) -> bool) -> Self {
for i in 1 .. a.len() {
for j in 0..i {
if ordering(a[i], a[j]) {
let old_a_j = a[j];
a[j] = a[i];
a[i] = old_a_j;
}
}
}
a
}

// Apply a function to each element of an array, returning a new array
// containing the mapped elements.
fn map<U>(self, f: fn(T) -> U) -> [U; N] {
let first_elem = f(self[0]);
let mut ret = [first_elem; N];

for i in 1 .. self.len() {
ret[i] = f(self[i]);
}

ret
}

// Apply a function to each element of the array and an accumulator value,
// returning the final accumulated value. This function is also sometimes
// called `foldl`, `fold_left`, `reduce`, or `inject`.
fn fold<U>(self, mut accumulator: U, f: fn(U, T) -> U) -> U {
for elem in self {
accumulator = f(accumulator, elem);
}
accumulator
}

// Apply a function to each element of the array and an accumulator value,
// returning the final accumulated value. Unlike fold, reduce uses the first
// element of the given array as its starting accumulator value.
fn reduce(self, f: fn(T, T) -> T) -> T {
let mut accumulator = self[0];
for i in 1 .. self.len() {
accumulator = f(accumulator, self[i]);
}
accumulator
}

// Returns true if all elements in the array satisfy the predicate
fn all(self, predicate: fn(T) -> bool) -> bool {
let mut ret = true;
for elem in self {
ret &= predicate(elem);
}
ret
}

// Returns true if any element in the array satisfies the predicate
fn any(self, predicate: fn(T) -> bool) -> bool {
let mut ret = false;
for elem in self {
ret |= predicate(elem);
}
ret
}
}
28 changes: 28 additions & 0 deletions samples/Noir/ecrecover_lib.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use dep::std;

mod secp256k1;

fn ecrecover(
pub_key_x: [u8; 32],
pub_key_y: [u8; 32],
signature: [u8; 64], // clip v value
hashed_message: [u8; 32]
) -> pub Field {
let key = secp256k1::PubKey::from_xy(pub_key_x, pub_key_y);

assert(key.verify_sig(signature, hashed_message) == true);
let addr = key.to_eth_address();

addr
}

#[test]
fn test_ecrecover() {
let pub_key_x = [131, 24, 83, 91, 84, 16, 93, 74, 122, 174, 96, 192, 143, 196, 95, 150, 135, 24, 27, 79, 223, 198, 37, 189, 26, 117, 63, 167, 57, 127, 237, 117];
let pub_key_y = [53, 71, 241, 28, 168, 105, 102, 70, 242, 243, 172, 176, 142, 49, 1, 106, 250, 194, 62, 99, 12, 93, 17, 245, 159, 97, 254, 245, 123, 13, 42, 165];
let signature = [57, 17, 112, 239, 241, 30, 64, 157, 170, 50, 85, 145, 156, 69, 226, 85, 147, 164, 10, 82, 71, 93, 42, 132, 200, 220, 161, 255, 95, 241, 211, 141, 81, 7, 150, 25, 25, 27, 162, 213, 80, 61, 12, 170, 50, 4, 154, 203, 252, 229, 119, 29, 202, 153, 50, 25, 126, 145, 245, 23, 136, 75, 29, 177];
let hashed_message = [13, 82, 120, 60, 76, 186, 215, 235, 175, 126, 185, 67, 252, 100, 143, 82, 130, 165, 32, 112, 68, 47, 193, 141, 141, 209, 109, 219, 47, 203, 175, 102];

let addr = ecrecover(pub_key_x, pub_key_y, signature, hashed_message);
assert(addr == 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266);
}
12 changes: 12 additions & 0 deletions samples/Noir/voting.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use dep::std;

fn main(root : pub Field, index : Field, hash_path : [Field; 2], secret: Field, priv_key: Field, proposalId: pub Field, vote: pub u8) -> pub Field {
let note_commitment = std::hash::pedersen([priv_key, secret]);
let nullifier = std::hash::pedersen([root, priv_key, proposalId]);

let is_member = std::merkle::check_membership(root, note_commitment[0], index, hash_path);
assert(is_member == 1);
assert(vote <= 1);

nullifier[0]
}
80 changes: 80 additions & 0 deletions samples/Roff/roff.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
.bp
.P1 MEMORY
.PP
The EM machine has two distinct address spaces,
one for instructions and one for data.
The data space is divided up into 8-bit bytes.
The smallest addressable unit is a byte.
Bytes are numbered consecutively from 0 to some maximum.
All sizes in EM are expressed in bytes.
.PP
Some EM instructions can transfer objects containing several bytes
to and/or from memory.
The size of all objects larger than a word must be a multiple of
the wordsize.
The size of all objects smaller than a word must be a divisor
of the wordsize.
For example: if the wordsize is 2 bytes, objects of the sizes 1,
2, 4, 6,... are allowed.
The address of such an object is the lowest address of all bytes it contains.
For objects smaller than the wordsize, the
address must be a multiple of the object size.
For all other objects the address must be a multiple of the
wordsize.
For example, if an instruction transfers a 4-byte object to memory at
location \fIm\fP and the wordsize is 2,
\fIm\fP must be a multiple of 2 and the bytes at
locations \fIm\fP, \fIm\fP\|+\|1,\fIm\fP\|+\|2 and
\fIm\fP\|+\|3 are overwritten.
.PP
The size of almost all objects in EM
is an integral number of words.
Only two operations are allowed on
objects whose size is a divisor of the wordsize:
push it onto the stack and pop it from the stack.
The addressing of these objects in memory is always indirect.
If such a small object is pushed onto the stack
it is assumed to be a small integer and stored
in the least significant part of a word.
The rest of the word is cleared to zero,
although
EM provides a way to sign-extend a small integer.
Popping a small object from the stack removes a word
from the stack, stores the least significant byte(s)
of this word in memory and discards the rest of the word.
.PP
The format of pointers into both address spaces is explicitly undefined.
The size of a pointer, however, is fixed for a member of EM, so that
the compiler writer knows how much storage to allocate for a pointer.
.PP
A minor problem is raised by the undefined pointer format.
Some languages, notably Pascal, require a special,
otherwise illegal, pointer value to represent the nil pointer.
The current Pascal-VU compiler uses the
integer value 0 as nil pointer.
This value is also used by many C programs as a normally impossible address.
A better solution would be to have a special
instruction loading an illegal pointer value,
but it is hard to imagine an implementation
for which the current solution is inadequate,
especially because the first word in the EM data space
is special and probably not the target of any pointer.
.PP
The next two chapters describe the EM memory
in more detail.
One describes the instruction address space,
the other the data address space.
.PP
A design goal of EM has been to allow
its implementation on a wide range of existing machines,
as well as allowing a new one to be built in hardware.
To this extent we have tried to minimize the demands
of EM on the memory structure of the target machine.
Therefore, apart from the logical partitioning,
EM memory is divided into 'fragments'.
A fragment consists of consecutive machine
words and has a base address and a size.
Pointer arithmetic is only defined within a fragment.
The only exception to this rule is comparison with the null
pointer.
All fragments must be word aligned.
7 changes: 7 additions & 0 deletions test/test_heuristics.rb
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,13 @@ def test_nl_by_heuristics
})
end

def test_nr_by_heuristics
assert_heuristics({
"Noir" => all_fixtures("Noir", "*.nr"),
"Roff" => all_fixtures("Roff", "*.nr")
})
end

def test_nu_by_heuristics
assert_heuristics({
"Nushell" => all_fixtures("Nushell", "*.nu"),
Expand Down
1 change: 1 addition & 0 deletions vendor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ This is a list of grammars that Linguist selects to provide syntax highlighting
- **Ninja:** [khyo/language-ninja](https://github.com/khyo/language-ninja)
- **Nit:** [R4PaSs/Sublime-Nit](https://github.com/R4PaSs/Sublime-Nit)
- **Nix:** [nix-community/tree-sitter-nix](https://github.com/nix-community/tree-sitter-nix) 🐌
- **Noir:** [noir-lang/vscode-noir](https://github.com/noir-lang/vscode-noir)
- **Nu:** [jsallis/nu.tmbundle](https://github.com/jsallis/nu.tmbundle)
- **Nunjucks:** [alohaas/language-nunjucks](https://github.com/alohaas/language-nunjucks)
- **Nushell:** [hustcer/nu-grammar](https://github.com/hustcer/nu-grammar)
Expand Down
1 change: 1 addition & 0 deletions vendor/grammars/vscode-noir
Submodule vscode-noir added at 611499
Loading

0 comments on commit 34ae2f4

Please sign in to comment.