mirror of
https://github.com/AleoHQ/leo.git
synced 2024-11-28 19:23:24 +03:00
Merge branch 'master' into compiler-tests
This commit is contained in:
commit
cb2bd62ea9
28
Cargo.lock
generated
28
Cargo.lock
generated
@ -424,10 +424,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
|
||||
|
||||
[[package]]
|
||||
name = "cpuid-bool"
|
||||
version = "0.1.2"
|
||||
name = "cpufeatures"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
|
||||
checksum = "5cd5a7748210e7ec1a9696610b1015e6e31fbf58f77a160801f124bd1c36592a"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
@ -2488,9 +2488,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "self_update"
|
||||
version = "0.26.0"
|
||||
version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9031099ba3962ce8faaff991066bcbe6ec1f7ccb0be12a4b56733028ae090054"
|
||||
checksum = "6fb85f1802f7b987237b8525c0fde86ea86f31c957c1875467c727d5b921179c"
|
||||
dependencies = [
|
||||
"hyper",
|
||||
"indicatif",
|
||||
@ -2616,13 +2616,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.9.3"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de"
|
||||
checksum = "d8f6b75b17576b792bef0db1bcc4b8b8bcdf9506744cf34b974195487af6cff2"
|
||||
dependencies = [
|
||||
"block-buffer 0.9.0",
|
||||
"cfg-if 1.0.0",
|
||||
"cpuid-bool",
|
||||
"cpufeatures",
|
||||
"digest 0.9.0",
|
||||
"opaque-debug 0.3.0",
|
||||
]
|
||||
@ -3136,9 +3136,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.25"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f"
|
||||
checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"pin-project-lite",
|
||||
@ -3159,9 +3159,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.17"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f"
|
||||
checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
@ -3199,9 +3199,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.2.17"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "705096c6f83bf68ea5d357a6aa01829ddbdac531b357b45abeca842938085baa"
|
||||
checksum = "aa5553bf0883ba7c9cbe493b085c29926bd41b66afc31ff72cf17ff4fb60dcd5"
|
||||
dependencies = [
|
||||
"ansi_term 0.12.1",
|
||||
"chrono",
|
||||
|
@ -125,7 +125,7 @@ version = "0.11.3"
|
||||
features = [ "blocking", "json", "multipart" ]
|
||||
|
||||
[dependencies.self_update]
|
||||
version = "0.26.0"
|
||||
version = "0.27.0"
|
||||
features = [ "archive-zip" ]
|
||||
|
||||
[dependencies.serde]
|
||||
|
@ -105,7 +105,7 @@ fn resolve_import_package_access(
|
||||
package: &PackageAccess,
|
||||
) {
|
||||
match package {
|
||||
PackageAccess::Star(span) => {
|
||||
PackageAccess::Star { span } => {
|
||||
output.push((package_segments, ImportSymbol::All, span.clone()));
|
||||
}
|
||||
PackageAccess::SubPackage(subpackage) => {
|
||||
@ -414,7 +414,7 @@ pub fn reform_ast<'a>(program: &Program<'a>) -> leo_ast::Program {
|
||||
.map(|(module, _)| leo_ast::ImportStatement {
|
||||
package_or_packages: leo_ast::PackageOrPackages::Package(leo_ast::Package {
|
||||
name: Identifier::new(module.clone().into()),
|
||||
access: leo_ast::PackageAccess::Star(Span::default()),
|
||||
access: leo_ast::PackageAccess::Star { span: Span::default() },
|
||||
span: Default::default(),
|
||||
}),
|
||||
span: Span::default(),
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
x: u32
|
||||
x: u32;
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
x: u32
|
||||
x: u32;
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
a: u8;
|
||||
|
||||
function bar() {}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
a: u8;
|
||||
|
||||
function bar() {}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
a: u8;
|
||||
|
||||
function bar() {}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
a: u8;
|
||||
|
||||
function set_a(self, new: u8) {
|
||||
self.a = new;
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
a: u8;
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
f: u32,
|
||||
f: u32;
|
||||
|
||||
function bar() -> u32 {
|
||||
return f;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Circuits are immutable by default.
|
||||
circuit Foo {
|
||||
x: u32
|
||||
x: u32;
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
a: u32,
|
||||
a: u32;
|
||||
}
|
||||
|
||||
circuit Bar {
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
x: u32
|
||||
x: u32;
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
x: u32,
|
||||
x: u32;
|
||||
|
||||
function add_x(self, y: u32) -> u32 {
|
||||
return self.x + y;
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
x: u32,
|
||||
x: u32;
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
foo: u32,
|
||||
foo: u32;
|
||||
|
||||
function bar() -> u32 {
|
||||
return 1u32;
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
a: u8;
|
||||
|
||||
function set_a(mut self, new: u8) {
|
||||
self.a = new;
|
||||
|
@ -5,7 +5,7 @@ function main() {
|
||||
}
|
||||
|
||||
circuit Foo {
|
||||
a: u32
|
||||
a: u32;
|
||||
|
||||
function bar(mut self) {
|
||||
if true {
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
a: u8;
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit PedersenHash {
|
||||
parameters: [u32; 512]
|
||||
parameters: [u32; 512];
|
||||
|
||||
function new(const parameters: [u32; 512]) -> Self {
|
||||
return Self { parameters: parameters };
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
f: u32,
|
||||
f: u32;
|
||||
|
||||
function bar(self) -> u32 {
|
||||
return self.f;
|
||||
|
@ -58,8 +58,8 @@ fn test_imports() {
|
||||
let mut imports = crate::mocked_resolver(&context);
|
||||
let test_import = r#"
|
||||
circuit Point {
|
||||
x: u32
|
||||
y: u32
|
||||
x: u32;
|
||||
y: u32;
|
||||
}
|
||||
|
||||
function foo() -> u32 {
|
||||
|
@ -1,3 +1,3 @@
|
||||
circuit Bat {
|
||||
t: u32
|
||||
t: u32;
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
circuit Baz {
|
||||
z: u32
|
||||
z: u32;
|
||||
}
|
||||
|
||||
circuit Bazzar {
|
||||
a: u32
|
||||
a: u32;
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
circuit Bar {
|
||||
r: u32
|
||||
r: u32;
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
circuit Car {
|
||||
c: u32
|
||||
c: u32;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
circuit Point {
|
||||
x: u32
|
||||
y: u32
|
||||
x: u32;
|
||||
y: u32;
|
||||
}
|
||||
|
||||
function foo() -> u32 {
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Adding the `mut` keyword makes a circuit variable mutable.
|
||||
circuit Foo {
|
||||
x: u32
|
||||
x: u32;
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Adding the `mut` keyword makes a circuit variable mutable.
|
||||
circuit Foo {
|
||||
x: u32
|
||||
x: u32;
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
@ -36,7 +36,7 @@ impl CanonicalizeError {
|
||||
}
|
||||
|
||||
pub fn invalid_array_dimension_size(span: &Span) -> Self {
|
||||
let message = "recieved dimension size of 0, expected it to be 1 or larger.".to_string();
|
||||
let message = "received dimension size of 0, expected it to be 1 or larger.".to_string();
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ use std::fmt;
|
||||
|
||||
#[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||
pub enum PackageAccess {
|
||||
Star(Span),
|
||||
Star { span: Span },
|
||||
SubPackage(Box<Package>),
|
||||
Symbol(ImportSymbol),
|
||||
Multiple(Packages),
|
||||
@ -30,7 +30,7 @@ pub enum PackageAccess {
|
||||
impl Node for PackageAccess {
|
||||
fn span(&self) -> &Span {
|
||||
match self {
|
||||
PackageAccess::Star(span) => span,
|
||||
PackageAccess::Star { span } => span,
|
||||
PackageAccess::SubPackage(package) => &package.span,
|
||||
PackageAccess::Symbol(package) => &package.span,
|
||||
PackageAccess::Multiple(package) => &package.span,
|
||||
@ -39,7 +39,7 @@ impl Node for PackageAccess {
|
||||
|
||||
fn set_span(&mut self, span: Span) {
|
||||
match self {
|
||||
PackageAccess::Star(package) => *package = span,
|
||||
PackageAccess::Star { span } => *span = span.clone(),
|
||||
PackageAccess::SubPackage(package) => package.span = span,
|
||||
PackageAccess::Symbol(package) => package.span = span,
|
||||
PackageAccess::Multiple(package) => package.span = span,
|
||||
@ -50,7 +50,7 @@ impl Node for PackageAccess {
|
||||
impl PackageAccess {
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
PackageAccess::Star(ref _span) => write!(f, "*"),
|
||||
PackageAccess::Star { .. } => write!(f, "*"),
|
||||
PackageAccess::SubPackage(ref package) => write!(f, "{}", package),
|
||||
PackageAccess::Symbol(ref symbol) => write!(f, "{}", symbol),
|
||||
PackageAccess::Multiple(ref packages) => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
x: u32
|
||||
x: u32;
|
||||
|
||||
function new() -> Self {
|
||||
let new: Self = Self {
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit Foo {
|
||||
x: u32
|
||||
x: u32;
|
||||
|
||||
function new() -> Self {
|
||||
let new: Self = Self {
|
||||
|
@ -1,6 +1,6 @@
|
||||
circuit Foo {
|
||||
f: u8,
|
||||
y: (u8, u8),
|
||||
f: u8;
|
||||
y: (u8, u8);
|
||||
|
||||
function z (mut self) -> u16 {
|
||||
self.y.0 += 1u8;
|
||||
|
@ -21,20 +21,19 @@ DRAFT
|
||||
The purpose of this proposal is to provide initial support for strings in Leo.
|
||||
Since strings are sequences of characters,
|
||||
the proposal inextricably also involves characters.
|
||||
This proposal is described as 'initial,'
|
||||
This proposal is described as initial,
|
||||
because it provides some basic features that we may extend in the future;
|
||||
the initial features should be sufficiently simple and conservative
|
||||
that they should not limit the design of the future features.
|
||||
|
||||
This proposal adds a new scalar type for characters
|
||||
This proposal adds a new scalar type for characters,
|
||||
along with a new kind of literals to denote characters.
|
||||
A string is then simply as an array of characters,
|
||||
A string is then simply an array of characters,
|
||||
but this proposal also adds a new kind of literals to denote strings
|
||||
more directly than via character array construction expressions.
|
||||
Along with equality and inequality, which always apply to every Leo type,
|
||||
this proposal also introduces operations for
|
||||
_[TODO: Summarize initial set of built-in or library operations
|
||||
on characters and strings.]_.
|
||||
this proposal also introduces some operations on characters and strings
|
||||
that can be implemented over time.
|
||||
|
||||
By not prescribing a new type for strings,
|
||||
this initial proposal leaves the door open
|
||||
@ -48,25 +47,23 @@ simple ones like URLs and token ticker symbols,
|
||||
and more complex ones like Bech32 encoding,
|
||||
edit distance in strings representing proteins,
|
||||
and zero-knowledge proofs of occurrences or absences of patterns in textual logs.
|
||||
_[TODO: Add more use cases if needed.]_
|
||||
|
||||
# Design
|
||||
|
||||
Since strings are sequences of characters,
|
||||
a design for strings inextricably also involves a design for characters.
|
||||
Thus, we first present a design for characters, then for strings.
|
||||
After that, we discuss the relation with Leo's existing format strings.
|
||||
We conclude this design section
|
||||
with a discussion of possible future extensions.
|
||||
Thus, we first present a design for both characters and strings.
|
||||
|
||||
## Characters
|
||||
|
||||
We add a new scalar type, `char` for characters.
|
||||
In accord with Leo's strong typing,
|
||||
this new type is separate from all the other scalar types.
|
||||
Type casts (a future feature of Leo) will be needed
|
||||
to convert between `char` and other types.
|
||||
|
||||
The set of values of type `char` is isomorphic to
|
||||
the set of Unicode code points from 0 to 10FFFFh (both inclusive).
|
||||
the set of Unicode code points from 0 to 10FFFF (both inclusive).
|
||||
That is, we support Unicode characters, more precisely code points
|
||||
(this may include some invalid code points,
|
||||
but it is simpler to allow every code point in that range).
|
||||
@ -81,38 +78,73 @@ e.g. `'a'`, `'*'`, and `'"'`.
|
||||
Single quotes must be escaped with a backslash, i.e. `'\''`;
|
||||
backslashes must be escaped as well, i.e. `'\\'`
|
||||
We allow other backslash escapes
|
||||
for commonly used characters that are not otherwise easily denoted,
|
||||
namely _[TODO: Decide which other escapes we want to allow, e.g. `'\n'`.]_
|
||||
* `\n`
|
||||
* `\r`
|
||||
* `\t`
|
||||
* `\0`
|
||||
* `\'`
|
||||
* `\"`
|
||||
|
||||
for commonly used characters that are not otherwise easily denoted.
|
||||
This is the complete list of single-character backslash escapes:
|
||||
* `\'` for code point 39 (single quote)
|
||||
* `\"` for code point 34 (double quote)
|
||||
* `\\` for code point 92 (backslash)
|
||||
* `\n` for code point 10 (line feed)
|
||||
* `\r` for code point 13 (carriage return)
|
||||
* `\t` for core point 9 (horizontal tab)
|
||||
* `\0` for code point 0 (the null character)
|
||||
|
||||
We also allow ASCII escapes of the form `\xOH`,
|
||||
where `O` is an octal digit and `H` is a hexadecimal digit
|
||||
(both uppercase and lowercase are allowed).
|
||||
These represent ASCII code points, i.e. from 0 to 127 (both inclusive).
|
||||
|
||||
We also allow Unicode escapes of the form `'\u{X}'`,
|
||||
where `X` is a sequence of one to six hex digits
|
||||
(both uppercase and lowercase letters are allowed)
|
||||
whose value must be between 0 and 10FFFF, inclusive.
|
||||
|
||||
Note that the literal character is assembled by the compiler---for
|
||||
creating literals, there is no need for the circuit to know
|
||||
which codepoints are disallowed.
|
||||
_[TODO: Do we want a different notation for Unicode escapes?
|
||||
Note that the `{` `}` delimiters are motivated by the fact that
|
||||
there may be a varying number of hex digits in this notation.]_
|
||||
This notation is supported by both Javascript and Rust.
|
||||
which code points are disallowed.
|
||||
|
||||
_[TODO: Which (initial) built-in or library operations
|
||||
do we want to provide for `char` values?]_
|
||||
- [ ] is_alphabetic - Returns `true` if the `char` has the `Alphabetic` property.
|
||||
- [ ] is_ascii - Returns `true` if the `char` is in the `ASCII` range.
|
||||
- [ ] is_ascii_alphabetic - Returns `true` if the `char` is in the `ASCII Alphabetic` range.
|
||||
- [ ] is_lowercase - Returns `true` if the `char` has the `Lowercase` property.
|
||||
- [ ] is_numeric - Returns `true` if the `char` has one of the general categories for numbers.
|
||||
- [ ] is_uppercase - Returns `true` if the `char` has the `Uppercase` property.
|
||||
- [ ] is_whitespace - Returns `true` if the `char` has the `White_Space` property.
|
||||
- [ ] to_digit - Converts the `char` to the given `radix` format.
|
||||
The equality operators `==` and `!=` are automatically available for `char`.
|
||||
Given that characters are essentially code points,
|
||||
we may also support the ordering operators `<`, `<=`, `>`, and `>=`;
|
||||
these may be useful to check whether a character is in certain range.
|
||||
|
||||
Below is a list of possible operations we could support on characters.
|
||||
It should be fairly easy to add more.
|
||||
- [ ] `is_alphabetic` - Returns `true` if the `char` has the `Alphabetic` property.
|
||||
- [ ] `is_ascii` - Returns `true` if the `char` is in the `ASCII` range.
|
||||
- [ ] `is_ascii_alphabetic` - Returns `true` if the `char` is in the `ASCII Alphabetic` range.
|
||||
- [ ] `is_lowercase` - Returns `true` if the `char` has the `Lowercase` property.
|
||||
- [ ] `is_numeric` - Returns `true` if the `char` has one of the general categories for numbers.
|
||||
- [ ] `is_uppercase` - Returns `true` if the `char` has the `Uppercase` property.
|
||||
- [ ] `is_whitespace` - Returns `true` if the `char` has the `White_Space` property.
|
||||
- [ ] `to_digit` - Converts the `char` to the given `radix` format.
|
||||
- [ ] `from_digit` - Inverse of to_digit.
|
||||
- [ ] `to_uppercase` - Converts lowercase to uppercase, leaving others unchanged.
|
||||
- [ ] `to_lowercase` - Converts uppercase to lowercase, leaving others unchanged.
|
||||
|
||||
It seems natural to convert between `char` values
|
||||
and `u8` or `u16` or `u32` values, under suitable range conditions;
|
||||
perhaps also between `char` values and
|
||||
(non-negative) `i8` or `i16` or `i32` values.
|
||||
This will be accomplished as part of the type casting extension of Leo.
|
||||
|
||||
The following code sample illustrates three ways of defining characters:
|
||||
character literal, single-character escapes, and Unicode escapes.
|
||||
|
||||
```js
|
||||
function main() -> [char; 5] {
|
||||
|
||||
// using char literals to form an array
|
||||
const world: [char; 5] = ['w', 'o', 'r', 'l', 'd'];
|
||||
|
||||
// escaped characters
|
||||
const escaped: [char; 4] = ['\n', '\t', '\\', '\''];
|
||||
|
||||
// unicode escapes - using emoji character 😊
|
||||
const smiling_face: char = '\u{1F60A}';
|
||||
|
||||
return [smiling_face, ...escaped];
|
||||
}
|
||||
```
|
||||
|
||||
## Strings
|
||||
|
||||
@ -133,12 +165,6 @@ Double quotes must be escaped with a backslash, e.g. `"say \"hi\""`;
|
||||
backslashes must be escaped as well, e.g. `"c:\\dir"`.
|
||||
We allow the same backslash escapes allowed for character literals
|
||||
(see the section on characters above).
|
||||
_[TODO: There is a difference in the treatment of single and double quotes:
|
||||
the former are allowed in string literals but not character literals,
|
||||
while the latter are allowed in character literals but not string literals;
|
||||
this asymmetry is also present in Java.
|
||||
However, for simplicity, we may want to symmetrically disallow
|
||||
both single and double quotes in both character and string literals.]_
|
||||
We also allow the same Unicode escapes allowed in character literals
|
||||
(described in the section on characters above).
|
||||
In any case, the type of a string literal is `[char; N]`,
|
||||
@ -160,30 +186,55 @@ in a future design iteration,
|
||||
a richer type for strings,
|
||||
as discussed in the section about future extensions below.
|
||||
|
||||
_[TODO: Which (initial) built-in or library operations
|
||||
do we want to provide for `[char; N]` values that are not already
|
||||
available with the existing array operations?]_
|
||||
- [ ] `u8` to `[char; 2]` hexstring, .., `u128` to `[char; 32]` hexstring
|
||||
- [ ] field element to `[char; 64]` hexstring. (Application can test leading zeros and slice them out if it needs to return, say, a 40-hex-digit string)
|
||||
- [ ] len - Returns the length of the `string`.
|
||||
- [ ] is_empty - Returns `true` if the `string` is empty.
|
||||
- [ ] pop - Pops a `char` to the `string`.
|
||||
- [ ] push - Pushes a `char` to the `string`.
|
||||
- [ ] append - Appends a `string` to the `string`.
|
||||
- [ ] clear - Empties the `string`.
|
||||
- [ ] _[TODO: more?]_
|
||||
Recall that empty arrays are disallowed in Leo.
|
||||
(The reason is that arrays,
|
||||
which must have a size known at compile time and are not resizable,
|
||||
are flattened into their elements when compiling to R1CS;
|
||||
thus, an empty array would be flattened into nothing.)
|
||||
Therefore, in this initial design empty strings must be disallowed as well.
|
||||
A future type of resizable strings will support empty strings.
|
||||
|
||||
## Input and Output of Literal Characters and Strings
|
||||
Because array, and therefore string, sizes must be known at compile time,
|
||||
there is no point to having an operation to return the length of a string.
|
||||
This operation will be supported for a future type of resizable strings.
|
||||
|
||||
Since UTF-8 is a standard encoding, it would make sense for
|
||||
the literal characters and strings in the `.in` file
|
||||
to be automatically converted to UTF-32 by the Leo compiler.
|
||||
However, the size of a string can be confusing since multiple
|
||||
Unicode code points can be composed into a single glyph which
|
||||
then appears to be a single character. If a parameter of type `[char; 10]`
|
||||
[if that is the syntax we decide on] is passed a literal string
|
||||
of a different size, the error message should explain that the
|
||||
size must be the number of codepoints needed to encode the string.
|
||||
Below are some examples of array operations
|
||||
that are also common for strings in other programming languages:
|
||||
* `[...s1, ...s2]` concatenates the strings `s1` and `s2`.
|
||||
* `[c, ...s]` adds the character `c` in front of the string `s`.
|
||||
* `s[i]` extracts the `i`-th character from the string `s`.
|
||||
* `s[1..]` removes the first character from the string `s`.
|
||||
|
||||
Below is a list of possible operations we could support on strings.
|
||||
It should be fairly easy to add more.
|
||||
- [ ] `u8` to `[char; 2]` hexstring, .., `u128` to `[char; 32]` hexstring.
|
||||
- [ ] Field element to `[char; 64]` hexstring. (Application can test leading zeros and slice them out if it needs to return, say, a 40-hex-digit string.)
|
||||
- [ ] Apply `to_uppercase` (see above) to every character.
|
||||
- [ ] Apply `to_lowercase` (see above) to every character.
|
||||
|
||||
Note that the latter two could be also realize via simple loops through the string.
|
||||
|
||||
Given the natural conversions between `char` values and integer values discussed earlier,
|
||||
it may be natural to also support element-wise conversions between strings and arrays of integers.
|
||||
This may be accomplished as part of the type casting extensions of Leo.
|
||||
|
||||
The following code shows a string literal and its actual transformation into an
|
||||
array of characters as well as possible array-like operations on strings:
|
||||
concatenation and comparison.
|
||||
|
||||
```js
|
||||
function main() -> bool {
|
||||
// double quotes create char array from string
|
||||
let hello: [char; 5] = "hello";
|
||||
let world: [char; 5] = ['w','o','r','l','d'];
|
||||
|
||||
// string concatenation can be performed using array syntax
|
||||
let hello_world: [char; 11] = [...hello, ' ', ...world];
|
||||
|
||||
// string comparison is also implemented via array type
|
||||
return hello_world == "hello world";
|
||||
}
|
||||
```
|
||||
|
||||
## Format Strings
|
||||
|
||||
@ -197,6 +248,38 @@ which will be interpreted as a format string
|
||||
according to the semantics of console print calls.
|
||||
The internal UTF-32 string will be translated to UTF-8 for output.
|
||||
|
||||
## Circuit Types for Character and String Operations
|
||||
|
||||
The operations on characters and lists described earlier, e.g. `is_ascii`,
|
||||
are provided as static member functions of two new built-in or library circuit types `Char` and `String`.
|
||||
Thus, an example call is `Char::is_ascii(c)`.
|
||||
This seems a general good way to organize built-in or library operations,
|
||||
and supports the use of the same name with different circuit types,
|
||||
e.g. `Char::to_uppercase` and `String::to_uppercase`.
|
||||
|
||||
These circuit types could also include constants, e.g. for certain ASCII characters.
|
||||
However, currently Leo does not support constants in circuit types,
|
||||
so that would have to be added separately first.
|
||||
|
||||
These two circuit types are just meant to collect static member functions for characters and strings.
|
||||
They are not meant to be the types of characters and strings:
|
||||
as mentioned previously, `char` is a new scalar (not circuit) type (like `bool`, `address`, `u8`, etc.)
|
||||
and there is no string type as such for now, but we use character arrays for strings.
|
||||
In the future we may want all the Leo types to be circuit types of some sort,
|
||||
but that is a separate feature that would have to be designed and developed independently.
|
||||
|
||||
## Input and Output of Literal Characters and Strings
|
||||
|
||||
Since UTF-8 is a standard encoding, it would make sense for
|
||||
the literal characters and strings in the `.in` file
|
||||
to be automatically converted to UTF-32 by the Leo compiler.
|
||||
However, the size of a string can be confusing since multiple
|
||||
Unicode code points can be composed into a single glyph which
|
||||
then appears to be a single character. If a parameter of type `[char; 10]`
|
||||
[if that is the syntax we decide on] is passed a literal string
|
||||
of a different size, the error message should explain that the
|
||||
size must be the number of codepoints needed to encode the string.
|
||||
|
||||
## Compilation to R1CS
|
||||
|
||||
So far, the discussion has been independent from R1CS
|
||||
@ -209,10 +292,10 @@ This section discusses R1CS compilation considerations
|
||||
for this proposal for characters and strings.
|
||||
|
||||
Values of type `char` can be represented directly as field elements,
|
||||
since the prime of the field is (much) larger than 10FFFFh.
|
||||
since the prime of the field is (much) larger than 10FFFF.
|
||||
This is more efficient than using a bit representation of characters.
|
||||
By construction, field elements that represent `char` values
|
||||
are never above 10FFFFh.
|
||||
are never above 10FFFF.
|
||||
Note that `field` and `char` remain separate types in Leo:
|
||||
it is only in the compilation to R1CS
|
||||
that everything is reduced to field elements.
|
||||
@ -226,6 +309,35 @@ applies to strings without exception.
|
||||
String literals are just syntactic sugar for
|
||||
suitable array inline construction expressions.
|
||||
|
||||
There are at least two approaches to implementing
|
||||
ordering operations `<` and `<=` on `char` values.
|
||||
Recalling that characters are represented as field values
|
||||
that are (well) below `(p-1)/2` where `p` is the prime,
|
||||
we can compare two field values `x` and `y`,
|
||||
both below `(p-1)/2`, via the constraints
|
||||
```
|
||||
(2) (x - y) = (b0 + 2*b1 + 4*b2 + ...)
|
||||
(b0) (1 - b0) = 0
|
||||
(b1) (1 - b1) = 0
|
||||
(b2) (1 - b2) = 0
|
||||
...
|
||||
```
|
||||
that take the difference, double it, and convert to bits.
|
||||
If `x >= y`, the difference is below `(p-1)/2`,
|
||||
and doubling results in an even number below `p`,
|
||||
with therefore `b0 = 0`.
|
||||
If `x < y`, the difference is above `(p-1)/2` (when reduced modulo `p`),
|
||||
and doubling results in an odd number when reduced modulo `p`,
|
||||
with therefore `b0 = 1`.
|
||||
Note that we need one variable and one constraint for every bit of `p`.
|
||||
The other approach is to convert the `x` and `y` to bits
|
||||
and compare them as integers;
|
||||
in this case we only need 21 bits for each.
|
||||
We need more analysis to determine which approach is more efficient.
|
||||
|
||||
The details of implementing other character and string operations in R1CS
|
||||
will be fleshed out as each operation is added.
|
||||
|
||||
## Future Extensions
|
||||
|
||||
As alluded to in the section about design above,
|
||||
@ -259,17 +371,18 @@ But the need to support characters and strings justifies the extra complexity.
|
||||
With the ability of Leo programs to process strings,
|
||||
it may be useful to have external tools that convert Leo strings
|
||||
to/from common formats, e.g. UTF-8.
|
||||
See the discussion of input files in the design section.
|
||||
|
||||
# Alternatives
|
||||
|
||||
We could avoid the new `char` type altogether,
|
||||
and instead, rely on the existing `u32` to represent Unicode code points,
|
||||
and provide character-oriented operations on `u32` values.
|
||||
(Note that both `u8` and `u16` are too small for 10FFFFh,
|
||||
(Note that both `u8` and `u16` are too small for 10FFFF,
|
||||
and that signed integer types include negative integers
|
||||
which are not Unicode code points:
|
||||
this makes `u32` the obvious choice.)
|
||||
However, many values of type `u32` are above 10FFFFh,
|
||||
However, many values of type `u32` are above 10FFFF,
|
||||
and many operations on `u32` do not really make sense on code points.
|
||||
We would probably want a notation for character literals anyhow,
|
||||
which could be (arguably mis)used for non-character unsigned integers.
|
||||
|
@ -1,5 +1,5 @@
|
||||
circuit PedersenHash {
|
||||
parameters: [group; 256],
|
||||
parameters: [group; 256];
|
||||
|
||||
// Instantiates a Pedersen hash circuit
|
||||
function new(parameters: [group; 256]) -> Self {
|
||||
|
@ -16,7 +16,7 @@
|
||||
circuit SillySudoku {
|
||||
// The starting grid values for the Sudoku puzzle.
|
||||
// Unset cells on the puzzle grid are set to 0.
|
||||
puzzle_grid: [u8; (3, 3)],
|
||||
puzzle_grid: [u8; (3, 3)];
|
||||
|
||||
/**
|
||||
* Returns true if a given Sudoku answer is correct.
|
||||
|
@ -476,7 +476,7 @@ Line terminators form whitespace, along with spaces and horizontal tabs.
|
||||
whitespace = space / horizontal-tab / newline
|
||||
```
|
||||
|
||||
Go to: _[space](#user-content-space), [newline](#user-content-newline), [horizontal-tab](#user-content-horizontal-tab)_;
|
||||
Go to: _[newline](#user-content-newline), [space](#user-content-space), [horizontal-tab](#user-content-horizontal-tab)_;
|
||||
|
||||
|
||||
There are two kinds of comments in Leo, as in other languages.
|
||||
@ -494,7 +494,7 @@ the ones used in the Java language reference.
|
||||
comment = block-comment / end-of-line-comment
|
||||
```
|
||||
|
||||
Go to: _[block-comment](#user-content-block-comment), [end-of-line-comment](#user-content-end-of-line-comment)_;
|
||||
Go to: _[end-of-line-comment](#user-content-end-of-line-comment), [block-comment](#user-content-block-comment)_;
|
||||
|
||||
|
||||
<a name="block-comment"></a>
|
||||
@ -511,7 +511,7 @@ rest-of-block-comment = "*" rest-of-block-comment-after-star
|
||||
/ not-star rest-of-block-comment
|
||||
```
|
||||
|
||||
Go to: _[rest-of-block-comment](#user-content-rest-of-block-comment), [rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star), [not-star](#user-content-not-star)_;
|
||||
Go to: _[rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star), [rest-of-block-comment](#user-content-rest-of-block-comment), [not-star](#user-content-not-star)_;
|
||||
|
||||
|
||||
<a name="rest-of-block-comment-after-star"></a>
|
||||
@ -521,7 +521,7 @@ rest-of-block-comment-after-star = "/"
|
||||
/ not-star-or-slash rest-of-block-comment
|
||||
```
|
||||
|
||||
Go to: _[rest-of-block-comment](#user-content-rest-of-block-comment), [not-star-or-slash](#user-content-not-star-or-slash), [rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star)_;
|
||||
Go to: _[not-star-or-slash](#user-content-not-star-or-slash), [rest-of-block-comment](#user-content-rest-of-block-comment), [rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star)_;
|
||||
|
||||
|
||||
<a name="end-of-line-comment"></a>
|
||||
@ -596,7 +596,7 @@ lowercase-letter = %x61-7A ; a-z
|
||||
letter = uppercase-letter / lowercase-letter
|
||||
```
|
||||
|
||||
Go to: _[lowercase-letter](#user-content-lowercase-letter), [uppercase-letter](#user-content-uppercase-letter)_;
|
||||
Go to: _[uppercase-letter](#user-content-uppercase-letter), [lowercase-letter](#user-content-lowercase-letter)_;
|
||||
|
||||
|
||||
An identifier is a non-empty sequence of letters, digits, and underscores,
|
||||
@ -642,7 +642,7 @@ format-string-element = not-double-quote-or-open-brace
|
||||
/ format-string-container
|
||||
```
|
||||
|
||||
Go to: _[format-string-container](#user-content-format-string-container), [not-double-quote-or-open-brace](#user-content-not-double-quote-or-open-brace), [not-double-quote-or-close-brace](#user-content-not-double-quote-or-close-brace)_;
|
||||
Go to: _[format-string-container](#user-content-format-string-container), [not-double-quote-or-close-brace](#user-content-not-double-quote-or-close-brace), [not-double-quote-or-open-brace](#user-content-not-double-quote-or-open-brace)_;
|
||||
|
||||
|
||||
<a name="format-string"></a>
|
||||
@ -767,7 +767,7 @@ atomic-literal = untyped-literal
|
||||
/ address-literal
|
||||
```
|
||||
|
||||
Go to: _[product-group-literal](#user-content-product-group-literal), [signed-literal](#user-content-signed-literal), [unsigned-literal](#user-content-unsigned-literal), [field-literal](#user-content-field-literal), [boolean-literal](#user-content-boolean-literal), [untyped-literal](#user-content-untyped-literal), [address-literal](#user-content-address-literal)_;
|
||||
Go to: _[untyped-literal](#user-content-untyped-literal), [product-group-literal](#user-content-product-group-literal), [unsigned-literal](#user-content-unsigned-literal), [signed-literal](#user-content-signed-literal), [boolean-literal](#user-content-boolean-literal), [address-literal](#user-content-address-literal), [field-literal](#user-content-field-literal)_;
|
||||
|
||||
|
||||
After defining the (mostly) alphanumeric tokens above,
|
||||
@ -812,7 +812,7 @@ token = keyword
|
||||
/ symbol
|
||||
```
|
||||
|
||||
Go to: _[package-name](#user-content-package-name), [annotation-name](#user-content-annotation-name), [format-string](#user-content-format-string), [keyword](#user-content-keyword), [atomic-literal](#user-content-atomic-literal), [identifier](#user-content-identifier), [symbol](#user-content-symbol)_;
|
||||
Go to: _[keyword](#user-content-keyword), [atomic-literal](#user-content-atomic-literal), [package-name](#user-content-package-name), [annotation-name](#user-content-annotation-name), [format-string](#user-content-format-string), [symbol](#user-content-symbol), [identifier](#user-content-identifier)_;
|
||||
|
||||
|
||||
|
||||
@ -848,7 +848,7 @@ signed-type = %s"i8" / %s"i16" / %s"i32" / %s"i64" / %s"i128"
|
||||
integer-type = unsigned-type / signed-type
|
||||
```
|
||||
|
||||
Go to: _[signed-type](#user-content-signed-type), [unsigned-type](#user-content-unsigned-type)_;
|
||||
Go to: _[unsigned-type](#user-content-unsigned-type), [signed-type](#user-content-signed-type)_;
|
||||
|
||||
|
||||
The integer types, along with the field and group types,
|
||||
@ -869,7 +869,7 @@ group-type = %s"group"
|
||||
arithmetic-type = integer-type / field-type / group-type
|
||||
```
|
||||
|
||||
Go to: _[integer-type](#user-content-integer-type), [field-type](#user-content-field-type), [group-type](#user-content-group-type)_;
|
||||
Go to: _[integer-type](#user-content-integer-type), [group-type](#user-content-group-type), [field-type](#user-content-field-type)_;
|
||||
|
||||
|
||||
The arithmetic types, along with the boolean and address types,
|
||||
@ -890,7 +890,7 @@ address-type = %s"address"
|
||||
scalar-type = boolean-type / arithmetic-type / address-type
|
||||
```
|
||||
|
||||
Go to: _[arithmetic-type](#user-content-arithmetic-type), [address-type](#user-content-address-type), [boolean-type](#user-content-boolean-type)_;
|
||||
Go to: _[address-type](#user-content-address-type), [boolean-type](#user-content-boolean-type), [arithmetic-type](#user-content-arithmetic-type)_;
|
||||
|
||||
|
||||
Circuit types are denoted by identifiers and the keyword `Self`.
|
||||
@ -951,7 +951,7 @@ i.e. types whose values contain (sub-)values
|
||||
aggregate-type = tuple-type / array-type / circuit-type
|
||||
```
|
||||
|
||||
Go to: _[tuple-type](#user-content-tuple-type), [array-type](#user-content-array-type), [circuit-type](#user-content-circuit-type)_;
|
||||
Go to: _[circuit-type](#user-content-circuit-type), [tuple-type](#user-content-tuple-type), [array-type](#user-content-array-type)_;
|
||||
|
||||
|
||||
Scalar and aggregate types form all the types.
|
||||
@ -997,7 +997,7 @@ A literal is either an atomic one or an affine group literal.
|
||||
literal = atomic-literal / affine-group-literal
|
||||
```
|
||||
|
||||
Go to: _[affine-group-literal](#user-content-affine-group-literal), [atomic-literal](#user-content-atomic-literal)_;
|
||||
Go to: _[atomic-literal](#user-content-atomic-literal), [affine-group-literal](#user-content-affine-group-literal)_;
|
||||
|
||||
|
||||
The following rule is not directly referenced in the rules for expressions
|
||||
@ -1039,7 +1039,7 @@ primary-expression = identifier
|
||||
/ circuit-expression
|
||||
```
|
||||
|
||||
Go to: _[tuple-expression](#user-content-tuple-expression), [identifier](#user-content-identifier), [expression](#user-content-expression), [array-expression](#user-content-array-expression), [circuit-expression](#user-content-circuit-expression), [literal](#user-content-literal)_;
|
||||
Go to: _[expression](#user-content-expression), [literal](#user-content-literal), [identifier](#user-content-identifier), [array-expression](#user-content-array-expression), [circuit-expression](#user-content-circuit-expression), [tuple-expression](#user-content-tuple-expression)_;
|
||||
|
||||
|
||||
Tuple expressions construct tuples.
|
||||
@ -1100,7 +1100,7 @@ Go to: _[expression](#user-content-expression), [array-dimensions](#user-content
|
||||
array-construction = array-inline-construction / array-repeat-construction
|
||||
```
|
||||
|
||||
Go to: _[array-repeat-construction](#user-content-array-repeat-construction), [array-inline-construction](#user-content-array-inline-construction)_;
|
||||
Go to: _[array-inline-construction](#user-content-array-inline-construction), [array-repeat-construction](#user-content-array-repeat-construction)_;
|
||||
|
||||
|
||||
<a name="array-expression"></a>
|
||||
@ -1128,7 +1128,7 @@ circuit-construction = circuit-type "{"
|
||||
"}"
|
||||
```
|
||||
|
||||
Go to: _[circuit-inline-element](#user-content-circuit-inline-element), [circuit-type](#user-content-circuit-type)_;
|
||||
Go to: _[circuit-type](#user-content-circuit-type), [circuit-inline-element](#user-content-circuit-inline-element)_;
|
||||
|
||||
|
||||
<a name="circuit-inline-element"></a>
|
||||
@ -1187,7 +1187,7 @@ postfix-expression = primary-expression
|
||||
/ postfix-expression "[" [expression] ".." [expression] "]"
|
||||
```
|
||||
|
||||
Go to: _[function-arguments](#user-content-function-arguments), [postfix-expression](#user-content-postfix-expression), [natural](#user-content-natural), [circuit-type](#user-content-circuit-type), [expression](#user-content-expression), [identifier](#user-content-identifier), [primary-expression](#user-content-primary-expression)_;
|
||||
Go to: _[expression](#user-content-expression), [natural](#user-content-natural), [identifier](#user-content-identifier), [primary-expression](#user-content-primary-expression), [circuit-type](#user-content-circuit-type), [function-arguments](#user-content-function-arguments), [postfix-expression](#user-content-postfix-expression)_;
|
||||
|
||||
|
||||
Unary operators have the highest operator precedence.
|
||||
@ -1201,7 +1201,7 @@ unary-expression = postfix-expression
|
||||
/ "-" unary-expression
|
||||
```
|
||||
|
||||
Go to: _[postfix-expression](#user-content-postfix-expression), [unary-expression](#user-content-unary-expression)_;
|
||||
Go to: _[unary-expression](#user-content-unary-expression), [postfix-expression](#user-content-postfix-expression)_;
|
||||
|
||||
|
||||
Next in the operator precedence is exponentiation,
|
||||
@ -1215,7 +1215,7 @@ exponential-expression = unary-expression
|
||||
/ unary-expression "**" exponential-expression
|
||||
```
|
||||
|
||||
Go to: _[unary-expression](#user-content-unary-expression), [exponential-expression](#user-content-exponential-expression)_;
|
||||
Go to: _[exponential-expression](#user-content-exponential-expression), [unary-expression](#user-content-unary-expression)_;
|
||||
|
||||
|
||||
Next in precedence come multiplication and division, both left-associative.
|
||||
@ -1227,7 +1227,7 @@ multiplicative-expression = exponential-expression
|
||||
/ multiplicative-expression "/" exponential-expression
|
||||
```
|
||||
|
||||
Go to: _[exponential-expression](#user-content-exponential-expression), [multiplicative-expression](#user-content-multiplicative-expression)_;
|
||||
Go to: _[multiplicative-expression](#user-content-multiplicative-expression), [exponential-expression](#user-content-exponential-expression)_;
|
||||
|
||||
|
||||
Then there are addition and subtraction, both left-assocative.
|
||||
@ -1239,7 +1239,7 @@ additive-expression = multiplicative-expression
|
||||
/ additive-expression "-" multiplicative-expression
|
||||
```
|
||||
|
||||
Go to: _[multiplicative-expression](#user-content-multiplicative-expression), [additive-expression](#user-content-additive-expression)_;
|
||||
Go to: _[additive-expression](#user-content-additive-expression), [multiplicative-expression](#user-content-multiplicative-expression)_;
|
||||
|
||||
|
||||
Next in the precedence order are ordering relations.
|
||||
@ -1267,7 +1267,7 @@ equality-expression = ordering-expression
|
||||
/ equality-expression "!=" ordering-expression
|
||||
```
|
||||
|
||||
Go to: _[equality-expression](#user-content-equality-expression), [ordering-expression](#user-content-ordering-expression)_;
|
||||
Go to: _[ordering-expression](#user-content-ordering-expression), [equality-expression](#user-content-equality-expression)_;
|
||||
|
||||
|
||||
Next come conjunctive expressions, left-associative.
|
||||
@ -1289,7 +1289,7 @@ disjunctive-expression = conjunctive-expression
|
||||
/ disjunctive-expression "||" conjunctive-expression
|
||||
```
|
||||
|
||||
Go to: _[disjunctive-expression](#user-content-disjunctive-expression), [conjunctive-expression](#user-content-conjunctive-expression)_;
|
||||
Go to: _[conjunctive-expression](#user-content-conjunctive-expression), [disjunctive-expression](#user-content-disjunctive-expression)_;
|
||||
|
||||
|
||||
Finally we have conditional expressions.
|
||||
@ -1302,7 +1302,7 @@ conditional-expression = disjunctive-expression
|
||||
":" conditional-expression
|
||||
```
|
||||
|
||||
Go to: _[expression](#user-content-expression), [conditional-expression](#user-content-conditional-expression), [disjunctive-expression](#user-content-disjunctive-expression)_;
|
||||
Go to: _[expression](#user-content-expression), [disjunctive-expression](#user-content-disjunctive-expression), [conditional-expression](#user-content-conditional-expression)_;
|
||||
|
||||
|
||||
Those above are all the expressions.
|
||||
@ -1335,7 +1335,7 @@ statement = expression-statement
|
||||
/ block
|
||||
```
|
||||
|
||||
Go to: _[expression-statement](#user-content-expression-statement), [return-statement](#user-content-return-statement), [assignment-statement](#user-content-assignment-statement), [block](#user-content-block), [loop-statement](#user-content-loop-statement), [constant-declaration](#user-content-constant-declaration), [conditional-statement](#user-content-conditional-statement), [console-statement](#user-content-console-statement), [variable-declaration](#user-content-variable-declaration)_;
|
||||
Go to: _[block](#user-content-block), [constant-declaration](#user-content-constant-declaration), [variable-declaration](#user-content-variable-declaration), [return-statement](#user-content-return-statement), [expression-statement](#user-content-expression-statement), [loop-statement](#user-content-loop-statement), [conditional-statement](#user-content-conditional-statement), [assignment-statement](#user-content-assignment-statement), [console-statement](#user-content-console-statement)_;
|
||||
|
||||
|
||||
<a name="block"></a>
|
||||
@ -1378,7 +1378,7 @@ variable-declaration = %s"let" identifier-or-identifiers [ ":" type ]
|
||||
"=" expression ";"
|
||||
```
|
||||
|
||||
Go to: _[type](#user-content-type), [identifier-or-identifiers](#user-content-identifier-or-identifiers), [expression](#user-content-expression)_;
|
||||
Go to: _[type](#user-content-type), [expression](#user-content-expression), [identifier-or-identifiers](#user-content-identifier-or-identifiers)_;
|
||||
|
||||
|
||||
<a name="constant-declaration"></a>
|
||||
@ -1387,7 +1387,7 @@ constant-declaration = %s"const" identifier-or-identifiers [ ":" type ]
|
||||
"=" expression ";"
|
||||
```
|
||||
|
||||
Go to: _[expression](#user-content-expression), [type](#user-content-type), [identifier-or-identifiers](#user-content-identifier-or-identifiers)_;
|
||||
Go to: _[identifier-or-identifiers](#user-content-identifier-or-identifiers), [type](#user-content-type), [expression](#user-content-expression)_;
|
||||
|
||||
|
||||
<a name="identifier-or-identifiers"></a>
|
||||
@ -1420,7 +1420,7 @@ conditional-statement = branch
|
||||
/ branch %s"else" conditional-statement
|
||||
```
|
||||
|
||||
Go to: _[block](#user-content-block), [branch](#user-content-branch), [conditional-statement](#user-content-conditional-statement)_;
|
||||
Go to: _[branch](#user-content-branch), [block](#user-content-block), [conditional-statement](#user-content-conditional-statement)_;
|
||||
|
||||
|
||||
A loop statement implicitly defines a loop variable
|
||||
@ -1432,7 +1432,7 @@ The body is a block.
|
||||
loop-statement = %s"for" identifier %s"in" expression ".." expression block
|
||||
```
|
||||
|
||||
Go to: _[identifier](#user-content-identifier), [expression](#user-content-expression), [block](#user-content-block)_;
|
||||
Go to: _[expression](#user-content-expression), [identifier](#user-content-identifier), [block](#user-content-block)_;
|
||||
|
||||
|
||||
An assignment statement is straightforward.
|
||||
@ -1476,7 +1476,7 @@ console-call = assert-call
|
||||
/ print-call
|
||||
```
|
||||
|
||||
Go to: _[print-call](#user-content-print-call), [assert-call](#user-content-assert-call)_;
|
||||
Go to: _[assert-call](#user-content-assert-call), [print-call](#user-content-print-call)_;
|
||||
|
||||
|
||||
<a name="assert-call"></a>
|
||||
@ -1535,7 +1535,7 @@ function-declaration = *annotation %s"function" identifier
|
||||
block
|
||||
```
|
||||
|
||||
Go to: _[block](#user-content-block), [identifier](#user-content-identifier), [function-parameters](#user-content-function-parameters), [type](#user-content-type)_;
|
||||
Go to: _[type](#user-content-type), [block](#user-content-block), [identifier](#user-content-identifier), [function-parameters](#user-content-function-parameters)_;
|
||||
|
||||
|
||||
<a name="function-parameters"></a>
|
||||
@ -1545,7 +1545,7 @@ function-parameters = self-parameter
|
||||
/ function-inputs
|
||||
```
|
||||
|
||||
Go to: _[self-parameter](#user-content-self-parameter), [function-inputs](#user-content-function-inputs)_;
|
||||
Go to: _[function-inputs](#user-content-function-inputs), [self-parameter](#user-content-self-parameter)_;
|
||||
|
||||
|
||||
<a name="self-parameter"></a>
|
||||
@ -1566,24 +1566,15 @@ Go to: _[function-input](#user-content-function-input)_;
|
||||
function-input = [ %s"const" ] identifier ":" type
|
||||
```
|
||||
|
||||
Go to: _[type](#user-content-type), [identifier](#user-content-identifier)_;
|
||||
Go to: _[identifier](#user-content-identifier), [type](#user-content-type)_;
|
||||
|
||||
|
||||
A circuit member variable declaration consists of an identifier and a type.
|
||||
A circuit member function declaration consists of a function declaration.
|
||||
|
||||
<a name="member-declaration"></a>
|
||||
<a name="member-variable-declarations"></a>
|
||||
```abnf
|
||||
member-declaration = member-variable-declaration
|
||||
/ member-function-declaration
|
||||
```
|
||||
|
||||
Go to: _[member-function-declaration](#user-content-member-function-declaration), [member-variable-declaration](#user-content-member-variable-declaration)_;
|
||||
|
||||
|
||||
<a name="member-variable-declaration"></a>
|
||||
```abnf
|
||||
member-variable-declaration = identifier ":" type
|
||||
member-variable-declarations = *(identifier ":" type ( "," / ";" )) identifier ":" type ( [ "," ] / ";" )
|
||||
```
|
||||
|
||||
Go to: _[identifier](#user-content-identifier), [type](#user-content-type)_;
|
||||
@ -1603,10 +1594,10 @@ as consisting of member variables and functions.
|
||||
<a name="circuit-declaration"></a>
|
||||
```abnf
|
||||
circuit-declaration = *annotation %s"circuit" identifier
|
||||
"{" member-declaration *( "," member-declaration ) "}"
|
||||
"{" [ member-variable-declarations ] *member-function-declaration "}"
|
||||
```
|
||||
|
||||
Go to: _[identifier](#user-content-identifier), [member-declaration](#user-content-member-declaration)_;
|
||||
Go to: _[member-variable-declarations](#user-content-member-variable-declarations), [identifier](#user-content-identifier)_;
|
||||
|
||||
|
||||
An import declaration consists of the `import` keyword
|
||||
@ -1621,10 +1612,10 @@ to be followed by a comma, for convenience.
|
||||
|
||||
<a name="import-declaration"></a>
|
||||
```abnf
|
||||
import-declaration = %s"import" package-path ";"
|
||||
import-declaration = %s"import" package-name "." package-path ";"
|
||||
```
|
||||
|
||||
Go to: _[package-path](#user-content-package-path)_;
|
||||
Go to: _[package-path](#user-content-package-path), [package-name](#user-content-package-name)_;
|
||||
|
||||
|
||||
<a name="package-path"></a>
|
||||
@ -1635,7 +1626,7 @@ package-path = "*"
|
||||
/ "(" package-path *( "," package-path ) [","] ")"
|
||||
```
|
||||
|
||||
Go to: _[identifier](#user-content-identifier), [package-path](#user-content-package-path), [package-name](#user-content-package-name)_;
|
||||
Go to: _[package-name](#user-content-package-name), [identifier](#user-content-identifier), [package-path](#user-content-package-path)_;
|
||||
|
||||
|
||||
Finally, we define a file as a sequence of zero or more declarations.
|
||||
@ -1650,7 +1641,7 @@ declaration = import-declaration
|
||||
/ constant-declaration
|
||||
```
|
||||
|
||||
Go to: _[constant-declaration](#user-content-constant-declaration), [import-declaration](#user-content-import-declaration), [function-declaration](#user-content-function-declaration), [circuit-declaration](#user-content-circuit-declaration)_;
|
||||
Go to: _[function-declaration](#user-content-function-declaration), [circuit-declaration](#user-content-circuit-declaration), [import-declaration](#user-content-import-declaration), [constant-declaration](#user-content-constant-declaration)_;
|
||||
|
||||
|
||||
<a name="file"></a>
|
||||
|
@ -942,21 +942,35 @@ function-inputs = function-input *( "," function-input )
|
||||
|
||||
function-input = [ %s"const" ] identifier ":" type
|
||||
|
||||
; A circuit member variable declaration consists of an identifier and a type.
|
||||
; A circuit member variable declaration consists of
|
||||
; an identifier and a type, terminated by semicolon.
|
||||
; For backward compatibility,
|
||||
; member variable declarations may be alternatively followed by commas,
|
||||
; and the last one may not be followed by anything:
|
||||
; these are deprecated, and will be eventually removed,
|
||||
; leaving only mandatory semicolons.
|
||||
; Note that there is no rule for a single `member-variable-declaration`,
|
||||
; but instead one for a sequence of them;
|
||||
; see the rule `circuit-declaration`.
|
||||
|
||||
member-variable-declarations = *( identifier ":" type ( "," / ";" ) )
|
||||
identifier ":" type ( [ "," ] / ";" )
|
||||
|
||||
; A circuit member function declaration consists of a function declaration.
|
||||
|
||||
member-declaration = member-variable-declaration
|
||||
/ member-function-declaration
|
||||
|
||||
member-variable-declaration = identifier ":" type
|
||||
|
||||
member-function-declaration = function-declaration
|
||||
|
||||
; A circuit declaration defines a circuit type,
|
||||
; as consisting of member variables and functions.
|
||||
; To more simply accommodate the backward compatibility
|
||||
; described for the rule `member-variable-declarations`,
|
||||
; all the member variables must precede all the member functions;
|
||||
; this may be relaxed after the backward compatibility is removed,
|
||||
; allowing member variables and member functions to be intermixed.
|
||||
|
||||
circuit-declaration = *annotation %s"circuit" identifier
|
||||
"{" member-declaration *( "," member-declaration ) "}"
|
||||
"{" [ member-variable-declarations ]
|
||||
*member-function-declaration "}"
|
||||
|
||||
; An import declaration consists of the `import` keyword
|
||||
; followed by a package path, which may be one of the following:
|
||||
@ -967,8 +981,12 @@ circuit-declaration = *annotation %s"circuit" identifier
|
||||
; which are "fan out" of the initial path.
|
||||
; Note that we allow the last element of the parenthesized list
|
||||
; to be followed by a comma, for convenience.
|
||||
; The package path in the import declaration must start with a package name
|
||||
; (e.g. it cannot be a `*`):
|
||||
; the rule for import declaration expresses this requirement
|
||||
; by using an explicit package name before the package path.
|
||||
|
||||
import-declaration = %s"import" package-path ";"
|
||||
import-declaration = %s"import" package-name "." package-path ";"
|
||||
|
||||
package-path = "*"
|
||||
/ identifier [ %s"as" identifier ]
|
||||
|
@ -6,260 +6,260 @@ function main() {
|
||||
}
|
||||
|
||||
circuit Foo {
|
||||
x0: u8,
|
||||
x1: u8,
|
||||
x2: u8,
|
||||
x3: u8,
|
||||
x4: u8,
|
||||
x5: u8,
|
||||
x6: u8,
|
||||
x7: u8,
|
||||
x8: u8,
|
||||
x9: u8,
|
||||
x10: u8,
|
||||
x11: u8,
|
||||
x12: u8,
|
||||
x13: u8,
|
||||
x14: u8,
|
||||
x15: u8,
|
||||
x16: u8,
|
||||
x17: u8,
|
||||
x18: u8,
|
||||
x19: u8,
|
||||
x20: u8,
|
||||
x21: u8,
|
||||
x22: u8,
|
||||
x23: u8,
|
||||
x24: u8,
|
||||
x25: u8,
|
||||
x26: u8,
|
||||
x27: u8,
|
||||
x28: u8,
|
||||
x29: u8,
|
||||
x30: u8,
|
||||
x31: u8,
|
||||
x32: u8,
|
||||
x33: u8,
|
||||
x34: u8,
|
||||
x35: u8,
|
||||
x36: u8,
|
||||
x37: u8,
|
||||
x38: u8,
|
||||
x39: u8,
|
||||
x40: u8,
|
||||
x41: u8,
|
||||
x42: u8,
|
||||
x43: u8,
|
||||
x44: u8,
|
||||
x45: u8,
|
||||
x46: u8,
|
||||
x47: u8,
|
||||
x48: u8,
|
||||
x49: u8,
|
||||
x50: u8,
|
||||
x51: u8,
|
||||
x52: u8,
|
||||
x53: u8,
|
||||
x54: u8,
|
||||
x55: u8,
|
||||
x56: u8,
|
||||
x57: u8,
|
||||
x58: u8,
|
||||
x59: u8,
|
||||
x60: u8,
|
||||
x61: u8,
|
||||
x62: u8,
|
||||
x63: u8,
|
||||
x64: u8,
|
||||
x65: u8,
|
||||
x66: u8,
|
||||
x67: u8,
|
||||
x68: u8,
|
||||
x69: u8,
|
||||
x70: u8,
|
||||
x71: u8,
|
||||
x72: u8,
|
||||
x73: u8,
|
||||
x74: u8,
|
||||
x75: u8,
|
||||
x76: u8,
|
||||
x77: u8,
|
||||
x78: u8,
|
||||
x79: u8,
|
||||
x80: u8,
|
||||
x81: u8,
|
||||
x82: u8,
|
||||
x83: u8,
|
||||
x84: u8,
|
||||
x85: u8,
|
||||
x86: u8,
|
||||
x87: u8,
|
||||
x88: u8,
|
||||
x89: u8,
|
||||
x90: u8,
|
||||
x91: u8,
|
||||
x92: u8,
|
||||
x93: u8,
|
||||
x94: u8,
|
||||
x95: u8,
|
||||
x96: u8,
|
||||
x97: u8,
|
||||
x98: u8,
|
||||
x99: u8,
|
||||
x100: u8,
|
||||
x101: u8,
|
||||
x102: u8,
|
||||
x103: u8,
|
||||
x104: u8,
|
||||
x105: u8,
|
||||
x106: u8,
|
||||
x107: u8,
|
||||
x108: u8,
|
||||
x109: u8,
|
||||
x110: u8,
|
||||
x111: u8,
|
||||
x112: u8,
|
||||
x113: u8,
|
||||
x114: u8,
|
||||
x115: u8,
|
||||
x116: u8,
|
||||
x117: u8,
|
||||
x118: u8,
|
||||
x119: u8,
|
||||
x120: u8,
|
||||
x121: u8,
|
||||
x122: u8,
|
||||
x123: u8,
|
||||
x124: u8,
|
||||
x125: u8,
|
||||
x126: u8,
|
||||
x127: u8,
|
||||
x128: u8,
|
||||
x129: u8,
|
||||
x130: u8,
|
||||
x131: u8,
|
||||
x132: u8,
|
||||
x133: u8,
|
||||
x134: u8,
|
||||
x135: u8,
|
||||
x136: u8,
|
||||
x137: u8,
|
||||
x138: u8,
|
||||
x139: u8,
|
||||
x140: u8,
|
||||
x141: u8,
|
||||
x142: u8,
|
||||
x143: u8,
|
||||
x144: u8,
|
||||
x145: u8,
|
||||
x146: u8,
|
||||
x147: u8,
|
||||
x148: u8,
|
||||
x149: u8,
|
||||
x150: u8,
|
||||
x151: u8,
|
||||
x152: u8,
|
||||
x153: u8,
|
||||
x154: u8,
|
||||
x155: u8,
|
||||
x156: u8,
|
||||
x157: u8,
|
||||
x158: u8,
|
||||
x159: u8,
|
||||
x160: u8,
|
||||
x161: u8,
|
||||
x162: u8,
|
||||
x163: u8,
|
||||
x164: u8,
|
||||
x165: u8,
|
||||
x166: u8,
|
||||
x167: u8,
|
||||
x168: u8,
|
||||
x169: u8,
|
||||
x170: u8,
|
||||
x171: u8,
|
||||
x172: u8,
|
||||
x173: u8,
|
||||
x174: u8,
|
||||
x175: u8,
|
||||
x176: u8,
|
||||
x177: u8,
|
||||
x178: u8,
|
||||
x179: u8,
|
||||
x180: u8,
|
||||
x181: u8,
|
||||
x182: u8,
|
||||
x183: u8,
|
||||
x184: u8,
|
||||
x185: u8,
|
||||
x186: u8,
|
||||
x187: u8,
|
||||
x188: u8,
|
||||
x189: u8,
|
||||
x190: u8,
|
||||
x191: u8,
|
||||
x192: u8,
|
||||
x193: u8,
|
||||
x194: u8,
|
||||
x195: u8,
|
||||
x196: u8,
|
||||
x197: u8,
|
||||
x198: u8,
|
||||
x199: u8,
|
||||
x200: u8,
|
||||
x201: u8,
|
||||
x202: u8,
|
||||
x203: u8,
|
||||
x204: u8,
|
||||
x205: u8,
|
||||
x206: u8,
|
||||
x207: u8,
|
||||
x208: u8,
|
||||
x209: u8,
|
||||
x210: u8,
|
||||
x211: u8,
|
||||
x212: u8,
|
||||
x213: u8,
|
||||
x214: u8,
|
||||
x215: u8,
|
||||
x216: u8,
|
||||
x217: u8,
|
||||
x218: u8,
|
||||
x219: u8,
|
||||
x220: u8,
|
||||
x221: u8,
|
||||
x222: u8,
|
||||
x223: u8,
|
||||
x224: u8,
|
||||
x225: u8,
|
||||
x226: u8,
|
||||
x227: u8,
|
||||
x228: u8,
|
||||
x229: u8,
|
||||
x230: u8,
|
||||
x231: u8,
|
||||
x232: u8,
|
||||
x233: u8,
|
||||
x234: u8,
|
||||
x235: u8,
|
||||
x236: u8,
|
||||
x237: u8,
|
||||
x238: u8,
|
||||
x239: u8,
|
||||
x240: u8,
|
||||
x241: u8,
|
||||
x242: u8,
|
||||
x243: u8,
|
||||
x244: u8,
|
||||
x245: u8,
|
||||
x246: u8,
|
||||
x247: u8,
|
||||
x248: u8,
|
||||
x249: u8,
|
||||
x250: u8,
|
||||
x251: u8,
|
||||
x252: u8,
|
||||
x253: u8,
|
||||
x254: u8,
|
||||
x255: u8
|
||||
x0: u8;
|
||||
x1: u8;
|
||||
x2: u8;
|
||||
x3: u8;
|
||||
x4: u8;
|
||||
x5: u8;
|
||||
x6: u8;
|
||||
x7: u8;
|
||||
x8: u8;
|
||||
x9: u8;
|
||||
x10: u8;
|
||||
x11: u8;
|
||||
x12: u8;
|
||||
x13: u8;
|
||||
x14: u8;
|
||||
x15: u8;
|
||||
x16: u8;
|
||||
x17: u8;
|
||||
x18: u8;
|
||||
x19: u8;
|
||||
x20: u8;
|
||||
x21: u8;
|
||||
x22: u8;
|
||||
x23: u8;
|
||||
x24: u8;
|
||||
x25: u8;
|
||||
x26: u8;
|
||||
x27: u8;
|
||||
x28: u8;
|
||||
x29: u8;
|
||||
x30: u8;
|
||||
x31: u8;
|
||||
x32: u8;
|
||||
x33: u8;
|
||||
x34: u8;
|
||||
x35: u8;
|
||||
x36: u8;
|
||||
x37: u8;
|
||||
x38: u8;
|
||||
x39: u8;
|
||||
x40: u8;
|
||||
x41: u8;
|
||||
x42: u8;
|
||||
x43: u8;
|
||||
x44: u8;
|
||||
x45: u8;
|
||||
x46: u8;
|
||||
x47: u8;
|
||||
x48: u8;
|
||||
x49: u8;
|
||||
x50: u8;
|
||||
x51: u8;
|
||||
x52: u8;
|
||||
x53: u8;
|
||||
x54: u8;
|
||||
x55: u8;
|
||||
x56: u8;
|
||||
x57: u8;
|
||||
x58: u8;
|
||||
x59: u8;
|
||||
x60: u8;
|
||||
x61: u8;
|
||||
x62: u8;
|
||||
x63: u8;
|
||||
x64: u8;
|
||||
x65: u8;
|
||||
x66: u8;
|
||||
x67: u8;
|
||||
x68: u8;
|
||||
x69: u8;
|
||||
x70: u8;
|
||||
x71: u8;
|
||||
x72: u8;
|
||||
x73: u8;
|
||||
x74: u8;
|
||||
x75: u8;
|
||||
x76: u8;
|
||||
x77: u8;
|
||||
x78: u8;
|
||||
x79: u8;
|
||||
x80: u8;
|
||||
x81: u8;
|
||||
x82: u8;
|
||||
x83: u8;
|
||||
x84: u8;
|
||||
x85: u8;
|
||||
x86: u8;
|
||||
x87: u8;
|
||||
x88: u8;
|
||||
x89: u8;
|
||||
x90: u8;
|
||||
x91: u8;
|
||||
x92: u8;
|
||||
x93: u8;
|
||||
x94: u8;
|
||||
x95: u8;
|
||||
x96: u8;
|
||||
x97: u8;
|
||||
x98: u8;
|
||||
x99: u8;
|
||||
x100: u8;
|
||||
x101: u8;
|
||||
x102: u8;
|
||||
x103: u8;
|
||||
x104: u8;
|
||||
x105: u8;
|
||||
x106: u8;
|
||||
x107: u8;
|
||||
x108: u8;
|
||||
x109: u8;
|
||||
x110: u8;
|
||||
x111: u8;
|
||||
x112: u8;
|
||||
x113: u8;
|
||||
x114: u8;
|
||||
x115: u8;
|
||||
x116: u8;
|
||||
x117: u8;
|
||||
x118: u8;
|
||||
x119: u8;
|
||||
x120: u8;
|
||||
x121: u8;
|
||||
x122: u8;
|
||||
x123: u8;
|
||||
x124: u8;
|
||||
x125: u8;
|
||||
x126: u8;
|
||||
x127: u8;
|
||||
x128: u8;
|
||||
x129: u8;
|
||||
x130: u8;
|
||||
x131: u8;
|
||||
x132: u8;
|
||||
x133: u8;
|
||||
x134: u8;
|
||||
x135: u8;
|
||||
x136: u8;
|
||||
x137: u8;
|
||||
x138: u8;
|
||||
x139: u8;
|
||||
x140: u8;
|
||||
x141: u8;
|
||||
x142: u8;
|
||||
x143: u8;
|
||||
x144: u8;
|
||||
x145: u8;
|
||||
x146: u8;
|
||||
x147: u8;
|
||||
x148: u8;
|
||||
x149: u8;
|
||||
x150: u8;
|
||||
x151: u8;
|
||||
x152: u8;
|
||||
x153: u8;
|
||||
x154: u8;
|
||||
x155: u8;
|
||||
x156: u8;
|
||||
x157: u8;
|
||||
x158: u8;
|
||||
x159: u8;
|
||||
x160: u8;
|
||||
x161: u8;
|
||||
x162: u8;
|
||||
x163: u8;
|
||||
x164: u8;
|
||||
x165: u8;
|
||||
x166: u8;
|
||||
x167: u8;
|
||||
x168: u8;
|
||||
x169: u8;
|
||||
x170: u8;
|
||||
x171: u8;
|
||||
x172: u8;
|
||||
x173: u8;
|
||||
x174: u8;
|
||||
x175: u8;
|
||||
x176: u8;
|
||||
x177: u8;
|
||||
x178: u8;
|
||||
x179: u8;
|
||||
x180: u8;
|
||||
x181: u8;
|
||||
x182: u8;
|
||||
x183: u8;
|
||||
x184: u8;
|
||||
x185: u8;
|
||||
x186: u8;
|
||||
x187: u8;
|
||||
x188: u8;
|
||||
x189: u8;
|
||||
x190: u8;
|
||||
x191: u8;
|
||||
x192: u8;
|
||||
x193: u8;
|
||||
x194: u8;
|
||||
x195: u8;
|
||||
x196: u8;
|
||||
x197: u8;
|
||||
x198: u8;
|
||||
x199: u8;
|
||||
x200: u8;
|
||||
x201: u8;
|
||||
x202: u8;
|
||||
x203: u8;
|
||||
x204: u8;
|
||||
x205: u8;
|
||||
x206: u8;
|
||||
x207: u8;
|
||||
x208: u8;
|
||||
x209: u8;
|
||||
x210: u8;
|
||||
x211: u8;
|
||||
x212: u8;
|
||||
x213: u8;
|
||||
x214: u8;
|
||||
x215: u8;
|
||||
x216: u8;
|
||||
x217: u8;
|
||||
x218: u8;
|
||||
x219: u8;
|
||||
x220: u8;
|
||||
x221: u8;
|
||||
x222: u8;
|
||||
x223: u8;
|
||||
x224: u8;
|
||||
x225: u8;
|
||||
x226: u8;
|
||||
x227: u8;
|
||||
x228: u8;
|
||||
x229: u8;
|
||||
x230: u8;
|
||||
x231: u8;
|
||||
x232: u8;
|
||||
x233: u8;
|
||||
x234: u8;
|
||||
x235: u8;
|
||||
x236: u8;
|
||||
x237: u8;
|
||||
x238: u8;
|
||||
x239: u8;
|
||||
x240: u8;
|
||||
x241: u8;
|
||||
x242: u8;
|
||||
x243: u8;
|
||||
x244: u8;
|
||||
x245: u8;
|
||||
x246: u8;
|
||||
x247: u8;
|
||||
x248: u8;
|
||||
x249: u8;
|
||||
x250: u8;
|
||||
x251: u8;
|
||||
x252: u8;
|
||||
x253: u8;
|
||||
x254: u8;
|
||||
x255: u8;
|
||||
}
|
@ -48,6 +48,10 @@ impl SyntaxError {
|
||||
SyntaxError::Error(FormattedError::new_from_span(message, span))
|
||||
}
|
||||
|
||||
pub fn invalid_import_list(span: &Span) -> Self {
|
||||
Self::new_from_span("Cannot import empty list".to_string(), span)
|
||||
}
|
||||
|
||||
pub fn unexpected_eof(span: &Span) -> Self {
|
||||
Self::new_from_span("unexpected EOF".to_string(), span)
|
||||
}
|
||||
@ -74,6 +78,13 @@ impl SyntaxError {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn mixed_commas_and_semicolons(span: &Span) -> Self {
|
||||
Self::new_from_span(
|
||||
"Cannot mix use of commas and semi-colons for circuit member variable declarations.".to_string(),
|
||||
span,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn unexpected_ident(got: &str, expected: &[&str], span: &Span) -> Self {
|
||||
Self::new_from_span(
|
||||
format!(
|
||||
|
@ -66,6 +66,13 @@ impl ParserContext {
|
||||
SyntaxError::unexpected_eof(&self.end_span)
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns a reference to the next next token or error if it does not exist.
|
||||
///
|
||||
pub fn peek_next(&self) -> SyntaxResult<&SpannedToken> {
|
||||
self.tokens.get(self.tokens.len() - 2).ok_or_else(|| self.eof())
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns a reference to the next token or error if it does not exist.
|
||||
///
|
||||
|
@ -136,7 +136,7 @@ impl ParserContext {
|
||||
/// Returns a vector of [`PackageAccess`] AST nodes if the next tokens represent package access
|
||||
/// expressions within an import statement.
|
||||
///
|
||||
pub fn parse_package_accesses(&mut self) -> SyntaxResult<Vec<PackageAccess>> {
|
||||
pub fn parse_package_accesses(&mut self, span: &Span) -> SyntaxResult<Vec<PackageAccess>> {
|
||||
let mut out = Vec::new();
|
||||
self.expect(Token::LeftParen)?;
|
||||
while self.eat(Token::RightParen).is_none() {
|
||||
@ -147,6 +147,11 @@ impl ParserContext {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if out.is_empty() {
|
||||
return Err(SyntaxError::invalid_import_list(span));
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
@ -156,7 +161,7 @@ impl ParserContext {
|
||||
///
|
||||
pub fn parse_package_access(&mut self) -> SyntaxResult<PackageAccess> {
|
||||
if let Some(SpannedToken { span, .. }) = self.eat(Token::Mul) {
|
||||
Ok(PackageAccess::Star(span))
|
||||
Ok(PackageAccess::Star { span })
|
||||
} else {
|
||||
let name = self.expect_ident()?;
|
||||
if self.peek_token().as_ref() == &Token::Dot {
|
||||
@ -247,7 +252,7 @@ impl ParserContext {
|
||||
let package_name = self.parse_package_name()?;
|
||||
self.expect(Token::Dot)?;
|
||||
if self.peek()?.token == Token::LeftParen {
|
||||
let accesses = self.parse_package_accesses()?;
|
||||
let accesses = self.parse_package_accesses(&package_name.span)?;
|
||||
Ok(PackageOrPackages::Packages(Packages {
|
||||
span: &package_name.span + accesses.last().map(|x| x.span()).unwrap_or(&package_name.span),
|
||||
name: package_name,
|
||||
@ -280,18 +285,82 @@ impl ParserContext {
|
||||
/// Returns a [`CircuitMember`] AST node if the next tokens represent a circuit member variable
|
||||
/// or circuit member function.
|
||||
///
|
||||
pub fn parse_circuit_member(&mut self) -> SyntaxResult<CircuitMember> {
|
||||
pub fn parse_circuit_declaration(&mut self) -> SyntaxResult<Vec<CircuitMember>> {
|
||||
let mut members = Vec::new();
|
||||
let peeked = &self.peek()?.token;
|
||||
if peeked == &Token::Function || peeked == &Token::At {
|
||||
let mut last_variable = peeked == &Token::Function || peeked == &Token::At;
|
||||
let (mut semi_colons, mut commas) = (false, false);
|
||||
while self.eat(Token::RightCurly).is_none() {
|
||||
if !last_variable {
|
||||
let (variable, last) = self.parse_member_variable_declaration()?;
|
||||
|
||||
members.push(variable);
|
||||
|
||||
let peeked = &self.peek()?;
|
||||
if peeked.token == Token::Semicolon {
|
||||
if commas {
|
||||
return Err(SyntaxError::mixed_commas_and_semicolons(&peeked.span));
|
||||
}
|
||||
|
||||
semi_colons = true;
|
||||
self.expect(Token::Semicolon)?;
|
||||
} else {
|
||||
if semi_colons {
|
||||
return Err(SyntaxError::mixed_commas_and_semicolons(&peeked.span));
|
||||
}
|
||||
|
||||
commas = true;
|
||||
self.eat(Token::Comma);
|
||||
}
|
||||
|
||||
if last {
|
||||
last_variable = last;
|
||||
}
|
||||
} else {
|
||||
let function = self.parse_member_function_declaration()?;
|
||||
members.push(function);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(members)
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns a [`CircuitMember`] AST node if the next tokens represent a circuit member variable.
|
||||
///
|
||||
pub fn parse_member_variable_declaration(&mut self) -> SyntaxResult<(CircuitMember, bool)> {
|
||||
let name = self.expect_ident()?;
|
||||
self.expect(Token::Colon)?;
|
||||
let type_ = self.parse_type()?.0;
|
||||
|
||||
let peeked = &self.peek()?.token;
|
||||
if peeked == &Token::Function || peeked == &Token::At || peeked == &Token::RightCurly {
|
||||
return Ok((CircuitMember::CircuitVariable(name, type_), true));
|
||||
} else if peeked == &Token::Comma || peeked == &Token::Semicolon {
|
||||
let peeked = &self.peek_next()?.token;
|
||||
if peeked == &Token::Function || peeked == &Token::At || peeked == &Token::RightCurly {
|
||||
return Ok((CircuitMember::CircuitVariable(name, type_), true));
|
||||
}
|
||||
}
|
||||
|
||||
Ok((CircuitMember::CircuitVariable(name, type_), false))
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns a [`CircuitMember`] AST node if the next tokens represent a circuit member function.
|
||||
///
|
||||
pub fn parse_member_function_declaration(&mut self) -> SyntaxResult<CircuitMember> {
|
||||
let peeked = &self.peek()?;
|
||||
let peeked_token = &peeked.token;
|
||||
if peeked_token == &Token::Function || peeked_token == &Token::At {
|
||||
let function = self.parse_function_declaration()?;
|
||||
Ok(CircuitMember::CircuitFunction(function.1))
|
||||
} else {
|
||||
// circuit variable
|
||||
let name = self.expect_ident()?;
|
||||
self.expect(Token::Colon)?;
|
||||
let type_ = self.parse_type()?.0;
|
||||
self.eat(Token::Comma);
|
||||
Ok(CircuitMember::CircuitVariable(name, type_))
|
||||
Err(SyntaxError::unexpected(
|
||||
peeked_token,
|
||||
&[Token::Function, Token::At],
|
||||
&peeked.span,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,11 +372,8 @@ impl ParserContext {
|
||||
self.expect(Token::Circuit)?;
|
||||
let name = self.expect_ident()?;
|
||||
self.expect(Token::LeftCurly)?;
|
||||
let mut members = Vec::new();
|
||||
while self.eat(Token::RightCurly).is_none() {
|
||||
let member = self.parse_circuit_member()?;
|
||||
members.push(member);
|
||||
}
|
||||
let members = self.parse_circuit_declaration()?;
|
||||
|
||||
Ok((name.clone(), Circuit {
|
||||
circuit_name: name,
|
||||
members,
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
a: u8;
|
||||
|
||||
function use_a(const self) -> u8 {
|
||||
return self.a + 1;
|
||||
|
@ -4,7 +4,7 @@ expectation: Fail
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
a: u8;
|
||||
|
||||
function set_a(const self, new: u8) {
|
||||
self.a = new;
|
||||
|
@ -4,7 +4,7 @@ expectation: Fail
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
x: u32
|
||||
x: u32;
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
@ -4,7 +4,7 @@ expectation: Fail
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
x: u8
|
||||
x: u8;
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
@ -8,7 +8,7 @@ inputs:
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
foo: u32,
|
||||
foo: u32;
|
||||
|
||||
function bar() -> u32 {
|
||||
return 1u32;
|
||||
|
@ -4,7 +4,7 @@ expectation: Fail
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
x: u32
|
||||
x: u32;
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
@ -4,7 +4,7 @@ expectation: Fail
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
a: u8;
|
||||
|
||||
function bar() {}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ expectation: Fail
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
a: u8;
|
||||
|
||||
function bar() {}
|
||||
|
||||
|
@ -4,7 +4,7 @@ expectation: Fail
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
a: u8;
|
||||
|
||||
function bar() {}
|
||||
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
a: u8;
|
||||
|
||||
function set_a(mut self, new: u8) {
|
||||
self.a = new;
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
a: u8;
|
||||
|
||||
function set_a(mut self, condition: bool, new: u8) {
|
||||
if condition {
|
||||
|
@ -10,7 +10,7 @@ function main() {
|
||||
}
|
||||
|
||||
circuit Foo {
|
||||
a: u32
|
||||
a: u32;
|
||||
|
||||
function bar(mut self) {
|
||||
if true {
|
||||
|
@ -4,7 +4,7 @@ expectation: Fail
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
a: u8;
|
||||
|
||||
function set_a(self, new: u8) {
|
||||
self.a = new;
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
a: u8;
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
@ -4,7 +4,7 @@ expectation: Fail
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
a: u8;
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
*/
|
||||
|
||||
circuit TestMe {
|
||||
x: u8,
|
||||
x: u8;
|
||||
|
||||
function test_me(mut self) -> u8 {
|
||||
self.x += 1;
|
||||
|
@ -11,7 +11,7 @@ inputs:
|
||||
*/
|
||||
|
||||
circuit PedersenHash {
|
||||
parameters: [u32; 512]
|
||||
parameters: [u32; 512];
|
||||
|
||||
function new(parameters: [u32; 512]) -> Self {
|
||||
return Self { parameters: parameters };
|
||||
|
@ -4,7 +4,7 @@ expectation: Pass
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
f: u32,
|
||||
f: u32;
|
||||
|
||||
function bar(self) -> u32 {
|
||||
return self.f;
|
||||
|
@ -4,7 +4,7 @@ expectation: Fail
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
f: u32,
|
||||
f: u32;
|
||||
|
||||
function bar() -> u32 {
|
||||
return f;
|
||||
|
@ -1,3 +1,3 @@
|
||||
circuit Bat {
|
||||
t: u32
|
||||
t: u32;
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
circuit Baz {
|
||||
z: u32
|
||||
z: u32;
|
||||
}
|
||||
|
||||
circuit Bazzar {
|
||||
a: u32
|
||||
}
|
||||
a: u32;
|
||||
}
|
||||
|
||||
const ONE: u8 = 1;
|
||||
|
@ -1,3 +1,3 @@
|
||||
circuit Bar {
|
||||
r: u32
|
||||
r: u32;
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
circuit Car {
|
||||
c: u32
|
||||
c: u32;
|
||||
}
|
@ -4,7 +4,7 @@ expectation: Fail
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
x: u32
|
||||
x: u32;
|
||||
}
|
||||
|
||||
// const variable is immutable
|
||||
|
@ -13,7 +13,7 @@ outputs:
|
||||
- "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\" x: u32,\\\"}\"}"
|
||||
- IntegerType: U32
|
||||
- CircuitVariable:
|
||||
- "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":5,\\\"line_stop\\\":5,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\" y: u32,\\\"}\"}"
|
||||
- "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":5,\\\"line_stop\\\":5,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\" y: u32\\\"}\"}"
|
||||
- IntegerType: U32
|
||||
- CircuitFunction:
|
||||
annotations: []
|
||||
|
@ -10,10 +10,10 @@ outputs:
|
||||
circuit_name: "{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}"
|
||||
members:
|
||||
- CircuitVariable:
|
||||
- "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\" x: u32,\\\"}\"}"
|
||||
- "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\" x: u32;\\\"}\"}"
|
||||
- IntegerType: U32
|
||||
- CircuitVariable:
|
||||
- "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":5,\\\"line_stop\\\":5,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\" y: u32,\\\"}\"}"
|
||||
- "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":5,\\\"line_stop\\\":5,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\" y: u32;\\\"}\"}"
|
||||
- IntegerType: U32
|
||||
global_consts: {}
|
||||
functions: {}
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
namespace: Parse
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- " --> test:10:11\n |\n 10 | y: u32;\n | ^\n |\n = Cannot mix use of commas and semi-colons for circuit member variable declarations."
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
namespace: Parse
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- " --> test:3:8\n |\n 3 | import a.();\n | ^\n |\n = Cannot import empty list"
|
@ -10,12 +10,13 @@ outputs:
|
||||
name: "{\"name\":\"test-import\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":8,\\\"col_stop\\\":19,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"import test-import.*; // local import\\\"}\"}"
|
||||
access:
|
||||
Star:
|
||||
line_start: 3
|
||||
line_stop: 3
|
||||
col_start: 20
|
||||
col_stop: 21
|
||||
path: test
|
||||
content: import test-import.*; // local import
|
||||
span:
|
||||
line_start: 3
|
||||
line_stop: 3
|
||||
col_start: 20
|
||||
col_stop: 21
|
||||
path: test
|
||||
content: import test-import.*; // local import
|
||||
span:
|
||||
line_start: 3
|
||||
line_stop: 3
|
||||
@ -35,12 +36,13 @@ outputs:
|
||||
name: "{\"name\":\"bar\",\"span\":\"{\\\"line_start\\\":5,\\\"line_stop\\\":5,\\\"col_start\\\":8,\\\"col_stop\\\":11,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"import bar.*; // imports directory import\\\"}\"}"
|
||||
access:
|
||||
Star:
|
||||
line_start: 5
|
||||
line_stop: 5
|
||||
col_start: 12
|
||||
col_stop: 13
|
||||
path: test
|
||||
content: import bar.*; // imports directory import
|
||||
span:
|
||||
line_start: 5
|
||||
line_stop: 5
|
||||
col_start: 12
|
||||
col_stop: 13
|
||||
path: test
|
||||
content: import bar.*; // imports directory import
|
||||
span:
|
||||
line_start: 5
|
||||
line_stop: 5
|
||||
@ -63,12 +65,13 @@ outputs:
|
||||
name: "{\"name\":\"baz\",\"span\":\"{\\\"line_start\\\":6,\\\"line_stop\\\":6,\\\"col_start\\\":12,\\\"col_stop\\\":15,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"import bar.baz.*; // imports directory import\\\"}\"}"
|
||||
access:
|
||||
Star:
|
||||
line_start: 6
|
||||
line_stop: 6
|
||||
col_start: 16
|
||||
col_stop: 17
|
||||
path: test
|
||||
content: import bar.baz.*; // imports directory import
|
||||
span:
|
||||
line_start: 6
|
||||
line_stop: 6
|
||||
col_start: 16
|
||||
col_stop: 17
|
||||
path: test
|
||||
content: import bar.baz.*; // imports directory import
|
||||
span:
|
||||
line_start: 6
|
||||
line_stop: 6
|
||||
@ -101,12 +104,13 @@ outputs:
|
||||
name: "{\"name\":\"bat\",\"span\":\"{\\\"line_start\\\":7,\\\"line_stop\\\":7,\\\"col_start\\\":16,\\\"col_stop\\\":19,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"import bar.bat.bat.*; // imports directory import\\\"}\"}"
|
||||
access:
|
||||
Star:
|
||||
line_start: 7
|
||||
line_stop: 7
|
||||
col_start: 20
|
||||
col_stop: 21
|
||||
path: test
|
||||
content: import bar.bat.bat.*; // imports directory import
|
||||
span:
|
||||
line_start: 7
|
||||
line_stop: 7
|
||||
col_start: 20
|
||||
col_stop: 21
|
||||
path: test
|
||||
content: import bar.bat.bat.*; // imports directory import
|
||||
span:
|
||||
line_start: 7
|
||||
line_stop: 7
|
||||
@ -140,12 +144,13 @@ outputs:
|
||||
name: "{\"name\":\"car\",\"span\":\"{\\\"line_start\\\":8,\\\"line_stop\\\":8,\\\"col_start\\\":8,\\\"col_stop\\\":11,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"import car.*; // imports directory import\\\"}\"}"
|
||||
access:
|
||||
Star:
|
||||
line_start: 8
|
||||
line_stop: 8
|
||||
col_start: 12
|
||||
col_stop: 13
|
||||
path: test
|
||||
content: import car.*; // imports directory import
|
||||
span:
|
||||
line_start: 8
|
||||
line_stop: 8
|
||||
col_start: 12
|
||||
col_stop: 13
|
||||
path: test
|
||||
content: import car.*; // imports directory import
|
||||
span:
|
||||
line_start: 8
|
||||
line_stop: 8
|
||||
|
@ -10,12 +10,13 @@ outputs:
|
||||
name: "{\"name\":\"test-import\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":8,\\\"col_stop\\\":19,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"import test-import.*;\\\"}\"}"
|
||||
access:
|
||||
Star:
|
||||
line_start: 3
|
||||
line_stop: 3
|
||||
col_start: 20
|
||||
col_stop: 21
|
||||
path: test
|
||||
content: import test-import.*;
|
||||
span:
|
||||
line_start: 3
|
||||
line_stop: 3
|
||||
col_start: 20
|
||||
col_stop: 21
|
||||
path: test
|
||||
content: import test-import.*;
|
||||
span:
|
||||
line_start: 3
|
||||
line_stop: 3
|
||||
|
@ -5,7 +5,7 @@ expectation: Pass
|
||||
|
||||
circuit X {
|
||||
x: u32,
|
||||
y: u32,
|
||||
y: u32
|
||||
function x() {
|
||||
return ();
|
||||
}
|
||||
|
@ -4,6 +4,6 @@ expectation: Pass
|
||||
*/
|
||||
|
||||
circuit X {
|
||||
x: u32,
|
||||
y: u32,
|
||||
x: u32;
|
||||
y: u32;
|
||||
}
|
14
tests/parser/circuits/fields_fail.leo
Normal file
14
tests/parser/circuits/fields_fail.leo
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
namespace: Parse
|
||||
expectation: Fail
|
||||
*/
|
||||
|
||||
circuit X {
|
||||
x: u32
|
||||
y: u32
|
||||
}
|
||||
|
||||
circuit X {
|
||||
x: u32,
|
||||
y: u32;
|
||||
}
|
6
tests/parser/import/import_empty_list_fail.leo
Normal file
6
tests/parser/import/import_empty_list_fail.leo
Normal file
@ -0,0 +1,6 @@
|
||||
/*
|
||||
namespace: Parse
|
||||
expectation: Fail
|
||||
*/
|
||||
|
||||
import a.();
|
Loading…
Reference in New Issue
Block a user