From 7752d73216578d5961751b5d0535088d384b4aa6 Mon Sep 17 00:00:00 2001 From: Arnaud Bailly Date: Sat, 25 Jan 2025 10:45:41 +0100 Subject: Move λ-calcul workshop code to subdirectory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rust/.gitignore | 1 - rust/Cargo.lock | 2753 --------------------------------------- rust/Cargo.toml | 45 - rust/README.md | 42 - rust/cover.sh | 4 - rust/sample/test.txt | 5 - rust/sample/test01/input | 1 - rust/sample/test01/output | 1 - rust/sample/test02/input | 6 - rust/sample/test02/output | 4 - rust/sample/test03/input | 12 - rust/sample/test03/output | 9 - rust/sample/test_bool.txt | 15 - rust/sample/test_full.txt | 1 - rust/sample/test_let.txt | 1 - rust/sample/test_nat.txt | 9 - rust/sample/test_normal.txt | 1 - rust/src/ast.rs | 117 -- rust/src/io.rs | 73 -- rust/src/lambda.rs | 292 ----- rust/src/lib.rs | 4 - rust/src/main.rs | 18 - rust/src/parser.rs | 392 ------ rust/src/tester.rs | 100 -- rust/src/web.rs | 899 ------------- rust/templates/leaderboard.html | 50 - rust/tests/interpret_test.rs | 25 - 27 files changed, 4880 deletions(-) delete mode 100644 rust/.gitignore delete mode 100644 rust/Cargo.lock delete mode 100644 rust/Cargo.toml delete mode 100644 rust/README.md delete mode 100755 rust/cover.sh delete mode 100644 rust/sample/test.txt delete mode 100644 rust/sample/test01/input delete mode 100644 rust/sample/test01/output delete mode 100644 rust/sample/test02/input delete mode 100644 rust/sample/test02/output delete mode 100644 rust/sample/test03/input delete mode 100644 rust/sample/test03/output delete mode 100644 rust/sample/test_bool.txt delete mode 100644 rust/sample/test_full.txt delete mode 100644 rust/sample/test_let.txt delete mode 100644 rust/sample/test_nat.txt delete mode 100644 rust/sample/test_normal.txt delete mode 100644 rust/src/ast.rs delete mode 100644 rust/src/io.rs delete mode 100644 rust/src/lambda.rs delete mode 100644 rust/src/lib.rs delete mode 100644 rust/src/main.rs delete mode 100644 rust/src/parser.rs delete mode 100644 rust/src/tester.rs delete mode 100644 rust/src/web.rs delete mode 100644 rust/templates/leaderboard.html delete mode 100644 rust/tests/interpret_test.rs (limited to 'rust') diff --git a/rust/.gitignore b/rust/.gitignore deleted file mode 100644 index 2f7896d..0000000 --- a/rust/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target/ diff --git a/rust/Cargo.lock b/rust/Cargo.lock deleted file mode 100644 index bdb2dd9..0000000 --- a/rust/Cargo.lock +++ /dev/null @@ -1,2753 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "actix-codec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" -dependencies = [ - "bitflags", - "bytes", - "futures-core", - "futures-sink", - "memchr", - "pin-project-lite", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "actix-http" -version = "3.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d48f96fc3003717aeb9856ca3d02a8c7de502667ad76eeacd830b48d2e91fac4" -dependencies = [ - "actix-codec", - "actix-rt", - "actix-service", - "actix-utils", - "ahash", - "base64", - "bitflags", - "brotli", - "bytes", - "bytestring", - "derive_more", - "encoding_rs", - "flate2", - "futures-core", - "h2 0.3.26", - "http 0.2.12", - "httparse", - "httpdate", - "itoa", - "language-tags", - "local-channel", - "mime", - "percent-encoding", - "pin-project-lite", - "rand", - "sha1", - "smallvec", - "tokio", - "tokio-util", - "tracing", - "zstd", -] - -[[package]] -name = "actix-macros" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "actix-router" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" -dependencies = [ - "bytestring", - "cfg-if", - "http 0.2.12", - "regex", - "regex-lite", - "serde", - "tracing", -] - -[[package]] -name = "actix-rt" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" -dependencies = [ - "futures-core", - "tokio", -] - -[[package]] -name = "actix-server" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca2549781d8dd6d75c40cf6b6051260a2cc2f3c62343d761a969a0640646894" -dependencies = [ - "actix-rt", - "actix-service", - "actix-utils", - "futures-core", - "futures-util", - "mio", - "socket2", - "tokio", - "tracing", -] - -[[package]] -name = "actix-service" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" -dependencies = [ - "futures-core", - "paste", - "pin-project-lite", -] - -[[package]] -name = "actix-utils" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" -dependencies = [ - "local-waker", - "pin-project-lite", -] - -[[package]] -name = "actix-web" -version = "4.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9180d76e5cc7ccbc4d60a506f2c727730b154010262df5b910eb17dbe4b8cb38" -dependencies = [ - "actix-codec", - "actix-http", - "actix-macros", - "actix-router", - "actix-rt", - "actix-server", - "actix-service", - "actix-utils", - "actix-web-codegen", - "ahash", - "bytes", - "bytestring", - "cfg-if", - "cookie", - "derive_more", - "encoding_rs", - "futures-core", - "futures-util", - "impl-more", - "itoa", - "language-tags", - "log", - "mime", - "once_cell", - "pin-project-lite", - "regex", - "regex-lite", - "serde", - "serde_json", - "serde_urlencoded", - "smallvec", - "socket2", - "time", - "url", -] - -[[package]] -name = "actix-web-codegen" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8" -dependencies = [ - "actix-router", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "addr2line" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "getrandom", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[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 = "anstream" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" - -[[package]] -name = "anstyle-parse" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" -dependencies = [ - "anstyle", - "windows-sys 0.52.0", -] - -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener 2.5.3", - "futures-core", -] - -[[package]] -name = "async-channel" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-executor" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "slab", -] - -[[package]] -name = "async-global-executor" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" -dependencies = [ - "async-channel 2.3.1", - "async-executor", - "async-io", - "async-lock", - "blocking", - "futures-lite", - "once_cell", -] - -[[package]] -name = "async-io" -version = "2.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" -dependencies = [ - "async-lock", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite", - "parking", - "polling", - "rustix", - "slab", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "async-lock" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" -dependencies = [ - "event-listener 5.3.1", - "event-listener-strategy", - "pin-project-lite", -] - -[[package]] -name = "async-std" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" -dependencies = [ - "async-channel 1.9.0", - "async-global-executor", - "async-io", - "async-lock", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - -[[package]] -name = "async-task" -version = "4.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[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.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - -[[package]] -name = "backtrace" -version = "0.3.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets", -] - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[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 = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "blocking" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" -dependencies = [ - "async-channel 2.3.1", - "async-task", - "futures-io", - "futures-lite", - "piper", -] - -[[package]] -name = "brotli" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "4.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" - -[[package]] -name = "bytestring" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" -dependencies = [ - "bytes", -] - -[[package]] -name = "cc" -version = "1.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bbb537bb4a30b90362caddba8f360c0a56bc13d3a5570028e7197204cb54a17" -dependencies = [ - "jobserver", - "libc", - "shlex", -] - -[[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.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-targets", -] - -[[package]] -name = "clap" -version = "4.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" - -[[package]] -name = "colorchoice" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" - -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "cookie" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "cpufeatures" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - -[[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 = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "derive_more" -version = "0.99.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "encoding_rs" -version = "0.8.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "env_logger" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "event-listener" -version = "5.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" -dependencies = [ - "event-listener 5.3.1", - "pin-project-lite", -] - -[[package]] -name = "fastrand" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" - -[[package]] -name = "flate2" -version = "1.0.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-lite" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] - -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" - -[[package]] -name = "gloo-timers" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "h2" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http 1.1.0", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "handlebars" -version = "5.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b" -dependencies = [ - "log", - "pest", - "pest_derive", - "serde", - "serde_json", - "thiserror", - "walkdir", -] - -[[package]] -name = "hashbrown" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[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.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http 1.1.0", -] - -[[package]] -name = "http-body-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" -dependencies = [ - "bytes", - "futures-util", - "http 1.1.0", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "hyper" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "h2 0.4.6", - "http 1.1.0", - "http-body", - "httparse", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" -dependencies = [ - "futures-util", - "http 1.1.0", - "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http 1.1.0", - "http-body", - "hyper", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "impl-more" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206ca75c9c03ba3d4ace2460e57b189f39f43de612c2f85836e65c929701bb2d" - -[[package]] -name = "indexmap" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "ipnet" -version = "2.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[package]] -name = "jobserver" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - -[[package]] -name = "language-tags" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libc" -version = "0.2.158" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" - -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - -[[package]] -name = "local-channel" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" -dependencies = [ - "futures-core", - "futures-sink", - "local-waker", -] - -[[package]] -name = "local-waker" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" -dependencies = [ - "value-bag", -] - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" -dependencies = [ - "adler2", -] - -[[package]] -name = "mio" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" -dependencies = [ - "hermit-abi 0.3.9", - "libc", - "log", - "wasi", - "windows-sys 0.52.0", -] - -[[package]] -name = "native-tls" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "object" -version = "0.36.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "openssl" -version = "0.10.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "parking" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pest" -version = "2.7.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdbef9d1d47087a895abd220ed25eb4ad973a5e26f6a4367b038c25e28dfc2d9" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.7.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d3a6e3394ec80feb3b6393c725571754c6188490265c61aaf260810d6b95aa0" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.7.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94429506bde1ca69d1b5601962c73f4172ab4726571a59ea95931218cb0e930e" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pest_meta" -version = "2.7.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac8a071862e93690b6e34e9a5fb8e33ff3734473ac0245b27232222c4906a33f" -dependencies = [ - "once_cell", - "pest", - "sha2", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "piper" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" -dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", -] - -[[package]] -name = "pkg-config" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" - -[[package]] -name = "polling" -version = "3.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" -dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi 0.4.0", - "pin-project-lite", - "rustix", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "proc-macro2" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "proptest" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" -dependencies = [ - "bit-set", - "bit-vec", - "bitflags", - "lazy_static", - "num-traits", - "rand", - "rand_chacha", - "rand_xorshift", - "regex-syntax", - "rusty-fork", - "tempfile", - "unarray", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quote" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "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 = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core", -] - -[[package]] -name = "redox_syscall" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" -dependencies = [ - "bitflags", -] - -[[package]] -name = "regex" -version = "1.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-lite" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" - -[[package]] -name = "regex-syntax" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" - -[[package]] -name = "reqwest" -version = "0.12.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" -dependencies = [ - "base64", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.4.6", - "http 1.1.0", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-tls", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows-registry", -] - -[[package]] -name = "ring" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" -dependencies = [ - "cc", - "cfg-if", - "getrandom", - "libc", - "spin", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "rust" -version = "0.1.0" -dependencies = [ - "actix-web", - "async-std", - "chrono", - "clap", - "env_logger", - "futures", - "handlebars", - "log", - "proptest", - "rand", - "reqwest", - "serde", - "serde_json", - "tokio", - "uuid", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "rustix" -version = "0.38.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustls" -version = "0.23.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" -dependencies = [ - "once_cell", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" - -[[package]] -name = "rustls-webpki" -version = "0.102.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rusty-fork" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" -dependencies = [ - "fnv", - "quick-error", - "tempfile", - "wait-timeout", -] - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - -[[package]] -name = "serde" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.128" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "socket2" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "2.0.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" -dependencies = [ - "futures-core", -] - -[[package]] -name = "system-configuration" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" -dependencies = [ - "bitflags", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tempfile" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" -dependencies = [ - "cfg-if", - "fastrand", - "once_cell", - "rustix", - "windows-sys 0.59.0", -] - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "thiserror" -version = "1.0.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tinyvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.52.0", -] - -[[package]] -name = "tokio-macros" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" -dependencies = [ - "rustls", - "rustls-pki-types", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "log", - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "ucd-trie" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" - -[[package]] -name = "unarray" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" - -[[package]] -name = "unicode-bidi" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" - -[[package]] -name = "unicode-ident" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" - -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "uuid" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" -dependencies = [ - "getrandom", - "rand", - "serde", - "uuid-macro-internal", -] - -[[package]] -name = "uuid-macro-internal" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee1cd046f83ea2c4e920d6ee9f7c3537ef928d75dce5d84a87c2c5d6b3999a3a" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "value-bag" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "wait-timeout" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[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.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" -dependencies = [ - "cfg-if", - "once_cell", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" - -[[package]] -name = "web-sys" -version = "0.3.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[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.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.59.0", -] - -[[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-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-registry" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" -dependencies = [ - "windows-result", - "windows-strings", - "windows-targets", -] - -[[package]] -name = "windows-result" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-strings" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" -dependencies = [ - "windows-result", - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" - -[[package]] -name = "zstd" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "7.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" -dependencies = [ - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.13+zstd.1.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" -dependencies = [ - "cc", - "pkg-config", -] diff --git a/rust/Cargo.toml b/rust/Cargo.toml deleted file mode 100644 index b2eab9c..0000000 --- a/rust/Cargo.toml +++ /dev/null @@ -1,45 +0,0 @@ -[package] -name = "rust" -version = "0.1.0" -edition = "2021" - -[dependencies] -rand = { version = "0.8.5", features = ["small_rng"] } -serde = { version = "1.0", features = ["derive"] } -chrono = { version= "0.4.38", features = ["serde"]} -serde_json = "1.0.128" -actix-web = "4.9.0" -env_logger = "0.8" -log = "0.4" -futures = "0.3.30" -async-std = "1.13.0" -reqwest = "0.12.8" -tokio = { version = "1.40.0", features = ["rt", "macros", "rt-multi-thread"]} -clap = { version = "4.5.19", features = ["derive"] } -proptest = "1.0.0" -handlebars = { version = "5", features = ["dir_source"] } - -[dependencies.uuid] -version = "1.10.0" -features = [ - "v4", # Lets you generate random UUIDs - "fast-rng", # Use a faster (but still sufficiently random) RNG - "macro-diagnostics", # Enable better diagnostics for compile-time UUIDs - "serde" -] - -[lib] -name = "lambda" -path = "src/lib.rs" - -[[bin]] -name = "eval" -path = "src/main.rs" - -[[bin]] -name = "tester" -path = "src/tester.rs" - -[[bin]] -name = "server" -path = "src/web.rs" diff --git a/rust/README.md b/rust/README.md deleted file mode 100644 index 7dfc03b..0000000 --- a/rust/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# Rust λ-calcul reference implementation - -This directory contains a reference implementation of a normal order semantics λ-calculus based language. -Current syntax is based on S-expressions, ie. Lisp. There is a command-line interpreter for batch and interactive evaluation of input, and an embryonic tester daemon. - -# Tester - -The tester daemon is inspired by [Extreme Startup](https://github.com/rchatley/extreme_startup): It's a REST-ish server and client that allows to repeatedly send λ-terms to a remote execution engine and compare the result against its expectations. - -The interaction flow is simple: - -* HTTP server starts on some known port (eg. 8080) -* Client sends a `POST /register` request, passing in as payload a JSON object with a `url` and `name` string fields - ``` - curl -v -X POST -d '{"url":"http://127.0.0.1:8888/eval", "name": "toto"}' -H 'Content-type: application/json' http://localhost:8080/register - ``` -* Obviously, client needs to start a HTTP server able to respond to a `GET` request at the given URL -* If URL is not already registered, server accepts the registration (returning a 200 result) and starts a _testing thread_ -* The _tester_ then repeatedly sends `POST` requests to the client's registered URL - * The body of the request is plain text S-expression representing a λ-term - * The tester expects the response to be the plain text result of the evaluation of those terms -* If the client fails to answer, or answers wrongly, the server keeps sending the same request -* If the client's answer is correct, the server sends another term to evaluate and awards 1 point to the client -* The `/leaderboard` endpoint provides a crude HTML page listing each clients' current score - -## Building - -This software is written in Rust (sorry @xvdw), so one needs a Rust toolchain installed, then: - -``` -cargo build && cargo test -``` - -## Running - -To run the server: - -``` -cargo run --bin server -``` - -There are `--port` and `--host` arguments should one want to change the defaults `127.0.0.1:8080` diff --git a/rust/cover.sh b/rust/cover.sh deleted file mode 100755 index c7befa6..0000000 --- a/rust/cover.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' LLVM_PROFILE_FILE='cargo-test-%p-%m.profraw' cargo test -rm -fr target/coverage/html -grcov . --binary-path ./target/debug/deps/ -s . -t html --branch --ignore-not-existing --ignore '../*' --ignore "/*" -o target/coverage/html diff --git a/rust/sample/test.txt b/rust/sample/test.txt deleted file mode 100644 index 76dc68a..0000000 --- a/rust/sample/test.txt +++ /dev/null @@ -1,5 +0,0 @@ -12 -foo - true - -(x x) diff --git a/rust/sample/test01/input b/rust/sample/test01/input deleted file mode 100644 index 48082f7..0000000 --- a/rust/sample/test01/input +++ /dev/null @@ -1 +0,0 @@ -12 diff --git a/rust/sample/test01/output b/rust/sample/test01/output deleted file mode 100644 index 48082f7..0000000 --- a/rust/sample/test01/output +++ /dev/null @@ -1 +0,0 @@ -12 diff --git a/rust/sample/test02/input b/rust/sample/test02/input deleted file mode 100644 index 81a0443..0000000 --- a/rust/sample/test02/input +++ /dev/null @@ -1,6 +0,0 @@ -(def pair (lam (a b f) (f a b))) - -(def fst (lam p (p (lam ( a b) a)))) -(def snd (lam p (p (lam ( a b) b)))) - -(fst (snd (pair 1 (pair 2 0)))) diff --git a/rust/sample/test02/output b/rust/sample/test02/output deleted file mode 100644 index c61e10e..0000000 --- a/rust/sample/test02/output +++ /dev/null @@ -1,4 +0,0 @@ -true -true -true -2 diff --git a/rust/sample/test03/input b/rust/sample/test03/input deleted file mode 100644 index 6cff466..0000000 --- a/rust/sample/test03/input +++ /dev/null @@ -1,12 +0,0 @@ -(def zero (lam (f s) s)) -(def succ (lam (n f s) (f (n f s)))) - -(def one (succ zero)) -(def two (succ one)) -(def three (succ two)) -(def four (succ three)) -(def five (succ four)) - -(def plus (lam (a b f s) (a f (b f s)))) - -(plus one three) diff --git a/rust/sample/test03/output b/rust/sample/test03/output deleted file mode 100644 index fd56297..0000000 --- a/rust/sample/test03/output +++ /dev/null @@ -1,9 +0,0 @@ -true -true -true -true -true -true -true -true -four diff --git a/rust/sample/test_bool.txt b/rust/sample/test_bool.txt deleted file mode 100644 index a1b1309..0000000 --- a/rust/sample/test_bool.txt +++ /dev/null @@ -1,15 +0,0 @@ -(def True (lam (x y) x)) -(def False (lam (x y) y)) -(def and (lam (a b) (a b False))) -(def or (lam (a b) (a True b))) -(def not (lam a (a False True))) - -(and True True) -(and True False) -(and False True) -(and False False) - -(or True True) -(or True False) -(or False True) -(or False False) diff --git a/rust/sample/test_full.txt b/rust/sample/test_full.txt deleted file mode 100644 index ece76b8..0000000 --- a/rust/sample/test_full.txt +++ /dev/null @@ -1 +0,0 @@ -(((lam x (lam x x)) 13) true) diff --git a/rust/sample/test_let.txt b/rust/sample/test_let.txt deleted file mode 100644 index 6027cd0..0000000 --- a/rust/sample/test_let.txt +++ /dev/null @@ -1 +0,0 @@ -(let (foo (lam x x)) ((let (foo foo) foo) 13)) diff --git a/rust/sample/test_nat.txt b/rust/sample/test_nat.txt deleted file mode 100644 index 81a6e9d..0000000 --- a/rust/sample/test_nat.txt +++ /dev/null @@ -1,9 +0,0 @@ -(def pair (lam (a b f) (f a b))) -(def fst (lam p (p (lam (a b) a)))) -(def snd (lam p (p (lam (a b) b)))) - -(def zero (lam (f s) s)) -(def succ (lam (n f s) (f (n f s)))) - -(def is-zero (lam n - (n (lam x False) true))) diff --git a/rust/sample/test_normal.txt b/rust/sample/test_normal.txt deleted file mode 100644 index 00abde9..0000000 --- a/rust/sample/test_normal.txt +++ /dev/null @@ -1 +0,0 @@ -((lam x 1) ((lam x (x x)) (lam x (x x)))) diff --git a/rust/src/ast.rs b/rust/src/ast.rs deleted file mode 100644 index d0f1d6f..0000000 --- a/rust/src/ast.rs +++ /dev/null @@ -1,117 +0,0 @@ -use proptest::{ - prelude::*, - string::{string_regex, RegexGeneratorStrategy}, -}; -use serde::{Deserialize, Serialize}; -use std::fmt::{self, Display}; - -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -pub enum Value { - Num(i32), - Bool(bool), - Sym(String), - App(Box, Box), - Lam(String, Box), - Def(String, Box), - Let(String, Box, Box), -} - -use Value::*; - -impl Value { - /// Return the spine of an application - fn spine(&self) -> Vec { - match self { - App(l, r) => { - let mut spine = l.spine(); - spine.push(*r.clone()); - spine - } - _ => vec![self.clone()], - } - } -} - -impl Display for Value { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Value::Num(i) => write!(f, "{}", i), - Value::Bool(b) => write!(f, "{}", b), - Value::Sym(s) => write!(f, "{}", s), - Value::App(_, _) => { - let app = self - .spine() - .iter() - .map(|v| v.to_string()) - .collect::>() - .join(" "); - write!(f, "({})", app) - } - Value::Lam(var, body) => write!(f, "(lam {} {})", var, body), - Value::Def(var, value) => write!(f, "(def {} {})", var, value), - Value::Let(var, value, body) => write!(f, "(let ({} {}) {})", var, value, body), - } - } -} - -pub const IDENTIFIER: &str = "\\pL(\\pL|\\pN)*"; - -pub fn identifier() -> RegexGeneratorStrategy { - string_regex(IDENTIFIER).unwrap() -} - -pub fn ascii_identifier() -> RegexGeneratorStrategy { - string_regex("[a-zA-Z][a-zA-Z0-9]*").unwrap() -} - -impl Arbitrary for Value { - type Parameters = (); - type Strategy = BoxedStrategy; - - fn arbitrary_with(_args: ()) -> Self::Strategy { - let any_num = any::().prop_map(Num); - let any_bool = any::().prop_map(Bool); - let leaf = prop_oneof![ - any_num, - any_bool, - // see https://unicode.org/reports/tr18/#General_Category_Property for one letter unicode categories - identifier().prop_map(Sym), - ]; - let expr = leaf.prop_recursive(4, 128, 5, move |inner| { - prop_oneof![ - (inner.clone(), inner.clone()).prop_map(|(l, r)| App(Box::new(l), Box::new(r))), - (identifier(), inner.clone()).prop_map(|(var, body)| Lam(var, Box::new(body))), - (identifier(), inner.clone(), inner.clone()).prop_map(|(var, body, expr)| { - Value::Let(var, Box::new(body), Box::new(expr)) - }), - ] - }); - prop_oneof![ - expr.clone(), - (identifier(), expr).prop_map(|(var, body)| Def(var, Box::new(body))) - ] - .boxed() - } -} - -#[cfg(test)] -mod ast_tests { - - use super::Value::{self, *}; - use proptest::collection::vec; - use proptest::prelude::*; - - proptest! { - - #[test] - fn display_multiple_applications_as_a_sequence(atoms in vec("[a-z]".prop_map(Sym), 2..10)) { - let init = atoms.first().unwrap().clone(); - let value = atoms.iter().skip(1).fold(init, |acc, expr| { - Value::App(Box::new(acc.clone()), Box::new(expr.clone())) - }); - assert_eq!(value.to_string(), - format!("({})", - atoms.iter().map(|v| v.to_string()).collect::>().join(" "))); - } - } -} diff --git a/rust/src/io.rs b/rust/src/io.rs deleted file mode 100644 index 8c628ba..0000000 --- a/rust/src/io.rs +++ /dev/null @@ -1,73 +0,0 @@ -use std::{ - fs::read_to_string, - io::{BufRead, BufReader, Read, Write}, -}; - -use crate::{ - ast::Value, - lambda::{eval_all, eval_whnf, Environment}, - parser::parse, -}; - -pub fn eval_file(file_name: &str) -> String { - let content = read_to_string(file_name).unwrap(); - let values = parse(&content.to_string()); - eval_all(&values) - .iter() - .map(|v| v.to_string()) - .collect::>() - .join(" ") -} - -pub fn batch_eval(inp: &mut I, outp: &mut O) { - let mut env = Environment::new(); - let mut reader = BufReader::new(inp); - loop { - let mut input = String::new(); - outp.flush().unwrap(); - match reader.read_line(&mut input) { - Ok(0) => break, - Ok(_) => (), - Err(e) => { - writeln!(outp, "{}", e).unwrap(); - break; - } - } - let values = parse(&input); - let results = values - .iter() - .map(|v| eval_whnf(v, &mut env)) - .collect::>(); - for result in results { - writeln!(outp, "{}", result).unwrap(); - outp.flush().unwrap(); - } - } -} - -pub fn repl(inp: &mut I, outp: &mut O) { - let mut env = Environment::new(); - let mut reader = BufReader::new(inp); - loop { - let mut input = String::new(); - write!(outp, "> ").unwrap(); - outp.flush().unwrap(); - match reader.read_line(&mut input) { - Ok(0) => break, - Ok(_) => (), - Err(e) => { - writeln!(outp, "{}", e).unwrap(); - break; - } - } - let values = parse(&input); - let results = values - .iter() - .map(|v| eval_whnf(v, &mut env)) - .collect::>(); - for result in results { - writeln!(outp, "{}", result).unwrap(); - outp.flush().unwrap(); - } - } -} diff --git a/rust/src/lambda.rs b/rust/src/lambda.rs deleted file mode 100644 index a73ca34..0000000 --- a/rust/src/lambda.rs +++ /dev/null @@ -1,292 +0,0 @@ -use proptest::{ - arbitrary::any, - prelude::*, - strategy::{Strategy, ValueTree}, - test_runner::TestRunner, -}; -use rand::Rng; -use std::collections::HashMap; - -use crate::ast::*; - -#[derive(Debug, PartialEq)] -pub struct Environment<'a> { - parent: Box>>, - bindings: HashMap, -} - -impl<'a> Environment<'a> { - pub fn new() -> Self { - Environment { - parent: Box::new(None), - bindings: HashMap::new(), - } - } - - fn bind(&mut self, var: &str, value: &Value) { - self.bindings.insert(var.to_string(), value.clone()); - } - - fn extends(&'a self) -> Self { - Environment { - parent: Box::new(Some(self)), - bindings: HashMap::new(), - } - } - - fn lookup(&self, var: &str) -> Option<&Value> { - self.bindings.get(var).or_else(|| match *self.parent { - Some(parent) => parent.lookup(var), - None => None, - }) - } -} - -impl<'a> Default for Environment<'a> { - fn default() -> Self { - Self::new() - } -} - -pub fn eval_all(values: &[Value]) -> Vec { - let mut env = Environment::new(); - values.iter().map(|v| eval_whnf(v, &mut env)).collect() -} - -/// Reduce the given value to weak head normal form using call-by-name -/// evaluation strategy. -/// -/// call-by-name reduces the leftmost outermost redex first, which is -/// not under a lambda abstraction. -pub fn eval_whnf(arg: &Value, env: &mut Environment) -> Value { - match arg { - Value::Def(var, value) => { - env.bind(var, value); - Value::Bool(true) // TODO: return a more meaningful value? - } - Value::Let(var, value, expr) => { - let mut newenv = env.extends(); - newenv.bind(var, value); - eval_whnf(expr, &mut newenv) - } - Value::App(l, r) => match eval_whnf(l, env) { - Value::Lam(v, body) => eval_whnf(&subst(&v, &body, r), env), - Value::Sym(var) => match env.lookup(&var) { - Some(val) => eval_whnf(&Value::App(Box::new(val.clone()), r.clone()), env), - None => arg.clone(), - }, - other => Value::App(Box::new(other), r.clone()), - }, - Value::Sym(var) => env.lookup(var).unwrap_or(arg).clone(), - other => other.clone(), - } -} - -fn subst(var: &str, body: &Value, e: &Value) -> Value { - match body { - Value::Sym(x) if x == var => e.clone(), - Value::Lam(x, b) if x == var => { - let y = gensym(); - let bd = subst(x, b, &Value::Sym(y.clone())); - Value::Lam(y, Box::new(bd)) - } - Value::Lam(x, b) => Value::Lam(x.to_string(), Box::new(subst(var, b, e))), - Value::App(l, r) => Value::App(Box::new(subst(var, l, e)), Box::new(subst(var, r, e))), - other => other.clone(), - } -} - -pub fn gensym() -> String { - let mut rng = rand::thread_rng(); - - let n1: u8 = rng.gen(); - format!("x_{}", n1) -} - -pub fn generate_expr(size: u32, runner: &mut TestRunner) -> Value { - match size { - 0 | 1 => { - let n = any::().new_tree(runner).unwrap().current(); - Value::Num(n.into()) - } - 2 => Value::Sym(ascii_identifier().new_tree(runner).unwrap().current()), - 3 => any_sym().new_tree(runner).unwrap().current(), - 4 => simple_app().new_tree(runner).unwrap().current(), - 5 => nested_simple_app().new_tree(runner).unwrap().current(), - 6 => simple_lambda().new_tree(runner).unwrap().current(), - 7 => app_to_lambda().new_tree(runner).unwrap().current(), - 8 => multi_app().new_tree(runner).unwrap().current(), - _ => any::() - .prop_flat_map(gen_terms) - .new_tree(runner) - .unwrap() - .current(), - } -} - -pub fn generate_exprs(size: u32, runner: &mut TestRunner) -> Vec { - let sz = (0..size).new_tree(runner).unwrap().current(); - (0..sz) - .collect::>() - .into_iter() - .map(|_| generate_expr(size, runner)) - .collect() -} - -fn simple_app() -> impl Strategy { - let leaf = prop_oneof![any_num(), any_sym()]; - (leaf.clone(), leaf.clone()).prop_map(|(l, r)| Value::App(Box::new(l), Box::new(r))) -} - -fn multi_app() -> impl Strategy { - let leaf = prop_oneof![any_num(), any_sym()]; - (leaf.clone(), leaf.clone()).prop_map(|(l, r)| Value::App(Box::new(l), Box::new(r))) -} - -fn any_num() -> impl Strategy { - any::().prop_map(Value::Num) -} - -fn nested_simple_app() -> impl Strategy { - let leaf = prop_oneof![any_num(), ascii_identifier().prop_map(Value::Sym)]; - leaf.prop_recursive(4, 128, 5, move |inner| { - (inner.clone(), inner.clone()).prop_map(|(l, r)| Value::App(Box::new(l), Box::new(r))) - }) -} - -fn any_sym() -> impl Strategy { - identifier().prop_map(Value::Sym) -} - -fn simple_lambda() -> impl Strategy { - // TODO: there's nothing to guarantee the variable appears in the body - (ascii_identifier(), nested_simple_app()).prop_map(|(v, b)| Value::Lam(v, Box::new(b))) -} - -fn app_to_lambda() -> impl Strategy { - let lam = simple_lambda(); - let arg = prop_oneof![any_num(), any_sym(), nested_simple_app()]; - (lam, arg).prop_map(|(l, a)| Value::App(Box::new(l), Box::new(a))) -} - -/// Cantor pairing function -/// See https://en.wikipedia.org/wiki/Pairing_function -fn pairing(k: u32) -> (u32, u32) { - let a = ((((8 * (k as u64) + 1) as f64).sqrt() - 1.0) / 2.0).floor(); - let b = (a * (a + 1.0)) / 2.0; - let n = (k as f64) - b; - (n as u32, (a - n) as u32) -} - -fn gen_terms(u: u32) -> impl Strategy { - if u % 2 != 0 { - let j = (u - 1) / 2; - if j % 2 == 0 { - let k = j / 2; - let (n, m) = pairing(k); - let r = (gen_terms(n), gen_terms(m)) - .prop_map(move |(l, r)| Value::App(Box::new(l), Box::new(r))); - r.boxed() - } else { - let k = (j - 1) / 2; - let (n, m) = pairing(k); - let r = gen_terms(m).prop_map(move |v| Value::Lam(format!("x_{}", n), Box::new(v))); - r.boxed() - } - } else { - let j = u / 2; - Just(Value::Sym(format!("x_{}", j))).boxed() - } -} - -#[cfg(test)] -mod lambda_test { - use crate::parser::parse; - - use super::{eval_all, eval_whnf, Environment, Value}; - - fn parse1(string: &str) -> Value { - parse(string).pop().unwrap() - } - - fn eval1(value: &Value) -> Value { - eval_whnf(value, &mut Environment::new()) - } - - #[test] - fn evaluating_a_non_reducible_value_yields_itself() { - let value = parse1("(foo 12)"); - assert_eq!(value, eval1(&value)); - } - - #[test] - fn evaluating_application_on_an_abstraction_reduces_it() { - let value = parse1("((lam x x) 12)"); - assert_eq!(Value::Num(12), eval1(&value)); - } - - #[test] - fn substitution_occurs_within_abstraction_body() { - let value = parse1("(((lam x (lam y x)) 13) 12)"); - assert_eq!(Value::Num(13), eval1(&value)); - } - - #[test] - fn substitution_occurs_within_application_body() { - let value = parse1("(((lam x (lam y (y x))) 13) 12)"); - assert_eq!( - Value::App(Box::new(Value::Num(12)), Box::new(Value::Num(13))), - eval1(&value) - ); - } - - #[test] - fn substitution_does_not_capture_free_variables() { - let value = parse1("(((lam x (lam x x)) 13) 12)"); - assert_eq!(Value::Num(12), eval1(&value)); - } - - #[test] - fn interpretation_applies_to_both_sides_of_application() { - let value = parse1("((lam x x) ((lam x x) 12))"); - assert_eq!(Value::Num(12), eval1(&value)); - } - - #[test] - fn reduction_is_applied_until_normal_form_is_reached() { - let value = parse1("((((lam y (lam x (lam y (x y)))) 13) (lam x x)) 11)"); - assert_eq!(Value::Num(11), eval1(&value)); - } - - #[test] - fn reduction_always_select_leftmost_outermost_redex() { - // this should not terminate if we evaluate the rightmost redex first, eg. - // applicative order reduction - let value = parse1("((lam x 1) ((lam x (x x)) (lam x (x x))))"); - assert_eq!(Value::Num(1), eval1(&value)); - } - - #[test] - fn defined_symbols_are_evaluated_to_their_definition() { - let values = parse("(def foo 12) foo"); - assert_eq!(vec![Value::Bool(true), Value::Num(12)], eval_all(&values)); - } - - #[test] - fn let_expressions_bind_symbol_to_expression_in_environment() { - let values = parse("(let (foo (lam x x)) (foo 12))"); - assert_eq!(vec![Value::Num(12)], eval_all(&values)); - } - - #[test] - fn let_expressions_introduce_new_scope_for_bindings() { - let values = parse("(let (foo (lam x x)) ((let (foo foo) foo) 13))"); - assert_eq!(vec![Value::Num(13)], eval_all(&values)); - } - - #[test] - fn bound_symbol_in_higher_scope_are_resolved() { - let values = parse("(let (id (lam x x)) (let (foo 12) (id foo)))"); - assert_eq!(vec![Value::Num(12)], eval_all(&values)); - } -} diff --git a/rust/src/lib.rs b/rust/src/lib.rs deleted file mode 100644 index a8cf18e..0000000 --- a/rust/src/lib.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod ast; -pub mod io; -pub mod lambda; -pub mod parser; diff --git a/rust/src/main.rs b/rust/src/main.rs deleted file mode 100644 index 8d52c46..0000000 --- a/rust/src/main.rs +++ /dev/null @@ -1,18 +0,0 @@ -use std::{ - env::args, - io::{stdin, stdout, IsTerminal}, -}; - -use lambda::io::{batch_eval, eval_file, repl}; - -fn main() { - if args().count() > 1 { - for file in args().skip(1) { - println!("{}", eval_file(&file)); - } - } else if stdin().is_terminal() { - repl(&mut stdin(), &mut stdout()); - } else { - batch_eval(&mut stdin(), &mut stdout()); - } -} diff --git a/rust/src/parser.rs b/rust/src/parser.rs deleted file mode 100644 index 52aad5a..0000000 --- a/rust/src/parser.rs +++ /dev/null @@ -1,392 +0,0 @@ -use crate::ast::*; - -#[derive(Debug, PartialEq)] -enum Token { - LParen, - RParen, - Lambda, - Word(String), - Define, - Let, -} - -#[derive(Debug)] -struct Parser { - tokens: Vec, - index: usize, -} - -impl Parser { - fn expect(&mut self, token: Token) -> Result<(), String> { - if self.tokens.get(self.index) == Some(&token) { - Ok(()) - } else { - Err(format!( - "Expected {:?}, got {:?}", - token, - self.tokens.get(self.index) - )) - } - .map(|_| { - self.next(); - }) - } - - fn expect_symbol(&mut self) -> Result { - if let Token::Word(s) = self.tokens.get(self.index).ok_or("Expected a symbol")? { - Ok(s.clone()) - } else { - Err("Expected a symbol".to_string()) - } - .map(|s| { - self.next(); - s - }) - } - - fn next(&mut self) { - self.index += 1; - } - - fn backtrack(&mut self) { - self.index -= 1; - } -} - -pub fn parse(arg: &str) -> Vec { - parse_total(arg) - .map_err(|e| panic!("Syntax error: {}", e)) - .unwrap() -} - -pub fn parse_total(arg: &str) -> Result, String> { - let tokens = tokenize(arg); - let mut parser = Parser { tokens, index: 0 }; - let mut result = Vec::new(); - while parser.index < parser.tokens.len() { - let expr = parse_toplevel(&mut parser)?; - result.push(expr); - } - Ok(result) -} - -fn parse_toplevel(parser: &mut Parser) -> Result { - parse_definition(parser).or_else(|_| parse_expression(parser)) -} - -fn parse_definition(parser: &mut Parser) -> Result { - parser.expect(Token::LParen)?; - parser.expect(Token::Define).map_err(|e| { - parser.backtrack(); - e.to_string() - })?; - let var = parse_variable(parser)?; - let body = parse_expression(parser)?; - parser.expect(Token::RParen)?; - Ok(Value::Def(var, Box::new(body))) -} - -fn parse_expression(parser: &mut Parser) -> Result { - parse_value(parser) - .or_else(|_| parse_abstraction(parser)) - .or_else(|_| parse_let(parser)) - .or_else(|_| parse_application(parser)) -} - -fn parse_abstraction(parser: &mut Parser) -> Result { - parser.expect(Token::LParen)?; - parser.expect(Token::Lambda).map_err(|e| { - parser.backtrack(); - e.to_string() - })?; - let vars = parse_variables(parser)?; - let body = parse_expression(parser)?; - parser.expect(Token::RParen)?; - let result = vars - .iter() - .rev() - .fold(body, |acc, var| Value::Lam(var.clone(), Box::new(acc))); - Ok(result) -} - -fn parse_variables(parser: &mut Parser) -> Result, String> { - parse_variable(parser) - .map(|s| vec![s]) - .or_else(|_| parse_variables_list(parser)) -} - -fn parse_variables_list(parser: &mut Parser) -> Result, String> { - let mut vars = Vec::new(); - parser.expect(Token::LParen)?; - while let Ok(var) = parse_variable(parser) { - vars.push(var); - } - parser.expect(Token::RParen)?; - Ok(vars) -} - -fn parse_variable(parser: &mut Parser) -> Result { - let var = parser.expect_symbol()?; - Ok(var) -} - -fn parse_let(parser: &mut Parser) -> Result { - parser.expect(Token::LParen)?; - parser.expect(Token::Let).map_err(|e| { - parser.backtrack(); - e.to_string() - })?; - parser.expect(Token::LParen)?; - let var = parse_variable(parser)?; - let body = parse_expression(parser)?; - parser.expect(Token::RParen)?; - let expr = parse_expression(parser)?; - parser.expect(Token::RParen)?; - Ok(Value::Let(var, Box::new(body), Box::new(expr))) -} - -fn parse_application(parser: &mut Parser) -> Result { - parser.expect(Token::LParen)?; - let init = parse_expression(parser)?; - let mut exprs = Vec::new(); - while let Ok(expr) = parse_expression(parser) { - exprs.push(expr); - } - if exprs.is_empty() { - return Err("Application needs two values".to_string()); - } - parser.expect(Token::RParen)?; - let app: Value = exprs.iter().fold(init, |acc, expr| { - Value::App(Box::new(acc.clone()), Box::new(expr.clone())) - }); - Ok(app.to_owned()) -} - -fn parse_value(parser: &mut Parser) -> Result { - let token = parser.tokens.get(parser.index).ok_or("Expected a value")?; - let val = parse_number(token) - .or_else(|_| parse_bool(token)) - .or_else(|_| parse_symbol(token))?; - parser.next(); - Ok(val) -} - -fn tokenize(arg: &str) -> Vec { - let mut result = Vec::new(); - let mut word = String::new(); - - for c in arg.chars() { - match c { - '(' => { - terminate(&mut result, &mut word); - result.push(Token::LParen) - } - ')' => { - terminate(&mut result, &mut word); - result.push(Token::RParen) - } - c if c.is_whitespace() => terminate(&mut result, &mut word), - c => word.push(c), - } - } - terminate(&mut result, &mut word); - result -} - -fn terminate(result: &mut Vec, word: &mut String) { - if !word.is_empty() { - let w = word.clone(); - if w == "lam" { - result.push(Token::Lambda); - } else if w == "def" { - result.push(Token::Define); - } else if w == "let" { - result.push(Token::Let); - } else { - result.push(Token::Word(w)); - } - word.clear(); - } -} - -fn parse_symbol(token: &Token) -> Result { - match token { - Token::Word(s) => Ok(Value::Sym(s.clone())), - _ => Err(format!("Expected a symbol, got {:?}", token)), - } -} - -fn parse_bool(token: &Token) -> Result { - match token { - Token::Word(s) => s - .parse::() - .map(Value::Bool) - .map_err(|e| e.to_string()), - _ => Err("Expected a boolean".to_string()), - } -} - -fn parse_number(token: &Token) -> Result { - match token { - Token::Word(s) => s.parse::().map(Value::Num).map_err(|e| e.to_string()), - _ => Err("Expected an integer".to_string()), - } -} - -#[cfg(test)] -mod tests { - use super::parse_total; - - use super::Token::*; - use super::Value; - use super::Value::*; - use super::{parse, tokenize}; - use proptest::prelude::*; - - proptest! { - #[test] - fn parse_integer_as_number(i in -1000i32..1000) { - let result = parse(&i.to_string()); - assert_eq!(vec![Num(i)], result); - } - - } - - #[test] - fn parse_truth_values_as_booleans() { - assert_eq!(vec![Bool(true)], parse("true")); - assert_eq!(vec![Bool(false)], parse("false")); - } - - #[test] - fn parse_identifiers_values_as_symbols() { - assert_eq!(vec![Sym("foo".to_string())], parse("foo")); - } - - #[test] - fn ignores_whitespace() { - assert_eq!(vec![Sym("foo".to_string())], parse(" foo \n\r")); - assert_eq!(vec![Num(-42)], parse("\n-42")); - } - - #[test] - fn tokenize_several_values() { - assert_eq!( - vec![ - Word("42".to_string()), - Word("foo".to_string()), - Word("true".to_string()) - ], - tokenize("42 foo \ntrue ") - ); - } - - #[test] - fn tokenize_string_with_parens() { - assert_eq!( - vec![ - LParen, - LParen, - RParen, - Word("42".to_string()), - RParen, - Word("true".to_string()), - LParen, - ], - tokenize("( \r() 42) \ntrue( ") - ); - } - - #[test] - fn tokenize_lambda_symbol() { - assert_eq!(vec![Lambda, LParen,], tokenize("lam (")); - } - - #[test] - fn parse_application_of_two_values() { - assert_eq!( - vec![App(Box::new(Sym("foo".to_string())), Box::new(Num(42)))], - parse("(foo 42)") - ); - } - - #[test] - fn reject_application_of_single_value() { - assert_eq!( - Err("Application needs two values".to_string()), - parse_total("(foo )") - ); - } - - #[test] - fn desugar_application_of_more_than_two_values() { - assert_eq!( - vec![App( - Box::new(App( - Box::new(App(Box::new(Sym("foo".to_string())), Box::new(Num(42)))), - Box::new(Bool(true)) - )), - Box::new(Sym("f".to_string())) - )], - parse("(foo 42 true f)") - ); - } - - #[test] - fn parse_abstraction() { - assert_eq!( - vec![Lam( - "x".to_string(), - Box::new(App( - Box::new(Sym("x".to_string())), - Box::new(Sym("x".to_string())) - )) - )], - parse("(lam x (x x))") - ); - } - - #[test] - fn desugar_abstraction_with_several_variables_into_nested_lambdas() { - assert_eq!( - vec![Lam( - "x".to_string(), - Box::new(Lam("y".to_string(), Box::new(Sym("y".to_string())))) - )], - parse("(lam (x y) y)") - ); - } - - #[test] - fn parse_definition() { - assert_eq!( - vec![Def("x".to_string(), Box::new(Num(12)))], - parse("(def x 12)") - ); - } - - #[test] - fn parse_multiple_values() { - assert_eq!(vec![Sym("foo".to_string()), Num(42)], parse("foo 42")); - } - - #[test] - fn parse_let_expressions() { - assert_eq!( - vec![Value::Let( - "x".to_string(), - Box::new(Num(12)), - Box::new(Sym("x".to_string())) - )], - parse("(let (x 12) x)") - ); - } - - proptest! { - #[test] - fn parse_is_inverse_to_display(values in any::>()) { - let result : Vec = values.iter().map(|v:&Value| v.to_string()).collect(); - assert_eq!(values, result.iter().flat_map(|s| parse(s)).collect::>()); - } - } -} diff --git a/rust/src/tester.rs b/rust/src/tester.rs deleted file mode 100644 index eb66d4e..0000000 --- a/rust/src/tester.rs +++ /dev/null @@ -1,100 +0,0 @@ -use serde::{Deserialize, Serialize}; -use std::{ - fs::{self, read_to_string, File}, - path::PathBuf, - process::{Command, Stdio}, - time::Instant, -}; - -pub fn main() { - let mut args: Vec = std::env::args().collect(); - // name of the process to run - let proc = args.remove(1); - if args.len() > 1 { - let run = traverse(&args) - .and_then(|paths| run_test(&proc, &paths)) - .expect("Failed to traverse directory"); - println!("{}", serde_json::to_string_pretty(&run).unwrap()); - } else { - println!( - r#"Usage: tester [options] + - -Options: - -p, --process The process to run. If the given process is not a - an absolute path, it will be resolved against the - PATH environment variable. - -j, --json Output the results in JSON format (default: false) - -h, --help Display this help message - -v, --version Display the version of the tester -"# - ); - } -} - -fn traverse(args: &[String]) -> Result, String> { - let mut files: Vec = Vec::new(); - for arg in args.iter().skip(1) { - let entries = fs::read_dir(arg).map_err(|e| e.to_string())?; - for entry in entries { - let dir = entry.map_err(|e| e.to_string())?; - let f = dir.metadata().map_err(|e| e.to_string())?; - if f.is_dir() { - files.push(dir.path()); - } - } - } - Ok(files) -} - -#[derive(Debug, Serialize, Deserialize)] -pub enum TestResult { - TestSucceeded, - TestFailed(String, String), -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct TestRun { - file: String, - test_result: TestResult, - duration: u128, -} - -fn run_test(proc: &str, files: &Vec) -> Result, String> { - let mut result = Vec::new(); - for file in files { - let mut inp = file.clone(); - let mut outp = file.clone(); - inp.push("input"); - outp.push("output"); - let (test_result, duration) = run_test_case(proc, &inp, &outp)?; - result.push(TestRun { - file: inp.as_path().to_str().unwrap().to_string(), - test_result, - duration, - }); - } - Ok(result) -} - -fn run_test_case( - proc: &str, - inp: &std::path::PathBuf, - outp: &std::path::PathBuf, -) -> Result<(TestResult, u128), String> { - let input = File::open(inp).map_err(|e| e.to_string())?; - let expected = read_to_string(outp).map_err(|e| e.to_string())?; - let start = Instant::now(); - - let actual = Command::new(proc) - .stdin(Stdio::from(input)) - .output() - .map_err(|e| e.to_string())?; - - let duration = (Instant::now() - start).as_millis(); - if expected.as_bytes() == actual.stdout { - Ok((TestResult::TestSucceeded, duration)) - } else { - let actual_string = String::from_utf8(actual.stdout).map_err(|e| e.to_string())?; - Ok((TestResult::TestFailed(expected, actual_string), duration)) - } -} diff --git a/rust/src/web.rs b/rust/src/web.rs deleted file mode 100644 index 3f8f056..0000000 --- a/rust/src/web.rs +++ /dev/null @@ -1,899 +0,0 @@ -use actix_web::{get, middleware::Logger, post, web, App, HttpResponse, HttpServer, Responder}; -use chrono::{DateTime, Utc}; -use clap::Parser; -use handlebars::{DirectorySourceOptions, Handlebars}; -use log::info; -use proptest::test_runner::{Config, RngAlgorithm, TestRng, TestRunner}; -use rand::Rng; -use serde::{Deserialize, Serialize}; -use std::sync::Mutex; -use std::time::Duration; -use std::{collections::HashMap, sync::Arc}; -use tokio::task::{self, JoinHandle}; -use uuid::Uuid; - -use lambda::lambda::{eval_all, eval_whnf, generate_expr, generate_exprs, gensym, Environment}; -use lambda::parser::{parse, parse_total}; - -#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] -struct Registration { - url: String, - name: String, -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -struct ClientData { - name: String, - grade: u8, - last_query: DateTime, - success: bool, -} - -impl ClientData { - fn from(client: &Client) -> Self { - ClientData { - name: client.name.clone(), - grade: client.grade, - last_query: client - .results - .last() - .map_or(chrono::offset::Utc::now(), |q| q.timestamp), - success: client - .results - .last() - .map_or(false, |q| matches!(q.result, TestResult::TestSucceeded)), - } - } -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -struct Leaderboard { - clients: Vec, -} - -trait AppState: Send + Sync { - fn register(&mut self, registration: &Registration) -> RegistrationResult; - fn unregister(&mut self, url: &String); -} - -#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] -enum RegistrationResult { - RegistrationSuccess { id: String, url: String }, - UrlAlreadyRegistered { url: String }, -} - -#[derive(Debug, Clone)] -struct Client { - id: Uuid, - name: String, - url: String, - grade: u8, - runner: TestRunner, - results: Vec, - delay: std::time::Duration, -} - -#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] -struct Test { - timestamp: DateTime, - result: TestResult, -} - -#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] -enum TestResult { - TestFailed(String), - ErrorSendingTest(String), - TestSucceeded, -} - -impl Client { - fn new(url: String, name: String, delay: Duration) -> Self { - let id = Uuid::new_v4(); - let runner = TestRunner::new_with_rng( - Config::default(), - TestRng::from_seed(RngAlgorithm::XorShift, &id.to_bytes_le()), - ); - Self { - id, - url, - name, - grade: 1, - runner, - results: Vec::new(), - delay, - } - } - - fn time_to_next_test(&self) -> Duration { - self.delay - } - - fn generate_expr(&mut self) -> (String, String) { - if self.grade >= 10 { - self.generate_exprs() - } else { - let input = generate_expr(self.grade.into(), &mut self.runner); - let expected = eval_whnf(&input, &mut Environment::new()); - (input.to_string(), expected.to_string()) - } - } - - fn generate_exprs(&mut self) -> (String, String) { - let exprs = generate_exprs(self.grade.into(), &mut self.runner); - let input = exprs - .iter() - .map(|v| format!("{}", v)) - .collect::>() - .join("\n"); - let expected = eval_all(&exprs); - ( - input, - expected - .iter() - .map(|v| format!("{}", v)) - .collect::>() - .join("\n"), - ) - } - - /// Applies a `Test` to update client's state - fn apply(&mut self, test: &Test) { - match test.result { - TestResult::TestSucceeded => { - self.grade = self.grade.saturating_add(1); - self.delay = Duration::from_secs_f64(self.delay.as_secs_f64() * 0.8); - if self.delay.as_millis() < 500 { - self.delay = Duration::from_millis(500); - } - } - TestResult::TestFailed(_) => { - self.delay = Duration::from_secs_f64(self.delay.as_secs_f64() * 1.2); - if self.delay.as_secs() > 30 { - self.delay = Duration::from_secs(30); - } - } - _ => (), - } - self.results.push(test.clone()); - } - - fn check_result(&self, expected: &String, response: &Result) -> Test { - let result = match response { - Ok(expr) => { - let vals = parse(expr); - let actual = eval_all(&vals) - .iter() - .map(|v| format!("{}", v)) - .collect::>() - .join("\n"); - if actual == *expected { - TestResult::TestSucceeded - } else { - TestResult::TestFailed(actual) - } - } - Err(res) => res.clone(), - }; - Test { - result, - timestamp: chrono::offset::Utc::now(), - } - } -} - -#[derive(Debug)] -struct State { - base_duration: Duration, - clients: HashMap>, JoinHandle<()>)>, -} - -impl State { - fn new() -> Self { - State::with_duration(Duration::from_secs(10)) - } - - fn with_duration(base_duration: Duration) -> Self { - Self { - base_duration, - clients: HashMap::new(), - } - } - - fn client_events(&self, url: &String) -> usize { - let client = self.clients.get(url).unwrap().0.lock().unwrap(); - client.results.len() - } -} - -impl AppState for State { - fn register(&mut self, registration: &Registration) -> RegistrationResult { - if self.clients.contains_key(®istration.url) { - RegistrationResult::UrlAlreadyRegistered { - url: registration.url.clone(), - } - } else { - let client = Client::new( - registration.url.clone(), - registration.name.clone(), - self.base_duration, - ); - let id = client.id.to_string(); - let client_ref = Arc::new(Mutex::new(client)); - // let it run in the background - // FIXME: should find a way to handle graceful termination - let client_handle = task::spawn(send_tests(client_ref.clone())); - - self.clients.insert( - registration.url.clone(), - (client_ref.clone(), client_handle), - ); - - RegistrationResult::RegistrationSuccess { - id, - url: registration.url.clone(), - } - } - } - - fn unregister(&mut self, url: &String) { - let (_, handle) = self.clients.get(url).unwrap(); - handle.abort() - } -} - -#[post("/register")] -async fn register( - app_state: web::Data>>, - registration: web::Json, -) -> impl Responder { - let result = app_state.lock().unwrap().register(®istration); - match result { - RegistrationResult::RegistrationSuccess { .. } => HttpResponse::Ok().json(result), - RegistrationResult::UrlAlreadyRegistered { .. } => HttpResponse::BadRequest().json(result), - } -} - -#[post("/eval")] -async fn eval(input: String) -> impl Responder { - let exprs = parse_total(&input); - match exprs { - Ok(exprs) => { - let mut rng = rand::thread_rng(); - if rng.gen_range(0..10) <= 2 { - return HttpResponse::Ok().body(gensym()); - } - let output = eval_all(&exprs) - .iter() - .map(|v| format!("{}", v)) - .collect::>() - .join("\n"); - HttpResponse::Ok().body(output.to_string()) - } - Err(e) => HttpResponse::BadRequest().body(e.to_string()), - } -} - -#[get("/leaderboard")] -async fn leaderboard( - app_state: web::Data>>, - hb: web::Data>, -) -> impl Responder { - let clients = &app_state.lock().unwrap().clients; - let mut client_data = vec![]; - for client in clients.values() { - let client = client.0.lock().unwrap(); - client_data.push(ClientData::from(&client)); - } - client_data.sort_by(|a, b| b.grade.cmp(&a.grade)); - - let body = hb - .render( - "leaderboard", - &Leaderboard { - clients: client_data, - }, - ) - .unwrap(); - - web::Html::new(body) -} - -#[derive(Parser, Debug)] -struct Options { - /// The port to listen on - /// Defaults to 8080 - #[arg(short, long, default_value_t = 8080)] - port: u16, - /// The host to bind the server to - /// Defaults to 127.0.0.1 - #[arg(long, default_value = "127.0.0.1")] - host: String, -} - -#[tokio::main] -async fn main() -> std::io::Result<()> { - let options = Options::parse(); - let app_state = Arc::new(Mutex::new(State::new())); - - env_logger::init(); - // Handlebars uses a repository for the compiled templates. This object must be - // shared between the application threads, and is therefore passed to the - // Application Builder as an atomic reference-counted pointer. - let mut handlebars = Handlebars::new(); - handlebars - .register_templates_directory( - "./templates", - DirectorySourceOptions { - tpl_extension: ".html".to_owned(), - hidden: false, - temporary: false, - }, - ) - .unwrap(); - - HttpServer::new(move || { - App::new() - .wrap(Logger::default()) - .app_data(web::Data::new(app_state.clone())) - .app_data(web::Data::new(handlebars.clone())) - .service(register) - .service(eval) - .service(leaderboard) - }) - .bind((options.host, options.port))? - .run() - .await -} - -fn get_test(client_m: &Mutex) -> (String, String, String) { - let mut client = client_m.lock().unwrap(); - let (input, expected) = client.generate_expr(); - (input, client.url.clone(), expected) -} - -async fn send_tests(client_m: Arc>) { - loop { - let sleep = sleep_time(&client_m); - tokio::time::sleep(sleep).await; - { - let (input, url, expected) = get_test(&client_m); - - let response = send_test(&input, &url, sleep).await; - - apply_result(&client_m, expected, response); - } - } -} - -fn apply_result(client_m: &Mutex, expected: String, response: Result) { - let mut client = client_m.lock().unwrap(); - let test = client.check_result(&expected, &response); - client.apply(&test); -} - -fn sleep_time(client_m: &Arc>) -> Duration { - client_m.lock().unwrap().time_to_next_test() -} - -async fn send_test(input: &String, url: &String, timeout: Duration) -> Result { - info!("Sending {} to {}", input, url); - let body = input.clone(); - let response = reqwest::Client::new() - .post(url) - .timeout(timeout) - .header("content-type", "text/plain") - .body(body) - .send() - .await; - match response { - Ok(response) => { - let body = response.text().await.unwrap(); - info!("Response from {}: {}", url, body); - Ok(body) - } - Err(e) => { - info!("Error sending test: {}", e); - Err(TestResult::ErrorSendingTest(e.to_string())) - } - } -} - -#[cfg(test)] -mod app_tests { - use std::str::from_utf8; - use std::sync::Arc; - - use actix_web::http::header::TryIntoHeaderValue; - use actix_web::{body, http::header::ContentType, middleware::Logger, test, App}; - use lambda::ast::Value; - - use super::*; - - #[actix_web::test] - async fn post_registration_returns_success_with_unique_id() { - let state = Arc::new(Mutex::new(State::new())); - // FIXME should only be called once, move to setup - env_logger::init(); - - let app = test::init_service( - App::new() - .wrap(Logger::default()) - .app_data(web::Data::new(state)) - .service(register), - ) - .await; - let url = "http://192.168.1.1".to_string(); - let req = test::TestRequest::post() - .uri("/register") - .set_json(Registration { - url: url.clone(), - name: "foo".to_string(), - }) - .insert_header(ContentType::json()) - .to_request(); - - let resp = test::call_service(&app, req).await; - - assert!(resp.status().is_success()); - - let body = resp.into_body(); - let bytes = body::to_bytes(body).await; - match serde_json::from_slice::(bytes.as_ref().unwrap()).unwrap() { - RegistrationResult::RegistrationSuccess { id: _, url: url1 } => assert_eq!(url1, url), - _ => panic!("Expected RegistrationSuccess, got {:?}", bytes.unwrap()), - }; - } - - #[actix_web::test] - async fn post_registration_returns_400_when_register_fails() { - let state = Arc::new(Mutex::new(State::new())); - - let app = test::init_service( - App::new() - .wrap(Logger::default()) - .app_data(web::Data::new(state.clone())) - .service(register), - ) - .await; - let url = "http://192.168.1.1".to_string(); - let registration = Registration { - url: url.clone(), - name: "foo".to_string(), - }; - - state.lock().unwrap().register(®istration); - - let req = test::TestRequest::post() - .uri("/register") - .set_json(registration) - .insert_header(ContentType::json()) - .to_request(); - - let resp = test::call_service(&app, req).await; - - assert!(resp.status().is_client_error()); - assert_eq!( - ContentType::json().try_into_value().unwrap(), - resp.headers().get("content-type").unwrap() - ); - } - - #[actix_web::test] - async fn post_expression_returns_evaluation() { - let app = test::init_service(App::new().wrap(Logger::default()).service(eval)).await; - - let req = test::TestRequest::post() - .uri("/eval") - .set_payload("((lam (x y) x) 1 2)") - .insert_header(ContentType::plaintext()) - .to_request(); - - let resp = test::call_service(&app, req).await; - - assert!(resp.status().is_success()); - - let body = resp.into_body(); - let bytes = body::to_bytes(body).await.unwrap(); - assert_eq!(bytes, "1".to_string().into_bytes()); - } - - #[actix_web::test] - async fn post_expression_returns_multiple_evaluations() { - let app = test::init_service(App::new().wrap(Logger::default()).service(eval)).await; - - let req = test::TestRequest::post() - .uri("/eval") - .set_payload("((lam (x y) x) 1 2)\n42") - .insert_header(ContentType::plaintext()) - .to_request(); - - let resp = test::call_service(&app, req).await; - - assert!(resp.status().is_success()); - - let body = resp.into_body(); - let bytes = body::to_bytes(body).await.unwrap(); - assert_eq!("1\n42".to_string().into_bytes(), bytes); - } - - #[actix_web::test] - async fn get_leaderboard_returns_html_page_listing_clients_state() { - let app_state = Arc::new(Mutex::new(State::new())); - app_state.lock().unwrap().register(&Registration { - url: "http://1.2.3.4".to_string(), - name: "client1".to_string(), - }); - - let mut handlebars = Handlebars::new(); - handlebars - .register_templates_directory( - "./templates", - DirectorySourceOptions { - tpl_extension: ".html".to_owned(), - hidden: false, - temporary: false, - }, - ) - .unwrap(); - - let app = test::init_service( - App::new() - .wrap(Logger::default()) - .app_data(web::Data::new(app_state.clone())) - .app_data(web::Data::new(handlebars.clone())) - .service(leaderboard), - ) - .await; - - let req = test::TestRequest::get().uri("/leaderboard").to_request(); - - let resp = test::call_service(&app, req).await; - - assert!(resp.status().is_success()); - - let bytes = body::to_bytes(resp.into_body()).await.unwrap(); - assert!(from_utf8(&bytes).unwrap().contains("client1")); - } - - #[test] - async fn app_does_not_register_same_url_twice() { - let mut app_state = State::new(); - let registration = Registration { - name: "foo".to_string(), - url: "http://1.2.3.4".to_string(), - }; - - app_state.register(®istration); - let result = app_state.register(®istration); - - assert_eq!( - RegistrationResult::UrlAlreadyRegistered { - url: "http://1.2.3.4".to_string() - }, - result - ); - } - - #[test] - async fn unregistering_registered_client_stops_tester_thread_from_sending_tests() { - let mut app_state = State::with_duration(Duration::from_millis(100)); - let registration = Registration { - name: "foo".to_string(), - url: "http://1.2.3.4".to_string(), - }; - - let reg = app_state.register(®istration); - assert!(matches!( - reg, - RegistrationResult::RegistrationSuccess { .. } - )); - - tokio::time::sleep(Duration::from_millis(500)).await; - - app_state.unregister(®istration.url); - - let grade_before = app_state.client_events(®istration.url); - tokio::time::sleep(Duration::from_millis(500)).await; - let grade_after = app_state.client_events(®istration.url); - - assert_eq!(grade_before, grade_after); - } - - fn client() -> Client { - Client::new( - "http://1.2.3.4".to_string(), - "foo".to_string(), - Duration::from_secs(10), - ) - } - - #[test] - async fn client_generates_constant_at_level_1() { - let mut client = client(); - - let (input, _) = client.generate_expr(); - - match parse(&input)[..] { - [Value::Num(_)] => (), - _ => panic!("Expected constant 3"), - } - } - - #[test] - async fn client_generates_different_inputs_on_each_call() { - let mut client = client(); - - let (input1, _) = client.generate_expr(); - let (input2, _) = client.generate_expr(); - - assert_ne!(input1, input2); - } - - #[test] - async fn client_generates_ascii_variables_at_level_2() { - let mut client = client(); - client.grade = 2; - - let (input, _) = client.generate_expr(); - - let parsed = parse(&input); - match &parsed[..] { - [Value::Sym(name)] => { - assert!(name.chars().all(|c| c.is_ascii_alphanumeric())); - } - _ => panic!("Expected symbol, got {:?}", parsed), - } - } - - #[test] - async fn client_generates_unicode_variables_at_level_3() { - let mut client = client(); - client.grade = 3; - - let (input, _) = client.generate_expr(); - - let parsed = parse(&input); - match &parsed[..] { - [Value::Sym(_)] => (), - _ => panic!("Expected symbol, got {:?}", parsed), - } - } - - #[test] - async fn client_generates_binary_application_at_level_4() { - let mut client = client(); - client.grade = 4; - - let (input, _) = client.generate_expr(); - - let parsed = parse(&input); - match &parsed[..] { - [Value::App(_, _)] => (), - _ => panic!("Expected symbol, got {:?}", parsed), - } - } - - #[test] - async fn client_generates_nested_applications_and_constants_at_level_5() { - let mut client = client(); - client.grade = 5; - - let (input, _) = client.generate_expr(); - - let parsed = parse(&input); - match &parsed[..] { - [Value::App(_, _)] => (), - [Value::Sym(_)] => (), - [Value::Num(_)] => (), - _ => panic!("Expected symbol, got {:?}", parsed), - } - } - - #[test] - async fn client_generates_lambda_terms_at_level_6() { - let mut client = client(); - client.grade = 6; - - let (input, _) = client.generate_expr(); - - let parsed = parse(&input); - match &parsed[..] { - [Value::Lam(_, _)] => (), - _ => panic!("Expected symbol, got {:?}", parsed), - } - } - - #[test] - async fn client_generates_application_with_lambda_terms_at_level_7() { - let mut client = client(); - client.grade = 7; - - let (input, _) = client.generate_expr(); - - let parsed = parse(&input); - match &parsed[..] { - [Value::App(t1, _)] if matches!(**t1, Value::Lam(_, _)) => (), - _ => panic!("Expected symbol, got {:?}", parsed), - } - } - - #[test] - async fn client_generates_applications_with_more_than_2_terms_at_level_8() { - let mut client = client(); - client.grade = 8; - - let (input, _) = client.generate_expr(); - - let parsed = parse(&input); - if let [Value::App(_, _)] = &parsed[..] { - assert!(input.split(' ').count() >= 2) - } - } - - #[test] - async fn client_generates_more_complex_terms_at_level_9() { - let mut client = client(); - client.grade = 9; - - let (input, _) = client.generate_expr(); - - let parsed = parse(&input); - - assert!(!parsed.is_empty()); - } - - #[test] - async fn client_generates_multiple_terms_at_level_10() { - let mut client = client(); - client.grade = 10; - - let (input, _) = client.generate_expr(); - - let parsed = parse(&input); - - assert!(!parsed.is_empty()); - } - - #[test] - async fn client_increases_grade_on_successful_test() { - let mut client = client(); - let test = Test { - timestamp: chrono::offset::Utc::now(), - result: TestResult::TestSucceeded, - }; - - client.apply(&test); - - assert_eq!(2, client.grade); - } - - #[test] - async fn client_stores_test_results() { - let mut client = client(); - let test = Test { - timestamp: chrono::offset::Utc::now(), - result: TestResult::TestSucceeded, - }; - - client.apply(&test); - - assert_eq!(test, client.results.first().unwrap().clone()); - } - - #[test] - async fn client_returns_test_successful_if_result_match() { - let client = client(); - let expected = "1".to_string(); - let response = Ok("1".to_string()); - - let test = client.check_result(&expected, &response); - - assert_eq!(TestResult::TestSucceeded, test.result); - } - - #[test] - async fn client_returns_test_failed_given_result_do_not_match() { - let client = client(); - let expected = "1".to_string(); - let response = Ok("2".to_string()); - - let test = client.check_result(&expected, &response); - - assert_eq!(TestResult::TestFailed("2".to_string()), test.result); - } - - #[test] - async fn client_does_not_increase_grade_on_failed_test() { - let mut client = client(); - let test = Test { - timestamp: chrono::offset::Utc::now(), - result: TestResult::TestFailed("2".to_string()), - }; - - client.apply(&test); - - assert_eq!(1, client.grade); - } - - #[test] - async fn client_starts_delay_to_next_test_at_10s() { - let client = client(); - - let delay = client.time_to_next_test(); - - assert_eq!(std::time::Duration::from_secs(10), delay); - } - - #[test] - async fn client_increases_delay_to_next_upon_failed_test() { - let mut client = client(); - let test = Test { - timestamp: chrono::offset::Utc::now(), - result: TestResult::TestFailed("2".to_string()), - }; - let delay_before = client.time_to_next_test(); - - client.apply(&test); - - assert!(delay_before < client.time_to_next_test()); - } - - #[test] - async fn client_increases_delay_to_maximum_of_30s() { - let mut client = client(); - let test = Test { - timestamp: chrono::offset::Utc::now(), - result: TestResult::TestFailed("2".to_string()), - }; - - for _ in 0..100 { - client.apply(&test); - } - - assert_eq!(Duration::from_secs(30), client.time_to_next_test()); - } - - #[test] - async fn client_score_cannot_go_beyond_255() { - let mut client = client(); - let test = Test { - timestamp: chrono::offset::Utc::now(), - result: TestResult::TestSucceeded, - }; - - for _ in 0..256 { - client.apply(&test); - } - - assert_eq!(255, client.grade); - } - - #[test] - async fn client_decreases_delay_to_next_upon_successful_test() { - let mut client = client(); - let test = Test { - timestamp: chrono::offset::Utc::now(), - result: TestResult::TestSucceeded, - }; - let delay_before = client.time_to_next_test(); - - client.apply(&test); - - assert!(delay_before > client.time_to_next_test()); - } - - #[test] - async fn client_decreases_delay_to_minimum_of_500ms() { - let mut client = client(); - let test = Test { - timestamp: chrono::offset::Utc::now(), - result: TestResult::TestSucceeded, - }; - - for _ in 0..100 { - client.apply(&test); - } - - assert_eq!(Duration::from_millis(500), client.time_to_next_test()); - } -} diff --git a/rust/templates/leaderboard.html b/rust/templates/leaderboard.html deleted file mode 100644 index 82992d1..0000000 --- a/rust/templates/leaderboard.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - Leaderboard - - - - - -

Leaderboard

- - - {{#each this.clients}} - - {{/each}} -
NameGradeLast test
{{this.name}}{{this.grade}}{{this.last_query}}
- - diff --git a/rust/tests/interpret_test.rs b/rust/tests/interpret_test.rs deleted file mode 100644 index 16e7fb7..0000000 --- a/rust/tests/interpret_test.rs +++ /dev/null @@ -1,25 +0,0 @@ -use lambda::io::{batch_eval, eval_file, repl}; - -#[test] -fn interpreter_can_read_and_interpret_file() { - assert_eq!("12 foo true (x x)", eval_file("sample/test.txt")); - assert_eq!("true", eval_file("sample/test_full.txt")); - assert_eq!("1", eval_file("sample/test_normal.txt")); - assert_eq!("13", eval_file("sample/test_let.txt")); -} - -#[test] -fn repl_can_read_and_interpret_input() { - let input = "(def id (lam x x))\n(id 12)"; - let mut output = Vec::new(); - repl(&mut input.as_bytes(), &mut output); - assert_eq!("> true\n> 12\n> ", String::from_utf8(output).unwrap()); -} - -#[test] -fn repl_can_read_and_interpret_input_in_batch_mode() { - let input = "(def id (lam x x))\n(id 12)"; - let mut output = Vec::new(); - batch_eval(&mut input.as_bytes(), &mut output); - assert_eq!("true\n12\n", String::from_utf8(output).unwrap()); -} -- cgit v1.2.3