diff --git a/Cargo.lock b/Cargo.lock index ce8402a5ac..7fb1f04a75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,9 +2,9 @@ # It is not intended for manual editing. [[package]] name = "addr2line" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072" +checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423" dependencies = [ "gimli", ] @@ -23,9 +23,9 @@ checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" [[package]] name = "aho-corasick" -version = "0.7.13" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" dependencies = [ "memchr", ] @@ -56,9 +56,9 @@ checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" [[package]] name = "arrayvec" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "atty" @@ -79,14 +79,14 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" -version = "0.3.50" +version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46254cf2fdcdf1badb5934448c1bcbe046a56537b3987d96c51a7afc5d03f293" +checksum = "2baad346b2d4e94a24347adeee9c7a93f412ee94b9cc26e5b59dea23848e9f28" dependencies = [ "addr2line", - "cfg-if", + "cfg-if 1.0.0", "libc", - "miniz_oxide 0.4.1", + "miniz_oxide 0.4.3", "object", "rustc-demangle", ] @@ -137,7 +137,7 @@ checksum = "66c0bb6167449588ff70803f4127f0684f9063097eca5016f37eb52b92c2cf36" dependencies = [ "bitflags", "cexpr", - "cfg-if", + "cfg-if 0.1.10", "clang-sys", "clap", "env_logger 0.7.1", @@ -145,7 +145,7 @@ dependencies = [ "lazycell", "log", "peeking_take_while", - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", "regex", "rustc-hash", @@ -173,9 +173,9 @@ dependencies = [ [[package]] name = "blake2b_simd" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" dependencies = [ "arrayref", "arrayvec", @@ -214,9 +214,9 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31accafdb70df7871592c058eca3985b71104e15ac32f64706022c58867da931" +checksum = "473fc6b38233f9af7baa94fb5852dca389e3d95b8e21c8e3719301462c5d9faf" dependencies = [ "lazy_static", "memchr", @@ -290,9 +290,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.59" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381" +checksum = "f1770ced377336a88a67c473594ccc14eca6f4559217c34f64aac8f83d641b40" dependencies = [ "jobserver", ] @@ -313,15 +313,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] -name = "chrono" -version = "0.4.15" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942f72db697d8767c22d46a598e01f2d3b475501ea43d0db4f16d90259182d0b" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ + "libc", "num-integer", "num-traits", "serde", "time", + "winapi 0.3.9", ] [[package]] @@ -395,6 +403,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "const_fn" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab" + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -403,9 +417,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "core-foundation" -version = "0.7.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" dependencies = [ "core-foundation-sys", "libc", @@ -413,9 +427,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.7.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" +checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" [[package]] name = "cpuid-bool" @@ -425,11 +439,11 @@ checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" [[package]] name = "crc32fast" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -470,36 +484,35 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.4.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ee0cc8804d5393478d743b035099520087a5186f3b93fa58cec08fa62407b6" +checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" dependencies = [ - "cfg-if", - "crossbeam-utils", + "cfg-if 1.0.0", + "crossbeam-utils 0.8.0", ] [[package]] name = "crossbeam-deque" -version = "0.7.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" +checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" dependencies = [ + "cfg-if 1.0.0", "crossbeam-epoch", - "crossbeam-utils", - "maybe-uninit", + "crossbeam-utils 0.8.0", ] [[package]] name = "crossbeam-epoch" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +checksum = "ec0f606a85340376eef0d6d8fec399e6d4a544d648386c6645eb6d0653b27d9f" dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", + "cfg-if 1.0.0", + "const_fn", + "crossbeam-utils 0.8.0", "lazy_static", - "maybe-uninit", "memoffset", "scopeguard", ] @@ -511,7 +524,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ "autocfg", - "cfg-if", + "cfg-if 0.1.10", + "lazy_static", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec91540d98355f690a86367e566ecad2e9e579f230230eb7c21398372be73ea5" +dependencies = [ + "autocfg", + "cfg-if 1.0.0", + "const_fn", "lazy_static", ] @@ -527,9 +552,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00affe7f6ab566df61b4be3ce8cf16bc2576bca0963ceb0955e45d514bf9a279" +checksum = "fc4666154fd004af3fd6f1da2e81a96fd5a81927fe8ddb6ecc79e2aa6e138b54" dependencies = [ "bstr", "csv-core", @@ -549,9 +574,9 @@ dependencies = [ [[package]] name = "curl" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78baca05127a115136a9898e266988fc49ca7ea2c839f60fc6e1fc9df1599168" +checksum = "e268162af1a5fe89917ae25ba3b0a77c8da752bdc58e7dbb4f15b91fbd33756e" dependencies = [ "curl-sys", "libc", @@ -564,9 +589,9 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.36+curl-7.71.1" +version = "0.4.38+curl-7.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68cad94adeb0c16558429c3c34a607acc9ea58e09a7b66310aabc9788fc5d721" +checksum = "498ecfb4f59997fd40023d62a9f1e506e768b2baeb59a1d311eb9751cdcd7e3f" dependencies = [ "cc", "libc", @@ -583,9 +608,9 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.39", + "syn 1.0.48", ] [[package]] @@ -640,9 +665,9 @@ checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b" [[package]] name = "either" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56b59865bce947ac5958779cfa508f6c3b9497cc762b7e24a12d11ccde2c4f" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "encode_unicode" @@ -652,11 +677,11 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.24" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a51b8cf747471cb9499b6d59e59b0444f4c90eba8968c4e44874e92b5b64ace2" +checksum = "801bbab217d7f79c0062f4f7205b5d4427c6d1a7bd7aafdd1475f7c59d62b283" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -711,9 +736,9 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.39", + "syn 1.0.48", "synstructure", ] @@ -725,11 +750,11 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "filetime" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed85775dcc68644b5c950ac06a2b23768d3bc9390464151aaf27136998dcf9e" +checksum = "0c122a393ea57648015bf06fbd3d372378992e86b9ff5a7a497b076a28c79efe" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall", "winapi 0.3.9", @@ -741,7 +766,7 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "crc32fast", "libc", "miniz_oxide 0.3.7", @@ -768,6 +793,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "form_urlencoded" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00" +dependencies = [ + "matches", + "percent-encoding 2.1.0", +] + [[package]] name = "from-pest" version = "0.3.1" @@ -821,57 +856,57 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futures" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" +checksum = "4c7e4c2612746b0df8fed4ce0c69156021b704c9aefa360311c04e6e9e002eed" [[package]] name = "futures-channel" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5" +checksum = "4b7109687aa4e177ef6fe84553af6280ef2778bdb7783ba44c9dc3399110fe64" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399" +checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748" [[package]] name = "futures-io" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789" +checksum = "611834ce18aaa1bd13c4b374f5d653e1027cf99b6b502584ff8c9a64413b30bb" [[package]] name = "futures-sink" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc" +checksum = "f878195a49cee50e006b02b93cf7e0a95a38ac7b776b4c4d9cc1207cd20fcb3d" [[package]] name = "futures-task" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626" +checksum = "7c554eb5bf48b2426c4771ab68c6b14468b6e76cc90996f528c3338d761a4d0d" dependencies = [ "once_cell", ] [[package]] name = "futures-util" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6" +checksum = "d304cff4a7b99cfb7986f7d43fbe93d175e72e704a8860787cc95e9ffd85cbd2" dependencies = [ "futures-core", "futures-io", "futures-task", "memchr", - "pin-project", + "pin-project 1.0.1", "pin-utils", "slab", ] @@ -919,20 +954,20 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] name = "gimli" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724" +checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" [[package]] name = "glob" @@ -942,9 +977,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "h2" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53" +checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535" dependencies = [ "bytes 0.5.6", "fnv", @@ -957,6 +992,7 @@ dependencies = [ "tokio", "tokio-util", "tracing", + "tracing-futures", ] [[package]] @@ -967,18 +1003,15 @@ checksum = "d36fab90f82edc3c747f9d438e06cf0a491055896f2a279638bb5beed6c40177" [[package]] name = "hashbrown" -version = "0.8.2" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" -dependencies = [ - "autocfg", -] +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" [[package]] name = "hermit-abi" -version = "0.1.15" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9" +checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" dependencies = [ "libc", ] @@ -1016,6 +1049,12 @@ version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" +[[package]] +name = "httpdate" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" + [[package]] name = "humantime" version = "1.3.0" @@ -1033,9 +1072,9 @@ checksum = "3c1ad908cc71012b7bea4d0c53ba96a8cba9962f048fa68d143376143d863b7a" [[package]] name = "hyper" -version = "0.13.7" +version = "0.13.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e68a8dd9716185d9e64ea473ea6ef63529252e3e27623295a0378a19665d5eb" +checksum = "f6ad767baac13b44d4529fcf58ba2cd0995e36e7b435bc5b039de6f47e880dbf" dependencies = [ "bytes 0.5.6", "futures-channel", @@ -1045,10 +1084,10 @@ dependencies = [ "http", "http-body", "httparse", + "httpdate", "itoa", - "pin-project", + "pin-project 1.0.1", "socket2", - "time", "tokio", "tower-service", "tracing", @@ -1098,9 +1137,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9" +checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2" dependencies = [ "autocfg", "hashbrown", @@ -1131,18 +1170,21 @@ dependencies = [ [[package]] name = "inotify-sys" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" +checksum = "c4563555856585ab3180a5bf0b2f9f8d301a728462afffc8195b3f5394229c55" dependencies = [ "libc", ] [[package]] name = "instant" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b141fdc7836c525d4d594027d318c84161ca17aaf8113ab1f81ab93ae897485" +checksum = "cb1fc4429a33e1f80d41dc9fea4d108a88bec1de8053878898ae448a0b52f613" +dependencies = [ + "cfg-if 1.0.0", +] [[package]] name = "iovec" @@ -1194,9 +1236,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.44" +version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85a7e2c92a4804dd459b86c339278d0fe87cf93757fae222c3fa3ae75458bc73" +checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8" dependencies = [ "wasm-bindgen", ] @@ -1247,15 +1289,13 @@ name = "leo-ast" version = "1.0.4" dependencies = [ "criterion", - "from-pest", - "lazy_static", + "leo-grammar", + "leo-input", "pest", - "pest-ast", - "pest_derive", "serde", "serde_json", - "thiserror", - "tracing", + "snarkos-errors", + "snarkos-models", ] [[package]] @@ -1267,10 +1307,11 @@ dependencies = [ "leo-ast", "leo-core", "leo-gadgets", + "leo-grammar", + "leo-imports", "leo-input", "leo-package", "leo-state", - "leo-typed", "num-bigint", "pest", "rand", @@ -1292,10 +1333,10 @@ dependencies = [ [[package]] name = "leo-core" -version = "1.0.2" +version = "1.0.4" dependencies = [ + "leo-ast", "leo-gadgets", - "leo-typed", "rand", "rand_xorshift", "snarkos-curves", @@ -1319,6 +1360,32 @@ dependencies = [ "thiserror", ] +[[package]] +name = "leo-grammar" +version = "1.0.4" +dependencies = [ + "criterion", + "from-pest", + "lazy_static", + "pest", + "pest-ast", + "pest_derive", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "leo-imports" +version = "1.0.4" +dependencies = [ + "leo-ast", + "leo-grammar", + "thiserror", + "tracing", +] + [[package]] name = "leo-input" version = "1.0.4" @@ -1348,9 +1415,10 @@ dependencies = [ "env_logger 0.8.1", "from-pest", "lazy_static", + "leo-ast", "leo-compiler", - "leo-core", "leo-gadgets", + "leo-imports", "leo-input", "leo-package", "leo-state", @@ -1398,8 +1466,8 @@ dependencies = [ name = "leo-state" version = "1.0.4" dependencies = [ + "leo-ast", "leo-input", - "leo-typed", "rand", "rand_xorshift", "snarkos-algorithms", @@ -1413,25 +1481,11 @@ dependencies = [ "thiserror", ] -[[package]] -name = "leo-typed" -version = "1.0.4" -dependencies = [ - "criterion", - "leo-ast", - "leo-input", - "pest", - "serde", - "serde_json", - "snarkos-errors", - "snarkos-models", -] - [[package]] name = "libc" -version = "0.2.76" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" +checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614" [[package]] name = "libloading" @@ -1457,9 +1511,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b34178653005c1181711c333f0e5604a14a1b5115c814fd42304bdd16245e0" +checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655" dependencies = [ "cc", "libc", @@ -1482,7 +1536,7 @@ version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", ] [[package]] @@ -1491,7 +1545,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0e8460f2f2121162705187214720353c517b97bdfb3494c0b1e33d83ebe4bed" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "generator", "scoped-tls", "serde", @@ -1519,23 +1573,17 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - [[package]] name = "memchr" -version = "2.3.3" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" [[package]] name = "memoffset" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c198b026e1bbf08a937e94c6c60f9ec4a2267f5b0d2eec9c1b21b061ce2be55f" +checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" dependencies = [ "autocfg", ] @@ -1567,11 +1615,12 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d7559a8a40d0f97e1edea3220f698f78b1c5ab67532e49f68fde3910323b722" +checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" dependencies = [ "adler", + "autocfg", ] [[package]] @@ -1580,7 +1629,7 @@ version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "fuchsia-zircon", "fuchsia-zircon-sys", "iovec", @@ -1619,9 +1668,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" +checksum = "6fcc7939b5edc4e4f86b1b4a04bb1498afaaf871b1a6691838ed06fcb48d3a3f" dependencies = [ "lazy_static", "libc", @@ -1637,11 +1686,11 @@ dependencies = [ [[package]] name = "net2" -version = "0.2.34" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7" +checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "winapi 0.3.9", ] @@ -1682,9 +1731,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f3fc75e3697059fb1bc465e3d8cca6cf92f56854f201158b3f9c77d5a3cfa0" +checksum = "5e9a41747ae4633fce5adffb4d2e81ffc5e89593cb19917f8fb2cc5ff76507bf" dependencies = [ "autocfg", "num-integer", @@ -1693,9 +1742,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" dependencies = [ "autocfg", "num-traits", @@ -1703,9 +1752,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ "autocfg", ] @@ -1728,15 +1777,15 @@ checksum = "17b02fc0ff9a9e4b35b3342880f48e896ebf69f2967921fe8646bf5b7125956a" [[package]] name = "object" -version = "0.20.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5" +checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" [[package]] name = "once_cell" -version = "1.4.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad" +checksum = "f53cef67919d7d247eb9a2f128ca9e522789967ef1eb4ccd8c71a95a8aedf596" [[package]] name = "oorandom" @@ -1763,7 +1812,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d575eff3665419f9b83678ff2815858ad9d11567e082f5ac1814baba4e2bcb4" dependencies = [ "bitflags", - "cfg-if", + "cfg-if 0.1.10", "foreign-types", "lazy_static", "libc", @@ -1806,7 +1855,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "cloudabi", "instant", "libc", @@ -1873,9 +1922,9 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.39", + "syn 1.0.48", ] [[package]] @@ -1891,29 +1940,49 @@ dependencies = [ [[package]] name = "pin-project" -version = "0.4.23" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca4433fff2ae79342e497d9f8ee990d174071408f28f726d6d83af93e58e48aa" +checksum = "2ffbc8e94b38ea3d2d8ba92aea2983b503cd75d0888d75b86bb37970b5698e15" dependencies = [ - "pin-project-internal", + "pin-project-internal 0.4.27", +] + +[[package]] +name = "pin-project" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee41d838744f60d959d7074e3afb6b35c7456d0f61cad38a24e35e6553f73841" +dependencies = [ + "pin-project-internal 1.0.1", ] [[package]] name = "pin-project-internal" -version = "0.4.23" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c0e815c3ee9a031fdf5af21c10aa17c573c9c6a566328d99e3936c34e36461f" +checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.39", + "syn 1.0.48", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81a4ffa594b66bff340084d4081df649a7dc049ac8d7fc458d8e628bfbbb2f86" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.7", + "syn 1.0.48", ] [[package]] name = "pin-project-lite" -version = "0.1.7" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282adbf10f2698a7a77f8e983a74b2d18176c19a7fd32a45446139ae7b02b715" +checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b" [[package]] name = "pin-utils" @@ -1923,9 +1992,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" [[package]] name = "plotters" @@ -1941,9 +2010,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "proc-macro2" @@ -1956,9 +2025,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.19" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" dependencies = [ "unicode-xid 0.2.1", ] @@ -1993,7 +2062,7 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", ] [[package]] @@ -2048,9 +2117,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfd016f0c045ad38b5251be2c9c0ab806917f82da4d36b2a327e5166adad9270" +checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" dependencies = [ "autocfg", "crossbeam-deque", @@ -2060,13 +2129,13 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91739a34c4355b5434ce54c9086c5895604a9c278586d1f1aa95e04f66b525a0" +checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" dependencies = [ "crossbeam-channel", "crossbeam-deque", - "crossbeam-utils", + "crossbeam-utils 0.8.0", "lazy_static", "num_cpus", ] @@ -2090,9 +2159,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.3.9" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" +checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" dependencies = [ "aho-corasick", "memchr", @@ -2112,9 +2181,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.18" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" +checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" [[package]] name = "remove_dir_all" @@ -2180,14 +2249,14 @@ dependencies = [ "base64 0.12.3", "blake2b_simd", "constant_time_eq", - "crossbeam-utils", + "crossbeam-utils 0.7.2", ] [[package]] name = "rustc-demangle" -version = "0.1.16" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" [[package]] name = "rustc-hash" @@ -2261,9 +2330,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "security-framework" -version = "0.4.4" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535" +checksum = "c1759c2e3c8580017a484a7ac56d3abc5a6c1feadf88db2f3633f12ae4268c69" dependencies = [ "bitflags", "core-foundation", @@ -2274,9 +2343,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "0.4.3" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405" +checksum = "f99b9d5e26d2a71633cc4f2ebae7cc9f874044e0c351a27e17892d76dce5678b" dependencies = [ "core-foundation-sys", "libc", @@ -2340,9 +2409,9 @@ version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.39", + "syn 1.0.48", ] [[package]] @@ -2382,12 +2451,12 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1" +checksum = "6e7aab86fe2149bad8c507606bdb3f4ef5e7b2380eb92350f56122cca72a42a8" dependencies = [ "block-buffer 0.9.0", - "cfg-if", + "cfg-if 1.0.0", "cpuid-bool", "digest 0.9.0", "opaque-debug 0.3.0", @@ -2473,9 +2542,9 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f6ce35f9f73c13e5381c6938747935ca105e22717998489c3e5ddb8c13120d" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.39", + "syn 1.0.48", ] [[package]] @@ -2626,11 +2695,11 @@ dependencies = [ [[package]] name = "socket2" -version = "0.3.12" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" +checksum = "7fd8b795c389288baa5f355489c65e71fd48a02104600d15c4cfbc561e9e429d" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "redox_syscall", "winapi 0.3.9", @@ -2661,11 +2730,11 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.39" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9" +checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", "unicode-xid 0.2.1", ] @@ -2676,9 +2745,9 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.39", + "syn 1.0.48", "unicode-xid 0.2.1", ] @@ -2688,7 +2757,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "rand", "redox_syscall", @@ -2726,22 +2795,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "318234ffa22e0920fe9a40d7b8369b5f649d490980cf7aadcf1eb91594869b42" +checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cae2447b6282786c3493999f40a9be2a6ad20cb8bd268b0a0dbf5a065535c0ab" +checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.39", + "syn 1.0.48", ] [[package]] @@ -2776,9 +2845,18 @@ dependencies = [ [[package]] name = "tinyvec" -version = "0.3.4" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" +checksum = "b78a366903f506d2ad52ca8dc552102ffdd3e937ba8a227f024dc1d1eae28575" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" @@ -2843,7 +2921,7 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0987850db3733619253fe60e17cb59b82d37c7e6c0236bb81e4d6b87c879f27" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "log", "pin-project-lite", "tracing-attributes", @@ -2856,9 +2934,9 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.39", + "syn 1.0.48", ] [[package]] @@ -2870,6 +2948,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "tracing-futures" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c" +dependencies = [ + "pin-project 0.4.27", + "tracing", +] + [[package]] name = "tracing-log" version = "0.1.1" @@ -2893,9 +2981,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2810660b9d5b18895d140caba6401765749a6a162e5d0736cfc44ea50db9d79d" +checksum = "a1fa8f0c8f4c594e4fc9debc1990deab13238077271ba84dd853d54902ee3401" dependencies = [ "ansi_term 0.12.1", "chrono", @@ -2951,9 +3039,9 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977" +checksum = "b7f98e67a4d84f730d343392f9bfff7d21e3fca562b9cb7a43b768350beeddc6" dependencies = [ "tinyvec", ] @@ -2978,10 +3066,11 @@ checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "url" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" +checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e" dependencies = [ + "form_urlencoded", "idna", "matches", "percent-encoding 2.1.0", @@ -3046,11 +3135,11 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" -version = "0.2.67" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0563a9a4b071746dd5aedbc3a28c6fe9be4586fb3fbadb67c400d4f53c6b16c" +checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "serde", "serde_json", "wasm-bindgen-macro", @@ -3058,26 +3147,26 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.67" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc71e4c5efa60fb9e74160e89b93353bc24059999c0ae0fb03affc39770310b0" +checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68" dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.39", + "syn 1.0.48", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.17" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95f8d235a77f880bcef268d379810ea6c0af2eacfa90b1ad5af731776e0c4699" +checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "js-sys", "wasm-bindgen", "web-sys", @@ -3085,9 +3174,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.67" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97c57cefa5fa80e2ba15641578b44d36e7a64279bc5ed43c6dbaf329457a2ed2" +checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" dependencies = [ "quote 1.0.7", "wasm-bindgen-macro-support", @@ -3095,28 +3184,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.67" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841a6d1c35c6f596ccea1f82504a192a60378f64b3bb0261904ad8f2f5657556" +checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.39", + "syn 1.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.67" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93b162580e34310e5931c4b792560108b10fd14d64915d7fff8ff00180e70092" +checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" [[package]] name = "web-sys" -version = "0.3.44" +version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dda38f4e5ca63eda02c059d243aa25b5f35ab98451e518c51612cd0f1bd19a47" +checksum = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index 7df4182df6..f49322dc12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,25 +30,32 @@ members = [ "compiler", "core", "gadgets", + "grammar", + "imports", "input", "linter", "package", - "typed", - "state" + "state", +# "symbol-table", +# "type-inference", ] +[dependencies.leo-ast] +path = "./ast" +version = "1.0.4" + [dependencies.leo-compiler] path = "./compiler" version = "1.0.4" -[dependencies.leo-core] -path = "./core" -version = "1.0.2" - [dependencies.leo-gadgets] path = "./gadgets" version = "1.0.4" +[dependencies.leo-imports] +path = "./imports" +version = "1.0.4" + [dependencies.leo-input] path = "./input" version = "1.0.4" diff --git a/ast/Cargo.toml b/ast/Cargo.toml index c59331058e..49cc0ae71e 100644 --- a/ast/Cargo.toml +++ b/ast/Cargo.toml @@ -2,7 +2,7 @@ name = "leo-ast" version = "1.0.4" authors = [ "The Aleo Team " ] -description = "AST of the Leo programming language" +description = "Core AST of the Leo programming language" homepage = "https://aleo.org" repository = "https://github.com/AleoHQ/leo" keywords = [ @@ -22,41 +22,38 @@ name = "leo_ast" path = "src/main.rs" [[bench]] -name = "ast" -path = "benches/ast.rs" +name = "leo_ast" +path = "benches/leo_ast.rs" harness = false -[dependencies.from-pest] -version = "0.3.1" +[dependencies.leo-grammar] +path = "../grammar" +version = "1.0.4" -[dependencies.lazy_static] -version = "1.3.0" +[dependencies.leo-input] +path = "../input" +version = "1.0.4" + +[dependencies.snarkos-errors] +version = "1.1.3" +default-features = false + +[dependencies.snarkos-models] +version = "1.1.3" +default-features = false [dependencies.pest] version = "2.0" -[dependencies.pest-ast] -version = "0.3.3" - -[dependencies.pest_derive] -version = "2.0" - [dependencies.serde] version = "1.0" -features = [ "derive" ] [dependencies.serde_json] version = "1.0" -[dependencies.thiserror] -version = "1.0" - -[dependencies.tracing] -version = "0.1" - [dev-dependencies.criterion] version = "0.3" [features] default = [ ] -ci_skip = [ ] +ci_skip = [ "leo-grammar/ci_skip" ] diff --git a/typed/benches/big_circuit.leo b/ast/benches/big_circuit.leo similarity index 100% rename from typed/benches/big_circuit.leo rename to ast/benches/big_circuit.leo diff --git a/typed/benches/big_if_else.leo b/ast/benches/big_if_else.leo similarity index 100% rename from typed/benches/big_if_else.leo rename to ast/benches/big_if_else.leo diff --git a/typed/benches/big_ternary.leo b/ast/benches/big_ternary.leo similarity index 100% rename from typed/benches/big_ternary.leo rename to ast/benches/big_ternary.leo diff --git a/typed/benches/typed_ast.rs b/ast/benches/leo_ast.rs similarity index 67% rename from typed/benches/typed_ast.rs rename to ast/benches/leo_ast.rs index cee9a756d4..a6f1e8dba8 100644 --- a/typed/benches/typed_ast.rs +++ b/ast/benches/leo_ast.rs @@ -15,69 +15,69 @@ // along with the Leo library. If not, see . use leo_ast::LeoAst; -use leo_typed::LeoTypedAst; +use leo_grammar::Grammar; use criterion::{criterion_group, criterion_main, Criterion}; use std::{path::Path, time::Duration}; -fn leo_typed_ast<'ast>(ast: &LeoAst<'ast>) -> LeoTypedAst { - LeoTypedAst::new("leo_typed_tree", &ast) +fn leo_ast<'ast>(ast: &Grammar<'ast>) -> LeoAst { + LeoAst::new("leo_tree", &ast) } fn bench_big_if_else(c: &mut Criterion) { let filepath = Path::new("./big_if_else.leo").to_path_buf(); let program_string = include_str!("./big_if_else.leo"); - let ast = LeoAst::new(&filepath, program_string).unwrap(); + let ast = Grammar::new(&filepath, program_string).unwrap(); - c.bench_function("LeoTypedAst::big_if_else", |b| b.iter(|| leo_typed_ast(&ast))); + c.bench_function("LeoAst::big_if_else", |b| b.iter(|| leo_ast(&ast))); } fn bench_big_ternary(c: &mut Criterion) { let filepath = Path::new("./big_ternary.leo").to_path_buf(); let program_string = include_str!("./big_ternary.leo"); - let ast = LeoAst::new(&filepath, program_string).unwrap(); + let ast = Grammar::new(&filepath, program_string).unwrap(); - c.bench_function("LeoTypedAst::big_ternary", |b| b.iter(|| leo_typed_ast(&ast))); + c.bench_function("LeoAst::big_ternary", |b| b.iter(|| leo_ast(&ast))); } fn bench_big_circuit(c: &mut Criterion) { let filepath = Path::new("./big_circuit.leo").to_path_buf(); let program_string = include_str!("./big_circuit.leo"); - let ast = LeoAst::new(&filepath, program_string).unwrap(); + let ast = Grammar::new(&filepath, program_string).unwrap(); - c.bench_function("LeoTypedAst::big_circuit", |b| b.iter(|| leo_typed_ast(&ast))); + c.bench_function("LeoAst::big_circuit", |b| b.iter(|| leo_ast(&ast))); } fn bench_long_expr(c: &mut Criterion) { let filepath = Path::new("./long_expr.leo").to_path_buf(); let program_string = include_str!("./long_expr.leo"); - let ast = LeoAst::new(&filepath, program_string).unwrap(); + let ast = Grammar::new(&filepath, program_string).unwrap(); - c.bench_function("LeoTypedAst::long_expr", |b| b.iter(|| leo_typed_ast(&ast))); + c.bench_function("LeoAst::long_expr", |b| b.iter(|| leo_ast(&ast))); } fn bench_long_array(c: &mut Criterion) { let filepath = Path::new("./long_array.leo").to_path_buf(); let program_string = include_str!("./long_array.leo"); - let ast = LeoAst::new(&filepath, program_string).unwrap(); + let ast = Grammar::new(&filepath, program_string).unwrap(); - c.bench_function("LeoTypedAst::long_array", |b| b.iter(|| leo_typed_ast(&ast))); + c.bench_function("LeoAst::long_array", |b| b.iter(|| leo_ast(&ast))); } fn bench_many_foos(c: &mut Criterion) { let filepath = Path::new("./many_foos.leo").to_path_buf(); let program_string = include_str!("./many_foos.leo"); - let ast = LeoAst::new(&filepath, program_string).unwrap(); + let ast = Grammar::new(&filepath, program_string).unwrap(); - c.bench_function("LeoTypedAst::many_foos", |b| b.iter(|| leo_typed_ast(&ast))); + c.bench_function("LeoAst::many_foos", |b| b.iter(|| leo_ast(&ast))); } fn bench_many_assigns(c: &mut Criterion) { let filepath = Path::new("./many_assigns.leo").to_path_buf(); let program_string = include_str!("./many_assigns.leo"); - let ast = LeoAst::new(&filepath, program_string).unwrap(); + let ast = Grammar::new(&filepath, program_string).unwrap(); - c.bench_function("LeoTypedAst::many_assigns", |b| b.iter(|| leo_typed_ast(&ast))); + c.bench_function("LeoAst::many_assigns", |b| b.iter(|| leo_ast(&ast))); } criterion_group!( diff --git a/typed/benches/long_array.leo b/ast/benches/long_array.leo similarity index 100% rename from typed/benches/long_array.leo rename to ast/benches/long_array.leo diff --git a/typed/benches/long_expr.leo b/ast/benches/long_expr.leo similarity index 100% rename from typed/benches/long_expr.leo rename to ast/benches/long_expr.leo diff --git a/typed/benches/many_assigns.leo b/ast/benches/many_assigns.leo similarity index 100% rename from typed/benches/many_assigns.leo rename to ast/benches/many_assigns.leo diff --git a/typed/benches/many_foos.leo b/ast/benches/many_foos.leo similarity index 100% rename from typed/benches/many_foos.leo rename to ast/benches/many_foos.leo diff --git a/typed/src/annotation.rs b/ast/src/annotation.rs similarity index 93% rename from typed/src/annotation.rs rename to ast/src/annotation.rs index 3c1b66ee39..2a882c1fc0 100644 --- a/typed/src/annotation.rs +++ b/ast/src/annotation.rs @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{Circuit, Function, Identifier, Import, InputVariable, TestFunction}; -use leo_ast::{ +use crate::{Circuit, Function, FunctionInput, Identifier, ImportStatement, TestFunction}; +use leo_grammar::{ annotations::{Annotation, AnnotationArguments, AnnotationName}, definitions::{AnnotatedDefinition, Definition}, }; @@ -24,11 +24,11 @@ use std::collections::HashMap; pub fn load_annotation( annotated_definition: AnnotatedDefinition, - _imports: &mut Vec, + _imports: &mut Vec, _circuits: &mut HashMap, _functions: &mut HashMap, tests: &mut HashMap, - _expected: &mut Vec, + _expected: &mut Vec, ) { let ast_annotation = annotated_definition.annotation; let ast_definition = *annotated_definition.definition; diff --git a/ast/src/circuits/circuit.rs b/ast/src/circuits/circuit.rs index 26bc545e00..010f408c78 100644 --- a/ast/src/circuits/circuit.rs +++ b/ast/src/circuits/circuit.rs @@ -14,18 +14,39 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ast::Rule, circuits::CircuitMember, common::Identifier, SpanDef}; +use crate::{CircuitMember, Identifier}; +use leo_grammar::circuits::Circuit as GrammarCircuit; -use pest::Span; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; +use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::circuit))] -pub struct Circuit<'ast> { - pub identifier: Identifier<'ast>, - pub members: Vec>, - #[pest_ast(outer())] - #[serde(with = "SpanDef")] - pub span: Span<'ast>, +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct Circuit { + pub circuit_name: Identifier, + pub members: Vec, +} + +impl<'ast> From> for Circuit { + fn from(circuit: GrammarCircuit<'ast>) -> Self { + let circuit_name = Identifier::from(circuit.identifier); + let members = circuit.members.into_iter().map(CircuitMember::from).collect(); + + Self { circuit_name, members } + } +} + +impl Circuit { + fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { + writeln!(f, "circuit {} {{ ", self.circuit_name)?; + for field in self.members.iter() { + writeln!(f, " {}", field)?; + } + write!(f, "}}") + } +} + +impl fmt::Debug for Circuit { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } } diff --git a/ast/src/circuits/circuit_member.rs b/ast/src/circuits/circuit_member.rs index d3d949e99b..f8e885dd9d 100644 --- a/ast/src/circuits/circuit_member.rs +++ b/ast/src/circuits/circuit_member.rs @@ -14,17 +14,67 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ - ast::Rule, - circuits::{CircuitFunction, CircuitVariableDefinition}, +use crate::{Function, Identifier, Type}; +use leo_grammar::circuits::{ + CircuitFunction as GrammarCircuitFunction, + CircuitMember as GrammarCircuitMember, + CircuitVariableDefinition as GrammarCircuitVariableDefinition, }; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; +use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::circuit_member))] -pub enum CircuitMember<'ast> { - CircuitVariableDefinition(CircuitVariableDefinition<'ast>), - CircuitFunction(CircuitFunction<'ast>), +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum CircuitMember { + // (is_mutable, variable_name, variable_type) + CircuitVariable(bool, Identifier, Type), + // (is_static, function) + CircuitFunction(bool, Function), +} + +impl<'ast> From> for CircuitMember { + fn from(circuit_value: GrammarCircuitVariableDefinition<'ast>) -> Self { + CircuitMember::CircuitVariable( + circuit_value.mutable.is_some(), + Identifier::from(circuit_value.identifier), + Type::from(circuit_value.type_), + ) + } +} + +impl<'ast> From> for CircuitMember { + fn from(circuit_function: GrammarCircuitFunction<'ast>) -> Self { + CircuitMember::CircuitFunction( + circuit_function._static.is_some(), + Function::from(circuit_function.function), + ) + } +} + +impl<'ast> From> for CircuitMember { + fn from(object: GrammarCircuitMember<'ast>) -> Self { + match object { + GrammarCircuitMember::CircuitVariableDefinition(circuit_value) => CircuitMember::from(circuit_value), + GrammarCircuitMember::CircuitFunction(circuit_function) => CircuitMember::from(circuit_function), + } + } +} + +impl fmt::Display for CircuitMember { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + CircuitMember::CircuitVariable(ref mutable, ref identifier, ref type_) => { + if *mutable { + write!(f, "mut ")?; + } + write!(f, "{}: {}", identifier, type_) + } + CircuitMember::CircuitFunction(ref static_, ref function) => { + if *static_ { + write!(f, "static ")?; + } + write!(f, "{}", function) + } + } + } } diff --git a/ast/src/circuits/circuit_variable_definition.rs b/ast/src/circuits/circuit_variable_definition.rs index 8bd462a099..efa345f9d5 100644 --- a/ast/src/circuits/circuit_variable_definition.rs +++ b/ast/src/circuits/circuit_variable_definition.rs @@ -14,24 +14,22 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ - ast::Rule, - common::{Identifier, Mutable}, - types::Type, - SpanDef, -}; +use crate::{Expression, Identifier}; +use leo_grammar::circuits::CircuitVariable; -use pest::Span; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::circuit_variable_definition))] -pub struct CircuitVariableDefinition<'ast> { - pub mutable: Option, - pub identifier: Identifier<'ast>, - pub type_: Type<'ast>, - #[pest_ast(outer())] - #[serde(with = "SpanDef")] - pub span: Span<'ast>, +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct CircuitVariableDefinition { + pub identifier: Identifier, + pub expression: Expression, +} + +impl<'ast> From> for CircuitVariableDefinition { + fn from(member: CircuitVariable<'ast>) -> Self { + CircuitVariableDefinition { + identifier: Identifier::from(member.identifier), + expression: Expression::from(member.expression), + } + } } diff --git a/ast/src/circuits/mod.rs b/ast/src/circuits/mod.rs index 768a36fd7e..e25aaff89e 100644 --- a/ast/src/circuits/mod.rs +++ b/ast/src/circuits/mod.rs @@ -17,14 +17,8 @@ pub mod circuit; pub use circuit::*; -pub mod circuit_variable; -pub use circuit_variable::*; - pub mod circuit_variable_definition; pub use circuit_variable_definition::*; -pub mod circuit_function; -pub use circuit_function::*; - pub mod circuit_member; pub use circuit_member::*; diff --git a/ast/src/common/array_dimensions.rs b/ast/src/common/array_dimensions.rs new file mode 100644 index 0000000000..b2bd90e124 --- /dev/null +++ b/ast/src/common/array_dimensions.rs @@ -0,0 +1,168 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{PositiveNumber, Span}; +use leo_grammar::types::ArrayDimensions as GrammarArrayDimensions; +use leo_input::types::ArrayDimensions as InputArrayDimensions; + +use serde::{Deserialize, Serialize}; +use std::{ + fmt, + hash::{Hash, Hasher}, +}; + +/// A vector of positive numbers that represent array dimensions. +/// Can be used in an array [`Type`] or an array initializer [`Expression`]. +#[derive(Debug, Default, Clone, Serialize, Deserialize)] +pub struct ArrayDimensions(pub Vec); + +impl ArrayDimensions { + /// + /// Creates a new `PositiveNumber` from the given `usize` and `Span`. + /// Appends the new `PositiveNumber` to the array dimensions. + /// + pub fn push_usize(&mut self, number: usize, span: Span) { + let positive_number = PositiveNumber { + value: number.to_string(), + span, + }; + + self.0.push(positive_number) + } + + /// + /// Appends a vector of array dimensions to the self array dimensions. + /// + pub fn append(&mut self, other: &mut ArrayDimensions) { + self.0.append(&mut other.0) + } + + /// + /// Returns the array dimensions as strings. + /// + pub fn to_strings(&self) -> Vec { + self.0.iter().map(|number| number.to_string()).collect() + } + + /// + /// Returns `true` if the all array dimensions have been removed. + /// + /// This method is called after repeated calls to `remove_first`. + /// + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// + /// Returns `true` if there is an array dimension equal to zero. + /// + pub fn is_zero(&self) -> bool { + self.0.iter().find(|number| number.is_zero()).is_some() + } + + /// + /// Returns the first dimension of the array. + /// + pub fn first(&self) -> Option<&PositiveNumber> { + self.0.first() + } + + /// + /// Attempts to remove the first dimension from the array. + /// + /// If the first dimension exists, then remove and return `Some(PositiveNumber)`. + /// If the first dimension does not exist, then return `None`. + /// + pub fn remove_first(&mut self) -> Option { + // If there are no dimensions in the array, then return None. + self.0.first()?; + + // Remove the first dimension. + let removed = self.0.remove(0); + + // Return the first dimension. + Some(removed) + } + + /// + /// Attempts to remove the last dimension from the array. + /// + /// If the last dimension exists, then remove and return `Some(PositiveNumber)`. + /// If the last dimension does not exist, then return `None`. + /// + pub fn remove_last(&mut self) -> Option { + self.0.pop() + } +} + +/// Create a new [`ArrayDimensions`] from a [`GrammarArrayDimensions`] in a Leo program file. +impl<'ast> From> for ArrayDimensions { + fn from(dimensions: GrammarArrayDimensions<'ast>) -> Self { + Self(match dimensions { + GrammarArrayDimensions::Single(single) => vec![PositiveNumber::from(single.number)], + GrammarArrayDimensions::Multiple(multiple) => { + multiple.numbers.into_iter().map(PositiveNumber::from).collect() + } + }) + } +} + +/// Create a new [`ArrayDimensions`] from a [`InputArrayDimensions`] in a Leo program file. +impl<'ast> From> for ArrayDimensions { + fn from(dimensions: InputArrayDimensions<'ast>) -> Self { + Self(match dimensions { + InputArrayDimensions::Single(single) => vec![PositiveNumber::from(single.number)], + InputArrayDimensions::Multiple(multiple) => { + multiple.numbers.into_iter().map(PositiveNumber::from).collect() + } + }) + } +} + +impl fmt::Display for ArrayDimensions { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.0.len() == 1 { + // Write dimensions without parenthesis. + write!(f, "{}", self.0[0]) + } else { + // Write dimensions with parenthesis. + let dimensions = self.0.iter().map(|x| x.to_string()).collect::>().join(", "); + + write!(f, "({})", dimensions) + } + } +} + +/// Compares two array dimensions and ignores `Span`s. +impl PartialEq for ArrayDimensions { + fn eq(&self, other: &Self) -> bool { + // If the number of dimensions differs return false. + if self.0.len() != other.0.len() { + return false; + } + + // Compare all dimensions and ignore `Span`s. + self.0.eq(&other.0) + } +} + +impl Eq for ArrayDimensions {} + +impl Hash for ArrayDimensions { + fn hash(&self, state: &mut H) { + self.0.hash(state) + } +} diff --git a/ast/src/common/assignee.rs b/ast/src/common/assignee.rs index 6136b05440..399af914c8 100644 --- a/ast/src/common/assignee.rs +++ b/ast/src/common/assignee.rs @@ -14,32 +14,72 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{access::AssigneeAccess, ast::Rule, common::SelfKeywordOrIdentifier, SpanDef}; +use crate::{Identifier, PositiveNumber, RangeOrExpression, Span}; +use leo_grammar::{access::AssigneeAccess as GrammarAssigneeAccess, common::Assignee as GrammarAssignee}; -use pest::Span; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::assignee))] -pub struct Assignee<'ast> { - pub name: SelfKeywordOrIdentifier<'ast>, - pub accesses: Vec>, - #[pest_ast(outer())] - #[serde(with = "SpanDef")] - pub span: Span<'ast>, +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum AssigneeAccess { + Array(RangeOrExpression), + Tuple(PositiveNumber, Span), + Member(Identifier), } -impl<'ast> fmt::Display for Assignee<'ast> { +impl<'ast> From> for AssigneeAccess { + fn from(access: GrammarAssigneeAccess<'ast>) -> Self { + match access { + GrammarAssigneeAccess::Array(array) => AssigneeAccess::Array(RangeOrExpression::from(array.expression)), + GrammarAssigneeAccess::Tuple(tuple) => { + AssigneeAccess::Tuple(PositiveNumber::from(tuple.number), Span::from(tuple.span)) + } + GrammarAssigneeAccess::Member(member) => AssigneeAccess::Member(Identifier::from(member.identifier)), + } + } +} + +/// Definition assignee: v, arr[0..2], Point p.x +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct Assignee { + pub identifier: Identifier, + pub accesses: Vec, + pub span: Span, +} + +impl Assignee { + /// Returns the name of the variable being assigned to + pub fn identifier(&self) -> &Identifier { + &self.identifier + } +} + +impl<'ast> From> for Assignee { + fn from(assignee: GrammarAssignee<'ast>) -> Self { + Assignee { + identifier: Identifier::from(assignee.name), + accesses: assignee + .accesses + .into_iter() + .map(AssigneeAccess::from) + .collect::>(), + span: Span::from(assignee.span), + } + } +} + +impl fmt::Display for Assignee { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.name)?; - for (i, access) in self.accesses.iter().enumerate() { - write!(f, "{}", access)?; - if i < self.accesses.len() - 1 { - write!(f, ", ")?; + write!(f, "{}", self.identifier)?; + + for access in &self.accesses { + match access { + AssigneeAccess::Array(expression) => write!(f, "[{}]", expression)?, + AssigneeAccess::Tuple(index, _span) => write!(f, ".{}", index)?, + AssigneeAccess::Member(member) => write!(f, ".{}", member)?, } } + write!(f, "") } } diff --git a/ast/src/common/declare.rs b/ast/src/common/declare.rs index dabc1bbfdb..399604831a 100644 --- a/ast/src/common/declare.rs +++ b/ast/src/common/declare.rs @@ -14,22 +14,31 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::ast::Rule; +use leo_grammar::common::Declare as GrammarDeclare; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; +use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::declare))] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum Declare { - Const(Const), - Let(Let), + Const, + Let, } -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::const_))] -pub struct Const {} +impl<'ast> From for Declare { + fn from(declare: GrammarDeclare) -> Self { + match declare { + GrammarDeclare::Const(_) => Declare::Const, + GrammarDeclare::Let(_) => Declare::Let, + } + } +} -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::let_))] -pub struct Let {} +impl fmt::Display for Declare { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Declare::Const => write!(f, "const"), + Declare::Let => write!(f, "let"), + } + } +} diff --git a/ast/src/common/identifier.rs b/ast/src/common/identifier.rs index e349a3b259..e6f3f4baf2 100644 --- a/ast/src/common/identifier.rs +++ b/ast/src/common/identifier.rs @@ -14,28 +14,236 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ - ast::{span_into_string, Rule}, - SpanDef, +use crate::Span; +use leo_grammar::{ + annotations::AnnotationArgument, + common::{Identifier as GrammarIdentifier, KeywordOrIdentifier, SelfKeyword, SelfKeywordOrIdentifier}, + expressions::CircuitName, + functions::InputKeyword, + imports::PackageName as GrammarPackageName, + types::SelfType, +}; +use leo_input::common::Identifier as InputIdentifier; + +use serde::{ + de::{self, Visitor}, + Deserialize, + Deserializer, + Serialize, + Serializer, +}; +use std::{ + collections::BTreeMap, + fmt, + hash::{Hash, Hasher}, }; -use pest::Span; -use pest_ast::FromPest; -use serde::Serialize; -use std::fmt; - -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::identifier))] -pub struct Identifier<'ast> { - #[pest_ast(outer(with(span_into_string)))] - pub value: String, - #[pest_ast(outer())] - #[serde(with = "SpanDef")] - pub span: Span<'ast>, +/// An identifier in the constrained program. +/// +/// Attention - When adding or removing fields from this struct, +/// please remember to update it's Serialize and Deserialize implementation +/// to reflect the new struct instantiation. +#[derive(Clone)] +pub struct Identifier { + pub name: String, + pub span: Span, } -impl<'ast> fmt::Display for Identifier<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.value) +impl Identifier { + pub fn new(name: String) -> Self { + Self { + name, + span: Span::default(), + } + } + + pub fn new_with_span(name: &str, span: &Span) -> Self { + Self { + name: name.to_owned(), + span: span.to_owned(), + } + } + + pub fn is_self_type(&self) -> bool { + self.name == "Self" + } + + pub fn is_self(&self) -> bool { + self.is_self_type() || self.name == "self" + } +} + +impl<'ast> From> for Identifier { + fn from(identifier: GrammarIdentifier<'ast>) -> Self { + Self { + name: identifier.value, + span: Span::from(identifier.span), + } + } +} + +impl<'ast> From> for Identifier { + fn from(name: GrammarPackageName<'ast>) -> Self { + Self { + name: name.value, + span: Span::from(name.span), + } + } +} + +impl<'ast> From> for Identifier { + fn from(identifier: InputIdentifier<'ast>) -> Self { + Self { + name: identifier.value, + span: Span::from(identifier.span), + } + } +} + +impl<'ast> From> for Identifier { + fn from(argument: AnnotationArgument<'ast>) -> Self { + Self { + name: argument.value, + span: Span::from(argument.span), + } + } +} + +impl<'ast> From> for Identifier { + fn from(name: KeywordOrIdentifier<'ast>) -> Self { + match name { + KeywordOrIdentifier::SelfKeywordOrIdentifier(keyword) => Identifier::from(keyword), + KeywordOrIdentifier::SelfType(self_type) => Identifier::from(self_type), + KeywordOrIdentifier::Input(keyword) => Identifier::from(keyword), + } + } +} + +impl<'ast> From> for Identifier { + fn from(name: SelfKeywordOrIdentifier<'ast>) -> Self { + match name { + SelfKeywordOrIdentifier::Identifier(identifier) => Identifier::from(identifier), + SelfKeywordOrIdentifier::SelfKeyword(keyword) => Identifier::from(keyword), + } + } +} + +impl<'ast> From> for Identifier { + fn from(self_: SelfKeyword<'ast>) -> Self { + Self { + name: self_.keyword, + span: Span::from(self_.span), + } + } +} + +impl<'ast> From> for Identifier { + fn from(input: InputKeyword<'ast>) -> Self { + Self { + name: input.keyword, + span: Span::from(input.span), + } + } +} + +impl<'ast> From> for Identifier { + fn from(name: CircuitName<'ast>) -> Self { + match name { + CircuitName::SelfType(self_type) => Identifier::from(self_type), + CircuitName::Identifier(identifier) => Identifier::from(identifier), + } + } +} + +impl<'ast> From> for Identifier { + fn from(self_type: SelfType<'ast>) -> Self { + Self { + name: self_type.keyword, + span: Span::from(self_type.span), + } + } +} + +impl fmt::Display for Identifier { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.name) + } +} +impl fmt::Debug for Identifier { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.name) + } +} + +impl PartialEq for Identifier { + fn eq(&self, other: &Self) -> bool { + self.name == other.name + } +} + +impl Eq for Identifier {} + +impl Hash for Identifier { + fn hash(&self, state: &mut H) { + self.name.hash(state); + self.span.hash(state); + } +} + +impl Serialize for Identifier { + fn serialize(&self, serializer: S) -> Result { + // Converts an element that implements Serialize into a string. + fn to_json_string(element: &E) -> Result { + serde_json::to_string(&element).map_err(|e| Error::custom(e.to_string())) + } + + // Load the struct elements into a BTreeMap (to preserve serialized ordering of keys). + let mut key: BTreeMap = BTreeMap::new(); + key.insert("name".to_string(), self.name.clone()); + key.insert("span".to_string(), to_json_string(&self.span)?); + + // Convert the serialized object into a string for use as a key. + serializer.serialize_str(&to_json_string(&key)?) + } +} + +impl<'de> Deserialize<'de> for Identifier { + fn deserialize>(deserializer: D) -> Result { + struct IdentifierVisitor; + + impl<'de> Visitor<'de> for IdentifierVisitor { + type Value = Identifier; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a string encoding the ast Identifier struct") + } + + /// Implementation for recovering a string that serializes Identifier. + fn visit_str(self, value: &str) -> Result { + // Converts a serialized string into an element that implements Deserialize. + fn to_json_string<'a, D: Deserialize<'a>, Error: serde::de::Error>( + serialized: &'a str, + ) -> Result { + serde_json::from_str::<'a>(serialized).map_err(|e| Error::custom(e.to_string())) + } + + // Convert the serialized string into a BTreeMap to recover Identifier. + let key: BTreeMap = to_json_string(value)?; + + let name = match key.get("name") { + Some(name) => name.clone(), + None => return Err(E::custom("missing 'name' in serialized Identifier struct")), + }; + + let span: Span = match key.get("span") { + Some(span) => to_json_string(span)?, + None => return Err(E::custom("missing 'span' in serialized Identifier struct")), + }; + + Ok(Identifier { name, span }) + } + } + + deserializer.deserialize_str(IdentifierVisitor) } } diff --git a/ast/src/common/mod.rs b/ast/src/common/mod.rs index 119287f5cc..382d82142c 100644 --- a/ast/src/common/mod.rs +++ b/ast/src/common/mod.rs @@ -14,48 +14,30 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . +pub mod array_dimensions; +pub use array_dimensions::*; + pub mod assignee; pub use assignee::*; pub mod declare; pub use declare::*; -pub mod eoi; -pub use eoi::*; - pub mod identifier; pub use identifier::*; -pub mod keyword_or_identifier; -pub use keyword_or_identifier::*; - -pub mod line_end; -pub use line_end::*; - -pub mod mutable; -pub use mutable::*; - -pub mod range; -pub use range::*; +pub mod positive_number; +pub use positive_number::*; pub mod range_or_expression; pub use range_or_expression::*; -pub mod self_keyword; -pub use self_keyword::*; - -pub mod self_keyword_or_identifier; -pub use self_keyword_or_identifier::*; - -pub mod spread; -pub use spread::*; +pub mod span; +pub use span::*; pub mod spread_or_expression; pub use spread_or_expression::*; -pub mod static_; -pub use static_::*; - pub mod variables; pub use variables::*; diff --git a/ast/src/common/positive_number.rs b/ast/src/common/positive_number.rs new file mode 100644 index 0000000000..d53e8d013f --- /dev/null +++ b/ast/src/common/positive_number.rs @@ -0,0 +1,82 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::Span; +use leo_grammar::values::PositiveNumber as GrammarPositiveNumber; +use leo_input::values::PositiveNumber as InputPositiveNumber; + +use serde::{Deserialize, Serialize}; +use std::{ + fmt, + hash::{Hash, Hasher}, +}; + +/// A number string guaranteed to be positive by the pest grammar. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct PositiveNumber { + pub value: String, + pub span: Span, +} + +impl PositiveNumber { + /// + /// Returns `true` if this number is zero. + /// + pub fn is_zero(&self) -> bool { + self.value.eq("0") + } +} + +/// Create a new [`PositiveNumber`] from a [`GrammarPositiveNumber`] in a Leo program file. +impl<'ast> From> for PositiveNumber { + fn from(array: GrammarPositiveNumber<'ast>) -> Self { + Self { + value: array.value, + span: Span::from(array.span), + } + } +} + +/// Create a new [`PositiveNumber`] from an [`InputPositiveNumber`] in a Leo input file. +impl<'ast> From> for PositiveNumber { + fn from(array: InputPositiveNumber<'ast>) -> Self { + Self { + value: array.value, + span: Span::from(array.span), + } + } +} + +impl fmt::Display for PositiveNumber { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.value) + } +} + +/// Compares two positive numbers and ignores `Span`s. +impl PartialEq for PositiveNumber { + fn eq(&self, other: &Self) -> bool { + self.value.eq(&other.value) + } +} + +impl Eq for PositiveNumber {} + +impl Hash for PositiveNumber { + fn hash(&self, state: &mut H) { + self.value.hash(state) + } +} diff --git a/ast/src/common/range_or_expression.rs b/ast/src/common/range_or_expression.rs index 5a13b3e4cc..23f04e0422 100644 --- a/ast/src/common/range_or_expression.rs +++ b/ast/src/common/range_or_expression.rs @@ -14,37 +14,42 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ast::Rule, common::Range, expressions::Expression}; +use crate::Expression; +use leo_grammar::common::RangeOrExpression as GrammarRangeOrExpression; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::range_or_expression))] -pub enum RangeOrExpression<'ast> { - Range(Range<'ast>), - Expression(Expression<'ast>), +/// Range or expression enum +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum RangeOrExpression { + Range(Option, Option), + Expression(Expression), } -impl<'ast> fmt::Display for RangeOrExpression<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - RangeOrExpression::Expression(ref expression) => write!(f, "{}", expression), - RangeOrExpression::Range(ref range) => write!( - f, - "{}..{}", - range - .from - .as_ref() - .map(|v| v.to_string()) - .unwrap_or_else(|| "".to_string()), - range - .to - .as_ref() - .map(|v| v.to_string()) - .unwrap_or_else(|| "".to_string()), - ), +impl<'ast> From> for RangeOrExpression { + fn from(range_or_expression: GrammarRangeOrExpression<'ast>) -> Self { + match range_or_expression { + GrammarRangeOrExpression::Range(range) => { + RangeOrExpression::Range(range.from.map(Expression::from), range.to.map(Expression::from)) + } + GrammarRangeOrExpression::Expression(expression) => { + RangeOrExpression::Expression(Expression::from(expression)) + } + } + } +} + +impl fmt::Display for RangeOrExpression { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + RangeOrExpression::Range(ref from, ref to) => write!( + f, + "{}..{}", + from.as_ref().map(|e| e.to_string()).unwrap_or_default(), + to.as_ref().map(|e| e.to_string()).unwrap_or_default() + ), + RangeOrExpression::Expression(ref e) => write!(f, "{}", e), } } } diff --git a/typed/src/common/span.rs b/ast/src/common/span.rs similarity index 90% rename from typed/src/common/span.rs rename to ast/src/common/span.rs index 5867b7bb8d..db4bc3f436 100644 --- a/typed/src/common/span.rs +++ b/ast/src/common/span.rs @@ -14,11 +14,11 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use pest::Span as AstSpan; +use pest::Span as GrammarSpan; use serde::{Deserialize, Serialize}; use std::hash::{Hash, Hasher}; -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct Span { /// text of input string pub text: String, @@ -46,8 +46,8 @@ impl Hash for Span { } } -impl<'ast> From> for Span { - fn from(span: AstSpan<'ast>) -> Self { +impl<'ast> From> for Span { + fn from(span: GrammarSpan<'ast>) -> Self { let mut text = " ".to_string(); let line_col = span.start_pos().line_col(); let end = span.end_pos().line_col().1; diff --git a/ast/src/common/spread_or_expression.rs b/ast/src/common/spread_or_expression.rs index 3dfcedb7d3..1353be71bb 100644 --- a/ast/src/common/spread_or_expression.rs +++ b/ast/src/common/spread_or_expression.rs @@ -14,23 +14,45 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ast::Rule, common::Spread, expressions::Expression}; +use crate::Expression; +use leo_grammar::{ + common::SpreadOrExpression as GrammarSpreadOrExpression, + expressions::Expression as GrammarExpression, +}; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::spread_or_expression))] -pub enum SpreadOrExpression<'ast> { - Spread(Spread<'ast>), - Expression(Expression<'ast>), +/// Spread or expression +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum SpreadOrExpression { + Spread(Expression), + Expression(Expression), } -impl<'ast> fmt::Display for SpreadOrExpression<'ast> { +impl<'ast> From> for SpreadOrExpression { + fn from(s_or_e: GrammarSpreadOrExpression<'ast>) -> Self { + match s_or_e { + GrammarSpreadOrExpression::Spread(spread) => { + SpreadOrExpression::Spread(Expression::from(spread.expression)) + } + GrammarSpreadOrExpression::Expression(expression) => { + SpreadOrExpression::Expression(Expression::from(expression)) + } + } + } +} + +impl<'ast> From> for SpreadOrExpression { + fn from(expression: GrammarExpression<'ast>) -> Self { + SpreadOrExpression::Expression(Expression::from(expression)) + } +} + +impl fmt::Display for SpreadOrExpression { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - SpreadOrExpression::Spread(ref spread) => write!(f, "{}", spread), + SpreadOrExpression::Spread(ref spread) => write!(f, "...{}", spread), SpreadOrExpression::Expression(ref expression) => write!(f, "{}", expression), } } diff --git a/ast/src/common/variable_name.rs b/ast/src/common/variable_name.rs index 76197bb0ed..134c4748d1 100644 --- a/ast/src/common/variable_name.rs +++ b/ast/src/common/variable_name.rs @@ -14,30 +14,32 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ - ast::Rule, - common::{Identifier, Mutable}, - SpanDef, -}; +use crate::common::{Identifier, Span}; +use leo_grammar::common::VariableName as GrammarVariableName; -use pest::Span; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::variable_name))] -pub struct VariableName<'ast> { - pub mutable: Option, - pub identifier: Identifier<'ast>, - #[pest_ast(outer())] - #[serde(with = "SpanDef")] - pub span: Span<'ast>, +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VariableName { + pub mutable: bool, + pub identifier: Identifier, + pub span: Span, } -impl<'ast> fmt::Display for VariableName<'ast> { +impl<'ast> From> for VariableName { + fn from(name: GrammarVariableName<'ast>) -> Self { + Self { + mutable: name.mutable.is_some(), + identifier: Identifier::from(name.identifier), + span: Span::from(name.span), + } + } +} + +impl fmt::Display for VariableName { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if let Some(ref _mutable) = self.mutable { + if self.mutable { write!(f, "mut ")?; } diff --git a/ast/src/common/variables.rs b/ast/src/common/variables.rs index 9d63803a93..49999efee2 100644 --- a/ast/src/common/variables.rs +++ b/ast/src/common/variables.rs @@ -14,24 +14,30 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ast::Rule, common::VariableName, types::Type, SpanDef}; +use crate::{Type, VariableName}; +use leo_grammar::common::Variables as GrammarVariables; -use pest::Span; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::variables))] -pub struct Variables<'ast> { - pub names: Vec>, - pub type_: Option>, - #[pest_ast(outer())] - #[serde(with = "SpanDef")] - pub span: Span<'ast>, +/// A variable that is assigned to a value in the constrained program +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct Variables { + pub names: Vec, + pub type_: Option, } -impl<'ast> fmt::Display for Variables<'ast> { +impl<'ast> From> for Variables { + fn from(variables: GrammarVariables<'ast>) -> Self { + let names = variables.names.into_iter().map(VariableName::from).collect::>(); + + let type_ = variables.type_.map(Type::from); + + Self { names, type_ } + } +} + +impl fmt::Display for Variables { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.names.len() == 1 { // mut a diff --git a/ast/src/console/console_function.rs b/ast/src/console/console_function.rs index 0b48af1a43..c9e3356c31 100644 --- a/ast/src/console/console_function.rs +++ b/ast/src/console/console_function.rs @@ -14,31 +14,68 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ - ast::Rule, - console::{ConsoleAssert, ConsoleDebug, ConsoleError, ConsoleLog}, +use crate::{Expression, FormattedString}; +use leo_grammar::console::{ + ConsoleAssert as GrammarConsoleAssert, + ConsoleDebug as GrammarConsoleDebug, + ConsoleError as GrammarConsoleError, + ConsoleFunction as GrammarConsoleFunction, + ConsoleLog as GrammarConsoleLog, }; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::console_function))] -pub enum ConsoleFunction<'ast> { - Assert(ConsoleAssert<'ast>), - Debug(ConsoleDebug<'ast>), - Error(ConsoleError<'ast>), - Log(ConsoleLog<'ast>), +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum ConsoleFunction { + Assert(Expression), + Debug(FormattedString), + Error(FormattedString), + Log(FormattedString), } -impl<'ast> fmt::Display for ConsoleFunction<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - ConsoleFunction::Assert(assert) => write!(f, "{}", assert), - ConsoleFunction::Debug(debug) => write!(f, "{}", debug), - ConsoleFunction::Error(error) => write!(f, "{}", error), - ConsoleFunction::Log(log) => write!(f, "{}", log), +impl<'ast> From> for ConsoleFunction { + fn from(console_function: GrammarConsoleFunction<'ast>) -> Self { + match console_function { + GrammarConsoleFunction::Assert(assert) => ConsoleFunction::from(assert), + GrammarConsoleFunction::Debug(debug) => ConsoleFunction::from(debug), + GrammarConsoleFunction::Error(error) => ConsoleFunction::from(error), + GrammarConsoleFunction::Log(log) => ConsoleFunction::from(log), + } + } +} + +impl<'ast> From> for ConsoleFunction { + fn from(assert: GrammarConsoleAssert<'ast>) -> Self { + ConsoleFunction::Assert(Expression::from(assert.expression)) + } +} + +impl<'ast> From> for ConsoleFunction { + fn from(debug: GrammarConsoleDebug<'ast>) -> Self { + ConsoleFunction::Debug(FormattedString::from(debug.string)) + } +} + +impl<'ast> From> for ConsoleFunction { + fn from(error: GrammarConsoleError<'ast>) -> Self { + ConsoleFunction::Error(FormattedString::from(error.string)) + } +} + +impl<'ast> From> for ConsoleFunction { + fn from(log: GrammarConsoleLog<'ast>) -> Self { + ConsoleFunction::Log(FormattedString::from(log.string)) + } +} + +impl fmt::Display for ConsoleFunction { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + ConsoleFunction::Assert(assert) => write!(f, "assert({})", assert), + ConsoleFunction::Debug(debug) => write!(f, "debug({})", debug), + ConsoleFunction::Error(error) => write!(f, "error{})", error), + ConsoleFunction::Log(log) => write!(f, "log({})", log), } } } diff --git a/ast/src/console/console_function_call.rs b/ast/src/console/console_function_call.rs index 2c14af2d76..7ec71b9ba6 100644 --- a/ast/src/console/console_function_call.rs +++ b/ast/src/console/console_function_call.rs @@ -14,30 +14,34 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ - ast::Rule, - common::LineEnd, - console::{ConsoleFunction, ConsoleKeyword}, - SpanDef, -}; +use crate::{ConsoleFunction, Span}; +use leo_grammar::console::ConsoleFunctionCall as GrammarConsoleFunctionCall; -use pest::Span; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::console_function_call))] -pub struct ConsoleFunctionCall<'ast> { - pub keyword: ConsoleKeyword<'ast>, - pub function: ConsoleFunction<'ast>, - pub line_end: LineEnd, - #[pest_ast(outer())] - #[serde(with = "SpanDef")] - pub span: Span<'ast>, +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct ConsoleFunctionCall { + pub function: ConsoleFunction, + pub span: Span, } -impl<'ast> fmt::Display for ConsoleFunctionCall<'ast> { +impl<'ast> From> for ConsoleFunctionCall { + fn from(console: GrammarConsoleFunctionCall<'ast>) -> Self { + ConsoleFunctionCall { + function: ConsoleFunction::from(console.function), + span: Span::from(console.span), + } + } +} + +impl fmt::Display for ConsoleFunctionCall { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "console.{};", self.function) + } +} + +impl fmt::Debug for ConsoleFunctionCall { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "console.{};", self.function) } diff --git a/ast/src/console/formatted_container.rs b/ast/src/console/formatted_container.rs index e6234dc723..0781bf3280 100644 --- a/ast/src/console/formatted_container.rs +++ b/ast/src/console/formatted_container.rs @@ -14,22 +14,26 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ast::Rule, SpanDef}; +use crate::Span; +use leo_grammar::console::FormattedContainer as GrammarFormattedContainer; -use pest::Span; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::formatted_container))] -pub struct FormattedContainer<'ast> { - #[pest_ast(outer())] - #[serde(with = "SpanDef")] - pub span: Span<'ast>, +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct FormattedContainer { + pub span: Span, } -impl<'ast> fmt::Display for FormattedContainer<'ast> { +impl<'ast> From> for FormattedContainer { + fn from(container: GrammarFormattedContainer<'ast>) -> Self { + Self { + span: Span::from(container.span), + } + } +} + +impl fmt::Display for FormattedContainer { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{{}}") } diff --git a/ast/src/console/formatted_parameter.rs b/ast/src/console/formatted_parameter.rs index c8b8c3cbe4..c95f0e9bd6 100644 --- a/ast/src/console/formatted_parameter.rs +++ b/ast/src/console/formatted_parameter.rs @@ -14,23 +14,28 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ast::Rule, expressions::Expression, SpanDef}; +use crate::{Expression, Span}; +use leo_grammar::console::FormattedParameter as GrammarFormattedParameter; -use pest::Span; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::formatted_parameter))] -pub struct FormattedParameter<'ast> { - pub expression: Expression<'ast>, - #[pest_ast(outer())] - #[serde(with = "SpanDef")] - pub span: Span<'ast>, +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct FormattedParameter { + pub expression: Expression, + pub span: Span, } -impl<'ast> fmt::Display for FormattedParameter<'ast> { +impl<'ast> From> for FormattedParameter { + fn from(parameter: GrammarFormattedParameter<'ast>) -> Self { + Self { + expression: Expression::from(parameter.expression), + span: Span::from(parameter.span), + } + } +} + +impl fmt::Display for FormattedParameter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.expression) } diff --git a/ast/src/console/formatted_string.rs b/ast/src/console/formatted_string.rs index d40d399f6b..2ef547219f 100644 --- a/ast/src/console/formatted_string.rs +++ b/ast/src/console/formatted_string.rs @@ -14,30 +14,37 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ - ast::{span_into_string, Rule}, - console::{FormattedContainer, FormattedParameter}, - SpanDef, -}; +use crate::{FormattedContainer, FormattedParameter, Span}; +use leo_grammar::console::FormattedString as GrammarFormattedString; -use pest::Span; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::formatted_string))] -pub struct FormattedString<'ast> { - #[pest_ast(outer(with(span_into_string)))] +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct FormattedString { pub string: String, - pub containers: Vec>, - pub parameters: Vec>, - #[pest_ast(outer())] - #[serde(with = "SpanDef")] - pub span: Span<'ast>, + pub containers: Vec, + pub parameters: Vec, + pub span: Span, } -impl<'ast> fmt::Display for FormattedString<'ast> { +impl<'ast> From> for FormattedString { + fn from(formatted: GrammarFormattedString<'ast>) -> Self { + let string = formatted.string; + let span = Span::from(formatted.span); + let containers = formatted.containers.into_iter().map(FormattedContainer::from).collect(); + let parameters = formatted.parameters.into_iter().map(FormattedParameter::from).collect(); + + Self { + string, + containers, + parameters, + span, + } + } +} + +impl fmt::Display for FormattedString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.string) } diff --git a/ast/src/console/mod.rs b/ast/src/console/mod.rs index bf4eb3b03e..071f43d819 100644 --- a/ast/src/console/mod.rs +++ b/ast/src/console/mod.rs @@ -14,27 +14,12 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -pub mod console_assert; -pub use console_assert::*; - -pub mod console_debug; -pub use console_debug::*; - -pub mod console_error; -pub use console_error::*; - pub mod console_function; pub use console_function::*; pub mod console_function_call; pub use console_function_call::*; -pub mod console_keyword; -pub use console_keyword::*; - -pub mod console_log; -pub use console_log::*; - pub mod formatted_container; pub use formatted_container::*; diff --git a/typed/src/errors/error.rs b/ast/src/errors/error.rs similarity index 100% rename from typed/src/errors/error.rs rename to ast/src/errors/error.rs diff --git a/ast/src/errors/mod.rs b/ast/src/errors/mod.rs index c60030f31f..d76128b38a 100644 --- a/ast/src/errors/mod.rs +++ b/ast/src/errors/mod.rs @@ -14,8 +14,5 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -pub mod parser; -pub use parser::*; - -pub mod syntax; -pub use syntax::*; +pub mod error; +pub use error::*; diff --git a/typed/src/expression.rs b/ast/src/expression.rs similarity index 81% rename from typed/src/expression.rs rename to ast/src/expression.rs index 1a8734448c..7fedd4b1d2 100644 --- a/typed/src/expression.rs +++ b/ast/src/expression.rs @@ -15,23 +15,25 @@ // along with the Leo library. If not, see . use crate::{ + ArrayDimensions, CircuitVariableDefinition, GroupValue, Identifier, IntegerType, + PositiveNumber, RangeOrExpression, Span, SpreadOrExpression, }; -use leo_ast::{ +use leo_grammar::{ access::{Access, AssigneeAccess}, - common::{Assignee, Identifier as AstIdentifier}, + common::{Assignee, Identifier as GrammarIdentifier}, expressions::{ ArrayInitializerExpression, ArrayInlineExpression, BinaryExpression, CircuitInlineExpression, - Expression as AstExpression, + Expression as GrammarExpression, PostfixExpression, TernaryExpression, UnaryExpression, @@ -41,16 +43,14 @@ use leo_ast::{ AddressValue, BooleanValue, FieldValue, - GroupValue as AstGroupValue, + GroupValue as GrammarGroupValue, IntegerValue, - NumberValue as AstNumber, - PositiveNumber as AstPositiveNumber, + NumberValue as GrammarNumber, Value, }, }; -use leo_input::{types::ArrayDimensions as InputArrayDimensions, values::PositiveNumber as InputAstPositiveNumber}; -use leo_ast::{expressions::TupleExpression, types::ArrayDimensions}; +use leo_grammar::{access::TupleAccess, expressions::TupleExpression}; use serde::{Deserialize, Serialize}; use std::fmt; @@ -92,15 +92,17 @@ pub enum Expression { // Arrays // (array_elements, span) - Array(Vec, Span), - // (array_name, range, span) + ArrayInline(Vec, Span), + // ((array element, dimensions), span) + ArrayInitializer(Box<(Expression, ArrayDimensions)>, Span), + // ((array_name, range), span) ArrayAccess(Box<(Expression, RangeOrExpression)>, Span), // Tuples // (tuple_elements, span) Tuple(Vec, Span), - // (tuple_name, index, span) - TupleAccess(Box, usize, Span), + // ((tuple_name, index), span) + TupleAccess(Box<(Expression, PositiveNumber)>, Span), // Circuits // (defined_circuit_name, circuit_members, span) @@ -139,11 +141,12 @@ impl Expression { Expression::Lt(_, old_span) => *old_span = new_span, Expression::IfElse(_, old_span) => *old_span = new_span, - Expression::Array(_, old_span) => *old_span = new_span, + Expression::ArrayInline(_, old_span) => *old_span = new_span, + Expression::ArrayInitializer(_, old_span) => *old_span = new_span, Expression::ArrayAccess(_, old_span) => *old_span = new_span, Expression::Tuple(_, old_span) => *old_span = new_span, - Expression::TupleAccess(_, _, old_span) => *old_span = new_span, + Expression::TupleAccess(_, old_span) => *old_span = new_span, Expression::Circuit(_, _, old_span) => *old_span = new_span, Expression::CircuitMemberAccess(_, _, old_span) => *old_span = new_span, @@ -156,40 +159,6 @@ impl Expression { } } -impl<'ast> Expression { - pub(crate) fn get_count_from_input_ast(number: InputAstPositiveNumber<'ast>) -> usize { - number - .value - .parse::() - .expect("Array size should be a positive number") - } - - pub(crate) fn get_input_array_dimensions(dimensions: InputArrayDimensions<'ast>) -> Vec { - match dimensions { - InputArrayDimensions::Single(single) => vec![Self::get_count_from_input_ast(single.number)], - InputArrayDimensions::Multiple(multiple) => multiple - .numbers - .into_iter() - .map(Self::get_count_from_input_ast) - .collect(), - } - } - - pub(crate) fn get_count_from_ast(number: AstPositiveNumber<'ast>) -> usize { - number - .value - .parse::() - .expect("Array size should be a positive number") - } - - pub(crate) fn get_array_dimensions(dimensions: ArrayDimensions<'ast>) -> Vec { - match dimensions { - ArrayDimensions::Single(single) => vec![Self::get_count_from_ast(single.number)], - ArrayDimensions::Multiple(multiple) => multiple.numbers.into_iter().map(Self::get_count_from_ast).collect(), - } - } -} - impl<'ast> fmt::Display for Expression { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -228,7 +197,7 @@ impl<'ast> fmt::Display for Expression { } // Arrays - Expression::Array(ref array, ref _span) => { + Expression::ArrayInline(ref array, ref _span) => { write!(f, "[")?; for (i, e) in array.iter().enumerate() { write!(f, "{}", e)?; @@ -238,6 +207,7 @@ impl<'ast> fmt::Display for Expression { } write!(f, "]") } + Expression::ArrayInitializer(ref array, ref _span) => write!(f, "[{}; {}]", array.0, array.1), Expression::ArrayAccess(ref array_w_index, ref _span) => { write!(f, "{}[{}]", array_w_index.0, array_w_index.1) } @@ -248,7 +218,9 @@ impl<'ast> fmt::Display for Expression { write!(f, "({})", values) } - Expression::TupleAccess(ref tuple, ref index, ref _span) => write!(f, "{}.{}", tuple, index), + Expression::TupleAccess(ref tuple_w_index, ref _span) => { + write!(f, "{}.{}", tuple_w_index.0, tuple_w_index.1) + } // Circuits Expression::Circuit(ref var, ref members, ref _span) => { @@ -326,8 +298,7 @@ impl<'ast> From> for Expression { // Handle tuple access Access::Tuple(tuple) => Expression::TupleAccess( - Box::new(acc), - Expression::get_count_from_ast(tuple.number), + Box::new((acc, PositiveNumber::from(tuple.number))), Span::from(tuple.span), ), @@ -356,19 +327,19 @@ impl<'ast> From> for Expression { } } -impl<'ast> From> for Expression { - fn from(expression: AstExpression<'ast>) -> Self { +impl<'ast> From> for Expression { + fn from(expression: GrammarExpression<'ast>) -> Self { match expression { - AstExpression::Value(value) => Expression::from(value), - AstExpression::Identifier(variable) => Expression::from(variable), - AstExpression::Unary(expression) => Expression::from(*expression), - AstExpression::Binary(expression) => Expression::from(*expression), - AstExpression::Ternary(expression) => Expression::from(*expression), - AstExpression::ArrayInline(expression) => Expression::from(expression), - AstExpression::ArrayInitializer(expression) => Expression::from(*expression), - AstExpression::Tuple(expression) => Expression::from(expression), - AstExpression::CircuitInline(expression) => Expression::from(expression), - AstExpression::Postfix(expression) => Expression::from(expression), + GrammarExpression::Value(value) => Expression::from(value), + GrammarExpression::Identifier(variable) => Expression::from(variable), + GrammarExpression::Unary(expression) => Expression::from(*expression), + GrammarExpression::Binary(expression) => Expression::from(*expression), + GrammarExpression::Ternary(expression) => Expression::from(*expression), + GrammarExpression::ArrayInline(expression) => Expression::from(expression), + GrammarExpression::ArrayInitializer(expression) => Expression::from(*expression), + GrammarExpression::Tuple(expression) => Expression::from(expression), + GrammarExpression::CircuitInline(expression) => Expression::from(expression), + GrammarExpression::Postfix(expression) => Expression::from(expression), } } } @@ -393,9 +364,8 @@ impl<'ast> From> for Expression { Span::from(array.span), ), AssigneeAccess::Tuple(tuple) => Expression::TupleAccess( - Box::new(acc), - Expression::get_count_from_ast(tuple.number), - Span::from(tuple.span), + Box::new((acc, PositiveNumber::from(tuple.number))), + Span::from(tuple.span.clone()), ), }) } @@ -482,7 +452,7 @@ impl<'ast> From> for Expression { impl<'ast> From> for Expression { fn from(array: ArrayInlineExpression<'ast>) -> Self { - Expression::Array( + Expression::ArrayInline( array.expressions.into_iter().map(SpreadOrExpression::from).collect(), Span::from(array.span), ) @@ -491,26 +461,13 @@ impl<'ast> From> for Expression { impl<'ast> From> for Expression { fn from(array: ArrayInitializerExpression<'ast>) -> Self { - let dimensions = Expression::get_array_dimensions(array.dimensions); - let expression = SpreadOrExpression::from(array.expression); - - let mut elements = vec![]; - - // Initializes an arrays elements using the rust `vec!` macro. - // If there are multiple array dimensions, then `elements` is used as the first expression in a `vec!` macro. - // This creates a multi-dimensional array by chaining `vec!` macros. - for (i, dimension) in dimensions.into_iter().rev().enumerate() { - if i == 0 { - elements = vec![expression.clone(); dimension]; - } else { - let element = - SpreadOrExpression::Expression(Expression::Array(elements, Span::from(array.span.clone()))); - - elements = vec![element; dimension]; - } - } - - Expression::Array(elements, Span::from(array.span)) + Expression::ArrayInitializer( + Box::new(( + Expression::from(array.expression), + ArrayDimensions::from(array.dimensions), + )), + Span::from(array.span), + ) } } @@ -569,17 +526,17 @@ impl<'ast> From> for Expression { } } -impl<'ast> From> for Expression { - fn from(ast_group: AstGroupValue<'ast>) -> Self { +impl<'ast> From> for Expression { + fn from(ast_group: GrammarGroupValue<'ast>) -> Self { Expression::Group(Box::new(GroupValue::from(ast_group))) } } -impl<'ast> From> for Expression { - fn from(number: AstNumber<'ast>) -> Self { +impl<'ast> From> for Expression { + fn from(number: GrammarNumber<'ast>) -> Self { let (value, span) = match number { - AstNumber::Positive(number) => (number.value, number.span), - AstNumber::Negative(number) => (number.value, number.span), + GrammarNumber::Positive(number) => (number.value, number.span), + GrammarNumber::Negative(number) => (number.value, number.span), }; Expression::Implicit(value, Span::from(span)) @@ -593,8 +550,8 @@ impl<'ast> From> for Expression { IntegerValue::Signed(integer) => { let type_ = IntegerType::from(integer.type_); let number = match integer.number { - AstNumber::Negative(number) => number.value, - AstNumber::Positive(number) => number.value, + GrammarNumber::Negative(number) => number.value, + GrammarNumber::Positive(number) => number.value, }; (type_, number) @@ -611,8 +568,14 @@ impl<'ast> From> for Expression { } } -impl<'ast> From> for Expression { - fn from(identifier: AstIdentifier<'ast>) -> Self { +impl<'ast> From> for Expression { + fn from(tuple: TupleAccess<'ast>) -> Self { + Expression::Implicit(tuple.number.to_string(), Span::from(tuple.span)) + } +} + +impl<'ast> From> for Expression { + fn from(identifier: GrammarIdentifier<'ast>) -> Self { Expression::Identifier(Identifier::from(identifier)) } } diff --git a/ast/src/functions/function.rs b/ast/src/functions/function.rs index 4129422ed0..be15d5131e 100644 --- a/ast/src/functions/function.rs +++ b/ast/src/functions/function.rs @@ -14,20 +14,79 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ast::Rule, common::Identifier, functions::input::Input, statements::Statement, types::Type, SpanDef}; +use crate::{FunctionInput, Identifier, Span, Statement, Type}; +use leo_grammar::functions::Function as GrammarFunction; -use pest::Span; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; +use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::function))] -pub struct Function<'ast> { - pub identifier: Identifier<'ast>, - pub parameters: Vec>, - pub returns: Option>, - pub statements: Vec>, - #[pest_ast(outer())] - #[serde(with = "SpanDef")] - pub span: Span<'ast>, +#[derive(Clone, Serialize, Deserialize)] +pub struct Function { + pub identifier: Identifier, + pub input: Vec, + pub output: Option, + pub statements: Vec, + pub span: Span, +} + +impl PartialEq for Function { + fn eq(&self, other: &Self) -> bool { + self.identifier == other.identifier + } +} + +impl Eq for Function {} + +impl<'ast> From> for Function { + fn from(function: GrammarFunction<'ast>) -> Self { + let function_name = Identifier::from(function.identifier); + + let parameters = function.parameters.into_iter().map(FunctionInput::from).collect(); + let returns = function.returns.map(Type::from); + let statements = function.statements.into_iter().map(Statement::from).collect(); + + Function { + identifier: function_name, + input: parameters, + output: returns, + statements, + span: Span::from(function.span), + } + } +} + +impl Function { + pub fn get_name(&self) -> &str { + &self.identifier.name + } + + fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "function {}", self.identifier)?; + + let parameters = self.input.iter().map(|x| x.to_string()).collect::>().join(","); + let returns = self.output.as_ref().map(|type_| type_.to_string()); + let statements = self + .statements + .iter() + .map(|s| format!("\t{}\n", s)) + .collect::>() + .join(""); + if returns.is_none() { + write!(f, "({}) {{\n{}}}", parameters, statements,) + } else { + write!(f, "({}) -> {} {{\n{}}}", parameters, returns.unwrap(), statements,) + } + } +} + +impl fmt::Display for Function { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } +} + +impl fmt::Debug for Function { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } } diff --git a/ast/src/functions/input/function_input.rs b/ast/src/functions/input/function_input.rs index 583cff1547..07dbafdf27 100644 --- a/ast/src/functions/input/function_input.rs +++ b/ast/src/functions/input/function_input.rs @@ -14,24 +14,50 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ - ast::Rule, - common::{Identifier, Mutable}, - types::Type, - SpanDef, -}; +use crate::{Identifier, Span, Type}; +use leo_grammar::functions::FunctionInput as GrammarFunctionInput; -use pest::Span; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; +use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::function_input))] -pub struct FunctionInput<'ast> { - pub mutable: Option, - pub identifier: Identifier<'ast>, - pub type_: Type<'ast>, - #[pest_ast(outer())] - #[serde(with = "SpanDef")] - pub span: Span<'ast>, +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct FunctionInputVariable { + pub identifier: Identifier, + pub mutable: bool, + pub type_: Type, + pub span: Span, +} + +impl<'ast> From> for FunctionInputVariable { + fn from(parameter: GrammarFunctionInput<'ast>) -> Self { + FunctionInputVariable { + identifier: Identifier::from(parameter.identifier), + mutable: parameter.mutable.is_some(), + type_: Type::from(parameter.type_), + span: Span::from(parameter.span), + } + } +} + +impl FunctionInputVariable { + fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { + // mut var: bool + if self.mutable { + write!(f, "mut ")?; + } + write!(f, "{}: ", self.identifier)?; + write!(f, "{}", self.type_) + } +} + +impl fmt::Display for FunctionInputVariable { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } +} + +impl fmt::Debug for FunctionInputVariable { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } } diff --git a/typed/src/functions/input/input_variable.rs b/ast/src/functions/input/input_variable.rs similarity index 64% rename from typed/src/functions/input/input_variable.rs rename to ast/src/functions/input/input_variable.rs index b3032d8b1b..cc7c75231c 100644 --- a/typed/src/functions/input/input_variable.rs +++ b/ast/src/functions/input/input_variable.rs @@ -14,52 +14,52 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{FunctionInput, Identifier, Span}; -use leo_ast::functions::input::Input as AstInput; +use crate::{FunctionInputVariable, Identifier, Span}; +use leo_grammar::functions::input::Input as GrammarInput; use serde::{Deserialize, Serialize}; use std::fmt; #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum InputVariable { +pub enum FunctionInput { InputKeyword(Identifier), - FunctionInput(FunctionInput), + Variable(FunctionInputVariable), } -impl<'ast> From> for InputVariable { - fn from(input: AstInput<'ast>) -> Self { +impl<'ast> From> for FunctionInput { + fn from(input: GrammarInput<'ast>) -> Self { match input { - AstInput::InputKeyword(input_keyword) => { + GrammarInput::InputKeyword(input_keyword) => { let id = Identifier { name: input_keyword.keyword, span: Span::from(input_keyword.span), }; - InputVariable::InputKeyword(id) + FunctionInput::InputKeyword(id) } - AstInput::FunctionInput(function_input) => { - InputVariable::FunctionInput(FunctionInput::from(function_input)) + GrammarInput::FunctionInput(function_input) => { + FunctionInput::Variable(FunctionInputVariable::from(function_input)) } } } } -impl InputVariable { +impl FunctionInput { fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - InputVariable::InputKeyword(id) => write!(f, "{}", id), - InputVariable::FunctionInput(function_input) => write!(f, "{}", function_input), + FunctionInput::InputKeyword(id) => write!(f, "{}", id), + FunctionInput::Variable(function_input) => write!(f, "{}", function_input), } } } -impl fmt::Display for InputVariable { +impl fmt::Display for FunctionInput { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.format(f) } } -impl fmt::Debug for InputVariable { +impl fmt::Debug for FunctionInput { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.format(f) } diff --git a/ast/src/functions/input/mod.rs b/ast/src/functions/input/mod.rs index 90c793d89d..d673bea746 100644 --- a/ast/src/functions/input/mod.rs +++ b/ast/src/functions/input/mod.rs @@ -14,13 +14,8 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -#![allow(clippy::module_inception)] - pub mod function_input; pub use function_input::*; -pub mod input; -pub use input::*; - -pub mod input_keyword; -pub use input_keyword::*; +pub mod input_variable; +pub use input_variable::*; diff --git a/ast/src/functions/test_function.rs b/ast/src/functions/test_function.rs index 54222deafd..6996b2da20 100644 --- a/ast/src/functions/test_function.rs +++ b/ast/src/functions/test_function.rs @@ -14,17 +14,22 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ast::Rule, functions::Function, SpanDef}; +use crate::{Function, Identifier}; +use leo_grammar::functions::TestFunction as GrammarTestFunction; -use pest::Span; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::test_function))] -pub struct TestFunction<'ast> { - pub function: Function<'ast>, - #[pest_ast(outer())] - #[serde(with = "SpanDef")] - pub span: Span<'ast>, +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct TestFunction { + pub function: Function, + pub input_file: Option, +} + +impl<'ast> From> for TestFunction { + fn from(test: GrammarTestFunction) -> Self { + TestFunction { + function: Function::from(test.function), + input_file: None, // pass custom input file with `@context` annotation + } + } } diff --git a/typed/src/groups/group_coordinate.rs b/ast/src/groups/group_coordinate.rs similarity index 73% rename from typed/src/groups/group_coordinate.rs rename to ast/src/groups/group_coordinate.rs index 8b84d950e2..e3dea687ac 100644 --- a/typed/src/groups/group_coordinate.rs +++ b/ast/src/groups/group_coordinate.rs @@ -15,12 +15,12 @@ // along with the Leo library. If not, see . use crate::common::span::Span; -use leo_ast::values::{ - GroupCoordinate as AstGroupCoordinate, - Inferred as AstInferred, - NumberValue as AstNumberValue, - SignHigh as AstSignHigh, - SignLow as AstSignLow, +use leo_grammar::values::{ + GroupCoordinate as GrammarGroupCoordinate, + Inferred as GrammarInferred, + NumberValue as GrammarNumberValue, + SignHigh as GrammarSignHigh, + SignLow as GrammarSignLow, }; use leo_input::values::{ GroupCoordinate as InputGroupCoordinate, @@ -41,13 +41,13 @@ pub enum GroupCoordinate { Inferred, } -impl<'ast> From> for GroupCoordinate { - fn from(coordinate: AstGroupCoordinate<'ast>) -> Self { +impl<'ast> From> for GroupCoordinate { + fn from(coordinate: GrammarGroupCoordinate<'ast>) -> Self { match coordinate { - AstGroupCoordinate::Number(number) => GroupCoordinate::from(number), - AstGroupCoordinate::SignHigh(sign_high) => GroupCoordinate::from(sign_high), - AstGroupCoordinate::SignLow(sign_low) => GroupCoordinate::from(sign_low), - AstGroupCoordinate::Inferred(inferred) => GroupCoordinate::from(inferred), + GrammarGroupCoordinate::Number(number) => GroupCoordinate::from(number), + GrammarGroupCoordinate::SignHigh(sign_high) => GroupCoordinate::from(sign_high), + GrammarGroupCoordinate::SignLow(sign_low) => GroupCoordinate::from(sign_low), + GrammarGroupCoordinate::Inferred(inferred) => GroupCoordinate::from(inferred), } } } @@ -74,8 +74,8 @@ impl fmt::Display for GroupCoordinate { } } -impl<'ast> From> for GroupCoordinate { - fn from(number: AstNumberValue<'ast>) -> Self { +impl<'ast> From> for GroupCoordinate { + fn from(number: GrammarNumberValue<'ast>) -> Self { let value = number.to_string(); let span = Span::from(number.span().clone()); @@ -83,20 +83,20 @@ impl<'ast> From> for GroupCoordinate { } } -impl<'ast> From> for GroupCoordinate { - fn from(_sign: AstSignHigh<'ast>) -> Self { +impl<'ast> From> for GroupCoordinate { + fn from(_sign: GrammarSignHigh<'ast>) -> Self { GroupCoordinate::SignHigh } } -impl<'ast> From> for GroupCoordinate { - fn from(_sign: AstSignLow<'ast>) -> Self { +impl<'ast> From> for GroupCoordinate { + fn from(_sign: GrammarSignLow<'ast>) -> Self { GroupCoordinate::SignLow } } -impl<'ast> From> for GroupCoordinate { - fn from(_sign: AstInferred<'ast>) -> Self { +impl<'ast> From> for GroupCoordinate { + fn from(_sign: GrammarInferred<'ast>) -> Self { GroupCoordinate::Inferred } } diff --git a/typed/src/groups/group_value.rs b/ast/src/groups/group_value.rs similarity index 80% rename from typed/src/groups/group_value.rs rename to ast/src/groups/group_value.rs index 26f902d615..0385e2896f 100644 --- a/typed/src/groups/group_value.rs +++ b/ast/src/groups/group_value.rs @@ -15,10 +15,10 @@ // along with the Leo library. If not, see . use crate::{common::span::Span, groups::GroupCoordinate}; -use leo_ast::values::{ - GroupRepresentation as AstGroupRepresentation, - GroupTuple as AstGroupTuple, - GroupValue as AstGroupValue, +use leo_grammar::values::{ + GroupRepresentation as GrammarGroupRepresentation, + GroupTuple as GrammarGroupTuple, + GroupValue as GrammarGroupValue, }; use leo_input::values::{ GroupRepresentation as InputGroupRepresentation, @@ -42,15 +42,22 @@ impl GroupValue { GroupValue::Tuple(tuple) => tuple.span = new_span, } } + + pub fn span(&self) -> &Span { + match self { + GroupValue::Single(_, span) => span, + GroupValue::Tuple(tuple) => &tuple.span, + } + } } -impl<'ast> From> for GroupValue { - fn from(ast_group: AstGroupValue) -> Self { +impl<'ast> From> for GroupValue { + fn from(ast_group: GrammarGroupValue) -> Self { let span = Span::from(ast_group.span); match ast_group.value { - AstGroupRepresentation::Single(number) => GroupValue::Single(number.to_string(), span), - AstGroupRepresentation::Tuple(tuple) => GroupValue::Tuple(GroupTuple::from(tuple)), + GrammarGroupRepresentation::Single(number) => GroupValue::Single(number.to_string(), span), + GrammarGroupRepresentation::Tuple(tuple) => GroupValue::Tuple(GroupTuple::from(tuple)), } } } @@ -82,8 +89,8 @@ pub struct GroupTuple { pub span: Span, } -impl<'ast> From> for GroupTuple { - fn from(ast_group: AstGroupTuple<'ast>) -> Self { +impl<'ast> From> for GroupTuple { + fn from(ast_group: GrammarGroupTuple<'ast>) -> Self { let ast_x = ast_group.x; let ast_y = ast_group.y; diff --git a/typed/src/groups/mod.rs b/ast/src/groups/mod.rs similarity index 100% rename from typed/src/groups/mod.rs rename to ast/src/groups/mod.rs diff --git a/ast/src/imports/import.rs b/ast/src/imports/import.rs index 5a8ff43b8a..72bca9e33e 100644 --- a/ast/src/imports/import.rs +++ b/ast/src/imports/import.rs @@ -14,18 +14,51 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ast::Rule, common::LineEnd, imports::Package, SpanDef}; +use crate::{Package, Span}; +use leo_grammar::imports::Import as GrammarImport; -use pest::Span; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; +use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::import))] -pub struct Import<'ast> { - pub package: Package<'ast>, - pub line_end: LineEnd, - #[pest_ast(outer())] - #[serde(with = "SpanDef")] - pub span: Span<'ast>, +/// Represents an import statement in a Leo program. +#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)] +pub struct ImportStatement { + pub package: Package, + pub span: Span, +} + +impl ImportStatement { + /// + /// Returns the the package file name of the self import statement. + /// + pub fn get_file_name(&self) -> &str { + &self.package.name.name + } +} + +impl<'ast> From> for ImportStatement { + fn from(import: GrammarImport<'ast>) -> Self { + ImportStatement { + package: Package::from(import.package), + span: Span::from(import.span), + } + } +} + +impl ImportStatement { + fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "import {};", self.package) + } +} + +impl fmt::Display for ImportStatement { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } +} + +impl fmt::Debug for ImportStatement { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } } diff --git a/ast/src/imports/import_symbol.rs b/ast/src/imports/import_symbol.rs index 619a9212aa..5ba0636c21 100644 --- a/ast/src/imports/import_symbol.rs +++ b/ast/src/imports/import_symbol.rs @@ -14,18 +14,63 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ast::Rule, common::Identifier, SpanDef}; +use crate::{Identifier, Span}; +use leo_grammar::imports::ImportSymbol as GrammarImportSymbol; -use pest::Span; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; +use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::import_symbol))] -pub struct ImportSymbol<'ast> { - pub value: Identifier<'ast>, - pub alias: Option>, - #[pest_ast(outer())] - #[serde(with = "SpanDef")] - pub span: Span<'ast>, +#[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)] +pub struct ImportSymbol { + pub symbol: Identifier, + pub alias: Option, + pub span: Span, +} + +impl<'ast> From> for ImportSymbol { + fn from(symbol: GrammarImportSymbol<'ast>) -> Self { + ImportSymbol { + symbol: Identifier::from(symbol.value), + alias: symbol.alias.map(Identifier::from), + span: Span::from(symbol.span), + } + } +} + +impl fmt::Display for ImportSymbol { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.alias.is_some() { + write!(f, "{} as {}", self.symbol, self.alias.as_ref().unwrap()) + } else { + write!(f, "{}", self.symbol) + } + } +} + +// TODO (collin): remove this +impl fmt::Debug for ImportSymbol { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.alias.is_some() { + write!(f, "{} as {}", self.symbol, self.alias.as_ref().unwrap()) + } else { + write!(f, "{}", self.symbol) + } + } +} + +impl ImportSymbol { + pub fn star(span: &Span) -> Self { + Self { + symbol: Identifier { + name: "*".to_string(), + span: span.clone(), + }, + alias: None, + span: span.clone(), + } + } + + pub fn is_star(&self) -> bool { + self.symbol.name.eq("*") + } } diff --git a/ast/src/imports/mod.rs b/ast/src/imports/mod.rs index 4a1343664a..faffbb0afe 100644 --- a/ast/src/imports/mod.rs +++ b/ast/src/imports/mod.rs @@ -25,9 +25,3 @@ pub use package::*; pub mod package_access; pub use package_access::*; - -pub mod package_name; -pub use package_name::*; - -pub mod star; -pub use star::*; diff --git a/ast/src/imports/package.rs b/ast/src/imports/package.rs index 75a3935913..071393fe54 100644 --- a/ast/src/imports/package.rs +++ b/ast/src/imports/package.rs @@ -14,22 +14,43 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ - ast::Rule, - imports::{PackageAccess, PackageName}, - SpanDef, -}; +use crate::{common::Identifier, PackageAccess, Span}; +use leo_grammar::imports::Package as GrammarPackage; -use pest::Span; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; +use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::package))] -pub struct Package<'ast> { - pub name: PackageName<'ast>, - pub access: PackageAccess<'ast>, - #[pest_ast(outer())] - #[serde(with = "SpanDef")] - pub span: Span<'ast>, +#[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)] +pub struct Package { + pub name: Identifier, + pub access: PackageAccess, + pub span: Span, +} + +impl<'ast> From> for Package { + fn from(package: GrammarPackage<'ast>) -> Self { + Package { + name: Identifier::from(package.name), + access: PackageAccess::from(package.access), + span: Span::from(package.span), + } + } +} + +impl Package { + fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}.{}", self.name, self.access) + } +} + +impl fmt::Display for Package { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } +} + +impl fmt::Debug for Package { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } } diff --git a/ast/src/imports/package_access.rs b/ast/src/imports/package_access.rs index 0e04906152..f7f0c92605 100644 --- a/ast/src/imports/package_access.rs +++ b/ast/src/imports/package_access.rs @@ -14,19 +14,61 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ - ast::Rule, - imports::{ImportSymbol, Package, Star}, -}; +use crate::{ImportSymbol, Package, Span}; +use leo_grammar::imports::PackageAccess as GrammarPackageAccess; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; +use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::package_access))] -pub enum PackageAccess<'ast> { - Star(Star<'ast>), - SubPackage(Box>), - Symbol(ImportSymbol<'ast>), - Multiple(Vec>), +#[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)] +pub enum PackageAccess { + Star(Span), + SubPackage(Box), + Symbol(ImportSymbol), + Multiple(Vec), +} + +impl<'ast> From> for PackageAccess { + fn from(access: GrammarPackageAccess<'ast>) -> Self { + match access { + GrammarPackageAccess::Star(star) => PackageAccess::Star(Span::from(star.span)), + GrammarPackageAccess::SubPackage(package) => PackageAccess::SubPackage(Box::new(Package::from(*package))), + GrammarPackageAccess::Symbol(symbol) => PackageAccess::Symbol(ImportSymbol::from(symbol)), + GrammarPackageAccess::Multiple(accesses) => { + PackageAccess::Multiple(accesses.into_iter().map(PackageAccess::from).collect()) + } + } + } +} + +impl PackageAccess { + fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + PackageAccess::Star(ref _span) => write!(f, "*"), + PackageAccess::SubPackage(ref package) => write!(f, "{}", package), + PackageAccess::Symbol(ref symbol) => write!(f, "{}", symbol), + PackageAccess::Multiple(ref accesses) => { + write!(f, "(")?; + for (i, access) in accesses.iter().enumerate() { + write!(f, "{}", access)?; + if i < accesses.len() - 1 { + write!(f, ", ")?; + } + } + write!(f, ")") + } + } + } +} + +impl fmt::Debug for PackageAccess { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } +} + +impl fmt::Display for PackageAccess { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } } diff --git a/typed/src/input/input.rs b/ast/src/input/input.rs similarity index 98% rename from typed/src/input/input.rs rename to ast/src/input/input.rs index 1252ef86e4..ed74c41937 100644 --- a/typed/src/input/input.rs +++ b/ast/src/input/input.rs @@ -80,7 +80,7 @@ impl Input { Ok(()) } - /// Parse all input variables included in a file and store them in `self`. + /// Parse all state variables included in a file and store them in `self`. pub fn parse_state(&mut self, file: File) -> Result<(), InputParserError> { for entry in file.entries.into_iter() { match entry { diff --git a/typed/src/input/input_value.rs b/ast/src/input/input_value.rs similarity index 78% rename from typed/src/input/input_value.rs rename to ast/src/input/input_value.rs index befc9c50d6..1f6124e518 100644 --- a/typed/src/input/input_value.rs +++ b/ast/src/input/input_value.rs @@ -14,13 +14,14 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{Expression as TypedExpression, GroupValue}; +use crate::{ArrayDimensions, GroupValue}; use leo_input::{ errors::InputParserError, expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression, TupleExpression}, types::{ArrayType, DataType, IntegerType, TupleType, Type}, values::{Address, AddressValue, BooleanValue, FieldValue, GroupValue as InputGroupValue, NumberValue, Value}, }; +use pest::Span; use std::fmt; @@ -102,11 +103,18 @@ impl InputValue { } } + /// + /// Returns a new `InputValue` from the given `ArrayType` and `ArrayInlineExpression`. + /// pub(crate) fn from_array_inline( mut array_type: ArrayType, inline: ArrayInlineExpression, ) -> Result { - let array_dimensions = TypedExpression::get_input_array_dimensions(array_type.dimensions.clone()); + // Create a new `ArrayDimensions` type from the input array_type dimensions. + let array_dimensions_type = ArrayDimensions::from(array_type.dimensions.clone()); + + // Convert the array dimensions to usize. + let array_dimensions = parse_array_dimensions(array_dimensions_type, array_type.span.clone())?; // Return an error if the outer array dimension does not equal the number of array elements. if array_dimensions[0] != inline.expressions.len() { @@ -137,14 +145,15 @@ impl InputValue { array_type: ArrayType, initializer: ArrayInitializerExpression, ) -> Result { - let initializer_dimensions = TypedExpression::get_input_array_dimensions(initializer.dimensions.clone()); + let array_dimensions_type = ArrayDimensions::from(initializer.dimensions.clone()); + let array_dimensions = parse_array_dimensions(array_dimensions_type, array_type.span.clone())?; - if initializer_dimensions.len() > 1 { + if array_dimensions.len() > 1 { // The expression is an array initializer with tuple syntax - Self::from_array_initializer_tuple(array_type, initializer, initializer_dimensions) + Self::from_array_initializer_tuple(array_type, initializer, array_dimensions) } else { // The expression is an array initializer with nested syntax - Self::from_array_initializer_nested(array_type, initializer, initializer_dimensions) + Self::from_array_initializer_nested(array_type, initializer, array_dimensions) } } @@ -153,7 +162,7 @@ impl InputValue { initializer: ArrayInitializerExpression, initializer_dimensions: Vec, ) -> Result { - let (array_dimensions, array_element_type) = fetch_nested_array_type_dimensions(array_type.clone(), vec![]); + let (array_dimensions, array_element_type) = fetch_nested_array_type_dimensions(array_type.clone(), vec![])?; // Return an error if the dimensions of the array are incorrect. if array_dimensions.ne(&initializer_dimensions) { @@ -186,7 +195,11 @@ impl InputValue { initializer: ArrayInitializerExpression, initializer_dimensions: Vec, ) -> Result { - let array_dimensions = TypedExpression::get_input_array_dimensions(array_type.dimensions.clone()); + // Create a new `ArrayDimensions` type from the input array_type dimensions. + let array_dimensions_type = ArrayDimensions::from(array_type.dimensions.clone()); + + // Convert the array dimensions to usize. + let array_dimensions = parse_array_dimensions(array_dimensions_type, array_type.span.clone())?; let current_array_dimension = array_dimensions[0]; let current_initializer_dimension = initializer_dimensions[0]; @@ -240,14 +253,52 @@ impl InputValue { } } -// Recursively fetch all dimensions from the array type -fn fetch_nested_array_type_dimensions(array_type: ArrayType, mut array_dimensions: Vec) -> (Vec, Type) { - let mut current_dimension = TypedExpression::get_input_array_dimensions(array_type.dimensions); +/// +/// Returns a new vector of usize values from an [`ArrayDimensions`] type. +/// +/// Attempts to parse each dimension in the array from a `String` to a `usize` value. If parsing +/// is successful, the `usize` value is appended to the return vector. If parsing fails, an error +/// is returned. +/// +fn parse_array_dimensions(array_dimensions_type: ArrayDimensions, span: Span) -> Result, InputParserError> { + // Convert the array dimensions to usize. + let mut array_dimensions = Vec::with_capacity(array_dimensions_type.0.len()); + + for dimension in array_dimensions_type.0 { + // Convert the dimension to a string. + let dimension_string = dimension.to_string(); + + // Convert the string to usize. + let dimension_usize = match dimension_string.parse::() { + Ok(dimension_usize) => dimension_usize, + Err(_) => return Err(InputParserError::array_index(dimension_string, span.clone())), + }; + + // Collect dimension usize values. + array_dimensions.push(dimension_usize); + } + + Ok(array_dimensions) +} + +/// +/// Recursively fetch all dimensions from the array type. +/// +fn fetch_nested_array_type_dimensions( + array_type: ArrayType, + mut array_dimensions: Vec, +) -> Result<(Vec, Type), InputParserError> { + // Create a new `ArrayDimensions` type from the input array_type dimensions. + let array_dimensions_type = ArrayDimensions::from(array_type.dimensions.clone()); + + // Convert the array dimensions to usize. + let mut current_dimension = parse_array_dimensions(array_dimensions_type, array_type.span.clone())?; + array_dimensions.append(&mut current_dimension); match *array_type.type_ { Type::Array(next_array_type) => fetch_nested_array_type_dimensions(next_array_type, array_dimensions), - type_ => (array_dimensions, type_), + type_ => Ok((array_dimensions, type_)), } } diff --git a/typed/src/input/macros.rs b/ast/src/input/macros.rs similarity index 100% rename from typed/src/input/macros.rs rename to ast/src/input/macros.rs diff --git a/typed/src/input/mod.rs b/ast/src/input/mod.rs similarity index 100% rename from typed/src/input/mod.rs rename to ast/src/input/mod.rs diff --git a/typed/src/input/parameters/mod.rs b/ast/src/input/parameters/mod.rs similarity index 100% rename from typed/src/input/parameters/mod.rs rename to ast/src/input/parameters/mod.rs diff --git a/typed/src/input/parameters/parameter.rs b/ast/src/input/parameters/parameter.rs similarity index 86% rename from typed/src/input/parameters/parameter.rs rename to ast/src/input/parameters/parameter.rs index 709cd38daa..964538dc88 100644 --- a/typed/src/input/parameters/parameter.rs +++ b/ast/src/input/parameters/parameter.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{Identifier, Span, Type}; -use leo_input::parameters::Parameter as AstParameter; +use leo_input::parameters::Parameter as GrammarParameter; #[derive(Clone, PartialEq, Eq, Hash)] pub struct Parameter { @@ -24,8 +24,8 @@ pub struct Parameter { pub span: Span, } -impl<'ast> From> for Parameter { - fn from(parameter: AstParameter<'ast>) -> Self { +impl<'ast> From> for Parameter { + fn from(parameter: GrammarParameter<'ast>) -> Self { Self { variable: Identifier::from(parameter.variable), type_: Type::from(parameter.type_), diff --git a/typed/src/input/program_input/main_input.rs b/ast/src/input/program_input/main_input.rs similarity index 100% rename from typed/src/input/program_input/main_input.rs rename to ast/src/input/program_input/main_input.rs diff --git a/typed/src/input/program_input/mod.rs b/ast/src/input/program_input/mod.rs similarity index 100% rename from typed/src/input/program_input/mod.rs rename to ast/src/input/program_input/mod.rs diff --git a/typed/src/input/program_input/program_input.rs b/ast/src/input/program_input/program_input.rs similarity index 100% rename from typed/src/input/program_input/program_input.rs rename to ast/src/input/program_input/program_input.rs diff --git a/typed/src/input/program_input/registers.rs b/ast/src/input/program_input/registers.rs similarity index 100% rename from typed/src/input/program_input/registers.rs rename to ast/src/input/program_input/registers.rs diff --git a/typed/src/input/program_state/mod.rs b/ast/src/input/program_state/mod.rs similarity index 100% rename from typed/src/input/program_state/mod.rs rename to ast/src/input/program_state/mod.rs diff --git a/typed/src/input/program_state/private_state/mod.rs b/ast/src/input/program_state/private_state/mod.rs similarity index 100% rename from typed/src/input/program_state/private_state/mod.rs rename to ast/src/input/program_state/private_state/mod.rs diff --git a/typed/src/input/program_state/private_state/private_state.rs b/ast/src/input/program_state/private_state/private_state.rs similarity index 100% rename from typed/src/input/program_state/private_state/private_state.rs rename to ast/src/input/program_state/private_state/private_state.rs diff --git a/typed/src/input/program_state/private_state/record.rs b/ast/src/input/program_state/private_state/record.rs similarity index 100% rename from typed/src/input/program_state/private_state/record.rs rename to ast/src/input/program_state/private_state/record.rs diff --git a/typed/src/input/program_state/private_state/state_leaf.rs b/ast/src/input/program_state/private_state/state_leaf.rs similarity index 100% rename from typed/src/input/program_state/private_state/state_leaf.rs rename to ast/src/input/program_state/private_state/state_leaf.rs diff --git a/typed/src/input/program_state/program_state.rs b/ast/src/input/program_state/program_state.rs similarity index 100% rename from typed/src/input/program_state/program_state.rs rename to ast/src/input/program_state/program_state.rs diff --git a/typed/src/input/program_state/public_state/mod.rs b/ast/src/input/program_state/public_state/mod.rs similarity index 100% rename from typed/src/input/program_state/public_state/mod.rs rename to ast/src/input/program_state/public_state/mod.rs diff --git a/typed/src/input/program_state/public_state/public_state.rs b/ast/src/input/program_state/public_state/public_state.rs similarity index 100% rename from typed/src/input/program_state/public_state/public_state.rs rename to ast/src/input/program_state/public_state/public_state.rs diff --git a/typed/src/input/program_state/public_state/state.rs b/ast/src/input/program_state/public_state/state.rs similarity index 100% rename from typed/src/input/program_state/public_state/state.rs rename to ast/src/input/program_state/public_state/state.rs diff --git a/ast/src/lib.rs b/ast/src/lib.rs index 19e29aa73b..787370078f 100644 --- a/ast/src/lib.rs +++ b/ast/src/lib.rs @@ -14,74 +14,85 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -#[macro_use] -extern crate lazy_static; -#[macro_use] -extern crate pest_derive; -#[macro_use] -extern crate thiserror; +//! The abstract syntax tree (ast) for a Leo program. +//! +//! This module contains the [`LeoAst`] type, a wrapper around the [`Program`] type. +//! The [`LeoAst`] type is intended to be parsed and modified by different passes +//! of the Leo compiler. The Leo compiler can generate a set of R1CS constraints from any [`LeoAst`]. -pub mod ast; +pub mod annotation; +pub use self::annotation::*; -pub mod access; -pub mod annotations; pub mod circuits; +pub use self::circuits::*; + pub mod common; +pub use self::common::*; + pub mod console; -pub mod definitions; -pub mod expressions; -pub mod files; -pub mod functions; -pub mod imports; -pub mod operations; -pub mod statements; -pub mod types; -pub mod values; +pub use self::console::*; pub mod errors; -pub use errors::*; +pub use self::errors::*; -pub(crate) mod span; -pub(crate) use span::*; +pub mod expression; +pub use self::expression::*; -use from_pest::FromPest; -use std::{fs, path::Path}; +pub mod functions; +pub use self::functions::*; -pub struct LeoAst<'ast> { - ast: files::File<'ast>, +pub mod groups; +pub use self::groups::*; + +pub mod imports; +pub use self::imports::*; + +pub mod input; +pub use self::input::*; + +pub mod program; +pub use self::program::*; + +pub mod statements; +pub use self::statements::*; + +pub mod types; +pub use self::types::*; + +use leo_grammar::Grammar; + +/// The abstract syntax tree (ast) for a Leo program. +/// +/// The [`LeoAst`] type represents a Leo program as a series of recursive data types. +/// These data types form a tree that begins from a [`Program`] type root. +/// +/// A new [`LeoAst`] can be created from a [`Grammar`] generated by the pest parser in the `grammar` module. +#[derive(Debug, Eq, PartialEq)] +pub struct LeoAst { + ast: Program, } -impl<'ast> LeoAst<'ast> { - /// Creates a new abstract syntax tree given the file path. - pub fn new(file_path: &'ast Path, program_string: &'ast str) -> Result { - // TODO (howardwu): Turn this check back on after fixing the testing module. - // assert_eq!(program_string, fs::read_to_string(file_path).map_err(|_| ParserError::FileReadError(file_path.clone()))?); - - // Parse the file using leo.pest - let file = &mut ast::parse(&program_string) - .map_err(|error| ParserError::from(error.with_path(file_path.to_str().unwrap())))?; - - // Builds the abstract syntax tree using pest derivation. - let ast = files::File::<'ast>::from_pest(file).map_err(|_| ParserError::SyntaxTreeError)?; - tracing::debug!("{:#?}", ast); - - Ok(Self { ast }) +impl LeoAst { + /// Creates a new syntax tree from a given program name and abstract syntax tree. + pub fn new<'ast>(program_name: &str, ast: &Grammar<'ast>) -> Self { + Self { + ast: Program::from(program_name, ast.as_repr()), + } } - // TODO (howardwu): Remove this in favor of a dedicated file loader to verify checksums - // and maintain a global cache of program strings during the compilation process. - /// Loads the Leo code as a string from the given file path. - pub fn load_file(file_path: &'ast Path) -> Result { - Ok(fs::read_to_string(file_path).map_err(|_| ParserError::FileReadError(file_path.to_owned()))?) + /// Returns a reference to the inner program syntax tree representation. + pub fn into_repr(self) -> Program { + self.ast } - /// Returns a reference to the inner abstract syntax tree representation. - pub fn as_repr(&self) -> &files::File<'ast> { - &self.ast - } - - /// Serializes the abstract syntax tree into a JSON string. - pub fn to_json_string(&self) -> Result { + /// Serializes the syntax tree into a JSON string. + pub fn to_json_string(&self) -> Result { Ok(serde_json::to_string_pretty(&self.ast)?) } + + /// Deserializes the JSON string into a syntax tree. + pub fn from_json_string(json: &str) -> Result { + let ast: Program = serde_json::from_str(json)?; + Ok(Self { ast }) + } } diff --git a/ast/src/main.rs b/ast/src/main.rs index df420eac74..35db61ec00 100644 --- a/ast/src/main.rs +++ b/ast/src/main.rs @@ -14,21 +14,25 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_ast::{LeoAst, ParserError}; +use leo_ast::LeoAst; +use leo_grammar::{Grammar, ParserError}; use std::{env, fs, path::Path}; -fn to_leo_ast(filepath: &Path) -> Result { +fn to_leo_tree(filepath: &Path) -> Result { // Loads the Leo code as a string from the given file path. let program_filepath = filepath.to_path_buf(); - let program_string = LeoAst::load_file(&program_filepath)?; + let program_string = Grammar::load_file(&program_filepath)?; - // Parses the Leo file and constructs an abstract syntax tree. - let ast = LeoAst::new(&program_filepath, &program_string)?; + // Parses the Leo file and constructs a pest ast. + let ast = Grammar::new(&program_filepath, &program_string)?; - // Serializes the abstract syntax tree into JSON format. - let serialized_ast = LeoAst::to_json_string(&ast)?; + // Parse the pest ast and constructs a ast. + let leo_ast = LeoAst::new("leo_tree", &ast); - Ok(serialized_ast) + // Serializes the tree into JSON format. + let serialized_leo_ast = LeoAst::to_json_string(&leo_ast)?; + + Ok(serialized_leo_ast) } fn main() -> Result<(), ParserError> { @@ -47,9 +51,9 @@ fn main() -> Result<(), ParserError> { // Construct the input filepath. let input_filepath = Path::new(&cli_arguments[1]); - // Construct the serialized abstract syntax tree. - let serialized_ast = to_leo_ast(&input_filepath)?; - println!("{}", serialized_ast); + // Construct the serialized syntax tree. + let serialized_leo_tree = to_leo_tree(&input_filepath)?; + println!("{}", serialized_leo_tree); // Determine the output directory. let output_directory = match cli_arguments.len() == 3 { @@ -61,8 +65,8 @@ fn main() -> Result<(), ParserError> { false => format!("./{}.json", input_filepath.file_stem().unwrap().to_str().unwrap()), }; - // Write the serialized abstract syntax tree to the output directory. - fs::write(Path::new(&output_directory), serialized_ast)?; + // Write the serialized syntax tree to the output directory. + fs::write(Path::new(&output_directory), serialized_leo_tree)?; Ok(()) } diff --git a/typed/src/program.rs b/ast/src/program.rs similarity index 88% rename from typed/src/program.rs rename to ast/src/program.rs index 8cc8b4f3ad..ac016363e5 100644 --- a/typed/src/program.rs +++ b/ast/src/program.rs @@ -14,21 +14,21 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -//! A typed Leo program consists of import, circuit, and function definitions. -//! Each defined type consists of typed statements and expressions. +//! A Leo program consists of import, circuit, and function definitions. +//! Each defined type consists of ast statements and expressions. -use crate::{load_annotation, Circuit, Function, Identifier, Import, InputVariable, TestFunction}; -use leo_ast::{definitions::Definition, files::File}; +use crate::{load_annotation, Circuit, Function, FunctionInput, Identifier, ImportStatement, TestFunction}; +use leo_grammar::{definitions::Definition, files::File}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; -/// A simple program with statement expressions, program arguments and program returns. +/// Stores the Leo program abstract syntax tree. #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] pub struct Program { pub name: String, - pub expected_input: Vec, - pub imports: Vec, + pub expected_input: Vec, + pub imports: Vec, pub circuits: HashMap, pub functions: HashMap, pub tests: HashMap, @@ -50,7 +50,7 @@ impl<'ast> Program { .to_owned() .into_iter() .for_each(|definition| match definition { - Definition::Import(import) => imports.push(Import::from(import)), + Definition::Import(import) => imports.push(ImportStatement::from(import)), Definition::Circuit(circuit) => { circuits.insert(Identifier::from(circuit.identifier.clone()), Circuit::from(circuit)); } diff --git a/ast/src/statements/conditional_nested_or_end_statement.rs b/ast/src/statements/conditional_nested_or_end_statement.rs index 120fc2ba7e..ddb1f75dc1 100644 --- a/ast/src/statements/conditional_nested_or_end_statement.rs +++ b/ast/src/statements/conditional_nested_or_end_statement.rs @@ -14,27 +14,42 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ - ast::Rule, - statements::{ConditionalStatement, Statement}, -}; +use crate::{ConditionalStatement, Statement}; +use leo_grammar::statements::ConditionalNestedOrEndStatement as GrammarConditionalNestedOrEndStatement; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::conditional_nested_or_end_statement))] -pub enum ConditionalNestedOrEndStatement<'ast> { - Nested(Box>), - End(Vec>), +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum ConditionalNestedOrEndStatement { + Nested(Box), + End(Vec), } -impl<'ast> fmt::Display for ConditionalNestedOrEndStatement<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ConditionalNestedOrEndStatement::Nested(ref nested) => write!(f, "else {}", nested), - ConditionalNestedOrEndStatement::End(ref statements) => write!(f, "else {{\n \t{:#?}\n }}", statements), +impl<'ast> From> for ConditionalNestedOrEndStatement { + fn from(statement: GrammarConditionalNestedOrEndStatement<'ast>) -> Self { + match statement { + GrammarConditionalNestedOrEndStatement::Nested(nested) => { + ConditionalNestedOrEndStatement::Nested(Box::new(ConditionalStatement::from(*nested))) + } + GrammarConditionalNestedOrEndStatement::End(statements) => { + ConditionalNestedOrEndStatement::End(statements.into_iter().map(Statement::from).collect()) + } + } + } +} + +impl fmt::Display for ConditionalNestedOrEndStatement { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + ConditionalNestedOrEndStatement::Nested(ref nested) => write!(f, "else {}", nested), + ConditionalNestedOrEndStatement::End(ref statements) => { + writeln!(f, "else {{")?; + for statement in statements.iter() { + writeln!(f, "\t\t{}", statement)?; + } + write!(f, "\t}}") + } } } } diff --git a/ast/src/statements/conditional_statement.rs b/ast/src/statements/conditional_statement.rs index 6cfd97d97e..628b0f9dc4 100644 --- a/ast/src/statements/conditional_statement.rs +++ b/ast/src/statements/conditional_statement.rs @@ -14,36 +14,41 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ - ast::Rule, - expressions::Expression, - statements::{ConditionalNestedOrEndStatement, Statement}, - SpanDef, -}; +use crate::{ConditionalNestedOrEndStatement, Expression, Statement}; +use leo_grammar::statements::ConditionalStatement as GrammarConditionalStatement; -use pest::Span; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::statement_conditional))] -pub struct ConditionalStatement<'ast> { - pub condition: Expression<'ast>, - pub statements: Vec>, - pub next: Option>, - #[pest_ast(outer())] - #[serde(with = "SpanDef")] - pub span: Span<'ast>, +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct ConditionalStatement { + pub condition: Expression, + pub statements: Vec, + pub next: Option, } -impl<'ast> fmt::Display for ConditionalStatement<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - writeln!(f, "if ({}) {{", self.condition)?; - writeln!(f, "\t{:#?}", self.statements)?; - self.next - .as_ref() - .map(|n_or_e| write!(f, "}} {}", n_or_e)) - .unwrap_or_else(|| write!(f, "}}")) +impl<'ast> From> for ConditionalStatement { + fn from(statement: GrammarConditionalStatement<'ast>) -> Self { + ConditionalStatement { + condition: Expression::from(statement.condition), + statements: statement.statements.into_iter().map(Statement::from).collect(), + next: statement + .next + .map(|n_or_e| Some(ConditionalNestedOrEndStatement::from(n_or_e))) + .unwrap_or(None), + } + } +} + +impl fmt::Display for ConditionalStatement { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + writeln!(f, "if ({}) {{", self.condition)?; + for statement in self.statements.iter() { + writeln!(f, "\t\t{}", statement)?; + } + match self.next.clone() { + Some(n_or_e) => write!(f, "\t}} {}", n_or_e), + None => write!(f, "\t}}"), + } } } diff --git a/ast/src/statements/mod.rs b/ast/src/statements/mod.rs index 95978fa8af..8fcd2b997e 100644 --- a/ast/src/statements/mod.rs +++ b/ast/src/statements/mod.rs @@ -14,26 +14,11 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -pub mod assign_statement; -pub use assign_statement::*; +pub mod conditional_nested_or_end_statement; +pub use conditional_nested_or_end_statement::*; pub mod conditional_statement; pub use conditional_statement::*; -pub mod conditional_nested_or_end_statement; -pub use conditional_nested_or_end_statement::*; - -pub mod definition_statement; -pub use definition_statement::*; - -pub mod expression_statement; -pub use expression_statement::*; - -pub mod for_statement; -pub use for_statement::*; - -pub mod return_statement; -pub use return_statement::*; - pub mod statement; pub use statement::*; diff --git a/ast/src/statements/statement.rs b/ast/src/statements/statement.rs index 602d7785fa..680ddf7dbd 100644 --- a/ast/src/statements/statement.rs +++ b/ast/src/statements/statement.rs @@ -14,34 +14,177 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ast::Rule, console::ConsoleFunctionCall, statements::*}; +use crate::{Assignee, ConditionalStatement, ConsoleFunctionCall, Declare, Expression, Identifier, Span, Variables}; +use leo_grammar::{ + console::ConsoleFunctionCall as GrammarConsoleFunctionCall, + operations::AssignOperation, + statements::{ + AssignStatement, + DefinitionStatement, + ExpressionStatement, + ForStatement, + ReturnStatement, + Statement as GrammarStatement, + }, +}; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::statement))] -pub enum Statement<'ast> { - Return(ReturnStatement<'ast>), - Definition(DefinitionStatement<'ast>), - Assign(AssignStatement<'ast>), - Conditional(ConditionalStatement<'ast>), - Iteration(ForStatement<'ast>), - Console(ConsoleFunctionCall<'ast>), - Expression(ExpressionStatement<'ast>), +/// Program statement that defines some action (or expression) to be carried out. +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum Statement { + Return(Expression, Span), + Definition(Declare, Variables, Expression, Span), + Assign(Assignee, Expression, Span), + Conditional(ConditionalStatement, Span), + Iteration(Identifier, Box<(Expression, Expression)>, Vec, Span), + Console(ConsoleFunctionCall), + Expression(Expression, Span), } -impl<'ast> fmt::Display for Statement<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Statement::Return(ref statement) => write!(f, "{}", statement), - Statement::Definition(ref statement) => write!(f, "{}", statement), - Statement::Assign(ref statement) => write!(f, "{}", statement), - Statement::Conditional(ref statement) => write!(f, "{}", statement), - Statement::Iteration(ref statement) => write!(f, "{}", statement), - Statement::Console(ref statement) => write!(f, "{}", statement), - Statement::Expression(ref statement) => write!(f, "{}", statement.expression), +impl<'ast> From> for Statement { + fn from(statement: ReturnStatement<'ast>) -> Self { + Statement::Return(Expression::from(statement.expression), Span::from(statement.span)) + } +} + +impl<'ast> From> for Statement { + fn from(statement: DefinitionStatement<'ast>) -> Self { + let span = Span::from(statement.span); + + Statement::Definition( + Declare::from(statement.declare), + Variables::from(statement.variables), + Expression::from(statement.expression), + span, + ) + } +} + +impl<'ast> From> for Statement { + fn from(statement: AssignStatement<'ast>) -> Self { + match statement.assign { + AssignOperation::Assign(ref _assign) => Statement::Assign( + Assignee::from(statement.assignee), + Expression::from(statement.expression), + Span::from(statement.span), + ), + operation_assign => { + // convert assignee into postfix expression + let converted = Expression::from(statement.assignee.clone()); + + match operation_assign { + AssignOperation::AddAssign(ref _assign) => Statement::Assign( + Assignee::from(statement.assignee), + Expression::Add( + Box::new((converted, Expression::from(statement.expression))), + Span::from(statement.span.clone()), + ), + Span::from(statement.span), + ), + AssignOperation::SubAssign(ref _assign) => Statement::Assign( + Assignee::from(statement.assignee), + Expression::Sub( + Box::new((converted, Expression::from(statement.expression))), + Span::from(statement.span.clone()), + ), + Span::from(statement.span), + ), + AssignOperation::MulAssign(ref _assign) => Statement::Assign( + Assignee::from(statement.assignee), + Expression::Mul( + Box::new((converted, Expression::from(statement.expression))), + Span::from(statement.span.clone()), + ), + Span::from(statement.span), + ), + AssignOperation::DivAssign(ref _assign) => Statement::Assign( + Assignee::from(statement.assignee), + Expression::Div( + Box::new((converted, Expression::from(statement.expression))), + Span::from(statement.span.clone()), + ), + Span::from(statement.span), + ), + AssignOperation::PowAssign(ref _assign) => Statement::Assign( + Assignee::from(statement.assignee), + Expression::Pow( + Box::new((converted, Expression::from(statement.expression))), + Span::from(statement.span.clone()), + ), + Span::from(statement.span), + ), + AssignOperation::Assign(ref _assign) => unimplemented!("cannot assign twice to assign statement"), + } + } + } + } +} + +impl<'ast> From> for Statement { + fn from(statement: ForStatement<'ast>) -> Self { + Statement::Iteration( + Identifier::from(statement.index), + Box::new((Expression::from(statement.start), Expression::from(statement.stop))), + statement.statements.into_iter().map(Statement::from).collect(), + Span::from(statement.span), + ) + } +} + +impl<'ast> From> for Statement { + fn from(function_call: GrammarConsoleFunctionCall<'ast>) -> Self { + Statement::Console(ConsoleFunctionCall::from(function_call)) + } +} + +impl<'ast> From> for Statement { + fn from(statement: ExpressionStatement<'ast>) -> Self { + let span = Span::from(statement.span); + let mut expression = Expression::from(statement.expression); + + expression.set_span(span.clone()); + + Statement::Expression(expression, span) + } +} + +impl<'ast> From> for Statement { + fn from(statement: GrammarStatement<'ast>) -> Self { + match statement { + GrammarStatement::Return(statement) => Statement::from(statement), + GrammarStatement::Definition(statement) => Statement::from(statement), + GrammarStatement::Assign(statement) => Statement::from(statement), + GrammarStatement::Conditional(statement) => { + let span = Span::from(statement.span.clone()); + Statement::Conditional(ConditionalStatement::from(statement), span) + } + GrammarStatement::Iteration(statement) => Statement::from(statement), + GrammarStatement::Console(console) => Statement::from(console), + GrammarStatement::Expression(statement) => Statement::from(statement), + } + } +} + +impl fmt::Display for Statement { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Statement::Return(ref expression, ref _span) => write!(f, "return {}", expression), + Statement::Definition(ref declare, ref variable, ref expression, ref _span) => { + write!(f, "{} {} = {};", declare, variable, expression) + } + Statement::Assign(ref variable, ref statement, ref _span) => write!(f, "{} = {};", variable, statement), + Statement::Conditional(ref statement, ref _span) => write!(f, "{}", statement), + Statement::Iteration(ref var, ref start_stop, ref list, ref _span) => { + writeln!(f, "for {} in {}..{} {{", var, start_stop.0, start_stop.1)?; + for l in list { + writeln!(f, "\t\t{}", l)?; + } + write!(f, "\t}}") + } + Statement::Console(ref console) => write!(f, "{}", console), + Statement::Expression(ref expression, ref _span) => write!(f, "{};", expression), } } } diff --git a/ast/src/types/integer_type.rs b/ast/src/types/integer_type.rs index e75785ea4e..a65e6595f0 100644 --- a/ast/src/types/integer_type.rs +++ b/ast/src/types/integer_type.rs @@ -14,17 +14,116 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ - ast::Rule, - types::{SignedIntegerType, UnsignedIntegerType}, +use leo_grammar::types::{ + IntegerType as GrammarIntegerType, + SignedIntegerType as GrammarSignedIntegerType, + UnsignedIntegerType as GrammarUnsignedIntegerType, +}; +use leo_input::types::{ + IntegerType as InputIntegerType, + SignedIntegerType as InputSignedIntegerType, + UnsignedIntegerType as InputUnsignedIntegerType, }; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; +use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::type_integer))] +/// Explicit integer type +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum IntegerType { - Signed(SignedIntegerType), - Unsigned(UnsignedIntegerType), + U8, + U16, + U32, + U64, + U128, + + I8, + I16, + I32, + I64, + I128, +} + +impl From for IntegerType { + fn from(integer_type: GrammarIntegerType) -> Self { + match integer_type { + GrammarIntegerType::Signed(signed) => Self::from(signed), + GrammarIntegerType::Unsigned(unsigned) => Self::from(unsigned), + } + } +} + +impl From for IntegerType { + fn from(integer_type: GrammarUnsignedIntegerType) -> Self { + match integer_type { + GrammarUnsignedIntegerType::U8Type(_type) => IntegerType::U8, + GrammarUnsignedIntegerType::U16Type(_type) => IntegerType::U16, + GrammarUnsignedIntegerType::U32Type(_type) => IntegerType::U32, + GrammarUnsignedIntegerType::U64Type(_type) => IntegerType::U64, + GrammarUnsignedIntegerType::U128Type(_type) => IntegerType::U128, + } + } +} + +impl From for IntegerType { + fn from(integer_type: GrammarSignedIntegerType) -> Self { + match integer_type { + GrammarSignedIntegerType::I8Type(_type) => IntegerType::I8, + GrammarSignedIntegerType::I16Type(_type) => IntegerType::I16, + GrammarSignedIntegerType::I32Type(_type) => IntegerType::I32, + GrammarSignedIntegerType::I64Type(_type) => IntegerType::I64, + GrammarSignedIntegerType::I128Type(_type) => IntegerType::I128, + } + } +} + +impl From for IntegerType { + fn from(integer_type: InputIntegerType) -> Self { + match integer_type { + InputIntegerType::Signed(signed) => Self::from(signed), + InputIntegerType::Unsigned(unsigned) => Self::from(unsigned), + } + } +} + +impl From for IntegerType { + fn from(integer_type: InputUnsignedIntegerType) -> Self { + match integer_type { + InputUnsignedIntegerType::U8Type(_type) => IntegerType::U8, + InputUnsignedIntegerType::U16Type(_type) => IntegerType::U16, + InputUnsignedIntegerType::U32Type(_type) => IntegerType::U32, + InputUnsignedIntegerType::U64Type(_type) => IntegerType::U64, + InputUnsignedIntegerType::U128Type(_type) => IntegerType::U128, + } + } +} + +impl From for IntegerType { + fn from(integer_type: InputSignedIntegerType) -> Self { + match integer_type { + InputSignedIntegerType::I8Type(_type) => IntegerType::I8, + InputSignedIntegerType::I16Type(_type) => IntegerType::I16, + InputSignedIntegerType::I32Type(_type) => IntegerType::I32, + InputSignedIntegerType::I64Type(_type) => IntegerType::I64, + InputSignedIntegerType::I128Type(_type) => IntegerType::I128, + } + } +} + +impl fmt::Display for IntegerType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + IntegerType::U8 => write!(f, "u8"), + IntegerType::U16 => write!(f, "u16"), + IntegerType::U32 => write!(f, "u32"), + IntegerType::U64 => write!(f, "u64"), + IntegerType::U128 => write!(f, "u128"), + + IntegerType::I8 => write!(f, "i8"), + IntegerType::I16 => write!(f, "i16"), + IntegerType::I32 => write!(f, "i32"), + IntegerType::I64 => write!(f, "i64"), + IntegerType::I128 => write!(f, "i128"), + } + } } diff --git a/ast/src/types/mod.rs b/ast/src/types/mod.rs index e00ea64af2..9d9ca5aa82 100644 --- a/ast/src/types/mod.rs +++ b/ast/src/types/mod.rs @@ -14,44 +14,8 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -pub mod address_type; -pub use address_type::*; - -pub mod array_dimensions; -pub use array_dimensions::*; - -pub mod array_type; -pub use array_type::*; - -pub mod boolean_type; -pub use boolean_type::*; - -pub mod circuit_type; -pub use circuit_type::*; - -pub mod data_type; -pub use data_type::*; - -pub mod field_type; -pub use field_type::*; - -pub mod group_type; -pub use group_type::*; - pub mod integer_type; pub use integer_type::*; -pub mod self_type; -pub use self_type::*; - -pub mod signed_integer_type; -pub use signed_integer_type::*; - -pub mod tuple_type; -pub use tuple_type::*; - pub mod type_; pub use type_::*; - -pub mod unsigned_integer_type; -pub use unsigned_integer_type::*; diff --git a/ast/src/types/type_.rs b/ast/src/types/type_.rs index 3664b232ab..554e524898 100644 --- a/ast/src/types/type_.rs +++ b/ast/src/types/type_.rs @@ -14,30 +14,220 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ast::Rule, types::*}; +use crate::{ArrayDimensions, Identifier, IntegerType}; +use leo_grammar::types::{ArrayType, CircuitType, DataType, TupleType, Type as GrammarType}; +use leo_input::types::{ + ArrayType as InputArrayType, + DataType as InputDataType, + TupleType as InputTupleType, + Type as InputType, +}; -use pest_ast::FromPest; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::type_))] -pub enum Type<'ast> { - Basic(DataType), - Array(ArrayType<'ast>), - Tuple(TupleType<'ast>), - Circuit(CircuitType<'ast>), - SelfType(SelfType<'ast>), +/// Explicit type used for defining a variable or expression type +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Type { + // Data types + Address, + Boolean, + Field, + Group, + IntegerType(IntegerType), + + // Data type wrappers + Array(Box, ArrayDimensions), + Tuple(Vec), + Circuit(Identifier), + SelfType, } -impl<'ast> fmt::Display for Type<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Type::Basic(ref _type) => write!(f, "basic"), - Type::Array(ref _type) => write!(f, "array"), - Type::Tuple(ref _type) => write!(f, "tuple"), - Type::Circuit(ref _type) => write!(f, "struct"), - Type::SelfType(ref type_) => write!(f, "{}", type_.keyword), +impl Type { + /// + /// Returns `true` if the self `Type` is the `SelfType`. + /// + pub fn is_self(&self) -> bool { + matches!(self, Type::SelfType) + } + + /// + /// Returns `true` if the self `Type` is a `Circuit`. + /// + pub fn is_circuit(&self) -> bool { + matches!(self, Type::Circuit(_)) + } + + /// + /// Returns `true` if the self `Type` is equal to the other `Type`. + /// + /// Flattens array syntax: `[[u8; 1]; 2] == [u8; (2, 1)] == true` + /// + pub fn eq_flat(&self, other: &Self) -> bool { + match (self, other) { + (Type::Address, Type::Address) => true, + (Type::Boolean, Type::Boolean) => true, + (Type::Field, Type::Field) => true, + (Type::Group, Type::Group) => true, + (Type::IntegerType(left), Type::IntegerType(right)) => left.eq(&right), + (Type::Circuit(left), Type::Circuit(right)) => left.eq(&right), + (Type::SelfType, Type::SelfType) => true, + (Type::Array(left_type, left_dim), Type::Array(right_type, right_dim)) => { + // Convert array dimensions to owned. + let mut left_dim_owned = left_dim.to_owned(); + let mut right_dim_owned = right_dim.to_owned(); + + // Remove the first element from both dimensions. + let left_first = left_dim_owned.remove_first(); + let right_first = right_dim_owned.remove_first(); + + // Compare the first dimensions. + if left_first.ne(&right_first) { + return false; + } + + // Create a new array type from the remaining array dimensions. + let left_new_type = inner_array_type(*left_type.to_owned(), left_dim_owned); + let right_new_type = inner_array_type(*right_type.to_owned(), right_dim_owned); + + // Call eq_flat() on the new left and right types. + left_new_type.eq_flat(&right_new_type) + } + (Type::Tuple(left), Type::Tuple(right)) => left + .iter() + .zip(right) + .all(|(left_type, right_type)| left_type.eq_flat(right_type)), + _ => false, } } } + +/// pest ast -> Explicit Type for defining circuit members and function params + +impl From for Type { + fn from(data_type: DataType) -> Self { + match data_type { + DataType::Address(_type) => Type::Address, + DataType::Boolean(_type) => Type::Boolean, + DataType::Field(_type) => Type::Field, + DataType::Group(_type) => Type::Group, + DataType::Integer(_type) => Type::IntegerType(IntegerType::from(_type)), + } + } +} + +impl<'ast> From> for Type { + fn from(array_type: ArrayType<'ast>) -> Self { + let element_type = Box::new(Type::from(*array_type.type_)); + let dimensions = ArrayDimensions::from(array_type.dimensions); + + Type::Array(element_type, dimensions) + } +} + +impl<'ast> From> for Type { + fn from(tuple_type: TupleType<'ast>) -> Self { + let types = tuple_type.types.into_iter().map(Type::from).collect(); + + Type::Tuple(types) + } +} + +impl<'ast> From> for Type { + fn from(circuit_type: CircuitType<'ast>) -> Self { + Type::Circuit(Identifier::from(circuit_type.identifier)) + } +} + +impl<'ast> From> for Type { + fn from(type_: GrammarType<'ast>) -> Self { + match type_ { + GrammarType::Basic(type_) => Type::from(type_), + GrammarType::Array(type_) => Type::from(type_), + GrammarType::Tuple(type_) => Type::from(type_), + GrammarType::Circuit(type_) => Type::from(type_), + GrammarType::SelfType(_type) => Type::SelfType, + } + } +} + +/// input pest ast -> Explicit Type + +impl From for Type { + fn from(data_type: InputDataType) -> Self { + match data_type { + InputDataType::Address(_type) => Type::Address, + InputDataType::Boolean(_type) => Type::Boolean, + InputDataType::Field(_type) => Type::Field, + InputDataType::Group(_type) => Type::Group, + InputDataType::Integer(type_) => Type::IntegerType(IntegerType::from(type_)), + } + } +} + +impl<'ast> From> for Type { + fn from(array_type: InputArrayType<'ast>) -> Self { + let element_type = Box::new(Type::from(*array_type.type_)); + let dimensions = ArrayDimensions::from(array_type.dimensions); + + Type::Array(element_type, dimensions) + } +} + +impl<'ast> From> for Type { + fn from(tuple_type: InputTupleType<'ast>) -> Self { + let types = tuple_type.types_.into_iter().map(Type::from).collect(); + + Type::Tuple(types) + } +} + +impl<'ast> From> for Type { + fn from(type_: InputType<'ast>) -> Self { + match type_ { + InputType::Basic(type_) => Type::from(type_), + InputType::Array(type_) => Type::from(type_), + InputType::Tuple(type_) => Type::from(type_), + } + } +} + +impl fmt::Display for Type { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Type::Address => write!(f, "address"), + Type::Boolean => write!(f, "bool"), + Type::Field => write!(f, "field"), + Type::Group => write!(f, "group"), + Type::IntegerType(ref integer_type) => write!(f, "{}", integer_type), + Type::Circuit(ref variable) => write!(f, "circuit {}", variable), + Type::SelfType => write!(f, "SelfType"), + Type::Array(ref array, ref dimensions) => write!(f, "[{}; {}]", *array, dimensions), + Type::Tuple(ref tuple) => { + let types = tuple.iter().map(|x| x.to_string()).collect::>().join(", "); + + write!(f, "({})", types) + } + } + } +} + +/// +/// Returns the type of the inner array given an array element and array dimensions. +/// +/// If the array has no dimensions, then an inner array does not exist. Simply return the given +/// element type. +/// +/// If the array has dimensions, then an inner array exists. Create a new type for the +/// inner array. The element type of the new array should be the same as the old array. The +/// dimensions of the new array should be the old array dimensions with the first dimension removed. +/// +pub fn inner_array_type(element_type: Type, dimensions: ArrayDimensions) -> Type { + if dimensions.is_empty() { + // The array has one dimension. + element_type + } else { + // The array has multiple dimensions. + Type::Array(Box::new(element_type), dimensions) + } +} diff --git a/ast/tests/mod.rs b/ast/tests/mod.rs index b4ed4e6d07..6698b5585a 100644 --- a/ast/tests/mod.rs +++ b/ast/tests/mod.rs @@ -14,7 +14,4 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -mod expression; -mod function; mod serialization; -mod tuple; diff --git a/typed/tests/serialization/expected_typed_ast.json b/ast/tests/serialization/expected_leo_ast.json similarity index 96% rename from typed/tests/serialization/expected_typed_ast.json rename to ast/tests/serialization/expected_leo_ast.json index 24c02118af..f542246816 100644 --- a/typed/tests/serialization/expected_typed_ast.json +++ b/ast/tests/serialization/expected_leo_ast.json @@ -1,5 +1,5 @@ { - "name": "leo_typed_tree", + "name": "leo_tree", "expected_input": [], "imports": [], "circuits": {}, @@ -7,7 +7,7 @@ "{\"name\":\"main\",\"span\":\"{\\\"text\\\":\\\" function main() {\\\",\\\"line\\\":1,\\\"start\\\":10,\\\"end\\\":14}\"}": { "identifier": "{\"name\":\"main\",\"span\":\"{\\\"text\\\":\\\" function main() {\\\",\\\"line\\\":1,\\\"start\\\":10,\\\"end\\\":14}\"}", "input": [], - "returns": null, + "output": null, "statements": [ { "Return": [ diff --git a/ast/tests/serialization/json.rs b/ast/tests/serialization/json.rs index 30f411a5d9..35edba92ae 100644 --- a/ast/tests/serialization/json.rs +++ b/ast/tests/serialization/json.rs @@ -14,25 +14,81 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . +use leo_ast::LeoAst; +#[cfg(not(feature = "ci_skip"))] +use leo_ast::Program; +use leo_grammar::Grammar; + +use std::path::{Path, PathBuf}; + +fn to_ast(program_filepath: &Path) -> LeoAst { + // Loads the Leo code as a string from the given file path. + let program_string = Grammar::load_file(program_filepath).unwrap(); + + // Parses the Leo file and constructs a grammar ast. + let ast = Grammar::new(&program_filepath, &program_string).unwrap(); + + // Parses the pest ast and constructs a Leo ast. + LeoAst::new("leo_tree", &ast) +} + #[test] #[cfg(not(feature = "ci_skip"))] fn test_serialize() { - use leo_ast::LeoAst; - use std::path::PathBuf; + // Construct a ast from the given test file. + let leo_ast = { + let mut program_filepath = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + program_filepath.push("tests/serialization/main.leo"); - let mut program_filepath = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - program_filepath.push("tests/serialization/main.leo"); + to_ast(&program_filepath) + }; - let expected = include_str!("./expected_ast.json"); + // Serializes the ast into JSON format. + let serialized_leo_ast: Program = + serde_json::from_value(serde_json::to_value(leo_ast.into_repr()).unwrap()).unwrap(); - // Loads the Leo code as a string from the given file path. - let program_string = LeoAst::load_file(&program_filepath).unwrap(); + // Load the expected ast. + let expected: Program = serde_json::from_str(include_str!("expected_leo_ast.json")).unwrap(); - // Parses the Leo file and constructs an abstract syntax tree. - let ast = LeoAst::new(&program_filepath, &program_string).unwrap(); - - // Serializes the abstract syntax tree into JSON format. - let serialized_ast = LeoAst::to_json_string(&ast).unwrap(); - - assert_eq!(expected, serialized_ast); + assert_eq!(expected, serialized_leo_ast); +} + +#[test] +#[cfg(not(feature = "ci_skip"))] +fn test_deserialize() { + // Load the expected ast. + let expected_leo_ast = { + let mut program_filepath = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + program_filepath.push("tests/serialization/main.leo"); + + to_ast(&program_filepath) + }; + + // Construct an ast by deserializing a ast JSON file. + let serialized_ast = include_str!("expected_leo_ast.json"); + let leo_ast = LeoAst::from_json_string(serialized_ast).unwrap(); + + assert_eq!(expected_leo_ast, leo_ast); +} + +#[test] +fn test_serialize_deserialize_serialize() { + // Construct a ast from the given test file. + let leo_ast = { + let mut program_filepath = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + program_filepath.push("tests/serialization/main.leo"); + + to_ast(&program_filepath) + }; + + // Serializes the ast into JSON format. + let serialized_leo_ast = leo_ast.to_json_string().unwrap(); + + // Deserializes the serialized ast into a LeoAst. + let leo_ast = LeoAst::from_json_string(&serialized_leo_ast).unwrap(); + + // Reserializes the ast into JSON format. + let reserialized_leo_ast = leo_ast.to_json_string().unwrap(); + + assert_eq!(serialized_leo_ast, reserialized_leo_ast); } diff --git a/compiler/Cargo.toml b/compiler/Cargo.toml index 8d741880ae..aa18805cce 100644 --- a/compiler/Cargo.toml +++ b/compiler/Cargo.toml @@ -23,12 +23,20 @@ version = "1.0.4" [dependencies.leo-core] path = "../core" -version = "1.0.2" +version = "1.0.4" [dependencies.leo-gadgets] path = "../gadgets" version = "1.0.4" +[dependencies.leo-grammar] +path = "../grammar" +version = "1.0.4" + +[dependencies.leo-imports] +path = "../imports" +version = "1.0.4" + [dependencies.leo-input] path = "../input" version = "1.0.4" @@ -37,14 +45,18 @@ version = "1.0.4" path = "../package" version = "1.0.4" -[dependencies.leo-typed] -path = "../typed" -version = "1.0.4" - [dependencies.leo-state] path = "../state" version = "1.0.4" +#[dependencies.leo-symbol-table] +#path = "../symbol-table" +#version = "1.0.4" + +#[dependencies.leo-type-inference] +#path = "../type-inference" +#version = "1.0.4" + [dependencies.snarkos-curves] version = "1.1.3" default-features = false @@ -112,4 +124,4 @@ default-features = false [features] default = [ ] -ci_skip = [ "leo-ast/ci_skip", "leo-typed/ci_skip" ] +ci_skip = [ "leo-grammar/ci_skip", "leo-ast/ci_skip" ] diff --git a/compiler/src/compiler.rs b/compiler/src/compiler.rs index 07bedb610f..c17eb9c398 100644 --- a/compiler/src/compiler.rs +++ b/compiler/src/compiler.rs @@ -20,15 +20,17 @@ use crate::{ constraints::{generate_constraints, generate_test_constraints}, errors::CompilerError, GroupType, - ImportParser, OutputBytes, OutputFile, }; -use leo_ast::LeoAst; +use leo_ast::{Input, LeoAst, MainInput, Program}; +use leo_grammar::Grammar; +use leo_imports::ImportParser; use leo_input::LeoInputParser; use leo_package::inputs::InputPairs; use leo_state::verify_local_data_commitment; -use leo_typed::{Input, LeoTypedAst, MainInput, Program}; +// use leo_symbol_table::SymbolTable; +// use leo_type_inference::TypeInference; use snarkos_dpc::{base_dpc::instantiated::Components, SystemParameters}; use snarkos_errors::gadgets::SynthesisError; @@ -44,6 +46,7 @@ use std::{ path::{Path, PathBuf}, }; +/// Stores information to compile a Leo program. #[derive(Clone)] pub struct Compiler> { package_name: String, @@ -57,6 +60,9 @@ pub struct Compiler> { } impl> Compiler { + /// + /// Returns a new Leo program compiler. + /// pub fn new(package_name: String, main_file_path: PathBuf, output_directory: PathBuf) -> Self { Self { package_name: package_name.clone(), @@ -64,14 +70,62 @@ impl> Compiler { output_directory, program: Program::new(package_name), program_input: Input::new(), - imported_programs: ImportParser::new(), + imported_programs: ImportParser::default(), _engine: PhantomData, _group: PhantomData, } } - /// Parse the input and state files. - /// Stores a typed ast of all input variables to the program. + /// + /// Returns a new `Compiler` from the given main file path. + /// + /// Parses and stores a program from the main file path. + /// Parses and stores all imported programs. + /// Performs type inference checking on the program and imported programs. + /// + pub fn parse_program_without_input( + package_name: String, + main_file_path: PathBuf, + output_directory: PathBuf, + ) -> Result { + let mut compiler = Self::new(package_name, main_file_path, output_directory); + + compiler.parse_and_check_program()?; + + Ok(compiler) + } + + /// + /// Returns a new `Compiler` from the given main file path. + /// + /// Parses and stores program input from from the input file path and state file path + /// Parses and stores a program from the main file path. + /// Parses and stores all imported programs. + /// Performs type inference checking on the program, imported programs, and program input. + /// + pub fn parse_program_with_input( + package_name: String, + main_file_path: PathBuf, + output_directory: PathBuf, + input_string: &str, + input_path: &Path, + state_string: &str, + state_path: &Path, + ) -> Result { + let mut compiler = Self::new(package_name, main_file_path, output_directory); + + compiler.parse_input(input_string, input_path, state_string, state_path)?; + + compiler.parse_and_check_program()?; + + Ok(compiler) + } + + /// + /// Parses and stores program input from from the input file path and state file path + /// + /// Calls `set_path()` on compiler errors with the given input file path or state file path + /// pub fn parse_input( &mut self, input_string: &str, @@ -104,55 +158,83 @@ impl> Compiler { Ok(()) } - /// Parses program files. - /// Returns a compiler struct that stores the typed program abstract syntax trees (ast). - pub fn parse_program_without_input( - package_name: String, - main_file_path: PathBuf, - output_directory: PathBuf, - ) -> Result { - let mut compiler = Self::new(package_name, main_file_path, output_directory); + /// + /// Runs program parser and type inference checker consecutively. + /// + pub(crate) fn parse_and_check_program(&mut self) -> Result<(), CompilerError> { + self.parse_program()?; - compiler.parse_program()?; - - Ok(compiler) + self.check_program() } - /// Parses input, state, and program files. - /// Returns a compiler struct that stores the typed input and typed program abstract syntax trees (ast). - pub fn parse_program_with_input( - package_name: String, - main_file_path: PathBuf, - output_directory: PathBuf, - input_string: &str, - input_path: &Path, - state_string: &str, - state_path: &Path, - ) -> Result { - let mut compiler = Self::new(package_name, main_file_path, output_directory); - - compiler.parse_input(input_string, input_path, state_string, state_path)?; - - compiler.parse_program()?; - - Ok(compiler) - } - - /// Parses the Leo program file, constructs a syntax tree, and generates a program. - #[allow(deprecated)] + /// + /// Parses and stores the main program file, constructs a syntax tree, and generates a program. + /// + /// Parses and stores all programs imported by the main program file. + /// pub(crate) fn parse_program(&mut self) -> Result<(), CompilerError> { - // Use the parser to construct the abstract syntax tree. - let program_string = LeoAst::load_file(&self.main_file_path)?; + // Load the program file. + let program_string = Grammar::load_file(&self.main_file_path)?; - self.parse_program_from_string(&program_string) + // Use the parser to construct the pest abstract syntax tree (ast). + let pest_ast = Grammar::new(&self.main_file_path, &program_string).map_err(|mut e| { + e.set_path(&self.main_file_path); + + e + })?; + + // Construct the core ast from the pest ast. + let core_ast = LeoAst::new(&self.package_name, &pest_ast); + + // Store the main program file. + self.program = core_ast.into_repr(); + + // Parse and store all programs imported by the main program file. + self.imported_programs = ImportParser::parse(&self.program)?; + + tracing::debug!("Program parsing complete\n{:#?}", self.program); + + Ok(()) } - /// Parses the Leo program string, constructs a syntax tree, and generates a program. + /// + /// Runs a type check on the program, imports, and input. + /// + /// First, a symbol table of all user defined types is created. + /// Second, a type inference check is run on the program - inferring a data type for all implicit types and + /// catching type mismatch errors. + /// + pub(crate) fn check_program(&self) -> Result<(), CompilerError> { + // // Create a new symbol table from the program, imported_programs, and program_input. + // let _symbol_table = + // SymbolTable::new(&self.program, &self.imported_programs, &self.program_input).map_err(|mut e| { + // e.set_path(&self.main_file_path); + // + // e + // })?; + + // // Run type inference check on program. + // TypeInference::new(&self.program, symbol_table).map_err(|mut e| { + // e.set_path(&self.main_file_path); + // + // e + // })?; + + tracing::debug!("Program checks complete"); + + Ok(()) + } + + /// + /// Equivalent to parse_and_check_program but uses the given program_string instead of a main + /// file path. + /// /// Used for testing only. + /// #[deprecated(note = "Please use the 'parse_program' method instead.")] pub fn parse_program_from_string(&mut self, program_string: &str) -> Result<(), CompilerError> { // Use the given bytes to construct the abstract syntax tree. - let ast = LeoAst::new(&self.main_file_path, &program_string).map_err(|mut e| { + let ast = Grammar::new(&self.main_file_path, &program_string).map_err(|mut e| { e.set_path(&self.main_file_path); e @@ -161,23 +243,38 @@ impl> Compiler { // Derive the package name. let package_name = &self.package_name; - // Use the typed parser to construct the typed syntax tree. - let typed_tree = LeoTypedAst::new(package_name, &ast); + // Construct the core ast from the pest ast. + let core_ast = LeoAst::new(package_name, &ast); - self.program = typed_tree.into_repr(); + // Store the main program file. + self.program = core_ast.into_repr(); + + // Parse and store all programs imported by the main program file. self.imported_programs = ImportParser::parse(&self.program)?; + // // Create a new symbol table from the program, imported programs, and program input. + // let _symbol_table = SymbolTable::new(&self.program, &self.imported_programs, &self.program_input)?; + + // // Run type inference check on program. + // TypeInference::new(&self.program, symbol_table)?; + tracing::debug!("Program parsing complete\n{:#?}", self.program); Ok(()) } - /// Manually sets main function input + /// + /// Manually sets main function input. + /// + /// Used for testing only. + /// pub fn set_main_input(&mut self, input: MainInput) { self.program_input.set_main_input(input); } - /// Verifies the input to the program + /// + /// Verifies the input to the program. + /// pub fn verify_local_data_commitment( &self, system_parameters: &SystemParameters, @@ -187,6 +284,9 @@ impl> Compiler { Ok(result) } + /// + /// Returns a Sha256 checksum of the program file. + /// pub fn checksum(&self) -> Result { // Read in the main file as string let unparsed_file = fs::read_to_string(&self.main_file_path) @@ -200,7 +300,9 @@ impl> Compiler { Ok(hex::encode(hash)) } + /// /// Synthesizes the circuit without program input to verify correctness. + /// pub fn compile_constraints>(self, cs: &mut CS) -> Result { let path = self.main_file_path; @@ -213,7 +315,9 @@ impl> Compiler { ) } + /// /// Synthesizes the circuit for test functions with program input. + /// pub fn compile_test_constraints(self, input_pairs: InputPairs) -> Result<(u32, u32), CompilerError> { generate_test_constraints::( self.program, @@ -224,7 +328,9 @@ impl> Compiler { ) } - /// Calls the internal generate_constraints method with arguments + /// + /// Calls the internal generate_constraints method with arguments. + /// pub fn generate_constraints_helper>( self, cs: &mut CS, @@ -237,30 +343,12 @@ impl> Compiler { }, ) } - - pub fn to_bytes(&self) -> Result, CompilerError> { - Ok(bincode::serialize(&self.program)?) - } - - pub fn from_bytes(bytes: &[u8]) -> Result { - let program: Program = bincode::deserialize(bytes)?; - let program_input = Input::new(); - - Ok(Self { - package_name: program.name.clone(), - main_file_path: PathBuf::new(), - output_directory: PathBuf::new(), - program, - program_input, - imported_programs: ImportParser::new(), - _engine: PhantomData, - _group: PhantomData, - }) - } } impl> ConstraintSynthesizer for Compiler { + /// /// Synthesizes the circuit with program input. + /// fn generate_constraints>(self, cs: &mut CS) -> Result<(), SynthesisError> { let output_directory = self.output_directory.clone(); let package_name = self.package_name.clone(); diff --git a/compiler/src/console/assert.rs b/compiler/src/console/assert.rs index 6e407c215b..66465bd11f 100644 --- a/compiler/src/console/assert.rs +++ b/compiler/src/console/assert.rs @@ -17,7 +17,7 @@ //! Enforces an assert equals statement in a compiled Leo program. use crate::{errors::ConsoleError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::{Expression, Span, Type}; +use leo_ast::{Expression, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/console/console.rs b/compiler/src/console/console.rs index af8da4ac25..1be1d801cb 100644 --- a/compiler/src/console/console.rs +++ b/compiler/src/console/console.rs @@ -17,7 +17,7 @@ //! Evaluates a macro in a compiled Leo program. use crate::{errors::ConsoleError, program::ConstrainedProgram, GroupType}; -use leo_typed::{ConsoleFunction, ConsoleFunctionCall}; +use leo_ast::{ConsoleFunction, ConsoleFunctionCall}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/console/format.rs b/compiler/src/console/format.rs index 87f2db1fb5..05cabbdc15 100644 --- a/compiler/src/console/format.rs +++ b/compiler/src/console/format.rs @@ -17,7 +17,7 @@ //! Evaluates a formatted string in a compiled Leo program. use crate::{errors::ConsoleError, program::ConstrainedProgram, GroupType}; -use leo_typed::FormattedString; +use leo_ast::FormattedString; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/constraints/constraints.rs b/compiler/src/constraints/constraints.rs index 215224eaad..0027f0762e 100644 --- a/compiler/src/constraints/constraints.rs +++ b/compiler/src/constraints/constraints.rs @@ -22,14 +22,14 @@ use crate::{ ConstrainedProgram, ConstrainedValue, GroupType, - ImportParser, OutputBytes, OutputFile, }; -use leo_typed::{Input, Program}; - +use leo_ast::{Input, Program}; +use leo_imports::ImportParser; use leo_input::LeoInputParser; use leo_package::inputs::InputPairs; + use snarkos_models::{ curves::{Field, PrimeField}, gadgets::r1cs::{ConstraintSystem, TestConstraintSystem}, @@ -48,9 +48,7 @@ pub fn generate_constraints, CS: Constrai resolved_program.store_definitions(program, imported_programs)?; - let main = resolved_program - .get(&main_function_name) - .ok_or_else(|| CompilerError::NoMain)?; + let main = resolved_program.get(&main_function_name).ok_or(CompilerError::NoMain)?; match main.clone() { ConstrainedValue::Function(_circuit_identifier, function) => { diff --git a/compiler/src/definition/definition.rs b/compiler/src/definition/definition.rs index d78aa90aa0..b684eadb75 100644 --- a/compiler/src/definition/definition.rs +++ b/compiler/src/definition/definition.rs @@ -21,7 +21,7 @@ use crate::{ value::ConstrainedValue, GroupType, }; -use leo_typed::Identifier; +use leo_ast::Identifier; use snarkos_models::curves::{Field, PrimeField}; diff --git a/compiler/src/definition/definitions.rs b/compiler/src/definition/definitions.rs index 9eaa597007..46bfa7ea07 100644 --- a/compiler/src/definition/definitions.rs +++ b/compiler/src/definition/definitions.rs @@ -21,9 +21,9 @@ use crate::{ program::{new_scope, ConstrainedProgram}, value::ConstrainedValue, GroupType, - ImportParser, }; -use leo_typed::Program; +use leo_ast::Program; +use leo_imports::ImportParser; use snarkos_models::curves::{Field, PrimeField}; diff --git a/compiler/src/errors/compiler.rs b/compiler/src/errors/compiler.rs index 762b0f0e1c..4239c18e7f 100644 --- a/compiler/src/errors/compiler.rs +++ b/compiler/src/errors/compiler.rs @@ -15,9 +15,12 @@ // along with the Leo library. If not, see . use crate::errors::{FunctionError, ImportError, OutputBytesError, OutputFileError}; -use leo_ast::ParserError; +use leo_grammar::ParserError; +use leo_imports::ImportParserError; use leo_input::InputParserError; use leo_state::LocalDataVerificationError; +// use leo_symbol_table::SymbolTableError; +// use leo_type_inference::TypeInferenceError; use bincode::Error as SerdeError; use std::path::{Path, PathBuf}; @@ -27,6 +30,9 @@ pub enum CompilerError { #[error("{}", _0)] ImportError(#[from] ImportError), + #[error("{}", _0)] + ImportParserError(#[from] ImportParserError), + #[error("{}", _0)] InputParserError(#[from] InputParserError), @@ -62,6 +68,11 @@ pub enum CompilerError { #[error("{}", _0)] SerdeError(#[from] SerdeError), + // #[error("{}", _0)] + // SymbolTableError(#[from] SymbolTableError), + + // #[error("{}", _0)] + // TypeInferenceError(#[from] TypeInferenceError), } impl CompilerError { @@ -70,6 +81,8 @@ impl CompilerError { CompilerError::InputParserError(error) => error.set_path(path), CompilerError::FunctionError(error) => error.set_path(path), CompilerError::OutputStringError(error) => error.set_path(path), + // CompilerError::SymbolTableError(error) => error.set_path(path), + // CompilerError::TypeInferenceError(error) => error.set_path(path), _ => {} } } diff --git a/compiler/src/errors/console.rs b/compiler/src/errors/console.rs index 330dd15d52..7366bf806f 100644 --- a/compiler/src/errors/console.rs +++ b/compiler/src/errors/console.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::errors::ExpressionError; -use leo_typed::{Error as FormattedError, Span}; +use leo_ast::{Error as FormattedError, Span}; use std::path::Path; diff --git a/compiler/src/errors/expression.rs b/compiler/src/errors/expression.rs index bb0ee8577f..41a83cd6f2 100644 --- a/compiler/src/errors/expression.rs +++ b/compiler/src/errors/expression.rs @@ -15,8 +15,8 @@ // along with the Leo library. If not, see . use crate::errors::{AddressError, BooleanError, FieldError, FunctionError, GroupError, IntegerError, ValueError}; -use leo_core::LeoCoreError; -use leo_typed::{Error as FormattedError, Identifier, Span}; +use leo_ast::{ArrayDimensions, Error as FormattedError, Identifier, PositiveNumber, Span}; +use leo_core::LeoCorePackageError; use snarkos_errors::gadgets::SynthesisError; use std::path::Path; @@ -45,7 +45,7 @@ pub enum ExpressionError { IntegerError(#[from] IntegerError), #[error("{}", _0)] - LeoCoreError(#[from] LeoCoreError), + LeoCoreError(#[from] LeoCorePackageError), #[error("{}", _0)] ValueError(#[from] ValueError), @@ -109,12 +109,30 @@ impl ExpressionError { Self::new_from_span(message, span) } - pub fn invalid_index(actual: String, span: Span) -> Self { - let message = format!("index must resolve to an integer, found `{}`", actual); + pub fn invalid_dimensions(expected: &ArrayDimensions, actual: &ArrayDimensions, span: Span) -> Self { + let message = format!( + "expected array dimensions {}, found array dimensions {}", + expected, actual + ); Self::new_from_span(message, span) } + pub fn invalid_first_dimension(expected: &PositiveNumber, actual: &PositiveNumber) -> Self { + let message = format!( + "expected array dimension {}, found array dimension {}", + expected, actual + ); + + Self::new_from_span(message, actual.span.to_owned()) + } + + pub fn invalid_index(actual: String, span: &Span) -> Self { + let message = format!("index must resolve to an integer, found `{}`", actual); + + Self::new_from_span(message, span.to_owned()) + } + pub fn invalid_length(expected: usize, actual: usize, span: Span) -> Self { let message = format!("expected array length {}, found one with length {}", expected, actual); @@ -157,6 +175,12 @@ impl ExpressionError { Self::new_from_span(message, span) } + pub fn undefined_tuple(actual: String, span: Span) -> Self { + let message = format!("tuple `{}` must be declared before it is used in an expression", actual); + + Self::new_from_span(message, span) + } + pub fn undefined_circuit(actual: String, span: Span) -> Self { let message = format!( "circuit `{}` must be declared before it is used in an expression", @@ -166,10 +190,10 @@ impl ExpressionError { Self::new_from_span(message, span) } - pub fn undefined_identifier(identifier: Identifier) -> Self { - let message = format!("cannot find value `{}` in this scope", identifier.name); + pub fn undefined_first_dimension(span: Span) -> Self { + let message = "the first dimension of the array must be a number".to_string(); - Self::new_from_span(message, identifier.span) + Self::new_from_span(message, span) } pub fn undefined_function(function: String, span: Span) -> Self { @@ -181,6 +205,12 @@ impl ExpressionError { Self::new_from_span(message, span) } + pub fn undefined_identifier(identifier: Identifier) -> Self { + let message = format!("cannot find value `{}` in this scope", identifier.name); + + Self::new_from_span(message, identifier.span) + } + pub fn undefined_member_access(circuit: String, member: String, span: Span) -> Self { let message = format!("Circuit `{}` has no member `{}`", circuit, member); diff --git a/compiler/src/errors/function.rs b/compiler/src/errors/function.rs index f4ccd09231..8f22e1fb87 100644 --- a/compiler/src/errors/function.rs +++ b/compiler/src/errors/function.rs @@ -25,7 +25,7 @@ use crate::errors::{ StatementError, ValueError, }; -use leo_typed::{Error as FormattedError, Span}; +use leo_ast::{Error as FormattedError, Span}; use std::path::Path; diff --git a/compiler/src/errors/import.rs b/compiler/src/errors/import.rs index 221effa76f..a38de223ad 100644 --- a/compiler/src/errors/import.rs +++ b/compiler/src/errors/import.rs @@ -14,11 +14,8 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_ast::ParserError; -use leo_typed::{Error as FormattedError, Identifier, ImportSymbol, Span}; - -use leo_core::LeoCoreError; -use std::{io, path::Path}; +use leo_ast::{Error as FormattedError, Identifier, ImportSymbol, Span}; +use leo_core::LeoCorePackageError; #[derive(Debug, Error)] pub enum ImportError { @@ -26,10 +23,7 @@ pub enum ImportError { Error(#[from] FormattedError), #[error("{}", _0)] - LeoCoreError(#[from] LeoCoreError), - - #[error("{}", _0)] - ParserError(#[from] ParserError), + LeoCoreError(#[from] LeoCorePackageError), } impl ImportError { @@ -37,55 +31,6 @@ impl ImportError { ImportError::Error(FormattedError::new_from_span(message, span)) } - fn new_from_span_with_path(message: String, span: Span, path: &Path) -> Self { - ImportError::Error(FormattedError::new_from_span_with_path(message, span, path)) - } - - pub fn conflicting_imports(identifier: Identifier) -> Self { - let message = format!("conflicting imports found for `{}`", identifier.name); - - Self::new_from_span(message, identifier.span) - } - - pub fn convert_os_string(span: Span) -> Self { - let message = "failed to convert file string name, maybe an illegal character?".to_string(); - - Self::new_from_span(message, span) - } - - pub fn current_directory_error(error: io::Error) -> Self { - let span = Span { - text: "".to_string(), - line: 0, - start: 0, - end: 0, - }; - let message = format!("compilation failed trying to find current directory - {:?}", error); - - Self::new_from_span(message, span) - } - - pub fn directory_error(error: io::Error, span: Span, path: &Path) -> Self { - let message = format!("compilation failed due to directory error - {:?}", error); - - Self::new_from_span_with_path(message, span, path) - } - - pub fn star(path: &Path, span: Span) -> Self { - let message = format!("cannot import `*` from path `{:?}`", path); - - Self::new_from_span(message, span) - } - - pub fn expected_lib_file(entry: String, span: Span) -> Self { - let message = format!( - "expected library file`{}` when looking for symbol `{}`", - entry, span.text - ); - - Self::new_from_span(message, span) - } - pub fn unknown_package(identifier: Identifier) -> Self { let message = format!( "cannot find imported package `{}` in source files or import directory", diff --git a/compiler/src/errors/output_bytes.rs b/compiler/src/errors/output_bytes.rs index d9ef930f35..d07af02bfa 100644 --- a/compiler/src/errors/output_bytes.rs +++ b/compiler/src/errors/output_bytes.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_typed::{Error as FormattedError, Span}; +use leo_ast::{Error as FormattedError, Span}; use std::path::Path; diff --git a/compiler/src/errors/statement.rs b/compiler/src/errors/statement.rs index e39dd2e53d..a70770ca53 100644 --- a/compiler/src/errors/statement.rs +++ b/compiler/src/errors/statement.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::errors::{AddressError, BooleanError, ConsoleError, ExpressionError, IntegerError, ValueError}; -use leo_typed::{Error as FormattedError, Span, Type}; +use leo_ast::{Error as FormattedError, Span, Type}; use std::path::Path; diff --git a/compiler/src/errors/value/address.rs b/compiler/src/errors/value/address.rs index 52e84aaccd..c48ae4a993 100644 --- a/compiler/src/errors/value/address.rs +++ b/compiler/src/errors/value/address.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_typed::{Error as FormattedError, Span}; +use leo_ast::{Error as FormattedError, Span}; use snarkos_errors::{gadgets::SynthesisError, objects::account::AccountError}; use std::path::Path; diff --git a/compiler/src/errors/value/boolean.rs b/compiler/src/errors/value/boolean.rs index cafdc4e3f3..1160f38d7a 100644 --- a/compiler/src/errors/value/boolean.rs +++ b/compiler/src/errors/value/boolean.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_typed::{Error as FormattedError, Span}; +use leo_ast::{Error as FormattedError, Span}; use snarkos_errors::gadgets::SynthesisError; use std::path::Path; diff --git a/compiler/src/errors/value/field.rs b/compiler/src/errors/value/field.rs index 200749be95..5dda86a677 100644 --- a/compiler/src/errors/value/field.rs +++ b/compiler/src/errors/value/field.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_typed::{Error as FormattedError, Span}; +use leo_ast::{Error as FormattedError, Span}; use snarkos_errors::gadgets::SynthesisError; use std::path::Path; diff --git a/compiler/src/errors/value/group.rs b/compiler/src/errors/value/group.rs index 63c20d5aad..d03c6b502f 100644 --- a/compiler/src/errors/value/group.rs +++ b/compiler/src/errors/value/group.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_typed::{Error as FormattedError, Span}; +use leo_ast::{Error as FormattedError, Span}; use snarkos_errors::gadgets::SynthesisError; use std::path::Path; diff --git a/compiler/src/errors/value/integer.rs b/compiler/src/errors/value/integer.rs index 1133a487f9..5ff19eb492 100644 --- a/compiler/src/errors/value/integer.rs +++ b/compiler/src/errors/value/integer.rs @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . +use leo_ast::{error::Error as FormattedError, IntegerType, Span, Type}; use leo_gadgets::errors::SignedIntegerError; -use leo_typed::{error::Error as FormattedError, Span}; use snarkos_errors::gadgets::SynthesisError; use std::path::Path; @@ -96,6 +96,18 @@ impl IntegerError { Self::new_from_span(message, span) } + pub fn invalid_integer_type(expected: &IntegerType, actual: &IntegerType, span: Span) -> Self { + let message = format!("expected integer type {} found integer type {}", expected, actual); + + Self::new_from_span(message, span) + } + + pub fn invalid_type(actual: &Type, span: Span) -> Self { + let message = format!("expected type {}, found type IntegerType", actual); + + Self::new_from_span(message, span) + } + pub fn missing_integer(expected: String, span: Span) -> Self { let message = format!("expected integer input `{}` not found", expected); diff --git a/compiler/src/errors/value/value.rs b/compiler/src/errors/value/value.rs index 8f4a3248fa..41c4c50e0c 100644 --- a/compiler/src/errors/value/value.rs +++ b/compiler/src/errors/value/value.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::errors::{AddressError, BooleanError, FieldError, GroupError, IntegerError}; -use leo_typed::{Error as FormattedError, Span}; +use leo_ast::{Error as FormattedError, Span}; use std::path::Path; diff --git a/compiler/src/expression/arithmetic/add.rs b/compiler/src/expression/arithmetic/add.rs index ba4f09a33a..504a4c99af 100644 --- a/compiler/src/expression/arithmetic/add.rs +++ b/compiler/src/expression/arithmetic/add.rs @@ -17,7 +17,7 @@ //! Enforces an arithmetic `+` operator in a resolved Leo program. use crate::{errors::ExpressionError, value::ConstrainedValue, GroupType}; -use leo_typed::Span; +use leo_ast::Span; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/arithmetic/div.rs b/compiler/src/expression/arithmetic/div.rs index daf79b142c..6120e1ecf3 100644 --- a/compiler/src/expression/arithmetic/div.rs +++ b/compiler/src/expression/arithmetic/div.rs @@ -17,7 +17,7 @@ //! Enforces an arithmetic `/` operator in a resolved Leo program. use crate::{errors::ExpressionError, value::ConstrainedValue, GroupType}; -use leo_typed::Span; +use leo_ast::Span; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/arithmetic/mul.rs b/compiler/src/expression/arithmetic/mul.rs index 0849d7ccd4..71eea3a663 100644 --- a/compiler/src/expression/arithmetic/mul.rs +++ b/compiler/src/expression/arithmetic/mul.rs @@ -17,7 +17,7 @@ //! Enforces an arithmetic `*` operator in a resolved Leo program. use crate::{errors::ExpressionError, value::ConstrainedValue, GroupType}; -use leo_typed::Span; +use leo_ast::Span; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/arithmetic/negate.rs b/compiler/src/expression/arithmetic/negate.rs index 2996283ae0..43c3483713 100644 --- a/compiler/src/expression/arithmetic/negate.rs +++ b/compiler/src/expression/arithmetic/negate.rs @@ -17,7 +17,7 @@ //! Enforces a unary negate `-` operator in a resolved Leo program. use crate::{errors::ExpressionError, value::ConstrainedValue, GroupType}; -use leo_typed::Span; +use leo_ast::Span; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/arithmetic/pow.rs b/compiler/src/expression/arithmetic/pow.rs index a416e58ce6..403e5f97d2 100644 --- a/compiler/src/expression/arithmetic/pow.rs +++ b/compiler/src/expression/arithmetic/pow.rs @@ -17,7 +17,7 @@ //! Enforces an arithmetic `**` operator in a resolved Leo program. use crate::{errors::ExpressionError, value::ConstrainedValue, GroupType}; -use leo_typed::Span; +use leo_ast::Span; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/arithmetic/sub.rs b/compiler/src/expression/arithmetic/sub.rs index bbad8a4262..a21aea905b 100644 --- a/compiler/src/expression/arithmetic/sub.rs +++ b/compiler/src/expression/arithmetic/sub.rs @@ -17,7 +17,7 @@ //! Enforces an arithmetic `-` operator in a resolved Leo program. use crate::{errors::ExpressionError, value::ConstrainedValue, GroupType}; -use leo_typed::Span; +use leo_ast::Span; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/array/access.rs b/compiler/src/expression/array/access.rs index 7f7b64d7be..71ecf71487 100644 --- a/compiler/src/expression/array/access.rs +++ b/compiler/src/expression/array/access.rs @@ -17,7 +17,7 @@ //! Enforces array access in a compiled Leo program. use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::{Expression, RangeOrExpression, Span, Type}; +use leo_ast::{Expression, RangeOrExpression, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/array/array.rs b/compiler/src/expression/array/array.rs index 9ff67a1ea7..fe740cc069 100644 --- a/compiler/src/expression/array/array.rs +++ b/compiler/src/expression/array/array.rs @@ -22,7 +22,7 @@ use crate::{ value::ConstrainedValue, GroupType, }; -use leo_typed::{Expression, Span, SpreadOrExpression, Type}; +use leo_ast::{ArrayDimensions, Expression, PositiveNumber, Span, SpreadOrExpression, Type}; use snarkos_models::{ curves::{Field, PrimeField}, @@ -40,21 +40,29 @@ impl> ConstrainedProgram { array: Vec, span: Span, ) -> Result, ExpressionError> { - // Check explicit array type dimension if given - let mut expected_dimensions = vec![]; + let mut expected_dimension = None; + // Check explicit array type dimension if given if let Some(type_) = expected_type { match type_ { - Type::Array(ref type_, ref dimensions) => { - let number = match dimensions.first() { - Some(number) => *number, + Type::Array(type_, mut dimensions) => { + // Remove the first dimension of the array. + let first = match dimensions.remove_first() { + Some(number) => { + // Parse the array dimension into a `usize`. + parse_index(&number, &span)? + } None => return Err(ExpressionError::unexpected_array(type_.to_string(), span)), }; - expected_dimensions.push(number); - expected_type = Some(type_.outer_dimension(dimensions)); + // Update the expected dimension to the first dimension. + expected_dimension = Some(first); + + // Update the expected type to a new array type with the first dimension removed. + expected_type = Some(inner_array_type(*type_, dimensions)); } ref type_ => { + // Return an error if the expected type is not an array. return Err(ExpressionError::unexpected_array(type_.to_string(), span)); } } @@ -88,15 +96,161 @@ impl> ConstrainedProgram { } } - // Check expected_dimensions if given - if !expected_dimensions.is_empty() && expected_dimensions[expected_dimensions.len() - 1] != result.len() { - return Err(ExpressionError::invalid_length( - expected_dimensions[expected_dimensions.len() - 1], - result.len(), - span, - )); + // Check expected_dimension if given. + if let Some(dimension) = expected_dimension { + // Return an error if the expected dimension != the actual dimension. + if dimension != result.len() { + return Err(ExpressionError::invalid_length(dimension, result.len(), span)); + } } Ok(ConstrainedValue::Array(result)) } + + /// + /// Returns an array value from an array initializer expression. + /// + #[allow(clippy::too_many_arguments)] + pub fn enforce_array_initializer>( + &mut self, + cs: &mut CS, + file_scope: &str, + function_scope: &str, + expected_type: Option, + element_expression: Expression, + mut actual_dimensions: ArrayDimensions, + span: Span, + ) -> Result, ExpressionError> { + // Compare dimensions + // Case 1: expected == actual => enforce expression with array element type + // Case 2: expected first dimension == actual first dimension => enforce expression with updated array type + // Case 3: expected first dimension != actual first dimension => return mismatched dimensions error + + if let Some(Type::Array(type_, mut expected_dimensions)) = expected_type { + if expected_dimensions.eq(&actual_dimensions) { + // Case 1 - enforce expression with array element type + let mut value = + self.enforce_expression(cs, file_scope, function_scope, Some(*type_), element_expression)?; + + // Allocate the array. + while let Some(dimension) = actual_dimensions.remove_last() { + // Parse the dimension into a `usize`. + let dimension_usize = parse_index(&dimension, &span)?; + + // Allocate the array dimension. + let array = vec![value; dimension_usize]; + + // Set the array value. + value = ConstrainedValue::Array(array); + } + + Ok(value) + } else if expected_dimensions.first().eq(&actual_dimensions.first()) { + // Case 2 - enforce expression with updated array type. + let dimension = match expected_dimensions.remove_first() { + Some(number) => { + // Parse the array dimension into a `usize`. + parse_index(&number, &span)? + } + None => return Err(ExpressionError::unexpected_array(type_.to_string(), span)), + }; + + // Update the actual array dimensions. + let _first_dimension = actual_dimensions.remove_first(); + + // Update the expected type to a new array type with the first dimension removed. + let expected_expression_type = Some(inner_array_type(*type_, expected_dimensions)); + + // If the expression has more dimensions. + let element_value = match actual_dimensions.first() { + Some(_dimension) => { + // Get the value of the array element as an initializer. + self.enforce_array_initializer( + cs, + file_scope, + function_scope, + expected_expression_type, + element_expression, + actual_dimensions.clone(), + span, + )? + } + None => { + // Get the value of the array element as an expression. + self.enforce_expression( + cs, + file_scope, + function_scope, + expected_expression_type, + element_expression, + )? + } + }; + + // Allocate the array of values. + let array_values = vec![element_value; dimension]; + + // Create a new value with the expected dimension. + Ok(ConstrainedValue::Array(array_values)) + } else { + // Case 3 - return mismatched dimensions error. + Err(ExpressionError::invalid_first_dimension( + expected_dimensions + .first() + .ok_or_else(|| ExpressionError::undefined_first_dimension(span.clone()))?, + actual_dimensions + .first() + .ok_or_else(|| ExpressionError::undefined_first_dimension(span))?, + )) + } + } else { + // No explicit type given - evaluate array element expression. + let mut value = + self.enforce_expression(cs, file_scope, function_scope, expected_type, element_expression)?; + + // Allocate the array. + while let Some(dimension) = actual_dimensions.remove_last() { + // Parse the dimension into a `usize`. + let dimension_usize = parse_index(&dimension, &span)?; + + // Allocate the array dimension. + let array = vec![value; dimension_usize]; + + // Set the array value. + value = ConstrainedValue::Array(array); + } + + Ok(value) + } + } +} + +/// +/// Returns the index as a usize. +/// +pub fn parse_index(number: &PositiveNumber, span: &Span) -> Result { + number + .value + .parse::() + .map_err(|_| ExpressionError::invalid_index(number.value.to_owned(), span)) +} + +/// +/// Returns the type of the inner array given an array element and array dimensions. +/// +/// If the array has no dimensions, then an inner array does not exist. Simply return the given +/// element type. +/// +/// If the array has dimensions, then an inner array exists. Create a new type for the +/// inner array. The element type of the new array should be the same as the old array. The +/// dimensions of the new array should be the old array dimensions with the first dimension removed. +/// +pub fn inner_array_type(element_type: Type, dimensions: ArrayDimensions) -> Type { + if dimensions.is_empty() { + // The array has one dimension. + element_type + } else { + // The array has multiple dimensions. + Type::Array(Box::new(element_type), dimensions) + } } diff --git a/compiler/src/expression/array/index.rs b/compiler/src/expression/array/index.rs index 575d4f5103..02d361bae5 100644 --- a/compiler/src/expression/array/index.rs +++ b/compiler/src/expression/array/index.rs @@ -17,7 +17,7 @@ //! Enforces an array index expression in a compiled Leo program. use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::{Expression, IntegerType, Span, Type}; +use leo_ast::{Expression, IntegerType, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, @@ -36,7 +36,7 @@ impl> ConstrainedProgram { let expected_type = Some(Type::IntegerType(IntegerType::U32)); match self.enforce_operand(cs, file_scope, function_scope, expected_type, index, &span)? { ConstrainedValue::Integer(number) => Ok(number.to_usize(span)?), - value => Err(ExpressionError::invalid_index(value.to_string(), span.to_owned())), + value => Err(ExpressionError::invalid_index(value.to_string(), span)), } } } diff --git a/compiler/src/expression/binary/binary.rs b/compiler/src/expression/binary/binary.rs index 91d9f98cbd..fade74bb0b 100644 --- a/compiler/src/expression/binary/binary.rs +++ b/compiler/src/expression/binary/binary.rs @@ -17,7 +17,7 @@ //! Enforces a binary expression in a compiled Leo program. use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::{Expression, Span, Type}; +use leo_ast::{Expression, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/binary/operand.rs b/compiler/src/expression/binary/operand.rs index e6ff9530b6..e9853b8adf 100644 --- a/compiler/src/expression/binary/operand.rs +++ b/compiler/src/expression/binary/operand.rs @@ -17,7 +17,7 @@ //! Enforces one operand in a binary expression in a compiled Leo program. use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::{Expression, Span, Type}; +use leo_ast::{Expression, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/circuit/access.rs b/compiler/src/expression/circuit/access.rs index d0c2f806c2..0d3864c295 100644 --- a/compiler/src/expression/circuit/access.rs +++ b/compiler/src/expression/circuit/access.rs @@ -22,7 +22,7 @@ use crate::{ value::ConstrainedValue, GroupType, }; -use leo_typed::{Expression, Identifier, Span, Type}; +use leo_ast::{Expression, Identifier, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/circuit/circuit.rs b/compiler/src/expression/circuit/circuit.rs index c70ae61107..e78cd00e91 100644 --- a/compiler/src/expression/circuit/circuit.rs +++ b/compiler/src/expression/circuit/circuit.rs @@ -22,7 +22,7 @@ use crate::{ value::{ConstrainedCircuitMember, ConstrainedValue}, GroupType, }; -use leo_typed::{CircuitMember, CircuitVariableDefinition, Identifier, Span}; +use leo_ast::{CircuitMember, CircuitVariableDefinition, Identifier, Span}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/circuit/static_access.rs b/compiler/src/expression/circuit/static_access.rs index 1f01fce5dd..31ed5bb865 100644 --- a/compiler/src/expression/circuit/static_access.rs +++ b/compiler/src/expression/circuit/static_access.rs @@ -17,7 +17,7 @@ //! Enforces a circuit static access expression in a compiled Leo program. use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::{CircuitMember, Expression, Identifier, Span, Type}; +use leo_ast::{CircuitMember, Expression, Identifier, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/conditional/conditional.rs b/compiler/src/expression/conditional/conditional.rs index cfae42dbb3..a0b8e5a090 100644 --- a/compiler/src/expression/conditional/conditional.rs +++ b/compiler/src/expression/conditional/conditional.rs @@ -17,7 +17,7 @@ //! Enforces a conditional expression in a compiled Leo program. use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::{Expression, Span, Type}; +use leo_ast::{Expression, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/expression.rs b/compiler/src/expression/expression.rs index 9c0d98c41f..186fb0e0b8 100644 --- a/compiler/src/expression/expression.rs +++ b/compiler/src/expression/expression.rs @@ -28,7 +28,7 @@ use crate::{ GroupType, Integer, }; -use leo_typed::{Expression, Type}; +use leo_ast::{Expression, Type}; use snarkos_models::{ curves::{Field, PrimeField}, @@ -56,8 +56,11 @@ impl> ConstrainedProgram { Expression::Field(field, span) => Ok(ConstrainedValue::Field(FieldType::constant(field, &span)?)), Expression::Group(group_element) => Ok(ConstrainedValue::Group(G::constant(*group_element)?)), Expression::Implicit(value, span) => Ok(enforce_number_implicit(expected_type, value, &span)?), - Expression::Integer(type_, integer, span) => Ok(ConstrainedValue::Integer(Integer::new_constant( - &type_, integer, &span, + Expression::Integer(type_, integer, span) => Ok(ConstrainedValue::Integer(Integer::new( + expected_type, + &type_, + integer, + &span, )?)), // Binary operations @@ -243,9 +246,18 @@ impl> ConstrainedProgram { ), // Arrays - Expression::Array(array, span) => { + Expression::ArrayInline(array, span) => { self.enforce_array(cs, file_scope, function_scope, expected_type, array, span) } + Expression::ArrayInitializer(array_w_dimensions, span) => self.enforce_array_initializer( + cs, + file_scope, + function_scope, + expected_type, + array_w_dimensions.0, + array_w_dimensions.1, + span, + ), Expression::ArrayAccess(array_w_index, span) => self.enforce_array_access( cs, file_scope, @@ -260,9 +272,15 @@ impl> ConstrainedProgram { Expression::Tuple(tuple, span) => { self.enforce_tuple(cs, file_scope, function_scope, expected_type, tuple, span) } - Expression::TupleAccess(tuple, index, span) => { - self.enforce_tuple_access(cs, file_scope, function_scope, expected_type, *tuple, index, &span) - } + Expression::TupleAccess(tuple_w_index, span) => self.enforce_tuple_access( + cs, + file_scope, + function_scope, + expected_type, + tuple_w_index.0, + tuple_w_index.1, + &span, + ), // Circuits Expression::Circuit(circuit_name, members, span) => { diff --git a/compiler/src/expression/function/core_circuit.rs b/compiler/src/expression/function/core_circuit.rs index c0314e775f..7e9835f076 100644 --- a/compiler/src/expression/function/core_circuit.rs +++ b/compiler/src/expression/function/core_circuit.rs @@ -16,8 +16,8 @@ use crate::{program::ConstrainedProgram, value::ConstrainedValue, GroupType}; use crate::errors::{ExpressionError, FunctionError}; +use leo_ast::{Expression, Span, Type}; use leo_core::call_core_circuit; -use leo_typed::{Expression, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, gadgets::r1cs::ConstraintSystem, diff --git a/compiler/src/expression/function/function.rs b/compiler/src/expression/function/function.rs index f24bcc84c6..a7fba95c49 100644 --- a/compiler/src/expression/function/function.rs +++ b/compiler/src/expression/function/function.rs @@ -17,7 +17,7 @@ //! Enforce a function call expression in a compiled Leo program. use crate::{errors::ExpressionError, new_scope, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::{Expression, Span, Type}; +use leo_ast::{Expression, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/identifier/identifier.rs b/compiler/src/expression/identifier/identifier.rs index f1c8c4662d..58abdddb30 100644 --- a/compiler/src/expression/identifier/identifier.rs +++ b/compiler/src/expression/identifier/identifier.rs @@ -23,7 +23,7 @@ use crate::{ Address, GroupType, }; -use leo_typed::{Identifier, Type}; +use leo_ast::{Identifier, Type}; use snarkos_models::curves::{Field, PrimeField}; diff --git a/compiler/src/expression/logical/and.rs b/compiler/src/expression/logical/and.rs index 60d6f58eae..b58cdb614f 100644 --- a/compiler/src/expression/logical/and.rs +++ b/compiler/src/expression/logical/and.rs @@ -17,7 +17,7 @@ //! Enforces a logical `&&` operator in a resolved Leo program. use crate::{errors::BooleanError, value::ConstrainedValue, GroupType}; -use leo_typed::Span; +use leo_ast::Span; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/logical/not.rs b/compiler/src/expression/logical/not.rs index 7f23b4651d..f40089f982 100644 --- a/compiler/src/expression/logical/not.rs +++ b/compiler/src/expression/logical/not.rs @@ -17,7 +17,7 @@ //! Enforces a logical `!` operator in a resolved Leo program. use crate::{errors::BooleanError, value::ConstrainedValue, GroupType}; -use leo_typed::Span; +use leo_ast::Span; use snarkos_models::curves::{Field, PrimeField}; diff --git a/compiler/src/expression/logical/or.rs b/compiler/src/expression/logical/or.rs index 6ba45a3050..0915d3e77b 100644 --- a/compiler/src/expression/logical/or.rs +++ b/compiler/src/expression/logical/or.rs @@ -17,7 +17,7 @@ //! Enforces a logical `||` operator in a resolved Leo program. use crate::{errors::BooleanError, value::ConstrainedValue, GroupType}; -use leo_typed::Span; +use leo_ast::Span; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/relational/eq.rs b/compiler/src/expression/relational/eq.rs index 69d8d1370f..75f8de4ae9 100644 --- a/compiler/src/expression/relational/eq.rs +++ b/compiler/src/expression/relational/eq.rs @@ -17,7 +17,7 @@ //! Enforces a relational `==` operator in a resolved Leo program. use crate::{enforce_and, errors::ExpressionError, value::ConstrainedValue, GroupType}; -use leo_typed::Span; +use leo_ast::Span; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/relational/ge.rs b/compiler/src/expression/relational/ge.rs index 15e91f9e27..c7ebb817d7 100644 --- a/compiler/src/expression/relational/ge.rs +++ b/compiler/src/expression/relational/ge.rs @@ -17,8 +17,8 @@ //! Enforces a relational `>=` operator in a resolved Leo program. use crate::{errors::ExpressionError, value::ConstrainedValue, GroupType}; +use leo_ast::Span; use leo_gadgets::bits::ComparatorGadget; -use leo_typed::Span; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/relational/gt.rs b/compiler/src/expression/relational/gt.rs index 45351cc999..e7d1283b11 100644 --- a/compiler/src/expression/relational/gt.rs +++ b/compiler/src/expression/relational/gt.rs @@ -17,8 +17,8 @@ //! Enforces a relational `>` operator in a resolved Leo program. use crate::{errors::ExpressionError, value::ConstrainedValue, GroupType}; +use leo_ast::Span; use leo_gadgets::bits::ComparatorGadget; -use leo_typed::Span; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/relational/le.rs b/compiler/src/expression/relational/le.rs index 91fbd5e6f9..d5794ca9bd 100644 --- a/compiler/src/expression/relational/le.rs +++ b/compiler/src/expression/relational/le.rs @@ -17,8 +17,8 @@ //! Enforces a relational `<=` operator in a resolved Leo program. use crate::{errors::ExpressionError, value::ConstrainedValue, GroupType}; +use leo_ast::Span; use leo_gadgets::bits::ComparatorGadget; -use leo_typed::Span; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/relational/lt.rs b/compiler/src/expression/relational/lt.rs index ef9dd01e93..17af89b832 100644 --- a/compiler/src/expression/relational/lt.rs +++ b/compiler/src/expression/relational/lt.rs @@ -17,8 +17,8 @@ //! Enforces a relational `<` operator in a resolved Leo program. use crate::{errors::ExpressionError, value::ConstrainedValue, GroupType}; +use leo_ast::Span; use leo_gadgets::bits::comparator::EvaluateLtGadget; -use leo_typed::Span; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/expression/tuple/access.rs b/compiler/src/expression/tuple/access.rs index c628ac4243..03cc03ebce 100644 --- a/compiler/src/expression/tuple/access.rs +++ b/compiler/src/expression/tuple/access.rs @@ -16,8 +16,8 @@ //! Enforces array access in a compiled Leo program. -use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::{Expression, Span, Type}; +use crate::{errors::ExpressionError, parse_index, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; +use leo_ast::{Expression, PositiveNumber, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, @@ -33,18 +33,23 @@ impl> ConstrainedProgram { function_scope: &str, expected_type: Option, tuple: Expression, - index: usize, + index: PositiveNumber, span: &Span, ) -> Result, ExpressionError> { + // Get the tuple values. let tuple = match self.enforce_operand(cs, file_scope, function_scope, expected_type, tuple, &span)? { ConstrainedValue::Tuple(tuple) => tuple, value => return Err(ExpressionError::undefined_array(value.to_string(), span.to_owned())), }; - if index > tuple.len() - 1 { - return Err(ExpressionError::index_out_of_bounds(index, span.to_owned())); + // Parse the tuple index. + let index_usize = parse_index(&index, &span)?; + + // Check for out of bounds access. + if index_usize > tuple.len() - 1 { + return Err(ExpressionError::index_out_of_bounds(index_usize, span.to_owned())); } - Ok(tuple[index].to_owned()) + Ok(tuple[index_usize].to_owned()) } } diff --git a/compiler/src/expression/tuple/tuple.rs b/compiler/src/expression/tuple/tuple.rs index 3295fb4fe3..b002908a46 100644 --- a/compiler/src/expression/tuple/tuple.rs +++ b/compiler/src/expression/tuple/tuple.rs @@ -17,7 +17,7 @@ //! Enforces an tuple expression in a compiled Leo program. use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::{Expression, Span, Type}; +use leo_ast::{Expression, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/function/function.rs b/compiler/src/function/function.rs index 2c5ab8ea12..ab944103f0 100644 --- a/compiler/src/function/function.rs +++ b/compiler/src/function/function.rs @@ -23,7 +23,7 @@ use crate::{ GroupType, }; -use leo_typed::{Expression, Function, InputVariable, Span, Type}; +use leo_ast::{Expression, Function, FunctionInput, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, @@ -57,13 +57,13 @@ impl> ConstrainedProgram { // Store input values as new variables in resolved program for (input_model, input_expression) in function.input.iter().zip(input.into_iter()) { let (name, value) = match input_model { - InputVariable::InputKeyword(identifier) => { + FunctionInput::InputKeyword(identifier) => { let input_value = self.enforce_function_input(cs, scope, caller_scope, &function_name, None, input_expression)?; (&identifier.name, input_value) } - InputVariable::FunctionInput(input_model) => { + FunctionInput::Variable(input_model) => { // First evaluate input expression let mut input_value = self.enforce_function_input( cs, @@ -97,7 +97,7 @@ impl> ConstrainedProgram { &function_name, None, statement.clone(), - function.returns.clone(), + function.output.clone(), declared_circuit_reference, )?; @@ -110,7 +110,7 @@ impl> ConstrainedProgram { Self::conditionally_select_result(cs, &mut return_values, results, &function.span)?; if let ConstrainedValue::Tuple(ref returns) = return_values { - let return_types = match function.returns { + let return_types = match function.output { Some(Type::Tuple(types)) => types.len(), Some(_) => 1usize, None => 0usize, diff --git a/compiler/src/function/input/array.rs b/compiler/src/function/input/array.rs index 6317fde9c3..5158947d0c 100644 --- a/compiler/src/function/input/array.rs +++ b/compiler/src/function/input/array.rs @@ -18,13 +18,16 @@ use crate::{ errors::FunctionError, + inner_array_type, + parse_index, program::{new_scope, ConstrainedProgram}, value::ConstrainedValue, GroupType, }; -use leo_typed::{InputValue, Span, Type}; +use leo_ast::{ArrayDimensions, InputValue, Span, Type}; +use crate::errors::ExpressionError; use snarkos_models::{ curves::{Field, PrimeField}, gadgets::r1cs::ConstraintSystem, @@ -36,11 +39,27 @@ impl> ConstrainedProgram { cs: &mut CS, name: &str, array_type: Type, - array_dimensions: Vec, + mut array_dimensions: ArrayDimensions, input_value: Option, span: &Span, ) -> Result, FunctionError> { - let expected_length = array_dimensions[0]; + let expected_length = match array_dimensions.remove_first() { + Some(number) => { + // Parse the array dimension into a `usize`. + parse_index(&number, &span)? + } + None => { + return Err(FunctionError::ExpressionError(ExpressionError::unexpected_array( + array_type.to_string(), + span.to_owned(), + ))); + } + }; + + // Get the expected type for each array element. + let inner_array_type = inner_array_type(array_type, array_dimensions); + + // Build the array value using the expected types. let mut array_value = vec![]; match input_value { @@ -48,11 +67,10 @@ impl> ConstrainedProgram { // Allocate each value in the current row for (i, value) in arr.into_iter().enumerate() { let value_name = new_scope(&name, &i.to_string()); - let value_type = array_type.outer_dimension(&array_dimensions); array_value.push(self.allocate_main_function_input( cs, - value_type, + inner_array_type.clone(), &value_name, Some(value), span, @@ -63,9 +81,14 @@ impl> ConstrainedProgram { // Allocate all row values as none for i in 0..expected_length { let value_name = new_scope(&name, &i.to_string()); - let value_type = array_type.outer_dimension(&array_dimensions); - array_value.push(self.allocate_main_function_input(cs, value_type, &value_name, None, span)?); + array_value.push(self.allocate_main_function_input( + cs, + inner_array_type.clone(), + &value_name, + None, + span, + )?); } } _ => { diff --git a/compiler/src/function/input/function_input.rs b/compiler/src/function/input/function_input.rs index a588d778c8..77624fbfc6 100644 --- a/compiler/src/function/input/function_input.rs +++ b/compiler/src/function/input/function_input.rs @@ -18,7 +18,7 @@ use crate::{errors::FunctionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::{Expression, Type}; +use leo_ast::{Expression, Type}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/function/input/input_keyword.rs b/compiler/src/function/input/input_keyword.rs index 10025484bd..5d74e55f70 100644 --- a/compiler/src/function/input/input_keyword.rs +++ b/compiler/src/function/input/input_keyword.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{errors::FunctionError, ConstrainedCircuitMember, ConstrainedProgram, ConstrainedValue, GroupType}; -use leo_typed::{Identifier, Input}; +use leo_ast::{Identifier, Input}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/function/input/input_section.rs b/compiler/src/function/input/input_section.rs index 96d24bfbd6..88b3e77da6 100644 --- a/compiler/src/function/input/input_section.rs +++ b/compiler/src/function/input/input_section.rs @@ -16,7 +16,7 @@ use crate::{errors::FunctionError, ConstrainedCircuitMember, ConstrainedProgram, ConstrainedValue, GroupType}; -use leo_typed::{Identifier, InputValue, Parameter}; +use leo_ast::{Identifier, InputValue, Parameter}; use snarkos_models::{ curves::{Field, PrimeField}, gadgets::r1cs::ConstraintSystem, diff --git a/compiler/src/function/input/main_function_input.rs b/compiler/src/function/input/main_function_input.rs index ef9db4092a..7bed5fc273 100644 --- a/compiler/src/function/input/main_function_input.rs +++ b/compiler/src/function/input/main_function_input.rs @@ -30,7 +30,7 @@ use crate::{ Integer, }; -use leo_typed::{InputValue, Span, Type}; +use leo_ast::{InputValue, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/function/input/tuple.rs b/compiler/src/function/input/tuple.rs index 77ee183309..8ad74507d0 100644 --- a/compiler/src/function/input/tuple.rs +++ b/compiler/src/function/input/tuple.rs @@ -23,7 +23,7 @@ use crate::{ GroupType, }; -use leo_typed::{InputValue, Span, Type}; +use leo_ast::{InputValue, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/function/main_function.rs b/compiler/src/function/main_function.rs index 6e4f0047d9..7604a80b28 100644 --- a/compiler/src/function/main_function.rs +++ b/compiler/src/function/main_function.rs @@ -23,7 +23,7 @@ use crate::{ OutputBytes, }; -use leo_typed::{Expression, Function, Input, InputVariable}; +use leo_ast::{Expression, Function, FunctionInput, Input}; use snarkos_models::{ curves::{Field, PrimeField}, @@ -45,12 +45,12 @@ impl> ConstrainedProgram { let mut input_variables = Vec::with_capacity(function.input.len()); for input_model in function.input.clone().into_iter() { let (identifier, value) = match input_model { - InputVariable::InputKeyword(identifier) => { + FunctionInput::InputKeyword(identifier) => { let value = self.allocate_input_keyword(cs, identifier.clone(), &input)?; (identifier, value) } - InputVariable::FunctionInput(input_model) => { + FunctionInput::Variable(input_model) => { let name = input_model.identifier.name.clone(); let input_option = input .get(&name) diff --git a/compiler/src/function/result/result.rs b/compiler/src/function/result/result.rs index cceafc612a..cec2a05810 100644 --- a/compiler/src/function/result/result.rs +++ b/compiler/src/function/result/result.rs @@ -18,7 +18,7 @@ use crate::{errors::StatementError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::Span; +use leo_ast::Span; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/import/mod.rs b/compiler/src/import/mod.rs index 1e72ba4545..e4767afd6b 100644 --- a/compiler/src/import/mod.rs +++ b/compiler/src/import/mod.rs @@ -13,13 +13,6 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . - -//! Imports are split up into two parts: parsing and storing - -/// The import parser creates a hashmap of import program names -> import program structs -pub mod parser; -pub use self::parser::*; - /// The import store brings an imported symbol into the main program from an import program struct pub mod store; pub use self::store::*; diff --git a/compiler/src/import/parser/import_parser.rs b/compiler/src/import/parser/import_parser.rs index 7d5bbfce20..9e440436ad 100644 --- a/compiler/src/import/parser/import_parser.rs +++ b/compiler/src/import/parser/import_parser.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::errors::ImportError; -use leo_typed::{Package, Program}; +use leo_ast::{Package, Program}; use std::{collections::HashMap, env::current_dir}; diff --git a/compiler/src/import/parser/parse_symbol.rs b/compiler/src/import/parser/parse_symbol.rs deleted file mode 100644 index 4e161ea849..0000000000 --- a/compiler/src/import/parser/parse_symbol.rs +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{errors::ImportError, ImportParser}; -use leo_ast::LeoAst; -use leo_typed::{ImportSymbol, Program, Span}; - -use std::{ffi::OsString, fs::DirEntry, path::PathBuf}; - -static LIBRARY_FILE: &str = "src/lib.leo"; -static FILE_EXTENSION: &str = "leo"; - -fn parse_import_file(entry: &DirEntry, span: &Span) -> Result { - // make sure the given entry is file - let file_type = entry - .file_type() - .map_err(|error| ImportError::directory_error(error, span.clone(), &entry.path()))?; - let file_name = entry - .file_name() - .into_string() - .map_err(|_| ImportError::convert_os_string(span.clone()))?; - - let mut file_path = entry.path(); - if file_type.is_dir() { - file_path.push(LIBRARY_FILE); - - if !file_path.exists() { - return Err(ImportError::expected_lib_file( - format!("{:?}", file_path.as_path()), - span.clone(), - )); - } - } - - // Builds the abstract syntax tree. - let program_string = &LeoAst::load_file(&file_path)?; - let ast = &LeoAst::new(&file_path, &program_string)?; - - // Generates the Leo program from file. - Ok(Program::from(&file_name, ast.as_repr())) -} - -impl ImportParser { - pub fn parse_import_star(&mut self, entry: &DirEntry, span: &Span) -> Result<(), ImportError> { - let path = entry.path(); - let is_dir = path.is_dir(); - let is_leo_file = path - .extension() - .map_or(false, |ext| ext.eq(&OsString::from(FILE_EXTENSION))); - - let mut package_path = path; - package_path.push(LIBRARY_FILE); - - let is_package = is_dir && package_path.exists(); - - // import * can only be invoked on a package with a library file or a leo file - if is_package || is_leo_file { - // Generate aleo program from file - let program = parse_import_file(entry, &span)?; - - // Store program's imports in imports hashmap - program - .imports - .iter() - .map(|import| self.parse_package(entry.path(), &import.package)) - .collect::, ImportError>>()?; - - // Store program in imports hashmap - let file_name_path = PathBuf::from(entry.file_name()); - let file_name = file_name_path - .file_stem() - .unwrap() - .to_os_string() - .into_string() - .unwrap(); // the file exists so these will not fail - - self.insert_import(file_name, program); - - Ok(()) - } else { - // importing * from a directory or non-leo file in `package/src/` is illegal - Err(ImportError::star(&entry.path(), span.clone())) - } - } - - pub fn parse_import_symbol(&mut self, entry: &DirEntry, symbol: &ImportSymbol) -> Result<(), ImportError> { - // Generate aleo program from file - let program = parse_import_file(entry, &symbol.span)?; - - // Store program's imports in imports hashmap - program - .imports - .iter() - .map(|import| self.parse_package(entry.path(), &import.package)) - .collect::, ImportError>>()?; - - // Store program in imports hashmap - let file_name_path = PathBuf::from(entry.file_name()); - let file_name = file_name_path - .file_stem() - .unwrap() - .to_os_string() - .into_string() - .unwrap(); // the file exists so these will not fail - - self.insert_import(file_name, program); - - Ok(()) - } -} diff --git a/compiler/src/import/store/core_package.rs b/compiler/src/import/store/core_package.rs index 2357c1d7b6..4eb6b49924 100644 --- a/compiler/src/import/store/core_package.rs +++ b/compiler/src/import/store/core_package.rs @@ -15,13 +15,13 @@ // along with the Leo library. If not, see . use crate::{new_scope, ConstrainedProgram, ConstrainedValue, GroupType}; -use leo_typed::Package; +use leo_ast::Package; -use leo_core::{CorePackageList, LeoCoreError}; +use leo_core::{CorePackageList, LeoCorePackageError}; use snarkos_models::curves::{Field, PrimeField}; impl> ConstrainedProgram { - pub(crate) fn store_core_package(&mut self, scope: &str, package: Package) -> Result<(), LeoCoreError> { + pub(crate) fn store_core_package(&mut self, scope: &str, package: Package) -> Result<(), LeoCorePackageError> { // Create list of imported core packages. let list = CorePackageList::from_package_access(package.access)?; diff --git a/compiler/src/import/store/import.rs b/compiler/src/import/store/import.rs index 7a4bed717e..8e34423557 100644 --- a/compiler/src/import/store/import.rs +++ b/compiler/src/import/store/import.rs @@ -14,8 +14,10 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{errors::ImportError, imported_symbols::ImportedSymbols, ConstrainedProgram, GroupType, ImportParser}; -use leo_typed::Import; +use crate::{errors::ImportError, ConstrainedProgram, GroupType}; +use leo_ast::ImportStatement; +use leo_imports::ImportParser; +// use leo_symbol_table::imported_symbols::ImportedSymbols; use snarkos_models::curves::{Field, PrimeField}; @@ -23,36 +25,33 @@ impl> ConstrainedProgram { pub(crate) fn store_import( &mut self, scope: &str, - import: &Import, + import: &ImportStatement, imported_programs: &ImportParser, ) -> Result<(), ImportError> { - // Fetch core dependencies - let core_dependency = imported_programs - .core_packages() - .iter() - .find(|package| import.package.eq(package)); + // Fetch core packages. + let core_package = imported_programs.get_core_package(&import.package); - if let Some(package) = core_dependency { + if let Some(package) = core_package { self.store_core_package(scope, package.clone())?; return Ok(()); } - // Fetch dependencies for the current import - let imported_symbols = ImportedSymbols::from(import); - - for (package, symbol) in imported_symbols.symbols { - // Find imported program - let program = imported_programs - .get_import(&package) - .ok_or_else(|| ImportError::unknown_package(import.package.name.clone()))?; - - // Parse imported program - self.store_definitions(program.clone(), imported_programs)?; - - // Store the imported symbol - self.store_symbol(scope, &package, &symbol, program)?; - } + // // Fetch dependencies for the current import + // let imported_symbols = ImportedSymbols::new(import); + // + // for (name, symbol) in imported_symbols.symbols { + // // Find imported program + // let program = imported_programs + // .get_import(&name) + // .ok_or_else(|| ImportError::unknown_package(import.package.name.clone()))?; + // + // // Parse imported program + // self.store_definitions(program.clone(), imported_programs)?; + // + // // Store the imported symbol + // self.store_symbol(scope, &name, &symbol, program)?; + // } Ok(()) } diff --git a/compiler/src/import/store/imported_symbols.rs b/compiler/src/import/store/imported_symbols.rs deleted file mode 100644 index 80545e01f4..0000000000 --- a/compiler/src/import/store/imported_symbols.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use leo_typed::{Import, ImportSymbol, Package, PackageAccess}; - -/// Stores the the package file name and imported symbol from an import statement -#[derive(Debug)] -pub(crate) struct ImportedSymbols { - pub symbols: Vec<(String, ImportSymbol)>, -} - -impl ImportedSymbols { - fn new() -> Self { - Self { symbols: vec![] } - } - - pub(crate) fn from(import: &Import) -> Self { - let mut symbols = Self::new(); - - symbols.from_package(&import.package); - - symbols - } - - fn from_package(&mut self, package: &Package) { - self.from_package_access(package.name.name.clone(), &package.access); - } - - fn from_package_access(&mut self, package: String, access: &PackageAccess) { - match access { - PackageAccess::SubPackage(package) => self.from_package(package), - PackageAccess::Star(span) => { - let star = ImportSymbol::star(span); - self.symbols.push((package, star)); - } - PackageAccess::Symbol(symbol) => self.symbols.push((package, symbol.clone())), - PackageAccess::Multiple(packages) => packages - .iter() - .for_each(|access| self.from_package_access(package.clone(), access)), - } - } -} diff --git a/compiler/src/import/store/mod.rs b/compiler/src/import/store/mod.rs index 7633655956..6b881f6016 100644 --- a/compiler/src/import/store/mod.rs +++ b/compiler/src/import/store/mod.rs @@ -21,7 +21,5 @@ pub use self::core_package::*; pub mod import; pub use self::import::*; -pub mod imported_symbols; - pub mod symbol; pub use self::symbol::*; diff --git a/compiler/src/import/store/symbol.rs b/compiler/src/import/store/symbol.rs index dfb9244cc2..e5ef574060 100644 --- a/compiler/src/import/store/symbol.rs +++ b/compiler/src/import/store/symbol.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{errors::ImportError, new_scope, ConstrainedProgram, ConstrainedValue, GroupType}; -use leo_typed::{ImportSymbol, Program}; +use leo_ast::{ImportSymbol, Program}; use snarkos_models::curves::{Field, PrimeField}; diff --git a/compiler/src/lib.rs b/compiler/src/lib.rs index 9e93ead53e..03abbf4457 100644 --- a/compiler/src/lib.rs +++ b/compiler/src/lib.rs @@ -14,7 +14,9 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -//! Module containing structs and types that make up a Leo program. +//! The compiler for Leo programs. +//! +//! The [`Compiler`] type compiles Leo programs into R1CS circuits. #![allow(clippy::module_inception)] diff --git a/compiler/src/output/output_bytes.rs b/compiler/src/output/output_bytes.rs index a451c2fc4d..8a797dae73 100644 --- a/compiler/src/output/output_bytes.rs +++ b/compiler/src/output/output_bytes.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{errors::OutputBytesError, ConstrainedValue, GroupType, REGISTERS_VARIABLE_NAME}; -use leo_typed::{Parameter, Registers, Span}; +use leo_ast::{Parameter, Registers, Span}; use snarkos_models::curves::{Field, PrimeField}; diff --git a/compiler/src/statement/assign/array.rs b/compiler/src/statement/assign/array.rs index c282ca0fee..842cdefbfe 100644 --- a/compiler/src/statement/assign/array.rs +++ b/compiler/src/statement/assign/array.rs @@ -17,7 +17,7 @@ //! Enforces an array assignment statement in a compiled Leo program. use crate::{errors::StatementError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::{RangeOrExpression, Span}; +use leo_ast::{RangeOrExpression, Span}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/statement/assign/assign.rs b/compiler/src/statement/assign/assign.rs index 2a317040a9..8899c9b286 100644 --- a/compiler/src/statement/assign/assign.rs +++ b/compiler/src/statement/assign/assign.rs @@ -24,7 +24,7 @@ use crate::{ value::ConstrainedValue, GroupType, }; -use leo_typed::{Assignee, Expression, Span}; +use leo_ast::{Assignee, AssigneeAccess, Expression, Span}; use snarkos_models::{ curves::{Field, PrimeField}, @@ -48,72 +48,66 @@ impl> ConstrainedProgram { span: &Span, ) -> Result<(), StatementError> { // Get the name of the variable we are assigning to - let variable_name = resolve_assignee(function_scope, assignee.clone()); + let variable_name = resolve_assignee(function_scope.to_string(), assignee.clone()); // Evaluate new value let mut new_value = self.enforce_expression(cs, file_scope, function_scope, None, expression)?; // Mutate the old value into the new value - match assignee { - Assignee::Identifier(_identifier) => { - let condition = indicator.unwrap_or(Boolean::Constant(true)); - let old_value = self.get_mutable_assignee(&variable_name, &span)?; + if assignee.accesses.is_empty() { + let condition = indicator.unwrap_or(Boolean::Constant(true)); + let old_value = self.get_mutable_assignee(&variable_name, span)?; - new_value.resolve_type(Some(old_value.to_type(&span)?), &span)?; + new_value.resolve_type(Some(old_value.to_type(&span)?), span)?; - let selected_value = ConstrainedValue::conditionally_select( - cs.ns(|| format!("select {} {}:{}", new_value, span.line, span.start)), - &condition, - &new_value, - old_value, - ) - .map_err(|_| { - StatementError::select_fail(new_value.to_string(), old_value.to_string(), span.to_owned()) - })?; + let selected_value = ConstrainedValue::conditionally_select( + cs.ns(|| format!("select {} {}:{}", new_value, span.line, span.start)), + &condition, + &new_value, + old_value, + ) + .map_err(|_| StatementError::select_fail(new_value.to_string(), old_value.to_string(), span.to_owned()))?; - *old_value = selected_value; + *old_value = selected_value; - Ok(()) - } - Assignee::Array(assignee_w_range_or_expression) => self.assign_array( - cs, - file_scope, - function_scope, - indicator, - &variable_name, - assignee_w_range_or_expression.1, - new_value, - span, - ), - Assignee::Tuple(_tuple, index) => self.assign_tuple(cs, indicator, &variable_name, index, new_value, span), - Assignee::CircuitField(assignee, circuit_variable) => { - // Mutate a circuit variable using the self keyword. - if let Assignee::Identifier(circuit_name) = *assignee { - if circuit_name.is_self() { - let self_circuit_variable_name = new_scope(&circuit_name.name, &circuit_variable.name); + Ok(()) + } else { + match assignee.accesses[0].clone() { + AssigneeAccess::Array(range_or_expression) => self.assign_array( + cs, + file_scope, + function_scope, + indicator, + &variable_name, + range_or_expression, + new_value, + span, + ), + AssigneeAccess::Tuple(index, span) => { + self.assign_tuple(cs, indicator, &variable_name, index, new_value, &span) + } + AssigneeAccess::Member(identifier) => { + // Mutate a circuit variable using the self keyword. + if assignee.identifier.is_self() { + let self_circuit_variable_name = new_scope(&assignee.identifier.name, &identifier.name); let self_variable_name = new_scope(file_scope, &self_circuit_variable_name); let value = self.mutate_circuit_variable( cs, indicator, declared_circuit_reference, - circuit_variable, + identifier, new_value, span, )?; self.store(self_variable_name, value); } else { - let _value = self.mutate_circuit_variable( - cs, - indicator, - &variable_name, - circuit_variable, - new_value, - span, - )?; + let _value = + self.mutate_circuit_variable(cs, indicator, &variable_name, identifier, new_value, span)?; } + + Ok(()) } - Ok(()) } } } diff --git a/compiler/src/statement/assign/assignee.rs b/compiler/src/statement/assign/assignee.rs index 13ba48f445..3a0fe2641c 100644 --- a/compiler/src/statement/assign/assignee.rs +++ b/compiler/src/statement/assign/assignee.rs @@ -17,17 +17,12 @@ //! Resolves assignees in a compiled Leo program. use crate::{errors::StatementError, new_scope, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::{Assignee, Span}; +use leo_ast::{Assignee, Span}; use snarkos_models::curves::{Field, PrimeField}; -pub fn resolve_assignee(scope: &str, assignee: Assignee) -> String { - match assignee { - Assignee::Identifier(name) => new_scope(scope, &name.to_string()), - Assignee::Array(array_w_index) => resolve_assignee(scope, array_w_index.0), - Assignee::Tuple(tuple, _index) => resolve_assignee(scope, *tuple), - Assignee::CircuitField(circuit_name, _member) => resolve_assignee(scope, *circuit_name), - } +pub fn resolve_assignee(scope: String, assignee: Assignee) -> String { + new_scope(&scope, &assignee.identifier().to_string()) } impl> ConstrainedProgram { diff --git a/compiler/src/statement/assign/circuit_variable.rs b/compiler/src/statement/assign/circuit_variable.rs index 2aea133662..146c95f983 100644 --- a/compiler/src/statement/assign/circuit_variable.rs +++ b/compiler/src/statement/assign/circuit_variable.rs @@ -17,7 +17,7 @@ //! Enforces a circuit variable assignment statement in a compiled Leo program. use crate::{errors::StatementError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::{Identifier, Span}; +use leo_ast::{Identifier, Span}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/statement/assign/tuple.rs b/compiler/src/statement/assign/tuple.rs index a8a8a0a7fb..5ecb0dd767 100644 --- a/compiler/src/statement/assign/tuple.rs +++ b/compiler/src/statement/assign/tuple.rs @@ -16,8 +16,8 @@ //! Enforces a tuple assignment statement in a compiled Leo program. -use crate::{errors::StatementError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::Span; +use crate::{errors::StatementError, parse_index, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; +use leo_ast::{PositiveNumber, Span}; use snarkos_models::{ curves::{Field, PrimeField}, @@ -33,28 +33,32 @@ impl> ConstrainedProgram { cs: &mut CS, indicator: Option, name: &str, - index: usize, + index: PositiveNumber, mut new_value: ConstrainedValue, span: &Span, ) -> Result<(), StatementError> { + // Get the indicator value. let condition = indicator.unwrap_or(Boolean::Constant(true)); + // Parse the index. + let index_usize = parse_index(&index, &span)?; + // Modify the single value of the tuple in place match self.get_mutable_assignee(name, &span)? { ConstrainedValue::Tuple(old) => { - new_value.resolve_type(Some(old[index].to_type(&span)?), &span)?; + new_value.resolve_type(Some(old[index_usize].to_type(&span)?), &span)?; let selected_value = ConstrainedValue::conditionally_select( cs.ns(|| format!("select {} {}:{}", new_value, span.line, span.start)), &condition, &new_value, - &old[index], + &old[index_usize], ) .map_err(|_| { - StatementError::select_fail(new_value.to_string(), old[index].to_string(), span.to_owned()) + StatementError::select_fail(new_value.to_string(), old[index_usize].to_string(), span.to_owned()) })?; - old[index] = selected_value; + old[index_usize] = selected_value; } _ => return Err(StatementError::tuple_assign_index(span.to_owned())), } diff --git a/compiler/src/statement/branch/branch.rs b/compiler/src/statement/branch/branch.rs index ddb6e91838..9d0d208036 100644 --- a/compiler/src/statement/branch/branch.rs +++ b/compiler/src/statement/branch/branch.rs @@ -17,7 +17,7 @@ //! Enforces a branch of a conditional or iteration statement in a compiled Leo program. use crate::{program::ConstrainedProgram, GroupType, IndicatorAndConstrainedValue, StatementResult}; -use leo_typed::{Statement, Type}; +use leo_ast::{Statement, Type}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/statement/conditional/conditional.rs b/compiler/src/statement/conditional/conditional.rs index db83d57ffb..48bad283b8 100644 --- a/compiler/src/statement/conditional/conditional.rs +++ b/compiler/src/statement/conditional/conditional.rs @@ -24,7 +24,7 @@ use crate::{ IndicatorAndConstrainedValue, StatementResult, }; -use leo_typed::{ConditionalNestedOrEndStatement, ConditionalStatement, Span, Type}; +use leo_ast::{ConditionalNestedOrEndStatement, ConditionalStatement, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/statement/definition/definition.rs b/compiler/src/statement/definition/definition.rs index 994b9ff6a8..feb839135a 100644 --- a/compiler/src/statement/definition/definition.rs +++ b/compiler/src/statement/definition/definition.rs @@ -17,7 +17,7 @@ //! Enforces a definition statement in a compiled Leo program. use crate::{errors::StatementError, program::ConstrainedProgram, ConstrainedValue, GroupType}; -use leo_typed::{Declare, Expression, Span, Type, VariableName, Variables}; +use leo_ast::{Declare, Expression, Span, VariableName, Variables}; use snarkos_models::{ curves::{Field, PrimeField}, @@ -48,67 +48,6 @@ impl> ConstrainedProgram { Ok(()) } - fn enforce_expressions>( - &mut self, - cs: &mut CS, - file_scope: &str, - function_scope: &str, - type_: Option, - expressions: Vec, - span: &Span, - ) -> Result>, StatementError> { - let types = match type_ { - Some(Type::Tuple(types)) => types, - Some(type_) => return Err(StatementError::tuple_type(type_.to_string(), span.to_owned())), - None => vec![], - }; - - let implicit_types = types.is_empty(); - let mut expected_types = Vec::with_capacity(expressions.len()); - - for ty in types.iter().take(expressions.len()) { - let expected_type = if implicit_types { None } else { Some(ty.clone()) }; - - expected_types.push(expected_type); - } - - let mut values = Vec::with_capacity(expressions.len()); - - for (expression, expected_type) in expressions.into_iter().zip(expected_types.into_iter()) { - let value = self.enforce_expression(cs, file_scope, function_scope, expected_type, expression)?; - - values.push(value); - } - - Ok(values) - } - - #[allow(clippy::too_many_arguments)] - fn enforce_tuple_definition>( - &mut self, - cs: &mut CS, - file_scope: &str, - function_scope: &str, - is_constant: bool, - variables: Variables, - expressions: Vec, - span: &Span, - ) -> Result<(), StatementError> { - let values = self.enforce_expressions( - cs, - file_scope, - function_scope, - variables.type_.clone(), - expressions, - span, - )?; - - let tuple = ConstrainedValue::Tuple(values); - let variable = variables.names[0].clone(); - - self.enforce_single_definition(cs, function_scope, is_constant, variable, tuple, span) - } - fn enforce_multiple_definition>( &mut self, cs: &mut CS, @@ -141,62 +80,30 @@ impl> ConstrainedProgram { function_scope: &str, declare: Declare, variables: Variables, - expressions: Vec, + expression: Expression, span: &Span, ) -> Result<(), StatementError> { let num_variables = variables.names.len(); - let num_values = expressions.len(); let is_constant = match declare { Declare::Let => false, Declare::Const => true, }; + let expression = + self.enforce_expression(cs, file_scope, function_scope, variables.type_.clone(), expression)?; - if num_variables == 1 && num_values == 1 { + if num_variables == 1 { // Define a single variable with a single value let variable = variables.names[0].clone(); - let expression = - self.enforce_expression(cs, file_scope, function_scope, variables.type_, expressions[0].clone())?; self.enforce_single_definition(cs, function_scope, is_constant, variable, expression, span) - } else if num_variables == 1 && num_values > 1 { - // Define a tuple (single variable with multiple values) - - self.enforce_tuple_definition( - cs, - file_scope, - function_scope, - is_constant, - variables, - expressions, - span, - ) - } else if num_variables > 1 && num_values == 1 { + } else { // Define multiple variables for an expression that returns multiple results (multiple definition) - - let values = match self.enforce_expression( - cs, - file_scope, - function_scope, - variables.type_.clone(), - expressions[0].clone(), - )? { + let values = match expression { // ConstrainedValue::Return(values) => values, ConstrainedValue::Tuple(values) => values, value => return Err(StatementError::multiple_definition(value.to_string(), span.to_owned())), }; - self.enforce_multiple_definition(cs, function_scope, is_constant, variables, values, span) - } else { - // Define multiple variables for multiple expressions - let values = self.enforce_expressions( - cs, - file_scope, - function_scope, - variables.type_.clone(), - expressions, - span, - )?; - self.enforce_multiple_definition(cs, function_scope, is_constant, variables, values, span) } } diff --git a/compiler/src/statement/iteration/iteration.rs b/compiler/src/statement/iteration/iteration.rs index f9c658ad1e..64104cbb45 100644 --- a/compiler/src/statement/iteration/iteration.rs +++ b/compiler/src/statement/iteration/iteration.rs @@ -25,7 +25,7 @@ use crate::{ Integer, StatementResult, }; -use leo_typed::{Expression, Identifier, Span, Statement, Type}; +use leo_ast::{Expression, Identifier, Span, Statement, Type}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/compiler/src/statement/return_/return_.rs b/compiler/src/statement/return_/return_.rs index 4c1cb083c6..f70b69ca79 100644 --- a/compiler/src/statement/return_/return_.rs +++ b/compiler/src/statement/return_/return_.rs @@ -17,7 +17,7 @@ //! Enforces a return statement in a compiled Leo program. use crate::{errors::StatementError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::{Expression, Span, Type}; +use leo_ast::{Expression, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, @@ -28,7 +28,7 @@ fn check_return_type(expected: Option, actual: Type, span: &Span) -> Resul match expected { Some(expected) => { if expected.ne(&actual) { - if (expected.is_self() && actual.is_circuit()) || expected.match_array_types(&actual) { + if (expected.is_self() && actual.is_circuit()) || expected.eq_flat(&actual) { return Ok(()); } else { return Err(StatementError::arguments_type(&expected, &actual, span.to_owned())); @@ -50,10 +50,9 @@ impl> ConstrainedProgram { return_type: Option, span: &Span, ) -> Result, StatementError> { - // Make sure we return the correct number of values - let result = self.enforce_operand(cs, file_scope, function_scope, return_type.clone(), expression, span)?; + // Make sure we return the correct type. check_return_type(return_type, result.to_type(&span)?, span)?; Ok(result) diff --git a/compiler/src/statement/statement.rs b/compiler/src/statement/statement.rs index 4aaae321bf..763ea328a7 100644 --- a/compiler/src/statement/statement.rs +++ b/compiler/src/statement/statement.rs @@ -17,7 +17,7 @@ //! Enforces a statement in a compiled Leo program. use crate::{errors::StatementError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; -use leo_typed::{Statement, Type}; +use leo_ast::{Statement, Type}; use snarkos_models::{ curves::{Field, PrimeField}, @@ -28,11 +28,13 @@ pub type StatementResult = Result; pub type IndicatorAndConstrainedValue = (Option, ConstrainedValue); impl> ConstrainedProgram { + /// /// Enforce a program statement. /// Returns a Vector of (indicator, value) tuples. /// Each evaluated statement may execute of one or more statements that may return early. /// To indicate which of these return values to take we conditionally select the value according /// to the `indicator` bit that evaluates to true. + /// #[allow(clippy::too_many_arguments)] pub fn enforce_statement>( &mut self, @@ -74,7 +76,7 @@ impl> ConstrainedProgram { declared_circuit_reference, indicator, variable, - *expression, + expression, &span, )?; } diff --git a/compiler/src/value/address/address.rs b/compiler/src/value/address/address.rs index e385138402..95566475b0 100644 --- a/compiler/src/value/address/address.rs +++ b/compiler/src/value/address/address.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{errors::AddressError, ConstrainedValue, GroupType}; -use leo_typed::{InputValue, Span}; +use leo_ast::{InputValue, Span}; use snarkos_dpc::base_dpc::instantiated::Components; use snarkos_errors::gadgets::SynthesisError; diff --git a/compiler/src/value/boolean/input.rs b/compiler/src/value/boolean/input.rs index 9b712b95d6..d35661f112 100644 --- a/compiler/src/value/boolean/input.rs +++ b/compiler/src/value/boolean/input.rs @@ -17,7 +17,7 @@ //! Methods to enforce constraints on input boolean values in a resolved Leo program. use crate::{errors::BooleanError, value::ConstrainedValue, GroupType}; -use leo_typed::{InputValue, Span}; +use leo_ast::{InputValue, Span}; use snarkos_errors::gadgets::SynthesisError; use snarkos_models::{ diff --git a/compiler/src/value/field/field_type.rs b/compiler/src/value/field/field_type.rs index c22bed7600..39146ae593 100644 --- a/compiler/src/value/field/field_type.rs +++ b/compiler/src/value/field/field_type.rs @@ -17,7 +17,7 @@ //! A data type that represents a field value use crate::errors::FieldError; -use leo_typed::Span; +use leo_ast::Span; use snarkos_errors::gadgets::SynthesisError; use snarkos_models::{ diff --git a/compiler/src/value/field/input.rs b/compiler/src/value/field/input.rs index 34d14d0f75..a498b25345 100644 --- a/compiler/src/value/field/input.rs +++ b/compiler/src/value/field/input.rs @@ -17,7 +17,7 @@ //! Methods to enforce constraints on input field values in a compiled Leo program. use crate::{errors::FieldError, value::ConstrainedValue, FieldType, GroupType}; -use leo_typed::{InputValue, Span}; +use leo_ast::{InputValue, Span}; use snarkos_errors::gadgets::SynthesisError; use snarkos_models::{ diff --git a/compiler/src/value/group/group_type.rs b/compiler/src/value/group/group_type.rs index 3dc2a0250d..c80a6a8325 100644 --- a/compiler/src/value/group/group_type.rs +++ b/compiler/src/value/group/group_type.rs @@ -17,7 +17,7 @@ //! A data type that represents members in the group formed by the set of affine points on a curve. use crate::errors::GroupError; -use leo_typed::{GroupValue, Span}; +use leo_ast::{GroupValue, Span}; use snarkos_models::{ curves::{Field, One}, diff --git a/compiler/src/value/group/input.rs b/compiler/src/value/group/input.rs index 293ffd92a0..2ff04b6095 100644 --- a/compiler/src/value/group/input.rs +++ b/compiler/src/value/group/input.rs @@ -17,7 +17,7 @@ //! Methods to enforce constraints on input group values in a Leo program. use crate::{errors::GroupError, ConstrainedValue, GroupType}; -use leo_typed::{GroupValue, InputValue, Span}; +use leo_ast::{GroupValue, InputValue, Span}; use snarkos_errors::gadgets::SynthesisError; use snarkos_models::{ diff --git a/compiler/src/value/group/targets/edwards_bls12.rs b/compiler/src/value/group/targets/edwards_bls12.rs index c146e04564..7a1ab306dc 100644 --- a/compiler/src/value/group/targets/edwards_bls12.rs +++ b/compiler/src/value/group/targets/edwards_bls12.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{errors::GroupError, GroupType}; -use leo_typed::{GroupCoordinate, GroupTuple, GroupValue, Span}; +use leo_ast::{GroupCoordinate, GroupTuple, GroupValue, Span}; use snarkos_curves::{ edwards_bls12::{EdwardsAffine, EdwardsParameters, Fq}, diff --git a/compiler/src/value/implicit/implicit.rs b/compiler/src/value/implicit/implicit.rs index 27b6cb76c6..d72c9f4648 100644 --- a/compiler/src/value/implicit/implicit.rs +++ b/compiler/src/value/implicit/implicit.rs @@ -17,7 +17,7 @@ //! Enforces constraints on an implicit number in a compiled Leo program. use crate::{errors::ValueError, value::ConstrainedValue, GroupType}; -use leo_typed::{Span, Type}; +use leo_ast::{Span, Type}; use snarkos_models::curves::{Field, PrimeField}; diff --git a/compiler/src/value/integer/integer.rs b/compiler/src/value/integer/integer.rs index 0384248624..13f8170a04 100644 --- a/compiler/src/value/integer/integer.rs +++ b/compiler/src/value/integer/integer.rs @@ -16,12 +16,12 @@ //! Conversion of integer declarations to constraints in Leo. use crate::{errors::IntegerError, IntegerTrait}; +use leo_ast::{InputValue, IntegerType, Span, Type}; use leo_gadgets::{ arithmetic::*, bits::comparator::{ComparatorGadget, EvaluateLtGadget}, signed_integer::*, }; -use leo_typed::{InputValue, IntegerType, Span}; use snarkos_errors::gadgets::SynthesisError; use snarkos_models::{ @@ -67,6 +67,44 @@ impl fmt::Display for Integer { } impl Integer { + /// + /// Returns a new integer from an expression. + /// + /// Checks that the expression is equal to the expected type if given. + /// + pub fn new( + expected_type: Option, + actual_integer_type: &IntegerType, + string: String, + span: &Span, + ) -> Result { + // Check expected type if given. + if let Some(type_) = expected_type { + // Check expected type is an integer. + match type_ { + Type::IntegerType(expected_integer_type) => { + // Check expected integer type == actual integer type + if expected_integer_type.ne(actual_integer_type) { + return Err(IntegerError::invalid_integer_type( + &expected_integer_type, + actual_integer_type, + span.to_owned(), + )); + } + } + type_ => return Err(IntegerError::invalid_type(&type_, span.to_owned())), + } + } + + // Return a new constant integer. + Self::new_constant(actual_integer_type, string, span) + } + + /// + /// Returns a new integer value from an expression. + /// + /// The returned integer value is "constant" and is not allocated in the constraint system. + /// pub fn new_constant(integer_type: &IntegerType, string: String, span: &Span) -> Result { match integer_type { IntegerType::U8 => { diff --git a/compiler/src/value/value.rs b/compiler/src/value/value.rs index de2d80f524..94f47d7295 100644 --- a/compiler/src/value/value.rs +++ b/compiler/src/value/value.rs @@ -26,8 +26,8 @@ use crate::{ GroupType, Integer, }; +use leo_ast::{ArrayDimensions, Circuit, Function, GroupValue, Identifier, Span, Type}; use leo_core::Value; -use leo_typed::{Circuit, Function, GroupValue, Identifier, Span, Type}; use snarkos_errors::gadgets::SynthesisError; use snarkos_models::{ @@ -114,7 +114,8 @@ impl> ConstrainedValue { // Data type wrappers ConstrainedValue::Array(array) => { let array_type = array[0].to_type(span)?; - let mut dimensions = vec![array.len()]; + let mut dimensions = ArrayDimensions::default(); + dimensions.push_usize(array.len(), span.to_owned()); // Nested array type if let Type::Array(inner_type, inner_dimensions) = &array_type { @@ -272,37 +273,25 @@ impl> ConstrainedValue { // Data type wrappers ConstrainedValue::Array(array) => { - array - .iter_mut() - .enumerate() - .map(|(i, value)| { - let unique_name = format!("allocate array member {} {}:{}", i, span.line, span.start); + array.iter_mut().enumerate().try_for_each(|(i, value)| { + let unique_name = format!("allocate array member {} {}:{}", i, span.line, span.start); - value.allocate_value(cs.ns(|| unique_name), span) - }) - .collect::>()?; + value.allocate_value(cs.ns(|| unique_name), span) + })?; } ConstrainedValue::Tuple(tuple) => { - tuple - .iter_mut() - .enumerate() - .map(|(i, value)| { - let unique_name = format!("allocate tuple member {} {}:{}", i, span.line, span.start); + tuple.iter_mut().enumerate().try_for_each(|(i, value)| { + let unique_name = format!("allocate tuple member {} {}:{}", i, span.line, span.start); - value.allocate_value(cs.ns(|| unique_name), span) - }) - .collect::>()?; + value.allocate_value(cs.ns(|| unique_name), span) + })?; } ConstrainedValue::CircuitExpression(_id, members) => { - members - .iter_mut() - .enumerate() - .map(|(i, member)| { - let unique_name = format!("allocate circuit member {} {}:{}", i, span.line, span.start); + members.iter_mut().enumerate().try_for_each(|(i, member)| { + let unique_name = format!("allocate circuit member {} {}:{}", i, span.line, span.start); - member.1.allocate_value(cs.ns(|| unique_name), span) - }) - .collect::>()?; + member.1.allocate_value(cs.ns(|| unique_name), span) + })?; } ConstrainedValue::Mutable(value) => { value.allocate_value(cs, span)?; diff --git a/compiler/tests/address/mod.rs b/compiler/tests/address/mod.rs index c3c2167cd4..3d892a5fb7 100644 --- a/compiler/tests/address/mod.rs +++ b/compiler/tests/address/mod.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{assert_satisfied, expect_compiler_error, generate_main_input, parse_program}; -use leo_typed::InputValue; +use leo_ast::InputValue; static TEST_ADDRESS_1: &str = "aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8"; static TEST_ADDRESS_2: &str = "aleo18qgam03qe483tdrcc3fkqwpp38ehff4a2xma6lu7hams6lfpgcpq3dq05r"; diff --git a/compiler/tests/array/mod.rs b/compiler/tests/array/mod.rs index 62a18bd541..59610476e5 100644 --- a/compiler/tests/array/mod.rs +++ b/compiler/tests/array/mod.rs @@ -152,7 +152,7 @@ fn test_multi_fail_initializer() { let program_bytes = include_bytes!("multi_fail_initializer.leo"); let program = parse_program(program_bytes).unwrap(); - expect_compiler_error(program); + let _err = expect_compiler_error(program); } #[test] @@ -160,7 +160,7 @@ fn test_multi_inline_fail() { let program_bytes = include_bytes!("multi_fail_inline.leo"); let program = parse_program(program_bytes).unwrap(); - expect_compiler_error(program); + let _err = expect_compiler_error(program); } #[test] @@ -176,7 +176,7 @@ fn test_multi_initializer_fail() { let program_bytes = include_bytes!("multi_initializer_fail.leo"); let program = parse_program(program_bytes).unwrap(); - expect_compiler_error(program); + let _err = expect_compiler_error(program); } #[test] @@ -192,7 +192,7 @@ fn test_nested_3x2_value_fail() { let program_bytes = include_bytes!("nested_3x2_value_fail.leo"); let program = parse_program(program_bytes).unwrap(); - expect_compiler_error(program); + let _err = expect_compiler_error(program); } #[test] @@ -208,7 +208,7 @@ fn test_tuple_3x2_value_fail() { let program_bytes = include_bytes!("tuple_3x2_value_fail.leo"); let program = parse_program(program_bytes).unwrap(); - expect_compiler_error(program); + let _err = expect_compiler_error(program); } #[test] @@ -252,7 +252,7 @@ fn test_type_nested_value_nested_3x2_fail() { let program_bytes = include_bytes!("type_nested_value_nested_3x2_fail.leo"); let program = parse_program(program_bytes).unwrap(); - expect_compiler_error(program); + let _err = expect_compiler_error(program); } #[test] @@ -268,7 +268,7 @@ fn test_type_nested_value_nested_4x3x2_fail() { let program_bytes = include_bytes!("type_nested_value_nested_4x3x2_fail.leo"); let program = parse_program(program_bytes).unwrap(); - expect_compiler_error(program); + let _err = expect_compiler_error(program); } #[test] @@ -284,7 +284,7 @@ fn test_type_nested_value_tuple_3x2_fail() { let program_bytes = include_bytes!("type_nested_value_tuple_3x2_fail.leo"); let program = parse_program(program_bytes).unwrap(); - expect_compiler_error(program); + let _err = expect_compiler_error(program); } #[test] @@ -300,7 +300,7 @@ fn test_type_nested_value_tuple_4x3x2_fail() { let program_bytes = include_bytes!("type_nested_value_tuple_4x3x2_fail.leo"); let program = parse_program(program_bytes).unwrap(); - expect_compiler_error(program); + let _err = expect_compiler_error(program); } #[test] @@ -316,7 +316,7 @@ fn test_type_tuple_value_nested_3x2_fail() { let program_bytes = include_bytes!("type_tuple_value_nested_3x2_fail.leo"); let program = parse_program(program_bytes).unwrap(); - expect_compiler_error(program); + let _err = expect_compiler_error(program); } #[test] @@ -332,7 +332,7 @@ fn test_type_tuple_value_nested_4x3x2_fail() { let program_bytes = include_bytes!("type_tuple_value_nested_4x3x2_fail.leo"); let program = parse_program(program_bytes).unwrap(); - expect_compiler_error(program); + let _err = expect_compiler_error(program); } #[test] @@ -348,7 +348,7 @@ fn test_type_tuple_value_tuple_3x2_fail() { let program_bytes = include_bytes!("type_tuple_value_tuple_3x2_fail.leo"); let program = parse_program(program_bytes).unwrap(); - expect_compiler_error(program); + let _err = expect_compiler_error(program); } #[test] @@ -364,7 +364,7 @@ fn test_type_tuple_value_tuple_4x3x2_fail() { let program_bytes = include_bytes!("type_tuple_value_tuple_4x3x2_fail.leo"); let program = parse_program(program_bytes).unwrap(); - expect_compiler_error(program); + let _err = expect_compiler_error(program); } // Tests for nested multi-dimensional arrays as input to the program diff --git a/compiler/tests/array/output/registers_ones.out b/compiler/tests/array/output/registers_ones.out index c6a97c7fd7..05a8842ec3 100644 --- a/compiler/tests/array/output/registers_ones.out +++ b/compiler/tests/array/output/registers_ones.out @@ -1,2 +1,2 @@ [registers] -r: [u8; (3)] = [1, 1, 1]; +r: [u8; 3] = [1, 1, 1]; diff --git a/compiler/tests/array/output/registers_zeros.out b/compiler/tests/array/output/registers_zeros.out index e8c21bb46a..4fdb9f3359 100644 --- a/compiler/tests/array/output/registers_zeros.out +++ b/compiler/tests/array/output/registers_zeros.out @@ -1,2 +1,2 @@ [registers] -r: [u8; (3)] = [0, 0, 0]; +r: [u8; 3] = [0, 0, 0]; diff --git a/compiler/tests/boolean/mod.rs b/compiler/tests/boolean/mod.rs index c51bacf790..ac221986d0 100644 --- a/compiler/tests/boolean/mod.rs +++ b/compiler/tests/boolean/mod.rs @@ -22,7 +22,6 @@ use crate::{ parse_program_with_input, EdwardsTestCompiler, }; -use leo_compiler::errors::{BooleanError, CompilerError, ExpressionError, FunctionError, StatementError}; pub fn output_true(program: EdwardsTestCompiler) { let expected = include_bytes!("output/registers_true.out"); @@ -38,15 +37,6 @@ pub fn output_false(program: EdwardsTestCompiler) { assert_eq!(expected, actual.bytes().as_slice()); } -fn fail_boolean_statement(program: EdwardsTestCompiler) { - match expect_compiler_error(program) { - CompilerError::FunctionError(FunctionError::StatementError(StatementError::ExpressionError( - ExpressionError::BooleanError(BooleanError::Error(_)), - ))) => {} - e => panic!("Expected boolean error, got {}", e), - } -} - #[test] fn test_input_pass() { let program_bytes = include_bytes!("assert_eq_input.leo"); @@ -136,13 +126,13 @@ fn test_false_or_false() { assert_satisfied(program); } -#[test] -fn test_true_or_u32() { - let bytes = include_bytes!("true_or_u32.leo"); - let program = parse_program(bytes).unwrap(); - - fail_boolean_statement(program); -} +// #[test] +// fn test_true_or_u32() { +// let bytes = include_bytes!("true_or_u32.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } // Boolean and && @@ -170,13 +160,13 @@ fn test_false_and_false() { assert_satisfied(program); } -#[test] -fn test_true_and_u32() { - let bytes = include_bytes!("true_and_u32.leo"); - let program = parse_program(bytes).unwrap(); - - fail_boolean_statement(program); -} +// #[test] +// fn test_true_and_u32() { +// let bytes = include_bytes!("true_and_u32.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } // All diff --git a/compiler/tests/circuits/mod.rs b/compiler/tests/circuits/mod.rs index 4c9c8665e9..df63410d1e 100644 --- a/compiler/tests/circuits/mod.rs +++ b/compiler/tests/circuits/mod.rs @@ -14,17 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{assert_satisfied, expect_compiler_error, parse_program, EdwardsTestCompiler}; -use leo_compiler::errors::{CompilerError, ExpressionError, FunctionError, StatementError}; - -fn expect_fail(program: EdwardsTestCompiler) { - match expect_compiler_error(program) { - CompilerError::FunctionError(FunctionError::StatementError(StatementError::ExpressionError( - ExpressionError::Error(_string), - ))) => {} - error => panic!("Expected invalid circuit member error, got {}", error), - } -} +use crate::{assert_satisfied, expect_compiler_error, parse_program}; // Expressions @@ -41,16 +31,16 @@ fn test_inline_fail() { let bytes = include_bytes!("inline_fail.leo"); let program = parse_program(bytes).unwrap(); - expect_fail(program); + expect_compiler_error(program); } -#[test] -fn test_inline_undefined() { - let bytes = include_bytes!("inline_undefined.leo"); - let program = parse_program(bytes).unwrap(); - - expect_fail(program); -} +// #[test] +// fn test_inline_undefined() { +// let bytes = include_bytes!("inline_undefined.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } // Members @@ -62,13 +52,13 @@ fn test_member_variable() { assert_satisfied(program); } -#[test] -fn test_member_variable_fail() { - let bytes = include_bytes!("member_variable_fail.leo"); - let program = parse_program(bytes).unwrap(); - - expect_fail(program); -} +// #[test] +// fn test_member_variable_fail() { +// let bytes = include_bytes!("member_variable_fail.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } #[test] fn test_member_variable_and_function() { @@ -86,21 +76,21 @@ fn test_member_function() { assert_satisfied(program); } -#[test] -fn test_member_function_fail() { - let bytes = include_bytes!("member_function_fail.leo"); - let program = parse_program(bytes).unwrap(); +// #[test] +// fn test_member_function_fail() { +// let bytes = include_bytes!("member_function_fail.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } - expect_fail(program); -} - -#[test] -fn test_member_function_invalid() { - let bytes = include_bytes!("member_function_invalid.leo"); - let program = parse_program(bytes).unwrap(); - - expect_fail(program); -} +// #[test] +// fn test_member_function_invalid() { +// let bytes = include_bytes!("member_function_invalid.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } #[test] fn test_member_function_nested() { @@ -126,31 +116,31 @@ fn test_member_static_function_nested() { assert_satisfied(program); } -#[test] -fn test_member_static_function_invalid() { - let bytes = include_bytes!("member_static_function_invalid.leo"); - let program = parse_program(bytes).unwrap(); +// #[test] +// fn test_member_static_function_invalid() { +// let bytes = include_bytes!("member_static_function_invalid.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error) +// } - expect_fail(program) -} - -#[test] -fn test_member_static_function_undefined() { - let bytes = include_bytes!("member_static_function_undefined.leo"); - let program = parse_program(bytes).unwrap(); - - expect_fail(program) -} +// #[test] +// fn test_member_static_function_undefined() { +// let bytes = include_bytes!("member_static_function_undefined.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error) +// } // Mutability -#[test] -fn test_mutate_function_fail() { - let bytes = include_bytes!("mut_function_fail.leo"); - let program = parse_program(bytes).unwrap(); - - expect_compiler_error(program); -} +// #[test] +// fn test_mutate_function_fail() { +// let bytes = include_bytes!("mut_function_fail.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } #[test] fn test_mutate_self_variable() { @@ -168,29 +158,29 @@ fn test_mutate_self_variable_fail() { expect_compiler_error(program); } -#[test] -fn test_mutate_self_function_fail() { - let bytes = include_bytes!("mut_self_function_fail.leo"); - let program = parse_program(bytes).unwrap(); +// #[test] +// fn test_mutate_self_function_fail() { +// let bytes = include_bytes!("mut_self_function_fail.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } - expect_compiler_error(program); -} +// #[test] +// fn test_mutate_self_static_function_fail() { +// let bytes = include_bytes!("mut_self_static_function_fail.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } -#[test] -fn test_mutate_self_static_function_fail() { - let bytes = include_bytes!("mut_self_static_function_fail.leo"); - let program = parse_program(bytes).unwrap(); - - expect_compiler_error(program); -} - -#[test] -fn test_mutate_static_function_fail() { - let bytes = include_bytes!("mut_static_function_fail.leo"); - let program = parse_program(bytes).unwrap(); - - expect_compiler_error(program); -} +// #[test] +// fn test_mutate_static_function_fail() { +// let bytes = include_bytes!("mut_static_function_fail.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } #[test] fn test_mutate_variable() { @@ -210,13 +200,13 @@ fn test_mutate_variable_fail() { // Self -#[test] -fn test_self_fail() { - let bytes = include_bytes!("self_fail.leo"); - let program = parse_program(bytes).unwrap(); - - expect_compiler_error(program); -} +// #[test] +// fn test_self_fail() { +// let bytes = include_bytes!("self_fail.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } #[test] fn test_self_member_pass() { @@ -234,13 +224,13 @@ fn test_self_member_invalid() { let _err = expect_compiler_error(program); } -#[test] -fn test_self_member_undefined() { - let bytes = include_bytes!("self_member_undefined.leo"); - let program = parse_program(bytes).unwrap(); - - let _err = expect_compiler_error(program); -} +// #[test] +// fn test_self_member_undefined() { +// let bytes = include_bytes!("self_member_undefined.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } // All diff --git a/compiler/tests/circuits/mut_function_fail.leo b/compiler/tests/circuits/mut_function_fail.leo index ed3092c656..3469f97627 100644 --- a/compiler/tests/circuits/mut_function_fail.leo +++ b/compiler/tests/circuits/mut_function_fail.leo @@ -1,4 +1,6 @@ circuit Foo { + a: u8, + function bar() {} } diff --git a/compiler/tests/console/mod.rs b/compiler/tests/console/mod.rs index 2716f815a5..ba7c48aae9 100644 --- a/compiler/tests/console/mod.rs +++ b/compiler/tests/console/mod.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{assert_satisfied, expect_compiler_error, generate_main_input, parse_program}; -use leo_typed::InputValue; +use leo_ast::InputValue; #[test] fn test_log() { diff --git a/compiler/tests/core/mod.rs b/compiler/tests/core/mod.rs index a520d60ac5..9e22953c05 100644 --- a/compiler/tests/core/mod.rs +++ b/compiler/tests/core/mod.rs @@ -16,39 +16,39 @@ pub mod packages; -use crate::{assert_satisfied, expect_compiler_error, parse_program}; +use crate::{assert_satisfied, parse_program}; -#[test] -fn test_core_circuit_invalid() { - let program_bytes = include_bytes!("core_package_invalid.leo"); - let program = parse_program(program_bytes).unwrap(); - - expect_compiler_error(program); -} - -#[test] -fn test_core_circuit_star_fail() { - let program_bytes = include_bytes!("core_circuit_star_fail.leo"); - let program = parse_program(program_bytes).unwrap(); - - expect_compiler_error(program); -} - -#[test] -fn test_core_package_invalid() { - let program_bytes = include_bytes!("core_package_invalid.leo"); - let program = parse_program(program_bytes).unwrap(); - - expect_compiler_error(program); -} - -#[test] -fn test_core_unstable_package_invalid() { - let program_bytes = include_bytes!("core_unstable_package_invalid.leo"); - let program = parse_program(program_bytes).unwrap(); - - expect_compiler_error(program); -} +// #[test] +// fn test_core_circuit_invalid() { +// let program_bytes = include_bytes!("core_package_invalid.leo"); +// let program = parse_program(program_bytes).err().unwrap(); +// +// expect_symbol_table_error(program); +// } +// +// #[test] +// fn test_core_circuit_star_fail() { +// let program_bytes = include_bytes!("core_circuit_star_fail.leo"); +// let error = parse_program(program_bytes).err().unwrap(); +// +// expect_symbol_table_error(error); +// } +// +// #[test] +// fn test_core_package_invalid() { +// let program_bytes = include_bytes!("core_package_invalid.leo"); +// let error = parse_program(program_bytes).err().unwrap(); +// +// expect_symbol_table_error(error); +// } +// +// #[test] +// fn test_core_unstable_package_invalid() { +// let program_bytes = include_bytes!("core_unstable_package_invalid.leo"); +// let error = parse_program(program_bytes).err().unwrap(); +// +// expect_symbol_table_error(error); +// } #[test] fn test_unstable_blake2s_sanity() { diff --git a/compiler/tests/core/packages/unstable/blake2s/mod.rs b/compiler/tests/core/packages/unstable/blake2s/mod.rs index 13de62b45a..1c1476c495 100644 --- a/compiler/tests/core/packages/unstable/blake2s/mod.rs +++ b/compiler/tests/core/packages/unstable/blake2s/mod.rs @@ -14,37 +14,30 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ - assert_satisfied, - expect_compiler_error, - generate_main_input, - get_output, - parse_program, - parse_program_with_input, -}; +use crate::{assert_satisfied, generate_main_input, get_output, parse_program, parse_program_with_input}; +use leo_ast::InputValue; use leo_input::types::{IntegerType, U8Type, UnsignedIntegerType}; -use leo_typed::InputValue; use rand::{Rng, SeedableRng}; use rand_xorshift::XorShiftRng; use snarkos_algorithms::prf::blake2s::Blake2s as B2SPRF; use snarkos_models::algorithms::PRF; +// +// #[test] +// fn test_arguments_length_fail() { +// let program_bytes = include_bytes!("arguments_length_fail.leo"); +// let error = parse_program(program_bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } -#[test] -fn test_arguments_length_fail() { - let program_bytes = include_bytes!("arguments_length_fail.leo"); - let program = parse_program(program_bytes).unwrap(); - - expect_compiler_error(program); -} - -#[test] -fn test_arguments_type_fail() { - let program_bytes = include_bytes!("arguments_type_fail.leo"); - let program = parse_program(program_bytes).unwrap(); - - expect_compiler_error(program); -} +// #[test] +// fn test_arguments_type_fail() { +// let program_bytes = include_bytes!("arguments_type_fail.leo"); +// let error = parse_program(program_bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } #[test] fn test_blake2s_input() { diff --git a/compiler/tests/core/packages/unstable/blake2s/outputs/valid_output.out b/compiler/tests/core/packages/unstable/blake2s/outputs/valid_output.out index 8a8a447558..f8f60f3e4e 100644 --- a/compiler/tests/core/packages/unstable/blake2s/outputs/valid_output.out +++ b/compiler/tests/core/packages/unstable/blake2s/outputs/valid_output.out @@ -1,2 +1,2 @@ [registers] -r0: [u8; (32)] = [174, 9, 219, 124, 213, 79, 66, 180, 144, 239, 9, 182, 188, 84, 26, 246, 136, 228, 149, 155, 184, 197, 63, 53, 154, 111, 86, 227, 138, 180, 84, 163]; +r0: [u8; 32] = [174, 9, 219, 124, 213, 79, 66, 180, 144, 239, 9, 182, 188, 84, 26, 246, 136, 228, 149, 155, 184, 197, 63, 53, 154, 111, 86, 227, 138, 180, 84, 163]; diff --git a/compiler/tests/field/mod.rs b/compiler/tests/field/mod.rs index a57817b2f7..0cb5e4198c 100644 --- a/compiler/tests/field/mod.rs +++ b/compiler/tests/field/mod.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{assert_satisfied, expect_compiler_error, generate_main_input, parse_program}; -use leo_typed::InputValue; +use leo_ast::InputValue; use snarkos_curves::edwards_bls12::Fq; use snarkos_utilities::bytes::ToBytes; diff --git a/compiler/tests/function/array_input.leo b/compiler/tests/function/array_input.leo new file mode 100644 index 0000000000..a70483cae7 --- /dev/null +++ b/compiler/tests/function/array_input.leo @@ -0,0 +1,6 @@ +function foo(a: [u8; 1]) {} + +function main() { + let a: [u16; 1] = [1; 1]; + foo(a); +} \ No newline at end of file diff --git a/compiler/tests/function/mod.rs b/compiler/tests/function/mod.rs index d5a3c3548b..a5a4e2c9db 100644 --- a/compiler/tests/function/mod.rs +++ b/compiler/tests/function/mod.rs @@ -14,25 +14,9 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ - assert_satisfied, - expect_compiler_error, - get_output, - parse_program, - parse_program_with_input, - EdwardsTestCompiler, -}; +use crate::{assert_satisfied, expect_compiler_error, get_output, parse_program, parse_program_with_input}; use leo_compiler::errors::{CompilerError, ExpressionError, FunctionError, StatementError}; -fn expect_undefined_identifier(program: EdwardsTestCompiler) { - match expect_compiler_error(program) { - CompilerError::FunctionError(FunctionError::StatementError(StatementError::ExpressionError( - ExpressionError::Error(_), - ))) => {} - error => panic!("Expected function undefined, got {}", error), - } -} - #[test] fn test_empty() { let bytes = include_bytes!("empty.leo"); @@ -126,13 +110,13 @@ fn test_scope_fail() { } } -#[test] -fn test_undefined() { - let bytes = include_bytes!("undefined.leo"); - let program = parse_program(bytes).unwrap(); - - expect_undefined_identifier(program); -} +// #[test] +// fn test_undefined() { +// let bytes = include_bytes!("undefined.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } #[test] fn test_value_unchanged() { @@ -142,6 +126,14 @@ fn test_value_unchanged() { assert_satisfied(program); } +// #[test] +// fn test_array_input() { +// let bytes = include_bytes!("array_input.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error) +// } + // Test return multidimensional arrays #[test] @@ -149,7 +141,7 @@ fn test_return_array_nested_fail() { let bytes = include_bytes!("return_array_nested_fail.leo"); let program = parse_program(bytes).unwrap(); - expect_compiler_error(program); + let _err = expect_compiler_error(program); } #[test] @@ -165,7 +157,7 @@ fn test_return_array_tuple_fail() { let bytes = include_bytes!("return_array_tuple_fail.leo"); let program = parse_program(bytes).unwrap(); - expect_compiler_error(program); + let _err = expect_compiler_error(program); } #[test] diff --git a/compiler/tests/group/mod.rs b/compiler/tests/group/mod.rs index 7606a738d3..c560afdc57 100644 --- a/compiler/tests/group/mod.rs +++ b/compiler/tests/group/mod.rs @@ -15,15 +15,10 @@ // along with the Leo library. If not, see . use crate::{ - assert_satisfied, - expect_compiler_error, - expect_synthesis_error, - field::field_to_decimal_string, - generate_main_input, - parse_program, - parse_program_with_input, + assert_satisfied, expect_compiler_error, expect_synthesis_error, field::field_to_decimal_string, + generate_main_input, parse_program, parse_program_with_input, }; -use leo_typed::{GroupCoordinate, GroupTuple, GroupValue, InputValue, Span}; +use leo_ast::{GroupCoordinate, GroupTuple, GroupValue, InputValue, Span}; use snarkos_curves::edwards_bls12::EdwardsAffine; diff --git a/compiler/tests/import/alias.leo b/compiler/tests/import/alias.leo index 96c65282ef..f153b5a128 100644 --- a/compiler/tests/import/alias.leo +++ b/compiler/tests/import/alias.leo @@ -1,4 +1,4 @@ -import test_import.foo as bar; +import test-import.foo as bar; function main() { console.assert(bar() == 1u32); diff --git a/compiler/tests/integers/i128/mod.rs b/compiler/tests/integers/i128/mod.rs index 9139cd5ec4..8cb73fff1a 100644 --- a/compiler/tests/integers/i128/mod.rs +++ b/compiler/tests/integers/i128/mod.rs @@ -21,8 +21,8 @@ use crate::{ integers::{expect_computation_error, expect_parsing_error, IntegerTester}, parse_program, }; +use leo_ast::InputValue; use leo_input::types::{I128Type, IntegerType, SignedIntegerType}; -use leo_typed::InputValue; test_int!( TestI128, diff --git a/compiler/tests/integers/i16/mod.rs b/compiler/tests/integers/i16/mod.rs index 9348352276..ad2988aad0 100644 --- a/compiler/tests/integers/i16/mod.rs +++ b/compiler/tests/integers/i16/mod.rs @@ -21,8 +21,8 @@ use crate::{ integers::{expect_computation_error, expect_parsing_error, IntegerTester}, parse_program, }; +use leo_ast::InputValue; use leo_input::types::{I16Type, IntegerType, SignedIntegerType}; -use leo_typed::InputValue; test_int!( TestI16, diff --git a/compiler/tests/integers/i32/mod.rs b/compiler/tests/integers/i32/mod.rs index 73e4e4a2f5..f4df3cc7ff 100644 --- a/compiler/tests/integers/i32/mod.rs +++ b/compiler/tests/integers/i32/mod.rs @@ -21,8 +21,8 @@ use crate::{ integers::{expect_computation_error, expect_parsing_error, IntegerTester}, parse_program, }; +use leo_ast::InputValue; use leo_input::types::{I32Type, IntegerType, SignedIntegerType}; -use leo_typed::InputValue; test_int!( TestI32, diff --git a/compiler/tests/integers/i64/mod.rs b/compiler/tests/integers/i64/mod.rs index 218842b3ad..713e02dd8e 100644 --- a/compiler/tests/integers/i64/mod.rs +++ b/compiler/tests/integers/i64/mod.rs @@ -21,8 +21,8 @@ use crate::{ integers::{expect_computation_error, expect_parsing_error, IntegerTester}, parse_program, }; +use leo_ast::InputValue; use leo_input::types::{I64Type, IntegerType, SignedIntegerType}; -use leo_typed::InputValue; test_int!( TestI64, diff --git a/compiler/tests/integers/i8/mod.rs b/compiler/tests/integers/i8/mod.rs index a17896c05d..813e2c13d2 100644 --- a/compiler/tests/integers/i8/mod.rs +++ b/compiler/tests/integers/i8/mod.rs @@ -21,8 +21,8 @@ use crate::{ integers::{expect_computation_error, expect_parsing_error, IntegerTester}, parse_program, }; +use leo_ast::InputValue; use leo_input::types::{I8Type, IntegerType, SignedIntegerType}; -use leo_typed::InputValue; test_int!( TestI8, diff --git a/compiler/tests/integers/u128/mod.rs b/compiler/tests/integers/u128/mod.rs index e5fd5f2d44..5312c43e5a 100644 --- a/compiler/tests/integers/u128/mod.rs +++ b/compiler/tests/integers/u128/mod.rs @@ -21,8 +21,8 @@ use crate::{ integers::{expect_parsing_error, IntegerTester}, parse_program, }; +use leo_ast::InputValue; use leo_input::types::{IntegerType, U128Type, UnsignedIntegerType}; -use leo_typed::InputValue; test_uint!( TestU128, diff --git a/compiler/tests/integers/u16/mod.rs b/compiler/tests/integers/u16/mod.rs index 1c2c45889b..fac708a456 100644 --- a/compiler/tests/integers/u16/mod.rs +++ b/compiler/tests/integers/u16/mod.rs @@ -21,8 +21,8 @@ use crate::{ integers::{expect_parsing_error, IntegerTester}, parse_program, }; +use leo_ast::InputValue; use leo_input::types::{IntegerType, U16Type, UnsignedIntegerType}; -use leo_typed::InputValue; test_uint!( TestU16, diff --git a/compiler/tests/integers/u32/mod.rs b/compiler/tests/integers/u32/mod.rs index 3ffb792f4d..ac6b51f3fd 100644 --- a/compiler/tests/integers/u32/mod.rs +++ b/compiler/tests/integers/u32/mod.rs @@ -21,8 +21,8 @@ use crate::{ integers::{expect_parsing_error, IntegerTester}, parse_program, }; +use leo_ast::InputValue; use leo_input::types::{IntegerType, U32Type, UnsignedIntegerType}; -use leo_typed::InputValue; test_uint!( TestU32, diff --git a/compiler/tests/integers/u64/mod.rs b/compiler/tests/integers/u64/mod.rs index 06fad4baa3..d66ec56e64 100644 --- a/compiler/tests/integers/u64/mod.rs +++ b/compiler/tests/integers/u64/mod.rs @@ -21,8 +21,8 @@ use crate::{ integers::{expect_parsing_error, IntegerTester}, parse_program, }; +use leo_ast::InputValue; use leo_input::types::{IntegerType, U64Type, UnsignedIntegerType}; -use leo_typed::InputValue; test_uint!( TestU64, diff --git a/compiler/tests/integers/u8/mod.rs b/compiler/tests/integers/u8/mod.rs index 335e4146ff..3eb3666263 100644 --- a/compiler/tests/integers/u8/mod.rs +++ b/compiler/tests/integers/u8/mod.rs @@ -21,8 +21,8 @@ use crate::{ integers::{expect_parsing_error, IntegerTester}, parse_program, }; +use leo_ast::InputValue; use leo_input::types::{IntegerType, U8Type, UnsignedIntegerType}; -use leo_typed::InputValue; test_uint!( TestU8, diff --git a/compiler/tests/mod.rs b/compiler/tests/mod.rs index 19d1039afd..478ccc9ab0 100644 --- a/compiler/tests/mod.rs +++ b/compiler/tests/mod.rs @@ -35,6 +35,7 @@ pub mod statements; pub mod syntax; pub mod tuples; +use leo_ast::{InputValue, MainInput}; use leo_compiler::{ compiler::Compiler, errors::CompilerError, @@ -43,7 +44,6 @@ use leo_compiler::{ OutputBytes, }; use leo_input::types::{IntegerType, U32Type, UnsignedIntegerType}; -use leo_typed::{InputValue, MainInput}; use snarkos_curves::edwards_bls12::Fq; use snarkos_models::gadgets::r1cs::TestConstraintSystem; @@ -180,12 +180,13 @@ pub(crate) fn expect_compiler_error(program: EdwardsTestCompiler) -> CompilerErr let mut cs = TestConstraintSystem::::new(); program.generate_constraints_helper(&mut cs).unwrap_err() } - -// pub(crate) fn expect_synthesis_error(program: EdwardsTestCompiler) { -// let mut cs = TestConstraintSystem::::new(); -// let _output = program.generate_constraints_helper(&mut cs).unwrap(); // -// assert!(!cs.is_satisfied()); +// pub(crate) fn expect_type_inference_error(error: CompilerError) { +// assert!(matches!(error, CompilerError::TypeInferenceError(_))) +// } + +// pub(crate) fn expect_symbol_table_error(error: CompilerError) { +// assert!(matches!(error, CompilerError::SymbolTableError(_))) // } pub(crate) fn generate_main_input(input: Vec<(&str, Option)>) -> MainInput { diff --git a/compiler/tests/mutability/mod.rs b/compiler/tests/mutability/mod.rs index ea380447bf..861ffd6a64 100644 --- a/compiler/tests/mutability/mod.rs +++ b/compiler/tests/mutability/mod.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{assert_satisfied, expect_compiler_error, generate_main_input, parse_program}; -use leo_typed::InputValue; +use leo_ast::InputValue; #[test] fn test_let() { @@ -89,21 +89,21 @@ fn test_circuit_variable_mut() { assert_satisfied(program); } -#[test] -fn test_circuit_function_mut() { - let bytes = include_bytes!("circuit_function_mut.leo"); - let program = parse_program(bytes).unwrap(); - - expect_compiler_error(program); -} - -#[test] -fn test_circuit_static_function_mut() { - let bytes = include_bytes!("circuit_static_function_mut.leo"); - let program = parse_program(bytes).unwrap(); - - expect_compiler_error(program); -} +// #[test] +// fn test_circuit_function_mut() { +// let bytes = include_bytes!("circuit_function_mut.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } +// +// #[test] +// fn test_circuit_static_function_mut() { +// let bytes = include_bytes!("circuit_static_function_mut.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } #[test] fn test_function_input() { diff --git a/compiler/tests/statements/conditional/mod.rs b/compiler/tests/statements/conditional/mod.rs index 9b6ae2fe2b..3c243c9804 100644 --- a/compiler/tests/statements/conditional/mod.rs +++ b/compiler/tests/statements/conditional/mod.rs @@ -24,7 +24,7 @@ use crate::{ parse_program_with_input, EdwardsTestCompiler, }; -use leo_typed::InputValue; +use leo_ast::InputValue; #[test] fn test_assert() { diff --git a/compiler/tests/statements/mod.rs b/compiler/tests/statements/mod.rs index 3180c6fa30..b5599d2dd5 100644 --- a/compiler/tests/statements/mod.rs +++ b/compiler/tests/statements/mod.rs @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{assert_satisfied, expect_compiler_error, generate_main_input, parse_program}; -use leo_typed::InputValue; +use crate::{assert_satisfied, generate_main_input, parse_program}; +use leo_ast::InputValue; pub mod conditional; @@ -57,10 +57,10 @@ fn test_iteration_basic() { assert_satisfied(program); } -#[test] -fn test_num_returns_fail() { - let bytes = include_bytes!("num_returns_fail.leo"); - let program = parse_program(bytes).unwrap(); - - expect_compiler_error(program); -} +// #[test] +// fn test_num_returns_fail() { +// let bytes = include_bytes!("num_returns_fail.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// expect_type_inference_error(error); +// } diff --git a/compiler/tests/statements/ternary_basic.leo b/compiler/tests/statements/ternary_basic.leo index 89158a3e78..5106363ce2 100644 --- a/compiler/tests/statements/ternary_basic.leo +++ b/compiler/tests/statements/ternary_basic.leo @@ -1,5 +1,5 @@ function main(a: bool, b: bool) { let c = if a ? true : false; - const a = c == b; + const d = c == b; } \ No newline at end of file diff --git a/compiler/tests/syntax/mod.rs b/compiler/tests/syntax/mod.rs index d1ba353324..9cd6aaf3f5 100644 --- a/compiler/tests/syntax/mod.rs +++ b/compiler/tests/syntax/mod.rs @@ -15,9 +15,10 @@ // along with the Leo library. If not, see . use crate::{expect_compiler_error, parse_input, parse_program}; -use leo_ast::ParserError; use leo_compiler::errors::{CompilerError, ExpressionError, FunctionError, StatementError}; +use leo_grammar::ParserError; use leo_input::InputParserError; +// use leo_type_inference::errors::{FrameError, TypeAssertionError, TypeInferenceError}; pub mod identifiers; @@ -67,17 +68,23 @@ fn input_syntax_error() { let bytes = include_bytes!("input_semicolon.leo"); let error = parse_input(bytes).err().unwrap(); + // Expect an input parser error. match error { CompilerError::InputParserError(InputParserError::SyntaxError(_)) => {} _ => panic!("input syntax error should be a ParserError"), } } -#[test] -fn test_compare_mismatched_types() { - let bytes = include_bytes!("compare_mismatched_types.leo"); - let program = parse_program(bytes).unwrap(); - - // previously this bug caused a stack overflow - expect_compiler_error(program); -} +// #[test] +// fn test_compare_mismatched_types() { +// let bytes = include_bytes!("compare_mismatched_types.leo"); +// let error = parse_program(bytes).err().unwrap(); +// +// // Expect a type inference error. +// match error { +// CompilerError::TypeInferenceError(TypeInferenceError::FrameError(FrameError::TypeAssertionError( +// TypeAssertionError::Error(_), +// ))) => {} +// error => panic!("Expected type inference error, found {}", error), +// } +// } diff --git a/core/Cargo.toml b/core/Cargo.toml index b752235b16..f62744892d 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leo-core" -version = "1.0.2" +version = "1.0.4" authors = [ "The Aleo Team " ] description = "Core package dependencies of the Leo programming language" homepage = "https://aleo.org" @@ -17,12 +17,12 @@ include = [ "Cargo.toml", "src", "README.md", "LICENSE.md" ] license = "GPL-3.0" edition = "2018" -[dependencies.leo-gadgets] -path = "../gadgets" +[dependencies.leo-ast] +path = "../ast" version = "1.0.4" -[dependencies.leo-typed] -path = "../typed" +[dependencies.leo-gadgets] +path = "../gadgets" version = "1.0.4" [dependencies.snarkos-errors] diff --git a/core/src/errors/core_circuit.rs b/core/src/errors/core_circuit.rs index 408d9617df..ce394e18de 100644 --- a/core/src/errors/core_circuit.rs +++ b/core/src/errors/core_circuit.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::Value; -use leo_typed::{Error as FormattedError, Span}; +use leo_ast::{Error as FormattedError, Span}; use snarkos_errors::gadgets::SynthesisError; diff --git a/core/src/errors/core_package.rs b/core/src/errors/core_package.rs index 2a285abfb7..7ce7f150b8 100644 --- a/core/src/errors/core_package.rs +++ b/core/src/errors/core_package.rs @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_typed::{Error as FormattedError, Span}; +use leo_ast::{Error as FormattedError, Span}; use std::path::Path; diff --git a/core/src/errors/core_package_list.rs b/core/src/errors/core_package_list.rs index cc23101924..f8c2f35026 100644 --- a/core/src/errors/core_package_list.rs +++ b/core/src/errors/core_package_list.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_typed::{Error as FormattedError, ImportSymbol, Span}; +use leo_ast::{Error as FormattedError, ImportSymbol, Span}; use crate::CorePackageError; use std::path::Path; diff --git a/core/src/errors/leo_core.rs b/core/src/errors/leo_core_package.rs similarity index 77% rename from core/src/errors/leo_core.rs rename to core/src/errors/leo_core_package.rs index 1c59ed9bc8..30db8ef7d3 100644 --- a/core/src/errors/leo_core.rs +++ b/core/src/errors/leo_core_package.rs @@ -15,12 +15,12 @@ // along with the Leo library. If not, see . use crate::{CoreCircuitError, CorePackageListError}; -use leo_typed::{Error as FormattedError, Span}; +use leo_ast::{Error as FormattedError, Span}; use std::path::Path; #[derive(Debug, Error)] -pub enum LeoCoreError { +pub enum LeoCorePackageError { #[error("{}", _0)] CoreCircuitError(#[from] CoreCircuitError), @@ -31,17 +31,17 @@ pub enum LeoCoreError { Error(#[from] FormattedError), } -impl LeoCoreError { +impl LeoCorePackageError { pub fn set_path(&mut self, path: &Path) { match self { - LeoCoreError::CoreCircuitError(error) => error.set_path(path), - LeoCoreError::CorePackageListError(error) => error.set_path(path), - LeoCoreError::Error(error) => error.set_path(path), + LeoCorePackageError::CoreCircuitError(error) => error.set_path(path), + LeoCorePackageError::CorePackageListError(error) => error.set_path(path), + LeoCorePackageError::Error(error) => error.set_path(path), } } fn new_from_span(message: String, span: Span) -> Self { - LeoCoreError::Error(FormattedError::new_from_span(message, span)) + LeoCorePackageError::Error(FormattedError::new_from_span(message, span)) } pub fn undefined_core_circuit(circuit_name: String, span: Span) -> Self { diff --git a/core/src/errors/mod.rs b/core/src/errors/mod.rs index 9bfb03c2ba..a99f9e8f47 100644 --- a/core/src/errors/mod.rs +++ b/core/src/errors/mod.rs @@ -23,5 +23,5 @@ pub use self::core_package::*; pub mod core_package_list; pub use self::core_package_list::*; -pub mod leo_core; -pub use self::leo_core::*; +pub mod leo_core_package; +pub use self::leo_core_package::*; diff --git a/core/src/lib.rs b/core/src/lib.rs index 73317cc472..67533ae4a5 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -27,7 +27,8 @@ pub mod types; pub use self::types::*; use crate::CoreCircuit; -use leo_typed::Span; +use leo_ast::Span; + use snarkos_models::{ curves::{Field, PrimeField}, gadgets::r1cs::ConstraintSystem, @@ -40,10 +41,10 @@ pub fn call_core_circuit>( circuit_name: String, arguments: Vec, span: Span, -) -> Result, LeoCoreError> { +) -> Result, LeoCorePackageError> { // Match core circuit name Ok(match circuit_name.as_str() { CORE_UNSTABLE_BLAKE2S_NAME => Blake2sCircuit::call(cs, arguments, span)?, - _ => return Err(LeoCoreError::undefined_core_circuit(circuit_name, span)), + _ => return Err(LeoCorePackageError::undefined_core_circuit(circuit_name, span)), }) } diff --git a/core/src/packages/unstable/blake2s.rs b/core/src/packages/unstable/blake2s.rs index 5031f32161..c4c37c4c91 100644 --- a/core/src/packages/unstable/blake2s.rs +++ b/core/src/packages/unstable/blake2s.rs @@ -16,15 +16,17 @@ use crate::{CoreCircuit, CoreCircuitError, Value}; -use leo_typed::{ +use leo_ast::{ + ArrayDimensions, Circuit, CircuitMember, Expression, Function, FunctionInput, + FunctionInputVariable, Identifier, - InputVariable, IntegerType, + PositiveNumber, Span, Statement, Type, @@ -67,26 +69,44 @@ impl CoreCircuit for Blake2sCircuit { span: span.clone(), }, input: vec![ - InputVariable::FunctionInput(FunctionInput { + FunctionInput::Variable(FunctionInputVariable { identifier: Identifier { name: "seed".to_owned(), span: span.clone(), }, mutable: false, - type_: Type::Array(Box::new(Type::IntegerType(IntegerType::U8)), vec![32usize]), + type_: Type::Array( + Box::new(Type::IntegerType(IntegerType::U8)), + ArrayDimensions(vec![PositiveNumber { + value: 32usize.to_string(), + span: span.clone(), + }]), + ), span: span.clone(), }), - InputVariable::FunctionInput(FunctionInput { + FunctionInput::Variable(FunctionInputVariable { identifier: Identifier { name: "message".to_owned(), span: span.clone(), }, mutable: false, - type_: Type::Array(Box::new(Type::IntegerType(IntegerType::U8)), vec![32usize]), + type_: Type::Array( + Box::new(Type::IntegerType(IntegerType::U8)), + ArrayDimensions(vec![PositiveNumber { + value: 32usize.to_string(), + span: span.clone(), + }]), + ), span: span.clone(), }), ], - returns: Some(Type::Array(Box::new(Type::IntegerType(IntegerType::U8)), vec![32usize])), + output: Some(Type::Array( + Box::new(Type::IntegerType(IntegerType::U8)), + ArrayDimensions(vec![PositiveNumber { + value: 32usize.to_string(), + span: span.clone(), + }]), + )), statements: vec![Statement::Return( Expression::CoreFunctionCall( Self::name(), diff --git a/core/src/types/core_circuit.rs b/core/src/types/core_circuit.rs index e1c3096e71..b098db3970 100644 --- a/core/src/types/core_circuit.rs +++ b/core/src/types/core_circuit.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{CoreCircuitError, Value}; -use leo_typed::{Circuit, Identifier, Span}; +use leo_ast::{Circuit, Identifier, Span}; use snarkos_models::{ curves::{Field, PrimeField}, diff --git a/core/src/types/core_circuit_struct_list.rs b/core/src/types/core_circuit_struct_list.rs index 4a93867bf4..8da8f6f160 100644 --- a/core/src/types/core_circuit_struct_list.rs +++ b/core/src/types/core_circuit_struct_list.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_typed::Circuit; +use leo_ast::Circuit; /// List of imported core circuit structs. /// This struct is created from a `CorePackageList` diff --git a/core/src/types/core_package.rs b/core/src/types/core_package.rs index fa9a4e7a00..814de215f5 100644 --- a/core/src/types/core_package.rs +++ b/core/src/types/core_package.rs @@ -20,7 +20,7 @@ use crate::{ CoreCircuitStructList, CorePackageError, }; -use leo_typed::{Identifier, ImportSymbol, Package, PackageAccess}; +use leo_ast::{Identifier, ImportSymbol, Package, PackageAccess}; use std::convert::TryFrom; /// A core package dependency to be imported into a Leo program. diff --git a/core/src/types/core_package_list.rs b/core/src/types/core_package_list.rs index 142e9f9089..cf2c760921 100644 --- a/core/src/types/core_package_list.rs +++ b/core/src/types/core_package_list.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{CoreCircuitStructList, CorePackage, CorePackageListError, UNSTABLE_CORE_PACKAGE_KEYWORD}; -use leo_typed::PackageAccess; +use leo_ast::PackageAccess; use std::convert::TryFrom; /// A list of core package dependencies. diff --git a/typed/Cargo.toml b/grammar/Cargo.toml similarity index 59% rename from typed/Cargo.toml rename to grammar/Cargo.toml index 5a02705611..c33d877dba 100644 --- a/typed/Cargo.toml +++ b/grammar/Cargo.toml @@ -1,8 +1,8 @@ [package] -name = "leo-typed" +name = "leo-grammar" version = "1.0.4" authors = [ "The Aleo Team " ] -description = "Typed AST of the Leo programming language" +description = "AST generated by pest from the Leo grammar rules" homepage = "https://aleo.org" repository = "https://github.com/AleoHQ/leo" keywords = [ @@ -18,42 +18,45 @@ license = "GPL-3.0" edition = "2018" [[bin]] -name = "leo_typed_ast" +name = "leo_grammar" path = "src/main.rs" [[bench]] -name = "typed_ast" -path = "benches/typed_ast.rs" +name = "ast" +path = "benches/ast.rs" harness = false -[dependencies.leo-ast] -path = "../ast" -version = "1.0.4" +[dependencies.from-pest] +version = "0.3.1" -[dependencies.leo-input] -path = "../input" -version = "1.0.4" - -[dependencies.snarkos-errors] -version = "1.1.3" -default-features = false - -[dependencies.snarkos-models] -version = "1.1.3" -default-features = false +[dependencies.lazy_static] +version = "1.3.0" [dependencies.pest] version = "2.0" +[dependencies.pest-ast] +version = "0.3.3" + +[dependencies.pest_derive] +version = "2.0" + [dependencies.serde] version = "1.0" +features = [ "derive" ] [dependencies.serde_json] version = "1.0" +[dependencies.thiserror] +version = "1.0" + +[dependencies.tracing] +version = "0.1" + [dev-dependencies.criterion] version = "0.3" [features] default = [ ] -ci_skip = [ "leo-ast/ci_skip" ] +ci_skip = [ ] diff --git a/ast/README.md b/grammar/README.md similarity index 70% rename from ast/README.md rename to grammar/README.md index 1752725766..b1b3c02f13 100644 --- a/ast/README.md +++ b/grammar/README.md @@ -1,9 +1,9 @@ -# leo-ast +# leo-grammar ## Command-line instructions To generate an AST of the Leo program and save it as a JSON file , run: ``` -leo_ast {PATH/TO/INPUT_FILENAME}.leo {PATH/TO/OUTPUT_DIRECTORY (optional)} +leo_grammar {PATH/TO/INPUT_FILENAME}.leo {PATH/TO/OUTPUT_DIRECTORY (optional)} ``` If no output directory is provided, then the program will store the JSON file in the local working directory. diff --git a/ast/benches/ast.rs b/grammar/benches/ast.rs similarity index 80% rename from ast/benches/ast.rs rename to grammar/benches/ast.rs index 1dc9fedf14..4b6d48b105 100644 --- a/ast/benches/ast.rs +++ b/grammar/benches/ast.rs @@ -14,13 +14,13 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_ast::LeoAst; +use leo_grammar::Grammar; use criterion::{black_box, criterion_group, criterion_main, Criterion}; use std::path::Path; -fn leo_ast<'ast>(filepath: &'ast Path, program_string: &'ast str) { - let result = LeoAst::<'ast>::new(filepath, program_string).unwrap(); +fn leo_grammar<'ast>(filepath: &'ast Path, program_string: &'ast str) { + let result = Grammar::<'ast>::new(filepath, program_string).unwrap(); black_box(result); } @@ -28,7 +28,7 @@ fn criterion_benchmark(c: &mut Criterion) { let filepath = Path::new("./main.leo").to_path_buf(); let program_string = include_str!("./main.leo"); - c.bench_function("LeoAst::new", |b| b.iter(|| leo_ast(&filepath, program_string))); + c.bench_function("Grammar::new", |b| b.iter(|| leo_grammar(&filepath, program_string))); } criterion_group!(benches, criterion_benchmark); diff --git a/ast/benches/main.leo b/grammar/benches/main.leo similarity index 100% rename from ast/benches/main.leo rename to grammar/benches/main.leo diff --git a/ast/src/access/access.rs b/grammar/src/access/access.rs similarity index 100% rename from ast/src/access/access.rs rename to grammar/src/access/access.rs diff --git a/ast/src/access/array_access.rs b/grammar/src/access/array_access.rs similarity index 100% rename from ast/src/access/array_access.rs rename to grammar/src/access/array_access.rs diff --git a/ast/src/access/assignee_access.rs b/grammar/src/access/assignee_access.rs similarity index 100% rename from ast/src/access/assignee_access.rs rename to grammar/src/access/assignee_access.rs diff --git a/ast/src/access/call_access.rs b/grammar/src/access/call_access.rs similarity index 100% rename from ast/src/access/call_access.rs rename to grammar/src/access/call_access.rs diff --git a/ast/src/access/member_access.rs b/grammar/src/access/member_access.rs similarity index 100% rename from ast/src/access/member_access.rs rename to grammar/src/access/member_access.rs diff --git a/ast/src/access/mod.rs b/grammar/src/access/mod.rs similarity index 100% rename from ast/src/access/mod.rs rename to grammar/src/access/mod.rs diff --git a/ast/src/access/static_member_access.rs b/grammar/src/access/static_member_access.rs similarity index 100% rename from ast/src/access/static_member_access.rs rename to grammar/src/access/static_member_access.rs diff --git a/ast/src/access/tuple_access.rs b/grammar/src/access/tuple_access.rs similarity index 100% rename from ast/src/access/tuple_access.rs rename to grammar/src/access/tuple_access.rs diff --git a/ast/src/annotations/annotation_arguments.rs b/grammar/src/annotations/annotation_arguments.rs similarity index 100% rename from ast/src/annotations/annotation_arguments.rs rename to grammar/src/annotations/annotation_arguments.rs diff --git a/ast/src/annotations/annotation_name.rs b/grammar/src/annotations/annotation_name.rs similarity index 100% rename from ast/src/annotations/annotation_name.rs rename to grammar/src/annotations/annotation_name.rs diff --git a/ast/src/annotations/annotation_symbol.rs b/grammar/src/annotations/annotation_symbol.rs similarity index 100% rename from ast/src/annotations/annotation_symbol.rs rename to grammar/src/annotations/annotation_symbol.rs diff --git a/ast/src/annotations/annotations.rs b/grammar/src/annotations/annotations.rs similarity index 100% rename from ast/src/annotations/annotations.rs rename to grammar/src/annotations/annotations.rs diff --git a/ast/src/annotations/mod.rs b/grammar/src/annotations/mod.rs similarity index 100% rename from ast/src/annotations/mod.rs rename to grammar/src/annotations/mod.rs diff --git a/ast/src/ast.rs b/grammar/src/ast.rs similarity index 100% rename from ast/src/ast.rs rename to grammar/src/ast.rs diff --git a/grammar/src/circuits/circuit.rs b/grammar/src/circuits/circuit.rs new file mode 100644 index 0000000000..26bc545e00 --- /dev/null +++ b/grammar/src/circuits/circuit.rs @@ -0,0 +1,31 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ast::Rule, circuits::CircuitMember, common::Identifier, SpanDef}; + +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::circuit))] +pub struct Circuit<'ast> { + pub identifier: Identifier<'ast>, + pub members: Vec>, + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, +} diff --git a/ast/src/circuits/circuit_function.rs b/grammar/src/circuits/circuit_function.rs similarity index 100% rename from ast/src/circuits/circuit_function.rs rename to grammar/src/circuits/circuit_function.rs diff --git a/grammar/src/circuits/circuit_member.rs b/grammar/src/circuits/circuit_member.rs new file mode 100644 index 0000000000..d3d949e99b --- /dev/null +++ b/grammar/src/circuits/circuit_member.rs @@ -0,0 +1,30 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ + ast::Rule, + circuits::{CircuitFunction, CircuitVariableDefinition}, +}; + +use pest_ast::FromPest; +use serde::Serialize; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::circuit_member))] +pub enum CircuitMember<'ast> { + CircuitVariableDefinition(CircuitVariableDefinition<'ast>), + CircuitFunction(CircuitFunction<'ast>), +} diff --git a/ast/src/circuits/circuit_variable.rs b/grammar/src/circuits/circuit_variable.rs similarity index 100% rename from ast/src/circuits/circuit_variable.rs rename to grammar/src/circuits/circuit_variable.rs diff --git a/grammar/src/circuits/circuit_variable_definition.rs b/grammar/src/circuits/circuit_variable_definition.rs new file mode 100644 index 0000000000..8bd462a099 --- /dev/null +++ b/grammar/src/circuits/circuit_variable_definition.rs @@ -0,0 +1,37 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ + ast::Rule, + common::{Identifier, Mutable}, + types::Type, + SpanDef, +}; + +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::circuit_variable_definition))] +pub struct CircuitVariableDefinition<'ast> { + pub mutable: Option, + pub identifier: Identifier<'ast>, + pub type_: Type<'ast>, + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, +} diff --git a/typed/src/circuits/mod.rs b/grammar/src/circuits/mod.rs similarity index 88% rename from typed/src/circuits/mod.rs rename to grammar/src/circuits/mod.rs index e25aaff89e..768a36fd7e 100644 --- a/typed/src/circuits/mod.rs +++ b/grammar/src/circuits/mod.rs @@ -17,8 +17,14 @@ pub mod circuit; pub use circuit::*; +pub mod circuit_variable; +pub use circuit_variable::*; + pub mod circuit_variable_definition; pub use circuit_variable_definition::*; +pub mod circuit_function; +pub use circuit_function::*; + pub mod circuit_member; pub use circuit_member::*; diff --git a/grammar/src/common/assignee.rs b/grammar/src/common/assignee.rs new file mode 100644 index 0000000000..6136b05440 --- /dev/null +++ b/grammar/src/common/assignee.rs @@ -0,0 +1,45 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{access::AssigneeAccess, ast::Rule, common::SelfKeywordOrIdentifier, SpanDef}; + +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::assignee))] +pub struct Assignee<'ast> { + pub name: SelfKeywordOrIdentifier<'ast>, + pub accesses: Vec>, + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for Assignee<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.name)?; + for (i, access) in self.accesses.iter().enumerate() { + write!(f, "{}", access)?; + if i < self.accesses.len() - 1 { + write!(f, ", ")?; + } + } + write!(f, "") + } +} diff --git a/grammar/src/common/declare.rs b/grammar/src/common/declare.rs new file mode 100644 index 0000000000..dabc1bbfdb --- /dev/null +++ b/grammar/src/common/declare.rs @@ -0,0 +1,35 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::ast::Rule; + +use pest_ast::FromPest; +use serde::Serialize; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::declare))] +pub enum Declare { + Const(Const), + Let(Let), +} + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::const_))] +pub struct Const {} + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::let_))] +pub struct Let {} diff --git a/ast/src/common/eoi.rs b/grammar/src/common/eoi.rs similarity index 100% rename from ast/src/common/eoi.rs rename to grammar/src/common/eoi.rs diff --git a/typed/src/functions/test_function.rs b/grammar/src/common/identifier.rs similarity index 57% rename from typed/src/functions/test_function.rs rename to grammar/src/common/identifier.rs index d4d2fec220..e349a3b259 100644 --- a/typed/src/functions/test_function.rs +++ b/grammar/src/common/identifier.rs @@ -14,22 +14,28 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{Function, Identifier}; -use leo_ast::functions::TestFunction as AstTestFunction; +use crate::{ + ast::{span_into_string, Rule}, + SpanDef, +}; -use serde::{Deserialize, Serialize}; +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; +use std::fmt; -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct TestFunction { - pub function: Function, - pub input_file: Option, +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::identifier))] +pub struct Identifier<'ast> { + #[pest_ast(outer(with(span_into_string)))] + pub value: String, + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, } -impl<'ast> From> for TestFunction { - fn from(test: AstTestFunction) -> Self { - TestFunction { - function: Function::from(test.function), - input_file: None, // pass custom input file with `@context` annotation - } +impl<'ast> fmt::Display for Identifier<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.value) } } diff --git a/ast/src/common/keyword_or_identifier.rs b/grammar/src/common/keyword_or_identifier.rs similarity index 100% rename from ast/src/common/keyword_or_identifier.rs rename to grammar/src/common/keyword_or_identifier.rs diff --git a/ast/src/common/line_end.rs b/grammar/src/common/line_end.rs similarity index 100% rename from ast/src/common/line_end.rs rename to grammar/src/common/line_end.rs diff --git a/typed/src/common/mod.rs b/grammar/src/common/mod.rs similarity index 72% rename from typed/src/common/mod.rs rename to grammar/src/common/mod.rs index 9187f2e653..119287f5cc 100644 --- a/typed/src/common/mod.rs +++ b/grammar/src/common/mod.rs @@ -20,18 +20,42 @@ pub use assignee::*; pub mod declare; pub use declare::*; +pub mod eoi; +pub use eoi::*; + pub mod identifier; pub use identifier::*; +pub mod keyword_or_identifier; +pub use keyword_or_identifier::*; + +pub mod line_end; +pub use line_end::*; + +pub mod mutable; +pub use mutable::*; + +pub mod range; +pub use range::*; + pub mod range_or_expression; pub use range_or_expression::*; -pub mod span; -pub use span::*; +pub mod self_keyword; +pub use self_keyword::*; + +pub mod self_keyword_or_identifier; +pub use self_keyword_or_identifier::*; + +pub mod spread; +pub use spread::*; pub mod spread_or_expression; pub use spread_or_expression::*; +pub mod static_; +pub use static_::*; + pub mod variables; pub use variables::*; diff --git a/ast/src/common/mutable.rs b/grammar/src/common/mutable.rs similarity index 100% rename from ast/src/common/mutable.rs rename to grammar/src/common/mutable.rs diff --git a/ast/src/common/range.rs b/grammar/src/common/range.rs similarity index 100% rename from ast/src/common/range.rs rename to grammar/src/common/range.rs diff --git a/grammar/src/common/range_or_expression.rs b/grammar/src/common/range_or_expression.rs new file mode 100644 index 0000000000..5a13b3e4cc --- /dev/null +++ b/grammar/src/common/range_or_expression.rs @@ -0,0 +1,50 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ast::Rule, common::Range, expressions::Expression}; + +use pest_ast::FromPest; +use serde::Serialize; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::range_or_expression))] +pub enum RangeOrExpression<'ast> { + Range(Range<'ast>), + Expression(Expression<'ast>), +} + +impl<'ast> fmt::Display for RangeOrExpression<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + RangeOrExpression::Expression(ref expression) => write!(f, "{}", expression), + RangeOrExpression::Range(ref range) => write!( + f, + "{}..{}", + range + .from + .as_ref() + .map(|v| v.to_string()) + .unwrap_or_else(|| "".to_string()), + range + .to + .as_ref() + .map(|v| v.to_string()) + .unwrap_or_else(|| "".to_string()), + ), + } + } +} diff --git a/ast/src/common/self_keyword.rs b/grammar/src/common/self_keyword.rs similarity index 100% rename from ast/src/common/self_keyword.rs rename to grammar/src/common/self_keyword.rs diff --git a/ast/src/common/self_keyword_or_identifier.rs b/grammar/src/common/self_keyword_or_identifier.rs similarity index 100% rename from ast/src/common/self_keyword_or_identifier.rs rename to grammar/src/common/self_keyword_or_identifier.rs diff --git a/ast/src/common/spread.rs b/grammar/src/common/spread.rs similarity index 100% rename from ast/src/common/spread.rs rename to grammar/src/common/spread.rs diff --git a/typed/src/common/declare.rs b/grammar/src/common/spread_or_expression.rs similarity index 59% rename from typed/src/common/declare.rs rename to grammar/src/common/spread_or_expression.rs index 4fb9d28d85..3dfcedb7d3 100644 --- a/typed/src/common/declare.rs +++ b/grammar/src/common/spread_or_expression.rs @@ -14,31 +14,24 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_ast::common::Declare as AstDeclare; +use crate::{ast::Rule, common::Spread, expressions::Expression}; -use serde::{Deserialize, Serialize}; +use pest_ast::FromPest; +use serde::Serialize; use std::fmt; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum Declare { - Const, - Let, +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::spread_or_expression))] +pub enum SpreadOrExpression<'ast> { + Spread(Spread<'ast>), + Expression(Expression<'ast>), } -impl<'ast> From for Declare { - fn from(declare: AstDeclare) -> Self { - match declare { - AstDeclare::Const(_) => Declare::Const, - AstDeclare::Let(_) => Declare::Let, - } - } -} - -impl fmt::Display for Declare { +impl<'ast> fmt::Display for SpreadOrExpression<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Declare::Const => write!(f, "const"), - Declare::Let => write!(f, "let"), + match *self { + SpreadOrExpression::Spread(ref spread) => write!(f, "{}", spread), + SpreadOrExpression::Expression(ref expression) => write!(f, "{}", expression), } } } diff --git a/ast/src/common/static_.rs b/grammar/src/common/static_.rs similarity index 100% rename from ast/src/common/static_.rs rename to grammar/src/common/static_.rs diff --git a/typed/src/common/variable_name.rs b/grammar/src/common/variable_name.rs similarity index 58% rename from typed/src/common/variable_name.rs rename to grammar/src/common/variable_name.rs index ac93f2dc60..76197bb0ed 100644 --- a/typed/src/common/variable_name.rs +++ b/grammar/src/common/variable_name.rs @@ -14,32 +14,30 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::common::{Identifier, Span}; -use leo_ast::common::VariableName as AstVariableName; +use crate::{ + ast::Rule, + common::{Identifier, Mutable}, + SpanDef, +}; -use serde::{Deserialize, Serialize}; +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; use std::fmt; -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct VariableName { - pub mutable: bool, - pub identifier: Identifier, - pub span: Span, +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::variable_name))] +pub struct VariableName<'ast> { + pub mutable: Option, + pub identifier: Identifier<'ast>, + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, } -impl<'ast> From> for VariableName { - fn from(name: AstVariableName<'ast>) -> Self { - Self { - mutable: name.mutable.is_some(), - identifier: Identifier::from(name.identifier), - span: Span::from(name.span), - } - } -} - -impl fmt::Display for VariableName { +impl<'ast> fmt::Display for VariableName<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.mutable { + if let Some(ref _mutable) = self.mutable { write!(f, "mut ")?; } diff --git a/typed/src/common/variables.rs b/grammar/src/common/variables.rs similarity index 65% rename from typed/src/common/variables.rs rename to grammar/src/common/variables.rs index f3c7efa68a..9d63803a93 100644 --- a/typed/src/common/variables.rs +++ b/grammar/src/common/variables.rs @@ -14,30 +14,24 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{Type, VariableName}; -use leo_ast::common::Variables as AstVariables; +use crate::{ast::Rule, common::VariableName, types::Type, SpanDef}; -use serde::{Deserialize, Serialize}; +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; use std::fmt; -/// A variable that is assigned to a value in the constrained program -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct Variables { - pub names: Vec, - pub type_: Option, +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::variables))] +pub struct Variables<'ast> { + pub names: Vec>, + pub type_: Option>, + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, } -impl<'ast> From> for Variables { - fn from(variables: AstVariables<'ast>) -> Self { - let names = variables.names.into_iter().map(VariableName::from).collect::>(); - - let type_ = variables.type_.map(Type::from); - - Self { names, type_ } - } -} - -impl fmt::Display for Variables { +impl<'ast> fmt::Display for Variables<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.names.len() == 1 { // mut a diff --git a/ast/src/console/console_assert.rs b/grammar/src/console/console_assert.rs similarity index 100% rename from ast/src/console/console_assert.rs rename to grammar/src/console/console_assert.rs diff --git a/ast/src/console/console_debug.rs b/grammar/src/console/console_debug.rs similarity index 100% rename from ast/src/console/console_debug.rs rename to grammar/src/console/console_debug.rs diff --git a/ast/src/console/console_error.rs b/grammar/src/console/console_error.rs similarity index 100% rename from ast/src/console/console_error.rs rename to grammar/src/console/console_error.rs diff --git a/grammar/src/console/console_function.rs b/grammar/src/console/console_function.rs new file mode 100644 index 0000000000..0b48af1a43 --- /dev/null +++ b/grammar/src/console/console_function.rs @@ -0,0 +1,44 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ + ast::Rule, + console::{ConsoleAssert, ConsoleDebug, ConsoleError, ConsoleLog}, +}; + +use pest_ast::FromPest; +use serde::Serialize; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::console_function))] +pub enum ConsoleFunction<'ast> { + Assert(ConsoleAssert<'ast>), + Debug(ConsoleDebug<'ast>), + Error(ConsoleError<'ast>), + Log(ConsoleLog<'ast>), +} + +impl<'ast> fmt::Display for ConsoleFunction<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + ConsoleFunction::Assert(assert) => write!(f, "{}", assert), + ConsoleFunction::Debug(debug) => write!(f, "{}", debug), + ConsoleFunction::Error(error) => write!(f, "{}", error), + ConsoleFunction::Log(log) => write!(f, "{}", log), + } + } +} diff --git a/typed/src/console/console_function_call.rs b/grammar/src/console/console_function_call.rs similarity index 58% rename from typed/src/console/console_function_call.rs rename to grammar/src/console/console_function_call.rs index b2a9ef09f1..2c14af2d76 100644 --- a/typed/src/console/console_function_call.rs +++ b/grammar/src/console/console_function_call.rs @@ -14,28 +14,30 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ConsoleFunction, Span}; -use leo_ast::console::ConsoleFunctionCall as AstConsoleFunctionCall; +use crate::{ + ast::Rule, + common::LineEnd, + console::{ConsoleFunction, ConsoleKeyword}, + SpanDef, +}; -use serde::{Deserialize, Serialize}; +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; use std::fmt; -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct ConsoleFunctionCall { - pub function: ConsoleFunction, - pub span: Span, +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::console_function_call))] +pub struct ConsoleFunctionCall<'ast> { + pub keyword: ConsoleKeyword<'ast>, + pub function: ConsoleFunction<'ast>, + pub line_end: LineEnd, + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, } -impl<'ast> From> for ConsoleFunctionCall { - fn from(console: AstConsoleFunctionCall<'ast>) -> Self { - ConsoleFunctionCall { - function: ConsoleFunction::from(console.function), - span: Span::from(console.span), - } - } -} - -impl fmt::Display for ConsoleFunctionCall { +impl<'ast> fmt::Display for ConsoleFunctionCall<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "console.{};", self.function) } diff --git a/ast/src/console/console_keyword.rs b/grammar/src/console/console_keyword.rs similarity index 100% rename from ast/src/console/console_keyword.rs rename to grammar/src/console/console_keyword.rs diff --git a/ast/src/console/console_log.rs b/grammar/src/console/console_log.rs similarity index 100% rename from ast/src/console/console_log.rs rename to grammar/src/console/console_log.rs diff --git a/typed/src/console/formatted_container.rs b/grammar/src/console/formatted_container.rs similarity index 63% rename from typed/src/console/formatted_container.rs rename to grammar/src/console/formatted_container.rs index 5e2ce9e0b9..e6234dc723 100644 --- a/typed/src/console/formatted_container.rs +++ b/grammar/src/console/formatted_container.rs @@ -14,26 +14,22 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::Span; -use leo_ast::console::FormattedContainer as AstFormattedContainer; +use crate::{ast::Rule, SpanDef}; -use serde::{Deserialize, Serialize}; +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; use std::fmt; -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct FormattedContainer { - pub span: Span, +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::formatted_container))] +pub struct FormattedContainer<'ast> { + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, } -impl<'ast> From> for FormattedContainer { - fn from(container: AstFormattedContainer<'ast>) -> Self { - Self { - span: Span::from(container.span), - } - } -} - -impl fmt::Display for FormattedContainer { +impl<'ast> fmt::Display for FormattedContainer<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{{}}") } diff --git a/typed/src/console/formatted_parameter.rs b/grammar/src/console/formatted_parameter.rs similarity index 59% rename from typed/src/console/formatted_parameter.rs rename to grammar/src/console/formatted_parameter.rs index 79249e5fbc..c8b8c3cbe4 100644 --- a/typed/src/console/formatted_parameter.rs +++ b/grammar/src/console/formatted_parameter.rs @@ -14,28 +14,23 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{Expression, Span}; -use leo_ast::console::FormattedParameter as AstFormattedParameter; +use crate::{ast::Rule, expressions::Expression, SpanDef}; -use serde::{Deserialize, Serialize}; +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; use std::fmt; -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct FormattedParameter { - pub expression: Expression, - pub span: Span, +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::formatted_parameter))] +pub struct FormattedParameter<'ast> { + pub expression: Expression<'ast>, + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, } -impl<'ast> From> for FormattedParameter { - fn from(parameter: AstFormattedParameter<'ast>) -> Self { - Self { - expression: Expression::from(parameter.expression), - span: Span::from(parameter.span), - } - } -} - -impl fmt::Display for FormattedParameter { +impl<'ast> fmt::Display for FormattedParameter<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.expression) } diff --git a/grammar/src/console/formatted_string.rs b/grammar/src/console/formatted_string.rs new file mode 100644 index 0000000000..d40d399f6b --- /dev/null +++ b/grammar/src/console/formatted_string.rs @@ -0,0 +1,44 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ + ast::{span_into_string, Rule}, + console::{FormattedContainer, FormattedParameter}, + SpanDef, +}; + +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::formatted_string))] +pub struct FormattedString<'ast> { + #[pest_ast(outer(with(span_into_string)))] + pub string: String, + pub containers: Vec>, + pub parameters: Vec>, + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for FormattedString<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.string) + } +} diff --git a/typed/src/console/mod.rs b/grammar/src/console/mod.rs similarity index 80% rename from typed/src/console/mod.rs rename to grammar/src/console/mod.rs index 071f43d819..bf4eb3b03e 100644 --- a/typed/src/console/mod.rs +++ b/grammar/src/console/mod.rs @@ -14,12 +14,27 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . +pub mod console_assert; +pub use console_assert::*; + +pub mod console_debug; +pub use console_debug::*; + +pub mod console_error; +pub use console_error::*; + pub mod console_function; pub use console_function::*; pub mod console_function_call; pub use console_function_call::*; +pub mod console_keyword; +pub use console_keyword::*; + +pub mod console_log; +pub use console_log::*; + pub mod formatted_container; pub use formatted_container::*; diff --git a/ast/src/definitions/annotated_definition.rs b/grammar/src/definitions/annotated_definition.rs similarity index 100% rename from ast/src/definitions/annotated_definition.rs rename to grammar/src/definitions/annotated_definition.rs diff --git a/ast/src/definitions/definition.rs b/grammar/src/definitions/definition.rs similarity index 100% rename from ast/src/definitions/definition.rs rename to grammar/src/definitions/definition.rs diff --git a/ast/src/definitions/mod.rs b/grammar/src/definitions/mod.rs similarity index 100% rename from ast/src/definitions/mod.rs rename to grammar/src/definitions/mod.rs diff --git a/typed/src/types/mod.rs b/grammar/src/errors/mod.rs similarity index 90% rename from typed/src/types/mod.rs rename to grammar/src/errors/mod.rs index 9d9ca5aa82..c60030f31f 100644 --- a/typed/src/types/mod.rs +++ b/grammar/src/errors/mod.rs @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -pub mod integer_type; -pub use integer_type::*; +pub mod parser; +pub use parser::*; -pub mod type_; -pub use type_::*; +pub mod syntax; +pub use syntax::*; diff --git a/ast/src/errors/parser.rs b/grammar/src/errors/parser.rs similarity index 100% rename from ast/src/errors/parser.rs rename to grammar/src/errors/parser.rs diff --git a/ast/src/errors/syntax.rs b/grammar/src/errors/syntax.rs similarity index 100% rename from ast/src/errors/syntax.rs rename to grammar/src/errors/syntax.rs diff --git a/ast/src/expressions/array_initializer_expression.rs b/grammar/src/expressions/array_initializer_expression.rs similarity index 100% rename from ast/src/expressions/array_initializer_expression.rs rename to grammar/src/expressions/array_initializer_expression.rs diff --git a/ast/src/expressions/array_inline_expression.rs b/grammar/src/expressions/array_inline_expression.rs similarity index 100% rename from ast/src/expressions/array_inline_expression.rs rename to grammar/src/expressions/array_inline_expression.rs diff --git a/ast/src/expressions/binary_expression.rs b/grammar/src/expressions/binary_expression.rs similarity index 100% rename from ast/src/expressions/binary_expression.rs rename to grammar/src/expressions/binary_expression.rs diff --git a/ast/src/expressions/circuit_inline_expression.rs b/grammar/src/expressions/circuit_inline_expression.rs similarity index 100% rename from ast/src/expressions/circuit_inline_expression.rs rename to grammar/src/expressions/circuit_inline_expression.rs diff --git a/ast/src/expressions/expression.rs b/grammar/src/expressions/expression.rs similarity index 100% rename from ast/src/expressions/expression.rs rename to grammar/src/expressions/expression.rs diff --git a/ast/src/expressions/mod.rs b/grammar/src/expressions/mod.rs similarity index 100% rename from ast/src/expressions/mod.rs rename to grammar/src/expressions/mod.rs diff --git a/ast/src/expressions/postfix_expression.rs b/grammar/src/expressions/postfix_expression.rs similarity index 100% rename from ast/src/expressions/postfix_expression.rs rename to grammar/src/expressions/postfix_expression.rs diff --git a/ast/src/expressions/ternary_expression.rs b/grammar/src/expressions/ternary_expression.rs similarity index 100% rename from ast/src/expressions/ternary_expression.rs rename to grammar/src/expressions/ternary_expression.rs diff --git a/ast/src/expressions/tuple_expression.rs b/grammar/src/expressions/tuple_expression.rs similarity index 100% rename from ast/src/expressions/tuple_expression.rs rename to grammar/src/expressions/tuple_expression.rs diff --git a/ast/src/expressions/unary_expression.rs b/grammar/src/expressions/unary_expression.rs similarity index 100% rename from ast/src/expressions/unary_expression.rs rename to grammar/src/expressions/unary_expression.rs diff --git a/ast/src/files/file.rs b/grammar/src/files/file.rs similarity index 100% rename from ast/src/files/file.rs rename to grammar/src/files/file.rs diff --git a/ast/src/files/mod.rs b/grammar/src/files/mod.rs similarity index 100% rename from ast/src/files/mod.rs rename to grammar/src/files/mod.rs diff --git a/grammar/src/functions/function.rs b/grammar/src/functions/function.rs new file mode 100644 index 0000000000..4129422ed0 --- /dev/null +++ b/grammar/src/functions/function.rs @@ -0,0 +1,33 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ast::Rule, common::Identifier, functions::input::Input, statements::Statement, types::Type, SpanDef}; + +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::function))] +pub struct Function<'ast> { + pub identifier: Identifier<'ast>, + pub parameters: Vec>, + pub returns: Option>, + pub statements: Vec>, + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, +} diff --git a/grammar/src/functions/input/function_input.rs b/grammar/src/functions/input/function_input.rs new file mode 100644 index 0000000000..583cff1547 --- /dev/null +++ b/grammar/src/functions/input/function_input.rs @@ -0,0 +1,37 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ + ast::Rule, + common::{Identifier, Mutable}, + types::Type, + SpanDef, +}; + +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::function_input))] +pub struct FunctionInput<'ast> { + pub mutable: Option, + pub identifier: Identifier<'ast>, + pub type_: Type<'ast>, + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, +} diff --git a/ast/src/functions/input/input.rs b/grammar/src/functions/input/input.rs similarity index 100% rename from ast/src/functions/input/input.rs rename to grammar/src/functions/input/input.rs diff --git a/ast/src/functions/input/input_keyword.rs b/grammar/src/functions/input/input_keyword.rs similarity index 100% rename from ast/src/functions/input/input_keyword.rs rename to grammar/src/functions/input/input_keyword.rs diff --git a/typed/src/functions/input/mod.rs b/grammar/src/functions/input/mod.rs similarity index 86% rename from typed/src/functions/input/mod.rs rename to grammar/src/functions/input/mod.rs index d673bea746..90c793d89d 100644 --- a/typed/src/functions/input/mod.rs +++ b/grammar/src/functions/input/mod.rs @@ -14,8 +14,13 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . +#![allow(clippy::module_inception)] + pub mod function_input; pub use function_input::*; -pub mod input_variable; -pub use input_variable::*; +pub mod input; +pub use input::*; + +pub mod input_keyword; +pub use input_keyword::*; diff --git a/typed/src/functions/mod.rs b/grammar/src/functions/mod.rs similarity index 100% rename from typed/src/functions/mod.rs rename to grammar/src/functions/mod.rs diff --git a/grammar/src/functions/test_function.rs b/grammar/src/functions/test_function.rs new file mode 100644 index 0000000000..54222deafd --- /dev/null +++ b/grammar/src/functions/test_function.rs @@ -0,0 +1,30 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ast::Rule, functions::Function, SpanDef}; + +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::test_function))] +pub struct TestFunction<'ast> { + pub function: Function<'ast>, + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, +} diff --git a/grammar/src/imports/import.rs b/grammar/src/imports/import.rs new file mode 100644 index 0000000000..5a8ff43b8a --- /dev/null +++ b/grammar/src/imports/import.rs @@ -0,0 +1,31 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ast::Rule, common::LineEnd, imports::Package, SpanDef}; + +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::import))] +pub struct Import<'ast> { + pub package: Package<'ast>, + pub line_end: LineEnd, + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, +} diff --git a/grammar/src/imports/import_symbol.rs b/grammar/src/imports/import_symbol.rs new file mode 100644 index 0000000000..619a9212aa --- /dev/null +++ b/grammar/src/imports/import_symbol.rs @@ -0,0 +1,31 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ast::Rule, common::Identifier, SpanDef}; + +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::import_symbol))] +pub struct ImportSymbol<'ast> { + pub value: Identifier<'ast>, + pub alias: Option>, + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, +} diff --git a/typed/src/imports/mod.rs b/grammar/src/imports/mod.rs similarity index 91% rename from typed/src/imports/mod.rs rename to grammar/src/imports/mod.rs index faffbb0afe..4a1343664a 100644 --- a/typed/src/imports/mod.rs +++ b/grammar/src/imports/mod.rs @@ -25,3 +25,9 @@ pub use package::*; pub mod package_access; pub use package_access::*; + +pub mod package_name; +pub use package_name::*; + +pub mod star; +pub use star::*; diff --git a/grammar/src/imports/package.rs b/grammar/src/imports/package.rs new file mode 100644 index 0000000000..75a3935913 --- /dev/null +++ b/grammar/src/imports/package.rs @@ -0,0 +1,35 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ + ast::Rule, + imports::{PackageAccess, PackageName}, + SpanDef, +}; + +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::package))] +pub struct Package<'ast> { + pub name: PackageName<'ast>, + pub access: PackageAccess<'ast>, + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, +} diff --git a/grammar/src/imports/package_access.rs b/grammar/src/imports/package_access.rs new file mode 100644 index 0000000000..0e04906152 --- /dev/null +++ b/grammar/src/imports/package_access.rs @@ -0,0 +1,32 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ + ast::Rule, + imports::{ImportSymbol, Package, Star}, +}; + +use pest_ast::FromPest; +use serde::Serialize; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::package_access))] +pub enum PackageAccess<'ast> { + Star(Star<'ast>), + SubPackage(Box>), + Symbol(ImportSymbol<'ast>), + Multiple(Vec>), +} diff --git a/ast/src/imports/package_name.rs b/grammar/src/imports/package_name.rs similarity index 100% rename from ast/src/imports/package_name.rs rename to grammar/src/imports/package_name.rs diff --git a/ast/src/imports/star.rs b/grammar/src/imports/star.rs similarity index 100% rename from ast/src/imports/star.rs rename to grammar/src/imports/star.rs diff --git a/ast/src/leo.pest b/grammar/src/leo.pest similarity index 100% rename from ast/src/leo.pest rename to grammar/src/leo.pest diff --git a/grammar/src/lib.rs b/grammar/src/lib.rs new file mode 100644 index 0000000000..77224db03e --- /dev/null +++ b/grammar/src/lib.rs @@ -0,0 +1,101 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +//! The pest abstract syntax tree (ast) for a Leo program. +//! +//! This module contains the [`Grammar`] type, a wrapper around the [`File`] type in this module. +//! The [`Grammar`] type is the datatype generated by the pest parser using grammar from `leo.pest`. +//! The [`Grammar`] type is intended to be parsed into a [`LeoAst`]. It should not be parsed by +//! any other pass of the compiler. + +#[macro_use] +extern crate lazy_static; +#[macro_use] +extern crate pest_derive; +#[macro_use] +extern crate thiserror; + +pub mod ast; + +pub mod access; +pub mod annotations; +pub mod circuits; +pub mod common; +pub mod console; +pub mod definitions; +pub mod expressions; +pub mod files; +pub mod functions; +pub mod imports; +pub mod operations; +pub mod statements; +pub mod types; +pub mod values; + +pub mod errors; +pub use errors::*; + +pub(crate) mod span; +pub(crate) use span::*; + +use from_pest::FromPest; +use std::{fs, path::Path}; + +/// The pest abstract syntax tree (ast) for a Leo program. +/// +/// The [`Grammar`] type represents a Leo program as a series of recursive data types. +/// These data types form a tree that begins from a [`File`] type root. +/// +/// A new [`Grammar`] type can be created from a `*.leo` file at a [`Path`]. +/// A [`Grammar`] type can be used to create a new [`LeoAst`] type. +pub struct Grammar<'ast> { + ast: files::File<'ast>, +} + +impl<'ast> Grammar<'ast> { + /// Creates a new abstract syntax tree given the file path. + pub fn new(file_path: &'ast Path, program_string: &'ast str) -> Result { + // TODO (howardwu): Turn this check back on after fixing the testing module. + // assert_eq!(program_string, fs::read_to_string(file_path).map_err(|_| ParserError::FileReadError(file_path.clone()))?); + + // Parse the file using leo.pest + let file = &mut ast::parse(&program_string) + .map_err(|error| ParserError::from(error.with_path(file_path.to_str().unwrap())))?; + + // Builds the abstract syntax tree using pest derivation. + let ast = files::File::<'ast>::from_pest(file).map_err(|_| ParserError::SyntaxTreeError)?; + tracing::debug!("{:#?}", ast); + + Ok(Self { ast }) + } + + // TODO (howardwu): Remove this in favor of a dedicated file loader to verify checksums + // and maintain a global cache of program strings during the compilation process. + /// Loads the Leo code as a string from the given file path. + pub fn load_file(file_path: &'ast Path) -> Result { + Ok(fs::read_to_string(file_path).map_err(|_| ParserError::FileReadError(file_path.to_owned()))?) + } + + /// Returns a reference to the inner abstract syntax tree representation. + pub fn as_repr(&self) -> &files::File<'ast> { + &self.ast + } + + /// Serializes the abstract syntax tree into a JSON string. + pub fn to_json_string(&self) -> Result { + Ok(serde_json::to_string_pretty(&self.ast)?) + } +} diff --git a/typed/src/main.rs b/grammar/src/main.rs similarity index 68% rename from typed/src/main.rs rename to grammar/src/main.rs index 38b928785c..27f1f7f7a7 100644 --- a/typed/src/main.rs +++ b/grammar/src/main.rs @@ -14,25 +14,21 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_ast::{LeoAst, ParserError}; -use leo_typed::LeoTypedAst; +use leo_grammar::{Grammar, ParserError}; use std::{env, fs, path::Path}; -fn to_leo_typed_tree(filepath: &Path) -> Result { +fn to_grammar(filepath: &Path) -> Result { // Loads the Leo code as a string from the given file path. let program_filepath = filepath.to_path_buf(); - let program_string = LeoAst::load_file(&program_filepath)?; + let program_string = Grammar::load_file(&program_filepath)?; // Parses the Leo file and constructs an abstract syntax tree. - let ast = LeoAst::new(&program_filepath, &program_string)?; + let ast = Grammar::new(&program_filepath, &program_string)?; - // Parse the abstract syntax tree and constructs a typed syntax tree. - let typed_ast = LeoTypedAst::new("leo_typed_tree", &ast); + // Serializes the abstract syntax tree into JSON format. + let serialized_ast = Grammar::to_json_string(&ast)?; - // Serializes the typed syntax tree into JSON format. - let serialized_typed_tree = LeoTypedAst::to_json_string(&typed_ast)?; - - Ok(serialized_typed_tree) + Ok(serialized_ast) } fn main() -> Result<(), ParserError> { @@ -43,7 +39,7 @@ fn main() -> Result<(), ParserError> { if cli_arguments.len() < 2 || cli_arguments.len() > 3 { eprintln!("Warning - an invalid number of command-line arguments were provided."); println!( - "\nCommand-line usage:\n\n\tleo_typed_ast {{PATH/TO/INPUT_FILENAME}}.leo {{PATH/TO/OUTPUT_DIRECTORY (optional)}}\n" + "\nCommand-line usage:\n\n\tleo_grammar {{PATH/TO/INPUT_FILENAME}}.leo {{PATH/TO/OUTPUT_DIRECTORY (optional)}}\n" ); return Ok(()); // Exit innocently } @@ -51,9 +47,9 @@ fn main() -> Result<(), ParserError> { // Construct the input filepath. let input_filepath = Path::new(&cli_arguments[1]); - // Construct the serialized typed syntax tree. - let serialized_typed_tree = to_leo_typed_tree(&input_filepath)?; - println!("{}", serialized_typed_tree); + // Construct the serialized abstract syntax tree. + let serialized_ast = to_grammar(&input_filepath)?; + println!("{}", serialized_ast); // Determine the output directory. let output_directory = match cli_arguments.len() == 3 { @@ -66,7 +62,7 @@ fn main() -> Result<(), ParserError> { }; // Write the serialized abstract syntax tree to the output directory. - fs::write(Path::new(&output_directory), serialized_typed_tree)?; + fs::write(Path::new(&output_directory), serialized_ast)?; Ok(()) } diff --git a/ast/src/operations/assign_operation.rs b/grammar/src/operations/assign_operation.rs similarity index 100% rename from ast/src/operations/assign_operation.rs rename to grammar/src/operations/assign_operation.rs diff --git a/ast/src/operations/binary_operation.rs b/grammar/src/operations/binary_operation.rs similarity index 100% rename from ast/src/operations/binary_operation.rs rename to grammar/src/operations/binary_operation.rs diff --git a/ast/src/operations/mod.rs b/grammar/src/operations/mod.rs similarity index 100% rename from ast/src/operations/mod.rs rename to grammar/src/operations/mod.rs diff --git a/ast/src/operations/unary_operation.rs b/grammar/src/operations/unary_operation.rs similarity index 100% rename from ast/src/operations/unary_operation.rs rename to grammar/src/operations/unary_operation.rs diff --git a/ast/src/span.rs b/grammar/src/span.rs similarity index 100% rename from ast/src/span.rs rename to grammar/src/span.rs diff --git a/ast/src/statements/assign_statement.rs b/grammar/src/statements/assign_statement.rs similarity index 100% rename from ast/src/statements/assign_statement.rs rename to grammar/src/statements/assign_statement.rs diff --git a/grammar/src/statements/conditional_nested_or_end_statement.rs b/grammar/src/statements/conditional_nested_or_end_statement.rs new file mode 100644 index 0000000000..120fc2ba7e --- /dev/null +++ b/grammar/src/statements/conditional_nested_or_end_statement.rs @@ -0,0 +1,40 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ + ast::Rule, + statements::{ConditionalStatement, Statement}, +}; + +use pest_ast::FromPest; +use serde::Serialize; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::conditional_nested_or_end_statement))] +pub enum ConditionalNestedOrEndStatement<'ast> { + Nested(Box>), + End(Vec>), +} + +impl<'ast> fmt::Display for ConditionalNestedOrEndStatement<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + ConditionalNestedOrEndStatement::Nested(ref nested) => write!(f, "else {}", nested), + ConditionalNestedOrEndStatement::End(ref statements) => write!(f, "else {{\n \t{:#?}\n }}", statements), + } + } +} diff --git a/grammar/src/statements/conditional_statement.rs b/grammar/src/statements/conditional_statement.rs new file mode 100644 index 0000000000..6cfd97d97e --- /dev/null +++ b/grammar/src/statements/conditional_statement.rs @@ -0,0 +1,49 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ + ast::Rule, + expressions::Expression, + statements::{ConditionalNestedOrEndStatement, Statement}, + SpanDef, +}; + +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::statement_conditional))] +pub struct ConditionalStatement<'ast> { + pub condition: Expression<'ast>, + pub statements: Vec>, + pub next: Option>, + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for ConditionalStatement<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + writeln!(f, "if ({}) {{", self.condition)?; + writeln!(f, "\t{:#?}", self.statements)?; + self.next + .as_ref() + .map(|n_or_e| write!(f, "}} {}", n_or_e)) + .unwrap_or_else(|| write!(f, "}}")) + } +} diff --git a/ast/src/statements/definition_statement.rs b/grammar/src/statements/definition_statement.rs similarity index 83% rename from ast/src/statements/definition_statement.rs rename to grammar/src/statements/definition_statement.rs index 4376e1c4f2..a8637cd0c1 100644 --- a/ast/src/statements/definition_statement.rs +++ b/grammar/src/statements/definition_statement.rs @@ -31,7 +31,7 @@ use std::fmt; pub struct DefinitionStatement<'ast> { pub declare: Declare, pub variables: Variables<'ast>, - pub expressions: Vec>, + pub expression: Expression<'ast>, pub line_end: LineEnd, #[pest_ast(outer())] #[serde(with = "SpanDef")] @@ -40,13 +40,6 @@ pub struct DefinitionStatement<'ast> { impl<'ast> fmt::Display for DefinitionStatement<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let expressions = self - .expressions - .iter() - .map(|x| x.to_string()) - .collect::>() - .join(","); - - write!(f, "let {} = {};", self.variables, expressions) + write!(f, "let {} = {};", self.variables, self.expression) } } diff --git a/ast/src/statements/expression_statement.rs b/grammar/src/statements/expression_statement.rs similarity index 100% rename from ast/src/statements/expression_statement.rs rename to grammar/src/statements/expression_statement.rs diff --git a/ast/src/statements/for_statement.rs b/grammar/src/statements/for_statement.rs similarity index 100% rename from ast/src/statements/for_statement.rs rename to grammar/src/statements/for_statement.rs diff --git a/typed/src/statements/mod.rs b/grammar/src/statements/mod.rs similarity index 76% rename from typed/src/statements/mod.rs rename to grammar/src/statements/mod.rs index 8fcd2b997e..95978fa8af 100644 --- a/typed/src/statements/mod.rs +++ b/grammar/src/statements/mod.rs @@ -14,11 +14,26 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -pub mod conditional_nested_or_end_statement; -pub use conditional_nested_or_end_statement::*; +pub mod assign_statement; +pub use assign_statement::*; pub mod conditional_statement; pub use conditional_statement::*; +pub mod conditional_nested_or_end_statement; +pub use conditional_nested_or_end_statement::*; + +pub mod definition_statement; +pub use definition_statement::*; + +pub mod expression_statement; +pub use expression_statement::*; + +pub mod for_statement; +pub use for_statement::*; + +pub mod return_statement; +pub use return_statement::*; + pub mod statement; pub use statement::*; diff --git a/ast/src/statements/return_statement.rs b/grammar/src/statements/return_statement.rs similarity index 100% rename from ast/src/statements/return_statement.rs rename to grammar/src/statements/return_statement.rs diff --git a/grammar/src/statements/statement.rs b/grammar/src/statements/statement.rs new file mode 100644 index 0000000000..602d7785fa --- /dev/null +++ b/grammar/src/statements/statement.rs @@ -0,0 +1,47 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ast::Rule, console::ConsoleFunctionCall, statements::*}; + +use pest_ast::FromPest; +use serde::Serialize; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::statement))] +pub enum Statement<'ast> { + Return(ReturnStatement<'ast>), + Definition(DefinitionStatement<'ast>), + Assign(AssignStatement<'ast>), + Conditional(ConditionalStatement<'ast>), + Iteration(ForStatement<'ast>), + Console(ConsoleFunctionCall<'ast>), + Expression(ExpressionStatement<'ast>), +} + +impl<'ast> fmt::Display for Statement<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Statement::Return(ref statement) => write!(f, "{}", statement), + Statement::Definition(ref statement) => write!(f, "{}", statement), + Statement::Assign(ref statement) => write!(f, "{}", statement), + Statement::Conditional(ref statement) => write!(f, "{}", statement), + Statement::Iteration(ref statement) => write!(f, "{}", statement), + Statement::Console(ref statement) => write!(f, "{}", statement), + Statement::Expression(ref statement) => write!(f, "{}", statement.expression), + } + } +} diff --git a/ast/src/types/address_type.rs b/grammar/src/types/address_type.rs similarity index 100% rename from ast/src/types/address_type.rs rename to grammar/src/types/address_type.rs diff --git a/ast/src/types/array_dimensions.rs b/grammar/src/types/array_dimensions.rs similarity index 100% rename from ast/src/types/array_dimensions.rs rename to grammar/src/types/array_dimensions.rs diff --git a/ast/src/types/array_type.rs b/grammar/src/types/array_type.rs similarity index 100% rename from ast/src/types/array_type.rs rename to grammar/src/types/array_type.rs diff --git a/ast/src/types/boolean_type.rs b/grammar/src/types/boolean_type.rs similarity index 100% rename from ast/src/types/boolean_type.rs rename to grammar/src/types/boolean_type.rs diff --git a/ast/src/types/circuit_type.rs b/grammar/src/types/circuit_type.rs similarity index 100% rename from ast/src/types/circuit_type.rs rename to grammar/src/types/circuit_type.rs diff --git a/ast/src/types/data_type.rs b/grammar/src/types/data_type.rs similarity index 100% rename from ast/src/types/data_type.rs rename to grammar/src/types/data_type.rs diff --git a/ast/src/types/field_type.rs b/grammar/src/types/field_type.rs similarity index 100% rename from ast/src/types/field_type.rs rename to grammar/src/types/field_type.rs diff --git a/ast/src/types/group_type.rs b/grammar/src/types/group_type.rs similarity index 100% rename from ast/src/types/group_type.rs rename to grammar/src/types/group_type.rs diff --git a/grammar/src/types/integer_type.rs b/grammar/src/types/integer_type.rs new file mode 100644 index 0000000000..e75785ea4e --- /dev/null +++ b/grammar/src/types/integer_type.rs @@ -0,0 +1,30 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ + ast::Rule, + types::{SignedIntegerType, UnsignedIntegerType}, +}; + +use pest_ast::FromPest; +use serde::Serialize; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::type_integer))] +pub enum IntegerType { + Signed(SignedIntegerType), + Unsigned(UnsignedIntegerType), +} diff --git a/grammar/src/types/mod.rs b/grammar/src/types/mod.rs new file mode 100644 index 0000000000..e00ea64af2 --- /dev/null +++ b/grammar/src/types/mod.rs @@ -0,0 +1,57 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +pub mod address_type; +pub use address_type::*; + +pub mod array_dimensions; +pub use array_dimensions::*; + +pub mod array_type; +pub use array_type::*; + +pub mod boolean_type; +pub use boolean_type::*; + +pub mod circuit_type; +pub use circuit_type::*; + +pub mod data_type; +pub use data_type::*; + +pub mod field_type; +pub use field_type::*; + +pub mod group_type; +pub use group_type::*; + +pub mod integer_type; +pub use integer_type::*; + +pub mod self_type; +pub use self_type::*; + +pub mod signed_integer_type; +pub use signed_integer_type::*; + +pub mod tuple_type; +pub use tuple_type::*; + +pub mod type_; +pub use type_::*; + +pub mod unsigned_integer_type; +pub use unsigned_integer_type::*; diff --git a/ast/src/types/self_type.rs b/grammar/src/types/self_type.rs similarity index 100% rename from ast/src/types/self_type.rs rename to grammar/src/types/self_type.rs diff --git a/ast/src/types/signed_integer_type.rs b/grammar/src/types/signed_integer_type.rs similarity index 100% rename from ast/src/types/signed_integer_type.rs rename to grammar/src/types/signed_integer_type.rs diff --git a/ast/src/types/tuple_type.rs b/grammar/src/types/tuple_type.rs similarity index 100% rename from ast/src/types/tuple_type.rs rename to grammar/src/types/tuple_type.rs diff --git a/grammar/src/types/type_.rs b/grammar/src/types/type_.rs new file mode 100644 index 0000000000..3664b232ab --- /dev/null +++ b/grammar/src/types/type_.rs @@ -0,0 +1,43 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{ast::Rule, types::*}; + +use pest_ast::FromPest; +use serde::Serialize; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::type_))] +pub enum Type<'ast> { + Basic(DataType), + Array(ArrayType<'ast>), + Tuple(TupleType<'ast>), + Circuit(CircuitType<'ast>), + SelfType(SelfType<'ast>), +} + +impl<'ast> fmt::Display for Type<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Type::Basic(ref _type) => write!(f, "basic"), + Type::Array(ref _type) => write!(f, "array"), + Type::Tuple(ref _type) => write!(f, "tuple"), + Type::Circuit(ref _type) => write!(f, "struct"), + Type::SelfType(ref type_) => write!(f, "{}", type_.keyword), + } + } +} diff --git a/ast/src/types/unsigned_integer_type.rs b/grammar/src/types/unsigned_integer_type.rs similarity index 100% rename from ast/src/types/unsigned_integer_type.rs rename to grammar/src/types/unsigned_integer_type.rs diff --git a/ast/src/values/address.rs b/grammar/src/values/address.rs similarity index 100% rename from ast/src/values/address.rs rename to grammar/src/values/address.rs diff --git a/ast/src/values/address_value.rs b/grammar/src/values/address_value.rs similarity index 100% rename from ast/src/values/address_value.rs rename to grammar/src/values/address_value.rs diff --git a/ast/src/values/boolean_value.rs b/grammar/src/values/boolean_value.rs similarity index 100% rename from ast/src/values/boolean_value.rs rename to grammar/src/values/boolean_value.rs diff --git a/ast/src/values/field_value.rs b/grammar/src/values/field_value.rs similarity index 100% rename from ast/src/values/field_value.rs rename to grammar/src/values/field_value.rs diff --git a/ast/src/values/group_coordinate.rs b/grammar/src/values/group_coordinate.rs similarity index 100% rename from ast/src/values/group_coordinate.rs rename to grammar/src/values/group_coordinate.rs diff --git a/ast/src/values/group_value.rs b/grammar/src/values/group_value.rs similarity index 100% rename from ast/src/values/group_value.rs rename to grammar/src/values/group_value.rs diff --git a/ast/src/values/integer_value.rs b/grammar/src/values/integer_value.rs similarity index 100% rename from ast/src/values/integer_value.rs rename to grammar/src/values/integer_value.rs diff --git a/ast/src/values/mod.rs b/grammar/src/values/mod.rs similarity index 100% rename from ast/src/values/mod.rs rename to grammar/src/values/mod.rs diff --git a/ast/src/values/negative_number.rs b/grammar/src/values/negative_number.rs similarity index 100% rename from ast/src/values/negative_number.rs rename to grammar/src/values/negative_number.rs diff --git a/ast/src/values/number_value.rs b/grammar/src/values/number_value.rs similarity index 100% rename from ast/src/values/number_value.rs rename to grammar/src/values/number_value.rs diff --git a/ast/src/values/positive_number.rs b/grammar/src/values/positive_number.rs similarity index 100% rename from ast/src/values/positive_number.rs rename to grammar/src/values/positive_number.rs diff --git a/ast/src/values/signed_integer_value.rs b/grammar/src/values/signed_integer_value.rs similarity index 100% rename from ast/src/values/signed_integer_value.rs rename to grammar/src/values/signed_integer_value.rs diff --git a/ast/src/values/unsigned_integer_value.rs b/grammar/src/values/unsigned_integer_value.rs similarity index 100% rename from ast/src/values/unsigned_integer_value.rs rename to grammar/src/values/unsigned_integer_value.rs diff --git a/ast/src/values/value.rs b/grammar/src/values/value.rs similarity index 100% rename from ast/src/values/value.rs rename to grammar/src/values/value.rs diff --git a/ast/tests/expression.rs b/grammar/tests/expression.rs similarity index 97% rename from ast/tests/expression.rs rename to grammar/tests/expression.rs index 99081e0004..f05aa7fb27 100644 --- a/ast/tests/expression.rs +++ b/grammar/tests/expression.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_ast::ast::{LanguageParser, Rule}; +use leo_grammar::ast::{LanguageParser, Rule}; use pest::*; diff --git a/ast/tests/function.rs b/grammar/tests/function.rs similarity index 98% rename from ast/tests/function.rs rename to grammar/tests/function.rs index 942976fb10..f2b4fa3629 100644 --- a/ast/tests/function.rs +++ b/grammar/tests/function.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_ast::ast::{LanguageParser, Rule}; +use leo_grammar::ast::{LanguageParser, Rule}; use pest::*; diff --git a/typed/tests/mod.rs b/grammar/tests/mod.rs similarity index 94% rename from typed/tests/mod.rs rename to grammar/tests/mod.rs index 6698b5585a..b4ed4e6d07 100644 --- a/typed/tests/mod.rs +++ b/grammar/tests/mod.rs @@ -14,4 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . +mod expression; +mod function; mod serialization; +mod tuple; diff --git a/ast/tests/serialization/expected_ast.json b/grammar/tests/serialization/expected_ast.json similarity index 100% rename from ast/tests/serialization/expected_ast.json rename to grammar/tests/serialization/expected_ast.json diff --git a/grammar/tests/serialization/json.rs b/grammar/tests/serialization/json.rs new file mode 100644 index 0000000000..13a62c1b71 --- /dev/null +++ b/grammar/tests/serialization/json.rs @@ -0,0 +1,38 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +#[test] +#[cfg(not(feature = "ci_skip"))] +fn test_serialize() { + use leo_grammar::Grammar; + use std::path::PathBuf; + + let mut program_filepath = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + program_filepath.push("tests/serialization/main.leo"); + + let expected = include_str!("./expected_ast.json"); + + // Loads the Leo code as a string from the given file path. + let program_string = Grammar::load_file(&program_filepath).unwrap(); + + // Parses the Leo file and constructs an abstract syntax tree. + let ast = Grammar::new(&program_filepath, &program_string).unwrap(); + + // Serializes the abstract syntax tree into JSON format. + let serialized_ast = Grammar::to_json_string(&ast).unwrap(); + + assert_eq!(expected, serialized_ast); +} diff --git a/typed/tests/serialization/main.leo b/grammar/tests/serialization/main.leo similarity index 100% rename from typed/tests/serialization/main.leo rename to grammar/tests/serialization/main.leo diff --git a/typed/tests/serialization/mod.rs b/grammar/tests/serialization/mod.rs similarity index 100% rename from typed/tests/serialization/mod.rs rename to grammar/tests/serialization/mod.rs diff --git a/ast/tests/tuple.rs b/grammar/tests/tuple.rs similarity index 98% rename from ast/tests/tuple.rs rename to grammar/tests/tuple.rs index 3b2825981c..201ac1b1da 100644 --- a/ast/tests/tuple.rs +++ b/grammar/tests/tuple.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use leo_ast::ast::{LanguageParser, Rule}; +use leo_grammar::ast::{LanguageParser, Rule}; use pest::*; diff --git a/imports/Cargo.toml b/imports/Cargo.toml new file mode 100644 index 0000000000..691215fec6 --- /dev/null +++ b/imports/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "leo-imports" +version = "1.0.4" +authors = [ "The Aleo Team "] +description = "Import parser for Leo program package dependencies" +homepage = "https://aleo.org" +repository = "https://github.com/AleoHQ/leo" +keywords = [ + "aleo", + "cryptography", + "leo", + "programming-language", + "zero-knowledge" +] +categories = [ "cryptography::cryptocurrencies", "web-programming" ] +include = ["Cargo.toml", "src", "README.md", "LICENSE.md" ] +license = "GPL-3.0" +edition = "2018" + +[dependencies.leo-ast] +path = "../ast" +version = "1.0.4" + +[dependencies.leo-grammar] +path = "../grammar" +version = "1.0.4" + +[dependencies.thiserror] +version = "1.0" + +[dependencies.tracing] +version = "0.1" \ No newline at end of file diff --git a/imports/src/errors/import_parser.rs b/imports/src/errors/import_parser.rs new file mode 100644 index 0000000000..647a37a259 --- /dev/null +++ b/imports/src/errors/import_parser.rs @@ -0,0 +1,122 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . +use leo_ast::{Error as FormattedError, Identifier, Span}; +use leo_grammar::ParserError; + +use std::{io, path::Path}; + +#[derive(Debug, Error)] +pub enum ImportParserError { + #[error("{}", _0)] + Error(#[from] FormattedError), + + #[error("{}", _0)] + ParserError(#[from] ParserError), +} + +impl ImportParserError { + fn new_from_span(message: String, span: Span) -> Self { + ImportParserError::Error(FormattedError::new_from_span(message, span)) + } + + fn new_from_span_with_path(message: String, span: Span, path: &Path) -> Self { + ImportParserError::Error(FormattedError::new_from_span_with_path(message, span, path)) + } + + /// + /// An imported package has the same name as an imported core_package. + /// + pub fn conflicting_imports(identifier: Identifier) -> Self { + let message = format!("conflicting imports found for `{}`.", identifier.name); + + Self::new_from_span(message, identifier.span) + } + + /// + /// A core package name has been imported twice. + /// + pub fn duplicate_core_package(identifier: Identifier) -> Self { + let message = format!("Duplicate core_package import `{}`.", identifier.name); + + Self::new_from_span(message, identifier.span) + } + + /// + /// Failed to convert a file path into an os string. + /// + pub fn convert_os_string(span: Span) -> Self { + let message = "Failed to convert file string name, maybe an illegal character?".to_string(); + + Self::new_from_span(message, span) + } + + /// + /// Failed to find the directory of the current file. + /// + pub fn current_directory_error(error: io::Error) -> Self { + let span = Span { + text: "".to_string(), + line: 0, + start: 0, + end: 0, + }; + let message = format!("Compilation failed trying to find current directory - {:?}.", error); + + Self::new_from_span(message, span) + } + + /// + /// Failed to open or get the name of a directory. + /// + pub fn directory_error(error: io::Error, span: Span, path: &Path) -> Self { + let message = format!("Compilation failed due to directory error - {:?}.", error); + + Self::new_from_span_with_path(message, span, path) + } + + /// + /// Failed to import all symbols at a package path. + /// + pub fn star(path: &Path, span: Span) -> Self { + let message = format!("Cannot import `*` from path `{:?}`.", path); + + Self::new_from_span(message, span) + } + + /// + /// Failed to find a library file for the current package. + /// + pub fn expected_lib_file(entry: String, span: Span) -> Self { + let message = format!( + "Expected library file`{}` when looking for symbol `{}`.", + entry, span.text + ); + + Self::new_from_span(message, span) + } + + /// + /// Failed to import a package name. + /// + pub fn unknown_package(identifier: Identifier) -> Self { + let message = format!( + "Cannot find imported package `{}` in source files or import directory.", + identifier.name + ); + + Self::new_from_span(message, identifier.span) + } +} diff --git a/typed/src/errors/mod.rs b/imports/src/errors/mod.rs similarity index 93% rename from typed/src/errors/mod.rs rename to imports/src/errors/mod.rs index d76128b38a..8cd075bde1 100644 --- a/typed/src/errors/mod.rs +++ b/imports/src/errors/mod.rs @@ -14,5 +14,5 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -pub mod error; -pub use error::*; +pub mod import_parser; +pub use self::import_parser::*; diff --git a/imports/src/lib.rs b/imports/src/lib.rs new file mode 100644 index 0000000000..8807f72fca --- /dev/null +++ b/imports/src/lib.rs @@ -0,0 +1,24 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +#[macro_use] +extern crate thiserror; + +pub mod errors; +pub use self::errors::*; + +pub mod parser; +pub use self::parser::*; diff --git a/compiler/src/import/parser/core_package.rs b/imports/src/parser/core_package.rs similarity index 75% rename from compiler/src/import/parser/core_package.rs rename to imports/src/parser/core_package.rs index 2873eb4346..67c3df8d47 100644 --- a/compiler/src/import/parser/core_package.rs +++ b/imports/src/parser/core_package.rs @@ -14,15 +14,19 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{errors::ImportError, ImportParser}; -use leo_typed::Package; +use crate::{errors::ImportParserError, ImportParser}; +use leo_ast::Package; pub static CORE_PACKAGE_NAME: &str = "core"; impl ImportParser { - // import a core package into scope - pub fn parse_core_package(&mut self, package: &Package) -> Result<(), ImportError> { - self.insert_core_package(package); + /// + /// Import a core package and insert into the `ImportParser`. + /// + pub fn parse_core_package(&mut self, package: &Package) -> Result<(), ImportParserError> { + // Insert a core package into the `ImportParser`. + self.insert_core_package(package)?; + Ok(()) } } diff --git a/imports/src/parser/import_parser.rs b/imports/src/parser/import_parser.rs new file mode 100644 index 0000000000..2466448ec9 --- /dev/null +++ b/imports/src/parser/import_parser.rs @@ -0,0 +1,101 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::errors::ImportParserError; +use leo_ast::{Package, Program}; + +use std::{ + collections::{HashMap, HashSet}, + env::current_dir, +}; + +/// Stores imported packages. +/// +/// A program can import one or more packages. A package can be found locally in the source +/// directory, foreign in the imports directory, or part of the core package list. +#[derive(Clone, Default)] +pub struct ImportParser { + imports: HashMap, + core_packages: HashSet, +} + +impl ImportParser { + /// + /// Inserts a (file name -> program) pair into the `ImportParser`. + /// + /// It is okay if the imported program is already present since importing multiple symbols from + /// the same file is allowed. + /// + pub(crate) fn insert_import(&mut self, file_name: String, program: Program) { + // Insert the imported program. + let _program = self.imports.insert(file_name, program); + } + + /// + /// Inserts a core package into the `ImportParser`. + /// + /// If the vector did not have this file_name present, `Ok()` is returned. + /// + /// If the vector did have this file_name present, a duplicate import error is thrown. + /// + pub(crate) fn insert_core_package(&mut self, package: &Package) -> Result<(), ImportParserError> { + // Check for duplicate core package name. + if self.core_packages.contains(package) { + return Err(ImportParserError::duplicate_core_package(package.name.clone())); + } + + // Append the core package. + self.core_packages.insert(package.clone()); + + Ok(()) + } + + /// + /// Returns a reference to the program corresponding to the file name. + /// + pub fn get_import(&self, file_name: &str) -> Option<&Program> { + self.imports.get(file_name) + } + + /// + /// Returns a reference to the core package corresponding to the given package. + /// + pub fn get_core_package(&self, package: &Package) -> Option<&Package> { + self.core_packages.iter().find(|core_package| core_package.eq(&package)) + } + + /// + /// Returns a new `ImportParser` from a given `Program`. + /// + /// For every import statement in the program: + /// 1. Check if the imported package exists. + /// 2. Create the Leo syntax tree for the imported package. + /// 3. Insert the Leo syntax tree into the `ImportParser` + /// + pub fn parse(program: &Program) -> Result { + let mut imports = Self::default(); + + // Find all imports relative to current directory. + let path = current_dir().map_err(ImportParserError::current_directory_error)?; + + // Parse each import statement. + for import in &program.imports { + imports.parse_package(path.clone(), &import.package)?; + } + + Ok(imports) + } +} diff --git a/compiler/src/import/parser/mod.rs b/imports/src/parser/mod.rs similarity index 100% rename from compiler/src/import/parser/mod.rs rename to imports/src/parser/mod.rs diff --git a/compiler/src/import/parser/parse_package.rs b/imports/src/parser/parse_package.rs similarity index 63% rename from compiler/src/import/parser/parse_package.rs rename to imports/src/parser/parse_package.rs index bf2ed6cb7d..78118acd53 100644 --- a/compiler/src/import/parser/parse_package.rs +++ b/imports/src/parser/parse_package.rs @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{errors::ImportError, ImportParser, CORE_PACKAGE_NAME}; -use leo_typed::{Package, PackageAccess}; +use crate::{errors::ImportParserError, ImportParser, CORE_PACKAGE_NAME}; +use leo_ast::{Package, PackageAccess}; use std::{fs, fs::DirEntry, path::PathBuf}; @@ -24,18 +24,25 @@ static SOURCE_DIRECTORY_NAME: &str = "src/"; static IMPORTS_DIRECTORY_NAME: &str = "imports/"; impl ImportParser { - // bring one or more import symbols into scope for the current constrained program - // we will recursively traverse sub packages here until we find the desired symbol - pub fn parse_package_access(&mut self, entry: &DirEntry, access: &PackageAccess) -> Result<(), ImportError> { - tracing::debug!("import {:?}", entry.path()); + /// + /// Import one or more symbols from a package. + /// + /// Will recursively traverse sub packages until the desired symbol is found. + /// + pub fn parse_package_access( + &mut self, + package: &DirEntry, + access: &PackageAccess, + ) -> Result<(), ImportParserError> { + tracing::debug!("import {:?}", package.path()); match access { - PackageAccess::Star(span) => self.parse_import_star(entry, span), - PackageAccess::Symbol(symbol) => self.parse_import_symbol(entry, symbol), - PackageAccess::SubPackage(package) => self.parse_package(entry.path(), package), + PackageAccess::Star(span) => self.parse_import_star(package, span), + PackageAccess::Symbol(symbol) => self.parse_import_symbol(package, symbol), + PackageAccess::SubPackage(sub_package) => self.parse_package(package.path(), sub_package), PackageAccess::Multiple(accesses) => { for access in accesses { - self.parse_package_access(entry, access)?; + self.parse_package_access(package, access)?; } Ok(()) @@ -43,7 +50,12 @@ impl ImportParser { } } - pub fn parse_package(&mut self, mut path: PathBuf, package: &Package) -> Result<(), ImportError> { + /// + /// Create the Leo syntax tree for an imported package. + /// + /// Inserts the Leo syntax tree into the `ImportParser`. + /// + pub fn parse_package(&mut self, mut path: PathBuf, package: &Package) -> Result<(), ImportParserError> { let error_path = path.clone(); let package_name = package.name.clone(); @@ -68,11 +80,13 @@ impl ImportParser { path = source_directory } + // Get a vector of all packages in the source directory. let entries = fs::read_dir(path) - .map_err(|error| ImportError::directory_error(error, package_name.span.clone(), &error_path))? + .map_err(|error| ImportParserError::directory_error(error, package_name.span.clone(), &error_path))? .collect::, std::io::Error>>() - .map_err(|error| ImportError::directory_error(error, package_name.span.clone(), &error_path))?; + .map_err(|error| ImportParserError::directory_error(error, package_name.span.clone(), &error_path))?; + // Check if the imported package name is in the source directory. let matched_source_entry = entries.into_iter().find(|entry| { entry .file_name() @@ -83,29 +97,32 @@ impl ImportParser { }); if core_package { - // Enforce core library package access + // Enforce core package access. self.parse_core_package(&package) } else if imports_directory.exists() { + // Get a vector of all packages in the imports directory. let entries = fs::read_dir(imports_directory) - .map_err(|error| ImportError::directory_error(error, package_name.span.clone(), &error_path))? + .map_err(|error| ImportParserError::directory_error(error, package_name.span.clone(), &error_path))? .collect::, std::io::Error>>() - .map_err(|error| ImportError::directory_error(error, package_name.span.clone(), &error_path))?; + .map_err(|error| ImportParserError::directory_error(error, package_name.span.clone(), &error_path))?; + // Check if the imported package name is in the imports directory. let matched_import_entry = entries .into_iter() .find(|entry| entry.file_name().into_string().unwrap().eq(&package_name.name)); + // Check if the package name was found in both the source and imports directory. match (matched_source_entry, matched_import_entry) { - (Some(_), Some(_)) => Err(ImportError::conflicting_imports(package_name)), + (Some(_), Some(_)) => Err(ImportParserError::conflicting_imports(package_name)), (Some(source_entry), None) => self.parse_package_access(&source_entry, &package.access), (None, Some(import_entry)) => self.parse_package_access(&import_entry, &package.access), - (None, None) => Err(ImportError::unknown_package(package_name)), + (None, None) => Err(ImportParserError::unknown_package(package_name)), } } else { // Enforce local package access with no found imports directory match matched_source_entry { Some(source_entry) => self.parse_package_access(&source_entry, &package.access), - None => Err(ImportError::unknown_package(package_name)), + None => Err(ImportParserError::unknown_package(package_name)), } } } diff --git a/imports/src/parser/parse_symbol.rs b/imports/src/parser/parse_symbol.rs new file mode 100644 index 0000000000..3061a7ff8a --- /dev/null +++ b/imports/src/parser/parse_symbol.rs @@ -0,0 +1,126 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::{errors::ImportParserError, ImportParser}; +use leo_ast::{ImportSymbol, Program, Span}; +use leo_grammar::Grammar; + +use std::{ffi::OsString, fs::DirEntry, path::PathBuf}; + +static LIBRARY_FILE: &str = "src/lib.leo"; +static FILE_EXTENSION: &str = "leo"; + +/// +/// Returns a Leo syntax tree from a given package. +/// +/// Builds an abstract syntax tree from the given file and then builds the Leo syntax tree. +/// +fn parse_import_file(package: &DirEntry, span: &Span) -> Result { + // Get the package file type. + let file_type = package + .file_type() + .map_err(|error| ImportParserError::directory_error(error, span.clone(), &package.path()))?; + let file_name = package + .file_name() + .into_string() + .map_err(|_| ImportParserError::convert_os_string(span.clone()))?; + + let mut file_path = package.path(); + if file_type.is_dir() { + file_path.push(LIBRARY_FILE); + + if !file_path.exists() { + return Err(ImportParserError::expected_lib_file( + format!("{:?}", file_path.as_path()), + span.clone(), + )); + } + } + + // Build the package abstract syntax tree. + let program_string = &Grammar::load_file(&file_path)?; + let ast = &Grammar::new(&file_path, &program_string)?; + + // Build the package Leo syntax tree from the package abstract syntax tree. + Ok(Program::from(&file_name, ast.as_repr())) +} + +impl ImportParser { + /// + /// Import all symbols from a given package. + /// + /// If the package is a Leo file, import all symbols from the file. + /// If the package is a directory, import all symbol from the library file. + /// + pub fn parse_import_star(&mut self, package: &DirEntry, span: &Span) -> Result<(), ImportParserError> { + let path = package.path(); + let is_dir = path.is_dir(); + + // Check if the package is a Leo file. + let is_leo_file = path + .extension() + .map_or(false, |ext| ext.eq(&OsString::from(FILE_EXTENSION))); + + let mut package_path = path; + package_path.push(LIBRARY_FILE); + + // Check if the package is a directory. + let is_package = is_dir && package_path.exists(); + + // import * can only be invoked on a package with a library file or a leo file + if is_package || is_leo_file { + self.parse_import_package(package, span) + } else { + // importing * from a directory or non-leo file in `package/src/` is illegal + Err(ImportParserError::star(&package.path(), span.clone())) + } + } + + /// + /// Import a symbol from a given package. + /// + pub fn parse_import_symbol(&mut self, package: &DirEntry, symbol: &ImportSymbol) -> Result<(), ImportParserError> { + // Get the package Leo syntax tree. + self.parse_import_package(package, &symbol.span) + } + + /// + /// Import a symbol from a given package. + /// + pub fn parse_import_package(&mut self, package: &DirEntry, span: &Span) -> Result<(), ImportParserError> { + // Get the package Leo syntax tree. + let program = parse_import_file(package, span)?; + + // Insert the package's imports into the import parser. + for import in &program.imports { + self.parse_package(package.path(), &import.package)?; + } + + // Get the package file name from the path. + let file_name_path = PathBuf::from(package.file_name()); + let file_name = file_name_path + .file_stem() + .unwrap() + .to_os_string() + .into_string() + .unwrap(); // the file exists so these will not fail + + // Attempt to insert the Leo syntax tree for the imported package. + self.insert_import(file_name, program); + + Ok(()) + } +} diff --git a/input/src/errors/parser.rs b/input/src/errors/parser.rs index 24bfaa5e52..a3f3684a04 100644 --- a/input/src/errors/parser.rs +++ b/input/src/errors/parser.rs @@ -77,6 +77,12 @@ impl InputParserError { InputParserError::SyntaxError(InputSyntaxError::from(error)) } + pub fn array_index(actual: String, span: Span) -> Self { + let message = format!("Expected constant number for array index, found `{}`", actual); + + Self::new_from_span(message, span) + } + pub fn implicit_type(data_type: DataType, implicit: NumberValue) -> Self { let message = format!("expected `{}`, found `{}`", data_type, implicit); diff --git a/leo/cli.rs b/leo/cli.rs index 80dd05eecd..caff530283 100644 --- a/leo/cli.rs +++ b/leo/cli.rs @@ -29,6 +29,7 @@ pub trait CLI { const OPTIONS: &'static [OptionType]; const SUBCOMMANDS: &'static [SubCommandType]; + #[allow(clippy::new_ret_no_self)] #[cfg_attr(tarpaulin, skip)] fn new<'a, 'b>() -> App<'a, 'b> { let arguments = &Self::ARGUMENTS diff --git a/state/Cargo.toml b/state/Cargo.toml index e56db37670..6f8b9063b7 100644 --- a/state/Cargo.toml +++ b/state/Cargo.toml @@ -21,8 +21,8 @@ edition = "2018" path = "../input" version = "1.0.4" -[dependencies.leo-typed] -path = "../typed" +[dependencies.leo-ast] +path = "../ast" version = "1.0.4" [dependencies.snarkos-algorithms] diff --git a/state/src/local_data_commitment/local_data_commitment.rs b/state/src/local_data_commitment/local_data_commitment.rs index 6a8f2906b3..2f795353f3 100644 --- a/state/src/local_data_commitment/local_data_commitment.rs +++ b/state/src/local_data_commitment/local_data_commitment.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{verify_record_commitment, LocalDataVerificationError, StateLeafValues, StateValues}; -use leo_typed::Input as TypedInput; +use leo_ast::Input as InputAst; use snarkos_algorithms::commitment_tree::CommitmentMerklePath; use snarkos_dpc::base_dpc::{ @@ -32,22 +32,22 @@ use std::convert::TryFrom; pub fn verify_local_data_commitment( system_parameters: &SystemParameters, - typed_input: &TypedInput, + input_ast: &InputAst, ) -> Result { // verify record commitment - let typed_record = typed_input.get_record(); + let typed_record = input_ast.get_record(); let dpc_record_values = verify_record_commitment(system_parameters, typed_record)?; let record_commitment: Vec = dpc_record_values.commitment; let record_serial_number: Vec = dpc_record_values.serial_number; // parse typed state values - let typed_state = typed_input.get_state(); + let typed_state = input_ast.get_state(); let state_values = StateValues::try_from(typed_state)?; let leaf_index: u32 = state_values.leaf_index; let root: Vec = state_values.root; // parse typed state leaf values - let typed_state_leaf = typed_input.get_state_leaf(); + let typed_state_leaf = input_ast.get_state_leaf(); let state_leaf_values = StateLeafValues::try_from(typed_state_leaf)?; let path: Vec = state_leaf_values.path; let memo: Vec = state_leaf_values.memo; diff --git a/state/src/local_data_commitment/state_leaf_values.rs b/state/src/local_data_commitment/state_leaf_values.rs index f7ca617ba4..3265c68310 100644 --- a/state/src/local_data_commitment/state_leaf_values.rs +++ b/state/src/local_data_commitment/state_leaf_values.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{find_input, input_to_integer_string, input_to_u8_vec, StateLeafValuesError}; -use leo_typed::StateLeaf as TypedStateLeaf; +use leo_ast::StateLeaf as StateLeafAst; use std::convert::TryFrom; @@ -31,10 +31,10 @@ pub struct StateLeafValues { pub leaf_randomness: Vec, } -impl TryFrom<&TypedStateLeaf> for StateLeafValues { +impl TryFrom<&StateLeafAst> for StateLeafValues { type Error = StateLeafValuesError; - fn try_from(state_leaf: &TypedStateLeaf) -> Result { + fn try_from(state_leaf: &StateLeafAst) -> Result { let parameters = state_leaf.values(); // Lookup path diff --git a/state/src/local_data_commitment/state_values.rs b/state/src/local_data_commitment/state_values.rs index 7fbba3dd6e..6b67ba7ea7 100644 --- a/state/src/local_data_commitment/state_values.rs +++ b/state/src/local_data_commitment/state_values.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{find_input, input_to_integer_string, input_to_u8_vec, StateValuesError}; -use leo_typed::State as TypedState; +use leo_ast::State as StateAst; use std::convert::TryFrom; @@ -27,10 +27,10 @@ pub struct StateValues { pub root: Vec, } -impl TryFrom<&TypedState> for StateValues { +impl TryFrom<&StateAst> for StateValues { type Error = StateValuesError; - fn try_from(state: &TypedState) -> Result { + fn try_from(state: &StateAst) -> Result { let parameters = state.values(); // Lookup leaf index diff --git a/state/src/record_commitment/dpc_record_values.rs b/state/src/record_commitment/dpc_record_values.rs index 4137267d40..16f4963ba6 100644 --- a/state/src/record_commitment/dpc_record_values.rs +++ b/state/src/record_commitment/dpc_record_values.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{utilities::*, DPCRecordValuesError}; -use leo_typed::Record as TypedRecord; +use leo_ast::Record as RecordAst; use snarkos_dpc::base_dpc::instantiated::Components; use snarkos_objects::AccountAddress; @@ -46,10 +46,10 @@ pub struct DPCRecordValues { pub commitment_randomness: Vec, } -impl TryFrom<&TypedRecord> for DPCRecordValues { +impl TryFrom<&RecordAst> for DPCRecordValues { type Error = DPCRecordValuesError; - fn try_from(record: &TypedRecord) -> Result { + fn try_from(record: &RecordAst) -> Result { let parameters = record.values(); // Lookup serial number diff --git a/state/src/record_commitment/record_commitment.rs b/state/src/record_commitment/record_commitment.rs index 1908c5a3da..89b633acf2 100644 --- a/state/src/record_commitment/record_commitment.rs +++ b/state/src/record_commitment/record_commitment.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{DPCRecordValues, RecordVerificationError}; -use leo_typed::Record as TypedRecord; +use leo_ast::Record as RecordAst; use snarkos_dpc::base_dpc::{ instantiated::{Components, RecordCommitment}, @@ -28,10 +28,10 @@ use std::convert::TryFrom; pub fn verify_record_commitment( system_parameters: &SystemParameters, - typed_record: &TypedRecord, + record_ast: &RecordAst, ) -> Result { // generate a dpc record from the typed record - let record = DPCRecordValues::try_from(typed_record)?; + let record = DPCRecordValues::try_from(record_ast)?; // verify record commitment let record_commitment_input = to_bytes![ diff --git a/state/src/utilities/input_value.rs b/state/src/utilities/input_value.rs index 9e1cc9421b..a04fde7c78 100644 --- a/state/src/utilities/input_value.rs +++ b/state/src/utilities/input_value.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::InputValueError; -use leo_typed::{InputValue, Parameter}; +use leo_ast::{InputValue, Parameter}; use std::collections::HashMap; diff --git a/state/tests/test_verify_local_data_commitment.rs b/state/tests/test_verify_local_data_commitment.rs index 89b8db06a3..83dc69a46b 100644 --- a/state/tests/test_verify_local_data_commitment.rs +++ b/state/tests/test_verify_local_data_commitment.rs @@ -14,9 +14,9 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . +use leo_ast::Input; use leo_input::LeoInputParser; use leo_state::verify_local_data_commitment; -use leo_typed::Input; use snarkos_dpc::base_dpc::{instantiated::*, record_payload::RecordPayload, DPC}; use snarkos_models::{ diff --git a/state/tests/test_verify_record_commitment.rs b/state/tests/test_verify_record_commitment.rs index 63dda73cb1..0a148a407f 100644 --- a/state/tests/test_verify_record_commitment.rs +++ b/state/tests/test_verify_record_commitment.rs @@ -14,9 +14,9 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . +use leo_ast::Input; use leo_input::LeoInputParser; use leo_state::verify_record_commitment; -use leo_typed::Input; use snarkos_dpc::base_dpc::instantiated::*; diff --git a/typed/src/circuits/circuit.rs b/typed/src/circuits/circuit.rs deleted file mode 100644 index cc5c6216af..0000000000 --- a/typed/src/circuits/circuit.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{CircuitMember, Identifier}; -use leo_ast::circuits::Circuit as AstCircuit; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct Circuit { - pub circuit_name: Identifier, - pub members: Vec, -} - -impl<'ast> From> for Circuit { - fn from(circuit: AstCircuit<'ast>) -> Self { - let circuit_name = Identifier::from(circuit.identifier); - let members = circuit.members.into_iter().map(CircuitMember::from).collect(); - - Self { circuit_name, members } - } -} - -impl Circuit { - fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { - writeln!(f, "circuit {} {{ ", self.circuit_name)?; - for field in self.members.iter() { - writeln!(f, " {}", field)?; - } - write!(f, "}}") - } -} - -impl fmt::Debug for Circuit { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.format(f) - } -} diff --git a/typed/src/circuits/circuit_member.rs b/typed/src/circuits/circuit_member.rs deleted file mode 100644 index 008806d3d3..0000000000 --- a/typed/src/circuits/circuit_member.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{Function, Identifier, Type}; -use leo_ast::circuits::{ - CircuitFunction as AstCircuitFunction, - CircuitMember as AstCircuitMember, - CircuitVariableDefinition as AstCircuitVariableDefinition, -}; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum CircuitMember { - // (is_mutable, variable_name, variable_type) - CircuitVariable(bool, Identifier, Type), - // (is_static, function) - CircuitFunction(bool, Function), -} - -impl<'ast> From> for CircuitMember { - fn from(circuit_value: AstCircuitVariableDefinition<'ast>) -> Self { - CircuitMember::CircuitVariable( - circuit_value.mutable.is_some(), - Identifier::from(circuit_value.identifier), - Type::from(circuit_value.type_), - ) - } -} - -impl<'ast> From> for CircuitMember { - fn from(circuit_function: AstCircuitFunction<'ast>) -> Self { - CircuitMember::CircuitFunction( - circuit_function._static.is_some(), - Function::from(circuit_function.function), - ) - } -} - -impl<'ast> From> for CircuitMember { - fn from(object: AstCircuitMember<'ast>) -> Self { - match object { - AstCircuitMember::CircuitVariableDefinition(circuit_value) => CircuitMember::from(circuit_value), - AstCircuitMember::CircuitFunction(circuit_function) => CircuitMember::from(circuit_function), - } - } -} - -impl fmt::Display for CircuitMember { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - CircuitMember::CircuitVariable(ref mutable, ref identifier, ref type_) => { - if *mutable { - write!(f, "mut ")?; - } - write!(f, "{}: {}", identifier, type_) - } - CircuitMember::CircuitFunction(ref static_, ref function) => { - if *static_ { - write!(f, "static ")?; - } - write!(f, "{}", function) - } - } - } -} diff --git a/typed/src/circuits/circuit_variable_definition.rs b/typed/src/circuits/circuit_variable_definition.rs deleted file mode 100644 index 2abba2b377..0000000000 --- a/typed/src/circuits/circuit_variable_definition.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{Expression, Identifier}; -use leo_ast::circuits::CircuitVariable; - -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct CircuitVariableDefinition { - pub identifier: Identifier, - pub expression: Expression, -} - -impl<'ast> From> for CircuitVariableDefinition { - fn from(member: CircuitVariable<'ast>) -> Self { - CircuitVariableDefinition { - identifier: Identifier::from(member.identifier), - expression: Expression::from(member.expression), - } - } -} diff --git a/typed/src/common/assignee.rs b/typed/src/common/assignee.rs deleted file mode 100644 index e18ae12d4a..0000000000 --- a/typed/src/common/assignee.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{Expression, Identifier, RangeOrExpression}; -use leo_ast::{ - access::AssigneeAccess as AstAssigneeAccess, - common::{Assignee as AstAssignee, Identifier as AstIdentifier, SelfKeywordOrIdentifier}, -}; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -/// Definition assignee: v, arr[0..2], Point p.x -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum Assignee { - Identifier(Identifier), - Array(Box<(Assignee, RangeOrExpression)>), - Tuple(Box, usize), - CircuitField(Box, Identifier), // (circuit name, circuit field name) -} - -impl<'ast> From> for Assignee { - fn from(variable: AstIdentifier<'ast>) -> Self { - Assignee::Identifier(Identifier::from(variable)) - } -} - -impl<'ast> From> for Assignee { - fn from(name: SelfKeywordOrIdentifier<'ast>) -> Self { - Assignee::Identifier(Identifier::from(name)) - } -} - -impl<'ast> From> for Assignee { - fn from(assignee: AstAssignee<'ast>) -> Self { - let variable = Assignee::from(assignee.name); - - // We start with the id, and we fold the array of accesses by wrapping the current value - assignee - .accesses - .into_iter() - .fold(variable, |acc, access| match access { - AstAssigneeAccess::Array(array) => { - Assignee::Array(Box::new((acc, RangeOrExpression::from(array.expression)))) - } - AstAssigneeAccess::Tuple(tuple) => { - Assignee::Tuple(Box::new(acc), Expression::get_count_from_ast(tuple.number)) - } - AstAssigneeAccess::Member(circuit_variable) => { - Assignee::CircuitField(Box::new(acc), Identifier::from(circuit_variable.identifier)) - } - }) - } -} - -impl fmt::Display for Assignee { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Assignee::Identifier(ref variable) => write!(f, "{}", variable), - Assignee::Array(ref array_w_index) => write!(f, "{}[{}]", array_w_index.0, array_w_index.1), - Assignee::Tuple(ref tuple, ref index) => write!(f, "{}.{}", tuple, index), - Assignee::CircuitField(ref circuit_variable, ref member) => write!(f, "{}.{}", circuit_variable, member), - } - } -} diff --git a/typed/src/common/identifier.rs b/typed/src/common/identifier.rs deleted file mode 100644 index 15a2abd83b..0000000000 --- a/typed/src/common/identifier.rs +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::Span; -use leo_ast::{ - annotations::AnnotationArgument, - common::{Identifier as AstIdentifier, KeywordOrIdentifier, SelfKeyword, SelfKeywordOrIdentifier}, - expressions::CircuitName, - functions::InputKeyword, - imports::PackageName as AstPackageName, - types::SelfType, -}; -use leo_input::common::Identifier as InputAstIdentifier; - -use serde::{ - de::{self, Visitor}, - Deserialize, - Deserializer, - Serialize, - Serializer, -}; -use std::{ - collections::BTreeMap, - fmt, - hash::{Hash, Hasher}, -}; - -/// An identifier in the constrained program. -/// -/// Attention - When adding or removing fields from this struct, -/// please remember to update it's Serialize and Deserialize implementation -/// to reflect the new struct instantiation. -#[derive(Clone)] -pub struct Identifier { - pub name: String, - pub span: Span, -} - -impl Identifier { - pub fn is_self(&self) -> bool { - self.name == "Self" || self.name == "self" - } -} - -impl<'ast> From> for Identifier { - fn from(identifier: AstIdentifier<'ast>) -> Self { - Self { - name: identifier.value, - span: Span::from(identifier.span), - } - } -} - -impl<'ast> From> for Identifier { - fn from(name: AstPackageName<'ast>) -> Self { - Self { - name: name.value, - span: Span::from(name.span), - } - } -} - -impl<'ast> From> for Identifier { - fn from(identifier: InputAstIdentifier<'ast>) -> Self { - Self { - name: identifier.value, - span: Span::from(identifier.span), - } - } -} - -impl<'ast> From> for Identifier { - fn from(argument: AnnotationArgument<'ast>) -> Self { - Self { - name: argument.value, - span: Span::from(argument.span), - } - } -} - -impl<'ast> From> for Identifier { - fn from(name: KeywordOrIdentifier<'ast>) -> Self { - match name { - KeywordOrIdentifier::SelfKeywordOrIdentifier(keyword) => Identifier::from(keyword), - KeywordOrIdentifier::SelfType(self_type) => Identifier::from(self_type), - KeywordOrIdentifier::Input(keyword) => Identifier::from(keyword), - } - } -} - -impl<'ast> From> for Identifier { - fn from(name: SelfKeywordOrIdentifier<'ast>) -> Self { - match name { - SelfKeywordOrIdentifier::Identifier(identifier) => Identifier::from(identifier), - SelfKeywordOrIdentifier::SelfKeyword(keyword) => Identifier::from(keyword), - } - } -} - -impl<'ast> From> for Identifier { - fn from(self_: SelfKeyword<'ast>) -> Self { - Self { - name: self_.keyword, - span: Span::from(self_.span), - } - } -} - -impl<'ast> From> for Identifier { - fn from(input: InputKeyword<'ast>) -> Self { - Self { - name: input.keyword, - span: Span::from(input.span), - } - } -} - -impl<'ast> From> for Identifier { - fn from(name: CircuitName<'ast>) -> Self { - match name { - CircuitName::SelfType(self_type) => Identifier::from(self_type), - CircuitName::Identifier(identifier) => Identifier::from(identifier), - } - } -} - -impl<'ast> From> for Identifier { - fn from(self_type: SelfType<'ast>) -> Self { - Self { - name: self_type.keyword, - span: Span::from(self_type.span), - } - } -} - -impl fmt::Display for Identifier { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.name) - } -} -impl fmt::Debug for Identifier { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.name) - } -} - -impl PartialEq for Identifier { - fn eq(&self, other: &Self) -> bool { - self.name == other.name - } -} - -impl Eq for Identifier {} - -impl Hash for Identifier { - fn hash(&self, state: &mut H) { - self.name.hash(state); - } -} - -impl Serialize for Identifier { - fn serialize(&self, serializer: S) -> Result { - // Converts an element that implements Serialize into a string. - fn to_json_string(element: &E) -> Result { - serde_json::to_string(&element).map_err(|e| Error::custom(e.to_string())) - } - - // Load the struct elements into a BTreeMap (to preserve serialized ordering of keys). - let mut key: BTreeMap = BTreeMap::new(); - key.insert("name".to_string(), self.name.clone()); - key.insert("span".to_string(), to_json_string(&self.span)?); - - // Convert the serialized object into a string for use as a key. - serializer.serialize_str(&to_json_string(&key)?) - } -} - -impl<'de> Deserialize<'de> for Identifier { - fn deserialize>(deserializer: D) -> Result { - struct IdentifierVisitor; - - impl<'de> Visitor<'de> for IdentifierVisitor { - type Value = Identifier; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a string encoding the typed Identifier struct") - } - - /// Implementation for recovering a string that serializes Identifier. - fn visit_str(self, value: &str) -> Result { - // Converts a serialized string into an element that implements Deserialize. - fn to_json_string<'a, D: Deserialize<'a>, Error: serde::de::Error>( - serialized: &'a str, - ) -> Result { - serde_json::from_str::<'a>(serialized).map_err(|e| Error::custom(e.to_string())) - } - - // Convert the serialized string into a BTreeMap to recover Identifier. - let key: BTreeMap = to_json_string(value)?; - - let name = match key.get("name") { - Some(name) => name.clone(), - None => return Err(E::custom("missing 'name' in serialized Identifier struct")), - }; - - let span: Span = match key.get("span") { - Some(span) => to_json_string(span)?, - None => return Err(E::custom("missing 'span' in serialized Identifier struct")), - }; - - Ok(Identifier { name, span }) - } - } - - deserializer.deserialize_str(IdentifierVisitor) - } -} diff --git a/typed/src/common/range_or_expression.rs b/typed/src/common/range_or_expression.rs deleted file mode 100644 index 60f1f97acd..0000000000 --- a/typed/src/common/range_or_expression.rs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::Expression; -use leo_ast::common::RangeOrExpression as AstRangeOrExpression; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -/// Range or expression enum -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum RangeOrExpression { - Range(Option, Option), - Expression(Expression), -} - -impl<'ast> From> for RangeOrExpression { - fn from(range_or_expression: AstRangeOrExpression<'ast>) -> Self { - match range_or_expression { - AstRangeOrExpression::Range(range) => { - RangeOrExpression::Range(range.from.map(Expression::from), range.to.map(Expression::from)) - } - AstRangeOrExpression::Expression(expression) => RangeOrExpression::Expression(Expression::from(expression)), - } - } -} - -impl fmt::Display for RangeOrExpression { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - RangeOrExpression::Range(ref from, ref to) => write!( - f, - "{}..{}", - from.as_ref().map(|e| e.to_string()).unwrap_or_default(), - to.as_ref().map(|e| e.to_string()).unwrap_or_default() - ), - RangeOrExpression::Expression(ref e) => write!(f, "{}", e), - } - } -} diff --git a/typed/src/common/spread_or_expression.rs b/typed/src/common/spread_or_expression.rs deleted file mode 100644 index c6f817bdc4..0000000000 --- a/typed/src/common/spread_or_expression.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::Expression; -use leo_ast::{common::SpreadOrExpression as AstSpreadOrExpression, expressions::Expression as AstExpression}; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -/// Spread or expression -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum SpreadOrExpression { - Spread(Expression), - Expression(Expression), -} - -impl<'ast> From> for SpreadOrExpression { - fn from(s_or_e: AstSpreadOrExpression<'ast>) -> Self { - match s_or_e { - AstSpreadOrExpression::Spread(spread) => SpreadOrExpression::Spread(Expression::from(spread.expression)), - AstSpreadOrExpression::Expression(expression) => { - SpreadOrExpression::Expression(Expression::from(expression)) - } - } - } -} - -impl<'ast> From> for SpreadOrExpression { - fn from(expression: AstExpression<'ast>) -> Self { - SpreadOrExpression::Expression(Expression::from(expression)) - } -} - -impl fmt::Display for SpreadOrExpression { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - SpreadOrExpression::Spread(ref spread) => write!(f, "...{}", spread), - SpreadOrExpression::Expression(ref expression) => write!(f, "{}", expression), - } - } -} diff --git a/typed/src/console/console_function.rs b/typed/src/console/console_function.rs deleted file mode 100644 index 95d0a0c37d..0000000000 --- a/typed/src/console/console_function.rs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{Expression, FormattedString}; -use leo_ast::console::{ - ConsoleAssert as AstConsoleAssert, - ConsoleDebug as AstConsoleDebug, - ConsoleError as AstConsoleError, - ConsoleFunction as AstConsoleFunction, - ConsoleLog as AstConsoleLog, -}; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum ConsoleFunction { - Assert(Expression), - Debug(FormattedString), - Error(FormattedString), - Log(FormattedString), -} - -impl<'ast> From> for ConsoleFunction { - fn from(console_function: AstConsoleFunction<'ast>) -> Self { - match console_function { - AstConsoleFunction::Assert(assert) => ConsoleFunction::from(assert), - AstConsoleFunction::Debug(debug) => ConsoleFunction::from(debug), - AstConsoleFunction::Error(error) => ConsoleFunction::from(error), - AstConsoleFunction::Log(log) => ConsoleFunction::from(log), - } - } -} - -impl<'ast> From> for ConsoleFunction { - fn from(assert: AstConsoleAssert<'ast>) -> Self { - ConsoleFunction::Assert(Expression::from(assert.expression)) - } -} - -impl<'ast> From> for ConsoleFunction { - fn from(debug: AstConsoleDebug<'ast>) -> Self { - ConsoleFunction::Debug(FormattedString::from(debug.string)) - } -} - -impl<'ast> From> for ConsoleFunction { - fn from(error: AstConsoleError<'ast>) -> Self { - ConsoleFunction::Error(FormattedString::from(error.string)) - } -} - -impl<'ast> From> for ConsoleFunction { - fn from(log: AstConsoleLog<'ast>) -> Self { - ConsoleFunction::Log(FormattedString::from(log.string)) - } -} - -impl fmt::Display for ConsoleFunction { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - ConsoleFunction::Assert(assert) => write!(f, "assert({})", assert), - ConsoleFunction::Debug(debug) => write!(f, "debug({})", debug), - ConsoleFunction::Error(error) => write!(f, "error{})", error), - ConsoleFunction::Log(log) => write!(f, "log({})", log), - } - } -} diff --git a/typed/src/console/formatted_string.rs b/typed/src/console/formatted_string.rs deleted file mode 100644 index b3d41fe20f..0000000000 --- a/typed/src/console/formatted_string.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{FormattedContainer, FormattedParameter, Span}; -use leo_ast::console::FormattedString as AstFormattedString; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct FormattedString { - pub string: String, - pub containers: Vec, - pub parameters: Vec, - pub span: Span, -} - -impl<'ast> From> for FormattedString { - fn from(formatted: AstFormattedString<'ast>) -> Self { - let string = formatted.string; - let span = Span::from(formatted.span); - let containers = formatted.containers.into_iter().map(FormattedContainer::from).collect(); - let parameters = formatted.parameters.into_iter().map(FormattedParameter::from).collect(); - - Self { - string, - containers, - parameters, - span, - } - } -} - -impl fmt::Display for FormattedString { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.string) - } -} diff --git a/typed/src/functions/function.rs b/typed/src/functions/function.rs deleted file mode 100644 index f1a8f3c512..0000000000 --- a/typed/src/functions/function.rs +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{Identifier, InputVariable, Span, Statement, Type}; -use leo_ast::functions::Function as AstFunction; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -#[derive(Clone, Serialize, Deserialize)] -pub struct Function { - pub identifier: Identifier, - pub input: Vec, - pub returns: Option, - pub statements: Vec, - pub span: Span, -} - -impl PartialEq for Function { - fn eq(&self, other: &Self) -> bool { - self.identifier == other.identifier - } -} - -impl Eq for Function {} - -impl<'ast> From> for Function { - fn from(function: AstFunction<'ast>) -> Self { - let function_name = Identifier::from(function.identifier); - let parameters = function.parameters.into_iter().map(InputVariable::from).collect(); - let returns = function.returns.map(Type::from); - let statements = function.statements.into_iter().map(Statement::from).collect(); - - Function { - identifier: function_name, - input: parameters, - returns, - statements, - span: Span::from(function.span), - } - } -} - -impl Function { - pub fn get_name(&self) -> &str { - &self.identifier.name - } - - fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "function {}", self.identifier)?; - let parameters = self.input.iter().map(|x| x.to_string()).collect::>().join(","); - let returns = self.returns.as_ref().map(|type_| type_.to_string()); - let statements = self - .statements - .iter() - .map(|s| format!("\t{}\n", s)) - .collect::>() - .join(""); - if returns.is_none() { - write!(f, "({}) {{\n{}}}", parameters, statements,) - } else { - write!(f, "({}) -> {} {{\n{}}}", parameters, returns.unwrap(), statements,) - } - } -} - -impl fmt::Display for Function { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.format(f) - } -} - -impl fmt::Debug for Function { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.format(f) - } -} diff --git a/typed/src/functions/input/function_input.rs b/typed/src/functions/input/function_input.rs deleted file mode 100644 index ea91b1b988..0000000000 --- a/typed/src/functions/input/function_input.rs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{Identifier, Span, Type}; -use leo_ast::functions::FunctionInput as AstFunctionInput; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct FunctionInput { - pub identifier: Identifier, - pub mutable: bool, - pub type_: Type, - pub span: Span, -} - -impl<'ast> From> for FunctionInput { - fn from(parameter: AstFunctionInput<'ast>) -> Self { - FunctionInput { - identifier: Identifier::from(parameter.identifier), - mutable: parameter.mutable.is_some(), - type_: Type::from(parameter.type_), - span: Span::from(parameter.span), - } - } -} - -impl FunctionInput { - fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { - // mut var: bool - if self.mutable { - write!(f, "mut ")?; - } - write!(f, "{}: ", self.identifier)?; - write!(f, "{}", self.type_) - } -} - -impl fmt::Display for FunctionInput { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.format(f) - } -} - -impl fmt::Debug for FunctionInput { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.format(f) - } -} diff --git a/typed/src/imports/import.rs b/typed/src/imports/import.rs deleted file mode 100644 index aeac7f0d3b..0000000000 --- a/typed/src/imports/import.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -//! The import type for a Leo program. - -use crate::{Package, Span}; -use leo_ast::imports::Import as AstImport; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)] -pub struct Import { - pub package: Package, - pub span: Span, -} - -impl<'ast> From> for Import { - fn from(import: AstImport<'ast>) -> Self { - Import { - package: Package::from(import.package), - span: Span::from(import.span), - } - } -} - -impl Import { - fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "import {};", self.package) - } -} - -impl fmt::Display for Import { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.format(f) - } -} - -impl fmt::Debug for Import { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.format(f) - } -} diff --git a/typed/src/imports/import_symbol.rs b/typed/src/imports/import_symbol.rs deleted file mode 100644 index 7c1e129927..0000000000 --- a/typed/src/imports/import_symbol.rs +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{Identifier, Span}; -use leo_ast::imports::ImportSymbol as AstImportSymbol; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)] -pub struct ImportSymbol { - pub symbol: Identifier, - pub alias: Option, - pub span: Span, -} - -impl<'ast> From> for ImportSymbol { - fn from(symbol: AstImportSymbol<'ast>) -> Self { - ImportSymbol { - symbol: Identifier::from(symbol.value), - alias: symbol.alias.map(Identifier::from), - span: Span::from(symbol.span), - } - } -} - -impl fmt::Display for ImportSymbol { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.alias.is_some() { - write!(f, "{} as {}", self.symbol, self.alias.as_ref().unwrap()) - } else { - write!(f, "{}", self.symbol) - } - } -} - -// TODO (collin): remove this -impl fmt::Debug for ImportSymbol { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.alias.is_some() { - write!(f, "{} as {}", self.symbol, self.alias.as_ref().unwrap()) - } else { - write!(f, "{}", self.symbol) - } - } -} - -impl ImportSymbol { - pub fn star(span: &Span) -> Self { - Self { - symbol: Identifier { - name: "*".to_string(), - span: span.clone(), - }, - alias: None, - span: span.clone(), - } - } - - pub fn is_star(&self) -> bool { - self.symbol.name.eq("*") - } -} diff --git a/typed/src/imports/package.rs b/typed/src/imports/package.rs deleted file mode 100644 index d67cde967f..0000000000 --- a/typed/src/imports/package.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{common::Identifier, PackageAccess, Span}; -use leo_ast::imports::Package as AstPackage; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)] -pub struct Package { - pub name: Identifier, - pub access: PackageAccess, - pub span: Span, -} - -impl<'ast> From> for Package { - fn from(package: AstPackage<'ast>) -> Self { - Package { - name: Identifier::from(package.name), - access: PackageAccess::from(package.access), - span: Span::from(package.span), - } - } -} - -impl Package { - fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}.{}", self.name, self.access) - } -} - -impl fmt::Display for Package { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.format(f) - } -} - -impl fmt::Debug for Package { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.format(f) - } -} diff --git a/typed/src/imports/package_access.rs b/typed/src/imports/package_access.rs deleted file mode 100644 index 27608905ad..0000000000 --- a/typed/src/imports/package_access.rs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{ImportSymbol, Package, Span}; -use leo_ast::imports::PackageAccess as AstPackageAccess; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)] -pub enum PackageAccess { - Star(Span), - SubPackage(Box), - Symbol(ImportSymbol), - Multiple(Vec), -} - -impl<'ast> From> for PackageAccess { - fn from(access: AstPackageAccess<'ast>) -> Self { - match access { - AstPackageAccess::Star(star) => PackageAccess::Star(Span::from(star.span)), - AstPackageAccess::SubPackage(package) => PackageAccess::SubPackage(Box::new(Package::from(*package))), - AstPackageAccess::Symbol(symbol) => PackageAccess::Symbol(ImportSymbol::from(symbol)), - AstPackageAccess::Multiple(accesses) => { - PackageAccess::Multiple(accesses.into_iter().map(PackageAccess::from).collect()) - } - } - } -} - -impl PackageAccess { - fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - PackageAccess::Star(ref _span) => write!(f, "*"), - PackageAccess::SubPackage(ref package) => write!(f, "{}", package), - PackageAccess::Symbol(ref symbol) => write!(f, "{}", symbol), - PackageAccess::Multiple(ref accesses) => { - write!(f, "(")?; - for (i, access) in accesses.iter().enumerate() { - write!(f, "{}", access)?; - if i < accesses.len() - 1 { - write!(f, ", ")?; - } - } - write!(f, ")") - } - } - } -} - -impl fmt::Debug for PackageAccess { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.format(f) - } -} - -impl fmt::Display for PackageAccess { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.format(f) - } -} diff --git a/typed/src/lib.rs b/typed/src/lib.rs deleted file mode 100644 index 12fb1699f5..0000000000 --- a/typed/src/lib.rs +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -//! A typed syntax tree is represented as a `Program` and consists of import, circuit, and function definitions. -//! Each defined type consists of typed statements and expressions. - -pub mod annotation; -pub use self::annotation::*; - -pub mod circuits; -pub use self::circuits::*; - -pub mod common; -pub use self::common::*; - -pub mod console; -pub use self::console::*; - -pub mod errors; -pub use self::errors::*; - -pub mod expression; -pub use self::expression::*; - -pub mod functions; -pub use self::functions::*; - -pub mod groups; -pub use self::groups::*; - -pub mod imports; -pub use self::imports::*; - -pub mod input; -pub use self::input::*; - -pub mod program; -pub use self::program::*; - -pub mod statements; -pub use self::statements::*; - -pub mod types; -pub use self::types::*; - -use leo_ast::LeoAst; - -#[derive(Debug, Eq, PartialEq)] -pub struct LeoTypedAst { - typed_ast: Program, -} - -impl LeoTypedAst { - /// Creates a new typed syntax tree from a given program name and abstract syntax tree. - pub fn new<'ast>(program_name: &str, ast: &LeoAst<'ast>) -> Self { - Self { - typed_ast: Program::from(program_name, ast.as_repr()), - } - } - - /// Returns a reference to the inner typed syntax tree representation. - pub fn into_repr(self) -> Program { - self.typed_ast - } - - /// Serializes the typed syntax tree into a JSON string. - pub fn to_json_string(&self) -> Result { - Ok(serde_json::to_string_pretty(&self.typed_ast)?) - } - - /// Deserializes the JSON string into a typed syntax tree. - pub fn from_json_string(json: &str) -> Result { - let typed_ast: Program = serde_json::from_str(json)?; - Ok(Self { typed_ast }) - } -} diff --git a/typed/src/statements/conditional_nested_or_end_statement.rs b/typed/src/statements/conditional_nested_or_end_statement.rs deleted file mode 100644 index 5dbe8b1c5d..0000000000 --- a/typed/src/statements/conditional_nested_or_end_statement.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{ConditionalStatement, Statement}; -use leo_ast::statements::ConditionalNestedOrEndStatement as AstConditionalNestedOrEndStatement; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum ConditionalNestedOrEndStatement { - Nested(Box), - End(Vec), -} - -impl<'ast> From> for ConditionalNestedOrEndStatement { - fn from(statement: AstConditionalNestedOrEndStatement<'ast>) -> Self { - match statement { - AstConditionalNestedOrEndStatement::Nested(nested) => { - ConditionalNestedOrEndStatement::Nested(Box::new(ConditionalStatement::from(*nested))) - } - AstConditionalNestedOrEndStatement::End(statements) => { - ConditionalNestedOrEndStatement::End(statements.into_iter().map(Statement::from).collect()) - } - } - } -} - -impl fmt::Display for ConditionalNestedOrEndStatement { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ConditionalNestedOrEndStatement::Nested(ref nested) => write!(f, "else {}", nested), - ConditionalNestedOrEndStatement::End(ref statements) => { - writeln!(f, "else {{")?; - for statement in statements.iter() { - writeln!(f, "\t\t{}", statement)?; - } - write!(f, "\t}}") - } - } - } -} diff --git a/typed/src/statements/conditional_statement.rs b/typed/src/statements/conditional_statement.rs deleted file mode 100644 index 90983251e6..0000000000 --- a/typed/src/statements/conditional_statement.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{ConditionalNestedOrEndStatement, Expression, Statement}; -use leo_ast::statements::ConditionalStatement as AstConditionalStatement; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct ConditionalStatement { - pub condition: Expression, - pub statements: Vec, - pub next: Option, -} - -impl<'ast> From> for ConditionalStatement { - fn from(statement: AstConditionalStatement<'ast>) -> Self { - ConditionalStatement { - condition: Expression::from(statement.condition), - statements: statement.statements.into_iter().map(Statement::from).collect(), - next: statement - .next - .map(|n_or_e| Some(ConditionalNestedOrEndStatement::from(n_or_e))) - .unwrap_or(None), - } - } -} - -impl fmt::Display for ConditionalStatement { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - writeln!(f, "if ({}) {{", self.condition)?; - for statement in self.statements.iter() { - writeln!(f, "\t\t{}", statement)?; - } - match self.next.clone() { - Some(n_or_e) => write!(f, "\t}} {}", n_or_e), - None => write!(f, "\t}}"), - } - } -} diff --git a/typed/src/statements/statement.rs b/typed/src/statements/statement.rs deleted file mode 100644 index 36da315e43..0000000000 --- a/typed/src/statements/statement.rs +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{Assignee, ConditionalStatement, ConsoleFunctionCall, Declare, Expression, Identifier, Span, Variables}; -use leo_ast::{ - console::ConsoleFunctionCall as AstConsoleFunctionCall, - operations::AssignOperation, - statements::{ - AssignStatement, - DefinitionStatement, - ExpressionStatement, - ForStatement, - ReturnStatement, - Statement as AstStatement, - }, -}; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -/// Program statement that defines some action (or expression) to be carried out. -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum Statement { - Return(Expression, Span), - Definition(Declare, Variables, Vec, Span), - Assign(Assignee, Box, Span), - Conditional(ConditionalStatement, Span), - Iteration(Identifier, Box<(Expression, Expression)>, Vec, Span), - Console(ConsoleFunctionCall), - Expression(Expression, Span), -} - -impl<'ast> From> for Statement { - fn from(statement: ReturnStatement<'ast>) -> Self { - Statement::Return(Expression::from(statement.expression), Span::from(statement.span)) - } -} - -impl<'ast> From> for Statement { - fn from(statement: DefinitionStatement<'ast>) -> Self { - let span = Span::from(statement.span); - - let expressions = statement - .expressions - .into_iter() - .map(|e| { - let mut expression = Expression::from(e); - expression.set_span(span.clone()); - - expression - }) - .collect::>(); - - Statement::Definition( - Declare::from(statement.declare), - Variables::from(statement.variables), - expressions, - span, - ) - } -} - -impl<'ast> From> for Statement { - fn from(statement: AssignStatement<'ast>) -> Self { - match statement.assign { - AssignOperation::Assign(ref _assign) => Statement::Assign( - Assignee::from(statement.assignee), - Box::new(Expression::from(statement.expression)), - Span::from(statement.span), - ), - operation_assign => { - // convert assignee into postfix expression - let converted = Expression::from(statement.assignee.clone()); - - match operation_assign { - AssignOperation::AddAssign(ref _assign) => Statement::Assign( - Assignee::from(statement.assignee), - Box::new(Expression::Add( - Box::new((converted, Expression::from(statement.expression))), - Span::from(statement.span.clone()), - )), - Span::from(statement.span), - ), - AssignOperation::SubAssign(ref _assign) => Statement::Assign( - Assignee::from(statement.assignee), - Box::new(Expression::Sub( - Box::new((converted, Expression::from(statement.expression))), - Span::from(statement.span.clone()), - )), - Span::from(statement.span), - ), - AssignOperation::MulAssign(ref _assign) => Statement::Assign( - Assignee::from(statement.assignee), - Box::new(Expression::Mul( - Box::new((converted, Expression::from(statement.expression))), - Span::from(statement.span.clone()), - )), - Span::from(statement.span), - ), - AssignOperation::DivAssign(ref _assign) => Statement::Assign( - Assignee::from(statement.assignee), - Box::new(Expression::Div( - Box::new((converted, Expression::from(statement.expression))), - Span::from(statement.span.clone()), - )), - Span::from(statement.span), - ), - AssignOperation::PowAssign(ref _assign) => Statement::Assign( - Assignee::from(statement.assignee), - Box::new(Expression::Pow( - Box::new((converted, Expression::from(statement.expression))), - Span::from(statement.span.clone()), - )), - Span::from(statement.span), - ), - AssignOperation::Assign(ref _assign) => unimplemented!("cannot assign twice to assign statement"), - } - } - } - } -} - -impl<'ast> From> for Statement { - fn from(statement: ForStatement<'ast>) -> Self { - Statement::Iteration( - Identifier::from(statement.index), - Box::new((Expression::from(statement.start), Expression::from(statement.stop))), - statement.statements.into_iter().map(Statement::from).collect(), - Span::from(statement.span), - ) - } -} - -impl<'ast> From> for Statement { - fn from(function_call: AstConsoleFunctionCall<'ast>) -> Self { - Statement::Console(ConsoleFunctionCall::from(function_call)) - } -} - -impl<'ast> From> for Statement { - fn from(statement: ExpressionStatement<'ast>) -> Self { - let span = Span::from(statement.span); - let mut expression = Expression::from(statement.expression); - - expression.set_span(span.clone()); - - Statement::Expression(expression, span) - } -} - -impl<'ast> From> for Statement { - fn from(statement: AstStatement<'ast>) -> Self { - match statement { - AstStatement::Return(statement) => Statement::from(statement), - AstStatement::Definition(statement) => Statement::from(statement), - AstStatement::Assign(statement) => Statement::from(statement), - AstStatement::Conditional(statement) => { - let span = Span::from(statement.span.clone()); - Statement::Conditional(ConditionalStatement::from(statement), span) - } - AstStatement::Iteration(statement) => Statement::from(statement), - AstStatement::Console(console) => Statement::from(console), - AstStatement::Expression(statement) => Statement::from(statement), - } - } -} - -impl fmt::Display for Statement { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Statement::Return(ref expression, ref _span) => write!(f, "return {}", expression), - Statement::Definition(ref declare, ref variable, ref expressions, ref _span) => { - let formatted_expressions = expressions.iter().map(|x| x.to_string()).collect::>().join(","); - - write!(f, "{} {} = {};", declare, variable, formatted_expressions) - } - Statement::Assign(ref variable, ref statement, ref _span) => write!(f, "{} = {};", variable, statement), - Statement::Conditional(ref statement, ref _span) => write!(f, "{}", statement), - Statement::Iteration(ref var, ref start_stop, ref list, ref _span) => { - writeln!(f, "for {} in {}..{} {{", var, start_stop.0, start_stop.1)?; - for l in list { - writeln!(f, "\t\t{}", l)?; - } - write!(f, "\t}}") - } - Statement::Console(ref console) => write!(f, "{}", console), - Statement::Expression(ref expression, ref _span) => write!(f, "{};", expression), - } - } -} diff --git a/typed/src/types/integer_type.rs b/typed/src/types/integer_type.rs deleted file mode 100644 index e766c65168..0000000000 --- a/typed/src/types/integer_type.rs +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use leo_ast::types::{ - IntegerType as AstIntegerType, - SignedIntegerType as AstSignedIntegerType, - UnsignedIntegerType as AstUnsignedIntegerType, -}; -use leo_input::types::{ - IntegerType as InputAstIntegerType, - SignedIntegerType as InputAstSignedIntegerType, - UnsignedIntegerType as InputAstUnsignedIntegerType, -}; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -/// Explicit integer type -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum IntegerType { - U8, - U16, - U32, - U64, - U128, - - I8, - I16, - I32, - I64, - I128, -} - -impl From for IntegerType { - fn from(integer_type: AstIntegerType) -> Self { - match integer_type { - AstIntegerType::Signed(signed) => Self::from(signed), - AstIntegerType::Unsigned(unsigned) => Self::from(unsigned), - } - } -} - -impl From for IntegerType { - fn from(integer_type: AstUnsignedIntegerType) -> Self { - match integer_type { - AstUnsignedIntegerType::U8Type(_type) => IntegerType::U8, - AstUnsignedIntegerType::U16Type(_type) => IntegerType::U16, - AstUnsignedIntegerType::U32Type(_type) => IntegerType::U32, - AstUnsignedIntegerType::U64Type(_type) => IntegerType::U64, - AstUnsignedIntegerType::U128Type(_type) => IntegerType::U128, - } - } -} - -impl From for IntegerType { - fn from(integer_type: AstSignedIntegerType) -> Self { - match integer_type { - AstSignedIntegerType::I8Type(_type) => IntegerType::I8, - AstSignedIntegerType::I16Type(_type) => IntegerType::I16, - AstSignedIntegerType::I32Type(_type) => IntegerType::I32, - AstSignedIntegerType::I64Type(_type) => IntegerType::I64, - AstSignedIntegerType::I128Type(_type) => IntegerType::I128, - } - } -} - -impl From for IntegerType { - fn from(integer_type: InputAstIntegerType) -> Self { - match integer_type { - InputAstIntegerType::Signed(signed) => Self::from(signed), - InputAstIntegerType::Unsigned(unsigned) => Self::from(unsigned), - } - } -} - -impl From for IntegerType { - fn from(integer_type: InputAstUnsignedIntegerType) -> Self { - match integer_type { - InputAstUnsignedIntegerType::U8Type(_type) => IntegerType::U8, - InputAstUnsignedIntegerType::U16Type(_type) => IntegerType::U16, - InputAstUnsignedIntegerType::U32Type(_type) => IntegerType::U32, - InputAstUnsignedIntegerType::U64Type(_type) => IntegerType::U64, - InputAstUnsignedIntegerType::U128Type(_type) => IntegerType::U128, - } - } -} - -impl From for IntegerType { - fn from(integer_type: InputAstSignedIntegerType) -> Self { - match integer_type { - InputAstSignedIntegerType::I8Type(_type) => IntegerType::I8, - InputAstSignedIntegerType::I16Type(_type) => IntegerType::I16, - InputAstSignedIntegerType::I32Type(_type) => IntegerType::I32, - InputAstSignedIntegerType::I64Type(_type) => IntegerType::I64, - InputAstSignedIntegerType::I128Type(_type) => IntegerType::I128, - } - } -} - -impl fmt::Display for IntegerType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - IntegerType::U8 => write!(f, "u8"), - IntegerType::U16 => write!(f, "u16"), - IntegerType::U32 => write!(f, "u32"), - IntegerType::U64 => write!(f, "u64"), - IntegerType::U128 => write!(f, "u128"), - - IntegerType::I8 => write!(f, "i8"), - IntegerType::I16 => write!(f, "i16"), - IntegerType::I32 => write!(f, "i32"), - IntegerType::I64 => write!(f, "i64"), - IntegerType::I128 => write!(f, "i128"), - } - } -} diff --git a/typed/src/types/type_.rs b/typed/src/types/type_.rs deleted file mode 100644 index e27918c020..0000000000 --- a/typed/src/types/type_.rs +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{Expression, Identifier, IntegerType}; -use leo_ast::types::{ArrayType, CircuitType, DataType, TupleType, Type as AstType}; -use leo_input::types::{ - ArrayType as InputArrayType, - DataType as InputDataType, - TupleType as InputTupleType, - Type as InputAstType, -}; - -use serde::{Deserialize, Serialize}; -use std::fmt; - -/// Explicit type used for defining a variable or expression type -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum Type { - // Data types - Address, - Boolean, - Field, - Group, - IntegerType(IntegerType), - - // Data type wrappers - Array(Box, Vec), - Tuple(Vec), - Circuit(Identifier), - SelfType, -} - -impl Type { - pub fn is_self(&self) -> bool { - matches!(self, Type::SelfType) - } - - pub fn is_circuit(&self) -> bool { - matches!(self, Type::Circuit(_)) - } - - pub fn match_array_types(&self, other: &Type) -> bool { - // Check that both `self` and `other` are of type array - let (type_1, dimensions_1) = match self { - Type::Array(type_, dimensions) => (type_, dimensions), - _ => return false, - }; - - let (type_2, dimensions_2) = match other { - Type::Array(type_, dimensions) => (type_, dimensions), - _ => return false, - }; - - // Expand multidimensional array syntax - let (type_1_expanded, dimensions_1_expanded) = expand_array_type(type_1, dimensions_1); - let (type_2_expanded, dimensions_2_expanded) = expand_array_type(type_2, dimensions_2); - - // Return true if expanded array types and dimensions match - type_1_expanded.eq(&type_2_expanded) && dimensions_1_expanded.eq(&dimensions_2_expanded) - } - - pub fn outer_dimension(&self, dimensions: &[usize]) -> Self { - let type_ = self.clone(); - - if dimensions.len() > 1 { - let next = dimensions[1..].to_vec(); - - return Type::Array(Box::new(type_), next); - } - - type_ - } - - pub fn inner_dimension(&self, dimensions: &[usize]) -> Self { - let type_ = self.clone(); - - if dimensions.len() > 1 { - let next = dimensions[..dimensions.len() - 1].to_vec(); - - return Type::Array(Box::new(type_), next); - } - - type_ - } -} - -fn expand_array_type(type_: &Type, dimensions: &[usize]) -> (Type, Vec) { - if let Type::Array(nested_type, nested_dimensions) = type_ { - // Expand nested array type - let mut expanded_dimensions = dimensions.to_vec(); - expanded_dimensions.append(&mut nested_dimensions.clone()); - - expand_array_type(nested_type, &expanded_dimensions) - } else { - // Array type is fully expanded - (type_.clone(), dimensions.to_vec()) - } -} - -/// pest ast -> Explicit Type for defining circuit members and function params - -impl From for Type { - fn from(data_type: DataType) -> Self { - match data_type { - DataType::Address(_type) => Type::Address, - DataType::Boolean(_type) => Type::Boolean, - DataType::Field(_type) => Type::Field, - DataType::Group(_type) => Type::Group, - DataType::Integer(_type) => Type::IntegerType(IntegerType::from(_type)), - } - } -} - -impl<'ast> From> for Type { - fn from(array_type: ArrayType<'ast>) -> Self { - let element_type = Box::new(Type::from(*array_type.type_)); - let dimensions = Expression::get_array_dimensions(array_type.dimensions); - - Type::Array(element_type, dimensions) - } -} - -impl<'ast> From> for Type { - fn from(tuple_type: TupleType<'ast>) -> Self { - let types = tuple_type.types.into_iter().map(Type::from).collect(); - - Type::Tuple(types) - } -} - -impl<'ast> From> for Type { - fn from(circuit_type: CircuitType<'ast>) -> Self { - Type::Circuit(Identifier::from(circuit_type.identifier)) - } -} - -impl<'ast> From> for Type { - fn from(type_: AstType<'ast>) -> Self { - match type_ { - AstType::Basic(type_) => Type::from(type_), - AstType::Array(type_) => Type::from(type_), - AstType::Tuple(type_) => Type::from(type_), - AstType::Circuit(type_) => Type::from(type_), - AstType::SelfType(_type) => Type::SelfType, - } - } -} - -/// input pest ast -> Explicit Type - -impl From for Type { - fn from(data_type: InputDataType) -> Self { - match data_type { - InputDataType::Address(_type) => Type::Address, - InputDataType::Boolean(_type) => Type::Boolean, - InputDataType::Field(_type) => Type::Field, - InputDataType::Group(_type) => Type::Group, - InputDataType::Integer(type_) => Type::IntegerType(IntegerType::from(type_)), - } - } -} - -impl<'ast> From> for Type { - fn from(array_type: InputArrayType<'ast>) -> Self { - let element_type = Box::new(Type::from(*array_type.type_)); - let dimensions = Expression::get_input_array_dimensions(array_type.dimensions); - - Type::Array(element_type, dimensions) - } -} - -impl<'ast> From> for Type { - fn from(tuple_type: InputTupleType<'ast>) -> Self { - let types = tuple_type.types_.into_iter().map(Type::from).collect(); - - Type::Tuple(types) - } -} - -impl<'ast> From> for Type { - fn from(type_: InputAstType<'ast>) -> Self { - match type_ { - InputAstType::Basic(type_) => Type::from(type_), - InputAstType::Array(type_) => Type::from(type_), - InputAstType::Tuple(type_) => Type::from(type_), - } - } -} - -impl fmt::Display for Type { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Type::Address => write!(f, "address"), - Type::Boolean => write!(f, "bool"), - Type::Field => write!(f, "field"), - Type::Group => write!(f, "group"), - Type::IntegerType(ref integer_type) => write!(f, "{}", integer_type), - Type::Circuit(ref variable) => write!(f, "circuit {}", variable), - Type::SelfType => write!(f, "SelfType"), - Type::Array(ref array, ref dimensions) => { - let dimensions = dimensions.iter().map(|x| x.to_string()).collect::>().join(", "); - write!(f, "[{}; ({})]", *array, dimensions) - } - Type::Tuple(ref tuple) => { - let types = tuple.iter().map(|x| x.to_string()).collect::>().join(", "); - - write!(f, "({})", types) - } - } - } -} diff --git a/typed/tests/serialization/json.rs b/typed/tests/serialization/json.rs deleted file mode 100644 index c952a8b992..0000000000 --- a/typed/tests/serialization/json.rs +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use leo_ast::LeoAst; -use leo_typed::LeoTypedAst; -#[cfg(not(feature = "ci_skip"))] -use leo_typed::Program; - -use std::path::{Path, PathBuf}; - -fn to_typed_ast(program_filepath: &Path) -> LeoTypedAst { - // Loads the Leo code as a string from the given file path. - let program_string = LeoAst::load_file(program_filepath).unwrap(); - - // Parses the Leo file and constructs an abstract syntax tree. - let ast = LeoAst::new(&program_filepath, &program_string).unwrap(); - - // Parse the abstract syntax tree and constructs a typed syntax tree. - LeoTypedAst::new("leo_typed_tree", &ast) -} - -#[test] -#[cfg(not(feature = "ci_skip"))] -fn test_serialize() { - // Construct a typed syntax tree from the given test file. - let typed_ast = { - let mut program_filepath = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - program_filepath.push("tests/serialization/main.leo"); - - to_typed_ast(&program_filepath) - }; - - // Serializes the typed syntax tree into JSON format. - let serialized_typed_ast: Program = - serde_json::from_value(serde_json::to_value(typed_ast.into_repr()).unwrap()).unwrap(); - - // Load the expected typed syntax tree. - let expected: Program = serde_json::from_str(include_str!("expected_typed_ast.json")).unwrap(); - - assert_eq!(expected, serialized_typed_ast); -} - -#[test] -#[cfg(not(feature = "ci_skip"))] -fn test_deserialize() { - // Load the expected typed syntax tree. - let expected_typed_ast = { - let mut program_filepath = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - program_filepath.push("tests/serialization/main.leo"); - - to_typed_ast(&program_filepath) - }; - - // Construct a typed syntax tree by deserializing a typed syntax tree JSON file. - let serialized_typed_ast = include_str!("expected_typed_ast.json"); - let typed_ast = LeoTypedAst::from_json_string(serialized_typed_ast).unwrap(); - - assert_eq!(expected_typed_ast, typed_ast); -} - -#[test] -fn test_serialize_deserialize_serialize() { - // Construct a typed syntax tree from the given test file. - let typed_ast = { - let mut program_filepath = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - program_filepath.push("tests/serialization/main.leo"); - - to_typed_ast(&program_filepath) - }; - - // Serializes the typed syntax tree into JSON format. - let serialized_typed_ast = typed_ast.to_json_string().unwrap(); - - // Deserializes the typed syntax tree into a LeoTypedAst. - let typed_ast = LeoTypedAst::from_json_string(&serialized_typed_ast).unwrap(); - - // Reserializes the typed syntax tree into JSON format. - let reserialized_typed_ast = typed_ast.to_json_string().unwrap(); - - assert_eq!(serialized_typed_ast, reserialized_typed_ast); -}