diff --git a/Cargo.lock b/Cargo.lock index 080622b..457098e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,9 +49,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.21" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -64,15 +64,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] @@ -83,7 +83,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -94,20 +94,14 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] name = "anyhow" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "autocfg" @@ -115,28 +109,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "aws-lc-rs" -version = "1.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7b6141e96a8c160799cc2d5adecd5cbbe5054cb8c7c4af53da0f83bb7ad256" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.37.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b092fe214090261288111db7a2b2c2118e5a7f30dc2569f1732c4069a6840549" -dependencies = [ - "cc", - "cmake", - "dunce", - "fs_extra", -] - [[package]] name = "backtrace" version = "0.3.76" @@ -161,44 +133,12 @@ dependencies = [ "backtrace", ] -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64ct" -version = "1.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" - [[package]] name = "bitflags" version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" -[[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 = "bstr" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" -dependencies = [ - "memchr", - "regex-automata", - "serde", -] - [[package]] name = "bumpalo" version = "3.20.2" @@ -208,27 +148,6 @@ dependencies = [ "allocator-api2", ] -[[package]] -name = "bytes" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" - -[[package]] -name = "bzip2" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a53fac24f34a81bc9954b5d6cfce0c21e18ec6959f44f56e8e90e4bb7c346c" -dependencies = [ - "libbz2-rs-sys", -] - -[[package]] -name = "camino" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" - [[package]] name = "cast" version = "0.3.0" @@ -237,22 +156,14 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.56" +version = "1.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" dependencies = [ "find-msvc-tools", - "jobserver", - "libc", "shlex", ] -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - [[package]] name = "cfg-if" version = "1.0.4" @@ -294,9 +205,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.59" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5caf74d17c3aec5495110c34cc3f78644bfa89af6c8993ed4de2790e49b6499" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" dependencies = [ "clap_builder", "clap_derive", @@ -304,9 +215,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.59" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "370daa45065b80218950227371916a1633217ae42b2715b2287b606dcd618e24" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -316,9 +227,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.55" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" dependencies = [ "heck", "proc-macro2", @@ -328,9 +239,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "clipboard-win" @@ -341,70 +252,11 @@ dependencies = [ "error-code", ] -[[package]] -name = "cmake" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" -dependencies = [ - "cc", -] - [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" - -[[package]] -name = "colored" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "convert_case" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "core-foundation" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" -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" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "countme" @@ -412,24 +264,6 @@ version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" -dependencies = [ - "cfg-if", -] - [[package]] name = "criterion" version = "0.8.2" @@ -496,154 +330,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" -[[package]] -name = "crypto-common" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "curve25519-dalek" -version = "4.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "digest", - "fiat-crypto", - "rustc_version", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "data-encoding" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" - -[[package]] -name = "der" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "derive_more" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" -dependencies = [ - "derive_more-impl", -] - -[[package]] -name = "derive_more-impl" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn", - "unicode-xid", -] - -[[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 = "dirs" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.61.2", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "ed25519" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" -dependencies = [ - "pkcs8", - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" -dependencies = [ - "curve25519-dalek", - "ed25519", - "serde", - "sha2", - "subtle", - "zeroize", -] - [[package]] name = "either" version = "1.15.0" @@ -652,24 +338,24 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "endian-type" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" +checksum = "869b0adbda23651a9c5c0c3d270aac9fcb52e8622a8f2b17e57802d7791962f2" [[package]] name = "env_filter" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f" +checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" dependencies = [ "log", ] [[package]] name = "env_logger" -version = "0.11.9" +version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" +checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" dependencies = [ "anstream", "anstyle", @@ -702,7 +388,7 @@ dependencies = [ "proc-macro2", "quote", "syn", - "thiserror 2.0.18", + "thiserror", "utf8-ranges", ] @@ -724,7 +410,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -733,51 +419,11 @@ version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" -[[package]] -name = "fallible-iterator" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" - -[[package]] -name = "fallible-streaming-iterator" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" - [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "fd-lock" -version = "4.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" -dependencies = [ - "cfg-if", - "rustix", - "windows-sys 0.59.0", -] - -[[package]] -name = "fiat-crypto" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" - -[[package]] -name = "filetime" -version = "0.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" -dependencies = [ - "cfg-if", - "libc", - "libredox", -] +checksum = "a043dc74da1e37d6afe657061213aa6f425f855399a11d3463c6ecccc4dfda1f" [[package]] name = "find-msvc-tools" @@ -790,62 +436,101 @@ name = "fix" version = "0.1.0" dependencies = [ "anyhow", - "base64", "bumpalo", - "bzip2", "clap", - "colored", "criterion", - "derive_more", - "dirs", "ere", - "flate2", - "gc-arena", + "fix-codegen", + "fix-common", + "fix-error", + "fix-ir", + "fix-vm", "ghost-cell", "hashbrown 0.16.1", - "hex", - "md5", "miette", "mimalloc", - "nix-compat", - "nix-nar", - "num_enum", - "regex", - "reqwest", "rnix", - "rowan", - "rusqlite", - "rust-embed", "rustyline", - "sealed", - "serde", - "serde_json", - "sha1", - "sha2", - "small-map", "smallvec", - "sptr", "string-interner", - "tap", - "tar", "tempfile", "test-log", - "thiserror 2.0.18", - "tokio", - "toml", + "thiserror", "tracing", "tracing-subscriber", - "xz2", ] [[package]] -name = "flate2" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +name = "fix-builtins" +version = "0.1.0" dependencies = [ - "crc32fast", - "miniz_oxide", + "gc-arena", + "num_enum", +] + +[[package]] +name = "fix-codegen" +version = "0.1.0" +dependencies = [ + "fix-builtins", + "fix-common", + "fix-ir", + "gc-arena", + "hashbrown 0.16.1", + "num_enum", + "rnix", + "string-interner", +] + +[[package]] +name = "fix-common" +version = "0.1.0" +dependencies = [ + "ere", + "gc-arena", + "string-interner", +] + +[[package]] +name = "fix-error" +version = "0.1.0" +dependencies = [ + "miette", + "rnix", + "thiserror", +] + +[[package]] +name = "fix-ir" +version = "0.1.0" +dependencies = [ + "bumpalo", + "fix-builtins", + "fix-common", + "fix-error", + "ghost-cell", + "hashbrown 0.16.1", + "num_enum", + "rnix", + "rowan", + "string-interner", +] + +[[package]] +name = "fix-vm" +version = "0.1.0" +dependencies = [ + "fix-builtins", + "fix-codegen", + "fix-common", + "fix-error", + "gc-arena", + "hashbrown 0.16.1", + "likely_stable", + "num_enum", + "smallvec", + "sptr", + "string-interner", ] [[package]] @@ -860,109 +545,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" -[[package]] -name = "form_urlencoded" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - -[[package]] -name = "futures" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" - -[[package]] -name = "futures-executor" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" - -[[package]] -name = "futures-macro" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" - -[[package]] -name = "futures-task" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" - -[[package]] -name = "futures-util" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "slab", -] - [[package]] name = "gc-arena" version = "0.5.3" @@ -985,48 +567,11 @@ dependencies = [ "synstructure", ] -[[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.17" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "r-efi", - "wasip2", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", @@ -1084,214 +629,19 @@ dependencies = [ "foldhash 0.2.0", ] -[[package]] -name = "hashlink" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0b22561a9c04a7cb1a302c013e0259cd3b4bb619f145b32f72b8b4bcbed230" -dependencies = [ - "hashbrown 0.16.1", -] - [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - [[package]] name = "home" version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "http" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" -dependencies = [ - "bytes", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "hyper" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" -dependencies = [ - "atomic-waker", - "bytes", - "futures-channel", - "futures-core", - "http", - "http-body", - "httparse", - "itoa", - "pin-project-lite", - "pin-utils", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" -dependencies = [ - "http", - "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" -dependencies = [ - "base64", - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "ipnet", - "libc", - "percent-encoding", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", -] - -[[package]] -name = "icu_collections" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" -dependencies = [ - "displaydoc", - "potential_utf", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" -dependencies = [ - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" - -[[package]] -name = "icu_properties" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" -dependencies = [ - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" - -[[package]] -name = "icu_provider" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" -dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", + "windows-sys", ] [[package]] @@ -1300,32 +650,11 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" -[[package]] -name = "idna" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - [[package]] name = "indexmap" -version = "2.13.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -1333,37 +662,12 @@ dependencies = [ "serde_core", ] -[[package]] -name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "iri-string" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "is_ci" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" -[[package]] -name = "is_executable" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baabb8b4867b26294d818bf3f651a454b6901431711abb96e296245888d6e8c4" -dependencies = [ - "windows-sys 0.60.2", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -1381,47 +685,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" - -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror 1.0.69", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom 0.3.4", - "libc", -] +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.85" +version = "0.3.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" dependencies = [ "once_cell", "wasm-bindgen", @@ -1439,17 +711,11 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" -[[package]] -name = "libbz2-rs-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7" - [[package]] name = "libc" -version = "0.2.182" +version = "0.2.184" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" [[package]] name = "libmimalloc-sys" @@ -1462,38 +728,19 @@ dependencies = [ ] [[package]] -name = "libredox" -version = "0.1.12" +name = "likely_stable" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +checksum = "d61f7017d8abea1fc23ff7f01a8147b2656dea3aeb24d519aab6e2177eaf671c" dependencies = [ - "bitflags", - "libc", - "redox_syscall", -] - -[[package]] -name = "libsqlite3-sys" -version = "0.36.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b4103cffefa72eb8428cb6b47d6627161e51c2739fc5e3b734584157bc642a" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", + "rustc_version", ] [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" - -[[package]] -name = "litemap" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "log" @@ -1501,23 +748,6 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" -[[package]] -name = "lru-slab" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" - -[[package]] -name = "lzma-sys" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - [[package]] name = "matchers" version = "0.2.0" @@ -1527,12 +757,6 @@ dependencies = [ "regex-automata", ] -[[package]] -name = "md5" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0" - [[package]] name = "memchr" version = "2.8.0" @@ -1585,18 +809,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", - "simd-adler32", -] - -[[package]] -name = "mio" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.61.2", ] [[package]] @@ -1610,9 +822,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.30.1" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" dependencies = [ "bitflags", "cfg-if", @@ -1620,67 +832,13 @@ dependencies = [ "libc", ] -[[package]] -name = "nix-compat" -version = "0.1.0" -source = "git+https://git.snix.dev/snix/snix.git#1b37f68842a7e5e226d9dc009e9a90d400c5fb14" -dependencies = [ - "bitflags", - "bstr", - "bytes", - "data-encoding", - "ed25519", - "ed25519-dalek", - "futures", - "mimalloc", - "nix-compat-derive", - "nom", - "num_enum", - "pin-project-lite", - "sha2", - "thiserror 2.0.18", - "tokio", - "tracing", -] - -[[package]] -name = "nix-compat-derive" -version = "0.1.0" -source = "git+https://git.snix.dev/snix/snix.git#1b37f68842a7e5e226d9dc009e9a90d400c5fb14" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "nix-nar" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15dbfa157df89f4283825ff1c21d53344cfe0d222ea8fde0f9514206dc62d9e0" -dependencies = [ - "camino", - "is_executable", - "symlink", - "thiserror 1.0.69", -] - -[[package]] -name = "nom" -version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" -dependencies = [ - "memchr", -] - [[package]] name = "nu-ansi-term" version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -1694,9 +852,9 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" dependencies = [ "num_enum_derive", "rustversion", @@ -1704,9 +862,9 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1725,9 +883,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "once_cell_polyfill" @@ -1741,23 +899,11 @@ version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" -[[package]] -name = "openssl-probe" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - [[package]] name = "owo-colors" -version = "4.2.3" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" +checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" [[package]] name = "page_size" @@ -1769,39 +915,11 @@ dependencies = [ "winapi", ] -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "plotters" @@ -1831,24 +949,6 @@ dependencies = [ "plotters-backend", ] -[[package]] -name = "potential_utf" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" -dependencies = [ - "zerovec", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - [[package]] name = "prettyplease" version = "0.2.37" @@ -1861,9 +961,9 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ "toml_edit", ] @@ -1877,134 +977,31 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "quinn" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" -dependencies = [ - "bytes", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash 2.1.1", - "rustls", - "socket2", - "thiserror 2.0.18", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" -dependencies = [ - "aws-lc-rs", - "bytes", - "getrandom 0.3.4", - "lru-slab", - "rand", - "ring", - "rustc-hash 2.1.1", - "rustls", - "rustls-pki-types", - "slab", - "thiserror 2.0.18", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.60.2", -] - [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" -version = "5.3.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "radix_trie" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +checksum = "3b4431027dcd37fc2a73ef740b5f233aa805897935b8bce0195e41bbf9a3289a" dependencies = [ "endian-type", "nibble_vec", ] -[[package]] -name = "rand" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" -dependencies = [ - "rand_chacha", - "rand_core 0.9.5", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.5", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.17", -] - -[[package]] -name = "rand_core" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" -dependencies = [ - "getrandom 0.3.4", -] - -[[package]] -name = "rapidhash" -version = "4.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e48930979c155e2f33aa36ab3119b5ee81332beb6482199a8ecd6029b80b59" -dependencies = [ - "rustversion", -] - [[package]] name = "rayon" version = "1.11.0" @@ -2025,26 +1022,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "redox_syscall" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35985aa610addc02e24fc232012c86fd11f14111180f902b67e2d5331f8ebf2b" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" -dependencies = [ - "getrandom 0.2.17", - "libredox", - "thiserror 2.0.18", -] - [[package]] name = "regex" version = "1.12.3" @@ -2070,60 +1047,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" - -[[package]] -name = "reqwest" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" -dependencies = [ - "base64", - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-util", - "js-sys", - "log", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls", - "rustls-pki-types", - "rustls-platform-verifier", - "sync_wrapper", - "tokio", - "tokio-rustls", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "ring" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.17", - "libc", - "untrusted", - "windows-sys 0.52.0", -] +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "rnix" @@ -2142,69 +1068,10 @@ checksum = "417a3a9f582e349834051b8a10c8d71ca88da4211e4093528e36b9845f6b5f21" dependencies = [ "countme", "hashbrown 0.14.5", - "rustc-hash 1.1.0", + "rustc-hash", "text-size", ] -[[package]] -name = "rsqlite-vfs" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a1f2315036ef6b1fbacd1972e8ee7688030b0a2121edfc2a6550febd41574d" -dependencies = [ - "hashbrown 0.16.1", - "thiserror 2.0.18", -] - -[[package]] -name = "rusqlite" -version = "0.38.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1c93dd1c9683b438c392c492109cb702b8090b2bfc8fed6f6e4eb4523f17af3" -dependencies = [ - "bitflags", - "fallible-iterator", - "fallible-streaming-iterator", - "hashlink", - "libsqlite3-sys", - "smallvec", - "sqlite-wasm-rs", -] - -[[package]] -name = "rust-embed" -version = "8.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04113cb9355a377d83f06ef1f0a45b8ab8cd7d8b1288160717d66df5c7988d27" -dependencies = [ - "rust-embed-impl", - "rust-embed-utils", - "walkdir", -] - -[[package]] -name = "rust-embed-impl" -version = "8.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0902e4c7c8e997159ab384e6d0fc91c221375f6894346ae107f47dd0f3ccaa" -dependencies = [ - "proc-macro2", - "quote", - "rust-embed-utils", - "syn", - "walkdir", -] - -[[package]] -name = "rust-embed-utils" -version = "8.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bcdef0be6fe7f6fa333b1073c949729274b05f123a0ad7efcb8efd878e5c3b1" -dependencies = [ - "sha2", - "walkdir", -] - [[package]] name = "rustc-demangle" version = "0.1.27" @@ -2217,12 +1084,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - [[package]] name = "rustc_version" version = "0.4.1" @@ -2234,90 +1095,15 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", -] - -[[package]] -name = "rustls" -version = "0.23.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" -dependencies = [ - "aws-lc-rs", - "once_cell", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-native-certs" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" -dependencies = [ - "openssl-probe", - "rustls-pki-types", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pki-types" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" -dependencies = [ - "web-time", - "zeroize", -] - -[[package]] -name = "rustls-platform-verifier" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" -dependencies = [ - "core-foundation", - "core-foundation-sys", - "jni", - "log", - "once_cell", - "rustls", - "rustls-native-certs", - "rustls-platform-verifier-android", - "rustls-webpki", - "security-framework", - "security-framework-sys", - "webpki-root-certs", - "windows-sys 0.61.2", -] - -[[package]] -name = "rustls-platform-verifier-android" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" - -[[package]] -name = "rustls-webpki" -version = "0.103.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" -dependencies = [ - "aws-lc-rs", - "ring", - "rustls-pki-types", - "untrusted", + "windows-sys", ] [[package]] @@ -2328,14 +1114,13 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "rustyline" -version = "17.0.2" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e902948a25149d50edc1a8e0141aad50f54e22ba83ff988cf8f7c9ef07f50564" +checksum = "4a990b25f351b25139ddc7f21ee3f6f56f86d6846b74ac8fad3a719a287cd4a0" dependencies = [ "bitflags", "cfg-if", "clipboard-win", - "fd-lock", "home", "libc", "log", @@ -2345,7 +1130,7 @@ dependencies = [ "unicode-segmentation", "unicode-width 0.2.2", "utf8parse", - "windows-sys 0.60.2", + "windows-sys", ] [[package]] @@ -2357,54 +1142,11 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "schannel" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "sealed" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22f968c5ea23d555e670b449c1c5e7b2fc399fdaec1d304a17cd48e288abc107" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "security-framework" -version = "3.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d17b898a6d6948c3a8ee4372c17cb384f90d2e6e912ef00895b14fd7ab54ec38" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321c8673b092a9a42605034a9879d73cb79101ed5fd117bc9a597b89b4e9e61a" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" @@ -2449,37 +1191,6 @@ dependencies = [ "zmij", ] -[[package]] -name = "serde_spanned" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" -dependencies = [ - "serde_core", -] - -[[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.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "sharded-slab" version = "0.1.7" @@ -2495,88 +1206,18 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "rand_core 0.6.4", -] - -[[package]] -name = "simd-adler32" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" - -[[package]] -name = "slab" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" - -[[package]] -name = "small-map" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64c0b79fa0e86d80062670059d27f93911776cdeba2555bf428b455d8738c32f" -dependencies = [ - "hashbrown 0.16.1", - "rapidhash", - "rustc-hash 2.1.1", -] - [[package]] name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" -[[package]] -name = "socket2" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" -dependencies = [ - "libc", - "windows-sys 0.60.2", -] - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] - [[package]] name = "sptr" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" -[[package]] -name = "sqlite-wasm-rs" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4206ed3a67690b9c29b77d728f6acc3ce78f16bf846d83c94f76400320181b" -dependencies = [ - "cc", - "js-sys", - "rsqlite-vfs", - "wasm-bindgen", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - [[package]] name = "string-interner" version = "0.19.0" @@ -2593,12 +1234,6 @@ 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 = "supports-color" version = "3.0.2" @@ -2620,32 +1255,17 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" -[[package]] -name = "symlink" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" - [[package]] name = "syn" -version = "2.0.116" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df424c70518695237746f84cede799c9c58fcb37450d7b23716568cc8bc69cb" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" -dependencies = [ - "futures-core", -] - [[package]] name = "synstructure" version = "0.13.2" @@ -2657,44 +1277,27 @@ dependencies = [ "syn", ] -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tar" -version = "0.4.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" -dependencies = [ - "filetime", - "libc", - "xattr", -] - [[package]] name = "tempfile" -version = "3.25.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.1", + "getrandom", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] name = "terminal_size" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" +checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ "rustix", - "windows-sys 0.60.2", + "windows-sys", ] [[package]] @@ -2735,33 +1338,13 @@ dependencies = [ "unicode-width 0.2.2", ] -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - [[package]] name = "thiserror" version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.18", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "thiserror-impl", ] [[package]] @@ -2784,16 +1367,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "tinystr" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" -dependencies = [ - "displaydoc", - "zerovec", -] - [[package]] name = "tinytemplate" version = "1.2.1" @@ -2804,86 +1377,20 @@ dependencies = [ "serde_json", ] -[[package]] -name = "tinyvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" -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.49.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" -dependencies = [ - "bytes", - "libc", - "mio", - "pin-project-lite", - "socket2", - "tokio-macros", - "windows-sys 0.61.2", -] - -[[package]] -name = "tokio-macros" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "toml" -version = "0.9.9+spec-1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5238e643fc34a1d5d7e753e1532a91912d74b63b92b3ea51fde8d1b7bc79dd" -dependencies = [ - "indexmap", - "serde_core", - "serde_spanned", - "toml_datetime", - "toml_parser", - "toml_writer", - "winnow", -] - [[package]] name = "toml_datetime" -version = "0.7.5+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ "serde_core", ] [[package]] name = "toml_edit" -version = "0.23.10+spec-1.0.0" +version = "0.25.10+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +checksum = "a82418ca169e235e6c399a84e395ab6debeb3bc90edc959bf0f48647c6a32d1b" dependencies = [ "indexmap", "toml_datetime", @@ -2893,64 +1400,13 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.9+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ "winnow", ] -[[package]] -name = "toml_writer" -version = "1.0.6+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" - -[[package]] -name = "tower" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" -dependencies = [ - "futures-core", - "futures-util", - "pin-project-lite", - "sync_wrapper", - "tokio", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-http" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" -dependencies = [ - "bitflags", - "bytes", - "futures-util", - "http", - "http-body", - "iri-string", - "pin-project-lite", - "tower", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[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.44" @@ -2996,9 +1452,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", @@ -3012,18 +1468,6 @@ dependencies = [ "tracing-log", ] -[[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.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" - [[package]] name = "unicode-ident" version = "1.0.24" @@ -3038,9 +1482,9 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "unicode-width" @@ -3060,36 +1504,12 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" -[[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.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - [[package]] name = "utf8-ranges" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcfc827f90e53a02eaef5e535ee14266c1d569214c6aa70133a624d8a3164ba" -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - [[package]] name = "utf8parse" version = "0.2.2" @@ -3102,18 +1522,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" -[[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 = "walkdir" version = "2.5.0" @@ -3124,21 +1532,6 @@ dependencies = [ "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.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - [[package]] name = "wasip2" version = "1.0.2+wasi-0.2.9" @@ -3159,9 +1552,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.108" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" dependencies = [ "cfg-if", "once_cell", @@ -3170,25 +1563,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" -dependencies = [ - "cfg-if", - "futures-util", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" -version = "0.2.108" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3196,9 +1575,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.108" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" dependencies = [ "bumpalo", "proc-macro2", @@ -3209,9 +1588,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.108" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" dependencies = [ "unicode-ident", ] @@ -3252,33 +1631,14 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.85" +version = "0.3.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" +checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" dependencies = [ "js-sys", "wasm-bindgen", ] -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki-root-certs" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "winapi" version = "0.3.9" @@ -3301,7 +1661,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -3316,42 +1676,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -3361,197 +1685,11 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[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_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[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_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - -[[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_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[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_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[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_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winnow" -version = "0.7.14" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" dependencies = [ "memchr", ] @@ -3644,128 +1782,20 @@ dependencies = [ "wasmparser", ] -[[package]] -name = "writeable" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" - -[[package]] -name = "xattr" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" -dependencies = [ - "libc", - "rustix", -] - -[[package]] -name = "xz2" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2" -dependencies = [ - "lzma-sys", -] - -[[package]] -name = "yoke" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" -dependencies = [ - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - [[package]] name = "zerocopy" -version = "0.8.39" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.39" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zerofrom" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zeroize" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" - -[[package]] -name = "zerotrie" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 8dc1a68..8237a58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,8 +2,35 @@ resolver = "3" members = [ "fix", + "fix-builtins", + "fix-codegen", + "fix-common", + "fix-error", + "fix-ir", + "fix-vm", ] [profile.profiling] inherits = "release" debug = true + +[workspace.dependencies] +bumpalo = { version = "3.20", features = [ + "allocator-api2", + "boxed", + "collections", +] } +ghost-cell = "0.2" +hashbrown = "0.16" +num_enum = "0.7.5" +smallvec = "1.15" +ere = "0.2" +string-interner = "0.19" +rnix = "0.14" +rowan = "0.16" +likely_stable = "0.1" + +[workspace.dependencies.gc-arena] +git = "https://github.com/kyren/gc-arena" +rev = "75671ae03f53718357b741ed4027560f14e90836" +features = ["allocator-api2", "hashbrown", "smallvec"] diff --git a/fix-builtins/Cargo.toml b/fix-builtins/Cargo.toml new file mode 100644 index 0000000..d84418a --- /dev/null +++ b/fix-builtins/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "fix-builtins" +version = "0.1.0" +edition = "2024" + +[dependencies] +num_enum = { workspace = true } +gc-arena = { workspace = true } diff --git a/fix-builtins/src/lib.rs b/fix-builtins/src/lib.rs new file mode 100644 index 0000000..acd3b42 --- /dev/null +++ b/fix-builtins/src/lib.rs @@ -0,0 +1,125 @@ +use gc_arena::Collect; +use num_enum::TryFromPrimitive; + +macro_rules! define_builtins { + ($(($name:literal, $variant:ident, $arity:expr)),* $(,)?) => { + /// Builtin function registry. + /// Array index IS the PrimOp id. (name, arity) pairs. + pub const BUILTINS: &[(&str, u8)] = &[ + $(($name, $arity),)* + ]; + + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive, Collect)] + #[repr(u8)] + #[collect(require_static)] + pub enum BuiltinId { + $($variant,)* + } + }; +} + +define_builtins! { + ("abort", Abort, 1), + ("__add", Add, 2), + ("__addErrorContext", AddErrorContext, 2), + ("__all", All, 2), + ("__any", Any, 2), + ("__appendContext", AppendContext, 2), + ("__attrNames", AttrNames, 1), + ("__attrValues", AttrValues, 1), + ("baseNameOf", BaseNameOf, 1), + ("__bitAnd", BitAnd, 2), + ("__bitOr", BitOr, 2), + ("__bitXor", BitXor, 2), + ("break", Break, 1), + ("__catAttrs", CatAttrs, 2), + ("__ceil", Ceil, 1), + ("__compareVersions", CompareVersions, 2), + ("__concatLists", ConcatLists, 1), + ("__concatMap", ConcatMap, 2), + ("__concatStringsSep", ConcatStringsSep, 2), + ("__convertHash", ConvertHash, 1), + ("__deepSeq", DeepSeq, 2), + ("derivation", Derivation, 1), + ("derivationStrict", DerivationStrict, 1), + ("dirOf", DirOf, 1), + ("__div", Div, 2), + ("__elem", Elem, 2), + ("__elemAt", ElemAt, 2), + ("fetchGit", FetchGit, 1), + ("fetchMercurial", FetchMercurial, 1), + ("fetchTarball", FetchTarball, 1), + ("fetchTree", FetchTree, 1), + ("__fetchurl", FetchUrl, 1), + ("__filter", Filter, 2), + ("__filterSource", FilterSource, 2), + ("__findFile", FindFile, 2), + ("__floor", Floor, 1), + ("__foldl'", FoldlStrict, 3), + ("__fromJSON", FromJSON, 1), + ("fromTOML", FromTOML, 1), + ("__functionArgs", FunctionArgs, 1), + ("__genList", GenList, 2), + ("__genericClosure", GenericClosure, 1), + ("__getAttr", GetAttr, 2), + ("__getContext", GetContext, 1), + ("__getEnv", GetEnv, 1), + ("__groupBy", GroupBy, 2), + ("__hasAttr", HasAttr, 2), + ("__hasContext", HasContext, 1), + ("__hashFile", HashFile, 2), + ("__hashString", HashString, 2), + ("__head", Head, 1), + ("import", Import, 1), + ("__intersectAttrs", IntersectAttrs, 2), + ("__isAttrs", IsAttrs, 1), + ("__isBool", IsBool, 1), + ("__isFloat", IsFloat, 1), + ("__isFunction", IsFunction, 1), + ("__isInt", IsInt, 1), + ("__isList", IsList, 1), + ("isNull", IsNull, 1), + ("__isPath", IsPath, 1), + ("__isString", IsString, 1), + ("__length", Length, 1), + ("__lessThan", LessThan, 2), + ("__listToAttrs", ListToAttrs, 1), + ("map", Map, 2), + ("__mapAttrs", MapAttrs, 2), + ("__match", Match, 2), + ("__mul", Mul, 2), + ("null", Null, 0), // constant, not a function + ("__parseDrvName", ParseDrvName, 1), + ("__partition", Partition, 2), + ("__path", Path, 1), + ("__pathExists", PathExists, 1), + ("placeholder", Placeholder, 1), + ("__readDir", ReadDir, 1), + ("__readFile", ReadFile, 1), + ("__readFileType", ReadFileType, 1), + ("removeAttrs", RemoveAttrs, 2), + ("__replaceStrings", ReplaceStrings, 3), + ("scopedImport", ScopedImport, 2), + ("__seq", Seq, 2), + ("__sort", Sort, 2), + ("__split", Split, 2), + ("__splitVersion", SplitVersion, 1), + ("__storePath", StorePath, 1), + ("__stringLength", StringLength, 1), + ("__sub", Sub, 2), + ("__substring", Substring, 3), + ("__tail", Tail, 1), + ("throw", Throw, 1), + ("__toFile", ToFile, 2), + ("__toJSON", ToJSON, 1), + ("__toPath", ToPath, 1), + ("toString", ToString, 1), + ("__toXML", ToXML, 1), + ("__trace", Trace, 2), + ("__tryEval", TryEval, 1), + ("__typeOf", TypeOf, 1), + ("__unsafeDiscardStringContext", UnsafeDiscardStringContext, 1), + ("__unsafeGetAttrPos", UnsafeGetAttrPos, 2), + ("__warn", Warn, 2), + ("__zipAttrsWith", ZipAttrsWith, 2), +} diff --git a/fix-codegen/Cargo.toml b/fix-codegen/Cargo.toml new file mode 100644 index 0000000..e3e01bc --- /dev/null +++ b/fix-codegen/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "fix-codegen" +version = "0.1.0" +edition = "2024" + +[dependencies] +gc-arena = { workspace = true } +hashbrown = { workspace = true } +num_enum = { workspace = true } +rnix = { workspace = true } +string-interner = { workspace = true } + +fix-builtins = { path = "../fix-builtins" } +fix-common = { path = "../fix-common" } +fix-ir = { path = "../fix-ir" } diff --git a/fix/src/codegen.rs b/fix-codegen/src/lib.rs similarity index 93% rename from fix/src/codegen.rs rename to fix-codegen/src/lib.rs index c4876d9..66c950b 100644 --- a/fix/src/codegen.rs +++ b/fix-codegen/src/lib.rs @@ -1,30 +1,21 @@ use std::ops::Deref; -use gc_arena::Collect; +use fix_builtins::{BUILTINS, BuiltinId}; +use fix_common::StringId; +use fix_ir::{Attr, BinOpKind, Ir, Param, RawIrRef, ThunkId, UnOpKind}; use hashbrown::HashMap; use num_enum::TryFromPrimitive; use rnix::TextRange; use string_interner::Symbol as _; -use crate::ir::{Attr, BinOpKind, Ir, Param, RawIrRef, StringId, ThunkId, UnOpKind}; -use crate::runtime::BUILTINS; -use crate::runtime::value::{Null, PrimOp, StaticValue}; +pub struct InstructionPtr(pub usize); -pub struct InstructionPtr(pub(crate) usize); - -#[derive(Collect)] -#[collect(require_static)] -pub struct Bytecode { - pub code: Box<[u8]>, - pub current_dir: String, -} - -pub(crate) trait BytecodeContext { +pub trait BytecodeContext { fn intern_string(&mut self, s: &str) -> StringId; fn register_span(&mut self, range: TextRange) -> u32; fn get_code(&self) -> &[u8]; fn get_code_mut(&mut self) -> &mut Vec; - fn add_constant(&mut self, val: crate::runtime::value::StaticValue) -> u32; + fn add_constant(&mut self, val: Const) -> u32; } #[repr(u8)] @@ -49,7 +40,6 @@ pub enum Op { MakePatternClosure, Call, - CallNoSpan, MakeAttrs, MakeEmptyAttrs, @@ -98,6 +88,8 @@ pub enum Op { LoadScopedBinding, Return, + + Illegal, } struct ScopeInfo { @@ -110,22 +102,39 @@ struct BytecodeEmitter<'a, Ctx: BytecodeContext> { scope_stack: Vec, } -pub(crate) const OPERAND_CONST: u8 = 0; -pub(crate) const OPERAND_LOCAL: u8 = 1; -pub(crate) const OPERAND_BUILTINS: u8 = 2; -pub(crate) const OPERAND_BIGINT: u8 = 3; +#[repr(u8)] +#[derive(Debug, Clone, Copy, TryFromPrimitive)] +pub enum OperandType { + Const, + Local, + Builtins, + BigInt, +} -pub(crate) const KEY_STATIC: u8 = 0; -pub(crate) const KEY_DYNAMIC: u8 = 1; +#[repr(u8)] +#[derive(Debug, Clone, Copy, TryFromPrimitive)] +pub enum AttrKeyType { + Static, + Dynamic, +} -enum InlineOperand { - Const(StaticValue), +pub enum Const { + Smi(i32), + Float(f64), + Bool(bool), + String(StringId), + PrimOp { id: BuiltinId, arity: u8 }, + Null, +} + +pub enum InlineOperand { + Const(Const), Local { layer: u16, local: u32 }, Builtins, BigInt(i64), } -pub(crate) fn compile_bytecode(ir: RawIrRef<'_>, ctx: &mut impl BytecodeContext) -> InstructionPtr { +pub fn compile_bytecode(ir: RawIrRef<'_>, ctx: &mut impl BytecodeContext) -> InstructionPtr { let ip = ctx.get_code().len(); let mut emitter = BytecodeEmitter::new(ctx); emitter.emit_toplevel(ir); @@ -144,17 +153,17 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> { match ir.deref() { &Ir::Int(x) => { if x <= i32::MAX as i64 { - InlineOperand::Const(StaticValue::new_inline(x as i32)) + InlineOperand::Const(Const::Smi(x as i32)) } else { InlineOperand::BigInt(x) } } - &Ir::Float(x) => InlineOperand::Const(StaticValue::new_float(x)), - &Ir::Bool(b) => InlineOperand::Const(StaticValue::new_inline(b)), - Ir::Null => InlineOperand::Const(StaticValue::new_inline(Null)), + &Ir::Float(x) => InlineOperand::Const(Const::Float(x)), + &Ir::Bool(b) => InlineOperand::Const(Const::Bool(b)), + Ir::Null => InlineOperand::Const(Const::Null), Ir::Str(s) => { let sid = self.ctx.intern_string(s.deref()); - InlineOperand::Const(StaticValue::new_inline(sid)) + InlineOperand::Const(Const::String(sid)) } &Ir::Thunk(id) => { let (layer, local) = self.resolve_thunk(id); @@ -166,7 +175,7 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> { }, &Ir::Builtin(id) => { let arity = BUILTINS[id as usize].1; - InlineOperand::Const(StaticValue::new_inline(PrimOp { id, arity })) + InlineOperand::Const(Const::PrimOp { id, arity }) } Ir::Builtins => InlineOperand::Builtins, _ => panic!("cannot classify IR node as inline operand"), @@ -177,19 +186,19 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> { match operand { InlineOperand::Const(val) => { let idx = self.ctx.add_constant(val); - self.emit_u8(OPERAND_CONST); + self.emit_u8(OperandType::Const as u8); self.emit_u32(idx); } InlineOperand::Local { layer, local } => { - self.emit_u8(OPERAND_LOCAL); + self.emit_u8(OperandType::Local as u8); self.emit_u8(layer as u8); self.emit_u32(local); } InlineOperand::Builtins => { - self.emit_u8(OPERAND_BUILTINS); + self.emit_u8(OperandType::Builtins as u8); } InlineOperand::BigInt(val) => { - self.emit_u8(OPERAND_BIGINT); + self.emit_u8(OperandType::BigInt as u8); self.emit_i64(val); } } @@ -566,12 +575,10 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> { } } } - &Ir::Call { func, arg, span } => { + &Ir::Call { func, arg, .. } => { self.emit_expr(arg); self.emit_expr(func); - let span_id = self.ctx.register_span(span); self.emit_op(Op::Call); - self.emit_u32(span_id); } &Ir::Arg { layer } => { self.emit_load(layer.try_into().expect("scope too deep!"), 0); @@ -725,12 +732,12 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> { PipeL => { self.emit_expr(rhs); self.emit_expr(lhs); - self.emit_op(Op::CallNoSpan); + self.emit_op(Op::Call); } PipeR => { self.emit_expr(lhs); self.emit_expr(rhs); - self.emit_op(Op::CallNoSpan); + self.emit_op(Op::Call); } _ => { self.emit_expr(lhs); @@ -808,7 +815,7 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> { fn emit_attrset( &mut self, - stcs: &crate::ir::HashMap<'_, StringId, (RawIrRef<'_>, TextRange)>, + stcs: &fix_ir::HashMap<'_, StringId, (RawIrRef<'_>, TextRange)>, dyns: &[(RawIrRef<'_>, RawIrRef<'_>, TextRange)], ) { if stcs.is_empty() && dyns.is_empty() { @@ -821,7 +828,7 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> { self.emit_u32(total as u32); for (&sym, &(val, span)) in stcs.iter() { - self.emit_u8(KEY_STATIC); + self.emit_u8(AttrKeyType::Static as u8); self.emit_str_id(sym); let val_operand = self.classify_value(val); self.emit_inline_operand(val_operand); @@ -829,7 +836,7 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> { self.emit_u32(span_id); } for &(key, val, span) in dyns.iter() { - self.emit_u8(KEY_DYNAMIC); + self.emit_u8(AttrKeyType::Dynamic as u8); let key_operand = self.classify_value(key); self.emit_inline_operand(key_operand); let val_operand = self.classify_value(val); @@ -867,11 +874,11 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> { for attr in attrpath.iter() { match *attr { Attr::Str(sym, _) => { - self.emit_u8(KEY_STATIC); + self.emit_u8(AttrKeyType::Static as u8); self.emit_str_id(sym); } Attr::Dynamic(_, _) => { - self.emit_u8(KEY_DYNAMIC); + self.emit_u8(AttrKeyType::Dynamic as u8); } } } @@ -889,11 +896,11 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> { for attr in rhs.iter() { match *attr { Attr::Str(sym, _) => { - self.emit_u8(KEY_STATIC); + self.emit_u8(AttrKeyType::Static as u8); self.emit_str_id(sym); } Attr::Dynamic(_, _) => { - self.emit_u8(KEY_DYNAMIC); + self.emit_u8(AttrKeyType::Dynamic as u8); } } } diff --git a/fix-common/Cargo.toml b/fix-common/Cargo.toml new file mode 100644 index 0000000..98d06bf --- /dev/null +++ b/fix-common/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "fix-common" +version = "0.1.0" +edition = "2024" + +[dependencies] +gc-arena = { workspace = true } +string-interner = { workspace = true } +ere = { workspace = true } diff --git a/fix/src/value.rs b/fix-common/src/lib.rs similarity index 93% rename from fix/src/value.rs rename to fix-common/src/lib.rs index 9425613..8a9e252 100644 --- a/fix/src/value.rs +++ b/fix-common/src/lib.rs @@ -1,14 +1,17 @@ -use core::fmt::{Debug, Display, Formatter, Result as FmtResult}; -use core::hash::Hash; -use core::ops::Deref; use std::borrow::Cow; use std::collections::BTreeMap; -use std::ops::DerefMut; +use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; +use std::ops::{Deref, DerefMut}; -use derive_more::{Constructor, IsVariant, Unwrap}; +use gc_arena::Collect; + +#[repr(transparent)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Collect)] +#[collect(require_static)] +pub struct StringId(pub string_interner::symbol::SymbolU32); /// Represents a Nix symbol, which is used as a key in attribute sets. -#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Constructor)] +#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Symbol<'a>(Cow<'a, str>); pub type StaticSymbol = Symbol<'static>; @@ -60,13 +63,36 @@ impl Deref for Symbol<'_> { } } +fn escape_quote_string(s: &str) -> String { + let mut ret = String::with_capacity(s.len() + 2); + ret.push('"'); + let mut iter = s.chars().peekable(); + while let Some(c) = iter.next() { + match c { + '\\' => ret.push_str("\\\\"), + '"' => ret.push_str("\\\""), + '\n' => ret.push_str("\\n"), + '\r' => ret.push_str("\\r"), + '\t' => ret.push_str("\\t"), + '$' if iter.peek() == Some(&'{') => ret.push_str("\\$"), + c => ret.push(c), + } + } + ret.push('"'); + ret +} + /// Represents a Nix attribute set, which is a map from symbols to values. -#[derive(Constructor, Default, Clone, PartialEq)] +#[derive(Default, Clone, PartialEq)] pub struct AttrSet { data: BTreeMap, } impl AttrSet { + pub fn new(data: BTreeMap) -> Self { + Self { data } + } + /// Gets a value by key (string or Symbol). pub fn get<'a, 'sym: 'a>(&'a self, key: impl Into>) -> Option<&'a Value> { self.data.get(&key.into()) @@ -154,11 +180,17 @@ impl Display for AttrSetCompatDisplay<'_> { } /// Represents a Nix list, which is a vector of values. -#[derive(Constructor, Default, Clone, Debug, PartialEq)] +#[derive(Default, Clone, Debug, PartialEq)] pub struct List { data: Vec, } +impl List { + pub fn new(data: Vec) -> Self { + Self { data } + } +} + impl Deref for List { type Target = Vec; fn deref(&self) -> &Self::Target { @@ -217,7 +249,7 @@ impl Display for ListCompatDisplay<'_> { } /// Represents any possible Nix value that can be returned from an evaluation. -#[derive(IsVariant, Unwrap, Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub enum Value { /// An integer value. Int(i64), @@ -248,27 +280,8 @@ pub enum Value { Repeated, } -fn escape_quote_string(s: &str) -> String { - let mut ret = String::with_capacity(s.len() + 2); - ret.push('"'); - let mut iter = s.chars().peekable(); - while let Some(c) = iter.next() { - match c { - '\\' => ret.push_str("\\\\"), - '"' => ret.push_str("\\\""), - '\n' => ret.push_str("\\n"), - '\r' => ret.push_str("\\r"), - '\t' => ret.push_str("\\t"), - '$' if iter.peek() == Some(&'{') => ret.push_str("\\$"), - c => ret.push(c), - } - } - ret.push('"'); - ret -} - /// Wrapper to format a float in Nix style (C printf `%g` with precision 6). -pub(crate) struct NixFloat(pub f64); +pub struct NixFloat(pub f64); impl Display for NixFloat { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { diff --git a/fix-error/Cargo.toml b/fix-error/Cargo.toml new file mode 100644 index 0000000..952f918 --- /dev/null +++ b/fix-error/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "fix-error" +version = "0.1.0" +edition = "2024" + +[dependencies] +miette = { version = "7.6", features = ["fancy"] } +thiserror = "2.0" +rnix = { workspace = true } diff --git a/fix-error/src/lib.rs b/fix-error/src/lib.rs new file mode 100644 index 0000000..c3e07f8 --- /dev/null +++ b/fix-error/src/lib.rs @@ -0,0 +1,223 @@ +use std::path::{Path, PathBuf}; +use std::sync::Arc; + +use miette::{Diagnostic, NamedSource, SourceSpan}; +use thiserror::Error; + +pub type Result = core::result::Result>; + +#[derive(Clone, Debug)] +pub enum SourceType { + /// dir + Eval(Arc), + /// dir + Repl(Arc), + /// file + File(Arc), + /// virtual (name, no path) + Virtual(Arc), +} + +#[derive(Clone, Debug)] +pub struct Source { + pub ty: SourceType, + pub src: Arc, +} + +impl TryFrom<&str> for Source { + type Error = Box; + fn try_from(value: &str) -> Result { + Source::new_eval(value.into()) + } +} + +impl From for NamedSource> { + fn from(value: Source) -> Self { + let name = value.get_name(); + NamedSource::new(name, value.src.clone()) + } +} + +impl Source { + pub fn new_file(path: PathBuf) -> std::io::Result { + Ok(Source { + src: std::fs::read_to_string(&path)?.into(), + ty: SourceType::File(Arc::new(path)), + }) + } + + pub fn new_eval(src: String) -> Result { + Ok(Self { + ty: std::env::current_dir() + .map_err(|err| Error::internal(format!("Failed to get current working dir: {err}"))) + .map(Arc::new) + .map(SourceType::Eval)?, + src: src.into(), + }) + } + + pub fn new_repl(src: String) -> Result { + Ok(Self { + ty: std::env::current_dir() + .map_err(|err| Error::internal(format!("Failed to get current working dir: {err}"))) + .map(Arc::new) + .map(SourceType::Repl)?, + src: src.into(), + }) + } + + pub fn new_virtual(name: Arc, src: String) -> Self { + Self { + ty: SourceType::Virtual(name), + src: src.into(), + } + } + + pub fn get_dir(&self) -> &Path { + use SourceType::*; + match &self.ty { + Eval(dir) | Repl(dir) => dir.as_ref(), + File(file) => file + .as_path() + .parent() + .expect("source file must have a parent dir"), + Virtual(_) => Path::new("/"), + } + } + + pub fn get_name(&self) -> String { + match &self.ty { + SourceType::Eval(_) => "«eval»".into(), + SourceType::Repl(_) => "«repl»".into(), + SourceType::File(path) => path.as_os_str().to_string_lossy().to_string(), + SourceType::Virtual(name) => name.to_string(), + } + } +} + +#[derive(Error, Debug, Diagnostic)] +pub enum Error { + #[error("Parse error: {message}")] + #[diagnostic(code(nix::parse))] + ParseError { + #[source_code] + src: Option>>, + #[label("error occurred here")] + span: Option, + message: String, + }, + + #[error("Downgrade error: {message}")] + #[diagnostic(code(nix::downgrade))] + DowngradeError { + #[source_code] + src: Option>>, + #[label("{message}")] + span: Option, + message: String, + }, + + #[error("Evaluation error: {message}")] + #[diagnostic(code(nix::eval))] + EvalError { + #[source_code] + src: Option>>, + #[label("error occurred here")] + span: Option, + message: String, + #[related] + stack_trace: Vec, + }, + + #[error("Internal error: {message}")] + #[diagnostic(code(nix::internal))] + InternalError { message: String }, + + #[error("{message}")] + #[diagnostic(code(nix::catchable))] + Catchable { message: String }, + + #[error("Unknown error")] + #[diagnostic(code(nix::unknown))] + Unknown, +} + +impl Error { + pub fn parse_error(msg: String) -> Box { + Error::ParseError { + src: None, + span: None, + message: msg, + } + .into() + } + + pub fn downgrade_error(msg: String, src: Source, span: rnix::TextRange) -> Box { + Error::DowngradeError { + src: Some(src.into()), + span: Some(text_range_to_source_span(span)), + message: msg, + } + .into() + } + + pub fn eval_error(msg: impl Into) -> Box { + Error::EvalError { + src: None, + span: None, + message: msg.into(), + stack_trace: Vec::new(), + } + .into() + } + + pub fn internal(msg: String) -> Box { + Error::InternalError { message: msg }.into() + } + + pub fn catchable(msg: String) -> Box { + Error::Catchable { message: msg }.into() + } + + pub fn with_span(mut self: Box, span: rnix::TextRange) -> Box { + use Error::*; + let source_span = Some(text_range_to_source_span(span)); + let (ParseError { span, .. } | DowngradeError { span, .. } | EvalError { span, .. }) = + self.as_mut() + else { + return self; + }; + *span = source_span; + self + } + + pub fn with_source(mut self: Box, source: Source) -> Box { + use Error::*; + let new_src = Some(source.into()); + let (ParseError { src, .. } | DowngradeError { src, .. } | EvalError { src, .. }) = + self.as_mut() + else { + return self; + }; + *src = new_src; + self + } +} + +pub fn text_range_to_source_span(range: rnix::TextRange) -> SourceSpan { + let start = usize::from(range.start()); + let len = usize::from(range.end()) - start; + SourceSpan::new(start.into(), len) +} + +/// Stack frame types from Nix evaluation +#[derive(Debug, Clone, Error, Diagnostic)] +#[error("{message}")] +pub struct StackFrame { + #[label] + pub span: SourceSpan, + #[help] + pub message: String, + #[source_code] + pub src: NamedSource>, +} diff --git a/fix-ir/Cargo.toml b/fix-ir/Cargo.toml new file mode 100644 index 0000000..f543bd1 --- /dev/null +++ b/fix-ir/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "fix-ir" +version = "0.1.0" +edition = "2024" + +[dependencies] +bumpalo = { workspace = true } +ghost-cell = { workspace = true } +rnix = { workspace = true } +rowan = { workspace = true } +string-interner = { workspace = true } +hashbrown = { workspace = true } +num_enum = { workspace = true } + +fix-builtins = { path = "../fix-builtins" } +fix-common = { path = "../fix-common" } +fix-error = { path = "../fix-error" } diff --git a/fix/src/downgrade.rs b/fix-ir/src/downgrade.rs similarity index 99% rename from fix/src/downgrade.rs rename to fix-ir/src/downgrade.rs index a7b04af..e103f46 100644 --- a/fix/src/downgrade.rs +++ b/fix-ir/src/downgrade.rs @@ -1,15 +1,15 @@ use bumpalo::boxed::Box; use bumpalo::collections::{CollectIn, Vec}; +use fix_builtins::BuiltinId; +use fix_common::Symbol; +use fix_error::{Error, Result, Source}; use hashbrown::HashSet; use hashbrown::hash_map::Entry; use rnix::TextRange; use rnix::ast::{self, Expr, HasEntry}; use rowan::ast::AstNode; -use crate::error::{Error, Result, Source}; -use crate::ir::*; -use crate::runtime::BuiltinId; -use crate::value::Symbol; +use super::*; trait Require<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>, T> { fn require(self, ctx: &Ctx, span: TextRange) -> Result; @@ -151,8 +151,7 @@ macro_rules! path { ($ty:ident) => { impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::$ty { fn downgrade(self, ctx: &mut Ctx) -> Result> { - let span = self.syntax().text_range(); - downgrade_path(self.parts(), span, ctx) + downgrade_path(self.parts(), ctx) } } }; @@ -1215,7 +1214,6 @@ fn finalize_pending_value<'id, 'ir, Ctx: DowngradeContext<'id, 'ir>, const ALLOW fn downgrade_path<'id, 'ir>( parts: impl IntoIterator>, - _span: rnix::TextRange, ctx: &mut impl DowngradeContext<'id, 'ir>, ) -> Result> { let bump = ctx.bump(); diff --git a/fix/src/ir.rs b/fix-ir/src/lib.rs similarity index 79% rename from fix/src/ir.rs rename to fix-ir/src/lib.rs index 74dea37..bc3c76a 100644 --- a/fix/src/ir.rs +++ b/fix-ir/src/lib.rs @@ -4,12 +4,14 @@ use std::ops::Deref; use bumpalo::Bump; use bumpalo::boxed::Box; use bumpalo::collections::Vec; -use gc_arena::Collect; +use fix_builtins::{BUILTINS, BuiltinId}; +use fix_common::StringId; use ghost_cell::{GhostCell, GhostToken}; +use num_enum::TryFromPrimitive as _; use rnix::{TextRange, ast}; -use string_interner::symbol::SymbolU32; +use string_interner::DefaultStringInterner; -use crate::runtime::BuiltinId; +pub mod downgrade; pub type HashMap<'ir, K, V> = hashbrown::HashMap; @@ -157,11 +159,6 @@ pub enum Ir<'ir, Ref> { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct ThunkId(pub usize); -#[repr(transparent)] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Collect)] -#[collect(require_static)] -pub struct StringId(pub SymbolU32); - #[repr(transparent)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct SpanId(pub u32); @@ -258,3 +255,47 @@ pub struct Param<'ir> { pub optional: Vec<'ir, (StringId, TextRange)>, pub ellipsis: bool, } + +pub fn new_global_env( + strings: &mut DefaultStringInterner, +) -> hashbrown::HashMap>> { + let mut global_env = hashbrown::HashMap::new(); + let builtins_sym = StringId(strings.get_or_intern("builtins")); + global_env.insert(builtins_sym, Ir::Builtins); + + for (idx, &(name, _)) in BUILTINS.iter().enumerate() { + let id = BuiltinId::try_from_primitive(idx as u8).expect("infallible"); + let name = StringId(strings.get_or_intern(name)); + global_env.insert(name, Ir::Builtin(id)); + } + + let consts = [ + ( + "__currentSystem", + Ir::BuiltinConst(StringId(strings.get_or_intern("currentSystem"))), + ), + ("__langVersion", Ir::Int(6)), + ( + "__nixVersion", + Ir::BuiltinConst(StringId(strings.get_or_intern("nixVersion"))), + ), + ( + "__storeDir", + Ir::BuiltinConst(StringId(strings.get_or_intern("storeDir"))), + ), + ( + "__nixPath", + Ir::BuiltinConst(StringId(strings.get_or_intern("nixPath"))), + ), + ("null", Ir::Null), + ("true", Ir::Bool(true)), + ("false", Ir::Bool(false)), + ]; + + for (name, ir) in consts { + let name = StringId(strings.get_or_intern(name)); + global_env.insert(name, ir); + } + + global_env +} diff --git a/fix-vm/Cargo.toml b/fix-vm/Cargo.toml new file mode 100644 index 0000000..5c69607 --- /dev/null +++ b/fix-vm/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "fix-vm" +version = "0.1.0" +edition = "2024" + +[dependencies] +gc-arena = { workspace = true } +hashbrown = { workspace = true } +num_enum = { workspace = true } +smallvec = { workspace = true } +string-interner = { workspace = true } +likely_stable = { workspace = true } +sptr = "0.3" + +fix-builtins = { path = "../fix-builtins" } +fix-codegen = { path = "../fix-codegen" } +fix-common = { path = "../fix-common" } +fix-error = { path = "../fix-error" } diff --git a/fix/src/boxing.rs b/fix-vm/src/boxing.rs similarity index 99% rename from fix/src/boxing.rs rename to fix-vm/src/boxing.rs index d5e80d2..1695269 100644 --- a/fix/src/boxing.rs +++ b/fix-vm/src/boxing.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + use std::fmt; use std::num::NonZeroU8; @@ -22,7 +24,7 @@ impl ArrayExt for [T; N] { } } -pub(crate) trait RawStore: Sized { +pub trait RawStore: Sized { fn to_val(self, value: &mut Value); fn from_val(value: &Value) -> Self; } diff --git a/fix-vm/src/helpers.rs b/fix-vm/src/helpers.rs new file mode 100644 index 0000000..d13a79b --- /dev/null +++ b/fix-vm/src/helpers.rs @@ -0,0 +1,18 @@ +use fix_error::Error; + +use crate::value::StrictValue; +use crate::{NixNum, VmError}; + +pub(super) fn vm_err(msg: impl Into) -> VmError { + VmError::Uncatchable(Error::eval_error(msg.into())) +} + +pub(super) fn get_num(val: StrictValue<'_>) -> Option { + if let Some(i) = val.as_inline::() { + Some(NixNum::Int(i as i64)) + } else if let Some(gc_i) = val.as_gc::() { + Some(NixNum::Int(*gc_i)) + } else { + val.as_float().map(NixNum::Float) + } +} diff --git a/fix/src/runtime/vm.rs b/fix-vm/src/lib.rs similarity index 79% rename from fix/src/runtime/vm.rs rename to fix-vm/src/lib.rs index d596a5a..c56cc38 100644 --- a/fix/src/runtime/vm.rs +++ b/fix-vm/src/lib.rs @@ -1,27 +1,27 @@ use std::path::PathBuf; +use fix_builtins::{BUILTINS, BuiltinId}; +use fix_codegen::{AttrKeyType, InstructionPtr, OperandType}; +use fix_common::StringId; +use fix_error::{Error, Result, Source}; use gc_arena::arena::CollectionPhase; -use gc_arena::{Collect, Gc, Mutation, RefLock}; +use gc_arena::{Arena, Collect, Gc, Mutation, RefLock, Rootable}; use hashbrown::HashMap; use num_enum::TryFromPrimitive; use smallvec::SmallVec; -use string_interner::{DefaultStringInterner, Symbol as _}; +use string_interner::Symbol as _; +mod boxing; +mod stack; +mod value; +use stack::Stack; +use value::*; +mod helpers; +use helpers::*; +pub use value::StaticValue; -use super::Runtime; -use super::builtins::{BUILTINS, BuiltinId}; -use super::stack::Stack; -use super::value::*; -use crate::codegen::{ - InstructionPtr, KEY_DYNAMIC, KEY_STATIC, OPERAND_BIGINT, OPERAND_BUILTINS, OPERAND_CONST, - OPERAND_LOCAL, -}; -use crate::error::{Error, Result}; -use crate::ir::{Ir, RawIrRef, StringId}; -use crate::runtime::init_builtins; +type VmResult = std::result::Result; -pub(super) type VmResult = std::result::Result; - -pub(super) enum VmError { +enum VmError { Catchable(String), Uncatchable(Box), } @@ -34,68 +34,198 @@ impl From> for VmError { #[derive(Collect, Clone, Copy, Debug, PartialEq, Eq, Default)] #[collect(require_static)] -pub(super) enum ForceMode { +pub enum ForceMode { #[default] AsIs, Shallow, Deep, } +pub trait VmContext { + fn intern_string(&mut self, s: impl AsRef) -> StringId; + fn resolve_string(&self, id: StringId) -> &str; + fn bytecode(&self) -> &[u8]; + fn get_const(&self, id: u32) -> StaticValue; + + fn compile(&mut self, source: Source); +} + +trait VmContextExt: VmContext { + fn get_string<'a, 'gc: 'a>(&'a self, val: StrictValue<'gc>) -> Option<&'a str>; + fn convert_value(&self, val: Value) -> fix_common::Value; +} + +impl VmContextExt for T { + fn get_string<'a, 'gc: 'a>(&'a self, val: StrictValue<'gc>) -> Option<&'a str> { + if let Some(sid) = val.as_inline::() { + Some(self.resolve_string(sid)) + } else { + val.as_gc::().map(|ns| ns.as_ref().as_str()) + } + } + + fn convert_value(&self, val: Value) -> fix_common::Value { + use fix_common::Value; + if let Some(i) = val.as_inline::() { + Value::Int(i as i64) + } else if let Some(gc_i) = val.as_gc::() { + Value::Int(*gc_i) + } else if let Some(f) = val.as_float() { + Value::Float(f) + } else if let Some(b) = val.as_inline::() { + Value::Bool(b) + } else if val.is::() { + Value::Null + } else if let Some(sid) = val.as_inline::() { + let s = self.resolve_string(sid).to_owned(); + Value::String(s) + } else if let Some(ns) = val.as_gc::() { + Value::String(ns.as_str().to_owned()) + } else if let Some(attrs) = val.as_gc::() { + let mut map = std::collections::BTreeMap::new(); + for &(key, val) in attrs.iter() { + let key = self.resolve_string(key).to_owned(); + let converted = self.convert_value(val); + map.insert(fix_common::Symbol::from(key), converted); + } + Value::AttrSet(fix_common::AttrSet::new(map)) + } else if let Some(list) = val.as_gc::() { + let items: Vec<_> = list + .inner + .iter() + .copied() + .map(|v| self.convert_value(v)) + .collect(); + Value::List(fix_common::List::new(items)) + } else if val.is::() { + Value::Func + } else if val.is::() { + Value::Thunk + } else if val.as_inline::().is_some() { + Value::PrimOp("primop".into()) + } else if val.is::() { + Value::PrimOpApp("primop-app".into()) + } else { + Value::Null + } + } +} + +pub struct Vm { + arena: Arena]>, + error_context: Vec, + ctx: C, + pc: usize, + fuel: usize, + force_mode: ForceMode, +} + #[derive(Collect)] #[collect(no_drop)] -pub(super) struct GcRoot<'gc> { +struct GcRoot<'gc> { stack: Stack<65536, Value<'gc>>, temp_stack: Vec>, frames: Stack<8192, CallFrame<'gc>>, - with_scope: Option>>, + with_env: Option>>, builtins: Value<'gc>, empty_list: Value<'gc>, empty_attrs: Value<'gc>, import_cache: HashMap>, - current_env: Option>>>, + current_env: Option>, } -pub(super) fn new_gc_root<'gc>( - mc: &Mutation<'gc>, - strings: &mut DefaultStringInterner, -) -> ( - GcRoot<'gc>, - HashMap>>, -) { - let (global_env, builtins) = init_builtins(mc, strings); - let root = GcRoot { - stack: Stack::new(), - temp_stack: Vec::new(), - frames: Stack::new(), - with_scope: None, - builtins, - empty_list: Value::new_gc(Gc::new(mc, List::default())), - empty_attrs: Value::new_gc(Gc::new(mc, AttrSet::default())), - import_cache: HashMap::new(), - current_env: None, - }; - (root, global_env) +// TODO: refactor +fn init_builtins<'gc>(mc: &Mutation<'gc>, ctx: &mut impl VmContext) -> Value<'gc> { + let mut entries = SmallVec::with_capacity(BUILTINS.len()); + + for (idx, &(name, arity)) in BUILTINS.iter().enumerate() { + let id = BuiltinId::try_from_primitive(idx as u8).expect("infallible"); + let name = name.strip_prefix("__").unwrap_or(name); + let name = ctx.intern_string(name); + entries.push((name, Value::new_inline(PrimOp { id, arity }))); + } + + let consts = [ + ( + "__currentSystem", + // FIXME: detect currentSystem + Value::new_gc(Gc::new(mc, NixString::new("x86_64-linux"))), + ), + ("__langVersion", Value::new_inline(6i32)), + ( + "__nixVersion", + Value::new_gc(Gc::new(mc, NixString::new("2.24.0"))), + ), + ( + "__storeDir", + Value::new_gc(Gc::new(mc, NixString::new("/nix/store"))), + ), + ( + "__nixPath", + // FIXME: get from config + Value::new_gc(Gc::new( + mc, + List { + inner: SmallVec::new(), + }, + )), + ), + ("null", Value::new_inline(Null)), + ("true", Value::new_inline(true)), + ("false", Value::new_inline(false)), + ]; + + for (name, val) in consts { + let name = name.strip_prefix("__").unwrap_or(name); + let name = ctx.intern_string(name); + entries.push((name, val)); + } + + // Self-reference thunk for builtins.builtins + let self_ref_thunk: Gc<'gc, Thunk<'gc>> = Gc::new(mc, RefLock::new(ThunkState::Blackhole)); + let sym = ctx.intern_string("builtins"); + entries.push((sym, Value::new_gc(self_ref_thunk))); + + entries.sort_by_key(|(k, _)| *k); + + let builtins_set = Gc::new(mc, AttrSet::from_sorted_unchecked(entries)); + Value::new_gc(builtins_set) } impl<'gc> GcRoot<'gc> { + fn new(mc: &Mutation<'gc>, ctx: &mut impl VmContext) -> Self { + let builtins = init_builtins(mc, ctx); + GcRoot { + stack: Stack::new(), + temp_stack: Vec::new(), + frames: Stack::new(), + with_env: None, + builtins, + empty_list: Value::new_gc(Gc::new(mc, List::default())), + empty_attrs: Value::new_gc(Gc::new(mc, AttrSet::default())), + import_cache: HashMap::new(), + current_env: None, + } + } + #[inline(always)] fn env(&self) -> Gc<'gc, RefLock>> { self.current_env.expect("no current env") } #[inline(always)] - pub(super) fn push_stack(&mut self, val: Value<'gc>) { + fn push_stack(&mut self, val: Value<'gc>) { self.stack.push(val).expect("stack overflow"); } #[inline(always)] - pub(super) fn pop_stack(&mut self) -> Value<'gc> { + fn pop_stack(&mut self) -> Value<'gc> { self.stack.pop().expect("stack underflow") } #[inline(always)] #[track_caller] - pub(super) fn pop_stack_forced(&mut self) -> StrictValue<'gc> { + fn pop_stack_forced(&mut self) -> StrictValue<'gc> { self.stack .pop() .expect("stack underflow") @@ -104,58 +234,26 @@ impl<'gc> GcRoot<'gc> { } } -pub(super) struct ErrorFrame { +struct ErrorFrame { span_id: u32, message: Option, } -#[derive(Collect, Debug)] -#[collect(no_drop)] -pub(super) struct WithScope<'gc> { - env: Value<'gc>, - prev: Option>>, -} - #[derive(Collect, Debug)] #[collect(no_drop)] struct CallFrame<'gc> { pc: usize, env: Gc<'gc, RefLock>>, -} - -#[derive(Clone, Copy, Debug)] -pub(super) enum BinOpTag { - Add, - Sub, - Mul, - Div, - Eq, - Neq, - Lt, - Gt, - Leq, - Geq, - Concat, - Update, -} - -pub(super) enum ForceResult<'gc> { - Ready(StrictValue<'gc>), - NeedEval { - ip: u32, - env: Gc<'gc, RefLock>>, - thunk: Gc<'gc, Thunk<'gc>>, - }, - NeedApply(Gc<'gc, Thunk<'gc>>), + with_env: Option>>, } pub(crate) enum Action { Continue, Return, - Done(Result), + Done(Result), } -pub(super) enum NixNum { +enum NixNum { Int(i64), Float(f64), } @@ -204,15 +302,28 @@ macro_rules! try_vm { ($self:ident; $expr:expr) => { match $expr { Ok(v) => v, - Err(e) => return Runtime::handle_vm_error($self, e), + Err(e) => return Vm::handle_vm_error($self, e), } }; } -impl Runtime { +impl Vm { + const DEFAULT_FUEL_AMOUNT: usize = 2048; + + pub fn new(mut ctx: C, ip: InstructionPtr, force_mode: ForceMode) -> Self { + Self { + arena: Arena::new(|mc| GcRoot::new(mc, &mut ctx)), + ctx, + force_mode, + pc: ip.0, + fuel: Self::DEFAULT_FUEL_AMOUNT, + error_context: Vec::new(), + } + } + #[inline(always)] fn read_array(&mut self) -> [u8; N] { - let ret = self.bytecode[self.pc..self.pc + N] + let ret = self.ctx.bytecode()[self.pc..self.pc + N] .try_into() .expect("read_array failed"); self.pc += N; @@ -252,29 +363,29 @@ impl Runtime { #[inline(always)] fn read_string_id(&mut self) -> StringId { let raw = self.read_u32(); - StringId(unsafe { - string_interner::symbol::SymbolU32::try_from_usize(raw as usize).unwrap_unchecked() - }) + StringId(string_interner::symbol::SymbolU32::try_from_usize(raw as usize).unwrap()) } fn read_operand(&mut self) -> OperandData { let tag = self.read_u8(); - match tag { - OPERAND_CONST => { - let idx = self.read_u32(); - OperandData::Const(self.constants[idx as usize]) + let Ok(ty) = OperandType::try_from_primitive(tag) + .map_err(|err| panic!("unknown operand tag: {:#04x}", err.number)); + match ty { + OperandType::Const => { + let id = self.read_u32(); + #[allow(clippy::unwrap_used)] + OperandData::Const(self.ctx.get_const(id)) } - OPERAND_LOCAL => { + OperandType::Local => { let layer = self.read_u8(); let idx = self.read_u32(); OperandData::Local { layer, idx } } - OPERAND_BUILTINS => OperandData::Builtins, - OPERAND_BIGINT => { + OperandType::Builtins => OperandData::Builtins, + OperandType::BigInt => { let val = self.read_i64(); OperandData::BigInt(val) } - _ => panic!("unknown operand tag: {tag:#04x}"), } } @@ -282,26 +393,43 @@ impl Runtime { let mut keys = SmallVec::with_capacity(n); for _ in 0..n { let tag = self.read_u8(); - match tag { - KEY_STATIC => { - let sid = self.read_string_id(); - keys.push(SelectKeyData::Static(sid)); - } - KEY_DYNAMIC => { - keys.push(SelectKeyData::Dynamic); - } - _ => panic!("unknown key tag: {tag:#04x}"), - } + let Ok(ty) = AttrKeyType::try_from_primitive(tag) + .map_err(|err| panic!("unknown key tag: {:#04x}", err.number)); + match ty { + AttrKeyType::Static => keys.push(SelectKeyData::Static(self.read_string_id())), + AttrKeyType::Dynamic => keys.push(SelectKeyData::Dynamic), + }; } keys } #[inline(always)] fn execute_one(&mut self) -> Action { - use crate::codegen::Op::{self, *}; + use fix_codegen::Op::{self, *}; - let Ok(op) = Op::try_from_primitive(self.bytecode[self.pc]) - .map_err(|err| panic!("unknown opcode: {:#04x}", err.number)); + const COLLECTOR_GRANULARITY: f64 = 1024.0; + + if likely_stable::unlikely(self.fuel == 0) { + if self.arena.metrics().allocation_debt() > COLLECTOR_GRANULARITY { + if self.arena.collection_phase() == CollectionPhase::Sweeping { + self.arena.collect_debt(); + } else if let Some(marked) = self.arena.mark_debt() { + marked.start_sweeping(); + } + } + self.fuel = Self::DEFAULT_FUEL_AMOUNT; + } + self.fuel -= 1; + + let byte = self.ctx.bytecode()[self.pc]; + if likely_stable::unlikely(!(0..Op::Illegal as u8).contains(&byte)) { + panic!("unknown opcode: {byte:#04x}") + } + let op = unsafe { + std::mem::transmute::(byte) + }; + // let Ok(op) = Op::try_from_primitive(self.ctx.bytecode()[self.pc]) + // .map_err(|err| panic!("unknown opcode: {:#04x}", err.number)); self.pc += 1; match op { @@ -368,6 +496,7 @@ impl Runtime { RefLock::new(ThunkState::Pending { ip: entry_point as usize, env: root.env(), + with_env: root.with_env, }), ); root.push_stack(Value::new_gc(thunk)); @@ -437,7 +566,6 @@ impl Runtime { Call => { // force func - let _span = self.read_u32(); self.force_tos(); self.arena.mutate_root(|mc, root| { let func = root.pop_stack(); @@ -455,6 +583,7 @@ impl Runtime { .push(CallFrame { pc: self.pc, env: root.env(), + with_env: root.with_env, }) .expect("frame stack overflow"); self.pc = ip as usize; @@ -465,19 +594,17 @@ impl Runtime { } }); } - CallNoSpan => { - todo!("implement CallNoSpan"); - } MakeAttrs => { let count = self.read_u32() as usize; let mut entries: SmallVec<[AttrEntry; 4]> = SmallVec::with_capacity(count); for _ in 0..count { let key_tag = self.read_u8(); - let key = match key_tag { - KEY_STATIC => AttrKeyData::Static(self.read_string_id()), - KEY_DYNAMIC => AttrKeyData::Dynamic(self.read_operand()), - _ => panic!("unknown key tag: {key_tag:#04x}"), + let Ok(ty) = AttrKeyType::try_from_primitive(key_tag) + .map_err(|err| panic!("unknown key tag: {:#04x}", err.number)); + let key = match ty { + AttrKeyType::Static => AttrKeyData::Static(self.read_string_id()), + AttrKeyType::Dynamic => AttrKeyData::Dynamic(self.read_operand()), }; let val = self.read_operand(); let _span_id = self.read_u32(); @@ -498,7 +625,7 @@ impl Runtime { kv.push((key_sid, val)); } kv.sort_by_key(|(k, _)| *k); - let attrs = Gc::new(mc, unsafe { AttrSet::from_sorted_unchecked(kv) }); + let attrs = Gc::new(mc, AttrSet::from_sorted_unchecked(kv)); root.push_stack(Value::new_gc(attrs)); }); } @@ -550,14 +677,14 @@ impl Runtime { }); match key_data { Ok(sid) => sid, - Err(s) => StringId(self.strings.get_or_intern(&s)), + Err(s) => self.ctx.intern_string(s), } } }; let result = self.arena.mutate_root(|_, root| { let val = root.pop_stack(); - let Some(attrset) = val.as_gc::>() else { + let Some(attrset) = val.as_gc::() else { return Err(vm_err("value is not a set while a set was expected")); }; match attrset.lookup(key_sid) { @@ -573,13 +700,13 @@ impl Runtime { Err(e) => { self.arena .mutate_root(|_, root| root.temp_stack.truncate(temp_base)); - return Runtime::handle_vm_error(self, e); + return Vm::handle_vm_error(self, e); } Ok(false) => { self.arena .mutate_root(|_, root| root.temp_stack.truncate(temp_base)); - let name = self.strings.resolve(key_sid.0).unwrap_or("«unknown»"); - return Runtime::handle_vm_error( + let name = self.ctx.resolve_string(key_sid); + return Vm::handle_vm_error( self, vm_err(format!("attribute '{name}' missing")), ); @@ -643,14 +770,14 @@ impl Runtime { }); match key_data { Ok(sid) => sid, - Err(s) => StringId(self.strings.get_or_intern(&s)), + Err(s) => self.ctx.intern_string(s), } } }; let found = self.arena.mutate_root(|_, root| { let val = root.pop_stack(); - if let Some(attrset) = val.as_gc::>() + if let Some(attrset) = val.as_gc::() && let Some(v) = attrset.lookup(key_sid) { root.push_stack(v); @@ -708,15 +835,13 @@ impl Runtime { OpAdd => { self.force_n(2); - let strings = &self.strings; let res = self.arena.mutate_root(|mc, root| { let rhs = root.pop_stack_forced(); let lhs = root.pop_stack_forced(); // FIXME: path & string context - if let (Some(ls), Some(rs)) = ( - Self::get_string(strings, lhs), - Self::get_string(strings, rhs), - ) { + if let (Some(ls), Some(rs)) = + (self.ctx.get_string(lhs), self.ctx.get_string(rhs)) + { let ns = Gc::new(mc, NixString::new(format!("{ls}{rs}"))); root.push_stack(Value::new_gc(ns)); return Ok(()); @@ -749,7 +874,7 @@ impl Runtime { let res = self.arena.mutate_root(|mc, root| { let rhs = root.pop_stack_forced(); let lhs = root.pop_stack_forced(); - match (Self::get_num(lhs), Self::get_num(rhs)) { + match (get_num(lhs), get_num(rhs)) { (_, Some(NixNum::Int(0))) => Err(vm_err("division by zero")), (_, Some(NixNum::Float(0.))) => Err(vm_err("division by zero")), _ => Ok(()), @@ -788,10 +913,10 @@ impl Runtime { let rhs = root.pop_stack_forced(); let lhs = root.pop_stack_forced(); // TODO: better type-assert ergonomic - let Some(l) = lhs.as_gc::>() else { + let Some(l) = lhs.as_gc::() else { return Err(vm_err("cannot concatenate: left operand is not a list")); }; - let Some(r) = rhs.as_gc::>() else { + let Some(r) = rhs.as_gc::() else { return Err(vm_err("cannot concatenate: right operand is not a list")); }; let mut items = SmallVec::new(); @@ -808,10 +933,10 @@ impl Runtime { let rhs = root.pop_stack_forced(); let lhs = root.pop_stack_forced(); // TODO: better type-assert ergonomic - let Some(l) = lhs.as_gc::>() else { + let Some(l) = lhs.as_gc::() else { return Err(vm_err("cannot update: left operand is not a set")); }; - let Some(r) = rhs.as_gc::>() else { + let Some(r) = rhs.as_gc::() else { return Err(vm_err("cannot update: right operand is not a set")); }; root.push_stack(Value::new_gc(l.merge(&r, mc))); @@ -876,27 +1001,28 @@ impl Runtime { let env = root.pop_stack(); let scope = Gc::new( mc, - WithScope { + WithEnv { env, - prev: root.with_scope, + prev: root.with_env, }, ); - root.with_scope = Some(scope); + root.with_env = Some(scope); }); } PopWith => self.arena.mutate_root(|_, root| { - let Some(scope) = root.with_scope else { + let Some(scope) = root.with_env else { unreachable!("no with_scope to pop"); }; - root.with_scope = scope.prev; + root.with_env = scope.prev; }), WithLookup => { let name = self.read_string_id(); let mut depth = 0; + // FIXME: this implementation is garbage loop { let found_scope = self.arena.mutate_root(|_, root| { - let mut cur = root.with_scope; + let mut cur = root.with_env; for _ in 0..depth { if let Some(s) = cur { cur = s.prev; @@ -914,8 +1040,8 @@ impl Runtime { }); if !found_scope { - let name_str = self.strings.resolve(name.0).unwrap_or("«unknown»"); - return Runtime::handle_vm_error( + let name_str = self.ctx.resolve_string(name); + return Vm::handle_vm_error( self, vm_err(format!("undefined variable '{name_str}'")), ); @@ -927,7 +1053,7 @@ impl Runtime { let lookup_result = self.arena.mutate_root(|_, root| { let val = root.pop_stack(); - let Some(attrs) = val.as_gc::>() else { + let Some(attrs) = val.as_gc::() else { return Err(vm_err("value in 'with' scope must be a set")); }; @@ -940,9 +1066,9 @@ impl Runtime { }); match lookup_result { - Ok(true) => break, // Successfully resolved and pushed to stack + Ok(true) => break, // Successfully resolved and pushed to stack Ok(false) => depth += 1, // Move to the parent 'with' scope - Err(e) => return Runtime::handle_vm_error(self, e), + Err(e) => return Vm::handle_vm_error(self, e), } } } @@ -978,32 +1104,13 @@ impl Runtime { Return => { return self.handle_return(); } + + Illegal => unreachable!() } Action::Continue } - pub(super) fn get_string<'a, 'gc: 'a>( - strings: &'a DefaultStringInterner, - val: StrictValue<'gc>, - ) -> Option<&'a str> { - if let Some(sid) = val.as_inline::() { - Some(strings.resolve(sid.0)?) - } else { - val.as_gc::().map(|ns| ns.as_ref().as_str()) - } - } - - pub(super) fn get_num(val: StrictValue<'_>) -> Option { - if let Some(i) = val.as_inline::() { - Some(NixNum::Int(i as i64)) - } else if let Some(gc_i) = val.as_gc::() { - Some(NixNum::Int(*gc_i)) - } else { - val.as_float().map(NixNum::Float) - } - } - #[inline] fn numeric_binop<'gc>( lhs: StrictValue<'gc>, @@ -1012,7 +1119,7 @@ impl Runtime { int_op: fn(i64, i64) -> i64, float_op: fn(f64, f64) -> f64, ) -> VmResult> { - match (Self::get_num(lhs), Self::get_num(rhs)) { + match (get_num(lhs), get_num(rhs)) { (Some(NixNum::Int(a)), Some(NixNum::Int(b))) => Ok(Value::make_int(int_op(a, b), mc)), (Some(NixNum::Float(a)), Some(NixNum::Float(b))) => { Ok(Value::new_float(float_op(a, b))) @@ -1027,19 +1134,19 @@ impl Runtime { } } - pub(super) fn values_equal(&mut self) -> VmResult { + #[inline] + fn values_equal(&mut self) -> VmResult { enum State { Bool(bool), List(usize), AttrSet(usize), } - let strings = &self.strings; let state = self.arena.mutate_root(|_, root| { let rhs = root.pop_stack_forced(); let lhs = root.pop_stack_forced(); - if let (Some(a), Some(b)) = (Self::get_num(lhs), Self::get_num(rhs)) { + if let (Some(a), Some(b)) = (get_num(lhs), get_num(rhs)) { return State::Bool(match (a, b) { (NixNum::Int(a), NixNum::Int(b)) => a == b, (NixNum::Float(a), NixNum::Float(b)) => a == b, @@ -1053,13 +1160,10 @@ impl Runtime { if lhs.is::() && rhs.is::() { return State::Bool(true); } - if let (Some(a), Some(b)) = ( - Self::get_string(strings, lhs), - Self::get_string(strings, rhs), - ) { + if let (Some(a), Some(b)) = (self.ctx.get_string(lhs), self.ctx.get_string(rhs)) { return State::Bool(a == b); } - if let (Some(a), Some(b)) = (lhs.as_gc::>(), rhs.as_gc::>()) { + if let (Some(a), Some(b)) = (lhs.as_gc::(), rhs.as_gc::()) { if a.inner.len() != b.inner.len() { return State::Bool(false); } @@ -1069,7 +1173,7 @@ impl Runtime { } return State::List(a.inner.len()); } - if let (Some(a), Some(b)) = (lhs.as_gc::>(), rhs.as_gc::>()) { + if let (Some(a), Some(b)) = (lhs.as_gc::(), rhs.as_gc::()) { if a.len() != b.len() { return State::Bool(false); } @@ -1112,16 +1216,13 @@ impl Runtime { } } - pub(super) fn compare_values( - &mut self, - pred: impl FnOnce(std::cmp::Ordering) -> bool, - ) -> VmResult<()> { - let strings = &self.strings; + #[inline] + fn compare_values(&mut self, pred: impl FnOnce(std::cmp::Ordering) -> bool) -> VmResult<()> { self.arena.mutate_root(|_, root| { let rhs = root.pop_stack_forced(); let lhs = root.pop_stack_forced(); - if let (Some(a), Some(b)) = (Self::get_num(lhs), Self::get_num(rhs)) { + if let (Some(a), Some(b)) = (get_num(lhs), get_num(rhs)) { let ord = match (a, b) { (NixNum::Int(a), NixNum::Int(b)) => a.cmp(&b), (NixNum::Float(a), NixNum::Float(b)) => { @@ -1137,10 +1238,7 @@ impl Runtime { root.push_stack(Value::new_inline(pred(ord))); return VmResult::Ok(()); } - if let (Some(a), Some(b)) = ( - Self::get_string(strings, lhs), - Self::get_string(strings, rhs), - ) { + if let (Some(a), Some(b)) = (self.ctx.get_string(lhs), self.ctx.get_string(rhs)) { root.push_stack(Value::new_inline(pred(a.cmp(b)))); return VmResult::Ok(()); } @@ -1149,30 +1247,7 @@ impl Runtime { Ok(()) } - #[inline(always)] - fn check_gc(&mut self) { - const COLLECTOR_GRANULARITY: f64 = 1024.0; - - if self.fuel == 0 { - if self.arena.metrics().allocation_debt() > COLLECTOR_GRANULARITY { - if self.arena.collection_phase() == CollectionPhase::Sweeping { - self.arena.collect_debt(); - } else if let Some(marked) = self.arena.mark_debt() { - marked.start_sweeping(); - } - } - self.fuel = Self::DEFAULT_FUEL_AMOUNT; - } - self.fuel -= 1; - } - - pub(super) fn run( - &mut self, - ip: InstructionPtr, - mode: ForceMode, - ) -> Result { - self.pc = ip.0; - self.force_mode = mode; + pub fn run(mut self) -> Result { self.arena.mutate_root(|mc, root| { if root.current_env.is_none() { root.current_env = Some(Gc::new(mc, RefLock::new(Env::empty()))); @@ -1180,7 +1255,6 @@ impl Runtime { }); loop { - self.check_gc(); match self.execute_one() { Action::Continue => (), Action::Return => (), @@ -1190,34 +1264,35 @@ impl Runtime { } #[inline(always)] - pub(super) fn push_stack(&mut self, f: impl for<'gc> FnOnce(&Mutation<'gc>) -> Value<'gc>) { + fn push_stack(&mut self, f: impl for<'gc> FnOnce(&Mutation<'gc>) -> Value<'gc>) { self.arena.mutate_root(|mc, root| { root.stack.push(f(mc)).expect("stack overflow"); }) } #[inline(always)] - pub(super) fn push_empty_list(&mut self) { + fn push_empty_list(&mut self) { self.arena.mutate_root(|_, root| { root.push_stack(root.empty_list); }); } #[inline(always)] - pub(super) fn push_empty_attrs(&mut self) { + fn push_empty_attrs(&mut self) { self.arena.mutate_root(|_, root| { root.push_stack(root.empty_attrs); }); } #[inline(always)] - pub(super) fn push_builtins(&mut self) { + fn push_builtins(&mut self) { self.arena.mutate_root(|_, root| { root.push_stack(root.builtins); }); } - pub(super) fn force_tos(&mut self) -> Action { + #[inline] + fn force_tos(&mut self) -> Action { loop { let (run, target_depth) = self.arena.mutate_root(|_mc, root| { let thunk = root.stack.tos_mut().expect("stack underflow"); @@ -1226,15 +1301,17 @@ impl Runtime { return (false, 0); }; match *thunk_state.borrow() { - ThunkState::Pending { ip, env } => { + ThunkState::Pending { ip, env, with_env } => { root.frames .push(CallFrame { pc: self.pc, env: root.env(), + with_env: root.with_env, }) .expect("call stack overflow"); self.pc = ip; root.current_env = Some(env); + root.with_env = with_env; (true, root.frames.len()) } ThunkState::Apply { .. } => todo!("force_tos"), @@ -1245,11 +1322,10 @@ impl Runtime { ThunkState::Blackhole => todo!("force_tos"), } }); - if !run { + if likely_stable::likely(!run) { return Action::Continue; } loop { - self.check_gc(); match self.execute_one() { Action::Continue => (), Action::Return => { @@ -1275,7 +1351,8 @@ impl Runtime { } } - pub(super) fn force_n(&mut self, n: usize) { + #[inline] + fn force_n(&mut self, n: usize) { if n == 0 { return; } @@ -1295,7 +1372,8 @@ impl Runtime { } } - pub(super) fn handle_return(&mut self) -> Action { + #[inline] + fn handle_return(&mut self) -> Action { self.force_tos(); let done = self.arena.mutate_root(|_, root| { let Some(frame) = root.frames.pop() else { @@ -1316,19 +1394,19 @@ impl Runtime { } } ForceMode::Deep => { - if let done @ Action::Done(_) = self.force_tos_shallow() { + if let done @ Action::Done(_) = self.force_tos_deep() { return done; } } } let val = self.arena.mutate_root(|_, root| { root.current_env = None; - convert_value(root.stack.pop().expect("stack underflow"), &self.strings) + self.ctx.convert_value(root.pop_stack()) }); Action::Done(Ok(val)) } - pub(super) fn force_tos_shallow(&mut self) -> Action { + fn force_tos_shallow(&mut self) -> Action { if let err @ Action::Done(Err(_)) = self.force_tos() { return err; } @@ -1336,14 +1414,15 @@ impl Runtime { let (is_list, is_attrs) = self.arena.mutate_root(|_, root| { let tos = *root.stack.tos().expect("stack underflow"); ( - tos.as_gc::>().is_some(), - tos.as_gc::>().is_some(), + tos.as_gc::().is_some(), + tos.as_gc::().is_some(), ) }); if is_list { let len = self.arena.mutate_root(|_, root| { - let list = root.pop_stack().as_gc::>().unwrap(); + #[allow(clippy::unwrap_used)] + let list = root.pop_stack().as_gc::().unwrap(); for &item in list.inner.iter() { root.temp_stack.push(item); } @@ -1383,7 +1462,8 @@ impl Runtime { }); } else if is_attrs { let len = self.arena.mutate_root(|_, root| { - let attrs = root.pop_stack().as_gc::>().unwrap(); + #[allow(clippy::unwrap_used)] + let attrs = root.pop_stack().as_gc::().unwrap(); for &(key, item) in attrs.iter() { root.temp_stack.push(Value::new_inline(key)); root.temp_stack.push(item); @@ -1415,6 +1495,7 @@ impl Runtime { let mut kv = SmallVec::with_capacity(len); let mut i = eval_base - len * 2; while i < eval_base { + #[allow(clippy::unwrap_used)] let key = root.temp_stack[i].as_inline::().unwrap(); let val = root.temp_stack[i + 1]; kv.push((key, val)); @@ -1423,7 +1504,7 @@ impl Runtime { kv.sort_by_key(|(k, _)| *k); root.temp_stack.truncate(eval_base - len * 2); - let new_attrs = Gc::new(mc, unsafe { AttrSet::from_sorted_unchecked(kv) }); + let new_attrs = Gc::new(mc, AttrSet::from_sorted_unchecked(kv)); root.push_stack(Value::new_gc(new_attrs)); }); } @@ -1431,7 +1512,7 @@ impl Runtime { Action::Continue } - pub(super) fn force_tos_deep(&mut self) -> Action { + fn force_tos_deep(&mut self) -> Action { if let err @ Action::Done(Err(_)) = self.force_tos() { return err; } @@ -1439,14 +1520,15 @@ impl Runtime { let (is_list, is_attrs) = self.arena.mutate_root(|_, root| { let tos = *root.stack.tos().expect("stack underflow"); ( - tos.as_gc::>().is_some(), - tos.as_gc::>().is_some(), + tos.as_gc::().is_some(), + tos.as_gc::().is_some(), ) }); if is_list { let len = self.arena.mutate_root(|_, root| { - let list = root.pop_stack().as_gc::>().unwrap(); + #[allow(clippy::unwrap_used)] + let list = root.pop_stack().as_gc::().unwrap(); for &item in list.inner.iter() { root.temp_stack.push(item); } @@ -1484,7 +1566,8 @@ impl Runtime { }); } else if is_attrs { let len = self.arena.mutate_root(|_, root| { - let attrs = root.pop_stack().as_gc::>().unwrap(); + #[allow(clippy::unwrap_used)] + let attrs = root.pop_stack().as_gc::().unwrap(); for &(key, item) in attrs.iter() { root.temp_stack.push(Value::new_inline(key)); root.temp_stack.push(item); @@ -1516,6 +1599,7 @@ impl Runtime { let mut kv = SmallVec::with_capacity(len); let mut i = eval_base - len * 2; while i < eval_base { + #[allow(clippy::unwrap_used)] let key = root.temp_stack[i].as_inline::().unwrap(); let val = root.temp_stack[i + 1]; kv.push((key, val)); @@ -1523,7 +1607,7 @@ impl Runtime { } kv.sort_by_key(|(k, _)| *k); root.temp_stack.truncate(eval_base - len * 2); - let new_attrs = Gc::new(mc, unsafe { AttrSet::from_sorted_unchecked(kv) }); + let new_attrs = Gc::new(mc, AttrSet::from_sorted_unchecked(kv)); root.push_stack(Value::new_gc(new_attrs)); }); } @@ -1540,52 +1624,3 @@ impl Runtime { } } } - -fn convert_value<'gc>(val: Value<'gc>, strings: &DefaultStringInterner) -> crate::value::Value { - if let Some(i) = val.as_inline::() { - crate::value::Value::Int(i as i64) - } else if let Some(gc_i) = val.as_gc::() { - crate::value::Value::Int(*gc_i) - } else if let Some(f) = val.as_float() { - crate::value::Value::Float(f) - } else if let Some(b) = val.as_inline::() { - crate::value::Value::Bool(b) - } else if val.is::() { - crate::value::Value::Null - } else if let Some(sid) = val.as_inline::() { - let s = strings.resolve(sid.0).unwrap_or("").to_owned(); - crate::value::Value::String(s) - } else if let Some(ns) = val.as_gc::() { - crate::value::Value::String(ns.as_str().to_owned()) - } else if let Some(attrs) = val.as_gc::>() { - let mut map = std::collections::BTreeMap::new(); - for &(key, val) in attrs.iter() { - let key_str = strings.resolve(key.0).unwrap_or("").to_owned(); - let converted = convert_value(val, strings); - map.insert(crate::value::Symbol::from(key_str), converted); - } - crate::value::Value::AttrSet(crate::value::AttrSet::new(map)) - } else if let Some(list) = val.as_gc::>() { - let items: Vec<_> = list - .inner - .iter() - .copied() - .map(|v| convert_value(v, strings)) - .collect(); - crate::value::Value::List(crate::value::List::new(items)) - } else if val.is::>() { - crate::value::Value::Func - } else if val.is::>() { - crate::value::Value::Thunk - } else if val.as_inline::().is_some() { - crate::value::Value::PrimOp("primop".into()) - } else if val.is::>() { - crate::value::Value::PrimOpApp("primop-app".into()) - } else { - crate::value::Value::Null - } -} - -pub(super) fn vm_err(msg: impl Into) -> VmError { - VmError::Uncatchable(Error::eval_error(msg.into())) -} diff --git a/fix/src/runtime/stack.rs b/fix-vm/src/stack.rs similarity index 81% rename from fix/src/runtime/stack.rs rename to fix-vm/src/stack.rs index 278ac47..41da55a 100644 --- a/fix/src/runtime/stack.rs +++ b/fix-vm/src/stack.rs @@ -1,7 +1,6 @@ use std::mem::MaybeUninit; use gc_arena::Collect; -use smallvec::SmallVec; pub(super) struct Stack { inner: Box<[MaybeUninit; N]>, @@ -74,15 +73,4 @@ impl Stack { pub(super) fn len(&self) -> usize { self.len } - - pub(super) fn pop_n(&mut self, n: usize) -> SmallVec<[T; M]> { - assert!(n <= self.len, "pop_n: not enough items on stack"); - let mut result = SmallVec::new(); - let start = self.len - n; - for i in start..self.len { - result.push(unsafe { self.inner.get_unchecked(i).assume_init_read() }); - } - self.len = start; - result - } } diff --git a/fix/src/runtime/value.rs b/fix-vm/src/value.rs similarity index 82% rename from fix/src/runtime/value.rs rename to fix-vm/src/value.rs index a11f9f3..dfc26c7 100644 --- a/fix/src/runtime/value.rs +++ b/fix-vm/src/value.rs @@ -1,25 +1,30 @@ +#![allow(dead_code)] + use std::fmt; use std::marker::PhantomData; use std::mem::size_of; use std::ops::Deref; +use fix_builtins::BuiltinId; +use fix_common::*; use gc_arena::collect::Trace; -use gc_arena::{Collect, Gc, Mutation, RefLock}; +use gc_arena::{Collect, Gc, GcRefLock, Mutation, RefLock}; use num_enum::TryFromPrimitive; -use sealed::sealed; use smallvec::SmallVec; use string_interner::Symbol; use string_interner::symbol::SymbolU32; +use crate::NixNum; use crate::boxing::{RawBox, RawStore, RawTag, Value as RawValue}; -use crate::ir::StringId; -use crate::runtime::builtins::BuiltinId; -#[sealed] +mod private { + pub trait Cealed {} +} + /// # Safety /// 1. TAG must be unique among all implementors. /// 2. TAG must be within 1..=7 -pub(crate) unsafe trait Storable { +pub(crate) unsafe trait Storable: private::Cealed { const TAG: (bool, u8); } pub(crate) trait InlineStorable: Storable + RawStore {} @@ -31,18 +36,18 @@ macro_rules! define_value_types { gc { $($gtype:ty => $gtag:expr, $gname:literal;)* } ) => { $( - #[sealed] unsafe impl Storable for $itype { const TAG: (bool, u8) = $itag; } impl InlineStorable for $itype {} + impl private::Cealed for $itype {} )* $( - #[sealed] unsafe impl Storable for $gtype { const TAG: (bool, u8) = $gtag; } impl GcStorable for $gtype {} + impl private::Cealed for $gtype {} )* const _: () = assert!(size_of::>() == 8); @@ -98,20 +103,6 @@ macro_rules! define_value_types { } } } - - impl fmt::Debug for StaticValue { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.tag() { - None => write!(f, "Float({:?})", unsafe { - self.raw.float().unwrap_unchecked() - }), - $(Some(<$itype as Storable>::TAG) => write!(f, "{}({:?})", $iname, unsafe { - self.as_inline::<$itype>().unwrap_unchecked() - }),)* - Some((neg, val)) => write!(f, "Unknown(neg={neg}, val={val})"), - } - } - } }; } @@ -166,7 +157,7 @@ impl<'gc> Value<'gc> { /// /// The value must actually store a `Gc<'gc, T>` with the matching type. #[inline(always)] - unsafe fn load_gc(&self) -> Gc<'gc, T> { + unsafe fn load_gc(self) -> Gc<'gc, T> { unsafe { let rv = self.raw.value().unwrap_unchecked(); let ptr: *const T = <*const T as RawStore>::from_val(rv); @@ -176,7 +167,7 @@ impl<'gc> Value<'gc> { /// Returns the `(negative, val)` tag, or `None` for a float. #[inline(always)] - fn tag(&self) -> Option<(bool, u8)> { + fn tag(self) -> Option<(bool, u8)> { self.raw.tag().map(|t| t.neg_val()) } } @@ -219,24 +210,24 @@ impl<'gc> Value<'gc> { impl<'gc> Value<'gc> { #[inline] - pub(crate) fn is_float(&self) -> bool { + pub(crate) fn is_float(self) -> bool { self.raw.is_float() } #[inline] - pub(crate) fn is(&self) -> bool { + pub(crate) fn is(self) -> bool { self.tag() == Some(T::TAG) } } impl<'gc> Value<'gc> { #[inline] - pub(crate) fn as_float(&self) -> Option { + pub(crate) fn as_float(self) -> Option { self.raw.float().copied() } #[inline] - pub(crate) fn as_inline(&self) -> Option { + pub(crate) fn as_inline(self) -> Option { if self.is::() { Some(unsafe { let rv = self.raw.value().unwrap_unchecked(); @@ -248,7 +239,7 @@ impl<'gc> Value<'gc> { } #[inline] - pub(crate) fn as_gc(&self) -> Option> { + pub(crate) fn as_gc(self) -> Option> { if self.is::() { Some(unsafe { let rv = self.raw.value().unwrap_unchecked(); @@ -260,6 +251,17 @@ impl<'gc> Value<'gc> { } } + #[inline] + pub(crate) fn as_num(self) -> Option { + if let Some(i) = self.as_inline::() { + Some(NixNum::Int(i as i64)) + } else if let Some(gc_i) = self.as_gc::() { + Some(NixNum::Int(*gc_i)) + } else { + self.as_float().map(NixNum::Float) + } + } + #[inline] pub(crate) fn restrict(self) -> Option> { if !self.is::>() { @@ -270,88 +272,50 @@ impl<'gc> Value<'gc> { } } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Default)] #[repr(transparent)] -pub(crate) struct StaticValue { - raw: RawBox, -} +pub struct StaticValue(Value<'static>); -impl Default for StaticValue { - #[inline(always)] - fn default() -> Self { - Self::new_inline(Null) - } -} - -impl From for Value<'_> { +impl<'gc> From for Value<'gc> { #[inline] fn from(value: StaticValue) -> Self { - Self { - raw: value.raw, - _marker: PhantomData, - } + // SAFETY: StaticValue is guaranteed to not contain any `Gc`. + unsafe { std::mem::transmute::, Value<'gc>>(value.0) } } } impl StaticValue { - #[inline(always)] - fn from_raw_value(rv: RawValue) -> Self { - Self { - raw: RawBox::from_value(rv), - } - } - #[inline] - pub(crate) fn to_bits(self) -> u64 { - self.raw.to_bits() + pub fn new_float(val: f64) -> Self { + Self(Value::new_float(val)) } - #[inline] - pub(crate) fn new_float(val: f64) -> Self { - Self { - raw: RawBox::from_float(val), - } + pub fn new_inline(val: T) -> Self { + Self(Value::new_inline(val)) } - #[inline] - pub(crate) fn new_inline(val: T) -> Self { - Self::from_raw_value(RawValue::store( - unsafe { RawTag::new_unchecked(T::TAG.0, T::TAG.1) }, - val, - )) + pub fn new_primop(id: BuiltinId, arity: u8) -> Self { + Self(Value::new_inline(PrimOp { id, arity })) } - #[inline] - pub(crate) fn is_float(&self) -> bool { - self.raw.is_float() + pub fn is_float(self) -> bool { + self.0.is_float() } - #[inline] - pub(crate) fn is(&self) -> bool { - self.tag() == Some(T::TAG) + pub fn is(self) -> bool { + self.0.is::() } - #[inline] - pub(crate) fn as_float(&self) -> Option { - self.raw.float().copied() + pub fn as_float(self) -> Option { + self.0.as_float() } - #[inline] - pub(crate) fn as_inline(&self) -> Option { - if self.is::() { - Some(unsafe { - let rv = self.raw.value().unwrap_unchecked(); - T::from_val(rv) - }) - } else { - None - } + pub fn as_inline(self) -> Option { + self.0.as_inline::() } - - /// Returns the `(negative, val)` tag, or `None` for a float. - #[inline(always)] - fn tag(&self) -> Option<(bool, u8)> { - self.raw.tag().map(|t| t.neg_val()) + #[inline] + pub fn to_bits(self) -> u64 { + self.0.raw.to_bits() } } @@ -420,7 +384,7 @@ impl<'gc> Deref for AttrSet<'gc> { } impl<'gc> AttrSet<'gc> { - pub(crate) unsafe fn from_sorted_unchecked( + pub(crate) fn from_sorted_unchecked( entries: SmallVec<[(StringId, Value<'gc>); 4]>, ) -> Self { debug_assert!(entries.is_sorted_by_key(|(key, _)| *key)); @@ -492,7 +456,8 @@ pub(crate) type Thunk<'gc> = RefLock>; pub(crate) enum ThunkState<'gc> { Pending { ip: usize, - env: Gc<'gc, RefLock>>, + env: GcEnv<'gc>, + with_env: Option>, }, Apply { func: Value<'gc>, @@ -506,8 +471,17 @@ pub(crate) enum ThunkState<'gc> { #[collect(no_drop)] pub(crate) struct Env<'gc> { pub(crate) locals: SmallVec<[Value<'gc>; 4]>, - pub(crate) prev: Option>>>, + pub(crate) prev: Option>, } +pub(crate) type GcEnv<'gc> = GcRefLock<'gc, Env<'gc>>; + +#[derive(Collect, Debug)] +#[collect(no_drop)] +pub(crate) struct WithEnv<'gc> { + pub(crate) env: Value<'gc>, + pub(crate) prev: Option>, +} +pub(crate) type GcWithEnv<'gc> = Gc<'gc, WithEnv<'gc>>; impl<'gc> Env<'gc> { pub(crate) fn empty() -> Self { diff --git a/fix/Cargo.toml b/fix/Cargo.toml index 72ec57c..fff4342 100644 --- a/fix/Cargo.toml +++ b/fix/Cargo.toml @@ -6,20 +6,9 @@ edition = "2024" [dependencies] mimalloc = "0.1" -tokio = { version = "1.41", features = [ - "rt-multi-thread", - "sync", - "net", - "io-util", -] } -nix-compat = { git = "https://git.snix.dev/snix/snix.git", version = "0.1.0", features = [ - "wire", - "async", -] } - # REPL anyhow = "1.0" -rustyline = "17.0" +rustyline = "18.0" # CLI clap = { version = "4", features = ["derive"] } @@ -28,67 +17,32 @@ clap = { version = "4", features = ["derive"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } -derive_more = { version = "2", features = ["full"] } +# Error Reporting thiserror = "2" miette = { version = "7.4", features = ["fancy"] } -hashbrown = "0.16" -string-interner = "0.19" -bumpalo = { version = "3.20", features = [ - "allocator-api2", - "boxed", - "collections", -] } +# Data Structure +hashbrown = { workspace = true } +smallvec = { workspace = true } +string-interner = { workspace = true } -rust-embed = "8.11" +# Memory Management +bumpalo = { workspace = true } -regex = "1.11" +rnix = { workspace = true } -nix-nar = "0.3" -sha2 = "0.10" -sha1 = "0.10" -md5 = "0.8" -hex = "0.4" +ere = { workspace = true } +ghost-cell = { workspace = true } -base64 = "0.22" - -reqwest = { version = "0.13", features = [ - "blocking", - "rustls", -], default-features = false } -tar = "0.4" -flate2 = "1.0" -xz2 = "0.1" -bzip2 = "0.6" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -# spec 1.0.0 -toml = "=0.9.9" -dirs = "6.0" -tempfile = "3.24" -rusqlite = { version = "0.38", features = ["bundled"] } - -rnix = "0.14" -rowan = "0.16" - -ere = "0.2.4" -num_enum = "0.7.5" -tap = "1.0.1" - -ghost-cell = "0.2" -colored = "3.1" -sptr = "0.3" -sealed = "0.6" -small-map = "0.1" -smallvec = "1.15" - -[dependencies.gc-arena] -git = "https://github.com/kyren/gc-arena" -rev = "75671ae03f53718357b741ed4027560f14e90836" -features = ["allocator-api2", "hashbrown", "smallvec"] +fix-common = { path = "../fix-common" } +fix-codegen = { path = "../fix-codegen" } +fix-error = { path = "../fix-error" } +fix-ir = { path = "../fix-ir" } +fix-vm = { path = "../fix-vm" } [dev-dependencies] criterion = { version = "0.8", features = ["html_reports"] } +tempfile = "3.24" test-log = { version = "0.2", features = ["trace"] } [[bench]] diff --git a/fix/benches/utils.rs b/fix/benches/utils.rs index 3e9fd5b..89bf3b8 100644 --- a/fix/benches/utils.rs +++ b/fix/benches/utils.rs @@ -1,18 +1,15 @@ #![allow(dead_code)] -use fix::error::{Result, Source}; -use fix::runtime::Runtime; -use fix::value::Value; +use fix::Evaluator; +use fix_common::Value; +use fix_error::{Result, Source}; pub fn eval(expr: &str) -> Value { - Runtime::new() - .unwrap() + Evaluator::new() .eval(Source::new_eval(expr.into()).unwrap()) .unwrap() } pub fn eval_result(expr: &str) -> Result { - Runtime::new() - .unwrap() - .eval(Source::new_eval(expr.into()).unwrap()) + Evaluator::new().eval(Source::new_eval(expr.into()).unwrap()) } diff --git a/fix/src/disassembler.rs b/fix/src/disassembler.rs deleted file mode 100644 index 48d2658..0000000 --- a/fix/src/disassembler.rs +++ /dev/null @@ -1,369 +0,0 @@ -use std::fmt::Write; - -use colored::Colorize; -use num_enum::TryFromPrimitive; - -use crate::codegen::{InstructionPtr, Op}; - -pub(crate) trait DisassemblerContext { - fn lookup_string(&self, id: u32) -> &str; - fn get_code(&self) -> &[u8]; -} - -pub(crate) struct Disassembler<'a, Ctx> { - code: &'a [u8], - ctx: &'a Ctx, - pc: usize, -} - -impl<'a, Ctx: DisassemblerContext> Disassembler<'a, Ctx> { - pub fn new(ip: InstructionPtr, ctx: &'a Ctx) -> Self { - Self { - code: ctx.get_code(), - ctx, - pc: ip.0, - } - } - - fn read_u8(&mut self) -> u8 { - let b = self.code[self.pc]; - self.pc += 1; - b - } - - fn read_u16(&mut self) -> u16 { - let bytes = self.code[self.pc..self.pc + 2] - .try_into() - .expect("no enough bytes"); - self.pc += 2; - u16::from_le_bytes(bytes) - } - - fn read_u32(&mut self) -> u32 { - let bytes = self.code[self.pc..self.pc + 4] - .try_into() - .expect("no enough bytes"); - self.pc += 4; - u32::from_le_bytes(bytes) - } - - fn read_i32(&mut self) -> i32 { - let bytes = self.code[self.pc..self.pc + 4] - .try_into() - .expect("no enough bytes"); - self.pc += 4; - i32::from_le_bytes(bytes) - } - - fn read_i64(&mut self) -> i64 { - let bytes = self.code[self.pc..self.pc + 8] - .try_into() - .expect("no enough bytes"); - self.pc += 8; - i64::from_le_bytes(bytes) - } - - fn read_f64(&mut self) -> f64 { - let bytes = self.code[self.pc..self.pc + 8] - .try_into() - .expect("no enough bytes"); - self.pc += 8; - f64::from_le_bytes(bytes) - } - - pub fn disassemble(&mut self) -> String { - self.disassemble_impl(false) - } - - pub fn disassemble_colored(&mut self) -> String { - self.disassemble_impl(true) - } - - fn disassemble_impl(&mut self, color: bool) -> String { - let mut out = String::new(); - if color { - let _ = writeln!(out, "{}", "=== Bytecode Disassembly ===".bold().white()); - let _ = writeln!( - out, - "{} {}", - "Length:".white(), - format!("{} bytes", self.code.len()).cyan() - ); - } else { - let _ = writeln!(out, "=== Bytecode Disassembly ==="); - let _ = writeln!(out, "Length: {} bytes", self.code.len()); - } - - while self.pc < self.code.len() { - let start_pos = self.pc; - let op_byte = self.read_u8(); - let (mnemonic, args) = self.decode_instruction(op_byte, start_pos); - - let bytes_slice = &self.code[start_pos + 1..self.pc]; - let mut chunks = bytes_slice.chunks(4); - - let first_chunk = chunks.next().unwrap_or(&[]); - let bytes_str = { - let mut temp = format!("{:02x}", self.code[start_pos]); - for b in first_chunk { - let _ = write!(&mut temp, " {:02x}", b); - } - temp - }; - - if color { - let sep = if args.is_empty() { "" } else { " " }; - let _ = writeln!( - out, - "{} {:<14} | {}{}{}", - format!("{:04x}", start_pos).dimmed(), - bytes_str.green(), - mnemonic.yellow().bold(), - sep, - args.cyan() - ); - } else { - let op_str = if args.is_empty() { - mnemonic.to_string() - } else { - format!("{} {}", mnemonic, args) - }; - let _ = writeln!(out, "{:04x} {:<14} | {}", start_pos, bytes_str, op_str); - } - - for chunk in chunks { - let bytes_str = { - let mut temp = String::from(" "); - for b in chunk { - let _ = write!(&mut temp, " {:02x}", b); - } - temp - }; - - let extra_width = if start_pos > 0 { - start_pos.ilog2() >> 4 - } else { - 0 - }; - - if color { - let _ = write!(out, " "); - for _ in 0..extra_width { - let _ = write!(out, " "); - } - let _ = writeln!(out, " {:<14} |", bytes_str.green()); - } else { - let _ = write!(out, " "); - for _ in 0..extra_width { - let _ = write!(out, " "); - } - let _ = writeln!(out, " {:<14} |", bytes_str); - } - } - } - out - } - - fn decode_instruction(&mut self, op_byte: u8, current_pc: usize) -> (&'static str, String) { - let op = Op::try_from_primitive(op_byte).expect("invalid op code"); - - match op { - Op::PushSmi => { - let val = self.read_i32(); - ("PushSmi", format!("{}", val)) - } - Op::PushBigInt => { - let val = self.read_i64(); - ("PushBigInt", format!("{}", val)) - } - Op::PushFloat => { - let val = self.read_f64(); - ("PushFloat", format!("{}", val)) - } - Op::PushString => { - let idx = self.read_u32(); - let s = self.ctx.lookup_string(idx); - let len = s.len(); - let mut s_fmt = format!("{:?}", s); - if s_fmt.len() > 60 { - s_fmt.truncate(57); - #[allow(clippy::unwrap_used)] - write!(s_fmt, "...\" (total {len} bytes)").unwrap(); - } - ("PushString", format!("@{} {}", idx, s_fmt)) - } - Op::PushNull => ("PushNull", String::new()), - Op::PushTrue => ("PushTrue", String::new()), - Op::PushFalse => ("PushFalse", String::new()), - - Op::LoadLocal => { - let idx = self.read_u32(); - ("LoadLocal", format!("[{}]", idx)) - } - Op::LoadOuter => { - let depth = self.read_u8(); - let idx = self.read_u32(); - ("LoadOuter", format!("depth={} [{}]", depth, idx)) - } - Op::StoreLocal => { - let idx = self.read_u32(); - ("StoreLocal", format!("[{}]", idx)) - } - Op::AllocLocals => { - let count = self.read_u32(); - ("AllocLocals", format!("count={}", count)) - } - - Op::MakeThunk => { - let offset = self.read_u32(); - ("MakeThunk", format!("-> {:04x}", offset)) - } - Op::MakeClosure => { - let offset = self.read_u32(); - let slots = self.read_u32(); - ("MakeClosure", format!("-> {:04x} slots={}", offset, slots)) - } - Op::MakePatternClosure => { - let offset = self.read_u32(); - let slots = self.read_u32(); - let req_count = self.read_u16(); - let opt_count = self.read_u16(); - let ellipsis = self.read_u8() != 0; - - let mut arg_str = format!( - "-> {:04x} slots={} req={} opt={} ...={})", - offset, slots, req_count, opt_count, ellipsis - ); - - arg_str.push_str(" Args=["); - for _ in 0..req_count { - let idx = self.read_u32(); - arg_str.push_str(&format!("Req({}) ", self.ctx.lookup_string(idx))); - } - for _ in 0..opt_count { - let idx = self.read_u32(); - arg_str.push_str(&format!("Opt({}) ", self.ctx.lookup_string(idx))); - } - - let total_args = req_count + opt_count; - for _ in 0..total_args { - let _name_idx = self.read_u32(); - let _span_id = self.read_u32(); - } - arg_str.push(']'); - - ("MakePatternClosure", arg_str) - } - - Op::Call => { - let span_id = self.read_u32(); - ("Call", format!("span={}", span_id)) - } - Op::CallNoSpan => ("CallNoSpan", String::new()), - - Op::MakeAttrs => { - let count = self.read_u32(); - ("MakeAttrs", format!("size={}", count)) - } - Op::MakeEmptyAttrs => ("MakeEmptyAttrs", String::new()), - - Op::Select => { - let path_len = self.read_u16(); - let span_id = self.read_u32(); - ("Select", format!("path_len={} span={}", path_len, span_id)) - } - Op::SelectDefault => { - let path_len = self.read_u16(); - let span_id = self.read_u32(); - ( - "SelectDefault", - format!("path_len={} span={}", path_len, span_id), - ) - } - Op::HasAttr => { - let path_len = self.read_u16(); - ("HasAttr", format!("path_len={}", path_len)) - } - - Op::MakeList => { - let count = self.read_u32(); - ("MakeList", format!("size={}", count)) - } - Op::MakeEmptyList => ("MakeEmptyList", String::new()), - - Op::OpAdd => ("OpAdd", String::new()), - Op::OpSub => ("OpSub", String::new()), - Op::OpMul => ("OpMul", String::new()), - Op::OpDiv => ("OpDiv", String::new()), - Op::OpEq => ("OpEq", String::new()), - Op::OpNeq => ("OpNeq", String::new()), - Op::OpLt => ("OpLt", String::new()), - Op::OpGt => ("OpGt", String::new()), - Op::OpLeq => ("OpLeq", String::new()), - Op::OpGeq => ("OpGeq", String::new()), - Op::OpConcat => ("OpConcat", String::new()), - Op::OpUpdate => ("OpUpdate", String::new()), - Op::OpNeg => ("OpNeg", String::new()), - Op::OpNot => ("OpNot", String::new()), - - Op::JumpIfFalse => { - let offset = self.read_i32(); - let target = (current_pc as isize + 1 + 4 + offset as isize) as usize; - ( - "JumpIfFalse", - format!("-> {:04x} offset={}", target, offset), - ) - } - Op::JumpIfTrue => { - let offset = self.read_i32(); - let target = (current_pc as isize + 1 + 4 + offset as isize) as usize; - ("JumpIfTrue", format!("-> {:04x} offset={}", target, offset)) - } - Op::Jump => { - let offset = self.read_i32(); - let target = (current_pc as isize + 1 + 4 + offset as isize) as usize; - ("Jump", format!("-> {:04x} offset={}", target, offset)) - } - - Op::ConcatStrings => { - let count = self.read_u16(); - let force = self.read_u8(); - ("ConcatStrings", format!("count={} force={}", count, force)) - } - Op::ResolvePath => ("ResolvePath", String::new()), - Op::Assert => { - let raw_idx = self.read_u32(); - let span_id = self.read_u32(); - ("Assert", format!("text_id={} span={}", raw_idx, span_id)) - } - Op::PushWith => ("PushWith", String::new()), - Op::PopWith => ("PopWith", String::new()), - Op::WithLookup => { - let idx = self.read_u32(); - let name = self.ctx.lookup_string(idx); - ("WithLookup", format!("{:?}", name)) - } - - Op::LoadBuiltins => ("LoadBuiltins", String::new()), - Op::LoadBuiltin => { - let id = self.read_u8(); - ("LoadBuiltin", format!("id={}", id)) - } - Op::MkPos => { - let span_id = self.read_u32(); - ("MkPos", format!("id={}", span_id)) - } - Op::LoadReplBinding => { - let idx = self.read_u32(); - let name = self.ctx.lookup_string(idx); - ("LoadReplBinding", format!("{:?}", name)) - } - Op::LoadScopedBinding => { - let idx = self.read_u32(); - let name = self.ctx.lookup_string(idx); - ("LoadScopedBinding", format!("{:?}", name)) - } - Op::Return => ("Return", String::new()), - } - } -} diff --git a/fix/src/lib.rs b/fix/src/lib.rs index 0035996..7cb4c60 100644 --- a/fix/src/lib.rs +++ b/fix/src/lib.rs @@ -1,22 +1,555 @@ #![warn(clippy::unwrap_used)] #![allow(dead_code)] -mod boxing; -pub mod error; -pub mod logging; -pub mod runtime; -pub mod value; +use bumpalo::Bump; +use fix_codegen::{BytecodeContext, InstructionPtr}; +use fix_common::{StringId, Symbol}; +use fix_error::{Error, Result, Source}; +use fix_ir::downgrade::{Downgrade as _, DowngradeContext}; +use fix_ir::{Ir, IrRef, RawIrRef, ThunkId}; +use fix_vm::{ForceMode, StaticValue, Vm, VmContext}; +use ghost_cell::{GhostCell, GhostToken}; +use hashbrown::{HashMap, HashSet}; +use string_interner::DefaultStringInterner; -mod codegen; -mod derivation; -mod disassembler; -mod downgrade; // mod fetcher; -mod ir; -mod nar; -mod nix_utils; -mod store; -mod string_context; +// mod nar; +// mod nix_utils; +// mod store; +// mod string_context; +mod derivation; +pub mod logging; #[global_allocator] static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; + +pub struct Evaluator { + bytecode: Vec, + constants: Constants, + strings: DefaultStringInterner, + + sources: Vec, + spans: Vec<(usize, rnix::TextRange)>, + // FIXME: remove? + thunk_count: usize, + + global_env: HashMap>>, +} + +impl Default for Evaluator { + fn default() -> Self { + Self::new() + } +} + +impl Evaluator { + pub fn new() -> Self { + let mut strings = DefaultStringInterner::new(); + let global_env = fix_ir::new_global_env(&mut strings); + Self { + sources: Vec::new(), + spans: Vec::new(), + strings, + thunk_count: 0, + bytecode: Vec::new(), + constants: Constants::default(), + + global_env, + } + } + + pub fn eval(&mut self, source: Source) -> Result { + self.do_eval(source, None, ForceMode::AsIs) + } + + pub fn eval_shallow(&mut self, source: Source) -> Result { + self.do_eval(source, None, ForceMode::Shallow) + } + + pub fn eval_deep(&mut self, source: Source) -> Result { + self.do_eval(source, None, ForceMode::Deep) + } + + pub fn eval_repl( + &mut self, + source: Source, + scope: &HashSet, + ) -> Result { + self.do_eval(source, Some(Scope::Repl(scope)), ForceMode::Shallow) + } + + fn do_eval<'ctx>( + &'ctx mut self, + source: Source, + extra_scope: Option>, + force_mode: ForceMode, + ) -> Result { + let root = self.downgrade(source, extra_scope)?; + let ip = fix_codegen::compile_bytecode(root.as_ref(), self); + let vm = Vm::new(self, ip, force_mode); + vm.run() + } + + pub fn add_binding( + &mut self, + _ident: &str, + _expr: &str, + _scope: &mut HashSet, + ) -> Result { + todo!() + } + + pub fn compile_bytecode(&mut self, source: Source) -> Result { + let root = self.downgrade(source, None)?; + let ip = fix_codegen::compile_bytecode(root.as_ref(), self); + Ok(ip) + } + + fn downgrade_ctx<'a, 'bump, 'id>( + &'a mut self, + bump: &'bump Bump, + token: GhostToken<'id>, + extra_scope: Option>, + ) -> DowngradeCtx<'a, 'id, 'bump> { + let Self { + global_env, + sources, + thunk_count, + strings, + .. + } = self; + DowngradeCtx { + bump, + token, + strings, + source: sources.last().expect("no current source").clone(), + scopes: [Scope::Global(global_env)] + .into_iter() + .chain(extra_scope) + .collect(), + with_scope_count: 0, + arg_count: 0, + thunk_count, + thunk_scopes: vec![ThunkScope::new_in(bump)], + } + } + + fn downgrade<'a>( + &'a mut self, + source: Source, + extra_scope: Option>, + ) -> Result { + tracing::debug!("Parsing Nix expression"); + + self.sources.push(source.clone()); + + let root = rnix::Root::parse(&source.src); + handle_parse_error(root.errors(), source).map_or(Ok(()), Err)?; + + tracing::debug!("Downgrading Nix expression"); + let expr = root + .tree() + .expr() + .ok_or_else(|| Error::parse_error("unexpected EOF".into()))?; + let bump = Bump::new(); + GhostToken::new(|token| { + let ir = self + .downgrade_ctx(&bump, token, extra_scope) + .downgrade_toplevel(expr)?; + let ir = unsafe { std::mem::transmute::, RawIrRef<'static>>(ir) }; + Ok(OwnedIr { _bump: bump, ir }) + }) + } +} + +impl VmContext for &mut Evaluator { + fn intern_string(&mut self, s: impl AsRef) -> StringId { + StringId(self.strings.get_or_intern(s)) + } + fn resolve_string(&self, id: StringId) -> &str { + #[allow(clippy::unwrap_used)] + self.strings.resolve(id.0).unwrap() + } + fn bytecode(&self) -> &[u8] { + &self.bytecode + } + fn get_const(&self, id: u32) -> StaticValue { + #[allow(clippy::unwrap_used)] + self.constants.get(id).unwrap() + } + + fn compile(&mut self, _source: Source) { + todo!(); + } +} + +#[derive(Default)] +struct Constants { + data: Vec, + dedup: HashMap, +} + +impl Constants { + fn insert(&mut self, val: StaticValue) -> u32 { + let bits = val.to_bits(); + *self.dedup.entry(bits).or_insert_with(|| { + let idx = self.data.len() as u32; + self.data.push(val); + idx + }) + } + + fn get(&self, id: u32) -> Option { + self.data.get(id as usize).copied() + } +} + +fn parse_error_span(error: &rnix::ParseError) -> Option { + use rnix::ParseError::*; + match error { + Unexpected(range) + | UnexpectedExtra(range) + | UnexpectedWanted(_, range, _) + | UnexpectedDoubleBind(range) + | DuplicatedArgs(range, _) => Some(*range), + _ => None, + } +} + +fn handle_parse_error<'a>( + errors: impl IntoIterator, + source: Source, +) -> Option> { + for err in errors { + if let Some(span) = parse_error_span(err) { + return Some( + Error::parse_error(err.to_string()) + .with_source(source) + .with_span(span), + ); + } + } + None +} + +struct DowngradeCtx<'ctx, 'id, 'ir> { + bump: &'ir Bump, + token: GhostToken<'id>, + strings: &'ctx mut DefaultStringInterner, + source: Source, + scopes: Vec>, + with_scope_count: u32, + arg_count: u32, + thunk_count: &'ctx mut usize, + thunk_scopes: Vec>, +} + +fn should_thunk<'id>(ir: IrRef<'id, '_>, token: &GhostToken<'id>) -> bool { + !matches!( + ir.borrow(token), + Ir::Builtin(_) + | Ir::Builtins + | Ir::Int(_) + | Ir::Float(_) + | Ir::Bool(_) + | Ir::Null + | Ir::Str(_) + | Ir::Thunk(_) + ) +} + +impl<'ctx, 'id, 'ir> DowngradeCtx<'ctx, 'id, 'ir> { + fn new( + bump: &'ir Bump, + token: GhostToken<'id>, + symbols: &'ctx mut DefaultStringInterner, + global: &'ctx HashMap>>, + extra_scope: Option>, + thunk_count: &'ctx mut usize, + source: Source, + ) -> Self { + Self { + bump, + token, + strings: symbols, + source, + scopes: std::iter::once(Scope::Global(global)) + .chain(extra_scope) + .collect(), + thunk_count, + arg_count: 0, + with_scope_count: 0, + thunk_scopes: vec![ThunkScope::new_in(bump)], + } + } +} + +impl<'ctx: 'ir, 'id, 'ir> DowngradeContext<'id, 'ir> for DowngradeCtx<'ctx, 'id, 'ir> { + fn new_expr(&self, expr: Ir<'ir, IrRef<'id, 'ir>>) -> IrRef<'id, 'ir> { + IrRef::new(self.bump.alloc(GhostCell::new(expr))) + } + + fn maybe_thunk(&mut self, ir: IrRef<'id, 'ir>) -> IrRef<'id, 'ir> { + if !should_thunk(ir, &self.token) { + return ir; + } + + let id = ThunkId(*self.thunk_count); + *self.thunk_count = self.thunk_count.checked_add(1).expect("thunk id overflow"); + self.thunk_scopes + .last_mut() + .expect("no active cache scope") + .add_binding(id, ir, &self.token); + IrRef::alloc(self.bump, Ir::Thunk(id)) + } + + fn new_sym(&mut self, sym: String) -> StringId { + StringId(self.strings.get_or_intern(sym)) + } + + fn get_sym(&self, id: StringId) -> Symbol<'_> { + self.strings.resolve(id.0).expect("no symbol found").into() + } + + fn lookup(&self, sym: StringId, span: rnix::TextRange) -> Result> { + for scope in self.scopes.iter().rev() { + match scope { + &Scope::Global(global_scope) => { + if let Some(expr) = global_scope.get(&sym) { + let ir = match expr { + Ir::Builtins => Ir::Builtins, + Ir::Builtin(s) => Ir::Builtin(*s), + Ir::Bool(b) => Ir::Bool(*b), + Ir::Null => Ir::Null, + _ => unreachable!("globals should only contain leaf IR nodes"), + }; + return Ok(self.new_expr(ir)); + } + } + &Scope::Repl(repl_bindings) => { + if repl_bindings.contains(&sym) { + return Ok(self.new_expr(Ir::ReplBinding(sym))); + } + } + Scope::ScopedImport(scoped_bindings) => { + if scoped_bindings.contains(&sym) { + return Ok(self.new_expr(Ir::ScopedImportBinding(sym))); + } + } + Scope::Let(let_scope) => { + if let Some(&expr) = let_scope.get(&sym) { + return Ok(self.new_expr(Ir::Thunk(expr))); + } + } + &Scope::Param { + sym: param_sym, + abs_layer, + } => { + if param_sym == sym { + return Ok(self.new_expr(Ir::Arg { + layer: self.thunk_scopes.len() - abs_layer, + })); + } + } + } + } + + if self.with_scope_count > 0 { + Ok(self.new_expr(Ir::WithLookup(sym))) + } else { + Err(Error::downgrade_error( + format!("'{}' not found", self.get_sym(sym)), + self.get_current_source(), + span, + )) + } + } + + fn get_current_source(&self) -> Source { + self.source.clone() + } + + fn with_let_scope(&mut self, keys: &[StringId], f: F) -> Result + where + F: FnOnce(&mut Self) -> Result<(bumpalo::collections::Vec<'ir, IrRef<'id, 'ir>>, R)>, + { + let base = *self.thunk_count; + *self.thunk_count = self + .thunk_count + .checked_add(keys.len()) + .expect("thunk id overflow"); + let iter = keys + .iter() + .enumerate() + .map(|(offset, &key)| (key, ThunkId(base + offset))); + self.scopes.push(Scope::Let(iter.collect())); + let (vals, ret) = { + let mut guard = ScopeGuard { ctx: self }; + f(guard.as_ctx())? + }; + assert_eq!(keys.len(), vals.len()); + let scope = self.thunk_scopes.last_mut().expect("no active thunk scope"); + scope.extend_bindings((base..base + keys.len()).map(ThunkId).zip(vals)); + Ok(ret) + } + + fn with_param_scope(&mut self, sym: StringId, f: F) -> R + where + F: FnOnce(&mut Self) -> R, + { + self.scopes.push(Scope::Param { + sym, + abs_layer: self.thunk_scopes.len(), + }); + let mut guard = ScopeGuard { ctx: self }; + f(guard.as_ctx()) + } + + fn with_with_scope(&mut self, f: F) -> R + where + F: FnOnce(&mut Self) -> R, + { + self.with_scope_count += 1; + let ret = f(self); + self.with_scope_count -= 1; + ret + } + + fn with_thunk_scope( + &mut self, + f: F, + ) -> ( + R, + bumpalo::collections::Vec<'ir, (ThunkId, IrRef<'id, 'ir>)>, + ) + where + F: FnOnce(&mut Self) -> R, + { + self.thunk_scopes.push(ThunkScope::new_in(self.bump)); + let ret = f(self); + ( + ret, + self.thunk_scopes + .pop() + .expect("no thunk scope left???") + .bindings, + ) + } + + fn bump(&self) -> &'ir bumpalo::Bump { + self.bump + } +} + +impl<'id, 'ir, 'ctx: 'ir> DowngradeCtx<'ctx, 'id, 'ir> { + fn downgrade_toplevel(mut self, root: rnix::ast::Expr) -> Result> { + let body = root.downgrade(&mut self)?; + let thunks = self + .thunk_scopes + .pop() + .expect("no thunk scope left???") + .bindings; + let ir = IrRef::alloc(self.bump, Ir::TopLevel { body, thunks }); + Ok(ir.freeze(self.token)) + } +} + +struct ThunkScope<'id, 'ir> { + bindings: bumpalo::collections::Vec<'ir, (ThunkId, IrRef<'id, 'ir>)>, +} + +impl<'id, 'ir> ThunkScope<'id, 'ir> { + fn new_in(bump: &'ir Bump) -> Self { + Self { + bindings: bumpalo::collections::Vec::new_in(bump), + } + } + + fn add_binding(&mut self, id: ThunkId, ir: IrRef<'id, 'ir>, _token: &GhostToken<'id>) { + self.bindings.push((id, ir)); + } + + fn extend_bindings(&mut self, iter: impl IntoIterator)>) { + self.bindings.extend(iter); + } +} + +enum Scope<'ctx> { + Global(&'ctx HashMap>>), + Repl(&'ctx HashSet), + ScopedImport(HashSet), + Let(HashMap), + Param { sym: StringId, abs_layer: usize }, +} + +struct ScopeGuard<'a, 'ctx, 'id, 'ir> { + ctx: &'a mut DowngradeCtx<'ctx, 'id, 'ir>, +} + +impl Drop for ScopeGuard<'_, '_, '_, '_> { + fn drop(&mut self) { + self.ctx.scopes.pop(); + } +} + +impl<'id, 'ir, 'ctx> ScopeGuard<'_, 'ctx, 'id, 'ir> { + fn as_ctx(&mut self) -> &mut DowngradeCtx<'ctx, 'id, 'ir> { + self.ctx + } +} + +struct OwnedIr { + _bump: Bump, + ir: RawIrRef<'static>, +} + +impl OwnedIr { + unsafe fn new(ir: RawIrRef<'_>, bump: Bump) -> Self { + Self { + _bump: bump, + ir: unsafe { std::mem::transmute::, RawIrRef<'static>>(ir) }, + } + } + + fn as_ref(&self) -> RawIrRef<'_> { + self.ir + } +} + +impl BytecodeContext for Evaluator { + fn intern_string(&mut self, s: &str) -> StringId { + StringId(self.strings.get_or_intern(s)) + } + + fn register_span(&mut self, range: rnix::TextRange) -> u32 { + let id = self.spans.len(); + let source_id = self + .sources + .len() + .checked_sub(1) + .expect("current_source not set"); + self.spans.push((source_id, range)); + id as u32 + } + + fn get_code(&self) -> &[u8] { + &self.bytecode + } + + fn get_code_mut(&mut self) -> &mut Vec { + &mut self.bytecode + } + + fn add_constant(&mut self, val: fix_codegen::Const) -> u32 { + use fix_codegen::Const::*; + let val = match val { + Smi(x) => StaticValue::new_inline(x), + Float(x) => StaticValue::new_float(x), + Bool(x) => StaticValue::new_inline(x), + String(x) => StaticValue::new_inline(x), + PrimOp { id, arity } => StaticValue::new_primop(id, arity), + Null => StaticValue::default(), + }; + self.constants.insert(val) + } +} diff --git a/fix/src/main.rs b/fix/src/main.rs index 1ffa236..674902e 100644 --- a/fix/src/main.rs +++ b/fix/src/main.rs @@ -3,8 +3,8 @@ use std::process::exit; use anyhow::Result; use clap::{Args, Parser, Subcommand}; -use fix::error::Source; -use fix::runtime::Runtime; +use fix::Evaluator; +use fix_error::Source; use hashbrown::HashSet; use rustyline::DefaultEditor; use rustyline::error::ReadlineError; @@ -40,7 +40,7 @@ struct ExprSource { file: Option, } -fn run_compile(runtime: &mut Runtime, src: ExprSource, silent: bool) -> Result<()> { +fn run_compile(eval: &mut Evaluator, src: ExprSource, _silent: bool) -> Result<()> { let src = if let Some(expr) = src.expr { Source::new_eval(expr)? } else if let Some(file) = src.file { @@ -48,11 +48,11 @@ fn run_compile(runtime: &mut Runtime, src: ExprSource, silent: bool) -> Result<( } else { unreachable!() }; - match runtime.compile_bytecode(src) { - Ok(ip) => { - if !silent { - println!("{}", runtime.disassemble_colored(ip)); - } + match eval.compile_bytecode(src) { + Ok(_ip) => { + // if !silent { + // println!("{}", eval.disassemble_colored(ip)); + // } } Err(err) => { eprintln!("{:?}", miette::Report::new(*err)); @@ -62,7 +62,7 @@ fn run_compile(runtime: &mut Runtime, src: ExprSource, silent: bool) -> Result<( Ok(()) } -fn run_eval(runtime: &mut Runtime, src: ExprSource) -> Result<()> { +fn run_eval(eval: &mut Evaluator, src: ExprSource) -> Result<()> { let src = if let Some(expr) = src.expr { Source::new_eval(expr)? } else if let Some(file) = src.file { @@ -70,7 +70,7 @@ fn run_eval(runtime: &mut Runtime, src: ExprSource) -> Result<()> { } else { unreachable!() }; - match runtime.eval_deep(src) { + match eval.eval_deep(src) { Ok(value) => { println!("{}", value.display_compat()); } @@ -82,7 +82,7 @@ fn run_eval(runtime: &mut Runtime, src: ExprSource) -> Result<()> { Ok(()) } -fn run_repl(runtime: &mut Runtime) -> Result<()> { +fn run_repl(eval: &mut Evaluator) -> Result<()> { let mut rl = DefaultEditor::new()?; let mut scope = HashSet::new(); const RE: ere::Regex<3> = ere::compile_regex!("^[ \t]*([a-zA-Z_][a-zA-Z0-9_'-]*)[ \t]*(.*)$"); @@ -101,20 +101,20 @@ fn run_repl(runtime: &mut Runtime) -> Result<()> { eprintln!("Error: missing expression after '='"); continue; } - match runtime.add_binding(ident, expr, &mut scope) { + match eval.add_binding(ident, expr, &mut scope) { Ok(value) => println!("{} = {}", ident, value), Err(err) => eprintln!("{:?}", miette::Report::new(*err)), } } else { let src = Source::new_repl(line)?; - match runtime.eval_repl(src, &scope) { + match eval.eval_repl(src, &scope) { Ok(value) => println!("{value}"), Err(err) => eprintln!("{:?}", miette::Report::new(*err)), } } } else { let src = Source::new_repl(line)?; - match runtime.eval_repl(src, &scope) { + match eval.eval_repl(src, &scope) { Ok(value) => println!("{value}"), Err(err) => eprintln!("{:?}", miette::Report::new(*err)), } @@ -141,11 +141,11 @@ fn main() -> Result<()> { let cli = Cli::parse(); - let mut runtime = Runtime::new()?; + let mut eval = Evaluator::new(); match cli.command { - Command::Compile { source, silent } => run_compile(&mut runtime, source, silent), - Command::Eval { source } => run_eval(&mut runtime, source), - Command::Repl => run_repl(&mut runtime), + Command::Compile { source, silent } => run_compile(&mut eval, source, silent), + Command::Eval { source } => run_eval(&mut eval, source), + Command::Repl => run_repl(&mut eval), } } diff --git a/fix/src/nar.rs b/fix/src/nar.rs index 77b3579..07e3877 100644 --- a/fix/src/nar.rs +++ b/fix/src/nar.rs @@ -4,7 +4,7 @@ use std::path::Path; use nix_nar::Encoder; use sha2::{Digest, Sha256}; -use crate::error::{Error, Result}; +use fix_error::{Error, Result}; pub fn compute_nar_hash(path: &Path) -> Result<[u8; 32]> { let mut hasher = Sha256::new(); diff --git a/fix/src/runtime.rs b/fix/src/runtime.rs deleted file mode 100644 index 6b53c86..0000000 --- a/fix/src/runtime.rs +++ /dev/null @@ -1,559 +0,0 @@ -use bumpalo::Bump; -use gc_arena::{Arena, Rootable}; -use ghost_cell::{GhostCell, GhostToken}; -use hashbrown::{HashMap, HashSet}; -use rnix::TextRange; -use string_interner::symbol::SymbolU32; -use string_interner::{DefaultStringInterner, Symbol as _}; - -use crate::codegen::{BytecodeContext, InstructionPtr}; -use crate::disassembler::{Disassembler, DisassemblerContext}; -use crate::downgrade::{Downgrade as _, DowngradeContext}; -use crate::error::{Error, Result, Source}; -use crate::ir::{Ir, IrRef, RawIrRef, StringId, ThunkId}; -use crate::runtime::builtins::init_builtins; -use crate::runtime::value::StaticValue; -use crate::runtime::vm::{ForceMode, new_gc_root}; -use crate::store::{DaemonStore, StoreConfig}; -use crate::value::Symbol; - -mod builtins; -mod stack; -pub(crate) mod value; -mod vm; -pub(crate) use builtins::{BUILTINS, BuiltinId}; -use stack::Stack; -use vm::{ErrorFrame, GcRoot}; - -pub struct Runtime { - // global - sources: Vec, - spans: Vec<(usize, TextRange)>, - store: DaemonStore, - strings: DefaultStringInterner, - // FIXME: remove? - thunk_count: usize, - bytecode: Vec, - pub(crate) constants: Vec, - constant_dedup: HashMap, - - // downgrade - global_env: HashMap>>, - - // eval - pc: usize, - fuel: usize, - error_contexts: Stack<8192, ErrorFrame>, - arena: Arena]>, - force_mode: ForceMode, -} - -impl Runtime { - const DEFAULT_FUEL_AMOUNT: usize = 2048; - - pub fn new() -> Result { - // HACK: what the heck... - let mut global_env = HashMap::new(); - let mut strings = DefaultStringInterner::new(); - let arena = Arena::new(|mc| { - let (root, env) = new_gc_root(mc, &mut strings); - global_env = env; - root - }); - - let config = StoreConfig::from_env(); - let store = DaemonStore::connect(&config.daemon_socket)?; - - Ok(Self { - sources: Vec::new(), - spans: Vec::new(), - store, - strings, - thunk_count: 0, - bytecode: Vec::new(), - constants: Vec::new(), - constant_dedup: HashMap::new(), - - global_env, - - pc: 0, - fuel: Self::DEFAULT_FUEL_AMOUNT, - error_contexts: Stack::new(), - arena, - force_mode: ForceMode::default(), - }) - } - - pub fn eval(&mut self, source: Source) -> Result { - self.do_eval(source, None, ForceMode::AsIs) - } - - pub fn eval_shallow(&mut self, source: Source) -> Result { - self.do_eval(source, None, ForceMode::Shallow) - } - - pub fn eval_deep(&mut self, source: Source) -> Result { - self.do_eval(source, None, ForceMode::Deep) - } - - pub fn eval_repl( - &mut self, - source: Source, - scope: &HashSet, - ) -> Result { - self.do_eval(source, Some(Scope::Repl(scope)), ForceMode::Shallow) - } - - fn do_eval<'ctx>( - &'ctx mut self, - source: Source, - extra_scope: Option>, - force_mode: ForceMode, - ) -> Result { - let root = self.downgrade(source, extra_scope)?; - let ip = crate::codegen::compile_bytecode(root.as_ref(), self); - self.run(ip, force_mode) - } - - pub fn add_binding( - &mut self, - _ident: &str, - _expr: &str, - _scope: &mut HashSet, - ) -> Result { - todo!() - } - - pub fn compile_bytecode(&mut self, source: Source) -> Result { - let root = self.downgrade(source, None)?; - let ip = crate::codegen::compile_bytecode(root.as_ref(), self); - Ok(ip) - } - - pub fn disassemble_colored(&mut self, ip: InstructionPtr) -> String { - Disassembler::new(ip, self).disassemble_colored() - } - - pub fn disassemble(&mut self, ip: InstructionPtr) -> String { - Disassembler::new(ip, self).disassemble() - } - - fn downgrade_ctx<'a, 'bump, 'id>( - &'a mut self, - bump: &'bump Bump, - token: GhostToken<'id>, - extra_scope: Option>, - ) -> DowngradeCtx<'a, 'id, 'bump> { - let Runtime { - global_env, - sources, - thunk_count, - strings, - .. - } = self; - DowngradeCtx { - bump, - token, - strings, - source: sources.last().expect("no current source").clone(), - scopes: [Scope::Global(global_env)] - .into_iter() - .chain(extra_scope) - .collect(), - with_scope_count: 0, - arg_count: 0, - thunk_count, - thunk_scopes: vec![ThunkScope::new_in(bump)], - } - } - - fn downgrade<'a>( - &'a mut self, - source: Source, - extra_scope: Option>, - ) -> Result { - tracing::debug!("Parsing Nix expression"); - - self.sources.push(source.clone()); - - let root = rnix::Root::parse(&source.src); - handle_parse_error(root.errors(), source).map_or(Ok(()), Err)?; - - tracing::debug!("Downgrading Nix expression"); - let expr = root - .tree() - .expr() - .ok_or_else(|| Error::parse_error("unexpected EOF".into()))?; - let bump = Bump::new(); - GhostToken::new(|token| { - let ir = self - .downgrade_ctx(&bump, token, extra_scope) - .downgrade_toplevel(expr)?; - let ir = unsafe { std::mem::transmute::, RawIrRef<'static>>(ir) }; - Ok(OwnedIr { _bump: bump, ir }) - }) - } -} - -fn parse_error_span(error: &rnix::ParseError) -> Option { - use rnix::ParseError::*; - match error { - Unexpected(range) - | UnexpectedExtra(range) - | UnexpectedWanted(_, range, _) - | UnexpectedDoubleBind(range) - | DuplicatedArgs(range, _) => Some(*range), - _ => None, - } -} - -fn handle_parse_error<'a>( - errors: impl IntoIterator, - source: Source, -) -> Option> { - for err in errors { - if let Some(span) = parse_error_span(err) { - return Some( - Error::parse_error(err.to_string()) - .with_source(source) - .with_span(span), - ); - } - } - None -} - -struct DowngradeCtx<'ctx, 'id, 'ir> { - bump: &'ir Bump, - token: GhostToken<'id>, - strings: &'ctx mut DefaultStringInterner, - source: Source, - scopes: Vec>, - with_scope_count: u32, - arg_count: u32, - thunk_count: &'ctx mut usize, - thunk_scopes: Vec>, -} - -fn should_thunk<'id>(ir: IrRef<'id, '_>, token: &GhostToken<'id>) -> bool { - !matches!( - ir.borrow(token), - Ir::Builtin(_) - | Ir::Builtins - | Ir::Int(_) - | Ir::Float(_) - | Ir::Bool(_) - | Ir::Null - | Ir::Str(_) - | Ir::Thunk(_) - ) -} - -impl<'ctx, 'id, 'ir> DowngradeCtx<'ctx, 'id, 'ir> { - fn new( - bump: &'ir Bump, - token: GhostToken<'id>, - symbols: &'ctx mut DefaultStringInterner, - global: &'ctx HashMap>>, - extra_scope: Option>, - thunk_count: &'ctx mut usize, - source: Source, - ) -> Self { - Self { - bump, - token, - strings: symbols, - source, - scopes: std::iter::once(Scope::Global(global)) - .chain(extra_scope) - .collect(), - thunk_count, - arg_count: 0, - with_scope_count: 0, - thunk_scopes: vec![ThunkScope::new_in(bump)], - } - } -} - -impl<'ctx: 'ir, 'id, 'ir> DowngradeContext<'id, 'ir> for DowngradeCtx<'ctx, 'id, 'ir> { - fn new_expr(&self, expr: Ir<'ir, IrRef<'id, 'ir>>) -> IrRef<'id, 'ir> { - IrRef::new(self.bump.alloc(GhostCell::new(expr))) - } - - fn maybe_thunk(&mut self, ir: IrRef<'id, 'ir>) -> IrRef<'id, 'ir> { - if !should_thunk(ir, &self.token) { - return ir; - } - - let id = ThunkId(*self.thunk_count); - *self.thunk_count = self.thunk_count.checked_add(1).expect("thunk id overflow"); - self.thunk_scopes - .last_mut() - .expect("no active cache scope") - .add_binding(id, ir, &self.token); - IrRef::alloc(self.bump, Ir::Thunk(id)) - } - - fn new_sym(&mut self, sym: String) -> StringId { - StringId(self.strings.get_or_intern(sym)) - } - - fn get_sym(&self, id: StringId) -> Symbol<'_> { - self.strings.resolve(id.0).expect("no symbol found").into() - } - - fn lookup(&self, sym: StringId, span: TextRange) -> Result> { - for scope in self.scopes.iter().rev() { - match scope { - &Scope::Global(global_scope) => { - if let Some(expr) = global_scope.get(&sym) { - let ir = match expr { - Ir::Builtins => Ir::Builtins, - Ir::Builtin(s) => Ir::Builtin(*s), - Ir::Bool(b) => Ir::Bool(*b), - Ir::Null => Ir::Null, - _ => unreachable!("globals should only contain leaf IR nodes"), - }; - return Ok(self.new_expr(ir)); - } - } - &Scope::Repl(repl_bindings) => { - if repl_bindings.contains(&sym) { - return Ok(self.new_expr(Ir::ReplBinding(sym))); - } - } - Scope::ScopedImport(scoped_bindings) => { - if scoped_bindings.contains(&sym) { - return Ok(self.new_expr(Ir::ScopedImportBinding(sym))); - } - } - Scope::Let(let_scope) => { - if let Some(&expr) = let_scope.get(&sym) { - return Ok(self.new_expr(Ir::Thunk(expr))); - } - } - &Scope::Param { - sym: param_sym, - abs_layer, - } => { - if param_sym == sym { - return Ok(self.new_expr(Ir::Arg { - layer: self.thunk_scopes.len() - abs_layer, - })); - } - } - } - } - - if self.with_scope_count > 0 { - Ok(self.new_expr(Ir::WithLookup(sym))) - } else { - Err(Error::downgrade_error( - format!("'{}' not found", self.get_sym(sym)), - self.get_current_source(), - span, - )) - } - } - - fn get_current_source(&self) -> Source { - self.source.clone() - } - - fn with_let_scope(&mut self, keys: &[StringId], f: F) -> Result - where - F: FnOnce(&mut Self) -> Result<(bumpalo::collections::Vec<'ir, IrRef<'id, 'ir>>, R)>, - { - let base = *self.thunk_count; - *self.thunk_count = self - .thunk_count - .checked_add(keys.len()) - .expect("thunk id overflow"); - let iter = keys.iter().enumerate().map(|(offset, &key)| { - ( - key, - ThunkId(unsafe { base.checked_add(offset).unwrap_unchecked() }), - ) - }); - self.scopes.push(Scope::Let(iter.collect())); - let (vals, ret) = { - let mut guard = ScopeGuard { ctx: self }; - f(guard.as_ctx())? - }; - assert_eq!(keys.len(), vals.len()); - let scope = self.thunk_scopes.last_mut().expect("no active thunk scope"); - scope.extend_bindings((base..base + keys.len()).map(ThunkId).zip(vals)); - Ok(ret) - } - - fn with_param_scope(&mut self, sym: StringId, f: F) -> R - where - F: FnOnce(&mut Self) -> R, - { - self.scopes.push(Scope::Param { - sym, - abs_layer: self.thunk_scopes.len(), - }); - let mut guard = ScopeGuard { ctx: self }; - f(guard.as_ctx()) - } - - fn with_with_scope(&mut self, f: F) -> R - where - F: FnOnce(&mut Self) -> R, - { - self.with_scope_count += 1; - let ret = f(self); - self.with_scope_count -= 1; - ret - } - - fn with_thunk_scope( - &mut self, - f: F, - ) -> ( - R, - bumpalo::collections::Vec<'ir, (ThunkId, IrRef<'id, 'ir>)>, - ) - where - F: FnOnce(&mut Self) -> R, - { - self.thunk_scopes.push(ThunkScope::new_in(self.bump)); - let ret = f(self); - ( - ret, - self.thunk_scopes - .pop() - .expect("no thunk scope left???") - .bindings, - ) - } - - fn bump(&self) -> &'ir bumpalo::Bump { - self.bump - } -} - -impl<'id, 'ir, 'ctx: 'ir> DowngradeCtx<'ctx, 'id, 'ir> { - fn downgrade_toplevel(mut self, root: rnix::ast::Expr) -> Result> { - let body = root.downgrade(&mut self)?; - let thunks = self - .thunk_scopes - .pop() - .expect("no thunk scope left???") - .bindings; - let ir = IrRef::alloc(self.bump, Ir::TopLevel { body, thunks }); - Ok(ir.freeze(self.token)) - } -} - -struct ThunkScope<'id, 'ir> { - bindings: bumpalo::collections::Vec<'ir, (ThunkId, IrRef<'id, 'ir>)>, -} - -impl<'id, 'ir> ThunkScope<'id, 'ir> { - fn new_in(bump: &'ir Bump) -> Self { - Self { - bindings: bumpalo::collections::Vec::new_in(bump), - } - } - - fn add_binding(&mut self, id: ThunkId, ir: IrRef<'id, 'ir>, _token: &GhostToken<'id>) { - self.bindings.push((id, ir)); - } - - fn extend_bindings(&mut self, iter: impl IntoIterator)>) { - self.bindings.extend(iter); - } -} - -enum Scope<'ctx> { - Global(&'ctx HashMap>>), - Repl(&'ctx HashSet), - ScopedImport(HashSet), - Let(HashMap), - Param { sym: StringId, abs_layer: usize }, -} - -struct ScopeGuard<'a, 'ctx, 'id, 'ir> { - ctx: &'a mut DowngradeCtx<'ctx, 'id, 'ir>, -} - -impl Drop for ScopeGuard<'_, '_, '_, '_> { - fn drop(&mut self) { - self.ctx.scopes.pop(); - } -} - -impl<'id, 'ir, 'ctx> ScopeGuard<'_, 'ctx, 'id, 'ir> { - fn as_ctx(&mut self) -> &mut DowngradeCtx<'ctx, 'id, 'ir> { - self.ctx - } -} - -struct OwnedIr { - _bump: Bump, - ir: RawIrRef<'static>, -} - -impl OwnedIr { - unsafe fn new(ir: RawIrRef<'_>, bump: Bump) -> Self { - Self { - _bump: bump, - ir: unsafe { std::mem::transmute::, RawIrRef<'static>>(ir) }, - } - } - - fn as_ref(&self) -> RawIrRef<'_> { - self.ir - } -} - -impl BytecodeContext for Runtime { - fn intern_string(&mut self, s: &str) -> StringId { - StringId(self.strings.get_or_intern(s)) - } - - fn register_span(&mut self, range: TextRange) -> u32 { - let id = self.spans.len(); - let source_id = self - .sources - .len() - .checked_sub(1) - .expect("current_source not set"); - self.spans.push((source_id, range)); - id as u32 - } - - fn get_code(&self) -> &[u8] { - &self.bytecode - } - - fn get_code_mut(&mut self) -> &mut Vec { - &mut self.bytecode - } - - fn add_constant(&mut self, val: StaticValue) -> u32 { - let bits = val.to_bits(); - *self.constant_dedup.entry(bits).or_insert_with(|| { - let idx = self.constants.len() as u32; - self.constants.push(val); - idx - }) - } -} - -impl DisassemblerContext for Runtime { - fn lookup_string(&self, id: u32) -> &str { - self.strings - .resolve(SymbolU32::try_from_usize(id as usize).expect("invalid string id")) - .expect("string not found") - } - fn get_code(&self) -> &[u8] { - &self.bytecode - } -} - -struct WellKnownSymbols { - // TODO: -} diff --git a/fix/src/runtime/builtins.rs b/fix/src/runtime/builtins.rs deleted file mode 100644 index 2060c04..0000000 --- a/fix/src/runtime/builtins.rs +++ /dev/null @@ -1,410 +0,0 @@ -use gc_arena::{Collect, Gc, Mutation, RefLock}; -use hashbrown::HashMap; -use num_enum::TryFromPrimitive; -use smallvec::SmallVec; -use string_interner::DefaultStringInterner; -use string_interner::symbol::SymbolU32; - -use super::value::*; -use crate::ir::{Ir, RawIrRef, StringId}; - -/// Generates both the BUILTINS const table and the BuiltinId enum -/// from a single source of truth, preventing index desync. -macro_rules! define_builtins { - ($(($name:literal, $variant:ident, $arity:expr)),* $(,)?) => { - /// Builtin function registry. - /// Array index IS the PrimOp id. (name, arity) pairs. - pub(crate) const BUILTINS: &[(&str, u8)] = &[ - $(($name, $arity),)* - ]; - - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive, Collect)] - #[repr(u8)] - #[collect(require_static)] - pub(crate) enum BuiltinId { - $($variant,)* - } - }; -} - -define_builtins! { - ("abort", Abort, 1), - ("__add", Add, 2), - ("__addErrorContext", AddErrorContext, 2), - ("__all", All, 2), - ("__any", Any, 2), - ("__appendContext", AppendContext, 2), - ("__attrNames", AttrNames, 1), - ("__attrValues", AttrValues, 1), - ("baseNameOf", BaseNameOf, 1), - ("__bitAnd", BitAnd, 2), - ("__bitOr", BitOr, 2), - ("__bitXor", BitXor, 2), - ("break", Break, 1), - ("__catAttrs", CatAttrs, 2), - ("__ceil", Ceil, 1), - ("__compareVersions", CompareVersions, 2), - ("__concatLists", ConcatLists, 1), - ("__concatMap", ConcatMap, 2), - ("__concatStringsSep", ConcatStringsSep, 2), - ("__convertHash", ConvertHash, 1), - ("__deepSeq", DeepSeq, 2), - ("derivation", Derivation, 1), - ("derivationStrict", DerivationStrict, 1), - ("dirOf", DirOf, 1), - ("__div", Div, 2), - ("__elem", Elem, 2), - ("__elemAt", ElemAt, 2), - ("fetchGit", FetchGit, 1), - ("fetchMercurial", FetchMercurial, 1), - ("fetchTarball", FetchTarball, 1), - ("fetchTree", FetchTree, 1), - ("__fetchurl", FetchUrl, 1), - ("__filter", Filter, 2), - ("__filterSource", FilterSource, 2), - ("__findFile", FindFile, 2), - ("__floor", Floor, 1), - ("__foldl'", FoldlStrict, 3), - ("__fromJSON", FromJSON, 1), - ("fromTOML", FromTOML, 1), - ("__functionArgs", FunctionArgs, 1), - ("__genList", GenList, 2), - ("__genericClosure", GenericClosure, 1), - ("__getAttr", GetAttr, 2), - ("__getContext", GetContext, 1), - ("__getEnv", GetEnv, 1), - ("__groupBy", GroupBy, 2), - ("__hasAttr", HasAttr, 2), - ("__hasContext", HasContext, 1), - ("__hashFile", HashFile, 2), - ("__hashString", HashString, 2), - ("__head", Head, 1), - ("import", Import, 1), - ("__intersectAttrs", IntersectAttrs, 2), - ("__isAttrs", IsAttrs, 1), - ("__isBool", IsBool, 1), - ("__isFloat", IsFloat, 1), - ("__isFunction", IsFunction, 1), - ("__isInt", IsInt, 1), - ("__isList", IsList, 1), - ("isNull", IsNull, 1), - ("__isPath", IsPath, 1), - ("__isString", IsString, 1), - ("__length", Length, 1), - ("__lessThan", LessThan, 2), - ("__listToAttrs", ListToAttrs, 1), - ("map", Map, 2), - ("__mapAttrs", MapAttrs, 2), - ("__match", Match, 2), - ("__mul", Mul, 2), - ("null", Null, 0), // constant, not a function - ("__parseDrvName", ParseDrvName, 1), - ("__partition", Partition, 2), - ("__path", Path, 1), - ("__pathExists", PathExists, 1), - ("placeholder", Placeholder, 1), - ("__readDir", ReadDir, 1), - ("__readFile", ReadFile, 1), - ("__readFileType", ReadFileType, 1), - ("removeAttrs", RemoveAttrs, 2), - ("__replaceStrings", ReplaceStrings, 3), - ("scopedImport", ScopedImport, 2), - ("__seq", Seq, 2), - ("__sort", Sort, 2), - ("__split", Split, 2), - ("__splitVersion", SplitVersion, 1), - ("__storePath", StorePath, 1), - ("__stringLength", StringLength, 1), - ("__sub", Sub, 2), - ("__substring", Substring, 3), - ("__tail", Tail, 1), - ("throw", Throw, 1), - ("__toFile", ToFile, 2), - ("__toJSON", ToJSON, 1), - ("__toPath", ToPath, 1), - ("toString", ToString, 1), - ("__toXML", ToXML, 1), - ("__trace", Trace, 2), - ("__tryEval", TryEval, 1), - ("__typeOf", TypeOf, 1), - ("__unsafeDiscardStringContext", UnsafeDiscardStringContext, 1), - ("__unsafeGetAttrPos", UnsafeGetAttrPos, 2), - ("__warn", Warn, 2), - ("__zipAttrsWith", ZipAttrsWith, 2), -} - -/// Names that need to be pre-interned for builtin implementations. -const EXTRA_INTERN_NAMES: &[&str] = &[ - "builtins", - "currentSystem", - "langVersion", - "nixVersion", - "storeDir", - "nixPath", - "true", - "false", - // typeOf return values - "int", - "float", - "bool", - "string", - "path", - "null", - "set", - "list", - "lambda", - // attrset keys used by builtins - "name", - "value", - "success", - "right", - "wrong", - "key", - "operator", - "startSet", - "__toString", - "outPath", - "__functor", - "drvPath", - "type", - "derivation", - "version", -]; - -/// Returns true if this builtin has lazy argument semantics -/// (not all args should be forced before dispatch). -pub(super) fn is_lazy_builtin(id: BuiltinId) -> bool { - matches!( - id, - BuiltinId::Seq - | BuiltinId::DeepSeq - | BuiltinId::Trace - | BuiltinId::Warn - | BuiltinId::TryEval - | BuiltinId::AddErrorContext - | BuiltinId::Break - ) -} - -/// Intern all builtin names and extra names needed at runtime. -fn intern_all_builtins(interner: &mut DefaultStringInterner) { - for &(name, _) in BUILTINS { - interner.get_or_intern(name); - } - for &name in EXTRA_INTERN_NAMES { - interner.get_or_intern(name); - } -} - -pub(super) fn init_builtins<'gc>( - mc: &Mutation<'gc>, - strings: &mut DefaultStringInterner, -) -> ( - HashMap>>, - Value<'gc>, -) { - let mut global_env = HashMap::new(); - let builtins_sym = StringId(strings.get_or_intern("builtins")); - global_env.insert(builtins_sym, Ir::Builtins); - let mut entries = SmallVec::with_capacity(BUILTINS.len()); - - for (idx, &(name, arity)) in BUILTINS.iter().enumerate() { - let id = BuiltinId::try_from_primitive(idx as u8).expect("infallible"); - if let Some(local_name) = name.strip_prefix("__") { - // scoped builtins - let name = StringId(strings.get_or_intern(name)); - let local_name = StringId(strings.get_or_intern(local_name)); - global_env.insert(name, Ir::Builtin(id)); - entries.push((local_name, Value::new_inline(PrimOp { id, arity }))); - } else { - // global builtins - let name = StringId(strings.get_or_intern(name)); - global_env.insert(name, Ir::Builtin(id)); - entries.push((name, Value::new_inline(PrimOp { id, arity }))); - } - } - - let consts = [ - ( - "__currentSystem", - Ir::BuiltinConst(StringId(strings.get_or_intern("currentSystem"))), - // FIXME: detect currentSystem - Value::new_gc(Gc::new(mc, NixString::new("x86_64-linux"))), - ), - ("__langVersion", Ir::Int(6), Value::new_inline(6i32)), - ( - "__nixVersion", - Ir::BuiltinConst(StringId(strings.get_or_intern("nixVersion"))), - Value::new_gc(Gc::new(mc, NixString::new("2.24.0"))), - ), - ( - "__storeDir", - Ir::BuiltinConst(StringId(strings.get_or_intern("storeDir"))), - Value::new_gc(Gc::new(mc, NixString::new("/nix/store"))), - ), - ( - "__nixPath", - Ir::BuiltinConst(StringId(strings.get_or_intern("nixPath"))), - // FIXME: get from config - Value::new_gc(Gc::new( - mc, - List { - inner: SmallVec::new(), - }, - )), - ), - ("null", Ir::Null, Value::new_inline(Null)), - ("true", Ir::Bool(true), Value::new_inline(true)), - ("false", Ir::Bool(false), Value::new_inline(false)), - ]; - - for (idx, &(name, arity)) in BUILTINS.iter().enumerate() { - let id = BuiltinId::try_from_primitive(idx as u8).expect("infallible"); - if let Some(local_name) = name.strip_prefix("__") { - // scoped builtins - let name = StringId(strings.get_or_intern(name)); - let local_name = StringId(strings.get_or_intern(local_name)); - global_env.insert(name, Ir::Builtin(id)); - entries.push((local_name, Value::new_inline(PrimOp { id, arity }))); - } else { - // global builtins - let name = StringId(strings.get_or_intern(name)); - global_env.insert(name, Ir::Builtin(id)); - entries.push((name, Value::new_inline(PrimOp { id, arity }))); - } - } - for (name, ir, val) in consts { - if let Some(local_name) = name.strip_prefix("__") { - let name = StringId(strings.get_or_intern(name)); - let local_name = StringId(strings.get_or_intern(local_name)); - global_env.insert(name, ir); - entries.push((local_name, val)); - } else { - let name = StringId(strings.get_or_intern(name)); - global_env.insert(name, ir); - entries.push((name, val)); - } - } - - // Self-reference thunk for builtins.builtins - let self_ref_thunk: Gc<'gc, Thunk<'gc>> = Gc::new(mc, RefLock::new(ThunkState::Blackhole)); - let sym = strings.get_or_intern("builtins"); - entries.push((StringId(sym), Value::new_gc(self_ref_thunk))); - - entries.sort_by_key(|(k, _)| *k); - - let builtins_set = Gc::new(mc, unsafe { AttrSet::from_sorted_unchecked(entries) }); - let builtins_val = Value::new_gc(builtins_set); - - (global_env, builtins_val) -} - -pub(super) type PrimOpArgs<'gc> = [Value<'gc>; 3]; -pub(super) type PrimOpStrictArgs<'gc> = [StrictValue<'gc>; 3]; - -#[allow(non_snake_case)] -pub(super) struct WellKnownSymbols { - abort: SymbolU32, - add: SymbolU32, - addErrorContext: SymbolU32, - all: SymbolU32, - any: SymbolU32, - appendContext: SymbolU32, - attrNames: SymbolU32, - attrValues: SymbolU32, - baseNameOf: SymbolU32, - bitAnd: SymbolU32, - bitOr: SymbolU32, - bitXor: SymbolU32, - catAttrs: SymbolU32, - ceil: SymbolU32, - compareVersions: SymbolU32, - concatLists: SymbolU32, - concatMap: SymbolU32, - concatStringsSep: SymbolU32, - convertHash: SymbolU32, - deepSeq: SymbolU32, - derivation: SymbolU32, - derivationStrict: SymbolU32, - dirOf: SymbolU32, - div: SymbolU32, - elem: SymbolU32, - elemAt: SymbolU32, - fetchGit: SymbolU32, - fetchMercurial: SymbolU32, - fetchTarball: SymbolU32, - fetchTree: SymbolU32, - fetchurl: SymbolU32, - filter: SymbolU32, - filterSource: SymbolU32, - findFile: SymbolU32, - floor: SymbolU32, - foldl: SymbolU32, - fromJSON: SymbolU32, - fromTOML: SymbolU32, - functionArgs: SymbolU32, - genList: SymbolU32, - genericClosure: SymbolU32, - getAttr: SymbolU32, - getContext: SymbolU32, - getEnv: SymbolU32, - groupBy: SymbolU32, - hasAttr: SymbolU32, - hasContext: SymbolU32, - hashFile: SymbolU32, - hashString: SymbolU32, - head: SymbolU32, - import: SymbolU32, - intersectAttrs: SymbolU32, - isAttrs: SymbolU32, - isBool: SymbolU32, - isFloat: SymbolU32, - isFunction: SymbolU32, - isInt: SymbolU32, - isList: SymbolU32, - isNull: SymbolU32, - isPath: SymbolU32, - isString: SymbolU32, - length: SymbolU32, - lessThan: SymbolU32, - listToAttrs: SymbolU32, - map: SymbolU32, - mapAttrs: SymbolU32, - match_: SymbolU32, - mul: SymbolU32, - null: SymbolU32, - parseDrvName: SymbolU32, - partition: SymbolU32, - path: SymbolU32, - pathExists: SymbolU32, - placeholder: SymbolU32, - readDir: SymbolU32, - readFile: SymbolU32, - readFileType: SymbolU32, - removeAttrs: SymbolU32, - replaceStrings: SymbolU32, - scopedImport: SymbolU32, - seq: SymbolU32, - sort: SymbolU32, - split: SymbolU32, - splitVersion: SymbolU32, - storePath: SymbolU32, - stringLength: SymbolU32, - sub: SymbolU32, - substring: SymbolU32, - tail: SymbolU32, - throw: SymbolU32, - toFile: SymbolU32, - toJSON: SymbolU32, - toPath: SymbolU32, - toString: SymbolU32, - toXML: SymbolU32, - trace: SymbolU32, - tryEval: SymbolU32, - typeOf: SymbolU32, - unsafeDiscardStringContext: SymbolU32, - unsafeGetAttrPos: SymbolU32, - warn: SymbolU32, - zipAttrsWith: SymbolU32, - break_: SymbolU32, -} diff --git a/fix/src/runtime/corepkgs/derivation.nix b/fix/src/runtime/corepkgs/derivation.nix deleted file mode 100644 index a7c4dda..0000000 --- a/fix/src/runtime/corepkgs/derivation.nix +++ /dev/null @@ -1,31 +0,0 @@ -drvAttrs@{ - outputs ? [ "out" ], - ... -}: - -let - - strict = derivationStrict drvAttrs; - - commonAttrs = - drvAttrs - // (builtins.listToAttrs outputsList) - // { - all = map (x: x.value) outputsList; - inherit drvAttrs; - }; - - outputToAttrListElement = outputName: { - name = outputName; - value = commonAttrs // { - outPath = builtins.getAttr outputName strict; - drvPath = strict.drvPath; - type = "derivation"; - inherit outputName; - }; - }; - - outputsList = map outputToAttrListElement outputs; - -in -(builtins.head outputsList).value diff --git a/fix/src/runtime/corepkgs/fetchurl.nix b/fix/src/runtime/corepkgs/fetchurl.nix deleted file mode 100644 index 6701140..0000000 --- a/fix/src/runtime/corepkgs/fetchurl.nix +++ /dev/null @@ -1,76 +0,0 @@ -{ - system ? "", # obsolete - url, - hash ? "", # an SRI hash - - # Legacy hash specification - md5 ? "", - sha1 ? "", - sha256 ? "", - sha512 ? "", - outputHash ? - if hash != "" then - hash - else if sha512 != "" then - sha512 - else if sha1 != "" then - sha1 - else if md5 != "" then - md5 - else - sha256, - outputHashAlgo ? - if hash != "" then - "" - else if sha512 != "" then - "sha512" - else if sha1 != "" then - "sha1" - else if md5 != "" then - "md5" - else - "sha256", - - executable ? false, - unpack ? false, - name ? baseNameOf (toString url), - # still translates to __impure to trigger derivationStrict error checks. - impure ? false, -}: - -derivation ( - { - builder = "builtin:fetchurl"; - - # New-style output content requirements. - outputHashMode = if unpack || executable then "recursive" else "flat"; - - inherit - name - url - executable - unpack - ; - - system = "builtin"; - - # No need to double the amount of network traffic - preferLocalBuild = true; - - impureEnvVars = [ - # We borrow these environment variables from the caller to allow - # easy proxy configuration. This is impure, but a fixed-output - # derivation like fetchurl is allowed to do so since its result is - # by definition pure. - "http_proxy" - "https_proxy" - "ftp_proxy" - "all_proxy" - "no_proxy" - ]; - - # To make "nix-prefetch-url" work. - urls = [ url ]; - } - // (if impure then { __impure = true; } else { inherit outputHashAlgo outputHash; }) -) diff --git a/fix/tests/tests/derivation.rs b/fix/tests/tests/derivation.rs index d1f8f70..9f33baf 100644 --- a/fix/tests/tests/derivation.rs +++ b/fix/tests/tests/derivation.rs @@ -1,4 +1,4 @@ -use fix::value::Value; +use fix_common::Value; use crate::utils::{eval_deep, eval_deep_result}; diff --git a/fix/tests/tests/io_operations.rs b/fix/tests/tests/io_operations.rs index 1fb0e1c..1d30545 100644 --- a/fix/tests/tests/io_operations.rs +++ b/fix/tests/tests/io_operations.rs @@ -1,6 +1,6 @@ -use fix::error::Source; -use fix::runtime::Runtime; -use fix::value::Value; +use fix::Evaluator; +use fix_common::Value; +use fix_error::Source; use crate::utils::{eval, eval_result}; @@ -97,7 +97,7 @@ fn import_with_complex_dependency_graph() { #[test_log::test] fn path_with_file() { - let mut ctx = Runtime::new().unwrap(); + let mut ctx = Evaluator::new(); let temp_dir = tempfile::tempdir().unwrap(); let test_file = temp_dir.path().join("test.txt"); std::fs::write(&test_file, "Hello, World!").unwrap(); @@ -136,7 +136,7 @@ fn path_with_custom_name() { #[test_log::test] fn path_with_directory_recursive() { - let mut ctx = Runtime::new().unwrap(); + let mut ctx = Evaluator::new(); let temp_dir = tempfile::tempdir().unwrap(); let test_dir = temp_dir.path().join("mydir"); std::fs::create_dir_all(&test_dir).unwrap(); @@ -159,7 +159,7 @@ fn path_with_directory_recursive() { #[test_log::test] fn path_flat_with_file() { - let mut ctx = Runtime::new().unwrap(); + let mut ctx = Evaluator::new(); let temp_dir = tempfile::tempdir().unwrap(); let test_file = temp_dir.path().join("flat.txt"); std::fs::write(&test_file, "Flat content").unwrap(); diff --git a/fix/tests/tests/lang.rs b/fix/tests/tests/lang.rs index 3d8bb97..a4f8f19 100644 --- a/fix/tests/tests/lang.rs +++ b/fix/tests/tests/lang.rs @@ -2,9 +2,9 @@ use std::path::PathBuf; -use fix::error::Source; -use fix::runtime::Runtime; -use fix::value::Value; +use fix::Evaluator; +use fix_common::Value; +use fix_error::{Source, SourceType}; fn get_lang_dir() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/tests/lang") @@ -14,10 +14,10 @@ fn eval_file(name: &str) -> Result<(Value, Source), String> { let lang_dir = get_lang_dir(); let nix_path = lang_dir.join(format!("{name}.nix")); - let mut ctx = Runtime::new().map_err(|e| e.to_string())?; + let mut ctx = Evaluator::new(); let content = std::fs::read_to_string(&nix_path).unwrap(); let source = Source { - ty: fix::error::SourceType::File(nix_path.into()), + ty: SourceType::File(nix_path.into()), src: content.into(), }; ctx.eval_deep(source.clone()) diff --git a/fix/tests/tests/string_context.rs b/fix/tests/tests/string_context.rs index 5d16581..689ae46 100644 --- a/fix/tests/tests/string_context.rs +++ b/fix/tests/tests/string_context.rs @@ -1,5 +1,5 @@ -use fix::runtime::Runtime; -use fix::value::Value; +use fix::Evaluator; +use fix_common::Value; use crate::utils::eval_result; @@ -153,7 +153,7 @@ fn string_add_merges_context() { #[test_log::test] fn context_in_derivation_args() { - let mut rt = Runtime::new().unwrap(); + let mut rt = Evaluator::new(); let result = rt .eval( r#" @@ -182,7 +182,7 @@ fn context_in_derivation_args() { #[test_log::test] fn context_in_derivation_env() { - let mut rt = Runtime::new().unwrap(); + let mut rt = Evaluator::new(); let result = rt .eval( r#" @@ -224,7 +224,7 @@ fn tostring_preserves_context() { #[test_log::test] fn interpolation_derivation_returns_outpath() { - let mut rt = Runtime::new().unwrap(); + let mut rt = Evaluator::new(); let result = rt .eval( r#" diff --git a/fix/tests/tests/utils.rs b/fix/tests/tests/utils.rs index c317c27..7a74009 100644 --- a/fix/tests/tests/utils.rs +++ b/fix/tests/tests/utils.rs @@ -1,38 +1,31 @@ #![allow(dead_code)] -use fix::error::{Result, Source}; -use fix::runtime::Runtime; -use fix::value::Value; +use fix::Evaluator; +use fix_common::Value; +use fix_error::{Result, Source}; pub fn eval(expr: &str) -> Value { - Runtime::new() - .unwrap() + Evaluator::new() .eval(Source::new_eval(expr.into()).unwrap()) .unwrap() } pub fn eval_shallow(expr: &str) -> Value { - Runtime::new() - .unwrap() + Evaluator::new() .eval_shallow(Source::new_eval(expr.into()).unwrap()) .unwrap() } pub fn eval_deep(expr: &str) -> Value { - Runtime::new() - .unwrap() + Evaluator::new() .eval_deep(Source::new_eval(expr.into()).unwrap()) .unwrap() } pub fn eval_deep_result(expr: &str) -> Result { - Runtime::new() - .unwrap() - .eval_deep(Source::new_eval(expr.into()).unwrap()) + Evaluator::new().eval_deep(Source::new_eval(expr.into()).unwrap()) } pub fn eval_result(expr: &str) -> Result { - Runtime::new() - .unwrap() - .eval(Source::new_eval(expr.into()).unwrap()) + Evaluator::new().eval(Source::new_eval(expr.into()).unwrap()) }