From 619ee7ecf668018394b5d6fe1f01f8921f56b9b7 Mon Sep 17 00:00:00 2001 From: Tarrence van As Date: Sun, 8 Jan 2023 12:01:12 -0500 Subject: [PATCH] dojo init --- .gitignore | 1 + Cargo.lock | 2473 +++++++++++++++++ Cargo.toml | 19 + clippy.toml | 1 + corelib/array.cairo | 8 + corelib/box.cairo | 6 + corelib/cairo_project.toml | 2 + corelib/debug.cairo | 7 + corelib/dict.cairo | 11 + corelib/ec.cairo | 10 + corelib/gas.cairo | 9 + corelib/hash.cairo | 3 + corelib/integer.cairo | 263 ++ corelib/lib.cairo | 227 ++ corelib/nullable.cairo | 7 + corelib/option.cairo | 1 + corelib/result.cairo | 1 + corelib/serde.cairo | 91 + corelib/starknet.cairo | 31 + corelib/test.cairo | 356 +++ corelib/traits.cairo | 2 + crates/cairo-lang-dojo/Cargo.toml | 35 + crates/cairo-lang-dojo/src/cli.rs | 32 + crates/cairo-lang-dojo/src/db.rs | 29 + crates/cairo-lang-dojo/src/lib.rs | 7 + crates/cairo-lang-dojo/src/plugin.rs | 694 +++++ crates/cairo-lang-dojo/src/plugin_test.rs | 58 + .../src/plugin_test_data/hello_starknet | 143 + rustfmt.toml | 33 + 29 files changed, 4560 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 clippy.toml create mode 100644 corelib/array.cairo create mode 100644 corelib/box.cairo create mode 100644 corelib/cairo_project.toml create mode 100644 corelib/debug.cairo create mode 100644 corelib/dict.cairo create mode 100644 corelib/ec.cairo create mode 100644 corelib/gas.cairo create mode 100644 corelib/hash.cairo create mode 100644 corelib/integer.cairo create mode 100644 corelib/lib.cairo create mode 100644 corelib/nullable.cairo create mode 100644 corelib/option.cairo create mode 100644 corelib/result.cairo create mode 100644 corelib/serde.cairo create mode 100644 corelib/starknet.cairo create mode 100644 corelib/test.cairo create mode 100644 corelib/traits.cairo create mode 100644 crates/cairo-lang-dojo/Cargo.toml create mode 100644 crates/cairo-lang-dojo/src/cli.rs create mode 100644 crates/cairo-lang-dojo/src/db.rs create mode 100644 crates/cairo-lang-dojo/src/lib.rs create mode 100644 crates/cairo-lang-dojo/src/plugin.rs create mode 100644 crates/cairo-lang-dojo/src/plugin_test.rs create mode 100644 crates/cairo-lang-dojo/src/plugin_test_data/hello_starknet create mode 100644 rustfmt.toml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..ea8c4bf7f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000000..a80f8f3551 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2473 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" + +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits 0.2.15", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.0-alpha.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cf4b42c978bd9b967f6a2ba54a4cc57f34780f9d0cf86916f8f7e922b4f80fe" +dependencies = [ + "ark-ff-asm 0.4.0-alpha.7", + "ark-ff-macros 0.4.0-alpha.7", + "ark-serialize 0.4.0-alpha.7", + "ark-std 0.4.0-alpha", + "derivative", + "digest 0.10.6", + "itertools", + "num-bigint", + "num-traits 0.2.15", + "paste", + "rustc_version 0.4.0", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.0-alpha.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3ba0a3cf584a8ede533a1749b86040e9018cf752265fc39a71c69fe1fafaba5" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits 0.2.15", + "quote", + "syn", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.0-alpha.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9989a01ec42d2f31232796831077ef730d4cd0d0931f5ef6962a43ebddd215fa" +dependencies = [ + "num-bigint", + "num-traits 0.2.15", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + +[[package]] +name = "ark-serialize" +version = "0.4.0-alpha.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84aeb60f7c6792ae71e9e2225412ecd59d7c85cfec4183a8c497f2a3a4cdb36e" +dependencies = [ + "ark-std 0.4.0-alpha", + "digest 0.10.6", + "num-bigint", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits 0.2.15", + "rand", +] + +[[package]] +name = "ark-std" +version = "0.4.0-alpha" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc5b16d734e9b2e43886ff586755219df7fb9639cc04ab00c7e636708a5ba06a" +dependencies = [ + "num-traits 0.2.15", + "rand", +] + +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term", +] + +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bigdecimal" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aaf33151a6429fe9211d1b276eafdf70cdff28b071e76c0b0e1503221ea3744" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits 0.2.15", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" + +[[package]] +name = "cairo-lang-casm" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "ark-ff 0.4.0-alpha.7", + "ark-std 0.3.0", + "cairo-lang-utils", + "cairo-vm", + "indoc", + "num-bigint", + "num-traits 0.2.15", + "thiserror", +] + +[[package]] +name = "cairo-lang-compiler" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "anyhow", + "cairo-lang-defs", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-lowering", + "cairo-lang-parser", + "cairo-lang-plugins", + "cairo-lang-project", + "cairo-lang-semantic", + "cairo-lang-sierra", + "cairo-lang-sierra-generator", + "cairo-lang-syntax", + "cairo-lang-utils", + "clap 4.0.29", + "log", + "salsa", + "thiserror", +] + +[[package]] +name = "cairo-lang-debug" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" + +[[package]] +name = "cairo-lang-defs" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "cairo-lang-debug", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-parser", + "cairo-lang-syntax", + "cairo-lang-utils", + "indexmap", + "itertools", + "salsa", + "smol_str", + "thiserror", +] + +[[package]] +name = "cairo-lang-diagnostics" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "cairo-lang-filesystem", + "cairo-lang-utils", + "itertools", + "salsa", +] + +[[package]] +name = "cairo-lang-dojo" +version = "0.1.0" +dependencies = [ + "anyhow", + "cairo-lang-defs", + "cairo-lang-diagnostics", + "cairo-lang-parser", + "cairo-lang-semantic", + "cairo-lang-starknet", + "cairo-lang-syntax", + "cairo-lang-test-utils", + "cairo-lang-utils", + "clap 4.0.29", + "env_logger", + "indoc", + "serde", + "serde_json", + "test-case", + "test-case-macros", + "test-log", +] + +[[package]] +name = "cairo-lang-eq-solver" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "cairo-lang-utils", + "good_lp", + "itertools", +] + +[[package]] +name = "cairo-lang-filesystem" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "cairo-lang-debug", + "cairo-lang-project", + "cairo-lang-utils", + "path-clean", + "salsa", + "smol_str", +] + +[[package]] +name = "cairo-lang-lowering" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "cairo-lang-debug", + "cairo-lang-defs", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-parser", + "cairo-lang-proc-macros", + "cairo-lang-semantic", + "cairo-lang-syntax", + "cairo-lang-utils", + "id-arena", + "itertools", + "log", + "num-bigint", + "num-traits 0.2.15", + "salsa", + "smol_str", +] + +[[package]] +name = "cairo-lang-parser" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-syntax", + "cairo-lang-syntax-codegen", + "cairo-lang-utils", + "colored", + "itertools", + "log", + "salsa", + "smol_str", +] + +[[package]] +name = "cairo-lang-plugins" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "cairo-lang-defs", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-parser", + "cairo-lang-semantic", + "cairo-lang-syntax", + "cairo-lang-utils", + "indoc", + "itertools", + "pretty_assertions", + "salsa", + "smol_str", +] + +[[package]] +name = "cairo-lang-proc-macros" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "cairo-lang-debug", + "quote", + "syn", +] + +[[package]] +name = "cairo-lang-project" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "serde", + "smol_str", + "thiserror", + "toml", +] + +[[package]] +name = "cairo-lang-semantic" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "cairo-lang-debug", + "cairo-lang-defs", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-parser", + "cairo-lang-proc-macros", + "cairo-lang-syntax", + "cairo-lang-utils", + "id-arena", + "itertools", + "num-bigint", + "num-traits 0.2.15", + "pretty_assertions", + "salsa", + "smol_str", + "unescaper", +] + +[[package]] +name = "cairo-lang-sierra" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "cairo-lang-utils", + "const-fnv1a-hash", + "convert_case", + "derivative", + "itertools", + "lalrpop", + "lalrpop-util", + "num-bigint", + "num-traits 0.2.15", + "regex", + "salsa", + "serde", + "smol_str", + "thiserror", +] + +[[package]] +name = "cairo-lang-sierra-ap-change" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "cairo-lang-eq-solver", + "cairo-lang-sierra", + "cairo-lang-utils", + "itertools", + "thiserror", +] + +[[package]] +name = "cairo-lang-sierra-gas" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "cairo-lang-eq-solver", + "cairo-lang-sierra", + "cairo-lang-utils", + "itertools", + "thiserror", +] + +[[package]] +name = "cairo-lang-sierra-generator" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "cairo-lang-debug", + "cairo-lang-defs", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-lowering", + "cairo-lang-parser", + "cairo-lang-plugins", + "cairo-lang-proc-macros", + "cairo-lang-semantic", + "cairo-lang-sierra", + "cairo-lang-syntax", + "cairo-lang-utils", + "id-arena", + "itertools", + "num-bigint", + "salsa", + "smol_str", +] + +[[package]] +name = "cairo-lang-sierra-to-casm" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "assert_matches", + "cairo-lang-casm", + "cairo-lang-sierra", + "cairo-lang-sierra-ap-change", + "cairo-lang-sierra-gas", + "cairo-lang-utils", + "clap 4.0.29", + "itertools", + "log", + "num-bigint", + "num-traits 0.2.15", + "thiserror", +] + +[[package]] +name = "cairo-lang-starknet" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "anyhow", + "cairo-lang-compiler", + "cairo-lang-defs", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-lowering", + "cairo-lang-parser", + "cairo-lang-plugins", + "cairo-lang-semantic", + "cairo-lang-sierra", + "cairo-lang-sierra-ap-change", + "cairo-lang-sierra-gas", + "cairo-lang-sierra-generator", + "cairo-lang-sierra-to-casm", + "cairo-lang-syntax", + "cairo-lang-utils", + "clap 4.0.29", + "convert_case", + "genco", + "indoc", + "itertools", + "log", + "num-bigint", + "num-integer", + "num-traits 0.2.15", + "serde", + "serde_json", + "sha3", + "smol_str", + "thiserror", +] + +[[package]] +name = "cairo-lang-syntax" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "cairo-lang-debug", + "cairo-lang-filesystem", + "cairo-lang-utils", + "salsa", + "smol_str", +] + +[[package]] +name = "cairo-lang-syntax-codegen" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "cairo-lang-utils", + "genco", + "log", + "xshell", +] + +[[package]] +name = "cairo-lang-test-utils" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "cairo-lang-utils", + "env_logger", + "log", + "pretty_assertions", +] + +[[package]] +name = "cairo-lang-utils" +version = "0.1.0" +source = "git+https://github.com/starkware-libs/cairo.git#426a2e97734faca2f23c5961963fddf1ce963035" +dependencies = [ + "chrono", + "env_logger", + "indexmap", + "itertools", + "log", + "num-bigint", +] + +[[package]] +name = "cairo-vm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0db448207a281d6ec29c4de24422fba5d52f0a0b9424dd7a758d995f5a89e40e" +dependencies = [ + "bincode", + "clap 3.2.23", + "generic-array", + "hex", + "keccak", + "lazy_static", + "mimalloc", + "nom", + "num-bigint", + "num-integer", + "num-traits 0.2.15", + "parse-hyperlinks", + "rand_core", + "serde", + "serde_bytes", + "serde_json", + "sha2 0.10.6", + "sha3", + "starknet-crypto", + "thiserror", +] + +[[package]] +name = "cc" +version = "1.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits 0.2.15", + "time", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "clap" +version = "3.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +dependencies = [ + "atty", + "bitflags", + "clap_derive 3.2.18", + "clap_lex 0.2.4", + "indexmap", + "once_cell", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap" +version = "4.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d63b9e9c07271b9957ad22c173bae2a4d9a81127680962039296abcd2f8251d" +dependencies = [ + "bitflags", + "clap_derive 4.0.21", + "clap_lex 0.3.0", + "is-terminal", + "once_cell", + "strsim", + "termcolor", +] + +[[package]] +name = "clap_derive" +version = "3.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" +dependencies = [ + "heck 0.4.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_derive" +version = "4.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014" +dependencies = [ + "heck 0.4.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "clap_lex" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "colored" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + +[[package]] +name = "const-fnv1a-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b13ea120a812beba79e34316b3942a857c86ec1593cb34f27bb28272ce2cca" + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "ctor" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "cxx" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdf07d07d6531bfcdbe9b8b739b104610c6508dcc4d63b410585faf338241daf" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2eb5b96ecdc99f72657332953d4d9c50135af1bac34277801cc3937906ebd39" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac040a39517fd1674e0f32177648334b0f4074625b5588a64519804ba0553b12" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1362b0ddcfc4eb0a1f57b68bd77dd99f0e826958a96abd0ae9bd092e114ffed6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +dependencies = [ + "block-buffer 0.10.3", + "crypto-common", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "either" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + +[[package]] +name = "ena" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3" +dependencies = [ + "log", +] + +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "genco" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8598ff0782dbc5231cf9eb727c1c5e398515b7b62ee68761c2c73950a1de1f4" +dependencies = [ + "genco-macros", + "relative-path", + "smallvec", +] + +[[package]] +name = "genco-macros" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40803f2757f84c877f088e62420931f6e05a72514f1f03630384aa30b91d667b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "good_lp" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b51d78cbb7b734379eea7f811ddb33b2b13defefa1dab50068d7bc7f781a3056" +dependencies = [ + "fnv", + "minilp", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + +[[package]] +name = "html-escape" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476" +dependencies = [ + "utf8-width", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "indoc" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adab1eaa3408fb7f0c777a73e7465fd5656136fc93b670eb6df3c88c2c1344e3" + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "is-terminal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927609f78c2913a6f6ac3c27a4fe87f43e2a35367c0c4b0f8265e8f49a104330" +dependencies = [ + "hermit-abi 0.2.6", + "io-lifetimes", + "rustix", + "windows-sys", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" + +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lalrpop" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b30455341b0e18f276fa64540aff54deafb54c589de6aca68659c63dd2d5d823" +dependencies = [ + "ascii-canvas", + "atty", + "bit-set", + "diff", + "ena", + "itertools", + "lalrpop-util", + "petgraph", + "pico-args", + "regex", + "regex-syntax", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", +] + +[[package]] +name = "lalrpop-util" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf796c978e9b4d983414f4caedc9273aa33ee214c5b887bd55fde84c85d2dc4" +dependencies = [ + "regex", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.138" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" + +[[package]] +name = "libmimalloc-sys" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04d1c67deb83e6b75fa4fe3309e09cfeade12e7721d95322af500d3814ea60c9" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "link-cplusplus" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +dependencies = [ + "cc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "matrixmultiply" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "916806ba0031cd542105d916a97c8572e1fa6dd79c9c51e7eb43a09ec2dd84c1" +dependencies = [ + "rawpointer", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "mimalloc" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2374e2999959a7b583e1811a1ddbf1d3a4b9496eceb9746f1192a59d871eca" +dependencies = [ + "libmimalloc-sys", +] + +[[package]] +name = "minilp" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82a7750a9e5076c660b7bec5e6457b4dbff402b9863c8d112891434e18fd5385" +dependencies = [ + "log", + "sprs", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "ndarray" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac06db03ec2f46ee0ecdca1a1c34a99c0d188a0d83439b84bf0cb4b386e4ab09" +dependencies = [ + "matrixmultiply", + "num-complex", + "num-integer", + "num-traits 0.2.15", + "rawpointer", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[package]] +name = "nom" +version = "7.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits 0.2.15", + "serde", +] + +[[package]] +name = "num-complex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +dependencies = [ + "autocfg", + "num-traits 0.2.15", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits 0.2.15", +] + +[[package]] +name = "num-traits" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" +dependencies = [ + "num-traits 0.2.15", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" + +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "os_str_bytes" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" + +[[package]] +name = "output_vt100" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" +dependencies = [ + "winapi", +] + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.5", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "parse-hyperlinks" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0181d37c4d5ae35cc8be7cf823c1a933005661da6a08bcb2855aa392c9a54b8e" +dependencies = [ + "html-escape", + "nom", + "percent-encoding", + "thiserror", +] + +[[package]] +name = "paste" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1c2c742266c2f1041c914ba65355a83ae8747b05f208319784083583494b4b" + +[[package]] +name = "path-clean" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecba01bf2678719532c5e3059e0b5f0811273d94b397088b82e3bd0a78c78fdd" + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "pest" +version = "2.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc8bed3549e0f9b0a2a78bf7c0018237a2cdf085eecbbc048e52612438e4e9d0" +dependencies = [ + "thiserror", + "ucd-trie", +] + +[[package]] +name = "petgraph" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pico-args" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "pretty_assertions" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" +dependencies = [ + "ctor", + "diff", + "output_vt100", + "yansi", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + +[[package]] +name = "relative-path" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0df32d82cedd1499386877b062ebe8721f806de80b08d183c70184ef17dd1d42" + +[[package]] +name = "rfc6979" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525" +dependencies = [ + "crypto-bigint", + "hmac", + "zeroize", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.16", +] + +[[package]] +name = "rustix" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rustversion" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" + +[[package]] +name = "ryu" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" + +[[package]] +name = "salsa" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b84d9f96071f3f3be0dc818eae3327625d8ebc95b58da37d6850724f31d3403" +dependencies = [ + "crossbeam-utils", + "indexmap", + "lock_api", + "log", + "oorandom", + "parking_lot 0.11.2", + "rustc-hash", + "salsa-macros", + "smallvec", +] + +[[package]] +name = "salsa-macros" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3904a4ba0a9d0211816177fd34b04c7095443f8cdacd11175064fe541c8fe2" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "scratch" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + +[[package]] +name = "serde" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e326c9ec8042f1b5da33252c8a37e9ffbd2c9bef0155215b6e6c80c790e05f91" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42a3df25b0713732468deadad63ab9da1f1fd75a48a15024b50363f128db627e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.6", +] + +[[package]] +name = "sha3" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9" +dependencies = [ + "digest 0.10.6", + "keccak", +] + +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "smol_str" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7475118a28b7e3a2e157ce0131ba8c5526ea96e90ee601d9f6bb2e286a35ab44" +dependencies = [ + "serde", +] + +[[package]] +name = "sprs" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec63571489873d4506683915840eeb1bb16b3198ee4894cc6f2fe3013d505e56" +dependencies = [ + "ndarray", + "num-complex", + "num-traits 0.1.43", +] + +[[package]] +name = "starknet-crypto" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be7d6b2c959fde2a10dbc31d54bdd0307eecb7ef6c05c23a0263e65b57b3e18a" +dependencies = [ + "crypto-bigint", + "hex", + "hmac", + "num-bigint", + "num-integer", + "num-traits 0.2.15", + "rfc6979", + "sha2 0.9.9", + "starknet-crypto-codegen", + "starknet-curve", + "starknet-ff", + "thiserror", + "zeroize", +] + +[[package]] +name = "starknet-crypto-codegen" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6569d70430f0f6edc41f6820d00acf63356e6308046ca01e57eeac22ad258c47" +dependencies = [ + "starknet-curve", + "starknet-ff", + "syn", +] + +[[package]] +name = "starknet-curve" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84be6079d3060fdbd8b5335574fef3d3783fa2f7ee6474d08ae0c1e4b0a29ba4" +dependencies = [ + "starknet-ff", +] + +[[package]] +name = "starknet-ff" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5874510620214ebeac50915b01d67437d8ca10a6682b1de85b93cd01157b58eb" +dependencies = [ + "ark-ff 0.3.0", + "bigdecimal", + "crypto-bigint", + "getrandom", + "hex", + "num-bigint", + "serde", + "thiserror", +] + +[[package]] +name = "string_cache" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot 0.12.1", + "phf_shared", + "precomputed-hash", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "test-case" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21d6cf5a7dffb3f9dceec8e6b8ca528d9bd71d36c9f074defb548ce161f598c0" +dependencies = [ + "test-case-macros", +] + +[[package]] +name = "test-case-macros" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e45b7bf6e19353ddd832745c8fcf77a17a93171df7151187f26623f2b75b5b26" +dependencies = [ + "cfg-if", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "test-log" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f0c854faeb68a048f0f2dc410c5ddae3bf83854ef0e4977d58306a5edef50e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + +[[package]] +name = "thiserror" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +dependencies = [ + "serde", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "ucd-trie" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" + +[[package]] +name = "unescaper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "995483205de764db1185c9461a000fff73fa4b9ee2bbe4c8b4027a94692700fe" +dependencies = [ + "thiserror", +] + +[[package]] +name = "unicode-ident" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" + +[[package]] +name = "unicode-segmentation" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "utf8-width" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + +[[package]] +name = "xshell" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d47097dc5c85234b1e41851b3422dd6d19b3befdd35b4ae5ce386724aeca981" +dependencies = [ + "xshell-macros", +] + +[[package]] +name = "xshell-macros" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88301b56c26dd9bf5c43d858538f82d6f3f7764767defbc5d34e59459901c41a" + +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + +[[package]] +name = "zeroize" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000000..9bb99eb349 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,19 @@ +[workspace] + +members = [ + "crates/cairo-lang-dojo" +] + +[workspace.package] +version = "0.1.0" +edition = "2021" +repository = "https://github.com/dojo-on-chain/dojo/" +license = "Apache-2.0" +license-file = "LICENSE" + +[workspace.dependencies] +env_logger = "0.9.3" +indoc = "1.0.7" +serde = { version = "1.0.130", features = ["derive"] } +serde_json = "1.0" +test-log = "0.2.11" diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 0000000000..c117dd79fb --- /dev/null +++ b/clippy.toml @@ -0,0 +1 @@ +enum-variant-name-threshold = 1 diff --git a/corelib/array.cairo b/corelib/array.cairo new file mode 100644 index 0000000000..9f43e3b712 --- /dev/null +++ b/corelib/array.cairo @@ -0,0 +1,8 @@ +extern type Array; +extern fn array_new() -> Array:: nopanic; +extern fn array_append(ref arr: Array::, value: T) nopanic; +extern fn array_pop_front(ref arr: Array::) -> Option:: nopanic; +extern fn array_at( + ref arr: Array::, index: u128 +) -> Option:: implicits(RangeCheck) nopanic; +extern fn array_len(ref arr: Array::) -> u128 nopanic; diff --git a/corelib/box.cairo b/corelib/box.cairo new file mode 100644 index 0000000000..5eed438eae --- /dev/null +++ b/corelib/box.cairo @@ -0,0 +1,6 @@ +extern type Box; +impl BoxFeltCopy of Copy::>; +impl BoxFeltDrop of Drop::>; + +extern fn into_box(value: T) -> Box:: nopanic; +extern fn unbox(box: Box::) -> T nopanic; diff --git a/corelib/cairo_project.toml b/corelib/cairo_project.toml new file mode 100644 index 0000000000..67cd29d47b --- /dev/null +++ b/corelib/cairo_project.toml @@ -0,0 +1,2 @@ +[crate_roots] +core = "." diff --git a/corelib/debug.cairo b/corelib/debug.cairo new file mode 100644 index 0000000000..c9ebf80284 --- /dev/null +++ b/corelib/debug.cairo @@ -0,0 +1,7 @@ +extern fn print(message: Array::) nopanic; + +fn print_felt(message: felt) { + let mut arr = array_new::(); + array_append::(arr, message); + print(arr); +} diff --git a/corelib/dict.cairo b/corelib/dict.cairo new file mode 100644 index 0000000000..9f07806167 --- /dev/null +++ b/corelib/dict.cairo @@ -0,0 +1,11 @@ +extern type DictManager; +extern type DictFeltTo; +extern type SquashedDictFeltTo; +impl SquashedDictFeltToFeltDrop of Drop::>; + +extern fn dict_felt_to_new() -> DictFeltTo:: implicits(DictManager) nopanic; +extern fn dict_felt_to_write(ref dict: DictFeltTo::, key: felt, value: T) nopanic; +extern fn dict_felt_to_read(ref dict: DictFeltTo::, key: felt) -> T nopanic; +extern fn dict_felt_to_squash( + dict: DictFeltTo:: +) -> SquashedDictFeltTo:: implicits(RangeCheck, DictManager) nopanic; diff --git a/corelib/ec.cairo b/corelib/ec.cairo new file mode 100644 index 0000000000..422e4435e9 --- /dev/null +++ b/corelib/ec.cairo @@ -0,0 +1,10 @@ +#[derive(Copy, Drop)] +extern type EcPoint; +#[derive(Copy, Drop)] +extern type EcState; + +#[panic_with('not on EC', ec_point_from_felts)] +extern fn ec_point_try_create(x: felt, y: felt) -> Option:: nopanic; +extern fn ec_point_unwrap(p: EcPoint) -> (felt, felt) nopanic; +extern fn ec_init_state() -> EcState nopanic; +extern fn ec_add_to_state(s: EcState, p: EcPoint) -> EcState nopanic; diff --git a/corelib/gas.cairo b/corelib/gas.cairo new file mode 100644 index 0000000000..3a675ce3a0 --- /dev/null +++ b/corelib/gas.cairo @@ -0,0 +1,9 @@ +#[derive(Copy, Drop)] +extern type BuiltinCosts; +extern type GasBuiltin; + +extern fn get_gas() -> Option::<()> implicits(RangeCheck, GasBuiltin) nopanic; +extern fn get_gas_all( + costs: BuiltinCosts +) -> Option::<()> implicits(RangeCheck, GasBuiltin) nopanic; +extern fn get_builtin_costs() -> BuiltinCosts nopanic; diff --git a/corelib/hash.cairo b/corelib/hash.cairo new file mode 100644 index 0000000000..30a73743ca --- /dev/null +++ b/corelib/hash.cairo @@ -0,0 +1,3 @@ +extern type Pedersen; + +extern fn pedersen(a: felt, b: felt) -> felt implicits(Pedersen) nopanic; diff --git a/corelib/integer.cairo b/corelib/integer.cairo new file mode 100644 index 0000000000..bef60469f4 --- /dev/null +++ b/corelib/integer.cairo @@ -0,0 +1,263 @@ +#[derive(Copy, Drop)] +extern type u128; +extern fn u128_const() -> u128 nopanic; + +enum U128sFromFeltResult { Narrow: u128, Wide: (u128, u128), } +extern fn u128s_from_felt(a: felt) -> U128sFromFeltResult implicits(RangeCheck) nopanic; + +#[panic_with('u128_from OF', u128_from_felt)] +fn u128_try_from_felt(a: felt) -> Option:: implicits(RangeCheck) nopanic { + match u128s_from_felt(a) { + U128sFromFeltResult::Narrow(x) => Option::::Some(x), + U128sFromFeltResult::Wide(x) => Option::::None(()), + } +} + +extern fn u128_to_felt(a: u128) -> felt nopanic; + +extern fn u128_overflow_add( + a: u128, b: u128 +) -> Result:: implicits(RangeCheck) nopanic; +extern fn u128_overflow_sub( + a: u128, b: u128 +) -> Result:: implicits(RangeCheck) nopanic; + +fn u128_wrapping_add(a: u128, b: u128) -> u128 implicits(RangeCheck) nopanic { + match u128_overflow_add(a, b) { + Result::Ok(x) => x, + Result::Err(x) => x, + } +} + +extern fn u128_wide_mul(a: u128, b: u128) -> (u128, u128) implicits(RangeCheck) nopanic; + +fn u128_overflow_mul(a: u128, b: u128) -> (u128, bool) implicits(RangeCheck) nopanic { + let (top_word, bottom_word) = u128_wide_mul(a, b); + match u128_to_felt(top_word) { + 0 => (bottom_word, false), + _ => (bottom_word, true), + } +} + +#[panic_with('u128_add OF', u128_add)] +fn u128_checked_add(a: u128, b: u128) -> Option:: implicits(RangeCheck) nopanic { + match u128_overflow_add(a, b) { + Result::Ok(r) => Option::::Some(r), + Result::Err(r) => Option::::None(()), + } +} + +#[panic_with('u128_sub OF', u128_sub)] +fn u128_checked_sub(a: u128, b: u128) -> Option:: implicits(RangeCheck) nopanic { + match u128_overflow_sub(a, b) { + Result::Ok(r) => Option::::Some(r), + Result::Err(r) => Option::::None(()), + } +} + +#[panic_with('u128_mul OF', u128_mul)] +fn u128_checked_mul(a: u128, b: u128) -> Option:: implicits(RangeCheck) nopanic { + let (top_word, bottom_word) = u128_wide_mul(a, b); + match u128_to_felt(top_word) { + 0 => Option::::Some(bottom_word), + _ => Option::::None(()), + } +} + +impl NonZeroU128Copy of Copy::>; +impl NonZeroU128Drop of Drop::>; + +#[panic_with('u128 is 0', u128_as_non_zero)] +fn u128_checked_as_non_zero(a: u128) -> Option::> implicits() nopanic { + match u128_jump_nz(a) { + JumpNzResult::Zero(()) => Option::>::None(()), + JumpNzResult::NonZero(x) => Option::>::Some(x), + } +} + +fn u128_safe_div(a: u128, b: NonZero::) -> u128 implicits(RangeCheck) nopanic { + let (q, r) = u128_safe_divmod(a, b); + q +} + +fn u128_div(a: u128, b: u128) -> u128 implicits(RangeCheck) { + u128_safe_div(a, u128_as_non_zero(b)) +} + +fn u128_safe_mod(a: u128, b: NonZero::) -> u128 implicits(RangeCheck) nopanic { + let (q, r) = u128_safe_divmod(a, b); + r +} + +fn u128_mod(a: u128, b: u128) -> u128 implicits(RangeCheck) { + u128_safe_mod(a, u128_as_non_zero(b)) +} + +extern fn u128_safe_divmod( + a: u128, b: NonZero:: + ) -> ( + u128, u128 +) implicits(RangeCheck) nopanic; + +extern fn u128_lt(a: u128, b: u128) -> bool implicits(RangeCheck) nopanic; +extern fn u128_eq(a: u128, b: u128) -> bool implicits() nopanic; +extern fn u128_le(a: u128, b: u128) -> bool implicits(RangeCheck) nopanic; + +fn u128_gt(a: u128, b: u128) -> bool implicits(RangeCheck) nopanic { + u128_lt(b, a) +} + +fn u128_ge(a: u128, b: u128) -> bool implicits(RangeCheck) nopanic { + u128_le(b, a) +} + +fn u128_ne(a: u128, b: u128) -> bool implicits() nopanic { + !(a == b) +} + +extern type Bitwise; +extern fn bitwise(a: u128, b: u128) -> (u128, u128, u128) implicits(Bitwise) nopanic; +fn u128_and(a: u128, b: u128) -> u128 implicits(Bitwise) nopanic { + let (v, _, _) = bitwise(a, b); + v +} +fn u128_xor(a: u128, b: u128) -> u128 implicits(Bitwise) nopanic { + let (_, v, _) = bitwise(a, b); + v +} +fn u128_or(a: u128, b: u128) -> u128 implicits(Bitwise) nopanic { + let (_, _, v) = bitwise(a, b); + v +} + +extern fn u128_jump_nz(a: u128) -> JumpNzResult:: implicits() nopanic; + +#[derive(Copy, Drop)] +struct u256 { low: u128, high: u128, } + +fn u256_overflow_add(a: u256, b: u256) -> (u256, bool) implicits(RangeCheck) nopanic { + let (high, overflow) = match u128_overflow_add(a.high, b.high) { + Result::Ok(high) => (high, false), + Result::Err(high) => (high, true), + }; + match u128_overflow_add(a.low, b.low) { + Result::Ok(low) => (u256 { low, high }, overflow), + Result::Err(low) => { + match u128_overflow_add(high, 1_u128) { + Result::Ok(high) => (u256 { low, high }, overflow), + Result::Err(high) => (u256 { low, high }, true), + } + }, + } +} + +fn u256_overflow_sub(a: u256, b: u256) -> (u256, bool) implicits(RangeCheck) nopanic { + let (high, overflow) = match u128_overflow_sub(a.high, b.high) { + Result::Ok(high) => (high, false), + Result::Err(high) => (high, true), + }; + match u128_overflow_sub(a.low, b.low) { + Result::Ok(low) => (u256 { low, high }, overflow), + Result::Err(low) => { + match u128_overflow_sub(high, 1_u128) { + Result::Ok(high) => (u256 { low, high }, overflow), + Result::Err(high) => (u256 { low, high }, true), + } + }, + } +} + +fn u256_overflow_mul(a: u256, b: u256) -> (u256, bool) nopanic { + let (high1, low) = u128_wide_mul(a.low, b.low); + let (overflow_value1, high2) = u128_wide_mul(a.low, b.high); + let (overflow_value2, high3) = u128_wide_mul(a.high, b.low); + let (high, overflow) = match u128_overflow_add(high1, high2) { + Result::Ok(high) => ( + high, + overflow_value1 != 0_u128 | overflow_value2 != 0_u128 | (a.high > 0_u128 & b.high > 0_u128) + ), + Result::Err(high) => (high, true), + }; + let (high, overflow) = match u128_overflow_add(high, high3) { + Result::Ok(high) => (high, overflow), + Result::Err(high) => (high, true), + }; + (u256 { low, high }, overflow) +} + +#[panic_with('u256_add OF', u256_add)] +fn u256_checked_add(a: u256, b: u256) -> Option:: implicits(RangeCheck) nopanic { + let (r, overflow) = u256_overflow_add(a, b); + if overflow { + Option::::None(()) + } else { + Option::::Some(r) + } +} + +#[panic_with('u256_sub OF', u256_sub)] +fn u256_checked_sub(a: u256, b: u256) -> Option:: implicits(RangeCheck) nopanic { + let (r, overflow) = u256_overflow_sub(a, b); + if overflow { + Option::::None(()) + } else { + Option::::Some(r) + } +} + +#[panic_with('u256_mul OF', u256_mul)] +fn u256_checked_mul(a: u256, b: u256) -> Option:: implicits(RangeCheck) nopanic { + let (r, overflow) = u256_overflow_mul(a, b); + if overflow { + Option::::None(()) + } else { + Option::::Some(r) + } +} + +fn u256_eq(a: u256, b: u256) -> bool implicits() { + a.low == b.low & a.high == b.high +} + +fn u256_ne(a: u256, b: u256) -> bool implicits() { + !(a == b) +} + +fn u256_lt(a: u256, b: u256) -> bool implicits(RangeCheck) nopanic { + if a.high < b.high { + true + } else if a.high == b.high { + a.low < b.low + } else { + false + } +} + +fn u256_le(a: u256, b: u256) -> bool implicits(RangeCheck) nopanic { + !u256_lt(b, a) +} + +fn u256_gt(a: u256, b: u256) -> bool implicits(RangeCheck) nopanic { + u256_lt(b, a) +} + +fn u256_ge(a: u256, b: u256) -> bool implicits(RangeCheck) nopanic { + !u256_lt(a, b) +} + +fn u256_and(a: u256, b: u256) -> u256 implicits(Bitwise) nopanic { + u256 { low: a.low & b.low, high: a.high & b.high } +} +fn u256_or(a: u256, b: u256) -> u256 implicits(Bitwise) nopanic { + u256 { low: a.low | b.low, high: a.high | b.high } +} +fn u256_xor(a: u256, b: u256) -> u256 implicits(Bitwise) nopanic { + u256 { low: a.low ^ b.low, high: a.high ^ b.high } +} + +fn u256_from_felt(a: felt) -> u256 implicits(RangeCheck) nopanic { + match u128s_from_felt(a) { + U128sFromFeltResult::Narrow(low) => u256 { low, high: 0_u128 }, + U128sFromFeltResult::Wide((high, low)) => u256 { low, high }, + } +} diff --git a/corelib/lib.cairo b/corelib/lib.cairo new file mode 100644 index 0000000000..e78502cabb --- /dev/null +++ b/corelib/lib.cairo @@ -0,0 +1,227 @@ +mod traits; +use traits::Copy; +use traits::Drop; + +#[derive(Copy, Drop)] +enum bool { False: (), True: (), } + +extern fn bool_and_impl(a: bool, b: bool) -> (bool,) implicits() nopanic; +fn bool_and(a: bool, b: bool) -> bool implicits() nopanic { + let (r,) = bool_and_impl(a, b); + r +} + +// TODO(orizi): Change to extern when added. +fn bool_or(a: bool, b: bool) -> bool implicits() nopanic { + match a { + bool::False(x) => b, + bool::True(x) => bool::True(()), + } +} + +extern fn bool_not_impl(a: bool) -> (bool,) implicits() nopanic; +fn bool_not(a: bool) -> bool implicits() nopanic { + let (r,) = bool_not_impl(a); + r +} + +extern fn bool_xor_impl(a: bool, b: bool) -> (bool,) implicits() nopanic; +fn bool_xor(a: bool, b: bool) -> bool implicits() nopanic { + let (r,) = bool_xor_impl(a, b); + r +} + +extern fn bool_eq(a: bool, b: bool) -> bool implicits() nopanic; + +fn bool_ne(a: bool, b: bool) -> bool implicits() nopanic { + !(a == b) +} + +// Felt. +extern type RangeCheck; + +#[derive(Copy, Drop)] +extern type felt; +extern fn felt_const() -> felt nopanic; + +// TODO(spapini): Make unnamed. +impl FeltCopy of Copy::; +impl FeltDrop of Drop::; + +extern fn felt_add(a: felt, b: felt) -> felt nopanic; +extern fn felt_sub(a: felt, b: felt) -> felt nopanic; +extern fn felt_mul(a: felt, b: felt) -> felt nopanic; +fn felt_neg(a: felt) -> felt nopanic { + a * felt_const::<-1>() +} + +extern type NonZero; +// TODO(spapini): Add generic impls for NonZero for Copy, Drop. +enum JumpNzResult { Zero: (), NonZero: NonZero::, } +extern fn unwrap_nz(a: NonZero::) -> T nopanic; + +impl NonZeroFeltCopy of Copy::>; +impl NonZeroFeltDrop of Drop::>; +extern fn felt_div(a: felt, b: NonZero::) -> felt nopanic; + +// TODO(orizi): Change to extern when added. +fn felt_eq(a: felt, b: felt) -> bool nopanic { + match a - b { + 0 => bool::True(()), + _ => bool::False(()), + } +} +fn felt_ne(a: felt, b: felt) -> bool nopanic { + !(a == b) +} + +fn felt_lt(a: felt, b: felt) -> bool implicits(RangeCheck) { + u256_from_felt(a) < u256_from_felt(b) +} + +fn felt_gt(a: felt, b: felt) -> bool implicits(RangeCheck) { + b < a +} + +fn felt_le(a: felt, b: felt) -> bool implicits(RangeCheck) { + !(b < a) +} + +fn felt_ge(a: felt, b: felt) -> bool implicits(RangeCheck) { + !(a < b) +} + +extern fn felt_jump_nz(a: felt) -> JumpNzResult:: nopanic; + +// TODO(spapini): Constraint using Copy and Drop traits. +extern fn dup(obj: T) -> (T, T) nopanic; +extern fn drop(obj: T) nopanic; + +// Boxes. +mod box; +use box::Box; +use box::into_box; +use box::unbox; + +// Nullable +mod nullable; +use nullable::FromNullableResult; +use nullable::Nullable; +use nullable::null; +use nullable::into_nullable; +use nullable::from_nullable; + +// Arrays. +mod array; +use array::Array; +use array::array_new; +use array::array_append; +use array::array_pop_front; +use array::array_at; +use array::array_len; + +// Dictionary. +mod dict; +use dict::DictFeltTo; +use dict::SquashedDictFeltTo; +use dict::dict_felt_to_new; +use dict::dict_felt_to_write; +use dict::dict_felt_to_read; +use dict::dict_felt_to_squash; + +// Result. +mod result; +use result::Result; + +// Option. +mod option; +use option::Option; + +// EC. +mod ec; +use ec::EcPoint; +use ec::EcState; +use ec::ec_add_to_state; +use ec::ec_init_state; +use ec::ec_point_from_felts; +use ec::ec_point_try_create; +use ec::ec_point_unwrap; + +// Integer. +mod integer; +use integer::u128; +use integer::u128_const; +use integer::u128_from_felt; +use integer::u128_try_from_felt; +use integer::u128_to_felt; +use integer::u128_add; +use integer::u128_sub; +use integer::u128_mul; +use integer::u128_as_non_zero; +use integer::u128_div; +use integer::u128_mod; +use integer::u128_lt; +use integer::u128_le; +use integer::u128_gt; +use integer::u128_ge; +use integer::u128_eq; +use integer::u128_ne; +use integer::u128_and; +use integer::u128_or; +use integer::u128_xor; +use integer::u128_jump_nz; +use integer::u256; +use integer::u256_add; +use integer::u256_sub; +use integer::u256_mul; +use integer::u256_eq; +use integer::u256_ne; +use integer::u256_lt; +use integer::u256_le; +use integer::u256_gt; +use integer::u256_ge; +use integer::u256_and; +use integer::u256_or; +use integer::u256_xor; +use integer::u256_from_felt; +use integer::Bitwise; + +// Gas. +mod gas; +use gas::BuiltinCosts; +use gas::GasBuiltin; +use gas::get_builtin_costs; +use gas::get_gas; +use gas::get_gas_all; + +// Panics. +enum PanicResult { Ok: T, Err: Array::, } +enum never { } +extern fn panic(data: Array::) -> never; + +fn assert(cond: bool, err_code: felt) { + if !cond { + let mut data = array_new::(); + array_append::(data, err_code); + panic(data); + } +} + +// Serialization and Deserialization. DO NOT USE DIRECTLY - direct usage pending traits. +mod serde; + +// Hash functions. +mod hash; +use hash::pedersen; +use hash::Pedersen; + +// Debug. +mod debug; + +// StarkNet +mod starknet; +use starknet::System; +use starknet::ContractAddress; + +#[cfg(test)] +mod test; diff --git a/corelib/nullable.cairo b/corelib/nullable.cairo new file mode 100644 index 0000000000..516fdc4c08 --- /dev/null +++ b/corelib/nullable.cairo @@ -0,0 +1,7 @@ +extern type Nullable; + +enum FromNullableResult { Null: (), NotNull: Box::, } + +extern fn null() -> Nullable:: nopanic; +extern fn into_nullable(value: Box::) -> Nullable:: nopanic; +extern fn from_nullable(value: Nullable::) -> FromNullableResult:: nopanic; diff --git a/corelib/option.cairo b/corelib/option.cairo new file mode 100644 index 0000000000..d1858d6f2e --- /dev/null +++ b/corelib/option.cairo @@ -0,0 +1 @@ +enum Option { Some: T, None: (), } diff --git a/corelib/result.cairo b/corelib/result.cairo new file mode 100644 index 0000000000..ae1d758add --- /dev/null +++ b/corelib/result.cairo @@ -0,0 +1 @@ +enum Result { Ok: T, Err: E, } diff --git a/corelib/serde.cairo b/corelib/serde.cairo new file mode 100644 index 0000000000..e6236c4b00 --- /dev/null +++ b/corelib/serde.cairo @@ -0,0 +1,91 @@ +fn serialize_felt(ref serialized: Array::, input: felt) { + array_append::(serialized, input); +} + +fn deserialize_felt(ref serialized: Array::) -> Option:: { + array_pop_front::(serialized) +} + +fn serialize_bool(ref serialized: Array::, input: bool) { + serialize_felt(serialized, if input { + 1 + } else { + 0 + }); +} + +fn deserialize_bool(ref serialized: Array::) -> Option:: { + Option::::Some(deserialize_felt(serialized)? != 0) +} + +fn serialize_u128(ref serialized: Array::, input: u128) { + serialize_felt(serialized, u128_to_felt(input)); +} + +fn deserialize_u128(ref serialized: Array::) -> Option:: { + u128_try_from_felt(deserialize_felt(serialized)?) +} + +fn serialize_u256(ref serialized: Array::, input: u256) { + serialize_u128(serialized, input.low); + serialize_u128(serialized, input.high); +} + +fn deserialize_u256(ref serialized: Array::) -> Option:: { + Option::::Some( + u256 { low: deserialize_u128(serialized)?, high: deserialize_u128(serialized)?, } + ) +} + +fn serialize_array_felt_helper(ref serialized: Array::, ref input: Array::) { + // TODO(orizi): Replace with simple call once inlining is supported. + match get_gas() { + Option::Some(_) => { + }, + Option::None(_) => { + let mut data = array_new::(); + array_append::(data, 'Out of gas'); + panic(data); + }, + } + match array_pop_front::(input) { + Option::Some(value) => { + serialize_felt(serialized, value); + serialize_array_felt_helper(serialized, input); + }, + Option::None(_) => { + }, + } +} + +fn serialize_array_felt(ref serialized: Array::, mut input: Array::) { + serialize_u128(serialized, array_len::(input)) + serialize_array_felt_helper(serialized, input); +} + +fn deserialize_array_felt_helper( + ref serialized: Array::, mut curr_output: Array::, remaining: felt +) -> Option::> { + // TODO(orizi): Replace with simple call once inlining is supported. + match get_gas() { + Option::Some(_) => { + }, + Option::None(_) => { + let mut data = array_new::(); + array_append::(data, 'Out of gas'); + panic(data); + }, + } + if remaining == 0 { + return Option::>::Some(curr_output); + } + let value = deserialize_felt(serialized)?; + array_append::(curr_output, value); + deserialize_array_felt_helper(serialized, curr_output, remaining - 1) +} + +fn deserialize_array_felt(ref serialized: Array::) -> Option::> { + let length = deserialize_felt(serialized)?; + let mut arr = array_new::(); + deserialize_array_felt_helper(serialized, arr, length) +} diff --git a/corelib/starknet.cairo b/corelib/starknet.cairo new file mode 100644 index 0000000000..78e491777f --- /dev/null +++ b/corelib/starknet.cairo @@ -0,0 +1,31 @@ +extern type System; +#[derive(Copy, Drop)] +extern type StorageAddress; +#[derive(Copy, Drop)] +extern type ContractAddress; + +// An Helper function to force the inclusion of `System` in the list of implicits. +fn use_system_implicit() implicits(System) { +} + +// Storage. +extern fn storage_address_const
() -> StorageAddress nopanic; +extern fn storage_addr_from_felt(addr: felt) -> StorageAddress implicits(RangeCheck) nopanic; + +// Only address_domain 0 is currently supported. +// This parameter is going to be used to access address spaces with different +// data availability guarantees. +extern fn storage_read_syscall( + address_domain: felt, address: StorageAddress, +) -> Result:: implicits(GasBuiltin, System) nopanic; +extern fn storage_write_syscall( + address_domain: felt, address: StorageAddress, value: felt +) -> Result::<(), felt> implicits(GasBuiltin, System) nopanic; + +// Interoperability. +type CallContractResult = Result::, +( +felt, Array:: +)>; extern fn call_contract_syscall( + address: ContractAddress, calldata: Array:: +) -> CallContractResult implicits(GasBuiltin, System) nopanic; diff --git a/corelib/test.cairo b/corelib/test.cairo new file mode 100644 index 0000000000..8c4ed49637 --- /dev/null +++ b/corelib/test.cairo @@ -0,0 +1,356 @@ +#[test] +#[should_panic] +fn test_assert_false() { + assert(false, 'assert(false)'); +} + +#[test] +fn test_assert_true() { + assert(true, 'assert(true)'); +} + +#[test] +fn test_bool_operators() { + assert(true == true, 't == t'); + assert(false == false, 'f == f'); + assert(!true == false, '!t == f'); + assert(!false == true, '!f == t'); + assert(true != false, 't != f'); + assert(false != true, 'f != t'); + assert(!(false & false), '!(f & f)'); + assert(!(true & false), '!(t & f)'); + assert(!(false & true), '!(f & t)'); + assert(true & true, 't & t'); + assert(!(false | false), '!(f | f)'); + assert(true | false, 't | f'); + assert(false | true, 'f | t'); + assert(true | true, 't | t'); + assert(!(false ^ false), '!(f ^ f)'); + assert(true ^ false, 't ^ f'); + assert(false ^ true, 'f ^ t'); + assert(!(true ^ true), '!(t ^ t)'); +} + +#[test] +fn test_ec_operations() { + let state = ec_init_state(); + // Beta + 2 is a square, and for x = 1 and alpha = 1, x^3 + alpha * x + beta = beta + 2. + let beta_plus_2 = 3141592653589793238462643383279502884197169399375105820974944592307816406667; + let beta_p2_root = 2487829544412206244690656897973144572467842667075005257202960243805141046681; + let p = ec_point_from_felts(1, beta_p2_root); + let (x, y) = ec_point_unwrap(p); + assert(x == 1, 'x == 1'); + assert(y == beta_p2_root, 'y is correct'); + let state2 = ec_add_to_state(state, p); +} + +#[test] +#[should_panic] +fn test_bad_ec_point_creation() { + ec_point_from_felts(0, 0); +} + +#[test] +fn test_felt_operators() { + assert(1 + 3 == 4, '1 + 3 == 4'); + assert(3 + 6 == 9, '3 + 6 == 9'); + assert(3 - 1 == 2, '3 - 1 == 2'); + assert(1231 - 231 == 1000, '1231-231=1000'); + assert(1 * 3 == 3, '1 * 3 == 3'); + assert(3 * 6 == 18, '3 * 6 == 18'); + assert(1 < 4, '1 < 4'); + assert(1 <= 4, '1 <= 4'); + assert(!(4 < 4), '!(4 < 4)'); + assert(4 <= 4, '4 <= 4'); + assert(5 > 2, '5 > 2'); + assert(5 >= 2, '5 >= 2'); + assert(!(3 > 3), '!(3 > 3)'); + assert(3 >= 3, '3 >= 3'); +} + +#[test] +fn test_u128_operators() { + assert(1_u128 == 1_u128, '1 == 1'); + assert(!(1_u128 == 2_u128), '!(1 == 2)'); + assert(1_u128 + 3_u128 == 4_u128, '1 + 3 == 4'); + assert(3_u128 + 6_u128 == 9_u128, '3 + 6 == 9'); + assert(3_u128 - 1_u128 == 2_u128, '3 - 1 == 2'); + assert(1231_u128 - 231_u128 == 1000_u128, '1231-231=1000'); + assert(1_u128 * 3_u128 == 3_u128, '1 * 3 == 3'); + assert(2_u128 * 4_u128 == 8_u128, '2 * 4 == 8'); + assert(8_u128 / 2_u128 == 4_u128, '8 / 2 == 4'); + assert(8_u128 % 2_u128 == 0_u128, '8 % 2 == 0'); + assert(7_u128 / 3_u128 == 2_u128, '7 / 3 == 2'); + assert(7_u128 % 3_u128 == 1_u128, '7 % 3 == 1'); + assert(1_u128 < 4_u128, '1 < 4'); + assert(1_u128 <= 4_u128, '1 <= 4'); + assert(!(4_u128 < 4_u128), '!(4 < 4)'); + assert(4_u128 <= 4_u128, '4 <= 4'); + assert(5_u128 > 2_u128, '5 > 2'); + assert(5_u128 >= 2_u128, '5 >= 2'); + assert(!(3_u128 > 3_u128), '!(3 > 3)'); + assert(3_u128 >= 3_u128, '3 >= 3'); + assert((1_u128 | 2_u128) == 3_u128, '1 | 2 == 3'); + assert((1_u128 & 2_u128) == 0_u128, '1 & 2 == 0'); + assert((1_u128 ^ 2_u128) == 3_u128, '1 ^ 2 == 3'); + assert((2_u128 | 2_u128) == 2_u128, '2 | 2 == 2'); + assert((2_u128 & 2_u128) == 2_u128, '2 & 2 == 2'); + assert((2_u128 & 3_u128) == 2_u128, '2 & 3 == 2'); + assert((3_u128 ^ 6_u128) == 5_u128, '3 ^ 6 == 5'); +} + +fn pow_2_127() -> u128 { + 0x80000000000000000000000000000000_u128 +} + +fn pow_2_64() -> u128 { + 0x10000000000000000_u128 +} + +#[test] +#[should_panic] +fn test_u128_sub_overflow_1() { + 0_u128 - 1_u128; +} + +#[test] +#[should_panic] +fn test_u128_sub_overflow_2() { + 0_u128 - 3_u128; +} + +#[test] +#[should_panic] +fn test_u128_sub_overflow_3() { + 1_u128 - 3_u128; +} + +#[test] +#[should_panic] +fn test_u128_sub_overflow_4() { + 100_u128 - 1000_u128; +} + +#[test] +#[should_panic] +fn test_u128_add_overflow_1() { + pow_2_127() + pow_2_127(); +} + +#[test] +#[should_panic] +fn test_u128_add_overflow_2() { + (pow_2_127() + 12_u128) + pow_2_127(); +} + +#[test] +#[should_panic] +fn test_u128_mul_overflow_1() { + pow_2_64() * pow_2_64(); +} + +#[test] +#[should_panic] +fn test_u128_mul_overflow_2() { + (pow_2_64() + 1_u128) * pow_2_64(); +} + +#[test] +#[should_panic] +fn test_u128_mul_overflow_3() { + 2_u128 * pow_2_127(); +} + +#[test] +#[should_panic] +fn test_u128_div_by_0() { + 2_u128 / 0_u128; +} + +#[test] +#[should_panic] +fn test_u128_mod_by_0() { + 2_u128 % 0_u128; +} + +// TODO(orizi): Remove when u256 literals are supported. +fn as_u256(high: u128, low: u128) -> u256 { + u256 { low, high } +} + +#[test] +fn test_u256_from_felt() { + assert(u256_from_felt(1) == as_u256(0_u128, 1_u128), 'into 1'); + assert( + u256_from_felt(170141183460469231731687303715884105728 * 2) == as_u256(1_u128, 0_u128), + 'into 2**128' + ); +} + +// TODO(orizi): Use u256 literals when supported. +#[test] +fn test_u256_operators() { + let max_u128 = 0xffffffffffffffffffffffffffffffff_u128; + assert(as_u256(1_u128, 1_u128) + as_u256(3_u128, 2_u128) == as_u256(4_u128, 3_u128), 'no OF'); + assert( + as_u256(1_u128, pow_2_127()) + as_u256(3_u128, pow_2_127()) == as_u256(5_u128, 0_u128), + 'basic OF' + ); + assert(as_u256(4_u128, 3_u128) - as_u256(1_u128, 1_u128) == as_u256(3_u128, 2_u128), 'no UF'); + assert( + as_u256(5_u128, 0_u128) - as_u256(1_u128, pow_2_127()) == as_u256(3_u128, pow_2_127()), + 'basic UF' + ); + assert( + as_u256(4_u128, 3_u128) * as_u256(0_u128, 1_u128) == as_u256(4_u128, 3_u128), 'mul by 1' + ); + assert( + as_u256(4_u128, 3_u128) * as_u256(0_u128, 2_u128) == as_u256(8_u128, 6_u128), 'mul by 2' + ); + assert( + as_u256(0_u128, pow_2_127()) * as_u256(0_u128, 2_u128) == as_u256(1_u128, 0_u128), + 'basic mul OF' + ); + assert( + as_u256(0_u128, max_u128) + * as_u256( + 0_u128, max_u128 + ) == as_u256(0xfffffffffffffffffffffffffffffffe_u128, 1_u128), + 'max_u128 * max_u128' + ); + assert( + as_u256(0_u128, max_u128) * as_u256(0_u128, 1_u128) == as_u256(0_u128, max_u128), + 'max_u128 * 1' + ); + assert( + as_u256(0_u128, 1_u128) * as_u256(0_u128, max_u128) == as_u256(0_u128, max_u128), + '1 * max_u128' + ); + assert( + (as_u256(1_u128, 2_u128) | as_u256(2_u128, 2_u128)) == as_u256(3_u128, 2_u128), + '1.2|2.2==3.2' + ); + assert( + (as_u256(2_u128, 1_u128) | as_u256(2_u128, 2_u128)) == as_u256(2_u128, 3_u128), + '2.1|2.2==2.3' + ); + assert( + (as_u256(2_u128, 2_u128) | as_u256(1_u128, 2_u128)) == as_u256(3_u128, 2_u128), + '2.2|1.2==3.2' + ); + assert( + (as_u256(2_u128, 2_u128) | as_u256(2_u128, 1_u128)) == as_u256(2_u128, 3_u128), + '2.2|2.1==2.3' + ); + assert( + (as_u256(1_u128, 2_u128) & as_u256(2_u128, 2_u128)) == as_u256(0_u128, 2_u128), + '1.2&2.2==0.2' + ); + assert( + (as_u256(2_u128, 1_u128) & as_u256(2_u128, 2_u128)) == as_u256(2_u128, 0_u128), + '2.1&2.2==2.0' + ); + assert( + (as_u256(2_u128, 2_u128) & as_u256(1_u128, 2_u128)) == as_u256(0_u128, 2_u128), + '2.2&1.2==0.2' + ); + assert( + (as_u256(2_u128, 2_u128) & as_u256(2_u128, 1_u128)) == as_u256(2_u128, 0_u128), + '2.2&2.1==2.0' + ); + assert( + (as_u256(1_u128, 2_u128) ^ as_u256(2_u128, 2_u128)) == as_u256(3_u128, 0_u128), + '1.2^2.2==3.0' + ); + assert( + (as_u256(2_u128, 1_u128) ^ as_u256(2_u128, 2_u128)) == as_u256(0_u128, 3_u128), + '2.1^2.2==0.3' + ); + assert( + (as_u256(2_u128, 2_u128) ^ as_u256(1_u128, 2_u128)) == as_u256(3_u128, 0_u128), + '2.2^1.2==3.0' + ); + assert( + (as_u256(2_u128, 2_u128) ^ as_u256(2_u128, 1_u128)) == as_u256(0_u128, 3_u128), + '2.2^2.1==0.3' + ); + assert(as_u256(1_u128, 2_u128) < as_u256(2_u128, 2_u128), '1.2<2.2'); + assert(as_u256(2_u128, 1_u128) < as_u256(2_u128, 2_u128), '2.1<2.2'); + assert(!(as_u256(2_u128, 2_u128) < as_u256(1_u128, 2_u128)), '2.2<1.2'); + assert(!(as_u256(2_u128, 2_u128) < as_u256(2_u128, 1_u128)), '2.2<2.1'); + assert(!(as_u256(2_u128, 2_u128) < as_u256(2_u128, 2_u128)), '2.2<2.2'); + assert(as_u256(1_u128, 2_u128) <= as_u256(2_u128, 2_u128), '1.2<=2.2'); + assert(as_u256(2_u128, 1_u128) <= as_u256(2_u128, 2_u128), '2.1<=2.2'); + assert(!(as_u256(2_u128, 2_u128) <= as_u256(1_u128, 2_u128)), '2.2<=1.2'); + assert(!(as_u256(2_u128, 2_u128) <= as_u256(2_u128, 1_u128)), '2.2<=2.1'); + assert(as_u256(2_u128, 2_u128) <= as_u256(2_u128, 2_u128), '2.2<=2.2'); + assert(!(as_u256(1_u128, 2_u128) > as_u256(2_u128, 2_u128)), '1.2>2.2'); + assert(!(as_u256(2_u128, 1_u128) > as_u256(2_u128, 2_u128)), '2.1>2.2'); + assert(as_u256(2_u128, 2_u128) > as_u256(1_u128, 2_u128), '2.2>1.2'); + assert(as_u256(2_u128, 2_u128) > as_u256(2_u128, 1_u128), '2.2>2.1'); + assert(!(as_u256(2_u128, 2_u128) > as_u256(2_u128, 2_u128)), '2.2>2.2'); + assert(!(as_u256(1_u128, 2_u128) >= as_u256(2_u128, 2_u128)), '1.2>=2.2'); + assert(!(as_u256(2_u128, 1_u128) >= as_u256(2_u128, 2_u128)), '2.1>=2.2'); + assert(as_u256(2_u128, 2_u128) >= as_u256(1_u128, 2_u128), '2.2>=1.2'); + assert(as_u256(2_u128, 2_u128) >= as_u256(2_u128, 1_u128), '2.2>=2.1'); + assert(as_u256(2_u128, 2_u128) >= as_u256(2_u128, 2_u128), '2.2>=2.2'); +} + +#[test] +#[should_panic] +fn test_u256_add_overflow() { + as_u256(pow_2_127(), 1_u128) + as_u256(pow_2_127(), 1_u128); +} + +#[test] +#[should_panic] +fn test_u256_sub_overflow() { + as_u256(1_u128, 1_u128) - as_u256(1_u128, 2_u128); +} + +#[test] +#[should_panic] +fn test_u256_mul_overflow_1() { + as_u256(1_u128, 1_u128) * as_u256(1_u128, 2_u128); +} + +#[test] +#[should_panic] +fn test_u256_mul_overflow_2() { + as_u256(0_u128, pow_2_127()) * as_u256(2_u128, 0_u128); +} + +// TODO(orizi): Switch to operators and literals when added. +fn test_array_helper(idx: u128) -> felt { + let mut arr = array_new::(); + array_append::(arr, 10); + array_append::(arr, 11); + array_append::(arr, 12); + match array_at::(arr, idx) { + Option::Some(x) => x, + Option::None(()) => { + let mut data = array_new::(); + array_append::(data, 'array index OOB'); + panic(data) + }, + } +} + +#[test] +fn test_array() { + assert(test_array_helper(0_u128) == 10, 'array[0] == 10'); + assert(test_array_helper(1_u128) == 11, 'array[1] == 11'); + assert(test_array_helper(2_u128) == 12, 'array[2] == 12'); +} + +#[test] +#[should_panic] +fn test_array_out_of_bound_1() { + test_array_helper(3_u128); +} + +#[test] +#[should_panic] +fn test_array_out_of_bound_2() { + test_array_helper(11_u128); +} diff --git a/corelib/traits.cairo b/corelib/traits.cairo new file mode 100644 index 0000000000..ce4d7d899d --- /dev/null +++ b/corelib/traits.cairo @@ -0,0 +1,2 @@ +trait Copy; +trait Drop; diff --git a/crates/cairo-lang-dojo/Cargo.toml b/crates/cairo-lang-dojo/Cargo.toml new file mode 100644 index 0000000000..096d13cde8 --- /dev/null +++ b/crates/cairo-lang-dojo/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "cairo-lang-dojo" +version.workspace = true +edition.workspace = true +repository.workspace = true +license-file.workspace = true +description = "Dojo capabilities and utilities on top of Starknet." + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.66" +clap = { version = "4.0", features = ["derive"] } +cairo-lang-defs = { git = "https://github.com/starkware-libs/cairo.git", version = "0.1.0" } +cairo-lang-diagnostics = { git = "https://github.com/starkware-libs/cairo.git", version = "0.1.0" } +cairo-lang-parser = { git = "https://github.com/starkware-libs/cairo.git", version = "0.1.0" } +cairo-lang-semantic = { git = "https://github.com/starkware-libs/cairo.git", version = "0.1.0" } +cairo-lang-starknet = { git = "https://github.com/starkware-libs/cairo.git", version = "0.1.0" } +cairo-lang-syntax = { git = "https://github.com/starkware-libs/cairo.git", version = "0.1.0" } +cairo-lang-utils = { git = "https://github.com/starkware-libs/cairo.git", version = "0.1.0" } +indoc.workspace = true +serde.workspace = true +serde_json.workspace = true + +[dev-dependencies] +env_logger.workspace = true +cairo-lang-semantic = { git = "https://github.com/starkware-libs/cairo.git", features = ["testing"] } +cairo-lang-test-utils = { git = "https://github.com/starkware-libs/cairo.git", version = "0.1.0" } +test-case = "2.2.2" +test-case-macros = "2.2.2" +test-log.workspace = true + +[[bin]] +name = "dojo-compile" +path = "src/cli.rs" diff --git a/crates/cairo-lang-dojo/src/cli.rs b/crates/cairo-lang-dojo/src/cli.rs new file mode 100644 index 0000000000..69dd9d8a6d --- /dev/null +++ b/crates/cairo-lang-dojo/src/cli.rs @@ -0,0 +1,32 @@ +use std::fs; +use std::path::PathBuf; + +use anyhow::Context; +use cairo_lang_starknet::contract_class::compile_path; +use clap::Parser; + +/// Command line args parser. +/// Exits with 0/1 if the input is formatted correctly/incorrectly. +#[derive(Parser, Debug)] +#[clap(version, verbatim_doc_comment)] +struct Args { + /// The file to compile + path: String, + /// The output file name (default: stdout). + output: Option, + /// Replaces sierra ids with human readable ones. + #[arg(short, long, default_value_t = false)] + replace_ids: bool, +} + +fn main() -> anyhow::Result<()> { + let args = Args::parse(); + let contract = compile_path(&PathBuf::from(args.path), args.replace_ids)?; + let res = serde_json::to_string_pretty(&contract).with_context(|| "Serialization failed.")?; + match args.output { + Some(path) => fs::write(path, res).with_context(|| "Failed to write output.")?, + None => println!("{}", res), + } + + Ok(()) +} diff --git a/crates/cairo-lang-dojo/src/db.rs b/crates/cairo-lang-dojo/src/db.rs new file mode 100644 index 0000000000..1a22e2e986 --- /dev/null +++ b/crates/cairo-lang-dojo/src/db.rs @@ -0,0 +1,29 @@ +use std::sync::Arc; + +use cairo_lang_compiler::db::RootDatabase; +use cairo_lang_lowering::db::LoweringGroup; +use cairo_lang_plugins::get_default_plugins; +use cairo_lang_semantic::corelib::get_core_ty_by_name; +use cairo_lang_semantic::db::SemanticGroup; +use itertools::Itertools; + +use crate::plugin::DojoPlugin; + +/// Returns a compiler database tuned to Dojo (e.g. Dojo plugin). +pub fn get_dojo_database() -> RootDatabase { + let mut db_val = RootDatabase::default(); + let db = &mut db_val; + + // Override implicit precedence for compatibility with the Starknet OS. + db.set_implicit_precedence(Arc::new( + ["Pedersen", "RangeCheck", "Bitwise", "GasBuiltin", "System"] + .iter() + .map(|name| get_core_ty_by_name(db, name.into(), vec![])) + .collect_vec(), + )); + + let mut plugins = get_default_plugins(); + plugins.push(Arc::new(DojoPlugin {})); + db.set_semantic_plugins(plugins); + db_val +} diff --git a/crates/cairo-lang-dojo/src/lib.rs b/crates/cairo-lang-dojo/src/lib.rs new file mode 100644 index 0000000000..229045b1eb --- /dev/null +++ b/crates/cairo-lang-dojo/src/lib.rs @@ -0,0 +1,7 @@ +//! Starknet capabilities and utilities on top of Cairo. +//! +//! StarkNet is a smart contract platform that enables developers to build and deploy smart +//! contracts on a permissionless Layer 2 network, secured by Ethereum using validity proofs. +//! +//! Learn more at [starkware.io](http://starknet.io/). +pub mod plugin; diff --git a/crates/cairo-lang-dojo/src/plugin.rs b/crates/cairo-lang-dojo/src/plugin.rs new file mode 100644 index 0000000000..a0a4fb7a5c --- /dev/null +++ b/crates/cairo-lang-dojo/src/plugin.rs @@ -0,0 +1,694 @@ +use std::collections::HashMap; +use std::sync::Arc; +use std::vec; + +use cairo_lang_defs::plugin::{ + DynGeneratedFileAuxData, GeneratedFileAuxData, MacroPlugin, PluginDiagnostic, + PluginGeneratedFile, PluginResult, +}; +use cairo_lang_diagnostics::DiagnosticEntry; +use cairo_lang_semantic::db::SemanticGroup; +use cairo_lang_semantic::patcher::{ModifiedNode, PatchBuilder, Patches, RewriteNode}; +use cairo_lang_semantic::plugin::{ + AsDynGeneratedFileAuxData, AsDynMacroPlugin, DiagnosticMapper, DynDiagnosticMapper, + PluginMappedDiagnostic, SemanticPlugin, +}; +use cairo_lang_semantic::SemanticDiagnostic; +use cairo_lang_syntax::node::ast::{ + ItemFreeFunction, MaybeModuleBody, MaybeTraitBody, Modifier, OptionReturnTypeClause, Param, +}; +use cairo_lang_syntax::node::db::SyntaxGroup; +use cairo_lang_syntax::node::helpers::{GetIdentifier, QueryAttrs}; +use cairo_lang_syntax::node::{ast, Terminal, TypedSyntaxNode}; +use cairo_lang_utils::try_extract_matches; +use indoc::formatdoc; + +use cairo_lang_starknet::contract::starknet_keccak; + +const ABI_ATTR: &str = "abi"; +const COMPONENT_ATTR: &str = "component"; +const EXTERNAL_ATTR: &str = "external"; +const VIEW_ATTR: &str = "view"; +pub const GENERATED_CONTRACT_ATTR: &str = "generated_contract"; +pub const ABI_TRAIT: &str = "__abi"; +pub const EXTERNAL_MODULE: &str = "__external"; + +/// The diagnostics remapper of the plugin. +#[derive(Debug, PartialEq, Eq)] +pub struct DiagnosticRemapper { + patches: Patches, +} +impl GeneratedFileAuxData for DiagnosticRemapper { + fn as_any(&self) -> &dyn std::any::Any { + self + } + fn eq(&self, other: &dyn GeneratedFileAuxData) -> bool { + if let Some(other) = other.as_any().downcast_ref::() { self == other } else { false } + } +} +impl AsDynGeneratedFileAuxData for DiagnosticRemapper { + fn as_dyn_macro_token(&self) -> &(dyn GeneratedFileAuxData + 'static) { + self + } +} +impl DiagnosticMapper for DiagnosticRemapper { + fn map_diag( + &self, + db: &(dyn SemanticGroup + 'static), + diag: &dyn std::any::Any, + ) -> Option { + let Some(diag) = diag.downcast_ref::() else {return None;}; + let span = self + .patches + .translate(db.upcast(), diag.stable_location.diagnostic_location(db.upcast()).span)?; + Some(PluginMappedDiagnostic { span, message: diag.format(db) }) + } +} + +#[cfg(test)] +#[path = "plugin_test.rs"] +mod test; + +#[derive(Debug)] +pub struct DojoPlugin {} + +impl MacroPlugin for DojoPlugin { + fn generate_code(&self, db: &dyn SyntaxGroup, item_ast: ast::Item) -> PluginResult { + match item_ast { + ast::Item::Module(module_ast) => handle_mod(db, module_ast), + ast::Item::Trait(trait_ast) => handle_trait(db, trait_ast), + // Nothing to do for other items. + _ => PluginResult::default(), + } + } +} +impl AsDynMacroPlugin for DojoPlugin { + fn as_dyn_macro_plugin<'a>(self: Arc) -> Arc + where + Self: 'a, + { + self + } +} +impl SemanticPlugin for DojoPlugin {} + +/// If the trait is annotated with ABI_ATTR, generate the relevant dispatcher logic. +fn handle_trait(db: &dyn SyntaxGroup, trait_ast: ast::ItemTrait) -> PluginResult { + let attrs = trait_ast.attributes(db).elements(db); + if !attrs.iter().any(|attr| attr.attr(db).text(db) == ABI_ATTR) { + return PluginResult::default(); + } + let body = match trait_ast.body(db) { + MaybeTraitBody::Some(body) => body, + MaybeTraitBody::None(empty_body) => { + return PluginResult { + code: None, + diagnostics: vec![PluginDiagnostic { + message: "ABIs without body are not supported.".to_string(), + stable_ptr: empty_body.stable_ptr().untyped(), + }], + remove_original_item: false, + }; + } + }; + + let mut diagnostics = vec![]; + let mut functions = vec![]; + for item_ast in body.items(db).elements(db) { + match item_ast { + ast::TraitItem::Function(func) => { + let declaration = func.declaration(db); + + let mut skip_generation = false; + let mut serialization_code = vec![]; + let signature = declaration.signature(db); + for param in signature.parameters(db).elements(db) { + if is_ref_param(db, ¶m) { + skip_generation = true; + + diagnostics.push(PluginDiagnostic { + message: "`ref` parameters are not supported in the ABI of a contract." + .to_string(), + stable_ptr: param.modifiers(db).stable_ptr().untyped(), + }) + } + + let param_type = param.type_clause(db).ty(db); + let type_name = ¶m_type.as_syntax_node().get_text(db); + if let Some((ser_func, _)) = get_type_serde_funcs(type_name) { + serialization_code.push(RewriteNode::interpolate_patched( + &formatdoc!(" {ser_func}(calldata, $arg_name$);\n"), + HashMap::from([( + "arg_name".to_string(), + RewriteNode::Trimmed(param.name(db).as_syntax_node()), + )]), + )); + } else { + diagnostics.push(PluginDiagnostic { + stable_ptr: param_type.stable_ptr().untyped(), + message: format!("Could not find serialization for type `{type_name}`"), + }); + skip_generation = true; + } + } + + if skip_generation { + // TODO(ilya): Consider generating an empty wrapper to avoid: + // Unknown function error. + continue; + } + + let ret_decode = match signature.ret_ty(db) { + OptionReturnTypeClause::Empty(_) => "".to_string(), + OptionReturnTypeClause::ReturnTypeClause(ty) => { + let ret_type_ast = ty.ty(db); + let type_name = ret_type_ast.as_syntax_node().get_text(db); + let Some((_, deser_func)) = get_type_serde_funcs(&type_name) else { + diagnostics.push(PluginDiagnostic { + stable_ptr: ret_type_ast.stable_ptr().untyped(), + message: format!( + "Could not find deserialization for type `{type_name}`"), + }); + continue; + }; + + format!(" {deser_func}(ret_data)") + } + }; + + let mut func_declaration = RewriteNode::from_ast(&declaration); + func_declaration + .modify_child(db, ast::FunctionDeclaration::INDEX_SIGNATURE) + .modify_child(db, ast::FunctionSignature::INDEX_PARAMETERS) + .modify(db) + .children + .splice( + 0..0, + [ + RewriteNode::Text("contract_address: ContractAddress".to_string()), + RewriteNode::Text(", ".to_string()), + ], + ); + + functions.push(RewriteNode::interpolate_patched( + "$func_decl$ { + let calldata = array_new::(); +$serialization_code$ + let ret_data = match starknet::call_contract_syscall( + contract_address, + calldata, + ) { + Result::Ok(ret_data) => ret_data, + Result::Err((reason, _ret_data)) => { + let mut err_data = array_new::(); + array_append::(err_data, 'call_contract_syscall failed'); + array_append::(err_data, reason); + // TODO(ilya): Handle ret_data. + panic(err_data) + }, + }; +$deserialization_code$ + } +", + HashMap::from([ + ("func_decl".to_string(), func_declaration), + ( + "serialization_code".to_string(), + RewriteNode::Modified(ModifiedNode { children: serialization_code }), + ), + ("deserialization_code".to_string(), RewriteNode::Text(ret_decode)), + ]), + )); + } + } + } + + let mut builder = PatchBuilder::new(db); + let dispatcher_name = format!("{}Dispatcher", trait_ast.name(db).text(db)); + builder.add_modified(RewriteNode::interpolate_patched( + &formatdoc!( + "mod {dispatcher_name} {{ + $body$ + }}", + ), + HashMap::from([( + "body".to_string(), + RewriteNode::Modified(ModifiedNode { children: functions }), + )]), + )); + PluginResult { + code: Some(PluginGeneratedFile { + name: dispatcher_name.into(), + content: builder.code, + aux_data: DynGeneratedFileAuxData::new(DynDiagnosticMapper::new(DiagnosticRemapper { + patches: builder.patches, + })), + }), + diagnostics, + remove_original_item: false, + } +} + +/// If the module is annotated with CONTRACT_ATTR, generate the relevant contract logic. +fn handle_mod(db: &dyn SyntaxGroup, module_ast: ast::ItemModule) -> PluginResult { + if !module_ast.has_attr(db, COMPONENT_ATTR) { + // TODO(ilya): diagnostic + return PluginResult::default(); + } + + let body = match module_ast.body(db) { + MaybeModuleBody::Some(body) => body, + MaybeModuleBody::None(empty_body) => { + return PluginResult { + code: None, + diagnostics: vec![PluginDiagnostic { + message: "Contracts without body are not supported.".to_string(), + stable_ptr: empty_body.stable_ptr().untyped(), + }], + remove_original_item: false, + }; + } + }; + let mut diagnostics = vec![]; + + let mut generated_external_functions = Vec::new(); + + let mut storage_code = RewriteNode::Text("".to_string()); + let mut original_items = Vec::new(); + let mut abi_functions = Vec::new(); + for item in body.items(db).elements(db) { + match &item { + ast::Item::FreeFunction(item_function) + if item_function.has_attr(db, EXTERNAL_ATTR) + || item_function.has_attr(db, VIEW_ATTR) => + { + // TODO(yuval): keep track of whether the function is external/view. + abi_functions.push(RewriteNode::Modified(ModifiedNode { + children: vec![ + RewriteNode::Trimmed(item_function.declaration(db).as_syntax_node()), + RewriteNode::Text(";\n ".to_string()), + ], + })); + + match generate_entry_point_wrapper(db, item_function) { + Ok(generated_function) => { + generated_external_functions.push(generated_function); + generated_external_functions + .push(RewriteNode::Text("\n ".to_string())); + } + Err(entry_point_diagnostics) => { + diagnostics.extend(entry_point_diagnostics); + } + } + } + ast::Item::Struct(item_struct) if item_struct.name(db).text(db) == "Storage" => { + let (storage_code_rewrite, storage_diagnostics) = + handle_storage_struct(db, item_struct.clone()); + storage_code = storage_code_rewrite; + diagnostics.extend(storage_diagnostics); + // Don't recreate the struct - as it might not be valid due to mappings. + continue; + } + _ => {} + }; + original_items.push(RewriteNode::Copied(item.as_syntax_node())); + } + + let generated_contract_mod = RewriteNode::interpolate_patched( + formatdoc!( + " + #[{GENERATED_CONTRACT_ATTR}] + mod $contract_name$ {{ + $original_items$ + $storage_code$ + trait {ABI_TRAIT} {{ + $abi_functions$ + }} + + mod {EXTERNAL_MODULE} {{ + $generated_external_functions$ + }} + }} + " + ) + .as_str(), + HashMap::from([ + ( + "contract_name".to_string(), + RewriteNode::Trimmed(module_ast.name(db).as_syntax_node()), + ), + ( + "original_items".to_string(), + RewriteNode::Modified(ModifiedNode { children: original_items }), + ), + ("storage_code".to_string(), storage_code), + ( + "abi_functions".to_string(), + RewriteNode::Modified(ModifiedNode { children: abi_functions }), + ), + ( + "generated_external_functions".to_string(), + RewriteNode::Modified(ModifiedNode { children: generated_external_functions }), + ), + ]), + ); + + let mut builder = PatchBuilder::new(db); + builder.add_modified(generated_contract_mod); + + PluginResult { + code: Some(PluginGeneratedFile { + name: "contract".into(), + content: builder.code, + aux_data: DynGeneratedFileAuxData::new(DynDiagnosticMapper::new(DiagnosticRemapper { + patches: builder.patches, + })), + }), + diagnostics, + remove_original_item: true, + } +} + +/// Generate getters and setters for the variables in the storage struct. +fn handle_storage_struct( + db: &dyn SyntaxGroup, + struct_ast: ast::ItemStruct, +) -> (RewriteNode, Vec) { + let mut members_code = Vec::new(); + let mut diagnostics = vec![]; + + for member in struct_ast.members(db).elements(db) { + let name = member.name(db).text(db); + let address = format!("0x{:x}", starknet_keccak(name.as_bytes())); + let type_ast = member.type_clause(db).ty(db); + if let Some((key_type_ast, value_type_ast)) = try_extract_mapping_types(db, &type_ast) { + match handle_mapping_storage_var( + key_type_ast.as_syntax_node().get_text(db).trim(), + value_type_ast.as_syntax_node().get_text(db).trim(), + &address, + ) { + Some(code) => members_code.push(RewriteNode::interpolate_patched( + code.as_str(), + HashMap::from([ + ( + "storage_var_name".to_string(), + RewriteNode::Trimmed(member.name(db).as_syntax_node()), + ), + ( + "key_type".to_string(), + RewriteNode::Trimmed(key_type_ast.as_syntax_node()), + ), + ( + "value_type".to_string(), + RewriteNode::Trimmed(value_type_ast.as_syntax_node()), + ), + ]), + )), + None => diagnostics.push(PluginDiagnostic { + stable_ptr: type_ast.stable_ptr().untyped(), + message: "Unsupported type for storage var.".to_string(), + }), + } + } else { + match handle_simple_storage_var(type_ast.as_syntax_node().get_text(db).trim(), &address) + { + Some(code) => members_code.push(RewriteNode::interpolate_patched( + code.as_str(), + HashMap::from([ + ( + "storage_var_name".to_string(), + RewriteNode::Trimmed(member.name(db).as_syntax_node()), + ), + ("type_name".to_string(), RewriteNode::Trimmed(type_ast.as_syntax_node())), + ]), + )), + None => diagnostics.push(PluginDiagnostic { + stable_ptr: type_ast.stable_ptr().untyped(), + message: "Unsupported type for storage var.".to_string(), + }), + } + } + } + (RewriteNode::Modified(ModifiedNode { children: members_code }), diagnostics) +} + +/// Given a type, if it is of form `Map::`, returns `K` and `V`. Otherwise, returns None. +fn try_extract_mapping_types( + db: &dyn SyntaxGroup, + type_ast: &ast::Expr, +) -> Option<(ast::Expr, ast::Expr)> { + let as_path = try_extract_matches!(type_ast, ast::Expr::Path)?; + let [ast::PathSegment::WithGenericArgs(segment)] = &as_path.elements(db)[..] else { + return None; + }; + let ty = segment.ident(db).text(db); + if ty == "Map" { + let [key_ty, value_ty] = + <[ast::Expr; 2]>::try_from(segment.generic_args(db).generic_args(db).elements(db)) + .ok()?; + Some((key_ty, value_ty)) + } else { + None + } +} + +/// Returns the conversion string to and from felt for the type. +fn get_conversions(type_name: &str) -> Option<(&str, &str)> { + Some(match type_name { + "felt" => ("value", "value"), + "bool" => ("if value == 0 { false } else { true }", "if value { 1 } else { 0 }"), + "u128" => ("u128_from_felt(value)", "u128_to_felt(value)"), + _ => return None, + }) +} + +/// Generate getters and setters skeleton for a non-mapping member in the storage struct. +fn handle_simple_storage_var(type_name: &str, address: &str) -> Option { + let (convert_to, convert_from) = get_conversions(type_name)?; + Some(format!( + " + mod $storage_var_name$ {{ + fn address() -> starknet::StorageAddress {{ + starknet::storage_address_const::<{address}>() + }} + fn read() -> $type_name$ {{ + // Only address_domain 0 is currently supported. + let address_domain = 0; + match starknet::storage_read_syscall(address_domain, address()) {{ + Result::Ok(value) => {convert_to}, + Result::Err(revert_reason) => {{ + let mut err_data = array_new::(); + array_append::(err_data, revert_reason); + panic(err_data) + }}, + }} + }} + fn write(value: $type_name$) {{ + // Only address_domain 0 is currently supported. + let address_domain = 0; + match starknet::storage_write_syscall(address_domain, address(), {convert_from}) {{ + Result::Ok(()) => {{}}, + Result::Err(revert_reason) => {{ + let mut err_data = array_new::(); + array_append::(err_data, revert_reason); + panic(err_data) + }}, + }} + }} + }}" + )) +} + +/// Generate getters and setters skeleton for a non-mapping member in the storage struct. +fn handle_mapping_storage_var( + key_type_name: &str, + value_type_name: &str, + address: &str, +) -> Option { + let key_convert_to = match key_type_name { + "felt" => "key", + "bool" => "if key { 1 } else { 0 }", + "u128" => "u128_to_felt(key)", + _ => return None, + }; + let (value_convert_to, value_convert_from) = get_conversions(value_type_name)?; + Some(format!( + " + mod $storage_var_name$ {{ + fn address(key: $key_type$) -> starknet::StorageAddress {{ + starknet::storage_addr_from_felt(pedersen({address}, {key_convert_to})) + }} + fn read(key: $key_type$) -> $value_type$ {{ + // Only address_domain 0 is currently supported. + let address_domain = 0; + match starknet::storage_read_syscall(address_domain, address(key)) {{ + Result::Ok(value) => {value_convert_to}, + Result::Err(revert_reason) => {{ + let mut err_data = array_new::(); + array_append::(err_data, revert_reason); + panic(err_data) + }}, + }} + }} + fn write(key: $key_type$, value: $value_type$) {{ + // Only address_domain 0 is currently supported. + let address_domain = 0; + match starknet::storage_write_syscall( + address_domain, + address(key), + {value_convert_from}, + ) {{ + Result::Ok(()) => {{}}, + Result::Err(revert_reason) => {{ + let mut err_data = array_new::(); + array_append::(err_data, revert_reason); + panic(err_data) + }}, + }} + }} + }}" + )) +} + +/// Returns the serde functions for a type. +// TODO(orizi): Use type ids when semantic information is available. +// TODO(orizi): Use traits for serialization when supported. +fn get_type_serde_funcs(name: &str) -> Option<(&str, &str)> { + match name.trim() { + "felt" => Some(("serde::serialize_felt", "serde::deserialize_felt")), + "bool" => Some(("serde::serialize_bool", "serde::deserialize_bool")), + "u128" => Some(("serde::serialize_u128", "serde::deserialize_u128")), + "u256" => Some(("serde::serialize_u256", "serde::deserialize_u256")), + "Array::" => Some(("serde::serialize_array_felt", "serde::deserialize_array_felt")), + _ => None, + } +} + +/// Generates Cairo code for an entry point wrapper. +fn generate_entry_point_wrapper( + db: &dyn SyntaxGroup, + function: &ItemFreeFunction, +) -> Result> { + let declaration = function.declaration(db); + let sig = declaration.signature(db); + let params = sig.parameters(db).elements(db); + let mut diagnostics = vec![]; + let mut arg_names = Vec::new(); + let mut arg_definitions = Vec::new(); + let mut ref_appends = Vec::new(); + let input_data_short_err = "'Input too short for arguments'"; + for param in params { + let arg_name = format!("__arg_{}", param.name(db).identifier(db)); + let arg_type_ast = param.type_clause(db).ty(db); + let type_name = arg_type_ast.as_syntax_node().get_text(db); + let Some((ser_func, deser_func)) = get_type_serde_funcs(&type_name) else { + diagnostics.push(PluginDiagnostic { + stable_ptr: arg_type_ast.stable_ptr().0, + message: format!("Could not find serialization for type `{type_name}`"), + }); + continue; + }; + + let is_ref = is_ref_param(db, ¶m); + arg_names.push(arg_name.clone()); + let mut_modifier = if is_ref { "mut " } else { "" }; + // TODO(yuval): use panicable version of deserializations when supported. + let arg_definition = format!( + " + let {mut_modifier}{arg_name} = match {deser_func}(data) {{ + Option::Some(x) => x, + Option::None(()) => {{ + let mut err_data = array_new::(); + array_append::(err_data, {input_data_short_err}); + panic(err_data) + }}, + }};" + ); + arg_definitions.push(arg_definition); + + if is_ref { + ref_appends + .push(RewriteNode::Text(format!("\n {ser_func}(arr, {arg_name});"))); + } + } + let arg_names_str = arg_names.join(", "); + + let function_name = RewriteNode::Trimmed(declaration.name(db).as_syntax_node()); + let wrapped_name = RewriteNode::interpolate_patched( + "super::$function_name$", + HashMap::from([("function_name".to_string(), function_name.clone())]), + ); + let (let_res, append_res) = match sig.ret_ty(db) { + OptionReturnTypeClause::Empty(_) => ("", "".to_string()), + OptionReturnTypeClause::ReturnTypeClause(ty) => { + let ret_type_ast = ty.ty(db); + let ret_type_name = ret_type_ast.as_syntax_node().get_text(db); + // TODO(orizi): Handle tuple types. + if let Some((ser_func, _)) = get_type_serde_funcs(&ret_type_name) { + ("\n let res = ", format!("\n {ser_func}(arr, res)")) + } else { + diagnostics.push(PluginDiagnostic { + stable_ptr: ret_type_ast.stable_ptr().0, + message: format!("Could not find serialization for type `{ret_type_name}`"), + }); + ("", "".to_string()) + } + } + }; + if !diagnostics.is_empty() { + return Err(diagnostics); + } + + let oog_err = "'Out of gas'"; + let input_data_long_err = "'Input too long for arguments'"; + + // TODO(yuval): use panicable version of `get_gas` once inlining is supported. + let arg_definitions = arg_definitions.join("\n"); + Ok(RewriteNode::interpolate_patched( + format!( + "fn $function_name$(mut data: Array::) -> Array:: {{ + match get_gas() {{ + Option::Some(_) => {{ + }}, + Option::None(_) => {{ + let mut err_data = array_new::(); + array_append::(err_data, {oog_err}); + panic(err_data); + }}, + }} + {arg_definitions} + if array_len::(data) != 0_u128 {{ + // Force the inclusion of `System` in the list of implicits. + starknet::use_system_implicit(); + + let mut err_data = array_new::(); + array_append::(err_data, {input_data_long_err}); + panic(err_data); + }} + {let_res}$wrapped_name$({arg_names_str}); + let mut arr = array_new::(); + // References.$ref_appends$ + // Result.{append_res} + arr + }}" + ) + .as_str(), + HashMap::from([ + ("function_name".to_string(), function_name), + ("wrapped_name".to_string(), wrapped_name), + ( + "ref_appends".to_string(), + RewriteNode::Modified(ModifiedNode { children: ref_appends }), + ), + ("nothing".to_string(), RewriteNode::Text("".to_string())), + ]), + )) +} + +/// Checks if the parameter is defined as a ref parameter. +fn is_ref_param(db: &dyn SyntaxGroup, param: &Param) -> bool { + let param_modifiers = param.modifiers(db).elements(db); + // TODO(yuval): This works only if "ref" is the only modifier. If the expansion was at the + // semantic level, we could just ask if it's a reference. + param_modifiers.len() == 1 && matches!(param_modifiers[0], Modifier::Ref(_)) +} diff --git a/crates/cairo-lang-dojo/src/plugin_test.rs b/crates/cairo-lang-dojo/src/plugin_test.rs new file mode 100644 index 0000000000..569e9e00ca --- /dev/null +++ b/crates/cairo-lang-dojo/src/plugin_test.rs @@ -0,0 +1,58 @@ +use cairo_lang_defs::plugin::{MacroPlugin, PluginGeneratedFile, PluginResult}; +use cairo_lang_diagnostics::{format_diagnostics, DiagnosticLocation}; +use cairo_lang_parser::test_utils::create_virtual_file; +use cairo_lang_parser::utils::{get_syntax_file_and_diagnostics, SimpleParserDatabase}; +use cairo_lang_syntax::node::TypedSyntaxNode; +use cairo_lang_utils::ordered_hash_map::OrderedHashMap; + +use crate::plugin::DojoPlugin; + +pub fn test_expand_contract( + inputs: &OrderedHashMap, +) -> OrderedHashMap { + let db = &mut SimpleParserDatabase::default(); + let cairo_code = &inputs["cairo_code"]; + let file_id = create_virtual_file(db, "dummy_file.cairo", cairo_code); + + let (syntax_file, diagnostics) = get_syntax_file_and_diagnostics(db, file_id, cairo_code); + assert_eq!(diagnostics.format(db), ""); + let file_syntax_node = syntax_file.as_syntax_node(); + let plugin = DojoPlugin {}; + let mut generated_items: Vec = Vec::new(); + let mut diagnostic_items: Vec = Vec::new(); + for item in syntax_file.items(db).elements(db).into_iter() { + let PluginResult { code, diagnostics, remove_original_item } = + plugin.generate_code(db, item.clone()); + + diagnostic_items.extend(diagnostics.iter().map(|diag| { + let syntax_node = file_syntax_node.lookup_ptr(db, diag.stable_ptr); + + let location = + DiagnosticLocation { file_id, span: syntax_node.span_without_trivia(db) }; + format_diagnostics(db, &diag.message, location) + })); + + let content = match code { + Some(PluginGeneratedFile { content, .. }) => content, + None => continue, + }; + if !remove_original_item { + generated_items.push(item.as_syntax_node().get_text(db)); + } + generated_items.push(content); + } + + OrderedHashMap::from([ + ("generated_cairo_code".into(), generated_items.join("\n")), + ("expected_diagnostics".into(), diagnostic_items.join("\n")), + ]) +} + +cairo_lang_test_utils::test_file_test!( + expand_contract, + "src/plugin_test_data", + { + hello_starknet: "hello_starknet", + }, + test_expand_contract +); diff --git a/crates/cairo-lang-dojo/src/plugin_test_data/hello_starknet b/crates/cairo-lang-dojo/src/plugin_test_data/hello_starknet new file mode 100644 index 0000000000..0cf9524bdb --- /dev/null +++ b/crates/cairo-lang-dojo/src/plugin_test_data/hello_starknet @@ -0,0 +1,143 @@ +//! > Test expansion of the hello_starknet contract. + +//! > test_function_name +test_expand_contract + +//! > cairo_code +#[contract] +mod HelloStarknet { + struct Storage { balance: felt, } + + // Increases the balance by the given amount. + #[external] + fn increase_balance(amount: felt) { + let res = balance::read(); + balance::write(res + amount); + } + + // Returns the current balance. + #[view] + fn get_balance() -> felt { + balance::read() + } +} + +//! > generated_cairo_code +#[generated_contract] +mod HelloStarknet { + + // Increases the balance by the given amount. + #[external] + fn increase_balance(amount: felt) { + let res = balance::read(); + balance::write(res + amount); + } + + // Returns the current balance. + #[view] + fn get_balance() -> felt { + balance::read() + } + + + mod balance { + fn address() -> starknet::StorageAddress { + starknet::storage_address_const::<0x206f38f7e4f15e87567361213c28f235cccdaa1d7fd34c9db1dfe9489c6a091>() + } + fn read() -> felt { + // Only address_domain 0 is currently supported. + let address_domain = 0; + match starknet::storage_read_syscall(address_domain, address()) { + Result::Ok(value) => value, + Result::Err(revert_reason) => { + let mut err_data = array_new::(); + array_append::(err_data, revert_reason); + panic(err_data) + }, + } + } + fn write(value: felt) { + // Only address_domain 0 is currently supported. + let address_domain = 0; + match starknet::storage_write_syscall(address_domain, address(), value) { + Result::Ok(()) => {}, + Result::Err(revert_reason) => { + let mut err_data = array_new::(); + array_append::(err_data, revert_reason); + panic(err_data) + }, + } + } + } + trait __abi { + fn increase_balance(amount: felt); + fn get_balance() -> felt; + + } + + mod __external { + fn increase_balance(mut data: Array::) -> Array:: { + match get_gas() { + Option::Some(_) => { + }, + Option::None(_) => { + let mut err_data = array_new::(); + array_append::(err_data, 'Out of gas'); + panic(err_data); + }, + } + + let __arg_amount = match serde::deserialize_felt(data) { + Option::Some(x) => x, + Option::None(()) => { + let mut err_data = array_new::(); + array_append::(err_data, 'Input too short for arguments'); + panic(err_data) + }, + }; + if array_len::(data) != 0_u128 { + // Force the inclusion of `System` in the list of implicits. + starknet::use_system_implicit(); + + let mut err_data = array_new::(); + array_append::(err_data, 'Input too long for arguments'); + panic(err_data); + } + super::increase_balance(__arg_amount); + let mut arr = array_new::(); + // References. + // Result. + arr + } + fn get_balance(mut data: Array::) -> Array:: { + match get_gas() { + Option::Some(_) => { + }, + Option::None(_) => { + let mut err_data = array_new::(); + array_append::(err_data, 'Out of gas'); + panic(err_data); + }, + } + + if array_len::(data) != 0_u128 { + // Force the inclusion of `System` in the list of implicits. + starknet::use_system_implicit(); + + let mut err_data = array_new::(); + array_append::(err_data, 'Input too long for arguments'); + panic(err_data); + } + + let res = super::get_balance(); + let mut arr = array_new::(); + // References. + // Result. + serde::serialize_felt(arr, res) + arr + } + + } +} + +//! > expected_diagnostics diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000000..71ed42e8fe --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,33 @@ +edition = "2021" +newline_style = "unix" +use_field_init_shorthand = true +use_small_heuristics = "Max" +use_try_shorthand = true +max_width = 100 + +# Unstable features below +unstable_features = true +version = "Two" +comment_width = 100 +format_code_in_doc_comments = true +format_macro_bodies = true +format_macro_matchers = true +format_strings = true +imports_granularity = "Module" +group_imports = "StdExternalCrate" +normalize_comments = true +normalize_doc_attributes = true +wrap_comments = true + +# To use these settings in vscode, add the following line to your settings: +# "rust-analyzer.rustfmt.overrideCommand": [ +# "rustup", +# "run", +# "nightly-2022-11-03", +# "--", +# "rustfmt", +# "--edition", +# "2021", +# "--" +# ] +# and run "rustup toolchain install nightly-2022-11-03".