mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-27 12:17:35 +03:00
resolve merge conflicts
This commit is contained in:
commit
eaa07934ed
@ -1 +1 @@
|
||||
v1.2.3
|
||||
v1.3.0
|
70
Cargo.lock
generated
70
Cargo.lock
generated
@ -138,11 +138,10 @@ checksum = "58946044516aa9dc922182e0d6e9d124a31aafe6b421614654eb27cf90cec09c"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.2"
|
||||
version = "1.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d175dfa69e619905c4c3cdb7c3c203fa3bdd5d51184e3afdb2742c0280493772"
|
||||
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"serde",
|
||||
]
|
||||
|
||||
@ -640,6 +639,12 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dtoa"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
@ -1241,7 +1246,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "leo-abnf"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
dependencies = [
|
||||
"abnf",
|
||||
"anyhow",
|
||||
@ -1249,7 +1254,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leo-asg"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
dependencies = [
|
||||
"criterion",
|
||||
"indexmap",
|
||||
@ -1265,14 +1270,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leo-asg-passes"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
dependencies = [
|
||||
"leo-asg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "leo-ast"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"criterion",
|
||||
@ -1287,7 +1292,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leo-compiler"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"hex",
|
||||
@ -1322,7 +1327,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leo-imports"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"leo-asg",
|
||||
@ -1334,7 +1339,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leo-input"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
dependencies = [
|
||||
"from-pest",
|
||||
"pest",
|
||||
@ -1346,8 +1351,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leo-lang"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
dependencies = [
|
||||
"ansi_term 0.12.1",
|
||||
"anyhow",
|
||||
"clap",
|
||||
"colored",
|
||||
@ -1385,11 +1391,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leo-linter"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[[package]]
|
||||
name = "leo-package"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"serde",
|
||||
@ -1402,7 +1408,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leo-parser"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
dependencies = [
|
||||
"criterion",
|
||||
"indexmap",
|
||||
@ -1410,6 +1416,7 @@ dependencies = [
|
||||
"leo-ast",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"tendril",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
@ -1417,7 +1424,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leo-state"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"leo-ast",
|
||||
@ -1435,7 +1442,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leo-synthesizer"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"serde",
|
||||
@ -1499,6 +1506,12 @@ dependencies = [
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.2"
|
||||
@ -2253,9 +2266,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.2"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf12057f289428dbf5c591c74bf10392e4a8003f993405a902f20117019022d4"
|
||||
checksum = "2296f2fac53979e8ccbc4a1136b25dcefd37be9ed7e4a1f6b05a6029c84ff124"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bytes",
|
||||
@ -2509,6 +2522,18 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.8.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15654ed4ab61726bf918a39cb8d98a2e2995b002387807fa6ba58fdf7f59bb23"
|
||||
dependencies = [
|
||||
"dtoa",
|
||||
"linked-hash-map",
|
||||
"serde",
|
||||
"yaml-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha-1"
|
||||
version = "0.8.2"
|
||||
@ -3422,6 +3447,15 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
|
||||
dependencies = [
|
||||
"linked-hash-map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "0.5.10"
|
||||
|
32
Cargo.toml
32
Cargo.toml
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leo-lang"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||
description = "The Leo programming language"
|
||||
homepage = "https://aleo.org"
|
||||
@ -27,6 +27,7 @@ path = "leo/main.rs"
|
||||
[workspace]
|
||||
members = [
|
||||
"asg",
|
||||
"asg-passes",
|
||||
"ast",
|
||||
"compiler",
|
||||
"grammar",
|
||||
@ -36,41 +37,39 @@ members = [
|
||||
"package",
|
||||
"parser",
|
||||
"state",
|
||||
"synthesizer",
|
||||
"asg-passes",
|
||||
"synthesizer"
|
||||
]
|
||||
|
||||
[dependencies.leo-ast]
|
||||
path = "./ast"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.leo-compiler]
|
||||
path = "./compiler"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.leo-imports]
|
||||
path = "./imports"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.leo-input]
|
||||
path = "./input"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.leo-package]
|
||||
path = "./package"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.leo-state]
|
||||
path = "./state"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.leo-synthesizer]
|
||||
path = "./synthesizer"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.snarkvm-algorithms]
|
||||
version = "0.2.2"
|
||||
#default-features = false
|
||||
|
||||
[dependencies.snarkvm-curves]
|
||||
version = "0.2.2"
|
||||
@ -121,7 +120,7 @@ version = "0.8"
|
||||
version = "0.6.2"
|
||||
|
||||
[dependencies.reqwest]
|
||||
version = "0.11.2"
|
||||
version = "0.11.3"
|
||||
features = [ "blocking", "json", "multipart" ]
|
||||
|
||||
[dependencies.self_update]
|
||||
@ -151,14 +150,17 @@ features = [ "fmt" ]
|
||||
[dependencies.zip]
|
||||
version = "0.5"
|
||||
|
||||
# add ansi support for Windows builds
|
||||
[target.'cfg(windows)'.dependencies.ansi_term]
|
||||
version = "0.12.1"
|
||||
|
||||
[dev-dependencies.rusty-hook]
|
||||
version = "0.11.2"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
default = [ ]
|
||||
ci_skip = [ "leo-compiler/ci_skip" ]
|
||||
# This feature flag is used to disable `target-cpu=native` in `.cargo/config`.
|
||||
noconfig = []
|
||||
noconfig = [ ]
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leo-asg-passes"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||
description = "The Leo programming language"
|
||||
homepage = "https://aleo.org"
|
||||
@ -13,7 +13,7 @@ keywords = [
|
||||
"zero-knowledge"
|
||||
]
|
||||
categories = [ "cryptography::cryptocurrencies", "web-programming" ]
|
||||
include = [ "Cargo.toml", "leo", "README.md", "LICENSE.md" ]
|
||||
include = [ "Cargo.toml", "src", "README.md", "LICENSE.md" ]
|
||||
license = "GPL-3.0"
|
||||
edition = "2018"
|
||||
|
||||
@ -22,4 +22,4 @@ path = "src/lib.rs"
|
||||
|
||||
[dependencies.leo-asg]
|
||||
path = "../asg"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leo-asg"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||
description = "ASG of the Leo programming language"
|
||||
homepage = "https://aleo.org"
|
||||
@ -30,11 +30,11 @@ version = "1.6"
|
||||
version = "1.0"
|
||||
|
||||
[dependencies.leo-ast]
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
path = "../ast"
|
||||
|
||||
[dependencies.leo-parser]
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
path = "../parser"
|
||||
|
||||
[dependencies.num-bigint]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leo-ast"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||
description = "Core AST of the Leo programming language"
|
||||
homepage = "https://aleo.org"
|
||||
@ -19,7 +19,7 @@ edition = "2018"
|
||||
|
||||
[dependencies.leo-input]
|
||||
path = "../input"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.indexmap]
|
||||
version = "1.6.2"
|
||||
@ -30,7 +30,7 @@ version = "2.0"
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
features = ["derive", "rc"]
|
||||
features = [ "derive", "rc" ]
|
||||
|
||||
[dependencies.serde_json]
|
||||
version = "1.0"
|
||||
|
@ -75,7 +75,7 @@ fn underline(mut start: usize, mut end: usize) -> String {
|
||||
|
||||
impl fmt::Display for FormattedError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let underline = underline(self.col_start - 1, self.col_stop - 1);
|
||||
let underline = underline(self.col_start, self.col_stop);
|
||||
|
||||
write!(
|
||||
f,
|
||||
@ -99,7 +99,7 @@ impl fmt::Display for FormattedError {
|
||||
|
||||
write!(
|
||||
f,
|
||||
"{indent } | {underline}\n\
|
||||
"{indent } |{underline}\n\
|
||||
{indent } |\n\
|
||||
{indent } = {message}",
|
||||
indent = INDENT,
|
||||
@ -121,8 +121,8 @@ fn test_error() {
|
||||
path: std::sync::Arc::new("file.leo".to_string()),
|
||||
line_start: 2,
|
||||
line_stop: 2,
|
||||
col_start: 8,
|
||||
col_stop: 9,
|
||||
col_start: 9,
|
||||
col_stop: 10,
|
||||
content: "let a = x;".into(),
|
||||
message: "undefined value `x`".to_string(),
|
||||
};
|
||||
@ -130,7 +130,7 @@ fn test_error() {
|
||||
assert_eq!(
|
||||
err.to_string(),
|
||||
vec![
|
||||
" --> file.leo: 2:8",
|
||||
" --> file.leo: 2:9",
|
||||
" |",
|
||||
" 2 | let a = x;",
|
||||
" | ^",
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leo-compiler"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||
description = "Compiler of the Leo programming language"
|
||||
homepage = "https://aleo.org"
|
||||
@ -19,35 +19,35 @@ edition = "2018"
|
||||
|
||||
[dependencies.leo-ast]
|
||||
path = "../ast"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.leo-imports]
|
||||
path = "../imports"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.leo-input]
|
||||
path = "../input"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.leo-package]
|
||||
path = "../package"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.leo-state]
|
||||
path = "../state"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.leo-asg]
|
||||
path = "../asg"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.leo-parser]
|
||||
path = "../parser"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.leo-asg-passes]
|
||||
path = "../asg-passes"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.tendril]
|
||||
version = "0.4"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,11 @@
|
||||
circuit Foo {
|
||||
f: u8,
|
||||
y: (u8, u8),
|
||||
|
||||
function z (mut self) -> u16 {
|
||||
self.y.0 += 1u8;
|
||||
return 1u16
|
||||
}
|
||||
}
|
||||
function main() {
|
||||
let x = 10u32;
|
||||
@ -14,11 +20,18 @@ function main() {
|
||||
z.1 += 3u8;
|
||||
console.assert(z.1 == 5u8);
|
||||
|
||||
let foo = Foo { f: 6u8 };
|
||||
let foo = Foo { f: 6u8, y: (1u8, 1u8) };
|
||||
foo.f += 2u8;
|
||||
console.assert(foo.f == 8u8);
|
||||
|
||||
let complex = 2u8;
|
||||
complex += 22u8 - 2u8+ 1u8;
|
||||
console.assert(complex == 23u8);
|
||||
let a = [[0u8; 1]; 4];
|
||||
a[2][0] += 1u8;
|
||||
console.assert(a[2][0] == 1u8);
|
||||
|
||||
let b = [0u8; (4, 1)];
|
||||
b[2][0] += 1u8;
|
||||
console.assert(a[2][0] == 1u8);
|
||||
}
|
@ -1,17 +1,21 @@
|
||||
[package]
|
||||
name = "leo-abnf"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||
description = "ABNF to Markdown converter"
|
||||
edition = "2018"
|
||||
description = "ABNF to Markdown converter for the Leo programming language"
|
||||
homepage = "https://aleo.org"
|
||||
repository = "https://github.com/AleoHQ/leo"
|
||||
keywords = [
|
||||
"aleo",
|
||||
"cryptography",
|
||||
"leo",
|
||||
"programming-language",
|
||||
"zero-knowledge",
|
||||
"leo-abnf"
|
||||
"zero-knowledge"
|
||||
]
|
||||
categories = [ "cryptography::cryptocurrencies", "web-programming" ]
|
||||
include = [ "Cargo.toml", "src", "README.md", "LICENSE.md" ]
|
||||
license = "GPL-3.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
abnf = "0.10.2"
|
||||
|
@ -475,7 +475,7 @@ Line terminators form whitespace, along with spaces and horizontal tabs.
|
||||
whitespace = space / horizontal-tab / newline
|
||||
```
|
||||
|
||||
Go to: _[space](#user-content-space), [horizontal-tab](#user-content-horizontal-tab), [newline](#user-content-newline)_;
|
||||
Go to: _[horizontal-tab](#user-content-horizontal-tab), [space](#user-content-space), [newline](#user-content-newline)_;
|
||||
|
||||
|
||||
There are two kinds of comments in Leo, as in other languages.
|
||||
@ -510,7 +510,7 @@ rest-of-block-comment = "*" rest-of-block-comment-after-star
|
||||
/ not-star rest-of-block-comment
|
||||
```
|
||||
|
||||
Go to: _[rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star), [not-star](#user-content-not-star), [rest-of-block-comment](#user-content-rest-of-block-comment)_;
|
||||
Go to: _[not-star](#user-content-not-star), [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="rest-of-block-comment-after-star"></a>
|
||||
@ -520,7 +520,7 @@ rest-of-block-comment-after-star = "/"
|
||||
/ not-star-or-slash rest-of-block-comment
|
||||
```
|
||||
|
||||
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-or-slash](#user-content-not-star-or-slash)_;
|
||||
Go to: _[rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star), [not-star-or-slash](#user-content-not-star-or-slash), [rest-of-block-comment](#user-content-rest-of-block-comment)_;
|
||||
|
||||
|
||||
<a name="end-of-line-comment"></a>
|
||||
@ -595,7 +595,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,
|
||||
@ -807,7 +807,7 @@ atomic-literal = untyped-literal
|
||||
/ address-literal
|
||||
```
|
||||
|
||||
Go to: _[signed-literal](#user-content-signed-literal), [field-literal](#user-content-field-literal), [boolean-literal](#user-content-boolean-literal), [untyped-literal](#user-content-untyped-literal), [unsigned-literal](#user-content-unsigned-literal), [product-group-literal](#user-content-product-group-literal), [address-literal](#user-content-address-literal)_;
|
||||
Go to: _[boolean-literal](#user-content-boolean-literal), [address-literal](#user-content-address-literal), [untyped-literal](#user-content-untyped-literal), [unsigned-literal](#user-content-unsigned-literal), [field-literal](#user-content-field-literal), [product-group-literal](#user-content-product-group-literal), [signed-literal](#user-content-signed-literal)_;
|
||||
|
||||
|
||||
After defining the (mostly) alphanumeric tokens above,
|
||||
@ -880,7 +880,7 @@ token = keyword
|
||||
/ symbol
|
||||
```
|
||||
|
||||
Go to: _[atomic-literal](#user-content-atomic-literal), [package-name](#user-content-package-name), [formatted-string](#user-content-formatted-string), [annotation-name](#user-content-annotation-name), [symbol](#user-content-symbol), [identifier](#user-content-identifier), [keyword](#user-content-keyword)_;
|
||||
Go to: _[identifier](#user-content-identifier), [keyword](#user-content-keyword), [package-name](#user-content-package-name), [formatted-string](#user-content-formatted-string), [atomic-literal](#user-content-atomic-literal), [annotation-name](#user-content-annotation-name), [symbol](#user-content-symbol)_;
|
||||
|
||||
|
||||
|
||||
@ -916,7 +916,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,
|
||||
@ -937,7 +937,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,
|
||||
@ -958,7 +958,7 @@ address-type = %s"address"
|
||||
scalar-type = boolean-type / arithmetic-type / address-type
|
||||
```
|
||||
|
||||
Go to: _[boolean-type](#user-content-boolean-type), [address-type](#user-content-address-type), [arithmetic-type](#user-content-arithmetic-type)_;
|
||||
Go to: _[arithmetic-type](#user-content-arithmetic-type), [address-type](#user-content-address-type), [boolean-type](#user-content-boolean-type)_;
|
||||
|
||||
|
||||
Circuit types are denoted by identifiers and the keyword 'Self'.
|
||||
@ -998,7 +998,7 @@ or a tuple of one or more dimensions.
|
||||
array-type = "[" type ";" array-dimensions "]"
|
||||
```
|
||||
|
||||
Go to: _[type](#user-content-type), [array-dimensions](#user-content-array-dimensions)_;
|
||||
Go to: _[array-dimensions](#user-content-array-dimensions), [type](#user-content-type)_;
|
||||
|
||||
|
||||
<a name="array-dimensions"></a>
|
||||
@ -1019,7 +1019,7 @@ i.e. types whose values contain (sub-)values
|
||||
aggregate-type = tuple-type / array-type / circuit-type
|
||||
```
|
||||
|
||||
Go to: _[array-type](#user-content-array-type), [tuple-type](#user-content-tuple-type), [circuit-type](#user-content-circuit-type)_;
|
||||
Go to: _[array-type](#user-content-array-type), [circuit-type](#user-content-circuit-type), [tuple-type](#user-content-tuple-type)_;
|
||||
|
||||
|
||||
Scalar and aggregate types form all the types.
|
||||
@ -1107,7 +1107,7 @@ primary-expression = identifier
|
||||
/ circuit-expression
|
||||
```
|
||||
|
||||
Go to: _[identifier](#user-content-identifier), [array-expression](#user-content-array-expression), [circuit-expression](#user-content-circuit-expression), [literal](#user-content-literal), [tuple-expression](#user-content-tuple-expression), [expression](#user-content-expression)_;
|
||||
Go to: _[tuple-expression](#user-content-tuple-expression), [identifier](#user-content-identifier), [expression](#user-content-expression), [literal](#user-content-literal), [array-expression](#user-content-array-expression), [circuit-expression](#user-content-circuit-expression)_;
|
||||
|
||||
|
||||
Tuple expressions construct tuples.
|
||||
@ -1168,7 +1168,7 @@ Go to: _[expression](#user-content-expression), [array-dimensions](#user-content
|
||||
array-construction = array-inline-construction / array-repeat-construction
|
||||
```
|
||||
|
||||
Go to: _[array-inline-construction](#user-content-array-inline-construction), [array-repeat-construction](#user-content-array-repeat-construction)_;
|
||||
Go to: _[array-repeat-construction](#user-content-array-repeat-construction), [array-inline-construction](#user-content-array-inline-construction)_;
|
||||
|
||||
|
||||
<a name="array-expression"></a>
|
||||
@ -1254,7 +1254,7 @@ postfix-expression = primary-expression
|
||||
/ postfix-expression "[" [expression] ".." [expression] "]"
|
||||
```
|
||||
|
||||
Go to: _[natural](#user-content-natural), [identifier](#user-content-identifier), [circuit-type](#user-content-circuit-type), [postfix-expression](#user-content-postfix-expression), [primary-expression](#user-content-primary-expression), [function-arguments](#user-content-function-arguments), [expression](#user-content-expression)_;
|
||||
Go to: _[function-arguments](#user-content-function-arguments), [expression](#user-content-expression), [natural](#user-content-natural), [circuit-type](#user-content-circuit-type), [primary-expression](#user-content-primary-expression), [identifier](#user-content-identifier), [postfix-expression](#user-content-postfix-expression)_;
|
||||
|
||||
|
||||
Unary operators have the highest operator precedence.
|
||||
@ -1268,7 +1268,7 @@ unary-expression = postfix-expression
|
||||
/ "-" unary-expression
|
||||
```
|
||||
|
||||
Go to: _[unary-expression](#user-content-unary-expression), [postfix-expression](#user-content-postfix-expression)_;
|
||||
Go to: _[postfix-expression](#user-content-postfix-expression), [unary-expression](#user-content-unary-expression)_;
|
||||
|
||||
|
||||
Next in the operator precedence is casting.
|
||||
@ -1290,10 +1290,10 @@ i.e. 'a ** b ** c' must be parsed as '(a ** b) ** c'.
|
||||
<a name="exponential-expression"></a>
|
||||
```abnf
|
||||
exponential-expression = cast-expression
|
||||
/ exponential-expression "**" cast-expression
|
||||
/ cast-expression "**" exponential-expression
|
||||
```
|
||||
|
||||
Go to: _[cast-expression](#user-content-cast-expression), [exponential-expression](#user-content-exponential-expression)_;
|
||||
Go to: _[exponential-expression](#user-content-exponential-expression), [cast-expression](#user-content-cast-expression)_;
|
||||
|
||||
|
||||
Next in precedence come multiplication and division, both left-associative.
|
||||
@ -1317,7 +1317,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.
|
||||
@ -1345,7 +1345,7 @@ equality-expression = ordering-expression
|
||||
/ equality-expression "!=" ordering-expression
|
||||
```
|
||||
|
||||
Go to: _[ordering-expression](#user-content-ordering-expression), [equality-expression](#user-content-equality-expression)_;
|
||||
Go to: _[equality-expression](#user-content-equality-expression), [ordering-expression](#user-content-ordering-expression)_;
|
||||
|
||||
|
||||
Next come conjunctive expressions, left-associative.
|
||||
@ -1356,7 +1356,7 @@ conjunctive-expression = equality-expression
|
||||
/ conjunctive-expression "&&" equality-expression
|
||||
```
|
||||
|
||||
Go to: _[equality-expression](#user-content-equality-expression), [conjunctive-expression](#user-content-conjunctive-expression)_;
|
||||
Go to: _[conjunctive-expression](#user-content-conjunctive-expression), [equality-expression](#user-content-equality-expression)_;
|
||||
|
||||
|
||||
Next come disjunctive expressions, left-associative.
|
||||
@ -1367,7 +1367,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.
|
||||
@ -1380,7 +1380,7 @@ conditional-expression = disjunctive-expression
|
||||
":" conditional-expression
|
||||
```
|
||||
|
||||
Go to: _[disjunctive-expression](#user-content-disjunctive-expression), [conditional-expression](#user-content-conditional-expression), [expression](#user-content-expression)_;
|
||||
Go to: _[conditional-expression](#user-content-conditional-expression), [disjunctive-expression](#user-content-disjunctive-expression), [expression](#user-content-expression)_;
|
||||
|
||||
|
||||
Those above are all the expressions.
|
||||
@ -1412,7 +1412,7 @@ statement = expression-statement
|
||||
/ block
|
||||
```
|
||||
|
||||
Go to: _[variable-definition-statement](#user-content-variable-definition-statement), [return-statement](#user-content-return-statement), [loop-statement](#user-content-loop-statement), [block](#user-content-block), [console-statement](#user-content-console-statement), [conditional-statement](#user-content-conditional-statement), [expression-statement](#user-content-expression-statement), [assignment-statement](#user-content-assignment-statement)_;
|
||||
Go to: _[expression-statement](#user-content-expression-statement), [conditional-statement](#user-content-conditional-statement), [loop-statement](#user-content-loop-statement), [console-statement](#user-content-console-statement), [variable-definition-statement](#user-content-variable-definition-statement), [assignment-statement](#user-content-assignment-statement), [block](#user-content-block), [return-statement](#user-content-return-statement)_;
|
||||
|
||||
|
||||
<a name="block"></a>
|
||||
@ -1455,7 +1455,7 @@ variable-definition-statement = ( %s"let" / %s"const" )
|
||||
[ ":" type ] "=" expression ";"
|
||||
```
|
||||
|
||||
Go to: _[type](#user-content-type), [expression](#user-content-expression), [identifier-or-identifiers](#user-content-identifier-or-identifiers)_;
|
||||
Go to: _[expression](#user-content-expression), [identifier-or-identifiers](#user-content-identifier-or-identifiers), [type](#user-content-type)_;
|
||||
|
||||
|
||||
<a name="identifier-or-identifiers"></a>
|
||||
@ -1478,7 +1478,7 @@ Note that blocks are required in all branches, not merely statements.
|
||||
branch = %s"if" expression block
|
||||
```
|
||||
|
||||
Go to: _[block](#user-content-block), [expression](#user-content-expression)_;
|
||||
Go to: _[expression](#user-content-expression), [block](#user-content-block)_;
|
||||
|
||||
|
||||
<a name="conditional-statement"></a>
|
||||
@ -1488,7 +1488,7 @@ conditional-statement = branch
|
||||
/ branch %s"else" conditional-statement
|
||||
```
|
||||
|
||||
Go to: _[conditional-statement](#user-content-conditional-statement), [block](#user-content-block), [branch](#user-content-branch)_;
|
||||
Go to: _[branch](#user-content-branch), [conditional-statement](#user-content-conditional-statement), [block](#user-content-block)_;
|
||||
|
||||
|
||||
A loop statement implicitly defines a loop variable
|
||||
@ -1500,7 +1500,7 @@ The body is a block.
|
||||
loop-statement = %s"for" identifier %s"in" expression ".." expression block
|
||||
```
|
||||
|
||||
Go to: _[expression](#user-content-expression), [block](#user-content-block), [identifier](#user-content-identifier)_;
|
||||
Go to: _[identifier](#user-content-identifier), [block](#user-content-block), [expression](#user-content-expression)_;
|
||||
|
||||
|
||||
An assignment statement is straightforward.
|
||||
@ -1517,7 +1517,7 @@ assignment-operator = "=" / "+=" / "-=" / "*=" / "/=" / "**="
|
||||
assignment-statement = expression assignment-operator expression ";"
|
||||
```
|
||||
|
||||
Go to: _[expression](#user-content-expression), [assignment-operator](#user-content-assignment-operator)_;
|
||||
Go to: _[assignment-operator](#user-content-assignment-operator), [expression](#user-content-expression)_;
|
||||
|
||||
|
||||
Console statements start with the 'console' keyword,
|
||||
@ -1544,7 +1544,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>
|
||||
@ -1586,7 +1586,7 @@ annotation = annotation-name
|
||||
[ "(" identifier *( "," identifier ) ")" ]
|
||||
```
|
||||
|
||||
Go to: _[annotation-name](#user-content-annotation-name), [identifier](#user-content-identifier)_;
|
||||
Go to: _[identifier](#user-content-identifier), [annotation-name](#user-content-annotation-name)_;
|
||||
|
||||
|
||||
A function declaration defines a function.
|
||||
@ -1604,7 +1604,7 @@ function-declaration = *annotation %s"function" identifier
|
||||
block
|
||||
```
|
||||
|
||||
Go to: _[type](#user-content-type), [function-parameters](#user-content-function-parameters), [block](#user-content-block), [identifier](#user-content-identifier)_;
|
||||
Go to: _[function-parameters](#user-content-function-parameters), [identifier](#user-content-identifier), [block](#user-content-block), [type](#user-content-type)_;
|
||||
|
||||
|
||||
<a name="function-parameters"></a>
|
||||
@ -1661,7 +1661,7 @@ Go to: _[member-variable-declaration](#user-content-member-variable-declaration)
|
||||
member-variable-declaration = identifier ":" type
|
||||
```
|
||||
|
||||
Go to: _[type](#user-content-type), [identifier](#user-content-identifier)_;
|
||||
Go to: _[identifier](#user-content-identifier), [type](#user-content-type)_;
|
||||
|
||||
|
||||
<a name="member-function-declaration"></a>
|
||||
@ -1710,7 +1710,7 @@ package-path = "*"
|
||||
/ "(" package-path *( "," package-path ) [","] ")"
|
||||
```
|
||||
|
||||
Go to: _[package-path](#user-content-package-path), [identifier](#user-content-identifier), [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.
|
||||
@ -1722,7 +1722,7 @@ declaration = import-declaration
|
||||
/ circuit-declaration
|
||||
```
|
||||
|
||||
Go to: _[import-declaration](#user-content-import-declaration), [circuit-declaration](#user-content-circuit-declaration), [function-declaration](#user-content-function-declaration)_;
|
||||
Go to: _[circuit-declaration](#user-content-circuit-declaration), [import-declaration](#user-content-import-declaration), [function-declaration](#user-content-function-declaration)_;
|
||||
|
||||
|
||||
<a name="file"></a>
|
||||
|
@ -813,7 +813,7 @@ cast-expression = unary-expression
|
||||
; i.e. 'a ** b ** c' must be parsed as '(a ** b) ** c'.
|
||||
|
||||
exponential-expression = cast-expression
|
||||
/ exponential-expression "**" cast-expression
|
||||
/ cast-expression "**" exponential-expression
|
||||
|
||||
; Next in precedence come multiplication and division, both left-associative.
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leo-imports"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||
description = "Import parser for Leo program package dependencies"
|
||||
homepage = "https://aleo.org"
|
||||
@ -19,15 +19,15 @@ edition = "2018"
|
||||
|
||||
[dependencies.leo-ast]
|
||||
path = "../ast"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.leo-asg]
|
||||
path = "../asg"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.leo-parser]
|
||||
path = "../parser"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.indexmap]
|
||||
version = "1.6.2"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leo-input"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||
description = "Input parser of the Leo programming language"
|
||||
homepage = "https://aleo.org"
|
||||
|
@ -202,6 +202,10 @@ where
|
||||
|
||||
/// Initialize logger with custom format and verbosity.
|
||||
pub fn init_logger(_app_name: &'static str, verbosity: usize) {
|
||||
// This line enables Windows 10 ANSI coloring API.
|
||||
#[cfg(target_family = "windows")]
|
||||
ansi_term::enable_ansi_support();
|
||||
|
||||
let subscriber = FmtSubscriber::builder()
|
||||
// all spans/events with a level higher than TRACE (e.g, debug, info, warn, etc.)
|
||||
// will be written to stdout.
|
||||
|
@ -2,7 +2,7 @@ dependencies = { }
|
||||
|
||||
[package]
|
||||
name = "leo-linter"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||
description = "Linter of the Leo programming language"
|
||||
homepage = "https://aleo.org"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leo-package"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||
description = "Package parser of the Leo programming language"
|
||||
homepage = "https://aleo.org"
|
||||
|
@ -106,7 +106,8 @@ impl ZipFile {
|
||||
// Write file or directory
|
||||
if path.is_file() {
|
||||
tracing::info!("Adding file {:?} as {:?}", path, name);
|
||||
zip.start_file(name.to_string_lossy(), options)?;
|
||||
#[allow(deprecated)]
|
||||
zip.start_file_from_path(name, options)?;
|
||||
let mut f = File::open(path)?;
|
||||
|
||||
f.read_to_end(&mut buffer)?;
|
||||
@ -116,7 +117,8 @@ impl ZipFile {
|
||||
// Only if not root Avoids path spec / warning
|
||||
// and mapname conversion failed error on unzip
|
||||
tracing::info!("Adding directory {:?} as {:?}", path, name);
|
||||
zip.add_directory(name.to_string_lossy(), options)?;
|
||||
#[allow(deprecated)]
|
||||
zip.add_directory_from_path(name, options)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leo-parser"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||
description = "AST generated by pest from the Leo grammar rules"
|
||||
homepage = "https://aleo.org"
|
||||
@ -24,7 +24,7 @@ harness = false
|
||||
|
||||
[dependencies.leo-ast]
|
||||
path = "../ast"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.lazy_static]
|
||||
version = "1.3.0"
|
||||
@ -42,15 +42,18 @@ version = "1.0"
|
||||
[dependencies.tracing]
|
||||
version = "0.1"
|
||||
|
||||
[dev-dependencies.criterion]
|
||||
version = "0.3"
|
||||
|
||||
[dependencies.indexmap]
|
||||
version = "1.6"
|
||||
|
||||
[dependencies.tendril]
|
||||
version = "0.4"
|
||||
|
||||
[dev-dependencies.criterion]
|
||||
version = "0.3"
|
||||
|
||||
[dev-dependencies.serde_yaml]
|
||||
version = "0.8"
|
||||
|
||||
[features]
|
||||
default = [ ]
|
||||
ci_skip = [ ]
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
use leo_ast::{FormattedError, LeoError, Span};
|
||||
|
||||
use crate::{DeprecatedError, Token, TokenError};
|
||||
use crate::{DeprecatedError, SyntaxResult, Token, TokenError};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SyntaxError {
|
||||
@ -32,6 +32,17 @@ pub enum SyntaxError {
|
||||
|
||||
impl LeoError for SyntaxError {}
|
||||
|
||||
pub fn assert_no_whitespace(left_span: &Span, right_span: &Span, left: &str, right: &str) -> SyntaxResult<()> {
|
||||
if left_span.col_stop != right_span.col_start {
|
||||
let mut error_span = left_span + right_span;
|
||||
error_span.col_start = left_span.col_stop - 1;
|
||||
error_span.col_stop = right_span.col_start - 1;
|
||||
return Err(SyntaxError::unexpected_whitespace(left, right, &error_span));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl SyntaxError {
|
||||
fn new_from_span(message: String, span: &Span) -> Self {
|
||||
SyntaxError::Error(FormattedError::new_from_span(message, span))
|
||||
|
@ -14,9 +14,9 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use std::unimplemented;
|
||||
use std::{borrow::Cow, unimplemented};
|
||||
|
||||
use crate::{tokenizer::*, unexpected_whitespace, SyntaxError, SyntaxResult, Token, KEYWORD_TOKENS};
|
||||
use crate::{assert_no_whitespace, tokenizer::*, SyntaxError, SyntaxResult, Token, KEYWORD_TOKENS};
|
||||
use leo_ast::*;
|
||||
use tendril::format_tendril;
|
||||
|
||||
@ -49,7 +49,11 @@ impl ParserContext {
|
||||
.filter(|x| !matches!(x.token, Token::CommentLine(_) | Token::CommentBlock(_)))
|
||||
.collect();
|
||||
ParserContext {
|
||||
end_span: tokens.last().map(|x| x.span.clone()).unwrap_or_default(),
|
||||
end_span: tokens
|
||||
.iter()
|
||||
.find(|x| !x.span.content.trim().is_empty())
|
||||
.map(|x| x.span.clone())
|
||||
.unwrap_or_default(),
|
||||
tokens,
|
||||
fuzzy_struct_state: false,
|
||||
}
|
||||
@ -69,6 +73,14 @@ impl ParserContext {
|
||||
self.tokens.last().ok_or_else(|| self.eof())
|
||||
}
|
||||
|
||||
pub fn peek_token(&self) -> Cow<'_, Token> {
|
||||
self.tokens
|
||||
.last()
|
||||
.map(|x| &x.token)
|
||||
.map(Cow::Borrowed)
|
||||
.unwrap_or_else(|| Cow::Owned(Token::Eof))
|
||||
}
|
||||
|
||||
// pub fn peek_oneof(&self, token: &[Token]) -> SyntaxResult<&SpannedToken> {
|
||||
// if let Some(spanned_token) = self.inner.last() {
|
||||
// if token.iter().any(|x| x == &spanned_token.token) {
|
||||
@ -140,15 +152,21 @@ impl ParserContext {
|
||||
/// the next token is not a [`GroupCoordinate`].
|
||||
///
|
||||
fn peek_group_coordinate(&self, i: &mut usize) -> Option<GroupCoordinate> {
|
||||
let token = self.tokens.get(*i)?;
|
||||
if *i < 1 {
|
||||
return None;
|
||||
}
|
||||
let token = self.tokens.get(*i - 1)?;
|
||||
*i -= 1;
|
||||
Some(match &token.token {
|
||||
Token::Add => GroupCoordinate::SignHigh,
|
||||
Token::Minus => match self.tokens.get(*i) {
|
||||
Token::Minus if *i > 0 => match self.tokens.get(*i - 1) {
|
||||
Some(SpannedToken {
|
||||
token: Token::Int(value),
|
||||
span,
|
||||
}) => {
|
||||
if *i < 1 {
|
||||
return None;
|
||||
}
|
||||
*i -= 1;
|
||||
GroupCoordinate::Number(format_tendril!("-{}", value), span.clone())
|
||||
}
|
||||
@ -164,32 +182,32 @@ impl ParserContext {
|
||||
/// Removes the next two tokens if they are a pair of [`GroupCoordinate`] and returns them,
|
||||
/// or [None] if the next token is not a [`GroupCoordinate`].
|
||||
///
|
||||
pub fn eat_group_partial(&mut self) -> SyntaxResult<Option<(GroupCoordinate, GroupCoordinate, Span)>> {
|
||||
let mut i = self.tokens.len() - 1;
|
||||
let start_span = match self.tokens.get(i) {
|
||||
Some(span) => span.span.clone(),
|
||||
None => return Ok(None),
|
||||
};
|
||||
let first = match self.peek_group_coordinate(&mut i) {
|
||||
Some(coord) => coord,
|
||||
None => return Ok(None),
|
||||
};
|
||||
match self.tokens.get(i) {
|
||||
pub fn eat_group_partial(&mut self) -> Option<SyntaxResult<(GroupCoordinate, GroupCoordinate, Span)>> {
|
||||
let mut i = self.tokens.len();
|
||||
if i < 1 {
|
||||
return None;
|
||||
}
|
||||
let start_span = self.tokens.get(i - 1)?.span.clone();
|
||||
let first = self.peek_group_coordinate(&mut i)?;
|
||||
if i < 1 {
|
||||
return None;
|
||||
}
|
||||
match self.tokens.get(i - 1) {
|
||||
Some(SpannedToken {
|
||||
token: Token::Comma, ..
|
||||
}) => {
|
||||
i -= 1;
|
||||
}
|
||||
_ => {
|
||||
return Ok(None);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
let second = match self.peek_group_coordinate(&mut i) {
|
||||
Some(coord) => coord,
|
||||
None => return Ok(None),
|
||||
};
|
||||
let second = self.peek_group_coordinate(&mut i)?;
|
||||
if i < 1 {
|
||||
return None;
|
||||
}
|
||||
let right_paren_span;
|
||||
match self.tokens.get(i) {
|
||||
match self.tokens.get(i - 1) {
|
||||
Some(SpannedToken {
|
||||
token: Token::RightParen,
|
||||
span,
|
||||
@ -198,11 +216,14 @@ impl ParserContext {
|
||||
i -= 1;
|
||||
}
|
||||
_ => {
|
||||
return Ok(None);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
if i < 1 {
|
||||
return None;
|
||||
}
|
||||
let end_span;
|
||||
match self.tokens.get(i) {
|
||||
match self.tokens.get(i - 1) {
|
||||
Some(SpannedToken {
|
||||
token: Token::Group,
|
||||
span,
|
||||
@ -211,18 +232,20 @@ impl ParserContext {
|
||||
i -= 1;
|
||||
}
|
||||
_ => {
|
||||
return Ok(None);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
self.tokens.drain((i + 1)..);
|
||||
unexpected_whitespace(
|
||||
self.tokens.drain(i..);
|
||||
if let Err(e) = assert_no_whitespace(
|
||||
&right_paren_span,
|
||||
&end_span,
|
||||
&format!("({},{})", first, second),
|
||||
"group",
|
||||
)?;
|
||||
Ok(Some((first, second, start_span + end_span)))
|
||||
) {
|
||||
return Some(Err(e));
|
||||
}
|
||||
Some(Ok((first, second, start_span + end_span)))
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -404,7 +404,7 @@ impl ParserContext {
|
||||
match token.token {
|
||||
Token::LeftSquare => {
|
||||
if self.eat(Token::DotDot).is_some() {
|
||||
let right = if self.peek()?.token != Token::RightSquare {
|
||||
let right = if self.peek_token().as_ref() != &Token::RightSquare {
|
||||
Some(Box::new(self.parse_expression()?))
|
||||
} else {
|
||||
None
|
||||
@ -422,7 +422,7 @@ impl ParserContext {
|
||||
|
||||
let left = self.parse_expression()?;
|
||||
if self.eat(Token::DotDot).is_some() {
|
||||
let right = if self.peek()?.token != Token::RightSquare {
|
||||
let right = if self.peek_token().as_ref() != &Token::RightSquare {
|
||||
Some(Box::new(self.parse_expression()?))
|
||||
} else {
|
||||
None
|
||||
@ -554,7 +554,7 @@ impl ParserContext {
|
||||
/// tuple initialization expression.
|
||||
///
|
||||
pub fn parse_tuple_expression(&mut self, span: &Span) -> SyntaxResult<Expression> {
|
||||
if let Some((left, right, span)) = self.eat_group_partial()? {
|
||||
if let Some((left, right, span)) = self.eat_group_partial().transpose()? {
|
||||
return Ok(Expression::Value(ValueExpression::Group(Box::new(GroupValue::Tuple(
|
||||
GroupTuple {
|
||||
span,
|
||||
@ -625,6 +625,10 @@ impl ParserContext {
|
||||
}
|
||||
if elements.len() == 1 {
|
||||
self.expect(Token::Comma)?;
|
||||
if let Some(token) = self.eat(Token::RightSquare) {
|
||||
end_span = token.span;
|
||||
break;
|
||||
}
|
||||
}
|
||||
elements.push(self.parse_spread_or_expression()?);
|
||||
if self.eat(Token::Comma).is_none() {
|
||||
@ -658,21 +662,21 @@ impl ParserContext {
|
||||
token: Token::Field,
|
||||
span: type_span,
|
||||
}) => {
|
||||
unexpected_whitespace(&span, &type_span, &value, "field")?;
|
||||
assert_no_whitespace(&span, &type_span, &value, "field")?;
|
||||
Expression::Value(ValueExpression::Field(value, span + type_span))
|
||||
}
|
||||
Some(SpannedToken {
|
||||
token: Token::Group,
|
||||
span: type_span,
|
||||
}) => {
|
||||
unexpected_whitespace(&span, &type_span, &value, "group")?;
|
||||
assert_no_whitespace(&span, &type_span, &value, "group")?;
|
||||
Expression::Value(ValueExpression::Group(Box::new(GroupValue::Single(
|
||||
value,
|
||||
span + type_span,
|
||||
))))
|
||||
}
|
||||
Some(SpannedToken { token, span: type_span }) => {
|
||||
unexpected_whitespace(&span, &type_span, &value, &token.to_string())?;
|
||||
assert_no_whitespace(&span, &type_span, &value, &token.to_string())?;
|
||||
Expression::Value(ValueExpression::Integer(
|
||||
Self::token_to_int_type(token).expect("unknown int type token"),
|
||||
value,
|
||||
@ -705,7 +709,7 @@ impl ParserContext {
|
||||
Token::LeftSquare => self.parse_array_expression(&span)?,
|
||||
Token::Ident(name) => {
|
||||
let ident = Identifier { name, span };
|
||||
if !self.fuzzy_struct_state && self.peek()?.token == Token::LeftCurly {
|
||||
if !self.fuzzy_struct_state && self.peek_token().as_ref() == &Token::LeftCurly {
|
||||
self.parse_circuit_expression(ident)?
|
||||
} else {
|
||||
Expression::Identifier(ident)
|
||||
@ -716,7 +720,7 @@ impl ParserContext {
|
||||
name: token.to_string().into(),
|
||||
span,
|
||||
};
|
||||
if !self.fuzzy_struct_state && self.peek()?.token == Token::LeftCurly {
|
||||
if !self.fuzzy_struct_state && self.peek_token().as_ref() == &Token::LeftCurly {
|
||||
self.parse_circuit_expression(ident)?
|
||||
} else {
|
||||
Expression::Identifier(ident)
|
||||
|
@ -91,7 +91,7 @@ impl ParserContext {
|
||||
)));
|
||||
}
|
||||
|
||||
unexpected_whitespace(&start, &name.span, &name.name, "@")?;
|
||||
assert_no_whitespace(&start, &name.span, &name.name, "@")?;
|
||||
|
||||
let end_span;
|
||||
let arguments = if self.eat(Token::LeftParen).is_some() {
|
||||
@ -153,7 +153,7 @@ impl ParserContext {
|
||||
Ok(PackageAccess::Star(span))
|
||||
} else {
|
||||
let name = self.expect_ident()?;
|
||||
if self.peek()?.token == Token::Dot {
|
||||
if self.peek_token().as_ref() == &Token::Dot {
|
||||
self.backtrack(SpannedToken {
|
||||
token: Token::Ident(name.name),
|
||||
span: name.span,
|
||||
@ -188,7 +188,7 @@ impl ParserContext {
|
||||
|
||||
// Build the rest of the package name including dashes.
|
||||
loop {
|
||||
match &self.peek()?.token {
|
||||
match &self.peek_token().as_ref() {
|
||||
Token::Minus => {
|
||||
let span = self.expect(Token::Minus)?;
|
||||
base.span = base.span + span;
|
||||
@ -369,7 +369,7 @@ impl ParserContext {
|
||||
///
|
||||
pub fn parse_function_declaration(&mut self) -> SyntaxResult<(Identifier, Function)> {
|
||||
let mut annotations = Vec::new();
|
||||
while self.peek()?.token == Token::At {
|
||||
while self.peek_token().as_ref() == &Token::At {
|
||||
annotations.push(self.parse_annotation()?);
|
||||
}
|
||||
let start = self.expect(Token::Function)?;
|
||||
|
@ -20,16 +20,16 @@
|
||||
//! method to create a new program ast.
|
||||
|
||||
mod context;
|
||||
use context::*;
|
||||
pub use context::*;
|
||||
|
||||
mod expression;
|
||||
mod file;
|
||||
mod statement;
|
||||
mod type_;
|
||||
pub mod expression;
|
||||
pub mod file;
|
||||
pub mod statement;
|
||||
pub mod type_;
|
||||
|
||||
use std::unimplemented;
|
||||
|
||||
use crate::{tokenizer::*, DeprecatedError, SyntaxError, Token};
|
||||
use crate::{errors::assert_no_whitespace, tokenizer::*, DeprecatedError, SyntaxError, Token};
|
||||
use indexmap::IndexMap;
|
||||
use leo_ast::*;
|
||||
|
||||
@ -41,14 +41,3 @@ pub fn parse(path: &str, source: &str) -> SyntaxResult<Program> {
|
||||
|
||||
tokens.parse_program()
|
||||
}
|
||||
|
||||
pub fn unexpected_whitespace(left_span: &Span, right_span: &Span, left: &str, right: &str) -> SyntaxResult<()> {
|
||||
if left_span.col_stop != right_span.col_start {
|
||||
let mut error_span = left_span + right_span;
|
||||
error_span.col_start = left_span.col_stop - 1;
|
||||
error_span.col_stop = right_span.col_start - 1;
|
||||
return Err(SyntaxError::unexpected_whitespace(left, right, &error_span));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ impl ParserContext {
|
||||
pub fn parse_return_statement(&mut self) -> SyntaxResult<ReturnStatement> {
|
||||
let start = self.expect(Token::Return)?;
|
||||
let expr = self.parse_expression()?;
|
||||
self.eat(Token::Comma);
|
||||
self.eat(Token::Semicolon);
|
||||
|
||||
Ok(ReturnStatement {
|
||||
span: &start + expr.span(),
|
||||
@ -316,10 +316,17 @@ impl ParserContext {
|
||||
let mut variable_names = Vec::new();
|
||||
if self.eat(Token::LeftParen).is_some() {
|
||||
variable_names.push(self.parse_variable_name(&declare)?);
|
||||
let mut eaten_ending = false;
|
||||
while self.eat(Token::Comma).is_some() {
|
||||
if self.eat(Token::RightParen).is_some() {
|
||||
eaten_ending = true;
|
||||
break;
|
||||
}
|
||||
variable_names.push(self.parse_variable_name(&declare)?);
|
||||
}
|
||||
self.expect(Token::RightParen)?;
|
||||
if !eaten_ending {
|
||||
self.expect(Token::RightParen)?;
|
||||
}
|
||||
} else {
|
||||
variable_names.push(self.parse_variable_name(&declare)?);
|
||||
}
|
||||
|
@ -15,15 +15,69 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use std::{
|
||||
fmt,
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use crate::SyntaxError;
|
||||
use leo_ast::{Expression, ExpressionStatement, Program, Span, Statement, ValueExpression};
|
||||
use serde_yaml::Value;
|
||||
use tokenizer::Token;
|
||||
|
||||
use crate::{tokenizer, DeprecatedError, ParserContext, SyntaxError, TokenError};
|
||||
|
||||
struct TestFailure {
|
||||
path: String,
|
||||
error: SyntaxError,
|
||||
errors: Vec<TestError>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum TestError {
|
||||
UnexpectedOutput {
|
||||
index: usize,
|
||||
expected: String,
|
||||
output: String,
|
||||
},
|
||||
PassedAndShouldntHave {
|
||||
index: usize,
|
||||
},
|
||||
FailedAndShouldntHave {
|
||||
index: usize,
|
||||
error: String,
|
||||
},
|
||||
UnexpectedError {
|
||||
index: usize,
|
||||
expected: String,
|
||||
output: String,
|
||||
},
|
||||
MismatchedTestExpectationLength,
|
||||
}
|
||||
|
||||
impl fmt::Display for TestError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
TestError::UnexpectedOutput {
|
||||
index,
|
||||
expected,
|
||||
output,
|
||||
} => {
|
||||
write!(f, "test #{} expected\n{}\ngot\n{}", index + 1, expected, output)
|
||||
}
|
||||
TestError::PassedAndShouldntHave { index } => write!(f, "test #{} passed and shouldn't have", index + 1),
|
||||
TestError::FailedAndShouldntHave { index, error } => {
|
||||
write!(f, "test #{} failed and shouldn't have:\n{}", index + 1, error)
|
||||
}
|
||||
TestError::UnexpectedError {
|
||||
expected,
|
||||
output,
|
||||
index,
|
||||
} => {
|
||||
write!(f, "test #{} expected error\n{}\ngot\n{}", index + 1, expected, output)
|
||||
}
|
||||
TestError::MismatchedTestExpectationLength => write!(f, "invalid number of test expectations"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_tests<T: AsRef<Path>>(path: T, out: &mut Vec<(String, String)>) {
|
||||
@ -40,13 +94,411 @@ pub fn find_tests<T: AsRef<Path>>(path: T, out: &mut Vec<(String, String)>) {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, PartialEq, Debug, Clone)]
|
||||
enum TestNamespace {
|
||||
Parse,
|
||||
ParseStatement,
|
||||
ParseExpression,
|
||||
Token,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, PartialEq, Debug, Clone)]
|
||||
enum TestExpectationMode {
|
||||
Pass,
|
||||
Fail,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
struct TestConfig {
|
||||
namespace: TestNamespace,
|
||||
expectation: TestExpectationMode,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Clone)]
|
||||
struct TestExpectation {
|
||||
namespace: TestNamespace,
|
||||
expectation: TestExpectationMode,
|
||||
outputs: Vec<Value>,
|
||||
}
|
||||
|
||||
fn extract_test_config(source: &str) -> Option<TestConfig> {
|
||||
let first_comment_start = source.find("/*")?;
|
||||
let end_first_comment = source[first_comment_start + 2..].find("*/")?;
|
||||
let comment_inner = &source[first_comment_start + 2..first_comment_start + 2 + end_first_comment];
|
||||
Some(serde_yaml::from_str(comment_inner).expect("invalid test configuration"))
|
||||
}
|
||||
|
||||
fn split_tests_oneline(source: &str) -> Vec<&str> {
|
||||
source.lines().map(|x| x.trim()).filter(|x| !x.is_empty()).collect()
|
||||
}
|
||||
|
||||
fn split_tests_twoline(source: &str) -> Vec<String> {
|
||||
let mut out = vec![];
|
||||
let mut lines = vec![];
|
||||
for line in source.lines() {
|
||||
let line = line.trim();
|
||||
if line.is_empty() {
|
||||
if !lines.is_empty() {
|
||||
out.push(lines.join("\n"));
|
||||
}
|
||||
lines.clear();
|
||||
continue;
|
||||
}
|
||||
lines.push(line);
|
||||
}
|
||||
let last_test = lines.join("\n");
|
||||
if !last_test.trim().is_empty() {
|
||||
out.push(last_test.trim().to_string());
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fn run_individual_token_test(path: &str, source: &str) -> Result<String, String> {
|
||||
let output = tokenizer::tokenize(path, source.into());
|
||||
output
|
||||
.map(|tokens| {
|
||||
tokens
|
||||
.into_iter()
|
||||
.map(|x| x.to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join(",")
|
||||
})
|
||||
.map_err(|x| strip_path_syntax_error(x.into()))
|
||||
}
|
||||
|
||||
fn not_fully_consumed(tokens: &mut ParserContext) -> Result<(), String> {
|
||||
if !tokens.has_next() {
|
||||
return Ok(());
|
||||
}
|
||||
let mut out = "did not consume all input: ".to_string();
|
||||
while tokens.has_next() {
|
||||
out.push_str(&tokens.expect_any().unwrap().to_string());
|
||||
out.push('\n');
|
||||
}
|
||||
Err(out)
|
||||
}
|
||||
|
||||
fn run_individual_expression_test(path: &str, source: &str) -> Result<Expression, String> {
|
||||
let tokenizer = tokenizer::tokenize(path, source.into()).map_err(|x| strip_path_syntax_error(x.into()))?;
|
||||
if tokenizer
|
||||
.iter()
|
||||
.all(|x| matches!(x.token, Token::CommentLine(_) | Token::CommentBlock(_)))
|
||||
{
|
||||
return Ok(Expression::Value(ValueExpression::Implicit("".into(), Span::default())));
|
||||
}
|
||||
let mut tokens = ParserContext::new(tokenizer);
|
||||
|
||||
let parsed = tokens.parse_expression().map_err(strip_path_syntax_error)?;
|
||||
not_fully_consumed(&mut tokens)?;
|
||||
|
||||
Ok(parsed)
|
||||
}
|
||||
|
||||
fn run_individual_statement_test(path: &str, source: &str) -> Result<Statement, String> {
|
||||
let tokenizer = tokenizer::tokenize(path, source.into()).map_err(|x| strip_path_syntax_error(x.into()))?;
|
||||
if tokenizer
|
||||
.iter()
|
||||
.all(|x| matches!(x.token, Token::CommentLine(_) | Token::CommentBlock(_)))
|
||||
{
|
||||
return Ok(Statement::Expression(ExpressionStatement {
|
||||
expression: Expression::Value(ValueExpression::Implicit("".into(), Span::default())),
|
||||
span: Span::default(),
|
||||
}));
|
||||
}
|
||||
let mut tokens = ParserContext::new(tokenizer);
|
||||
|
||||
let parsed = tokens.parse_statement().map_err(strip_path_syntax_error)?;
|
||||
not_fully_consumed(&mut tokens)?;
|
||||
|
||||
Ok(parsed)
|
||||
}
|
||||
|
||||
fn strip_path_syntax_error(mut err: SyntaxError) -> String {
|
||||
let inner = match &mut err {
|
||||
SyntaxError::DeprecatedError(DeprecatedError::Error(x)) => x,
|
||||
SyntaxError::Error(x) => x,
|
||||
SyntaxError::TokenError(TokenError::Error(x)) => x,
|
||||
};
|
||||
inner.path = Arc::new("test".to_string());
|
||||
err.to_string()
|
||||
}
|
||||
|
||||
fn run_individual_parse_test(path: &str, source: &str) -> Result<Program, String> {
|
||||
let tokenizer = tokenizer::tokenize(path, source.into()).map_err(|x| strip_path_syntax_error(x.into()))?;
|
||||
let mut tokens = ParserContext::new(tokenizer);
|
||||
|
||||
let parsed = tokens.parse_program().map_err(strip_path_syntax_error)?;
|
||||
not_fully_consumed(&mut tokens)?;
|
||||
|
||||
Ok(parsed)
|
||||
}
|
||||
|
||||
fn emit_errors<T: PartialEq + ToString + serde::de::DeserializeOwned>(
|
||||
output: Result<&T, &str>,
|
||||
mode: &TestExpectationMode,
|
||||
expected_output: Option<Value>,
|
||||
test_index: usize,
|
||||
) -> Option<TestError> {
|
||||
match (output, mode) {
|
||||
(Ok(output), TestExpectationMode::Pass) => {
|
||||
let expected_output: Option<T> =
|
||||
expected_output.map(|x| serde_yaml::from_value(x).expect("test expectation deserialize failed"));
|
||||
// passed and should have
|
||||
if let Some(expected_output) = expected_output.as_ref() {
|
||||
if output != expected_output {
|
||||
// invalid output
|
||||
return Some(TestError::UnexpectedOutput {
|
||||
index: test_index,
|
||||
expected: expected_output.to_string(),
|
||||
output: output.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
(Ok(_tokens), TestExpectationMode::Fail) => Some(TestError::PassedAndShouldntHave { index: test_index }),
|
||||
(Err(err), TestExpectationMode::Pass) => Some(TestError::FailedAndShouldntHave {
|
||||
error: err.to_string(),
|
||||
index: test_index,
|
||||
}),
|
||||
(Err(err), TestExpectationMode::Fail) => {
|
||||
let expected_output: Option<String> =
|
||||
expected_output.map(|x| serde_yaml::from_value(x).expect("test expectation deserialize failed"));
|
||||
if let Some(expected_output) = expected_output.as_deref() {
|
||||
if err != expected_output {
|
||||
// invalid output
|
||||
return Some(TestError::UnexpectedError {
|
||||
expected: expected_output.to_string(),
|
||||
output: err.to_string(),
|
||||
index: test_index,
|
||||
});
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn run_test(
|
||||
config: &TestConfig,
|
||||
path: &str,
|
||||
source: &str,
|
||||
expectations: Option<&TestExpectation>,
|
||||
errors: &mut Vec<TestError>,
|
||||
) -> Vec<Value> {
|
||||
let end_of_header = source.find("*/").expect("failed to find header block in test");
|
||||
let source = &source[end_of_header + 2..];
|
||||
let mut outputs = vec![];
|
||||
match &config.namespace {
|
||||
TestNamespace::Token => {
|
||||
let tests = split_tests_oneline(source);
|
||||
if let Some(expectations) = expectations.as_ref() {
|
||||
if tests.len() != expectations.outputs.len() {
|
||||
errors.push(TestError::MismatchedTestExpectationLength);
|
||||
}
|
||||
}
|
||||
let mut expected_output = expectations.as_ref().map(|x| x.outputs.iter());
|
||||
for (i, test) in tests.into_iter().enumerate() {
|
||||
let expected_output = expected_output
|
||||
.as_mut()
|
||||
.map(|x| x.next())
|
||||
.flatten()
|
||||
.map(|x| x.as_str())
|
||||
.flatten();
|
||||
let output = run_individual_token_test(path, test);
|
||||
if let Some(error) = emit_errors(
|
||||
output.as_ref().map_err(|x| &**x),
|
||||
&config.expectation,
|
||||
expected_output.map(|x| Value::String(x.to_string())),
|
||||
i,
|
||||
) {
|
||||
errors.push(error);
|
||||
} else {
|
||||
outputs.push(serde_yaml::to_value(output.unwrap_or_else(|e| e)).expect("serialization failed"));
|
||||
}
|
||||
}
|
||||
}
|
||||
TestNamespace::Parse => {
|
||||
if let Some(expectations) = expectations.as_ref() {
|
||||
if expectations.outputs.len() != 1 {
|
||||
errors.push(TestError::MismatchedTestExpectationLength);
|
||||
}
|
||||
}
|
||||
let expected_output = expectations
|
||||
.map(|x| x.outputs.get(0))
|
||||
.flatten()
|
||||
.map(|x| serde_yaml::from_value(x.clone()).expect("invalid test expectation form"));
|
||||
let output = run_individual_parse_test(path, source);
|
||||
if let Some(error) = emit_errors(
|
||||
output.as_ref().map_err(|x| &**x),
|
||||
&config.expectation,
|
||||
expected_output,
|
||||
0,
|
||||
) {
|
||||
errors.push(error);
|
||||
} else {
|
||||
outputs.push(
|
||||
output
|
||||
.map(|x| serde_yaml::to_value(x).expect("serialization failed"))
|
||||
.unwrap_or_else(|e| serde_yaml::to_value(e).expect("serialization failed")),
|
||||
);
|
||||
}
|
||||
}
|
||||
TestNamespace::ParseStatement => {
|
||||
let tests = split_tests_twoline(source);
|
||||
if let Some(expectations) = expectations.as_ref() {
|
||||
if tests.len() != expectations.outputs.len() {
|
||||
errors.push(TestError::MismatchedTestExpectationLength);
|
||||
}
|
||||
}
|
||||
let mut expected_output = expectations.as_ref().map(|x| x.outputs.iter());
|
||||
for (i, test) in tests.into_iter().enumerate() {
|
||||
let expected_output = expected_output
|
||||
.as_mut()
|
||||
.map(|x| x.next())
|
||||
.flatten()
|
||||
.map(|x| serde_yaml::from_value(x.clone()).expect("invalid test expectation form"));
|
||||
|
||||
let output = run_individual_statement_test(path, &test);
|
||||
if let Some(error) = emit_errors(
|
||||
output.as_ref().map_err(|x| &**x),
|
||||
&config.expectation,
|
||||
expected_output,
|
||||
i,
|
||||
) {
|
||||
errors.push(error);
|
||||
} else {
|
||||
outputs.push(
|
||||
output
|
||||
.map(|x| serde_yaml::to_value(x).expect("serialization failed"))
|
||||
.unwrap_or_else(|e| serde_yaml::to_value(e).expect("serialization failed")),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
TestNamespace::ParseExpression => {
|
||||
let tests = split_tests_oneline(source);
|
||||
if let Some(expectations) = expectations.as_ref() {
|
||||
if tests.len() != expectations.outputs.len() {
|
||||
errors.push(TestError::MismatchedTestExpectationLength);
|
||||
}
|
||||
}
|
||||
let mut expected_output = expectations.as_ref().map(|x| x.outputs.iter());
|
||||
for (i, test) in tests.into_iter().enumerate() {
|
||||
let expected_output = expected_output
|
||||
.as_mut()
|
||||
.map(|x| x.next())
|
||||
.flatten()
|
||||
.map(|x| serde_yaml::from_value(x.clone()).expect("invalid test expectation form"));
|
||||
|
||||
let output = run_individual_expression_test(path, test);
|
||||
if let Some(error) = emit_errors(
|
||||
output.as_ref().map_err(|x| &**x),
|
||||
&config.expectation,
|
||||
expected_output,
|
||||
i,
|
||||
) {
|
||||
errors.push(error);
|
||||
} else {
|
||||
outputs.push(
|
||||
output
|
||||
.map(|x| serde_yaml::to_value(x).expect("serialization failed"))
|
||||
.unwrap_or_else(|e| serde_yaml::to_value(e).expect("serialization failed")),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
outputs
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn parser_tests() {
|
||||
let mut pass = 0;
|
||||
let mut fail = Vec::new();
|
||||
let mut tests = Vec::new();
|
||||
let mut test_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
test_dir.push("../tests/parser/");
|
||||
find_tests(&test_dir, &mut tests);
|
||||
let mut outputs = vec![];
|
||||
for (path, content) in tests.into_iter() {
|
||||
let config = extract_test_config(&content);
|
||||
if config.is_none() {
|
||||
panic!("missing configuration for {}", path);
|
||||
}
|
||||
let config = config.unwrap();
|
||||
let mut expectation_path = path.clone();
|
||||
expectation_path += ".out";
|
||||
let expectations: Option<TestExpectation> = if std::path::Path::new(&expectation_path).exists() {
|
||||
if !std::env::var("CLEAR_LEO_TEST_EXPECTATIONS")
|
||||
.unwrap_or_default()
|
||||
.trim()
|
||||
.is_empty()
|
||||
{
|
||||
None
|
||||
} else {
|
||||
let raw = std::fs::read_to_string(&expectation_path).expect("failed to read expectations file");
|
||||
Some(serde_yaml::from_str(&raw).expect("invalid yaml in expectations file"))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let mut errors = vec![];
|
||||
let raw_path = Path::new(&path);
|
||||
let new_outputs = run_test(
|
||||
&config,
|
||||
raw_path.file_name().unwrap_or_default().to_str().unwrap_or_default(),
|
||||
&content,
|
||||
expectations.as_ref(),
|
||||
&mut errors,
|
||||
);
|
||||
if errors.is_empty() {
|
||||
if expectations.is_none() {
|
||||
outputs.push((expectation_path, TestExpectation {
|
||||
namespace: config.namespace,
|
||||
expectation: config.expectation,
|
||||
outputs: new_outputs,
|
||||
}));
|
||||
}
|
||||
pass += 1;
|
||||
} else {
|
||||
fail.push(TestFailure {
|
||||
path: path.clone(),
|
||||
errors,
|
||||
})
|
||||
}
|
||||
}
|
||||
if !fail.is_empty() {
|
||||
for (i, fail) in fail.iter().enumerate() {
|
||||
println!(
|
||||
"\n\n-----------------TEST #{} FAILED (and shouldn't have)-----------------",
|
||||
i + 1
|
||||
);
|
||||
println!("File: {}", fail.path);
|
||||
for error in &fail.errors {
|
||||
println!("{}", error);
|
||||
}
|
||||
}
|
||||
panic!("failed {}/{} tests", fail.len(), fail.len() + pass);
|
||||
} else {
|
||||
for (path, new_expectation) in outputs {
|
||||
std::fs::write(
|
||||
&path,
|
||||
serde_yaml::to_string(&new_expectation).expect("failed to serialize expectation yaml"),
|
||||
)
|
||||
.expect("failed to write expectation file");
|
||||
}
|
||||
println!("passed {}/{} tests", pass, pass);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn parser_pass_tests() {
|
||||
let mut pass = 0;
|
||||
let mut fail = Vec::new();
|
||||
let mut tests = Vec::new();
|
||||
let mut test_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
test_dir.push("../tests/pass/parse/");
|
||||
test_dir.push("../tests/old/pass/");
|
||||
find_tests(&test_dir, &mut tests);
|
||||
for (path, content) in tests.into_iter() {
|
||||
match crate::parse(&path, &content) {
|
||||
@ -54,7 +506,13 @@ pub fn parser_pass_tests() {
|
||||
pass += 1;
|
||||
}
|
||||
Err(e) => {
|
||||
fail.push(TestFailure { path, error: e });
|
||||
fail.push(TestFailure {
|
||||
path,
|
||||
errors: vec![TestError::FailedAndShouldntHave {
|
||||
index: 0,
|
||||
error: e.to_string(),
|
||||
}],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -65,7 +523,9 @@ pub fn parser_pass_tests() {
|
||||
i + 1
|
||||
);
|
||||
println!("File: {}", fail.path);
|
||||
println!("{}", fail.error);
|
||||
for error in &fail.errors {
|
||||
println!("{}", error);
|
||||
}
|
||||
}
|
||||
panic!("failed {}/{} tests", fail.len(), fail.len() + pass);
|
||||
} else {
|
||||
@ -79,7 +539,7 @@ pub fn parser_fail_tests() {
|
||||
let mut fail = Vec::new();
|
||||
let mut tests = Vec::new();
|
||||
let mut test_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
test_dir.push("../tests/fail/parse/");
|
||||
test_dir.push("../tests/old/fail/");
|
||||
find_tests(&test_dir, &mut tests);
|
||||
for (path, content) in tests.into_iter() {
|
||||
match crate::parse(&path, &content) {
|
||||
|
@ -306,11 +306,7 @@ impl Token {
|
||||
return (
|
||||
ident.len(),
|
||||
Some(match &*ident {
|
||||
x if x.starts_with("aleo1")
|
||||
&& x.chars().skip(5).all(|x| x.is_ascii_lowercase() || x.is_ascii_digit()) =>
|
||||
{
|
||||
Token::AddressLit(ident)
|
||||
}
|
||||
x if x.starts_with("aleo1") => Token::AddressLit(ident),
|
||||
"address" => Token::Address,
|
||||
"as" => Token::As,
|
||||
"bool" => Token::Bool,
|
||||
|
@ -146,6 +146,9 @@ pub enum Token {
|
||||
// ModEq,
|
||||
// OrEq,
|
||||
// AndEq,
|
||||
|
||||
// Meta Tokens
|
||||
Eof,
|
||||
}
|
||||
|
||||
/// Represents all valid Leo keyword tokens.
|
||||
@ -289,6 +292,7 @@ impl fmt::Display for Token {
|
||||
Return => write!(f, "return"),
|
||||
Static => write!(f, "static"),
|
||||
String => write!(f, "string"),
|
||||
Eof => write!(f, ""),
|
||||
// BitAnd => write!(f, "&"),
|
||||
// BitAndEq => write!(f, "&="),
|
||||
// BitOr => write!(f, "|"),
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leo-state"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||
description = "State parser of the Leo programming language"
|
||||
homepage = "https://aleo.org"
|
||||
@ -19,15 +19,14 @@ edition = "2018"
|
||||
|
||||
[dependencies.leo-input]
|
||||
path = "../input"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.leo-ast]
|
||||
path = "../ast"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
|
||||
[dependencies.snarkvm-algorithms]
|
||||
version = "0.2.2"
|
||||
#default-features = false
|
||||
|
||||
[dependencies.snarkvm-curves]
|
||||
version = "0.2.2"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leo-synthesizer"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0"
|
||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||
description = "Circuit synthesizer of the Leo programming language"
|
||||
homepage = "https://aleo.org"
|
||||
@ -27,7 +27,6 @@ default-features = false
|
||||
|
||||
[dependencies.snarkvm-gadgets]
|
||||
version = "0.2.2"
|
||||
default-features = false
|
||||
|
||||
[dependencies.snarkvm-r1cs]
|
||||
version = "0.2.2"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user