From 7c3538982999007c839c6a0d74b1f67d2ec9d598 Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 11 May 2022 10:00:11 +0200 Subject: [PATCH] start split to crates --- Cargo.lock | 330 ++-- Cargo.toml | 4 + zokrates_ark/Cargo.toml | 10 + .../ark => zokrates_ark/src}/gm17.rs | 4 +- .../ark => zokrates_ark/src}/groth16.rs | 4 +- .../ark/mod.rs => zokrates_ark/src/lib.rs | 2 +- .../ark => zokrates_ark/src}/marlin.rs | 4 +- zokrates_ast/Cargo.toml | 20 + .../src => zokrates_ast/src/common}/embed.rs | 100 +- zokrates_ast/src/common/error.rs | 82 + zokrates_ast/src/common/mod.rs | 11 + .../src/common/parameter.rs | 31 +- .../src/common/solvers.rs | 0 .../src/common/variable.rs | 34 +- zokrates_ast/src/flat/folder.rs | 92 ++ .../src/flat}/mod.rs | 110 +- .../src/ir/expression.rs | 71 +- .../src/ir/folder.rs | 14 +- .../src/ir/from_flat.rs | 2 +- {zokrates_core => zokrates_ast}/src/ir/mod.rs | 32 +- .../src/ir/serialize.rs | 34 +- .../src/ir/smtlib2.rs | 10 +- .../src/ir/visitor.rs | 12 +- .../src/ir/witness.rs | 33 +- zokrates_ast/src/lib.rs | 10 + .../src/typed}/abi.rs | 6 +- .../src/typed}/folder.rs | 4 +- .../src/typed}/identifier.rs | 2 +- .../src/typed}/integer.rs | 8 +- .../src/typed}/mod.rs | 26 +- .../src/typed}/parameter.rs | 4 +- .../src/typed}/result_folder.rs | 4 +- .../src/typed}/types.rs | 4 +- .../src/typed}/uint.rs | 4 +- .../src/typed}/variable.rs | 12 +- zokrates_ast/src/untyped/from_ast.rs | 1398 +++++++++++++++++ .../absy => zokrates_ast/src/untyped}/mod.rs | 12 +- .../absy => zokrates_ast/src/untyped}/node.rs | 4 +- .../src/untyped}/parameter.rs | 2 +- .../src/untyped}/position.rs | 0 .../src/untyped}/types.rs | 8 +- .../src/untyped}/variable.rs | 6 +- .../src/zir/folder.rs | 0 .../src/zir/from_typed.rs | 2 +- .../src/zir/identifier.rs | 2 +- .../src/zir/mod.rs | 2 +- .../src/zir/parameter.rs | 0 .../src/zir/result_folder.rs | 0 .../src/zir/types.rs | 0 .../src/zir/uint.rs | 0 .../src/zir/variable.rs | 0 zokrates_core/Cargo.toml | 3 +- zokrates_core/src/absy/from_ast.rs | 1386 ---------------- zokrates_core/src/compile.rs | 5 +- zokrates_core/src/flatten/mod.rs | 269 ++-- zokrates_core/src/imports.rs | 3 +- zokrates_core/src/lib.rs | 12 +- zokrates_core/src/optimizer/canonicalizer.rs | 2 +- zokrates_core/src/optimizer/directive.rs | 12 +- zokrates_core/src/optimizer/duplicate.rs | 26 +- zokrates_core/src/optimizer/mod.rs | 76 +- zokrates_core/src/optimizer/redefinition.rs | 71 +- zokrates_core/src/optimizer/tautology.rs | 6 +- zokrates_core/src/parser/mod.rs | 3 - zokrates_core/src/parser/tokenize/mod.rs | 3 - .../src/proof_system/bellman/groth16.rs | 14 +- zokrates_core/src/proof_system/bellman/mod.rs | 70 +- .../src/proof_system/libsnark/gm17.rs | 4 +- .../src/proof_system/libsnark/mod.rs | 2 +- .../src/proof_system/libsnark/pghr13.rs | 4 +- zokrates_core/src/proof_system/mod.rs | 4 +- zokrates_core/src/semantics.rs | 2 - .../src/static_analysis/branch_isolator.rs | 2 +- .../constant_argument_checker.rs | 2 +- .../src/static_analysis/constant_resolver.rs | 2 +- .../src/static_analysis/flat_propagation.rs | 76 +- zokrates_core/src/static_analysis/mod.rs | 127 +- .../src/static_analysis/propagation.rs | 2 +- .../src/static_analysis/reducer/inline.rs | 2 +- .../static_analysis/reducer/shallow_ssa.rs | 2 +- .../src/static_analysis/struct_concretizer.rs | 2 +- .../src/static_analysis/uint_optimizer.rs | 2 +- .../src/static_analysis/unconstrained_vars.rs | 18 +- .../static_analysis/variable_write_remover.rs | 2 +- .../src/static_analysis/zir_propagation.rs | 10 +- zokrates_interpreter/Cargo.toml | 10 + .../src/lib.rs | 72 +- 87 files changed, 2504 insertions(+), 2370 deletions(-) create mode 100644 zokrates_ark/Cargo.toml rename {zokrates_core/src/proof_system/ark => zokrates_ark/src}/gm17.rs (98%) rename {zokrates_core/src/proof_system/ark => zokrates_ark/src}/groth16.rs (98%) rename zokrates_core/src/proof_system/ark/mod.rs => zokrates_ark/src/lib.rs (99%) rename {zokrates_core/src/proof_system/ark => zokrates_ark/src}/marlin.rs (99%) create mode 100644 zokrates_ast/Cargo.toml rename {zokrates_core/src => zokrates_ast/src/common}/embed.rs (91%) create mode 100644 zokrates_ast/src/common/error.rs create mode 100644 zokrates_ast/src/common/mod.rs rename zokrates_core/src/flat_absy/flat_parameter.rs => zokrates_ast/src/common/parameter.rs (50%) rename zokrates_core/src/solvers/mod.rs => zokrates_ast/src/common/solvers.rs (100%) rename zokrates_core/src/flat_absy/flat_variable.rs => zokrates_ast/src/common/variable.rs (71%) create mode 100644 zokrates_ast/src/flat/folder.rs rename {zokrates_core/src/flat_absy => zokrates_ast/src/flat}/mod.rs (71%) rename {zokrates_core => zokrates_ast}/src/ir/expression.rs (82%) rename {zokrates_core => zokrates_ast}/src/ir/folder.rs (85%) rename {zokrates_core => zokrates_ast}/src/ir/from_flat.rs (98%) rename {zokrates_core => zokrates_ast}/src/ir/mod.rs (85%) rename {zokrates_core => zokrates_ast}/src/ir/serialize.rs (92%) rename {zokrates_core => zokrates_ast}/src/ir/smtlib2.rs (93%) rename {zokrates_core => zokrates_ast}/src/ir/visitor.rs (89%) rename {zokrates_core => zokrates_ast}/src/ir/witness.rs (82%) create mode 100644 zokrates_ast/src/lib.rs rename {zokrates_core/src/typed_absy => zokrates_ast/src/typed}/abi.rs (99%) rename {zokrates_core/src/typed_absy => zokrates_ast/src/typed}/folder.rs (99%) rename {zokrates_core/src/typed_absy => zokrates_ast/src/typed}/identifier.rs (97%) rename {zokrates_core/src/typed_absy => zokrates_ast/src/typed}/integer.rs (99%) rename {zokrates_core/src/typed_absy => zokrates_ast/src/typed}/mod.rs (99%) rename {zokrates_core/src/typed_absy => zokrates_ast/src/typed}/parameter.rs (91%) rename {zokrates_core/src/typed_absy => zokrates_ast/src/typed}/result_folder.rs (99%) rename {zokrates_core/src/typed_absy => zokrates_ast/src/typed}/types.rs (99%) rename {zokrates_core/src/typed_absy => zokrates_ast/src/typed}/uint.rs (99%) rename {zokrates_core/src/typed_absy => zokrates_ast/src/typed}/variable.rs (88%) create mode 100644 zokrates_ast/src/untyped/from_ast.rs rename {zokrates_core/src/absy => zokrates_ast/src/untyped}/mod.rs (98%) rename {zokrates_core/src/absy => zokrates_ast/src/untyped}/node.rs (97%) rename {zokrates_core/src/absy => zokrates_ast/src/untyped}/parameter.rs (96%) rename {zokrates_core/src/parser/tokenize => zokrates_ast/src/untyped}/position.rs (100%) rename {zokrates_core/src/absy => zokrates_ast/src/untyped}/types.rs (96%) rename {zokrates_core/src/absy => zokrates_ast/src/untyped}/variable.rs (88%) rename {zokrates_core => zokrates_ast}/src/zir/folder.rs (100%) rename {zokrates_core => zokrates_ast}/src/zir/from_typed.rs (97%) rename {zokrates_core => zokrates_ast}/src/zir/identifier.rs (95%) rename {zokrates_core => zokrates_ast}/src/zir/mod.rs (99%) rename {zokrates_core => zokrates_ast}/src/zir/parameter.rs (100%) rename {zokrates_core => zokrates_ast}/src/zir/result_folder.rs (100%) rename {zokrates_core => zokrates_ast}/src/zir/types.rs (100%) rename {zokrates_core => zokrates_ast}/src/zir/uint.rs (100%) rename {zokrates_core => zokrates_ast}/src/zir/variable.rs (100%) delete mode 100644 zokrates_core/src/absy/from_ast.rs delete mode 100644 zokrates_core/src/parser/mod.rs delete mode 100644 zokrates_core/src/parser/tokenize/mod.rs create mode 100644 zokrates_interpreter/Cargo.toml rename zokrates_core/src/ir/interpreter.rs => zokrates_interpreter/src/lib.rs (87%) diff --git a/Cargo.lock b/Cargo.lock index 1f27e682..3865c1d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,7 +140,7 @@ dependencies = [ "ark-serialize", "ark-std", "derivative", - "num-traits 0.2.14", + "num-traits 0.2.15", "zeroize", ] @@ -156,7 +156,7 @@ dependencies = [ "ark-std", "derivative", "num-bigint 0.4.3", - "num-traits 0.2.14", + "num-traits 0.2.15", "paste", "rustc_version", "zeroize", @@ -168,8 +168,8 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" dependencies = [ - "quote 1.0.17", - "syn 1.0.91", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -179,9 +179,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" dependencies = [ "num-bigint 0.4.3", - "num-traits 0.2.14", - "quote 1.0.17", - "syn 1.0.91", + "num-traits 0.2.15", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -246,7 +246,7 @@ dependencies = [ "derivative", "num-bigint 0.4.3", "num-integer", - "num-traits 0.2.14", + "num-traits 0.2.15", "tracing", ] @@ -291,7 +291,7 @@ dependencies = [ "ark-std", "derivative", "num-bigint 0.4.3", - "num-traits 0.2.14", + "num-traits 0.2.15", "tracing", ] @@ -323,9 +323,9 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8dd4e5f0bf8285d5ed538d27fab7411f3e297908fd93c62195de8bee3f199e82" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -345,7 +345,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" dependencies = [ - "num-traits 0.2.14", + "num-traits 0.2.15", "rand 0.8.5", ] @@ -402,9 +402,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7862e21c893d65a1650125d157eaeec691439379a1cee17ee49031b79236ada4" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -415,9 +415,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" +checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61" dependencies = [ "addr2line", "cc", @@ -644,7 +644,7 @@ checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" dependencies = [ "camino", "cargo-platform", - "semver 1.0.7", + "semver 1.0.9", "serde", "serde_json", ] @@ -866,8 +866,8 @@ version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" dependencies = [ - "quote 1.0.17", - "syn 1.0.91", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -876,9 +876,9 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -1044,9 +1044,9 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", "synstructure", ] @@ -1096,10 +1096,10 @@ checksum = "50c052fa6d4c2f12305ec364bfb8ef884836f3f61ea015b202372ff996d1ac4b" dependencies = [ "num-bigint 0.2.6", "num-integer", - "num-traits 0.2.14", - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "num-traits 0.2.15", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -1287,9 +1287,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c21d40587b92fa6a6c6e3c1bdbf87d75511db5672f9c93175574b3a00df1758" +checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" dependencies = [ "ahash", ] @@ -1354,9 +1354,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -1434,15 +1434,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.122" +version = "0.2.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259" +checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" [[package]] name = "log" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if 1.0.0", ] @@ -1461,9 +1461,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" @@ -1476,12 +1476,11 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.4.4" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" dependencies = [ "adler", - "autocfg", ] [[package]] @@ -1498,7 +1497,7 @@ checksum = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" dependencies = [ "num-integer", "num-iter", - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] @@ -1512,7 +1511,7 @@ dependencies = [ "num-integer", "num-iter", "num-rational", - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] @@ -1523,7 +1522,7 @@ checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" dependencies = [ "autocfg", "num-integer", - "num-traits 0.2.14", + "num-traits 0.2.15", "serde", ] @@ -1535,37 +1534,37 @@ checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ "autocfg", "num-integer", - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] name = "num-complex" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085" +checksum = "97fbc387afefefd5e9e39493299f3069e14a140dd34dc19b4c1c1a8fddb6a790" dependencies = [ - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] name = "num-integer" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] name = "num-iter" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" dependencies = [ "autocfg", "num-integer", - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] @@ -1577,7 +1576,7 @@ dependencies = [ "autocfg", "num-bigint 0.4.3", "num-integer", - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] @@ -1586,14 +1585,14 @@ version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" dependencies = [ - "num-traits 0.2.14", + "num-traits 0.2.15", ] [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", ] @@ -1624,16 +1623,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" dependencies = [ "proc-macro-crate", - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] name = "object" -version = "0.27.1" +version = "0.28.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" dependencies = [ "memchr", ] @@ -1697,9 +1696,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c45ed1f39709f5a89338fab50e59816b2e8815f5bb58276e7ddf9afd495f73f8" dependencies = [ "proc-macro-crate", - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -1748,9 +1747,9 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -1782,9 +1781,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -1840,9 +1839,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", "version_check", ] @@ -1852,8 +1851,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", + "proc-macro2 1.0.38", + "quote 1.0.18", "version_check", ] @@ -1868,11 +1867,11 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" +checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" dependencies = [ - "unicode-xid 0.2.2", + "unicode-xid 0.2.3", ] [[package]] @@ -1897,11 +1896,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2 1.0.38", ] [[package]] @@ -2059,13 +2058,13 @@ dependencies = [ [[package]] name = "revm" -version = "1.2.0" -source = "git+https://github.com/bluealloy/revm#5f789910838ca144feb196dd91f88f5b5b1fe923" +version = "1.3.1" +source = "git+https://github.com/bluealloy/revm#8c63ba6c7f3667064608c2489c3e4b3e54451110" dependencies = [ "arrayref", "auto_impl", "bytes", - "hashbrown 0.12.0", + "hashbrown 0.12.1", "num_enum", "primitive-types", "revm_precompiles", @@ -2075,8 +2074,8 @@ dependencies = [ [[package]] name = "revm_precompiles" -version = "0.4.0" -source = "git+https://github.com/bluealloy/revm#5f789910838ca144feb196dd91f88f5b5b1fe923" +version = "1.0.0" +source = "git+https://github.com/bluealloy/revm#8c63ba6c7f3667064608c2489c3e4b3e54451110" dependencies = [ "bytes", "num 0.4.0", @@ -2183,9 +2182,9 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b5b9d7322572e1f3aeed208668ce87789b3645dbb73082c5ce99a004103a35" +checksum = "aa6f71720acd498e888501dd485d54bb437735f02dd95eb717dac5aee6631894" dependencies = [ "cc", ] @@ -2201,9 +2200,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4" +checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" dependencies = [ "serde", ] @@ -2219,9 +2218,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" dependencies = [ "serde_derive", ] @@ -2238,20 +2237,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] name = "serde_json" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" dependencies = [ "indexmap", "itoa 1.0.1", @@ -2411,13 +2410,13 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.91" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" +checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "unicode-xid 0.2.2", + "proc-macro2 1.0.38", + "quote 1.0.18", + "unicode-xid 0.2.3", ] [[package]] @@ -2426,10 +2425,10 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", - "unicode-xid 0.2.2", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", + "unicode-xid 0.2.3", ] [[package]] @@ -2482,22 +2481,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -2520,18 +2519,18 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "serde", ] [[package]] name = "tracing" -version = "0.1.32" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f" +checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", @@ -2541,20 +2540,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" +checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] name = "tracing-core" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90442985ee2f57c9e1b548ee72ae842f4a9a20e3f417cc38dbc5dc684d9bb4ee" +checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" [[package]] name = "typed-arena" @@ -2615,9 +2614,9 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" [[package]] name = "utf8-ranges" @@ -2679,9 +2678,9 @@ dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", "wasm-bindgen-shared", ] @@ -2703,7 +2702,7 @@ version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" dependencies = [ - "quote 1.0.17", + "quote 1.0.18", "wasm-bindgen-macro-support", ] @@ -2713,9 +2712,9 @@ version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2746,8 +2745,8 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a77c5a6f82cc6093a321ca5fb3dc9327fe51675d477b3799b4a9375bac3b7b4c" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", + "proc-macro2 1.0.38", + "quote 1.0.18", ] [[package]] @@ -2802,9 +2801,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb5728b8afd3f280a869ce1d4c554ffaed35f45c231fc41bfbd0381bef50317" +checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" dependencies = [ "zeroize_derive", ] @@ -2815,9 +2814,9 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.17", - "syn 1.0.91", + "proc-macro2 1.0.38", + "quote 1.0.18", + "syn 1.0.92", "synstructure", ] @@ -2832,6 +2831,28 @@ dependencies = [ "zokrates_field", ] +[[package]] +name = "zokrates_ark" +version = "0.1.0" +dependencies = [ + "zokrates_ast", + "zokrates_field", +] + +[[package]] +name = "zokrates_ast" +version = "0.1.0" +dependencies = [ + "cfg-if 0.1.10", + "csv", + "num-bigint 0.2.6", + "serde", + "serde_cbor", + "serde_json", + "zokrates_field", + "zokrates_pest_ast", +] + [[package]] name = "zokrates_cli" version = "0.7.13" @@ -2911,15 +2932,16 @@ dependencies = [ "reduce", "regex 0.2.11", "serde", - "serde_cbor", "serde_json", "sha3 0.9.1", "typed-arena", "wasm-bindgen-test", + "zokrates_ast", "zokrates_common", "zokrates_embed", "zokrates_field", "zokrates_fs_resolver", + "zokrates_interpreter", "zokrates_pest_ast", ] @@ -2965,7 +2987,7 @@ dependencies = [ "lazy_static", "num-bigint 0.2.6", "num-integer", - "num-traits 0.2.14", + "num-traits 0.2.15", "rand 0.4.6", "serde", "serde_derive", @@ -2981,6 +3003,16 @@ dependencies = [ "zokrates_common", ] +[[package]] +name = "zokrates_interpreter" +version = "0.1.0" +dependencies = [ + "num 0.1.42", + "num-bigint 0.2.6", + "zokrates_ast", + "zokrates_field", +] + [[package]] name = "zokrates_parser" version = "0.2.6" diff --git a/Cargo.toml b/Cargo.toml index 80ac413c..b93fb355 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,10 @@ members = [ "zokrates_test", "zokrates_core_test", "zokrates_solidity_test", + "zokrates_ark", + "zokrates_ast", + "zokrates_interpreter", + "zokrates_embed", ] exclude = ["zokrates_js"] \ No newline at end of file diff --git a/zokrates_ark/Cargo.toml b/zokrates_ark/Cargo.toml new file mode 100644 index 00000000..2658fc61 --- /dev/null +++ b/zokrates_ark/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "zokrates_ark" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +zokrates_field = { version = "0.5", path = "../zokrates_field", default-features = false } +zokrates_ast = { version = "0.1", path = "../zokrates_ast", default-features = false } diff --git a/zokrates_core/src/proof_system/ark/gm17.rs b/zokrates_ark/src/gm17.rs similarity index 98% rename from zokrates_core/src/proof_system/ark/gm17.rs rename to zokrates_ark/src/gm17.rs index 79fd6eff..6ef10a92 100644 --- a/zokrates_core/src/proof_system/ark/gm17.rs +++ b/zokrates_ark/src/gm17.rs @@ -6,7 +6,6 @@ use ark_gm17::{ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use zokrates_field::{ArkFieldExtensions, Bw6_761Field, Field}; -use crate::ir::{ProgIterator, Statement, Witness}; use crate::proof_system::ark::Computation; use crate::proof_system::ark::{parse_fr, parse_g1, parse_g2, parse_g2_fq}; use crate::proof_system::ark::{serialization, Ark}; @@ -15,6 +14,7 @@ use crate::proof_system::{Backend, NonUniversalBackend, Proof, SetupKeypair}; use crate::proof_system::{NotBw6_761Field, Scheme}; use ark_bw6_761::BW6_761; use rand_0_8::{rngs::StdRng, SeedableRng}; +use zokrates_ast::ir::{ProgIterator, Statement, Witness}; impl NonUniversalBackend for Ark { fn setup>>( @@ -209,7 +209,7 @@ impl Backend for Ark { #[cfg(test)] mod tests { use crate::flat_absy::{FlatParameter, FlatVariable}; - use crate::ir::{Interpreter, Prog, Statement}; + use zokrates_ast::ir::{Interpreter, Prog, Statement}; use super::*; use zokrates_field::{Bls12_377Field, Bw6_761Field}; diff --git a/zokrates_core/src/proof_system/ark/groth16.rs b/zokrates_ark/src/groth16.rs similarity index 98% rename from zokrates_core/src/proof_system/ark/groth16.rs rename to zokrates_ark/src/groth16.rs index 87ef2721..13fc867f 100644 --- a/zokrates_core/src/proof_system/ark/groth16.rs +++ b/zokrates_ark/src/groth16.rs @@ -8,7 +8,6 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use zokrates_field::Field; use zokrates_field::{ArkFieldExtensions, Bw6_761Field}; -use crate::ir::{ProgIterator, Statement, Witness}; use crate::proof_system::ark::Computation; use crate::proof_system::ark::{parse_fr, serialization, Ark}; use crate::proof_system::ark::{parse_g1, parse_g2}; @@ -16,6 +15,7 @@ use crate::proof_system::groth16::{ProofPoints, VerificationKey, G16}; use crate::proof_system::Scheme; use ark_bw6_761::BW6_761; use rand_0_8::{rngs::StdRng, SeedableRng}; +use zokrates_ast::ir::{ProgIterator, Statement, Witness}; const G16_WARNING: &str = "WARNING: You are using the G16 scheme which is subject to malleability. See zokrates.github.io/toolbox/proving_schemes.html#g16-malleability for implications."; @@ -213,7 +213,7 @@ impl NonUniversalBackend for Ark { #[cfg(test)] mod tests { use crate::flat_absy::{FlatParameter, FlatVariable}; - use crate::ir::{Interpreter, Prog, Statement}; + use zokrates_ast::ir::{Interpreter, Prog, Statement}; use super::*; use zokrates_field::{Bls12_377Field, Bw6_761Field}; diff --git a/zokrates_core/src/proof_system/ark/mod.rs b/zokrates_ark/src/lib.rs similarity index 99% rename from zokrates_core/src/proof_system/ark/mod.rs rename to zokrates_ark/src/lib.rs index 192d7303..40f090c6 100644 --- a/zokrates_core/src/proof_system/ark/mod.rs +++ b/zokrates_ark/src/lib.rs @@ -3,13 +3,13 @@ pub mod groth16; pub mod marlin; use crate::flat_absy::FlatVariable; -use crate::ir::{CanonicalLinComb, ProgIterator, Statement, Witness}; use ark_ec::PairingEngine; use ark_relations::r1cs::{ ConstraintSynthesizer, ConstraintSystem, ConstraintSystemRef, LinearCombination, SynthesisError, Variable, }; use std::collections::BTreeMap; +use zokrates_ast::ir::{CanonicalLinComb, ProgIterator, Statement, Witness}; use zokrates_field::{ArkFieldExtensions, Field}; pub use self::parse::*; diff --git a/zokrates_core/src/proof_system/ark/marlin.rs b/zokrates_ark/src/marlin.rs similarity index 99% rename from zokrates_core/src/proof_system/ark/marlin.rs rename to zokrates_ark/src/marlin.rs index 15a813db..576acd84 100644 --- a/zokrates_core/src/proof_system/ark/marlin.rs +++ b/zokrates_ark/src/marlin.rs @@ -23,13 +23,13 @@ use std::marker::PhantomData; use zokrates_field::{ArkFieldExtensions, Field}; -use crate::ir::{ProgIterator, Statement, Witness}; use crate::proof_system::ark::Ark; use crate::proof_system::ark::Computation; use crate::proof_system::ark::{parse_fr, parse_g1, parse_g2, serialization}; use crate::proof_system::marlin::{self, KZGVerifierKey, ProofPoints, VerificationKey}; use crate::proof_system::Scheme; use crate::proof_system::{Backend, Proof, SetupKeypair, UniversalBackend}; +use zokrates_ast::ir::{ProgIterator, Statement, Witness}; const MINIMUM_CONSTRAINT_COUNT: usize = 2; @@ -387,7 +387,7 @@ impl Backend for Ark { #[cfg(test)] mod tests { use crate::flat_absy::{FlatParameter, FlatVariable}; - use crate::ir::{Interpreter, Prog, QuadComb, Statement}; + use zokrates_ast::ir::{Interpreter, Prog, QuadComb, Statement}; use super::*; use crate::proof_system::scheme::Marlin; diff --git a/zokrates_ast/Cargo.toml b/zokrates_ast/Cargo.toml new file mode 100644 index 00000000..63288786 --- /dev/null +++ b/zokrates_ast/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "zokrates_ast" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +zokrates_pest_ast = { version = "0.2.0", path = "../zokrates_pest_ast" } +cfg-if = "0.1" +zokrates_field = { version = "0.5", path = "../zokrates_field", default-features = false } +serde = { version = "1.0", features = ["derive"] } +csv = "1" +serde_cbor = "0.11.2" +num-bigint = { version = "0.2", default-features = false } +serde_json = { version = "1.0", features = ["preserve_order"] } + + + + diff --git a/zokrates_core/src/embed.rs b/zokrates_ast/src/common/embed.rs similarity index 91% rename from zokrates_core/src/embed.rs rename to zokrates_ast/src/common/embed.rs index 54906148..47551172 100644 --- a/zokrates_core/src/embed.rs +++ b/zokrates_ast/src/common/embed.rs @@ -1,16 +1,13 @@ -use crate::absy::{ - types::{UnresolvedSignature, UnresolvedType}, - ConstantGenericNode, Expression, -}; -use crate::flat_absy::{ - FlatDirective, FlatExpression, FlatFunctionIterator, FlatParameter, FlatStatement, - FlatVariable, RuntimeError, -}; -use crate::solvers::Solver; -use crate::typed_absy::types::{ +use crate::common::{Parameter, RuntimeError, Solver, Variable}; +use crate::flat::{FlatDirective, FlatExpression, FlatFunctionIterator, FlatStatement}; +use crate::typed::types::{ ConcreteGenericsAssignment, DeclarationConstant, DeclarationSignature, DeclarationType, GenericIdentifier, }; +use crate::untyped::{ + types::{UnresolvedSignature, UnresolvedType}, + ConstantGenericNode, Expression, +}; use std::collections::HashMap; use zokrates_field::Field; @@ -324,7 +321,7 @@ fn flat_expression_from_vec(v: &[(usize, T)]) -> FlatExpression { let (key, val) = v[0].clone(); FlatExpression::Mult( box FlatExpression::Number(val), - box FlatExpression::Identifier(FlatVariable::new(key)), + box FlatExpression::Identifier(Variable::new(key)), ) } n => { @@ -347,6 +344,7 @@ fn flat_expression_from_vec(v: &[(usize, T)]) -> FlatExpression { #[cfg(feature = "bellman")] pub fn sha256_round( ) -> FlatFunctionIterator>> { + use zokrates_ast::ir::RuntimeError; use zokrates_field::Bn128Field; assert_eq!(T::id(), Bn128Field::id()); @@ -383,14 +381,14 @@ pub fn sha256_round( .clone() .into_iter() .chain(current_hash_argument_indices.clone()) - .map(|i| FlatParameter { - id: FlatVariable::new(i), + .map(|i| Parameter { + id: Variable::new(i), private: true, }) .collect(); // define a binding of the first variable in the constraint system to one let one_binding_statement = FlatStatement::Condition( - FlatVariable::new(0).into(), + Variable::new(0).into(), FlatExpression::Number(T::from(1)), RuntimeError::BellmanOneBinding, ); @@ -398,8 +396,8 @@ pub fn sha256_round( // bind input and current_hash to inputs input_indices.chain(current_hash_indices).zip(input_argument_indices.clone().into_iter().chain(current_hash_argument_indices.clone())).map(|(cs_index, argument_index)| { FlatStatement::Condition( - FlatVariable::new(cs_index).into(), - FlatVariable::new(argument_index).into(), + Variable::new(cs_index).into(), + Variable::new(argument_index).into(), RuntimeError::BellmanInputBinding ) }); @@ -418,14 +416,14 @@ pub fn sha256_round( }); // define which subset of the witness is returned - let outputs = output_indices.map(|o| FlatExpression::Identifier(FlatVariable::new(o))); + let outputs = output_indices.map(|o| FlatExpression::Identifier(Variable::new(o))); // insert a directive to set the witness based on the bellman gadget and inputs let directive_statement = FlatStatement::Directive(FlatDirective { - outputs: cs_indices.map(FlatVariable::new).collect(), + outputs: cs_indices.map(Variable::new).collect(), inputs: input_argument_indices .into_iter() .chain(current_hash_argument_indices) - .map(|i| FlatVariable::new(i).into()) + .map(|i| Variable::new(i).into()) .collect(), solver: Solver::Sha256Round, }); @@ -433,7 +431,7 @@ pub fn sha256_round( let return_statements = outputs .into_iter() .enumerate() - .map(|(index, e)| FlatStatement::Definition(FlatVariable::public(index), e)); + .map(|(index, e)| FlatStatement::Definition(Variable::public(index), e)); let statements = std::iter::once(directive_statement) .chain(std::iter::once(one_binding_statement)) .chain(input_binding_statements) @@ -451,6 +449,7 @@ pub fn sha256_round( pub fn snark_verify_bls12_377( n: usize, ) -> FlatFunctionIterator>> { + use zokrates_ast::ir::RuntimeError; use zokrates_field::Bw6_761Field; assert_eq!(T::id(), Bw6_761Field::id()); @@ -471,15 +470,15 @@ pub fn snark_verify_bls12_377( let input_arguments = input_argument_indices .clone() - .map(|i| FlatParameter::private(FlatVariable::new(i))); + .map(|i| Parameter::private(Variable::new(i))); let proof_arguments = proof_argument_indices .clone() - .map(|i| FlatParameter::private(FlatVariable::new(i))); + .map(|i| Parameter::private(Variable::new(i))); let vk_arguments = vk_argument_indices .clone() - .map(|i| FlatParameter::private(FlatVariable::new(i))); + .map(|i| Parameter::private(Variable::new(i))); let arguments = input_arguments .chain(proof_arguments) @@ -487,7 +486,7 @@ pub fn snark_verify_bls12_377( .collect(); let one_binding_statement = FlatStatement::Condition( - FlatExpression::Identifier(FlatVariable::new(0)), + FlatExpression::Identifier(Variable::new(0)), FlatExpression::Number(T::from(1)), RuntimeError::ArkOneBinding, ); @@ -503,8 +502,8 @@ pub fn snark_verify_bls12_377( ) .map(|(cs_index, argument_index)| { FlatStatement::Condition( - FlatVariable::new(cs_index).into(), - FlatVariable::new(argument_index).into(), + Variable::new(cs_index).into(), + Variable::new(argument_index).into(), RuntimeError::ArkInputBinding, ) }) @@ -527,17 +526,17 @@ pub fn snark_verify_bls12_377( .collect(); let return_statement = FlatStatement::Definition( - FlatVariable::public(0), - FlatExpression::Identifier(FlatVariable::new(out_index)), + Variable::public(0), + FlatExpression::Identifier(Variable::new(out_index)), ); // insert a directive to set the witness let directive_statement = FlatStatement::Directive(FlatDirective { - outputs: cs_indices.map(FlatVariable::new).collect(), + outputs: cs_indices.map(Variable::new).collect(), inputs: input_argument_indices .chain(proof_argument_indices) .chain(vk_argument_indices) - .map(|i| FlatVariable::new(i).into()) + .map(|i| Variable::new(i).into()) .collect(), solver: Solver::SnarkVerifyBls12377(n), }); @@ -556,11 +555,11 @@ pub fn snark_verify_bls12_377( } fn use_variable( - layout: &mut HashMap, + layout: &mut HashMap, name: String, index: &mut usize, -) -> FlatVariable { - let var = FlatVariable::new(*index); +) -> Variable { + let var = Variable::new(*index); layout.insert(name, var); *index += 1; var @@ -581,8 +580,8 @@ pub fn unpack_to_bitwidth( let mut layout = HashMap::new(); - let arguments = vec![FlatParameter { - id: FlatVariable::new(0), + let arguments = vec![Parameter { + id: Variable::new(0), private: true, }]; @@ -594,7 +593,7 @@ pub fn unpack_to_bitwidth( &mut counter, ))]; - let directive_outputs: Vec = (0..bit_width) + let directive_outputs: Vec = (0..bit_width) .map(|index| use_variable(&mut layout, format!("o{}", index), &mut counter)) .collect(); @@ -610,7 +609,7 @@ pub fn unpack_to_bitwidth( // o253, o252, ... o{253 - (bit_width - 1)} are bits let mut statements: Vec> = (0..bit_width) .map(|index| { - let bit = FlatExpression::Identifier(FlatVariable::new(bit_width - index)); + let bit = FlatExpression::Identifier(Variable::new(bit_width - index)); FlatStatement::Condition( bit.clone(), FlatExpression::Mult(box bit.clone(), box bit.clone()), @@ -626,7 +625,7 @@ pub fn unpack_to_bitwidth( lhs_sum = FlatExpression::Add( box lhs_sum, box FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(bit_width - i)), + box FlatExpression::Identifier(Variable::new(bit_width - i)), box FlatExpression::Number(T::from(2).pow(i)), ), ); @@ -635,7 +634,7 @@ pub fn unpack_to_bitwidth( statements.push(FlatStatement::Condition( lhs_sum, FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(0)), + box FlatExpression::Identifier(Variable::new(0)), box FlatExpression::Number(T::from(1)), ), RuntimeError::Sum, @@ -654,7 +653,7 @@ pub fn unpack_to_bitwidth( outputs .into_iter() .enumerate() - .map(|(index, e)| FlatStatement::Definition(FlatVariable::public(index), e)), + .map(|(index, e)| FlatStatement::Definition(Variable::public(index), e)), ); FlatFunctionIterator { @@ -678,18 +677,15 @@ mod tests { let unpack = unpack_to_bitwidth::(Bn128Field::get_required_bits()).collect(); - assert_eq!( - unpack.arguments, - vec![FlatParameter::private(FlatVariable::new(0))] - ); + assert_eq!(unpack.arguments, vec![Parameter::private(Variable::new(0))]); assert_eq!( unpack.statements[0], FlatStatement::Directive(FlatDirective::new( (0..Bn128Field::get_required_bits()) - .map(|i| FlatVariable::new(i + 1)) + .map(|i| Variable::new(i + 1)) .collect(), Solver::bits(Bn128Field::get_required_bits()), - vec![FlatVariable::new(0)] + vec![Variable::new(0)] )) ); assert_eq!( @@ -703,7 +699,7 @@ mod tests { #[cfg(test)] mod sha256 { use super::*; - use crate::ir::Interpreter; + use zokrates_ast::ir::Interpreter; #[test] fn generate_sha256_constraints() { @@ -732,14 +728,14 @@ mod tests { // function input should be offset by variable_count assert_eq!( compiled.arguments[0].id, - FlatVariable::new(directive.outputs.len() + 1) + Variable::new(directive.outputs.len() + 1) ); // bellman variable #0: index 0 should equal 1 assert_eq!( compiled.statements[1], FlatStatement::Condition( - FlatVariable::new(0).into(), + Variable::new(0).into(), FlatExpression::Number(Bn128Field::from(1)), RuntimeError::BellmanOneBinding ) @@ -749,8 +745,8 @@ mod tests { assert_eq!( compiled.statements[2], FlatStatement::Condition( - FlatVariable::new(1).into(), - FlatVariable::new(26936).into(), + Variable::new(1).into(), + Variable::new(26936).into(), RuntimeError::BellmanInputBinding ) ); @@ -761,7 +757,7 @@ mod tests { .map(Bn128Field::from) .collect(); - let ir = crate::ir::from_flat::from_flat(compiled); + let ir = zokrates_ast::ir::from_flat::from_flat(compiled); let interpreter = Interpreter::default(); interpreter.execute(ir, &input).unwrap(); diff --git a/zokrates_ast/src/common/error.rs b/zokrates_ast/src/common/error.rs new file mode 100644 index 00000000..c1fe0656 --- /dev/null +++ b/zokrates_ast/src/common/error.rs @@ -0,0 +1,82 @@ +use serde::{Deserialize, Serialize}; +use std::fmt; + +#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)] +pub enum RuntimeError { + BellmanConstraint, + BellmanOneBinding, + BellmanInputBinding, + ArkConstraint, + ArkOneBinding, + ArkInputBinding, + Bitness, + Sum, + Equal, + Le, + BranchIsolation, + ConstantLtBitness, + ConstantLtSum, + LtBitness, + LtSum, + LtFinalBitness, + LtFinalSum, + LtSymetric, + Or, + Xor, + Inverse, + Euclidean, + ShaXor, + Division, + SourceAssertion(String), + ArgumentBitness, + SelectRangeCheck, +} + +impl RuntimeError { + pub fn is_malicious(&self) -> bool { + use RuntimeError::*; + + !matches!( + self, + SourceAssertion(_) | Inverse | LtSum | SelectRangeCheck | ArgumentBitness + ) + } +} + +impl fmt::Display for RuntimeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use RuntimeError::*; + + let msg = match self { + BellmanConstraint => "Bellman constraint is unsatisfied", + BellmanOneBinding => "Bellman ~one binding is unsatisfied", + BellmanInputBinding => "Bellman input binding is unsatisfied", + ArkConstraint => "Ark constraint is unsatisfied", + ArkOneBinding => "Ark ~one binding is unsatisfied", + ArkInputBinding => "Ark input binding is unsatisfied", + Bitness => "Bitness check failed", + Sum => "Sum check failed", + Equal => "Equal check failed", + Le => "Constant Le check failed", + BranchIsolation => "Branch isolation failed", + ConstantLtBitness => "Bitness check failed in constant Lt check", + ConstantLtSum => "Sum check failed in constant Lt check", + LtBitness => "Bitness check failed in Lt check", + LtSum => "Sum check failed in Lt check", + LtFinalBitness => "Bitness check failed in final Lt check", + LtFinalSum => "Sum check failed in final Lt check", + LtSymetric => "Symetrical check failed in Lt check", + Or => "Or check failed", + Xor => "Xor check failed", + Inverse => "Division by zero", + Euclidean => "Euclidean check failed", + ShaXor => "Internal Sha check failed", + Division => "Division check failed", + SourceAssertion(m) => m.as_str(), + ArgumentBitness => "Argument bitness check failed", + SelectRangeCheck => "Out of bounds array access", + }; + + write!(f, "{}", msg) + } +} diff --git a/zokrates_ast/src/common/mod.rs b/zokrates_ast/src/common/mod.rs new file mode 100644 index 00000000..c7d5e0b4 --- /dev/null +++ b/zokrates_ast/src/common/mod.rs @@ -0,0 +1,11 @@ +pub mod embed; +mod error; +mod parameter; +mod solvers; +mod variable; + +pub use self::embed::FlatEmbed; +pub use self::error::RuntimeError; +pub use self::parameter::Parameter; +pub use self::solvers::Solver; +pub use self::variable::Variable; diff --git a/zokrates_core/src/flat_absy/flat_parameter.rs b/zokrates_ast/src/common/parameter.rs similarity index 50% rename from zokrates_core/src/flat_absy/flat_parameter.rs rename to zokrates_ast/src/common/parameter.rs index c54ec5e7..4b17395f 100644 --- a/zokrates_core/src/flat_absy/flat_parameter.rs +++ b/zokrates_ast/src/common/parameter.rs @@ -1,47 +1,44 @@ -use crate::flat_absy::flat_variable::FlatVariable; +use super::variable::Variable; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fmt; #[derive(Serialize, Deserialize, Hash, Eq, PartialEq, Clone, Copy)] -pub struct FlatParameter { - pub id: FlatVariable, +pub struct Parameter { + pub id: Variable, pub private: bool, } -impl FlatParameter { - fn new(id: FlatVariable, private: bool) -> Self { - FlatParameter { id, private } +impl Parameter { + fn new(id: Variable, private: bool) -> Self { + Parameter { id, private } } - pub fn public(v: FlatVariable) -> Self { + pub fn public(v: Variable) -> Self { Self::new(v, false) } - pub fn private(v: FlatVariable) -> Self { + pub fn private(v: Variable) -> Self { Self::new(v, true) } } -impl fmt::Display for FlatParameter { +impl fmt::Display for Parameter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let visibility = if self.private { "private " } else { "" }; write!(f, "{}{}", visibility, self.id) } } -impl fmt::Debug for FlatParameter { +impl fmt::Debug for Parameter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "FlatParameter(id: {:?})", self.id) + write!(f, "Parameter(id: {:?})", self.id) } } -impl FlatParameter { - pub fn apply_substitution( - self, - substitution: &HashMap, - ) -> FlatParameter { - FlatParameter { +impl Parameter { + pub fn apply_substitution(self, substitution: &HashMap) -> Parameter { + Parameter { id: *substitution.get(&self.id).unwrap(), private: self.private, } diff --git a/zokrates_core/src/solvers/mod.rs b/zokrates_ast/src/common/solvers.rs similarity index 100% rename from zokrates_core/src/solvers/mod.rs rename to zokrates_ast/src/common/solvers.rs diff --git a/zokrates_core/src/flat_absy/flat_variable.rs b/zokrates_ast/src/common/variable.rs similarity index 71% rename from zokrates_core/src/flat_absy/flat_variable.rs rename to zokrates_ast/src/common/variable.rs index 1fe3f6b4..7a6b9b01 100644 --- a/zokrates_core/src/flat_absy/flat_variable.rs +++ b/zokrates_ast/src/common/variable.rs @@ -7,23 +7,23 @@ use std::fmt; // id == 0 for ~one // id < 0 for public outputs #[derive(Serialize, Deserialize, Clone, PartialEq, Hash, Eq, Ord, PartialOrd, Copy)] -pub struct FlatVariable { +pub struct Variable { id: isize, } -impl FlatVariable { +impl Variable { pub fn new(id: usize) -> Self { - FlatVariable { + Variable { id: 1 + id as isize, } } pub fn one() -> Self { - FlatVariable { id: 0 } + Variable { id: 0 } } pub fn public(id: usize) -> Self { - FlatVariable { + Variable { id: -(id as isize) - 1, } } @@ -35,21 +35,21 @@ impl FlatVariable { pub fn try_from_human_readable(s: &str) -> Result { if s == "~one" { - return Ok(FlatVariable::one()); + return Ok(Variable::one()); } let mut public = s.split("~out_"); match public.nth(1) { Some(v) => { let v = v.parse().map_err(|_| s)?; - Ok(FlatVariable::public(v)) + Ok(Variable::public(v)) } None => { let mut private = s.split('_'); match private.nth(1) { Some(v) => { let v = v.parse().map_err(|_| s)?; - Ok(FlatVariable::new(v)) + Ok(Variable::new(v)) } None => Err(s), } @@ -58,7 +58,7 @@ impl FlatVariable { } } -impl fmt::Display for FlatVariable { +impl fmt::Display for Variable { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.id { 0 => write!(f, "~one"), @@ -68,7 +68,7 @@ impl fmt::Display for FlatVariable { } } -impl fmt::Debug for FlatVariable { +impl fmt::Debug for Variable { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.id { 0 => write!(f, "~one"), @@ -78,8 +78,8 @@ impl fmt::Debug for FlatVariable { } } -impl FlatVariable { - pub fn apply_substitution(self, substitution: &HashMap) -> &Self { +impl Variable { + pub fn apply_substitution(self, substitution: &HashMap) -> &Self { substitution.get(&self).unwrap() } @@ -94,18 +94,18 @@ mod tests { #[test] fn one() { - assert_eq!(format!("{}", FlatVariable::one()), "~one"); + assert_eq!(format!("{}", Variable::one()), "~one"); } #[test] fn public() { - assert_eq!(format!("{}", FlatVariable::public(0)), "~out_0"); - assert_eq!(format!("{}", FlatVariable::public(42)), "~out_42"); + assert_eq!(format!("{}", Variable::public(0)), "~out_0"); + assert_eq!(format!("{}", Variable::public(42)), "~out_42"); } #[test] fn private() { - assert_eq!(format!("{}", FlatVariable::new(0)), "_0"); - assert_eq!(format!("{}", FlatVariable::new(42)), "_42"); + assert_eq!(format!("{}", Variable::new(0)), "_0"); + assert_eq!(format!("{}", Variable::new(42)), "_42"); } } diff --git a/zokrates_ast/src/flat/folder.rs b/zokrates_ast/src/flat/folder.rs new file mode 100644 index 00000000..a000c8b4 --- /dev/null +++ b/zokrates_ast/src/flat/folder.rs @@ -0,0 +1,92 @@ +// Generic walk through an IR AST. Not mutating in place + +use super::*; +use crate::common::Variable; +use zokrates_field::Field; + +pub trait Folder: Sized { + fn fold_program(&mut self, p: FlatProg) -> FlatProg { + fold_program(self, p) + } + + fn fold_argument(&mut self, p: Parameter) -> Parameter { + fold_argument(self, p) + } + + fn fold_variable(&mut self, v: Variable) -> Variable { + fold_variable(self, v) + } + + fn fold_statement(&mut self, s: FlatStatement) -> Vec> { + fold_statement(self, s) + } + + fn fold_expression(&mut self, e: FlatExpression) -> FlatExpression { + fold_expression(self, e) + } + + fn fold_directive(&mut self, d: FlatDirective) -> FlatDirective { + fold_directive(self, d) + } +} + +pub fn fold_program>(f: &mut F, p: FlatProg) -> FlatProg { + FlatProg { + arguments: p + .arguments + .into_iter() + .map(|a| f.fold_argument(a)) + .collect(), + statements: p + .statements + .into_iter() + .flat_map(|s| f.fold_statement(s)) + .collect(), + return_count: p.return_count, + } +} + +pub fn fold_statement>( + f: &mut F, + s: FlatStatement, +) -> Vec> { + // match s { + // Statement::Constraint(quad, lin, message) => vec![Statement::Constraint( + // f.fold_quadratic_combination(quad), + // f.fold_linear_combination(lin), + // message, + // )], + // Statement::Directive(dir) => vec![Statement::Directive(f.fold_directive(dir))], + // } + unimplemented!() +} + +pub fn fold_expression>( + f: &mut F, + e: FlatExpression, +) -> FlatExpression { + unimplemented!() +} + +pub fn fold_directive>(f: &mut F, ds: FlatDirective) -> FlatDirective { + FlatDirective { + inputs: ds + .inputs + .into_iter() + .map(|e| f.fold_expression(e)) + .collect(), + outputs: ds.outputs.into_iter().map(|o| f.fold_variable(o)).collect(), + ..ds + } +} + +pub fn fold_argument>(f: &mut F, a: Parameter) -> Parameter { + Parameter { + id: f.fold_variable(a.id), + private: a.private, + } +} + +pub fn fold_variable>(_f: &mut F, v: Variable) -> Variable { + v +} diff --git a/zokrates_core/src/flat_absy/mod.rs b/zokrates_ast/src/flat/mod.rs similarity index 71% rename from zokrates_core/src/flat_absy/mod.rs rename to zokrates_ast/src/flat/mod.rs index 01260145..27ac6e7f 100644 --- a/zokrates_core/src/flat_absy/mod.rs +++ b/zokrates_ast/src/flat/mod.rs @@ -5,99 +5,17 @@ //! @author Jacob Eberhardt //! @date 2017 -pub mod flat_parameter; -pub mod flat_variable; +pub mod folder; -pub use self::flat_parameter::FlatParameter; -pub use self::flat_variable::FlatVariable; +pub use crate::common::Parameter; +pub use crate::common::RuntimeError; +pub use crate::common::Variable; -use serde::{Deserialize, Serialize}; - -use crate::solvers::Solver; +use crate::common::Solver; use std::collections::HashMap; use std::fmt; use zokrates_field::Field; -#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)] -pub enum RuntimeError { - BellmanConstraint, - BellmanOneBinding, - BellmanInputBinding, - ArkConstraint, - ArkOneBinding, - ArkInputBinding, - Bitness, - Sum, - Equal, - Le, - BranchIsolation, - ConstantLtBitness, - ConstantLtSum, - LtBitness, - LtSum, - LtFinalBitness, - LtFinalSum, - LtSymetric, - Or, - Xor, - Inverse, - Euclidean, - ShaXor, - Division, - SourceAssertion(String), - ArgumentBitness, - SelectRangeCheck, -} - -impl RuntimeError { - pub(crate) fn is_malicious(&self) -> bool { - use RuntimeError::*; - - !matches!( - self, - SourceAssertion(_) | Inverse | LtSum | SelectRangeCheck | ArgumentBitness - ) - } -} - -impl fmt::Display for RuntimeError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use RuntimeError::*; - - let msg = match self { - BellmanConstraint => "Bellman constraint is unsatisfied", - BellmanOneBinding => "Bellman ~one binding is unsatisfied", - BellmanInputBinding => "Bellman input binding is unsatisfied", - ArkConstraint => "Ark constraint is unsatisfied", - ArkOneBinding => "Ark ~one binding is unsatisfied", - ArkInputBinding => "Ark input binding is unsatisfied", - Bitness => "Bitness check failed", - Sum => "Sum check failed", - Equal => "Equal check failed", - Le => "Constant Le check failed", - BranchIsolation => "Branch isolation failed", - ConstantLtBitness => "Bitness check failed in constant Lt check", - ConstantLtSum => "Sum check failed in constant Lt check", - LtBitness => "Bitness check failed in Lt check", - LtSum => "Sum check failed in Lt check", - LtFinalBitness => "Bitness check failed in final Lt check", - LtFinalSum => "Sum check failed in final Lt check", - LtSymetric => "Symetrical check failed in Lt check", - Or => "Or check failed", - Xor => "Xor check failed", - Inverse => "Division by zero", - Euclidean => "Euclidean check failed", - ShaXor => "Internal Sha check failed", - Division => "Division check failed", - SourceAssertion(m) => m.as_str(), - ArgumentBitness => "Argument bitness check failed", - SelectRangeCheck => "Out of bounds array access", - }; - - write!(f, "{}", msg) - } -} - pub type FlatProg = FlatFunction; pub type FlatFunction = FlatFunctionIterator>>; @@ -107,7 +25,7 @@ pub type FlatProgIterator = FlatFunctionIterator; #[derive(Clone, PartialEq, Debug)] pub struct FlatFunctionIterator>> { /// Arguments of the function - pub arguments: Vec, + pub arguments: Vec, /// Vector of statements that are executed when running the function pub statements: I, /// Number of outputs @@ -157,7 +75,7 @@ impl fmt::Display for FlatFunction { #[derive(Clone, PartialEq, Debug)] pub enum FlatStatement { Condition(FlatExpression, FlatExpression, RuntimeError), - Definition(FlatVariable, FlatExpression), + Definition(Variable, FlatExpression), Directive(FlatDirective), } @@ -176,7 +94,7 @@ impl fmt::Display for FlatStatement { impl FlatStatement { pub fn apply_substitution( self, - substitution: &HashMap, + substitution: &HashMap, ) -> FlatStatement { match self { FlatStatement::Definition(id, x) => FlatStatement::Definition( @@ -213,13 +131,13 @@ impl FlatStatement { #[derive(Clone, Hash, Debug, PartialEq, Eq)] pub struct FlatDirective { pub inputs: Vec>, - pub outputs: Vec, + pub outputs: Vec, pub solver: Solver, } impl FlatDirective { pub fn new>>( - outputs: Vec, + outputs: Vec, solver: Solver, inputs: Vec, ) -> Self { @@ -257,7 +175,7 @@ impl fmt::Display for FlatDirective { #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub enum FlatExpression { Number(T), - Identifier(FlatVariable), + Identifier(Variable), Add(Box>, Box>), Sub(Box>, Box>), Mult(Box>, Box>), @@ -272,7 +190,7 @@ impl From for FlatExpression { impl FlatExpression { pub fn apply_substitution( self, - substitution: &HashMap, + substitution: &HashMap, ) -> FlatExpression { match self { e @ FlatExpression::Number(_) => e, @@ -328,8 +246,8 @@ impl fmt::Display for FlatExpression { } } -impl From for FlatExpression { - fn from(v: FlatVariable) -> FlatExpression { +impl From for FlatExpression { + fn from(v: Variable) -> FlatExpression { FlatExpression::Identifier(v) } } diff --git a/zokrates_core/src/ir/expression.rs b/zokrates_ast/src/ir/expression.rs similarity index 82% rename from zokrates_core/src/ir/expression.rs rename to zokrates_ast/src/ir/expression.rs index 57ec2753..a32a1293 100644 --- a/zokrates_core/src/ir/expression.rs +++ b/zokrates_ast/src/ir/expression.rs @@ -1,4 +1,5 @@ -use crate::flat_absy::FlatVariable; +use super::Witness; +use crate::common::Variable; use serde::{Deserialize, Serialize}; use std::collections::btree_map::{BTreeMap, Entry}; use std::fmt; @@ -54,10 +55,10 @@ impl fmt::Display for QuadComb { } #[derive(Clone, Debug, Serialize, Deserialize, Hash, PartialEq, Eq)] -pub struct LinComb(pub Vec<(FlatVariable, T)>); +pub struct LinComb(pub Vec<(Variable, T)>); #[derive(PartialEq, PartialOrd, Clone, Eq, Ord, Hash, Debug, Serialize, Deserialize)] -pub struct CanonicalLinComb(pub BTreeMap); +pub struct CanonicalLinComb(pub BTreeMap); #[derive(PartialEq, PartialOrd, Clone, Eq, Ord, Hash, Debug, Serialize, Deserialize)] pub struct CanonicalQuadComb { @@ -81,7 +82,7 @@ impl From> for LinComb { } impl LinComb { - pub fn summand>(mult: U, var: FlatVariable) -> LinComb { + pub fn summand>(mult: U, var: Variable) -> LinComb { let res = vec![(var, mult.into())]; LinComb(res) @@ -105,7 +106,7 @@ impl LinComb { // take the first variable in the lincomb let first = &self.0[0].0; - if first != &FlatVariable::one() { + if first != &Variable::one() { return Err(self); } @@ -119,7 +120,13 @@ impl LinComb { } } - pub fn try_summand(self) -> Result<(FlatVariable, T), Self> { + pub fn is_assignee(&self, witness: &Witness) -> bool { + self.0.len() == 1 + && self.0.get(0).unwrap().1 == T::from(1) + && !witness.0.contains_key(&self.0.get(0).unwrap().0) + } + + pub fn try_summand(self) -> Result<(Variable, T), Self> { match self.0.len() { // if the lincomb is empty, it is not reduceable to a summand 0 => Err(self), @@ -143,7 +150,7 @@ impl LinComb { } pub fn one() -> LinComb { - Self::summand(1, FlatVariable::one()) + Self::summand(1, Variable::one()) } } @@ -212,8 +219,8 @@ impl fmt::Display for LinComb { } } -impl From for LinComb { - fn from(v: FlatVariable) -> LinComb { +impl From for LinComb { + fn from(v: Variable) -> LinComb { let r = vec![(v, T::one())]; LinComb(r) } @@ -277,32 +284,32 @@ mod tests { #[test] fn add_zero() { let a: LinComb = LinComb::zero(); - let b: LinComb = FlatVariable::new(42).into(); + let b: LinComb = Variable::new(42).into(); let c = a + b.clone(); assert_eq!(c, b); } #[test] fn add() { - let a: LinComb = FlatVariable::new(42).into(); - let b: LinComb = FlatVariable::new(42).into(); + let a: LinComb = Variable::new(42).into(); + let b: LinComb = Variable::new(42).into(); let c = a + b; let expected_vec = vec![ - (FlatVariable::new(42), Bn128Field::from(1)), - (FlatVariable::new(42), Bn128Field::from(1)), + (Variable::new(42), Bn128Field::from(1)), + (Variable::new(42), Bn128Field::from(1)), ]; assert_eq!(c, LinComb(expected_vec)); } #[test] fn sub() { - let a: LinComb = FlatVariable::new(42).into(); - let b: LinComb = FlatVariable::new(42).into(); + let a: LinComb = Variable::new(42).into(); + let b: LinComb = Variable::new(42).into(); let c = a - b; let expected_vec = vec![ - (FlatVariable::new(42), Bn128Field::from(1)), - (FlatVariable::new(42), Bn128Field::from(-1)), + (Variable::new(42), Bn128Field::from(1)), + (Variable::new(42), Bn128Field::from(-1)), ]; assert_eq!(c, LinComb(expected_vec)); @@ -311,7 +318,7 @@ mod tests { #[test] fn display() { let a: LinComb = - LinComb::from(FlatVariable::new(42)) + LinComb::summand(3, FlatVariable::new(21)); + LinComb::from(Variable::new(42)) + LinComb::summand(3, Variable::new(21)); assert_eq!(&a.to_string(), "1 * _42 + 3 * _21"); let zero: LinComb = LinComb::zero(); assert_eq!(&zero.to_string(), "0"); @@ -322,8 +329,8 @@ mod tests { use super::*; #[test] fn from_linear() { - let a: LinComb = LinComb::summand(3, FlatVariable::new(42)) - + LinComb::summand(4, FlatVariable::new(33)); + let a: LinComb = + LinComb::summand(3, Variable::new(42)) + LinComb::summand(4, Variable::new(33)); let expected = QuadComb { left: LinComb::one(), right: a.clone(), @@ -344,14 +351,14 @@ mod tests { #[test] fn display() { let a: QuadComb = QuadComb { - left: LinComb::summand(3, FlatVariable::new(42)) - + LinComb::summand(4, FlatVariable::new(33)), - right: LinComb::summand(1, FlatVariable::new(21)), + left: LinComb::summand(3, Variable::new(42)) + + LinComb::summand(4, Variable::new(33)), + right: LinComb::summand(1, Variable::new(21)), }; assert_eq!(&a.to_string(), "(3 * _42 + 4 * _33) * (1 * _21)"); let a: QuadComb = QuadComb { left: LinComb::zero(), - right: LinComb::summand(1, FlatVariable::new(21)), + right: LinComb::summand(1, Variable::new(21)), }; assert_eq!(&a.to_string(), "(0) * (1 * _21)"); } @@ -363,19 +370,19 @@ mod tests { #[test] fn try_summand() { let summand = LinComb(vec![ - (FlatVariable::new(42), Bn128Field::from(1)), - (FlatVariable::new(42), Bn128Field::from(2)), - (FlatVariable::new(42), Bn128Field::from(3)), + (Variable::new(42), Bn128Field::from(1)), + (Variable::new(42), Bn128Field::from(2)), + (Variable::new(42), Bn128Field::from(3)), ]); assert_eq!( summand.try_summand(), - Ok((FlatVariable::new(42), Bn128Field::from(6))) + Ok((Variable::new(42), Bn128Field::from(6))) ); let not_summand = LinComb(vec![ - (FlatVariable::new(41), Bn128Field::from(1)), - (FlatVariable::new(42), Bn128Field::from(2)), - (FlatVariable::new(42), Bn128Field::from(3)), + (Variable::new(41), Bn128Field::from(1)), + (Variable::new(42), Bn128Field::from(2)), + (Variable::new(42), Bn128Field::from(3)), ]); assert!(not_summand.try_summand().is_err()); diff --git a/zokrates_core/src/ir/folder.rs b/zokrates_ast/src/ir/folder.rs similarity index 85% rename from zokrates_core/src/ir/folder.rs rename to zokrates_ast/src/ir/folder.rs index a50c71f6..753a3836 100644 --- a/zokrates_core/src/ir/folder.rs +++ b/zokrates_ast/src/ir/folder.rs @@ -1,7 +1,7 @@ // Generic walk through an IR AST. Not mutating in place -use crate::flat_absy::flat_variable::FlatVariable; -use crate::ir::*; +use super::*; +use crate::common::Variable; use zokrates_field::Field; pub trait Folder: Sized { @@ -9,11 +9,11 @@ pub trait Folder: Sized { fold_program(self, p) } - fn fold_argument(&mut self, p: FlatParameter) -> FlatParameter { + fn fold_argument(&mut self, p: Parameter) -> Parameter { fold_argument(self, p) } - fn fold_variable(&mut self, v: FlatVariable) -> FlatVariable { + fn fold_variable(&mut self, v: Variable) -> Variable { fold_variable(self, v) } @@ -91,13 +91,13 @@ pub fn fold_directive>(f: &mut F, ds: Directive) -> Di } } -pub fn fold_argument>(f: &mut F, a: FlatParameter) -> FlatParameter { - FlatParameter { +pub fn fold_argument>(f: &mut F, a: Parameter) -> Parameter { + Parameter { id: f.fold_variable(a.id), private: a.private, } } -pub fn fold_variable>(_f: &mut F, v: FlatVariable) -> FlatVariable { +pub fn fold_variable>(_f: &mut F, v: Variable) -> Variable { v } diff --git a/zokrates_core/src/ir/from_flat.rs b/zokrates_ast/src/ir/from_flat.rs similarity index 98% rename from zokrates_core/src/ir/from_flat.rs rename to zokrates_ast/src/ir/from_flat.rs index 640336b3..c6a4e4e5 100644 --- a/zokrates_core/src/ir/from_flat.rs +++ b/zokrates_ast/src/ir/from_flat.rs @@ -1,7 +1,7 @@ use crate::flat_absy::{ FlatDirective, FlatExpression, FlatProgIterator, FlatStatement, FlatVariable, }; -use crate::ir::{Directive, LinComb, ProgIterator, QuadComb, Statement}; +use zokrates_ast::ir::{Directive, LinComb, ProgIterator, QuadComb, Statement}; use zokrates_field::Field; impl QuadComb { diff --git a/zokrates_core/src/ir/mod.rs b/zokrates_ast/src/ir/mod.rs similarity index 85% rename from zokrates_core/src/ir/mod.rs rename to zokrates_ast/src/ir/mod.rs index 1b96ea00..430b1525 100644 --- a/zokrates_core/src/ir/mod.rs +++ b/zokrates_ast/src/ir/mod.rs @@ -1,6 +1,4 @@ -use crate::flat_absy::flat_parameter::FlatParameter; -use crate::flat_absy::{FlatVariable, RuntimeError}; -use crate::solvers::Solver; +//use crate::solvers::Solver; use serde::{Deserialize, Serialize}; use std::fmt; use std::hash::Hash; @@ -8,8 +6,7 @@ use zokrates_field::Field; mod expression; pub mod folder; -pub mod from_flat; -mod interpreter; +//pub mod from_flat; mod serialize; pub mod smtlib2; pub mod visitor; @@ -18,8 +15,11 @@ mod witness; pub use self::expression::QuadComb; pub use self::expression::{CanonicalLinComb, LinComb}; pub use self::serialize::ProgEnum; +pub use crate::common::Parameter; +pub use crate::common::RuntimeError; +pub use crate::common::Solver; +pub use crate::common::Variable; -pub use self::interpreter::{Error, ExecutionResult, Interpreter}; pub use self::witness::Witness; #[derive(Debug, Serialize, Deserialize, Clone, Hash, PartialEq, Eq)] @@ -29,7 +29,7 @@ pub enum Statement { } impl Statement { - pub fn definition>>(v: FlatVariable, e: U) -> Self { + pub fn definition>>(v: Variable, e: U) -> Self { Statement::Constraint(e.into(), v.into(), None) } @@ -41,7 +41,7 @@ impl Statement { #[derive(Clone, Debug, Serialize, Deserialize, Hash, PartialEq, Eq)] pub struct Directive { pub inputs: Vec>, - pub outputs: Vec, + pub outputs: Vec, pub solver: Solver, } @@ -78,13 +78,13 @@ pub type Prog = ProgIterator>>; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)] pub struct ProgIterator>> { - pub arguments: Vec, + pub arguments: Vec, pub return_count: usize, pub statements: I, } impl>> ProgIterator { - pub fn new(arguments: Vec, statements: I, return_count: usize) -> Self { + pub fn new(arguments: Vec, statements: I, return_count: usize) -> Self { Self { arguments, return_count, @@ -100,8 +100,8 @@ impl>> ProgIterator { } } - pub fn returns(&self) -> Vec { - (0..self.return_count).map(FlatVariable::public).collect() + pub fn returns(&self) -> Vec { + (0..self.return_count).map(Variable::public).collect() } pub fn public_count(&self) -> usize { @@ -156,7 +156,7 @@ impl fmt::Display for Prog { f, "\treturn {}", (0..self.return_count) - .map(FlatVariable::public) + .map(Variable::public) .map(|e| format!("{}", e)) .collect::>() .join(", ") @@ -176,10 +176,10 @@ mod tests { fn print_constraint() { let c: Statement = Statement::Constraint( QuadComb::from_linear_combinations( - FlatVariable::new(42).into(), - FlatVariable::new(42).into(), + Variable::new(42).into(), + Variable::new(42).into(), ), - FlatVariable::new(42).into(), + Variable::new(42).into(), None, ); assert_eq!(format!("{}", c), "(1 * _42) * (1 * _42) == 1 * _42") diff --git a/zokrates_core/src/ir/serialize.rs b/zokrates_ast/src/ir/serialize.rs similarity index 92% rename from zokrates_core/src/ir/serialize.rs rename to zokrates_ast/src/ir/serialize.rs index fecf1324..ea03f00d 100644 --- a/zokrates_core/src/ir/serialize.rs +++ b/zokrates_ast/src/ir/serialize.rs @@ -1,7 +1,4 @@ -use crate::{ - ir::{ProgIterator, Statement}, - static_analysis::UnconstrainedVariableDetector, -}; +use super::{ProgIterator, Statement}; use serde_cbor::{self, StreamDeserializer}; use std::io::{Read, Write}; use zokrates_field::*; @@ -60,7 +57,7 @@ impl>> ProgIterator { /// serialize a program iterator, returning the number of constraints serialized /// Note that we only return constraints, not other statements such as directives pub fn serialize(self, mut w: W) -> Result { - use crate::ir::folder::Folder; + //use super::folder::Folder; w.write_all(ZOKRATES_MAGIC)?; w.write_all(ZOKRATES_VERSION_2)?; @@ -69,7 +66,7 @@ impl>> ProgIterator { serde_cbor::to_writer(&mut w, &self.arguments)?; serde_cbor::to_writer(&mut w, &self.return_count)?; - let mut unconstrained_variable_detector = UnconstrainedVariableDetector::new(&self); + //let mut unconstrained_variable_detector = UnconstrainedVariableDetector::new(&self); let statements = self.statements.into_iter(); @@ -78,16 +75,17 @@ impl>> ProgIterator { if matches!(s, Statement::Constraint(..)) { count += 1; } - let s = unconstrained_variable_detector.fold_statement(s); - for s in s { - serde_cbor::to_writer(&mut w, &s)?; - } + //let s = unconstrained_variable_detector.fold_statement(s); + //for s in s { + serde_cbor::to_writer(&mut w, &s)?; + //} } - unconstrained_variable_detector - .finalize() - .map(|_| count) - .map_err(|count| format!("Error: Found {} unconstrained variable(s)", count).into()) + // unconstrained_variable_detector + // .finalize() + // .map(|_| count) + // .map_err(|count| format!("Error: Found {} unconstrained variable(s)", count).into()) + Ok(count) } } @@ -137,7 +135,7 @@ impl<'de, R: Read> struct ArgumentsVisitor; impl<'de> serde::de::Visitor<'de> for ArgumentsVisitor { - type Value = Vec; + type Value = Vec; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { formatter.write_str("seq of flat param") } @@ -239,13 +237,13 @@ impl<'de, R: Read> #[cfg(test)] mod tests { use super::*; - use crate::ir; + use crate::ir::Prog; use std::io::{Cursor, Seek, SeekFrom}; use zokrates_field::{Bls12_381Field, Bn128Field}; #[test] fn ser_deser_v2() { - let p: ir::Prog = ir::Prog::default(); + let p: Prog = Prog::default(); let mut buffer = Cursor::new(vec![]); p.clone().serialize(&mut buffer).unwrap(); @@ -258,7 +256,7 @@ mod tests { assert_eq!(ProgEnum::Bn128Program(p), deserialized_p.collect()); - let p: ir::Prog = ir::Prog::default(); + let p: Prog = Prog::default(); let mut buffer = Cursor::new(vec![]); p.clone().serialize(&mut buffer).unwrap(); diff --git a/zokrates_core/src/ir/smtlib2.rs b/zokrates_ast/src/ir/smtlib2.rs similarity index 93% rename from zokrates_core/src/ir/smtlib2.rs rename to zokrates_ast/src/ir/smtlib2.rs index 560a1b90..66e78ccf 100644 --- a/zokrates_core/src/ir/smtlib2.rs +++ b/zokrates_ast/src/ir/smtlib2.rs @@ -21,11 +21,11 @@ impl fmt::Display for SMTLib2Display<'_, T> { } struct FlatVariableCollector { - variables: BTreeSet, + variables: BTreeSet, } impl Visitor for FlatVariableCollector { - fn visit_variable(&mut self, v: &FlatVariable) { + fn visit_variable(&mut self, v: &Variable) { self.variables.insert(*v); } } @@ -33,10 +33,10 @@ impl Visitor for FlatVariableCollector { impl SMTLib2 for Prog { fn to_smtlib2(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut collector = FlatVariableCollector { - variables: BTreeSet::::new(), + variables: BTreeSet::::new(), }; collector.visit_module(self); - collector.variables.insert(FlatVariable::one()); + collector.variables.insert(Variable::one()); writeln!(f, "; Auto generated by ZoKrates")?; writeln!( @@ -122,7 +122,7 @@ impl SMTLib2 for LinComb { } } -impl SMTLib2 for FlatVariable { +impl SMTLib2 for Variable { fn to_smtlib2(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "|{}|", self) } diff --git a/zokrates_core/src/ir/visitor.rs b/zokrates_ast/src/ir/visitor.rs similarity index 89% rename from zokrates_core/src/ir/visitor.rs rename to zokrates_ast/src/ir/visitor.rs index 236ade45..8de5a1f5 100644 --- a/zokrates_core/src/ir/visitor.rs +++ b/zokrates_ast/src/ir/visitor.rs @@ -1,7 +1,7 @@ // Generic walk through an IR AST. Not mutating in place -use crate::flat_absy::flat_variable::FlatVariable; -use crate::ir::*; +use super::*; +use crate::common::Variable; use zokrates_field::Field; pub trait Visitor: Sized { @@ -9,11 +9,11 @@ pub trait Visitor: Sized { visit_module(self, p) } - fn visit_argument(&mut self, p: &FlatParameter) { + fn visit_argument(&mut self, p: &Parameter) { visit_argument(self, p) } - fn visit_variable(&mut self, v: &FlatVariable) { + fn visit_variable(&mut self, v: &Variable) { visit_variable(self, v) } @@ -85,11 +85,11 @@ pub fn visit_directive>(f: &mut F, ds: &Directive) { } } -pub fn visit_argument>(f: &mut F, a: &FlatParameter) { +pub fn visit_argument>(f: &mut F, a: &Parameter) { f.visit_variable(&a.id) } -pub fn visit_variable>(_f: &mut F, _v: &FlatVariable) {} +pub fn visit_variable>(_f: &mut F, _v: &Variable) {} pub fn visit_value>(_f: &mut F, _v: &T) {} diff --git a/zokrates_core/src/ir/witness.rs b/zokrates_ast/src/ir/witness.rs similarity index 82% rename from zokrates_core/src/ir/witness.rs rename to zokrates_ast/src/ir/witness.rs index 865556b5..e1ef7090 100644 --- a/zokrates_core/src/ir/witness.rs +++ b/zokrates_ast/src/ir/witness.rs @@ -1,12 +1,12 @@ -use crate::flat_absy::FlatVariable; +use crate::common::Variable; use std::collections::{BTreeMap, HashMap}; use std::fmt; use std::io; use std::io::{Read, Write}; use zokrates_field::Field; -#[derive(Clone, Debug, PartialEq)] -pub struct Witness(pub BTreeMap); +#[derive(Clone, Debug, PartialEq, Default)] +pub struct Witness(pub BTreeMap); impl Witness { pub fn return_values(&self) -> Vec { @@ -17,11 +17,15 @@ impl Witness { .collect::>(); (0..out.len()) - .map(|i| *out.get(&FlatVariable::public(i)).unwrap()) + .map(|i| *out.get(&Variable::public(i)).unwrap()) .cloned() .collect() } + pub fn insert(&mut self, var: Variable, val: T) -> Option { + self.0.insert(var, val) + } + pub fn format_outputs(&self) -> String { self.0 .iter() @@ -63,13 +67,12 @@ impl Witness { .deserialize::<(String, String)>() .map(|r| { r.map(|(variable, value)| { - let variable = - FlatVariable::try_from_human_readable(&variable).map_err(|why| { - io::Error::new( - io::ErrorKind::Other, - format!("Invalid variable in witness: {}", why), - ) - })?; + let variable = Variable::try_from_human_readable(&variable).map_err(|why| { + io::Error::new( + io::ErrorKind::Other, + format!("Invalid variable in witness: {}", why), + ) + })?; let value = T::try_from_dec_str(&value).map_err(|_| { io::Error::new( io::ErrorKind::Other, @@ -83,7 +86,7 @@ impl Witness { e => io::Error::new(io::ErrorKind::Other, format!("{:?}", e)), })? }) - .collect::>>()?; + .collect::>>()?; Ok(Witness(map)) } @@ -116,9 +119,9 @@ mod tests { fn serialize_deserialize() { let w = Witness( vec![ - (FlatVariable::new(42), Bn128Field::from(42)), - (FlatVariable::public(8), Bn128Field::from(8)), - (FlatVariable::one(), Bn128Field::from(1)), + (Variable::new(42), Bn128Field::from(42)), + (Variable::public(8), Bn128Field::from(8)), + (Variable::one(), Bn128Field::from(1)), ] .into_iter() .collect(), diff --git a/zokrates_ast/src/lib.rs b/zokrates_ast/src/lib.rs new file mode 100644 index 00000000..797b8561 --- /dev/null +++ b/zokrates_ast/src/lib.rs @@ -0,0 +1,10 @@ +#![feature(box_patterns, box_syntax)] + +pub mod common; +pub mod flat; +pub mod ir; +pub mod typed; +pub mod untyped; +pub mod zir; + +pub use common::Solver; diff --git a/zokrates_core/src/typed_absy/abi.rs b/zokrates_ast/src/typed/abi.rs similarity index 99% rename from zokrates_core/src/typed_absy/abi.rs rename to zokrates_ast/src/typed/abi.rs index 4bcd11b6..897cc2c8 100644 --- a/zokrates_core/src/typed_absy/abi.rs +++ b/zokrates_ast/src/typed/abi.rs @@ -1,4 +1,4 @@ -use crate::typed_absy::types::{ConcreteSignature, ConcreteType}; +use crate::typed::types::{ConcreteSignature, ConcreteType}; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] @@ -30,10 +30,10 @@ impl Abi { #[cfg(test)] mod tests { use super::*; - use crate::typed_absy::types::{ + use crate::typed::types::{ ConcreteArrayType, ConcreteFunctionKey, ConcreteStructMember, ConcreteStructType, UBitwidth, }; - use crate::typed_absy::{ + use crate::typed::{ parameter::DeclarationParameter, variable::DeclarationVariable, ConcreteTupleType, ConcreteType, TypedFunction, TypedFunctionSymbol, TypedFunctionSymbolDeclaration, TypedModule, TypedProgram, diff --git a/zokrates_core/src/typed_absy/folder.rs b/zokrates_ast/src/typed/folder.rs similarity index 99% rename from zokrates_core/src/typed_absy/folder.rs rename to zokrates_ast/src/typed/folder.rs index 1f0aba6d..3dda0ee0 100644 --- a/zokrates_core/src/typed_absy/folder.rs +++ b/zokrates_ast/src/typed/folder.rs @@ -1,7 +1,7 @@ // Generic walk through a typed AST. Not mutating in place -use crate::typed_absy::types::*; -use crate::typed_absy::*; +use crate::typed::types::*; +use crate::typed::*; use zokrates_field::Field; pub trait Fold<'ast, T: Field>: Sized { diff --git a/zokrates_core/src/typed_absy/identifier.rs b/zokrates_ast/src/typed/identifier.rs similarity index 97% rename from zokrates_core/src/typed_absy/identifier.rs rename to zokrates_ast/src/typed/identifier.rs index 56246eb5..2eb64390 100644 --- a/zokrates_core/src/typed_absy/identifier.rs +++ b/zokrates_ast/src/typed/identifier.rs @@ -1,4 +1,4 @@ -use crate::typed_absy::CanonicalConstantIdentifier; +use crate::typed::CanonicalConstantIdentifier; use std::convert::TryInto; use std::fmt; diff --git a/zokrates_core/src/typed_absy/integer.rs b/zokrates_ast/src/typed/integer.rs similarity index 99% rename from zokrates_core/src/typed_absy/integer.rs rename to zokrates_ast/src/typed/integer.rs index 79b00113..60d70782 100644 --- a/zokrates_core/src/typed_absy/integer.rs +++ b/zokrates_ast/src/typed/integer.rs @@ -1,10 +1,10 @@ -use crate::typed_absy::types::{ +use crate::typed::types::{ ArrayType, DeclarationArrayType, DeclarationConstant, DeclarationStructMember, DeclarationStructType, DeclarationTupleType, DeclarationType, GArrayType, GStructType, GTupleType, GType, GenericIdentifier, StructType, TupleType, Type, }; -use crate::typed_absy::UBitwidth; -use crate::typed_absy::{ +use crate::typed::UBitwidth; +use crate::typed::{ ArrayExpression, ArrayExpressionInner, BooleanExpression, Conditional, ConditionalExpression, Expr, FieldElementExpression, Select, SelectExpression, StructExpression, StructExpressionInner, TupleExpression, TupleExpressionInner, Typed, TypedExpression, @@ -791,7 +791,7 @@ impl<'ast, T> From for IntExpression<'ast, T> { #[cfg(test)] mod tests { use super::*; - use crate::typed_absy::ConditionalKind; + use crate::typed::ConditionalKind; use zokrates_field::Bn128Field; #[test] diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_ast/src/typed/mod.rs similarity index 99% rename from zokrates_core/src/typed_absy/mod.rs rename to zokrates_ast/src/typed/mod.rs index c10ebf74..8ee9d622 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_ast/src/typed/mod.rs @@ -25,28 +25,28 @@ pub use self::types::{ GArrayType, GStructType, GType, GenericIdentifier, IntoTypes, Signature, StructType, TupleType, Type, Types, UBitwidth, }; -use crate::parser::Position; -use crate::typed_absy::types::ConcreteGenericsAssignment; +use crate::typed::types::ConcreteGenericsAssignment; +use crate::untyped::Position; pub use self::variable::{ConcreteVariable, DeclarationVariable, GVariable, Variable}; use std::marker::PhantomData; use std::path::{Path, PathBuf}; -pub use crate::typed_absy::integer::IntExpression; -pub use crate::typed_absy::uint::{bitwidth, UExpression, UExpressionInner, UMetadata}; +pub use crate::typed::integer::IntExpression; +pub use crate::typed::uint::{bitwidth, UExpression, UExpressionInner, UMetadata}; -use crate::embed::FlatEmbed; +use crate::common::FlatEmbed; use std::collections::BTreeMap; use std::convert::{TryFrom, TryInto}; use std::fmt; -pub use crate::typed_absy::types::{ArrayType, FunctionKey, MemberId}; +pub use crate::typed::types::{ArrayType, FunctionKey, MemberId}; use zokrates_field::Field; pub use self::folder::Folder; -use crate::typed_absy::abi::{Abi, AbiInput}; +use crate::typed::abi::{Abi, AbiInput}; use std::ops::{Add, Div, Mul, Sub}; pub use self::identifier::Identifier; @@ -109,7 +109,7 @@ impl<'ast, T: Field> TypedProgram<'ast, T> { .iter() .map(|p| { types::ConcreteType::try_from( - crate::typed_absy::types::try_from_g_type::< + crate::typed::types::try_from_g_type::< DeclarationConstant<'ast, T>, UExpression<'ast, T>, >(p.id._type.clone()) @@ -129,7 +129,7 @@ impl<'ast, T: Field> TypedProgram<'ast, T> { .iter() .map(|ty| { types::ConcreteType::try_from( - crate::typed_absy::types::try_from_g_type::< + crate::typed::types::try_from_g_type::< DeclarationConstant<'ast, T>, UExpression<'ast, T>, >(ty.clone()) @@ -2236,7 +2236,7 @@ impl<'ast, T: Clone> Member<'ast, T> for UExpression<'ast, T> { fn member(s: StructExpression<'ast, T>, id: MemberId) -> Self { let ty = s.ty().members.iter().find(|member| id == member.id); let bitwidth = match ty { - Some(crate::typed_absy::types::StructMember { + Some(crate::typed::types::StructMember { ty: box Type::Uint(bitwidth), .. }) => *bitwidth, @@ -2250,7 +2250,7 @@ impl<'ast, T: Clone> Member<'ast, T> for ArrayExpression<'ast, T> { fn member(s: StructExpression<'ast, T>, id: MemberId) -> Self { let ty = s.ty().members.iter().find(|member| id == member.id); let (ty, size) = match ty { - Some(crate::typed_absy::types::StructMember { + Some(crate::typed::types::StructMember { ty: box Type::Array(array_ty), .. }) => (*array_ty.ty.clone(), array_ty.size.clone()), @@ -2264,7 +2264,7 @@ impl<'ast, T: Clone> Member<'ast, T> for StructExpression<'ast, T> { fn member(s: StructExpression<'ast, T>, id: MemberId) -> Self { let ty = s.ty().members.iter().find(|member| id == member.id); let struct_ty = match ty { - Some(crate::typed_absy::types::StructMember { + Some(crate::typed::types::StructMember { ty: box Type::Struct(struct_ty), .. }) => struct_ty.clone(), @@ -2278,7 +2278,7 @@ impl<'ast, T: Clone> Member<'ast, T> for TupleExpression<'ast, T> { fn member(s: StructExpression<'ast, T>, id: MemberId) -> Self { let ty = s.ty().members.iter().find(|member| id == member.id); let tuple_ty = match ty { - Some(crate::typed_absy::types::StructMember { + Some(crate::typed::types::StructMember { ty: box Type::Tuple(tuple_ty), .. }) => tuple_ty.clone(), diff --git a/zokrates_core/src/typed_absy/parameter.rs b/zokrates_ast/src/typed/parameter.rs similarity index 91% rename from zokrates_core/src/typed_absy/parameter.rs rename to zokrates_ast/src/typed/parameter.rs index 34dbb5b0..4fad5c82 100644 --- a/zokrates_core/src/typed_absy/parameter.rs +++ b/zokrates_ast/src/typed/parameter.rs @@ -1,5 +1,5 @@ -use crate::typed_absy::types::DeclarationConstant; -use crate::typed_absy::GVariable; +use crate::typed::types::DeclarationConstant; +use crate::typed::GVariable; use std::fmt; #[derive(Clone, PartialEq, Eq, Hash)] diff --git a/zokrates_core/src/typed_absy/result_folder.rs b/zokrates_ast/src/typed/result_folder.rs similarity index 99% rename from zokrates_core/src/typed_absy/result_folder.rs rename to zokrates_ast/src/typed/result_folder.rs index 842e9852..dad24578 100644 --- a/zokrates_core/src/typed_absy/result_folder.rs +++ b/zokrates_ast/src/typed/result_folder.rs @@ -1,7 +1,7 @@ // Generic walk through a typed AST. Not mutating in place -use crate::typed_absy::types::*; -use crate::typed_absy::*; +use crate::typed::types::*; +use crate::typed::*; use zokrates_field::Field; pub trait ResultFold<'ast, T: Field>: Sized { diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_ast/src/typed/types.rs similarity index 99% rename from zokrates_core/src/typed_absy/types.rs rename to zokrates_ast/src/typed/types.rs index f817c65f..8e35f589 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_ast/src/typed/types.rs @@ -1,7 +1,7 @@ -use crate::typed_absy::{ +use crate::typed::{ CoreIdentifier, Identifier, OwnedTypedModuleId, TypedExpression, UExpression, UExpressionInner, }; -use crate::typed_absy::{TryFrom, TryInto}; +use crate::typed::{TryFrom, TryInto}; use serde::{de::Error, ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; use std::collections::BTreeMap; use std::fmt; diff --git a/zokrates_core/src/typed_absy/uint.rs b/zokrates_ast/src/typed/uint.rs similarity index 99% rename from zokrates_core/src/typed_absy/uint.rs rename to zokrates_ast/src/typed/uint.rs index 09c34689..51579e6b 100644 --- a/zokrates_core/src/typed_absy/uint.rs +++ b/zokrates_ast/src/typed/uint.rs @@ -1,5 +1,5 @@ -use crate::typed_absy::types::UBitwidth; -use crate::typed_absy::*; +use crate::typed::types::UBitwidth; +use crate::typed::*; use std::ops::{Add, Div, Mul, Neg, Not, Rem, Sub}; use zokrates_field::Field; diff --git a/zokrates_core/src/typed_absy/variable.rs b/zokrates_ast/src/typed/variable.rs similarity index 88% rename from zokrates_core/src/typed_absy/variable.rs rename to zokrates_ast/src/typed/variable.rs index f287eda5..e4eadffe 100644 --- a/zokrates_core/src/typed_absy/variable.rs +++ b/zokrates_ast/src/typed/variable.rs @@ -1,8 +1,8 @@ -use crate::typed_absy::types::{DeclarationConstant, GStructType, UBitwidth}; -use crate::typed_absy::types::{GType, SpecializationError}; -use crate::typed_absy::Identifier; -use crate::typed_absy::UExpression; -use crate::typed_absy::{TryFrom, TryInto}; +use crate::typed::types::{DeclarationConstant, GStructType, UBitwidth}; +use crate::typed::types::{GType, SpecializationError}; +use crate::typed::Identifier; +use crate::typed::UExpression; +use crate::typed::{TryFrom, TryInto}; use std::fmt; #[derive(Clone, PartialEq, Hash, Eq, PartialOrd, Ord)] @@ -36,7 +36,7 @@ impl<'ast, T> From> for Variable<'ast, T> { pub fn try_from_g_variable, U>( v: GVariable, ) -> Result, SpecializationError> { - let _type = crate::typed_absy::types::try_from_g_type(v._type)?; + let _type = crate::typed::types::try_from_g_type(v._type)?; Ok(GVariable { _type, id: v.id }) } diff --git a/zokrates_ast/src/untyped/from_ast.rs b/zokrates_ast/src/untyped/from_ast.rs new file mode 100644 index 00000000..8a79989d --- /dev/null +++ b/zokrates_ast/src/untyped/from_ast.rs @@ -0,0 +1,1398 @@ +use crate::untyped; + +use num_bigint::BigUint; +use std::path::Path; +use zokrates_pest_ast as pest; + +impl<'ast> From> for untyped::Module<'ast> { + fn from(file: pest::File<'ast>) -> untyped::Module<'ast> { + untyped::Module::with_symbols(file.declarations.into_iter().flat_map(|d| match d { + pest::SymbolDeclaration::Import(i) => import_directive_to_symbol_vec(i), + pest::SymbolDeclaration::Constant(c) => vec![c.into()], + pest::SymbolDeclaration::Struct(s) => vec![s.into()], + pest::SymbolDeclaration::Type(t) => vec![t.into()], + pest::SymbolDeclaration::Function(f) => vec![f.into()], + })) + } +} + +fn import_directive_to_symbol_vec( + import: pest::ImportDirective, +) -> Vec { + use crate::untyped::NodeValue; + + match import { + pest::ImportDirective::Main(import) => { + let span = import.span; + let source = Path::new(import.source.span.as_str()); + let id = "main"; + let alias = import.alias.map(|a| a.span.as_str()); + + let import = untyped::CanonicalImport { + source, + id: untyped::SymbolIdentifier::from(id).alias(alias), + } + .span(span.clone()); + + vec![untyped::SymbolDeclaration { + id: alias.unwrap_or(id), + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Import(import)), + } + .span(span.clone())] + } + pest::ImportDirective::From(import) => { + let span = import.span; + let source = Path::new(import.source.span.as_str()); + import + .symbols + .into_iter() + .map(|symbol| { + let alias = symbol + .alias + .as_ref() + .map(|a| a.span.as_str()) + .unwrap_or_else(|| symbol.id.span.as_str()); + + let import = untyped::CanonicalImport { + source, + id: untyped::SymbolIdentifier::from(symbol.id.span.as_str()) + .alias(Some(alias)), + } + .span(span.clone()); + + untyped::SymbolDeclaration { + id: alias, + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Import(import)), + } + .span(span.clone()) + }) + .collect() + } + } +} + +impl<'ast> From> for untyped::SymbolDeclarationNode<'ast> { + fn from(definition: pest::StructDefinition<'ast>) -> untyped::SymbolDeclarationNode<'ast> { + use crate::untyped::NodeValue; + + let span = definition.span; + + let id = definition.id.span.as_str(); + + let ty = untyped::StructDefinition { + generics: definition + .generics + .into_iter() + .map(untyped::ConstantGenericNode::from) + .collect(), + fields: definition + .fields + .into_iter() + .map(untyped::StructDefinitionFieldNode::from) + .collect(), + } + .span(span.clone()); + + untyped::SymbolDeclaration { + id, + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Struct(ty)), + } + .span(span) + } +} + +impl<'ast> From> for untyped::StructDefinitionFieldNode<'ast> { + fn from(field: pest::StructField<'ast>) -> untyped::StructDefinitionFieldNode<'ast> { + use crate::untyped::NodeValue; + + let span = field.span; + + let id = field.id.span.as_str(); + + let ty = untyped::UnresolvedTypeNode::from(field.ty); + + untyped::StructDefinitionField { id, ty }.span(span) + } +} + +impl<'ast> From> for untyped::SymbolDeclarationNode<'ast> { + fn from(definition: pest::ConstantDefinition<'ast>) -> untyped::SymbolDeclarationNode<'ast> { + use crate::untyped::NodeValue; + + let span = definition.span; + let id = definition.id.span.as_str(); + + let ty = untyped::ConstantDefinition { + ty: definition.ty.into(), + expression: definition.expression.into(), + } + .span(span.clone()); + + untyped::SymbolDeclaration { + id, + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Constant(ty)), + } + .span(span) + } +} + +impl<'ast> From> for untyped::SymbolDeclarationNode<'ast> { + fn from(definition: pest::TypeDefinition<'ast>) -> untyped::SymbolDeclarationNode<'ast> { + use crate::untyped::NodeValue; + + let span = definition.span; + let id = definition.id.span.as_str(); + + let ty = untyped::TypeDefinition { + generics: definition + .generics + .into_iter() + .map(untyped::ConstantGenericNode::from) + .collect(), + ty: definition.ty.into(), + } + .span(span.clone()); + + untyped::SymbolDeclaration { + id, + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Type(ty)), + } + .span(span) + } +} + +impl<'ast> From> for untyped::SymbolDeclarationNode<'ast> { + fn from(function: pest::FunctionDefinition<'ast>) -> untyped::SymbolDeclarationNode<'ast> { + use crate::untyped::NodeValue; + + let span = function.span; + + let signature = untyped::UnresolvedSignature::new() + .generics( + function + .generics + .into_iter() + .map(untyped::ConstantGenericNode::from) + .collect(), + ) + .inputs( + function + .parameters + .clone() + .into_iter() + .map(|p| untyped::UnresolvedTypeNode::from(p.ty)) + .collect(), + ) + .outputs( + function + .returns + .clone() + .into_iter() + .map(untyped::UnresolvedTypeNode::from) + .collect(), + ); + + let id = function.id.span.as_str(); + + let function = untyped::Function { + arguments: function + .parameters + .into_iter() + .map(untyped::ParameterNode::from) + .collect(), + statements: function + .statements + .into_iter() + .flat_map(statements_from_statement) + .collect(), + signature, + } + .span(span.clone()); + + untyped::SymbolDeclaration { + id, + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function(function)), + } + .span(span) + } +} + +impl<'ast> From> for untyped::ConstantGenericNode<'ast> { + fn from(g: pest::IdentifierExpression<'ast>) -> untyped::ConstantGenericNode<'ast> { + use untyped::NodeValue; + + let name = g.span.as_str(); + + name.span(g.span) + } +} + +impl<'ast> From> for untyped::ParameterNode<'ast> { + fn from(param: pest::Parameter<'ast>) -> untyped::ParameterNode<'ast> { + use crate::untyped::NodeValue; + + let private = param + .visibility + .map(|v| match v { + pest::Visibility::Private(_) => true, + pest::Visibility::Public(_) => false, + }) + .unwrap_or(false); + + let variable = untyped::Variable::new( + param.id.span.as_str(), + untyped::UnresolvedTypeNode::from(param.ty), + ) + .span(param.id.span); + + untyped::Parameter::new(variable, private).span(param.span) + } +} + +fn statements_from_statement(statement: pest::Statement) -> Vec { + match statement { + pest::Statement::Definition(s) => statements_from_definition(s), + pest::Statement::Iteration(s) => vec![untyped::StatementNode::from(s)], + pest::Statement::Assertion(s) => vec![untyped::StatementNode::from(s)], + pest::Statement::Return(s) => vec![untyped::StatementNode::from(s)], + } +} + +fn statements_from_definition( + definition: pest::DefinitionStatement, +) -> Vec { + use crate::untyped::NodeValue; + + let lhs = definition.lhs; + + match lhs.len() { + 1 => { + // Definition or assignment + let a = lhs[0].clone(); + + let e: untyped::ExpressionNode = untyped::ExpressionNode::from(definition.expression); + + match a { + pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => { + let declaration = untyped::Statement::Declaration( + untyped::Variable::new( + i.identifier.span.as_str(), + untyped::UnresolvedTypeNode::from(i.ty), + ) + .span(i.identifier.span.clone()), + ) + .span(definition.span.clone()); + + let s = match e.value { + untyped::Expression::FunctionCall(..) => { + untyped::Statement::MultipleDefinition( + vec![untyped::AssigneeNode::from(i.identifier.clone())], + e, + ) + } + _ => untyped::Statement::Definition( + untyped::AssigneeNode::from(i.identifier.clone()), + e, + ), + }; + + vec![declaration, s.span(definition.span)] + } + pest::TypedIdentifierOrAssignee::Assignee(a) => { + let s = match e.value { + untyped::Expression::FunctionCall(..) => { + untyped::Statement::MultipleDefinition( + vec![untyped::AssigneeNode::from(a)], + e, + ) + } + _ => untyped::Statement::Definition(untyped::AssigneeNode::from(a), e), + }; + + vec![s.span(definition.span)] + } + } + } + _ => { + // Multidefinition + let declarations = lhs.clone().into_iter().filter_map(|i| match i { + pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => { + let ty = i.ty; + let id = i.identifier; + + Some( + untyped::Statement::Declaration( + untyped::Variable::new( + id.span.as_str(), + untyped::UnresolvedTypeNode::from(ty), + ) + .span(id.span), + ) + .span(i.span), + ) + } + _ => None, + }); + + let lhs = lhs + .into_iter() + .map(|i| match i { + pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => { + untyped::Assignee::Identifier(i.identifier.span.as_str()) + .span(i.identifier.span) + } + pest::TypedIdentifierOrAssignee::Assignee(a) => untyped::AssigneeNode::from(a), + }) + .collect(); + + let multi_def = untyped::Statement::MultipleDefinition( + lhs, + untyped::ExpressionNode::from(definition.expression), + ) + .span(definition.span); + + declarations.chain(std::iter::once(multi_def)).collect() + } + } +} + +impl<'ast> From> for untyped::StatementNode<'ast> { + fn from(statement: pest::ReturnStatement<'ast>) -> untyped::StatementNode<'ast> { + use crate::untyped::NodeValue; + + untyped::Statement::Return( + untyped::ExpressionList { + expressions: statement + .expressions + .into_iter() + .map(untyped::ExpressionNode::from) + .collect(), + } + .span(statement.span.clone()), + ) + .span(statement.span) + } +} + +impl<'ast> From> for untyped::StatementNode<'ast> { + fn from(statement: pest::AssertionStatement<'ast>) -> untyped::StatementNode<'ast> { + use crate::untyped::NodeValue; + + untyped::Statement::Assertion( + untyped::ExpressionNode::from(statement.expression), + statement.message.map(|m| m.value), + ) + .span(statement.span) + } +} + +impl<'ast> From> for untyped::StatementNode<'ast> { + fn from(statement: pest::IterationStatement<'ast>) -> untyped::StatementNode<'ast> { + use crate::untyped::NodeValue; + let from = untyped::ExpressionNode::from(statement.from); + let to = untyped::ExpressionNode::from(statement.to); + let index = statement.index.span.as_str(); + let ty = untyped::UnresolvedTypeNode::from(statement.ty); + let statements: Vec> = statement + .statements + .into_iter() + .flat_map(statements_from_statement) + .collect(); + + let var = untyped::Variable::new(index, ty).span(statement.index.span); + + untyped::Statement::For(var, from, to, statements).span(statement.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::Expression<'ast>) -> untyped::ExpressionNode<'ast> { + match expression { + pest::Expression::Binary(e) => untyped::ExpressionNode::from(e), + pest::Expression::Ternary(e) => untyped::ExpressionNode::from(e), + pest::Expression::IfElse(e) => untyped::ExpressionNode::from(e), + pest::Expression::Literal(e) => untyped::ExpressionNode::from(e), + pest::Expression::Identifier(e) => untyped::ExpressionNode::from(e), + pest::Expression::Postfix(e) => untyped::ExpressionNode::from(e), + pest::Expression::InlineArray(e) => untyped::ExpressionNode::from(e), + pest::Expression::InlineTuple(e) => untyped::ExpressionNode::from(e), + pest::Expression::InlineStruct(e) => untyped::ExpressionNode::from(e), + pest::Expression::ArrayInitializer(e) => untyped::ExpressionNode::from(e), + pest::Expression::Unary(e) => untyped::ExpressionNode::from(e), + } + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::BinaryExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + match expression.op { + pest::BinaryOperator::Add => untyped::Expression::Add( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Sub => untyped::Expression::Sub( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Mul => untyped::Expression::Mult( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Div => untyped::Expression::Div( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Rem => untyped::Expression::Rem( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Eq => untyped::Expression::Eq( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Lt => untyped::Expression::Lt( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Lte => untyped::Expression::Le( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Gt => untyped::Expression::Gt( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Gte => untyped::Expression::Ge( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::And => untyped::Expression::And( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Or => untyped::Expression::Or( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::Pow => untyped::Expression::Pow( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::BitXor => untyped::Expression::BitXor( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::LeftShift => untyped::Expression::LeftShift( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::RightShift => untyped::Expression::RightShift( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::BitAnd => untyped::Expression::BitAnd( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + pest::BinaryOperator::BitOr => untyped::Expression::BitOr( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ), + // rewrite (a != b)` as `!(a == b)` + pest::BinaryOperator::NotEq => untyped::Expression::Not( + box untyped::Expression::Eq( + box untyped::ExpressionNode::from(*expression.left), + box untyped::ExpressionNode::from(*expression.right), + ) + .span(expression.span.clone()), + ), + } + .span(expression.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::IfElseExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + untyped::Expression::Conditional( + box untyped::ExpressionNode::from(*expression.condition), + box untyped::ExpressionNode::from(*expression.consequence), + box untyped::ExpressionNode::from(*expression.alternative), + untyped::ConditionalKind::IfElse, + ) + .span(expression.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::TernaryExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + untyped::Expression::Conditional( + box untyped::ExpressionNode::from(*expression.condition), + box untyped::ExpressionNode::from(*expression.consequence), + box untyped::ExpressionNode::from(*expression.alternative), + untyped::ConditionalKind::Ternary, + ) + .span(expression.span) + } +} + +impl<'ast> From> for untyped::SpreadNode<'ast> { + fn from(spread: pest::Spread<'ast>) -> untyped::SpreadNode<'ast> { + use crate::untyped::NodeValue; + untyped::Spread { + expression: untyped::ExpressionNode::from(spread.expression), + } + .span(spread.span) + } +} + +impl<'ast> From> for untyped::RangeNode<'ast> { + fn from(range: pest::Range<'ast>) -> untyped::RangeNode<'ast> { + use crate::untyped::NodeValue; + + let from = range.from.map(|e| untyped::ExpressionNode::from(e.0)); + + let to = range.to.map(|e| untyped::ExpressionNode::from(e.0)); + + untyped::Range { from, to }.span(range.span) + } +} + +impl<'ast> From> for untyped::RangeOrExpression<'ast> { + fn from( + range_or_expression: pest::RangeOrExpression<'ast>, + ) -> untyped::RangeOrExpression<'ast> { + match range_or_expression { + pest::RangeOrExpression::Expression(e) => { + untyped::RangeOrExpression::Expression(untyped::ExpressionNode::from(e)) + } + pest::RangeOrExpression::Range(r) => { + untyped::RangeOrExpression::Range(untyped::RangeNode::from(r)) + } + } + } +} + +impl<'ast> From> for untyped::SpreadOrExpression<'ast> { + fn from( + spread_or_expression: pest::SpreadOrExpression<'ast>, + ) -> untyped::SpreadOrExpression<'ast> { + match spread_or_expression { + pest::SpreadOrExpression::Expression(e) => { + untyped::SpreadOrExpression::Expression(untyped::ExpressionNode::from(e)) + } + pest::SpreadOrExpression::Spread(s) => { + untyped::SpreadOrExpression::Spread(untyped::SpreadNode::from(s)) + } + } + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(array: pest::InlineArrayExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + untyped::Expression::InlineArray( + array + .expressions + .into_iter() + .map(untyped::SpreadOrExpression::from) + .collect(), + ) + .span(array.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(tuple: pest::InlineTupleExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + untyped::Expression::InlineTuple( + tuple + .elements + .into_iter() + .map(untyped::ExpressionNode::from) + .collect(), + ) + .span(tuple.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(s: pest::InlineStructExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + untyped::Expression::InlineStruct( + s.ty.span.as_str().to_string(), + s.members + .into_iter() + .map(|member| { + ( + member.id.span.as_str(), + untyped::ExpressionNode::from(member.expression), + ) + }) + .collect(), + ) + .span(s.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(initializer: pest::ArrayInitializerExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + + let value = untyped::ExpressionNode::from(*initializer.value); + let count = untyped::ExpressionNode::from(*initializer.count); + untyped::Expression::ArrayInitializer(box value, box count).span(initializer.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(unary: pest::UnaryExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + + let expression = Box::new(untyped::ExpressionNode::from(*unary.expression)); + + match unary.op { + pest::UnaryOperator::Not(..) => untyped::Expression::Not(expression), + pest::UnaryOperator::Neg(..) => untyped::Expression::Neg(expression), + pest::UnaryOperator::Pos(..) => untyped::Expression::Pos(expression), + } + .span(unary.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::PostfixExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + + let base = untyped::ExpressionNode::from(*expression.base); + + // pest::PostFixExpression contains an array of "accesses": `a(34)[42]` is represented as `[a, [Call(34), Select(42)]]`, but untyped::ExpressionNode + // is recursive, so it is `Select(Call(a, 34), 42)`. We apply this transformation here + // we start with the base, and we fold the array of accesses by wrapping the current value + expression + .accesses + .into_iter() + .fold(base, |acc, a| match a { + pest::Access::Call(a) => untyped::Expression::FunctionCall( + Box::new(acc), + a.explicit_generics.map(|explicit_generics| { + explicit_generics + .values + .into_iter() + .map(|i| match i { + pest::ConstantGenericValue::Underscore(_) => None, + pest::ConstantGenericValue::Value(v) => { + Some(untyped::ExpressionNode::from(v)) + } + pest::ConstantGenericValue::Identifier(i) => Some( + untyped::Expression::Identifier(i.span.as_str()).span(i.span), + ), + }) + .collect() + }), + a.arguments + .expressions + .into_iter() + .map(untyped::ExpressionNode::from) + .collect(), + ) + .span(a.span), + pest::Access::Select(a) => untyped::Expression::Select( + box acc, + box untyped::RangeOrExpression::from(a.expression), + ) + .span(a.span), + pest::Access::Dot(m) => match m.inner { + pest::IdentifierOrDecimal::Identifier(id) => { + untyped::Expression::Member(box acc, box id.span.as_str()).span(m.span) + } + pest::IdentifierOrDecimal::Decimal(id) => { + untyped::Expression::Element(box acc, id.span.as_str().parse().unwrap()) + .span(m.span) + } + }, + }) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::DecimalLiteralExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + + match expression.suffix { + Some(suffix) => match suffix { + pest::DecimalSuffix::Field(_) => untyped::Expression::FieldConstant( + BigUint::parse_bytes(expression.value.span.as_str().as_bytes(), 10).unwrap(), + ), + pest::DecimalSuffix::U64(_) => untyped::Expression::U64Constant( + expression.value.span.as_str().parse().unwrap(), + ), + pest::DecimalSuffix::U32(_) => untyped::Expression::U32Constant( + expression.value.span.as_str().parse().unwrap(), + ), + pest::DecimalSuffix::U16(_) => untyped::Expression::U16Constant( + expression.value.span.as_str().parse().unwrap(), + ), + pest::DecimalSuffix::U8(_) => { + untyped::Expression::U8Constant(expression.value.span.as_str().parse().unwrap()) + } + } + .span(expression.span), + None => untyped::Expression::IntConstant( + BigUint::parse_bytes(expression.value.span.as_str().as_bytes(), 10).unwrap(), + ) + .span(expression.span), + } + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::HexLiteralExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + + match expression.value { + pest::HexNumberExpression::U64(e) => { + untyped::Expression::U64Constant(u64::from_str_radix(e.span.as_str(), 16).unwrap()) + } + pest::HexNumberExpression::U32(e) => { + untyped::Expression::U32Constant(u32::from_str_radix(e.span.as_str(), 16).unwrap()) + } + pest::HexNumberExpression::U16(e) => { + untyped::Expression::U16Constant(u16::from_str_radix(e.span.as_str(), 16).unwrap()) + } + pest::HexNumberExpression::U8(e) => { + untyped::Expression::U8Constant(u8::from_str_radix(e.span.as_str(), 16).unwrap()) + } + } + .span(expression.span) + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::LiteralExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + + match expression { + pest::LiteralExpression::BooleanLiteral(c) => { + untyped::Expression::BooleanConstant(c.value.parse().unwrap()).span(c.span) + } + pest::LiteralExpression::DecimalLiteral(n) => untyped::ExpressionNode::from(n), + pest::LiteralExpression::HexLiteral(n) => untyped::ExpressionNode::from(n), + } + } +} + +impl<'ast> From> for untyped::ExpressionNode<'ast> { + fn from(expression: pest::IdentifierExpression<'ast>) -> untyped::ExpressionNode<'ast> { + use crate::untyped::NodeValue; + untyped::Expression::Identifier(expression.span.as_str()).span(expression.span) + } +} + +impl<'ast> From> for untyped::AssigneeNode<'ast> { + fn from(expression: pest::IdentifierExpression<'ast>) -> untyped::AssigneeNode<'ast> { + use crate::untyped::NodeValue; + + untyped::Assignee::Identifier(expression.span.as_str()).span(expression.span) + } +} + +impl<'ast> From> for untyped::AssigneeNode<'ast> { + fn from(assignee: pest::Assignee<'ast>) -> untyped::AssigneeNode<'ast> { + use crate::untyped::NodeValue; + + let a = untyped::AssigneeNode::from(assignee.id); + let span = assignee.span; + + assignee.accesses.into_iter().fold(a, |acc, s| { + match s { + pest::AssigneeAccess::Select(s) => untyped::Assignee::Select( + box acc, + box untyped::RangeOrExpression::from(s.expression), + ), + pest::AssigneeAccess::Dot(a) => match a.inner { + pest::IdentifierOrDecimal::Identifier(id) => { + untyped::Assignee::Member(box acc, box id.span.as_str()) + } + pest::IdentifierOrDecimal::Decimal(id) => { + untyped::Assignee::Element(box acc, id.span.as_str().parse().unwrap()) + } + }, + } + .span(span.clone()) + }) + } +} + +impl<'ast> From> for untyped::UnresolvedTypeNode<'ast> { + fn from(t: pest::Type<'ast>) -> untyped::UnresolvedTypeNode<'ast> { + use crate::untyped::types::UnresolvedType; + use crate::untyped::NodeValue; + + match t { + pest::Type::Basic(t) => match t { + pest::BasicType::Field(t) => UnresolvedType::FieldElement.span(t.span), + pest::BasicType::Boolean(t) => UnresolvedType::Boolean.span(t.span), + pest::BasicType::U8(t) => UnresolvedType::Uint(8).span(t.span), + pest::BasicType::U16(t) => UnresolvedType::Uint(16).span(t.span), + pest::BasicType::U32(t) => UnresolvedType::Uint(32).span(t.span), + pest::BasicType::U64(t) => UnresolvedType::Uint(64).span(t.span), + }, + pest::Type::Array(t) => { + let inner_type = match t.ty { + pest::BasicOrStructOrTupleType::Basic(t) => match t { + pest::BasicType::Field(t) => UnresolvedType::FieldElement.span(t.span), + pest::BasicType::Boolean(t) => UnresolvedType::Boolean.span(t.span), + pest::BasicType::U8(t) => UnresolvedType::Uint(8).span(t.span), + pest::BasicType::U16(t) => UnresolvedType::Uint(16).span(t.span), + pest::BasicType::U32(t) => UnresolvedType::Uint(32).span(t.span), + pest::BasicType::U64(t) => UnresolvedType::Uint(64).span(t.span), + }, + pest::BasicOrStructOrTupleType::Struct(t) => UnresolvedType::User( + t.id.span.as_str().to_string(), + t.explicit_generics.map(|explicit_generics| { + explicit_generics + .values + .into_iter() + .map(|i| match i { + pest::ConstantGenericValue::Underscore(_) => None, + pest::ConstantGenericValue::Value(v) => { + Some(untyped::ExpressionNode::from(v)) + } + pest::ConstantGenericValue::Identifier(i) => Some( + untyped::Expression::Identifier(i.span.as_str()) + .span(i.span), + ), + }) + .collect() + }), + ) + .span(t.span), + pest::BasicOrStructOrTupleType::Tuple(t) => UnresolvedType::Tuple( + t.elements + .into_iter() + .map(untyped::UnresolvedTypeNode::from) + .collect(), + ) + .span(t.span), + }; + + let span = t.span; + + t.dimensions + .into_iter() + .map(untyped::ExpressionNode::from) + .rev() + .fold(None, |acc, s| match acc { + None => Some(UnresolvedType::array(inner_type.clone(), s)), + Some(acc) => Some(UnresolvedType::array(acc.span(span.clone()), s)), + }) + .unwrap() + .span(span.clone()) + } + pest::Type::Struct(s) => UnresolvedType::User( + s.id.span.as_str().to_string(), + s.explicit_generics.map(|explicit_generics| { + explicit_generics + .values + .into_iter() + .map(|i| match i { + pest::ConstantGenericValue::Underscore(_) => None, + pest::ConstantGenericValue::Value(v) => { + Some(untyped::ExpressionNode::from(v)) + } + pest::ConstantGenericValue::Identifier(i) => { + Some(untyped::Expression::Identifier(i.span.as_str()).span(i.span)) + } + }) + .collect() + }), + ) + .span(s.span), + pest::Type::Tuple(t) => UnresolvedType::Tuple( + t.elements + .into_iter() + .map(untyped::UnresolvedTypeNode::from) + .collect(), + ) + .span(t.span), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::untyped::types::{UnresolvedSignature, UnresolvedType}; + use crate::untyped::NodeValue; + + #[test] + fn return_forty_two() { + let source = "def main() -> field: return 42"; + let ast = pest::generate_ast(source).unwrap(); + let expected: untyped::Module = untyped::Module { + symbols: vec![untyped::SymbolDeclaration { + id: &source[4..8], + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function( + untyped::Function { + arguments: vec![], + statements: vec![untyped::Statement::Return( + untyped::ExpressionList { + expressions: vec![ + untyped::Expression::IntConstant(42usize.into()).into() + ], + } + .into(), + ) + .into()], + signature: UnresolvedSignature::new() + .inputs(vec![]) + .outputs(vec![UnresolvedType::FieldElement.mock()]), + } + .into(), + )), + } + .into()], + }; + assert_eq!(untyped::Module::from(ast), expected); + } + + #[test] + fn return_true() { + let source = "def main() -> bool: return true"; + let ast = pest::generate_ast(source).unwrap(); + let expected: untyped::Module = + untyped::Module { + symbols: vec![untyped::SymbolDeclaration { + id: &source[4..8], + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function( + untyped::Function { + arguments: vec![], + statements: vec![untyped::Statement::Return( + untyped::ExpressionList { + expressions: vec![ + untyped::Expression::BooleanConstant(true).into() + ], + } + .into(), + ) + .into()], + signature: UnresolvedSignature::new() + .inputs(vec![]) + .outputs(vec![UnresolvedType::Boolean.mock()]), + } + .into(), + )), + } + .into()], + }; + assert_eq!(untyped::Module::from(ast), expected); + } + + #[test] + fn arguments() { + let source = "def main(private field a, bool b) -> field: return 42"; + let ast = pest::generate_ast(source).unwrap(); + + let expected: untyped::Module = untyped::Module { + symbols: vec![untyped::SymbolDeclaration { + id: &source[4..8], + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function( + untyped::Function { + arguments: vec![ + untyped::Parameter::private( + untyped::Variable::new( + &source[23..24], + UnresolvedType::FieldElement.mock(), + ) + .into(), + ) + .into(), + untyped::Parameter::public( + untyped::Variable::new( + &source[31..32], + UnresolvedType::Boolean.mock(), + ) + .into(), + ) + .into(), + ], + statements: vec![untyped::Statement::Return( + untyped::ExpressionList { + expressions: vec![ + untyped::Expression::IntConstant(42usize.into()).into() + ], + } + .into(), + ) + .into()], + signature: UnresolvedSignature::new() + .inputs(vec![ + UnresolvedType::FieldElement.mock(), + UnresolvedType::Boolean.mock(), + ]) + .outputs(vec![UnresolvedType::FieldElement.mock()]), + } + .into(), + )), + } + .into()], + }; + + assert_eq!(untyped::Module::from(ast), expected); + } + + mod types { + use super::*; + + /// Helper method to generate the ast for `def main(private {ty} a): return` which we use to check ty + fn wrap(ty: UnresolvedType<'static>) -> untyped::Module<'static> { + untyped::Module { + symbols: vec![untyped::SymbolDeclaration { + id: "main", + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function( + untyped::Function { + arguments: vec![untyped::Parameter::private( + untyped::Variable::new("a", ty.clone().mock()).into(), + ) + .into()], + statements: vec![untyped::Statement::Return( + untyped::ExpressionList { + expressions: vec![], + } + .into(), + ) + .into()], + signature: UnresolvedSignature::new().inputs(vec![ty.mock()]), + } + .into(), + )), + } + .into()], + } + } + + #[test] + fn array() { + let vectors = vec![ + ("field", UnresolvedType::FieldElement), + ("bool", UnresolvedType::Boolean), + ( + "field[2]", + untyped::UnresolvedType::Array( + box untyped::UnresolvedType::FieldElement.mock(), + untyped::Expression::IntConstant(2usize.into()).mock(), + ), + ), + ( + "field[2][3]", + untyped::UnresolvedType::Array( + box untyped::UnresolvedType::Array( + box untyped::UnresolvedType::FieldElement.mock(), + untyped::Expression::IntConstant(3usize.into()).mock(), + ) + .mock(), + untyped::Expression::IntConstant(2usize.into()).mock(), + ), + ), + ( + "bool[2][3u32]", + untyped::UnresolvedType::Array( + box untyped::UnresolvedType::Array( + box untyped::UnresolvedType::Boolean.mock(), + untyped::Expression::U32Constant(3u32).mock(), + ) + .mock(), + untyped::Expression::IntConstant(2usize.into()).mock(), + ), + ), + ]; + + for (ty, expected) in vectors { + let source = format!("def main(private {} a): return", ty); + let expected = wrap(expected); + let ast = pest::generate_ast(&source).unwrap(); + assert_eq!(untyped::Module::from(ast), expected); + } + } + } + + mod postfix { + use super::*; + fn wrap(expression: untyped::Expression<'static>) -> untyped::Module { + untyped::Module { + symbols: vec![untyped::SymbolDeclaration { + id: "main", + symbol: untyped::Symbol::Here(untyped::SymbolDefinition::Function( + untyped::Function { + arguments: vec![], + statements: vec![untyped::Statement::Return( + untyped::ExpressionList { + expressions: vec![expression.into()], + } + .into(), + ) + .into()], + signature: UnresolvedSignature::new(), + } + .into(), + )), + } + .into()], + } + } + + #[test] + fn success() { + // we basically accept `()?[]*` : an optional call at first, then only array accesses + + let vectors = vec![ + ("a", untyped::Expression::Identifier("a")), + ( + "a[3]", + untyped::Expression::Select( + box untyped::Expression::Identifier("a").into(), + box untyped::RangeOrExpression::Expression( + untyped::Expression::IntConstant(3usize.into()).into(), + ), + ), + ), + ( + "a[3][4]", + untyped::Expression::Select( + box untyped::Expression::Select( + box untyped::Expression::Identifier("a").into(), + box untyped::RangeOrExpression::Expression( + untyped::Expression::IntConstant(3usize.into()).into(), + ), + ) + .into(), + box untyped::RangeOrExpression::Expression( + untyped::Expression::IntConstant(4usize.into()).into(), + ), + ), + ), + ( + "a(3)[4]", + untyped::Expression::Select( + box untyped::Expression::FunctionCall( + box untyped::Expression::Identifier("a").mock(), + None, + vec![untyped::Expression::IntConstant(3usize.into()).into()], + ) + .into(), + box untyped::RangeOrExpression::Expression( + untyped::Expression::IntConstant(4usize.into()).into(), + ), + ), + ), + ( + "a(3)[4][5]", + untyped::Expression::Select( + box untyped::Expression::Select( + box untyped::Expression::FunctionCall( + box untyped::Expression::Identifier("a").mock(), + None, + vec![untyped::Expression::IntConstant(3usize.into()).into()], + ) + .into(), + box untyped::RangeOrExpression::Expression( + untyped::Expression::IntConstant(4usize.into()).into(), + ), + ) + .into(), + box untyped::RangeOrExpression::Expression( + untyped::Expression::IntConstant(5usize.into()).into(), + ), + ), + ), + ]; + + for (source, expected) in vectors { + let source = format!("def main(): return {}", source); + let expected = wrap(expected); + let ast = pest::generate_ast(&source).unwrap(); + assert_eq!(untyped::Module::from(ast), expected); + } + } + + #[test] + fn call_array_element() { + // a call after an array access should be accepted + let source = "def main(): return a[2](3)"; + let ast = pest::generate_ast(source).unwrap(); + assert_eq!( + untyped::Module::from(ast), + wrap(untyped::Expression::FunctionCall( + box untyped::Expression::Select( + box untyped::Expression::Identifier("a").mock(), + box untyped::RangeOrExpression::Expression( + untyped::Expression::IntConstant(2u32.into()).mock() + ) + ) + .mock(), + None, + vec![untyped::Expression::IntConstant(3u32.into()).mock()], + )) + ); + } + + #[test] + fn call_call_result() { + // a call after a call should be accepted + let source = "def main(): return a(2)(3)"; + + let ast = pest::generate_ast(source).unwrap(); + assert_eq!( + untyped::Module::from(ast), + wrap(untyped::Expression::FunctionCall( + box untyped::Expression::FunctionCall( + box untyped::Expression::Identifier("a").mock(), + None, + vec![untyped::Expression::IntConstant(2u32.into()).mock()] + ) + .mock(), + None, + vec![untyped::Expression::IntConstant(3u32.into()).mock()], + )) + ); + } + } + #[test] + fn declarations() { + use self::pest::Span; + + let span = Span::new("", 0, 0).unwrap(); + + // For different definitions, we generate declarations + // Case 1: `id = expr` where `expr` is not a function call + // This is a simple assignment, doesn't implicitely declare a variable + // A `Definition` is generated and no `Declaration`s + + let definition = pest::DefinitionStatement { + lhs: vec![pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee { + id: pest::IdentifierExpression { + value: String::from("a"), + span: span.clone(), + }, + accesses: vec![], + span: span.clone(), + })], + expression: pest::Expression::Literal(pest::LiteralExpression::DecimalLiteral( + pest::DecimalLiteralExpression { + value: pest::DecimalNumber { + span: Span::new("1", 0, 1).unwrap(), + }, + suffix: None, + span: span.clone(), + }, + )), + span: span.clone(), + }; + + let statements: Vec = statements_from_definition(definition); + + assert_eq!(statements.len(), 1); + match &statements[0].value { + untyped::Statement::Definition(..) => {} + s => { + panic!("should be a Definition, found {}", s); + } + }; + + // Case 2: `id = expr` where `expr` is a function call + // A MultiDef is generated + + let definition = pest::DefinitionStatement { + lhs: vec![pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee { + id: pest::IdentifierExpression { + value: String::from("a"), + span: span.clone(), + }, + accesses: vec![], + span: span.clone(), + })], + expression: pest::Expression::Postfix(pest::PostfixExpression { + base: box pest::Expression::Identifier(pest::IdentifierExpression { + value: String::from("foo"), + span: span.clone(), + }), + accesses: vec![pest::Access::Call(pest::CallAccess { + explicit_generics: None, + arguments: pest::Arguments { + expressions: vec![], + span: span.clone(), + }, + span: span.clone(), + })], + span: span.clone(), + }), + span: span.clone(), + }; + + let statements: Vec = statements_from_definition(definition); + + assert_eq!(statements.len(), 1); + match &statements[0].value { + untyped::Statement::MultipleDefinition(..) => {} + s => { + panic!("should be a Definition, found {}", s); + } + }; + // Case 3: `ids = expr` where `expr` is a function call + // This implicitely declares all variables which are type annotated + + // `field a, b = foo()` + + let definition = pest::DefinitionStatement { + lhs: vec![ + pest::TypedIdentifierOrAssignee::TypedIdentifier(pest::TypedIdentifier { + ty: pest::Type::Basic(pest::BasicType::Field(pest::FieldType { + span: span.clone(), + })), + identifier: pest::IdentifierExpression { + value: String::from("a"), + span: span.clone(), + }, + span: span.clone(), + }), + pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee { + id: pest::IdentifierExpression { + value: String::from("b"), + span: span.clone(), + }, + accesses: vec![], + span: span.clone(), + }), + ], + expression: pest::Expression::Postfix(pest::PostfixExpression { + base: box pest::Expression::Identifier(pest::IdentifierExpression { + value: String::from("foo"), + span: span.clone(), + }), + accesses: vec![pest::Access::Call(pest::CallAccess { + explicit_generics: None, + arguments: pest::Arguments { + expressions: vec![], + span: span.clone(), + }, + span: span.clone(), + })], + span: span.clone(), + }), + span: span.clone(), + }; + + let statements: Vec = statements_from_definition(definition); + + assert_eq!(statements.len(), 2); + match &statements[1].value { + untyped::Statement::MultipleDefinition(..) => {} + s => { + panic!("should be a Definition, found {}", s); + } + }; + } +} diff --git a/zokrates_core/src/absy/mod.rs b/zokrates_ast/src/untyped/mod.rs similarity index 98% rename from zokrates_core/src/absy/mod.rs rename to zokrates_ast/src/untyped/mod.rs index c9caa5dd..a0afe35e 100644 --- a/zokrates_core/src/absy/mod.rs +++ b/zokrates_ast/src/untyped/mod.rs @@ -8,14 +8,16 @@ mod from_ast; mod node; pub mod parameter; +mod position; pub mod types; pub mod variable; -pub use crate::absy::node::{Node, NodeValue}; -pub use crate::absy::parameter::{Parameter, ParameterNode}; -use crate::absy::types::{UnresolvedSignature, UnresolvedType, UserTypeId}; -pub use crate::absy::variable::{Variable, VariableNode}; -use crate::embed::FlatEmbed; +pub use self::node::{Node, NodeValue}; +pub use self::parameter::{Parameter, ParameterNode}; +pub use self::position::Position; +use self::types::{UnresolvedSignature, UnresolvedType, UserTypeId}; +pub use self::variable::{Variable, VariableNode}; +use crate::common::FlatEmbed; use std::path::{Path, PathBuf}; use std::fmt; diff --git a/zokrates_core/src/absy/node.rs b/zokrates_ast/src/untyped/node.rs similarity index 97% rename from zokrates_core/src/absy/node.rs rename to zokrates_ast/src/untyped/node.rs index 0332ad57..75c9d598 100644 --- a/zokrates_core/src/absy/node.rs +++ b/zokrates_ast/src/untyped/node.rs @@ -1,4 +1,3 @@ -use crate::parser::Position; use std::fmt; use zokrates_pest_ast::Span; @@ -81,8 +80,7 @@ impl From for Node { } } -use crate::absy::types::UnresolvedType; -use crate::absy::*; +use super::*; impl<'ast> NodeValue for Expression<'ast> {} impl<'ast> NodeValue for ExpressionList<'ast> {} diff --git a/zokrates_core/src/absy/parameter.rs b/zokrates_ast/src/untyped/parameter.rs similarity index 96% rename from zokrates_core/src/absy/parameter.rs rename to zokrates_ast/src/untyped/parameter.rs index cc103321..14700678 100644 --- a/zokrates_core/src/absy/parameter.rs +++ b/zokrates_ast/src/untyped/parameter.rs @@ -1,4 +1,4 @@ -use crate::absy::{Node, VariableNode}; +use super::{Node, VariableNode}; use std::fmt; #[derive(Clone, PartialEq)] diff --git a/zokrates_core/src/parser/tokenize/position.rs b/zokrates_ast/src/untyped/position.rs similarity index 100% rename from zokrates_core/src/parser/tokenize/position.rs rename to zokrates_ast/src/untyped/position.rs diff --git a/zokrates_core/src/absy/types.rs b/zokrates_ast/src/untyped/types.rs similarity index 96% rename from zokrates_core/src/absy/types.rs rename to zokrates_ast/src/untyped/types.rs index 924e72cf..1bdbded3 100644 --- a/zokrates_core/src/absy/types.rs +++ b/zokrates_ast/src/untyped/types.rs @@ -1,5 +1,5 @@ -use crate::absy::ExpressionNode; -use crate::absy::UnresolvedTypeNode; +use super::ExpressionNode; +use super::UnresolvedTypeNode; use std::fmt; pub type Identifier<'ast> = &'ast str; @@ -76,10 +76,10 @@ impl<'ast> UnresolvedType<'ast> { pub use self::signature::UnresolvedSignature; mod signature { - use crate::absy::ConstantGenericNode; + use crate::untyped::ConstantGenericNode; use std::fmt; - use crate::absy::UnresolvedTypeNode; + use crate::untyped::UnresolvedTypeNode; #[derive(Clone, PartialEq, Default)] pub struct UnresolvedSignature<'ast> { diff --git a/zokrates_core/src/absy/variable.rs b/zokrates_ast/src/untyped/variable.rs similarity index 88% rename from zokrates_core/src/absy/variable.rs rename to zokrates_ast/src/untyped/variable.rs index 6b8f9b60..c7bcbe21 100644 --- a/zokrates_core/src/absy/variable.rs +++ b/zokrates_ast/src/untyped/variable.rs @@ -1,8 +1,8 @@ -use crate::absy::types::UnresolvedType; -use crate::absy::{Node, UnresolvedTypeNode}; +use super::types::UnresolvedType; +use super::{Node, UnresolvedTypeNode}; use std::fmt; -use crate::absy::Identifier; +use super::Identifier; #[derive(Clone, PartialEq)] pub struct Variable<'ast> { diff --git a/zokrates_core/src/zir/folder.rs b/zokrates_ast/src/zir/folder.rs similarity index 100% rename from zokrates_core/src/zir/folder.rs rename to zokrates_ast/src/zir/folder.rs diff --git a/zokrates_core/src/zir/from_typed.rs b/zokrates_ast/src/zir/from_typed.rs similarity index 97% rename from zokrates_core/src/zir/from_typed.rs rename to zokrates_ast/src/zir/from_typed.rs index 3b5b9384..fb3f9475 100644 --- a/zokrates_core/src/zir/from_typed.rs +++ b/zokrates_ast/src/zir/from_typed.rs @@ -1,4 +1,4 @@ -use crate::typed_absy; +use crate::typed as typed_absy; use crate::zir; impl From for zir::types::Signature { diff --git a/zokrates_core/src/zir/identifier.rs b/zokrates_ast/src/zir/identifier.rs similarity index 95% rename from zokrates_core/src/zir/identifier.rs rename to zokrates_ast/src/zir/identifier.rs index 5d379c2a..f010f2f8 100644 --- a/zokrates_core/src/zir/identifier.rs +++ b/zokrates_ast/src/zir/identifier.rs @@ -1,7 +1,7 @@ use crate::zir::types::MemberId; use std::fmt; -use crate::typed_absy::Identifier as CoreIdentifier; +use crate::typed::Identifier as CoreIdentifier; #[derive(Debug, PartialEq, Clone, Hash, Eq)] pub enum Identifier<'ast> { diff --git a/zokrates_core/src/zir/mod.rs b/zokrates_ast/src/zir/mod.rs similarity index 99% rename from zokrates_core/src/zir/mod.rs rename to zokrates_ast/src/zir/mod.rs index 2f7dcd89..f93ea719 100644 --- a/zokrates_core/src/zir/mod.rs +++ b/zokrates_ast/src/zir/mod.rs @@ -10,9 +10,9 @@ mod variable; pub use self::parameter::Parameter; pub use self::types::Type; pub use self::variable::Variable; +use crate::common::FlatEmbed; pub use crate::zir::uint::{ShouldReduce, UExpression, UExpressionInner, UMetadata}; -use crate::embed::FlatEmbed; use crate::zir::types::Signature; use std::convert::TryFrom; use std::fmt; diff --git a/zokrates_core/src/zir/parameter.rs b/zokrates_ast/src/zir/parameter.rs similarity index 100% rename from zokrates_core/src/zir/parameter.rs rename to zokrates_ast/src/zir/parameter.rs diff --git a/zokrates_core/src/zir/result_folder.rs b/zokrates_ast/src/zir/result_folder.rs similarity index 100% rename from zokrates_core/src/zir/result_folder.rs rename to zokrates_ast/src/zir/result_folder.rs diff --git a/zokrates_core/src/zir/types.rs b/zokrates_ast/src/zir/types.rs similarity index 100% rename from zokrates_core/src/zir/types.rs rename to zokrates_ast/src/zir/types.rs diff --git a/zokrates_core/src/zir/uint.rs b/zokrates_ast/src/zir/uint.rs similarity index 100% rename from zokrates_core/src/zir/uint.rs rename to zokrates_ast/src/zir/uint.rs diff --git a/zokrates_core/src/zir/variable.rs b/zokrates_ast/src/zir/variable.rs similarity index 100% rename from zokrates_core/src/zir/variable.rs rename to zokrates_ast/src/zir/variable.rs diff --git a/zokrates_core/Cargo.toml b/zokrates_core/Cargo.toml index 67176eb2..e469112a 100644 --- a/zokrates_core/Cargo.toml +++ b/zokrates_core/Cargo.toml @@ -26,13 +26,14 @@ reduce = "0.1.1" # serialization and deserialization serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", features = ["preserve_order"] } -serde_cbor = "0.11.2" hex = "0.4.2" regex = "0.2" zokrates_field = { version = "0.5.0", path = "../zokrates_field", default-features = false } zokrates_pest_ast = { version = "0.2.0", path = "../zokrates_pest_ast" } zokrates_common = { path = "../zokrates_common" } zokrates_embed = { version = "0.1.0", path = "../zokrates_embed" } +zokrates_interpreter = { version = "0.1", path = "../zokrates_interpreter" } +zokrates_ast = { version = "0.1", path = "../zokrates_ast" } getrandom = { version = "0.2", features = ["js", "wasm-bindgen"] } rand_0_4 = { version = "0.4", package = "rand" } rand_0_8 = { version = "0.8", package = "rand" } diff --git a/zokrates_core/src/absy/from_ast.rs b/zokrates_core/src/absy/from_ast.rs deleted file mode 100644 index 81b0ccc8..00000000 --- a/zokrates_core/src/absy/from_ast.rs +++ /dev/null @@ -1,1386 +0,0 @@ -use crate::absy; - -use crate::absy::SymbolDefinition; -use num_bigint::BigUint; -use std::path::Path; -use zokrates_pest_ast as pest; - -impl<'ast> From> for absy::Module<'ast> { - fn from(file: pest::File<'ast>) -> absy::Module<'ast> { - absy::Module::with_symbols(file.declarations.into_iter().flat_map(|d| match d { - pest::SymbolDeclaration::Import(i) => import_directive_to_symbol_vec(i), - pest::SymbolDeclaration::Constant(c) => vec![c.into()], - pest::SymbolDeclaration::Struct(s) => vec![s.into()], - pest::SymbolDeclaration::Type(t) => vec![t.into()], - pest::SymbolDeclaration::Function(f) => vec![f.into()], - })) - } -} - -fn import_directive_to_symbol_vec( - import: pest::ImportDirective, -) -> Vec { - use crate::absy::NodeValue; - - match import { - pest::ImportDirective::Main(import) => { - let span = import.span; - let source = Path::new(import.source.span.as_str()); - let id = "main"; - let alias = import.alias.map(|a| a.span.as_str()); - - let import = absy::CanonicalImport { - source, - id: absy::SymbolIdentifier::from(id).alias(alias), - } - .span(span.clone()); - - vec![absy::SymbolDeclaration { - id: alias.unwrap_or(id), - symbol: absy::Symbol::Here(absy::SymbolDefinition::Import(import)), - } - .span(span.clone())] - } - pest::ImportDirective::From(import) => { - let span = import.span; - let source = Path::new(import.source.span.as_str()); - import - .symbols - .into_iter() - .map(|symbol| { - let alias = symbol - .alias - .as_ref() - .map(|a| a.span.as_str()) - .unwrap_or_else(|| symbol.id.span.as_str()); - - let import = absy::CanonicalImport { - source, - id: absy::SymbolIdentifier::from(symbol.id.span.as_str()) - .alias(Some(alias)), - } - .span(span.clone()); - - absy::SymbolDeclaration { - id: alias, - symbol: absy::Symbol::Here(absy::SymbolDefinition::Import(import)), - } - .span(span.clone()) - }) - .collect() - } - } -} - -impl<'ast> From> for absy::SymbolDeclarationNode<'ast> { - fn from(definition: pest::StructDefinition<'ast>) -> absy::SymbolDeclarationNode<'ast> { - use crate::absy::NodeValue; - - let span = definition.span; - - let id = definition.id.span.as_str(); - - let ty = absy::StructDefinition { - generics: definition - .generics - .into_iter() - .map(absy::ConstantGenericNode::from) - .collect(), - fields: definition - .fields - .into_iter() - .map(absy::StructDefinitionFieldNode::from) - .collect(), - } - .span(span.clone()); - - absy::SymbolDeclaration { - id, - symbol: absy::Symbol::Here(absy::SymbolDefinition::Struct(ty)), - } - .span(span) - } -} - -impl<'ast> From> for absy::StructDefinitionFieldNode<'ast> { - fn from(field: pest::StructField<'ast>) -> absy::StructDefinitionFieldNode<'ast> { - use crate::absy::NodeValue; - - let span = field.span; - - let id = field.id.span.as_str(); - - let ty = absy::UnresolvedTypeNode::from(field.ty); - - absy::StructDefinitionField { id, ty }.span(span) - } -} - -impl<'ast> From> for absy::SymbolDeclarationNode<'ast> { - fn from(definition: pest::ConstantDefinition<'ast>) -> absy::SymbolDeclarationNode<'ast> { - use crate::absy::NodeValue; - - let span = definition.span; - let id = definition.id.span.as_str(); - - let ty = absy::ConstantDefinition { - ty: definition.ty.into(), - expression: definition.expression.into(), - } - .span(span.clone()); - - absy::SymbolDeclaration { - id, - symbol: absy::Symbol::Here(absy::SymbolDefinition::Constant(ty)), - } - .span(span) - } -} - -impl<'ast> From> for absy::SymbolDeclarationNode<'ast> { - fn from(definition: pest::TypeDefinition<'ast>) -> absy::SymbolDeclarationNode<'ast> { - use crate::absy::NodeValue; - - let span = definition.span; - let id = definition.id.span.as_str(); - - let ty = absy::TypeDefinition { - generics: definition - .generics - .into_iter() - .map(absy::ConstantGenericNode::from) - .collect(), - ty: definition.ty.into(), - } - .span(span.clone()); - - absy::SymbolDeclaration { - id, - symbol: absy::Symbol::Here(SymbolDefinition::Type(ty)), - } - .span(span) - } -} - -impl<'ast> From> for absy::SymbolDeclarationNode<'ast> { - fn from(function: pest::FunctionDefinition<'ast>) -> absy::SymbolDeclarationNode<'ast> { - use crate::absy::NodeValue; - - let span = function.span; - - let signature = absy::UnresolvedSignature::new() - .generics( - function - .generics - .into_iter() - .map(absy::ConstantGenericNode::from) - .collect(), - ) - .inputs( - function - .parameters - .clone() - .into_iter() - .map(|p| absy::UnresolvedTypeNode::from(p.ty)) - .collect(), - ) - .outputs( - function - .returns - .clone() - .into_iter() - .map(absy::UnresolvedTypeNode::from) - .collect(), - ); - - let id = function.id.span.as_str(); - - let function = absy::Function { - arguments: function - .parameters - .into_iter() - .map(absy::ParameterNode::from) - .collect(), - statements: function - .statements - .into_iter() - .flat_map(statements_from_statement) - .collect(), - signature, - } - .span(span.clone()); - - absy::SymbolDeclaration { - id, - symbol: absy::Symbol::Here(absy::SymbolDefinition::Function(function)), - } - .span(span) - } -} - -impl<'ast> From> for absy::ConstantGenericNode<'ast> { - fn from(g: pest::IdentifierExpression<'ast>) -> absy::ConstantGenericNode<'ast> { - use absy::NodeValue; - - let name = g.span.as_str(); - - name.span(g.span) - } -} - -impl<'ast> From> for absy::ParameterNode<'ast> { - fn from(param: pest::Parameter<'ast>) -> absy::ParameterNode<'ast> { - use crate::absy::NodeValue; - - let private = param - .visibility - .map(|v| match v { - pest::Visibility::Private(_) => true, - pest::Visibility::Public(_) => false, - }) - .unwrap_or(false); - - let variable = absy::Variable::new( - param.id.span.as_str(), - absy::UnresolvedTypeNode::from(param.ty), - ) - .span(param.id.span); - - absy::Parameter::new(variable, private).span(param.span) - } -} - -fn statements_from_statement(statement: pest::Statement) -> Vec { - match statement { - pest::Statement::Definition(s) => statements_from_definition(s), - pest::Statement::Iteration(s) => vec![absy::StatementNode::from(s)], - pest::Statement::Assertion(s) => vec![absy::StatementNode::from(s)], - pest::Statement::Return(s) => vec![absy::StatementNode::from(s)], - } -} - -fn statements_from_definition(definition: pest::DefinitionStatement) -> Vec { - use crate::absy::NodeValue; - - let lhs = definition.lhs; - - match lhs.len() { - 1 => { - // Definition or assignment - let a = lhs[0].clone(); - - let e: absy::ExpressionNode = absy::ExpressionNode::from(definition.expression); - - match a { - pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => { - let declaration = absy::Statement::Declaration( - absy::Variable::new( - i.identifier.span.as_str(), - absy::UnresolvedTypeNode::from(i.ty), - ) - .span(i.identifier.span.clone()), - ) - .span(definition.span.clone()); - - let s = match e.value { - absy::Expression::FunctionCall(..) => absy::Statement::MultipleDefinition( - vec![absy::AssigneeNode::from(i.identifier.clone())], - e, - ), - _ => absy::Statement::Definition( - absy::AssigneeNode::from(i.identifier.clone()), - e, - ), - }; - - vec![declaration, s.span(definition.span)] - } - pest::TypedIdentifierOrAssignee::Assignee(a) => { - let s = match e.value { - absy::Expression::FunctionCall(..) => absy::Statement::MultipleDefinition( - vec![absy::AssigneeNode::from(a)], - e, - ), - _ => absy::Statement::Definition(absy::AssigneeNode::from(a), e), - }; - - vec![s.span(definition.span)] - } - } - } - _ => { - // Multidefinition - let declarations = lhs.clone().into_iter().filter_map(|i| match i { - pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => { - let ty = i.ty; - let id = i.identifier; - - Some( - absy::Statement::Declaration( - absy::Variable::new( - id.span.as_str(), - absy::UnresolvedTypeNode::from(ty), - ) - .span(id.span), - ) - .span(i.span), - ) - } - _ => None, - }); - - let lhs = lhs - .into_iter() - .map(|i| match i { - pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => { - absy::Assignee::Identifier(i.identifier.span.as_str()) - .span(i.identifier.span) - } - pest::TypedIdentifierOrAssignee::Assignee(a) => absy::AssigneeNode::from(a), - }) - .collect(); - - let multi_def = absy::Statement::MultipleDefinition( - lhs, - absy::ExpressionNode::from(definition.expression), - ) - .span(definition.span); - - declarations.chain(std::iter::once(multi_def)).collect() - } - } -} - -impl<'ast> From> for absy::StatementNode<'ast> { - fn from(statement: pest::ReturnStatement<'ast>) -> absy::StatementNode<'ast> { - use crate::absy::NodeValue; - - absy::Statement::Return( - absy::ExpressionList { - expressions: statement - .expressions - .into_iter() - .map(absy::ExpressionNode::from) - .collect(), - } - .span(statement.span.clone()), - ) - .span(statement.span) - } -} - -impl<'ast> From> for absy::StatementNode<'ast> { - fn from(statement: pest::AssertionStatement<'ast>) -> absy::StatementNode<'ast> { - use crate::absy::NodeValue; - - absy::Statement::Assertion( - absy::ExpressionNode::from(statement.expression), - statement.message.map(|m| m.value), - ) - .span(statement.span) - } -} - -impl<'ast> From> for absy::StatementNode<'ast> { - fn from(statement: pest::IterationStatement<'ast>) -> absy::StatementNode<'ast> { - use crate::absy::NodeValue; - let from = absy::ExpressionNode::from(statement.from); - let to = absy::ExpressionNode::from(statement.to); - let index = statement.index.span.as_str(); - let ty = absy::UnresolvedTypeNode::from(statement.ty); - let statements: Vec> = statement - .statements - .into_iter() - .flat_map(statements_from_statement) - .collect(); - - let var = absy::Variable::new(index, ty).span(statement.index.span); - - absy::Statement::For(var, from, to, statements).span(statement.span) - } -} - -impl<'ast> From> for absy::ExpressionNode<'ast> { - fn from(expression: pest::Expression<'ast>) -> absy::ExpressionNode<'ast> { - match expression { - pest::Expression::Binary(e) => absy::ExpressionNode::from(e), - pest::Expression::Ternary(e) => absy::ExpressionNode::from(e), - pest::Expression::IfElse(e) => absy::ExpressionNode::from(e), - pest::Expression::Literal(e) => absy::ExpressionNode::from(e), - pest::Expression::Identifier(e) => absy::ExpressionNode::from(e), - pest::Expression::Postfix(e) => absy::ExpressionNode::from(e), - pest::Expression::InlineArray(e) => absy::ExpressionNode::from(e), - pest::Expression::InlineTuple(e) => absy::ExpressionNode::from(e), - pest::Expression::InlineStruct(e) => absy::ExpressionNode::from(e), - pest::Expression::ArrayInitializer(e) => absy::ExpressionNode::from(e), - pest::Expression::Unary(e) => absy::ExpressionNode::from(e), - } - } -} - -impl<'ast> From> for absy::ExpressionNode<'ast> { - fn from(expression: pest::BinaryExpression<'ast>) -> absy::ExpressionNode<'ast> { - use crate::absy::NodeValue; - match expression.op { - pest::BinaryOperator::Add => absy::Expression::Add( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - pest::BinaryOperator::Sub => absy::Expression::Sub( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - pest::BinaryOperator::Mul => absy::Expression::Mult( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - pest::BinaryOperator::Div => absy::Expression::Div( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - pest::BinaryOperator::Rem => absy::Expression::Rem( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - pest::BinaryOperator::Eq => absy::Expression::Eq( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - pest::BinaryOperator::Lt => absy::Expression::Lt( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - pest::BinaryOperator::Lte => absy::Expression::Le( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - pest::BinaryOperator::Gt => absy::Expression::Gt( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - pest::BinaryOperator::Gte => absy::Expression::Ge( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - pest::BinaryOperator::And => absy::Expression::And( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - pest::BinaryOperator::Or => absy::Expression::Or( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - pest::BinaryOperator::Pow => absy::Expression::Pow( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - pest::BinaryOperator::BitXor => absy::Expression::BitXor( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - pest::BinaryOperator::LeftShift => absy::Expression::LeftShift( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - pest::BinaryOperator::RightShift => absy::Expression::RightShift( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - pest::BinaryOperator::BitAnd => absy::Expression::BitAnd( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - pest::BinaryOperator::BitOr => absy::Expression::BitOr( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ), - // rewrite (a != b)` as `!(a == b)` - pest::BinaryOperator::NotEq => absy::Expression::Not( - box absy::Expression::Eq( - box absy::ExpressionNode::from(*expression.left), - box absy::ExpressionNode::from(*expression.right), - ) - .span(expression.span.clone()), - ), - } - .span(expression.span) - } -} - -impl<'ast> From> for absy::ExpressionNode<'ast> { - fn from(expression: pest::IfElseExpression<'ast>) -> absy::ExpressionNode<'ast> { - use crate::absy::NodeValue; - absy::Expression::Conditional( - box absy::ExpressionNode::from(*expression.condition), - box absy::ExpressionNode::from(*expression.consequence), - box absy::ExpressionNode::from(*expression.alternative), - absy::ConditionalKind::IfElse, - ) - .span(expression.span) - } -} - -impl<'ast> From> for absy::ExpressionNode<'ast> { - fn from(expression: pest::TernaryExpression<'ast>) -> absy::ExpressionNode<'ast> { - use crate::absy::NodeValue; - absy::Expression::Conditional( - box absy::ExpressionNode::from(*expression.condition), - box absy::ExpressionNode::from(*expression.consequence), - box absy::ExpressionNode::from(*expression.alternative), - absy::ConditionalKind::Ternary, - ) - .span(expression.span) - } -} - -impl<'ast> From> for absy::SpreadNode<'ast> { - fn from(spread: pest::Spread<'ast>) -> absy::SpreadNode<'ast> { - use crate::absy::NodeValue; - absy::Spread { - expression: absy::ExpressionNode::from(spread.expression), - } - .span(spread.span) - } -} - -impl<'ast> From> for absy::RangeNode<'ast> { - fn from(range: pest::Range<'ast>) -> absy::RangeNode<'ast> { - use crate::absy::NodeValue; - - let from = range.from.map(|e| absy::ExpressionNode::from(e.0)); - - let to = range.to.map(|e| absy::ExpressionNode::from(e.0)); - - absy::Range { from, to }.span(range.span) - } -} - -impl<'ast> From> for absy::RangeOrExpression<'ast> { - fn from(range_or_expression: pest::RangeOrExpression<'ast>) -> absy::RangeOrExpression<'ast> { - match range_or_expression { - pest::RangeOrExpression::Expression(e) => { - absy::RangeOrExpression::Expression(absy::ExpressionNode::from(e)) - } - pest::RangeOrExpression::Range(r) => { - absy::RangeOrExpression::Range(absy::RangeNode::from(r)) - } - } - } -} - -impl<'ast> From> for absy::SpreadOrExpression<'ast> { - fn from( - spread_or_expression: pest::SpreadOrExpression<'ast>, - ) -> absy::SpreadOrExpression<'ast> { - match spread_or_expression { - pest::SpreadOrExpression::Expression(e) => { - absy::SpreadOrExpression::Expression(absy::ExpressionNode::from(e)) - } - pest::SpreadOrExpression::Spread(s) => { - absy::SpreadOrExpression::Spread(absy::SpreadNode::from(s)) - } - } - } -} - -impl<'ast> From> for absy::ExpressionNode<'ast> { - fn from(array: pest::InlineArrayExpression<'ast>) -> absy::ExpressionNode<'ast> { - use crate::absy::NodeValue; - absy::Expression::InlineArray( - array - .expressions - .into_iter() - .map(absy::SpreadOrExpression::from) - .collect(), - ) - .span(array.span) - } -} - -impl<'ast> From> for absy::ExpressionNode<'ast> { - fn from(tuple: pest::InlineTupleExpression<'ast>) -> absy::ExpressionNode<'ast> { - use crate::absy::NodeValue; - absy::Expression::InlineTuple( - tuple - .elements - .into_iter() - .map(absy::ExpressionNode::from) - .collect(), - ) - .span(tuple.span) - } -} - -impl<'ast> From> for absy::ExpressionNode<'ast> { - fn from(s: pest::InlineStructExpression<'ast>) -> absy::ExpressionNode<'ast> { - use crate::absy::NodeValue; - absy::Expression::InlineStruct( - s.ty.span.as_str().to_string(), - s.members - .into_iter() - .map(|member| { - ( - member.id.span.as_str(), - absy::ExpressionNode::from(member.expression), - ) - }) - .collect(), - ) - .span(s.span) - } -} - -impl<'ast> From> for absy::ExpressionNode<'ast> { - fn from(initializer: pest::ArrayInitializerExpression<'ast>) -> absy::ExpressionNode<'ast> { - use crate::absy::NodeValue; - - let value = absy::ExpressionNode::from(*initializer.value); - let count = absy::ExpressionNode::from(*initializer.count); - absy::Expression::ArrayInitializer(box value, box count).span(initializer.span) - } -} - -impl<'ast> From> for absy::ExpressionNode<'ast> { - fn from(unary: pest::UnaryExpression<'ast>) -> absy::ExpressionNode<'ast> { - use crate::absy::NodeValue; - - let expression = Box::new(absy::ExpressionNode::from(*unary.expression)); - - match unary.op { - pest::UnaryOperator::Not(..) => absy::Expression::Not(expression), - pest::UnaryOperator::Neg(..) => absy::Expression::Neg(expression), - pest::UnaryOperator::Pos(..) => absy::Expression::Pos(expression), - } - .span(unary.span) - } -} - -impl<'ast> From> for absy::ExpressionNode<'ast> { - fn from(expression: pest::PostfixExpression<'ast>) -> absy::ExpressionNode<'ast> { - use crate::absy::NodeValue; - - let base = absy::ExpressionNode::from(*expression.base); - - // pest::PostFixExpression contains an array of "accesses": `a(34)[42]` is represented as `[a, [Call(34), Select(42)]]`, but absy::ExpressionNode - // is recursive, so it is `Select(Call(a, 34), 42)`. We apply this transformation here - // we start with the base, and we fold the array of accesses by wrapping the current value - expression - .accesses - .into_iter() - .fold(base, |acc, a| match a { - pest::Access::Call(a) => absy::Expression::FunctionCall( - Box::new(acc), - a.explicit_generics.map(|explicit_generics| { - explicit_generics - .values - .into_iter() - .map(|i| match i { - pest::ConstantGenericValue::Underscore(_) => None, - pest::ConstantGenericValue::Value(v) => { - Some(absy::ExpressionNode::from(v)) - } - pest::ConstantGenericValue::Identifier(i) => { - Some(absy::Expression::Identifier(i.span.as_str()).span(i.span)) - } - }) - .collect() - }), - a.arguments - .expressions - .into_iter() - .map(absy::ExpressionNode::from) - .collect(), - ) - .span(a.span), - pest::Access::Select(a) => absy::Expression::Select( - box acc, - box absy::RangeOrExpression::from(a.expression), - ) - .span(a.span), - pest::Access::Dot(m) => match m.inner { - pest::IdentifierOrDecimal::Identifier(id) => { - absy::Expression::Member(box acc, box id.span.as_str()).span(m.span) - } - pest::IdentifierOrDecimal::Decimal(id) => { - absy::Expression::Element(box acc, id.span.as_str().parse().unwrap()) - .span(m.span) - } - }, - }) - } -} - -impl<'ast> From> for absy::ExpressionNode<'ast> { - fn from(expression: pest::DecimalLiteralExpression<'ast>) -> absy::ExpressionNode<'ast> { - use crate::absy::NodeValue; - - match expression.suffix { - Some(suffix) => match suffix { - pest::DecimalSuffix::Field(_) => absy::Expression::FieldConstant( - BigUint::parse_bytes(expression.value.span.as_str().as_bytes(), 10).unwrap(), - ), - pest::DecimalSuffix::U64(_) => { - absy::Expression::U64Constant(expression.value.span.as_str().parse().unwrap()) - } - pest::DecimalSuffix::U32(_) => { - absy::Expression::U32Constant(expression.value.span.as_str().parse().unwrap()) - } - pest::DecimalSuffix::U16(_) => { - absy::Expression::U16Constant(expression.value.span.as_str().parse().unwrap()) - } - pest::DecimalSuffix::U8(_) => { - absy::Expression::U8Constant(expression.value.span.as_str().parse().unwrap()) - } - } - .span(expression.span), - None => absy::Expression::IntConstant( - BigUint::parse_bytes(expression.value.span.as_str().as_bytes(), 10).unwrap(), - ) - .span(expression.span), - } - } -} - -impl<'ast> From> for absy::ExpressionNode<'ast> { - fn from(expression: pest::HexLiteralExpression<'ast>) -> absy::ExpressionNode<'ast> { - use crate::absy::NodeValue; - - match expression.value { - pest::HexNumberExpression::U64(e) => { - absy::Expression::U64Constant(u64::from_str_radix(e.span.as_str(), 16).unwrap()) - } - pest::HexNumberExpression::U32(e) => { - absy::Expression::U32Constant(u32::from_str_radix(e.span.as_str(), 16).unwrap()) - } - pest::HexNumberExpression::U16(e) => { - absy::Expression::U16Constant(u16::from_str_radix(e.span.as_str(), 16).unwrap()) - } - pest::HexNumberExpression::U8(e) => { - absy::Expression::U8Constant(u8::from_str_radix(e.span.as_str(), 16).unwrap()) - } - } - .span(expression.span) - } -} - -impl<'ast> From> for absy::ExpressionNode<'ast> { - fn from(expression: pest::LiteralExpression<'ast>) -> absy::ExpressionNode<'ast> { - use crate::absy::NodeValue; - - match expression { - pest::LiteralExpression::BooleanLiteral(c) => { - absy::Expression::BooleanConstant(c.value.parse().unwrap()).span(c.span) - } - pest::LiteralExpression::DecimalLiteral(n) => absy::ExpressionNode::from(n), - pest::LiteralExpression::HexLiteral(n) => absy::ExpressionNode::from(n), - } - } -} - -impl<'ast> From> for absy::ExpressionNode<'ast> { - fn from(expression: pest::IdentifierExpression<'ast>) -> absy::ExpressionNode<'ast> { - use crate::absy::NodeValue; - absy::Expression::Identifier(expression.span.as_str()).span(expression.span) - } -} - -impl<'ast> From> for absy::AssigneeNode<'ast> { - fn from(expression: pest::IdentifierExpression<'ast>) -> absy::AssigneeNode<'ast> { - use crate::absy::NodeValue; - - absy::Assignee::Identifier(expression.span.as_str()).span(expression.span) - } -} - -impl<'ast> From> for absy::AssigneeNode<'ast> { - fn from(assignee: pest::Assignee<'ast>) -> absy::AssigneeNode<'ast> { - use crate::absy::NodeValue; - - let a = absy::AssigneeNode::from(assignee.id); - let span = assignee.span; - - assignee.accesses.into_iter().fold(a, |acc, s| { - match s { - pest::AssigneeAccess::Select(s) => { - absy::Assignee::Select(box acc, box absy::RangeOrExpression::from(s.expression)) - } - pest::AssigneeAccess::Dot(a) => match a.inner { - pest::IdentifierOrDecimal::Identifier(id) => { - absy::Assignee::Member(box acc, box id.span.as_str()) - } - pest::IdentifierOrDecimal::Decimal(id) => { - absy::Assignee::Element(box acc, id.span.as_str().parse().unwrap()) - } - }, - } - .span(span.clone()) - }) - } -} - -impl<'ast> From> for absy::UnresolvedTypeNode<'ast> { - fn from(t: pest::Type<'ast>) -> absy::UnresolvedTypeNode<'ast> { - use crate::absy::types::UnresolvedType; - use crate::absy::NodeValue; - - match t { - pest::Type::Basic(t) => match t { - pest::BasicType::Field(t) => UnresolvedType::FieldElement.span(t.span), - pest::BasicType::Boolean(t) => UnresolvedType::Boolean.span(t.span), - pest::BasicType::U8(t) => UnresolvedType::Uint(8).span(t.span), - pest::BasicType::U16(t) => UnresolvedType::Uint(16).span(t.span), - pest::BasicType::U32(t) => UnresolvedType::Uint(32).span(t.span), - pest::BasicType::U64(t) => UnresolvedType::Uint(64).span(t.span), - }, - pest::Type::Array(t) => { - let inner_type = match t.ty { - pest::BasicOrStructOrTupleType::Basic(t) => match t { - pest::BasicType::Field(t) => UnresolvedType::FieldElement.span(t.span), - pest::BasicType::Boolean(t) => UnresolvedType::Boolean.span(t.span), - pest::BasicType::U8(t) => UnresolvedType::Uint(8).span(t.span), - pest::BasicType::U16(t) => UnresolvedType::Uint(16).span(t.span), - pest::BasicType::U32(t) => UnresolvedType::Uint(32).span(t.span), - pest::BasicType::U64(t) => UnresolvedType::Uint(64).span(t.span), - }, - pest::BasicOrStructOrTupleType::Struct(t) => UnresolvedType::User( - t.id.span.as_str().to_string(), - t.explicit_generics.map(|explicit_generics| { - explicit_generics - .values - .into_iter() - .map(|i| match i { - pest::ConstantGenericValue::Underscore(_) => None, - pest::ConstantGenericValue::Value(v) => { - Some(absy::ExpressionNode::from(v)) - } - pest::ConstantGenericValue::Identifier(i) => Some( - absy::Expression::Identifier(i.span.as_str()).span(i.span), - ), - }) - .collect() - }), - ) - .span(t.span), - pest::BasicOrStructOrTupleType::Tuple(t) => UnresolvedType::Tuple( - t.elements - .into_iter() - .map(absy::UnresolvedTypeNode::from) - .collect(), - ) - .span(t.span), - }; - - let span = t.span; - - t.dimensions - .into_iter() - .map(absy::ExpressionNode::from) - .rev() - .fold(None, |acc, s| match acc { - None => Some(UnresolvedType::array(inner_type.clone(), s)), - Some(acc) => Some(UnresolvedType::array(acc.span(span.clone()), s)), - }) - .unwrap() - .span(span.clone()) - } - pest::Type::Struct(s) => UnresolvedType::User( - s.id.span.as_str().to_string(), - s.explicit_generics.map(|explicit_generics| { - explicit_generics - .values - .into_iter() - .map(|i| match i { - pest::ConstantGenericValue::Underscore(_) => None, - pest::ConstantGenericValue::Value(v) => { - Some(absy::ExpressionNode::from(v)) - } - pest::ConstantGenericValue::Identifier(i) => { - Some(absy::Expression::Identifier(i.span.as_str()).span(i.span)) - } - }) - .collect() - }), - ) - .span(s.span), - pest::Type::Tuple(t) => UnresolvedType::Tuple( - t.elements - .into_iter() - .map(absy::UnresolvedTypeNode::from) - .collect(), - ) - .span(t.span), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::absy::types::{UnresolvedSignature, UnresolvedType}; - use crate::absy::NodeValue; - - #[test] - fn return_forty_two() { - let source = "def main() -> field: return 42"; - let ast = pest::generate_ast(source).unwrap(); - let expected: absy::Module = absy::Module { - symbols: vec![absy::SymbolDeclaration { - id: &source[4..8], - symbol: absy::Symbol::Here(absy::SymbolDefinition::Function( - absy::Function { - arguments: vec![], - statements: vec![absy::Statement::Return( - absy::ExpressionList { - expressions: vec![ - absy::Expression::IntConstant(42usize.into()).into() - ], - } - .into(), - ) - .into()], - signature: UnresolvedSignature::new() - .inputs(vec![]) - .outputs(vec![UnresolvedType::FieldElement.mock()]), - } - .into(), - )), - } - .into()], - }; - assert_eq!(absy::Module::from(ast), expected); - } - - #[test] - fn return_true() { - let source = "def main() -> bool: return true"; - let ast = pest::generate_ast(source).unwrap(); - let expected: absy::Module = absy::Module { - symbols: vec![absy::SymbolDeclaration { - id: &source[4..8], - symbol: absy::Symbol::Here(absy::SymbolDefinition::Function( - absy::Function { - arguments: vec![], - statements: vec![absy::Statement::Return( - absy::ExpressionList { - expressions: vec![absy::Expression::BooleanConstant(true).into()], - } - .into(), - ) - .into()], - signature: UnresolvedSignature::new() - .inputs(vec![]) - .outputs(vec![UnresolvedType::Boolean.mock()]), - } - .into(), - )), - } - .into()], - }; - assert_eq!(absy::Module::from(ast), expected); - } - - #[test] - fn arguments() { - let source = "def main(private field a, bool b) -> field: return 42"; - let ast = pest::generate_ast(source).unwrap(); - - let expected: absy::Module = absy::Module { - symbols: vec![absy::SymbolDeclaration { - id: &source[4..8], - symbol: absy::Symbol::Here(absy::SymbolDefinition::Function( - absy::Function { - arguments: vec![ - absy::Parameter::private( - absy::Variable::new( - &source[23..24], - UnresolvedType::FieldElement.mock(), - ) - .into(), - ) - .into(), - absy::Parameter::public( - absy::Variable::new( - &source[31..32], - UnresolvedType::Boolean.mock(), - ) - .into(), - ) - .into(), - ], - statements: vec![absy::Statement::Return( - absy::ExpressionList { - expressions: vec![ - absy::Expression::IntConstant(42usize.into()).into() - ], - } - .into(), - ) - .into()], - signature: UnresolvedSignature::new() - .inputs(vec![ - UnresolvedType::FieldElement.mock(), - UnresolvedType::Boolean.mock(), - ]) - .outputs(vec![UnresolvedType::FieldElement.mock()]), - } - .into(), - )), - } - .into()], - }; - - assert_eq!(absy::Module::from(ast), expected); - } - - mod types { - use super::*; - - /// Helper method to generate the ast for `def main(private {ty} a): return` which we use to check ty - fn wrap(ty: UnresolvedType<'static>) -> absy::Module<'static> { - absy::Module { - symbols: vec![absy::SymbolDeclaration { - id: "main", - symbol: absy::Symbol::Here(absy::SymbolDefinition::Function( - absy::Function { - arguments: vec![absy::Parameter::private( - absy::Variable::new("a", ty.clone().mock()).into(), - ) - .into()], - statements: vec![absy::Statement::Return( - absy::ExpressionList { - expressions: vec![], - } - .into(), - ) - .into()], - signature: UnresolvedSignature::new().inputs(vec![ty.mock()]), - } - .into(), - )), - } - .into()], - } - } - - #[test] - fn array() { - let vectors = vec![ - ("field", UnresolvedType::FieldElement), - ("bool", UnresolvedType::Boolean), - ( - "field[2]", - absy::UnresolvedType::Array( - box absy::UnresolvedType::FieldElement.mock(), - absy::Expression::IntConstant(2usize.into()).mock(), - ), - ), - ( - "field[2][3]", - absy::UnresolvedType::Array( - box absy::UnresolvedType::Array( - box absy::UnresolvedType::FieldElement.mock(), - absy::Expression::IntConstant(3usize.into()).mock(), - ) - .mock(), - absy::Expression::IntConstant(2usize.into()).mock(), - ), - ), - ( - "bool[2][3u32]", - absy::UnresolvedType::Array( - box absy::UnresolvedType::Array( - box absy::UnresolvedType::Boolean.mock(), - absy::Expression::U32Constant(3u32).mock(), - ) - .mock(), - absy::Expression::IntConstant(2usize.into()).mock(), - ), - ), - ]; - - for (ty, expected) in vectors { - let source = format!("def main(private {} a): return", ty); - let expected = wrap(expected); - let ast = pest::generate_ast(&source).unwrap(); - assert_eq!(absy::Module::from(ast), expected); - } - } - } - - mod postfix { - use super::*; - fn wrap(expression: absy::Expression<'static>) -> absy::Module { - absy::Module { - symbols: vec![absy::SymbolDeclaration { - id: "main", - symbol: absy::Symbol::Here(absy::SymbolDefinition::Function( - absy::Function { - arguments: vec![], - statements: vec![absy::Statement::Return( - absy::ExpressionList { - expressions: vec![expression.into()], - } - .into(), - ) - .into()], - signature: UnresolvedSignature::new(), - } - .into(), - )), - } - .into()], - } - } - - #[test] - fn success() { - // we basically accept `()?[]*` : an optional call at first, then only array accesses - - let vectors = vec![ - ("a", absy::Expression::Identifier("a")), - ( - "a[3]", - absy::Expression::Select( - box absy::Expression::Identifier("a").into(), - box absy::RangeOrExpression::Expression( - absy::Expression::IntConstant(3usize.into()).into(), - ), - ), - ), - ( - "a[3][4]", - absy::Expression::Select( - box absy::Expression::Select( - box absy::Expression::Identifier("a").into(), - box absy::RangeOrExpression::Expression( - absy::Expression::IntConstant(3usize.into()).into(), - ), - ) - .into(), - box absy::RangeOrExpression::Expression( - absy::Expression::IntConstant(4usize.into()).into(), - ), - ), - ), - ( - "a(3)[4]", - absy::Expression::Select( - box absy::Expression::FunctionCall( - box absy::Expression::Identifier("a").mock(), - None, - vec![absy::Expression::IntConstant(3usize.into()).into()], - ) - .into(), - box absy::RangeOrExpression::Expression( - absy::Expression::IntConstant(4usize.into()).into(), - ), - ), - ), - ( - "a(3)[4][5]", - absy::Expression::Select( - box absy::Expression::Select( - box absy::Expression::FunctionCall( - box absy::Expression::Identifier("a").mock(), - None, - vec![absy::Expression::IntConstant(3usize.into()).into()], - ) - .into(), - box absy::RangeOrExpression::Expression( - absy::Expression::IntConstant(4usize.into()).into(), - ), - ) - .into(), - box absy::RangeOrExpression::Expression( - absy::Expression::IntConstant(5usize.into()).into(), - ), - ), - ), - ]; - - for (source, expected) in vectors { - let source = format!("def main(): return {}", source); - let expected = wrap(expected); - let ast = pest::generate_ast(&source).unwrap(); - assert_eq!(absy::Module::from(ast), expected); - } - } - - #[test] - fn call_array_element() { - // a call after an array access should be accepted - let source = "def main(): return a[2](3)"; - let ast = pest::generate_ast(source).unwrap(); - assert_eq!( - absy::Module::from(ast), - wrap(absy::Expression::FunctionCall( - box absy::Expression::Select( - box absy::Expression::Identifier("a").mock(), - box absy::RangeOrExpression::Expression( - absy::Expression::IntConstant(2u32.into()).mock() - ) - ) - .mock(), - None, - vec![absy::Expression::IntConstant(3u32.into()).mock()], - )) - ); - } - - #[test] - fn call_call_result() { - // a call after a call should be accepted - let source = "def main(): return a(2)(3)"; - - let ast = pest::generate_ast(source).unwrap(); - assert_eq!( - absy::Module::from(ast), - wrap(absy::Expression::FunctionCall( - box absy::Expression::FunctionCall( - box absy::Expression::Identifier("a").mock(), - None, - vec![absy::Expression::IntConstant(2u32.into()).mock()] - ) - .mock(), - None, - vec![absy::Expression::IntConstant(3u32.into()).mock()], - )) - ); - } - } - #[test] - fn declarations() { - use self::pest::Span; - - let span = Span::new("", 0, 0).unwrap(); - - // For different definitions, we generate declarations - // Case 1: `id = expr` where `expr` is not a function call - // This is a simple assignment, doesn't implicitely declare a variable - // A `Definition` is generated and no `Declaration`s - - let definition = pest::DefinitionStatement { - lhs: vec![pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee { - id: pest::IdentifierExpression { - value: String::from("a"), - span: span.clone(), - }, - accesses: vec![], - span: span.clone(), - })], - expression: pest::Expression::Literal(pest::LiteralExpression::DecimalLiteral( - pest::DecimalLiteralExpression { - value: pest::DecimalNumber { - span: Span::new("1", 0, 1).unwrap(), - }, - suffix: None, - span: span.clone(), - }, - )), - span: span.clone(), - }; - - let statements: Vec = statements_from_definition(definition); - - assert_eq!(statements.len(), 1); - match &statements[0].value { - absy::Statement::Definition(..) => {} - s => { - panic!("should be a Definition, found {}", s); - } - }; - - // Case 2: `id = expr` where `expr` is a function call - // A MultiDef is generated - - let definition = pest::DefinitionStatement { - lhs: vec![pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee { - id: pest::IdentifierExpression { - value: String::from("a"), - span: span.clone(), - }, - accesses: vec![], - span: span.clone(), - })], - expression: pest::Expression::Postfix(pest::PostfixExpression { - base: box pest::Expression::Identifier(pest::IdentifierExpression { - value: String::from("foo"), - span: span.clone(), - }), - accesses: vec![pest::Access::Call(pest::CallAccess { - explicit_generics: None, - arguments: pest::Arguments { - expressions: vec![], - span: span.clone(), - }, - span: span.clone(), - })], - span: span.clone(), - }), - span: span.clone(), - }; - - let statements: Vec = statements_from_definition(definition); - - assert_eq!(statements.len(), 1); - match &statements[0].value { - absy::Statement::MultipleDefinition(..) => {} - s => { - panic!("should be a Definition, found {}", s); - } - }; - // Case 3: `ids = expr` where `expr` is a function call - // This implicitely declares all variables which are type annotated - - // `field a, b = foo()` - - let definition = pest::DefinitionStatement { - lhs: vec![ - pest::TypedIdentifierOrAssignee::TypedIdentifier(pest::TypedIdentifier { - ty: pest::Type::Basic(pest::BasicType::Field(pest::FieldType { - span: span.clone(), - })), - identifier: pest::IdentifierExpression { - value: String::from("a"), - span: span.clone(), - }, - span: span.clone(), - }), - pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee { - id: pest::IdentifierExpression { - value: String::from("b"), - span: span.clone(), - }, - accesses: vec![], - span: span.clone(), - }), - ], - expression: pest::Expression::Postfix(pest::PostfixExpression { - base: box pest::Expression::Identifier(pest::IdentifierExpression { - value: String::from("foo"), - span: span.clone(), - }), - accesses: vec![pest::Access::Call(pest::CallAccess { - explicit_generics: None, - arguments: pest::Arguments { - expressions: vec![], - span: span.clone(), - }, - span: span.clone(), - })], - span: span.clone(), - }), - span: span.clone(), - }; - - let statements: Vec = statements_from_definition(definition); - - assert_eq!(statements.len(), 2); - match &statements[1].value { - absy::Statement::MultipleDefinition(..) => {} - s => { - panic!("should be a Definition, found {}", s); - } - }; - } -} diff --git a/zokrates_core/src/compile.rs b/zokrates_core/src/compile.rs index f8804bbf..f7986766 100644 --- a/zokrates_core/src/compile.rs +++ b/zokrates_core/src/compile.rs @@ -6,7 +6,6 @@ use crate::absy::{Module, OwnedModuleId, Program}; use crate::flatten::FlattenerIterator; use crate::imports::{self, Importer}; -use crate::ir; use crate::macros; use crate::semantics::{self, Checker}; use crate::static_analysis; @@ -19,6 +18,7 @@ use std::fmt; use std::io; use std::path::{Path, PathBuf}; use typed_arena::Arena; +use zokrates_ast::ir; use zokrates_common::Resolver; use zokrates_field::Field; use zokrates_pest_ast as pest; @@ -204,7 +204,8 @@ pub fn compile<'ast, T: Field, E: Into>( // convert to ir log::debug!("Convert to IR"); - let ir_prog = ir::from_flat::from_flat(program_flattened); + //let ir_prog = ir::from_flat::from_flat(program_flattened); + let ir_prog = unimplemented!(); // optimize log::debug!("Optimise IR"); diff --git a/zokrates_core/src/flatten/mod.rs b/zokrates_core/src/flatten/mod.rs index 64fc11b5..a724825b 100644 --- a/zokrates_core/src/flatten/mod.rs +++ b/zokrates_core/src/flatten/mod.rs @@ -8,19 +8,26 @@ mod utils; use self::utils::flat_expression_from_bits; -use crate::ir::Interpreter; +use zokrates_ast::zir::{ShouldReduce, UMetadata, ZirExpressionList}; +use zokrates_interpreter::Interpreter; use crate::compile::CompileConfig; -use crate::embed::FlatEmbed; -use crate::flat_absy::{RuntimeError, *}; -use crate::solvers::Solver; +use crate::flat_absy::*; use crate::zir::types::{Type, UBitwidth}; -use crate::zir::*; +use crate::zir::{ + BooleanExpression, FieldElementExpression, Identifier, IfElse, Parameter as ZirParameter, + UExpression, UExpressionInner, Variable as ZirVariable, ZirExpression, ZirFunction, + ZirStatement, +}; use std::collections::{ hash_map::{Entry, HashMap}, VecDeque, }; use std::convert::TryFrom; +use zokrates_ast::common::embed::*; +use zokrates_ast::common::FlatEmbed; +use zokrates_ast::common::{RuntimeError, Variable}; +use zokrates_ast::ir::Solver; use zokrates_field::Field; type FlatStatements = VecDeque>; @@ -29,26 +36,27 @@ type FlatStatements = VecDeque>; /// /// # Arguments /// * `funct` - `ZirFunction` that will be flattened -impl<'ast, T: Field> FlattenerIterator<'ast, T> { - pub fn from_function_and_config(funct: ZirFunction<'ast, T>, config: CompileConfig) -> Self { - let mut flattener = Flattener::new(config); - let mut statements_flattened = FlatStatements::new(); - // push parameters - let arguments_flattened = funct - .arguments - .into_iter() - .map(|p| flattener.use_parameter(&p, &mut statements_flattened)) - .collect(); +pub fn from_function_and_config<'ast, T: Field>( + funct: ZirFunction<'ast, T>, + config: CompileConfig, +) -> FlattenerIterator<'ast, T> { + let mut flattener = Flattener::new(config); + let mut statements_flattened = FlatStatements::new(); + // push parameters + let arguments_flattened = funct + .arguments + .into_iter() + .map(|p| flattener.use_parameter(&p, &mut statements_flattened)) + .collect(); - FlattenerIterator { - arguments: arguments_flattened, - statements: FlattenerIteratorInner { - statements: funct.statements.into(), - statements_flattened, - flattener, - }, - return_count: funct.signature.outputs.len(), - } + FlattenerIterator { + arguments: arguments_flattened, + statements: FlattenerIteratorInner { + statements: funct.statements.into(), + statements_flattened, + flattener, + }, + return_count: funct.signature.outputs.len(), } } @@ -85,8 +93,8 @@ pub struct Flattener<'ast, T> { config: CompileConfig, /// Index of the next introduced variable while processing the program. next_var_idx: usize, - /// `FlatVariable`s corresponding to each `Identifier` - layout: HashMap, FlatVariable>, + /// `Variable`s corresponding to each `Identifier` + layout: HashMap, Variable>, /// Cached bit decompositions to avoid re-generating them bits_cache: HashMap, Vec>>, } @@ -200,14 +208,14 @@ impl FlatUExpression { } } -impl From for RuntimeError { - fn from(error: crate::zir::RuntimeError) -> Self { - match error { - crate::zir::RuntimeError::SourceAssertion(s) => RuntimeError::SourceAssertion(s), - crate::zir::RuntimeError::SelectRangeCheck => RuntimeError::SelectRangeCheck, - } - } -} +// impl From for RuntimeError { +// fn from(error: crate::zir::RuntimeError) -> Self { +// match error { +// crate::zir::RuntimeError::SourceAssertion(s) => RuntimeError::SourceAssertion(s), +// crate::zir::RuntimeError::SelectRangeCheck => RuntimeError::SelectRangeCheck, +// } +// } +// } impl<'ast, T: Field> Flattener<'ast, T> { /// Returns a `Flattener` with fresh `layout`. @@ -225,7 +233,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { &mut self, e: FlatExpression, statements_flattened: &mut FlatStatements, - ) -> FlatVariable { + ) -> Variable { match e { FlatExpression::Identifier(id) => id, e => { @@ -774,7 +782,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { let sub_width = bit_width + 1; // define variables for the bits - let shifted_sub_bits_be: Vec = + let shifted_sub_bits_be: Vec = (0..sub_width).map(|_| self.use_sym()).collect(); // add a directive to get the bits @@ -1160,19 +1168,17 @@ impl<'ast, T: Field> Flattener<'ast, T> { FlatEmbed::Unpack => self.flatten_embed_call_aux( statements_flattened, params, - crate::embed::unpack_to_bitwidth(generics[0] as usize), + unpack_to_bitwidth(generics[0] as usize), ), #[cfg(feature = "bellman")] - FlatEmbed::Sha256Round => self.flatten_embed_call_aux( - statements_flattened, - params, - crate::embed::sha256_round(), - ), + FlatEmbed::Sha256Round => { + self.flatten_embed_call_aux(statements_flattened, params, sha256_round()) + } #[cfg(feature = "ark")] FlatEmbed::SnarkVerifyBls12377 => self.flatten_embed_call_aux( statements_flattened, params, - crate::embed::snark_verify_bls12_377::(generics[0] as usize), + snark_verify_bls12_377::(generics[0] as usize), ), _ => unreachable!(), }, @@ -1191,7 +1197,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { // Rename Parameters, assign them to values in call. Resolve complex expressions with definitions let params_flattened = params.into_iter().map(|e| e.get_field_unchecked()); - let return_values = (0..funct.return_count).map(FlatVariable::public); + let return_values = (0..funct.return_count).map(Variable::public); for (concrete_argument, formal_argument) in params_flattened.zip(funct.arguments) { let new_var = self.define(concrete_argument, statements_flattened); @@ -2315,9 +2321,10 @@ impl<'ast, T: Field> Flattener<'ast, T> { .collect(); statements_flattened.extend( - flat_expressions.into_iter().enumerate().map(|(index, e)| { - FlatStatement::Definition(FlatVariable::public(index), e) - }), + flat_expressions + .into_iter() + .enumerate() + .map(|(index, e)| FlatStatement::Definition(Variable::public(index), e)), ); } ZirStatement::IfElse(condition, consequence, alternative) => { @@ -2629,11 +2636,11 @@ impl<'ast, T: Field> Flattener<'ast, T> { } } - /// Returns a fresh FlatVariable for a given Variable + /// Returns a fresh Variable for a given Variable /// # Arguments /// /// * `variable` - a variable in the program being flattened - fn use_variable(&mut self, variable: &Variable<'ast>) -> FlatVariable { + fn use_variable(&mut self, variable: &ZirVariable<'ast>) -> Variable { let var = self.issue_new_variable(); self.layout.insert(variable.id.clone(), var); @@ -2647,17 +2654,17 @@ impl<'ast, T: Field> Flattener<'ast, T> { /// * `flat_variable` - an existing flat variable fn use_variable_with_existing( &mut self, - variable: &Variable<'ast>, - flat_variable: FlatVariable, + variable: &ZirVariable<'ast>, + flat_variable: Variable, ) { self.layout.insert(variable.id.clone(), flat_variable); } fn use_parameter( &mut self, - parameter: &Parameter<'ast>, + parameter: &ZirParameter<'ast>, statements_flattened: &mut FlatStatements, - ) -> FlatParameter { + ) -> Parameter { let variable = self.use_variable(¶meter.id); match parameter.id.get_type() { @@ -2682,20 +2689,20 @@ impl<'ast, T: Field> Flattener<'ast, T> { Type::FieldElement => {} } - FlatParameter { + Parameter { id: variable, private: parameter.private, } } - fn issue_new_variable(&mut self) -> FlatVariable { - let var = FlatVariable::new(self.next_var_idx); + fn issue_new_variable(&mut self) -> Variable { + let var = Variable::new(self.next_var_idx); self.next_var_idx += 1; var } // create an internal variable. We do not register it in the layout - fn use_sym(&mut self) -> FlatVariable { + fn use_sym(&mut self) -> Variable { self.issue_new_variable() } } @@ -2755,17 +2762,17 @@ mod tests { return_count: 0, statements: vec![ FlatStatement::Definition( - FlatVariable::new(0), + Variable::new(0), FlatExpression::Number(Bn128Field::from(1)), ), FlatStatement::Definition( - FlatVariable::new(1), + Variable::new(1), FlatExpression::Number(Bn128Field::from(1)), ), FlatStatement::Condition( - FlatExpression::Identifier(FlatVariable::new(1)), + FlatExpression::Identifier(Variable::new(1)), FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(0)), + box FlatExpression::Identifier(Variable::new(0)), box FlatExpression::Number(Bn128Field::from(1)), ), zir::RuntimeError::mock().into(), @@ -2823,18 +2830,18 @@ mod tests { return_count: 0, statements: vec![ FlatStatement::Definition( - FlatVariable::new(0), + Variable::new(0), FlatExpression::Number(Bn128Field::from(1)), ), FlatStatement::Definition( - FlatVariable::new(1), + Variable::new(1), FlatExpression::Number(Bn128Field::from(2)), ), FlatStatement::Condition( - FlatExpression::Identifier(FlatVariable::new(1)), + FlatExpression::Identifier(Variable::new(1)), FlatExpression::Mult( box FlatExpression::Add( - box FlatExpression::Identifier(FlatVariable::new(0)), + box FlatExpression::Identifier(Variable::new(0)), box FlatExpression::Number(Bn128Field::from(1)), ), box FlatExpression::Number(Bn128Field::from(1)), @@ -2896,13 +2903,13 @@ mod tests { return_count: 0, statements: vec![ FlatStatement::Definition( - FlatVariable::new(0), + Variable::new(0), FlatExpression::Number(Bn128Field::from(42)), ), FlatStatement::Condition( FlatExpression::Number(Bn128Field::from(42)), FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(0)), + box FlatExpression::Identifier(Variable::new(0)), box FlatExpression::Number(Bn128Field::from(1)), ), zir::RuntimeError::mock().into(), @@ -2958,17 +2965,17 @@ mod tests { return_count: 0, statements: vec![ FlatStatement::Definition( - FlatVariable::new(0), + Variable::new(0), FlatExpression::Number(Bn128Field::from(2)), ), FlatStatement::Definition( - FlatVariable::new(1), + Variable::new(1), FlatExpression::Number(Bn128Field::from(2)), ), FlatStatement::Condition( - FlatExpression::Identifier(FlatVariable::new(1)), + FlatExpression::Identifier(Variable::new(1)), FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(0)), + box FlatExpression::Identifier(Variable::new(0)), box FlatExpression::Number(Bn128Field::from(1)), ), zir::RuntimeError::mock().into(), @@ -3033,22 +3040,22 @@ mod tests { return_count: 0, statements: vec![ FlatStatement::Definition( - FlatVariable::new(0), + Variable::new(0), FlatExpression::Number(Bn128Field::from(2)), ), FlatStatement::Definition( - FlatVariable::new(1), + Variable::new(1), FlatExpression::Number(Bn128Field::from(2)), ), FlatStatement::Definition( - FlatVariable::new(2), + Variable::new(2), FlatExpression::Number(Bn128Field::from(4)), ), FlatStatement::Condition( - FlatExpression::Identifier(FlatVariable::new(2)), + FlatExpression::Identifier(Variable::new(2)), FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(0)), - box FlatExpression::Identifier(FlatVariable::new(1)), + box FlatExpression::Identifier(Variable::new(0)), + box FlatExpression::Identifier(Variable::new(1)), ), zir::RuntimeError::mock().into(), ), @@ -3112,22 +3119,22 @@ mod tests { return_count: 0, statements: vec![ FlatStatement::Definition( - FlatVariable::new(0), + Variable::new(0), FlatExpression::Number(Bn128Field::from(2)), ), FlatStatement::Definition( - FlatVariable::new(1), + Variable::new(1), FlatExpression::Number(Bn128Field::from(2)), ), FlatStatement::Definition( - FlatVariable::new(2), + Variable::new(2), FlatExpression::Number(Bn128Field::from(4)), ), FlatStatement::Condition( - FlatExpression::Identifier(FlatVariable::new(2)), + FlatExpression::Identifier(Variable::new(2)), FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(0)), - box FlatExpression::Identifier(FlatVariable::new(1)), + box FlatExpression::Identifier(Variable::new(0)), + box FlatExpression::Identifier(Variable::new(1)), ), zir::RuntimeError::mock().into(), ), @@ -3199,33 +3206,33 @@ mod tests { return_count: 0, statements: vec![ FlatStatement::Definition( - FlatVariable::new(0), + Variable::new(0), FlatExpression::Number(Bn128Field::from(4)), ), FlatStatement::Definition( - FlatVariable::new(1), + Variable::new(1), FlatExpression::Number(Bn128Field::from(4)), ), FlatStatement::Definition( - FlatVariable::new(2), + Variable::new(2), FlatExpression::Number(Bn128Field::from(8)), ), FlatStatement::Definition( - FlatVariable::new(3), + Variable::new(3), FlatExpression::Number(Bn128Field::from(2)), ), FlatStatement::Definition( - FlatVariable::new(4), + Variable::new(4), FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(2)), - box FlatExpression::Identifier(FlatVariable::new(3)), + box FlatExpression::Identifier(Variable::new(2)), + box FlatExpression::Identifier(Variable::new(3)), ), ), FlatStatement::Condition( - FlatExpression::Identifier(FlatVariable::new(4)), + FlatExpression::Identifier(Variable::new(4)), FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(0)), - box FlatExpression::Identifier(FlatVariable::new(1)), + box FlatExpression::Identifier(Variable::new(0)), + box FlatExpression::Identifier(Variable::new(1)), ), zir::RuntimeError::mock().into(), ), @@ -3274,16 +3281,16 @@ mod tests { return_count: 1, statements: vec![ FlatStatement::Definition( - FlatVariable::new(0), + Variable::new(0), FlatExpression::Number(Bn128Field::from(7)), ), FlatStatement::Definition( - FlatVariable::new(1), + Variable::new(1), FlatExpression::Number(Bn128Field::from(1)), ), FlatStatement::Definition( - FlatVariable::public(0), - FlatExpression::Identifier(FlatVariable::new(1)), + Variable::public(0), + FlatExpression::Identifier(Variable::new(1)), ), ], }; @@ -3333,19 +3340,19 @@ mod tests { return_count: 1, statements: vec![ FlatStatement::Definition( - FlatVariable::new(0), + Variable::new(0), FlatExpression::Number(Bn128Field::from(7)), ), FlatStatement::Definition( - FlatVariable::new(1), + Variable::new(1), FlatExpression::Mult( box FlatExpression::Number(Bn128Field::from(1)), - box FlatExpression::Identifier(FlatVariable::new(0)), + box FlatExpression::Identifier(Variable::new(0)), ), ), FlatStatement::Definition( - FlatVariable::public(0), - FlatExpression::Identifier(FlatVariable::new(1)), + Variable::public(0), + FlatExpression::Identifier(Variable::new(1)), ), ], }; @@ -3412,54 +3419,54 @@ mod tests { return_count: 1, statements: vec![ FlatStatement::Definition( - FlatVariable::new(0), + Variable::new(0), FlatExpression::Number(Bn128Field::from(7)), ), FlatStatement::Definition( - FlatVariable::new(1), + Variable::new(1), FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(0)), - box FlatExpression::Identifier(FlatVariable::new(0)), + box FlatExpression::Identifier(Variable::new(0)), + box FlatExpression::Identifier(Variable::new(0)), ), ), FlatStatement::Definition( - FlatVariable::new(2), + Variable::new(2), FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(1)), - box FlatExpression::Identifier(FlatVariable::new(1)), + box FlatExpression::Identifier(Variable::new(1)), + box FlatExpression::Identifier(Variable::new(1)), ), ), FlatStatement::Definition( - FlatVariable::new(3), + Variable::new(3), FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(2)), - box FlatExpression::Identifier(FlatVariable::new(2)), + box FlatExpression::Identifier(Variable::new(2)), + box FlatExpression::Identifier(Variable::new(2)), ), ), FlatStatement::Definition( - FlatVariable::new(4), + Variable::new(4), FlatExpression::Mult( box FlatExpression::Number(Bn128Field::from(1)), - box FlatExpression::Identifier(FlatVariable::new(0)), + box FlatExpression::Identifier(Variable::new(0)), ), ), FlatStatement::Definition( - FlatVariable::new(5), + Variable::new(5), FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(4)), - box FlatExpression::Identifier(FlatVariable::new(2)), + box FlatExpression::Identifier(Variable::new(4)), + box FlatExpression::Identifier(Variable::new(2)), ), ), FlatStatement::Definition( - FlatVariable::new(6), + Variable::new(6), FlatExpression::Mult( - box FlatExpression::Identifier(FlatVariable::new(5)), - box FlatExpression::Identifier(FlatVariable::new(3)), + box FlatExpression::Identifier(Variable::new(5)), + box FlatExpression::Identifier(Variable::new(3)), ), ), FlatStatement::Definition( - FlatVariable::public(0), - FlatExpression::Identifier(FlatVariable::new(6)), + Variable::public(0), + FlatExpression::Identifier(Variable::new(6)), ), ], }; @@ -3556,22 +3563,22 @@ mod tests { flattener.flatten_statement(&mut statements_flattened, statement); // define b - let b = FlatVariable::new(0); + let b = Variable::new(0); // define new wires for members of Div - let five = FlatVariable::new(1); - let b0 = FlatVariable::new(2); + let five = Variable::new(1); + let b0 = Variable::new(2); // Define inverse of denominator to prevent div by 0 - let invb0 = FlatVariable::new(3); + let invb0 = Variable::new(3); // Define inverse - let sym_0 = FlatVariable::new(4); + let sym_0 = Variable::new(4); // Define result, which is first member to next Div - let sym_1 = FlatVariable::new(5); + let sym_1 = Variable::new(5); // Define second member - let b1 = FlatVariable::new(6); + let b1 = Variable::new(6); // Define inverse of denominator to prevent div by 0 - let invb1 = FlatVariable::new(7); + let invb1 = Variable::new(7); // Define inverse - let sym_2 = FlatVariable::new(8); + let sym_2 = Variable::new(8); assert_eq!( statements_flattened, diff --git a/zokrates_core/src/imports.rs b/zokrates_core/src/imports.rs index 00814b74..760bbbdc 100644 --- a/zokrates_core/src/imports.rs +++ b/zokrates_core/src/imports.rs @@ -7,8 +7,6 @@ use crate::absy::*; use crate::compile::parse_module; use crate::compile::{CompileErrorInner, CompileErrors}; -use crate::embed::FlatEmbed; -use crate::parser::Position; use std::collections::HashMap; use std::fmt; use std::io; @@ -16,6 +14,7 @@ use std::path::{Path, PathBuf}; use crate::absy::types::UnresolvedType; use typed_arena::Arena; +use zokrates_ast::common::FlatEmbed; use zokrates_common::Resolver; use zokrates_field::Field; diff --git a/zokrates_core/src/lib.rs b/zokrates_core/src/lib.rs index 955218a2..ae703cda 100644 --- a/zokrates_core/src/lib.rs +++ b/zokrates_core/src/lib.rs @@ -8,20 +8,16 @@ cfg_if::cfg_if! { } } -mod embed; mod flatten; pub mod imports; mod macros; mod optimizer; -mod parser; mod semantics; -mod solvers; mod static_analysis; -mod zir; +use zokrates_ast::zir; -pub mod absy; +pub use zokrates_ast::untyped as absy; pub mod compile; -pub mod flat_absy; -pub mod ir; +pub use zokrates_ast::flat as flat_absy; pub mod proof_system; -pub mod typed_absy; +pub use zokrates_ast::typed as typed_absy; diff --git a/zokrates_core/src/optimizer/canonicalizer.rs b/zokrates_core/src/optimizer/canonicalizer.rs index d5c6bae3..4a65bc85 100644 --- a/zokrates_core/src/optimizer/canonicalizer.rs +++ b/zokrates_core/src/optimizer/canonicalizer.rs @@ -1,4 +1,4 @@ -use crate::ir::{folder::Folder, LinComb}; +use zokrates_ast::ir::{folder::Folder, LinComb}; use zokrates_field::Field; #[derive(Default)] diff --git a/zokrates_core/src/optimizer/directive.rs b/zokrates_core/src/optimizer/directive.rs index f651c551..afabc87b 100644 --- a/zokrates_core/src/optimizer/directive.rs +++ b/zokrates_core/src/optimizer/directive.rs @@ -9,22 +9,20 @@ // c := b // ``` -use crate::flat_absy::flat_variable::FlatVariable; -use crate::ir::folder::*; -use crate::ir::*; -use crate::solvers::Solver; use std::collections::hash_map::{Entry, HashMap}; +use zokrates_ast::ir::folder::*; +use zokrates_ast::ir::*; use zokrates_field::Field; #[derive(Debug, Default)] pub struct DirectiveOptimizer { - calls: HashMap<(Solver, Vec>), Vec>, + calls: HashMap<(Solver, Vec>), Vec>, /// Map of renamings for reassigned variables while processing the program. - substitution: HashMap, + substitution: HashMap, } impl Folder for DirectiveOptimizer { - fn fold_variable(&mut self, v: FlatVariable) -> FlatVariable { + fn fold_variable(&mut self, v: Variable) -> Variable { *self.substitution.get(&v).unwrap_or(&v) } diff --git a/zokrates_core/src/optimizer/duplicate.rs b/zokrates_core/src/optimizer/duplicate.rs index 7edd2c99..ea596403 100644 --- a/zokrates_core/src/optimizer/duplicate.rs +++ b/zokrates_core/src/optimizer/duplicate.rs @@ -1,9 +1,9 @@ //! Module containing the `DuplicateOptimizer` to remove duplicate constraints -use crate::ir::folder::*; -use crate::ir::*; use crate::optimizer::canonicalizer::Canonicalizer; use std::collections::{hash_map::DefaultHasher, HashSet}; +use zokrates_ast::ir::folder::*; +use zokrates_ast::ir::*; use zokrates_field::Field; type Hash = u64; @@ -53,7 +53,7 @@ impl Folder for DuplicateOptimizer { #[cfg(test)] mod tests { use super::*; - use crate::flat_absy::FlatVariable; + use crate::flat_absy::Variable; use zokrates_field::Bn128Field; #[test] @@ -62,15 +62,15 @@ mod tests { statements: vec![ Statement::constraint( QuadComb::from_linear_combinations( - LinComb::summand(3, FlatVariable::new(3)), - LinComb::summand(3, FlatVariable::new(3)), + LinComb::summand(3, Variable::new(3)), + LinComb::summand(3, Variable::new(3)), ), LinComb::one(), ), Statement::constraint( QuadComb::from_linear_combinations( - LinComb::summand(3, FlatVariable::new(42)), - LinComb::summand(3, FlatVariable::new(3)), + LinComb::summand(3, Variable::new(42)), + LinComb::summand(3, Variable::new(3)), ), LinComb::zero(), ), @@ -91,8 +91,8 @@ mod tests { fn remove_duplicates() { let constraint = Statement::constraint( QuadComb::from_linear_combinations( - LinComb::summand(3, FlatVariable::new(3)), - LinComb::summand(3, FlatVariable::new(3)), + LinComb::summand(3, Variable::new(3)), + LinComb::summand(3, Variable::new(3)), ), LinComb::one(), ); @@ -103,8 +103,8 @@ mod tests { constraint.clone(), Statement::constraint( QuadComb::from_linear_combinations( - LinComb::summand(3, FlatVariable::new(42)), - LinComb::summand(3, FlatVariable::new(3)), + LinComb::summand(3, Variable::new(42)), + LinComb::summand(3, Variable::new(3)), ), LinComb::zero(), ), @@ -120,8 +120,8 @@ mod tests { constraint, Statement::constraint( QuadComb::from_linear_combinations( - LinComb::summand(3, FlatVariable::new(42)), - LinComb::summand(3, FlatVariable::new(3)), + LinComb::summand(3, Variable::new(42)), + LinComb::summand(3, Variable::new(3)), ), LinComb::zero(), ), diff --git a/zokrates_core/src/optimizer/mod.rs b/zokrates_core/src/optimizer/mod.rs index 051519f0..cecee2e3 100644 --- a/zokrates_core/src/optimizer/mod.rs +++ b/zokrates_core/src/optimizer/mod.rs @@ -16,50 +16,46 @@ use self::duplicate::DuplicateOptimizer; use self::redefinition::RedefinitionOptimizer; use self::tautology::TautologyOptimizer; -use crate::ir::{ProgIterator, Statement}; +use zokrates_ast::ir::{ProgIterator, Statement}; use zokrates_field::Field; -impl>> ProgIterator { - pub fn optimize(self) -> ProgIterator>> { - // remove redefinitions - log::debug!( - "Optimizer: Remove redefinitions and tautologies and directives and duplicates" - ); +pub fn optimize>>( + p: ProgIterator, +) -> ProgIterator>> { + // remove redefinitions + log::debug!("Optimizer: Remove redefinitions and tautologies and directives and duplicates"); - // define all optimizer steps - let mut redefinition_optimizer = RedefinitionOptimizer::init(&self); - let mut tautologies_optimizer = TautologyOptimizer::default(); - let mut directive_optimizer = DirectiveOptimizer::default(); - let mut canonicalizer = Canonicalizer::default(); - let mut duplicate_optimizer = DuplicateOptimizer::default(); + // define all optimizer steps + let mut redefinition_optimizer = RedefinitionOptimizer::init(&p); + let mut tautologies_optimizer = TautologyOptimizer::default(); + let mut directive_optimizer = DirectiveOptimizer::default(); + let mut canonicalizer = Canonicalizer::default(); + let mut duplicate_optimizer = DuplicateOptimizer::default(); - use crate::ir::folder::Folder; + use zokrates_ast::ir::folder::Folder; - let r = ProgIterator { - arguments: self - .arguments - .into_iter() - .map(|a| redefinition_optimizer.fold_argument(a)) - .map(|a| { - >::fold_argument(&mut tautologies_optimizer, a) - }) - .map(|a| directive_optimizer.fold_argument(a)) - .map(|a| { - >::fold_argument(&mut duplicate_optimizer, a) - }) - .collect(), - statements: self - .statements - .into_iter() - .flat_map(move |s| redefinition_optimizer.fold_statement(s)) - .flat_map(move |s| tautologies_optimizer.fold_statement(s)) - .flat_map(move |s| canonicalizer.fold_statement(s)) - .flat_map(move |s| directive_optimizer.fold_statement(s)) - .flat_map(move |s| duplicate_optimizer.fold_statement(s)), - return_count: self.return_count, - }; + let r = ProgIterator { + arguments: p + .arguments + .into_iter() + .map(|a| redefinition_optimizer.fold_argument(a)) + .map(|a| { + >::fold_argument(&mut tautologies_optimizer, a) + }) + .map(|a| directive_optimizer.fold_argument(a)) + .map(|a| >::fold_argument(&mut duplicate_optimizer, a)) + .collect(), + statements: p + .statements + .into_iter() + .flat_map(move |s| redefinition_optimizer.fold_statement(s)) + .flat_map(move |s| tautologies_optimizer.fold_statement(s)) + .flat_map(move |s| canonicalizer.fold_statement(s)) + .flat_map(move |s| directive_optimizer.fold_statement(s)) + .flat_map(move |s| duplicate_optimizer.fold_statement(s)), + return_count: p.return_count, + }; - log::debug!("Done"); - r - } + log::debug!("Done"); + r } diff --git a/zokrates_core/src/optimizer/redefinition.rs b/zokrates_core/src/optimizer/redefinition.rs index 0d35c5eb..14e42cd7 100644 --- a/zokrates_core/src/optimizer/redefinition.rs +++ b/zokrates_core/src/optimizer/redefinition.rs @@ -36,26 +36,27 @@ // - `q == k * v if v isn't in i`: insert `v` into `i` and return `c_0` // - otherwise return `c_0` -use crate::flat_absy::flat_variable::FlatVariable; -use crate::ir::folder::Folder; -use crate::ir::LinComb; -use crate::ir::*; +use crate::flat_absy::Variable; use std::collections::{HashMap, HashSet}; +use zokrates_ast::ir::folder::Folder; +use zokrates_ast::ir::LinComb; +use zokrates_ast::ir::*; use zokrates_field::Field; +use zokrates_interpreter::Interpreter; #[derive(Debug)] pub struct RedefinitionOptimizer { /// Map of renamings for reassigned variables while processing the program. - substitution: HashMap>, + substitution: HashMap>, /// Set of variables that should not be substituted - pub ignore: HashSet, + pub ignore: HashSet, } impl RedefinitionOptimizer { pub fn init>>(p: &ProgIterator) -> Self { RedefinitionOptimizer { substitution: HashMap::new(), - ignore: vec![FlatVariable::one()] + ignore: vec![Variable::one()] .into_iter() .chain(p.arguments.iter().map(|p| p.id)) .chain(p.returns()) @@ -156,7 +157,7 @@ impl Folder for RedefinitionOptimizer { let inputs: Vec<_> = inputs .into_iter() .map(|i| { - i.map(|v| LinComb::summand(v, FlatVariable::one()).into()) + i.map(|v| LinComb::summand(v, Variable::one()).into()) .unwrap_or_else(|q| q) }) .collect(); @@ -197,7 +198,7 @@ impl Folder for RedefinitionOptimizer { #[cfg(test)] mod tests { use super::*; - use crate::flat_absy::FlatParameter; + use crate::flat_absy::Parameter; use zokrates_field::Bn128Field; #[test] @@ -207,9 +208,9 @@ mod tests { // z = y // return z - let x = FlatParameter::public(FlatVariable::new(0)); - let y = FlatVariable::new(1); - let out = FlatVariable::public(0); + let x = Parameter::public(Variable::new(0)); + let y = Variable::new(1); + let out = Variable::public(0); let p: Prog = Prog { arguments: vec![x], @@ -235,8 +236,8 @@ mod tests { // def main(x): // one = x - let one = FlatVariable::one(); - let x = FlatParameter::public(FlatVariable::new(0)); + let one = Variable::one(); + let x = Parameter::public(Variable::new(0)); let p: Prog = Prog { arguments: vec![x], @@ -264,10 +265,10 @@ mod tests { // x == x // will be eliminated as a tautology // return x - let x = FlatParameter::public(FlatVariable::new(0)); - let y = FlatVariable::new(1); - let z = FlatVariable::new(2); - let out = FlatVariable::public(0); + let x = Parameter::public(Variable::new(0)); + let y = Variable::new(1); + let z = Variable::new(2); + let out = Variable::public(0); let p: Prog = Prog { arguments: vec![x], @@ -308,13 +309,13 @@ mod tests { // def main(x): // return x, 1 - let x = FlatParameter::public(FlatVariable::new(0)); - let y = FlatVariable::new(1); - let z = FlatVariable::new(2); - let t = FlatVariable::new(3); - let w = FlatVariable::new(4); - let out_1 = FlatVariable::public(0); - let out_0 = FlatVariable::public(1); + let x = Parameter::public(Variable::new(0)); + let y = Variable::new(1); + let z = Variable::new(2); + let t = Variable::new(3); + let w = Variable::new(4); + let out_1 = Variable::public(0); + let out_0 = Variable::public(1); let p: Prog = Prog { arguments: vec![x], @@ -358,12 +359,12 @@ mod tests { // 1*x + 1*y + 2*x + 2*y + 3*x + 3*y == 6*x + 6*y // will be eliminated as a tautology // ~out_0 = 6*x + 6*y - let x = FlatParameter::public(FlatVariable::new(0)); - let y = FlatParameter::public(FlatVariable::new(1)); - let a = FlatVariable::new(2); - let b = FlatVariable::new(3); - let c = FlatVariable::new(4); - let r = FlatVariable::public(0); + let x = Parameter::public(Variable::new(0)); + let y = Parameter::public(Variable::new(1)); + let a = Variable::new(2); + let b = Variable::new(3); + let c = Variable::new(4); + let r = Variable::public(0); let p: Prog = Prog { arguments: vec![x, y], @@ -427,9 +428,9 @@ mod tests { // z = x // return - let x = FlatParameter::public(FlatVariable::new(0)); - let y = FlatParameter::public(FlatVariable::new(1)); - let z = FlatVariable::new(2); + let x = Parameter::public(Variable::new(0)); + let y = Parameter::public(Variable::new(1)); + let z = Variable::new(2); let p: Prog = Prog { arguments: vec![x, y], @@ -460,7 +461,7 @@ mod tests { // unchanged - let x = FlatParameter::public(FlatVariable::new(0)); + let x = Parameter::public(Variable::new(0)); let p: Prog = Prog { arguments: vec![x], diff --git a/zokrates_core/src/optimizer/tautology.rs b/zokrates_core/src/optimizer/tautology.rs index e1146d3a..4a9ce847 100644 --- a/zokrates_core/src/optimizer/tautology.rs +++ b/zokrates_core/src/optimizer/tautology.rs @@ -5,9 +5,9 @@ // // This makes the assumption that ~one has value 1, as should be guaranteed by the verifier -use crate::ir::folder::fold_statement; -use crate::ir::folder::Folder; -use crate::ir::*; +use zokrates_ast::ir::folder::fold_statement; +use zokrates_ast::ir::folder::Folder; +use zokrates_ast::ir::*; use zokrates_field::Field; #[derive(Default)] diff --git a/zokrates_core/src/parser/mod.rs b/zokrates_core/src/parser/mod.rs deleted file mode 100644 index 7c903042..00000000 --- a/zokrates_core/src/parser/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod tokenize; - -pub use crate::parser::tokenize::Position; diff --git a/zokrates_core/src/parser/tokenize/mod.rs b/zokrates_core/src/parser/tokenize/mod.rs deleted file mode 100644 index 12044aff..00000000 --- a/zokrates_core/src/parser/tokenize/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod position; - -pub use self::position::Position; diff --git a/zokrates_core/src/proof_system/bellman/groth16.rs b/zokrates_core/src/proof_system/bellman/groth16.rs index 43127a34..c29a8dec 100644 --- a/zokrates_core/src/proof_system/bellman/groth16.rs +++ b/zokrates_core/src/proof_system/bellman/groth16.rs @@ -8,7 +8,6 @@ use crate::proof_system::{Backend, MpcBackend, NonUniversalBackend, Proof, Setup use zokrates_field::BellmanFieldExtensions; use zokrates_field::Field; -use crate::ir::{ProgIterator, Statement, Witness}; use crate::proof_system::bellman::Bellman; use crate::proof_system::bellman::Computation; use crate::proof_system::bellman::{parse_g1, parse_g2}; @@ -17,6 +16,7 @@ use crate::proof_system::Scheme; use phase2::MPCParameters; use rand_0_4::Rng; use std::io::{Read, Write}; +use zokrates_ast::ir::{ProgIterator, Statement, Witness}; const G16_WARNING: &str = "WARNING: You are using the G16 scheme which is subject to malleability. See zokrates.github.io/toolbox/proving_schemes.html#g16-malleability for implications."; @@ -197,20 +197,18 @@ pub mod serialization { #[cfg(test)] mod tests { use zokrates_field::Bn128Field; + use zokrates_interpreter::Interpreter; use super::*; - use crate::flat_absy::{FlatParameter, FlatVariable}; - use crate::ir::{Interpreter, Prog, Statement}; + use crate::flat_absy::{Parameter, Variable}; + use zokrates_ast::ir::{Prog, Statement}; #[test] fn verify() { let program: Prog = Prog { - arguments: vec![FlatParameter::public(FlatVariable::new(0))], + arguments: vec![Parameter::public(Variable::new(0))], return_count: 1, - statements: vec![Statement::constraint( - FlatVariable::new(0), - FlatVariable::public(0), - )], + statements: vec![Statement::constraint(Variable::new(0), Variable::public(0))], }; let keypair = >::setup(program.clone()); diff --git a/zokrates_core/src/proof_system/bellman/mod.rs b/zokrates_core/src/proof_system/bellman/mod.rs index 3e3cd2fc..67c81bb5 100644 --- a/zokrates_core/src/proof_system/bellman/mod.rs +++ b/zokrates_core/src/proof_system/bellman/mod.rs @@ -1,18 +1,20 @@ pub mod groth16; -use crate::ir::{CanonicalLinComb, ProgIterator, Statement, Witness}; use bellman::groth16::Proof; use bellman::groth16::{ create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof, Parameters, }; use bellman::pairing::ff::ScalarEngine; -use bellman::{Circuit, ConstraintSystem, LinearCombination, SynthesisError, Variable}; +use bellman::{ + Circuit, ConstraintSystem, LinearCombination, SynthesisError, Variable as BellmanVariable, +}; use std::collections::BTreeMap; +use zokrates_ast::common::Variable; +use zokrates_ast::ir::{CanonicalLinComb, ProgIterator, Statement, Witness}; use zokrates_field::BellmanFieldExtensions; use zokrates_field::Field; -use crate::flat_absy::FlatVariable; use rand_0_4::ChaChaRng; pub use self::parse::*; @@ -44,7 +46,7 @@ impl>> Computation { fn bellman_combination>( l: CanonicalLinComb, cs: &mut CS, - symbols: &mut BTreeMap, + symbols: &mut BTreeMap, witness: &mut Witness, ) -> LinearCombination { l.0.into_iter() @@ -81,18 +83,17 @@ fn bellman_combination>> ProgIterator { +impl>> Computation { pub fn synthesize>( self, cs: &mut CS, - witness: Option>, ) -> Result<(), SynthesisError> { // mapping from IR variables let mut symbols = BTreeMap::new(); - let mut witness = witness.unwrap_or_else(Witness::empty); + let mut witness = self.witness.unwrap_or_else(Witness::empty); - assert!(symbols.insert(FlatVariable::one(), CS::one()).is_none()); + assert!(symbols.insert(Variable::one(), CS::one()).is_none()); symbols.extend(self.arguments.iter().enumerate().map(|(index, p)| { let wire = match p.private { @@ -246,14 +247,14 @@ mod parse { #[cfg(test)] mod tests { use super::*; - use crate::ir::Interpreter; - use crate::ir::LinComb; + use zokrates_ast::ir::LinComb; use zokrates_field::Bn128Field; + use zokrates_interpreter::Interpreter; mod prove { use super::*; - use crate::flat_absy::FlatParameter; - use crate::ir::Prog; + use crate::flat_absy::Parameter; + use zokrates_ast::ir::Prog; #[test] fn empty() { @@ -271,12 +272,9 @@ mod tests { #[test] fn identity() { let program: Prog = Prog { - arguments: vec![FlatParameter::private(FlatVariable::new(0))], + arguments: vec![Parameter::private(Variable::new(0))], return_count: 1, - statements: vec![Statement::constraint( - FlatVariable::new(0), - FlatVariable::public(0), - )], + statements: vec![Statement::constraint(Variable::new(0), Variable::public(0))], }; let interpreter = Interpreter::default(); @@ -294,12 +292,9 @@ mod tests { #[test] fn public_identity() { let program: Prog = Prog { - arguments: vec![FlatParameter::public(FlatVariable::new(0))], + arguments: vec![Parameter::public(Variable::new(0))], return_count: 1, - statements: vec![Statement::constraint( - FlatVariable::new(0), - FlatVariable::public(0), - )], + statements: vec![Statement::constraint(Variable::new(0), Variable::public(0))], }; let interpreter = Interpreter::default(); @@ -319,10 +314,7 @@ mod tests { let program: Prog = Prog { arguments: vec![], return_count: 1, - statements: vec![Statement::constraint( - FlatVariable::one(), - FlatVariable::public(0), - )], + statements: vec![Statement::constraint(Variable::one(), Variable::public(0))], }; let interpreter = Interpreter::default(); @@ -340,18 +332,18 @@ mod tests { // private variables can be unordered let program: Prog = Prog { arguments: vec![ - FlatParameter::private(FlatVariable::new(42)), - FlatParameter::public(FlatVariable::new(51)), + Parameter::private(Variable::new(42)), + Parameter::public(Variable::new(51)), ], return_count: 2, statements: vec![ Statement::constraint( - LinComb::from(FlatVariable::new(42)) + LinComb::from(FlatVariable::new(51)), - FlatVariable::public(0), + LinComb::from(Variable::new(42)) + LinComb::from(Variable::new(51)), + Variable::public(0), ), Statement::constraint( - LinComb::from(FlatVariable::one()) + LinComb::from(FlatVariable::new(42)), - FlatVariable::public(1), + LinComb::from(Variable::one()) + LinComb::from(Variable::new(42)), + Variable::public(1), ), ], }; @@ -370,11 +362,11 @@ mod tests { #[test] fn one() { let program: Prog = Prog { - arguments: vec![FlatParameter::public(FlatVariable::new(42))], + arguments: vec![Parameter::public(Variable::new(42))], return_count: 1, statements: vec![Statement::constraint( - LinComb::from(FlatVariable::new(42)) + LinComb::one(), - FlatVariable::public(0), + LinComb::from(Variable::new(42)) + LinComb::one(), + Variable::public(0), )], }; @@ -394,13 +386,13 @@ mod tests { fn with_directives() { let program: Prog = Prog { arguments: vec![ - FlatParameter::private(FlatVariable::new(42)), - FlatParameter::public(FlatVariable::new(51)), + Parameter::private(Variable::new(42)), + Parameter::public(Variable::new(51)), ], return_count: 1, statements: vec![Statement::constraint( - LinComb::from(FlatVariable::new(42)) + LinComb::from(FlatVariable::new(51)), - FlatVariable::public(0), + LinComb::from(Variable::new(42)) + LinComb::from(Variable::new(51)), + Variable::public(0), )], }; diff --git a/zokrates_core/src/proof_system/libsnark/gm17.rs b/zokrates_core/src/proof_system/libsnark/gm17.rs index 1d13d635..83915cdb 100644 --- a/zokrates_core/src/proof_system/libsnark/gm17.rs +++ b/zokrates_core/src/proof_system/libsnark/gm17.rs @@ -1,4 +1,3 @@ -use crate::ir::{ProgIterator, Statement, Witness}; use crate::proof_system::gm17::{ProofPoints, VerificationKey, GM17}; use crate::proof_system::libsnark::ffi::{c_free, Buffer, ProofResult, SetupResult}; use crate::proof_system::libsnark::{ @@ -7,6 +6,7 @@ use crate::proof_system::libsnark::{ use crate::proof_system::Scheme; use crate::proof_system::{Backend, G1Affine, G2Affine, NonUniversalBackend, Proof, SetupKeypair}; use std::io::{BufReader, BufWriter, Write}; +use zokrates_ast::ir::{ProgIterator, Statement, Witness}; use zokrates_field::{Bn128Field, Field}; extern "C" { @@ -197,7 +197,7 @@ impl NonUniversalBackend for Libsnark { mod tests { use super::*; use crate::flat_absy::{FlatParameter, FlatVariable}; - use crate::ir::{Interpreter, Prog, Statement}; + use zokrates_ast::ir::{Interpreter, Prog, Statement}; use zokrates_field::Bn128Field; #[test] diff --git a/zokrates_core/src/proof_system/libsnark/mod.rs b/zokrates_core/src/proof_system/libsnark/mod.rs index 9a4ee0cc..bc152dc4 100644 --- a/zokrates_core/src/proof_system/libsnark/mod.rs +++ b/zokrates_core/src/proof_system/libsnark/mod.rs @@ -3,9 +3,9 @@ pub mod gm17; pub mod pghr13; use crate::flat_absy::FlatVariable; -use crate::ir::{self, Statement}; use std::cmp::max; use std::collections::HashMap; +use zokrates_ast::ir::{self, Statement}; use zokrates_field::Field; pub struct Libsnark; diff --git a/zokrates_core/src/proof_system/libsnark/pghr13.rs b/zokrates_core/src/proof_system/libsnark/pghr13.rs index 9c884036..f2d26528 100644 --- a/zokrates_core/src/proof_system/libsnark/pghr13.rs +++ b/zokrates_core/src/proof_system/libsnark/pghr13.rs @@ -4,11 +4,11 @@ use crate::proof_system::libsnark::{ }; use crate::proof_system::{Backend, G1Affine, G2Affine, NonUniversalBackend, Proof, SetupKeypair}; -use crate::ir::{ProgIterator, Statement, Witness}; use crate::proof_system::libsnark::serialization::{read_g1, read_g2, write_g1, write_g2}; use crate::proof_system::pghr13::{ProofPoints, VerificationKey, PGHR13}; use crate::proof_system::Scheme; use std::io::{BufReader, BufWriter, Write}; +use zokrates_ast::ir::{ProgIterator, Statement, Witness}; use zokrates_field::Bn128Field; use zokrates_field::Field; @@ -227,7 +227,7 @@ impl NonUniversalBackend for Libsnark { mod tests { use super::*; use crate::flat_absy::{FlatParameter, FlatVariable}; - use crate::ir::{Interpreter, Prog, Statement}; + use zokrates_ast::ir::{Interpreter, Prog, Statement}; use zokrates_field::Bn128Field; #[test] diff --git a/zokrates_core/src/proof_system/mod.rs b/zokrates_core/src/proof_system/mod.rs index e2e7210f..64e30928 100644 --- a/zokrates_core/src/proof_system/mod.rs +++ b/zokrates_core/src/proof_system/mod.rs @@ -1,5 +1,3 @@ -#[cfg(feature = "ark")] -pub mod ark; #[cfg(feature = "bellman")] pub mod bellman; #[cfg(feature = "libsnark")] @@ -13,7 +11,7 @@ mod solidity; pub use self::scheme::*; pub use self::solidity::*; -use crate::ir; +use zokrates_ast::ir; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 7e3c2626..f907274b 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -15,8 +15,6 @@ use std::fmt; use std::path::PathBuf; use zokrates_field::Field; -use crate::parser::Position; - use crate::absy::types::{UnresolvedSignature, UnresolvedType, UserTypeId}; use crate::typed_absy::types::{ diff --git a/zokrates_core/src/static_analysis/branch_isolator.rs b/zokrates_core/src/static_analysis/branch_isolator.rs index 77580386..4ad54d28 100644 --- a/zokrates_core/src/static_analysis/branch_isolator.rs +++ b/zokrates_core/src/static_analysis/branch_isolator.rs @@ -3,8 +3,8 @@ // `if c then a else b fi` becomes `if c then { a } else { b } fi`, and down the line any statements resulting from trating `a` and `b` can be safely kept inside the respective blocks. -use crate::typed_absy::folder::*; use crate::typed_absy::*; +use zokrates_ast::typed::folder::*; use zokrates_field::Field; pub struct Isolator; diff --git a/zokrates_core/src/static_analysis/constant_argument_checker.rs b/zokrates_core/src/static_analysis/constant_argument_checker.rs index 42bb3b66..160eb806 100644 --- a/zokrates_core/src/static_analysis/constant_argument_checker.rs +++ b/zokrates_core/src/static_analysis/constant_argument_checker.rs @@ -1,4 +1,3 @@ -use crate::embed::FlatEmbed; use crate::typed_absy::TypedProgram; use crate::typed_absy::{ result_folder::ResultFolder, @@ -6,6 +5,7 @@ use crate::typed_absy::{ Constant, TypedExpressionListInner, Types, UBitwidth, UExpressionInner, }; use std::fmt; +use zokrates_ast::common::FlatEmbed; use zokrates_field::Field; pub struct ConstantArgumentChecker; diff --git a/zokrates_core/src/static_analysis/constant_resolver.rs b/zokrates_core/src/static_analysis/constant_resolver.rs index 546b9b56..62fe07cc 100644 --- a/zokrates_core/src/static_analysis/constant_resolver.rs +++ b/zokrates_core/src/static_analysis/constant_resolver.rs @@ -2,9 +2,9 @@ // This does *not* reduce constants to their literal value // This step cannot fail as the imports were checked during semantics -use crate::typed_absy::folder::*; use crate::typed_absy::*; use std::collections::HashMap; +use zokrates_ast::typed::folder::*; use zokrates_field::Field; // a map of the canonical constants in this program. with all imported constants reduced to their canonical value diff --git a/zokrates_core/src/static_analysis/flat_propagation.rs b/zokrates_core/src/static_analysis/flat_propagation.rs index caa58473..36d9a72e 100644 --- a/zokrates_core/src/static_analysis/flat_propagation.rs +++ b/zokrates_core/src/static_analysis/flat_propagation.rs @@ -6,26 +6,36 @@ use crate::flat_absy::*; use std::collections::HashMap; +use zokrates_ast::flat::folder::*; use zokrates_field::Field; -pub trait Propagate { - fn propagate(self) -> Self; +struct Propagator { + constants: HashMap, } -pub trait PropagateWithContext { - fn propagate(self, constants: &mut HashMap) -> Self; -} +impl Folder for Propagator { + fn fold_statement(&mut self, s: FlatStatement) -> Vec> { + match s { + FlatStatement::Definition(var, expr) => match self.fold_expression(expr) { + FlatExpression::Number(n) => { + self.constants.insert(var, n); + vec![] + } + e => vec![FlatStatement::Definition(var, e)], + }, + s => fold_statement(self, s), + } + } -impl PropagateWithContext for FlatExpression { - fn propagate(self, constants: &mut HashMap) -> FlatExpression { - match self { + fn fold_expression(&mut self, e: FlatExpression) -> FlatExpression { + match e { FlatExpression::Number(n) => FlatExpression::Number(n), - FlatExpression::Identifier(id) => match constants.get(&id) { + FlatExpression::Identifier(id) => match self.constants.get(&id) { Some(c) => FlatExpression::Number(c.clone()), None => FlatExpression::Identifier(id), }, FlatExpression::Add(box e1, box e2) => { - match (e1.propagate(constants), e2.propagate(constants)) { + match (self.fold_expression(e1), self.fold_expression(e2)) { (FlatExpression::Number(n1), FlatExpression::Number(n2)) => { FlatExpression::Number(n1 + n2) } @@ -33,7 +43,7 @@ impl PropagateWithContext for FlatExpression { } } FlatExpression::Sub(box e1, box e2) => { - match (e1.propagate(constants), e2.propagate(constants)) { + match (self.fold_expression(e1), self.fold_expression(e2)) { (FlatExpression::Number(n1), FlatExpression::Number(n2)) => { FlatExpression::Number(n1 - n2) } @@ -41,7 +51,7 @@ impl PropagateWithContext for FlatExpression { } } FlatExpression::Mult(box e1, box e2) => { - match (e1.propagate(constants), e2.propagate(constants)) { + match (self.fold_expression(e1), self.fold_expression(e2)) { (FlatExpression::Number(n1), FlatExpression::Number(n2)) => { FlatExpression::Number(n1 * n2) } @@ -52,48 +62,6 @@ impl PropagateWithContext for FlatExpression { } } -impl FlatStatement { - fn propagate(self, constants: &mut HashMap) -> Option> { - match self { - FlatStatement::Definition(var, expr) => match expr.propagate(constants) { - FlatExpression::Number(n) => { - constants.insert(var, n); - None - } - e => Some(FlatStatement::Definition(var, e)), - }, - FlatStatement::Condition(e1, e2, message) => Some(FlatStatement::Condition( - e1.propagate(constants), - e2.propagate(constants), - message, - )), - FlatStatement::Directive(d) => Some(FlatStatement::Directive(FlatDirective { - inputs: d - .inputs - .into_iter() - .map(|i| i.propagate(constants)) - .collect(), - ..d - })), - } - } -} - -impl Propagate for FlatFunction { - fn propagate(self) -> FlatFunction { - let mut constants = HashMap::new(); - - FlatFunction { - statements: self - .statements - .into_iter() - .filter_map(|s| s.propagate(&mut constants)) - .collect(), - ..self - } - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/zokrates_core/src/static_analysis/mod.rs b/zokrates_core/src/static_analysis/mod.rs index ed362863..2629f0e1 100644 --- a/zokrates_core/src/static_analysis/mod.rs +++ b/zokrates_core/src/static_analysis/mod.rs @@ -89,81 +89,82 @@ impl fmt::Display for Error { } } -impl<'ast, T: Field> TypedProgram<'ast, T> { - pub fn analyse(self, config: &CompileConfig) -> Result<(ZirProgram<'ast, T>, Abi), Error> { - // inline user-defined constants - log::debug!("Static analyser: Inline constants"); - let r = ConstantResolver::inline(self); +pub fn analyse<'ast, T: Field>( + p: TypedProgram<'ast, T>, + config: &CompileConfig, +) -> Result<(ZirProgram<'ast, T>, Abi), Error> { + // inline user-defined constants + log::debug!("Static analyser: Inline constants"); + let r = ConstantResolver::inline(p); + log::trace!("\n{}", r); + + // isolate branches + let r = if config.isolate_branches { + log::debug!("Static analyser: Isolate branches"); + let r = Isolator::isolate(r); log::trace!("\n{}", r); + r + } else { + log::debug!("Static analyser: Branch isolation skipped"); + r + }; - // isolate branches - let r = if config.isolate_branches { - log::debug!("Static analyser: Isolate branches"); - let r = Isolator::isolate(r); - log::trace!("\n{}", r); - r - } else { - log::debug!("Static analyser: Branch isolation skipped"); - r - }; + // reduce the program to a single function + log::debug!("Static analyser: Reduce program"); + let r = reduce_program(r).map_err(Error::from)?; + log::trace!("\n{}", r); - // reduce the program to a single function - log::debug!("Static analyser: Reduce program"); - let r = reduce_program(r).map_err(Error::from)?; - log::trace!("\n{}", r); + log::debug!("Static analyser: Propagate"); + let r = Propagator::propagate(r)?; + log::trace!("\n{}", r); - log::debug!("Static analyser: Propagate"); - let r = Propagator::propagate(r)?; - log::trace!("\n{}", r); + log::debug!("Static analyser: Concretize structs"); + let r = StructConcretizer::concretize(r); + log::trace!("\n{}", r); - log::debug!("Static analyser: Concretize structs"); - let r = StructConcretizer::concretize(r); - log::trace!("\n{}", r); + // generate abi + log::debug!("Static analyser: Generate abi"); + let abi = r.abi(); - // generate abi - log::debug!("Static analyser: Generate abi"); - let abi = r.abi(); + // propagate + log::debug!("Static analyser: Propagate"); + let r = Propagator::propagate(r).map_err(Error::from)?; + log::trace!("\n{}", r); - // propagate - log::debug!("Static analyser: Propagate"); - let r = Propagator::propagate(r).map_err(Error::from)?; - log::trace!("\n{}", r); + // remove assignment to variable index + log::debug!("Static analyser: Remove variable index"); + let r = VariableWriteRemover::apply(r); + log::trace!("\n{}", r); - // remove assignment to variable index - log::debug!("Static analyser: Remove variable index"); - let r = VariableWriteRemover::apply(r); - log::trace!("\n{}", r); + // detect non constant shifts and constant lt bounds + log::debug!("Static analyser: Detect non constant arguments"); + let r = ConstantArgumentChecker::check(r).map_err(Error::from)?; + log::trace!("\n{}", r); - // detect non constant shifts and constant lt bounds - log::debug!("Static analyser: Detect non constant arguments"); - let r = ConstantArgumentChecker::check(r).map_err(Error::from)?; - log::trace!("\n{}", r); + // detect out of bounds reads and writes + log::debug!("Static analyser: Detect out of bound accesses"); + let r = OutOfBoundsChecker::check(r).map_err(Error::from)?; + log::trace!("\n{}", r); - // detect out of bounds reads and writes - log::debug!("Static analyser: Detect out of bound accesses"); - let r = OutOfBoundsChecker::check(r).map_err(Error::from)?; - log::trace!("\n{}", r); + // redefine conditions + log::debug!("Static analyser: Redefine conditions"); + let r = ConditionRedefiner::redefine(r); + log::trace!("\n{}", r); - // redefine conditions - log::debug!("Static analyser: Redefine conditions"); - let r = ConditionRedefiner::redefine(r); - log::trace!("\n{}", r); + // convert to zir, removing complex types + log::debug!("Static analyser: Convert to zir"); + let zir = Flattener::flatten(r); + log::trace!("\n{}", zir); - // convert to zir, removing complex types - log::debug!("Static analyser: Convert to zir"); - let zir = Flattener::flatten(r); - log::trace!("\n{}", zir); + // apply propagation in zir + log::debug!("Static analyser: Apply propagation in zir"); + let zir = ZirPropagator::propagate(zir).map_err(Error::from)?; + log::trace!("\n{}", zir); - // apply propagation in zir - log::debug!("Static analyser: Apply propagation in zir"); - let zir = ZirPropagator::propagate(zir).map_err(Error::from)?; - log::trace!("\n{}", zir); + // optimize uint expressions + log::debug!("Static analyser: Optimize uints"); + let zir = UintOptimizer::optimize(zir); + log::trace!("\n{}", zir); - // optimize uint expressions - log::debug!("Static analyser: Optimize uints"); - let zir = UintOptimizer::optimize(zir); - log::trace!("\n{}", zir); - - Ok((zir, abi)) - } + Ok((zir, abi)) } diff --git a/zokrates_core/src/static_analysis/propagation.rs b/zokrates_core/src/static_analysis/propagation.rs index 6922d8c0..33ce5ca6 100644 --- a/zokrates_core/src/static_analysis/propagation.rs +++ b/zokrates_core/src/static_analysis/propagation.rs @@ -7,13 +7,13 @@ //! @author Thibaut Schaeffer //! @date 2018 -use crate::embed::FlatEmbed; use crate::typed_absy::result_folder::*; use crate::typed_absy::types::Type; use crate::typed_absy::*; use std::collections::HashMap; use std::convert::{TryFrom, TryInto}; use std::fmt; +use zokrates_ast::common::FlatEmbed; use zokrates_field::Field; pub type Constants<'ast, T> = HashMap, TypedExpression<'ast, T>>; diff --git a/zokrates_core/src/static_analysis/reducer/inline.rs b/zokrates_core/src/static_analysis/reducer/inline.rs index 51efdbdc..3303766f 100644 --- a/zokrates_core/src/static_analysis/reducer/inline.rs +++ b/zokrates_core/src/static_analysis/reducer/inline.rs @@ -25,7 +25,6 @@ // - The body of the function is in SSA form // - The return value(s) are assigned to internal variables -use crate::embed::FlatEmbed; use crate::static_analysis::reducer::Output; use crate::static_analysis::reducer::ShallowTransformer; use crate::static_analysis::reducer::Versions; @@ -38,6 +37,7 @@ use crate::typed_absy::{ Signature, TypedExpression, TypedFunctionSymbol, TypedFunctionSymbolDeclaration, TypedProgram, TypedStatement, Types, UExpression, UExpressionInner, Variable, }; +use zokrates_ast::common::FlatEmbed; use zokrates_field::Field; pub enum InlineError<'ast, T> { diff --git a/zokrates_core/src/static_analysis/reducer/shallow_ssa.rs b/zokrates_core/src/static_analysis/reducer/shallow_ssa.rs index 33d6d930..44ef2922 100644 --- a/zokrates_core/src/static_analysis/reducer/shallow_ssa.rs +++ b/zokrates_core/src/static_analysis/reducer/shallow_ssa.rs @@ -24,10 +24,10 @@ // endfor // return b_3 // we leave versions b_1 and b_2 to make b accessible and modifiable inside the for-loop -use crate::typed_absy::folder::*; use crate::typed_absy::types::ConcreteGenericsAssignment; use crate::typed_absy::types::Type; use crate::typed_absy::*; +use zokrates_ast::typed::folder::*; use zokrates_field::Field; diff --git a/zokrates_core/src/static_analysis/struct_concretizer.rs b/zokrates_core/src/static_analysis/struct_concretizer.rs index 71502cc1..e3d30f14 100644 --- a/zokrates_core/src/static_analysis/struct_concretizer.rs +++ b/zokrates_core/src/static_analysis/struct_concretizer.rs @@ -5,7 +5,6 @@ // for structs, `Foo { field[N] a }` is propagated to `Foo<42> { field[N] a }`. The missing step is replacing `N` by `42` // *inside* the canonical type, so that it can be concretized in the same way arrays are. -use crate::typed_absy::folder::*; use crate::typed_absy::{ types::{ ConcreteGenericsAssignment, DeclarationArrayType, DeclarationConstant, @@ -14,6 +13,7 @@ use crate::typed_absy::{ DeclarationStructType, GenericIdentifier, TypedProgram, }; use std::marker::PhantomData; +use zokrates_ast::typed::folder::*; use zokrates_field::Field; pub struct StructConcretizer<'ast, T> { diff --git a/zokrates_core/src/static_analysis/uint_optimizer.rs b/zokrates_core/src/static_analysis/uint_optimizer.rs index 7219b652..65796bd2 100644 --- a/zokrates_core/src/static_analysis/uint_optimizer.rs +++ b/zokrates_core/src/static_analysis/uint_optimizer.rs @@ -1,8 +1,8 @@ -use crate::embed::FlatEmbed; use crate::zir::folder::*; use crate::zir::*; use std::collections::HashMap; use std::ops::{BitAnd, Shl, Shr}; +use zokrates_ast::common::FlatEmbed; use zokrates_field::Field; #[derive(Default)] diff --git a/zokrates_core/src/static_analysis/unconstrained_vars.rs b/zokrates_core/src/static_analysis/unconstrained_vars.rs index 807ceae4..ad52b4d8 100644 --- a/zokrates_core/src/static_analysis/unconstrained_vars.rs +++ b/zokrates_core/src/static_analysis/unconstrained_vars.rs @@ -1,15 +1,15 @@ -use crate::flat_absy::FlatParameter; -use crate::flat_absy::FlatVariable; -use crate::ir::folder::Folder; -use crate::ir::Directive; -use crate::ir::ProgIterator; -use crate::ir::Statement; use std::collections::HashSet; +use zokrates_ast::ir::folder::Folder; +use zokrates_ast::ir::Directive; +use zokrates_ast::ir::Parameter; +use zokrates_ast::ir::ProgIterator; +use zokrates_ast::ir::Statement; +use zokrates_ast::ir::Variable; use zokrates_field::Field; #[derive(Debug)] pub struct UnconstrainedVariableDetector { - pub(self) variables: HashSet, + pub(self) variables: HashSet, } impl UnconstrainedVariableDetector { @@ -33,10 +33,10 @@ impl UnconstrainedVariableDetector { } impl Folder for UnconstrainedVariableDetector { - fn fold_argument(&mut self, p: FlatParameter) -> FlatParameter { + fn fold_argument(&mut self, p: Parameter) -> Parameter { p } - fn fold_variable(&mut self, v: FlatVariable) -> FlatVariable { + fn fold_variable(&mut self, v: Variable) -> Variable { self.variables.remove(&v); v } diff --git a/zokrates_core/src/static_analysis/variable_write_remover.rs b/zokrates_core/src/static_analysis/variable_write_remover.rs index bbd68c28..4a6040d4 100644 --- a/zokrates_core/src/static_analysis/variable_write_remover.rs +++ b/zokrates_core/src/static_analysis/variable_write_remover.rs @@ -4,10 +4,10 @@ //! @author Thibaut Schaeffer //! @date 2018 -use crate::typed_absy::folder::*; use crate::typed_absy::types::{MemberId, Type}; use crate::typed_absy::*; use std::collections::HashSet; +use zokrates_ast::typed::folder::*; use zokrates_field::Field; pub struct VariableWriteRemover; diff --git a/zokrates_core/src/static_analysis/zir_propagation.rs b/zokrates_core/src/static_analysis/zir_propagation.rs index db0d8eb1..d06ba04d 100644 --- a/zokrates_core/src/static_analysis/zir_propagation.rs +++ b/zokrates_core/src/static_analysis/zir_propagation.rs @@ -707,10 +707,8 @@ mod tests { use crate::zir::RuntimeError; use zokrates_field::Bn128Field; - impl RuntimeError { - pub fn mock() -> Self { - RuntimeError::SourceAssertion(String::default()) - } + pub fn mock() -> RuntimeError { + RuntimeError::SourceAssertion(String::default()) } #[test] @@ -727,7 +725,7 @@ mod tests { box FieldElementExpression::Number(Bn128Field::from(1)), ), ), - RuntimeError::mock(), + mock(), )]; let mut propagator = ZirPropagator::default(); @@ -747,7 +745,7 @@ mod tests { box FieldElementExpression::Identifier("x".into()), box FieldElementExpression::Identifier("y".into()), ), - RuntimeError::mock() + mock() )] ); } diff --git a/zokrates_interpreter/Cargo.toml b/zokrates_interpreter/Cargo.toml new file mode 100644 index 00000000..f18876b0 --- /dev/null +++ b/zokrates_interpreter/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "zokrates_interpreter" +version = "0.1.0" +edition = "2021" + +[dependencies] +zokrates_field = { version = "0.5", path = "../zokrates_field", default-features = false } +zokrates_ast = { version = "0.1", path = "../zokrates_ast", default-features = false } +num = { version = "0.1.36", default-features = false } +num-bigint = { version = "0.2", default-features = false } diff --git a/zokrates_core/src/ir/interpreter.rs b/zokrates_interpreter/src/lib.rs similarity index 87% rename from zokrates_core/src/ir/interpreter.rs rename to zokrates_interpreter/src/lib.rs index 67a91a02..ea6cabcb 100644 --- a/zokrates_core/src/ir/interpreter.rs +++ b/zokrates_interpreter/src/lib.rs @@ -1,10 +1,8 @@ -use crate::flat_absy::flat_variable::FlatVariable; -use crate::flat_absy::RuntimeError; -use crate::ir::{LinComb, ProgIterator, QuadComb, Statement, Witness}; -use crate::solvers::Solver; -use serde::{Deserialize, Serialize}; -use std::collections::BTreeMap; +use num::traits::ops::checked::CheckedDiv; use std::fmt; +use zokrates_ast::ir::{ + LinComb, ProgIterator, QuadComb, RuntimeError, Solver, Statement, Variable, Witness, +}; use zokrates_field::Field; pub type ExecutionResult = Result, Error>; @@ -31,8 +29,8 @@ impl Interpreter { inputs: &[T], ) -> ExecutionResult { self.check_inputs(&program, inputs)?; - let mut witness = BTreeMap::new(); - witness.insert(FlatVariable::one(), T::one()); + let mut witness = Witness::default(); + witness.insert(Variable::one(), T::one()); for (arg, value) in program.arguments.iter().zip(inputs.iter()) { witness.insert(arg.id, value.clone()); @@ -42,12 +40,12 @@ impl Interpreter { match statement { Statement::Constraint(quad, lin, error) => match lin.is_assignee(&witness) { true => { - let val = quad.evaluate(&witness).unwrap(); + let val = evaluate_quad(&witness, &quad).unwrap(); witness.insert(lin.0.get(0).unwrap().0, val); } false => { - let lhs_value = quad.evaluate(&witness).unwrap(); - let rhs_value = lin.evaluate(&witness).unwrap(); + let lhs_value = evaluate_quad(&witness, &quad).unwrap(); + let rhs_value = evaluate_lin(&witness, &lin).unwrap(); if lhs_value != rhs_value { return Err(Error::UnsatisfiedConstraint { error }); } @@ -57,7 +55,7 @@ impl Interpreter { let mut inputs: Vec<_> = d .inputs .iter() - .map(|i| i.evaluate(&witness).unwrap()) + .map(|i| evaluate_quad(&witness, i).unwrap()) .collect(); let res = match (&d.solver, self.should_try_out_of_range) { @@ -78,7 +76,7 @@ impl Interpreter { } } - Ok(Witness(witness)) + Ok(witness) } fn try_solve_with_out_of_range_bits(bit_width: usize, input: T) -> Vec { @@ -239,42 +237,30 @@ impl Interpreter { #[derive(Debug)] pub struct EvaluationError; -impl LinComb { - fn evaluate(&self, witness: &BTreeMap) -> Result { - self.0 - .iter() - .map(|(var, mult)| { - witness - .get(var) - .map(|v| v.clone() * mult) - .ok_or(EvaluationError) - }) // get each term - .collect::, _>>() // fail if any term isn't found - .map(|v| v.iter().fold(T::from(0), |acc, t| acc + t)) // return the sum - } - - fn is_assignee(&self, witness: &BTreeMap) -> bool { - self.0.len() == 1 - && self.0.get(0).unwrap().1 == T::from(1) - && !witness.contains_key(&self.0.get(0).unwrap().0) - } -} - -impl QuadComb { - pub fn evaluate(&self, witness: &BTreeMap) -> Result { - let left = self.left.evaluate(witness)?; - let right = self.right.evaluate(witness)?; - Ok(left * right) - } -} - -#[derive(PartialEq, Serialize, Deserialize, Clone)] +#[derive(PartialEq, Clone)] pub enum Error { UnsatisfiedConstraint { error: Option }, Solver, WrongInputCount { expected: usize, received: usize }, } +fn evaluate_lin(w: &Witness, l: &LinComb) -> Result { + l.0.iter() + .map(|(var, mult)| { + w.0.get(var) + .map(|v| v.clone() * mult) + .ok_or(EvaluationError) + }) // get each term + .collect::, _>>() // fail if any term isn't found + .map(|v| v.iter().fold(T::from(0), |acc, t| acc + t)) // return the sum +} + +pub fn evaluate_quad(w: &Witness, q: &QuadComb) -> Result { + let left = evaluate_lin(w, &q.left)?; + let right = evaluate_lin(w, &q.right)?; + Ok(left * right) +} + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self {