merge master

This commit is contained in:
collin 2020-06-08 10:49:31 -07:00
commit e10a1e1be0
406 changed files with 11263 additions and 5534 deletions

2
.cargo/config Normal file
View File

@ -0,0 +1,2 @@
[build]
rustflags = ["-C", "target-cpu=native"]

3
.gitignore vendored
View File

@ -1,7 +1,4 @@
/target /target
**.idea/ **.idea/
Leo.toml
src/
inputs/
outputs/ outputs/
*.DS_Store *.DS_Store

317
Cargo.lock generated
View File

@ -99,13 +99,14 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]] [[package]]
name = "blake2" name = "blake2"
version = "0.7.1" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b77e29dbd0115e43938be2d5128ecf81c0353e00acaa65339a1242586951d9" checksum = "94cb07b0da6a73955f8fb85d24c466778e70cda767a568229b104f0264089330"
dependencies = [ dependencies = [
"byte-tools 0.2.0", "byte-tools",
"crypto-mac", "crypto-mac",
"digest 0.7.6", "digest",
"opaque-debug",
] ]
[[package]] [[package]]
@ -115,9 +116,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
dependencies = [ dependencies = [
"block-padding", "block-padding",
"byte-tools 0.3.1", "byte-tools",
"byteorder", "byteorder",
"generic-array 0.12.3", "generic-array",
] ]
[[package]] [[package]]
@ -126,15 +127,9 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
dependencies = [ dependencies = [
"byte-tools 0.3.1", "byte-tools",
] ]
[[package]]
name = "byte-tools"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
[[package]] [[package]]
name = "byte-tools" name = "byte-tools"
version = "0.3.1" version = "0.3.1"
@ -208,12 +203,6 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "constant_time_eq"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
[[package]] [[package]]
name = "crossbeam-deque" name = "crossbeam-deque"
version = "0.7.3" version = "0.7.3"
@ -263,32 +252,53 @@ dependencies = [
[[package]] [[package]]
name = "crypto-mac" name = "crypto-mac"
version = "0.5.2" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0999b4ff4d3446d4ddb19a63e9e00c1876e75cd7000d20e57a693b4b3f08d958" checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5"
dependencies = [ dependencies = [
"constant_time_eq", "generic-array",
"generic-array 0.9.0", "subtle",
]
[[package]]
name = "curl"
version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "762e34611d2d5233a506a79072be944fddd057db2f18e04c0d6fa79e3fd466fd"
dependencies = [
"curl-sys",
"libc",
"openssl-probe",
"openssl-sys",
"schannel",
"socket2",
"winapi",
]
[[package]]
name = "curl-sys"
version = "0.4.31+curl-7.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcd62757cc4f5ab9404bc6ca9f0ae447e729a1403948ce5106bd588ceac6a3b0"
dependencies = [
"cc",
"libc",
"libz-sys",
"openssl-sys",
"pkg-config",
"vcpkg",
"winapi",
] ]
[[package]] [[package]]
name = "derivative" name = "derivative"
version = "1.0.4" version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c6d883546668a3e2011b6a716a7330b82eabb0151b138217f632c8243e17135" checksum = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f"
dependencies = [ dependencies = [
"proc-macro2 0.4.30", "proc-macro2 1.0.9",
"quote 0.6.13", "quote 1.0.3",
"syn 0.15.44", "syn 1.0.16",
]
[[package]]
name = "digest"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
dependencies = [
"generic-array 0.9.0",
] ]
[[package]] [[package]]
@ -297,7 +307,7 @@ version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
dependencies = [ dependencies = [
"generic-array 0.12.3", "generic-array",
] ]
[[package]] [[package]]
@ -363,15 +373,6 @@ version = "0.1.29"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef"
[[package]]
name = "generic-array"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
dependencies = [
"typenum",
]
[[package]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.12.3" version = "0.12.3"
@ -398,15 +399,6 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "heck"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
dependencies = [
"unicode-segmentation",
]
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.8" version = "0.1.8"
@ -448,9 +440,9 @@ checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
[[package]] [[package]]
name = "jsonrpc-core" name = "jsonrpc-core"
version = "14.1.0" version = "14.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25525f6002338fb4debb5167a89a0b47f727a5a48418417545ad3429758b7fec" checksum = "a0747307121ffb9703afd93afbd0fb4f854c38fb873f2c8b90e0e902f27c7b62"
dependencies = [ dependencies = [
"futures", "futures",
"log", "log",
@ -478,7 +470,6 @@ dependencies = [
"clap", "clap",
"colored", "colored",
"env_logger", "env_logger",
"failure",
"from-pest", "from-pest",
"leo-compiler", "leo-compiler",
"leo-inputs", "leo-inputs",
@ -493,36 +484,31 @@ dependencies = [
"snarkos-gadgets", "snarkos-gadgets",
"snarkos-models", "snarkos-models",
"snarkos-utilities", "snarkos-utilities",
"structopt", "thiserror",
"toml", "toml",
] ]
[[package]] [[package]]
name = "leo-benchmark" name = "leo-ast"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"from-pest", "from-pest",
"leo-compiler", "lazy_static",
"rand", "log",
"snarkos-algorithms", "pest",
"snarkos-curves", "pest-ast",
"snarkos-errors", "pest_derive",
"snarkos-gadgets", "thiserror",
"snarkos-models",
] ]
[[package]] [[package]]
name = "leo-compiler" name = "leo-compiler"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"failure",
"from-pest",
"hex", "hex",
"lazy_static", "leo-ast",
"leo-types",
"log", "log",
"pest",
"pest-ast",
"pest_derive",
"rand", "rand",
"sha2", "sha2",
"snarkos-algorithms", "snarkos-algorithms",
@ -530,6 +516,8 @@ dependencies = [
"snarkos-errors", "snarkos-errors",
"snarkos-gadgets", "snarkos-gadgets",
"snarkos-models", "snarkos-models",
"snarkos-utilities",
"thiserror",
] ]
[[package]] [[package]]
@ -548,6 +536,16 @@ dependencies = [
"snarkos-models", "snarkos-models",
] ]
[[package]]
name = "leo-types"
version = "0.1.0"
dependencies = [
"leo-ast",
"snarkos-errors",
"snarkos-models",
"thiserror",
]
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.67" version = "0.2.67"
@ -576,6 +574,18 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "libz-sys"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.8" version = "0.4.8"
@ -638,6 +648,25 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
[[package]]
name = "openssl-probe"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
[[package]]
name = "openssl-sys"
version = "0.9.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7410fef80af8ac071d4f63755c0ab89ac3df0fd1ea91f1d1f37cf5cec4395990"
dependencies = [
"autocfg",
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]] [[package]]
name = "peeking_take_while" name = "peeking_take_while"
version = "0.1.2" version = "0.1.2"
@ -700,38 +729,18 @@ dependencies = [
"sha-1", "sha-1",
] ]
[[package]]
name = "pkg-config"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.6" version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
[[package]]
name = "proc-macro-error"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678"
dependencies = [
"proc-macro-error-attr",
"proc-macro2 1.0.9",
"quote 1.0.3",
"syn 1.0.16",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53"
dependencies = [
"proc-macro2 1.0.9",
"quote 1.0.3",
"syn 1.0.16",
"syn-mid",
"version_check",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "0.4.30" version = "0.4.30"
@ -848,6 +857,12 @@ dependencies = [
"num_cpus", "num_cpus",
] ]
[[package]]
name = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.3.4" version = "1.3.4"
@ -894,6 +909,16 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
[[package]]
name = "schannel"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
dependencies = [
"lazy_static",
"winapi",
]
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.1.0" version = "1.1.0"
@ -938,7 +963,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
dependencies = [ dependencies = [
"block-buffer", "block-buffer",
"digest 0.8.1", "digest",
"fake-simd", "fake-simd",
"opaque-debug", "opaque-debug",
] ]
@ -950,7 +975,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0"
dependencies = [ dependencies = [
"block-buffer", "block-buffer",
"digest 0.8.1", "digest",
"fake-simd", "fake-simd",
"opaque-debug", "opaque-debug",
] ]
@ -982,8 +1007,9 @@ version = "0.8.0"
dependencies = [ dependencies = [
"blake2", "blake2",
"derivative", "derivative",
"digest 0.7.6", "digest",
"rand", "rand",
"rand_chacha",
"rayon", "rayon",
"sha2", "sha2",
"smallvec", "smallvec",
@ -1009,10 +1035,11 @@ name = "snarkos-errors"
version = "0.8.0" version = "0.8.0"
dependencies = [ dependencies = [
"bincode", "bincode",
"failure", "curl",
"hex", "hex",
"jsonrpc-core", "jsonrpc-core",
"rocksdb", "rocksdb",
"thiserror",
] ]
[[package]] [[package]]
@ -1020,7 +1047,7 @@ name = "snarkos-gadgets"
version = "0.8.0" version = "0.8.0"
dependencies = [ dependencies = [
"derivative", "derivative",
"digest 0.7.6", "digest",
"snarkos-algorithms", "snarkos-algorithms",
"snarkos-curves", "snarkos-curves",
"snarkos-errors", "snarkos-errors",
@ -1033,7 +1060,6 @@ name = "snarkos-models"
version = "0.8.0" version = "0.8.0"
dependencies = [ dependencies = [
"derivative", "derivative",
"failure",
"rand", "rand",
"rand_xorshift", "rand_xorshift",
"smallvec", "smallvec",
@ -1052,6 +1078,18 @@ dependencies = [
"rand", "rand",
] ]
[[package]]
name = "socket2"
version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"winapi",
]
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.8.0" version = "0.8.0"
@ -1059,28 +1097,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]] [[package]]
name = "structopt" name = "subtle"
version = "0.3.14" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef" checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
dependencies = [
"clap",
"lazy_static",
"structopt-derive",
]
[[package]]
name = "structopt-derive"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2 1.0.9",
"quote 1.0.3",
"syn 1.0.16",
]
[[package]] [[package]]
name = "syn" name = "syn"
@ -1104,17 +1124,6 @@ dependencies = [
"unicode-xid 0.2.0", "unicode-xid 0.2.0",
] ]
[[package]]
name = "syn-mid"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
dependencies = [
"proc-macro2 1.0.9",
"quote 1.0.3",
"syn 1.0.16",
]
[[package]] [[package]]
name = "synstructure" name = "synstructure"
version = "0.12.3" version = "0.12.3"
@ -1145,6 +1154,26 @@ dependencies = [
"unicode-width", "unicode-width",
] ]
[[package]]
name = "thiserror"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d12a1dae4add0f0d568eebc7bf142f145ba1aa2544cafb195c76f0f409091b60"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f34e0c1caaa462fd840ec6b768946ea1e7842620d94fe29d5b847138f521269"
dependencies = [
"proc-macro2 1.0.9",
"quote 1.0.3",
"syn 1.0.16",
]
[[package]] [[package]]
name = "thread_local" name = "thread_local"
version = "1.0.1" version = "1.0.1"
@ -1175,12 +1204,6 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" checksum = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2"
[[package]]
name = "unicode-segmentation"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
version = "0.1.7" version = "0.1.7"
@ -1199,6 +1222,12 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
[[package]]
name = "vcpkg"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55d1e41d56121e07f1e223db0a4def204e45c85425f6a16d462fd07c8d10d74c"
[[package]] [[package]]
name = "vec_map" name = "vec_map"
version = "0.8.1" version = "0.8.1"

View File

@ -13,7 +13,7 @@ name = "leo"
path = "leo/main.rs" path = "leo/main.rs"
[workspace] [workspace]
members = [ "benchmark", "compiler", "leo-inputs" ] members = [ "ast", "compiler", "types" ]
[dependencies] [dependencies]
leo-compiler = { path = "compiler", version = "0.1.0" } leo-compiler = { path = "compiler", version = "0.1.0" }
@ -29,12 +29,11 @@ snarkos-utilities = { path = "../snarkOS/utilities", version = "0.8.0" }
clap = { version = "2.33.0" } clap = { version = "2.33.0" }
colored = { version = "1.9" } colored = { version = "1.9" }
env_logger = { version = "0.7" } env_logger = { version = "0.7" }
failure = { version = "0.1.5" }
from-pest = { version = "0.3.1" } from-pest = { version = "0.3.1" }
log = { version = "0.4" } log = { version = "0.4" }
rand = { version = "0.7" } rand = { version = "0.7" }
rand_core = { version = "0.5.1" } rand_core = { version = "0.5.1" }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0" } serde_json = { version = "1.0" }
structopt = { version = "0.3.14" }
toml = { version = "0.5" } toml = { version = "0.5" }
thiserror = { version = "1.0" }

3
Leo.toml Normal file
View File

@ -0,0 +1,3 @@
[package]
name = "language"
version = "0.1.0"

332
README.md
View File

@ -1,41 +1,87 @@
# The Leo Language # The Leo Programming Language
* All code examples can be copied and pasted into `main.leo` directly and executed with cargo run
* Programs should be formatted: * Programs should be formatted:
1. Import definitions 1. Import definitions
2. Struct definitions 2. Circuit definitions
3. Function definitions 3. Function definitions
### Integers: ## Mutability
Currently, all integers are parsed as u32. * All defined variables in Leo are immutable by default.
You can choose to explicitly add the type or let the compiler interpret implicitly. * Variables can be made mutable with the `mut` keyword.
```rust ```rust
function main() -> u32 { function main() {
let a : u32 = 1u32 + 1u32; // explicit type let a = 0u32;
let b = 1 - 1; // implicit type //a = 1 <- Will fail
let c = 2 * 2;
let d = 4 / 2; let mut b = 0u32;
let e = 2 ** 3; b = 1; // <- Ok
}
```
## Booleans
Explicit types are optional.
```rust
function main() -> bool {
let a: bool = true || false;
let b = false && false;
let c = 1u32 == 1u32;
return a return a
} }
``` ```
### Field Elements: ## Numbers
Field elements must have the type added explicitly. * The definition of a number must include an explict type.
* After assignment, you can choose to explicitly add the type or let the compiler interpret implicitly.
* Type casting is not supported.
* Comparators are not supported.
### Integers
Supported integer types: `u8`, `u16`, `u32`, `u64`, `u128`
```rust ```rust
function main() -> fe { function main() -> u32 {
let f : fe = 21888242871839275222246405745257275088548364400416034343698204186575808495617fe; let a = 2u32; // explicit type
let a = 1fe + 1fe; let a: u32 = 1 + 1; // explicit type
let b = 1fe - 1fe;
let c = 2fe * 2fe; let b = a - 1; // implicit type
let d = 4fe / 2fe; let c = b * 4;
return a let d = c / 2;
let e = d ** 3;
return e
} }
``` ```
### Operator Assignment Statements: ### Field Elements
```rust
function main() -> field {
let a = 1000field; // explicit type
let a: field = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // explicit type
let b = a + 1; // implicit type
let c = b - 1;
let d = c * 4;
let e = d / 2;
return e
}
```
### Affine Points
The set of affine points on the elliptic curve passed into the leo compiler forms a group.
Leo supports this set as a primitive data type.
```rust
function main() -> group {
let a = 1000group; // explicit type
let a = (21888242871839275222246405745257275088548364400416034343698204186575808495617, 21888242871839275222246405745257275088548364400416034343698204186575808495617)group; // explicit type
let b = a + 0; // implicit type
let c = b - 0;
return c
}
```
### Operator Assignment Statements
```rust ```rust
function main() -> u32 { function main() -> u32 {
let a = 10; let mut a = 10;
a += 5; a += 5;
a -= 10; a -= 10;
a *= 5; a *= 5;
@ -46,30 +92,18 @@ function main() -> u32 {
} }
``` ```
## Arrays
### Booleans:
```rust
function main() -> bool {
let a : bool = true || false;
let b = false && false;
let c = 1 == 1;
return a
}
```
### Arrays:
Leo supports static arrays with fixed length. Leo supports static arrays with fixed length.
Array type must be explicitly stated
```rust ```rust
function main() -> u32[2] { function main() -> u32[2] {
// initialize an integer array with integer values // initialize an integer array with integer values
let a : u32[3] = [1, 2, 3]; let mut a: u32[3] = [1, 2, 3];
// set a member to a value // set a mutable member to a value
a[2] = 4; a[2] = 4;
// initialize an array of 4 values all equal to 42 // initialize an array of 4 values all equal to 42
let b = [42; 4]; let b = [42u8; 4];
// initialize an array of 5 values copying all elements of b using a spread // initialize an array of 5 values copying all elements of b using a spread
let c = [1, ...b]; let c = [1, ...b];
@ -78,63 +112,42 @@ function main() -> u32[2] {
let d = c[1..3]; let d = c[1..3];
// initialize a field array // initialize a field array
let e = [5fe; 2]; let e = [5field; 2];
// initialize a boolean array // initialize a boolean array
let f = [true, false || true, true]; let f = [true, false || true, true];
// return an array
return d return d
} }
``` ```
### Structs:
### Multidimensional Arrays
```rust ```rust
struct Point { function main() -> u32[3][2] {
u32 x let m = [[0u32, 0u32], [0u32, 0u32]];
u32 y
} let m: u32[3][2] = [[0; 3]; 2];
function main() -> u32 {
Point p = Point {x: 1, y: 0} return m
return p.x
}
```
```rust
struct Foo {
bool x
}
function main() -> Foo {
let f = Foo {x: true};
f.x = false;
return f
} }
``` ```
### Assert Equals: ## Conditionals
This will enforce that the two values are equal in the constraint system.
```rust ### If Else Ternary Expression
function main() {
assert_eq(45, 45);
assert_eq(2fe, 2fe);
assert_eq(true, true);
}
```
### Conditionals:
#### If Else Ternary Expression
```rust ```rust
function main() -> u32 { function main() -> u32 {
let y = if 3==3 ? 1 : 5; let y = if 3==3 ? 1 : 5;
return y return y
} }
``` ```
#### If Else Conditional Statement
### If Else Conditional Statement
** **Experimental** **
The current constraint system is not optimized for statement branching. Please use the ternary expression above until this feature is stable.
```rust ```rust
function main(a: private bool, b: private bool) -> u32 { function main(a: private bool, b: private bool) -> u32 {
let res = 0; let mut res = 0u32;
if (a) { if (a) {
res = 1; res = 1;
} else if (b) { } else if (b) {
@ -145,25 +158,26 @@ function main(a: private bool, b: private bool) -> u32 {
return res return res
} }
``` ```
#### For loop
### For loop
```rust ```rust
function main() -> fe { function main() -> fe {
let a = 1fe; let mut a = 1field;
for i in 0..4 { for i in 0..4 {
a = a + 1fe; a = a + 1;
} }
return a return a
} }
``` ```
### Functions: ## Functions
```rust ```rust
function test1(a : u32) -> u32 { function test1(a : u32) -> u32 {
return a + 1 return a + 1
} }
function test2(b: fe) -> fe { function test2(b: fe) -> field {
return b * 2fe return b * 2field
} }
function test3(c: bool) -> bool { function test3(c: bool) -> bool {
@ -176,20 +190,20 @@ function main() -> u32 {
``` ```
#### Function Scope: ### Function Scope
```rust ```rust
function foo() -> field { function foo() -> field {
// return myGlobal <- not allowed // return myGlobal <- not allowed
return 42fe return 42field
} }
function main() -> field { function main() -> field {
let myGlobal = 42fe; let myGlobal = 42field;
return foo() return foo()
} }
``` ```
#### Multiple returns: ### Multiple returns
Functions can return tuples whose types are specified in the function signature. Functions can return tuples whose types are specified in the function signature.
```rust ```rust
function test() -> (u32, u32[2]) { function test() -> (u32, u32[2]) {
@ -198,26 +212,32 @@ function test() -> (u32, u32[2]) {
function main() -> u32[3] { function main() -> u32[3] {
let (a, b) = test(); let (a, b) = test();
// a, u32[2] b = test() <- explicit type also works // (a, u32[2] b) = test() <- explicit type also works
return [a, ...b] return [a, ...b]
} }
``` ```
#### Parameters: ### Main function inputs
Main function arguments are allocated as public or private variables in the program's constaint system. Main function inputs are allocated as public or private variables in the program's constaint system.
```rust ```rust
function main(a: private fe) -> fe { function main(a: private field) -> field {
return a return a
} }
``` ```
```rust ```rust
function main(a: public fe) -> fe { function main(a: public field) -> field {
return a return a
} }
``` ```
Function parameters are passed by value. Private by default. Below `a` is implicitly private.
```rust ```rust
function test(a: u32) { function main(a: field) -> field {
return a
}
```
Function inputs are passed by value.
```rust
function test(mut a: u32) {
a = 0; a = 0;
} }
@ -229,17 +249,76 @@ function main() -> u32 {
} }
``` ```
### Imports: ## Circuits
Circuits in Leo are similar to classes in object oriented langauges. Circuits are defined above functions in a Leo program. Circuits can have one or more members.
Members can be defined as fields which hold primitive values
```rust
circuit Point {
x: u32
y: u32
}
function main() -> u32 {
let p = Point {x: 1, y: 0};
return p.x
}
```
Members can also be defined as functions.
```rust
circuit Circ {
function echo(x: u32) -> u32 {
return x
}
}
function main() -> u32 {
let c = Circ { };
return c.echo(1u32)
}
```
Circuit functions can be made static, enabling them to be called without instantiation.
```rust
circuit Circ {
static function echo(x: u32) -> u32 {
return x
}
}
function main() -> u32 {
return Circ::echo(1u32)
}
```
The `Self` keyword is supported in circuit functions.
```rust
circuit Circ {
b: bool
static function new() -> Self {
return Self { b: true }
}
}
function main() -> Circ {
let c = Circ::new();
return c.b
}
```
## Imports
Both struct and function imports are supported. Both struct and function imports are supported.
import all: `*` import all: `*`
import alias: `symbol as alias` import alias: `symbol as alias`
/simple_import.leo `src/simple_import.leo`
```rust ```rust
struct Point { circuit Point {
u32 x x: u32
u32 y y: u32
} }
function test() -> (u32, u32[2]) { function test() -> (u32, u32[2]) {
@ -247,7 +326,7 @@ function test() -> (u32, u32[2]) {
} }
``` ```
/simple.leo `src/simple.leo`
```rust ```rust
from "./simple_import" import { from "./simple_import" import {
Point as Foo, Point as Foo,
@ -257,12 +336,50 @@ from "./simple_import" import {
// from "./simple_import" import * // from "./simple_import" import *
function main() -> (u32[3]) { function main() -> (u32[3]) {
let (a, b) = test();
let p = Foo { x: 1, y: 2}; let p = Foo { x: 1, y: 2};
let (a, b) = test();
return [a, ...b] return [a, ...b]
} }
``` ```
## Constraints
### Assert Equals
This will enforce that the two values are equal in the constraint system.
```rust
function main() {
assert_eq(45, 45);
assert_eq(2fe, 2fe);
assert_eq(true, true);
}
```
## Testing
Use the `test` keyword to add tests to a leo program. Tests must have 0 function inputs and 0 function returns.
```rust
function main(a: u32) -> u32 {
return a
}
test function expect_pass() {
let a = 1u32;
let res = main(a);
assert_eq!(res, 1u32);
}
test function expect_fail() {
assert_eq!(1u8, 0u8);
}
```
# Leo CLI # Leo CLI
@ -283,7 +400,7 @@ This will create a new directory with a given package name. The new package will
- lib.leo # Your program library - lib.leo # Your program library
- main.leo # Your program - main.leo # Your program
- tests - tests
- tests.leo # Your program tests - test.leo # Your program tests
- Leo.toml # Your program manifest - Leo.toml # Your program manifest
``` ```
@ -308,6 +425,12 @@ To execute unit tests on your program, run:
``` ```
leo test leo test
``` ```
The results of test compilation and the constraint system will be printed:
```
INFO leo Running 2 tests
INFO leo test language::expect_pass compiled. Constraint system satisfied: true
ERROR leo test language::expect_fail errored: Assertion 1u8 == 0u8 failed
```
## Run ## Run
@ -377,6 +500,13 @@ To deploy your program to Aleo, run:
leo deploy leo deploy
``` ```
# Install
To install Leo from source, in the root directory of the repository, run:
```
cargo install --path .
```
## TODO ## TODO
- Change `target` directory to some other directory to avoid collision. - Change `target` directory to some other directory to avoid collision.

14
ast/Cargo.toml Normal file
View File

@ -0,0 +1,14 @@
[package]
name = "leo-ast"
version = "0.1.0"
authors = ["The Aleo Team <hello@aleo.org>"]
edition = "2018"
[dependencies]
from-pest = { version = "0.3.1" }
lazy_static = { version = "1.3.0" }
log = { version = "0.4" }
pest = { version = "2.0" }
pest-ast = { version = "0.3.3" }
pest_derive = { version = "2.0" }
thiserror = { version = "1.0" }

1
ast/README.md Normal file
View File

@ -0,0 +1 @@
# leo-ast

12
ast/src/access/access.rs Normal file
View File

@ -0,0 +1,12 @@
use crate::{access::*, ast::Rule};
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::access))]
pub enum Access<'ast> {
Array(ArrayAccess<'ast>),
Call(CallAccess<'ast>),
Object(MemberAccess<'ast>),
StaticObject(StaticMemberAccess<'ast>),
}

View File

@ -0,0 +1,12 @@
use crate::{ast::Rule, common::RangeOrExpression};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::access_array))]
pub struct ArrayAccess<'ast> {
pub expression: RangeOrExpression<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,20 @@
use crate::{access::{ArrayAccess, MemberAccess}, ast::Rule};
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::access_assignee))]
pub enum AssigneeAccess<'ast> {
Array(ArrayAccess<'ast>),
Member(MemberAccess<'ast>),
}
impl<'ast> fmt::Display for AssigneeAccess<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
AssigneeAccess::Array(ref array) => write!(f, "[{}]", array.expression),
AssigneeAccess::Member(ref member) => write!(f, ".{}", member.identifier),
}
}
}

View File

@ -0,0 +1,12 @@
use crate::{ast::Rule, expressions::Expression};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::access_call))]
pub struct CallAccess<'ast> {
pub expressions: Vec<Expression<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,12 @@
use crate::{ast::Rule, common::Identifier};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::access_member))]
pub struct MemberAccess<'ast> {
pub identifier: Identifier<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

17
ast/src/access/mod.rs Normal file
View File

@ -0,0 +1,17 @@
pub mod access;
pub use access::*;
pub mod array_access;
pub use array_access::*;
pub mod assignee_access;
pub use assignee_access::*;
pub mod call_access;
pub use call_access::*;
pub mod member_access;
pub use member_access::*;
pub mod static_member_access;
pub use static_member_access::*;

View File

@ -0,0 +1,12 @@
use crate::{ast::Rule, common::Identifier};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::access_static_member))]
pub struct StaticMemberAccess<'ast> {
pub identifier: Identifier<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

173
ast/src/ast.rs Normal file
View File

@ -0,0 +1,173 @@
//! Abstract syntax tree (ast) representation from leo.pest.
use crate::{
common::Identifier,
expressions::{
ArrayInlineExpression,
ArrayInitializerExpression,
CircuitInlineExpression,
Expression,
TernaryExpression,
NotExpression,
PostfixExpression
},
operations::{
BinaryOperation,
NotOperation,
},
values::Value,
};
use from_pest::{ConversionError, FromPest, Void};
use pest::{
error::Error,
iterators::{Pair, Pairs},
prec_climber::{Assoc, Operator, PrecClimber},
Parser, Span,
};
#[derive(Parser)]
#[grammar = "leo.pest"]
pub struct LanguageParser;
pub fn parse(input: &str) -> Result<Pairs<Rule>, Error<Rule>> {
LanguageParser::parse(Rule::file, input)
}
pub(crate) fn span_into_string(span: Span) -> String {
span.as_str().to_string()
}
lazy_static! {
static ref PRECEDENCE_CLIMBER: PrecClimber<Rule> = precedence_climber();
}
// Expressions
fn precedence_climber() -> PrecClimber<Rule> {
PrecClimber::new(vec![
Operator::new(Rule::operation_or, Assoc::Left),
Operator::new(Rule::operation_and, Assoc::Left),
Operator::new(Rule::operation_eq, Assoc::Left)
| Operator::new(Rule::operation_ne, Assoc::Left),
Operator::new(Rule::operation_ge, Assoc::Left)
| Operator::new(Rule::operation_gt, Assoc::Left)
| Operator::new(Rule::operation_le, Assoc::Left)
| Operator::new(Rule::operation_lt, Assoc::Left),
Operator::new(Rule::operation_add, Assoc::Left)
| Operator::new(Rule::operation_sub, Assoc::Left),
Operator::new(Rule::operation_mul, Assoc::Left)
| Operator::new(Rule::operation_div, Assoc::Left),
Operator::new(Rule::operation_pow, Assoc::Left),
])
}
fn parse_term(pair: Pair<Rule>) -> Box<Expression> {
Box::new(match pair.as_rule() {
Rule::expression_term => {
let clone = pair.clone();
let next = clone.into_inner().next().unwrap();
match next.as_rule() {
Rule::expression => Expression::from_pest(&mut pair.into_inner()).unwrap(), // Parenthesis case
Rule::expression_array_inline => {
Expression::ArrayInline(
ArrayInlineExpression::from_pest(&mut pair.into_inner()).unwrap()
)
},
Rule::expression_array_initializer => {
Expression::ArrayInitializer(
ArrayInitializerExpression::from_pest(&mut pair.into_inner()).unwrap()
)
},
Rule::expression_circuit_inline => {
Expression::CircuitInline(
CircuitInlineExpression::from_pest(&mut pair.into_inner()).unwrap(),
)
},
Rule::expression_conditional => {
Expression::Ternary(
TernaryExpression::from_pest(&mut pair.into_inner()).unwrap(),
)
},
Rule::expression_not => {
let span = next.as_span();
let mut inner = next.into_inner();
let operation = match inner.next().unwrap().as_rule() {
Rule::operation_not => NotOperation::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(),
rule => unreachable!("`expression_not` should yield `operation_pre_not`, found {:#?}", rule)
};
let expression = parse_term(inner.next().unwrap());
Expression::Not(NotExpression { operation, expression, span })
},
Rule::expression_postfix => {
Expression::Postfix(
PostfixExpression::from_pest(&mut pair.into_inner()).unwrap(),
)
}
Rule::expression_primitive => {
let next = next.into_inner().next().unwrap();
match next.as_rule() {
Rule::value => {
Expression::Value(
Value::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap()
)
},
Rule::identifier => Expression::Identifier(
Identifier::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(),
),
rule => unreachable!("`expression_primitive` should contain one of [`value`, `identifier`], found {:#?}", rule)
}
},
rule => unreachable!("`term` should contain one of ['value', 'identifier', 'expression', 'expression_not', 'expression_increment', 'expression_decrement'], found {:#?}", rule)
}
}
rule => unreachable!(
"`parse_expression_term` should be invoked on `Rule::expression_term`, found {:#?}",
rule
),
})
}
fn binary_expression<'ast>(
lhs: Box<Expression<'ast>>,
pair: Pair<'ast, Rule>,
rhs: Box<Expression<'ast>>,
) -> Box<Expression<'ast>> {
let (start, _) = lhs.span().clone().split();
let (_, end) = rhs.span().clone().split();
let span = start.span(&end);
Box::new(match pair.as_rule() {
Rule::operation_or => Expression::binary(BinaryOperation::Or, lhs, rhs, span),
Rule::operation_and => Expression::binary(BinaryOperation::And, lhs, rhs, span),
Rule::operation_eq => Expression::binary(BinaryOperation::Eq, lhs, rhs, span),
Rule::operation_ne => Expression::binary(BinaryOperation::Ne, lhs, rhs, span),
Rule::operation_ge => Expression::binary(BinaryOperation::Ge, lhs, rhs, span),
Rule::operation_gt => Expression::binary(BinaryOperation::Gt, lhs, rhs, span),
Rule::operation_le => Expression::binary(BinaryOperation::Le, lhs, rhs, span),
Rule::operation_lt => Expression::binary(BinaryOperation::Lt, lhs, rhs, span),
Rule::operation_add => Expression::binary(BinaryOperation::Add, lhs, rhs, span),
Rule::operation_sub => Expression::binary(BinaryOperation::Sub, lhs, rhs, span),
Rule::operation_mul => Expression::binary(BinaryOperation::Mul, lhs, rhs, span),
Rule::operation_div => Expression::binary(BinaryOperation::Div, lhs, rhs, span),
Rule::operation_pow => Expression::binary(BinaryOperation::Pow, lhs, rhs, span),
_ => unreachable!(),
})
}
impl<'ast> FromPest<'ast> for Expression<'ast> {
type Rule = Rule;
type FatalError = Void;
fn from_pest(pest: &mut Pairs<'ast, Rule>) -> Result<Self, ConversionError<Void>> {
let mut clone = pest.clone();
let pair = clone.next().ok_or(::from_pest::ConversionError::NoMatch)?;
match pair.as_rule() {
Rule::expression => {
// Transfer iterated state to pest.
*pest = clone;
Ok(*PRECEDENCE_CLIMBER.climb(pair.into_inner(), parse_term, binary_expression))
}
_ => Err(ConversionError::NoMatch),
}
}
}

View File

@ -0,0 +1,13 @@
use crate::{ast::Rule, circuits::CircuitMember, common::Identifier};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::circuit_definition))]
pub struct Circuit<'ast> {
pub identifier: Identifier<'ast>,
pub members: Vec<CircuitMember<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,13 @@
use crate::{ast::Rule, common::Identifier, expressions::Expression};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::circuit_field))]
pub struct CircuitField<'ast> {
pub identifier: Identifier<'ast>,
pub expression: Expression<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,13 @@
use crate::{ast::Rule, common::Identifier, types::Type};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::circuit_field_definition))]
pub struct CircuitFieldDefinition<'ast> {
pub identifier: Identifier<'ast>,
pub _type: Type<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,13 @@
use crate::{ast::Rule, common::Static, functions::Function};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::circuit_function))]
pub struct CircuitFunction<'ast> {
pub _static: Option<Static>,
pub function: Function<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,10 @@
use crate::{ast::Rule, circuits::{CircuitFunction, CircuitFieldDefinition}};
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::circuit_member))]
pub enum CircuitMember<'ast> {
CircuitFieldDefinition(CircuitFieldDefinition<'ast>),
CircuitFunction(CircuitFunction<'ast>),
}

14
ast/src/circuits/mod.rs Normal file
View File

@ -0,0 +1,14 @@
pub mod circuit;
pub use circuit::*;
pub mod circuit_field;
pub use circuit_field::*;
pub mod circuit_field_definition;
pub use circuit_field_definition::*;
pub mod circuit_function;
pub use circuit_function::*;
pub mod circuit_member;
pub use circuit_member::*;

View File

@ -0,0 +1,27 @@
use crate::{access::AssigneeAccess, ast::Rule, common::Identifier};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::assignee))]
pub struct Assignee<'ast> {
pub identifier: Identifier<'ast>,
pub accesses: Vec<AssigneeAccess<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for Assignee<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.identifier)?;
for (i, access) in self.accesses.iter().enumerate() {
write!(f, "{}", access)?;
if i < self.accesses.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, "")
}
}

7
ast/src/common/eoi.rs Normal file
View File

@ -0,0 +1,7 @@
use crate::ast::Rule;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::EOI))]
pub struct EOI;

View File

@ -0,0 +1,20 @@
use crate::ast::{span_into_string, Rule};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::identifier))]
pub struct Identifier<'ast> {
#[pest_ast(outer(with(span_into_string)))]
pub value: String,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for Identifier<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.value)
}
}

View File

@ -0,0 +1,7 @@
use crate::ast::Rule;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::LINE_END))]
pub struct LineEnd;

35
ast/src/common/mod.rs Normal file
View File

@ -0,0 +1,35 @@
pub mod assignee;
pub use assignee::*;
pub mod eoi;
pub use eoi::*;
pub mod identifier;
pub use identifier::*;
pub mod line_end;
pub use line_end::*;
pub mod mutable;
pub use mutable::*;
pub mod range;
pub use range::*;
pub mod range_or_expression;
pub use range_or_expression::*;
pub mod spread;
pub use spread::*;
pub mod spread_or_expression;
pub use spread_or_expression::*;
pub mod static_;
pub use static_::*;
pub mod variable;
pub use variable::*;
pub mod visibility;
pub use visibility::*;

View File

@ -0,0 +1,7 @@
use crate::ast::Rule;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::mutable))]
pub struct Mutable {}

21
ast/src/common/range.rs Normal file
View File

@ -0,0 +1,21 @@
use crate::{ast::Rule, expressions::Expression};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::range))]
pub struct Range<'ast> {
pub from: Option<FromExpression<'ast>>,
pub to: Option<ToExpression<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::from_expression))]
pub struct FromExpression<'ast>(pub Expression<'ast>);
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::to_expression))]
pub struct ToExpression<'ast>(pub Expression<'ast>);

View File

@ -0,0 +1,33 @@
use crate::{ast::Rule, common::Range, expressions::Expression};
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::range_or_expression))]
pub enum RangeOrExpression<'ast> {
Range(Range<'ast>),
Expression(Expression<'ast>),
}
impl<'ast> fmt::Display for RangeOrExpression<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
RangeOrExpression::Expression(ref expression) => write!(f, "{}", expression),
RangeOrExpression::Range(ref range) => write!(
f,
"{}..{}",
range
.from
.as_ref()
.map(|e| e.0.to_string())
.unwrap_or("".to_string()),
range
.to
.as_ref()
.map(|e| e.0.to_string())
.unwrap_or("".to_string())
),
}
}
}

19
ast/src/common/spread.rs Normal file
View File

@ -0,0 +1,19 @@
use crate::{ast::Rule, expressions::Expression};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::spread))]
pub struct Spread<'ast> {
pub expression: Expression<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for Spread<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "...{}", self.expression)
}
}

View File

@ -0,0 +1,20 @@
use crate::{ast::Rule, common::Spread, expressions::Expression};
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::spread_or_expression))]
pub enum SpreadOrExpression<'ast> {
Spread(Spread<'ast>),
Expression(Expression<'ast>),
}
impl<'ast> fmt::Display for SpreadOrExpression<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
SpreadOrExpression::Spread(ref spread) => write!(f, "{}", spread),
SpreadOrExpression::Expression(ref expression) => write!(f, "{}", expression),
}
}
}

View File

@ -0,0 +1,7 @@
use crate::ast::Rule;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::static_))]
pub struct Static {}

View File

@ -0,0 +1,31 @@
use crate::{ast::Rule, common::{Identifier, Mutable}, types::Type};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::variable))]
pub struct Variable<'ast> {
pub mutable: Option<Mutable>,
pub identifier: Identifier<'ast>,
pub _type: Option<Type<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for Variable<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(ref _mutable) = self.mutable {
write!(f, "mut ")?;
}
write!(f, "{}", self.identifier)?;
if let Some(ref _type) = self._type {
write!(f, ": {}", _type)?;
}
write!(f, "")
}
}

View File

@ -0,0 +1,18 @@
use crate::ast::Rule;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::visibility))]
pub enum Visibility {
Public(Public),
Private(Private),
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::visibility_public))]
pub struct Public {}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::visibility_private))]
pub struct Private {}

5
ast/src/errors/mod.rs Normal file
View File

@ -0,0 +1,5 @@
pub mod parser;
pub use parser::*;
pub mod syntax;
pub use syntax::*;

22
ast/src/errors/parser.rs Normal file
View File

@ -0,0 +1,22 @@
use crate::{ast::Rule, errors::SyntaxError};
use pest::error::Error;
use std::path::PathBuf;
#[derive(Debug, Error)]
pub enum ParserError {
#[error("Cannot read from the provided file path - {:?}", _0)]
FileReadError(PathBuf),
#[error("{}", _0)]
SyntaxError(#[from] SyntaxError),
#[error("Unable to construct abstract syntax tree")]
SyntaxTreeError,
}
impl From<Error<Rule>> for ParserError {
fn from(error: Error<Rule>) -> Self {
ParserError::SyntaxError(SyntaxError::from(error))
}
}

44
ast/src/errors/syntax.rs Normal file
View File

@ -0,0 +1,44 @@
use crate::ast::Rule;
use pest::error::Error;
#[derive(Debug, Error)]
pub enum SyntaxError {
#[error("aborting due to syntax error")]
Error,
}
impl From<Error<Rule>> for SyntaxError {
fn from(mut error: Error<Rule>) -> Self {
error = error.renamed_rules(|rule| match *rule {
Rule::LINE_END => "`;`".to_owned(),
Rule::type_integer => "`u32`".to_owned(),
Rule::type_field => "`field`".to_owned(),
Rule::type_group => "`group`".to_owned(),
Rule::file => "an import, circuit, or function".to_owned(),
Rule::identifier => "a variable name".to_owned(),
Rule::type_ => "a type".to_owned(),
Rule::access => "`.`, `::`, `()`".to_owned(),
Rule::operation_and => "`&&`".to_owned(),
Rule::operation_or => "`||`".to_owned(),
Rule::operation_eq => "`==`".to_owned(),
Rule::operation_ne => "`!=`".to_owned(),
Rule::operation_ge => "`>=`".to_owned(),
Rule::operation_gt => "`>`".to_owned(),
Rule::operation_le => "`<=`".to_owned(),
Rule::operation_lt => "`<`".to_owned(),
Rule::operation_add => "`+`".to_owned(),
Rule::operation_sub => "`-`".to_owned(),
Rule::operation_mul => "`*`".to_owned(),
Rule::operation_div => "`/`".to_owned(),
Rule::operation_pow => "`**`".to_owned(),
rule => format!("{:?}", rule),
});
log::error!("{}\n", error);
SyntaxError::Error
}
}

View File

@ -0,0 +1,13 @@
use crate::{ast::Rule, common::SpreadOrExpression, values::Value};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::expression_array_initializer))]
pub struct ArrayInitializerExpression<'ast> {
pub expression: Box<SpreadOrExpression<'ast>>,
pub count: Value<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,12 @@
use crate::{ast::Rule, common::SpreadOrExpression};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::expression_array_inline))]
pub struct ArrayInlineExpression<'ast> {
pub expressions: Vec<SpreadOrExpression<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,11 @@
use crate::{expressions::Expression, operations::BinaryOperation};
use pest::Span;
#[derive(Clone, Debug, PartialEq)]
pub struct BinaryExpression<'ast> {
pub operation: BinaryOperation,
pub left: Box<Expression<'ast>>,
pub right: Box<Expression<'ast>>,
pub span: Span<'ast>,
}

View File

@ -0,0 +1,13 @@
use crate::{ast::Rule, circuits::CircuitField, common::Identifier,};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::expression_circuit_inline))]
pub struct CircuitInlineExpression<'ast> {
pub identifier: Identifier<'ast>,
pub members: Vec<CircuitField<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,99 @@
use crate::{common::Identifier, expressions::*, operations::BinaryOperation, values::Value,};
use pest::Span;
use std::fmt;
#[derive(Clone, Debug, PartialEq)]
pub enum Expression<'ast> {
Value(Value<'ast>),
Identifier(Identifier<'ast>),
Not(NotExpression<'ast>),
Binary(BinaryExpression<'ast>),
Ternary(TernaryExpression<'ast>),
ArrayInline(ArrayInlineExpression<'ast>),
ArrayInitializer(ArrayInitializerExpression<'ast>),
CircuitInline(CircuitInlineExpression<'ast>),
Postfix(PostfixExpression<'ast>),
}
impl<'ast> Expression<'ast> {
pub fn binary(
operation: BinaryOperation,
left: Box<Expression<'ast>>,
right: Box<Expression<'ast>>,
span: Span<'ast>,
) -> Self {
Expression::Binary(BinaryExpression {
operation,
left,
right,
span,
})
}
pub fn ternary(
first: Box<Expression<'ast>>,
second: Box<Expression<'ast>>,
third: Box<Expression<'ast>>,
span: Span<'ast>,
) -> Self {
Expression::Ternary(TernaryExpression {
first,
second,
third,
span,
})
}
pub fn span(&self) -> &Span<'ast> {
match self {
Expression::Value(expression) => &expression.span(),
Expression::Identifier(expression) => &expression.span,
Expression::Not(expression) => &expression.span,
Expression::Binary(expression) => &expression.span,
Expression::Ternary(expression) => &expression.span,
Expression::ArrayInline(expression) => &expression.span,
Expression::ArrayInitializer(expression) => &expression.span,
Expression::CircuitInline(expression) => &expression.span,
Expression::Postfix(expression) => &expression.span,
}
}
}
impl<'ast> fmt::Display for Expression<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Expression::Value(ref expression) => write!(f, "{}", expression),
Expression::Identifier(ref expression) => write!(f, "{}", expression),
Expression::Not(ref expression) => write!(f, "!{}", expression.expression),
Expression::Binary(ref expression) => {
write!(f, "{} == {}", expression.left, expression.right)
}
Expression::Ternary(ref expression) => write!(
f,
"if {} ? {} : {}",
expression.first, expression.second, expression.third
),
Expression::ArrayInline(ref expression) => {
for (i, spread_or_expression) in expression.expressions.iter().enumerate() {
write!(f, "{}", spread_or_expression)?;
if i < expression.expressions.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, "")
}
Expression::ArrayInitializer(ref expression) => {
write!(f, "[{} ; {}]", expression.expression, expression.count)
}
Expression::CircuitInline(ref expression) => write!(
f,
"inline circuit display not impl {}",
expression.identifier
),
Expression::Postfix(ref expression) => {
write!(f, "Postfix display not impl {}", expression.identifier)
}
}
}
}

View File

@ -0,0 +1,23 @@
pub mod array_initializer_expression;
pub use array_initializer_expression::*;
pub mod array_inline_expression;
pub use array_inline_expression::*;
pub mod binary_expression;
pub use binary_expression::*;
pub mod circuit_inline_expression;
pub use circuit_inline_expression::*;
pub mod expression;
pub use expression::*;
pub mod not_expression;
pub use not_expression::*;
pub mod postfix_expression;
pub use postfix_expression::*;
pub mod ternary_expression;
pub use ternary_expression::*;

View File

@ -0,0 +1,13 @@
use crate::{ast::Rule, expressions::Expression, operations::NotOperation};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::expression_not))]
pub struct NotExpression<'ast> {
pub operation: NotOperation<'ast>,
pub expression: Box<Expression<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,13 @@
use crate::{access::Access, ast::Rule, common::Identifier};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::expression_postfix))]
pub struct PostfixExpression<'ast> {
pub identifier: Identifier<'ast>,
pub accesses: Vec<Access<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,14 @@
use crate::{ast::Rule, expressions::Expression};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::expression_conditional))]
pub struct TernaryExpression<'ast> {
pub first: Box<Expression<'ast>>,
pub second: Box<Expression<'ast>>,
pub third: Box<Expression<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

16
ast/src/files/file.rs Normal file
View File

@ -0,0 +1,16 @@
use crate::{ast::Rule, common::EOI, functions::{Function, TestFunction}, imports::Import, circuits::Circuit};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::file))]
pub struct File<'ast> {
pub imports: Vec<Import<'ast>>,
pub circuits: Vec<Circuit<'ast>>,
pub functions: Vec<Function<'ast>>,
pub tests: Vec<TestFunction<'ast>>,
pub eoi: EOI,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

2
ast/src/files/mod.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod file;
pub use file::*;

View File

@ -0,0 +1,15 @@
use crate::{ast::Rule, common::Identifier, functions::FunctionInput, statements::Statement, types::Type};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::function_definition))]
pub struct Function<'ast> {
pub function_name: Identifier<'ast>,
pub parameters: Vec<FunctionInput<'ast>>,
pub returns: Vec<Type<'ast>>,
pub statements: Vec<Statement<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,15 @@
use crate::{ast::Rule, common::{Identifier, Visibility, Mutable}, types::Type};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::function_input))]
pub struct FunctionInput<'ast> {
pub mutable: Option<Mutable>,
pub identifier: Identifier<'ast>,
pub visibility: Option<Visibility>,
pub _type: Type<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

8
ast/src/functions/mod.rs Normal file
View File

@ -0,0 +1,8 @@
pub mod function;
pub use function::*;
pub mod function_input;
pub use function_input::*;
pub mod test_function;
pub use test_function::*;

View File

@ -0,0 +1,12 @@
use crate::{ast::Rule, functions::Function};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::test_function))]
pub struct TestFunction<'ast> {
pub function: Function<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

14
ast/src/imports/import.rs Normal file
View File

@ -0,0 +1,14 @@
use crate::{ast::Rule, common::LineEnd, imports::{ImportSource, ImportSymbol}};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::import))]
pub struct Import<'ast> {
pub source: ImportSource<'ast>,
pub symbols: Vec<ImportSymbol<'ast>>,
pub line_end: LineEnd,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,13 @@
use crate::ast::{Rule, span_into_string};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::import_source))]
pub struct ImportSource<'ast> {
#[pest_ast(outer(with(span_into_string)))]
pub value: String,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,13 @@
use crate::{ast::Rule, common::Identifier};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::import_symbol))]
pub struct ImportSymbol<'ast> {
pub value: Identifier<'ast>,
pub alias: Option<Identifier<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

8
ast/src/imports/mod.rs Normal file
View File

@ -0,0 +1,8 @@
pub mod import;
pub use import::*;
pub mod import_source;
pub use import_source::*;
pub mod import_symbol;
pub use import_symbol::*;

299
ast/src/leo.pest Normal file
View File

@ -0,0 +1,299 @@
/// Common
// Declared in common/assignee.rs
assignee = { identifier ~ access_assignee* }
// Declared in common/file.rs
file = { SOI ~ NEWLINE* ~ import* ~ NEWLINE* ~ circuit_definition* ~ NEWLINE* ~ function_definition* ~ NEWLINE* ~ test_function* ~ NEWLINE* ~ EOI }
// Declared in common/identifier.rs
identifier = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHANUMERIC | "_"))) ~ (ASCII_ALPHANUMERIC | "_")* }
protected_name = { visibility | "let" | "for"| "if" | "else" | "as" | "return" }
// Declared in common/line_end.rs
LINE_END = { ";" ~ NEWLINE* }
// Declared in common/mutable.rs
mutable = { "mut" }
// Declared in common/range.rs
range = { from_expression? ~ ".." ~ to_expression }
from_expression = { expression }
to_expression = { expression }
// Declared in common/range_or_expression.rs
range_or_expression = { range | expression }
// Declared in common/spread.rs
spread = { "..." ~ expression }
// Declared in common/spread_or_expression.rs
spread_or_expression = { spread | expression }
// Declared in common/static_.rs
static_ = { "static" }
// Declared in common/variable.rs
variable = { mutable? ~ identifier ~ (":" ~ type_)? }
// Declared in common/visibility.rs
visibility = { visibility_public | visibility_private }
visibility_public = { "public" }
visibility_private = { "private" }
/// Operations
// Declared in operations/not_operation.rs
operation_not = { "!" }
// Declared in operations/binary_operation.rs
operation_and = { "&&" }
operation_or = { "||" }
operation_eq = { "==" }
operation_ne = { "!=" }
operation_ge = { ">=" }
operation_gt = { ">" }
operation_le = { "<=" }
operation_lt = { "<" }
operation_add = { "+" }
operation_sub = { "-" }
operation_mul = { "*" }
operation_div = { "/" }
operation_pow = { "**" }
operation_compare = _{
operation_eq | operation_ne |
operation_ge | operation_gt |
operation_le | operation_lt
}
operation_binary = _{
operation_compare | operation_and | operation_or |
operation_add | operation_sub | operation_pow | operation_mul | operation_div
}
// Declared in operations/assign_operation.rs
operation_assign = {
assign | operation_add_assign | operation_sub_assign |
operation_mul_assign | operation_div_assign | operation_pow_assign
}
assign = { "=" }
operation_add_assign = { "+=" }
operation_sub_assign = { "-=" }
operation_mul_assign = { "*=" }
operation_div_assign = { "/=" }
operation_pow_assign = { "**=" }
/// Types
// Declared in types/type_.rs
type_ = { type_self | type_array | type_data | type_circuit }
// Declared in types/integer.rs
type_integer = {
type_u8
| type_u16
| type_u32
| type_u64
| type_u128
}
type_u8 = { "u8" }
type_u16 = { "u16" }
type_u32 = { "u32" }
type_u64 = { "u64" }
type_u128 = { "u128" }
// Declared in types/field_type.rs
type_field = { "field" }
// Declared in types/group_type.rs
type_group = { "group" }
// Declared in types/boolean_type.rs
type_boolean = { "bool" }
// Declared in types/data_type.rs
type_data = { type_field | type_group | type_boolean | type_integer }
// Declared in types/self_type.rs
type_self = { "Self" }
// Declared in types/self_type.rs
type_circuit = { identifier }
// Declared in types/array_type.rs
type_array = { type_data ~ ("[" ~ value ~ "]")+ }
type_list = _{ (type_ ~ ("," ~ type_)*)? }
/// Values
// Declared in values/value.rs
value = { value_field | value_group | value_boolean | value_integer | value_implicit }
// Declared in values/number_value.rs
value_number = @{ "0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT* }
// Declared in values/number_implicit_value.rs
value_implicit = { value_number }
// Declared in values/integer_value.rs
value_integer = { value_number ~ type_integer }
// Declared in values/boolean_value.rs
value_boolean = { "true" | "false" }
// Declared in values/field_value.rs
value_field = { value_number ~ type_field }
// Declared in values/group_value.rs
value_group = { group_single_or_tuple ~ type_group }
group_tuple = {"(" ~ value_number ~ "," ~ value_number ~ ")"}
group_single_or_tuple = {value_number | group_tuple}
/// Access
// Declared in access/access.rs
access = { access_array | access_call | access_member | access_static_member}
// Declared in access/array_access.rs
access_array = { "[" ~ range_or_expression ~ "]" }
// Declared in access/assignee_access.rs
access_assignee = { access_array | access_member }
// Declared in access/call_access.rs
access_call = { "(" ~ expression_tuple ~ ")" }
// Declared in access/member_access.rs
access_member = { "." ~ identifier }
// Declared in access/static_member_access.rs
access_static_member = { "::" ~ identifier }
/// Circuits
// Declared in circuits/circuit_definition.rs
circuit_definition = { "circuit" ~ identifier ~ "{" ~ NEWLINE* ~ circuit_member* ~ NEWLINE* ~ "}" ~ NEWLINE* }
// Declared in circuits/circuit_field.rs
circuit_field = { identifier ~ ":" ~ expression }
// Declared in circuits/circuit_field_definition.rs
circuit_field_definition = { identifier ~ ":" ~ type_ ~ NEWLINE* }
// Declared in circuits/circuit_function.rs
circuit_function = { static_? ~ function_definition }
// Declared in circuits/circuit_member.rs
circuit_member = { circuit_function | circuit_field_definition }
/// Conditionals
expression_conditional = { "if" ~ expression ~ "?" ~ expression ~ ":" ~ expression}
/// Expressions
expression_term = {
("(" ~ expression ~ ")")
| expression_array_initializer
| expression_array_inline
| expression_circuit_inline
| expression_conditional
| expression_not
| expression_postfix
| expression_primitive
}
expression_primitive = { value | identifier }
expression_tuple = _{ (expression ~ ("," ~ expression)*)? }
// Declared in expressions/expression.rs
expression = { expression_term ~ (operation_binary ~ expression_term)* }
// Declared in expressions/array_initializer_expression.rs
expression_array_initializer = { "[" ~ spread_or_expression ~ ";" ~ value ~ "]" }
// Declared in expressions/array_inline_expression.rs
expression_array_inline = { "[" ~ NEWLINE* ~ inline_array_inner ~ NEWLINE* ~ "]"}
inline_array_inner = _{(spread_or_expression ~ ("," ~ NEWLINE* ~ spread_or_expression)*)?}
// Declared in expressions/circuit_inline_expression.rs
expression_circuit_inline = { identifier ~ "{" ~ NEWLINE* ~ circuit_field_list ~ NEWLINE* ~ "}" }
circuit_field_list = _{ (circuit_field ~ ("," ~ NEWLINE* ~ circuit_field)*)? ~ ","? }
// Declared in expressions/not_expression.rs
expression_not = { operation_not ~ expression_term }
// Declared in expressions/postfix_expression.rs
expression_postfix = { identifier ~ access+ }
/// Statements
// Declared in statements/statement.rs
statement = {
(statement_return
| statement_conditional
| statement_for
| (statement_multiple_assignment
| statement_assert
| statement_definition
| statement_assign
| statement_expression
)
) ~ NEWLINE*
}
// Declared in statements/assert_statement.rs
statement_assert = { assert_eq }
assert_eq = {"assert_eq!" ~ "(" ~ NEWLINE* ~ expression ~ "," ~ NEWLINE* ~ expression ~ NEWLINE* ~ ")" ~ LINE_END}
// Declared in statements/assign_statement.rs
statement_assign = { assignee ~ operation_assign ~ expression ~ LINE_END }
// Declared in statements/conditional_statement.rs
statement_conditional = {"if" ~ (expression | "(" ~ expression ~ ")") ~ "{" ~ NEWLINE* ~ statement+ ~ "}" ~ ("else" ~ conditional_nested_or_end_statement)?}
conditional_nested_or_end_statement = { statement_conditional | "{" ~ NEWLINE* ~ statement+ ~ "}"}
// Declared in statements/definition_statement.rs
statement_definition = { "let" ~ variable ~ "=" ~ expression ~ LINE_END}
// Declared in statements/expression_statement.rs
statement_expression = { expression ~ LINE_END }
// Declared in statements/for_statement.rs
statement_for = { "for" ~ identifier ~ "in" ~ expression ~ ".." ~ expression ~ "{" ~ NEWLINE* ~ statement+ ~ "}"}
// Declared in statements/multiple_assignment_statement.rs
statement_multiple_assignment = { "let" ~ "(" ~ variable_tuple ~ ")" ~ "=" ~ identifier ~ "(" ~ expression_tuple ~ ")" ~ LINE_END}
variable_tuple = _{ variable ~ ("," ~ variable)* }
// Declared in statements/return_statement.rs
statement_return = { "return" ~ expression_tuple }
/// Functions
// Declared in functions/function.rs
function_definition = { "function" ~ identifier ~ "(" ~ input_model_list ~ ")" ~ ("->" ~ (type_ | "(" ~ type_list ~ ")"))? ~ "{" ~ NEWLINE* ~ statement* ~ NEWLINE* ~ "}" ~ NEWLINE* }
// Declared in functions/function_input.rs
function_input = { mutable? ~ identifier ~ ":" ~ visibility? ~ type_ }
input_model_list = _{ (function_input ~ ("," ~ function_input)*)? }
// Declared in functions/test_function.rs
test_function = { "test" ~ function_definition }
/// Imports
// Declared in imports/import.rs
import = { "from" ~ "\"" ~ import_source ~ "\"" ~ "import" ~ ("*" | ("{" ~ NEWLINE* ~ import_symbol_tuple ~ NEWLINE* ~ "}") | import_symbol) ~ LINE_END}
// Declared in imports/import_source.rs
import_source = @{ (!"\"" ~ ANY)* }
// Declared in imports/import_symbol.rs
import_symbol = { identifier ~ ("as" ~ identifier)? }
import_symbol_tuple = _{ import_symbol ~ ("," ~ NEWLINE* ~ import_symbol)* }
/// Utilities
COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | ("//" ~ (!NEWLINE ~ ANY)*) }
WHITESPACE = _{ " " | "\t" ~ (NEWLINE)* }

48
ast/src/lib.rs Normal file
View File

@ -0,0 +1,48 @@
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate pest_derive;
#[macro_use]
extern crate thiserror;
pub mod errors;
pub use errors::*;
pub mod access;
mod ast;
pub mod circuits;
pub mod common;
pub mod expressions;
pub mod files;
pub mod functions;
pub mod imports;
pub mod operations;
pub mod statements;
pub mod values;
pub mod types;
use from_pest::FromPest;
use std::{path::PathBuf, fs};
pub struct LeoParser;
impl LeoParser {
/// Reads in the given file path into a string.
pub fn load_file(file_path: &PathBuf) -> Result<String, ParserError> {
Ok(fs::read_to_string(file_path).map_err(|_| ParserError::FileReadError(file_path.clone()))?)
}
/// Parses the input file and constructs a syntax tree.
pub fn parse_file<'a>(file_path: &'a PathBuf, input_file: &'a str) -> Result<files::File<'a>, ParserError> {
// Parse the file using leo.pest
let mut file = ast::parse(input_file).map_err(|error| {
ParserError::from(error.with_path(file_path.to_str().unwrap()))
})?;
// Build the abstract syntax tree
let syntax_tree = files::File::from_pest(&mut file).map_err(|_| ParserError::SyntaxTreeError)?;
log::debug!("{:#?}", syntax_tree);
Ok(syntax_tree)
}
}

View File

@ -0,0 +1,38 @@
use crate::ast::Rule;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::operation_assign))]
pub enum AssignOperation {
Assign(Assign),
AddAssign(AddAssign),
SubAssign(SubAssign),
MulAssign(MulAssign),
DivAssign(DivAssign),
PowAssign(PowAssign),
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::assign))]
pub struct Assign {}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::operation_add_assign))]
pub struct AddAssign {}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::operation_sub_assign))]
pub struct SubAssign {}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::operation_mul_assign))]
pub struct MulAssign {}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::operation_div_assign))]
pub struct DivAssign {}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::operation_pow_assign))]
pub struct PowAssign {}

View File

@ -0,0 +1,21 @@
use crate::ast::Rule;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::operation_binary))]
pub enum BinaryOperation {
Or,
And,
Eq,
Ne,
Ge,
Gt,
Le,
Lt,
Add,
Sub,
Mul,
Div,
Pow,
}

View File

@ -0,0 +1,8 @@
pub mod assign_operation;
pub use assign_operation::*;
pub mod binary_operation;
pub use binary_operation::*;
pub mod not_operation;
pub use not_operation::*;

View File

@ -0,0 +1,11 @@
use crate::ast::Rule;
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::operation_not))]
pub struct NotOperation<'ast> {
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,31 @@
use crate::{ast::Rule, common::LineEnd, expressions::Expression};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::statement_assert))]
pub enum AssertStatement<'ast> {
AssertEq(AssertEq<'ast>),
}
impl<'ast> fmt::Display for AssertStatement<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
AssertStatement::AssertEq(ref assert) => {
write!(f, "assert_eq({}, {});", assert.left, assert.right)
}
}
}
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::assert_eq))]
pub struct AssertEq<'ast> {
pub left: Expression<'ast>,
pub right: Expression<'ast>,
pub line_end: LineEnd,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,22 @@
use crate::{ast::Rule, common::{Assignee, LineEnd}, expressions::Expression, operations::AssignOperation};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::statement_assign))]
pub struct AssignStatement<'ast> {
pub assignee: Assignee<'ast>,
pub assign: AssignOperation,
pub expression: Expression<'ast>,
pub line_end: LineEnd,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for AssignStatement<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} = {};", self.assignee, self.expression)
}
}

View File

@ -0,0 +1,22 @@
use crate::{ast::Rule, statements::{ConditionalStatement, Statement}};
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::conditional_nested_or_end_statement))]
pub enum ConditionalNestedOrEndStatement<'ast> {
Nested(Box<ConditionalStatement<'ast>>),
End(Vec<Statement<'ast>>),
}
impl<'ast> fmt::Display for ConditionalNestedOrEndStatement<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ConditionalNestedOrEndStatement::Nested(ref nested) => write!(f, "else {}", nested),
ConditionalNestedOrEndStatement::End(ref statements) => {
write!(f, "else {{\n \t{:#?}\n }}", statements)
}
}
}
}

View File

@ -0,0 +1,26 @@
use crate::{ast::Rule, expressions::Expression, statements::{ConditionalNestedOrEndStatement, Statement}};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::statement_conditional))]
pub struct ConditionalStatement<'ast> {
pub condition: Expression<'ast>,
pub statements: Vec<Statement<'ast>>,
pub next: Option<ConditionalNestedOrEndStatement<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for ConditionalStatement<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "if ({}) {{\n", self.condition)?;
write!(f, "\t{:#?}\n", self.statements)?;
self.next
.as_ref()
.map(|n_or_e| write!(f, "}} {}", n_or_e))
.unwrap_or(write!(f, "}}"))
}
}

View File

@ -0,0 +1,21 @@
use crate::{ast::Rule, common::{LineEnd, Variable}, expressions::Expression};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::statement_definition))]
pub struct DefinitionStatement<'ast> {
pub variable: Variable<'ast>,
pub expression: Expression<'ast>,
pub line_end: LineEnd,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for DefinitionStatement<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "let {} = {};", self.variable, self.expression)
}
}

View File

@ -0,0 +1,13 @@
use crate::{ast::Rule, common::LineEnd, expressions::Expression};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::statement_expression))]
pub struct ExpressionStatement<'ast> {
pub expression: Expression<'ast>,
pub line_end: LineEnd,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,26 @@
use crate::{ast::Rule, expressions::{Expression}, statements::Statement, common::Identifier};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::statement_for))]
pub struct ForStatement<'ast> {
pub index: Identifier<'ast>,
pub start: Expression<'ast>,
pub stop: Expression<'ast>,
pub statements: Vec<Statement<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for ForStatement<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"for {} in {}..{} {{ {:#?} }}",
self.index, self.start, self.stop, self.statements
)
}
}

29
ast/src/statements/mod.rs Normal file
View File

@ -0,0 +1,29 @@
pub mod assert_statement;
pub use assert_statement::*;
pub mod assign_statement;
pub use assign_statement::*;
pub mod conditional_statement;
pub use conditional_statement::*;
pub mod conditional_nested_or_end_statement;
pub use conditional_nested_or_end_statement::*;
pub mod definition_statement;
pub use definition_statement::*;
pub mod expression_statement;
pub use expression_statement::*;
pub mod for_statement;
pub use for_statement::*;
pub mod multiple_assignment_statement;
pub use multiple_assignment_statement::*;
pub mod return_statement;
pub use return_statement::*;
pub mod statement;
pub use statement::*;

View File

@ -0,0 +1,28 @@
use crate::{ast::Rule, common::{Identifier, LineEnd, Variable}, expressions::{Expression}};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::statement_multiple_assignment))]
pub struct MultipleAssignmentStatement<'ast> {
pub variables: Vec<Variable<'ast>>,
pub function_name: Identifier<'ast>,
pub arguments: Vec<Expression<'ast>>,
pub line_end: LineEnd,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for MultipleAssignmentStatement<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for (i, id) in self.variables.iter().enumerate() {
write!(f, "{}", id)?;
if i < self.variables.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, " = {}", self.function_name)
}
}

View File

@ -0,0 +1,25 @@
use crate::{ast::Rule, expressions::Expression};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::statement_return))]
pub struct ReturnStatement<'ast> {
pub expressions: Vec<Expression<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for ReturnStatement<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for (i, expression) in self.expressions.iter().enumerate() {
write!(f, "{}", expression)?;
if i < self.expressions.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, "")
}
}

View File

@ -0,0 +1,32 @@
use crate::{ast::Rule, statements::*};
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::statement))]
pub enum Statement<'ast> {
Return(ReturnStatement<'ast>),
Definition(DefinitionStatement<'ast>),
Assign(AssignStatement<'ast>),
MultipleAssignment(MultipleAssignmentStatement<'ast>),
Conditional(ConditionalStatement<'ast>),
Iteration(ForStatement<'ast>),
Assert(AssertStatement<'ast>),
Expression(ExpressionStatement<'ast>),
}
impl<'ast> fmt::Display for Statement<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Statement::Return(ref statement) => write!(f, "{}", statement),
Statement::Definition(ref statement) => write!(f, "{}", statement),
Statement::Assign(ref statement) => write!(f, "{}", statement),
Statement::MultipleAssignment(ref statement) => write!(f, "{}", statement),
Statement::Conditional(ref statement) => write!(f, "{}", statement),
Statement::Iteration(ref statement) => write!(f, "{}", statement),
Statement::Assert(ref statement) => write!(f, "{}", statement),
Statement::Expression(ref statement) => write!(f, "{}", statement.expression),
}
}
}

View File

@ -0,0 +1,13 @@
use crate::{ast::Rule, types::DataType, values::Value};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::type_array))]
pub struct ArrayType<'ast> {
pub _type: DataType,
pub dimensions: Vec<Value<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,7 @@
use crate::ast::Rule;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::type_boolean))]
pub struct BooleanType {}

View File

@ -0,0 +1,12 @@
use crate::{ast::Rule, common::Identifier};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::type_circuit))]
pub struct CircuitType<'ast> {
pub identifier: Identifier<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -0,0 +1,12 @@
use crate::{ast::Rule, types::{IntegerType, FieldType, GroupType, BooleanType}};
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::type_data))]
pub enum DataType {
Integer(IntegerType),
Field(FieldType),
Group(GroupType),
Boolean(BooleanType),
}

View File

@ -0,0 +1,7 @@
use crate::ast::Rule;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::type_field))]
pub struct FieldType {}

View File

@ -0,0 +1,7 @@
use crate::ast::Rule;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::type_group))]
pub struct GroupType {}

View File

@ -0,0 +1,33 @@
use crate::ast::Rule;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::type_integer))]
pub enum IntegerType {
U8Type(U8Type),
U16Type(U16Type),
U32Type(U32Type),
U64Type(U64Type),
U128Type(U128Type),
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::type_u8))]
pub struct U8Type {}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::type_u16))]
pub struct U16Type {}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::type_u32))]
pub struct U32Type {}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::type_u64))]
pub struct U64Type {}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::type_u128))]
pub struct U128Type {}

26
ast/src/types/mod.rs Normal file
View File

@ -0,0 +1,26 @@
pub mod array_type;
pub use array_type::*;
pub mod boolean_type;
pub use boolean_type::*;
pub mod circuit_type;
pub use circuit_type::*;
pub mod data_type;
pub use data_type::*;
pub mod field_type;
pub use field_type::*;
pub mod group_type;
pub use group_type::*;
pub mod integer_type;
pub use integer_type::*;
pub mod self_type;
pub use self_type::*;
pub mod type_;
pub use type_::*;

View File

@ -0,0 +1,7 @@
use crate::ast::Rule;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::type_self))]
pub struct SelfType {}

24
ast/src/types/type_.rs Normal file
View File

@ -0,0 +1,24 @@
use crate::{ast::Rule, types::*};
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::type_))]
pub enum Type<'ast> {
Basic(DataType),
Array(ArrayType<'ast>),
Circuit(CircuitType<'ast>),
SelfType(SelfType),
}
impl<'ast> fmt::Display for Type<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Type::Basic(ref _type) => write!(f, "basic"),
Type::Array(ref _type) => write!(f, "array"),
Type::Circuit(ref _type) => write!(f, "struct"),
Type::SelfType(ref _type) => write!(f, "Self"),
}
}
}

View File

@ -0,0 +1,20 @@
use crate::ast::{Rule, span_into_string};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::value_boolean))]
pub struct BooleanValue<'ast> {
#[pest_ast(outer(with(span_into_string)))]
pub value: String,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for BooleanValue<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.value)
}
}

View File

@ -0,0 +1,20 @@
use crate::{ast::Rule, types::FieldType, values::NumberValue,};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::value_field))]
pub struct FieldValue<'ast> {
pub number: NumberValue<'ast>,
pub _type: FieldType,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for FieldValue<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.number)
}
}

View File

@ -0,0 +1,51 @@
use crate::{ast::Rule, types::GroupType, values::NumberValue,};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::value_group))]
pub struct GroupValue<'ast> {
pub value: GroupRepresentation<'ast>,
pub _type: GroupType,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for GroupValue<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.value)
}
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::group_single_or_tuple))]
pub enum GroupRepresentation<'ast> {
Single(NumberValue<'ast>),
Tuple(GroupTuple<'ast>),
}
impl<'ast> fmt::Display for GroupRepresentation<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
GroupRepresentation::Single(number) => write!(f, "{}", number),
GroupRepresentation::Tuple(tuple) => write!(f, "{}", tuple),
}
}
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::group_tuple))]
pub struct GroupTuple<'ast> {
pub x: NumberValue<'ast>,
pub y: NumberValue<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for GroupTuple<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}

View File

@ -0,0 +1,20 @@
use crate::{ast::Rule, types::IntegerType, values::NumberValue};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::value_integer))]
pub struct IntegerValue<'ast> {
pub number: NumberValue<'ast>,
pub _type: IntegerType,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for IntegerValue<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.number)
}
}

20
ast/src/values/mod.rs Normal file
View File

@ -0,0 +1,20 @@
pub mod boolean_value;
pub use boolean_value::*;
pub mod field_value;
pub use field_value::*;
pub mod group_value;
pub use group_value::*;
pub mod integer_value;
pub use integer_value::*;
pub mod number_implicit_value;
pub use number_implicit_value::*;
pub mod number_value;
pub use number_value::*;
pub mod value;
pub use value::*;

View File

@ -0,0 +1,19 @@
use crate::{ast::Rule, values::NumberValue};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::value_implicit))]
pub struct NumberImplicitValue<'ast> {
pub number: NumberValue<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for NumberImplicitValue<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.number)
}
}

View File

@ -0,0 +1,20 @@
use crate::ast::{Rule, span_into_string};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::value_number))]
pub struct NumberValue<'ast> {
#[pest_ast(outer(with(span_into_string)))]
pub value: String,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for NumberValue<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.value)
}
}

39
ast/src/values/value.rs Normal file
View File

@ -0,0 +1,39 @@
use crate::{ast::Rule, values::{BooleanValue, IntegerValue, FieldValue, GroupValue, NumberImplicitValue}};
use pest::Span;
use pest_ast::FromPest;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::value))]
pub enum Value<'ast> {
Integer(IntegerValue<'ast>),
Field(FieldValue<'ast>),
Group(GroupValue<'ast>),
Boolean(BooleanValue<'ast>),
Implicit(NumberImplicitValue<'ast>),
}
impl<'ast> Value<'ast> {
pub fn span(&self) -> &Span<'ast> {
match self {
Value::Integer(value) => &value.span,
Value::Field(value) => &value.span,
Value::Group(value) => &value.span,
Value::Boolean(value) => &value.span,
Value::Implicit(value) => &value.span,
}
}
}
impl<'ast> fmt::Display for Value<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Value::Integer(ref value) => write!(f, "{}", value),
Value::Field(ref value) => write!(f, "{}", value),
Value::Group(ref value) => write!(f, "{}", value),
Value::Boolean(ref value) => write!(f, "{}", value),
Value::Implicit(ref value) => write!(f, "{}", value),
}
}
}

View File

@ -1,17 +0,0 @@
[package]
name = "leo-benchmark"
version = "0.1.0"
authors = ["The Aleo Team <hello@aleo.org>"]
edition = "2018"
[dependencies]
leo-compiler = { path = "../compiler", version = "0.1.0" }
snarkos-algorithms = { path = "../../snarkOS/algorithms", version = "0.8.0" }
snarkos-curves = { path = "../../snarkOS/curves", version = "0.8.0" }
snarkos-errors = { path = "../../snarkOS/errors", version = "0.8.0" }
snarkos-gadgets = { path = "../../snarkOS/gadgets", version = "0.8.0" }
snarkos-models = { path = "../../snarkOS/models", version = "0.8.0" }
from-pest = { version = "0.3.1" }
rand = { version = "0.7" }

View File

@ -1,15 +0,0 @@
struct Foo {
x: u32
y: u32
}
function main(a: private fe) {
let b = a + 1fe;
assert_eq(b, 2fe);
let c = Foo {
x: 4,
y: 5,
};
}

View File

@ -1,8 +0,0 @@
struct Point {
u32 x
u32 y
}
function test() -> (u32) {
return 5
}

View File

@ -1,131 +0,0 @@
use leo_compiler::{self, ast, errors::CompilerError, ParameterValue, Program};
use from_pest::FromPest;
use rand::thread_rng;
use snarkos_algorithms::snark::{
create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof,
};
use snarkos_curves::bls12_377::{Bls12_377, Fr};
use snarkos_errors::gadgets::SynthesisError;
use snarkos_models::{
curves::{Field, PrimeField},
gadgets::r1cs::{ConstraintSynthesizer, ConstraintSystem},
};
use std::{
fs,
marker::PhantomData,
time::{Duration, Instant},
};
#[derive(Clone)]
pub struct Benchmark<F: Field + PrimeField> {
program: Program<F>,
parameters: Vec<Option<ParameterValue<F>>>,
_engine: PhantomData<F>,
}
impl<F: Field + PrimeField> Benchmark<F> {
pub fn new() -> Self {
Self {
program: Program::new(),
parameters: vec![],
_engine: PhantomData,
}
}
pub fn evaluate_program(&mut self) -> Result<(), CompilerError> {
// Read in file as string
let unparsed_file = fs::read_to_string("simple.leo").expect("cannot read file");
// Parse the file using leo.pest
let mut file = ast::parse(&unparsed_file).expect("unsuccessful parse");
// Build the abstract syntax tree
let syntax_tree = ast::File::from_pest(&mut file).expect("infallible");
// println!("{:#?}", syntax_tree);
// Build a leo program from the syntax tree
self.program = Program::<F>::from(syntax_tree, "simple".into());
self.parameters = vec![None; self.program.num_parameters];
println!(" compiled: {:#?}\n", self.program);
Ok(())
}
}
impl<F: Field + PrimeField> ConstraintSynthesizer<F> for Benchmark<F> {
fn generate_constraints<CS: ConstraintSystem<F>>(
self,
cs: &mut CS,
) -> Result<(), SynthesisError> {
let _res =
leo_compiler::ResolvedProgram::generate_constraints(cs, self.program, self.parameters);
println!(" Result: {}", _res);
// Write results to file or something
Ok(())
}
}
fn main() {
let mut setup = Duration::new(0, 0);
let mut proving = Duration::new(0, 0);
let mut verifying = Duration::new(0, 0);
let rng = &mut thread_rng();
let start = Instant::now();
// Load and compile program
let mut program = Benchmark::<Fr>::new();
program.evaluate_program().unwrap();
// Generate proof parameters
let params = { generate_random_parameters::<Bls12_377, _, _>(program.clone(), rng).unwrap() };
let prepared_verifying_key = prepare_verifying_key::<Bls12_377>(&params.vk);
setup += start.elapsed();
let start = Instant::now();
// Set main function arguments in compiled program
let argument = Some(ParameterValue::Field(Fr::one()));
program.parameters = vec![argument];
// Generate proof
let proof = create_random_proof(program, &params, rng).unwrap();
proving += start.elapsed();
let start = Instant::now();
// let public_input = Fr::one();
// Verify proof
let is_success = verify_proof(&prepared_verifying_key, &proof, &[]).unwrap();
verifying += start.elapsed();
println!(" ");
println!(" Setup time : {:?} milliseconds", setup.as_millis());
println!(" Prover time : {:?} milliseconds", proving.as_millis());
println!(
" Verifier time : {:?} milliseconds",
verifying.as_millis()
);
println!(" Verifier output : {}", is_success);
println!(" ");
// let mut cs = TestConstraintSystem::<Fr>::new();
//
// println!("\n satisfied: {:?}", cs.is_satisfied());
//
// println!(
// "\n number of constraints for input: {}",
// cs.num_constraints()
// );
//
}

View File

@ -5,19 +5,18 @@ authors = ["The Aleo Team <hello@aleo.org>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
leo-ast = { path = "../ast", version = "0.1.0" }
leo-types = { path = "../types", version = "0.1.0" }
snarkos-algorithms = { path = "../../snarkOS/algorithms", version = "0.8.0" } snarkos-algorithms = { path = "../../snarkOS/algorithms", version = "0.8.0" }
snarkos-curves = { path = "../../snarkOS/curves", version = "0.8.0" } snarkos-curves = { path = "../../snarkOS/curves", version = "0.8.0" }
snarkos-errors = { path = "../../snarkOS/errors", version = "0.8.0" } snarkos-errors = { path = "../../snarkOS/errors", version = "0.8.0" }
snarkos-gadgets = { path = "../../snarkOS/gadgets", version = "0.8.0" } snarkos-gadgets = { path = "../../snarkOS/gadgets", version = "0.8.0" }
snarkos-models = { path = "../../snarkOS/models", version = "0.8.0" } snarkos-models = { path = "../../snarkOS/models", version = "0.8.0" }
snarkos-utilities = { path = "../../snarkOS/utilities", version = "0.8.0" }
failure = { version = "0.1.5" }
from-pest = { version = "0.3.1" }
hex = { version = "0.4.2" } hex = { version = "0.4.2" }
lazy_static = { version = "1.3.0" }
log = { version = "0.4" } log = { version = "0.4" }
pest = { version = "2.0" }
pest-ast = { version = "0.3.3" }
pest_derive = { version = "2.0" }
rand = { version = "0.7" } rand = { version = "0.7" }
sha2 = { version = "0.8" } sha2 = { version = "0.8" }
thiserror = { version = "1.0" }

File diff suppressed because it is too large Load Diff

View File

@ -1,37 +1,51 @@
//! Compiles a Leo program from a file path. //! Compiles a Leo program from a file path.
use crate::{ast, errors::CompilerError, ParameterValue, Program, ResolvedProgram, ResolvedValue}; use crate::{
constraints::{generate_constraints, generate_test_constraints, ConstrainedValue},
errors::CompilerError,
GroupType,
};
use leo_ast::LeoParser;
use leo_types::{InputValue, Program};
use snarkos_errors::gadgets::SynthesisError; use snarkos_errors::gadgets::SynthesisError;
use snarkos_models::{ use snarkos_models::{
curves::{Field, PrimeField}, curves::{Field, PrimeField},
gadgets::r1cs::{ConstraintSynthesizer, ConstraintSystem}, gadgets::r1cs::{ConstraintSynthesizer, ConstraintSystem, TestConstraintSystem},
}; };
use from_pest::FromPest;
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use std::{fs, marker::PhantomData, path::PathBuf}; use std::{fs, marker::PhantomData, path::PathBuf};
#[derive(Clone)] #[derive(Clone)]
pub struct Compiler<F: Field + PrimeField> { pub struct Compiler<F: Field + PrimeField, G: GroupType<F>> {
package_name: String, package_name: String,
main_file_path: PathBuf, main_file_path: PathBuf,
program: Program<F>, program: Program,
parameters: Vec<Option<ParameterValue<F>>>, program_inputs: Vec<Option<InputValue>>,
output: Option<ResolvedValue<F>>, output: Option<ConstrainedValue<F, G>>,
_engine: PhantomData<F>, _engine: PhantomData<F>,
} }
impl<F: Field + PrimeField> Compiler<F> { impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
pub fn init(package_name: String, main_file_path: PathBuf) -> Self { pub fn init(package_name: String, main_file_path: PathBuf) -> Result<Self, CompilerError> {
Self { let mut program = Self {
package_name, package_name,
main_file_path, main_file_path,
program: Program::new(), program: Program::new(),
parameters: vec![], program_inputs: vec![],
output: None, output: None,
_engine: PhantomData, _engine: PhantomData,
};
// Generate the abstract syntax tree and assemble the program
program.parse_program()?;
Ok(program)
} }
pub fn set_inputs(&mut self, program_inputs: Vec<Option<InputValue>>) {
self.program_inputs = program_inputs;
} }
pub fn checksum(&self) -> Result<String, CompilerError> { pub fn checksum(&self) -> Result<String, CompilerError> {
@ -47,51 +61,45 @@ impl<F: Field + PrimeField> Compiler<F> {
Ok(hex::encode(hash)) Ok(hex::encode(hash))
} }
// pub fn compile(&self) -> Result<ast::File, CompilerError> { pub fn compile_constraints<CS: ConstraintSystem<F>>(
// // Read in the main file as string self,
// let unparsed_file = fs::read_to_string(&self.main_file_path).map_err(|_| CompilerError::FileReadError(self.main_file_path.clone()))?; cs: &mut CS,
// ) -> Result<ConstrainedValue<F, G>, CompilerError> {
// // Parse the file using leo.pest generate_constraints(cs, self.program, self.program_inputs)
// let mut file = ast::parse(&unparsed_file).map_err(|_| CompilerError::FileParsingError)?; }
//
// // Build the abstract syntax tree
// let syntax_tree = ast::File::from_pest(&mut file).map_err(|_| CompilerError::SyntaxTreeError)?;
// log::debug!("{:#?}", syntax_tree);
//
// Ok(syntax_tree)
// }
pub fn evaluate_program<CS: ConstraintSystem<F>>(&mut self) -> Result<(), CompilerError> { pub fn compile_test_constraints(
// Read in the main file as string self,
let unparsed_file = fs::read_to_string(&self.main_file_path) cs: &mut TestConstraintSystem<F>,
.map_err(|_| CompilerError::FileReadError(self.main_file_path.clone()))?; ) -> Result<(), CompilerError> {
generate_test_constraints::<F, G>(cs, self.program)
}
// Parse the file using leo.pest fn parse_program(&mut self) -> Result<(), CompilerError> {
let mut file = ast::parse(&unparsed_file).map_err(|_| CompilerError::FileParsingError)?; // Build the program syntax tree
let file_path = &self.main_file_path;
let input_file = &LeoParser::load_file(file_path)?;
let syntax_tree = LeoParser::parse_file(file_path, input_file)?;
// Build the abstract syntax tree // Build program from syntax tree
let syntax_tree =
ast::File::from_pest(&mut file).map_err(|_| CompilerError::SyntaxTreeError)?;
log::debug!("{:#?}", syntax_tree);
// Build program from abstract syntax tree
let package_name = self.package_name.clone(); let package_name = self.package_name.clone();
self.program = Program::<F>::from(syntax_tree, package_name); self.program = Program::from(syntax_tree, package_name);
self.parameters = vec![None; self.program.num_parameters]; self.program_inputs = vec![None; self.program.num_parameters];
log::debug!("Compilation complete\n{:#?}", self.program); log::debug!("Program parsing complete\n{:#?}", self.program);
Ok(()) Ok(())
} }
} }
impl<F: Field + PrimeField> ConstraintSynthesizer<F> for Compiler<F> { impl<F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compiler<F, G> {
fn generate_constraints<CS: ConstraintSystem<F>>( fn generate_constraints<CS: ConstraintSystem<F>>(
self, self,
cs: &mut CS, cs: &mut CS,
) -> Result<(), SynthesisError> { ) -> Result<(), SynthesisError> {
let _res = ResolvedProgram::generate_constraints(cs, self.program, self.parameters); let _result =
generate_constraints::<_, G, _>(cs, self.program, self.program_inputs).unwrap();
// Write results to file or something // Write results to file or something

View File

@ -1,9 +1,11 @@
//! Methods to enforce constraints on booleans in a resolved Leo program. //! Methods to enforce constraints on booleans in a resolved Leo program.
use crate::{ use crate::{
constraints::{new_variable_from_variable, ResolvedProgram, ResolvedValue}, constraints::{ConstrainedProgram, ConstrainedValue},
types::{ParameterModel, ParameterValue, Variable}, errors::BooleanError,
GroupType,
}; };
use leo_types::InputValue;
use snarkos_errors::gadgets::SynthesisError; use snarkos_errors::gadgets::SynthesisError;
use snarkos_models::{ use snarkos_models::{
@ -14,125 +16,97 @@ use snarkos_models::{
}, },
}; };
impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> { impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> ConstrainedProgram<F, G, CS> {
pub(crate) fn bool_from_parameter( pub(crate) fn bool_from_input(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
scope: String, name: String,
parameter_model: ParameterModel<F>, private: bool,
parameter_value: Option<ParameterValue<F>>, input_value: Option<InputValue>,
) -> Variable<F> { ) -> Result<ConstrainedValue<F, G>, BooleanError> {
// Check that the parameter value is the correct type // Check that the input value is the correct type
let bool_value = parameter_value.map(|parameter| match parameter { let bool_value = match input_value {
ParameterValue::Boolean(b) => b, Some(input) => {
value => unimplemented!("expected boolean parameter, got {}", value), if let InputValue::Boolean(bool) = input {
}); Some(bool)
} else {
return Err(BooleanError::InvalidBoolean(input.to_string()));
}
}
None => None,
};
// Check visibility of parameter // Check visibility of input
let name = parameter_model.variable.name.clone(); let number = if private {
let number = if parameter_model.private {
Boolean::alloc(cs.ns(|| name), || { Boolean::alloc(cs.ns(|| name), || {
bool_value.ok_or(SynthesisError::AssignmentMissing) bool_value.ok_or(SynthesisError::AssignmentMissing)
}) })?
.unwrap()
} else { } else {
Boolean::alloc_input(cs.ns(|| name), || { Boolean::alloc_input(cs.ns(|| name), || {
bool_value.ok_or(SynthesisError::AssignmentMissing) bool_value.ok_or(SynthesisError::AssignmentMissing)
}) })?
.unwrap()
}; };
let parameter_variable = new_variable_from_variable(scope, &parameter_model.variable); Ok(ConstrainedValue::Boolean(number))
// store each argument as variable in resolved program
self.store_variable(parameter_variable.clone(), ResolvedValue::Boolean(number));
parameter_variable
} }
pub(crate) fn boolean_array_from_parameter( pub(crate) fn get_boolean_constant(bool: Boolean) -> ConstrainedValue<F, G> {
&mut self, ConstrainedValue::Boolean(bool)
_cs: &mut CS,
_scope: String,
_parameter_model: ParameterModel<F>,
_parameter_value: Option<ParameterValue<F>>,
) -> Variable<F> {
unimplemented!("Cannot enforce boolean array as parameter")
// // Check visibility of parameter
// let mut array_value = vec![];
// let name = parameter.variable.name.clone();
// for argument in argument_array {
// let number = if parameter.private {
// Boolean::alloc(cs.ns(|| name), ||bool_value.ok_or(SynthesisError::AssignmentMissing).unwrap()
// } else {
// Boolean::alloc_input(cs.ns(|| name), || Ok(argument)).unwrap()
// };
//
// array_value.push(number);
// }
//
//
// let parameter_variable = new_variable_from_variable(scope, &parameter.variable);
//
// // store array as variable in resolved program
// self.store_variable(parameter_variable.clone(), ResolvedValue::BooleanArray(array_value));
//
// parameter_variable
} }
pub(crate) fn get_boolean_constant(bool: bool) -> ResolvedValue<F> { pub(crate) fn evaluate_not(
ResolvedValue::Boolean(Boolean::Constant(bool)) value: ConstrainedValue<F, G>,
} ) -> Result<ConstrainedValue<F, G>, BooleanError> {
pub(crate) fn evaluate_not(value: ResolvedValue<F>) -> ResolvedValue<F> {
match value { match value {
ResolvedValue::Boolean(boolean) => ResolvedValue::Boolean(boolean.not()), ConstrainedValue::Boolean(boolean) => Ok(ConstrainedValue::Boolean(boolean.not())),
value => unimplemented!("cannot enforce not on non-boolean value {}", value), value => Err(BooleanError::CannotEvaluate(format!("!{}", value))),
} }
} }
pub(crate) fn enforce_or( pub(crate) fn enforce_or(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
left: ResolvedValue<F>, left: ConstrainedValue<F, G>,
right: ResolvedValue<F>, right: ConstrainedValue<F, G>,
) -> ResolvedValue<F> { ) -> Result<ConstrainedValue<F, G>, BooleanError> {
match (left, right) { match (left, right) {
(ResolvedValue::Boolean(left_bool), ResolvedValue::Boolean(right_bool)) => { (ConstrainedValue::Boolean(left_bool), ConstrainedValue::Boolean(right_bool)) => Ok(
ResolvedValue::Boolean(Boolean::or(cs, &left_bool, &right_bool).unwrap()) ConstrainedValue::Boolean(Boolean::or(cs, &left_bool, &right_bool)?),
}
(left_value, right_value) => unimplemented!(
"cannot enforce or on non-boolean values {} || {}",
left_value,
right_value
), ),
(left_value, right_value) => Err(BooleanError::CannotEnforce(format!(
"{} || {}",
left_value, right_value
))),
} }
} }
pub(crate) fn enforce_and( pub(crate) fn enforce_and(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
left: ResolvedValue<F>, left: ConstrainedValue<F, G>,
right: ResolvedValue<F>, right: ConstrainedValue<F, G>,
) -> ResolvedValue<F> { ) -> Result<ConstrainedValue<F, G>, BooleanError> {
match (left, right) { match (left, right) {
(ResolvedValue::Boolean(left_bool), ResolvedValue::Boolean(right_bool)) => { (ConstrainedValue::Boolean(left_bool), ConstrainedValue::Boolean(right_bool)) => Ok(
ResolvedValue::Boolean(Boolean::and(cs, &left_bool, &right_bool).unwrap()) ConstrainedValue::Boolean(Boolean::and(cs, &left_bool, &right_bool)?),
}
(left_value, right_value) => unimplemented!(
"cannot enforce and on non-boolean values {} && {}",
left_value,
right_value
), ),
(left_value, right_value) => Err(BooleanError::CannotEnforce(format!(
"{} && {}",
left_value, right_value
))),
} }
} }
pub(crate) fn boolean_eq(left: Boolean, right: Boolean) -> ResolvedValue<F> { pub(crate) fn boolean_eq(left: Boolean, right: Boolean) -> ConstrainedValue<F, G> {
ResolvedValue::Boolean(Boolean::Constant(left.eq(&right))) ConstrainedValue::Boolean(Boolean::Constant(left.eq(&right)))
} }
pub(crate) fn enforce_boolean_eq(&mut self, cs: &mut CS, left: Boolean, right: Boolean) { pub(crate) fn enforce_boolean_eq(
left.enforce_equal(cs.ns(|| format!("enforce bool equal")), &right) &mut self,
.unwrap(); cs: &mut CS,
left: Boolean,
right: Boolean,
) -> Result<(), BooleanError> {
Ok(left.enforce_equal(cs.ns(|| format!("enforce bool equal")), &right)?)
} }
} }

Some files were not shown because too many files have changed in this diff Show More